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)
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/>. */
24 #include "coretypes.h"
28 #include "hard-reg-set.h"
30 #include "insn-config.h"
31 #include "conditions.h"
32 #include "insn-attr.h"
45 #include "target-def.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
;
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)
206 fprintf (stderr
, "unknown MCU '%s' specified\nKnown MCU names:\n",
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. */
249 avr_regno_reg_class (int r
)
252 return reg_class_tab
[r
];
256 /* Return nonzero if FUNC is a naked function. */
259 avr_naked_function_p (tree func
)
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. */
273 interrupt_function_p (tree func
)
277 if (TREE_CODE (func
) != FUNCTION_DECL
)
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. */
288 signal_function_p (tree func
)
292 if (TREE_CODE (func
) != FUNCTION_DECL
)
295 a
= lookup_attribute ("signal", DECL_ATTRIBUTES (func
));
296 return a
!= NULL_TREE
;
299 /* Return nonzero if FUNC is a OS_task function. */
302 avr_OS_task_function_p (tree func
)
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. */
315 avr_OS_main_function_p (tree func
)
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. */
329 avr_regs_to_save (HARD_REG_SET
*set
)
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 ();
339 CLEAR_HARD_REG_SET (*set
);
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
)
349 for (reg
= 0; reg
< 32; reg
++)
351 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
352 any global register variables. */
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)))))
363 SET_HARD_REG_BIT (*set
, reg
);
370 /* Return true if register FROM can be eliminated via register TO. */
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
)
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. */
426 sequent_regs_live (void)
432 for (reg
= 0; reg
< 18; ++reg
)
434 if (!call_used_regs
[reg
])
436 if (df_regs_ever_live_p (reg
))
446 if (!frame_pointer_needed
)
448 if (df_regs_ever_live_p (REG_Y
))
456 if (df_regs_ever_live_p (REG_Y
+1))
469 return (cur_seq
== live_seq
) ? live_seq
: 0;
472 /* Obtain the length sequence of insns. */
475 get_sequence_length (rtx insns
)
480 for (insn
= insns
, length
= 0; insn
; insn
= NEXT_INSN (insn
))
481 length
+= get_attr_length (insn
);
486 /* Output function prologue. */
489 expand_prologue (void)
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
));
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
)
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
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;
536 insn
= emit_move_insn (pushbyte
, zero_reg_rtx
);
537 RTX_FRAME_RELATED_P (insn
) = 1;
540 insn
= emit_move_insn (pushbyte
, tmp_reg_rtx
);
541 RTX_FRAME_RELATED_P (insn
) = 1;
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;
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)
572 insn
= emit_move_insn (gen_rtx_REG (HImode
, REG_X
),
573 gen_int_mode (size
, HImode
));
574 RTX_FRAME_RELATED_P (insn
) = 1;
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;
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;
604 insn
= emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
605 RTX_FRAME_RELATED_P (insn
) = 1;
609 /* Creating a frame can be done by direct manipulation of the
610 stack or via the frame pointer. These two methods are:
617 the optimum method depends on function type, stack and frame size.
618 To avoid a complex logic, both methods are tested and shortest
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
));
632 /* Normal sized addition. */
633 myfp
= frame_pointer_rtx
;
636 /* Method 1-Adjust frame pointer. */
639 insn
= emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
640 RTX_FRAME_RELATED_P (insn
) = 1;
643 emit_move_insn (myfp
,
644 gen_rtx_PLUS (GET_MODE(myfp
), 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
)
660 emit_insn (gen_movhi_sp_r_irq_off (stack_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
,
668 RTX_FRAME_RELATED_P (insn
) = 1;
672 insn
= emit_move_insn (stack_pointer_rtx
, frame_pointer_rtx
);
673 RTX_FRAME_RELATED_P (insn
) = 1;
676 fp_plus_insns
= get_insns ();
679 /* Method 2-Adjust Stack pointer. */
685 emit_move_insn (stack_pointer_rtx
,
686 gen_rtx_PLUS (HImode
,
690 RTX_FRAME_RELATED_P (insn
) = 1;
693 emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
694 RTX_FRAME_RELATED_P (insn
) = 1;
696 sp_plus_insns
= get_insns ();
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
);
705 emit_insn (fp_plus_insns
);
711 /* Output summary at end of function prologue. */
714 avr_asm_function_end_prologue (FILE *file
)
716 if (cfun
->machine
->is_naked
)
718 fputs ("/* prologue: naked */\n", file
);
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
);
731 fputs ("/* prologue: function */\n", file
);
733 fprintf (file
, "/* frame size = " HOST_WIDE_INT_PRINT_DEC
" */\n",
738 /* Implement EPILOGUE_USES. */
741 avr_epilogue_uses (int regno ATTRIBUTE_UNUSED
)
745 && (cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
))
750 /* Output RTL epilogue. */
753 expand_epilogue (void)
759 HOST_WIDE_INT size
= get_frame_size();
761 /* epilogue: naked */
762 if (cfun
->machine
->is_naked
)
764 emit_jump_insn (gen_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
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
)));
788 emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
791 emit_insn (gen_epilogue_restores (gen_int_mode (live_seq
, HImode
)));
795 if (frame_pointer_needed
)
799 /* Try two methods to adjust stack and select shortest. */
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
));
812 /* Normal sized addition. */
813 myfp
= frame_pointer_rtx
;
816 /* Method 1-Adjust frame pointer. */
819 emit_move_insn (myfp
,
820 gen_rtx_PLUS (HImode
, 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
,
835 else if (cfun
->machine
->is_interrupt
)
837 emit_insn (gen_movhi_sp_r_irq_on (stack_pointer_rtx
,
842 emit_move_insn (stack_pointer_rtx
, frame_pointer_rtx
);
845 fp_plus_insns
= get_insns ();
848 /* Method 2-Adjust Stack pointer. */
853 emit_move_insn (stack_pointer_rtx
,
854 gen_rtx_PLUS (HImode
, stack_pointer_rtx
,
858 sp_plus_insns
= get_insns ();
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
);
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. */
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
)),
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
)),
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. */
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. */
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:",
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
)
940 fprintf (stderr
, "(r%d ---> r%d)", REGNO (XEXP (x
, 0)),
941 true_regnum (XEXP (x
, 0)));
944 if (!strict
&& GET_CODE (x
) == SUBREG
)
946 if (REG_P (x
) && (strict
? REG_OK_FOR_BASE_STRICT_P (x
)
947 : REG_OK_FOR_BASE_NOSTRICT_P (x
)))
949 else if (CONSTANT_ADDRESS_P (x
))
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
);
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
)
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))))
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
)
992 if (TARGET_ALL_DEBUG
)
994 fprintf (stderr
, "legitimize_address mode: %s", GET_MODE_NAME(mode
));
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
);
1019 /* Return a pointer register name as a string. */
1022 ptrreg_to_str (int regno
)
1026 case REG_X
: return "X";
1027 case REG_Y
: return "Y";
1028 case REG_Z
: return "Z";
1030 output_operand_lossage ("address operand requires constraint for X, Y, or Z register");
1035 /* Return the condition name as a string.
1036 Used in conditional jump constructing */
1039 cond_string (enum rtx_code code
)
1048 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1053 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1066 /* Output ADDR to FILE as address. */
1069 print_operand_address (FILE *file
, rtx addr
)
1071 switch (GET_CODE (addr
))
1074 fprintf (file
, ptrreg_to_str (REGNO (addr
)));
1078 fprintf (file
, "-%s", ptrreg_to_str (REGNO (XEXP (addr
, 0))));
1082 fprintf (file
, "%s+", ptrreg_to_str (REGNO (XEXP (addr
, 0))));
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
,")");
1095 output_addr_const (file
, addr
);
1100 /* Output X as assembler operand to file FILE. */
1103 print_operand (FILE *file
, rtx x
, int code
)
1107 if (code
>= 'A' && code
<= 'D')
1112 if (!AVR_HAVE_JMP_CALL
)
1115 else if (code
== '!')
1117 if (AVR_HAVE_EIJMP_EICALL
)
1122 if (x
== zero_reg_rtx
)
1123 fprintf (file
, "__zero_reg__");
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
)
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
);
1152 print_operand_address (file
, XEXP (addr
, 0)); /* X, Y, Z */
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:"
1163 print_operand (file
, XEXP (addr
,1), code
);
1166 print_operand_address (file
, addr
);
1168 else if (GET_CODE (x
) == CONST_DOUBLE
)
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
);
1183 print_operand_address (file
, x
);
1186 /* Update the condition code in the INSN. */
1189 notice_update_cc (rtx body ATTRIBUTE_UNUSED
, rtx insn
)
1193 switch (get_attr_cc (insn
))
1196 /* Insn does not affect CC at all. */
1204 set
= single_set (insn
);
1208 cc_status
.flags
|= CC_NO_OVERFLOW
;
1209 cc_status
.value1
= SET_DEST (set
);
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
);
1221 cc_status
.value1
= SET_DEST (set
);
1222 cc_status
.flags
|= CC_OVERFLOW_UNUSABLE
;
1227 set
= single_set (insn
);
1230 cc_status
.value1
= SET_SRC (set
);
1234 /* Insn doesn't leave CC in a usable state. */
1237 /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1238 set
= single_set (insn
);
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
1252 cc_status
.value1
= SET_DEST (set
);
1253 cc_status
.flags
|= CC_OVERFLOW_UNUSABLE
;
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)
1285 else if (-2046 <= jump_distance
&& jump_distance
<= 2045)
1287 else if (AVR_HAVE_JMP_CALL
)
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. */
1299 ret_cond_branch (rtx x
, int len
, int reverse
)
1301 RTX_CODE cond
= reverse
? reverse_condition (GET_CODE (x
)) : GET_CODE (x
);
1306 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1307 return (len
== 1 ? (AS1 (breq
,.+2) CR_TAB
1309 len
== 2 ? (AS1 (breq
,.+4) CR_TAB
1310 AS1 (brmi
,.+2) CR_TAB
1312 (AS1 (breq
,.+6) CR_TAB
1313 AS1 (brmi
,.+4) CR_TAB
1317 return (len
== 1 ? (AS1 (breq
,.+2) CR_TAB
1319 len
== 2 ? (AS1 (breq
,.+4) CR_TAB
1320 AS1 (brlt
,.+2) CR_TAB
1322 (AS1 (breq
,.+6) CR_TAB
1323 AS1 (brlt
,.+4) CR_TAB
1326 return (len
== 1 ? (AS1 (breq
,.+2) CR_TAB
1328 len
== 2 ? (AS1 (breq
,.+4) CR_TAB
1329 AS1 (brlo
,.+2) CR_TAB
1331 (AS1 (breq
,.+6) CR_TAB
1332 AS1 (brlo
,.+4) CR_TAB
1335 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1336 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1338 len
== 2 ? (AS1 (breq
,.+2) CR_TAB
1339 AS1 (brpl
,.+2) CR_TAB
1341 (AS1 (breq
,.+2) CR_TAB
1342 AS1 (brpl
,.+4) CR_TAB
1345 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1347 len
== 2 ? (AS1 (breq
,.+2) CR_TAB
1348 AS1 (brge
,.+2) CR_TAB
1350 (AS1 (breq
,.+2) CR_TAB
1351 AS1 (brge
,.+4) CR_TAB
1354 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1356 len
== 2 ? (AS1 (breq
,.+2) CR_TAB
1357 AS1 (brsh
,.+2) CR_TAB
1359 (AS1 (breq
,.+2) CR_TAB
1360 AS1 (brsh
,.+4) CR_TAB
1368 return AS1 (br
%k1
,%0);
1370 return (AS1 (br
%j1
,.+2) CR_TAB
1373 return (AS1 (br
%j1
,.+4) CR_TAB
1382 return AS1 (br
%j1
,%0);
1384 return (AS1 (br
%k1
,.+2) CR_TAB
1387 return (AS1 (br
%k1
,.+4) CR_TAB
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. */
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
)
1438 if (max
!= (INTVAL (x
) & max
)
1439 && INTVAL (x
) != 0xff)
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. */
1459 init_cumulative_args (CUMULATIVE_ARGS
*cum
, tree fntype
, rtx libname
,
1460 tree fndecl ATTRIBUTE_UNUSED
)
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
));
1474 /* Returns the number of registers to allocate for a function argument. */
1477 avr_num_arg_regs (enum machine_mode mode
, tree type
)
1481 if (mode
== BLKmode
)
1482 size
= int_size_in_bytes (type
);
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
);
1507 /* Update the summarizer variable CUM to advance past an argument
1508 in the argument list. */
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)
1522 cum
->regno
= FIRST_CUM_REG
;
1526 /***********************************************************************
1527 Functions for outputting various mov's for a various modes
1528 ************************************************************************/
1530 output_movqi (rtx insn
, rtx operands
[], int *l
)
1533 rtx dest
= operands
[0];
1534 rtx src
= operands
[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
)
1565 return (AS1 (clr
,%0) CR_TAB
1568 else if (src
== constm1_rtx
)
1570 /* Immediate constants -1 to any register */
1572 return (AS1 (clr
,%0) CR_TAB
1577 int bit_nr
= exact_log2 (INTVAL (src
));
1583 output_asm_insn ((AS1 (clr
,%0) CR_TAB
1586 avr_output_bld (operands
, bit_nr
);
1593 /* Last resort, larger than loading from memory. */
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
)
1607 if (src
== const0_rtx
)
1608 operands
[1] = zero_reg_rtx
;
1610 templ
= out_movqi_mr_r (insn
, operands
, real_l
);
1613 output_asm_insn (templ
, operands
);
1622 output_movhi (rtx insn
, rtx operands
[], int *l
)
1625 rtx dest
= operands
[0];
1626 rtx src
= operands
[1];
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
1642 else if (TARGET_NO_INTERRUPTS
)
1643 return *l
= 2, (AS2 (out
,__SP_H__
,%B1
) CR_TAB
1644 AS2 (out
,__SP_L__
,%A1
));
1646 return (AS2 (in
,__tmp_reg__
,__SREG__
) 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
))
1655 return (AS2 (in
,%A0
,__SP_L__
) CR_TAB
1656 AS2 (in
,%B0
,__SP_H__
));
1662 return (AS2 (movw
,%0,%1));
1667 return (AS2 (mov
,%A0
,%A1
) CR_TAB
1671 else if (CONSTANT_P (src
))
1673 if (test_hard_reg_class (LD_REGS
, dest
)) /* ldi d,i */
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 */
1685 return (AS1 (clr
,%A0
) CR_TAB
1688 else if (src
== const1_rtx
)
1691 return (AS1 (clr
,%A0
) CR_TAB
1692 AS1 (clr
,%B0
) CR_TAB
1695 else if (src
== constm1_rtx
)
1697 /* Immediate constants -1 to any register */
1699 return (AS1 (clr
,%0) CR_TAB
1700 AS1 (dec
,%A0
) CR_TAB
1705 int bit_nr
= exact_log2 (INTVAL (src
));
1711 output_asm_insn ((AS1 (clr
,%A0
) CR_TAB
1712 AS1 (clr
,%B0
) CR_TAB
1715 avr_output_bld (operands
, bit_nr
);
1721 if ((INTVAL (src
) & 0xff) == 0)
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)
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. */
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
)
1757 if (src
== const0_rtx
)
1758 operands
[1] = zero_reg_rtx
;
1760 templ
= out_movhi_mr_r (insn
, operands
, real_l
);
1763 output_asm_insn (templ
, operands
);
1768 fatal_insn ("invalid insn:", insn
);
1773 out_movqi_r_mr (rtx insn
, rtx op
[], int *l
)
1777 rtx x
= XEXP (src
, 0);
1783 if (CONSTANT_ADDRESS_P (x
))
1785 if (CONST_INT_P (x
) && INTVAL (x
) == SREG_ADDR
)
1788 return AS2 (in
,%0,__SREG__
);
1790 if (optimize
> 0 && io_address_operand (x
, QImode
))
1793 return AS2 (in
,%0,%1-0x20);
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
1829 return *l
= 3, (AS2 (adiw
,r26
,%o1
) CR_TAB
1830 AS2 (ld
,%0,X
) CR_TAB
1831 AS2 (sbiw
,r26
,%o1
));
1834 return AS2 (ldd
,%0,%1);
1837 return AS2 (ld
,%0,%1);
1841 out_movhi_r_mr (rtx insn
, rtx op
[], int *l
)
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
);
1858 if (reg_dest
== reg_base
) /* R = (R) */
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
))
1870 return (AS2 (ld
,%A0
,X
+) CR_TAB
1874 return (AS2 (ld
,%A0
,X
+) CR_TAB
1875 AS2 (ld
,%B0
,X
) CR_TAB
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. */
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
)
1930 return (AS2 (ldd
,__tmp_reg__
,%A1
) CR_TAB
1931 AS2 (ldd
,%B0
,%B1
) CR_TAB
1932 AS2 (mov
,%A0
,__tmp_reg__
));
1936 return (AS2 (ldd
,%A0
,%A1
) CR_TAB
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
);
1946 if (REGNO (XEXP (base
, 0)) == REG_X
)
1949 return (AS2 (sbiw
,r26
,2) CR_TAB
1950 AS2 (ld
,%A0
,X
+) CR_TAB
1951 AS2 (ld
,%B0
,X
) CR_TAB
1957 return (AS2 (sbiw
,%r1
,2) CR_TAB
1958 AS2 (ld
,%A0
,%p1
) CR_TAB
1959 AS2 (ldd
,%B0
,%p1
+1));
1964 return (AS2 (ld
,%B0
,%1) CR_TAB
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
);
1973 return (AS2 (ld
,%A0
,%1) CR_TAB
1976 else if (CONSTANT_ADDRESS_P (base
))
1978 if (optimize
> 0 && io_address_operand (base
, HImode
))
1981 return (AS2 (in
,%A0
,%A1
-0x20) CR_TAB
1982 AS2 (in
,%B0
,%B1
-0x20));
1985 return (AS2 (lds
,%A0
,%A1
) CR_TAB
1989 fatal_insn ("unknown move insn:",insn
);
1994 out_movsi_r_mr (rtx insn
, rtx op
[], int *l
)
1998 rtx base
= XEXP (src
, 0);
1999 int reg_dest
= true_regnum (dest
);
2000 int reg_base
= true_regnum (base
);
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
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
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__
));
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
)
2089 if (reg_dest
== REG_X
)
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__
));
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
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
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
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
2150 fatal_insn ("unknown move insn:",insn
);
2155 out_movsi_mr_r (rtx insn
, rtx op
[], int *l
)
2159 rtx base
= XEXP (dest
, 0);
2160 int reg_base
= true_regnum (base
);
2161 int reg_src
= true_regnum (src
);
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
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
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
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__
));
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
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
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
)
2256 if (reg_src
== REG_X
)
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)
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));
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
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
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
2305 fatal_insn ("unknown move insn:",insn
);
2310 output_movsisf(rtx insn
, rtx operands
[], int *l
)
2313 rtx dest
= operands
[0];
2314 rtx src
= operands
[1];
2320 if (register_operand (dest
, VOIDmode
))
2322 if (register_operand (src
, VOIDmode
)) /* mov r,r */
2324 if (true_regnum (dest
) > true_regnum (src
))
2329 return (AS2 (movw
,%C0
,%C1
) CR_TAB
2330 AS2 (movw
,%A0
,%A1
));
2333 return (AS2 (mov
,%D0
,%D1
) CR_TAB
2334 AS2 (mov
,%C0
,%C1
) CR_TAB
2335 AS2 (mov
,%B0
,%B1
) CR_TAB
2343 return (AS2 (movw
,%A0
,%A1
) CR_TAB
2344 AS2 (movw
,%C0
,%C1
));
2347 return (AS2 (mov
,%A0
,%A1
) CR_TAB
2348 AS2 (mov
,%B0
,%B1
) CR_TAB
2349 AS2 (mov
,%C0
,%C1
) CR_TAB
2353 else if (CONSTANT_P (src
))
2355 if (test_hard_reg_class (LD_REGS
, dest
)) /* ldi d,i */
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
2370 : (AS1 (clr
,%A0
) CR_TAB
2371 AS1 (clr
,%B0
) CR_TAB
2372 AS1 (clr
,%C0
) CR_TAB
2375 if (src
== const0_rtx
) /* mov r,L */
2377 *l
= AVR_HAVE_MOVW
? 3 : 4;
2380 else if (src
== const1_rtx
)
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 */
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
));
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
2407 int bit_nr
= exact_log2 (INTVAL (src
));
2411 *l
= AVR_HAVE_MOVW
? 5 : 6;
2414 output_asm_insn (clr_op0
, operands
);
2415 output_asm_insn ("set", operands
);
2418 avr_output_bld (operands
, bit_nr
);
2425 /* Last resort, better than loading from memory. */
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
)
2445 if (src
== const0_rtx
)
2446 operands
[1] = zero_reg_rtx
;
2448 templ
= out_movsi_mr_r (insn
, operands
, real_l
);
2451 output_asm_insn (templ
, operands
);
2456 fatal_insn ("invalid insn:", insn
);
2461 out_movqi_mr_r (rtx insn
, rtx op
[], int *l
)
2465 rtx x
= XEXP (dest
, 0);
2471 if (CONSTANT_ADDRESS_P (x
))
2473 if (CONST_INT_P (x
) && INTVAL (x
) == SREG_ADDR
)
2476 return AS2 (out
,__SREG__
,%1);
2478 if (optimize
> 0 && io_address_operand (x
, QImode
))
2481 return AS2 (out
,%0-0x20,%1);
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
));
2524 if (reg_unused_after (insn
, XEXP (x
,0)))
2525 return *l
= 2, (AS2 (adiw
,r26
,%o0
) CR_TAB
2528 return *l
= 3, (AS2 (adiw
,r26
,%o0
) CR_TAB
2529 AS2 (st
,X
,%1) CR_TAB
2530 AS2 (sbiw
,r26
,%o0
));
2534 return AS2 (std
,%0,%1);
2537 return AS2 (st
,%0,%1);
2541 out_movhi_mr_r (rtx insn
, rtx op
[], int *l
)
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
);
2555 if (CONSTANT_ADDRESS_P (base
))
2557 if (optimize
> 0 && io_address_operand (base
, HImode
))
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
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__
));
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
2587 if (!mem_volatile_p
&& reg_unused_after (insn
, base
))
2588 return *l
=2, (AS2 (st
,X
+,%A1
) CR_TAB
2591 return *l
=3, (AS2 (adiw
,r26
,1) CR_TAB
2592 AS2 (st
,X
,%B1
) CR_TAB
2597 return *l
=2, (AS2 (std
,%0+1,%B1
) CR_TAB
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
)
2625 if (reg_src
== REG_X
)
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
));
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
2645 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2646 return *l
=2, (AS2 (st
,%0,%B1
) CR_TAB
2648 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2652 if (REGNO (XEXP (base
, 0)) == REG_X
)
2655 return (AS2 (adiw
,r26
,1) CR_TAB
2656 AS2 (st
,X
,%B1
) CR_TAB
2657 AS2 (st
,-X
,%A1
) CR_TAB
2663 return (AS2 (std
,%p0
+1,%B1
) CR_TAB
2664 AS2 (st
,%p0
,%A1
) CR_TAB
2670 return (AS2 (st
,%0,%A1
) CR_TAB
2673 fatal_insn ("unknown move insn:",insn
);
2677 /* Return 1 if frame pointer for current function required. */
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. */
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
);
2704 /* Returns nonzero if INSN is a tst insn that only tests the sign. */
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. */
2736 out_tsthi (rtx insn
, rtx op
, int *l
)
2738 if (compare_sign_p (insn
))
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. */
2748 return "or %A0,%B0";
2750 if (test_hard_reg_class (ADDW_REGS
, op
))
2753 return AS2 (sbiw
,%0,0);
2756 return (AS2 (cp
,%A0
,__zero_reg__
) CR_TAB
2757 AS2 (cpc
,%B0
,__zero_reg__
));
2761 /* Output test instruction for SImode. */
2764 out_tstsi (rtx insn
, rtx op
, int *l
)
2766 if (compare_sign_p (insn
))
2769 return AS1 (tst
,%D0
);
2771 if (test_hard_reg_class (ADDW_REGS
, op
))
2774 return (AS2 (sbiw
,%A0
,0) CR_TAB
2775 AS2 (cpc
,%C0
,__zero_reg__
) CR_TAB
2776 AS2 (cpc
,%D0
,__zero_reg__
));
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. */
2792 out_shift_with_cnt (const char *templ
, rtx insn
, rtx operands
[],
2793 int *len
, int t_len
)
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];
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. */
2823 if (count
< 8 && !scratch
)
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. */
2833 *len
= t_len
* count
;
2837 output_asm_insn (templ
, op
);
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
;
2857 strcat (str
, ("set" CR_TAB
2858 AS2 (bld
,%3,%2-1)));
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
;
2871 *len
= 3; /* Includes "mov %3,%4" after the loop. */
2873 strcat (str
, (AS2 (mov
,%4,%3) CR_TAB
2879 else if (GET_CODE (operands
[2]) == MEM
)
2883 op
[3] = op_mov
[0] = tmp_reg_rtx
;
2887 out_movqi_r_mr (insn
, op_mov
, len
);
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]))
2897 op
[3] = tmp_reg_rtx
;
2899 strcat (str
, (AS2 (mov
,%3,%2) CR_TAB
));
2903 fatal_insn ("bad shift insn:", insn
);
2910 strcat (str
, AS1 (rjmp
,2f
));
2914 *len
+= t_len
+ 2; /* template + dec + brXX */
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
));
2924 strcat (str
, (CR_TAB
AS2 (mov
,%3,%4)));
2925 output_asm_insn (str
, op
);
2930 /* 8bit shift left ((char)x << i) */
2933 ashlqi3_out (rtx insn
, rtx operands
[], int *len
)
2935 if (GET_CODE (operands
[2]) == CONST_INT
)
2942 switch (INTVAL (operands
[2]))
2945 if (INTVAL (operands
[2]) < 8)
2949 return AS1 (clr
,%0);
2953 return AS1 (lsl
,%0);
2957 return (AS1 (lsl
,%0) CR_TAB
2962 return (AS1 (lsl
,%0) CR_TAB
2967 if (test_hard_reg_class (LD_REGS
, operands
[0]))
2970 return (AS1 (swap
,%0) CR_TAB
2971 AS2 (andi
,%0,0xf0));
2974 return (AS1 (lsl
,%0) CR_TAB
2980 if (test_hard_reg_class (LD_REGS
, operands
[0]))
2983 return (AS1 (swap
,%0) CR_TAB
2985 AS2 (andi
,%0,0xe0));
2988 return (AS1 (lsl
,%0) CR_TAB
2995 if (test_hard_reg_class (LD_REGS
, operands
[0]))
2998 return (AS1 (swap
,%0) CR_TAB
3001 AS2 (andi
,%0,0xc0));
3004 return (AS1 (lsl
,%0) CR_TAB
3013 return (AS1 (ror
,%0) CR_TAB
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);
3027 /* 16bit shift left ((short)x << i) */
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]);
3042 switch (INTVAL (operands
[2]))
3045 if (INTVAL (operands
[2]) < 16)
3049 return (AS1 (clr
,%B0
) CR_TAB
3053 if (optimize_size
&& scratch
)
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
3068 return (AS1 (swap
,%A0
) CR_TAB
3069 AS1 (swap
,%B0
) CR_TAB
3070 AS2 (ldi
,%3,0xf0) CR_TAB
3072 AS2 (eor
,%B0
,%A0
) CR_TAB
3076 break; /* optimize_size ? 6 : 8 */
3080 break; /* scratch ? 5 : 6 */
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
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
3102 AS2 (eor
,%B0
,%A0
) CR_TAB
3110 break; /* scratch ? 5 : 6 */
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__
));
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
3131 return *len
= 2, (AS2 (mov
,%B0
,%A1
) CR_TAB
3136 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3137 AS1 (clr
,%A0
) CR_TAB
3142 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3143 AS1 (clr
,%A0
) CR_TAB
3144 AS1 (lsl
,%B0
) CR_TAB
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
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));
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
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
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
)
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
)
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
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__
));
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
3232 if (AVR_HAVE_MUL
&& ldi_ok
)
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
)
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
)
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
3259 if (optimize_size
&& scratch
)
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
3271 return (AS1 (clr
,%B0
) CR_TAB
3272 AS1 (lsr
,%A0
) CR_TAB
3273 AS1 (ror
,%B0
) CR_TAB
3278 out_shift_with_cnt ((AS1 (lsl
,%A0
) CR_TAB
3280 insn
, operands
, len
, 2);
3285 /* 32bit shift left ((long)x << i) */
3288 ashlsi3_out (rtx insn
, rtx operands
[], int *len
)
3290 if (GET_CODE (operands
[2]) == CONST_INT
)
3298 switch (INTVAL (operands
[2]))
3301 if (INTVAL (operands
[2]) < 32)
3305 return *len
= 3, (AS1 (clr
,%D0
) CR_TAB
3306 AS1 (clr
,%C0
) CR_TAB
3307 AS2 (movw
,%A0
,%C0
));
3309 return (AS1 (clr
,%D0
) CR_TAB
3310 AS1 (clr
,%C0
) CR_TAB
3311 AS1 (clr
,%B0
) CR_TAB
3316 int reg0
= true_regnum (operands
[0]);
3317 int reg1
= true_regnum (operands
[1]);
3320 return (AS2 (mov
,%D0
,%C1
) CR_TAB
3321 AS2 (mov
,%C0
,%B1
) CR_TAB
3322 AS2 (mov
,%B0
,%A1
) CR_TAB
3325 return (AS1 (clr
,%A0
) CR_TAB
3326 AS2 (mov
,%B0
,%A1
) CR_TAB
3327 AS2 (mov
,%C0
,%B1
) CR_TAB
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
3339 return *len
= 3, (AS2 (movw
,%C0
,%A1
) CR_TAB
3340 AS1 (clr
,%B0
) CR_TAB
3343 return *len
= 4, (AS2 (mov
,%C0
,%A1
) CR_TAB
3344 AS2 (mov
,%D0
,%B1
) CR_TAB
3345 AS1 (clr
,%B0
) CR_TAB
3351 return (AS2 (mov
,%D0
,%A1
) CR_TAB
3352 AS1 (clr
,%C0
) CR_TAB
3353 AS1 (clr
,%B0
) CR_TAB
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
3367 out_shift_with_cnt ((AS1 (lsl
,%A0
) CR_TAB
3368 AS1 (rol
,%B0
) CR_TAB
3369 AS1 (rol
,%C0
) CR_TAB
3371 insn
, operands
, len
, 4);
3375 /* 8bit arithmetic shift right ((signed char)x >> i) */
3378 ashrqi3_out (rtx insn
, rtx operands
[], int *len
)
3380 if (GET_CODE (operands
[2]) == CONST_INT
)
3387 switch (INTVAL (operands
[2]))
3391 return AS1 (asr
,%0);
3395 return (AS1 (asr
,%0) CR_TAB
3400 return (AS1 (asr
,%0) CR_TAB
3406 return (AS1 (asr
,%0) CR_TAB
3413 return (AS1 (asr
,%0) CR_TAB
3421 return (AS2 (bst
,%0,6) CR_TAB
3423 AS2 (sbc
,%0,%0) CR_TAB
3427 if (INTVAL (operands
[2]) < 8)
3434 return (AS1 (lsl
,%0) CR_TAB
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);
3447 /* 16bit arithmetic shift right ((signed short)x >> i) */
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]);
3462 switch (INTVAL (operands
[2]))
3466 /* XXX try to optimize this too? */
3471 break; /* scratch ? 5 : 6 */
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
3484 return (AS1 (lsl
,%A0
) CR_TAB
3485 AS2 (mov
,%A0
,%B0
) CR_TAB
3486 AS1 (rol
,%A0
) CR_TAB
3491 int reg0
= true_regnum (operands
[0]);
3492 int reg1
= true_regnum (operands
[1]);
3495 return *len
= 3, (AS2 (mov
,%A0
,%B0
) CR_TAB
3496 AS1 (lsl
,%B0
) CR_TAB
3499 return *len
= 4, (AS2 (mov
,%A0
,%B1
) CR_TAB
3500 AS1 (clr
,%B0
) CR_TAB
3501 AS2 (sbrc
,%A0
,7) CR_TAB
3507 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3508 AS1 (lsl
,%B0
) CR_TAB
3509 AS2 (sbc
,%B0
,%B0
) CR_TAB
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
3521 if (AVR_HAVE_MUL
&& ldi_ok
)
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
)
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
3541 if (AVR_HAVE_MUL
&& ldi_ok
)
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
)
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
3562 if (AVR_HAVE_MUL
&& ldi_ok
)
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__
));
3572 break; /* scratch ? 5 : 7 */
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
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
3592 if (INTVAL (operands
[2]) < 16)
3598 return *len
= 3, (AS1 (lsl
,%B0
) CR_TAB
3599 AS2 (sbc
,%A0
,%A0
) CR_TAB
3604 out_shift_with_cnt ((AS1 (asr
,%B0
) CR_TAB
3606 insn
, operands
, len
, 2);
3611 /* 32bit arithmetic shift right ((signed long)x >> i) */
3614 ashrsi3_out (rtx insn
, rtx operands
[], int *len
)
3616 if (GET_CODE (operands
[2]) == CONST_INT
)
3624 switch (INTVAL (operands
[2]))
3628 int reg0
= true_regnum (operands
[0]);
3629 int reg1
= true_regnum (operands
[1]);
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
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
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
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
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
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
3681 if (INTVAL (operands
[2]) < 32)
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
));
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
3701 out_shift_with_cnt ((AS1 (asr
,%D0
) CR_TAB
3702 AS1 (ror
,%C0
) CR_TAB
3703 AS1 (ror
,%B0
) CR_TAB
3705 insn
, operands
, len
, 4);
3709 /* 8bit logic shift right ((unsigned char)x >> i) */
3712 lshrqi3_out (rtx insn
, rtx operands
[], int *len
)
3714 if (GET_CODE (operands
[2]) == CONST_INT
)
3721 switch (INTVAL (operands
[2]))
3724 if (INTVAL (operands
[2]) < 8)
3728 return AS1 (clr
,%0);
3732 return AS1 (lsr
,%0);
3736 return (AS1 (lsr
,%0) CR_TAB
3740 return (AS1 (lsr
,%0) CR_TAB
3745 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3748 return (AS1 (swap
,%0) CR_TAB
3749 AS2 (andi
,%0,0x0f));
3752 return (AS1 (lsr
,%0) CR_TAB
3758 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3761 return (AS1 (swap
,%0) CR_TAB
3766 return (AS1 (lsr
,%0) CR_TAB
3773 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3776 return (AS1 (swap
,%0) CR_TAB
3782 return (AS1 (lsr
,%0) CR_TAB
3791 return (AS1 (rol
,%0) CR_TAB
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);
3804 /* 16bit logic shift right ((unsigned short)x >> i) */
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]);
3819 switch (INTVAL (operands
[2]))
3822 if (INTVAL (operands
[2]) < 16)
3826 return (AS1 (clr
,%B0
) CR_TAB
3830 if (optimize_size
&& scratch
)
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
3845 return (AS1 (swap
,%B0
) CR_TAB
3846 AS1 (swap
,%A0
) CR_TAB
3847 AS2 (ldi
,%3,0x0f) CR_TAB
3849 AS2 (eor
,%A0
,%B0
) CR_TAB
3853 break; /* optimize_size ? 6 : 8 */
3857 break; /* scratch ? 5 : 6 */
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
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
3879 AS2 (eor
,%A0
,%B0
) CR_TAB
3887 break; /* scratch ? 5 : 6 */
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__
));
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
3908 return *len
= 2, (AS2 (mov
,%A0
,%B1
) CR_TAB
3913 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3914 AS1 (clr
,%B0
) CR_TAB
3919 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3920 AS1 (clr
,%B0
) CR_TAB
3921 AS1 (lsr
,%A0
) CR_TAB
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
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));
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
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
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
)
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
)
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
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__
));
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
4009 if (AVR_HAVE_MUL
&& ldi_ok
)
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
)
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
)
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
4036 if (optimize_size
&& scratch
)
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
4048 return (AS1 (clr
,%A0
) CR_TAB
4049 AS1 (lsl
,%B0
) CR_TAB
4050 AS1 (rol
,%A0
) CR_TAB
4055 out_shift_with_cnt ((AS1 (lsr
,%B0
) CR_TAB
4057 insn
, operands
, len
, 2);
4061 /* 32bit logic shift right ((unsigned int)x >> i) */
4064 lshrsi3_out (rtx insn
, rtx operands
[], int *len
)
4066 if (GET_CODE (operands
[2]) == CONST_INT
)
4074 switch (INTVAL (operands
[2]))
4077 if (INTVAL (operands
[2]) < 32)
4081 return *len
= 3, (AS1 (clr
,%D0
) CR_TAB
4082 AS1 (clr
,%C0
) CR_TAB
4083 AS2 (movw
,%A0
,%C0
));
4085 return (AS1 (clr
,%D0
) CR_TAB
4086 AS1 (clr
,%C0
) CR_TAB
4087 AS1 (clr
,%B0
) CR_TAB
4092 int reg0
= true_regnum (operands
[0]);
4093 int reg1
= true_regnum (operands
[1]);
4096 return (AS2 (mov
,%A0
,%B1
) CR_TAB
4097 AS2 (mov
,%B0
,%C1
) CR_TAB
4098 AS2 (mov
,%C0
,%D1
) CR_TAB
4101 return (AS1 (clr
,%D0
) CR_TAB
4102 AS2 (mov
,%C0
,%D1
) CR_TAB
4103 AS2 (mov
,%B0
,%C1
) CR_TAB
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
4116 return *len
= 3, (AS2 (movw
,%A0
,%C1
) CR_TAB
4117 AS1 (clr
,%C0
) CR_TAB
4120 return *len
= 4, (AS2 (mov
,%B0
,%D1
) CR_TAB
4121 AS2 (mov
,%A0
,%C1
) CR_TAB
4122 AS1 (clr
,%C0
) CR_TAB
4127 return *len
= 4, (AS2 (mov
,%A0
,%D1
) CR_TAB
4128 AS1 (clr
,%B0
) CR_TAB
4129 AS1 (clr
,%C0
) CR_TAB
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
4143 out_shift_with_cnt ((AS1 (lsr
,%D0
) CR_TAB
4144 AS1 (ror
,%C0
) CR_TAB
4145 AS1 (ror
,%B0
) CR_TAB
4147 insn
, operands
, len
, 4);
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
);
4160 if (GET_CODE (patt
) == SET
)
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]))
4171 output_movqi (insn
, op
, &len
);
4174 output_movhi (insn
, op
, &len
);
4178 output_movsisf (insn
, op
, &len
);
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;
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
);
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]))
4245 output_reload_inhi (insn
, op
, &len
);
4249 output_reload_insisf (insn
, op
, &len
);
4255 else if (GET_CODE (op
[1]) == ASHIFT
4256 || GET_CODE (op
[1]) == ASHIFTRT
4257 || GET_CODE (op
[1]) == LSHIFTRT
)
4261 ops
[1] = XEXP (op
[1],0);
4262 ops
[2] = XEXP (op
[1],1);
4263 switch (GET_CODE (op
[1]))
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;
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;
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;
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
)
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
)))
4327 while ((insn
= NEXT_INSN (insn
)))
4330 code
= GET_CODE (insn
);
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
)
4345 if (code
== JUMP_INSN
)
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
)
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
)
4364 else if (GET_CODE (this_insn
) == JUMP_INSN
)
4366 if (INSN_ANNULLED_BRANCH_P (this_insn
))
4371 if (set
&& reg_overlap_mentioned_p (reg
, SET_SRC (set
)))
4373 if (set
&& reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
4375 if (GET_CODE (SET_DEST (set
)) != MEM
)
4381 && reg_overlap_mentioned_p (reg
, PATTERN (this_insn
)))
4386 else if (code
== JUMP_INSN
)
4390 if (code
== CALL_INSN
)
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)))
4398 if (call_used_regs
[REGNO (reg
)])
4402 set
= single_set (insn
);
4404 if (set
&& reg_overlap_mentioned_p (reg
, SET_SRC (set
)))
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
)))
4414 /* Target hook for assembling integer objects. The AVR version needs
4415 special handling for references to certain labels. */
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
);
4429 return default_assemble_integer (x
, size
, aligned_p
);
4432 /* Worker function for ASM_DECLARE_FUNCTION_NAME. */
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",
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",
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). */
4473 gas_output_limited_string(FILE *file
, const char *str
)
4475 const unsigned char *_limited_str
= (const unsigned char *) str
;
4477 fprintf (file
, "%s\"", STRING_ASM_OP
);
4478 for (; (ch
= *_limited_str
); _limited_str
++)
4481 switch (escape
= ESCAPES
[ch
])
4487 fprintf (file
, "\\%03o", ch
);
4491 putc (escape
, file
);
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. */
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");
4519 for (p
= _ascii_bytes
; p
< limit
&& *p
!= '\0'; p
++)
4521 if (p
< limit
&& (p
- _ascii_bytes
) <= (signed)STRING_LIMIT
)
4523 if (bytes_in_chunk
> 0)
4525 fprintf (file
, "\"\n");
4528 gas_output_limited_string (file
, (const char*)_ascii_bytes
);
4535 if (bytes_in_chunk
== 0)
4536 fprintf (file
, "\t.ascii\t\"");
4537 switch (escape
= ESCAPES
[ch
= *_ascii_bytes
])
4544 fprintf (file
, "\\%03o", ch
);
4545 bytes_in_chunk
+= 4;
4549 putc (escape
, file
);
4550 bytes_in_chunk
+= 2;
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. */
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. */
4582 avr_handle_progmem_attribute (tree
*node
, tree name
,
4583 tree args ATTRIBUTE_UNUSED
,
4584 int flags ATTRIBUTE_UNUSED
,
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;
4613 warning (OPT_Wattributes
, "%qE attribute ignored",
4615 *no_add_attrs
= true;
4622 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4623 struct attribute_spec.handler. */
4626 avr_handle_fndecl_attribute (tree
*node
, tree name
,
4627 tree args ATTRIBUTE_UNUSED
,
4628 int flags ATTRIBUTE_UNUSED
,
4631 if (TREE_CODE (*node
) != FUNCTION_DECL
)
4633 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
4635 *no_add_attrs
= true;
4642 avr_handle_fntype_attribute (tree
*node
, tree name
,
4643 tree args ATTRIBUTE_UNUSED
,
4644 int flags ATTRIBUTE_UNUSED
,
4647 if (TREE_CODE (*node
) != FUNCTION_TYPE
)
4649 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
4651 *no_add_attrs
= true;
4657 /* Look for attribute `progmem' in DECL
4658 if found return 1, otherwise 0. */
4661 avr_progmem_p (tree decl
, tree attributes
)
4665 if (TREE_CODE (decl
) != VAR_DECL
)
4669 != lookup_attribute ("progmem", attributes
))
4675 while (TREE_CODE (a
) == ARRAY_TYPE
);
4677 if (a
== error_mark_node
)
4680 if (NULL_TREE
!= lookup_attribute ("progmem", TYPE_ATTRIBUTES (a
)))
4686 /* Add the section attribute if the variable is in progmem. */
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
)),
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. */
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. */
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
,
4726 readonly_data_section
= data_section
;
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 */
4740 warning (0, "only uninitialized variables can be placed in the "
4747 /* Outputs some appropriate text to go at the start of an assembler
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"
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. */
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. */
4789 order_regs_for_local_alloc (void)
4792 static const int order_0
[] = {
4800 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4804 static const int order_1
[] = {
4812 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4816 static const int order_2
[] = {
4825 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4830 const int *order
= (TARGET_ORDER_1
? order_1
:
4831 TARGET_ORDER_2
? order_2
:
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. */
4844 avr_operand_rtx_cost (rtx x
, enum machine_mode mode
, enum rtx_code outer
,
4847 enum rtx_code code
= GET_CODE (x
);
4858 return COSTS_N_INSNS (GET_MODE_SIZE (mode
));
4865 avr_rtx_costs (x
, code
, outer
, &total
, speed
);
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. */
4875 avr_rtx_costs (rtx x
, int codearg
, int outer_code ATTRIBUTE_UNUSED
, int *total
,
4878 enum rtx_code code
= (enum rtx_code
) codearg
;
4879 enum machine_mode mode
= GET_MODE (x
);
4886 /* Immediate constants are as cheap as registers. */
4894 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
4902 *total
= COSTS_N_INSNS (1);
4906 *total
= COSTS_N_INSNS (3);
4910 *total
= COSTS_N_INSNS (7);
4916 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
4924 *total
= COSTS_N_INSNS (1);
4930 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
4934 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
4935 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
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
);
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
);
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
);
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);
4968 *total
= COSTS_N_INSNS (2);
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);
4980 *total
= COSTS_N_INSNS (4);
4986 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
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
);
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
);
5009 *total
= COSTS_N_INSNS (!speed
? 3 : 4);
5011 *total
= COSTS_N_INSNS (AVR_HAVE_JMP_CALL
? 2 : 1);
5018 *total
= COSTS_N_INSNS (!speed
? 7 : 10);
5020 *total
= COSTS_N_INSNS (AVR_HAVE_JMP_CALL
? 2 : 1);
5028 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
5029 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5037 *total
= COSTS_N_INSNS (AVR_HAVE_JMP_CALL
? 2 : 1);
5040 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
5041 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5048 if (CONST_INT_P (XEXP (x
, 1)) && INTVAL (XEXP (x
, 1)) == 4)
5049 *total
= COSTS_N_INSNS (1);
5054 if (CONST_INT_P (XEXP (x
, 1)) && INTVAL (XEXP (x
, 1)) == 8)
5055 *total
= COSTS_N_INSNS (3);
5060 if (CONST_INT_P (XEXP (x
, 1)))
5061 switch (INTVAL (XEXP (x
, 1)))
5065 *total
= COSTS_N_INSNS (5);
5068 *total
= COSTS_N_INSNS (AVR_HAVE_MOVW
? 4 : 6);
5076 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
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
);
5090 val
= INTVAL (XEXP (x
, 1));
5092 *total
= COSTS_N_INSNS (3);
5093 else if (val
>= 0 && val
<= 7)
5094 *total
= COSTS_N_INSNS (val
);
5096 *total
= COSTS_N_INSNS (1);
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
);
5107 switch (INTVAL (XEXP (x
, 1)))
5114 *total
= COSTS_N_INSNS (2);
5117 *total
= COSTS_N_INSNS (3);
5123 *total
= COSTS_N_INSNS (4);
5128 *total
= COSTS_N_INSNS (5);
5131 *total
= COSTS_N_INSNS (!speed
? 5 : 8);
5134 *total
= COSTS_N_INSNS (!speed
? 5 : 9);
5137 *total
= COSTS_N_INSNS (!speed
? 5 : 10);
5140 *total
= COSTS_N_INSNS (!speed
? 5 : 41);
5141 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
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
);
5152 switch (INTVAL (XEXP (x
, 1)))
5158 *total
= COSTS_N_INSNS (3);
5163 *total
= COSTS_N_INSNS (4);
5166 *total
= COSTS_N_INSNS (6);
5169 *total
= COSTS_N_INSNS (!speed
? 7 : 8);
5172 *total
= COSTS_N_INSNS (!speed
? 7 : 113);
5173 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5180 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
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
);
5194 val
= INTVAL (XEXP (x
, 1));
5196 *total
= COSTS_N_INSNS (4);
5198 *total
= COSTS_N_INSNS (2);
5199 else if (val
>= 0 && val
<= 7)
5200 *total
= COSTS_N_INSNS (val
);
5202 *total
= COSTS_N_INSNS (1);
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
);
5213 switch (INTVAL (XEXP (x
, 1)))
5219 *total
= COSTS_N_INSNS (2);
5222 *total
= COSTS_N_INSNS (3);
5228 *total
= COSTS_N_INSNS (4);
5232 *total
= COSTS_N_INSNS (5);
5235 *total
= COSTS_N_INSNS (!speed
? 5 : 6);
5238 *total
= COSTS_N_INSNS (!speed
? 5 : 7);
5242 *total
= COSTS_N_INSNS (!speed
? 5 : 8);
5245 *total
= COSTS_N_INSNS (!speed
? 5 : 41);
5246 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
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
);
5257 switch (INTVAL (XEXP (x
, 1)))
5263 *total
= COSTS_N_INSNS (4);
5268 *total
= COSTS_N_INSNS (6);
5271 *total
= COSTS_N_INSNS (!speed
? 7 : 8);
5274 *total
= COSTS_N_INSNS (AVR_HAVE_MOVW
? 4 : 5);
5277 *total
= COSTS_N_INSNS (!speed
? 7 : 113);
5278 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5285 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
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
);
5299 val
= INTVAL (XEXP (x
, 1));
5301 *total
= COSTS_N_INSNS (3);
5302 else if (val
>= 0 && val
<= 7)
5303 *total
= COSTS_N_INSNS (val
);
5305 *total
= COSTS_N_INSNS (1);
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
);
5316 switch (INTVAL (XEXP (x
, 1)))
5323 *total
= COSTS_N_INSNS (2);
5326 *total
= COSTS_N_INSNS (3);
5331 *total
= COSTS_N_INSNS (4);
5335 *total
= COSTS_N_INSNS (5);
5341 *total
= COSTS_N_INSNS (!speed
? 5 : 6);
5344 *total
= COSTS_N_INSNS (!speed
? 5 : 7);
5348 *total
= COSTS_N_INSNS (!speed
? 5 : 9);
5351 *total
= COSTS_N_INSNS (!speed
? 5 : 41);
5352 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
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
);
5363 switch (INTVAL (XEXP (x
, 1)))
5369 *total
= COSTS_N_INSNS (4);
5372 *total
= COSTS_N_INSNS (!speed
? 7 : 8);
5377 *total
= COSTS_N_INSNS (4);
5380 *total
= COSTS_N_INSNS (6);
5383 *total
= COSTS_N_INSNS (!speed
? 7 : 113);
5384 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, speed
);
5391 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
5395 switch (GET_MODE (XEXP (x
, 0)))
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
);
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);
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);
5422 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, speed
);
5431 /* Calculate the cost of a memory address. */
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)
5441 if (CONSTANT_ADDRESS_P (x
))
5443 if (optimize
> 0 && io_address_operand (x
, QImode
))
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
);
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 */
5483 /* Convert condition code CONDITION to the valid AVR condition code. */
5486 avr_normalize_condition (RTX_CODE condition
)
5503 /* This function optimizes conditional jumps. */
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
))
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)
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
);
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
)
5612 if (TYPE_MODE (type
) != BLKmode
)
5613 return avr_libcall_value (TYPE_MODE (type
));
5615 offs
= int_size_in_bytes (type
);
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
5631 preferred_reload_class (rtx x ATTRIBUTE_UNUSED
, enum reg_class rclass
)
5637 test_hard_reg_class (enum reg_class rclass
, rtx x
)
5639 int regno
= true_regnum (x
);
5643 if (TEST_HARD_REG_CLASS (rclass
, regno
))
5651 jump_over_one_insn_p (rtx insn
, rtx dest
)
5653 int uid
= INSN_UID (GET_CODE (dest
) == LABEL_REF
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
)
5673 /* The only thing that can go into registers r28:r29 is a Pmode. */
5674 if (regno
== REG_Y
&& mode
== Pmode
)
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))
5684 /* Modes larger than QImode occupy consecutive registers. */
5685 if (regno
+ GET_MODE_SIZE (mode
) > FIRST_PSEUDO_REGISTER
)
5688 /* All modes larger than QImode should start in an even register. */
5689 return !(regno
& 1);
5693 output_reload_inhi (rtx insn ATTRIBUTE_UNUSED
, rtx
*operands
, int *len
)
5699 if (GET_CODE (operands
[1]) == CONST_INT
)
5701 int val
= INTVAL (operands
[1]);
5702 if ((val
& 0xff) == 0)
5705 return (AS2 (mov
,%A0
,__zero_reg__
) CR_TAB
5706 AS2 (ldi
,%2,hi8(%1)) CR_TAB
5709 else if ((val
& 0xff00) == 0)
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))
5719 return (AS2 (ldi
,%2,lo8(%1)) CR_TAB
5720 AS2 (mov
,%A0
,%2) CR_TAB
5725 return (AS2 (ldi
,%2,lo8(%1)) CR_TAB
5726 AS2 (mov
,%A0
,%2) CR_TAB
5727 AS2 (ldi
,%2,hi8(%1)) CR_TAB
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
);
5741 *len
= 4 + ((INTVAL (src
) & 0xff) != 0)
5742 + ((INTVAL (src
) & 0xff00) != 0)
5743 + ((INTVAL (src
) & 0xff0000) != 0)
5744 + ((INTVAL (src
) & 0xff000000) != 0);
5751 if (cnst
&& ((INTVAL (src
) & 0xff) == 0))
5752 output_asm_insn (AS2 (mov
, %A0
, __zero_reg__
), operands
);
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
);
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
);
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
);
5776 output_asm_insn (AS2 (ldi
, %2, hhi8(%1)), operands
);
5777 output_asm_insn (AS2 (mov
, %D0
, %2), operands
);
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
);
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
);
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. */
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
))
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
5828 if ((cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
)
5829 && !df_regs_ever_live_p (new_reg
))
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. */
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]);
5852 else if (comp
== LT
)
5856 comp
= reverse_condition (comp
);
5858 if (GET_CODE (operands
[1]) == CONST_INT
)
5860 if (INTVAL (operands
[1]) < 0x40)
5863 output_asm_insn (AS2 (sbis
,%1-0x20,%2), operands
);
5865 output_asm_insn (AS2 (sbic
,%1-0x20,%2), operands
);
5869 output_asm_insn (AS2 (in
,__tmp_reg__
,%1-0x20), operands
);
5871 output_asm_insn (AS2 (sbrs
,__tmp_reg__
,%2), operands
);
5873 output_asm_insn (AS2 (sbrc
,__tmp_reg__
,%2), operands
);
5876 else /* GET_CODE (operands[1]) == REG */
5878 if (GET_MODE (operands
[1]) == QImode
)
5881 output_asm_insn (AS2 (sbrs
,%1,%2), operands
);
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
);
5899 return (AS1 (rjmp
,.+4) CR_TAB
5902 return AS1 (rjmp
,%3);
5906 /* Worker function for TARGET_ASM_CONSTRUCTOR. */
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. */
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. */
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);
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;