1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2 Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3 Contributed by Denis Chertykov (denisc@overta.ru)
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
26 #include "hard-reg-set.h"
28 #include "insn-config.h"
29 #include "conditions.h"
30 #include "insn-attr.h"
42 #include "target-def.h"
44 /* Maximal allowed offset for an address in the LD command */
45 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
47 static int avr_naked_function_p
PARAMS ((tree
));
48 static int interrupt_function_p
PARAMS ((tree
));
49 static int signal_function_p
PARAMS ((tree
));
50 static int avr_regs_to_save
PARAMS ((HARD_REG_SET
*));
51 static int sequent_regs_live
PARAMS ((void));
52 static const char * ptrreg_to_str
PARAMS ((int));
53 static const char * cond_string
PARAMS ((enum rtx_code
));
54 static int avr_num_arg_regs
PARAMS ((enum machine_mode
, tree
));
55 static int out_adj_frame_ptr
PARAMS ((FILE *, int));
56 static int out_set_stack_ptr
PARAMS ((FILE *, int, int));
57 static RTX_CODE compare_condition
PARAMS ((rtx insn
));
58 static int compare_sign_p
PARAMS ((rtx insn
));
59 static int reg_was_0
PARAMS ((rtx insn
, rtx op
));
60 static tree avr_handle_progmem_attribute
PARAMS ((tree
*, tree
, tree
, int, bool *));
61 static tree avr_handle_fndecl_attribute
PARAMS ((tree
*, tree
, tree
, int, bool *));
62 const struct attribute_spec avr_attribute_table
[];
63 static bool avr_assemble_integer
PARAMS ((rtx
, unsigned int, int));
64 static void avr_output_function_prologue
PARAMS ((FILE *, HOST_WIDE_INT
));
65 static void avr_output_function_epilogue
PARAMS ((FILE *, HOST_WIDE_INT
));
66 static void avr_unique_section
PARAMS ((tree
, int));
67 static void avr_encode_section_info
PARAMS ((tree
, int));
68 static unsigned int avr_section_type_flags
PARAMS ((tree
, const char *, int));
70 static void avr_asm_out_ctor
PARAMS ((rtx
, int));
71 static void avr_asm_out_dtor
PARAMS ((rtx
, int));
73 /* Allocate registers from r25 to r8 for parameters for function calls */
74 #define FIRST_CUM_REG 26
76 /* Temporary register RTX (gen_rtx (REG,QImode,TMP_REGNO)) */
79 /* Zeroed register RTX (gen_rtx (REG,QImode,ZERO_REGNO)) */
82 /* RTX for register which will be used for loading immediate values to
86 /* AVR register names {"r0", "r1", ..., "r31"} */
87 static const char *const avr_regnames
[] = REGISTER_NAMES
;
89 /* This holds the last insn address. */
90 static int last_insn_address
= 0;
92 /* Commands count in the compiled file */
93 static int commands_in_file
;
95 /* Commands in the functions prologues in the compiled file */
96 static int commands_in_prologues
;
98 /* Commands in the functions epilogues in the compiled file */
99 static int commands_in_epilogues
;
101 /* Prologue/Epilogue size in words */
102 static int prologue_size
;
103 static int epilogue_size
;
105 /* Size of all jump tables in the current function, in words. */
106 static int jump_tables_size
;
108 /* Initial stack value specified by the `-minit-stack=' option */
109 const char *avr_init_stack
= "__stack";
111 /* Default MCU name */
112 const char *avr_mcu_name
= "avr2";
114 /* Preprocessor macros to define depending on MCU type. */
115 const char *avr_base_arch_macro
;
116 const char *avr_extra_arch_macro
;
118 /* More than 8K of program memory: use "call" and "jmp". */
121 /* Enhanced core: use "movw", "mul", ... */
122 int avr_enhanced_p
= 0;
124 /* Assembler only. */
125 int avr_asm_only_p
= 0;
131 const char *const macro
;
134 static const struct base_arch_s avr_arch_types
[] = {
135 { 1, 0, 0, NULL
}, /* unknown device specified */
136 { 1, 0, 0, "__AVR_ARCH__=1" },
137 { 0, 0, 0, "__AVR_ARCH__=2" },
138 { 0, 0, 1, "__AVR_ARCH__=3" },
139 { 0, 1, 0, "__AVR_ARCH__=4" },
140 { 0, 1, 1, "__AVR_ARCH__=5" }
144 const char *const name
;
145 int arch
; /* index in avr_arch_types[] */
146 /* Must lie outside user's namespace. NULL == no macro. */
147 const char *const macro
;
150 /* List of all known AVR MCU types - if updated, it has to be kept
151 in sync in several places (FIXME: is there a better way?):
153 - avr.h (CPP_SPEC, LINK_SPEC, CRT_BINUTILS_SPECS)
154 - t-avr (MULTILIB_MATCHES)
155 - gas/config/tc-avr.c
158 static const struct mcu_type_s avr_mcu_types
[] = {
159 /* Classic, <= 8K. */
161 { "at90s2313", 2, "__AVR_AT90S2313__" },
162 { "at90s2323", 2, "__AVR_AT90S2323__" },
163 { "at90s2333", 2, "__AVR_AT90S2333__" },
164 { "at90s2343", 2, "__AVR_AT90S2343__" },
165 { "attiny22", 2, "__AVR_ATtiny22__" },
166 { "attiny26", 2, "__AVR_ATtiny26__" },
167 { "at90s4414", 2, "__AVR_AT90S4414__" },
168 { "at90s4433", 2, "__AVR_AT90S4433__" },
169 { "at90s4434", 2, "__AVR_AT90S4434__" },
170 { "at90s8515", 2, "__AVR_AT90S8515__" },
171 { "at90c8534", 2, "__AVR_AT90C8534__" },
172 { "at90s8535", 2, "__AVR_AT90S8535__" },
173 { "at86rf401", 2, "__AVR_AT86RF401__" },
176 { "atmega103", 3, "__AVR_ATmega103__" },
177 { "atmega603", 3, "__AVR_ATmega603__" },
178 { "at43usb320", 3, "__AVR_AT43USB320__" },
179 { "at43usb355", 3, "__AVR_AT43USB355__" },
180 { "at76c711", 3, "__AVR_AT76C711__" },
181 /* Enhanced, <= 8K. */
183 { "atmega8", 4, "__AVR_ATmega8__" },
184 { "atmega8515", 4, "__AVR_ATmega8515__" },
185 { "atmega8535", 4, "__AVR_ATmega8535__" },
186 /* Enhanced, > 8K. */
188 { "atmega16", 5, "__AVR_ATmega16__" },
189 { "atmega161", 5, "__AVR_ATmega161__" },
190 { "atmega162", 5, "__AVR_ATmega162__" },
191 { "atmega163", 5, "__AVR_ATmega163__" },
192 { "atmega169", 5, "__AVR_ATmega169__" },
193 { "atmega32", 5, "__AVR_ATmega32__" },
194 { "atmega323", 5, "__AVR_ATmega323__" },
195 { "atmega64", 5, "__AVR_ATmega64__" },
196 { "atmega128", 5, "__AVR_ATmega128__" },
197 { "at94k", 5, "__AVR_AT94K__" },
198 /* Assembler only. */
200 { "at90s1200", 1, "__AVR_AT90S1200__" },
201 { "attiny11", 1, "__AVR_ATtiny11__" },
202 { "attiny12", 1, "__AVR_ATtiny12__" },
203 { "attiny15", 1, "__AVR_ATtiny15__" },
204 { "attiny28", 1, "__AVR_ATtiny28__" },
208 int avr_case_values_threshold
= 30000;
210 /* Initialize the GCC target structure. */
211 #undef TARGET_ASM_ALIGNED_HI_OP
212 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
213 #undef TARGET_ASM_INTEGER
214 #define TARGET_ASM_INTEGER avr_assemble_integer
216 #undef TARGET_ASM_FUNCTION_PROLOGUE
217 #define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
218 #undef TARGET_ASM_FUNCTION_EPILOGUE
219 #define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
220 #undef TARGET_ATTRIBUTE_TABLE
221 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
222 #undef TARGET_ASM_UNIQUE_SECTION
223 #define TARGET_ASM_UNIQUE_SECTION avr_unique_section
224 #undef TARGET_ENCODE_SECTION_INFO
225 #define TARGET_ENCODE_SECTION_INFO avr_encode_section_info
226 #undef TARGET_SECTION_TYPE_FLAGS
227 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
229 struct gcc_target targetm
= TARGET_INITIALIZER
;
232 avr_override_options ()
234 const struct mcu_type_s
*t
;
235 const struct base_arch_s
*base
;
237 for (t
= avr_mcu_types
; t
->name
; t
++)
238 if (strcmp (t
->name
, avr_mcu_name
) == 0)
243 fprintf (stderr
, "unknown MCU `%s' specified\nKnown MCU names:\n",
245 for (t
= avr_mcu_types
; t
->name
; t
++)
246 fprintf (stderr
," %s\n", t
->name
);
249 base
= &avr_arch_types
[t
->arch
];
250 avr_asm_only_p
= base
->asm_only
;
251 avr_enhanced_p
= base
->enhanced
;
252 avr_mega_p
= base
->mega
;
253 avr_base_arch_macro
= base
->macro
;
254 avr_extra_arch_macro
= t
->macro
;
256 if (optimize
&& !TARGET_NO_TABLEJUMP
)
257 avr_case_values_threshold
= (!AVR_MEGA
|| TARGET_CALL_PROLOGUES
) ? 8 : 17;
261 /* Initialize TMP_REG_RTX and ZERO_REG_RTX */
265 tmp_reg_rtx
= xmalloc (sizeof (struct rtx_def
) + 1 * sizeof (rtunion
));
266 memset (tmp_reg_rtx
, 0, sizeof (struct rtx_def
) + 1 * sizeof (rtunion
));
267 PUT_CODE (tmp_reg_rtx
, REG
);
268 PUT_MODE (tmp_reg_rtx
, QImode
);
269 XINT (tmp_reg_rtx
, 0) = TMP_REGNO
;
271 zero_reg_rtx
= xmalloc (sizeof (struct rtx_def
) + 1 * sizeof (rtunion
));
272 memset (zero_reg_rtx
, 0, sizeof (struct rtx_def
) + 1 * sizeof (rtunion
));
273 PUT_CODE (zero_reg_rtx
, REG
);
274 PUT_MODE (zero_reg_rtx
, QImode
);
275 XINT (zero_reg_rtx
, 0) = ZERO_REGNO
;
277 ldi_reg_rtx
= xmalloc (sizeof (struct rtx_def
) + 1 * sizeof (rtunion
));
278 memset (ldi_reg_rtx
, 0, sizeof (struct rtx_def
) + 1 * sizeof (rtunion
));
279 PUT_CODE (ldi_reg_rtx
, REG
);
280 PUT_MODE (ldi_reg_rtx
, QImode
);
281 XINT (ldi_reg_rtx
, 0) = LDI_REG_REGNO
;
284 /* return register class from register number */
286 static const int reg_class_tab
[]={
287 GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,
288 GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,
289 GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,
290 GENERAL_REGS
, /* r0 - r15 */
291 LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,
292 LD_REGS
, /* r16 - 23 */
293 ADDW_REGS
,ADDW_REGS
, /* r24,r25 */
294 POINTER_X_REGS
,POINTER_X_REGS
, /* r26,27 */
295 POINTER_Y_REGS
,POINTER_Y_REGS
, /* r28,r29 */
296 POINTER_Z_REGS
,POINTER_Z_REGS
, /* r30,r31 */
297 STACK_REG
,STACK_REG
/* SPL,SPH */
300 /* Return register class for register R */
303 avr_regno_reg_class (r
)
307 return reg_class_tab
[r
];
312 /* A C expression which defines the machine-dependent operand
313 constraint letters for register classes. If C is such a
314 letter, the value should be the register class corresponding to
315 it. Otherwise, the value should be `NO_REGS'. The register
316 letter `r', corresponding to class `GENERAL_REGS', will not be
317 passed to this macro; you do not need to handle it. */
320 avr_reg_class_from_letter (c
)
325 case 't' : return R0_REG
;
326 case 'b' : return BASE_POINTER_REGS
;
327 case 'e' : return POINTER_REGS
;
328 case 'w' : return ADDW_REGS
;
329 case 'd' : return LD_REGS
;
330 case 'l' : return NO_LD_REGS
;
331 case 'a' : return SIMPLE_LD_REGS
;
332 case 'x' : return POINTER_X_REGS
;
333 case 'y' : return POINTER_Y_REGS
;
334 case 'z' : return POINTER_Z_REGS
;
335 case 'q' : return STACK_REG
;
341 /* Return nonzero if FUNC is a naked function. */
344 avr_naked_function_p (func
)
349 if (TREE_CODE (func
) != FUNCTION_DECL
)
352 a
= lookup_attribute ("naked", DECL_ATTRIBUTES (func
));
353 return a
!= NULL_TREE
;
356 /* Return nonzero if FUNC is an interrupt function as specified
357 by the "interrupt" attribute. */
360 interrupt_function_p (func
)
365 if (TREE_CODE (func
) != FUNCTION_DECL
)
368 a
= lookup_attribute ("interrupt", DECL_ATTRIBUTES (func
));
369 return a
!= NULL_TREE
;
372 /* Return nonzero if FUNC is a signal function as specified
373 by the "signal" attribute. */
376 signal_function_p (func
)
381 if (TREE_CODE (func
) != FUNCTION_DECL
)
384 a
= lookup_attribute ("signal", DECL_ATTRIBUTES (func
));
385 return a
!= NULL_TREE
;
388 /* Return the number of hard registers to push/pop in the prologue/epilogue
389 of the current function, and optionally store these registers in SET. */
392 avr_regs_to_save (set
)
396 int int_or_sig_p
= (interrupt_function_p (current_function_decl
)
397 || signal_function_p (current_function_decl
));
398 int leaf_func_p
= leaf_function_p ();
401 CLEAR_HARD_REG_SET (*set
);
404 /* No need to save any registers if the function never returns. */
405 if (TREE_THIS_VOLATILE (current_function_decl
))
408 for (reg
= 0; reg
< 32; reg
++)
410 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
411 any global register variables. */
415 if ((int_or_sig_p
&& !leaf_func_p
&& call_used_regs
[reg
])
416 || (regs_ever_live
[reg
]
417 && (int_or_sig_p
|| !call_used_regs
[reg
])
418 && !(frame_pointer_needed
419 && (reg
== REG_Y
|| reg
== (REG_Y
+1)))))
422 SET_HARD_REG_BIT (*set
, reg
);
429 /* Compute offset between arg_pointer and frame_pointer */
432 initial_elimination_offset (from
, to
)
436 if (from
== FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
440 int offset
= frame_pointer_needed
? 2 : 0;
442 offset
+= avr_regs_to_save (NULL
);
443 return get_frame_size () + 2 + 1 + offset
;
447 /* Return 1 if the function epilogue is just a single "ret". */
450 avr_simple_epilogue ()
452 return (! frame_pointer_needed
453 && get_frame_size () == 0
454 && avr_regs_to_save (NULL
) == 0
455 && ! interrupt_function_p (current_function_decl
)
456 && ! signal_function_p (current_function_decl
)
457 && ! avr_naked_function_p (current_function_decl
)
458 && ! MAIN_NAME_P (DECL_NAME (current_function_decl
))
459 && ! TREE_THIS_VOLATILE (current_function_decl
));
462 /* This function checks sequence of live registers */
471 for (reg
= 0; reg
< 18; ++reg
)
473 if (!call_used_regs
[reg
])
475 if (regs_ever_live
[reg
])
485 if (!frame_pointer_needed
)
487 if (regs_ever_live
[REG_Y
])
495 if (regs_ever_live
[REG_Y
+1])
508 return (cur_seq
== live_seq
) ? live_seq
: 0;
512 /* Output to FILE the asm instructions to adjust the frame pointer by
513 ADJ (r29:r28 -= ADJ;) which can be positive (prologue) or negative
514 (epilogue). Returns the number of instructions generated. */
517 out_adj_frame_ptr (file
, adj
)
525 if (TARGET_TINY_STACK
)
527 if (adj
< -63 || adj
> 63)
528 warning ("large frame pointer change (%d) with -mtiny-stack", adj
);
530 /* The high byte (r29) doesn't change - prefer "subi" (1 cycle)
531 over "sbiw" (2 cycles, same size). */
533 fprintf (file
, (AS2 (subi
, r28
, %d
) CR_TAB
), adj
);
536 else if (adj
< -63 || adj
> 63)
538 fprintf (file
, (AS2 (subi
, r28
, lo8(%d
)) CR_TAB
539 AS2 (sbci
, r29
, hi8(%d
)) CR_TAB
),
545 fprintf (file
, (AS2 (adiw
, r28
, %d
) CR_TAB
), -adj
);
550 fprintf (file
, (AS2 (sbiw
, r28
, %d
) CR_TAB
), adj
);
558 /* Output to FILE the asm instructions to copy r29:r28 to SPH:SPL,
559 handling various cases of interrupt enable flag state BEFORE and AFTER
560 (0=disabled, 1=enabled, -1=unknown/unchanged) and target_flags.
561 Returns the number of instructions generated. */
564 out_set_stack_ptr (file
, before
, after
)
569 int do_sph
, do_cli
, do_save
, do_sei
, lock_sph
, size
;
571 /* The logic here is so that -mno-interrupts actually means
572 "it is safe to write SPH in one instruction, then SPL in the
573 next instruction, without disabling interrupts first".
574 The after != -1 case (interrupt/signal) is not affected. */
576 do_sph
= !TARGET_TINY_STACK
;
577 lock_sph
= do_sph
&& !TARGET_NO_INTERRUPTS
;
578 do_cli
= (before
!= 0 && (after
== 0 || lock_sph
));
579 do_save
= (do_cli
&& before
== -1 && after
== -1);
580 do_sei
= ((do_cli
|| before
!= 1) && after
== 1);
585 fprintf (file
, AS2 (in
, __tmp_reg__
, __SREG__
) CR_TAB
);
591 fprintf (file
, "cli" CR_TAB
);
595 /* Do SPH first - maybe this will disable interrupts for one instruction
596 someday (a suggestion has been sent to avr@atmel.com for consideration
597 in future devices - that would make -mno-interrupts always safe). */
600 fprintf (file
, AS2 (out
, __SP_H__
, r29
) CR_TAB
);
604 /* Set/restore the I flag now - interrupts will be really enabled only
605 after the next instruction. This is not clearly documented, but
606 believed to be true for all AVR devices. */
609 fprintf (file
, AS2 (out
, __SREG__
, __tmp_reg__
) CR_TAB
);
614 fprintf (file
, "sei" CR_TAB
);
618 fprintf (file
, AS2 (out
, __SP_L__
, r28
) "\n");
624 /* Output function prologue */
627 avr_output_function_prologue (file
, size
)
632 int interrupt_func_p
;
638 last_insn_address
= 0;
639 jump_tables_size
= 0;
641 fprintf (file
, "/* prologue: frame size=%d */\n", size
);
643 if (avr_naked_function_p (current_function_decl
))
645 fputs ("/* prologue: naked */\n", file
);
649 interrupt_func_p
= interrupt_function_p (current_function_decl
);
650 signal_func_p
= signal_function_p (current_function_decl
);
651 main_p
= MAIN_NAME_P (DECL_NAME (current_function_decl
));
652 live_seq
= sequent_regs_live ();
653 minimize
= (TARGET_CALL_PROLOGUES
654 && !interrupt_func_p
&& !signal_func_p
&& live_seq
);
656 if (interrupt_func_p
)
658 fprintf (file
,"\tsei\n");
661 if (interrupt_func_p
|| signal_func_p
)
664 AS1 (push
,__zero_reg__
) CR_TAB
665 AS1 (push
,__tmp_reg__
) CR_TAB
666 AS2 (in
,__tmp_reg__
,__SREG__
) CR_TAB
667 AS1 (push
,__tmp_reg__
) CR_TAB
668 AS1 (clr
,__zero_reg__
) "\n");
674 AS2 (ldi
,r28
,lo8(%s
- %d
)) CR_TAB
675 AS2 (ldi
,r29
,hi8(%s
- %d
)) CR_TAB
676 AS2 (out
,__SP_H__
,r29
) CR_TAB
677 AS2 (out
,__SP_L__
,r28
) "\n"),
678 avr_init_stack
, size
, avr_init_stack
, size
);
682 else if (minimize
&& (frame_pointer_needed
|| live_seq
> 6))
685 AS2 (ldi
, r26
, lo8(%d
)) CR_TAB
686 AS2 (ldi
, r27
, hi8(%d
)) CR_TAB
), size
, size
);
688 fprintf (file
, (AS2 (ldi
, r30
, pm_lo8(.L_
%s_body
)) CR_TAB
689 AS2 (ldi
, r31
, pm_hi8(.L_
%s_body
)) CR_TAB
)
690 ,current_function_name
, current_function_name
);
696 fprintf (file
, AS1 (jmp
,__prologue_saves__
+%d
) "\n",
697 (18 - live_seq
) * 2);
702 fprintf (file
, AS1 (rjmp
,__prologue_saves__
+%d
) "\n",
703 (18 - live_seq
) * 2);
706 fprintf (file
, ".L_%s_body:\n", current_function_name
);
712 prologue_size
+= avr_regs_to_save (&set
);
713 for (reg
= 0; reg
< 32; ++reg
)
715 if (TEST_HARD_REG_BIT (set
, reg
))
717 fprintf (file
, "\t" AS1 (push
,%s
) "\n", avr_regnames
[reg
]);
720 if (frame_pointer_needed
)
724 AS1 (push
,r28
) CR_TAB
725 AS1 (push
,r29
) CR_TAB
726 AS2 (in
,r28
,__SP_L__
) CR_TAB
727 AS2 (in
,r29
,__SP_H__
) "\n");
732 prologue_size
+= out_adj_frame_ptr (file
, size
);
734 if (interrupt_func_p
)
736 prologue_size
+= out_set_stack_ptr (file
, 1, 1);
738 else if (signal_func_p
)
740 prologue_size
+= out_set_stack_ptr (file
, 0, 0);
744 prologue_size
+= out_set_stack_ptr (file
, -1, -1);
752 fprintf (file
, "/* prologue end (size=%d) */\n", prologue_size
);
755 /* Output function epilogue */
758 avr_output_function_epilogue (file
, size
)
763 int interrupt_func_p
;
769 rtx last
= get_last_nonnote_insn ();
771 function_size
= jump_tables_size
;
774 rtx first
= get_first_nonnote_insn ();
775 function_size
+= (INSN_ADDRESSES (INSN_UID (last
)) -
776 INSN_ADDRESSES (INSN_UID (first
)));
777 function_size
+= get_attr_length (last
);
780 fprintf (file
, "/* epilogue: frame size=%d */\n", size
);
783 if (avr_naked_function_p (current_function_decl
))
785 fputs ("/* epilogue: naked */\n", file
);
789 if (last
&& GET_CODE (last
) == BARRIER
)
791 fputs ("/* epilogue: noreturn */\n", file
);
795 interrupt_func_p
= interrupt_function_p (current_function_decl
);
796 signal_func_p
= signal_function_p (current_function_decl
);
797 main_p
= MAIN_NAME_P (DECL_NAME (current_function_decl
));
798 live_seq
= sequent_regs_live ();
799 minimize
= (TARGET_CALL_PROLOGUES
800 && !interrupt_func_p
&& !signal_func_p
&& live_seq
);
804 /* Return value from main() is already in the correct registers
805 (r25:r24) as the exit() argument. */
808 fputs ("\t" AS1 (jmp
,exit
) "\n", file
);
813 fputs ("\t" AS1 (rjmp
,exit
) "\n", file
);
817 else if (minimize
&& (frame_pointer_needed
|| live_seq
> 4))
819 fprintf (file
, ("\t" AS2 (ldi
, r30
, %d
) CR_TAB
), live_seq
);
821 if (frame_pointer_needed
)
823 epilogue_size
+= out_adj_frame_ptr (file
, -size
);
827 fprintf (file
, (AS2 (in
, r28
, __SP_L__
) CR_TAB
828 AS2 (in
, r29
, __SP_H__
) CR_TAB
));
834 fprintf (file
, AS1 (jmp
,__epilogue_restores__
+%d
) "\n",
835 (18 - live_seq
) * 2);
840 fprintf (file
, AS1 (rjmp
,__epilogue_restores__
+%d
) "\n",
841 (18 - live_seq
) * 2);
849 if (frame_pointer_needed
)
854 epilogue_size
+= out_adj_frame_ptr (file
, -size
);
856 if (interrupt_func_p
|| signal_func_p
)
858 epilogue_size
+= out_set_stack_ptr (file
, -1, 0);
862 epilogue_size
+= out_set_stack_ptr (file
, -1, -1);
871 epilogue_size
+= avr_regs_to_save (&set
);
872 for (reg
= 31; reg
>= 0; --reg
)
874 if (TEST_HARD_REG_BIT (set
, reg
))
876 fprintf (file
, "\t" AS1 (pop
,%s
) "\n", avr_regnames
[reg
]);
880 if (interrupt_func_p
|| signal_func_p
)
883 AS1 (pop
,__tmp_reg__
) CR_TAB
884 AS2 (out
,__SREG__
,__tmp_reg__
) CR_TAB
885 AS1 (pop
,__tmp_reg__
) CR_TAB
886 AS1 (pop
,__zero_reg__
) "\n");
888 fprintf (file
, "\treti\n");
891 fprintf (file
, "\tret\n");
896 fprintf (file
, "/* epilogue end (size=%d) */\n", epilogue_size
);
897 fprintf (file
, "/* function %s size %d (%d) */\n", current_function_name
,
898 prologue_size
+ function_size
+ epilogue_size
, function_size
);
899 commands_in_file
+= prologue_size
+ function_size
+ epilogue_size
;
900 commands_in_prologues
+= prologue_size
;
901 commands_in_epilogues
+= epilogue_size
;
905 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
906 machine for a memory operand of mode MODE. */
909 legitimate_address_p (mode
, x
, strict
)
910 enum machine_mode mode
;
914 enum reg_class r
= NO_REGS
;
916 if (TARGET_ALL_DEBUG
)
918 fprintf (stderr
, "mode: (%s) %s %s %s %s:",
920 strict
? "(strict)": "",
921 reload_completed
? "(reload_completed)": "",
922 reload_in_progress
? "(reload_in_progress)": "",
923 reg_renumber
? "(reg_renumber)" : "");
924 if (GET_CODE (x
) == PLUS
925 && REG_P (XEXP (x
, 0))
926 && GET_CODE (XEXP (x
, 1)) == CONST_INT
927 && INTVAL (XEXP (x
, 1)) >= 0
928 && INTVAL (XEXP (x
, 1)) <= MAX_LD_OFFSET (mode
)
931 fprintf (stderr
, "(r%d ---> r%d)", REGNO (XEXP (x
, 0)),
932 true_regnum (XEXP (x
, 0)));
935 if (REG_P (x
) && (strict
? REG_OK_FOR_BASE_STRICT_P (x
)
936 : REG_OK_FOR_BASE_NOSTRICT_P (x
)))
938 else if (CONSTANT_ADDRESS_P (x
))
940 else if (GET_CODE (x
) == PLUS
941 && REG_P (XEXP (x
, 0))
942 && GET_CODE (XEXP (x
, 1)) == CONST_INT
943 && INTVAL (XEXP (x
, 1)) >= 0)
945 int fit
= INTVAL (XEXP (x
, 1)) <= MAX_LD_OFFSET (mode
);
949 || REGNO (XEXP (x
,0)) == REG_Y
950 || REGNO (XEXP (x
,0)) == REG_Z
)
951 r
= BASE_POINTER_REGS
;
952 if (XEXP (x
,0) == frame_pointer_rtx
953 || XEXP (x
,0) == arg_pointer_rtx
)
954 r
= BASE_POINTER_REGS
;
956 else if (frame_pointer_needed
&& XEXP (x
,0) == frame_pointer_rtx
)
959 else if ((GET_CODE (x
) == PRE_DEC
|| GET_CODE (x
) == POST_INC
)
960 && REG_P (XEXP (x
, 0))
961 && (strict
? REG_OK_FOR_BASE_STRICT_P (XEXP (x
, 0))
962 : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x
, 0))))
966 if (TARGET_ALL_DEBUG
)
968 fprintf (stderr
, " ret = %c\n", r
);
970 return r
== NO_REGS
? 0 : (int)r
;
973 /* Attempts to replace X with a valid
974 memory address for an operand of mode MODE */
977 legitimize_address (x
, oldx
, mode
)
980 enum machine_mode mode
;
983 if (TARGET_ALL_DEBUG
)
985 fprintf (stderr
, "legitimize_address mode: %s", GET_MODE_NAME(mode
));
989 if (GET_CODE (oldx
) == PLUS
990 && REG_P (XEXP (oldx
,0)))
992 if (REG_P (XEXP (oldx
,1)))
993 x
= force_reg (GET_MODE (oldx
), oldx
);
994 else if (GET_CODE (XEXP (oldx
, 1)) == CONST_INT
)
996 int offs
= INTVAL (XEXP (oldx
,1));
997 if (frame_pointer_rtx
!= XEXP (oldx
,0))
998 if (offs
> MAX_LD_OFFSET (mode
))
1000 if (TARGET_ALL_DEBUG
)
1001 fprintf (stderr
, "force_reg (big offset)\n");
1002 x
= force_reg (GET_MODE (oldx
), oldx
);
1010 /* Return a pointer register name as a string */
1013 ptrreg_to_str (regno
)
1018 case REG_X
: return "X";
1019 case REG_Y
: return "Y";
1020 case REG_Z
: return "Z";
1027 /* Return the condition name as a string.
1028 Used in conditional jump constructing */
1041 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1046 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1059 /* Output ADDR to FILE as address */
1062 print_operand_address (file
, addr
)
1066 switch (GET_CODE (addr
))
1069 fprintf (file
, ptrreg_to_str (REGNO (addr
)));
1073 fprintf (file
, "-%s", ptrreg_to_str (REGNO (XEXP (addr
, 0))));
1077 fprintf (file
, "%s+", ptrreg_to_str (REGNO (XEXP (addr
, 0))));
1081 if (CONSTANT_ADDRESS_P (addr
)
1082 && ((GET_CODE (addr
) == SYMBOL_REF
&& SYMBOL_REF_FLAG (addr
))
1083 || GET_CODE (addr
) == LABEL_REF
))
1085 fprintf (file
, "pm(");
1086 output_addr_const (file
,addr
);
1087 fprintf (file
,")");
1090 output_addr_const (file
, addr
);
1095 /* Output X as assembler operand to file FILE */
1098 print_operand (file
, x
, code
)
1105 if (code
>= 'A' && code
<= 'D')
1115 if (x
== zero_reg_rtx
)
1116 fprintf (file
, "__zero_reg__");
1118 fprintf (file
, reg_names
[true_regnum (x
) + abcd
]);
1120 else if (GET_CODE (x
) == CONST_INT
)
1121 fprintf (file
, "%d", INTVAL (x
) + abcd
);
1122 else if (GET_CODE (x
) == MEM
)
1124 rtx addr
= XEXP (x
,0);
1126 if (CONSTANT_P (addr
) && abcd
)
1129 output_address (addr
);
1130 fprintf (file
, ")+%d", abcd
);
1132 else if (code
== 'o')
1134 if (GET_CODE (addr
) != PLUS
)
1135 fatal_insn ("bad address, not (reg+disp):", addr
);
1137 print_operand (file
, XEXP (addr
, 1), 0);
1139 else if (GET_CODE (addr
) == PLUS
)
1141 print_operand_address (file
, XEXP (addr
,0));
1142 if (REGNO (XEXP (addr
, 0)) == REG_X
)
1143 fatal_insn ("internal compiler error. Bad address:"
1146 print_operand (file
, XEXP (addr
,1), code
);
1149 print_operand_address (file
, addr
);
1151 else if (GET_CODE (x
) == CONST_DOUBLE
)
1155 if (GET_MODE (x
) != SFmode
)
1156 fatal_insn ("internal compiler error. Unknown mode:", x
);
1157 REAL_VALUE_FROM_CONST_DOUBLE (rv
, x
);
1158 REAL_VALUE_TO_TARGET_SINGLE (rv
, val
);
1159 fprintf (file
, "0x%lx", val
);
1161 else if (code
== 'j')
1162 fputs (cond_string (GET_CODE (x
)), file
);
1163 else if (code
== 'k')
1164 fputs (cond_string (reverse_condition (GET_CODE (x
))), file
);
1166 print_operand_address (file
, x
);
1169 /* Recognize operand OP of mode MODE used in call instructions */
1172 call_insn_operand (op
, mode
)
1174 enum machine_mode mode ATTRIBUTE_UNUSED
;
1176 if (GET_CODE (op
) == MEM
)
1178 rtx inside
= XEXP (op
, 0);
1179 if (register_operand (inside
, Pmode
))
1181 if (CONSTANT_ADDRESS_P (inside
))
1187 /* Update the condition code in the INSN. */
1190 notice_update_cc (body
, insn
)
1191 rtx body ATTRIBUTE_UNUSED
;
1196 switch (get_attr_cc (insn
))
1199 /* Insn does not affect CC at all. */
1207 set
= single_set (insn
);
1211 cc_status
.flags
|= CC_NO_OVERFLOW
;
1212 cc_status
.value1
= SET_DEST (set
);
1217 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
1218 The V flag may or may not be known but that's ok because
1219 alter_cond will change tests to use EQ/NE. */
1220 set
= single_set (insn
);
1224 cc_status
.value1
= SET_DEST (set
);
1225 cc_status
.flags
|= CC_OVERFLOW_UNUSABLE
;
1230 set
= single_set (insn
);
1233 cc_status
.value1
= SET_SRC (set
);
1237 /* Insn doesn't leave CC in a usable state. */
1240 /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1241 set
= single_set (insn
);
1244 rtx src
= SET_SRC (set
);
1246 if (GET_CODE (src
) == ASHIFTRT
1247 && GET_MODE (src
) == QImode
)
1249 rtx x
= XEXP (src
, 1);
1251 if (GET_CODE (x
) == CONST_INT
1254 cc_status
.value1
= SET_DEST (set
);
1255 cc_status
.flags
|= CC_OVERFLOW_UNUSABLE
;
1263 /* Return maximum number of consecutive registers of
1264 class CLASS needed to hold a value of mode MODE. */
1267 class_max_nregs (class, mode
)
1268 enum reg_class
class ATTRIBUTE_UNUSED
;
1269 enum machine_mode mode
;
1271 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
);
1274 /* Choose mode for jump insn:
1275 1 - relative jump in range -63 <= x <= 62 ;
1276 2 - relative jump in range -2046 <= x <= 2045 ;
1277 3 - absolute jump (only for ATmega[16]03). */
1280 avr_jump_mode (x
, insn
)
1281 rtx x
; /* jump operand */
1282 rtx insn
; /* jump insn */
1284 int dest_addr
= INSN_ADDRESSES (INSN_UID (GET_MODE (x
) == LABEL_REF
1285 ? XEXP (x
, 0) : x
));
1286 int cur_addr
= INSN_ADDRESSES (INSN_UID (insn
));
1287 int jump_distance
= cur_addr
- dest_addr
;
1289 if (-63 <= jump_distance
&& jump_distance
<= 62)
1291 else if (-2046 <= jump_distance
&& jump_distance
<= 2045)
1299 /* return an AVR condition jump commands.
1300 X is a comparison RTX.
1301 LEN is a number returned by avr_jump_mode function.
1302 if REVERSE nonzero then condition code in X must be reversed. */
1305 ret_cond_branch (x
, len
, reverse
)
1310 RTX_CODE cond
= reverse
? reverse_condition (GET_CODE (x
)) : GET_CODE (x
);
1315 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1316 return (len
== 1 ? (AS1 (breq
,.+2) CR_TAB
1318 len
== 2 ? (AS1 (breq
,.+4) CR_TAB
1319 AS1 (brmi
,.+2) CR_TAB
1321 (AS1 (breq
,.+6) CR_TAB
1322 AS1 (brmi
,.+4) CR_TAB
1326 return (len
== 1 ? (AS1 (breq
,.+2) CR_TAB
1328 len
== 2 ? (AS1 (breq
,.+4) CR_TAB
1329 AS1 (brlt
,.+2) CR_TAB
1331 (AS1 (breq
,.+6) CR_TAB
1332 AS1 (brlt
,.+4) CR_TAB
1335 return (len
== 1 ? (AS1 (breq
,.+2) CR_TAB
1337 len
== 2 ? (AS1 (breq
,.+4) CR_TAB
1338 AS1 (brlo
,.+2) CR_TAB
1340 (AS1 (breq
,.+6) CR_TAB
1341 AS1 (brlo
,.+4) CR_TAB
1344 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1345 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1347 len
== 2 ? (AS1 (breq
,.+2) CR_TAB
1348 AS1 (brpl
,.+2) CR_TAB
1350 (AS1 (breq
,.+2) CR_TAB
1351 AS1 (brpl
,.+4) CR_TAB
1354 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1356 len
== 2 ? (AS1 (breq
,.+2) CR_TAB
1357 AS1 (brge
,.+2) CR_TAB
1359 (AS1 (breq
,.+2) CR_TAB
1360 AS1 (brge
,.+4) CR_TAB
1363 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1365 len
== 2 ? (AS1 (breq
,.+2) CR_TAB
1366 AS1 (brsh
,.+2) CR_TAB
1368 (AS1 (breq
,.+2) CR_TAB
1369 AS1 (brsh
,.+4) CR_TAB
1377 return AS1 (br
%k1
,%0);
1379 return (AS1 (br
%j1
,.+2) CR_TAB
1382 return (AS1 (br
%j1
,.+4) CR_TAB
1391 return AS1 (br
%j1
,%0);
1393 return (AS1 (br
%k1
,.+2) CR_TAB
1396 return (AS1 (br
%k1
,.+4) CR_TAB
1404 /* Predicate function for immediate operand which fits to byte (8bit) */
1407 byte_immediate_operand (op
, mode
)
1409 enum machine_mode mode ATTRIBUTE_UNUSED
;
1411 return (GET_CODE (op
) == CONST_INT
1412 && INTVAL (op
) <= 0xff && INTVAL (op
) >= 0);
1415 /* Output all insn addresses and their sizes into the assembly language
1416 output file. This is helpful for debugging whether the length attributes
1417 in the md file are correct.
1418 Output insn cost for next insn. */
1421 final_prescan_insn (insn
, operand
, num_operands
)
1422 rtx insn
, *operand ATTRIBUTE_UNUSED
;
1423 int num_operands ATTRIBUTE_UNUSED
;
1425 int uid
= INSN_UID (insn
);
1427 if (TARGET_INSN_SIZE_DUMP
|| TARGET_ALL_DEBUG
)
1429 fprintf (asm_out_file
, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
1430 INSN_ADDRESSES (uid
),
1431 INSN_ADDRESSES (uid
) - last_insn_address
,
1432 rtx_cost (PATTERN (insn
), INSN
));
1434 last_insn_address
= INSN_ADDRESSES (uid
);
1436 if (TARGET_RTL_DUMP
)
1438 fprintf (asm_out_file
, "/*****************\n");
1439 print_rtl_single (asm_out_file
, insn
);
1440 fprintf (asm_out_file
, "*****************/\n");
1444 /* Return 0 if undefined, 1 if always true or always false. */
1447 avr_simplify_comparision_p (mode
, operator, x
)
1448 enum machine_mode mode
;
1452 unsigned int max
= (mode
== QImode
? 0xff :
1453 mode
== HImode
? 0xffff :
1454 mode
== SImode
? 0xffffffff : 0);
1455 if (max
&& operator && GET_CODE (x
) == CONST_INT
)
1457 if (unsigned_condition (operator) != operator)
1460 if (max
!= (INTVAL (x
) & max
)
1461 && INTVAL (x
) != 0xff)
1468 /* Returns nonzero if REGNO is the number of a hard
1469 register in which function arguments are sometimes passed. */
1472 function_arg_regno_p(r
)
1475 return (r
>= 8 && r
<= 25);
1478 /* Initializing the variable cum for the state at the beginning
1479 of the argument list. */
1482 init_cumulative_args (cum
, fntype
, libname
, indirect
)
1483 CUMULATIVE_ARGS
*cum
;
1486 int indirect ATTRIBUTE_UNUSED
;
1489 cum
->regno
= FIRST_CUM_REG
;
1490 if (!libname
&& fntype
)
1492 int stdarg
= (TYPE_ARG_TYPES (fntype
) != 0
1493 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype
)))
1494 != void_type_node
));
1500 /* Returns the number of registers to allocate for a function argument. */
1503 avr_num_arg_regs (mode
, type
)
1504 enum machine_mode mode
;
1509 if (mode
== BLKmode
)
1510 size
= int_size_in_bytes (type
);
1512 size
= GET_MODE_SIZE (mode
);
1514 /* Align all function arguments to start in even-numbered registers.
1515 Odd-sized arguments leave holes above them. */
1517 return (size
+ 1) & ~1;
1520 /* Controls whether a function argument is passed
1521 in a register, and which register. */
1524 function_arg (cum
, mode
, type
, named
)
1525 CUMULATIVE_ARGS
*cum
;
1526 enum machine_mode mode
;
1528 int named ATTRIBUTE_UNUSED
;
1530 int bytes
= avr_num_arg_regs (mode
, type
);
1532 if (cum
->nregs
&& bytes
<= cum
->nregs
)
1533 return gen_rtx (REG
, mode
, cum
->regno
- bytes
);
1538 /* Update the summarizer variable CUM to advance past an argument
1539 in the argument list. */
1542 function_arg_advance (cum
, mode
, type
, named
)
1543 CUMULATIVE_ARGS
*cum
; /* current arg information */
1544 enum machine_mode mode
; /* current arg mode */
1545 tree type
; /* type of the argument or 0 if lib support */
1546 int named ATTRIBUTE_UNUSED
; /* whether or not the argument was named */
1548 int bytes
= avr_num_arg_regs (mode
, type
);
1550 cum
->nregs
-= bytes
;
1551 cum
->regno
-= bytes
;
1553 if (cum
->nregs
<= 0)
1556 cum
->regno
= FIRST_CUM_REG
;
1560 /***********************************************************************
1561 Functions for outputting various mov's for a various modes
1562 ************************************************************************/
1564 output_movqi (insn
, operands
, l
)
1570 rtx dest
= operands
[0];
1571 rtx src
= operands
[1];
1579 if (register_operand (dest
, QImode
))
1581 if (register_operand (src
, QImode
)) /* mov r,r */
1583 if (test_hard_reg_class (STACK_REG
, dest
))
1584 return AS2 (out
,%0,%1);
1585 else if (test_hard_reg_class (STACK_REG
, src
))
1586 return AS2 (in
,%0,%1);
1588 return AS2 (mov
,%0,%1);
1590 else if (CONSTANT_P (src
))
1592 if (test_hard_reg_class (LD_REGS
, dest
)) /* ldi d,i */
1593 return AS2 (ldi
,%0,lo8(%1));
1595 if (GET_CODE (src
) == CONST_INT
)
1597 if (src
== const0_rtx
) /* mov r,L */
1598 return AS1 (clr
,%0);
1599 else if (src
== const1_rtx
)
1601 if (reg_was_0 (insn
, dest
))
1602 return AS1 (inc
,%0 ; reg_was_0
);
1605 return (AS1 (clr
,%0) CR_TAB
1608 else if (src
== constm1_rtx
)
1610 /* Immediate constants -1 to any register */
1611 if (reg_was_0 (insn
, dest
))
1612 return AS1 (dec
,%0 ; reg_was_0
);
1615 return (AS1 (clr
,%0) CR_TAB
1620 int bit_nr
= exact_log2 (INTVAL (src
));
1624 if (reg_was_0 (insn
, dest
))
1628 output_asm_insn ("set ; reg_was_0", operands
);
1634 output_asm_insn ((AS1 (clr
,%0) CR_TAB
1638 avr_output_bld (operands
, bit_nr
);
1645 /* Last resort, larger than loading from memory. */
1647 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1648 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
1649 AS2 (mov
,%0,r31
) CR_TAB
1650 AS2 (mov
,r31
,__tmp_reg__
));
1652 else if (GET_CODE (src
) == MEM
)
1653 return out_movqi_r_mr (insn
, operands
, real_l
); /* mov r,m */
1655 else if (GET_CODE (dest
) == MEM
)
1657 const char *template;
1659 if (src
== const0_rtx
)
1660 operands
[1] = zero_reg_rtx
;
1662 template = out_movqi_mr_r (insn
, operands
, real_l
);
1665 output_asm_insn (template, operands
);
1674 output_movhi (insn
, operands
, l
)
1680 rtx dest
= operands
[0];
1681 rtx src
= operands
[1];
1687 if (register_operand (dest
, HImode
))
1689 if (register_operand (src
, HImode
)) /* mov r,r */
1691 if (test_hard_reg_class (STACK_REG
, dest
))
1693 if (TARGET_TINY_STACK
)
1696 return AS2 (out
,__SP_L__
,%A1
);
1698 else if (TARGET_NO_INTERRUPTS
)
1701 return (AS2 (out
,__SP_H__
,%B1
) CR_TAB
1702 AS2 (out
,__SP_L__
,%A1
));
1706 return (AS2 (in
,__tmp_reg__
,__SREG__
) CR_TAB
1708 AS2 (out
,__SP_H__
,%B1
) CR_TAB
1709 AS2 (out
,__SREG__
,__tmp_reg__
) CR_TAB
1710 AS2 (out
,__SP_L__
,%A1
));
1712 else if (test_hard_reg_class (STACK_REG
, src
))
1715 return (AS2 (in
,%A0
,__SP_L__
) CR_TAB
1716 AS2 (in
,%B0
,__SP_H__
));
1722 return (AS2 (movw
,%0,%1));
1725 if (true_regnum (dest
) > true_regnum (src
))
1728 return (AS2 (mov
,%B0
,%B1
) CR_TAB
1734 return (AS2 (mov
,%A0
,%A1
) CR_TAB
1738 else if (CONSTANT_P (src
))
1740 if (test_hard_reg_class (LD_REGS
, dest
)) /* ldi d,i */
1742 if (byte_immediate_operand (src
, HImode
)
1743 && reg_was_0 (insn
, dest
))
1746 return (AS2 (ldi
,%A0
,lo8(%1) ; reg_was_0
));
1750 return (AS2 (ldi
,%A0
,lo8(%1)) CR_TAB
1751 AS2 (ldi
,%B0
,hi8(%1)));
1754 if (GET_CODE (src
) == CONST_INT
)
1756 if (src
== const0_rtx
) /* mov r,L */
1759 return (AS1 (clr
,%A0
) CR_TAB
1762 else if (src
== const1_rtx
)
1764 if (reg_was_0 (insn
, dest
))
1767 return AS1 (inc
,%0 ; reg_was_0
);
1771 return (AS1 (clr
,%A0
) CR_TAB
1772 AS1 (clr
,%B0
) CR_TAB
1775 else if (src
== constm1_rtx
)
1777 /* Immediate constants -1 to any register */
1778 if (reg_was_0 (insn
, dest
))
1781 return (AS1 (dec
,%A0
; reg_was_0
) CR_TAB
1786 return (AS1 (clr
,%0) CR_TAB
1787 AS1 (dec
,%A0
) CR_TAB
1792 int bit_nr
= exact_log2 (INTVAL (src
));
1796 if (reg_was_0 (insn
, dest
))
1800 output_asm_insn ("set ; reg_was_0", operands
);
1806 output_asm_insn ((AS1 (clr
,%A0
) CR_TAB
1807 AS1 (clr
,%B0
) CR_TAB
1811 avr_output_bld (operands
, bit_nr
);
1817 if ((INTVAL (src
) & 0xff) == 0)
1820 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1821 AS1 (clr
,%A0
) CR_TAB
1822 AS2 (ldi
,r31
,hi8(%1)) CR_TAB
1823 AS2 (mov
,%B0
,r31
) CR_TAB
1824 AS2 (mov
,r31
,__tmp_reg__
));
1826 else if ((INTVAL (src
) & 0xff00) == 0)
1829 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1830 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
1831 AS2 (mov
,%A0
,r31
) CR_TAB
1832 AS1 (clr
,%B0
) CR_TAB
1833 AS2 (mov
,r31
,__tmp_reg__
));
1837 /* Last resort, equal to loading from memory. */
1839 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1840 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
1841 AS2 (mov
,%A0
,r31
) CR_TAB
1842 AS2 (ldi
,r31
,hi8(%1)) CR_TAB
1843 AS2 (mov
,%B0
,r31
) CR_TAB
1844 AS2 (mov
,r31
,__tmp_reg__
));
1846 else if (GET_CODE (src
) == MEM
)
1847 return out_movhi_r_mr (insn
, operands
, real_l
); /* mov r,m */
1849 else if (GET_CODE (dest
) == MEM
)
1851 const char *template;
1853 if (src
== const0_rtx
)
1854 operands
[1] = zero_reg_rtx
;
1856 template = out_movhi_mr_r (insn
, operands
, real_l
);
1859 output_asm_insn (template, operands
);
1864 fatal_insn ("invalid insn:", insn
);
1869 out_movqi_r_mr (insn
, op
, l
)
1872 int *l
; /* instruction length */
1876 rtx x
= XEXP (src
, 0);
1882 if (CONSTANT_ADDRESS_P (x
))
1884 if (avr_io_address_p (x
, 1))
1887 return AS2 (in
,%0,%1-0x20);
1890 return AS2 (lds
,%0,%1);
1892 /* memory access by reg+disp */
1893 else if (GET_CODE (x
) == PLUS
1894 && REG_P (XEXP (x
,0))
1895 && GET_CODE (XEXP (x
,1)) == CONST_INT
)
1897 if ((INTVAL (XEXP (x
,1)) - GET_MODE_SIZE (GET_MODE (src
))) >= 63)
1899 int disp
= INTVAL (XEXP (x
,1));
1900 if (REGNO (XEXP (x
,0)) != REG_Y
)
1901 fatal_insn ("incorrect insn:",insn
);
1903 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
1904 return *l
= 3, (AS2 (adiw
,r28
,%o1
-63) CR_TAB
1905 AS2 (ldd
,%0,Y
+63) CR_TAB
1906 AS2 (sbiw
,r28
,%o1
-63));
1908 return *l
= 5, (AS2 (subi
,r28
,lo8(-%o1
)) CR_TAB
1909 AS2 (sbci
,r29
,hi8(-%o1
)) CR_TAB
1910 AS2 (ld
,%0,Y
) CR_TAB
1911 AS2 (subi
,r28
,lo8(%o1
)) CR_TAB
1912 AS2 (sbci
,r29
,hi8(%o1
)));
1914 else if (REGNO (XEXP (x
,0)) == REG_X
)
1916 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
1917 it but I have this situation with extremal optimizing options. */
1918 if (reg_overlap_mentioned_p (dest
, XEXP (x
,0))
1919 || reg_unused_after (insn
, XEXP (x
,0)))
1920 return *l
= 2, (AS2 (adiw
,r26
,%o1
) CR_TAB
1923 return *l
= 3, (AS2 (adiw
,r26
,%o1
) CR_TAB
1924 AS2 (ld
,%0,X
) CR_TAB
1925 AS2 (sbiw
,r26
,%o1
));
1928 return AS2 (ldd
,%0,%1);
1931 return AS2 (ld
,%0,%1);
1935 out_movhi_r_mr (insn
, op
, l
)
1938 int *l
; /* instruction length */
1942 rtx base
= XEXP (src
, 0);
1943 int reg_dest
= true_regnum (dest
);
1944 int reg_base
= true_regnum (base
);
1952 if (reg_dest
== reg_base
) /* R = (R) */
1955 return (AS2 (ld
,__tmp_reg__
,%1+) CR_TAB
1956 AS2 (ld
,%B0
,%1) CR_TAB
1957 AS2 (mov
,%A0
,__tmp_reg__
));
1959 else if (reg_base
== REG_X
) /* (R26) */
1961 if (reg_unused_after (insn
, base
))
1964 return (AS2 (ld
,%A0
,X
+) CR_TAB
1968 return (AS2 (ld
,%A0
,X
+) CR_TAB
1969 AS2 (ld
,%B0
,X
) CR_TAB
1975 return (AS2 (ld
,%A0
,%1) CR_TAB
1976 AS2 (ldd
,%B0
,%1+1));
1979 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
1981 int disp
= INTVAL (XEXP (base
, 1));
1982 int reg_base
= true_regnum (XEXP (base
, 0));
1984 if (disp
> MAX_LD_OFFSET (GET_MODE (src
)))
1986 if (REGNO (XEXP (base
, 0)) != REG_Y
)
1987 fatal_insn ("incorrect insn:",insn
);
1989 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
1990 return *l
= 4, (AS2 (adiw
,r28
,%o1
-62) CR_TAB
1991 AS2 (ldd
,%A0
,Y
+62) CR_TAB
1992 AS2 (ldd
,%B0
,Y
+63) CR_TAB
1993 AS2 (sbiw
,r28
,%o1
-62));
1995 return *l
= 6, (AS2 (subi
,r28
,lo8(-%o1
)) CR_TAB
1996 AS2 (sbci
,r29
,hi8(-%o1
)) CR_TAB
1997 AS2 (ld
,%A0
,Y
) CR_TAB
1998 AS2 (ldd
,%B0
,Y
+1) CR_TAB
1999 AS2 (subi
,r28
,lo8(%o1
)) CR_TAB
2000 AS2 (sbci
,r29
,hi8(%o1
)));
2002 if (reg_base
== REG_X
)
2004 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
2005 it but I have this situation with extremal
2006 optimization options. */
2009 if (reg_base
== reg_dest
)
2010 return (AS2 (adiw
,r26
,%o1
) CR_TAB
2011 AS2 (ld
,__tmp_reg__
,X
+) CR_TAB
2012 AS2 (ld
,%B0
,X
) CR_TAB
2013 AS2 (mov
,%A0
,__tmp_reg__
));
2015 return (AS2 (adiw
,r26
,%o1
) CR_TAB
2016 AS2 (ld
,%A0
,X
+) CR_TAB
2017 AS2 (ld
,%B0
,X
) CR_TAB
2018 AS2 (sbiw
,r26
,%o1
+1));
2021 if (reg_base
== reg_dest
)
2024 return (AS2 (ldd
,__tmp_reg__
,%A1
) CR_TAB
2025 AS2 (ldd
,%B0
,%B1
) CR_TAB
2026 AS2 (mov
,%A0
,__tmp_reg__
));
2030 return (AS2 (ldd
,%A0
,%A1
) CR_TAB
2033 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2035 if (reg_overlap_mentioned_p (dest
, XEXP (base
, 0)))
2036 fatal_insn ("incorrect insn:", insn
);
2039 return (AS2 (ld
,%B0
,%1) CR_TAB
2042 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2044 if (reg_overlap_mentioned_p (dest
, XEXP (base
, 0)))
2045 fatal_insn ("incorrect insn:", insn
);
2048 return (AS2 (ld
,%A0
,%1) CR_TAB
2051 else if (CONSTANT_ADDRESS_P (base
))
2053 if (avr_io_address_p (base
, 2))
2056 return (AS2 (in
,%A0
,%A1
-0x20) CR_TAB
2057 AS2 (in
,%B0
,%B1
-0x20));
2060 return (AS2 (lds
,%A0
,%A1
) CR_TAB
2064 fatal_insn ("unknown move insn:",insn
);
2069 out_movsi_r_mr (insn
, op
, l
)
2072 int *l
; /* instruction length */
2076 rtx base
= XEXP (src
, 0);
2077 int reg_dest
= true_regnum (dest
);
2078 int reg_base
= true_regnum (base
);
2086 if (reg_base
== REG_X
) /* (R26) */
2088 if (reg_dest
== REG_X
)
2089 /* "ld r26,-X" is undefined */
2090 return *l
=7, (AS2 (adiw
,r26
,3) CR_TAB
2091 AS2 (ld
,r29
,X
) CR_TAB
2092 AS2 (ld
,r28
,-X
) CR_TAB
2093 AS2 (ld
,__tmp_reg__
,-X
) CR_TAB
2094 AS2 (sbiw
,r26
,1) CR_TAB
2095 AS2 (ld
,r26
,X
) CR_TAB
2096 AS2 (mov
,r27
,__tmp_reg__
));
2097 else if (reg_dest
== REG_X
- 2)
2098 return *l
=5, (AS2 (ld
,%A0
,X
+) CR_TAB
2099 AS2 (ld
,%B0
,X
+) CR_TAB
2100 AS2 (ld
,__tmp_reg__
,X
+) CR_TAB
2101 AS2 (ld
,%D0
,X
) CR_TAB
2102 AS2 (mov
,%C0
,__tmp_reg__
));
2103 else if (reg_unused_after (insn
, base
))
2104 return *l
=4, (AS2 (ld
,%A0
,X
+) CR_TAB
2105 AS2 (ld
,%B0
,X
+) CR_TAB
2106 AS2 (ld
,%C0
,X
+) CR_TAB
2109 return *l
=5, (AS2 (ld
,%A0
,X
+) CR_TAB
2110 AS2 (ld
,%B0
,X
+) CR_TAB
2111 AS2 (ld
,%C0
,X
+) CR_TAB
2112 AS2 (ld
,%D0
,X
) CR_TAB
2117 if (reg_dest
== reg_base
)
2118 return *l
=5, (AS2 (ldd
,%D0
,%1+3) CR_TAB
2119 AS2 (ldd
,%C0
,%1+2) CR_TAB
2120 AS2 (ldd
,__tmp_reg__
,%1+1) CR_TAB
2121 AS2 (ld
,%A0
,%1) CR_TAB
2122 AS2 (mov
,%B0
,__tmp_reg__
));
2123 else if (reg_base
== reg_dest
+ 2)
2124 return *l
=5, (AS2 (ld
,%A0
,%1) CR_TAB
2125 AS2 (ldd
,%B0
,%1+1) CR_TAB
2126 AS2 (ldd
,__tmp_reg__
,%1+2) CR_TAB
2127 AS2 (ldd
,%D0
,%1+3) CR_TAB
2128 AS2 (mov
,%C0
,__tmp_reg__
));
2130 return *l
=4, (AS2 (ld
,%A0
,%1) CR_TAB
2131 AS2 (ldd
,%B0
,%1+1) CR_TAB
2132 AS2 (ldd
,%C0
,%1+2) CR_TAB
2133 AS2 (ldd
,%D0
,%1+3));
2136 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
2138 int disp
= INTVAL (XEXP (base
, 1));
2140 if (disp
> MAX_LD_OFFSET (GET_MODE (src
)))
2142 if (REGNO (XEXP (base
, 0)) != REG_Y
)
2143 fatal_insn ("incorrect insn:",insn
);
2145 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
2146 return *l
= 6, (AS2 (adiw
,r28
,%o1
-60) CR_TAB
2147 AS2 (ldd
,%A0
,Y
+60) CR_TAB
2148 AS2 (ldd
,%B0
,Y
+61) CR_TAB
2149 AS2 (ldd
,%C0
,Y
+62) CR_TAB
2150 AS2 (ldd
,%D0
,Y
+63) CR_TAB
2151 AS2 (sbiw
,r28
,%o1
-60));
2153 return *l
= 8, (AS2 (subi
,r28
,lo8(-%o1
)) CR_TAB
2154 AS2 (sbci
,r29
,hi8(-%o1
)) CR_TAB
2155 AS2 (ld
,%A0
,Y
) CR_TAB
2156 AS2 (ldd
,%B0
,Y
+1) CR_TAB
2157 AS2 (ldd
,%C0
,Y
+2) CR_TAB
2158 AS2 (ldd
,%D0
,Y
+3) CR_TAB
2159 AS2 (subi
,r28
,lo8(%o1
)) CR_TAB
2160 AS2 (sbci
,r29
,hi8(%o1
)));
2163 reg_base
= true_regnum (XEXP (base
, 0));
2164 if (reg_base
== REG_X
)
2167 if (reg_dest
== REG_X
)
2170 /* "ld r26,-X" is undefined */
2171 return (AS2 (adiw
,r26
,%o1
+3) CR_TAB
2172 AS2 (ld
,r29
,X
) CR_TAB
2173 AS2 (ld
,r28
,-X
) CR_TAB
2174 AS2 (ld
,__tmp_reg__
,-X
) CR_TAB
2175 AS2 (sbiw
,r26
,1) CR_TAB
2176 AS2 (ld
,r26
,X
) CR_TAB
2177 AS2 (mov
,r27
,__tmp_reg__
));
2180 if (reg_dest
== REG_X
- 2)
2181 return (AS2 (adiw
,r26
,%o1
) CR_TAB
2182 AS2 (ld
,r24
,X
+) CR_TAB
2183 AS2 (ld
,r25
,X
+) CR_TAB
2184 AS2 (ld
,__tmp_reg__
,X
+) CR_TAB
2185 AS2 (ld
,r27
,X
) CR_TAB
2186 AS2 (mov
,r26
,__tmp_reg__
));
2188 return (AS2 (adiw
,r26
,%o1
) CR_TAB
2189 AS2 (ld
,%A0
,X
+) CR_TAB
2190 AS2 (ld
,%B0
,X
+) CR_TAB
2191 AS2 (ld
,%C0
,X
+) CR_TAB
2192 AS2 (ld
,%D0
,X
) CR_TAB
2193 AS2 (sbiw
,r26
,%o1
+3));
2195 if (reg_dest
== reg_base
)
2196 return *l
=5, (AS2 (ldd
,%D0
,%D1
) CR_TAB
2197 AS2 (ldd
,%C0
,%C1
) CR_TAB
2198 AS2 (ldd
,__tmp_reg__
,%B1
) CR_TAB
2199 AS2 (ldd
,%A0
,%A1
) CR_TAB
2200 AS2 (mov
,%B0
,__tmp_reg__
));
2201 else if (reg_dest
== reg_base
- 2)
2202 return *l
=5, (AS2 (ldd
,%A0
,%A1
) CR_TAB
2203 AS2 (ldd
,%B0
,%B1
) CR_TAB
2204 AS2 (ldd
,__tmp_reg__
,%C1
) CR_TAB
2205 AS2 (ldd
,%D0
,%D1
) CR_TAB
2206 AS2 (mov
,%C0
,__tmp_reg__
));
2207 return *l
=4, (AS2 (ldd
,%A0
,%A1
) CR_TAB
2208 AS2 (ldd
,%B0
,%B1
) CR_TAB
2209 AS2 (ldd
,%C0
,%C1
) CR_TAB
2212 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2213 return *l
=4, (AS2 (ld
,%D0
,%1) CR_TAB
2214 AS2 (ld
,%C0
,%1) CR_TAB
2215 AS2 (ld
,%B0
,%1) CR_TAB
2217 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2218 return *l
=4, (AS2 (ld
,%A0
,%1) CR_TAB
2219 AS2 (ld
,%B0
,%1) CR_TAB
2220 AS2 (ld
,%C0
,%1) CR_TAB
2222 else if (CONSTANT_ADDRESS_P (base
))
2223 return *l
=8, (AS2 (lds
,%A0
,%A1
) CR_TAB
2224 AS2 (lds
,%B0
,%B1
) CR_TAB
2225 AS2 (lds
,%C0
,%C1
) CR_TAB
2228 fatal_insn ("unknown move insn:",insn
);
2233 out_movsi_mr_r (insn
, op
, l
)
2240 rtx base
= XEXP (dest
, 0);
2241 int reg_base
= true_regnum (base
);
2242 int reg_src
= true_regnum (src
);
2248 if (CONSTANT_ADDRESS_P (base
))
2249 return *l
=8,(AS2 (sts
,%A0
,%A1
) CR_TAB
2250 AS2 (sts
,%B0
,%B1
) CR_TAB
2251 AS2 (sts
,%C0
,%C1
) CR_TAB
2253 if (reg_base
> 0) /* (r) */
2255 if (reg_base
== REG_X
) /* (R26) */
2257 if (reg_src
== REG_X
)
2259 /* "st X+,r26" is undefined */
2260 if (reg_unused_after (insn
, base
))
2261 return *l
=6, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2262 AS2 (st
,X
,r26
) CR_TAB
2263 AS2 (adiw
,r26
,1) CR_TAB
2264 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2265 AS2 (st
,X
+,r28
) CR_TAB
2268 return *l
=7, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2269 AS2 (st
,X
,r26
) CR_TAB
2270 AS2 (adiw
,r26
,1) CR_TAB
2271 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2272 AS2 (st
,X
+,r28
) CR_TAB
2273 AS2 (st
,X
,r29
) CR_TAB
2276 else if (reg_base
== reg_src
+ 2)
2278 if (reg_unused_after (insn
, base
))
2279 return *l
=7, (AS2 (mov
,__zero_reg__
,%C1
) CR_TAB
2280 AS2 (mov
,__tmp_reg__
,%D1
) CR_TAB
2281 AS2 (st
,%0+,%A1
) CR_TAB
2282 AS2 (st
,%0+,%B1
) CR_TAB
2283 AS2 (st
,%0+,__zero_reg__
) CR_TAB
2284 AS2 (st
,%0,__tmp_reg__
) CR_TAB
2285 AS1 (clr
,__zero_reg__
));
2287 return *l
=8, (AS2 (mov
,__zero_reg__
,%C1
) CR_TAB
2288 AS2 (mov
,__tmp_reg__
,%D1
) CR_TAB
2289 AS2 (st
,%0+,%A1
) CR_TAB
2290 AS2 (st
,%0+,%B1
) CR_TAB
2291 AS2 (st
,%0+,__zero_reg__
) CR_TAB
2292 AS2 (st
,%0,__tmp_reg__
) CR_TAB
2293 AS1 (clr
,__zero_reg__
) CR_TAB
2296 return *l
=5, (AS2 (st
,%0+,%A1
) CR_TAB
2297 AS2 (st
,%0+,%B1
) CR_TAB
2298 AS2 (st
,%0+,%C1
) CR_TAB
2299 AS2 (st
,%0,%D1
) CR_TAB
2303 return *l
=4, (AS2 (st
,%0,%A1
) CR_TAB
2304 AS2 (std
,%0+1,%B1
) CR_TAB
2305 AS2 (std
,%0+2,%C1
) CR_TAB
2306 AS2 (std
,%0+3,%D1
));
2308 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
2310 int disp
= INTVAL (XEXP (base
, 1));
2311 reg_base
= REGNO (XEXP (base
, 0));
2312 if (disp
> MAX_LD_OFFSET (GET_MODE (dest
)))
2314 if (reg_base
!= REG_Y
)
2315 fatal_insn ("incorrect insn:",insn
);
2317 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
2318 return *l
= 6, (AS2 (adiw
,r28
,%o0
-60) CR_TAB
2319 AS2 (std
,Y
+60,%A1
) CR_TAB
2320 AS2 (std
,Y
+61,%B1
) CR_TAB
2321 AS2 (std
,Y
+62,%C1
) CR_TAB
2322 AS2 (std
,Y
+63,%D1
) CR_TAB
2323 AS2 (sbiw
,r28
,%o0
-60));
2325 return *l
= 8, (AS2 (subi
,r28
,lo8(-%o0
)) CR_TAB
2326 AS2 (sbci
,r29
,hi8(-%o0
)) CR_TAB
2327 AS2 (st
,Y
,%A1
) CR_TAB
2328 AS2 (std
,Y
+1,%B1
) CR_TAB
2329 AS2 (std
,Y
+2,%C1
) CR_TAB
2330 AS2 (std
,Y
+3,%D1
) CR_TAB
2331 AS2 (subi
,r28
,lo8(%o0
)) CR_TAB
2332 AS2 (sbci
,r29
,hi8(%o0
)));
2334 if (reg_base
== REG_X
)
2337 if (reg_src
== REG_X
)
2340 return (AS2 (mov
,__tmp_reg__
,r26
) CR_TAB
2341 AS2 (mov
,__zero_reg__
,r27
) CR_TAB
2342 AS2 (adiw
,r26
,%o0
) CR_TAB
2343 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2344 AS2 (st
,X
+,__zero_reg__
) CR_TAB
2345 AS2 (st
,X
+,r28
) CR_TAB
2346 AS2 (st
,X
,r29
) CR_TAB
2347 AS1 (clr
,__zero_reg__
) CR_TAB
2348 AS2 (sbiw
,r26
,%o0
+3));
2350 else if (reg_src
== REG_X
- 2)
2353 return (AS2 (mov
,__tmp_reg__
,r26
) CR_TAB
2354 AS2 (mov
,__zero_reg__
,r27
) CR_TAB
2355 AS2 (adiw
,r26
,%o0
) CR_TAB
2356 AS2 (st
,X
+,r24
) CR_TAB
2357 AS2 (st
,X
+,r25
) CR_TAB
2358 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2359 AS2 (st
,X
,__zero_reg__
) CR_TAB
2360 AS1 (clr
,__zero_reg__
) CR_TAB
2361 AS2 (sbiw
,r26
,%o0
+3));
2364 return (AS2 (adiw
,r26
,%o0
) CR_TAB
2365 AS2 (st
,X
+,%A1
) CR_TAB
2366 AS2 (st
,X
+,%B1
) CR_TAB
2367 AS2 (st
,X
+,%C1
) CR_TAB
2368 AS2 (st
,X
,%D1
) CR_TAB
2369 AS2 (sbiw
,r26
,%o0
+3));
2371 return *l
=4, (AS2 (std
,%A0
,%A1
) CR_TAB
2372 AS2 (std
,%B0
,%B1
) CR_TAB
2373 AS2 (std
,%C0
,%C1
) CR_TAB
2376 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2377 return *l
=4, (AS2 (st
,%0,%D1
) CR_TAB
2378 AS2 (st
,%0,%C1
) CR_TAB
2379 AS2 (st
,%0,%B1
) CR_TAB
2381 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2382 return *l
=4, (AS2 (st
,%0,%A1
) CR_TAB
2383 AS2 (st
,%0,%B1
) CR_TAB
2384 AS2 (st
,%0,%C1
) CR_TAB
2386 fatal_insn ("unknown move insn:",insn
);
2391 output_movsisf(insn
, operands
, l
)
2397 rtx dest
= operands
[0];
2398 rtx src
= operands
[1];
2404 if (register_operand (dest
, VOIDmode
))
2406 if (register_operand (src
, VOIDmode
)) /* mov r,r */
2408 if (true_regnum (dest
) > true_regnum (src
))
2413 return (AS2 (movw
,%C0
,%C1
) CR_TAB
2414 AS2 (movw
,%A0
,%A1
));
2417 return (AS2 (mov
,%D0
,%D1
) CR_TAB
2418 AS2 (mov
,%C0
,%C1
) CR_TAB
2419 AS2 (mov
,%B0
,%B1
) CR_TAB
2427 return (AS2 (movw
,%A0
,%A1
) CR_TAB
2428 AS2 (movw
,%C0
,%C1
));
2431 return (AS2 (mov
,%A0
,%A1
) CR_TAB
2432 AS2 (mov
,%B0
,%B1
) CR_TAB
2433 AS2 (mov
,%C0
,%C1
) CR_TAB
2437 else if (CONSTANT_P (src
))
2439 if (test_hard_reg_class (LD_REGS
, dest
)) /* ldi d,i */
2441 if (byte_immediate_operand (src
, SImode
)
2442 && reg_was_0 (insn
, dest
))
2445 return (AS2 (ldi
,%A0
,lo8(%1) ; reg_was_0
));
2449 return (AS2 (ldi
,%A0
,lo8(%1)) CR_TAB
2450 AS2 (ldi
,%B0
,hi8(%1)) CR_TAB
2451 AS2 (ldi
,%C0
,hlo8(%1)) CR_TAB
2452 AS2 (ldi
,%D0
,hhi8(%1)));
2455 if (GET_CODE (src
) == CONST_INT
)
2457 const char *const clr_op0
=
2458 AVR_ENHANCED
? (AS1 (clr
,%A0
) CR_TAB
2459 AS1 (clr
,%B0
) CR_TAB
2461 : (AS1 (clr
,%A0
) CR_TAB
2462 AS1 (clr
,%B0
) CR_TAB
2463 AS1 (clr
,%C0
) CR_TAB
2466 if (src
== const0_rtx
) /* mov r,L */
2468 *l
= AVR_ENHANCED
? 3 : 4;
2471 else if (src
== const1_rtx
)
2473 if (reg_was_0 (insn
, dest
))
2476 return AS1 (inc
,%A0
; reg_was_0
);
2479 output_asm_insn (clr_op0
, operands
);
2480 *l
= AVR_ENHANCED
? 4 : 5;
2481 return AS1 (inc
,%A0
);
2483 else if (src
== constm1_rtx
)
2485 /* Immediate constants -1 to any register */
2486 if (reg_was_0 (insn
, dest
))
2491 return (AS1 (dec
,%A0
) CR_TAB
2492 AS1 (dec
,%B0
) CR_TAB
2493 AS2 (movw
,%C0
,%A0
));
2496 return (AS1 (dec
,%D0
; reg_was_0
) CR_TAB
2497 AS1 (dec
,%C0
) CR_TAB
2498 AS1 (dec
,%B0
) CR_TAB
2504 return (AS1 (clr
,%A0
) CR_TAB
2505 AS1 (dec
,%A0
) CR_TAB
2506 AS2 (mov
,%B0
,%A0
) CR_TAB
2507 AS2 (movw
,%C0
,%A0
));
2510 return (AS1 (clr
,%A0
) CR_TAB
2511 AS1 (dec
,%A0
) CR_TAB
2512 AS2 (mov
,%B0
,%A0
) CR_TAB
2513 AS2 (mov
,%C0
,%A0
) CR_TAB
2518 int bit_nr
= exact_log2 (INTVAL (src
));
2522 if (reg_was_0 (insn
, dest
))
2526 output_asm_insn ("set ; reg_was_0", operands
);
2530 *l
= AVR_ENHANCED
? 5 : 6;
2533 output_asm_insn (clr_op0
, operands
);
2534 output_asm_insn ("set", operands
);
2538 avr_output_bld (operands
, bit_nr
);
2545 /* Last resort, better than loading from memory. */
2547 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
2548 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
2549 AS2 (mov
,%A0
,r31
) CR_TAB
2550 AS2 (ldi
,r31
,hi8(%1)) CR_TAB
2551 AS2 (mov
,%B0
,r31
) CR_TAB
2552 AS2 (ldi
,r31
,hlo8(%1)) CR_TAB
2553 AS2 (mov
,%C0
,r31
) CR_TAB
2554 AS2 (ldi
,r31
,hhi8(%1)) CR_TAB
2555 AS2 (mov
,%D0
,r31
) CR_TAB
2556 AS2 (mov
,r31
,__tmp_reg__
));
2558 else if (GET_CODE (src
) == MEM
)
2559 return out_movsi_r_mr (insn
, operands
, real_l
); /* mov r,m */
2561 else if (GET_CODE (dest
) == MEM
)
2563 const char *template;
2565 if (src
== const0_rtx
)
2566 operands
[1] = zero_reg_rtx
;
2568 template = out_movsi_mr_r (insn
, operands
, real_l
);
2571 output_asm_insn (template, operands
);
2576 fatal_insn ("invalid insn:", insn
);
2581 out_movqi_mr_r (insn
, op
, l
)
2584 int *l
; /* instruction length */
2588 rtx x
= XEXP (dest
, 0);
2594 if (CONSTANT_ADDRESS_P (x
))
2596 if (avr_io_address_p (x
, 1))
2599 return AS2 (out
,%0-0x20,%1);
2602 return AS2 (sts
,%0,%1);
2604 /* memory access by reg+disp */
2605 else if (GET_CODE (x
) == PLUS
2606 && REG_P (XEXP (x
,0))
2607 && GET_CODE (XEXP (x
,1)) == CONST_INT
)
2609 if ((INTVAL (XEXP (x
,1)) - GET_MODE_SIZE (GET_MODE (dest
))) >= 63)
2611 int disp
= INTVAL (XEXP (x
,1));
2612 if (REGNO (XEXP (x
,0)) != REG_Y
)
2613 fatal_insn ("incorrect insn:",insn
);
2615 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
2616 return *l
= 3, (AS2 (adiw
,r28
,%o0
-63) CR_TAB
2617 AS2 (std
,Y
+63,%1) CR_TAB
2618 AS2 (sbiw
,r28
,%o0
-63));
2620 return *l
= 5, (AS2 (subi
,r28
,lo8(-%o0
)) CR_TAB
2621 AS2 (sbci
,r29
,hi8(-%o0
)) CR_TAB
2622 AS2 (st
,Y
,%1) CR_TAB
2623 AS2 (subi
,r28
,lo8(%o0
)) CR_TAB
2624 AS2 (sbci
,r29
,hi8(%o0
)));
2626 else if (REGNO (XEXP (x
,0)) == REG_X
)
2628 if (reg_overlap_mentioned_p (src
, XEXP (x
, 0)))
2630 if (reg_unused_after (insn
, XEXP (x
,0)))
2631 return *l
= 3, (AS2 (mov
,__tmp_reg__
,%1) CR_TAB
2632 AS2 (adiw
,r26
,%o0
) CR_TAB
2633 AS2 (st
,X
,__tmp_reg__
));
2635 return *l
= 4, (AS2 (mov
,__tmp_reg__
,%1) CR_TAB
2636 AS2 (adiw
,r26
,%o0
) CR_TAB
2637 AS2 (st
,X
,__tmp_reg__
) CR_TAB
2638 AS2 (sbiw
,r26
,%o0
));
2642 if (reg_unused_after (insn
, XEXP (x
,0)))
2643 return *l
= 2, (AS2 (adiw
,r26
,%o0
) CR_TAB
2646 return *l
= 3, (AS2 (adiw
,r26
,%o0
) CR_TAB
2647 AS2 (st
,X
,%1) CR_TAB
2648 AS2 (sbiw
,r26
,%o0
));
2652 return AS2 (std
,%0,%1);
2655 return AS2 (st
,%0,%1);
2659 out_movhi_mr_r (insn
, op
, l
)
2666 rtx base
= XEXP (dest
, 0);
2667 int reg_base
= true_regnum (base
);
2668 int reg_src
= true_regnum (src
);
2672 if (CONSTANT_ADDRESS_P (base
))
2674 if (avr_io_address_p (base
, 2))
2677 return (AS2 (out
,%B0
-0x20,%B1
) CR_TAB
2678 AS2 (out
,%A0
-0x20,%A1
));
2680 return *l
= 4, (AS2 (sts
,%B0
,%B1
) CR_TAB
2685 if (reg_base
== REG_X
)
2687 if (reg_src
== REG_X
)
2689 /* "st X+,r26" is undefined */
2690 if (reg_unused_after (insn
, src
))
2691 return *l
=4, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2692 AS2 (st
,X
,r26
) CR_TAB
2693 AS2 (adiw
,r26
,1) CR_TAB
2694 AS2 (st
,X
,__tmp_reg__
));
2696 return *l
=5, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2697 AS2 (st
,X
,r26
) CR_TAB
2698 AS2 (adiw
,r26
,1) CR_TAB
2699 AS2 (st
,X
,__tmp_reg__
) CR_TAB
2704 if (reg_unused_after (insn
, base
))
2705 return *l
=2, (AS2 (st
,X
+,%A1
) CR_TAB
2708 return *l
=3, (AS2 (st
,X
+,%A1
) CR_TAB
2709 AS2 (st
,X
,%B1
) CR_TAB
2714 return *l
=2, (AS2 (st
,%0,%A1
) CR_TAB
2715 AS2 (std
,%0+1,%B1
));
2717 else if (GET_CODE (base
) == PLUS
)
2719 int disp
= INTVAL (XEXP (base
, 1));
2720 reg_base
= REGNO (XEXP (base
, 0));
2721 if (disp
> MAX_LD_OFFSET (GET_MODE (dest
)))
2723 if (reg_base
!= REG_Y
)
2724 fatal_insn ("incorrect insn:",insn
);
2726 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
2727 return *l
= 4, (AS2 (adiw
,r28
,%o0
-62) CR_TAB
2728 AS2 (std
,Y
+62,%A1
) CR_TAB
2729 AS2 (std
,Y
+63,%B1
) CR_TAB
2730 AS2 (sbiw
,r28
,%o0
-62));
2732 return *l
= 6, (AS2 (subi
,r28
,lo8(-%o0
)) CR_TAB
2733 AS2 (sbci
,r29
,hi8(-%o0
)) CR_TAB
2734 AS2 (st
,Y
,%A1
) CR_TAB
2735 AS2 (std
,Y
+1,%B1
) CR_TAB
2736 AS2 (subi
,r28
,lo8(%o0
)) CR_TAB
2737 AS2 (sbci
,r29
,hi8(%o0
)));
2739 if (reg_base
== REG_X
)
2742 if (reg_src
== REG_X
)
2745 return (AS2 (mov
,__tmp_reg__
,r26
) CR_TAB
2746 AS2 (mov
,__zero_reg__
,r27
) CR_TAB
2747 AS2 (adiw
,r26
,%o0
) CR_TAB
2748 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2749 AS2 (st
,X
,__zero_reg__
) CR_TAB
2750 AS1 (clr
,__zero_reg__
) CR_TAB
2751 AS2 (sbiw
,r26
,%o0
+1));
2754 return (AS2 (adiw
,r26
,%o0
) CR_TAB
2755 AS2 (st
,X
+,%A1
) CR_TAB
2756 AS2 (st
,X
,%B1
) CR_TAB
2757 AS2 (sbiw
,r26
,%o0
+1));
2759 return *l
=2, (AS2 (std
,%A0
,%A1
) CR_TAB
2762 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2763 return *l
=2, (AS2 (st
,%0,%B1
) CR_TAB
2765 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2766 return *l
=2, (AS2 (st
,%0,%A1
) CR_TAB
2768 fatal_insn ("unknown move insn:",insn
);
2772 /* Return 1 if frame pointer for current function required */
2775 frame_pointer_required_p ()
2777 return (current_function_calls_alloca
2778 || current_function_args_info
.nregs
== 0
2779 || get_frame_size () > 0);
2782 /* Returns the condition of compare insn INSN, or UNKNOWN. */
2785 compare_condition (insn
)
2788 rtx next
= next_real_insn (insn
);
2789 RTX_CODE cond
= UNKNOWN
;
2790 if (next
&& GET_CODE (next
) == JUMP_INSN
)
2792 rtx pat
= PATTERN (next
);
2793 rtx src
= SET_SRC (pat
);
2794 rtx t
= XEXP (src
, 0);
2795 cond
= GET_CODE (t
);
2800 /* Returns nonzero if INSN is a tst insn that only tests the sign. */
2803 compare_sign_p (insn
)
2806 RTX_CODE cond
= compare_condition (insn
);
2807 return (cond
== GE
|| cond
== LT
);
2810 /* Returns nonzero if the next insn is a JUMP_INSN with a condition
2811 that needs to be swapped (GT, GTU, LE, LEU). */
2814 compare_diff_p (insn
)
2817 RTX_CODE cond
= compare_condition (insn
);
2818 return (cond
== GT
|| cond
== GTU
|| cond
== LE
|| cond
== LEU
) ? cond
: 0;
2821 /* Returns nonzero if INSN is a compare insn with the EQ or NE condition. */
2827 RTX_CODE cond
= compare_condition (insn
);
2828 return (cond
== EQ
|| cond
== NE
);
2832 /* Output test instruction for HImode */
2839 if (compare_sign_p (insn
))
2842 return AS1 (tst
,%B0
);
2844 if (reg_unused_after (insn
, SET_SRC (PATTERN (insn
)))
2845 && compare_eq_p (insn
))
2847 /* faster than sbiw if we can clobber the operand */
2849 return AS2 (or,%A0
,%B0
);
2851 if (test_hard_reg_class (ADDW_REGS
, SET_SRC (PATTERN (insn
))))
2854 return AS2 (sbiw
,%0,0);
2857 return (AS2 (cp
,%A0
,__zero_reg__
) CR_TAB
2858 AS2 (cpc
,%B0
,__zero_reg__
));
2862 /* Output test instruction for SImode */
2869 if (compare_sign_p (insn
))
2872 return AS1 (tst
,%D0
);
2874 if (test_hard_reg_class (ADDW_REGS
, SET_SRC (PATTERN (insn
))))
2877 return (AS2 (sbiw
,%A0
,0) CR_TAB
2878 AS2 (cpc
,%C0
,__zero_reg__
) CR_TAB
2879 AS2 (cpc
,%D0
,__zero_reg__
));
2882 return (AS2 (cp
,%A0
,__zero_reg__
) CR_TAB
2883 AS2 (cpc
,%B0
,__zero_reg__
) CR_TAB
2884 AS2 (cpc
,%C0
,__zero_reg__
) CR_TAB
2885 AS2 (cpc
,%D0
,__zero_reg__
));
2889 /* Generate asm equivalent for various shifts.
2890 Shift count is a CONST_INT, MEM or REG.
2891 This only handles cases that are not already
2892 carefully hand-optimized in ?sh??i3_out. */
2895 out_shift_with_cnt (template, insn
, operands
, len
, t_len
)
2896 const char *template;
2900 int t_len
; /* Length of template. */
2904 int second_label
= 1;
2905 int saved_in_tmp
= 0;
2906 int use_zero_reg
= 0;
2908 op
[0] = operands
[0];
2909 op
[1] = operands
[1];
2910 op
[2] = operands
[2];
2911 op
[3] = operands
[3];
2917 if (GET_CODE (operands
[2]) == CONST_INT
)
2919 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
2920 int count
= INTVAL (operands
[2]);
2921 int max_len
= 10; /* If larger than this, always use a loop. */
2923 if (count
< 8 && !scratch
)
2927 max_len
= t_len
+ (scratch
? 3 : (use_zero_reg
? 4 : 5));
2929 if (t_len
* count
<= max_len
)
2931 /* Output shifts inline with no loop - faster. */
2933 *len
= t_len
* count
;
2937 output_asm_insn (template, op
);
2946 strcat (str
, AS2 (ldi
,%3,%2));
2948 else if (use_zero_reg
)
2950 /* Hack to save one word: use __zero_reg__ as loop counter.
2951 Set one bit, then shift in a loop until it is 0 again. */
2953 op
[3] = zero_reg_rtx
;
2957 strcat (str
, ("set" CR_TAB
2958 AS2 (bld
,%3,%2-1)));
2962 /* No scratch register available, use one from LD_REGS (saved in
2963 __tmp_reg__) that doesn't overlap with registers to shift. */
2965 op
[3] = gen_rtx (REG
, QImode
,
2966 ((true_regnum (operands
[0]) - 1) & 15) + 16);
2967 op
[4] = tmp_reg_rtx
;
2971 *len
= 3; /* Includes "mov %3,%4" after the loop. */
2973 strcat (str
, (AS2 (mov
,%4,%3) CR_TAB
2979 else if (GET_CODE (operands
[2]) == MEM
)
2983 op
[3] = op_mov
[0] = tmp_reg_rtx
;
2987 out_movqi_r_mr (insn
, op_mov
, len
);
2989 output_asm_insn (out_movqi_r_mr (insn
, op_mov
, NULL
), op_mov
);
2991 else if (register_operand (operands
[2], QImode
))
2993 if (reg_unused_after (insn
, operands
[2]))
2997 op
[3] = tmp_reg_rtx
;
2999 strcat (str
, (AS2 (mov
,%3,%2) CR_TAB
));
3003 fatal_insn ("bad shift insn:", insn
);
3010 strcat (str
, AS1 (rjmp
,2f
));
3014 *len
+= t_len
+ 2; /* template + dec + brXX */
3017 strcat (str
, "\n1:\t");
3018 strcat (str
, template);
3019 strcat (str
, second_label
? "\n2:\t" : "\n\t");
3020 strcat (str
, use_zero_reg
? AS1 (lsr
,%3) : AS1 (dec
,%3));
3021 strcat (str
, CR_TAB
);
3022 strcat (str
, second_label
? AS1 (brpl
,1b
) : AS1 (brne
,1b
));
3024 strcat (str
, (CR_TAB
AS2 (mov
,%3,%4)));
3025 output_asm_insn (str
, op
);
3030 /* 8bit shift left ((char)x << i) */
3033 ashlqi3_out (insn
, operands
, len
)
3036 int *len
; /* insn length (may be NULL) */
3038 if (GET_CODE (operands
[2]) == CONST_INT
)
3045 switch (INTVAL (operands
[2]))
3049 return AS1 (clr
,%0);
3053 return AS1 (lsl
,%0);
3057 return (AS1 (lsl
,%0) CR_TAB
3062 return (AS1 (lsl
,%0) CR_TAB
3067 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3070 return (AS1 (swap
,%0) CR_TAB
3071 AS2 (andi
,%0,0xf0));
3074 return (AS1 (lsl
,%0) CR_TAB
3080 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3083 return (AS1 (swap
,%0) CR_TAB
3085 AS2 (andi
,%0,0xe0));
3088 return (AS1 (lsl
,%0) CR_TAB
3095 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3098 return (AS1 (swap
,%0) CR_TAB
3101 AS2 (andi
,%0,0xc0));
3104 return (AS1 (lsl
,%0) CR_TAB
3113 return (AS1 (ror
,%0) CR_TAB
3118 else if (CONSTANT_P (operands
[2]))
3119 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
3121 out_shift_with_cnt (AS1 (lsl
,%0),
3122 insn
, operands
, len
, 1);
3127 /* 16bit shift left ((short)x << i) */
3130 ashlhi3_out (insn
, operands
, len
)
3135 if (GET_CODE (operands
[2]) == CONST_INT
)
3137 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
3138 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
3145 switch (INTVAL (operands
[2]))
3148 if (optimize_size
&& scratch
)
3153 return (AS1 (swap
,%A0
) CR_TAB
3154 AS1 (swap
,%B0
) CR_TAB
3155 AS2 (andi
,%B0
,0xf0) CR_TAB
3156 AS2 (eor
,%B0
,%A0
) CR_TAB
3157 AS2 (andi
,%A0
,0xf0) CR_TAB
3163 return (AS1 (swap
,%A0
) CR_TAB
3164 AS1 (swap
,%B0
) CR_TAB
3165 AS2 (ldi
,%3,0xf0) CR_TAB
3166 AS2 (and,%B0
,%3) CR_TAB
3167 AS2 (eor
,%B0
,%A0
) CR_TAB
3168 AS2 (and,%A0
,%3) CR_TAB
3171 break; /* optimize_size ? 6 : 8 */
3175 break; /* scratch ? 5 : 6 */
3179 return (AS1 (lsl
,%A0
) CR_TAB
3180 AS1 (rol
,%B0
) CR_TAB
3181 AS1 (swap
,%A0
) CR_TAB
3182 AS1 (swap
,%B0
) CR_TAB
3183 AS2 (andi
,%B0
,0xf0) CR_TAB
3184 AS2 (eor
,%B0
,%A0
) CR_TAB
3185 AS2 (andi
,%A0
,0xf0) CR_TAB
3191 return (AS1 (lsl
,%A0
) CR_TAB
3192 AS1 (rol
,%B0
) CR_TAB
3193 AS1 (swap
,%A0
) CR_TAB
3194 AS1 (swap
,%B0
) CR_TAB
3195 AS2 (ldi
,%3,0xf0) CR_TAB
3196 AS2 (and,%B0
,%3) CR_TAB
3197 AS2 (eor
,%B0
,%A0
) CR_TAB
3198 AS2 (and,%A0
,%3) CR_TAB
3205 break; /* scratch ? 5 : 6 */
3207 return (AS1 (clr
,__tmp_reg__
) CR_TAB
3208 AS1 (lsr
,%B0
) CR_TAB
3209 AS1 (ror
,%A0
) CR_TAB
3210 AS1 (ror
,__tmp_reg__
) CR_TAB
3211 AS1 (lsr
,%B0
) CR_TAB
3212 AS1 (ror
,%A0
) CR_TAB
3213 AS1 (ror
,__tmp_reg__
) CR_TAB
3214 AS2 (mov
,%B0
,%A0
) CR_TAB
3215 AS2 (mov
,%A0
,__tmp_reg__
));
3219 return (AS1 (lsr
,%B0
) CR_TAB
3220 AS2 (mov
,%B0
,%A0
) CR_TAB
3221 AS1 (clr
,%A0
) CR_TAB
3222 AS1 (ror
,%B0
) CR_TAB
3226 if (true_regnum (operands
[0]) + 1 == true_regnum (operands
[1]))
3227 return *len
= 1, AS1 (clr
,%A0
);
3229 return *len
= 2, (AS2 (mov
,%B0
,%A1
) CR_TAB
3234 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3235 AS1 (clr
,%A0
) CR_TAB
3240 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3241 AS1 (clr
,%A0
) CR_TAB
3242 AS1 (lsl
,%B0
) CR_TAB
3247 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3248 AS1 (clr
,%A0
) CR_TAB
3249 AS1 (lsl
,%B0
) CR_TAB
3250 AS1 (lsl
,%B0
) CR_TAB
3257 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3258 AS1 (clr
,%A0
) CR_TAB
3259 AS1 (swap
,%B0
) CR_TAB
3260 AS2 (andi
,%B0
,0xf0));
3265 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3266 AS1 (clr
,%A0
) CR_TAB
3267 AS1 (swap
,%B0
) CR_TAB
3268 AS2 (ldi
,%3,0xf0) CR_TAB
3272 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3273 AS1 (clr
,%A0
) CR_TAB
3274 AS1 (lsl
,%B0
) CR_TAB
3275 AS1 (lsl
,%B0
) CR_TAB
3276 AS1 (lsl
,%B0
) CR_TAB
3283 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3284 AS1 (clr
,%A0
) CR_TAB
3285 AS1 (swap
,%B0
) CR_TAB
3286 AS1 (lsl
,%B0
) CR_TAB
3287 AS2 (andi
,%B0
,0xe0));
3289 if (AVR_ENHANCED
&& scratch
)
3292 return (AS2 (ldi
,%3,0x20) CR_TAB
3293 AS2 (mul
,%A0
,%3) CR_TAB
3294 AS2 (mov
,%B0
,r0
) CR_TAB
3295 AS1 (clr
,%A0
) CR_TAB
3296 AS1 (clr
,__zero_reg__
));
3298 if (optimize_size
&& scratch
)
3303 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3304 AS1 (clr
,%A0
) CR_TAB
3305 AS1 (swap
,%B0
) CR_TAB
3306 AS1 (lsl
,%B0
) CR_TAB
3307 AS2 (ldi
,%3,0xe0) CR_TAB
3313 return ("set" CR_TAB
3314 AS2 (bld
,r1
,5) CR_TAB
3315 AS2 (mul
,%A0
,r1
) CR_TAB
3316 AS2 (mov
,%B0
,r0
) CR_TAB
3317 AS1 (clr
,%A0
) CR_TAB
3318 AS1 (clr
,__zero_reg__
));
3321 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3322 AS1 (clr
,%A0
) CR_TAB
3323 AS1 (lsl
,%B0
) CR_TAB
3324 AS1 (lsl
,%B0
) CR_TAB
3325 AS1 (lsl
,%B0
) CR_TAB
3326 AS1 (lsl
,%B0
) CR_TAB
3330 if (AVR_ENHANCED
&& ldi_ok
)
3333 return (AS2 (ldi
,%B0
,0x40) CR_TAB
3334 AS2 (mul
,%A0
,%B0
) CR_TAB
3335 AS2 (mov
,%B0
,r0
) CR_TAB
3336 AS1 (clr
,%A0
) CR_TAB
3337 AS1 (clr
,__zero_reg__
));
3339 if (AVR_ENHANCED
&& scratch
)
3342 return (AS2 (ldi
,%3,0x40) CR_TAB
3343 AS2 (mul
,%A0
,%3) CR_TAB
3344 AS2 (mov
,%B0
,r0
) CR_TAB
3345 AS1 (clr
,%A0
) CR_TAB
3346 AS1 (clr
,__zero_reg__
));
3348 if (optimize_size
&& ldi_ok
)
3351 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3352 AS2 (ldi
,%A0
,6) "\n1:\t"
3353 AS1 (lsl
,%B0
) CR_TAB
3354 AS1 (dec
,%A0
) CR_TAB
3357 if (optimize_size
&& scratch
)
3360 return (AS1 (clr
,%B0
) CR_TAB
3361 AS1 (lsr
,%A0
) CR_TAB
3362 AS1 (ror
,%B0
) CR_TAB
3363 AS1 (lsr
,%A0
) CR_TAB
3364 AS1 (ror
,%B0
) CR_TAB
3369 return (AS1 (clr
,%B0
) CR_TAB
3370 AS1 (lsr
,%A0
) CR_TAB
3371 AS1 (ror
,%B0
) CR_TAB
3376 out_shift_with_cnt ((AS1 (lsl
,%A0
) CR_TAB
3378 insn
, operands
, len
, 2);
3383 /* 32bit shift left ((long)x << i) */
3386 ashlsi3_out (insn
, operands
, len
)
3391 if (GET_CODE (operands
[2]) == CONST_INT
)
3399 switch (INTVAL (operands
[2]))
3403 int reg0
= true_regnum (operands
[0]);
3404 int reg1
= true_regnum (operands
[1]);
3407 return (AS2 (mov
,%D0
,%C1
) CR_TAB
3408 AS2 (mov
,%C0
,%B1
) CR_TAB
3409 AS2 (mov
,%B0
,%A1
) CR_TAB
3411 else if (reg0
+ 1 == reg1
)
3414 return AS1 (clr
,%A0
);
3417 return (AS1 (clr
,%A0
) CR_TAB
3418 AS2 (mov
,%B0
,%A1
) CR_TAB
3419 AS2 (mov
,%C0
,%B1
) CR_TAB
3425 int reg0
= true_regnum (operands
[0]);
3426 int reg1
= true_regnum (operands
[1]);
3428 if (AVR_ENHANCED
&& (reg0
+ 2 != reg1
))
3431 return (AS2 (movw
,%C0
,%A1
) CR_TAB
3432 AS1 (clr
,%B0
) CR_TAB
3435 if (reg0
+ 1 >= reg1
)
3436 return (AS2 (mov
,%D0
,%B1
) CR_TAB
3437 AS2 (mov
,%C0
,%A1
) CR_TAB
3438 AS1 (clr
,%B0
) CR_TAB
3440 if (reg0
+ 2 == reg1
)
3443 return (AS1 (clr
,%B0
) CR_TAB
3447 return (AS2 (mov
,%C0
,%A1
) CR_TAB
3448 AS2 (mov
,%D0
,%B1
) CR_TAB
3449 AS1 (clr
,%B0
) CR_TAB
3455 if (true_regnum (operands
[0]) + 3 != true_regnum (operands
[1]))
3456 return (AS2 (mov
,%D0
,%A1
) CR_TAB
3457 AS1 (clr
,%C0
) CR_TAB
3458 AS1 (clr
,%B0
) CR_TAB
3463 return (AS1 (clr
,%C0
) CR_TAB
3464 AS1 (clr
,%B0
) CR_TAB
3470 return (AS1 (clr
,%D0
) CR_TAB
3471 AS1 (lsr
,%A0
) CR_TAB
3472 AS1 (ror
,%D0
) CR_TAB
3473 AS1 (clr
,%C0
) CR_TAB
3474 AS1 (clr
,%B0
) CR_TAB
3479 out_shift_with_cnt ((AS1 (lsl
,%A0
) CR_TAB
3480 AS1 (rol
,%B0
) CR_TAB
3481 AS1 (rol
,%C0
) CR_TAB
3483 insn
, operands
, len
, 4);
3487 /* 8bit arithmetic shift right ((signed char)x >> i) */
3490 ashrqi3_out (insn
, operands
, len
)
3493 int *len
; /* insn length */
3495 if (GET_CODE (operands
[2]) == CONST_INT
)
3502 switch (INTVAL (operands
[2]))
3506 return AS1 (asr
,%0);
3510 return (AS1 (asr
,%0) CR_TAB
3515 return (AS1 (asr
,%0) CR_TAB
3521 return (AS1 (asr
,%0) CR_TAB
3528 return (AS1 (asr
,%0) CR_TAB
3536 return (AS2 (bst
,%0,6) CR_TAB
3538 AS2 (sbc
,%0,%0) CR_TAB
3544 return (AS1 (lsl
,%0) CR_TAB
3548 else if (CONSTANT_P (operands
[2]))
3549 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
3551 out_shift_with_cnt (AS1 (asr
,%0),
3552 insn
, operands
, len
, 1);
3557 /* 16bit arithmetic shift right ((signed short)x >> i) */
3560 ashrhi3_out (insn
, operands
, len
)
3565 if (GET_CODE (operands
[2]) == CONST_INT
)
3567 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
3568 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
3575 switch (INTVAL (operands
[2]))
3579 /* XXX try to optimize this too? */
3584 break; /* scratch ? 5 : 6 */
3586 return (AS2 (mov
,__tmp_reg__
,%A0
) CR_TAB
3587 AS2 (mov
,%A0
,%B0
) CR_TAB
3588 AS1 (lsl
,__tmp_reg__
) CR_TAB
3589 AS1 (rol
,%A0
) CR_TAB
3590 AS2 (sbc
,%B0
,%B0
) CR_TAB
3591 AS1 (lsl
,__tmp_reg__
) CR_TAB
3592 AS1 (rol
,%A0
) CR_TAB
3597 return (AS1 (lsl
,%A0
) CR_TAB
3598 AS2 (mov
,%A0
,%B0
) CR_TAB
3599 AS1 (rol
,%A0
) CR_TAB
3604 int reg0
= true_regnum (operands
[0]);
3605 int reg1
= true_regnum (operands
[1]);
3608 return *len
= 3, (AS2 (mov
,%A0
,%B0
) CR_TAB
3609 AS1 (lsl
,%B0
) CR_TAB
3611 else if (reg0
== reg1
+ 1)
3612 return *len
= 3, (AS1 (clr
,%B0
) CR_TAB
3613 AS2 (sbrc
,%A0
,7) CR_TAB
3616 return *len
= 4, (AS2 (mov
,%A0
,%B1
) CR_TAB
3617 AS1 (clr
,%B0
) CR_TAB
3618 AS2 (sbrc
,%A0
,7) CR_TAB
3624 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3625 AS1 (lsl
,%B0
) CR_TAB
3626 AS2 (sbc
,%B0
,%B0
) CR_TAB
3631 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3632 AS1 (lsl
,%B0
) CR_TAB
3633 AS2 (sbc
,%B0
,%B0
) CR_TAB
3634 AS1 (asr
,%A0
) CR_TAB
3638 if (AVR_ENHANCED
&& ldi_ok
)
3641 return (AS2 (ldi
,%A0
,0x20) CR_TAB
3642 AS2 (muls
,%B0
,%A0
) CR_TAB
3643 AS2 (mov
,%A0
,r1
) CR_TAB
3644 AS2 (sbc
,%B0
,%B0
) CR_TAB
3645 AS1 (clr
,__zero_reg__
));
3647 if (optimize_size
&& scratch
)
3650 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3651 AS1 (lsl
,%B0
) CR_TAB
3652 AS2 (sbc
,%B0
,%B0
) CR_TAB
3653 AS1 (asr
,%A0
) CR_TAB
3654 AS1 (asr
,%A0
) CR_TAB
3658 if (AVR_ENHANCED
&& ldi_ok
)
3661 return (AS2 (ldi
,%A0
,0x10) CR_TAB
3662 AS2 (muls
,%B0
,%A0
) CR_TAB
3663 AS2 (mov
,%A0
,r1
) CR_TAB
3664 AS2 (sbc
,%B0
,%B0
) CR_TAB
3665 AS1 (clr
,__zero_reg__
));
3667 if (optimize_size
&& scratch
)
3670 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3671 AS1 (lsl
,%B0
) CR_TAB
3672 AS2 (sbc
,%B0
,%B0
) CR_TAB
3673 AS1 (asr
,%A0
) CR_TAB
3674 AS1 (asr
,%A0
) CR_TAB
3675 AS1 (asr
,%A0
) CR_TAB
3679 if (AVR_ENHANCED
&& ldi_ok
)
3682 return (AS2 (ldi
,%A0
,0x08) CR_TAB
3683 AS2 (muls
,%B0
,%A0
) CR_TAB
3684 AS2 (mov
,%A0
,r1
) CR_TAB
3685 AS2 (sbc
,%B0
,%B0
) CR_TAB
3686 AS1 (clr
,__zero_reg__
));
3689 break; /* scratch ? 5 : 7 */
3691 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3692 AS1 (lsl
,%B0
) CR_TAB
3693 AS2 (sbc
,%B0
,%B0
) CR_TAB
3694 AS1 (asr
,%A0
) CR_TAB
3695 AS1 (asr
,%A0
) CR_TAB
3696 AS1 (asr
,%A0
) CR_TAB
3697 AS1 (asr
,%A0
) CR_TAB
3702 return (AS1 (lsl
,%B0
) CR_TAB
3703 AS2 (sbc
,%A0
,%A0
) CR_TAB
3704 AS1 (lsl
,%B0
) CR_TAB
3705 AS2 (mov
,%B0
,%A0
) CR_TAB
3709 return *len
= 3, (AS1 (lsl
,%B0
) CR_TAB
3710 AS2 (sbc
,%A0
,%A0
) CR_TAB
3715 out_shift_with_cnt ((AS1 (asr
,%B0
) CR_TAB
3717 insn
, operands
, len
, 2);
3722 /* 32bit arithmetic shift right ((signed long)x >> i) */
3725 ashrsi3_out (insn
, operands
, len
)
3730 if (GET_CODE (operands
[2]) == CONST_INT
)
3738 switch (INTVAL (operands
[2]))
3742 int reg0
= true_regnum (operands
[0]);
3743 int reg1
= true_regnum (operands
[1]);
3746 return (AS2 (mov
,%A0
,%B1
) CR_TAB
3747 AS2 (mov
,%B0
,%C1
) CR_TAB
3748 AS2 (mov
,%C0
,%D1
) CR_TAB
3749 AS1 (clr
,%D0
) CR_TAB
3750 AS2 (sbrc
,%C0
,7) CR_TAB
3752 else if (reg0
== reg1
+ 1)
3755 return (AS1 (clr
,%D0
) CR_TAB
3756 AS2 (sbrc
,%C0
,7) CR_TAB
3760 return (AS1 (clr
,%D0
) CR_TAB
3761 AS2 (sbrc
,%D1
,7) CR_TAB
3762 AS1 (dec
,%D0
) CR_TAB
3763 AS2 (mov
,%C0
,%D1
) CR_TAB
3764 AS2 (mov
,%B0
,%C1
) CR_TAB
3770 int reg0
= true_regnum (operands
[0]);
3771 int reg1
= true_regnum (operands
[1]);
3773 if (AVR_ENHANCED
&& (reg0
!= reg1
+ 2))
3776 return (AS2 (movw
,%A0
,%C1
) CR_TAB
3777 AS1 (clr
,%D0
) CR_TAB
3778 AS2 (sbrc
,%B0
,7) CR_TAB
3779 AS1 (com
,%D0
) CR_TAB
3782 if (reg0
<= reg1
+ 1)
3783 return (AS2 (mov
,%A0
,%C1
) CR_TAB
3784 AS2 (mov
,%B0
,%D1
) CR_TAB
3785 AS1 (clr
,%D0
) CR_TAB
3786 AS2 (sbrc
,%B0
,7) CR_TAB
3787 AS1 (com
,%D0
) CR_TAB
3789 else if (reg0
== reg1
+ 2)
3790 return *len
= 4, (AS1 (clr
,%D0
) CR_TAB
3791 AS2 (sbrc
,%B0
,7) CR_TAB
3792 AS1 (com
,%D0
) CR_TAB
3795 return (AS2 (mov
,%B0
,%D1
) CR_TAB
3796 AS2 (mov
,%A0
,%C1
) CR_TAB
3797 AS1 (clr
,%D0
) CR_TAB
3798 AS2 (sbrc
,%B0
,7) CR_TAB
3799 AS1 (com
,%D0
) CR_TAB
3804 if (true_regnum (operands
[0]) != true_regnum (operands
[1]) + 3)
3805 return *len
= 6, (AS2 (mov
,%A0
,%D1
) CR_TAB
3806 AS1 (clr
,%D0
) CR_TAB
3807 AS2 (sbrc
,%A0
,7) CR_TAB
3808 AS1 (com
,%D0
) CR_TAB
3809 AS2 (mov
,%B0
,%D0
) CR_TAB
3812 return *len
= 5, (AS1 (clr
,%D0
) CR_TAB
3813 AS2 (sbrc
,%A0
,7) CR_TAB
3814 AS1 (com
,%D0
) CR_TAB
3815 AS2 (mov
,%B0
,%D0
) CR_TAB
3820 return *len
= 4, (AS1 (lsl
,%D0
) CR_TAB
3821 AS2 (sbc
,%A0
,%A0
) CR_TAB
3822 AS2 (mov
,%B0
,%A0
) CR_TAB
3823 AS2 (movw
,%C0
,%A0
));
3825 return *len
= 5, (AS1 (lsl
,%D0
) CR_TAB
3826 AS2 (sbc
,%A0
,%A0
) CR_TAB
3827 AS2 (mov
,%B0
,%A0
) CR_TAB
3828 AS2 (mov
,%C0
,%A0
) CR_TAB
3833 out_shift_with_cnt ((AS1 (asr
,%D0
) CR_TAB
3834 AS1 (ror
,%C0
) CR_TAB
3835 AS1 (ror
,%B0
) CR_TAB
3837 insn
, operands
, len
, 4);
3841 /* 8bit logic shift right ((unsigned char)x >> i) */
3844 lshrqi3_out (insn
, operands
, len
)
3849 if (GET_CODE (operands
[2]) == CONST_INT
)
3856 switch (INTVAL (operands
[2]))
3860 return AS1 (clr
,%0);
3864 return AS1 (lsr
,%0);
3868 return (AS1 (lsr
,%0) CR_TAB
3872 return (AS1 (lsr
,%0) CR_TAB
3877 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3880 return (AS1 (swap
,%0) CR_TAB
3881 AS2 (andi
,%0,0x0f));
3884 return (AS1 (lsr
,%0) CR_TAB
3890 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3893 return (AS1 (swap
,%0) CR_TAB
3898 return (AS1 (lsr
,%0) CR_TAB
3905 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3908 return (AS1 (swap
,%0) CR_TAB
3914 return (AS1 (lsr
,%0) CR_TAB
3923 return (AS1 (rol
,%0) CR_TAB
3928 else if (CONSTANT_P (operands
[2]))
3929 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
3931 out_shift_with_cnt (AS1 (lsr
,%0),
3932 insn
, operands
, len
, 1);
3936 /* 16bit logic shift right ((unsigned short)x >> i) */
3939 lshrhi3_out (insn
, operands
, len
)
3944 if (GET_CODE (operands
[2]) == CONST_INT
)
3946 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
3947 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
3954 switch (INTVAL (operands
[2]))
3957 if (optimize_size
&& scratch
)
3962 return (AS1 (swap
,%B0
) CR_TAB
3963 AS1 (swap
,%A0
) CR_TAB
3964 AS2 (andi
,%A0
,0x0f) CR_TAB
3965 AS2 (eor
,%A0
,%B0
) CR_TAB
3966 AS2 (andi
,%B0
,0x0f) CR_TAB
3972 return (AS1 (swap
,%B0
) CR_TAB
3973 AS1 (swap
,%A0
) CR_TAB
3974 AS2 (ldi
,%3,0x0f) CR_TAB
3975 AS2 (and,%A0
,%3) CR_TAB
3976 AS2 (eor
,%A0
,%B0
) CR_TAB
3977 AS2 (and,%B0
,%3) CR_TAB
3980 break; /* optimize_size ? 6 : 8 */
3984 break; /* scratch ? 5 : 6 */
3988 return (AS1 (lsr
,%B0
) CR_TAB
3989 AS1 (ror
,%A0
) CR_TAB
3990 AS1 (swap
,%B0
) CR_TAB
3991 AS1 (swap
,%A0
) CR_TAB
3992 AS2 (andi
,%A0
,0x0f) CR_TAB
3993 AS2 (eor
,%A0
,%B0
) CR_TAB
3994 AS2 (andi
,%B0
,0x0f) CR_TAB
4000 return (AS1 (lsr
,%B0
) CR_TAB
4001 AS1 (ror
,%A0
) CR_TAB
4002 AS1 (swap
,%B0
) CR_TAB
4003 AS1 (swap
,%A0
) CR_TAB
4004 AS2 (ldi
,%3,0x0f) CR_TAB
4005 AS2 (and,%A0
,%3) CR_TAB
4006 AS2 (eor
,%A0
,%B0
) CR_TAB
4007 AS2 (and,%B0
,%3) CR_TAB
4014 break; /* scratch ? 5 : 6 */
4016 return (AS1 (clr
,__tmp_reg__
) CR_TAB
4017 AS1 (lsl
,%A0
) CR_TAB
4018 AS1 (rol
,%B0
) CR_TAB
4019 AS1 (rol
,__tmp_reg__
) CR_TAB
4020 AS1 (lsl
,%A0
) CR_TAB
4021 AS1 (rol
,%B0
) CR_TAB
4022 AS1 (rol
,__tmp_reg__
) CR_TAB
4023 AS2 (mov
,%A0
,%B0
) CR_TAB
4024 AS2 (mov
,%B0
,__tmp_reg__
));
4028 return (AS1 (lsl
,%A0
) CR_TAB
4029 AS2 (mov
,%A0
,%B0
) CR_TAB
4030 AS1 (rol
,%A0
) CR_TAB
4031 AS2 (sbc
,%B0
,%B0
) CR_TAB
4035 if (true_regnum (operands
[0]) != true_regnum (operands
[1]) + 1)
4036 return *len
= 2, (AS2 (mov
,%A0
,%B1
) CR_TAB
4039 return *len
= 1, AS1 (clr
,%B0
);
4043 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4044 AS1 (clr
,%B0
) CR_TAB
4049 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4050 AS1 (clr
,%B0
) CR_TAB
4051 AS1 (lsr
,%A0
) CR_TAB
4056 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4057 AS1 (clr
,%B0
) CR_TAB
4058 AS1 (lsr
,%A0
) CR_TAB
4059 AS1 (lsr
,%A0
) CR_TAB
4066 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4067 AS1 (clr
,%B0
) CR_TAB
4068 AS1 (swap
,%A0
) CR_TAB
4069 AS2 (andi
,%A0
,0x0f));
4074 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4075 AS1 (clr
,%B0
) CR_TAB
4076 AS1 (swap
,%A0
) CR_TAB
4077 AS2 (ldi
,%3,0x0f) CR_TAB
4081 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4082 AS1 (clr
,%B0
) CR_TAB
4083 AS1 (lsr
,%A0
) CR_TAB
4084 AS1 (lsr
,%A0
) CR_TAB
4085 AS1 (lsr
,%A0
) CR_TAB
4092 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4093 AS1 (clr
,%B0
) CR_TAB
4094 AS1 (swap
,%A0
) CR_TAB
4095 AS1 (lsr
,%A0
) CR_TAB
4096 AS2 (andi
,%A0
,0x07));
4098 if (AVR_ENHANCED
&& scratch
)
4101 return (AS2 (ldi
,%3,0x08) CR_TAB
4102 AS2 (mul
,%B0
,%3) CR_TAB
4103 AS2 (mov
,%A0
,r1
) CR_TAB
4104 AS1 (clr
,%B0
) CR_TAB
4105 AS1 (clr
,__zero_reg__
));
4107 if (optimize_size
&& scratch
)
4112 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4113 AS1 (clr
,%B0
) CR_TAB
4114 AS1 (swap
,%A0
) CR_TAB
4115 AS1 (lsr
,%A0
) CR_TAB
4116 AS2 (ldi
,%3,0x07) CR_TAB
4122 return ("set" CR_TAB
4123 AS2 (bld
,r1
,3) CR_TAB
4124 AS2 (mul
,%B0
,r1
) CR_TAB
4125 AS2 (mov
,%A0
,r1
) CR_TAB
4126 AS1 (clr
,%B0
) CR_TAB
4127 AS1 (clr
,__zero_reg__
));
4130 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4131 AS1 (clr
,%B0
) CR_TAB
4132 AS1 (lsr
,%A0
) CR_TAB
4133 AS1 (lsr
,%A0
) CR_TAB
4134 AS1 (lsr
,%A0
) CR_TAB
4135 AS1 (lsr
,%A0
) CR_TAB
4139 if (AVR_ENHANCED
&& ldi_ok
)
4142 return (AS2 (ldi
,%A0
,0x04) CR_TAB
4143 AS2 (mul
,%B0
,%A0
) CR_TAB
4144 AS2 (mov
,%A0
,r1
) CR_TAB
4145 AS1 (clr
,%B0
) CR_TAB
4146 AS1 (clr
,__zero_reg__
));
4148 if (AVR_ENHANCED
&& scratch
)
4151 return (AS2 (ldi
,%3,0x04) CR_TAB
4152 AS2 (mul
,%B0
,%3) CR_TAB
4153 AS2 (mov
,%A0
,r1
) CR_TAB
4154 AS1 (clr
,%B0
) CR_TAB
4155 AS1 (clr
,__zero_reg__
));
4157 if (optimize_size
&& ldi_ok
)
4160 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4161 AS2 (ldi
,%B0
,6) "\n1:\t"
4162 AS1 (lsr
,%A0
) CR_TAB
4163 AS1 (dec
,%B0
) CR_TAB
4166 if (optimize_size
&& scratch
)
4169 return (AS1 (clr
,%A0
) CR_TAB
4170 AS1 (lsl
,%B0
) CR_TAB
4171 AS1 (rol
,%A0
) CR_TAB
4172 AS1 (lsl
,%B0
) CR_TAB
4173 AS1 (rol
,%A0
) CR_TAB
4178 return (AS1 (clr
,%A0
) CR_TAB
4179 AS1 (lsl
,%B0
) CR_TAB
4180 AS1 (rol
,%A0
) CR_TAB
4185 out_shift_with_cnt ((AS1 (lsr
,%B0
) CR_TAB
4187 insn
, operands
, len
, 2);
4191 /* 32bit logic shift right ((unsigned int)x >> i) */
4194 lshrsi3_out (insn
, operands
, len
)
4199 if (GET_CODE (operands
[2]) == CONST_INT
)
4207 switch (INTVAL (operands
[2]))
4211 int reg0
= true_regnum (operands
[0]);
4212 int reg1
= true_regnum (operands
[1]);
4215 return (AS2 (mov
,%A0
,%B1
) CR_TAB
4216 AS2 (mov
,%B0
,%C1
) CR_TAB
4217 AS2 (mov
,%C0
,%D1
) CR_TAB
4219 else if (reg0
== reg1
+ 1)
4220 return *len
= 1, AS1 (clr
,%D0
);
4222 return (AS1 (clr
,%D0
) CR_TAB
4223 AS2 (mov
,%C0
,%D1
) CR_TAB
4224 AS2 (mov
,%B0
,%C1
) CR_TAB
4230 int reg0
= true_regnum (operands
[0]);
4231 int reg1
= true_regnum (operands
[1]);
4233 if (AVR_ENHANCED
&& (reg0
!= reg1
+ 2))
4236 return (AS2 (movw
,%A0
,%C1
) CR_TAB
4237 AS1 (clr
,%C0
) CR_TAB
4240 if (reg0
<= reg1
+ 1)
4241 return (AS2 (mov
,%A0
,%C1
) CR_TAB
4242 AS2 (mov
,%B0
,%D1
) CR_TAB
4243 AS1 (clr
,%C0
) CR_TAB
4245 else if (reg0
== reg1
+ 2)
4246 return *len
= 2, (AS1 (clr
,%C0
) CR_TAB
4249 return (AS2 (mov
,%B0
,%D1
) CR_TAB
4250 AS2 (mov
,%A0
,%C1
) CR_TAB
4251 AS1 (clr
,%C0
) CR_TAB
4256 if (true_regnum (operands
[0]) != true_regnum (operands
[1]) + 3)
4257 return *len
= 4, (AS2 (mov
,%A0
,%D1
) CR_TAB
4258 AS1 (clr
,%B0
) CR_TAB
4259 AS1 (clr
,%C0
) CR_TAB
4262 return *len
= 3, (AS1 (clr
,%B0
) CR_TAB
4263 AS1 (clr
,%C0
) CR_TAB
4268 return (AS1 (clr
,%A0
) CR_TAB
4269 AS2 (sbrc
,%D0
,7) CR_TAB
4270 AS1 (inc
,%A0
) CR_TAB
4271 AS1 (clr
,%B0
) CR_TAB
4272 AS1 (clr
,%C0
) CR_TAB
4277 out_shift_with_cnt ((AS1 (lsr
,%D0
) CR_TAB
4278 AS1 (ror
,%C0
) CR_TAB
4279 AS1 (ror
,%B0
) CR_TAB
4281 insn
, operands
, len
, 4);
4285 /* Modifies the length assigned to instruction INSN
4286 LEN is the initially computed length of the insn. */
4289 adjust_insn_length (insn
, len
)
4293 rtx patt
= PATTERN (insn
);
4296 if (GET_CODE (patt
) == SET
)
4299 op
[1] = SET_SRC (patt
);
4300 op
[0] = SET_DEST (patt
);
4301 if (general_operand (op
[1], VOIDmode
)
4302 && general_operand (op
[0], VOIDmode
))
4304 switch (GET_MODE (op
[0]))
4307 output_movqi (insn
, op
, &len
);
4310 output_movhi (insn
, op
, &len
);
4314 output_movsisf (insn
, op
, &len
);
4320 else if (op
[0] == cc0_rtx
&& REG_P (op
[1]))
4322 switch (GET_MODE (op
[1]))
4324 case HImode
: out_tsthi (insn
,&len
); break;
4325 case SImode
: out_tstsi (insn
,&len
); break;
4329 else if (GET_CODE (op
[1]) == AND
)
4331 if (GET_CODE (XEXP (op
[1],1)) == CONST_INT
)
4333 HOST_WIDE_INT mask
= INTVAL (XEXP (op
[1],1));
4334 if (GET_MODE (op
[1]) == SImode
)
4335 len
= (((mask
& 0xff) != 0xff)
4336 + ((mask
& 0xff00) != 0xff00)
4337 + ((mask
& 0xff0000L
) != 0xff0000L
)
4338 + ((mask
& 0xff000000L
) != 0xff000000L
));
4339 else if (GET_MODE (op
[1]) == HImode
)
4340 len
= (((mask
& 0xff) != 0xff)
4341 + ((mask
& 0xff00) != 0xff00));
4344 else if (GET_CODE (op
[1]) == IOR
)
4346 if (GET_CODE (XEXP (op
[1],1)) == CONST_INT
)
4348 HOST_WIDE_INT mask
= INTVAL (XEXP (op
[1],1));
4349 if (GET_MODE (op
[1]) == SImode
)
4350 len
= (((mask
& 0xff) != 0)
4351 + ((mask
& 0xff00) != 0)
4352 + ((mask
& 0xff0000L
) != 0)
4353 + ((mask
& 0xff000000L
) != 0));
4354 else if (GET_MODE (op
[1]) == HImode
)
4355 len
= (((mask
& 0xff) != 0)
4356 + ((mask
& 0xff00) != 0));
4360 set
= single_set (insn
);
4365 op
[1] = SET_SRC (set
);
4366 op
[0] = SET_DEST (set
);
4368 if (GET_CODE (patt
) == PARALLEL
4369 && general_operand (op
[1], VOIDmode
)
4370 && general_operand (op
[0], VOIDmode
))
4372 if (XVECLEN (patt
, 0) == 2)
4373 op
[2] = XVECEXP (patt
, 0, 1);
4375 switch (GET_MODE (op
[0]))
4381 output_reload_inhi (insn
, op
, &len
);
4385 output_reload_insisf (insn
, op
, &len
);
4391 else if (GET_CODE (op
[1]) == ASHIFT
4392 || GET_CODE (op
[1]) == ASHIFTRT
4393 || GET_CODE (op
[1]) == LSHIFTRT
)
4397 ops
[1] = XEXP (op
[1],0);
4398 ops
[2] = XEXP (op
[1],1);
4399 switch (GET_CODE (op
[1]))
4402 switch (GET_MODE (op
[0]))
4404 case QImode
: ashlqi3_out (insn
,ops
,&len
); break;
4405 case HImode
: ashlhi3_out (insn
,ops
,&len
); break;
4406 case SImode
: ashlsi3_out (insn
,ops
,&len
); break;
4411 switch (GET_MODE (op
[0]))
4413 case QImode
: ashrqi3_out (insn
,ops
,&len
); break;
4414 case HImode
: ashrhi3_out (insn
,ops
,&len
); break;
4415 case SImode
: ashrsi3_out (insn
,ops
,&len
); break;
4420 switch (GET_MODE (op
[0]))
4422 case QImode
: lshrqi3_out (insn
,ops
,&len
); break;
4423 case HImode
: lshrhi3_out (insn
,ops
,&len
); break;
4424 case SImode
: lshrsi3_out (insn
,ops
,&len
); break;
4436 /* Return nonzero if register REG dead after INSN */
4439 reg_unused_after (insn
, reg
)
4443 return (dead_or_set_p (insn
, reg
)
4444 || (REG_P(reg
) && _reg_unused_after (insn
, reg
)));
4447 /* Return nonzero if REG is not used after INSN.
4448 We assume REG is a reload reg, and therefore does
4449 not live past labels. It may live past calls or jumps though. */
4452 _reg_unused_after (insn
, reg
)
4459 /* If the reg is set by this instruction, then it is safe for our
4460 case. Disregard the case where this is a store to memory, since
4461 we are checking a register used in the store address. */
4462 set
= single_set (insn
);
4463 if (set
&& GET_CODE (SET_DEST (set
)) != MEM
4464 && reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
4467 while ((insn
= NEXT_INSN (insn
)))
4469 code
= GET_CODE (insn
);
4472 /* If this is a label that existed before reload, then the register
4473 if dead here. However, if this is a label added by reorg, then
4474 the register may still be live here. We can't tell the difference,
4475 so we just ignore labels completely. */
4476 if (code
== CODE_LABEL
)
4481 if (code
== JUMP_INSN
)
4484 /* If this is a sequence, we must handle them all at once.
4485 We could have for instance a call that sets the target register,
4486 and an insn in a delay slot that uses the register. In this case,
4487 we must return 0. */
4488 else if (code
== INSN
&& GET_CODE (PATTERN (insn
)) == SEQUENCE
)
4493 for (i
= 0; i
< XVECLEN (PATTERN (insn
), 0); i
++)
4495 rtx this_insn
= XVECEXP (PATTERN (insn
), 0, i
);
4496 rtx set
= single_set (this_insn
);
4498 if (GET_CODE (this_insn
) == CALL_INSN
)
4500 else if (GET_CODE (this_insn
) == JUMP_INSN
)
4502 if (INSN_ANNULLED_BRANCH_P (this_insn
))
4507 if (set
&& reg_overlap_mentioned_p (reg
, SET_SRC (set
)))
4509 if (set
&& reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
4511 if (GET_CODE (SET_DEST (set
)) != MEM
)
4517 && reg_overlap_mentioned_p (reg
, PATTERN (this_insn
)))
4522 else if (code
== JUMP_INSN
)
4526 if (code
== CALL_INSN
)
4529 for (tem
= CALL_INSN_FUNCTION_USAGE (insn
); tem
; tem
= XEXP (tem
, 1))
4530 if (GET_CODE (XEXP (tem
, 0)) == USE
4531 && REG_P (XEXP (XEXP (tem
, 0), 0))
4532 && reg_overlap_mentioned_p (reg
, XEXP (XEXP (tem
, 0), 0)))
4534 if (call_used_regs
[REGNO (reg
)])
4538 if (GET_RTX_CLASS (code
) == 'i')
4540 rtx set
= single_set (insn
);
4542 if (set
&& reg_overlap_mentioned_p (reg
, SET_SRC (set
)))
4544 if (set
&& reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
4545 return GET_CODE (SET_DEST (set
)) != MEM
;
4546 if (set
== 0 && reg_overlap_mentioned_p (reg
, PATTERN (insn
)))
4553 /* Target hook for assembling integer objects. The AVR version needs
4554 special handling for references to certain labels. */
4557 avr_assemble_integer (x
, size
, aligned_p
)
4562 if (size
== POINTER_SIZE
/ BITS_PER_UNIT
&& aligned_p
4563 && ((GET_CODE (x
) == SYMBOL_REF
&& SYMBOL_REF_FLAG (x
))
4564 || GET_CODE (x
) == LABEL_REF
))
4566 fputs ("\t.word\tpm(", asm_out_file
);
4567 output_addr_const (asm_out_file
, x
);
4568 fputs (")\n", asm_out_file
);
4571 return default_assemble_integer (x
, size
, aligned_p
);
4574 /* Sets section name for declaration DECL */
4577 avr_unique_section (decl
, reloc
)
4579 int reloc ATTRIBUTE_UNUSED
;
4582 const char *name
, *prefix
;
4585 name
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
));
4586 name
= (* targetm
.strip_name_encoding
) (name
);
4588 if (TREE_CODE (decl
) == FUNCTION_DECL
)
4590 if (flag_function_sections
)
4598 if (flag_function_sections
)
4600 len
= strlen (name
) + strlen (prefix
);
4601 string
= alloca (len
+ 1);
4602 sprintf (string
, "%s%s", prefix
, name
);
4603 DECL_SECTION_NAME (decl
) = build_string (len
, string
);
4608 /* The routine used to output NUL terminated strings. We use a special
4609 version of this for most svr4 targets because doing so makes the
4610 generated assembly code more compact (and thus faster to assemble)
4611 as well as more readable, especially for targets like the i386
4612 (where the only alternative is to output character sequences as
4613 comma separated lists of numbers). */
4616 gas_output_limited_string(file
, str
)
4620 const unsigned char *_limited_str
= (unsigned char *) str
;
4622 fprintf (file
, "%s\"", STRING_ASM_OP
);
4623 for (; (ch
= *_limited_str
); _limited_str
++)
4626 switch (escape
= ESCAPES
[ch
])
4632 fprintf (file
, "\\%03o", ch
);
4636 putc (escape
, file
);
4640 fprintf (file
, "\"\n");
4643 /* The routine used to output sequences of byte values. We use a special
4644 version of this for most svr4 targets because doing so makes the
4645 generated assembly code more compact (and thus faster to assemble)
4646 as well as more readable. Note that if we find subparts of the
4647 character sequence which end with NUL (and which are shorter than
4648 STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
4651 gas_output_ascii(file
, str
, length
)
4656 const unsigned char *_ascii_bytes
= (const unsigned char *) str
;
4657 const unsigned char *limit
= _ascii_bytes
+ length
;
4658 unsigned bytes_in_chunk
= 0;
4659 for (; _ascii_bytes
< limit
; _ascii_bytes
++)
4661 const unsigned char *p
;
4662 if (bytes_in_chunk
>= 60)
4664 fprintf (file
, "\"\n");
4667 for (p
= _ascii_bytes
; p
< limit
&& *p
!= '\0'; p
++)
4669 if (p
< limit
&& (p
- _ascii_bytes
) <= (signed)STRING_LIMIT
)
4671 if (bytes_in_chunk
> 0)
4673 fprintf (file
, "\"\n");
4676 gas_output_limited_string (file
, (char*)_ascii_bytes
);
4683 if (bytes_in_chunk
== 0)
4684 fprintf (file
, "\t.ascii\t\"");
4685 switch (escape
= ESCAPES
[ch
= *_ascii_bytes
])
4692 fprintf (file
, "\\%03o", ch
);
4693 bytes_in_chunk
+= 4;
4697 putc (escape
, file
);
4698 bytes_in_chunk
+= 2;
4703 if (bytes_in_chunk
> 0)
4704 fprintf (file
, "\"\n");
4707 /* Return value is nonzero if pseudos that have been
4708 assigned to registers of class CLASS would likely be spilled
4709 because registers of CLASS are needed for spill registers. */
4712 class_likely_spilled_p (c
)
4715 return (c
!= ALL_REGS
&& c
!= ADDW_REGS
);
4718 /* Valid attributes:
4719 progmem - put data to program memory;
4720 signal - make a function to be hardware interrupt. After function
4721 prologue interrupts are disabled;
4722 interrupt - make a function to be hardware interrupt. After function
4723 prologue interrupts are enabled;
4724 naked - don't generate function prologue/epilogue and `ret' command.
4726 Only `progmem' attribute valid for type. */
4728 const struct attribute_spec avr_attribute_table
[] =
4730 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4731 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute
},
4732 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute
},
4733 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute
},
4734 { "naked", 0, 0, true, false, false, avr_handle_fndecl_attribute
},
4735 { NULL
, 0, 0, false, false, false, NULL
}
4738 /* Handle a "progmem" attribute; arguments as in
4739 struct attribute_spec.handler. */
4741 avr_handle_progmem_attribute (node
, name
, args
, flags
, no_add_attrs
)
4744 tree args ATTRIBUTE_UNUSED
;
4745 int flags ATTRIBUTE_UNUSED
;
4750 if (TREE_CODE (*node
) == TYPE_DECL
)
4752 /* This is really a decl attribute, not a type attribute,
4753 but try to handle it for GCC 3.0 backwards compatibility. */
4755 tree type
= TREE_TYPE (*node
);
4756 tree attr
= tree_cons (name
, args
, TYPE_ATTRIBUTES (type
));
4757 tree newtype
= build_type_attribute_variant (type
, attr
);
4759 TYPE_MAIN_VARIANT (newtype
) = TYPE_MAIN_VARIANT (type
);
4760 TREE_TYPE (*node
) = newtype
;
4761 *no_add_attrs
= true;
4763 else if (TREE_STATIC (*node
) || DECL_EXTERNAL (*node
))
4765 if (DECL_INITIAL (*node
) == NULL_TREE
&& !DECL_EXTERNAL (*node
))
4767 warning ("only initialized variables can be placed into "
4768 "program memory area");
4769 *no_add_attrs
= true;
4774 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name
));
4775 *no_add_attrs
= true;
4782 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4783 struct attribute_spec.handler. */
4785 avr_handle_fndecl_attribute (node
, name
, args
, flags
, no_add_attrs
)
4788 tree args ATTRIBUTE_UNUSED
;
4789 int flags ATTRIBUTE_UNUSED
;
4792 if (TREE_CODE (*node
) != FUNCTION_DECL
)
4794 warning ("`%s' attribute only applies to functions",
4795 IDENTIFIER_POINTER (name
));
4796 *no_add_attrs
= true;
4802 /* Look for attribute `progmem' in DECL
4803 if found return 1, otherwise 0. */
4806 avr_progmem_p (decl
)
4811 if (TREE_CODE (decl
) != VAR_DECL
)
4815 != lookup_attribute ("progmem", DECL_ATTRIBUTES (decl
)))
4821 while (TREE_CODE (a
) == ARRAY_TYPE
);
4823 if (a
== error_mark_node
)
4826 if (NULL_TREE
!= lookup_attribute ("progmem", TYPE_ATTRIBUTES (a
)))
4832 /* Encode section information about tree DECL. */
4835 avr_encode_section_info (decl
, first
)
4839 if (TREE_CODE (decl
) == FUNCTION_DECL
)
4840 SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl
), 0)) = 1;
4842 && (TREE_STATIC (decl
) || DECL_EXTERNAL (decl
))
4843 && TREE_CODE (decl
) == VAR_DECL
4844 && avr_progmem_p (decl
))
4846 static const char *const dsec
= ".progmem.data";
4847 DECL_SECTION_NAME (decl
) = build_string (strlen (dsec
), dsec
);
4848 TREE_READONLY (decl
) = 1;
4853 avr_section_type_flags (decl
, name
, reloc
)
4858 unsigned int flags
= default_section_type_flags (decl
, name
, reloc
);
4860 if (strncmp (name
, ".noinit", 7) == 0)
4862 if (decl
&& TREE_CODE (decl
) == VAR_DECL
4863 && DECL_INITIAL (decl
) == NULL_TREE
)
4864 flags
|= SECTION_BSS
; /* @nobits */
4866 warning ("only uninitialized variables can be placed in the "
4873 /* Outputs to the stdio stream FILE some
4874 appropriate text to go at the start of an assembler file. */
4877 asm_file_start (file
)
4881 error ("MCU `%s' supported for assembler only", avr_mcu_name
);
4883 output_file_directive (file
, main_input_filename
);
4884 fprintf (file
, "\t.arch %s\n", avr_mcu_name
);
4885 fputs ("__SREG__ = 0x3f\n"
4887 "__SP_L__ = 0x3d\n", file
);
4889 fputs ("__tmp_reg__ = 0\n"
4890 "__zero_reg__ = 1\n", file
);
4892 /* FIXME: output these only if there is anything in the .data / .bss
4893 sections - some code size could be saved by not linking in the
4894 initialization code from libgcc if one or both sections are empty. */
4895 fputs ("\t.global __do_copy_data\n", file
);
4896 fputs ("\t.global __do_clear_bss\n", file
);
4898 commands_in_file
= 0;
4899 commands_in_prologues
= 0;
4900 commands_in_epilogues
= 0;
4903 /* Outputs to the stdio stream FILE some
4904 appropriate text to go at the end of an assembler file. */
4910 fputs ("/* File ", file
);
4911 output_quoted_string (file
, main_input_filename
);
4913 ": code %4d = 0x%04x (%4d), prologues %3d, epilogues %3d */\n",
4916 commands_in_file
- commands_in_prologues
- commands_in_epilogues
,
4917 commands_in_prologues
, commands_in_epilogues
);
4920 /* Choose the order in which to allocate hard registers for
4921 pseudo-registers local to a basic block.
4923 Store the desired register order in the array `reg_alloc_order'.
4924 Element 0 should be the register to allocate first; element 1, the
4925 next register; and so on. */
4928 order_regs_for_local_alloc ()
4931 static const int order_0
[] = {
4939 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4943 static const int order_1
[] = {
4951 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4955 static const int order_2
[] = {
4964 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4969 const int *order
= (TARGET_ORDER_1
? order_1
:
4970 TARGET_ORDER_2
? order_2
:
4972 for (i
=0; i
< ARRAY_SIZE (order_0
); ++i
)
4973 reg_alloc_order
[i
] = order
[i
];
4976 /* Calculate the cost of X code of the expression in which it is contained,
4977 found in OUTER_CODE */
4980 default_rtx_costs (X
, code
, outer_code
)
4983 enum rtx_code outer_code
;
4990 cost
= 2 * GET_MODE_SIZE (GET_MODE (X
));
4993 if (outer_code
!= SET
)
4995 if (GET_CODE (XEXP (X
,0)) == SYMBOL_REF
)
4996 cost
+= 2 * GET_MODE_SIZE (GET_MODE (X
));
4998 cost
+= GET_MODE_SIZE (GET_MODE (X
));
5004 if (outer_code
== SET
)
5005 cost
= GET_MODE_SIZE (GET_MODE (X
));
5007 cost
= -GET_MODE_SIZE (GET_MODE (X
));
5010 if (outer_code
== SET
)
5011 cost
= GET_MODE_SIZE (GET_MODE (X
));
5017 if (outer_code
== SET
)
5019 if (X
== stack_pointer_rtx
)
5021 else if (GET_CODE (XEXP (X
,1)) == CONST_INT
)
5022 cost
= (INTVAL (XEXP (X
,1)) <= 63 ? 1 :
5023 GET_MODE_SIZE (GET_MODE (X
)));
5025 cost
= GET_MODE_SIZE (GET_MODE (X
));
5029 if (GET_CODE (XEXP (X
,1)) == CONST_INT
)
5030 cost
= GET_MODE_SIZE (GET_MODE (XEXP (X
,0)));
5038 /* Calculate the cost of a memory address */
5041 avr_address_cost (x
)
5044 if (GET_CODE (x
) == PLUS
5045 && GET_CODE (XEXP (x
,1)) == CONST_INT
5046 && (REG_P (XEXP (x
,0)) || GET_CODE (XEXP (x
,0)) == SUBREG
)
5047 && INTVAL (XEXP (x
,1)) >= 61)
5049 if (CONSTANT_ADDRESS_P (x
))
5051 if (avr_io_address_p (x
, 1))
5058 /* EXTRA_CONSTRAINT helper */
5061 extra_constraint (x
, c
)
5066 && GET_CODE (x
) == MEM
5067 && GET_CODE (XEXP (x
,0)) == PLUS
)
5069 if (TARGET_ALL_DEBUG
)
5071 fprintf (stderr
, ("extra_constraint:\n"
5072 "reload_completed: %d\n"
5073 "reload_in_progress: %d\n"),
5074 reload_completed
, reload_in_progress
);
5077 if (GET_CODE (x
) == MEM
5078 && GET_CODE (XEXP (x
,0)) == PLUS
5079 && REG_P (XEXP (XEXP (x
,0), 0))
5080 && GET_CODE (XEXP (XEXP (x
,0), 1)) == CONST_INT
5081 && (INTVAL (XEXP (XEXP (x
,0), 1))
5082 <= MAX_LD_OFFSET (GET_MODE (x
))))
5084 rtx xx
= XEXP (XEXP (x
,0), 0);
5085 int regno
= REGNO (xx
);
5086 if (TARGET_ALL_DEBUG
)
5088 fprintf (stderr
, ("extra_constraint:\n"
5089 "reload_completed: %d\n"
5090 "reload_in_progress: %d\n"),
5091 reload_completed
, reload_in_progress
);
5094 if (regno
>= FIRST_PSEUDO_REGISTER
)
5095 return 1; /* allocate pseudos */
5096 else if (regno
== REG_Z
|| regno
== REG_Y
)
5097 return 1; /* strictly check */
5098 else if (xx
== frame_pointer_rtx
5099 || xx
== arg_pointer_rtx
)
5100 return 1; /* XXX frame & arg pointer checks */
5106 /* Convert condition code CONDITION to the valid AVR condition code */
5109 avr_normalize_condition (condition
)
5127 /* This fnction optimizes conditional jumps */
5130 machine_dependent_reorg (first_insn
)
5135 for (insn
= first_insn
; insn
; insn
= NEXT_INSN (insn
))
5137 if (! (GET_CODE (insn
) == INSN
5138 || GET_CODE (insn
) == CALL_INSN
5139 || GET_CODE (insn
) == JUMP_INSN
)
5140 || !single_set (insn
))
5143 pattern
= PATTERN (insn
);
5145 if (GET_CODE (pattern
) == PARALLEL
)
5146 pattern
= XVECEXP (pattern
, 0, 0);
5147 if (GET_CODE (pattern
) == SET
5148 && SET_DEST (pattern
) == cc0_rtx
5149 && compare_diff_p (insn
))
5151 if (GET_CODE (SET_SRC (pattern
)) == COMPARE
)
5153 /* Now we work under compare insn */
5155 pattern
= SET_SRC (pattern
);
5156 if (true_regnum (XEXP (pattern
,0)) >= 0
5157 && true_regnum (XEXP (pattern
,1)) >= 0 )
5159 rtx x
= XEXP (pattern
,0);
5160 rtx next
= next_real_insn (insn
);
5161 rtx pat
= PATTERN (next
);
5162 rtx src
= SET_SRC (pat
);
5163 rtx t
= XEXP (src
,0);
5164 PUT_CODE (t
, swap_condition (GET_CODE (t
)));
5165 XEXP (pattern
,0) = XEXP (pattern
,1);
5166 XEXP (pattern
,1) = x
;
5167 INSN_CODE (next
) = -1;
5169 else if (true_regnum (XEXP (pattern
,0)) >= 0
5170 && GET_CODE (XEXP (pattern
,1)) == CONST_INT
)
5172 rtx x
= XEXP (pattern
,1);
5173 rtx next
= next_real_insn (insn
);
5174 rtx pat
= PATTERN (next
);
5175 rtx src
= SET_SRC (pat
);
5176 rtx t
= XEXP (src
,0);
5177 enum machine_mode mode
= GET_MODE (XEXP (pattern
, 0));
5179 if (avr_simplify_comparision_p (mode
, GET_CODE (t
), x
))
5181 XEXP (pattern
, 1) = gen_int_mode (INTVAL (x
) + 1, mode
);
5182 PUT_CODE (t
, avr_normalize_condition (GET_CODE (t
)));
5183 INSN_CODE (next
) = -1;
5184 INSN_CODE (insn
) = -1;
5188 else if (true_regnum (SET_SRC (pattern
)) >= 0)
5190 /* This is a tst insn */
5191 rtx next
= next_real_insn (insn
);
5192 rtx pat
= PATTERN (next
);
5193 rtx src
= SET_SRC (pat
);
5194 rtx t
= XEXP (src
,0);
5196 PUT_CODE (t
, swap_condition (GET_CODE (t
)));
5197 SET_SRC (pattern
) = gen_rtx (NEG
,
5198 GET_MODE (SET_SRC (pattern
)),
5200 INSN_CODE (next
) = -1;
5201 INSN_CODE (insn
) = -1;
5207 /* Returns register number for function return value.*/
5215 /* Ceate an RTX representing the place where a
5216 library function returns a value of mode MODE. */
5219 avr_libcall_value (mode
)
5220 enum machine_mode mode
;
5222 int offs
= GET_MODE_SIZE (mode
);
5225 return gen_rtx (REG
, mode
, RET_REGISTER
+ 2 - offs
);
5228 /* Create an RTX representing the place where a
5229 function returns a value of data type VALTYPE. */
5232 avr_function_value (type
, func
)
5234 tree func ATTRIBUTE_UNUSED
;
5238 if (TYPE_MODE (type
) != BLKmode
)
5239 return avr_libcall_value (TYPE_MODE (type
));
5241 offs
= int_size_in_bytes (type
);
5244 if (offs
> 2 && offs
< GET_MODE_SIZE (SImode
))
5245 offs
= GET_MODE_SIZE (SImode
);
5246 else if (offs
> GET_MODE_SIZE (SImode
) && offs
< GET_MODE_SIZE (DImode
))
5247 offs
= GET_MODE_SIZE (DImode
);
5249 return gen_rtx (REG
, BLKmode
, RET_REGISTER
+ 2 - offs
);
5252 /* Returns nonzero if the number MASK has only one bit set. */
5255 mask_one_bit_p (mask
)
5259 unsigned HOST_WIDE_INT n
=mask
;
5260 for (i
= 0; i
< 32; ++i
)
5262 if (n
& 0x80000000L
)
5264 if (n
& 0x7fffffffL
)
5275 /* Places additional restrictions on the register class to
5276 use when it is necessary to copy value X into a register
5280 preferred_reload_class (x
, class)
5281 rtx x ATTRIBUTE_UNUSED
;
5282 enum reg_class
class;
5288 test_hard_reg_class (class, x
)
5289 enum reg_class
class;
5292 int regno
= true_regnum (x
);
5296 if (TEST_HARD_REG_CLASS (class, regno
))
5304 jump_over_one_insn_p (insn
, dest
)
5308 int uid
= INSN_UID (GET_CODE (dest
) == LABEL_REF
5311 int jump_addr
= INSN_ADDRESSES (INSN_UID (insn
));
5312 int dest_addr
= INSN_ADDRESSES (uid
);
5313 return dest_addr
- jump_addr
== get_attr_length (insn
) + 1;
5316 /* Returns 1 if a value of mode MODE can be stored starting with hard
5317 register number REGNO. On the enhanced core, anything larger than
5318 1 byte must start in even numbered register for "movw" to work
5319 (this way we don't have to check for odd registers everywhere). */
5322 avr_hard_regno_mode_ok (regno
, mode
)
5324 enum machine_mode mode
;
5326 /* Bug workaround: recog.c (peep2_find_free_register) and probably
5327 a few other places assume that the frame pointer is a single hard
5328 register, so r29 may be allocated and overwrite the high byte of
5329 the frame pointer. Do not allow any value to start in r29. */
5330 if (regno
== REG_Y
+ 1)
5335 /* if (regno < 24 && !AVR_ENHANCED)
5337 return !(regno
& 1);
5340 /* Returns 1 if we know register operand OP was 0 before INSN. */
5343 reg_was_0 (insn
, op
)
5348 return (optimize
> 0 && insn
&& op
&& REG_P (op
)
5349 && (link
= find_reg_note (insn
, REG_WAS_0
, 0))
5350 /* Make sure the insn that stored the 0 is still present. */
5351 && ! INSN_DELETED_P (XEXP (link
, 0))
5352 && GET_CODE (XEXP (link
, 0)) != NOTE
5353 /* Make sure cross jumping didn't happen here. */
5354 && no_labels_between_p (XEXP (link
, 0), insn
)
5355 /* Make sure the reg hasn't been clobbered. */
5356 && ! reg_set_between_p (op
, XEXP (link
, 0), insn
));
5359 /* Returns 1 if X is a valid address for an I/O register of size SIZE
5360 (1 or 2). Used for lds/sts -> in/out optimization. Add 0x20 to SIZE
5361 to check for the lower half of I/O space (for cbi/sbi/sbic/sbis). */
5364 avr_io_address_p (x
, size
)
5368 return (optimize
> 0 && GET_CODE (x
) == CONST_INT
5369 && INTVAL (x
) >= 0x20 && INTVAL (x
) <= 0x60 - size
);
5372 /* Returns nonzero (bit number + 1) if X, or -X, is a constant power of 2. */
5375 const_int_pow2_p (x
)
5378 if (GET_CODE (x
) == CONST_INT
)
5380 HOST_WIDE_INT d
= INTVAL (x
);
5381 HOST_WIDE_INT abs_d
= (d
>= 0) ? d
: -d
;
5382 return exact_log2 (abs_d
) + 1;
5388 output_reload_inhi (insn
, operands
, len
)
5389 rtx insn ATTRIBUTE_UNUSED
;
5397 if (GET_CODE (operands
[1]) == CONST_INT
)
5399 int val
= INTVAL (operands
[1]);
5400 if ((val
& 0xff) == 0)
5403 return (AS2 (mov
,%A0
,__zero_reg__
) CR_TAB
5404 AS2 (ldi
,%2,hi8(%1)) CR_TAB
5407 else if ((val
& 0xff00) == 0)
5410 return (AS2 (ldi
,%2,lo8(%1)) CR_TAB
5411 AS2 (mov
,%A0
,%2) CR_TAB
5412 AS2 (mov
,%B0
,__zero_reg__
));
5414 else if ((val
& 0xff) == ((val
& 0xff00) >> 8))
5417 return (AS2 (ldi
,%2,lo8(%1)) CR_TAB
5418 AS2 (mov
,%A0
,%2) CR_TAB
5423 return (AS2 (ldi
,%2,lo8(%1)) CR_TAB
5424 AS2 (mov
,%A0
,%2) CR_TAB
5425 AS2 (ldi
,%2,hi8(%1)) CR_TAB
5431 output_reload_insisf (insn
, operands
, len
)
5432 rtx insn ATTRIBUTE_UNUSED
;
5436 rtx src
= operands
[1];
5437 int cnst
= (GET_CODE (src
) == CONST_INT
);
5442 *len
= 4 + ((INTVAL (src
) & 0xff) != 0)
5443 + ((INTVAL (src
) & 0xff00) != 0)
5444 + ((INTVAL (src
) & 0xff0000) != 0)
5445 + ((INTVAL (src
) & 0xff000000) != 0);
5452 if (cnst
&& ((INTVAL (src
) & 0xff) == 0))
5453 output_asm_insn (AS2 (mov
, %A0
, __zero_reg__
), operands
);
5456 output_asm_insn (AS2 (ldi
, %2, lo8(%1)), operands
);
5457 output_asm_insn (AS2 (mov
, %A0
, %2), operands
);
5459 if (cnst
&& ((INTVAL (src
) & 0xff00) == 0))
5460 output_asm_insn (AS2 (mov
, %B0
, __zero_reg__
), operands
);
5463 output_asm_insn (AS2 (ldi
, %2, hi8(%1)), operands
);
5464 output_asm_insn (AS2 (mov
, %B0
, %2), operands
);
5466 if (cnst
&& ((INTVAL (src
) & 0xff0000) == 0))
5467 output_asm_insn (AS2 (mov
, %C0
, __zero_reg__
), operands
);
5470 output_asm_insn (AS2 (ldi
, %2, hlo8(%1)), operands
);
5471 output_asm_insn (AS2 (mov
, %C0
, %2), operands
);
5473 if (cnst
&& ((INTVAL (src
) & 0xff000000) == 0))
5474 output_asm_insn (AS2 (mov
, %D0
, __zero_reg__
), operands
);
5477 output_asm_insn (AS2 (ldi
, %2, hhi8(%1)), operands
);
5478 output_asm_insn (AS2 (mov
, %D0
, %2), operands
);
5484 avr_output_bld (operands
, bit_nr
)
5488 static char s
[] = "bld %A0,0";
5490 s
[5] = 'A' + (bit_nr
>> 3);
5491 s
[8] = '0' + (bit_nr
& 7);
5492 output_asm_insn (s
, operands
);
5496 avr_output_addr_vec_elt (stream
, value
)
5501 fprintf (stream
, "\t.word pm(.L%d)\n", value
);
5503 fprintf (stream
, "\trjmp .L%d\n", value
);
5508 /* Returns 1 if SCRATCH are safe to be allocated as a scratch
5509 registers (for a define_peephole2) in the current function. */
5512 avr_peep2_scratch_safe (scratch
)
5515 if ((interrupt_function_p (current_function_decl
)
5516 || signal_function_p (current_function_decl
))
5517 && leaf_function_p ())
5519 int first_reg
= true_regnum (scratch
);
5520 int last_reg
= first_reg
+ GET_MODE_SIZE (GET_MODE (scratch
)) - 1;
5523 for (reg
= first_reg
; reg
<= last_reg
; reg
++)
5525 if (!regs_ever_live
[reg
])
5532 /* Output a branch that tests a single bit of a register (QI, HI or SImode)
5533 or memory location in the I/O space (QImode only).
5535 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
5536 Operand 1: register operand to test, or CONST_INT memory address.
5537 Operand 2: bit number (for QImode operand) or mask (HImode, SImode).
5538 Operand 3: label to jump to if the test is true. */
5541 avr_out_sbxx_branch (insn
, operands
)
5545 enum rtx_code comp
= GET_CODE (operands
[0]);
5546 int long_jump
= (get_attr_length (insn
) >= 4);
5547 int reverse
= long_jump
|| jump_over_one_insn_p (insn
, operands
[3]);
5551 else if (comp
== LT
)
5555 comp
= reverse_condition (comp
);
5557 if (GET_CODE (operands
[1]) == CONST_INT
)
5559 if (INTVAL (operands
[1]) < 0x40)
5562 output_asm_insn (AS2 (sbis
,%1-0x20,%2), operands
);
5564 output_asm_insn (AS2 (sbic
,%1-0x20,%2), operands
);
5568 output_asm_insn (AS2 (in
,__tmp_reg__
,%1-0x20), operands
);
5570 output_asm_insn (AS2 (sbrs
,__tmp_reg__
,%2), operands
);
5572 output_asm_insn (AS2 (sbrc
,__tmp_reg__
,%2), operands
);
5575 else /* GET_CODE (operands[1]) == REG */
5577 if (GET_MODE (operands
[1]) == QImode
)
5580 output_asm_insn (AS2 (sbrs
,%1,%2), operands
);
5582 output_asm_insn (AS2 (sbrc
,%1,%2), operands
);
5584 else /* HImode or SImode */
5586 static char buf
[] = "sbrc %A1,0";
5587 int bit_nr
= exact_log2 (INTVAL (operands
[2])
5588 & GET_MODE_MASK (GET_MODE (operands
[1])));
5590 buf
[3] = (comp
== EQ
) ? 's' : 'c';
5591 buf
[6] = 'A' + (bit_nr
>> 3);
5592 buf
[9] = '0' + (bit_nr
& 7);
5593 output_asm_insn (buf
, operands
);
5598 return (AS1 (rjmp
,.+4) CR_TAB
5601 return AS1 (rjmp
,%3);
5606 avr_asm_out_ctor (symbol
, priority
)
5610 fputs ("\t.global __do_global_ctors\n", asm_out_file
);
5611 default_ctor_section_asm_out_constructor (symbol
, priority
);
5615 avr_asm_out_dtor (symbol
, priority
)
5619 fputs ("\t.global __do_global_dtors\n", asm_out_file
);
5620 default_dtor_section_asm_out_destructor (symbol
, priority
);