1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007
3 Free Software Foundation, Inc.
4 Contributed by Denis Chertykov (denisc@overta.ru)
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING. If not, write to
20 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
25 #include "coretypes.h"
29 #include "hard-reg-set.h"
31 #include "insn-config.h"
32 #include "conditions.h"
33 #include "insn-attr.h"
46 #include "target-def.h"
48 /* Maximal allowed offset for an address in the LD command */
49 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
51 static int avr_naked_function_p (tree
);
52 static int interrupt_function_p (tree
);
53 static int signal_function_p (tree
);
54 static int avr_regs_to_save (HARD_REG_SET
*);
55 static int sequent_regs_live (void);
56 static const char *ptrreg_to_str (int);
57 static const char *cond_string (enum rtx_code
);
58 static int avr_num_arg_regs (enum machine_mode
, tree
);
59 static int out_adj_frame_ptr (FILE *, int);
60 static int out_set_stack_ptr (FILE *, int, int);
61 static RTX_CODE
compare_condition (rtx insn
);
62 static int compare_sign_p (rtx insn
);
63 static tree
avr_handle_progmem_attribute (tree
*, tree
, tree
, int, bool *);
64 static tree
avr_handle_fndecl_attribute (tree
*, tree
, tree
, int, bool *);
65 const struct attribute_spec avr_attribute_table
[];
66 static bool avr_assemble_integer (rtx
, unsigned int, int);
67 static void avr_file_start (void);
68 static void avr_file_end (void);
69 static void avr_output_function_prologue (FILE *, HOST_WIDE_INT
);
70 static void avr_output_function_epilogue (FILE *, HOST_WIDE_INT
);
71 static void avr_insert_attributes (tree
, tree
*);
72 static void avr_asm_init_sections (void);
73 static unsigned int avr_section_type_flags (tree
, const char *, int);
75 static void avr_reorg (void);
76 static void avr_asm_out_ctor (rtx
, int);
77 static void avr_asm_out_dtor (rtx
, int);
78 static int avr_operand_rtx_cost (rtx
, enum machine_mode
, enum rtx_code
);
79 static bool avr_rtx_costs (rtx
, int, int, int *);
80 static int avr_address_cost (rtx
);
81 static bool avr_return_in_memory (tree
, tree
);
83 /* Allocate registers from r25 to r8 for parameters for function calls. */
84 #define FIRST_CUM_REG 26
86 /* Temporary register RTX (gen_rtx_REG (QImode, TMP_REGNO)) */
87 static GTY(()) rtx tmp_reg_rtx
;
89 /* Zeroed register RTX (gen_rtx_REG (QImode, ZERO_REGNO)) */
90 static GTY(()) rtx zero_reg_rtx
;
92 /* AVR register names {"r0", "r1", ..., "r31"} */
93 static const char *const avr_regnames
[] = REGISTER_NAMES
;
95 /* This holds the last insn address. */
96 static int last_insn_address
= 0;
98 /* Commands count in the compiled file */
99 static int commands_in_file
;
101 /* Commands in the functions prologues in the compiled file */
102 static int commands_in_prologues
;
104 /* Commands in the functions epilogues in the compiled file */
105 static int commands_in_epilogues
;
107 /* Prologue/Epilogue size in words */
108 static int prologue_size
;
109 static int epilogue_size
;
111 /* Size of all jump tables in the current function, in words. */
112 static int jump_tables_size
;
114 /* Preprocessor macros to define depending on MCU type. */
115 const char *avr_base_arch_macro
;
116 const char *avr_extra_arch_macro
;
118 section
*progmem_section
;
120 /* More than 8K of program memory: use "call" and "jmp". */
123 /* Core have 'MUL*' instructions. */
124 int avr_have_mul_p
= 0;
126 /* Assembler only. */
127 int avr_asm_only_p
= 0;
129 /* Core have 'MOVW' and 'LPM Rx,Z' instructions. */
130 int avr_have_movw_lpmx_p
= 0;
137 const char *const macro
;
140 static const struct base_arch_s avr_arch_types
[] = {
141 { 1, 0, 0, 0, NULL
}, /* unknown device specified */
142 { 1, 0, 0, 0, "__AVR_ARCH__=1" },
143 { 0, 0, 0, 0, "__AVR_ARCH__=2" },
144 { 0, 0, 1, 0, "__AVR_ARCH__=3" },
145 { 0, 1, 0, 1, "__AVR_ARCH__=4" },
146 { 0, 1, 1, 1, "__AVR_ARCH__=5" },
147 { 0, 0, 0, 1, "__AVR_ARCH__=25"}
151 const char *const name
;
152 int arch
; /* index in avr_arch_types[] */
153 /* Must lie outside user's namespace. NULL == no macro. */
154 const char *const macro
;
157 /* List of all known AVR MCU types - if updated, it has to be kept
158 in sync in several places (FIXME: is there a better way?):
160 - avr.h (CPP_SPEC, LINK_SPEC, CRT_BINUTILS_SPECS)
161 - t-avr (MULTILIB_MATCHES)
162 - gas/config/tc-avr.c
165 static const struct mcu_type_s avr_mcu_types
[] = {
166 /* Classic, <= 8K. */
168 { "at90s2313", 2, "__AVR_AT90S2313__" },
169 { "at90s2323", 2, "__AVR_AT90S2323__" },
170 { "at90s2333", 2, "__AVR_AT90S2333__" },
171 { "at90s2343", 2, "__AVR_AT90S2343__" },
172 { "attiny22", 2, "__AVR_ATtiny22__" },
173 { "attiny26", 2, "__AVR_ATtiny26__" },
174 { "at90s4414", 2, "__AVR_AT90S4414__" },
175 { "at90s4433", 2, "__AVR_AT90S4433__" },
176 { "at90s4434", 2, "__AVR_AT90S4434__" },
177 { "at90s8515", 2, "__AVR_AT90S8515__" },
178 { "at90c8534", 2, "__AVR_AT90C8534__" },
179 { "at90s8535", 2, "__AVR_AT90S8535__" },
180 /* Classic + MOVW, <= 8K. */
181 { "avr25", 6, NULL
},
182 { "attiny13", 6, "__AVR_ATtiny13__" },
183 { "attiny2313", 6, "__AVR_ATtiny2313__" },
184 { "attiny24", 6, "__AVR_ATtiny24__" },
185 { "attiny44", 6, "__AVR_ATtiny44__" },
186 { "attiny84", 6, "__AVR_ATtiny84__" },
187 { "attiny25", 6, "__AVR_ATtiny25__" },
188 { "attiny45", 6, "__AVR_ATtiny45__" },
189 { "attiny85", 6, "__AVR_ATtiny85__" },
190 { "attiny261", 6, "__AVR_ATtiny261__" },
191 { "attiny461", 6, "__AVR_ATtiny461__" },
192 { "attiny861", 6, "__AVR_ATtiny861__" },
193 { "at86rf401", 6, "__AVR_AT86RF401__" },
196 { "atmega103", 3, "__AVR_ATmega103__" },
197 { "atmega603", 3, "__AVR_ATmega603__" },
198 { "at43usb320", 3, "__AVR_AT43USB320__" },
199 { "at43usb355", 3, "__AVR_AT43USB355__" },
200 { "at76c711", 3, "__AVR_AT76C711__" },
201 /* Enhanced, <= 8K. */
203 { "atmega8", 4, "__AVR_ATmega8__" },
204 { "atmega48", 4, "__AVR_ATmega48__" },
205 { "atmega88", 4, "__AVR_ATmega88__" },
206 { "atmega8515", 4, "__AVR_ATmega8515__" },
207 { "atmega8535", 4, "__AVR_ATmega8535__" },
208 { "at90pwm1", 4, "__AVR_AT90PWM1__" },
209 { "at90pwm2", 4, "__AVR_AT90PWM2__" },
210 { "at90pwm3", 4, "__AVR_AT90PWM3__" },
211 /* Enhanced, > 8K. */
213 { "atmega16", 5, "__AVR_ATmega16__" },
214 { "atmega161", 5, "__AVR_ATmega161__" },
215 { "atmega162", 5, "__AVR_ATmega162__" },
216 { "atmega163", 5, "__AVR_ATmega163__" },
217 { "atmega164p",5, "__AVR_ATmega164P__" },
218 { "atmega165", 5, "__AVR_ATmega165__" },
219 { "atmega165p",5, "__AVR_ATmega165P__" },
220 { "atmega168", 5, "__AVR_ATmega168__" },
221 { "atmega169", 5, "__AVR_ATmega169__" },
222 { "atmega169p",5, "__AVR_ATmega169P__" },
223 { "atmega32", 5, "__AVR_ATmega32__" },
224 { "atmega323", 5, "__AVR_ATmega323__" },
225 { "atmega324p",5, "__AVR_ATmega324P__" },
226 { "atmega325", 5, "__AVR_ATmega325__" },
227 { "atmega3250", 5, "__AVR_ATmega3250__" },
228 { "atmega329", 5, "__AVR_ATmega329__" },
229 { "atmega3290", 5, "__AVR_ATmega3290__" },
230 { "atmega406", 5, "__AVR_ATmega406__" },
231 { "atmega64", 5, "__AVR_ATmega64__" },
232 { "atmega640", 5, "__AVR_ATmega640__" },
233 { "atmega644", 5, "__AVR_ATmega644__" },
234 { "atmega644p",5, "__AVR_ATmega644P__" },
235 { "atmega645", 5, "__AVR_ATmega645__" },
236 { "atmega6450", 5, "__AVR_ATmega6450__" },
237 { "atmega649", 5, "__AVR_ATmega649__" },
238 { "atmega6490", 5, "__AVR_ATmega6490__" },
239 { "atmega128", 5, "__AVR_ATmega128__" },
240 { "atmega1280",5, "__AVR_ATmega1280__" },
241 { "atmega1281",5, "__AVR_ATmega1281__" },
242 { "at90can32", 5, "__AVR_AT90CAN32__" },
243 { "at90can64", 5, "__AVR_AT90CAN64__" },
244 { "at90can128", 5, "__AVR_AT90CAN128__" },
245 { "at90usb646", 5, "__AVR_AT90USB646__" },
246 { "at90usb647", 5, "__AVR_AT90USB647__" },
247 { "at90usb1286", 5, "__AVR_AT90USB1286__" },
248 { "at90usb1287", 5, "__AVR_AT90USB1287__" },
249 { "at94k", 5, "__AVR_AT94K__" },
250 /* Assembler only. */
252 { "at90s1200", 1, "__AVR_AT90S1200__" },
253 { "attiny11", 1, "__AVR_ATtiny11__" },
254 { "attiny12", 1, "__AVR_ATtiny12__" },
255 { "attiny15", 1, "__AVR_ATtiny15__" },
256 { "attiny28", 1, "__AVR_ATtiny28__" },
260 int avr_case_values_threshold
= 30000;
262 /* Initialize the GCC target structure. */
263 #undef TARGET_ASM_ALIGNED_HI_OP
264 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
265 #undef TARGET_ASM_ALIGNED_SI_OP
266 #define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
267 #undef TARGET_ASM_UNALIGNED_HI_OP
268 #define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
269 #undef TARGET_ASM_UNALIGNED_SI_OP
270 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
271 #undef TARGET_ASM_INTEGER
272 #define TARGET_ASM_INTEGER avr_assemble_integer
273 #undef TARGET_ASM_FILE_START
274 #define TARGET_ASM_FILE_START avr_file_start
275 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
276 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
277 #undef TARGET_ASM_FILE_END
278 #define TARGET_ASM_FILE_END avr_file_end
280 #undef TARGET_ASM_FUNCTION_PROLOGUE
281 #define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
282 #undef TARGET_ASM_FUNCTION_EPILOGUE
283 #define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
284 #undef TARGET_ATTRIBUTE_TABLE
285 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
286 #undef TARGET_ASM_FUNCTION_RODATA_SECTION
287 #define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
288 #undef TARGET_INSERT_ATTRIBUTES
289 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
290 #undef TARGET_SECTION_TYPE_FLAGS
291 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
292 #undef TARGET_RTX_COSTS
293 #define TARGET_RTX_COSTS avr_rtx_costs
294 #undef TARGET_ADDRESS_COST
295 #define TARGET_ADDRESS_COST avr_address_cost
296 #undef TARGET_MACHINE_DEPENDENT_REORG
297 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
299 #undef TARGET_RETURN_IN_MEMORY
300 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
302 #undef TARGET_STRICT_ARGUMENT_NAMING
303 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
305 struct gcc_target targetm
= TARGET_INITIALIZER
;
308 avr_override_options (void)
310 const struct mcu_type_s
*t
;
311 const struct base_arch_s
*base
;
313 for (t
= avr_mcu_types
; t
->name
; t
++)
314 if (strcmp (t
->name
, avr_mcu_name
) == 0)
319 fprintf (stderr
, "unknown MCU '%s' specified\nKnown MCU names:\n",
321 for (t
= avr_mcu_types
; t
->name
; t
++)
322 fprintf (stderr
," %s\n", t
->name
);
325 base
= &avr_arch_types
[t
->arch
];
326 avr_asm_only_p
= base
->asm_only
;
327 avr_have_mul_p
= base
->have_mul
;
328 avr_mega_p
= base
->mega
;
329 avr_have_movw_lpmx_p
= base
->have_movw_lpmx
;
330 avr_base_arch_macro
= base
->macro
;
331 avr_extra_arch_macro
= t
->macro
;
333 if (optimize
&& !TARGET_NO_TABLEJUMP
)
334 avr_case_values_threshold
= (!AVR_MEGA
|| TARGET_CALL_PROLOGUES
) ? 8 : 17;
336 tmp_reg_rtx
= gen_rtx_REG (QImode
, TMP_REGNO
);
337 zero_reg_rtx
= gen_rtx_REG (QImode
, ZERO_REGNO
);
340 /* return register class from register number. */
342 static const int reg_class_tab
[]={
343 GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,
344 GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,
345 GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,
346 GENERAL_REGS
, /* r0 - r15 */
347 LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,
348 LD_REGS
, /* r16 - 23 */
349 ADDW_REGS
,ADDW_REGS
, /* r24,r25 */
350 POINTER_X_REGS
,POINTER_X_REGS
, /* r26,27 */
351 POINTER_Y_REGS
,POINTER_Y_REGS
, /* r28,r29 */
352 POINTER_Z_REGS
,POINTER_Z_REGS
, /* r30,r31 */
353 STACK_REG
,STACK_REG
/* SPL,SPH */
356 /* Return register class for register R. */
359 avr_regno_reg_class (int r
)
362 return reg_class_tab
[r
];
366 /* Return nonzero if FUNC is a naked function. */
369 avr_naked_function_p (tree func
)
373 gcc_assert (TREE_CODE (func
) == FUNCTION_DECL
);
375 a
= lookup_attribute ("naked", DECL_ATTRIBUTES (func
));
376 return a
!= NULL_TREE
;
379 /* Return nonzero if FUNC is an interrupt function as specified
380 by the "interrupt" attribute. */
383 interrupt_function_p (tree func
)
387 if (TREE_CODE (func
) != FUNCTION_DECL
)
390 a
= lookup_attribute ("interrupt", DECL_ATTRIBUTES (func
));
391 return a
!= NULL_TREE
;
394 /* Return nonzero if FUNC is a signal function as specified
395 by the "signal" attribute. */
398 signal_function_p (tree func
)
402 if (TREE_CODE (func
) != FUNCTION_DECL
)
405 a
= lookup_attribute ("signal", DECL_ATTRIBUTES (func
));
406 return a
!= NULL_TREE
;
409 /* Return the number of hard registers to push/pop in the prologue/epilogue
410 of the current function, and optionally store these registers in SET. */
413 avr_regs_to_save (HARD_REG_SET
*set
)
416 int int_or_sig_p
= (interrupt_function_p (current_function_decl
)
417 || signal_function_p (current_function_decl
));
418 int leaf_func_p
= leaf_function_p ();
421 CLEAR_HARD_REG_SET (*set
);
424 /* No need to save any registers if the function never returns. */
425 if (TREE_THIS_VOLATILE (current_function_decl
))
428 for (reg
= 0; reg
< 32; reg
++)
430 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
431 any global register variables. */
435 if ((int_or_sig_p
&& !leaf_func_p
&& call_used_regs
[reg
])
436 || (regs_ever_live
[reg
]
437 && (int_or_sig_p
|| !call_used_regs
[reg
])
438 && !(frame_pointer_needed
439 && (reg
== REG_Y
|| reg
== (REG_Y
+1)))))
442 SET_HARD_REG_BIT (*set
, reg
);
449 /* Compute offset between arg_pointer and frame_pointer. */
452 initial_elimination_offset (int from
, int to
)
454 if (from
== FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
458 int offset
= frame_pointer_needed
? 2 : 0;
460 offset
+= avr_regs_to_save (NULL
);
461 return get_frame_size () + 2 + 1 + offset
;
465 /* Return 1 if the function epilogue is just a single "ret". */
468 avr_simple_epilogue (void)
470 return (! frame_pointer_needed
471 && get_frame_size () == 0
472 && avr_regs_to_save (NULL
) == 0
473 && ! interrupt_function_p (current_function_decl
)
474 && ! signal_function_p (current_function_decl
)
475 && ! avr_naked_function_p (current_function_decl
)
476 && ! MAIN_NAME_P (DECL_NAME (current_function_decl
))
477 && ! TREE_THIS_VOLATILE (current_function_decl
));
480 /* This function checks sequence of live registers. */
483 sequent_regs_live (void)
489 for (reg
= 0; reg
< 18; ++reg
)
491 if (!call_used_regs
[reg
])
493 if (regs_ever_live
[reg
])
503 if (!frame_pointer_needed
)
505 if (regs_ever_live
[REG_Y
])
513 if (regs_ever_live
[REG_Y
+1])
526 return (cur_seq
== live_seq
) ? live_seq
: 0;
530 /* Output to FILE the asm instructions to adjust the frame pointer by
531 ADJ (r29:r28 -= ADJ;) which can be positive (prologue) or negative
532 (epilogue). Returns the number of instructions generated. */
535 out_adj_frame_ptr (FILE *file
, int adj
)
541 if (TARGET_TINY_STACK
)
543 if (adj
< -63 || adj
> 63)
544 warning (0, "large frame pointer change (%d) with -mtiny-stack", adj
);
546 /* The high byte (r29) doesn't change - prefer "subi" (1 cycle)
547 over "sbiw" (2 cycles, same size). */
549 fprintf (file
, (AS2 (subi
, r28
, %d
) CR_TAB
), adj
);
552 else if (adj
< -63 || adj
> 63)
554 fprintf (file
, (AS2 (subi
, r28
, lo8(%d
)) CR_TAB
555 AS2 (sbci
, r29
, hi8(%d
)) CR_TAB
),
561 fprintf (file
, (AS2 (adiw
, r28
, %d
) CR_TAB
), -adj
);
566 fprintf (file
, (AS2 (sbiw
, r28
, %d
) CR_TAB
), adj
);
574 /* Output to FILE the asm instructions to copy r29:r28 to SPH:SPL,
575 handling various cases of interrupt enable flag state BEFORE and AFTER
576 (0=disabled, 1=enabled, -1=unknown/unchanged) and target_flags.
577 Returns the number of instructions generated. */
580 out_set_stack_ptr (FILE *file
, int before
, int after
)
582 int do_sph
, do_cli
, do_save
, do_sei
, lock_sph
, size
;
584 /* The logic here is so that -mno-interrupts actually means
585 "it is safe to write SPH in one instruction, then SPL in the
586 next instruction, without disabling interrupts first".
587 The after != -1 case (interrupt/signal) is not affected. */
589 do_sph
= !TARGET_TINY_STACK
;
590 lock_sph
= do_sph
&& !TARGET_NO_INTERRUPTS
;
591 do_cli
= (before
!= 0 && (after
== 0 || lock_sph
));
592 do_save
= (do_cli
&& before
== -1 && after
== -1);
593 do_sei
= ((do_cli
|| before
!= 1) && after
== 1);
598 fprintf (file
, AS2 (in
, __tmp_reg__
, __SREG__
) CR_TAB
);
604 fprintf (file
, "cli" CR_TAB
);
608 /* Do SPH first - maybe this will disable interrupts for one instruction
609 someday (a suggestion has been sent to avr@atmel.com for consideration
610 in future devices - that would make -mno-interrupts always safe). */
613 fprintf (file
, AS2 (out
, __SP_H__
, r29
) CR_TAB
);
617 /* Set/restore the I flag now - interrupts will be really enabled only
618 after the next instruction. This is not clearly documented, but
619 believed to be true for all AVR devices. */
622 fprintf (file
, AS2 (out
, __SREG__
, __tmp_reg__
) CR_TAB
);
627 fprintf (file
, "sei" CR_TAB
);
631 fprintf (file
, AS2 (out
, __SP_L__
, r28
) "\n");
637 /* Output function prologue. */
640 avr_output_function_prologue (FILE *file
, HOST_WIDE_INT size
)
643 int interrupt_func_p
;
649 last_insn_address
= 0;
650 jump_tables_size
= 0;
652 fprintf (file
, "/* prologue: frame size=" HOST_WIDE_INT_PRINT_DEC
" */\n",
655 if (avr_naked_function_p (current_function_decl
))
657 fputs ("/* prologue: naked */\n", file
);
661 interrupt_func_p
= interrupt_function_p (current_function_decl
);
662 signal_func_p
= signal_function_p (current_function_decl
);
663 main_p
= MAIN_NAME_P (DECL_NAME (current_function_decl
));
664 live_seq
= sequent_regs_live ();
665 minimize
= (TARGET_CALL_PROLOGUES
666 && !interrupt_func_p
&& !signal_func_p
&& live_seq
);
668 if (interrupt_func_p
)
670 fprintf (file
,"\tsei\n");
673 if (interrupt_func_p
|| signal_func_p
)
676 AS1 (push
,__zero_reg__
) CR_TAB
677 AS1 (push
,__tmp_reg__
) CR_TAB
678 AS2 (in
,__tmp_reg__
,__SREG__
) CR_TAB
679 AS1 (push
,__tmp_reg__
) CR_TAB
680 AS1 (clr
,__zero_reg__
) "\n");
686 AS1 (ldi
,r28
) ",lo8(%s - " HOST_WIDE_INT_PRINT_DEC
")" CR_TAB
687 AS1 (ldi
,r29
) ",hi8(%s - " HOST_WIDE_INT_PRINT_DEC
")" CR_TAB
688 AS2 (out
,__SP_H__
,r29
) CR_TAB
689 AS2 (out
,__SP_L__
,r28
) "\n"),
690 avr_init_stack
, size
, avr_init_stack
, size
);
694 else if (minimize
&& (frame_pointer_needed
|| live_seq
> 6))
697 AS1 (ldi
, r26
) ",lo8(" HOST_WIDE_INT_PRINT_DEC
")" CR_TAB
698 AS1 (ldi
, r27
) ",hi8(" HOST_WIDE_INT_PRINT_DEC
")" CR_TAB
), size
, size
);
700 fputs ((AS2 (ldi
,r30
,pm_lo8(1f
)) CR_TAB
701 AS2 (ldi
,r31
,pm_hi8(1f
)) CR_TAB
), file
);
707 fprintf (file
, AS1 (jmp
,__prologue_saves__
+%d
) "\n",
708 (18 - live_seq
) * 2);
713 fprintf (file
, AS1 (rjmp
,__prologue_saves__
+%d
) "\n",
714 (18 - live_seq
) * 2);
717 fputs ("1:\n", file
);
723 prologue_size
+= avr_regs_to_save (&set
);
724 for (reg
= 0; reg
< 32; ++reg
)
726 if (TEST_HARD_REG_BIT (set
, reg
))
728 fprintf (file
, "\t" AS1 (push
,%s
) "\n", avr_regnames
[reg
]);
731 if (frame_pointer_needed
)
734 AS1 (push
,r28
) CR_TAB
735 AS1 (push
,r29
) CR_TAB
736 AS2 (in
,r28
,__SP_L__
) CR_TAB
737 AS2 (in
,r29
,__SP_H__
) "\n");
742 prologue_size
+= out_adj_frame_ptr (file
, size
);
744 if (interrupt_func_p
)
746 prologue_size
+= out_set_stack_ptr (file
, 1, 1);
748 else if (signal_func_p
)
750 prologue_size
+= out_set_stack_ptr (file
, 0, 0);
754 prologue_size
+= out_set_stack_ptr (file
, -1, -1);
761 fprintf (file
, "/* prologue end (size=%d) */\n", prologue_size
);
764 /* Output function epilogue. */
767 avr_output_function_epilogue (FILE *file
, HOST_WIDE_INT size
)
770 int interrupt_func_p
;
776 rtx last
= get_last_nonnote_insn ();
778 function_size
= jump_tables_size
;
781 rtx first
= get_first_nonnote_insn ();
782 function_size
+= (INSN_ADDRESSES (INSN_UID (last
)) -
783 INSN_ADDRESSES (INSN_UID (first
)));
784 function_size
+= get_attr_length (last
);
787 fprintf (file
, "/* epilogue: frame size=" HOST_WIDE_INT_PRINT_DEC
" */\n", size
);
790 if (avr_naked_function_p (current_function_decl
))
792 fputs ("/* epilogue: naked */\n", file
);
796 if (last
&& GET_CODE (last
) == BARRIER
)
798 fputs ("/* epilogue: noreturn */\n", file
);
802 interrupt_func_p
= interrupt_function_p (current_function_decl
);
803 signal_func_p
= signal_function_p (current_function_decl
);
804 main_p
= MAIN_NAME_P (DECL_NAME (current_function_decl
));
805 live_seq
= sequent_regs_live ();
806 minimize
= (TARGET_CALL_PROLOGUES
807 && !interrupt_func_p
&& !signal_func_p
&& live_seq
);
811 /* Return value from main() is already in the correct registers
812 (r25:r24) as the exit() argument. */
815 fputs ("\t" AS1 (jmp
,exit
) "\n", file
);
820 fputs ("\t" AS1 (rjmp
,exit
) "\n", file
);
824 else if (minimize
&& (frame_pointer_needed
|| live_seq
> 4))
826 fprintf (file
, ("\t" AS2 (ldi
, r30
, %d
) CR_TAB
), live_seq
);
828 if (frame_pointer_needed
)
830 epilogue_size
+= out_adj_frame_ptr (file
, -size
);
834 fprintf (file
, (AS2 (in
, r28
, __SP_L__
) CR_TAB
835 AS2 (in
, r29
, __SP_H__
) CR_TAB
));
841 fprintf (file
, AS1 (jmp
,__epilogue_restores__
+%d
) "\n",
842 (18 - live_seq
) * 2);
847 fprintf (file
, AS1 (rjmp
,__epilogue_restores__
+%d
) "\n",
848 (18 - live_seq
) * 2);
856 if (frame_pointer_needed
)
861 epilogue_size
+= out_adj_frame_ptr (file
, -size
);
863 if (interrupt_func_p
|| signal_func_p
)
865 epilogue_size
+= out_set_stack_ptr (file
, -1, 0);
869 epilogue_size
+= out_set_stack_ptr (file
, -1, -1);
878 epilogue_size
+= avr_regs_to_save (&set
);
879 for (reg
= 31; reg
>= 0; --reg
)
881 if (TEST_HARD_REG_BIT (set
, reg
))
883 fprintf (file
, "\t" AS1 (pop
,%s
) "\n", avr_regnames
[reg
]);
887 if (interrupt_func_p
|| signal_func_p
)
890 AS1 (pop
,__tmp_reg__
) CR_TAB
891 AS2 (out
,__SREG__
,__tmp_reg__
) CR_TAB
892 AS1 (pop
,__tmp_reg__
) CR_TAB
893 AS1 (pop
,__zero_reg__
) "\n");
895 fprintf (file
, "\treti\n");
898 fprintf (file
, "\tret\n");
903 fprintf (file
, "/* epilogue end (size=%d) */\n", epilogue_size
);
904 fprintf (file
, "/* function %s size %d (%d) */\n", current_function_name (),
905 prologue_size
+ function_size
+ epilogue_size
, function_size
);
906 commands_in_file
+= prologue_size
+ function_size
+ epilogue_size
;
907 commands_in_prologues
+= prologue_size
;
908 commands_in_epilogues
+= epilogue_size
;
912 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
913 machine for a memory operand of mode MODE. */
916 legitimate_address_p (enum machine_mode mode
, rtx x
, int strict
)
918 enum reg_class r
= NO_REGS
;
920 if (TARGET_ALL_DEBUG
)
922 fprintf (stderr
, "mode: (%s) %s %s %s %s:",
924 strict
? "(strict)": "",
925 reload_completed
? "(reload_completed)": "",
926 reload_in_progress
? "(reload_in_progress)": "",
927 reg_renumber
? "(reg_renumber)" : "");
928 if (GET_CODE (x
) == PLUS
929 && REG_P (XEXP (x
, 0))
930 && GET_CODE (XEXP (x
, 1)) == CONST_INT
931 && INTVAL (XEXP (x
, 1)) >= 0
932 && INTVAL (XEXP (x
, 1)) <= MAX_LD_OFFSET (mode
)
935 fprintf (stderr
, "(r%d ---> r%d)", REGNO (XEXP (x
, 0)),
936 true_regnum (XEXP (x
, 0)));
939 if (REG_P (x
) && (strict
? REG_OK_FOR_BASE_STRICT_P (x
)
940 : REG_OK_FOR_BASE_NOSTRICT_P (x
)))
942 else if (CONSTANT_ADDRESS_P (x
))
944 else if (GET_CODE (x
) == PLUS
945 && REG_P (XEXP (x
, 0))
946 && GET_CODE (XEXP (x
, 1)) == CONST_INT
947 && INTVAL (XEXP (x
, 1)) >= 0)
949 int fit
= INTVAL (XEXP (x
, 1)) <= MAX_LD_OFFSET (mode
);
953 || REGNO (XEXP (x
,0)) == REG_Y
954 || REGNO (XEXP (x
,0)) == REG_Z
)
955 r
= BASE_POINTER_REGS
;
956 if (XEXP (x
,0) == frame_pointer_rtx
957 || XEXP (x
,0) == arg_pointer_rtx
)
958 r
= BASE_POINTER_REGS
;
960 else if (frame_pointer_needed
&& XEXP (x
,0) == frame_pointer_rtx
)
963 else if ((GET_CODE (x
) == PRE_DEC
|| GET_CODE (x
) == POST_INC
)
964 && REG_P (XEXP (x
, 0))
965 && (strict
? REG_OK_FOR_BASE_STRICT_P (XEXP (x
, 0))
966 : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x
, 0))))
970 if (TARGET_ALL_DEBUG
)
972 fprintf (stderr
, " ret = %c\n", r
+ '0');
974 return r
== NO_REGS
? 0 : (int)r
;
977 /* Attempts to replace X with a valid
978 memory address for an operand of mode MODE */
981 legitimize_address (rtx x
, rtx oldx
, enum machine_mode mode
)
984 if (TARGET_ALL_DEBUG
)
986 fprintf (stderr
, "legitimize_address mode: %s", GET_MODE_NAME(mode
));
990 if (GET_CODE (oldx
) == PLUS
991 && REG_P (XEXP (oldx
,0)))
993 if (REG_P (XEXP (oldx
,1)))
994 x
= force_reg (GET_MODE (oldx
), oldx
);
995 else if (GET_CODE (XEXP (oldx
, 1)) == CONST_INT
)
997 int offs
= INTVAL (XEXP (oldx
,1));
998 if (frame_pointer_rtx
!= XEXP (oldx
,0))
999 if (offs
> MAX_LD_OFFSET (mode
))
1001 if (TARGET_ALL_DEBUG
)
1002 fprintf (stderr
, "force_reg (big offset)\n");
1003 x
= force_reg (GET_MODE (oldx
), oldx
);
1011 /* Return a pointer register name as a string. */
1014 ptrreg_to_str (int 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 */
1031 cond_string (enum rtx_code code
)
1040 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1045 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1058 /* Output ADDR to FILE as address. */
1061 print_operand_address (FILE *file
, rtx addr
)
1063 switch (GET_CODE (addr
))
1066 fprintf (file
, ptrreg_to_str (REGNO (addr
)));
1070 fprintf (file
, "-%s", ptrreg_to_str (REGNO (XEXP (addr
, 0))));
1074 fprintf (file
, "%s+", ptrreg_to_str (REGNO (XEXP (addr
, 0))));
1078 if (CONSTANT_ADDRESS_P (addr
)
1079 && ((GET_CODE (addr
) == SYMBOL_REF
&& SYMBOL_REF_FUNCTION_P (addr
))
1080 || GET_CODE (addr
) == LABEL_REF
))
1082 fprintf (file
, "pm(");
1083 output_addr_const (file
,addr
);
1084 fprintf (file
,")");
1087 output_addr_const (file
, addr
);
1092 /* Output X as assembler operand to file FILE. */
1095 print_operand (FILE *file
, rtx x
, int code
)
1099 if (code
>= 'A' && code
<= 'D')
1109 if (x
== zero_reg_rtx
)
1110 fprintf (file
, "__zero_reg__");
1112 fprintf (file
, reg_names
[true_regnum (x
) + abcd
]);
1114 else if (GET_CODE (x
) == CONST_INT
)
1115 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
) + abcd
);
1116 else if (GET_CODE (x
) == MEM
)
1118 rtx addr
= XEXP (x
,0);
1120 if (CONSTANT_P (addr
) && abcd
)
1123 output_address (addr
);
1124 fprintf (file
, ")+%d", abcd
);
1126 else if (code
== 'o')
1128 if (GET_CODE (addr
) != PLUS
)
1129 fatal_insn ("bad address, not (reg+disp):", addr
);
1131 print_operand (file
, XEXP (addr
, 1), 0);
1133 else if (code
== 'p' || code
== 'r')
1135 if (GET_CODE (addr
) != POST_INC
&& GET_CODE (addr
) != PRE_DEC
)
1136 fatal_insn ("bad address, not post_inc or pre_dec:", addr
);
1139 print_operand_address (file
, XEXP (addr
, 0)); /* X, Y, Z */
1141 print_operand (file
, XEXP (addr
, 0), 0); /* r26, r28, r30 */
1143 else if (GET_CODE (addr
) == PLUS
)
1145 print_operand_address (file
, XEXP (addr
,0));
1146 if (REGNO (XEXP (addr
, 0)) == REG_X
)
1147 fatal_insn ("internal compiler error. Bad address:"
1150 print_operand (file
, XEXP (addr
,1), code
);
1153 print_operand_address (file
, addr
);
1155 else if (GET_CODE (x
) == CONST_DOUBLE
)
1159 if (GET_MODE (x
) != SFmode
)
1160 fatal_insn ("internal compiler error. Unknown mode:", x
);
1161 REAL_VALUE_FROM_CONST_DOUBLE (rv
, x
);
1162 REAL_VALUE_TO_TARGET_SINGLE (rv
, val
);
1163 fprintf (file
, "0x%lx", val
);
1165 else if (code
== 'j')
1166 fputs (cond_string (GET_CODE (x
)), file
);
1167 else if (code
== 'k')
1168 fputs (cond_string (reverse_condition (GET_CODE (x
))), file
);
1170 print_operand_address (file
, x
);
1173 /* Update the condition code in the INSN. */
1176 notice_update_cc (rtx body ATTRIBUTE_UNUSED
, rtx insn
)
1180 switch (get_attr_cc (insn
))
1183 /* Insn does not affect CC at all. */
1191 set
= single_set (insn
);
1195 cc_status
.flags
|= CC_NO_OVERFLOW
;
1196 cc_status
.value1
= SET_DEST (set
);
1201 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
1202 The V flag may or may not be known but that's ok because
1203 alter_cond will change tests to use EQ/NE. */
1204 set
= single_set (insn
);
1208 cc_status
.value1
= SET_DEST (set
);
1209 cc_status
.flags
|= CC_OVERFLOW_UNUSABLE
;
1214 set
= single_set (insn
);
1217 cc_status
.value1
= SET_SRC (set
);
1221 /* Insn doesn't leave CC in a usable state. */
1224 /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1225 set
= single_set (insn
);
1228 rtx src
= SET_SRC (set
);
1230 if (GET_CODE (src
) == ASHIFTRT
1231 && GET_MODE (src
) == QImode
)
1233 rtx x
= XEXP (src
, 1);
1235 if (GET_CODE (x
) == CONST_INT
1239 cc_status
.value1
= SET_DEST (set
);
1240 cc_status
.flags
|= CC_OVERFLOW_UNUSABLE
;
1248 /* Return maximum number of consecutive registers of
1249 class CLASS needed to hold a value of mode MODE. */
1252 class_max_nregs (enum reg_class
class ATTRIBUTE_UNUSED
,enum machine_mode mode
)
1254 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
);
1257 /* Choose mode for jump insn:
1258 1 - relative jump in range -63 <= x <= 62 ;
1259 2 - relative jump in range -2046 <= x <= 2045 ;
1260 3 - absolute jump (only for ATmega[16]03). */
1263 avr_jump_mode (rtx x
, rtx insn
)
1265 int dest_addr
= INSN_ADDRESSES (INSN_UID (GET_MODE (x
) == LABEL_REF
1266 ? XEXP (x
, 0) : x
));
1267 int cur_addr
= INSN_ADDRESSES (INSN_UID (insn
));
1268 int jump_distance
= cur_addr
- dest_addr
;
1270 if (-63 <= jump_distance
&& jump_distance
<= 62)
1272 else if (-2046 <= jump_distance
&& jump_distance
<= 2045)
1280 /* return an AVR condition jump commands.
1281 X is a comparison RTX.
1282 LEN is a number returned by avr_jump_mode function.
1283 if REVERSE nonzero then condition code in X must be reversed. */
1286 ret_cond_branch (rtx x
, int len
, int reverse
)
1288 RTX_CODE cond
= reverse
? reverse_condition (GET_CODE (x
)) : GET_CODE (x
);
1293 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1294 return (len
== 1 ? (AS1 (breq
,.+2) CR_TAB
1296 len
== 2 ? (AS1 (breq
,.+4) CR_TAB
1297 AS1 (brmi
,.+2) CR_TAB
1299 (AS1 (breq
,.+6) CR_TAB
1300 AS1 (brmi
,.+4) CR_TAB
1304 return (len
== 1 ? (AS1 (breq
,.+2) CR_TAB
1306 len
== 2 ? (AS1 (breq
,.+4) CR_TAB
1307 AS1 (brlt
,.+2) CR_TAB
1309 (AS1 (breq
,.+6) CR_TAB
1310 AS1 (brlt
,.+4) CR_TAB
1313 return (len
== 1 ? (AS1 (breq
,.+2) CR_TAB
1315 len
== 2 ? (AS1 (breq
,.+4) CR_TAB
1316 AS1 (brlo
,.+2) CR_TAB
1318 (AS1 (breq
,.+6) CR_TAB
1319 AS1 (brlo
,.+4) CR_TAB
1322 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1323 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1325 len
== 2 ? (AS1 (breq
,.+2) CR_TAB
1326 AS1 (brpl
,.+2) CR_TAB
1328 (AS1 (breq
,.+2) CR_TAB
1329 AS1 (brpl
,.+4) CR_TAB
1332 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1334 len
== 2 ? (AS1 (breq
,.+2) CR_TAB
1335 AS1 (brge
,.+2) CR_TAB
1337 (AS1 (breq
,.+2) CR_TAB
1338 AS1 (brge
,.+4) CR_TAB
1341 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1343 len
== 2 ? (AS1 (breq
,.+2) CR_TAB
1344 AS1 (brsh
,.+2) CR_TAB
1346 (AS1 (breq
,.+2) CR_TAB
1347 AS1 (brsh
,.+4) CR_TAB
1355 return AS1 (br
%k1
,%0);
1357 return (AS1 (br
%j1
,.+2) CR_TAB
1360 return (AS1 (br
%j1
,.+4) CR_TAB
1369 return AS1 (br
%j1
,%0);
1371 return (AS1 (br
%k1
,.+2) CR_TAB
1374 return (AS1 (br
%k1
,.+4) CR_TAB
1382 /* Predicate function for immediate operand which fits to byte (8bit) */
1385 byte_immediate_operand (rtx op
, enum machine_mode mode ATTRIBUTE_UNUSED
)
1387 return (GET_CODE (op
) == CONST_INT
1388 && INTVAL (op
) <= 0xff && INTVAL (op
) >= 0);
1391 /* Output all insn addresses and their sizes into the assembly language
1392 output file. This is helpful for debugging whether the length attributes
1393 in the md file are correct.
1394 Output insn cost for next insn. */
1397 final_prescan_insn (rtx insn
, rtx
*operand ATTRIBUTE_UNUSED
,
1398 int num_operands ATTRIBUTE_UNUSED
)
1400 int uid
= INSN_UID (insn
);
1402 if (TARGET_INSN_SIZE_DUMP
|| TARGET_ALL_DEBUG
)
1404 fprintf (asm_out_file
, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
1405 INSN_ADDRESSES (uid
),
1406 INSN_ADDRESSES (uid
) - last_insn_address
,
1407 rtx_cost (PATTERN (insn
), INSN
));
1409 last_insn_address
= INSN_ADDRESSES (uid
);
1412 /* Return 0 if undefined, 1 if always true or always false. */
1415 avr_simplify_comparison_p (enum machine_mode mode
, RTX_CODE
operator, rtx x
)
1417 unsigned int max
= (mode
== QImode
? 0xff :
1418 mode
== HImode
? 0xffff :
1419 mode
== SImode
? 0xffffffff : 0);
1420 if (max
&& operator && GET_CODE (x
) == CONST_INT
)
1422 if (unsigned_condition (operator) != operator)
1425 if (max
!= (INTVAL (x
) & max
)
1426 && INTVAL (x
) != 0xff)
1433 /* Returns nonzero if REGNO is the number of a hard
1434 register in which function arguments are sometimes passed. */
1437 function_arg_regno_p(int r
)
1439 return (r
>= 8 && r
<= 25);
1442 /* Initializing the variable cum for the state at the beginning
1443 of the argument list. */
1446 init_cumulative_args (CUMULATIVE_ARGS
*cum
, tree fntype
, rtx libname
,
1447 tree fndecl ATTRIBUTE_UNUSED
)
1450 cum
->regno
= FIRST_CUM_REG
;
1451 if (!libname
&& fntype
)
1453 int stdarg
= (TYPE_ARG_TYPES (fntype
) != 0
1454 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype
)))
1455 != void_type_node
));
1461 /* Returns the number of registers to allocate for a function argument. */
1464 avr_num_arg_regs (enum machine_mode mode
, tree type
)
1468 if (mode
== BLKmode
)
1469 size
= int_size_in_bytes (type
);
1471 size
= GET_MODE_SIZE (mode
);
1473 /* Align all function arguments to start in even-numbered registers.
1474 Odd-sized arguments leave holes above them. */
1476 return (size
+ 1) & ~1;
1479 /* Controls whether a function argument is passed
1480 in a register, and which register. */
1483 function_arg (CUMULATIVE_ARGS
*cum
, enum machine_mode mode
, tree type
,
1484 int named ATTRIBUTE_UNUSED
)
1486 int bytes
= avr_num_arg_regs (mode
, type
);
1488 if (cum
->nregs
&& bytes
<= cum
->nregs
)
1489 return gen_rtx_REG (mode
, cum
->regno
- bytes
);
1494 /* Update the summarizer variable CUM to advance past an argument
1495 in the argument list. */
1498 function_arg_advance (CUMULATIVE_ARGS
*cum
, enum machine_mode mode
, tree type
,
1499 int named ATTRIBUTE_UNUSED
)
1501 int bytes
= avr_num_arg_regs (mode
, type
);
1503 cum
->nregs
-= bytes
;
1504 cum
->regno
-= bytes
;
1506 if (cum
->nregs
<= 0)
1509 cum
->regno
= FIRST_CUM_REG
;
1513 /***********************************************************************
1514 Functions for outputting various mov's for a various modes
1515 ************************************************************************/
1517 output_movqi (rtx insn
, rtx operands
[], int *l
)
1520 rtx dest
= operands
[0];
1521 rtx src
= operands
[1];
1529 if (register_operand (dest
, QImode
))
1531 if (register_operand (src
, QImode
)) /* mov r,r */
1533 if (test_hard_reg_class (STACK_REG
, dest
))
1534 return AS2 (out
,%0,%1);
1535 else if (test_hard_reg_class (STACK_REG
, src
))
1536 return AS2 (in
,%0,%1);
1538 return AS2 (mov
,%0,%1);
1540 else if (CONSTANT_P (src
))
1542 if (test_hard_reg_class (LD_REGS
, dest
)) /* ldi d,i */
1543 return AS2 (ldi
,%0,lo8(%1));
1545 if (GET_CODE (src
) == CONST_INT
)
1547 if (src
== const0_rtx
) /* mov r,L */
1548 return AS1 (clr
,%0);
1549 else if (src
== const1_rtx
)
1552 return (AS1 (clr
,%0) CR_TAB
1555 else if (src
== constm1_rtx
)
1557 /* Immediate constants -1 to any register */
1559 return (AS1 (clr
,%0) CR_TAB
1564 int bit_nr
= exact_log2 (INTVAL (src
));
1570 output_asm_insn ((AS1 (clr
,%0) CR_TAB
1573 avr_output_bld (operands
, bit_nr
);
1580 /* Last resort, larger than loading from memory. */
1582 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1583 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
1584 AS2 (mov
,%0,r31
) CR_TAB
1585 AS2 (mov
,r31
,__tmp_reg__
));
1587 else if (GET_CODE (src
) == MEM
)
1588 return out_movqi_r_mr (insn
, operands
, real_l
); /* mov r,m */
1590 else if (GET_CODE (dest
) == MEM
)
1592 const char *template;
1594 if (src
== const0_rtx
)
1595 operands
[1] = zero_reg_rtx
;
1597 template = out_movqi_mr_r (insn
, operands
, real_l
);
1600 output_asm_insn (template, operands
);
1609 output_movhi (rtx insn
, rtx operands
[], int *l
)
1612 rtx dest
= operands
[0];
1613 rtx src
= operands
[1];
1619 if (register_operand (dest
, HImode
))
1621 if (register_operand (src
, HImode
)) /* mov r,r */
1623 if (test_hard_reg_class (STACK_REG
, dest
))
1625 if (TARGET_TINY_STACK
)
1628 return AS2 (out
,__SP_L__
,%A1
);
1630 else if (TARGET_NO_INTERRUPTS
)
1633 return (AS2 (out
,__SP_H__
,%B1
) CR_TAB
1634 AS2 (out
,__SP_L__
,%A1
));
1638 return (AS2 (in
,__tmp_reg__
,__SREG__
) CR_TAB
1640 AS2 (out
,__SP_H__
,%B1
) CR_TAB
1641 AS2 (out
,__SREG__
,__tmp_reg__
) CR_TAB
1642 AS2 (out
,__SP_L__
,%A1
));
1644 else if (test_hard_reg_class (STACK_REG
, src
))
1647 return (AS2 (in
,%A0
,__SP_L__
) CR_TAB
1648 AS2 (in
,%B0
,__SP_H__
));
1654 return (AS2 (movw
,%0,%1));
1659 return (AS2 (mov
,%A0
,%A1
) CR_TAB
1663 else if (CONSTANT_P (src
))
1665 if (test_hard_reg_class (LD_REGS
, dest
)) /* ldi d,i */
1668 return (AS2 (ldi
,%A0
,lo8(%1)) CR_TAB
1669 AS2 (ldi
,%B0
,hi8(%1)));
1672 if (GET_CODE (src
) == CONST_INT
)
1674 if (src
== const0_rtx
) /* mov r,L */
1677 return (AS1 (clr
,%A0
) CR_TAB
1680 else if (src
== const1_rtx
)
1683 return (AS1 (clr
,%A0
) CR_TAB
1684 AS1 (clr
,%B0
) CR_TAB
1687 else if (src
== constm1_rtx
)
1689 /* Immediate constants -1 to any register */
1691 return (AS1 (clr
,%0) CR_TAB
1692 AS1 (dec
,%A0
) CR_TAB
1697 int bit_nr
= exact_log2 (INTVAL (src
));
1703 output_asm_insn ((AS1 (clr
,%A0
) CR_TAB
1704 AS1 (clr
,%B0
) CR_TAB
1707 avr_output_bld (operands
, bit_nr
);
1713 if ((INTVAL (src
) & 0xff) == 0)
1716 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1717 AS1 (clr
,%A0
) CR_TAB
1718 AS2 (ldi
,r31
,hi8(%1)) CR_TAB
1719 AS2 (mov
,%B0
,r31
) CR_TAB
1720 AS2 (mov
,r31
,__tmp_reg__
));
1722 else if ((INTVAL (src
) & 0xff00) == 0)
1725 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1726 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
1727 AS2 (mov
,%A0
,r31
) CR_TAB
1728 AS1 (clr
,%B0
) CR_TAB
1729 AS2 (mov
,r31
,__tmp_reg__
));
1733 /* Last resort, equal to loading from memory. */
1735 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1736 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
1737 AS2 (mov
,%A0
,r31
) CR_TAB
1738 AS2 (ldi
,r31
,hi8(%1)) CR_TAB
1739 AS2 (mov
,%B0
,r31
) CR_TAB
1740 AS2 (mov
,r31
,__tmp_reg__
));
1742 else if (GET_CODE (src
) == MEM
)
1743 return out_movhi_r_mr (insn
, operands
, real_l
); /* mov r,m */
1745 else if (GET_CODE (dest
) == MEM
)
1747 const char *template;
1749 if (src
== const0_rtx
)
1750 operands
[1] = zero_reg_rtx
;
1752 template = out_movhi_mr_r (insn
, operands
, real_l
);
1755 output_asm_insn (template, operands
);
1760 fatal_insn ("invalid insn:", insn
);
1765 out_movqi_r_mr (rtx insn
, rtx op
[], int *l
)
1769 rtx x
= XEXP (src
, 0);
1775 if (CONSTANT_ADDRESS_P (x
))
1777 if (avr_io_address_p (x
, 1))
1780 return AS2 (in
,%0,%1-0x20);
1783 return AS2 (lds
,%0,%1);
1785 /* memory access by reg+disp */
1786 else if (GET_CODE (x
) == PLUS
1787 && REG_P (XEXP (x
,0))
1788 && GET_CODE (XEXP (x
,1)) == CONST_INT
)
1790 if ((INTVAL (XEXP (x
,1)) - GET_MODE_SIZE (GET_MODE (src
))) >= 63)
1792 int disp
= INTVAL (XEXP (x
,1));
1793 if (REGNO (XEXP (x
,0)) != REG_Y
)
1794 fatal_insn ("incorrect insn:",insn
);
1796 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
1797 return *l
= 3, (AS2 (adiw
,r28
,%o1
-63) CR_TAB
1798 AS2 (ldd
,%0,Y
+63) CR_TAB
1799 AS2 (sbiw
,r28
,%o1
-63));
1801 return *l
= 5, (AS2 (subi
,r28
,lo8(-%o1
)) CR_TAB
1802 AS2 (sbci
,r29
,hi8(-%o1
)) CR_TAB
1803 AS2 (ld
,%0,Y
) CR_TAB
1804 AS2 (subi
,r28
,lo8(%o1
)) CR_TAB
1805 AS2 (sbci
,r29
,hi8(%o1
)));
1807 else if (REGNO (XEXP (x
,0)) == REG_X
)
1809 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
1810 it but I have this situation with extremal optimizing options. */
1811 if (reg_overlap_mentioned_p (dest
, XEXP (x
,0))
1812 || reg_unused_after (insn
, XEXP (x
,0)))
1813 return *l
= 2, (AS2 (adiw
,r26
,%o1
) CR_TAB
1816 return *l
= 3, (AS2 (adiw
,r26
,%o1
) CR_TAB
1817 AS2 (ld
,%0,X
) CR_TAB
1818 AS2 (sbiw
,r26
,%o1
));
1821 return AS2 (ldd
,%0,%1);
1824 return AS2 (ld
,%0,%1);
1828 out_movhi_r_mr (rtx insn
, rtx op
[], int *l
)
1832 rtx base
= XEXP (src
, 0);
1833 int reg_dest
= true_regnum (dest
);
1834 int reg_base
= true_regnum (base
);
1835 /* "volatile" forces reading low byte first, even if less efficient,
1836 for correct operation with 16-bit I/O registers. */
1837 int mem_volatile_p
= MEM_VOLATILE_P (src
);
1845 if (reg_dest
== reg_base
) /* R = (R) */
1848 return (AS2 (ld
,__tmp_reg__
,%1+) CR_TAB
1849 AS2 (ld
,%B0
,%1) CR_TAB
1850 AS2 (mov
,%A0
,__tmp_reg__
));
1852 else if (reg_base
== REG_X
) /* (R26) */
1854 if (reg_unused_after (insn
, base
))
1857 return (AS2 (ld
,%A0
,X
+) CR_TAB
1861 return (AS2 (ld
,%A0
,X
+) CR_TAB
1862 AS2 (ld
,%B0
,X
) CR_TAB
1868 return (AS2 (ld
,%A0
,%1) CR_TAB
1869 AS2 (ldd
,%B0
,%1+1));
1872 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
1874 int disp
= INTVAL (XEXP (base
, 1));
1875 int reg_base
= true_regnum (XEXP (base
, 0));
1877 if (disp
> MAX_LD_OFFSET (GET_MODE (src
)))
1879 if (REGNO (XEXP (base
, 0)) != REG_Y
)
1880 fatal_insn ("incorrect insn:",insn
);
1882 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
1883 return *l
= 4, (AS2 (adiw
,r28
,%o1
-62) CR_TAB
1884 AS2 (ldd
,%A0
,Y
+62) CR_TAB
1885 AS2 (ldd
,%B0
,Y
+63) CR_TAB
1886 AS2 (sbiw
,r28
,%o1
-62));
1888 return *l
= 6, (AS2 (subi
,r28
,lo8(-%o1
)) CR_TAB
1889 AS2 (sbci
,r29
,hi8(-%o1
)) CR_TAB
1890 AS2 (ld
,%A0
,Y
) CR_TAB
1891 AS2 (ldd
,%B0
,Y
+1) CR_TAB
1892 AS2 (subi
,r28
,lo8(%o1
)) CR_TAB
1893 AS2 (sbci
,r29
,hi8(%o1
)));
1895 if (reg_base
== REG_X
)
1897 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
1898 it but I have this situation with extremal
1899 optimization options. */
1902 if (reg_base
== reg_dest
)
1903 return (AS2 (adiw
,r26
,%o1
) CR_TAB
1904 AS2 (ld
,__tmp_reg__
,X
+) CR_TAB
1905 AS2 (ld
,%B0
,X
) CR_TAB
1906 AS2 (mov
,%A0
,__tmp_reg__
));
1908 return (AS2 (adiw
,r26
,%o1
) CR_TAB
1909 AS2 (ld
,%A0
,X
+) CR_TAB
1910 AS2 (ld
,%B0
,X
) CR_TAB
1911 AS2 (sbiw
,r26
,%o1
+1));
1914 if (reg_base
== reg_dest
)
1917 return (AS2 (ldd
,__tmp_reg__
,%A1
) CR_TAB
1918 AS2 (ldd
,%B0
,%B1
) CR_TAB
1919 AS2 (mov
,%A0
,__tmp_reg__
));
1923 return (AS2 (ldd
,%A0
,%A1
) CR_TAB
1926 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
1928 if (reg_overlap_mentioned_p (dest
, XEXP (base
, 0)))
1929 fatal_insn ("incorrect insn:", insn
);
1933 if (REGNO (XEXP (base
, 0)) == REG_X
)
1936 return (AS2 (sbiw
,r26
,2) CR_TAB
1937 AS2 (ld
,%A0
,X
+) CR_TAB
1938 AS2 (ld
,%B0
,X
) CR_TAB
1944 return (AS2 (sbiw
,%r1
,2) CR_TAB
1945 AS2 (ld
,%A0
,%p1
) CR_TAB
1946 AS2 (ldd
,%B0
,%p1
+1));
1951 return (AS2 (ld
,%B0
,%1) CR_TAB
1954 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
1956 if (reg_overlap_mentioned_p (dest
, XEXP (base
, 0)))
1957 fatal_insn ("incorrect insn:", insn
);
1960 return (AS2 (ld
,%A0
,%1) CR_TAB
1963 else if (CONSTANT_ADDRESS_P (base
))
1965 if (avr_io_address_p (base
, 2))
1968 return (AS2 (in
,%A0
,%A1
-0x20) CR_TAB
1969 AS2 (in
,%B0
,%B1
-0x20));
1972 return (AS2 (lds
,%A0
,%A1
) CR_TAB
1976 fatal_insn ("unknown move insn:",insn
);
1981 out_movsi_r_mr (rtx insn
, rtx op
[], int *l
)
1985 rtx base
= XEXP (src
, 0);
1986 int reg_dest
= true_regnum (dest
);
1987 int reg_base
= true_regnum (base
);
1995 if (reg_base
== REG_X
) /* (R26) */
1997 if (reg_dest
== REG_X
)
1998 /* "ld r26,-X" is undefined */
1999 return *l
=7, (AS2 (adiw
,r26
,3) CR_TAB
2000 AS2 (ld
,r29
,X
) CR_TAB
2001 AS2 (ld
,r28
,-X
) CR_TAB
2002 AS2 (ld
,__tmp_reg__
,-X
) CR_TAB
2003 AS2 (sbiw
,r26
,1) CR_TAB
2004 AS2 (ld
,r26
,X
) CR_TAB
2005 AS2 (mov
,r27
,__tmp_reg__
));
2006 else if (reg_dest
== REG_X
- 2)
2007 return *l
=5, (AS2 (ld
,%A0
,X
+) CR_TAB
2008 AS2 (ld
,%B0
,X
+) CR_TAB
2009 AS2 (ld
,__tmp_reg__
,X
+) CR_TAB
2010 AS2 (ld
,%D0
,X
) CR_TAB
2011 AS2 (mov
,%C0
,__tmp_reg__
));
2012 else if (reg_unused_after (insn
, base
))
2013 return *l
=4, (AS2 (ld
,%A0
,X
+) CR_TAB
2014 AS2 (ld
,%B0
,X
+) CR_TAB
2015 AS2 (ld
,%C0
,X
+) CR_TAB
2018 return *l
=5, (AS2 (ld
,%A0
,X
+) CR_TAB
2019 AS2 (ld
,%B0
,X
+) CR_TAB
2020 AS2 (ld
,%C0
,X
+) CR_TAB
2021 AS2 (ld
,%D0
,X
) CR_TAB
2026 if (reg_dest
== reg_base
)
2027 return *l
=5, (AS2 (ldd
,%D0
,%1+3) CR_TAB
2028 AS2 (ldd
,%C0
,%1+2) CR_TAB
2029 AS2 (ldd
,__tmp_reg__
,%1+1) CR_TAB
2030 AS2 (ld
,%A0
,%1) CR_TAB
2031 AS2 (mov
,%B0
,__tmp_reg__
));
2032 else if (reg_base
== reg_dest
+ 2)
2033 return *l
=5, (AS2 (ld
,%A0
,%1) CR_TAB
2034 AS2 (ldd
,%B0
,%1+1) CR_TAB
2035 AS2 (ldd
,__tmp_reg__
,%1+2) CR_TAB
2036 AS2 (ldd
,%D0
,%1+3) CR_TAB
2037 AS2 (mov
,%C0
,__tmp_reg__
));
2039 return *l
=4, (AS2 (ld
,%A0
,%1) CR_TAB
2040 AS2 (ldd
,%B0
,%1+1) CR_TAB
2041 AS2 (ldd
,%C0
,%1+2) CR_TAB
2042 AS2 (ldd
,%D0
,%1+3));
2045 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
2047 int disp
= INTVAL (XEXP (base
, 1));
2049 if (disp
> MAX_LD_OFFSET (GET_MODE (src
)))
2051 if (REGNO (XEXP (base
, 0)) != REG_Y
)
2052 fatal_insn ("incorrect insn:",insn
);
2054 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
2055 return *l
= 6, (AS2 (adiw
,r28
,%o1
-60) CR_TAB
2056 AS2 (ldd
,%A0
,Y
+60) CR_TAB
2057 AS2 (ldd
,%B0
,Y
+61) CR_TAB
2058 AS2 (ldd
,%C0
,Y
+62) CR_TAB
2059 AS2 (ldd
,%D0
,Y
+63) CR_TAB
2060 AS2 (sbiw
,r28
,%o1
-60));
2062 return *l
= 8, (AS2 (subi
,r28
,lo8(-%o1
)) CR_TAB
2063 AS2 (sbci
,r29
,hi8(-%o1
)) CR_TAB
2064 AS2 (ld
,%A0
,Y
) CR_TAB
2065 AS2 (ldd
,%B0
,Y
+1) CR_TAB
2066 AS2 (ldd
,%C0
,Y
+2) CR_TAB
2067 AS2 (ldd
,%D0
,Y
+3) CR_TAB
2068 AS2 (subi
,r28
,lo8(%o1
)) CR_TAB
2069 AS2 (sbci
,r29
,hi8(%o1
)));
2072 reg_base
= true_regnum (XEXP (base
, 0));
2073 if (reg_base
== REG_X
)
2076 if (reg_dest
== REG_X
)
2079 /* "ld r26,-X" is undefined */
2080 return (AS2 (adiw
,r26
,%o1
+3) CR_TAB
2081 AS2 (ld
,r29
,X
) CR_TAB
2082 AS2 (ld
,r28
,-X
) CR_TAB
2083 AS2 (ld
,__tmp_reg__
,-X
) CR_TAB
2084 AS2 (sbiw
,r26
,1) CR_TAB
2085 AS2 (ld
,r26
,X
) CR_TAB
2086 AS2 (mov
,r27
,__tmp_reg__
));
2089 if (reg_dest
== REG_X
- 2)
2090 return (AS2 (adiw
,r26
,%o1
) CR_TAB
2091 AS2 (ld
,r24
,X
+) CR_TAB
2092 AS2 (ld
,r25
,X
+) CR_TAB
2093 AS2 (ld
,__tmp_reg__
,X
+) CR_TAB
2094 AS2 (ld
,r27
,X
) CR_TAB
2095 AS2 (mov
,r26
,__tmp_reg__
));
2097 return (AS2 (adiw
,r26
,%o1
) CR_TAB
2098 AS2 (ld
,%A0
,X
+) CR_TAB
2099 AS2 (ld
,%B0
,X
+) CR_TAB
2100 AS2 (ld
,%C0
,X
+) CR_TAB
2101 AS2 (ld
,%D0
,X
) CR_TAB
2102 AS2 (sbiw
,r26
,%o1
+3));
2104 if (reg_dest
== reg_base
)
2105 return *l
=5, (AS2 (ldd
,%D0
,%D1
) CR_TAB
2106 AS2 (ldd
,%C0
,%C1
) CR_TAB
2107 AS2 (ldd
,__tmp_reg__
,%B1
) CR_TAB
2108 AS2 (ldd
,%A0
,%A1
) CR_TAB
2109 AS2 (mov
,%B0
,__tmp_reg__
));
2110 else if (reg_dest
== reg_base
- 2)
2111 return *l
=5, (AS2 (ldd
,%A0
,%A1
) CR_TAB
2112 AS2 (ldd
,%B0
,%B1
) CR_TAB
2113 AS2 (ldd
,__tmp_reg__
,%C1
) CR_TAB
2114 AS2 (ldd
,%D0
,%D1
) CR_TAB
2115 AS2 (mov
,%C0
,__tmp_reg__
));
2116 return *l
=4, (AS2 (ldd
,%A0
,%A1
) CR_TAB
2117 AS2 (ldd
,%B0
,%B1
) CR_TAB
2118 AS2 (ldd
,%C0
,%C1
) CR_TAB
2121 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2122 return *l
=4, (AS2 (ld
,%D0
,%1) CR_TAB
2123 AS2 (ld
,%C0
,%1) CR_TAB
2124 AS2 (ld
,%B0
,%1) CR_TAB
2126 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2127 return *l
=4, (AS2 (ld
,%A0
,%1) CR_TAB
2128 AS2 (ld
,%B0
,%1) CR_TAB
2129 AS2 (ld
,%C0
,%1) CR_TAB
2131 else if (CONSTANT_ADDRESS_P (base
))
2132 return *l
=8, (AS2 (lds
,%A0
,%A1
) CR_TAB
2133 AS2 (lds
,%B0
,%B1
) CR_TAB
2134 AS2 (lds
,%C0
,%C1
) CR_TAB
2137 fatal_insn ("unknown move insn:",insn
);
2142 out_movsi_mr_r (rtx insn
, rtx op
[], int *l
)
2146 rtx base
= XEXP (dest
, 0);
2147 int reg_base
= true_regnum (base
);
2148 int reg_src
= true_regnum (src
);
2154 if (CONSTANT_ADDRESS_P (base
))
2155 return *l
=8,(AS2 (sts
,%A0
,%A1
) CR_TAB
2156 AS2 (sts
,%B0
,%B1
) CR_TAB
2157 AS2 (sts
,%C0
,%C1
) CR_TAB
2159 if (reg_base
> 0) /* (r) */
2161 if (reg_base
== REG_X
) /* (R26) */
2163 if (reg_src
== REG_X
)
2165 /* "st X+,r26" is undefined */
2166 if (reg_unused_after (insn
, base
))
2167 return *l
=6, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2168 AS2 (st
,X
,r26
) CR_TAB
2169 AS2 (adiw
,r26
,1) CR_TAB
2170 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2171 AS2 (st
,X
+,r28
) CR_TAB
2174 return *l
=7, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2175 AS2 (st
,X
,r26
) CR_TAB
2176 AS2 (adiw
,r26
,1) CR_TAB
2177 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2178 AS2 (st
,X
+,r28
) CR_TAB
2179 AS2 (st
,X
,r29
) CR_TAB
2182 else if (reg_base
== reg_src
+ 2)
2184 if (reg_unused_after (insn
, base
))
2185 return *l
=7, (AS2 (mov
,__zero_reg__
,%C1
) CR_TAB
2186 AS2 (mov
,__tmp_reg__
,%D1
) CR_TAB
2187 AS2 (st
,%0+,%A1
) CR_TAB
2188 AS2 (st
,%0+,%B1
) CR_TAB
2189 AS2 (st
,%0+,__zero_reg__
) CR_TAB
2190 AS2 (st
,%0,__tmp_reg__
) CR_TAB
2191 AS1 (clr
,__zero_reg__
));
2193 return *l
=8, (AS2 (mov
,__zero_reg__
,%C1
) CR_TAB
2194 AS2 (mov
,__tmp_reg__
,%D1
) CR_TAB
2195 AS2 (st
,%0+,%A1
) CR_TAB
2196 AS2 (st
,%0+,%B1
) CR_TAB
2197 AS2 (st
,%0+,__zero_reg__
) CR_TAB
2198 AS2 (st
,%0,__tmp_reg__
) CR_TAB
2199 AS1 (clr
,__zero_reg__
) CR_TAB
2202 return *l
=5, (AS2 (st
,%0+,%A1
) CR_TAB
2203 AS2 (st
,%0+,%B1
) CR_TAB
2204 AS2 (st
,%0+,%C1
) CR_TAB
2205 AS2 (st
,%0,%D1
) CR_TAB
2209 return *l
=4, (AS2 (st
,%0,%A1
) CR_TAB
2210 AS2 (std
,%0+1,%B1
) CR_TAB
2211 AS2 (std
,%0+2,%C1
) CR_TAB
2212 AS2 (std
,%0+3,%D1
));
2214 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
2216 int disp
= INTVAL (XEXP (base
, 1));
2217 reg_base
= REGNO (XEXP (base
, 0));
2218 if (disp
> MAX_LD_OFFSET (GET_MODE (dest
)))
2220 if (reg_base
!= REG_Y
)
2221 fatal_insn ("incorrect insn:",insn
);
2223 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
2224 return *l
= 6, (AS2 (adiw
,r28
,%o0
-60) CR_TAB
2225 AS2 (std
,Y
+60,%A1
) CR_TAB
2226 AS2 (std
,Y
+61,%B1
) CR_TAB
2227 AS2 (std
,Y
+62,%C1
) CR_TAB
2228 AS2 (std
,Y
+63,%D1
) CR_TAB
2229 AS2 (sbiw
,r28
,%o0
-60));
2231 return *l
= 8, (AS2 (subi
,r28
,lo8(-%o0
)) CR_TAB
2232 AS2 (sbci
,r29
,hi8(-%o0
)) CR_TAB
2233 AS2 (st
,Y
,%A1
) CR_TAB
2234 AS2 (std
,Y
+1,%B1
) CR_TAB
2235 AS2 (std
,Y
+2,%C1
) CR_TAB
2236 AS2 (std
,Y
+3,%D1
) CR_TAB
2237 AS2 (subi
,r28
,lo8(%o0
)) CR_TAB
2238 AS2 (sbci
,r29
,hi8(%o0
)));
2240 if (reg_base
== REG_X
)
2243 if (reg_src
== REG_X
)
2246 return (AS2 (mov
,__tmp_reg__
,r26
) CR_TAB
2247 AS2 (mov
,__zero_reg__
,r27
) CR_TAB
2248 AS2 (adiw
,r26
,%o0
) CR_TAB
2249 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2250 AS2 (st
,X
+,__zero_reg__
) CR_TAB
2251 AS2 (st
,X
+,r28
) CR_TAB
2252 AS2 (st
,X
,r29
) CR_TAB
2253 AS1 (clr
,__zero_reg__
) CR_TAB
2254 AS2 (sbiw
,r26
,%o0
+3));
2256 else if (reg_src
== REG_X
- 2)
2259 return (AS2 (mov
,__tmp_reg__
,r26
) CR_TAB
2260 AS2 (mov
,__zero_reg__
,r27
) CR_TAB
2261 AS2 (adiw
,r26
,%o0
) CR_TAB
2262 AS2 (st
,X
+,r24
) CR_TAB
2263 AS2 (st
,X
+,r25
) CR_TAB
2264 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2265 AS2 (st
,X
,__zero_reg__
) CR_TAB
2266 AS1 (clr
,__zero_reg__
) CR_TAB
2267 AS2 (sbiw
,r26
,%o0
+3));
2270 return (AS2 (adiw
,r26
,%o0
) CR_TAB
2271 AS2 (st
,X
+,%A1
) CR_TAB
2272 AS2 (st
,X
+,%B1
) CR_TAB
2273 AS2 (st
,X
+,%C1
) CR_TAB
2274 AS2 (st
,X
,%D1
) CR_TAB
2275 AS2 (sbiw
,r26
,%o0
+3));
2277 return *l
=4, (AS2 (std
,%A0
,%A1
) CR_TAB
2278 AS2 (std
,%B0
,%B1
) CR_TAB
2279 AS2 (std
,%C0
,%C1
) CR_TAB
2282 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2283 return *l
=4, (AS2 (st
,%0,%D1
) CR_TAB
2284 AS2 (st
,%0,%C1
) CR_TAB
2285 AS2 (st
,%0,%B1
) CR_TAB
2287 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2288 return *l
=4, (AS2 (st
,%0,%A1
) CR_TAB
2289 AS2 (st
,%0,%B1
) CR_TAB
2290 AS2 (st
,%0,%C1
) CR_TAB
2292 fatal_insn ("unknown move insn:",insn
);
2297 output_movsisf(rtx insn
, rtx operands
[], int *l
)
2300 rtx dest
= operands
[0];
2301 rtx src
= operands
[1];
2307 if (register_operand (dest
, VOIDmode
))
2309 if (register_operand (src
, VOIDmode
)) /* mov r,r */
2311 if (true_regnum (dest
) > true_regnum (src
))
2316 return (AS2 (movw
,%C0
,%C1
) CR_TAB
2317 AS2 (movw
,%A0
,%A1
));
2320 return (AS2 (mov
,%D0
,%D1
) CR_TAB
2321 AS2 (mov
,%C0
,%C1
) CR_TAB
2322 AS2 (mov
,%B0
,%B1
) CR_TAB
2330 return (AS2 (movw
,%A0
,%A1
) CR_TAB
2331 AS2 (movw
,%C0
,%C1
));
2334 return (AS2 (mov
,%A0
,%A1
) CR_TAB
2335 AS2 (mov
,%B0
,%B1
) CR_TAB
2336 AS2 (mov
,%C0
,%C1
) CR_TAB
2340 else if (CONSTANT_P (src
))
2342 if (test_hard_reg_class (LD_REGS
, dest
)) /* ldi d,i */
2345 return (AS2 (ldi
,%A0
,lo8(%1)) CR_TAB
2346 AS2 (ldi
,%B0
,hi8(%1)) CR_TAB
2347 AS2 (ldi
,%C0
,hlo8(%1)) CR_TAB
2348 AS2 (ldi
,%D0
,hhi8(%1)));
2351 if (GET_CODE (src
) == CONST_INT
)
2353 const char *const clr_op0
=
2354 AVR_HAVE_MOVW
? (AS1 (clr
,%A0
) CR_TAB
2355 AS1 (clr
,%B0
) CR_TAB
2357 : (AS1 (clr
,%A0
) CR_TAB
2358 AS1 (clr
,%B0
) CR_TAB
2359 AS1 (clr
,%C0
) CR_TAB
2362 if (src
== const0_rtx
) /* mov r,L */
2364 *l
= AVR_HAVE_MOVW
? 3 : 4;
2367 else if (src
== const1_rtx
)
2370 output_asm_insn (clr_op0
, operands
);
2371 *l
= AVR_HAVE_MOVW
? 4 : 5;
2372 return AS1 (inc
,%A0
);
2374 else if (src
== constm1_rtx
)
2376 /* Immediate constants -1 to any register */
2380 return (AS1 (clr
,%A0
) CR_TAB
2381 AS1 (dec
,%A0
) CR_TAB
2382 AS2 (mov
,%B0
,%A0
) CR_TAB
2383 AS2 (movw
,%C0
,%A0
));
2386 return (AS1 (clr
,%A0
) CR_TAB
2387 AS1 (dec
,%A0
) CR_TAB
2388 AS2 (mov
,%B0
,%A0
) CR_TAB
2389 AS2 (mov
,%C0
,%A0
) CR_TAB
2394 int bit_nr
= exact_log2 (INTVAL (src
));
2398 *l
= AVR_HAVE_MOVW
? 5 : 6;
2401 output_asm_insn (clr_op0
, operands
);
2402 output_asm_insn ("set", operands
);
2405 avr_output_bld (operands
, bit_nr
);
2412 /* Last resort, better than loading from memory. */
2414 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
2415 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
2416 AS2 (mov
,%A0
,r31
) CR_TAB
2417 AS2 (ldi
,r31
,hi8(%1)) CR_TAB
2418 AS2 (mov
,%B0
,r31
) CR_TAB
2419 AS2 (ldi
,r31
,hlo8(%1)) CR_TAB
2420 AS2 (mov
,%C0
,r31
) CR_TAB
2421 AS2 (ldi
,r31
,hhi8(%1)) CR_TAB
2422 AS2 (mov
,%D0
,r31
) CR_TAB
2423 AS2 (mov
,r31
,__tmp_reg__
));
2425 else if (GET_CODE (src
) == MEM
)
2426 return out_movsi_r_mr (insn
, operands
, real_l
); /* mov r,m */
2428 else if (GET_CODE (dest
) == MEM
)
2430 const char *template;
2432 if (src
== const0_rtx
)
2433 operands
[1] = zero_reg_rtx
;
2435 template = out_movsi_mr_r (insn
, operands
, real_l
);
2438 output_asm_insn (template, operands
);
2443 fatal_insn ("invalid insn:", insn
);
2448 out_movqi_mr_r (rtx insn
, rtx op
[], int *l
)
2452 rtx x
= XEXP (dest
, 0);
2458 if (CONSTANT_ADDRESS_P (x
))
2460 if (avr_io_address_p (x
, 1))
2463 return AS2 (out
,%0-0x20,%1);
2466 return AS2 (sts
,%0,%1);
2468 /* memory access by reg+disp */
2469 else if (GET_CODE (x
) == PLUS
2470 && REG_P (XEXP (x
,0))
2471 && GET_CODE (XEXP (x
,1)) == CONST_INT
)
2473 if ((INTVAL (XEXP (x
,1)) - GET_MODE_SIZE (GET_MODE (dest
))) >= 63)
2475 int disp
= INTVAL (XEXP (x
,1));
2476 if (REGNO (XEXP (x
,0)) != REG_Y
)
2477 fatal_insn ("incorrect insn:",insn
);
2479 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
2480 return *l
= 3, (AS2 (adiw
,r28
,%o0
-63) CR_TAB
2481 AS2 (std
,Y
+63,%1) CR_TAB
2482 AS2 (sbiw
,r28
,%o0
-63));
2484 return *l
= 5, (AS2 (subi
,r28
,lo8(-%o0
)) CR_TAB
2485 AS2 (sbci
,r29
,hi8(-%o0
)) CR_TAB
2486 AS2 (st
,Y
,%1) CR_TAB
2487 AS2 (subi
,r28
,lo8(%o0
)) CR_TAB
2488 AS2 (sbci
,r29
,hi8(%o0
)));
2490 else if (REGNO (XEXP (x
,0)) == REG_X
)
2492 if (reg_overlap_mentioned_p (src
, XEXP (x
, 0)))
2494 if (reg_unused_after (insn
, XEXP (x
,0)))
2495 return *l
= 3, (AS2 (mov
,__tmp_reg__
,%1) CR_TAB
2496 AS2 (adiw
,r26
,%o0
) CR_TAB
2497 AS2 (st
,X
,__tmp_reg__
));
2499 return *l
= 4, (AS2 (mov
,__tmp_reg__
,%1) CR_TAB
2500 AS2 (adiw
,r26
,%o0
) CR_TAB
2501 AS2 (st
,X
,__tmp_reg__
) CR_TAB
2502 AS2 (sbiw
,r26
,%o0
));
2506 if (reg_unused_after (insn
, XEXP (x
,0)))
2507 return *l
= 2, (AS2 (adiw
,r26
,%o0
) CR_TAB
2510 return *l
= 3, (AS2 (adiw
,r26
,%o0
) CR_TAB
2511 AS2 (st
,X
,%1) CR_TAB
2512 AS2 (sbiw
,r26
,%o0
));
2516 return AS2 (std
,%0,%1);
2519 return AS2 (st
,%0,%1);
2523 out_movhi_mr_r (rtx insn
, rtx op
[], int *l
)
2527 rtx base
= XEXP (dest
, 0);
2528 int reg_base
= true_regnum (base
);
2529 int reg_src
= true_regnum (src
);
2530 /* "volatile" forces writing high byte first, even if less efficient,
2531 for correct operation with 16-bit I/O registers. */
2532 int mem_volatile_p
= MEM_VOLATILE_P (dest
);
2537 if (CONSTANT_ADDRESS_P (base
))
2539 if (avr_io_address_p (base
, 2))
2542 return (AS2 (out
,%B0
-0x20,%B1
) CR_TAB
2543 AS2 (out
,%A0
-0x20,%A1
));
2545 return *l
= 4, (AS2 (sts
,%B0
,%B1
) CR_TAB
2550 if (reg_base
== REG_X
)
2552 if (reg_src
== REG_X
)
2554 /* "st X+,r26" and "st -X,r26" are undefined. */
2555 if (!mem_volatile_p
&& reg_unused_after (insn
, src
))
2556 return *l
=4, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2557 AS2 (st
,X
,r26
) CR_TAB
2558 AS2 (adiw
,r26
,1) CR_TAB
2559 AS2 (st
,X
,__tmp_reg__
));
2561 return *l
=5, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2562 AS2 (adiw
,r26
,1) CR_TAB
2563 AS2 (st
,X
,__tmp_reg__
) CR_TAB
2564 AS2 (sbiw
,r26
,1) CR_TAB
2569 if (!mem_volatile_p
&& reg_unused_after (insn
, base
))
2570 return *l
=2, (AS2 (st
,X
+,%A1
) CR_TAB
2573 return *l
=3, (AS2 (adiw
,r26
,1) CR_TAB
2574 AS2 (st
,X
,%B1
) CR_TAB
2579 return *l
=2, (AS2 (std
,%0+1,%B1
) CR_TAB
2582 else if (GET_CODE (base
) == PLUS
)
2584 int disp
= INTVAL (XEXP (base
, 1));
2585 reg_base
= REGNO (XEXP (base
, 0));
2586 if (disp
> MAX_LD_OFFSET (GET_MODE (dest
)))
2588 if (reg_base
!= REG_Y
)
2589 fatal_insn ("incorrect insn:",insn
);
2591 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
2592 return *l
= 4, (AS2 (adiw
,r28
,%o0
-62) CR_TAB
2593 AS2 (std
,Y
+63,%B1
) CR_TAB
2594 AS2 (std
,Y
+62,%A1
) CR_TAB
2595 AS2 (sbiw
,r28
,%o0
-62));
2597 return *l
= 6, (AS2 (subi
,r28
,lo8(-%o0
)) CR_TAB
2598 AS2 (sbci
,r29
,hi8(-%o0
)) CR_TAB
2599 AS2 (std
,Y
+1,%B1
) CR_TAB
2600 AS2 (st
,Y
,%A1
) CR_TAB
2601 AS2 (subi
,r28
,lo8(%o0
)) CR_TAB
2602 AS2 (sbci
,r29
,hi8(%o0
)));
2604 if (reg_base
== REG_X
)
2607 if (reg_src
== REG_X
)
2610 return (AS2 (mov
,__tmp_reg__
,r26
) CR_TAB
2611 AS2 (mov
,__zero_reg__
,r27
) CR_TAB
2612 AS2 (adiw
,r26
,%o0
+1) CR_TAB
2613 AS2 (st
,X
,__zero_reg__
) CR_TAB
2614 AS2 (st
,-X
,__tmp_reg__
) CR_TAB
2615 AS1 (clr
,__zero_reg__
) CR_TAB
2616 AS2 (sbiw
,r26
,%o0
));
2619 return (AS2 (adiw
,r26
,%o0
+1) CR_TAB
2620 AS2 (st
,X
,%B1
) CR_TAB
2621 AS2 (st
,-X
,%A1
) CR_TAB
2622 AS2 (sbiw
,r26
,%o0
));
2624 return *l
=2, (AS2 (std
,%B0
,%B1
) CR_TAB
2627 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2628 return *l
=2, (AS2 (st
,%0,%B1
) CR_TAB
2630 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2634 if (REGNO (XEXP (base
, 0)) == REG_X
)
2637 return (AS2 (adiw
,r26
,1) CR_TAB
2638 AS2 (st
,X
,%B1
) CR_TAB
2639 AS2 (st
,-X
,%A1
) CR_TAB
2645 return (AS2 (std
,%p0
+1,%B1
) CR_TAB
2646 AS2 (st
,%p0
,%A1
) CR_TAB
2652 return (AS2 (st
,%0,%A1
) CR_TAB
2655 fatal_insn ("unknown move insn:",insn
);
2659 /* Return 1 if frame pointer for current function required. */
2662 frame_pointer_required_p (void)
2664 return (current_function_calls_alloca
2665 || current_function_args_info
.nregs
== 0
2666 || get_frame_size () > 0);
2669 /* Returns the condition of compare insn INSN, or UNKNOWN. */
2672 compare_condition (rtx insn
)
2674 rtx next
= next_real_insn (insn
);
2675 RTX_CODE cond
= UNKNOWN
;
2676 if (next
&& GET_CODE (next
) == JUMP_INSN
)
2678 rtx pat
= PATTERN (next
);
2679 rtx src
= SET_SRC (pat
);
2680 rtx t
= XEXP (src
, 0);
2681 cond
= GET_CODE (t
);
2686 /* Returns nonzero if INSN is a tst insn that only tests the sign. */
2689 compare_sign_p (rtx insn
)
2691 RTX_CODE cond
= compare_condition (insn
);
2692 return (cond
== GE
|| cond
== LT
);
2695 /* Returns nonzero if the next insn is a JUMP_INSN with a condition
2696 that needs to be swapped (GT, GTU, LE, LEU). */
2699 compare_diff_p (rtx insn
)
2701 RTX_CODE cond
= compare_condition (insn
);
2702 return (cond
== GT
|| cond
== GTU
|| cond
== LE
|| cond
== LEU
) ? cond
: 0;
2705 /* Returns nonzero if INSN is a compare insn with the EQ or NE condition. */
2708 compare_eq_p (rtx insn
)
2710 RTX_CODE cond
= compare_condition (insn
);
2711 return (cond
== EQ
|| cond
== NE
);
2715 /* Output test instruction for HImode. */
2718 out_tsthi (rtx insn
, int *l
)
2720 if (compare_sign_p (insn
))
2723 return AS1 (tst
,%B0
);
2725 if (reg_unused_after (insn
, SET_SRC (PATTERN (insn
)))
2726 && compare_eq_p (insn
))
2728 /* Faster than sbiw if we can clobber the operand. */
2730 return AS2 (or,%A0
,%B0
);
2732 if (test_hard_reg_class (ADDW_REGS
, SET_SRC (PATTERN (insn
))))
2735 return AS2 (sbiw
,%0,0);
2738 return (AS2 (cp
,%A0
,__zero_reg__
) CR_TAB
2739 AS2 (cpc
,%B0
,__zero_reg__
));
2743 /* Output test instruction for SImode. */
2746 out_tstsi (rtx insn
, int *l
)
2748 if (compare_sign_p (insn
))
2751 return AS1 (tst
,%D0
);
2753 if (test_hard_reg_class (ADDW_REGS
, SET_SRC (PATTERN (insn
))))
2756 return (AS2 (sbiw
,%A0
,0) CR_TAB
2757 AS2 (cpc
,%C0
,__zero_reg__
) CR_TAB
2758 AS2 (cpc
,%D0
,__zero_reg__
));
2761 return (AS2 (cp
,%A0
,__zero_reg__
) CR_TAB
2762 AS2 (cpc
,%B0
,__zero_reg__
) CR_TAB
2763 AS2 (cpc
,%C0
,__zero_reg__
) CR_TAB
2764 AS2 (cpc
,%D0
,__zero_reg__
));
2768 /* Generate asm equivalent for various shifts.
2769 Shift count is a CONST_INT, MEM or REG.
2770 This only handles cases that are not already
2771 carefully hand-optimized in ?sh??i3_out. */
2774 out_shift_with_cnt (const char *template, rtx insn
, rtx operands
[],
2775 int *len
, int t_len
)
2779 int second_label
= 1;
2780 int saved_in_tmp
= 0;
2781 int use_zero_reg
= 0;
2783 op
[0] = operands
[0];
2784 op
[1] = operands
[1];
2785 op
[2] = operands
[2];
2786 op
[3] = operands
[3];
2792 if (GET_CODE (operands
[2]) == CONST_INT
)
2794 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
2795 int count
= INTVAL (operands
[2]);
2796 int max_len
= 10; /* If larger than this, always use a loop. */
2805 if (count
< 8 && !scratch
)
2809 max_len
= t_len
+ (scratch
? 3 : (use_zero_reg
? 4 : 5));
2811 if (t_len
* count
<= max_len
)
2813 /* Output shifts inline with no loop - faster. */
2815 *len
= t_len
* count
;
2819 output_asm_insn (template, op
);
2828 strcat (str
, AS2 (ldi
,%3,%2));
2830 else if (use_zero_reg
)
2832 /* Hack to save one word: use __zero_reg__ as loop counter.
2833 Set one bit, then shift in a loop until it is 0 again. */
2835 op
[3] = zero_reg_rtx
;
2839 strcat (str
, ("set" CR_TAB
2840 AS2 (bld
,%3,%2-1)));
2844 /* No scratch register available, use one from LD_REGS (saved in
2845 __tmp_reg__) that doesn't overlap with registers to shift. */
2847 op
[3] = gen_rtx_REG (QImode
,
2848 ((true_regnum (operands
[0]) - 1) & 15) + 16);
2849 op
[4] = tmp_reg_rtx
;
2853 *len
= 3; /* Includes "mov %3,%4" after the loop. */
2855 strcat (str
, (AS2 (mov
,%4,%3) CR_TAB
2861 else if (GET_CODE (operands
[2]) == MEM
)
2865 op
[3] = op_mov
[0] = tmp_reg_rtx
;
2869 out_movqi_r_mr (insn
, op_mov
, len
);
2871 output_asm_insn (out_movqi_r_mr (insn
, op_mov
, NULL
), op_mov
);
2873 else if (register_operand (operands
[2], QImode
))
2875 if (reg_unused_after (insn
, operands
[2]))
2879 op
[3] = tmp_reg_rtx
;
2881 strcat (str
, (AS2 (mov
,%3,%2) CR_TAB
));
2885 fatal_insn ("bad shift insn:", insn
);
2892 strcat (str
, AS1 (rjmp
,2f
));
2896 *len
+= t_len
+ 2; /* template + dec + brXX */
2899 strcat (str
, "\n1:\t");
2900 strcat (str
, template);
2901 strcat (str
, second_label
? "\n2:\t" : "\n\t");
2902 strcat (str
, use_zero_reg
? AS1 (lsr
,%3) : AS1 (dec
,%3));
2903 strcat (str
, CR_TAB
);
2904 strcat (str
, second_label
? AS1 (brpl
,1b
) : AS1 (brne
,1b
));
2906 strcat (str
, (CR_TAB
AS2 (mov
,%3,%4)));
2907 output_asm_insn (str
, op
);
2912 /* 8bit shift left ((char)x << i) */
2915 ashlqi3_out (rtx insn
, rtx operands
[], int *len
)
2917 if (GET_CODE (operands
[2]) == CONST_INT
)
2924 switch (INTVAL (operands
[2]))
2927 if (INTVAL (operands
[2]) < 8)
2931 return AS1 (clr
,%0);
2935 return AS1 (lsl
,%0);
2939 return (AS1 (lsl
,%0) CR_TAB
2944 return (AS1 (lsl
,%0) CR_TAB
2949 if (test_hard_reg_class (LD_REGS
, operands
[0]))
2952 return (AS1 (swap
,%0) CR_TAB
2953 AS2 (andi
,%0,0xf0));
2956 return (AS1 (lsl
,%0) CR_TAB
2962 if (test_hard_reg_class (LD_REGS
, operands
[0]))
2965 return (AS1 (swap
,%0) CR_TAB
2967 AS2 (andi
,%0,0xe0));
2970 return (AS1 (lsl
,%0) CR_TAB
2977 if (test_hard_reg_class (LD_REGS
, operands
[0]))
2980 return (AS1 (swap
,%0) CR_TAB
2983 AS2 (andi
,%0,0xc0));
2986 return (AS1 (lsl
,%0) CR_TAB
2995 return (AS1 (ror
,%0) CR_TAB
3000 else if (CONSTANT_P (operands
[2]))
3001 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
3003 out_shift_with_cnt (AS1 (lsl
,%0),
3004 insn
, operands
, len
, 1);
3009 /* 16bit shift left ((short)x << i) */
3012 ashlhi3_out (rtx insn
, rtx operands
[], int *len
)
3014 if (GET_CODE (operands
[2]) == CONST_INT
)
3016 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
3017 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
3024 switch (INTVAL (operands
[2]))
3027 if (INTVAL (operands
[2]) < 16)
3031 return (AS1 (clr
,%B0
) CR_TAB
3035 if (optimize_size
&& scratch
)
3040 return (AS1 (swap
,%A0
) CR_TAB
3041 AS1 (swap
,%B0
) CR_TAB
3042 AS2 (andi
,%B0
,0xf0) CR_TAB
3043 AS2 (eor
,%B0
,%A0
) CR_TAB
3044 AS2 (andi
,%A0
,0xf0) CR_TAB
3050 return (AS1 (swap
,%A0
) CR_TAB
3051 AS1 (swap
,%B0
) CR_TAB
3052 AS2 (ldi
,%3,0xf0) CR_TAB
3053 AS2 (and,%B0
,%3) CR_TAB
3054 AS2 (eor
,%B0
,%A0
) CR_TAB
3055 AS2 (and,%A0
,%3) CR_TAB
3058 break; /* optimize_size ? 6 : 8 */
3062 break; /* scratch ? 5 : 6 */
3066 return (AS1 (lsl
,%A0
) CR_TAB
3067 AS1 (rol
,%B0
) CR_TAB
3068 AS1 (swap
,%A0
) CR_TAB
3069 AS1 (swap
,%B0
) CR_TAB
3070 AS2 (andi
,%B0
,0xf0) CR_TAB
3071 AS2 (eor
,%B0
,%A0
) CR_TAB
3072 AS2 (andi
,%A0
,0xf0) CR_TAB
3078 return (AS1 (lsl
,%A0
) CR_TAB
3079 AS1 (rol
,%B0
) CR_TAB
3080 AS1 (swap
,%A0
) CR_TAB
3081 AS1 (swap
,%B0
) CR_TAB
3082 AS2 (ldi
,%3,0xf0) CR_TAB
3083 AS2 (and,%B0
,%3) CR_TAB
3084 AS2 (eor
,%B0
,%A0
) CR_TAB
3085 AS2 (and,%A0
,%3) CR_TAB
3092 break; /* scratch ? 5 : 6 */
3094 return (AS1 (clr
,__tmp_reg__
) CR_TAB
3095 AS1 (lsr
,%B0
) CR_TAB
3096 AS1 (ror
,%A0
) CR_TAB
3097 AS1 (ror
,__tmp_reg__
) CR_TAB
3098 AS1 (lsr
,%B0
) CR_TAB
3099 AS1 (ror
,%A0
) CR_TAB
3100 AS1 (ror
,__tmp_reg__
) CR_TAB
3101 AS2 (mov
,%B0
,%A0
) CR_TAB
3102 AS2 (mov
,%A0
,__tmp_reg__
));
3106 return (AS1 (lsr
,%B0
) CR_TAB
3107 AS2 (mov
,%B0
,%A0
) CR_TAB
3108 AS1 (clr
,%A0
) CR_TAB
3109 AS1 (ror
,%B0
) CR_TAB
3113 return *len
= 2, (AS2 (mov
,%B0
,%A1
) CR_TAB
3118 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3119 AS1 (clr
,%A0
) CR_TAB
3124 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3125 AS1 (clr
,%A0
) CR_TAB
3126 AS1 (lsl
,%B0
) CR_TAB
3131 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3132 AS1 (clr
,%A0
) CR_TAB
3133 AS1 (lsl
,%B0
) CR_TAB
3134 AS1 (lsl
,%B0
) CR_TAB
3141 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3142 AS1 (clr
,%A0
) CR_TAB
3143 AS1 (swap
,%B0
) CR_TAB
3144 AS2 (andi
,%B0
,0xf0));
3149 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3150 AS1 (clr
,%A0
) CR_TAB
3151 AS1 (swap
,%B0
) CR_TAB
3152 AS2 (ldi
,%3,0xf0) CR_TAB
3156 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3157 AS1 (clr
,%A0
) CR_TAB
3158 AS1 (lsl
,%B0
) CR_TAB
3159 AS1 (lsl
,%B0
) CR_TAB
3160 AS1 (lsl
,%B0
) CR_TAB
3167 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3168 AS1 (clr
,%A0
) CR_TAB
3169 AS1 (swap
,%B0
) CR_TAB
3170 AS1 (lsl
,%B0
) CR_TAB
3171 AS2 (andi
,%B0
,0xe0));
3173 if (AVR_HAVE_MUL
&& scratch
)
3176 return (AS2 (ldi
,%3,0x20) CR_TAB
3177 AS2 (mul
,%A0
,%3) CR_TAB
3178 AS2 (mov
,%B0
,r0
) CR_TAB
3179 AS1 (clr
,%A0
) CR_TAB
3180 AS1 (clr
,__zero_reg__
));
3182 if (optimize_size
&& scratch
)
3187 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3188 AS1 (clr
,%A0
) CR_TAB
3189 AS1 (swap
,%B0
) CR_TAB
3190 AS1 (lsl
,%B0
) CR_TAB
3191 AS2 (ldi
,%3,0xe0) CR_TAB
3197 return ("set" CR_TAB
3198 AS2 (bld
,r1
,5) CR_TAB
3199 AS2 (mul
,%A0
,r1
) CR_TAB
3200 AS2 (mov
,%B0
,r0
) CR_TAB
3201 AS1 (clr
,%A0
) CR_TAB
3202 AS1 (clr
,__zero_reg__
));
3205 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3206 AS1 (clr
,%A0
) CR_TAB
3207 AS1 (lsl
,%B0
) CR_TAB
3208 AS1 (lsl
,%B0
) CR_TAB
3209 AS1 (lsl
,%B0
) CR_TAB
3210 AS1 (lsl
,%B0
) CR_TAB
3214 if (AVR_HAVE_MUL
&& ldi_ok
)
3217 return (AS2 (ldi
,%B0
,0x40) CR_TAB
3218 AS2 (mul
,%A0
,%B0
) CR_TAB
3219 AS2 (mov
,%B0
,r0
) CR_TAB
3220 AS1 (clr
,%A0
) CR_TAB
3221 AS1 (clr
,__zero_reg__
));
3223 if (AVR_HAVE_MUL
&& scratch
)
3226 return (AS2 (ldi
,%3,0x40) CR_TAB
3227 AS2 (mul
,%A0
,%3) CR_TAB
3228 AS2 (mov
,%B0
,r0
) CR_TAB
3229 AS1 (clr
,%A0
) CR_TAB
3230 AS1 (clr
,__zero_reg__
));
3232 if (optimize_size
&& ldi_ok
)
3235 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3236 AS2 (ldi
,%A0
,6) "\n1:\t"
3237 AS1 (lsl
,%B0
) CR_TAB
3238 AS1 (dec
,%A0
) CR_TAB
3241 if (optimize_size
&& scratch
)
3244 return (AS1 (clr
,%B0
) CR_TAB
3245 AS1 (lsr
,%A0
) CR_TAB
3246 AS1 (ror
,%B0
) CR_TAB
3247 AS1 (lsr
,%A0
) CR_TAB
3248 AS1 (ror
,%B0
) CR_TAB
3253 return (AS1 (clr
,%B0
) CR_TAB
3254 AS1 (lsr
,%A0
) CR_TAB
3255 AS1 (ror
,%B0
) CR_TAB
3260 out_shift_with_cnt ((AS1 (lsl
,%A0
) CR_TAB
3262 insn
, operands
, len
, 2);
3267 /* 32bit shift left ((long)x << i) */
3270 ashlsi3_out (rtx insn
, rtx operands
[], int *len
)
3272 if (GET_CODE (operands
[2]) == CONST_INT
)
3280 switch (INTVAL (operands
[2]))
3283 if (INTVAL (operands
[2]) < 32)
3287 return *len
= 3, (AS1 (clr
,%D0
) CR_TAB
3288 AS1 (clr
,%C0
) CR_TAB
3289 AS2 (movw
,%A0
,%C0
));
3291 return (AS1 (clr
,%D0
) CR_TAB
3292 AS1 (clr
,%C0
) CR_TAB
3293 AS1 (clr
,%B0
) CR_TAB
3298 int reg0
= true_regnum (operands
[0]);
3299 int reg1
= true_regnum (operands
[1]);
3302 return (AS2 (mov
,%D0
,%C1
) CR_TAB
3303 AS2 (mov
,%C0
,%B1
) CR_TAB
3304 AS2 (mov
,%B0
,%A1
) CR_TAB
3307 return (AS1 (clr
,%A0
) CR_TAB
3308 AS2 (mov
,%B0
,%A1
) CR_TAB
3309 AS2 (mov
,%C0
,%B1
) CR_TAB
3315 int reg0
= true_regnum (operands
[0]);
3316 int reg1
= true_regnum (operands
[1]);
3317 if (reg0
+ 2 == reg1
)
3318 return *len
= 2, (AS1 (clr
,%B0
) CR_TAB
3321 return *len
= 3, (AS2 (movw
,%C0
,%A1
) CR_TAB
3322 AS1 (clr
,%B0
) CR_TAB
3325 return *len
= 4, (AS2 (mov
,%C0
,%A1
) CR_TAB
3326 AS2 (mov
,%D0
,%B1
) CR_TAB
3327 AS1 (clr
,%B0
) CR_TAB
3333 return (AS2 (mov
,%D0
,%A1
) CR_TAB
3334 AS1 (clr
,%C0
) CR_TAB
3335 AS1 (clr
,%B0
) CR_TAB
3340 return (AS1 (clr
,%D0
) CR_TAB
3341 AS1 (lsr
,%A0
) CR_TAB
3342 AS1 (ror
,%D0
) CR_TAB
3343 AS1 (clr
,%C0
) CR_TAB
3344 AS1 (clr
,%B0
) CR_TAB
3349 out_shift_with_cnt ((AS1 (lsl
,%A0
) CR_TAB
3350 AS1 (rol
,%B0
) CR_TAB
3351 AS1 (rol
,%C0
) CR_TAB
3353 insn
, operands
, len
, 4);
3357 /* 8bit arithmetic shift right ((signed char)x >> i) */
3360 ashrqi3_out (rtx insn
, rtx operands
[], int *len
)
3362 if (GET_CODE (operands
[2]) == CONST_INT
)
3369 switch (INTVAL (operands
[2]))
3373 return AS1 (asr
,%0);
3377 return (AS1 (asr
,%0) CR_TAB
3382 return (AS1 (asr
,%0) CR_TAB
3388 return (AS1 (asr
,%0) CR_TAB
3395 return (AS1 (asr
,%0) CR_TAB
3403 return (AS2 (bst
,%0,6) CR_TAB
3405 AS2 (sbc
,%0,%0) CR_TAB
3409 if (INTVAL (operands
[2]) < 8)
3416 return (AS1 (lsl
,%0) CR_TAB
3420 else if (CONSTANT_P (operands
[2]))
3421 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
3423 out_shift_with_cnt (AS1 (asr
,%0),
3424 insn
, operands
, len
, 1);
3429 /* 16bit arithmetic shift right ((signed short)x >> i) */
3432 ashrhi3_out (rtx insn
, rtx operands
[], int *len
)
3434 if (GET_CODE (operands
[2]) == CONST_INT
)
3436 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
3437 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
3444 switch (INTVAL (operands
[2]))
3448 /* XXX try to optimize this too? */
3453 break; /* scratch ? 5 : 6 */
3455 return (AS2 (mov
,__tmp_reg__
,%A0
) CR_TAB
3456 AS2 (mov
,%A0
,%B0
) CR_TAB
3457 AS1 (lsl
,__tmp_reg__
) CR_TAB
3458 AS1 (rol
,%A0
) CR_TAB
3459 AS2 (sbc
,%B0
,%B0
) CR_TAB
3460 AS1 (lsl
,__tmp_reg__
) CR_TAB
3461 AS1 (rol
,%A0
) CR_TAB
3466 return (AS1 (lsl
,%A0
) CR_TAB
3467 AS2 (mov
,%A0
,%B0
) CR_TAB
3468 AS1 (rol
,%A0
) CR_TAB
3473 int reg0
= true_regnum (operands
[0]);
3474 int reg1
= true_regnum (operands
[1]);
3477 return *len
= 3, (AS2 (mov
,%A0
,%B0
) CR_TAB
3478 AS1 (lsl
,%B0
) CR_TAB
3481 return *len
= 4, (AS2 (mov
,%A0
,%B1
) CR_TAB
3482 AS1 (clr
,%B0
) CR_TAB
3483 AS2 (sbrc
,%A0
,7) CR_TAB
3489 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3490 AS1 (lsl
,%B0
) CR_TAB
3491 AS2 (sbc
,%B0
,%B0
) CR_TAB
3496 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3497 AS1 (lsl
,%B0
) CR_TAB
3498 AS2 (sbc
,%B0
,%B0
) CR_TAB
3499 AS1 (asr
,%A0
) CR_TAB
3503 if (AVR_HAVE_MUL
&& ldi_ok
)
3506 return (AS2 (ldi
,%A0
,0x20) CR_TAB
3507 AS2 (muls
,%B0
,%A0
) CR_TAB
3508 AS2 (mov
,%A0
,r1
) CR_TAB
3509 AS2 (sbc
,%B0
,%B0
) CR_TAB
3510 AS1 (clr
,__zero_reg__
));
3512 if (optimize_size
&& scratch
)
3515 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3516 AS1 (lsl
,%B0
) CR_TAB
3517 AS2 (sbc
,%B0
,%B0
) CR_TAB
3518 AS1 (asr
,%A0
) CR_TAB
3519 AS1 (asr
,%A0
) CR_TAB
3523 if (AVR_HAVE_MUL
&& ldi_ok
)
3526 return (AS2 (ldi
,%A0
,0x10) CR_TAB
3527 AS2 (muls
,%B0
,%A0
) CR_TAB
3528 AS2 (mov
,%A0
,r1
) CR_TAB
3529 AS2 (sbc
,%B0
,%B0
) CR_TAB
3530 AS1 (clr
,__zero_reg__
));
3532 if (optimize_size
&& scratch
)
3535 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3536 AS1 (lsl
,%B0
) CR_TAB
3537 AS2 (sbc
,%B0
,%B0
) CR_TAB
3538 AS1 (asr
,%A0
) CR_TAB
3539 AS1 (asr
,%A0
) CR_TAB
3540 AS1 (asr
,%A0
) CR_TAB
3544 if (AVR_HAVE_MUL
&& ldi_ok
)
3547 return (AS2 (ldi
,%A0
,0x08) CR_TAB
3548 AS2 (muls
,%B0
,%A0
) CR_TAB
3549 AS2 (mov
,%A0
,r1
) CR_TAB
3550 AS2 (sbc
,%B0
,%B0
) CR_TAB
3551 AS1 (clr
,__zero_reg__
));
3554 break; /* scratch ? 5 : 7 */
3556 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3557 AS1 (lsl
,%B0
) CR_TAB
3558 AS2 (sbc
,%B0
,%B0
) CR_TAB
3559 AS1 (asr
,%A0
) CR_TAB
3560 AS1 (asr
,%A0
) CR_TAB
3561 AS1 (asr
,%A0
) CR_TAB
3562 AS1 (asr
,%A0
) CR_TAB
3567 return (AS1 (lsl
,%B0
) CR_TAB
3568 AS2 (sbc
,%A0
,%A0
) CR_TAB
3569 AS1 (lsl
,%B0
) CR_TAB
3570 AS2 (mov
,%B0
,%A0
) CR_TAB
3574 if (INTVAL (operands
[2]) < 16)
3580 return *len
= 3, (AS1 (lsl
,%B0
) CR_TAB
3581 AS2 (sbc
,%A0
,%A0
) CR_TAB
3586 out_shift_with_cnt ((AS1 (asr
,%B0
) CR_TAB
3588 insn
, operands
, len
, 2);
3593 /* 32bit arithmetic shift right ((signed long)x >> i) */
3596 ashrsi3_out (rtx insn
, rtx operands
[], int *len
)
3598 if (GET_CODE (operands
[2]) == CONST_INT
)
3606 switch (INTVAL (operands
[2]))
3610 int reg0
= true_regnum (operands
[0]);
3611 int reg1
= true_regnum (operands
[1]);
3614 return (AS2 (mov
,%A0
,%B1
) CR_TAB
3615 AS2 (mov
,%B0
,%C1
) CR_TAB
3616 AS2 (mov
,%C0
,%D1
) CR_TAB
3617 AS1 (clr
,%D0
) CR_TAB
3618 AS2 (sbrc
,%C0
,7) CR_TAB
3621 return (AS1 (clr
,%D0
) CR_TAB
3622 AS2 (sbrc
,%D1
,7) CR_TAB
3623 AS1 (dec
,%D0
) CR_TAB
3624 AS2 (mov
,%C0
,%D1
) CR_TAB
3625 AS2 (mov
,%B0
,%C1
) CR_TAB
3631 int reg0
= true_regnum (operands
[0]);
3632 int reg1
= true_regnum (operands
[1]);
3634 if (reg0
== reg1
+ 2)
3635 return *len
= 4, (AS1 (clr
,%D0
) CR_TAB
3636 AS2 (sbrc
,%B0
,7) CR_TAB
3637 AS1 (com
,%D0
) CR_TAB
3640 return *len
= 5, (AS2 (movw
,%A0
,%C1
) CR_TAB
3641 AS1 (clr
,%D0
) CR_TAB
3642 AS2 (sbrc
,%B0
,7) CR_TAB
3643 AS1 (com
,%D0
) CR_TAB
3646 return *len
= 6, (AS2 (mov
,%B0
,%D1
) CR_TAB
3647 AS2 (mov
,%A0
,%C1
) CR_TAB
3648 AS1 (clr
,%D0
) CR_TAB
3649 AS2 (sbrc
,%B0
,7) CR_TAB
3650 AS1 (com
,%D0
) CR_TAB
3655 return *len
= 6, (AS2 (mov
,%A0
,%D1
) CR_TAB
3656 AS1 (clr
,%D0
) CR_TAB
3657 AS2 (sbrc
,%A0
,7) CR_TAB
3658 AS1 (com
,%D0
) CR_TAB
3659 AS2 (mov
,%B0
,%D0
) CR_TAB
3663 if (INTVAL (operands
[2]) < 32)
3670 return *len
= 4, (AS1 (lsl
,%D0
) CR_TAB
3671 AS2 (sbc
,%A0
,%A0
) CR_TAB
3672 AS2 (mov
,%B0
,%A0
) CR_TAB
3673 AS2 (movw
,%C0
,%A0
));
3675 return *len
= 5, (AS1 (lsl
,%D0
) CR_TAB
3676 AS2 (sbc
,%A0
,%A0
) CR_TAB
3677 AS2 (mov
,%B0
,%A0
) CR_TAB
3678 AS2 (mov
,%C0
,%A0
) CR_TAB
3683 out_shift_with_cnt ((AS1 (asr
,%D0
) CR_TAB
3684 AS1 (ror
,%C0
) CR_TAB
3685 AS1 (ror
,%B0
) CR_TAB
3687 insn
, operands
, len
, 4);
3691 /* 8bit logic shift right ((unsigned char)x >> i) */
3694 lshrqi3_out (rtx insn
, rtx operands
[], int *len
)
3696 if (GET_CODE (operands
[2]) == CONST_INT
)
3703 switch (INTVAL (operands
[2]))
3706 if (INTVAL (operands
[2]) < 8)
3710 return AS1 (clr
,%0);
3714 return AS1 (lsr
,%0);
3718 return (AS1 (lsr
,%0) CR_TAB
3722 return (AS1 (lsr
,%0) CR_TAB
3727 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3730 return (AS1 (swap
,%0) CR_TAB
3731 AS2 (andi
,%0,0x0f));
3734 return (AS1 (lsr
,%0) CR_TAB
3740 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3743 return (AS1 (swap
,%0) CR_TAB
3748 return (AS1 (lsr
,%0) CR_TAB
3755 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3758 return (AS1 (swap
,%0) CR_TAB
3764 return (AS1 (lsr
,%0) CR_TAB
3773 return (AS1 (rol
,%0) CR_TAB
3778 else if (CONSTANT_P (operands
[2]))
3779 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
3781 out_shift_with_cnt (AS1 (lsr
,%0),
3782 insn
, operands
, len
, 1);
3786 /* 16bit logic shift right ((unsigned short)x >> i) */
3789 lshrhi3_out (rtx insn
, rtx operands
[], int *len
)
3791 if (GET_CODE (operands
[2]) == CONST_INT
)
3793 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
3794 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
3801 switch (INTVAL (operands
[2]))
3804 if (INTVAL (operands
[2]) < 16)
3808 return (AS1 (clr
,%B0
) CR_TAB
3812 if (optimize_size
&& scratch
)
3817 return (AS1 (swap
,%B0
) CR_TAB
3818 AS1 (swap
,%A0
) CR_TAB
3819 AS2 (andi
,%A0
,0x0f) CR_TAB
3820 AS2 (eor
,%A0
,%B0
) CR_TAB
3821 AS2 (andi
,%B0
,0x0f) CR_TAB
3827 return (AS1 (swap
,%B0
) CR_TAB
3828 AS1 (swap
,%A0
) CR_TAB
3829 AS2 (ldi
,%3,0x0f) CR_TAB
3830 AS2 (and,%A0
,%3) CR_TAB
3831 AS2 (eor
,%A0
,%B0
) CR_TAB
3832 AS2 (and,%B0
,%3) CR_TAB
3835 break; /* optimize_size ? 6 : 8 */
3839 break; /* scratch ? 5 : 6 */
3843 return (AS1 (lsr
,%B0
) CR_TAB
3844 AS1 (ror
,%A0
) CR_TAB
3845 AS1 (swap
,%B0
) CR_TAB
3846 AS1 (swap
,%A0
) CR_TAB
3847 AS2 (andi
,%A0
,0x0f) CR_TAB
3848 AS2 (eor
,%A0
,%B0
) CR_TAB
3849 AS2 (andi
,%B0
,0x0f) CR_TAB
3855 return (AS1 (lsr
,%B0
) CR_TAB
3856 AS1 (ror
,%A0
) CR_TAB
3857 AS1 (swap
,%B0
) CR_TAB
3858 AS1 (swap
,%A0
) CR_TAB
3859 AS2 (ldi
,%3,0x0f) CR_TAB
3860 AS2 (and,%A0
,%3) CR_TAB
3861 AS2 (eor
,%A0
,%B0
) CR_TAB
3862 AS2 (and,%B0
,%3) CR_TAB
3869 break; /* scratch ? 5 : 6 */
3871 return (AS1 (clr
,__tmp_reg__
) CR_TAB
3872 AS1 (lsl
,%A0
) CR_TAB
3873 AS1 (rol
,%B0
) CR_TAB
3874 AS1 (rol
,__tmp_reg__
) CR_TAB
3875 AS1 (lsl
,%A0
) CR_TAB
3876 AS1 (rol
,%B0
) CR_TAB
3877 AS1 (rol
,__tmp_reg__
) CR_TAB
3878 AS2 (mov
,%A0
,%B0
) CR_TAB
3879 AS2 (mov
,%B0
,__tmp_reg__
));
3883 return (AS1 (lsl
,%A0
) CR_TAB
3884 AS2 (mov
,%A0
,%B0
) CR_TAB
3885 AS1 (rol
,%A0
) CR_TAB
3886 AS2 (sbc
,%B0
,%B0
) CR_TAB
3890 return *len
= 2, (AS2 (mov
,%A0
,%B1
) CR_TAB
3895 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3896 AS1 (clr
,%B0
) CR_TAB
3901 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3902 AS1 (clr
,%B0
) CR_TAB
3903 AS1 (lsr
,%A0
) CR_TAB
3908 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3909 AS1 (clr
,%B0
) CR_TAB
3910 AS1 (lsr
,%A0
) CR_TAB
3911 AS1 (lsr
,%A0
) CR_TAB
3918 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3919 AS1 (clr
,%B0
) CR_TAB
3920 AS1 (swap
,%A0
) CR_TAB
3921 AS2 (andi
,%A0
,0x0f));
3926 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3927 AS1 (clr
,%B0
) CR_TAB
3928 AS1 (swap
,%A0
) CR_TAB
3929 AS2 (ldi
,%3,0x0f) CR_TAB
3933 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3934 AS1 (clr
,%B0
) CR_TAB
3935 AS1 (lsr
,%A0
) CR_TAB
3936 AS1 (lsr
,%A0
) CR_TAB
3937 AS1 (lsr
,%A0
) CR_TAB
3944 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3945 AS1 (clr
,%B0
) CR_TAB
3946 AS1 (swap
,%A0
) CR_TAB
3947 AS1 (lsr
,%A0
) CR_TAB
3948 AS2 (andi
,%A0
,0x07));
3950 if (AVR_HAVE_MUL
&& scratch
)
3953 return (AS2 (ldi
,%3,0x08) CR_TAB
3954 AS2 (mul
,%B0
,%3) CR_TAB
3955 AS2 (mov
,%A0
,r1
) CR_TAB
3956 AS1 (clr
,%B0
) CR_TAB
3957 AS1 (clr
,__zero_reg__
));
3959 if (optimize_size
&& scratch
)
3964 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3965 AS1 (clr
,%B0
) CR_TAB
3966 AS1 (swap
,%A0
) CR_TAB
3967 AS1 (lsr
,%A0
) CR_TAB
3968 AS2 (ldi
,%3,0x07) CR_TAB
3974 return ("set" CR_TAB
3975 AS2 (bld
,r1
,3) CR_TAB
3976 AS2 (mul
,%B0
,r1
) CR_TAB
3977 AS2 (mov
,%A0
,r1
) CR_TAB
3978 AS1 (clr
,%B0
) CR_TAB
3979 AS1 (clr
,__zero_reg__
));
3982 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3983 AS1 (clr
,%B0
) CR_TAB
3984 AS1 (lsr
,%A0
) CR_TAB
3985 AS1 (lsr
,%A0
) CR_TAB
3986 AS1 (lsr
,%A0
) CR_TAB
3987 AS1 (lsr
,%A0
) CR_TAB
3991 if (AVR_HAVE_MUL
&& ldi_ok
)
3994 return (AS2 (ldi
,%A0
,0x04) CR_TAB
3995 AS2 (mul
,%B0
,%A0
) CR_TAB
3996 AS2 (mov
,%A0
,r1
) CR_TAB
3997 AS1 (clr
,%B0
) CR_TAB
3998 AS1 (clr
,__zero_reg__
));
4000 if (AVR_HAVE_MUL
&& scratch
)
4003 return (AS2 (ldi
,%3,0x04) CR_TAB
4004 AS2 (mul
,%B0
,%3) CR_TAB
4005 AS2 (mov
,%A0
,r1
) CR_TAB
4006 AS1 (clr
,%B0
) CR_TAB
4007 AS1 (clr
,__zero_reg__
));
4009 if (optimize_size
&& ldi_ok
)
4012 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4013 AS2 (ldi
,%B0
,6) "\n1:\t"
4014 AS1 (lsr
,%A0
) CR_TAB
4015 AS1 (dec
,%B0
) CR_TAB
4018 if (optimize_size
&& scratch
)
4021 return (AS1 (clr
,%A0
) CR_TAB
4022 AS1 (lsl
,%B0
) CR_TAB
4023 AS1 (rol
,%A0
) CR_TAB
4024 AS1 (lsl
,%B0
) CR_TAB
4025 AS1 (rol
,%A0
) CR_TAB
4030 return (AS1 (clr
,%A0
) CR_TAB
4031 AS1 (lsl
,%B0
) CR_TAB
4032 AS1 (rol
,%A0
) CR_TAB
4037 out_shift_with_cnt ((AS1 (lsr
,%B0
) CR_TAB
4039 insn
, operands
, len
, 2);
4043 /* 32bit logic shift right ((unsigned int)x >> i) */
4046 lshrsi3_out (rtx insn
, rtx operands
[], int *len
)
4048 if (GET_CODE (operands
[2]) == CONST_INT
)
4056 switch (INTVAL (operands
[2]))
4059 if (INTVAL (operands
[2]) < 32)
4063 return *len
= 3, (AS1 (clr
,%D0
) CR_TAB
4064 AS1 (clr
,%C0
) CR_TAB
4065 AS2 (movw
,%A0
,%C0
));
4067 return (AS1 (clr
,%D0
) CR_TAB
4068 AS1 (clr
,%C0
) CR_TAB
4069 AS1 (clr
,%B0
) CR_TAB
4074 int reg0
= true_regnum (operands
[0]);
4075 int reg1
= true_regnum (operands
[1]);
4078 return (AS2 (mov
,%A0
,%B1
) CR_TAB
4079 AS2 (mov
,%B0
,%C1
) CR_TAB
4080 AS2 (mov
,%C0
,%D1
) CR_TAB
4083 return (AS1 (clr
,%D0
) CR_TAB
4084 AS2 (mov
,%C0
,%D1
) CR_TAB
4085 AS2 (mov
,%B0
,%C1
) CR_TAB
4091 int reg0
= true_regnum (operands
[0]);
4092 int reg1
= true_regnum (operands
[1]);
4094 if (reg0
== reg1
+ 2)
4095 return *len
= 2, (AS1 (clr
,%C0
) CR_TAB
4098 return *len
= 3, (AS2 (movw
,%A0
,%C1
) CR_TAB
4099 AS1 (clr
,%C0
) CR_TAB
4102 return *len
= 4, (AS2 (mov
,%B0
,%D1
) CR_TAB
4103 AS2 (mov
,%A0
,%C1
) CR_TAB
4104 AS1 (clr
,%C0
) CR_TAB
4109 return *len
= 4, (AS2 (mov
,%A0
,%D1
) CR_TAB
4110 AS1 (clr
,%B0
) CR_TAB
4111 AS1 (clr
,%C0
) CR_TAB
4116 return (AS1 (clr
,%A0
) CR_TAB
4117 AS2 (sbrc
,%D0
,7) CR_TAB
4118 AS1 (inc
,%A0
) CR_TAB
4119 AS1 (clr
,%B0
) CR_TAB
4120 AS1 (clr
,%C0
) CR_TAB
4125 out_shift_with_cnt ((AS1 (lsr
,%D0
) CR_TAB
4126 AS1 (ror
,%C0
) CR_TAB
4127 AS1 (ror
,%B0
) CR_TAB
4129 insn
, operands
, len
, 4);
4133 /* Modifies the length assigned to instruction INSN
4134 LEN is the initially computed length of the insn. */
4137 adjust_insn_length (rtx insn
, int len
)
4139 rtx patt
= PATTERN (insn
);
4142 if (GET_CODE (patt
) == SET
)
4145 op
[1] = SET_SRC (patt
);
4146 op
[0] = SET_DEST (patt
);
4147 if (general_operand (op
[1], VOIDmode
)
4148 && general_operand (op
[0], VOIDmode
))
4150 switch (GET_MODE (op
[0]))
4153 output_movqi (insn
, op
, &len
);
4156 output_movhi (insn
, op
, &len
);
4160 output_movsisf (insn
, op
, &len
);
4166 else if (op
[0] == cc0_rtx
&& REG_P (op
[1]))
4168 switch (GET_MODE (op
[1]))
4170 case HImode
: out_tsthi (insn
,&len
); break;
4171 case SImode
: out_tstsi (insn
,&len
); break;
4175 else if (GET_CODE (op
[1]) == AND
)
4177 if (GET_CODE (XEXP (op
[1],1)) == CONST_INT
)
4179 HOST_WIDE_INT mask
= INTVAL (XEXP (op
[1],1));
4180 if (GET_MODE (op
[1]) == SImode
)
4181 len
= (((mask
& 0xff) != 0xff)
4182 + ((mask
& 0xff00) != 0xff00)
4183 + ((mask
& 0xff0000L
) != 0xff0000L
)
4184 + ((mask
& 0xff000000L
) != 0xff000000L
));
4185 else if (GET_MODE (op
[1]) == HImode
)
4186 len
= (((mask
& 0xff) != 0xff)
4187 + ((mask
& 0xff00) != 0xff00));
4190 else if (GET_CODE (op
[1]) == IOR
)
4192 if (GET_CODE (XEXP (op
[1],1)) == CONST_INT
)
4194 HOST_WIDE_INT mask
= INTVAL (XEXP (op
[1],1));
4195 if (GET_MODE (op
[1]) == SImode
)
4196 len
= (((mask
& 0xff) != 0)
4197 + ((mask
& 0xff00) != 0)
4198 + ((mask
& 0xff0000L
) != 0)
4199 + ((mask
& 0xff000000L
) != 0));
4200 else if (GET_MODE (op
[1]) == HImode
)
4201 len
= (((mask
& 0xff) != 0)
4202 + ((mask
& 0xff00) != 0));
4206 set
= single_set (insn
);
4211 op
[1] = SET_SRC (set
);
4212 op
[0] = SET_DEST (set
);
4214 if (GET_CODE (patt
) == PARALLEL
4215 && general_operand (op
[1], VOIDmode
)
4216 && general_operand (op
[0], VOIDmode
))
4218 if (XVECLEN (patt
, 0) == 2)
4219 op
[2] = XVECEXP (patt
, 0, 1);
4221 switch (GET_MODE (op
[0]))
4227 output_reload_inhi (insn
, op
, &len
);
4231 output_reload_insisf (insn
, op
, &len
);
4237 else if (GET_CODE (op
[1]) == ASHIFT
4238 || GET_CODE (op
[1]) == ASHIFTRT
4239 || GET_CODE (op
[1]) == LSHIFTRT
)
4243 ops
[1] = XEXP (op
[1],0);
4244 ops
[2] = XEXP (op
[1],1);
4245 switch (GET_CODE (op
[1]))
4248 switch (GET_MODE (op
[0]))
4250 case QImode
: ashlqi3_out (insn
,ops
,&len
); break;
4251 case HImode
: ashlhi3_out (insn
,ops
,&len
); break;
4252 case SImode
: ashlsi3_out (insn
,ops
,&len
); break;
4257 switch (GET_MODE (op
[0]))
4259 case QImode
: ashrqi3_out (insn
,ops
,&len
); break;
4260 case HImode
: ashrhi3_out (insn
,ops
,&len
); break;
4261 case SImode
: ashrsi3_out (insn
,ops
,&len
); break;
4266 switch (GET_MODE (op
[0]))
4268 case QImode
: lshrqi3_out (insn
,ops
,&len
); break;
4269 case HImode
: lshrhi3_out (insn
,ops
,&len
); break;
4270 case SImode
: lshrsi3_out (insn
,ops
,&len
); break;
4282 /* Return nonzero if register REG dead after INSN. */
4285 reg_unused_after (rtx insn
, rtx reg
)
4287 return (dead_or_set_p (insn
, reg
)
4288 || (REG_P(reg
) && _reg_unused_after (insn
, reg
)));
4291 /* Return nonzero if REG is not used after INSN.
4292 We assume REG is a reload reg, and therefore does
4293 not live past labels. It may live past calls or jumps though. */
4296 _reg_unused_after (rtx insn
, rtx reg
)
4301 /* If the reg is set by this instruction, then it is safe for our
4302 case. Disregard the case where this is a store to memory, since
4303 we are checking a register used in the store address. */
4304 set
= single_set (insn
);
4305 if (set
&& GET_CODE (SET_DEST (set
)) != MEM
4306 && reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
4309 while ((insn
= NEXT_INSN (insn
)))
4312 code
= GET_CODE (insn
);
4315 /* If this is a label that existed before reload, then the register
4316 if dead here. However, if this is a label added by reorg, then
4317 the register may still be live here. We can't tell the difference,
4318 so we just ignore labels completely. */
4319 if (code
== CODE_LABEL
)
4327 if (code
== JUMP_INSN
)
4330 /* If this is a sequence, we must handle them all at once.
4331 We could have for instance a call that sets the target register,
4332 and an insn in a delay slot that uses the register. In this case,
4333 we must return 0. */
4334 else if (code
== INSN
&& GET_CODE (PATTERN (insn
)) == SEQUENCE
)
4339 for (i
= 0; i
< XVECLEN (PATTERN (insn
), 0); i
++)
4341 rtx this_insn
= XVECEXP (PATTERN (insn
), 0, i
);
4342 rtx set
= single_set (this_insn
);
4344 if (GET_CODE (this_insn
) == CALL_INSN
)
4346 else if (GET_CODE (this_insn
) == JUMP_INSN
)
4348 if (INSN_ANNULLED_BRANCH_P (this_insn
))
4353 if (set
&& reg_overlap_mentioned_p (reg
, SET_SRC (set
)))
4355 if (set
&& reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
4357 if (GET_CODE (SET_DEST (set
)) != MEM
)
4363 && reg_overlap_mentioned_p (reg
, PATTERN (this_insn
)))
4368 else if (code
== JUMP_INSN
)
4372 if (code
== CALL_INSN
)
4375 for (tem
= CALL_INSN_FUNCTION_USAGE (insn
); tem
; tem
= XEXP (tem
, 1))
4376 if (GET_CODE (XEXP (tem
, 0)) == USE
4377 && REG_P (XEXP (XEXP (tem
, 0), 0))
4378 && reg_overlap_mentioned_p (reg
, XEXP (XEXP (tem
, 0), 0)))
4380 if (call_used_regs
[REGNO (reg
)])
4384 set
= single_set (insn
);
4386 if (set
&& reg_overlap_mentioned_p (reg
, SET_SRC (set
)))
4388 if (set
&& reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
4389 return GET_CODE (SET_DEST (set
)) != MEM
;
4390 if (set
== 0 && reg_overlap_mentioned_p (reg
, PATTERN (insn
)))
4396 /* Target hook for assembling integer objects. The AVR version needs
4397 special handling for references to certain labels. */
4400 avr_assemble_integer (rtx x
, unsigned int size
, int aligned_p
)
4402 if (size
== POINTER_SIZE
/ BITS_PER_UNIT
&& aligned_p
4403 && ((GET_CODE (x
) == SYMBOL_REF
&& SYMBOL_REF_FUNCTION_P (x
))
4404 || GET_CODE (x
) == LABEL_REF
))
4406 fputs ("\t.word\tpm(", asm_out_file
);
4407 output_addr_const (asm_out_file
, x
);
4408 fputs (")\n", asm_out_file
);
4411 return default_assemble_integer (x
, size
, aligned_p
);
4414 /* The routine used to output NUL terminated strings. We use a special
4415 version of this for most svr4 targets because doing so makes the
4416 generated assembly code more compact (and thus faster to assemble)
4417 as well as more readable, especially for targets like the i386
4418 (where the only alternative is to output character sequences as
4419 comma separated lists of numbers). */
4422 gas_output_limited_string(FILE *file
, const char *str
)
4424 const unsigned char *_limited_str
= (unsigned char *) str
;
4426 fprintf (file
, "%s\"", STRING_ASM_OP
);
4427 for (; (ch
= *_limited_str
); _limited_str
++)
4430 switch (escape
= ESCAPES
[ch
])
4436 fprintf (file
, "\\%03o", ch
);
4440 putc (escape
, file
);
4444 fprintf (file
, "\"\n");
4447 /* The routine used to output sequences of byte values. We use a special
4448 version of this for most svr4 targets because doing so makes the
4449 generated assembly code more compact (and thus faster to assemble)
4450 as well as more readable. Note that if we find subparts of the
4451 character sequence which end with NUL (and which are shorter than
4452 STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
4455 gas_output_ascii(FILE *file
, const char *str
, size_t length
)
4457 const unsigned char *_ascii_bytes
= (const unsigned char *) str
;
4458 const unsigned char *limit
= _ascii_bytes
+ length
;
4459 unsigned bytes_in_chunk
= 0;
4460 for (; _ascii_bytes
< limit
; _ascii_bytes
++)
4462 const unsigned char *p
;
4463 if (bytes_in_chunk
>= 60)
4465 fprintf (file
, "\"\n");
4468 for (p
= _ascii_bytes
; p
< limit
&& *p
!= '\0'; p
++)
4470 if (p
< limit
&& (p
- _ascii_bytes
) <= (signed)STRING_LIMIT
)
4472 if (bytes_in_chunk
> 0)
4474 fprintf (file
, "\"\n");
4477 gas_output_limited_string (file
, (char*)_ascii_bytes
);
4484 if (bytes_in_chunk
== 0)
4485 fprintf (file
, "\t.ascii\t\"");
4486 switch (escape
= ESCAPES
[ch
= *_ascii_bytes
])
4493 fprintf (file
, "\\%03o", ch
);
4494 bytes_in_chunk
+= 4;
4498 putc (escape
, file
);
4499 bytes_in_chunk
+= 2;
4504 if (bytes_in_chunk
> 0)
4505 fprintf (file
, "\"\n");
4508 /* Return value is nonzero if pseudos that have been
4509 assigned to registers of class CLASS would likely be spilled
4510 because registers of CLASS are needed for spill registers. */
4513 class_likely_spilled_p (int c
)
4515 return (c
!= ALL_REGS
&& c
!= ADDW_REGS
);
4518 /* Valid attributes:
4519 progmem - put data to program memory;
4520 signal - make a function to be hardware interrupt. After function
4521 prologue interrupts are disabled;
4522 interrupt - make a function to be hardware interrupt. After function
4523 prologue interrupts are enabled;
4524 naked - don't generate function prologue/epilogue and `ret' command.
4526 Only `progmem' attribute valid for type. */
4528 const struct attribute_spec avr_attribute_table
[] =
4530 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4531 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute
},
4532 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute
},
4533 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute
},
4534 { "naked", 0, 0, true, false, false, avr_handle_fndecl_attribute
},
4535 { NULL
, 0, 0, false, false, false, NULL
}
4538 /* Handle a "progmem" attribute; arguments as in
4539 struct attribute_spec.handler. */
4541 avr_handle_progmem_attribute (tree
*node
, tree name
,
4542 tree args ATTRIBUTE_UNUSED
,
4543 int flags ATTRIBUTE_UNUSED
,
4548 if (TREE_CODE (*node
) == TYPE_DECL
)
4550 /* This is really a decl attribute, not a type attribute,
4551 but try to handle it for GCC 3.0 backwards compatibility. */
4553 tree type
= TREE_TYPE (*node
);
4554 tree attr
= tree_cons (name
, args
, TYPE_ATTRIBUTES (type
));
4555 tree newtype
= build_type_attribute_variant (type
, attr
);
4557 TYPE_MAIN_VARIANT (newtype
) = TYPE_MAIN_VARIANT (type
);
4558 TREE_TYPE (*node
) = newtype
;
4559 *no_add_attrs
= true;
4561 else if (TREE_STATIC (*node
) || DECL_EXTERNAL (*node
))
4563 if (DECL_INITIAL (*node
) == NULL_TREE
&& !DECL_EXTERNAL (*node
))
4565 warning (0, "only initialized variables can be placed into "
4566 "program memory area");
4567 *no_add_attrs
= true;
4572 warning (OPT_Wattributes
, "%qs attribute ignored",
4573 IDENTIFIER_POINTER (name
));
4574 *no_add_attrs
= true;
4581 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4582 struct attribute_spec.handler. */
4585 avr_handle_fndecl_attribute (tree
*node
, tree name
,
4586 tree args ATTRIBUTE_UNUSED
,
4587 int flags ATTRIBUTE_UNUSED
,
4590 if (TREE_CODE (*node
) != FUNCTION_DECL
)
4592 warning (OPT_Wattributes
, "%qs attribute only applies to functions",
4593 IDENTIFIER_POINTER (name
));
4594 *no_add_attrs
= true;
4598 const char *func_name
= IDENTIFIER_POINTER (DECL_NAME (*node
));
4599 const char *attr
= IDENTIFIER_POINTER (name
);
4601 /* If the function has the 'signal' or 'interrupt' attribute, test to
4602 make sure that the name of the function is "__vector_NN" so as to
4603 catch when the user misspells the interrupt vector name. */
4605 if (strncmp (attr
, "interrupt", strlen ("interrupt")) == 0)
4607 if (strncmp (func_name
, "__vector", strlen ("__vector")) != 0)
4609 warning (0, "%qs appears to be a misspelled interrupt handler",
4613 else if (strncmp (attr
, "signal", strlen ("signal")) == 0)
4615 if (strncmp (func_name
, "__vector", strlen ("__vector")) != 0)
4617 warning (0, "%qs appears to be a misspelled signal handler",
4626 /* Look for attribute `progmem' in DECL
4627 if found return 1, otherwise 0. */
4630 avr_progmem_p (tree decl
, tree attributes
)
4634 if (TREE_CODE (decl
) != VAR_DECL
)
4638 != lookup_attribute ("progmem", attributes
))
4644 while (TREE_CODE (a
) == ARRAY_TYPE
);
4646 if (a
== error_mark_node
)
4649 if (NULL_TREE
!= lookup_attribute ("progmem", TYPE_ATTRIBUTES (a
)))
4655 /* Add the section attribute if the variable is in progmem. */
4658 avr_insert_attributes (tree node
, tree
*attributes
)
4660 if (TREE_CODE (node
) == VAR_DECL
4661 && (TREE_STATIC (node
) || DECL_EXTERNAL (node
))
4662 && avr_progmem_p (node
, *attributes
))
4664 static const char dsec
[] = ".progmem.data";
4665 *attributes
= tree_cons (get_identifier ("section"),
4666 build_tree_list (NULL
, build_string (strlen (dsec
), dsec
)),
4669 /* ??? This seems sketchy. Why can't the user declare the
4670 thing const in the first place? */
4671 TREE_READONLY (node
) = 1;
4675 /* A get_unnamed_section callback for switching to progmem_section. */
4678 avr_output_progmem_section_asm_op (const void *arg ATTRIBUTE_UNUSED
)
4680 fprintf (asm_out_file
,
4681 "\t.section .progmem.gcc_sw_table, \"%s\", @progbits\n",
4682 AVR_MEGA
? "a" : "ax");
4683 /* Should already be aligned, this is just to be safe if it isn't. */
4684 fprintf (asm_out_file
, "\t.p2align 1\n");
4687 /* Implement TARGET_ASM_INIT_SECTIONS. */
4690 avr_asm_init_sections (void)
4692 progmem_section
= get_unnamed_section (AVR_MEGA
? 0 : SECTION_CODE
,
4693 avr_output_progmem_section_asm_op
,
4695 readonly_data_section
= data_section
;
4699 avr_section_type_flags (tree decl
, const char *name
, int reloc
)
4701 unsigned int flags
= default_section_type_flags (decl
, name
, reloc
);
4703 if (strncmp (name
, ".noinit", 7) == 0)
4705 if (decl
&& TREE_CODE (decl
) == VAR_DECL
4706 && DECL_INITIAL (decl
) == NULL_TREE
)
4707 flags
|= SECTION_BSS
; /* @nobits */
4709 warning (0, "only uninitialized variables can be placed in the "
4716 /* Outputs some appropriate text to go at the start of an assembler
4720 avr_file_start (void)
4723 error ("MCU %qs supported for assembler only", avr_mcu_name
);
4725 default_file_start ();
4727 /* fprintf (asm_out_file, "\t.arch %s\n", avr_mcu_name);*/
4728 fputs ("__SREG__ = 0x3f\n"
4730 "__SP_L__ = 0x3d\n", asm_out_file
);
4732 fputs ("__tmp_reg__ = 0\n"
4733 "__zero_reg__ = 1\n", asm_out_file
);
4735 /* FIXME: output these only if there is anything in the .data / .bss
4736 sections - some code size could be saved by not linking in the
4737 initialization code from libgcc if one or both sections are empty. */
4738 fputs ("\t.global __do_copy_data\n", asm_out_file
);
4739 fputs ("\t.global __do_clear_bss\n", asm_out_file
);
4741 commands_in_file
= 0;
4742 commands_in_prologues
= 0;
4743 commands_in_epilogues
= 0;
4746 /* Outputs to the stdio stream FILE some
4747 appropriate text to go at the end of an assembler file. */
4752 fputs ("/* File ", asm_out_file
);
4753 output_quoted_string (asm_out_file
, main_input_filename
);
4754 fprintf (asm_out_file
,
4755 ": code %4d = 0x%04x (%4d), prologues %3d, epilogues %3d */\n",
4758 commands_in_file
- commands_in_prologues
- commands_in_epilogues
,
4759 commands_in_prologues
, commands_in_epilogues
);
4762 /* Choose the order in which to allocate hard registers for
4763 pseudo-registers local to a basic block.
4765 Store the desired register order in the array `reg_alloc_order'.
4766 Element 0 should be the register to allocate first; element 1, the
4767 next register; and so on. */
4770 order_regs_for_local_alloc (void)
4773 static const int order_0
[] = {
4781 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4785 static const int order_1
[] = {
4793 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4797 static const int order_2
[] = {
4806 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4811 const int *order
= (TARGET_ORDER_1
? order_1
:
4812 TARGET_ORDER_2
? order_2
:
4814 for (i
=0; i
< ARRAY_SIZE (order_0
); ++i
)
4815 reg_alloc_order
[i
] = order
[i
];
4819 /* Mutually recursive subroutine of avr_rtx_cost for calculating the
4820 cost of an RTX operand given its context. X is the rtx of the
4821 operand, MODE is its mode, and OUTER is the rtx_code of this
4822 operand's parent operator. */
4825 avr_operand_rtx_cost (rtx x
, enum machine_mode mode
, enum rtx_code outer
)
4827 enum rtx_code code
= GET_CODE (x
);
4838 return COSTS_N_INSNS (GET_MODE_SIZE (mode
));
4845 avr_rtx_costs (x
, code
, outer
, &total
);
4849 /* The AVR backend's rtx_cost function. X is rtx expression whose cost
4850 is to be calculated. Return true if the complete cost has been
4851 computed, and false if subexpressions should be scanned. In either
4852 case, *TOTAL contains the cost result. */
4855 avr_rtx_costs (rtx x
, int code
, int outer_code ATTRIBUTE_UNUSED
, int *total
)
4857 enum machine_mode mode
= GET_MODE (x
);
4864 /* Immediate constants are as cheap as registers. */
4872 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
4880 *total
= COSTS_N_INSNS (1);
4884 *total
= COSTS_N_INSNS (3);
4888 *total
= COSTS_N_INSNS (7);
4894 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
4902 *total
= COSTS_N_INSNS (1);
4908 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
4912 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
4913 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
4917 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
)
4918 - GET_MODE_SIZE (GET_MODE (XEXP (x
, 0))));
4919 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
4923 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
) + 2
4924 - GET_MODE_SIZE (GET_MODE (XEXP (x
, 0))));
4925 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
4932 *total
= COSTS_N_INSNS (1);
4933 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
4934 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
4938 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
4940 *total
= COSTS_N_INSNS (2);
4941 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
4943 else if (INTVAL (XEXP (x
, 1)) >= -63 && INTVAL (XEXP (x
, 1)) <= 63)
4944 *total
= COSTS_N_INSNS (1);
4946 *total
= COSTS_N_INSNS (2);
4950 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
4952 *total
= COSTS_N_INSNS (4);
4953 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
4955 else if (INTVAL (XEXP (x
, 1)) >= -63 && INTVAL (XEXP (x
, 1)) <= 63)
4956 *total
= COSTS_N_INSNS (1);
4958 *total
= COSTS_N_INSNS (4);
4964 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
4970 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
4971 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
4972 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
4973 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
4977 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
4978 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
4979 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
4987 *total
= COSTS_N_INSNS (optimize_size
? 3 : 4);
4988 else if (optimize_size
)
4989 *total
= COSTS_N_INSNS (AVR_MEGA
? 2 : 1);
4995 *total
= COSTS_N_INSNS (optimize_size
? 7 : 10);
4996 else if (optimize_size
)
4997 *total
= COSTS_N_INSNS (AVR_MEGA
? 2 : 1);
5004 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5005 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5013 *total
= COSTS_N_INSNS (AVR_MEGA
? 2 : 1);
5016 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5017 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5024 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5026 *total
= COSTS_N_INSNS (optimize_size
? 4 : 17);
5027 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5031 val
= INTVAL (XEXP (x
, 1));
5033 *total
= COSTS_N_INSNS (3);
5034 else if (val
>= 0 && val
<= 7)
5035 *total
= COSTS_N_INSNS (val
);
5037 *total
= COSTS_N_INSNS (1);
5042 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5044 *total
= COSTS_N_INSNS (optimize_size
? 5 : 41);
5045 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5048 switch (INTVAL (XEXP (x
, 1)))
5055 *total
= COSTS_N_INSNS (2);
5058 *total
= COSTS_N_INSNS (3);
5064 *total
= COSTS_N_INSNS (4);
5069 *total
= COSTS_N_INSNS (5);
5072 *total
= COSTS_N_INSNS (optimize_size
? 5 : 8);
5075 *total
= COSTS_N_INSNS (optimize_size
? 5 : 9);
5078 *total
= COSTS_N_INSNS (optimize_size
? 5 : 10);
5081 *total
= COSTS_N_INSNS (optimize_size
? 5 : 41);
5082 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5087 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5089 *total
= COSTS_N_INSNS (optimize_size
? 7 : 113);
5090 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5093 switch (INTVAL (XEXP (x
, 1)))
5099 *total
= COSTS_N_INSNS (3);
5104 *total
= COSTS_N_INSNS (4);
5107 *total
= COSTS_N_INSNS (6);
5110 *total
= COSTS_N_INSNS (optimize_size
? 7 : 8);
5113 *total
= COSTS_N_INSNS (optimize_size
? 7 : 113);
5114 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5121 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5128 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5130 *total
= COSTS_N_INSNS (optimize_size
? 4 : 17);
5131 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5135 val
= INTVAL (XEXP (x
, 1));
5137 *total
= COSTS_N_INSNS (4);
5139 *total
= COSTS_N_INSNS (2);
5140 else if (val
>= 0 && val
<= 7)
5141 *total
= COSTS_N_INSNS (val
);
5143 *total
= COSTS_N_INSNS (1);
5148 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5150 *total
= COSTS_N_INSNS (optimize_size
? 5 : 41);
5151 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5154 switch (INTVAL (XEXP (x
, 1)))
5160 *total
= COSTS_N_INSNS (2);
5163 *total
= COSTS_N_INSNS (3);
5169 *total
= COSTS_N_INSNS (4);
5173 *total
= COSTS_N_INSNS (5);
5176 *total
= COSTS_N_INSNS (optimize_size
? 5 : 6);
5179 *total
= COSTS_N_INSNS (optimize_size
? 5 : 7);
5183 *total
= COSTS_N_INSNS (optimize_size
? 5 : 8);
5186 *total
= COSTS_N_INSNS (optimize_size
? 5 : 41);
5187 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5192 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5194 *total
= COSTS_N_INSNS (optimize_size
? 7 : 113);
5195 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5198 switch (INTVAL (XEXP (x
, 1)))
5204 *total
= COSTS_N_INSNS (4);
5209 *total
= COSTS_N_INSNS (6);
5212 *total
= COSTS_N_INSNS (optimize_size
? 7 : 8);
5215 *total
= COSTS_N_INSNS (AVR_HAVE_MOVW
? 4 : 5);
5218 *total
= COSTS_N_INSNS (optimize_size
? 7 : 113);
5219 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5226 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5233 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5235 *total
= COSTS_N_INSNS (optimize_size
? 4 : 17);
5236 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5240 val
= INTVAL (XEXP (x
, 1));
5242 *total
= COSTS_N_INSNS (3);
5243 else if (val
>= 0 && val
<= 7)
5244 *total
= COSTS_N_INSNS (val
);
5246 *total
= COSTS_N_INSNS (1);
5251 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5253 *total
= COSTS_N_INSNS (optimize_size
? 5 : 41);
5254 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5257 switch (INTVAL (XEXP (x
, 1)))
5264 *total
= COSTS_N_INSNS (2);
5267 *total
= COSTS_N_INSNS (3);
5272 *total
= COSTS_N_INSNS (4);
5276 *total
= COSTS_N_INSNS (5);
5282 *total
= COSTS_N_INSNS (optimize_size
? 5 : 6);
5285 *total
= COSTS_N_INSNS (optimize_size
? 5 : 7);
5289 *total
= COSTS_N_INSNS (optimize_size
? 5 : 9);
5292 *total
= COSTS_N_INSNS (optimize_size
? 5 : 41);
5293 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5298 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5300 *total
= COSTS_N_INSNS (optimize_size
? 7 : 113);
5301 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5304 switch (INTVAL (XEXP (x
, 1)))
5310 *total
= COSTS_N_INSNS (4);
5313 *total
= COSTS_N_INSNS (optimize_size
? 7 : 8);
5318 *total
= COSTS_N_INSNS (4);
5321 *total
= COSTS_N_INSNS (6);
5324 *total
= COSTS_N_INSNS (optimize_size
? 7 : 113);
5325 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5332 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5336 switch (GET_MODE (XEXP (x
, 0)))
5339 *total
= COSTS_N_INSNS (1);
5340 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5341 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5345 *total
= COSTS_N_INSNS (2);
5346 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5347 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5348 else if (INTVAL (XEXP (x
, 1)) != 0)
5349 *total
+= COSTS_N_INSNS (1);
5353 *total
= COSTS_N_INSNS (4);
5354 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5355 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5356 else if (INTVAL (XEXP (x
, 1)) != 0)
5357 *total
+= COSTS_N_INSNS (3);
5363 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5372 /* Calculate the cost of a memory address. */
5375 avr_address_cost (rtx x
)
5377 if (GET_CODE (x
) == PLUS
5378 && GET_CODE (XEXP (x
,1)) == CONST_INT
5379 && (REG_P (XEXP (x
,0)) || GET_CODE (XEXP (x
,0)) == SUBREG
)
5380 && INTVAL (XEXP (x
,1)) >= 61)
5382 if (CONSTANT_ADDRESS_P (x
))
5384 if (avr_io_address_p (x
, 1))
5391 /* Test for extra memory constraint 'Q'.
5392 It's a memory address based on Y or Z pointer with valid displacement. */
5395 extra_constraint_Q (rtx x
)
5397 if (GET_CODE (XEXP (x
,0)) == PLUS
5398 && REG_P (XEXP (XEXP (x
,0), 0))
5399 && GET_CODE (XEXP (XEXP (x
,0), 1)) == CONST_INT
5400 && (INTVAL (XEXP (XEXP (x
,0), 1))
5401 <= MAX_LD_OFFSET (GET_MODE (x
))))
5403 rtx xx
= XEXP (XEXP (x
,0), 0);
5404 int regno
= REGNO (xx
);
5405 if (TARGET_ALL_DEBUG
)
5407 fprintf (stderr
, ("extra_constraint:\n"
5408 "reload_completed: %d\n"
5409 "reload_in_progress: %d\n"),
5410 reload_completed
, reload_in_progress
);
5413 if (regno
>= FIRST_PSEUDO_REGISTER
)
5414 return 1; /* allocate pseudos */
5415 else if (regno
== REG_Z
|| regno
== REG_Y
)
5416 return 1; /* strictly check */
5417 else if (xx
== frame_pointer_rtx
5418 || xx
== arg_pointer_rtx
)
5419 return 1; /* XXX frame & arg pointer checks */
5424 /* Convert condition code CONDITION to the valid AVR condition code. */
5427 avr_normalize_condition (RTX_CODE condition
)
5444 /* This function optimizes conditional jumps. */
5451 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
5453 if (! (GET_CODE (insn
) == INSN
5454 || GET_CODE (insn
) == CALL_INSN
5455 || GET_CODE (insn
) == JUMP_INSN
)
5456 || !single_set (insn
))
5459 pattern
= PATTERN (insn
);
5461 if (GET_CODE (pattern
) == PARALLEL
)
5462 pattern
= XVECEXP (pattern
, 0, 0);
5463 if (GET_CODE (pattern
) == SET
5464 && SET_DEST (pattern
) == cc0_rtx
5465 && compare_diff_p (insn
))
5467 if (GET_CODE (SET_SRC (pattern
)) == COMPARE
)
5469 /* Now we work under compare insn. */
5471 pattern
= SET_SRC (pattern
);
5472 if (true_regnum (XEXP (pattern
,0)) >= 0
5473 && true_regnum (XEXP (pattern
,1)) >= 0 )
5475 rtx x
= XEXP (pattern
,0);
5476 rtx next
= next_real_insn (insn
);
5477 rtx pat
= PATTERN (next
);
5478 rtx src
= SET_SRC (pat
);
5479 rtx t
= XEXP (src
,0);
5480 PUT_CODE (t
, swap_condition (GET_CODE (t
)));
5481 XEXP (pattern
,0) = XEXP (pattern
,1);
5482 XEXP (pattern
,1) = x
;
5483 INSN_CODE (next
) = -1;
5485 else if (true_regnum (XEXP (pattern
,0)) >= 0
5486 && GET_CODE (XEXP (pattern
,1)) == CONST_INT
)
5488 rtx x
= XEXP (pattern
,1);
5489 rtx next
= next_real_insn (insn
);
5490 rtx pat
= PATTERN (next
);
5491 rtx src
= SET_SRC (pat
);
5492 rtx t
= XEXP (src
,0);
5493 enum machine_mode mode
= GET_MODE (XEXP (pattern
, 0));
5495 if (avr_simplify_comparison_p (mode
, GET_CODE (t
), x
))
5497 XEXP (pattern
, 1) = gen_int_mode (INTVAL (x
) + 1, mode
);
5498 PUT_CODE (t
, avr_normalize_condition (GET_CODE (t
)));
5499 INSN_CODE (next
) = -1;
5500 INSN_CODE (insn
) = -1;
5504 else if (true_regnum (SET_SRC (pattern
)) >= 0)
5506 /* This is a tst insn */
5507 rtx next
= next_real_insn (insn
);
5508 rtx pat
= PATTERN (next
);
5509 rtx src
= SET_SRC (pat
);
5510 rtx t
= XEXP (src
,0);
5512 PUT_CODE (t
, swap_condition (GET_CODE (t
)));
5513 SET_SRC (pattern
) = gen_rtx_NEG (GET_MODE (SET_SRC (pattern
)),
5515 INSN_CODE (next
) = -1;
5516 INSN_CODE (insn
) = -1;
5522 /* Returns register number for function return value.*/
5525 avr_ret_register (void)
5530 /* Ceate an RTX representing the place where a
5531 library function returns a value of mode MODE. */
5534 avr_libcall_value (enum machine_mode mode
)
5536 int offs
= GET_MODE_SIZE (mode
);
5539 return gen_rtx_REG (mode
, RET_REGISTER
+ 2 - offs
);
5542 /* Create an RTX representing the place where a
5543 function returns a value of data type VALTYPE. */
5546 avr_function_value (tree type
, tree func ATTRIBUTE_UNUSED
)
5550 if (TYPE_MODE (type
) != BLKmode
)
5551 return avr_libcall_value (TYPE_MODE (type
));
5553 offs
= int_size_in_bytes (type
);
5556 if (offs
> 2 && offs
< GET_MODE_SIZE (SImode
))
5557 offs
= GET_MODE_SIZE (SImode
);
5558 else if (offs
> GET_MODE_SIZE (SImode
) && offs
< GET_MODE_SIZE (DImode
))
5559 offs
= GET_MODE_SIZE (DImode
);
5561 return gen_rtx_REG (BLKmode
, RET_REGISTER
+ 2 - offs
);
5564 /* Places additional restrictions on the register class to
5565 use when it is necessary to copy value X into a register
5569 preferred_reload_class (rtx x ATTRIBUTE_UNUSED
, enum reg_class
class)
5575 test_hard_reg_class (enum reg_class
class, rtx x
)
5577 int regno
= true_regnum (x
);
5581 if (TEST_HARD_REG_CLASS (class, regno
))
5589 jump_over_one_insn_p (rtx insn
, rtx dest
)
5591 int uid
= INSN_UID (GET_CODE (dest
) == LABEL_REF
5594 int jump_addr
= INSN_ADDRESSES (INSN_UID (insn
));
5595 int dest_addr
= INSN_ADDRESSES (uid
);
5596 return dest_addr
- jump_addr
== get_attr_length (insn
) + 1;
5599 /* Returns 1 if a value of mode MODE can be stored starting with hard
5600 register number REGNO. On the enhanced core, anything larger than
5601 1 byte must start in even numbered register for "movw" to work
5602 (this way we don't have to check for odd registers everywhere). */
5605 avr_hard_regno_mode_ok (int regno
, enum machine_mode mode
)
5607 /* The only thing that can go into registers r28:r29 is a Pmode. */
5608 if (regno
== REG_Y
&& mode
== Pmode
)
5611 /* Otherwise disallow all regno/mode combinations that span r28:r29. */
5612 if (regno
<= (REG_Y
+ 1) && (regno
+ GET_MODE_SIZE (mode
)) >= (REG_Y
+ 1))
5618 /* Modes larger than QImode occupy consecutive registers. */
5619 if (regno
+ GET_MODE_SIZE (mode
) > FIRST_PSEUDO_REGISTER
)
5622 /* All modes larger than QImode should start in an even register. */
5623 return !(regno
& 1);
5626 /* Returns 1 if X is a valid address for an I/O register of size SIZE
5627 (1 or 2). Used for lds/sts -> in/out optimization. Add 0x20 to SIZE
5628 to check for the lower half of I/O space (for cbi/sbi/sbic/sbis). */
5631 avr_io_address_p (rtx x
, int size
)
5633 return (optimize
> 0 && GET_CODE (x
) == CONST_INT
5634 && INTVAL (x
) >= 0x20 && INTVAL (x
) <= 0x60 - size
);
5638 output_reload_inhi (rtx insn ATTRIBUTE_UNUSED
, rtx
*operands
, int *len
)
5644 if (GET_CODE (operands
[1]) == CONST_INT
)
5646 int val
= INTVAL (operands
[1]);
5647 if ((val
& 0xff) == 0)
5650 return (AS2 (mov
,%A0
,__zero_reg__
) CR_TAB
5651 AS2 (ldi
,%2,hi8(%1)) CR_TAB
5654 else if ((val
& 0xff00) == 0)
5657 return (AS2 (ldi
,%2,lo8(%1)) CR_TAB
5658 AS2 (mov
,%A0
,%2) CR_TAB
5659 AS2 (mov
,%B0
,__zero_reg__
));
5661 else if ((val
& 0xff) == ((val
& 0xff00) >> 8))
5664 return (AS2 (ldi
,%2,lo8(%1)) CR_TAB
5665 AS2 (mov
,%A0
,%2) CR_TAB
5670 return (AS2 (ldi
,%2,lo8(%1)) CR_TAB
5671 AS2 (mov
,%A0
,%2) CR_TAB
5672 AS2 (ldi
,%2,hi8(%1)) CR_TAB
5678 output_reload_insisf (rtx insn ATTRIBUTE_UNUSED
, rtx
*operands
, int *len
)
5680 rtx src
= operands
[1];
5681 int cnst
= (GET_CODE (src
) == CONST_INT
);
5686 *len
= 4 + ((INTVAL (src
) & 0xff) != 0)
5687 + ((INTVAL (src
) & 0xff00) != 0)
5688 + ((INTVAL (src
) & 0xff0000) != 0)
5689 + ((INTVAL (src
) & 0xff000000) != 0);
5696 if (cnst
&& ((INTVAL (src
) & 0xff) == 0))
5697 output_asm_insn (AS2 (mov
, %A0
, __zero_reg__
), operands
);
5700 output_asm_insn (AS2 (ldi
, %2, lo8(%1)), operands
);
5701 output_asm_insn (AS2 (mov
, %A0
, %2), operands
);
5703 if (cnst
&& ((INTVAL (src
) & 0xff00) == 0))
5704 output_asm_insn (AS2 (mov
, %B0
, __zero_reg__
), operands
);
5707 output_asm_insn (AS2 (ldi
, %2, hi8(%1)), operands
);
5708 output_asm_insn (AS2 (mov
, %B0
, %2), operands
);
5710 if (cnst
&& ((INTVAL (src
) & 0xff0000) == 0))
5711 output_asm_insn (AS2 (mov
, %C0
, __zero_reg__
), operands
);
5714 output_asm_insn (AS2 (ldi
, %2, hlo8(%1)), operands
);
5715 output_asm_insn (AS2 (mov
, %C0
, %2), operands
);
5717 if (cnst
&& ((INTVAL (src
) & 0xff000000) == 0))
5718 output_asm_insn (AS2 (mov
, %D0
, __zero_reg__
), operands
);
5721 output_asm_insn (AS2 (ldi
, %2, hhi8(%1)), operands
);
5722 output_asm_insn (AS2 (mov
, %D0
, %2), operands
);
5728 avr_output_bld (rtx operands
[], int bit_nr
)
5730 static char s
[] = "bld %A0,0";
5732 s
[5] = 'A' + (bit_nr
>> 3);
5733 s
[8] = '0' + (bit_nr
& 7);
5734 output_asm_insn (s
, operands
);
5738 avr_output_addr_vec_elt (FILE *stream
, int value
)
5740 switch_to_section (progmem_section
);
5742 fprintf (stream
, "\t.word pm(.L%d)\n", value
);
5744 fprintf (stream
, "\trjmp .L%d\n", value
);
5749 /* Returns 1 if SCRATCH are safe to be allocated as a scratch
5750 registers (for a define_peephole2) in the current function. */
5753 avr_peep2_scratch_safe (rtx scratch
)
5755 if ((interrupt_function_p (current_function_decl
)
5756 || signal_function_p (current_function_decl
))
5757 && leaf_function_p ())
5759 int first_reg
= true_regnum (scratch
);
5760 int last_reg
= first_reg
+ GET_MODE_SIZE (GET_MODE (scratch
)) - 1;
5763 for (reg
= first_reg
; reg
<= last_reg
; reg
++)
5765 if (!regs_ever_live
[reg
])
5772 /* Output a branch that tests a single bit of a register (QI, HI or SImode)
5773 or memory location in the I/O space (QImode only).
5775 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
5776 Operand 1: register operand to test, or CONST_INT memory address.
5777 Operand 2: bit number (for QImode operand) or mask (HImode, SImode).
5778 Operand 3: label to jump to if the test is true. */
5781 avr_out_sbxx_branch (rtx insn
, rtx operands
[])
5783 enum rtx_code comp
= GET_CODE (operands
[0]);
5784 int long_jump
= (get_attr_length (insn
) >= 4);
5785 int reverse
= long_jump
|| jump_over_one_insn_p (insn
, operands
[3]);
5789 else if (comp
== LT
)
5793 comp
= reverse_condition (comp
);
5795 if (GET_CODE (operands
[1]) == CONST_INT
)
5797 if (INTVAL (operands
[1]) < 0x40)
5800 output_asm_insn (AS2 (sbis
,%1-0x20,%2), operands
);
5802 output_asm_insn (AS2 (sbic
,%1-0x20,%2), operands
);
5806 output_asm_insn (AS2 (in
,__tmp_reg__
,%1-0x20), operands
);
5808 output_asm_insn (AS2 (sbrs
,__tmp_reg__
,%2), operands
);
5810 output_asm_insn (AS2 (sbrc
,__tmp_reg__
,%2), operands
);
5813 else /* GET_CODE (operands[1]) == REG */
5815 if (GET_MODE (operands
[1]) == QImode
)
5818 output_asm_insn (AS2 (sbrs
,%1,%2), operands
);
5820 output_asm_insn (AS2 (sbrc
,%1,%2), operands
);
5822 else /* HImode or SImode */
5824 static char buf
[] = "sbrc %A1,0";
5825 int bit_nr
= exact_log2 (INTVAL (operands
[2])
5826 & GET_MODE_MASK (GET_MODE (operands
[1])));
5828 buf
[3] = (comp
== EQ
) ? 's' : 'c';
5829 buf
[6] = 'A' + (bit_nr
>> 3);
5830 buf
[9] = '0' + (bit_nr
& 7);
5831 output_asm_insn (buf
, operands
);
5836 return (AS1 (rjmp
,.+4) CR_TAB
5839 return AS1 (rjmp
,%3);
5843 /* Worker function for TARGET_ASM_CONSTRUCTOR. */
5846 avr_asm_out_ctor (rtx symbol
, int priority
)
5848 fputs ("\t.global __do_global_ctors\n", asm_out_file
);
5849 default_ctor_section_asm_out_constructor (symbol
, priority
);
5852 /* Worker function for TARGET_ASM_DESTRUCTOR. */
5855 avr_asm_out_dtor (rtx symbol
, int priority
)
5857 fputs ("\t.global __do_global_dtors\n", asm_out_file
);
5858 default_dtor_section_asm_out_destructor (symbol
, priority
);
5861 /* Worker function for TARGET_RETURN_IN_MEMORY. */
5864 avr_return_in_memory (tree type
, tree fntype ATTRIBUTE_UNUSED
)
5866 if (TYPE_MODE (type
) == BLKmode
)
5868 HOST_WIDE_INT size
= int_size_in_bytes (type
);
5869 return (size
== -1 || size
> 8);