1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005
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 /* Enhanced core: use "movw", "mul", ... */
124 int avr_enhanced_p
= 0;
126 /* Assembler only. */
127 int avr_asm_only_p
= 0;
133 const char *const macro
;
136 static const struct base_arch_s avr_arch_types
[] = {
137 { 1, 0, 0, NULL
}, /* unknown device specified */
138 { 1, 0, 0, "__AVR_ARCH__=1" },
139 { 0, 0, 0, "__AVR_ARCH__=2" },
140 { 0, 0, 1, "__AVR_ARCH__=3" },
141 { 0, 1, 0, "__AVR_ARCH__=4" },
142 { 0, 1, 1, "__AVR_ARCH__=5" }
146 const char *const name
;
147 int arch
; /* index in avr_arch_types[] */
148 /* Must lie outside user's namespace. NULL == no macro. */
149 const char *const macro
;
152 /* List of all known AVR MCU types - if updated, it has to be kept
153 in sync in several places (FIXME: is there a better way?):
155 - avr.h (CPP_SPEC, LINK_SPEC, CRT_BINUTILS_SPECS)
156 - t-avr (MULTILIB_MATCHES)
157 - gas/config/tc-avr.c
160 static const struct mcu_type_s avr_mcu_types
[] = {
161 /* Classic, <= 8K. */
163 { "at90s2313", 2, "__AVR_AT90S2313__" },
164 { "at90s2323", 2, "__AVR_AT90S2323__" },
165 { "at90s2333", 2, "__AVR_AT90S2333__" },
166 { "at90s2343", 2, "__AVR_AT90S2343__" },
167 { "attiny22", 2, "__AVR_ATtiny22__" },
168 { "attiny26", 2, "__AVR_ATtiny26__" },
169 { "at90s4414", 2, "__AVR_AT90S4414__" },
170 { "at90s4433", 2, "__AVR_AT90S4433__" },
171 { "at90s4434", 2, "__AVR_AT90S4434__" },
172 { "at90s8515", 2, "__AVR_AT90S8515__" },
173 { "at90c8534", 2, "__AVR_AT90C8534__" },
174 { "at90s8535", 2, "__AVR_AT90S8535__" },
175 { "at86rf401", 2, "__AVR_AT86RF401__" },
176 /* Classic + MOVW, <= 8K. */
177 { "attiny13", 2, "__AVR_ATtiny13__" },
178 { "attiny2313", 2, "__AVR_ATtiny2313__" },
181 { "atmega103", 3, "__AVR_ATmega103__" },
182 { "atmega603", 3, "__AVR_ATmega603__" },
183 { "at43usb320", 3, "__AVR_AT43USB320__" },
184 { "at43usb355", 3, "__AVR_AT43USB355__" },
185 { "at76c711", 3, "__AVR_AT76C711__" },
186 /* Enhanced, <= 8K. */
188 { "atmega8", 4, "__AVR_ATmega8__" },
189 { "atmega48", 4, "__AVR_ATmega48__" },
190 { "atmega88", 4, "__AVR_ATmega88__" },
191 { "atmega8515", 4, "__AVR_ATmega8515__" },
192 { "atmega8535", 4, "__AVR_ATmega8535__" },
193 /* Enhanced, > 8K. */
195 { "atmega16", 5, "__AVR_ATmega16__" },
196 { "atmega161", 5, "__AVR_ATmega161__" },
197 { "atmega162", 5, "__AVR_ATmega162__" },
198 { "atmega163", 5, "__AVR_ATmega163__" },
199 { "atmega165", 5, "__AVR_ATmega165__" },
200 { "atmega168", 5, "__AVR_ATmega168__" },
201 { "atmega169", 5, "__AVR_ATmega169__" },
202 { "atmega32", 5, "__AVR_ATmega32__" },
203 { "atmega323", 5, "__AVR_ATmega323__" },
204 { "atmega325", 5, "__AVR_ATmega325__" },
205 { "atmega3250", 5, "__AVR_ATmega3250__" },
206 { "atmega64", 5, "__AVR_ATmega64__" },
207 { "atmega645", 5, "__AVR_ATmega645__" },
208 { "atmega6450", 5, "__AVR_ATmega6450__" },
209 { "atmega128", 5, "__AVR_ATmega128__" },
210 { "at90can128", 5, "__AVR_AT90CAN128__" },
211 { "at94k", 5, "__AVR_AT94K__" },
212 /* Assembler only. */
214 { "at90s1200", 1, "__AVR_AT90S1200__" },
215 { "attiny11", 1, "__AVR_ATtiny11__" },
216 { "attiny12", 1, "__AVR_ATtiny12__" },
217 { "attiny15", 1, "__AVR_ATtiny15__" },
218 { "attiny28", 1, "__AVR_ATtiny28__" },
222 int avr_case_values_threshold
= 30000;
224 /* Initialize the GCC target structure. */
225 #undef TARGET_ASM_ALIGNED_HI_OP
226 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
227 #undef TARGET_ASM_ALIGNED_SI_OP
228 #define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
229 #undef TARGET_ASM_UNALIGNED_HI_OP
230 #define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
231 #undef TARGET_ASM_UNALIGNED_SI_OP
232 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
233 #undef TARGET_ASM_INTEGER
234 #define TARGET_ASM_INTEGER avr_assemble_integer
235 #undef TARGET_ASM_FILE_START
236 #define TARGET_ASM_FILE_START avr_file_start
237 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
238 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
239 #undef TARGET_ASM_FILE_END
240 #define TARGET_ASM_FILE_END avr_file_end
242 #undef TARGET_ASM_FUNCTION_PROLOGUE
243 #define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
244 #undef TARGET_ASM_FUNCTION_EPILOGUE
245 #define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
246 #undef TARGET_ATTRIBUTE_TABLE
247 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
248 #undef TARGET_ASM_FUNCTION_RODATA_SECTION
249 #define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
250 #undef TARGET_INSERT_ATTRIBUTES
251 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
252 #undef TARGET_SECTION_TYPE_FLAGS
253 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
254 #undef TARGET_RTX_COSTS
255 #define TARGET_RTX_COSTS avr_rtx_costs
256 #undef TARGET_ADDRESS_COST
257 #define TARGET_ADDRESS_COST avr_address_cost
258 #undef TARGET_MACHINE_DEPENDENT_REORG
259 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
261 #undef TARGET_RETURN_IN_MEMORY
262 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
264 #undef TARGET_STRICT_ARGUMENT_NAMING
265 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
267 struct gcc_target targetm
= TARGET_INITIALIZER
;
270 avr_override_options (void)
272 const struct mcu_type_s
*t
;
273 const struct base_arch_s
*base
;
275 for (t
= avr_mcu_types
; t
->name
; t
++)
276 if (strcmp (t
->name
, avr_mcu_name
) == 0)
281 fprintf (stderr
, "unknown MCU '%s' specified\nKnown MCU names:\n",
283 for (t
= avr_mcu_types
; t
->name
; t
++)
284 fprintf (stderr
," %s\n", t
->name
);
287 base
= &avr_arch_types
[t
->arch
];
288 avr_asm_only_p
= base
->asm_only
;
289 avr_enhanced_p
= base
->enhanced
;
290 avr_mega_p
= base
->mega
;
291 avr_base_arch_macro
= base
->macro
;
292 avr_extra_arch_macro
= t
->macro
;
294 if (optimize
&& !TARGET_NO_TABLEJUMP
)
295 avr_case_values_threshold
= (!AVR_MEGA
|| TARGET_CALL_PROLOGUES
) ? 8 : 17;
297 tmp_reg_rtx
= gen_rtx_REG (QImode
, TMP_REGNO
);
298 zero_reg_rtx
= gen_rtx_REG (QImode
, ZERO_REGNO
);
301 /* return register class from register number. */
303 static const int reg_class_tab
[]={
304 GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,
305 GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,
306 GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,
307 GENERAL_REGS
, /* r0 - r15 */
308 LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,
309 LD_REGS
, /* r16 - 23 */
310 ADDW_REGS
,ADDW_REGS
, /* r24,r25 */
311 POINTER_X_REGS
,POINTER_X_REGS
, /* r26,27 */
312 POINTER_Y_REGS
,POINTER_Y_REGS
, /* r28,r29 */
313 POINTER_Z_REGS
,POINTER_Z_REGS
, /* r30,r31 */
314 STACK_REG
,STACK_REG
/* SPL,SPH */
317 /* Return register class for register R. */
320 avr_regno_reg_class (int r
)
323 return reg_class_tab
[r
];
328 /* A C expression which defines the machine-dependent operand
329 constraint letters for register classes. If C is such a
330 letter, the value should be the register class corresponding to
331 it. Otherwise, the value should be `NO_REGS'. The register
332 letter `r', corresponding to class `GENERAL_REGS', will not be
333 passed to this macro; you do not need to handle it. */
336 avr_reg_class_from_letter (int c
)
340 case 't' : return R0_REG
;
341 case 'b' : return BASE_POINTER_REGS
;
342 case 'e' : return POINTER_REGS
;
343 case 'w' : return ADDW_REGS
;
344 case 'd' : return LD_REGS
;
345 case 'l' : return NO_LD_REGS
;
346 case 'a' : return SIMPLE_LD_REGS
;
347 case 'x' : return POINTER_X_REGS
;
348 case 'y' : return POINTER_Y_REGS
;
349 case 'z' : return POINTER_Z_REGS
;
350 case 'q' : return STACK_REG
;
356 /* Return nonzero if FUNC is a naked function. */
359 avr_naked_function_p (tree func
)
363 gcc_assert (TREE_CODE (func
) == FUNCTION_DECL
);
365 a
= lookup_attribute ("naked", DECL_ATTRIBUTES (func
));
366 return a
!= NULL_TREE
;
369 /* Return nonzero if FUNC is an interrupt function as specified
370 by the "interrupt" attribute. */
373 interrupt_function_p (tree func
)
377 if (TREE_CODE (func
) != FUNCTION_DECL
)
380 a
= lookup_attribute ("interrupt", DECL_ATTRIBUTES (func
));
381 return a
!= NULL_TREE
;
384 /* Return nonzero if FUNC is a signal function as specified
385 by the "signal" attribute. */
388 signal_function_p (tree func
)
392 if (TREE_CODE (func
) != FUNCTION_DECL
)
395 a
= lookup_attribute ("signal", DECL_ATTRIBUTES (func
));
396 return a
!= NULL_TREE
;
399 /* Return the number of hard registers to push/pop in the prologue/epilogue
400 of the current function, and optionally store these registers in SET. */
403 avr_regs_to_save (HARD_REG_SET
*set
)
406 int int_or_sig_p
= (interrupt_function_p (current_function_decl
)
407 || signal_function_p (current_function_decl
));
408 int leaf_func_p
= leaf_function_p ();
411 CLEAR_HARD_REG_SET (*set
);
414 /* No need to save any registers if the function never returns. */
415 if (TREE_THIS_VOLATILE (current_function_decl
))
418 for (reg
= 0; reg
< 32; reg
++)
420 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
421 any global register variables. */
425 if ((int_or_sig_p
&& !leaf_func_p
&& call_used_regs
[reg
])
426 || (regs_ever_live
[reg
]
427 && (int_or_sig_p
|| !call_used_regs
[reg
])
428 && !(frame_pointer_needed
429 && (reg
== REG_Y
|| reg
== (REG_Y
+1)))))
432 SET_HARD_REG_BIT (*set
, reg
);
439 /* Compute offset between arg_pointer and frame_pointer. */
442 initial_elimination_offset (int from
, int to
)
444 if (from
== FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
448 int offset
= frame_pointer_needed
? 2 : 0;
450 offset
+= avr_regs_to_save (NULL
);
451 return get_frame_size () + 2 + 1 + offset
;
455 /* Return 1 if the function epilogue is just a single "ret". */
458 avr_simple_epilogue (void)
460 return (! frame_pointer_needed
461 && get_frame_size () == 0
462 && avr_regs_to_save (NULL
) == 0
463 && ! interrupt_function_p (current_function_decl
)
464 && ! signal_function_p (current_function_decl
)
465 && ! avr_naked_function_p (current_function_decl
)
466 && ! MAIN_NAME_P (DECL_NAME (current_function_decl
))
467 && ! TREE_THIS_VOLATILE (current_function_decl
));
470 /* This function checks sequence of live registers. */
473 sequent_regs_live (void)
479 for (reg
= 0; reg
< 18; ++reg
)
481 if (!call_used_regs
[reg
])
483 if (regs_ever_live
[reg
])
493 if (!frame_pointer_needed
)
495 if (regs_ever_live
[REG_Y
])
503 if (regs_ever_live
[REG_Y
+1])
516 return (cur_seq
== live_seq
) ? live_seq
: 0;
520 /* Output to FILE the asm instructions to adjust the frame pointer by
521 ADJ (r29:r28 -= ADJ;) which can be positive (prologue) or negative
522 (epilogue). Returns the number of instructions generated. */
525 out_adj_frame_ptr (FILE *file
, int adj
)
531 if (TARGET_TINY_STACK
)
533 if (adj
< -63 || adj
> 63)
534 warning (0, "large frame pointer change (%d) with -mtiny-stack", adj
);
536 /* The high byte (r29) doesn't change - prefer "subi" (1 cycle)
537 over "sbiw" (2 cycles, same size). */
539 fprintf (file
, (AS2 (subi
, r28
, %d
) CR_TAB
), adj
);
542 else if (adj
< -63 || adj
> 63)
544 fprintf (file
, (AS2 (subi
, r28
, lo8(%d
)) CR_TAB
545 AS2 (sbci
, r29
, hi8(%d
)) CR_TAB
),
551 fprintf (file
, (AS2 (adiw
, r28
, %d
) CR_TAB
), -adj
);
556 fprintf (file
, (AS2 (sbiw
, r28
, %d
) CR_TAB
), adj
);
564 /* Output to FILE the asm instructions to copy r29:r28 to SPH:SPL,
565 handling various cases of interrupt enable flag state BEFORE and AFTER
566 (0=disabled, 1=enabled, -1=unknown/unchanged) and target_flags.
567 Returns the number of instructions generated. */
570 out_set_stack_ptr (FILE *file
, int before
, int after
)
572 int do_sph
, do_cli
, do_save
, do_sei
, lock_sph
, size
;
574 /* The logic here is so that -mno-interrupts actually means
575 "it is safe to write SPH in one instruction, then SPL in the
576 next instruction, without disabling interrupts first".
577 The after != -1 case (interrupt/signal) is not affected. */
579 do_sph
= !TARGET_TINY_STACK
;
580 lock_sph
= do_sph
&& !TARGET_NO_INTERRUPTS
;
581 do_cli
= (before
!= 0 && (after
== 0 || lock_sph
));
582 do_save
= (do_cli
&& before
== -1 && after
== -1);
583 do_sei
= ((do_cli
|| before
!= 1) && after
== 1);
588 fprintf (file
, AS2 (in
, __tmp_reg__
, __SREG__
) CR_TAB
);
594 fprintf (file
, "cli" CR_TAB
);
598 /* Do SPH first - maybe this will disable interrupts for one instruction
599 someday (a suggestion has been sent to avr@atmel.com for consideration
600 in future devices - that would make -mno-interrupts always safe). */
603 fprintf (file
, AS2 (out
, __SP_H__
, r29
) CR_TAB
);
607 /* Set/restore the I flag now - interrupts will be really enabled only
608 after the next instruction. This is not clearly documented, but
609 believed to be true for all AVR devices. */
612 fprintf (file
, AS2 (out
, __SREG__
, __tmp_reg__
) CR_TAB
);
617 fprintf (file
, "sei" CR_TAB
);
621 fprintf (file
, AS2 (out
, __SP_L__
, r28
) "\n");
627 /* Output function prologue. */
630 avr_output_function_prologue (FILE *file
, HOST_WIDE_INT size
)
633 int interrupt_func_p
;
639 last_insn_address
= 0;
640 jump_tables_size
= 0;
642 fprintf (file
, "/* prologue: frame size=" HOST_WIDE_INT_PRINT_DEC
" */\n",
645 if (avr_naked_function_p (current_function_decl
))
647 fputs ("/* prologue: naked */\n", file
);
651 interrupt_func_p
= interrupt_function_p (current_function_decl
);
652 signal_func_p
= signal_function_p (current_function_decl
);
653 main_p
= MAIN_NAME_P (DECL_NAME (current_function_decl
));
654 live_seq
= sequent_regs_live ();
655 minimize
= (TARGET_CALL_PROLOGUES
656 && !interrupt_func_p
&& !signal_func_p
&& live_seq
);
658 if (interrupt_func_p
)
660 fprintf (file
,"\tsei\n");
663 if (interrupt_func_p
|| signal_func_p
)
666 AS1 (push
,__zero_reg__
) CR_TAB
667 AS1 (push
,__tmp_reg__
) CR_TAB
668 AS2 (in
,__tmp_reg__
,__SREG__
) CR_TAB
669 AS1 (push
,__tmp_reg__
) CR_TAB
670 AS1 (clr
,__zero_reg__
) "\n");
676 AS1 (ldi
,r28
) ",lo8(%s - " HOST_WIDE_INT_PRINT_DEC
")" CR_TAB
677 AS1 (ldi
,r29
) ",hi8(%s - " HOST_WIDE_INT_PRINT_DEC
")" CR_TAB
678 AS2 (out
,__SP_H__
,r29
) CR_TAB
679 AS2 (out
,__SP_L__
,r28
) "\n"),
680 avr_init_stack
, size
, avr_init_stack
, size
);
684 else if (minimize
&& (frame_pointer_needed
|| live_seq
> 6))
687 AS1 (ldi
, r26
) ",lo8(" HOST_WIDE_INT_PRINT_DEC
")" CR_TAB
688 AS1 (ldi
, r27
) ",hi8(" HOST_WIDE_INT_PRINT_DEC
")" CR_TAB
), size
, size
);
690 fputs ((AS2 (ldi
,r30
,pm_lo8(1f
)) CR_TAB
691 AS2 (ldi
,r31
,pm_hi8(1f
)) CR_TAB
), file
);
697 fprintf (file
, AS1 (jmp
,__prologue_saves__
+%d
) "\n",
698 (18 - live_seq
) * 2);
703 fprintf (file
, AS1 (rjmp
,__prologue_saves__
+%d
) "\n",
704 (18 - live_seq
) * 2);
707 fputs ("1:\n", file
);
713 prologue_size
+= avr_regs_to_save (&set
);
714 for (reg
= 0; reg
< 32; ++reg
)
716 if (TEST_HARD_REG_BIT (set
, reg
))
718 fprintf (file
, "\t" AS1 (push
,%s
) "\n", avr_regnames
[reg
]);
721 if (frame_pointer_needed
)
724 AS1 (push
,r28
) CR_TAB
725 AS1 (push
,r29
) CR_TAB
726 AS2 (in
,r28
,__SP_L__
) CR_TAB
727 AS2 (in
,r29
,__SP_H__
) "\n");
732 prologue_size
+= out_adj_frame_ptr (file
, size
);
734 if (interrupt_func_p
)
736 prologue_size
+= out_set_stack_ptr (file
, 1, 1);
738 else if (signal_func_p
)
740 prologue_size
+= out_set_stack_ptr (file
, 0, 0);
744 prologue_size
+= out_set_stack_ptr (file
, -1, -1);
751 fprintf (file
, "/* prologue end (size=%d) */\n", prologue_size
);
754 /* Output function epilogue. */
757 avr_output_function_epilogue (FILE *file
, HOST_WIDE_INT size
)
760 int interrupt_func_p
;
766 rtx last
= get_last_nonnote_insn ();
768 function_size
= jump_tables_size
;
771 rtx first
= get_first_nonnote_insn ();
772 function_size
+= (INSN_ADDRESSES (INSN_UID (last
)) -
773 INSN_ADDRESSES (INSN_UID (first
)));
774 function_size
+= get_attr_length (last
);
777 fprintf (file
, "/* epilogue: frame size=" HOST_WIDE_INT_PRINT_DEC
" */\n", size
);
780 if (avr_naked_function_p (current_function_decl
))
782 fputs ("/* epilogue: naked */\n", file
);
786 if (last
&& GET_CODE (last
) == BARRIER
)
788 fputs ("/* epilogue: noreturn */\n", file
);
792 interrupt_func_p
= interrupt_function_p (current_function_decl
);
793 signal_func_p
= signal_function_p (current_function_decl
);
794 main_p
= MAIN_NAME_P (DECL_NAME (current_function_decl
));
795 live_seq
= sequent_regs_live ();
796 minimize
= (TARGET_CALL_PROLOGUES
797 && !interrupt_func_p
&& !signal_func_p
&& live_seq
);
801 /* Return value from main() is already in the correct registers
802 (r25:r24) as the exit() argument. */
805 fputs ("\t" AS1 (jmp
,exit
) "\n", file
);
810 fputs ("\t" AS1 (rjmp
,exit
) "\n", file
);
814 else if (minimize
&& (frame_pointer_needed
|| live_seq
> 4))
816 fprintf (file
, ("\t" AS2 (ldi
, r30
, %d
) CR_TAB
), live_seq
);
818 if (frame_pointer_needed
)
820 epilogue_size
+= out_adj_frame_ptr (file
, -size
);
824 fprintf (file
, (AS2 (in
, r28
, __SP_L__
) CR_TAB
825 AS2 (in
, r29
, __SP_H__
) CR_TAB
));
831 fprintf (file
, AS1 (jmp
,__epilogue_restores__
+%d
) "\n",
832 (18 - live_seq
) * 2);
837 fprintf (file
, AS1 (rjmp
,__epilogue_restores__
+%d
) "\n",
838 (18 - live_seq
) * 2);
846 if (frame_pointer_needed
)
851 epilogue_size
+= out_adj_frame_ptr (file
, -size
);
853 if (interrupt_func_p
|| signal_func_p
)
855 epilogue_size
+= out_set_stack_ptr (file
, -1, 0);
859 epilogue_size
+= out_set_stack_ptr (file
, -1, -1);
868 epilogue_size
+= avr_regs_to_save (&set
);
869 for (reg
= 31; reg
>= 0; --reg
)
871 if (TEST_HARD_REG_BIT (set
, reg
))
873 fprintf (file
, "\t" AS1 (pop
,%s
) "\n", avr_regnames
[reg
]);
877 if (interrupt_func_p
|| signal_func_p
)
880 AS1 (pop
,__tmp_reg__
) CR_TAB
881 AS2 (out
,__SREG__
,__tmp_reg__
) CR_TAB
882 AS1 (pop
,__tmp_reg__
) CR_TAB
883 AS1 (pop
,__zero_reg__
) "\n");
885 fprintf (file
, "\treti\n");
888 fprintf (file
, "\tret\n");
893 fprintf (file
, "/* epilogue end (size=%d) */\n", epilogue_size
);
894 fprintf (file
, "/* function %s size %d (%d) */\n", current_function_name (),
895 prologue_size
+ function_size
+ epilogue_size
, function_size
);
896 commands_in_file
+= prologue_size
+ function_size
+ epilogue_size
;
897 commands_in_prologues
+= prologue_size
;
898 commands_in_epilogues
+= epilogue_size
;
902 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
903 machine for a memory operand of mode MODE. */
906 legitimate_address_p (enum machine_mode mode
, rtx x
, int strict
)
908 enum reg_class r
= NO_REGS
;
910 if (TARGET_ALL_DEBUG
)
912 fprintf (stderr
, "mode: (%s) %s %s %s %s:",
914 strict
? "(strict)": "",
915 reload_completed
? "(reload_completed)": "",
916 reload_in_progress
? "(reload_in_progress)": "",
917 reg_renumber
? "(reg_renumber)" : "");
918 if (GET_CODE (x
) == PLUS
919 && REG_P (XEXP (x
, 0))
920 && GET_CODE (XEXP (x
, 1)) == CONST_INT
921 && INTVAL (XEXP (x
, 1)) >= 0
922 && INTVAL (XEXP (x
, 1)) <= MAX_LD_OFFSET (mode
)
925 fprintf (stderr
, "(r%d ---> r%d)", REGNO (XEXP (x
, 0)),
926 true_regnum (XEXP (x
, 0)));
929 if (REG_P (x
) && (strict
? REG_OK_FOR_BASE_STRICT_P (x
)
930 : REG_OK_FOR_BASE_NOSTRICT_P (x
)))
932 else if (CONSTANT_ADDRESS_P (x
))
934 else if (GET_CODE (x
) == PLUS
935 && REG_P (XEXP (x
, 0))
936 && GET_CODE (XEXP (x
, 1)) == CONST_INT
937 && INTVAL (XEXP (x
, 1)) >= 0)
939 int fit
= INTVAL (XEXP (x
, 1)) <= MAX_LD_OFFSET (mode
);
943 || REGNO (XEXP (x
,0)) == REG_Y
944 || REGNO (XEXP (x
,0)) == REG_Z
)
945 r
= BASE_POINTER_REGS
;
946 if (XEXP (x
,0) == frame_pointer_rtx
947 || XEXP (x
,0) == arg_pointer_rtx
)
948 r
= BASE_POINTER_REGS
;
950 else if (frame_pointer_needed
&& XEXP (x
,0) == frame_pointer_rtx
)
953 else if ((GET_CODE (x
) == PRE_DEC
|| GET_CODE (x
) == POST_INC
)
954 && REG_P (XEXP (x
, 0))
955 && (strict
? REG_OK_FOR_BASE_STRICT_P (XEXP (x
, 0))
956 : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x
, 0))))
960 if (TARGET_ALL_DEBUG
)
962 fprintf (stderr
, " ret = %c\n", r
+ '0');
964 return r
== NO_REGS
? 0 : (int)r
;
967 /* Attempts to replace X with a valid
968 memory address for an operand of mode MODE */
971 legitimize_address (rtx x
, rtx oldx
, enum machine_mode mode
)
974 if (TARGET_ALL_DEBUG
)
976 fprintf (stderr
, "legitimize_address mode: %s", GET_MODE_NAME(mode
));
980 if (GET_CODE (oldx
) == PLUS
981 && REG_P (XEXP (oldx
,0)))
983 if (REG_P (XEXP (oldx
,1)))
984 x
= force_reg (GET_MODE (oldx
), oldx
);
985 else if (GET_CODE (XEXP (oldx
, 1)) == CONST_INT
)
987 int offs
= INTVAL (XEXP (oldx
,1));
988 if (frame_pointer_rtx
!= XEXP (oldx
,0))
989 if (offs
> MAX_LD_OFFSET (mode
))
991 if (TARGET_ALL_DEBUG
)
992 fprintf (stderr
, "force_reg (big offset)\n");
993 x
= force_reg (GET_MODE (oldx
), oldx
);
1001 /* Return a pointer register name as a string. */
1004 ptrreg_to_str (int regno
)
1008 case REG_X
: return "X";
1009 case REG_Y
: return "Y";
1010 case REG_Z
: return "Z";
1017 /* Return the condition name as a string.
1018 Used in conditional jump constructing */
1021 cond_string (enum rtx_code code
)
1030 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1035 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1048 /* Output ADDR to FILE as address. */
1051 print_operand_address (FILE *file
, rtx addr
)
1053 switch (GET_CODE (addr
))
1056 fprintf (file
, ptrreg_to_str (REGNO (addr
)));
1060 fprintf (file
, "-%s", ptrreg_to_str (REGNO (XEXP (addr
, 0))));
1064 fprintf (file
, "%s+", ptrreg_to_str (REGNO (XEXP (addr
, 0))));
1068 if (CONSTANT_ADDRESS_P (addr
)
1069 && ((GET_CODE (addr
) == SYMBOL_REF
&& SYMBOL_REF_FUNCTION_P (addr
))
1070 || GET_CODE (addr
) == LABEL_REF
))
1072 fprintf (file
, "pm(");
1073 output_addr_const (file
,addr
);
1074 fprintf (file
,")");
1077 output_addr_const (file
, addr
);
1082 /* Output X as assembler operand to file FILE. */
1085 print_operand (FILE *file
, rtx x
, int code
)
1089 if (code
>= 'A' && code
<= 'D')
1099 if (x
== zero_reg_rtx
)
1100 fprintf (file
, "__zero_reg__");
1102 fprintf (file
, reg_names
[true_regnum (x
) + abcd
]);
1104 else if (GET_CODE (x
) == CONST_INT
)
1105 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
) + abcd
);
1106 else if (GET_CODE (x
) == MEM
)
1108 rtx addr
= XEXP (x
,0);
1110 if (CONSTANT_P (addr
) && abcd
)
1113 output_address (addr
);
1114 fprintf (file
, ")+%d", abcd
);
1116 else if (code
== 'o')
1118 if (GET_CODE (addr
) != PLUS
)
1119 fatal_insn ("bad address, not (reg+disp):", addr
);
1121 print_operand (file
, XEXP (addr
, 1), 0);
1123 else if (code
== 'p' || code
== 'r')
1125 if (GET_CODE (addr
) != POST_INC
&& GET_CODE (addr
) != PRE_DEC
)
1126 fatal_insn ("bad address, not post_inc or pre_dec:", addr
);
1129 print_operand_address (file
, XEXP (addr
, 0)); /* X, Y, Z */
1131 print_operand (file
, XEXP (addr
, 0), 0); /* r26, r28, r30 */
1133 else if (GET_CODE (addr
) == PLUS
)
1135 print_operand_address (file
, XEXP (addr
,0));
1136 if (REGNO (XEXP (addr
, 0)) == REG_X
)
1137 fatal_insn ("internal compiler error. Bad address:"
1140 print_operand (file
, XEXP (addr
,1), code
);
1143 print_operand_address (file
, addr
);
1145 else if (GET_CODE (x
) == CONST_DOUBLE
)
1149 if (GET_MODE (x
) != SFmode
)
1150 fatal_insn ("internal compiler error. Unknown mode:", x
);
1151 REAL_VALUE_FROM_CONST_DOUBLE (rv
, x
);
1152 REAL_VALUE_TO_TARGET_SINGLE (rv
, val
);
1153 fprintf (file
, "0x%lx", val
);
1155 else if (code
== 'j')
1156 fputs (cond_string (GET_CODE (x
)), file
);
1157 else if (code
== 'k')
1158 fputs (cond_string (reverse_condition (GET_CODE (x
))), file
);
1160 print_operand_address (file
, x
);
1163 /* Recognize operand OP of mode MODE used in call instructions. */
1166 call_insn_operand (rtx op
, enum machine_mode mode ATTRIBUTE_UNUSED
)
1168 if (GET_CODE (op
) == MEM
)
1170 rtx inside
= XEXP (op
, 0);
1171 if (register_operand (inside
, Pmode
))
1173 if (CONSTANT_ADDRESS_P (inside
))
1179 /* Update the condition code in the INSN. */
1182 notice_update_cc (rtx body ATTRIBUTE_UNUSED
, rtx insn
)
1186 switch (get_attr_cc (insn
))
1189 /* Insn does not affect CC at all. */
1197 set
= single_set (insn
);
1201 cc_status
.flags
|= CC_NO_OVERFLOW
;
1202 cc_status
.value1
= SET_DEST (set
);
1207 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
1208 The V flag may or may not be known but that's ok because
1209 alter_cond will change tests to use EQ/NE. */
1210 set
= single_set (insn
);
1214 cc_status
.value1
= SET_DEST (set
);
1215 cc_status
.flags
|= CC_OVERFLOW_UNUSABLE
;
1220 set
= single_set (insn
);
1223 cc_status
.value1
= SET_SRC (set
);
1227 /* Insn doesn't leave CC in a usable state. */
1230 /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1231 set
= single_set (insn
);
1234 rtx src
= SET_SRC (set
);
1236 if (GET_CODE (src
) == ASHIFTRT
1237 && GET_MODE (src
) == QImode
)
1239 rtx x
= XEXP (src
, 1);
1241 if (GET_CODE (x
) == CONST_INT
1245 cc_status
.value1
= SET_DEST (set
);
1246 cc_status
.flags
|= CC_OVERFLOW_UNUSABLE
;
1254 /* Return maximum number of consecutive registers of
1255 class CLASS needed to hold a value of mode MODE. */
1258 class_max_nregs (enum reg_class
class ATTRIBUTE_UNUSED
,enum machine_mode mode
)
1260 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
);
1263 /* Choose mode for jump insn:
1264 1 - relative jump in range -63 <= x <= 62 ;
1265 2 - relative jump in range -2046 <= x <= 2045 ;
1266 3 - absolute jump (only for ATmega[16]03). */
1269 avr_jump_mode (rtx x
, rtx insn
)
1271 int dest_addr
= INSN_ADDRESSES (INSN_UID (GET_MODE (x
) == LABEL_REF
1272 ? XEXP (x
, 0) : x
));
1273 int cur_addr
= INSN_ADDRESSES (INSN_UID (insn
));
1274 int jump_distance
= cur_addr
- dest_addr
;
1276 if (-63 <= jump_distance
&& jump_distance
<= 62)
1278 else if (-2046 <= jump_distance
&& jump_distance
<= 2045)
1286 /* return an AVR condition jump commands.
1287 X is a comparison RTX.
1288 LEN is a number returned by avr_jump_mode function.
1289 if REVERSE nonzero then condition code in X must be reversed. */
1292 ret_cond_branch (rtx x
, int len
, int reverse
)
1294 RTX_CODE cond
= reverse
? reverse_condition (GET_CODE (x
)) : GET_CODE (x
);
1299 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1300 return (len
== 1 ? (AS1 (breq
,.+2) CR_TAB
1302 len
== 2 ? (AS1 (breq
,.+4) CR_TAB
1303 AS1 (brmi
,.+2) CR_TAB
1305 (AS1 (breq
,.+6) CR_TAB
1306 AS1 (brmi
,.+4) CR_TAB
1310 return (len
== 1 ? (AS1 (breq
,.+2) CR_TAB
1312 len
== 2 ? (AS1 (breq
,.+4) CR_TAB
1313 AS1 (brlt
,.+2) CR_TAB
1315 (AS1 (breq
,.+6) CR_TAB
1316 AS1 (brlt
,.+4) CR_TAB
1319 return (len
== 1 ? (AS1 (breq
,.+2) CR_TAB
1321 len
== 2 ? (AS1 (breq
,.+4) CR_TAB
1322 AS1 (brlo
,.+2) CR_TAB
1324 (AS1 (breq
,.+6) CR_TAB
1325 AS1 (brlo
,.+4) CR_TAB
1328 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1329 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1331 len
== 2 ? (AS1 (breq
,.+2) CR_TAB
1332 AS1 (brpl
,.+2) CR_TAB
1334 (AS1 (breq
,.+2) CR_TAB
1335 AS1 (brpl
,.+4) CR_TAB
1338 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1340 len
== 2 ? (AS1 (breq
,.+2) CR_TAB
1341 AS1 (brge
,.+2) CR_TAB
1343 (AS1 (breq
,.+2) CR_TAB
1344 AS1 (brge
,.+4) CR_TAB
1347 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1349 len
== 2 ? (AS1 (breq
,.+2) CR_TAB
1350 AS1 (brsh
,.+2) CR_TAB
1352 (AS1 (breq
,.+2) CR_TAB
1353 AS1 (brsh
,.+4) CR_TAB
1361 return AS1 (br
%k1
,%0);
1363 return (AS1 (br
%j1
,.+2) CR_TAB
1366 return (AS1 (br
%j1
,.+4) CR_TAB
1375 return AS1 (br
%j1
,%0);
1377 return (AS1 (br
%k1
,.+2) CR_TAB
1380 return (AS1 (br
%k1
,.+4) CR_TAB
1388 /* Predicate function for immediate operand which fits to byte (8bit) */
1391 byte_immediate_operand (rtx op
, enum machine_mode mode ATTRIBUTE_UNUSED
)
1393 return (GET_CODE (op
) == CONST_INT
1394 && INTVAL (op
) <= 0xff && INTVAL (op
) >= 0);
1397 /* Output all insn addresses and their sizes into the assembly language
1398 output file. This is helpful for debugging whether the length attributes
1399 in the md file are correct.
1400 Output insn cost for next insn. */
1403 final_prescan_insn (rtx insn
, rtx
*operand ATTRIBUTE_UNUSED
,
1404 int num_operands ATTRIBUTE_UNUSED
)
1406 int uid
= INSN_UID (insn
);
1408 if (TARGET_INSN_SIZE_DUMP
|| TARGET_ALL_DEBUG
)
1410 fprintf (asm_out_file
, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
1411 INSN_ADDRESSES (uid
),
1412 INSN_ADDRESSES (uid
) - last_insn_address
,
1413 rtx_cost (PATTERN (insn
), INSN
));
1415 last_insn_address
= INSN_ADDRESSES (uid
);
1418 /* Return 0 if undefined, 1 if always true or always false. */
1421 avr_simplify_comparison_p (enum machine_mode mode
, RTX_CODE
operator, rtx x
)
1423 unsigned int max
= (mode
== QImode
? 0xff :
1424 mode
== HImode
? 0xffff :
1425 mode
== SImode
? 0xffffffff : 0);
1426 if (max
&& operator && GET_CODE (x
) == CONST_INT
)
1428 if (unsigned_condition (operator) != operator)
1431 if (max
!= (INTVAL (x
) & max
)
1432 && INTVAL (x
) != 0xff)
1439 /* Returns nonzero if REGNO is the number of a hard
1440 register in which function arguments are sometimes passed. */
1443 function_arg_regno_p(int r
)
1445 return (r
>= 8 && r
<= 25);
1448 /* Initializing the variable cum for the state at the beginning
1449 of the argument list. */
1452 init_cumulative_args (CUMULATIVE_ARGS
*cum
, tree fntype
, rtx libname
,
1453 tree fndecl ATTRIBUTE_UNUSED
)
1456 cum
->regno
= FIRST_CUM_REG
;
1457 if (!libname
&& fntype
)
1459 int stdarg
= (TYPE_ARG_TYPES (fntype
) != 0
1460 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype
)))
1461 != void_type_node
));
1467 /* Returns the number of registers to allocate for a function argument. */
1470 avr_num_arg_regs (enum machine_mode mode
, tree type
)
1474 if (mode
== BLKmode
)
1475 size
= int_size_in_bytes (type
);
1477 size
= GET_MODE_SIZE (mode
);
1479 /* Align all function arguments to start in even-numbered registers.
1480 Odd-sized arguments leave holes above them. */
1482 return (size
+ 1) & ~1;
1485 /* Controls whether a function argument is passed
1486 in a register, and which register. */
1489 function_arg (CUMULATIVE_ARGS
*cum
, enum machine_mode mode
, tree type
,
1490 int named ATTRIBUTE_UNUSED
)
1492 int bytes
= avr_num_arg_regs (mode
, type
);
1494 if (cum
->nregs
&& bytes
<= cum
->nregs
)
1495 return gen_rtx_REG (mode
, cum
->regno
- bytes
);
1500 /* Update the summarizer variable CUM to advance past an argument
1501 in the argument list. */
1504 function_arg_advance (CUMULATIVE_ARGS
*cum
, enum machine_mode mode
, tree type
,
1505 int named ATTRIBUTE_UNUSED
)
1507 int bytes
= avr_num_arg_regs (mode
, type
);
1509 cum
->nregs
-= bytes
;
1510 cum
->regno
-= bytes
;
1512 if (cum
->nregs
<= 0)
1515 cum
->regno
= FIRST_CUM_REG
;
1519 /***********************************************************************
1520 Functions for outputting various mov's for a various modes
1521 ************************************************************************/
1523 output_movqi (rtx insn
, rtx operands
[], int *l
)
1526 rtx dest
= operands
[0];
1527 rtx src
= operands
[1];
1535 if (register_operand (dest
, QImode
))
1537 if (register_operand (src
, QImode
)) /* mov r,r */
1539 if (test_hard_reg_class (STACK_REG
, dest
))
1540 return AS2 (out
,%0,%1);
1541 else if (test_hard_reg_class (STACK_REG
, src
))
1542 return AS2 (in
,%0,%1);
1544 return AS2 (mov
,%0,%1);
1546 else if (CONSTANT_P (src
))
1548 if (test_hard_reg_class (LD_REGS
, dest
)) /* ldi d,i */
1549 return AS2 (ldi
,%0,lo8(%1));
1551 if (GET_CODE (src
) == CONST_INT
)
1553 if (src
== const0_rtx
) /* mov r,L */
1554 return AS1 (clr
,%0);
1555 else if (src
== const1_rtx
)
1558 return (AS1 (clr
,%0) CR_TAB
1561 else if (src
== constm1_rtx
)
1563 /* Immediate constants -1 to any register */
1565 return (AS1 (clr
,%0) CR_TAB
1570 int bit_nr
= exact_log2 (INTVAL (src
));
1576 output_asm_insn ((AS1 (clr
,%0) CR_TAB
1579 avr_output_bld (operands
, bit_nr
);
1586 /* Last resort, larger than loading from memory. */
1588 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1589 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
1590 AS2 (mov
,%0,r31
) CR_TAB
1591 AS2 (mov
,r31
,__tmp_reg__
));
1593 else if (GET_CODE (src
) == MEM
)
1594 return out_movqi_r_mr (insn
, operands
, real_l
); /* mov r,m */
1596 else if (GET_CODE (dest
) == MEM
)
1598 const char *template;
1600 if (src
== const0_rtx
)
1601 operands
[1] = zero_reg_rtx
;
1603 template = out_movqi_mr_r (insn
, operands
, real_l
);
1606 output_asm_insn (template, operands
);
1615 output_movhi (rtx insn
, rtx operands
[], int *l
)
1618 rtx dest
= operands
[0];
1619 rtx src
= operands
[1];
1625 if (register_operand (dest
, HImode
))
1627 if (register_operand (src
, HImode
)) /* mov r,r */
1629 if (test_hard_reg_class (STACK_REG
, dest
))
1631 if (TARGET_TINY_STACK
)
1634 return AS2 (out
,__SP_L__
,%A1
);
1636 else if (TARGET_NO_INTERRUPTS
)
1639 return (AS2 (out
,__SP_H__
,%B1
) CR_TAB
1640 AS2 (out
,__SP_L__
,%A1
));
1644 return (AS2 (in
,__tmp_reg__
,__SREG__
) CR_TAB
1646 AS2 (out
,__SP_H__
,%B1
) CR_TAB
1647 AS2 (out
,__SREG__
,__tmp_reg__
) CR_TAB
1648 AS2 (out
,__SP_L__
,%A1
));
1650 else if (test_hard_reg_class (STACK_REG
, src
))
1653 return (AS2 (in
,%A0
,__SP_L__
) CR_TAB
1654 AS2 (in
,%B0
,__SP_H__
));
1660 return (AS2 (movw
,%0,%1));
1663 if (true_regnum (dest
) > true_regnum (src
))
1666 return (AS2 (mov
,%B0
,%B1
) CR_TAB
1672 return (AS2 (mov
,%A0
,%A1
) CR_TAB
1676 else if (CONSTANT_P (src
))
1678 if (test_hard_reg_class (LD_REGS
, dest
)) /* ldi d,i */
1681 return (AS2 (ldi
,%A0
,lo8(%1)) CR_TAB
1682 AS2 (ldi
,%B0
,hi8(%1)));
1685 if (GET_CODE (src
) == CONST_INT
)
1687 if (src
== const0_rtx
) /* mov r,L */
1690 return (AS1 (clr
,%A0
) CR_TAB
1693 else if (src
== const1_rtx
)
1696 return (AS1 (clr
,%A0
) CR_TAB
1697 AS1 (clr
,%B0
) CR_TAB
1700 else if (src
== constm1_rtx
)
1702 /* Immediate constants -1 to any register */
1704 return (AS1 (clr
,%0) CR_TAB
1705 AS1 (dec
,%A0
) CR_TAB
1710 int bit_nr
= exact_log2 (INTVAL (src
));
1716 output_asm_insn ((AS1 (clr
,%A0
) CR_TAB
1717 AS1 (clr
,%B0
) CR_TAB
1720 avr_output_bld (operands
, bit_nr
);
1726 if ((INTVAL (src
) & 0xff) == 0)
1729 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1730 AS1 (clr
,%A0
) CR_TAB
1731 AS2 (ldi
,r31
,hi8(%1)) CR_TAB
1732 AS2 (mov
,%B0
,r31
) CR_TAB
1733 AS2 (mov
,r31
,__tmp_reg__
));
1735 else if ((INTVAL (src
) & 0xff00) == 0)
1738 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1739 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
1740 AS2 (mov
,%A0
,r31
) CR_TAB
1741 AS1 (clr
,%B0
) CR_TAB
1742 AS2 (mov
,r31
,__tmp_reg__
));
1746 /* Last resort, equal to loading from memory. */
1748 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1749 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
1750 AS2 (mov
,%A0
,r31
) CR_TAB
1751 AS2 (ldi
,r31
,hi8(%1)) CR_TAB
1752 AS2 (mov
,%B0
,r31
) CR_TAB
1753 AS2 (mov
,r31
,__tmp_reg__
));
1755 else if (GET_CODE (src
) == MEM
)
1756 return out_movhi_r_mr (insn
, operands
, real_l
); /* mov r,m */
1758 else if (GET_CODE (dest
) == MEM
)
1760 const char *template;
1762 if (src
== const0_rtx
)
1763 operands
[1] = zero_reg_rtx
;
1765 template = out_movhi_mr_r (insn
, operands
, real_l
);
1768 output_asm_insn (template, operands
);
1773 fatal_insn ("invalid insn:", insn
);
1778 out_movqi_r_mr (rtx insn
, rtx op
[], int *l
)
1782 rtx x
= XEXP (src
, 0);
1788 if (CONSTANT_ADDRESS_P (x
))
1790 if (avr_io_address_p (x
, 1))
1793 return AS2 (in
,%0,%1-0x20);
1796 return AS2 (lds
,%0,%1);
1798 /* memory access by reg+disp */
1799 else if (GET_CODE (x
) == PLUS
1800 && REG_P (XEXP (x
,0))
1801 && GET_CODE (XEXP (x
,1)) == CONST_INT
)
1803 if ((INTVAL (XEXP (x
,1)) - GET_MODE_SIZE (GET_MODE (src
))) >= 63)
1805 int disp
= INTVAL (XEXP (x
,1));
1806 if (REGNO (XEXP (x
,0)) != REG_Y
)
1807 fatal_insn ("incorrect insn:",insn
);
1809 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
1810 return *l
= 3, (AS2 (adiw
,r28
,%o1
-63) CR_TAB
1811 AS2 (ldd
,%0,Y
+63) CR_TAB
1812 AS2 (sbiw
,r28
,%o1
-63));
1814 return *l
= 5, (AS2 (subi
,r28
,lo8(-%o1
)) CR_TAB
1815 AS2 (sbci
,r29
,hi8(-%o1
)) CR_TAB
1816 AS2 (ld
,%0,Y
) CR_TAB
1817 AS2 (subi
,r28
,lo8(%o1
)) CR_TAB
1818 AS2 (sbci
,r29
,hi8(%o1
)));
1820 else if (REGNO (XEXP (x
,0)) == REG_X
)
1822 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
1823 it but I have this situation with extremal optimizing options. */
1824 if (reg_overlap_mentioned_p (dest
, XEXP (x
,0))
1825 || reg_unused_after (insn
, XEXP (x
,0)))
1826 return *l
= 2, (AS2 (adiw
,r26
,%o1
) CR_TAB
1829 return *l
= 3, (AS2 (adiw
,r26
,%o1
) CR_TAB
1830 AS2 (ld
,%0,X
) CR_TAB
1831 AS2 (sbiw
,r26
,%o1
));
1834 return AS2 (ldd
,%0,%1);
1837 return AS2 (ld
,%0,%1);
1841 out_movhi_r_mr (rtx insn
, rtx op
[], int *l
)
1845 rtx base
= XEXP (src
, 0);
1846 int reg_dest
= true_regnum (dest
);
1847 int reg_base
= true_regnum (base
);
1848 /* "volatile" forces reading low byte first, even if less efficient,
1849 for correct operation with 16-bit I/O registers. */
1850 int mem_volatile_p
= MEM_VOLATILE_P (src
);
1858 if (reg_dest
== reg_base
) /* R = (R) */
1861 return (AS2 (ld
,__tmp_reg__
,%1+) CR_TAB
1862 AS2 (ld
,%B0
,%1) CR_TAB
1863 AS2 (mov
,%A0
,__tmp_reg__
));
1865 else if (reg_base
== REG_X
) /* (R26) */
1867 if (reg_unused_after (insn
, base
))
1870 return (AS2 (ld
,%A0
,X
+) CR_TAB
1874 return (AS2 (ld
,%A0
,X
+) CR_TAB
1875 AS2 (ld
,%B0
,X
) CR_TAB
1881 return (AS2 (ld
,%A0
,%1) CR_TAB
1882 AS2 (ldd
,%B0
,%1+1));
1885 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
1887 int disp
= INTVAL (XEXP (base
, 1));
1888 int reg_base
= true_regnum (XEXP (base
, 0));
1890 if (disp
> MAX_LD_OFFSET (GET_MODE (src
)))
1892 if (REGNO (XEXP (base
, 0)) != REG_Y
)
1893 fatal_insn ("incorrect insn:",insn
);
1895 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
1896 return *l
= 4, (AS2 (adiw
,r28
,%o1
-62) CR_TAB
1897 AS2 (ldd
,%A0
,Y
+62) CR_TAB
1898 AS2 (ldd
,%B0
,Y
+63) CR_TAB
1899 AS2 (sbiw
,r28
,%o1
-62));
1901 return *l
= 6, (AS2 (subi
,r28
,lo8(-%o1
)) CR_TAB
1902 AS2 (sbci
,r29
,hi8(-%o1
)) CR_TAB
1903 AS2 (ld
,%A0
,Y
) CR_TAB
1904 AS2 (ldd
,%B0
,Y
+1) CR_TAB
1905 AS2 (subi
,r28
,lo8(%o1
)) CR_TAB
1906 AS2 (sbci
,r29
,hi8(%o1
)));
1908 if (reg_base
== REG_X
)
1910 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
1911 it but I have this situation with extremal
1912 optimization options. */
1915 if (reg_base
== reg_dest
)
1916 return (AS2 (adiw
,r26
,%o1
) CR_TAB
1917 AS2 (ld
,__tmp_reg__
,X
+) CR_TAB
1918 AS2 (ld
,%B0
,X
) CR_TAB
1919 AS2 (mov
,%A0
,__tmp_reg__
));
1921 return (AS2 (adiw
,r26
,%o1
) CR_TAB
1922 AS2 (ld
,%A0
,X
+) CR_TAB
1923 AS2 (ld
,%B0
,X
) CR_TAB
1924 AS2 (sbiw
,r26
,%o1
+1));
1927 if (reg_base
== reg_dest
)
1930 return (AS2 (ldd
,__tmp_reg__
,%A1
) CR_TAB
1931 AS2 (ldd
,%B0
,%B1
) CR_TAB
1932 AS2 (mov
,%A0
,__tmp_reg__
));
1936 return (AS2 (ldd
,%A0
,%A1
) CR_TAB
1939 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
1941 if (reg_overlap_mentioned_p (dest
, XEXP (base
, 0)))
1942 fatal_insn ("incorrect insn:", insn
);
1946 if (REGNO (XEXP (base
, 0)) == REG_X
)
1949 return (AS2 (sbiw
,r26
,2) CR_TAB
1950 AS2 (ld
,%A0
,X
+) CR_TAB
1951 AS2 (ld
,%B0
,X
) CR_TAB
1957 return (AS2 (sbiw
,%r1
,2) CR_TAB
1958 AS2 (ld
,%A0
,%p1
) CR_TAB
1959 AS2 (ldd
,%B0
,%p1
+1));
1964 return (AS2 (ld
,%B0
,%1) CR_TAB
1967 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
1969 if (reg_overlap_mentioned_p (dest
, XEXP (base
, 0)))
1970 fatal_insn ("incorrect insn:", insn
);
1973 return (AS2 (ld
,%A0
,%1) CR_TAB
1976 else if (CONSTANT_ADDRESS_P (base
))
1978 if (avr_io_address_p (base
, 2))
1981 return (AS2 (in
,%A0
,%A1
-0x20) CR_TAB
1982 AS2 (in
,%B0
,%B1
-0x20));
1985 return (AS2 (lds
,%A0
,%A1
) CR_TAB
1989 fatal_insn ("unknown move insn:",insn
);
1994 out_movsi_r_mr (rtx insn
, rtx op
[], int *l
)
1998 rtx base
= XEXP (src
, 0);
1999 int reg_dest
= true_regnum (dest
);
2000 int reg_base
= true_regnum (base
);
2008 if (reg_base
== REG_X
) /* (R26) */
2010 if (reg_dest
== REG_X
)
2011 /* "ld r26,-X" is undefined */
2012 return *l
=7, (AS2 (adiw
,r26
,3) CR_TAB
2013 AS2 (ld
,r29
,X
) CR_TAB
2014 AS2 (ld
,r28
,-X
) CR_TAB
2015 AS2 (ld
,__tmp_reg__
,-X
) CR_TAB
2016 AS2 (sbiw
,r26
,1) CR_TAB
2017 AS2 (ld
,r26
,X
) CR_TAB
2018 AS2 (mov
,r27
,__tmp_reg__
));
2019 else if (reg_dest
== REG_X
- 2)
2020 return *l
=5, (AS2 (ld
,%A0
,X
+) CR_TAB
2021 AS2 (ld
,%B0
,X
+) CR_TAB
2022 AS2 (ld
,__tmp_reg__
,X
+) CR_TAB
2023 AS2 (ld
,%D0
,X
) CR_TAB
2024 AS2 (mov
,%C0
,__tmp_reg__
));
2025 else if (reg_unused_after (insn
, base
))
2026 return *l
=4, (AS2 (ld
,%A0
,X
+) CR_TAB
2027 AS2 (ld
,%B0
,X
+) CR_TAB
2028 AS2 (ld
,%C0
,X
+) CR_TAB
2031 return *l
=5, (AS2 (ld
,%A0
,X
+) CR_TAB
2032 AS2 (ld
,%B0
,X
+) CR_TAB
2033 AS2 (ld
,%C0
,X
+) CR_TAB
2034 AS2 (ld
,%D0
,X
) CR_TAB
2039 if (reg_dest
== reg_base
)
2040 return *l
=5, (AS2 (ldd
,%D0
,%1+3) CR_TAB
2041 AS2 (ldd
,%C0
,%1+2) CR_TAB
2042 AS2 (ldd
,__tmp_reg__
,%1+1) CR_TAB
2043 AS2 (ld
,%A0
,%1) CR_TAB
2044 AS2 (mov
,%B0
,__tmp_reg__
));
2045 else if (reg_base
== reg_dest
+ 2)
2046 return *l
=5, (AS2 (ld
,%A0
,%1) CR_TAB
2047 AS2 (ldd
,%B0
,%1+1) CR_TAB
2048 AS2 (ldd
,__tmp_reg__
,%1+2) CR_TAB
2049 AS2 (ldd
,%D0
,%1+3) CR_TAB
2050 AS2 (mov
,%C0
,__tmp_reg__
));
2052 return *l
=4, (AS2 (ld
,%A0
,%1) CR_TAB
2053 AS2 (ldd
,%B0
,%1+1) CR_TAB
2054 AS2 (ldd
,%C0
,%1+2) CR_TAB
2055 AS2 (ldd
,%D0
,%1+3));
2058 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
2060 int disp
= INTVAL (XEXP (base
, 1));
2062 if (disp
> MAX_LD_OFFSET (GET_MODE (src
)))
2064 if (REGNO (XEXP (base
, 0)) != REG_Y
)
2065 fatal_insn ("incorrect insn:",insn
);
2067 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
2068 return *l
= 6, (AS2 (adiw
,r28
,%o1
-60) CR_TAB
2069 AS2 (ldd
,%A0
,Y
+60) CR_TAB
2070 AS2 (ldd
,%B0
,Y
+61) CR_TAB
2071 AS2 (ldd
,%C0
,Y
+62) CR_TAB
2072 AS2 (ldd
,%D0
,Y
+63) CR_TAB
2073 AS2 (sbiw
,r28
,%o1
-60));
2075 return *l
= 8, (AS2 (subi
,r28
,lo8(-%o1
)) CR_TAB
2076 AS2 (sbci
,r29
,hi8(-%o1
)) CR_TAB
2077 AS2 (ld
,%A0
,Y
) CR_TAB
2078 AS2 (ldd
,%B0
,Y
+1) CR_TAB
2079 AS2 (ldd
,%C0
,Y
+2) CR_TAB
2080 AS2 (ldd
,%D0
,Y
+3) CR_TAB
2081 AS2 (subi
,r28
,lo8(%o1
)) CR_TAB
2082 AS2 (sbci
,r29
,hi8(%o1
)));
2085 reg_base
= true_regnum (XEXP (base
, 0));
2086 if (reg_base
== REG_X
)
2089 if (reg_dest
== REG_X
)
2092 /* "ld r26,-X" is undefined */
2093 return (AS2 (adiw
,r26
,%o1
+3) CR_TAB
2094 AS2 (ld
,r29
,X
) CR_TAB
2095 AS2 (ld
,r28
,-X
) CR_TAB
2096 AS2 (ld
,__tmp_reg__
,-X
) CR_TAB
2097 AS2 (sbiw
,r26
,1) CR_TAB
2098 AS2 (ld
,r26
,X
) CR_TAB
2099 AS2 (mov
,r27
,__tmp_reg__
));
2102 if (reg_dest
== REG_X
- 2)
2103 return (AS2 (adiw
,r26
,%o1
) CR_TAB
2104 AS2 (ld
,r24
,X
+) CR_TAB
2105 AS2 (ld
,r25
,X
+) CR_TAB
2106 AS2 (ld
,__tmp_reg__
,X
+) CR_TAB
2107 AS2 (ld
,r27
,X
) CR_TAB
2108 AS2 (mov
,r26
,__tmp_reg__
));
2110 return (AS2 (adiw
,r26
,%o1
) CR_TAB
2111 AS2 (ld
,%A0
,X
+) CR_TAB
2112 AS2 (ld
,%B0
,X
+) CR_TAB
2113 AS2 (ld
,%C0
,X
+) CR_TAB
2114 AS2 (ld
,%D0
,X
) CR_TAB
2115 AS2 (sbiw
,r26
,%o1
+3));
2117 if (reg_dest
== reg_base
)
2118 return *l
=5, (AS2 (ldd
,%D0
,%D1
) CR_TAB
2119 AS2 (ldd
,%C0
,%C1
) CR_TAB
2120 AS2 (ldd
,__tmp_reg__
,%B1
) CR_TAB
2121 AS2 (ldd
,%A0
,%A1
) CR_TAB
2122 AS2 (mov
,%B0
,__tmp_reg__
));
2123 else if (reg_dest
== reg_base
- 2)
2124 return *l
=5, (AS2 (ldd
,%A0
,%A1
) CR_TAB
2125 AS2 (ldd
,%B0
,%B1
) CR_TAB
2126 AS2 (ldd
,__tmp_reg__
,%C1
) CR_TAB
2127 AS2 (ldd
,%D0
,%D1
) CR_TAB
2128 AS2 (mov
,%C0
,__tmp_reg__
));
2129 return *l
=4, (AS2 (ldd
,%A0
,%A1
) CR_TAB
2130 AS2 (ldd
,%B0
,%B1
) CR_TAB
2131 AS2 (ldd
,%C0
,%C1
) CR_TAB
2134 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2135 return *l
=4, (AS2 (ld
,%D0
,%1) CR_TAB
2136 AS2 (ld
,%C0
,%1) CR_TAB
2137 AS2 (ld
,%B0
,%1) CR_TAB
2139 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2140 return *l
=4, (AS2 (ld
,%A0
,%1) CR_TAB
2141 AS2 (ld
,%B0
,%1) CR_TAB
2142 AS2 (ld
,%C0
,%1) CR_TAB
2144 else if (CONSTANT_ADDRESS_P (base
))
2145 return *l
=8, (AS2 (lds
,%A0
,%A1
) CR_TAB
2146 AS2 (lds
,%B0
,%B1
) CR_TAB
2147 AS2 (lds
,%C0
,%C1
) CR_TAB
2150 fatal_insn ("unknown move insn:",insn
);
2155 out_movsi_mr_r (rtx insn
, rtx op
[], int *l
)
2159 rtx base
= XEXP (dest
, 0);
2160 int reg_base
= true_regnum (base
);
2161 int reg_src
= true_regnum (src
);
2167 if (CONSTANT_ADDRESS_P (base
))
2168 return *l
=8,(AS2 (sts
,%A0
,%A1
) CR_TAB
2169 AS2 (sts
,%B0
,%B1
) CR_TAB
2170 AS2 (sts
,%C0
,%C1
) CR_TAB
2172 if (reg_base
> 0) /* (r) */
2174 if (reg_base
== REG_X
) /* (R26) */
2176 if (reg_src
== REG_X
)
2178 /* "st X+,r26" is undefined */
2179 if (reg_unused_after (insn
, base
))
2180 return *l
=6, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2181 AS2 (st
,X
,r26
) CR_TAB
2182 AS2 (adiw
,r26
,1) CR_TAB
2183 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2184 AS2 (st
,X
+,r28
) CR_TAB
2187 return *l
=7, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2188 AS2 (st
,X
,r26
) CR_TAB
2189 AS2 (adiw
,r26
,1) CR_TAB
2190 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2191 AS2 (st
,X
+,r28
) CR_TAB
2192 AS2 (st
,X
,r29
) CR_TAB
2195 else if (reg_base
== reg_src
+ 2)
2197 if (reg_unused_after (insn
, base
))
2198 return *l
=7, (AS2 (mov
,__zero_reg__
,%C1
) CR_TAB
2199 AS2 (mov
,__tmp_reg__
,%D1
) CR_TAB
2200 AS2 (st
,%0+,%A1
) CR_TAB
2201 AS2 (st
,%0+,%B1
) CR_TAB
2202 AS2 (st
,%0+,__zero_reg__
) CR_TAB
2203 AS2 (st
,%0,__tmp_reg__
) CR_TAB
2204 AS1 (clr
,__zero_reg__
));
2206 return *l
=8, (AS2 (mov
,__zero_reg__
,%C1
) CR_TAB
2207 AS2 (mov
,__tmp_reg__
,%D1
) CR_TAB
2208 AS2 (st
,%0+,%A1
) CR_TAB
2209 AS2 (st
,%0+,%B1
) CR_TAB
2210 AS2 (st
,%0+,__zero_reg__
) CR_TAB
2211 AS2 (st
,%0,__tmp_reg__
) CR_TAB
2212 AS1 (clr
,__zero_reg__
) CR_TAB
2215 return *l
=5, (AS2 (st
,%0+,%A1
) CR_TAB
2216 AS2 (st
,%0+,%B1
) CR_TAB
2217 AS2 (st
,%0+,%C1
) CR_TAB
2218 AS2 (st
,%0,%D1
) CR_TAB
2222 return *l
=4, (AS2 (st
,%0,%A1
) CR_TAB
2223 AS2 (std
,%0+1,%B1
) CR_TAB
2224 AS2 (std
,%0+2,%C1
) CR_TAB
2225 AS2 (std
,%0+3,%D1
));
2227 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
2229 int disp
= INTVAL (XEXP (base
, 1));
2230 reg_base
= REGNO (XEXP (base
, 0));
2231 if (disp
> MAX_LD_OFFSET (GET_MODE (dest
)))
2233 if (reg_base
!= REG_Y
)
2234 fatal_insn ("incorrect insn:",insn
);
2236 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
2237 return *l
= 6, (AS2 (adiw
,r28
,%o0
-60) CR_TAB
2238 AS2 (std
,Y
+60,%A1
) CR_TAB
2239 AS2 (std
,Y
+61,%B1
) CR_TAB
2240 AS2 (std
,Y
+62,%C1
) CR_TAB
2241 AS2 (std
,Y
+63,%D1
) CR_TAB
2242 AS2 (sbiw
,r28
,%o0
-60));
2244 return *l
= 8, (AS2 (subi
,r28
,lo8(-%o0
)) CR_TAB
2245 AS2 (sbci
,r29
,hi8(-%o0
)) CR_TAB
2246 AS2 (st
,Y
,%A1
) CR_TAB
2247 AS2 (std
,Y
+1,%B1
) CR_TAB
2248 AS2 (std
,Y
+2,%C1
) CR_TAB
2249 AS2 (std
,Y
+3,%D1
) CR_TAB
2250 AS2 (subi
,r28
,lo8(%o0
)) CR_TAB
2251 AS2 (sbci
,r29
,hi8(%o0
)));
2253 if (reg_base
== REG_X
)
2256 if (reg_src
== REG_X
)
2259 return (AS2 (mov
,__tmp_reg__
,r26
) CR_TAB
2260 AS2 (mov
,__zero_reg__
,r27
) CR_TAB
2261 AS2 (adiw
,r26
,%o0
) CR_TAB
2262 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2263 AS2 (st
,X
+,__zero_reg__
) CR_TAB
2264 AS2 (st
,X
+,r28
) CR_TAB
2265 AS2 (st
,X
,r29
) CR_TAB
2266 AS1 (clr
,__zero_reg__
) CR_TAB
2267 AS2 (sbiw
,r26
,%o0
+3));
2269 else if (reg_src
== REG_X
- 2)
2272 return (AS2 (mov
,__tmp_reg__
,r26
) CR_TAB
2273 AS2 (mov
,__zero_reg__
,r27
) CR_TAB
2274 AS2 (adiw
,r26
,%o0
) CR_TAB
2275 AS2 (st
,X
+,r24
) CR_TAB
2276 AS2 (st
,X
+,r25
) CR_TAB
2277 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2278 AS2 (st
,X
,__zero_reg__
) CR_TAB
2279 AS1 (clr
,__zero_reg__
) CR_TAB
2280 AS2 (sbiw
,r26
,%o0
+3));
2283 return (AS2 (adiw
,r26
,%o0
) CR_TAB
2284 AS2 (st
,X
+,%A1
) CR_TAB
2285 AS2 (st
,X
+,%B1
) CR_TAB
2286 AS2 (st
,X
+,%C1
) CR_TAB
2287 AS2 (st
,X
,%D1
) CR_TAB
2288 AS2 (sbiw
,r26
,%o0
+3));
2290 return *l
=4, (AS2 (std
,%A0
,%A1
) CR_TAB
2291 AS2 (std
,%B0
,%B1
) CR_TAB
2292 AS2 (std
,%C0
,%C1
) CR_TAB
2295 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2296 return *l
=4, (AS2 (st
,%0,%D1
) CR_TAB
2297 AS2 (st
,%0,%C1
) CR_TAB
2298 AS2 (st
,%0,%B1
) CR_TAB
2300 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2301 return *l
=4, (AS2 (st
,%0,%A1
) CR_TAB
2302 AS2 (st
,%0,%B1
) CR_TAB
2303 AS2 (st
,%0,%C1
) CR_TAB
2305 fatal_insn ("unknown move insn:",insn
);
2310 output_movsisf(rtx insn
, rtx operands
[], int *l
)
2313 rtx dest
= operands
[0];
2314 rtx src
= operands
[1];
2320 if (register_operand (dest
, VOIDmode
))
2322 if (register_operand (src
, VOIDmode
)) /* mov r,r */
2324 if (true_regnum (dest
) > true_regnum (src
))
2329 return (AS2 (movw
,%C0
,%C1
) CR_TAB
2330 AS2 (movw
,%A0
,%A1
));
2333 return (AS2 (mov
,%D0
,%D1
) CR_TAB
2334 AS2 (mov
,%C0
,%C1
) CR_TAB
2335 AS2 (mov
,%B0
,%B1
) CR_TAB
2343 return (AS2 (movw
,%A0
,%A1
) CR_TAB
2344 AS2 (movw
,%C0
,%C1
));
2347 return (AS2 (mov
,%A0
,%A1
) CR_TAB
2348 AS2 (mov
,%B0
,%B1
) CR_TAB
2349 AS2 (mov
,%C0
,%C1
) CR_TAB
2353 else if (CONSTANT_P (src
))
2355 if (test_hard_reg_class (LD_REGS
, dest
)) /* ldi d,i */
2358 return (AS2 (ldi
,%A0
,lo8(%1)) CR_TAB
2359 AS2 (ldi
,%B0
,hi8(%1)) CR_TAB
2360 AS2 (ldi
,%C0
,hlo8(%1)) CR_TAB
2361 AS2 (ldi
,%D0
,hhi8(%1)));
2364 if (GET_CODE (src
) == CONST_INT
)
2366 const char *const clr_op0
=
2367 AVR_ENHANCED
? (AS1 (clr
,%A0
) CR_TAB
2368 AS1 (clr
,%B0
) CR_TAB
2370 : (AS1 (clr
,%A0
) CR_TAB
2371 AS1 (clr
,%B0
) CR_TAB
2372 AS1 (clr
,%C0
) CR_TAB
2375 if (src
== const0_rtx
) /* mov r,L */
2377 *l
= AVR_ENHANCED
? 3 : 4;
2380 else if (src
== const1_rtx
)
2383 output_asm_insn (clr_op0
, operands
);
2384 *l
= AVR_ENHANCED
? 4 : 5;
2385 return AS1 (inc
,%A0
);
2387 else if (src
== constm1_rtx
)
2389 /* Immediate constants -1 to any register */
2393 return (AS1 (clr
,%A0
) CR_TAB
2394 AS1 (dec
,%A0
) CR_TAB
2395 AS2 (mov
,%B0
,%A0
) CR_TAB
2396 AS2 (movw
,%C0
,%A0
));
2399 return (AS1 (clr
,%A0
) CR_TAB
2400 AS1 (dec
,%A0
) CR_TAB
2401 AS2 (mov
,%B0
,%A0
) CR_TAB
2402 AS2 (mov
,%C0
,%A0
) CR_TAB
2407 int bit_nr
= exact_log2 (INTVAL (src
));
2411 *l
= AVR_ENHANCED
? 5 : 6;
2414 output_asm_insn (clr_op0
, operands
);
2415 output_asm_insn ("set", operands
);
2418 avr_output_bld (operands
, bit_nr
);
2425 /* Last resort, better than loading from memory. */
2427 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
2428 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
2429 AS2 (mov
,%A0
,r31
) CR_TAB
2430 AS2 (ldi
,r31
,hi8(%1)) CR_TAB
2431 AS2 (mov
,%B0
,r31
) CR_TAB
2432 AS2 (ldi
,r31
,hlo8(%1)) CR_TAB
2433 AS2 (mov
,%C0
,r31
) CR_TAB
2434 AS2 (ldi
,r31
,hhi8(%1)) CR_TAB
2435 AS2 (mov
,%D0
,r31
) CR_TAB
2436 AS2 (mov
,r31
,__tmp_reg__
));
2438 else if (GET_CODE (src
) == MEM
)
2439 return out_movsi_r_mr (insn
, operands
, real_l
); /* mov r,m */
2441 else if (GET_CODE (dest
) == MEM
)
2443 const char *template;
2445 if (src
== const0_rtx
)
2446 operands
[1] = zero_reg_rtx
;
2448 template = out_movsi_mr_r (insn
, operands
, real_l
);
2451 output_asm_insn (template, operands
);
2456 fatal_insn ("invalid insn:", insn
);
2461 out_movqi_mr_r (rtx insn
, rtx op
[], int *l
)
2465 rtx x
= XEXP (dest
, 0);
2471 if (CONSTANT_ADDRESS_P (x
))
2473 if (avr_io_address_p (x
, 1))
2476 return AS2 (out
,%0-0x20,%1);
2479 return AS2 (sts
,%0,%1);
2481 /* memory access by reg+disp */
2482 else if (GET_CODE (x
) == PLUS
2483 && REG_P (XEXP (x
,0))
2484 && GET_CODE (XEXP (x
,1)) == CONST_INT
)
2486 if ((INTVAL (XEXP (x
,1)) - GET_MODE_SIZE (GET_MODE (dest
))) >= 63)
2488 int disp
= INTVAL (XEXP (x
,1));
2489 if (REGNO (XEXP (x
,0)) != REG_Y
)
2490 fatal_insn ("incorrect insn:",insn
);
2492 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
2493 return *l
= 3, (AS2 (adiw
,r28
,%o0
-63) CR_TAB
2494 AS2 (std
,Y
+63,%1) CR_TAB
2495 AS2 (sbiw
,r28
,%o0
-63));
2497 return *l
= 5, (AS2 (subi
,r28
,lo8(-%o0
)) CR_TAB
2498 AS2 (sbci
,r29
,hi8(-%o0
)) CR_TAB
2499 AS2 (st
,Y
,%1) CR_TAB
2500 AS2 (subi
,r28
,lo8(%o0
)) CR_TAB
2501 AS2 (sbci
,r29
,hi8(%o0
)));
2503 else if (REGNO (XEXP (x
,0)) == REG_X
)
2505 if (reg_overlap_mentioned_p (src
, XEXP (x
, 0)))
2507 if (reg_unused_after (insn
, XEXP (x
,0)))
2508 return *l
= 3, (AS2 (mov
,__tmp_reg__
,%1) CR_TAB
2509 AS2 (adiw
,r26
,%o0
) CR_TAB
2510 AS2 (st
,X
,__tmp_reg__
));
2512 return *l
= 4, (AS2 (mov
,__tmp_reg__
,%1) CR_TAB
2513 AS2 (adiw
,r26
,%o0
) CR_TAB
2514 AS2 (st
,X
,__tmp_reg__
) CR_TAB
2515 AS2 (sbiw
,r26
,%o0
));
2519 if (reg_unused_after (insn
, XEXP (x
,0)))
2520 return *l
= 2, (AS2 (adiw
,r26
,%o0
) CR_TAB
2523 return *l
= 3, (AS2 (adiw
,r26
,%o0
) CR_TAB
2524 AS2 (st
,X
,%1) CR_TAB
2525 AS2 (sbiw
,r26
,%o0
));
2529 return AS2 (std
,%0,%1);
2532 return AS2 (st
,%0,%1);
2536 out_movhi_mr_r (rtx insn
, rtx op
[], int *l
)
2540 rtx base
= XEXP (dest
, 0);
2541 int reg_base
= true_regnum (base
);
2542 int reg_src
= true_regnum (src
);
2543 /* "volatile" forces writing high byte first, even if less efficient,
2544 for correct operation with 16-bit I/O registers. */
2545 int mem_volatile_p
= MEM_VOLATILE_P (dest
);
2550 if (CONSTANT_ADDRESS_P (base
))
2552 if (avr_io_address_p (base
, 2))
2555 return (AS2 (out
,%B0
-0x20,%B1
) CR_TAB
2556 AS2 (out
,%A0
-0x20,%A1
));
2558 return *l
= 4, (AS2 (sts
,%B0
,%B1
) CR_TAB
2563 if (reg_base
== REG_X
)
2565 if (reg_src
== REG_X
)
2567 /* "st X+,r26" and "st -X,r26" are undefined. */
2568 if (!mem_volatile_p
&& reg_unused_after (insn
, src
))
2569 return *l
=4, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2570 AS2 (st
,X
,r26
) CR_TAB
2571 AS2 (adiw
,r26
,1) CR_TAB
2572 AS2 (st
,X
,__tmp_reg__
));
2574 return *l
=5, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2575 AS2 (adiw
,r26
,1) CR_TAB
2576 AS2 (st
,X
,__tmp_reg__
) CR_TAB
2577 AS2 (sbiw
,r26
,1) CR_TAB
2582 if (!mem_volatile_p
&& reg_unused_after (insn
, base
))
2583 return *l
=2, (AS2 (st
,X
+,%A1
) CR_TAB
2586 return *l
=3, (AS2 (adiw
,r26
,1) CR_TAB
2587 AS2 (st
,X
,%B1
) CR_TAB
2592 return *l
=2, (AS2 (std
,%0+1,%B1
) CR_TAB
2595 else if (GET_CODE (base
) == PLUS
)
2597 int disp
= INTVAL (XEXP (base
, 1));
2598 reg_base
= REGNO (XEXP (base
, 0));
2599 if (disp
> MAX_LD_OFFSET (GET_MODE (dest
)))
2601 if (reg_base
!= REG_Y
)
2602 fatal_insn ("incorrect insn:",insn
);
2604 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
2605 return *l
= 4, (AS2 (adiw
,r28
,%o0
-62) CR_TAB
2606 AS2 (std
,Y
+63,%B1
) CR_TAB
2607 AS2 (std
,Y
+62,%A1
) CR_TAB
2608 AS2 (sbiw
,r28
,%o0
-62));
2610 return *l
= 6, (AS2 (subi
,r28
,lo8(-%o0
)) CR_TAB
2611 AS2 (sbci
,r29
,hi8(-%o0
)) CR_TAB
2612 AS2 (std
,Y
+1,%B1
) CR_TAB
2613 AS2 (st
,Y
,%A1
) CR_TAB
2614 AS2 (subi
,r28
,lo8(%o0
)) CR_TAB
2615 AS2 (sbci
,r29
,hi8(%o0
)));
2617 if (reg_base
== REG_X
)
2620 if (reg_src
== REG_X
)
2623 return (AS2 (mov
,__tmp_reg__
,r26
) CR_TAB
2624 AS2 (mov
,__zero_reg__
,r27
) CR_TAB
2625 AS2 (adiw
,r26
,%o0
+1) CR_TAB
2626 AS2 (st
,X
,__zero_reg__
) CR_TAB
2627 AS2 (st
,-X
,__tmp_reg__
) CR_TAB
2628 AS1 (clr
,__zero_reg__
) CR_TAB
2629 AS2 (sbiw
,r26
,%o0
));
2632 return (AS2 (adiw
,r26
,%o0
+1) CR_TAB
2633 AS2 (st
,X
,%B1
) CR_TAB
2634 AS2 (st
,-X
,%A1
) CR_TAB
2635 AS2 (sbiw
,r26
,%o0
));
2637 return *l
=2, (AS2 (std
,%B0
,%B1
) CR_TAB
2640 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2641 return *l
=2, (AS2 (st
,%0,%B1
) CR_TAB
2643 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2647 if (REGNO (XEXP (base
, 0)) == REG_X
)
2650 return (AS2 (adiw
,r26
,1) CR_TAB
2651 AS2 (st
,X
,%B1
) CR_TAB
2652 AS2 (st
,-X
,%A1
) CR_TAB
2658 return (AS2 (std
,%p0
+1,%B1
) CR_TAB
2659 AS2 (st
,%p0
,%A1
) CR_TAB
2665 return (AS2 (st
,%0,%A1
) CR_TAB
2668 fatal_insn ("unknown move insn:",insn
);
2672 /* Return 1 if frame pointer for current function required. */
2675 frame_pointer_required_p (void)
2677 return (current_function_calls_alloca
2678 || current_function_args_info
.nregs
== 0
2679 || get_frame_size () > 0);
2682 /* Returns the condition of compare insn INSN, or UNKNOWN. */
2685 compare_condition (rtx insn
)
2687 rtx next
= next_real_insn (insn
);
2688 RTX_CODE cond
= UNKNOWN
;
2689 if (next
&& GET_CODE (next
) == JUMP_INSN
)
2691 rtx pat
= PATTERN (next
);
2692 rtx src
= SET_SRC (pat
);
2693 rtx t
= XEXP (src
, 0);
2694 cond
= GET_CODE (t
);
2699 /* Returns nonzero if INSN is a tst insn that only tests the sign. */
2702 compare_sign_p (rtx insn
)
2704 RTX_CODE cond
= compare_condition (insn
);
2705 return (cond
== GE
|| cond
== LT
);
2708 /* Returns nonzero if the next insn is a JUMP_INSN with a condition
2709 that needs to be swapped (GT, GTU, LE, LEU). */
2712 compare_diff_p (rtx insn
)
2714 RTX_CODE cond
= compare_condition (insn
);
2715 return (cond
== GT
|| cond
== GTU
|| cond
== LE
|| cond
== LEU
) ? cond
: 0;
2718 /* Returns nonzero if INSN is a compare insn with the EQ or NE condition. */
2721 compare_eq_p (rtx insn
)
2723 RTX_CODE cond
= compare_condition (insn
);
2724 return (cond
== EQ
|| cond
== NE
);
2728 /* Output test instruction for HImode. */
2731 out_tsthi (rtx insn
, int *l
)
2733 if (compare_sign_p (insn
))
2736 return AS1 (tst
,%B0
);
2738 if (reg_unused_after (insn
, SET_SRC (PATTERN (insn
)))
2739 && compare_eq_p (insn
))
2741 /* Faster than sbiw if we can clobber the operand. */
2743 return AS2 (or,%A0
,%B0
);
2745 if (test_hard_reg_class (ADDW_REGS
, SET_SRC (PATTERN (insn
))))
2748 return AS2 (sbiw
,%0,0);
2751 return (AS2 (cp
,%A0
,__zero_reg__
) CR_TAB
2752 AS2 (cpc
,%B0
,__zero_reg__
));
2756 /* Output test instruction for SImode. */
2759 out_tstsi (rtx insn
, int *l
)
2761 if (compare_sign_p (insn
))
2764 return AS1 (tst
,%D0
);
2766 if (test_hard_reg_class (ADDW_REGS
, SET_SRC (PATTERN (insn
))))
2769 return (AS2 (sbiw
,%A0
,0) CR_TAB
2770 AS2 (cpc
,%C0
,__zero_reg__
) CR_TAB
2771 AS2 (cpc
,%D0
,__zero_reg__
));
2774 return (AS2 (cp
,%A0
,__zero_reg__
) CR_TAB
2775 AS2 (cpc
,%B0
,__zero_reg__
) CR_TAB
2776 AS2 (cpc
,%C0
,__zero_reg__
) CR_TAB
2777 AS2 (cpc
,%D0
,__zero_reg__
));
2781 /* Generate asm equivalent for various shifts.
2782 Shift count is a CONST_INT, MEM or REG.
2783 This only handles cases that are not already
2784 carefully hand-optimized in ?sh??i3_out. */
2787 out_shift_with_cnt (const char *template, rtx insn
, rtx operands
[],
2788 int *len
, int t_len
)
2792 int second_label
= 1;
2793 int saved_in_tmp
= 0;
2794 int use_zero_reg
= 0;
2796 op
[0] = operands
[0];
2797 op
[1] = operands
[1];
2798 op
[2] = operands
[2];
2799 op
[3] = operands
[3];
2805 if (GET_CODE (operands
[2]) == CONST_INT
)
2807 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
2808 int count
= INTVAL (operands
[2]);
2809 int max_len
= 10; /* If larger than this, always use a loop. */
2818 if (count
< 8 && !scratch
)
2822 max_len
= t_len
+ (scratch
? 3 : (use_zero_reg
? 4 : 5));
2824 if (t_len
* count
<= max_len
)
2826 /* Output shifts inline with no loop - faster. */
2828 *len
= t_len
* count
;
2832 output_asm_insn (template, op
);
2841 strcat (str
, AS2 (ldi
,%3,%2));
2843 else if (use_zero_reg
)
2845 /* Hack to save one word: use __zero_reg__ as loop counter.
2846 Set one bit, then shift in a loop until it is 0 again. */
2848 op
[3] = zero_reg_rtx
;
2852 strcat (str
, ("set" CR_TAB
2853 AS2 (bld
,%3,%2-1)));
2857 /* No scratch register available, use one from LD_REGS (saved in
2858 __tmp_reg__) that doesn't overlap with registers to shift. */
2860 op
[3] = gen_rtx_REG (QImode
,
2861 ((true_regnum (operands
[0]) - 1) & 15) + 16);
2862 op
[4] = tmp_reg_rtx
;
2866 *len
= 3; /* Includes "mov %3,%4" after the loop. */
2868 strcat (str
, (AS2 (mov
,%4,%3) CR_TAB
2874 else if (GET_CODE (operands
[2]) == MEM
)
2878 op
[3] = op_mov
[0] = tmp_reg_rtx
;
2882 out_movqi_r_mr (insn
, op_mov
, len
);
2884 output_asm_insn (out_movqi_r_mr (insn
, op_mov
, NULL
), op_mov
);
2886 else if (register_operand (operands
[2], QImode
))
2888 if (reg_unused_after (insn
, operands
[2]))
2892 op
[3] = tmp_reg_rtx
;
2894 strcat (str
, (AS2 (mov
,%3,%2) CR_TAB
));
2898 fatal_insn ("bad shift insn:", insn
);
2905 strcat (str
, AS1 (rjmp
,2f
));
2909 *len
+= t_len
+ 2; /* template + dec + brXX */
2912 strcat (str
, "\n1:\t");
2913 strcat (str
, template);
2914 strcat (str
, second_label
? "\n2:\t" : "\n\t");
2915 strcat (str
, use_zero_reg
? AS1 (lsr
,%3) : AS1 (dec
,%3));
2916 strcat (str
, CR_TAB
);
2917 strcat (str
, second_label
? AS1 (brpl
,1b
) : AS1 (brne
,1b
));
2919 strcat (str
, (CR_TAB
AS2 (mov
,%3,%4)));
2920 output_asm_insn (str
, op
);
2925 /* 8bit shift left ((char)x << i) */
2928 ashlqi3_out (rtx insn
, rtx operands
[], int *len
)
2930 if (GET_CODE (operands
[2]) == CONST_INT
)
2937 switch (INTVAL (operands
[2]))
2940 if (INTVAL (operands
[2]) < 8)
2944 return AS1 (clr
,%0);
2948 return AS1 (lsl
,%0);
2952 return (AS1 (lsl
,%0) CR_TAB
2957 return (AS1 (lsl
,%0) CR_TAB
2962 if (test_hard_reg_class (LD_REGS
, operands
[0]))
2965 return (AS1 (swap
,%0) CR_TAB
2966 AS2 (andi
,%0,0xf0));
2969 return (AS1 (lsl
,%0) CR_TAB
2975 if (test_hard_reg_class (LD_REGS
, operands
[0]))
2978 return (AS1 (swap
,%0) CR_TAB
2980 AS2 (andi
,%0,0xe0));
2983 return (AS1 (lsl
,%0) CR_TAB
2990 if (test_hard_reg_class (LD_REGS
, operands
[0]))
2993 return (AS1 (swap
,%0) CR_TAB
2996 AS2 (andi
,%0,0xc0));
2999 return (AS1 (lsl
,%0) CR_TAB
3008 return (AS1 (ror
,%0) CR_TAB
3013 else if (CONSTANT_P (operands
[2]))
3014 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
3016 out_shift_with_cnt (AS1 (lsl
,%0),
3017 insn
, operands
, len
, 1);
3022 /* 16bit shift left ((short)x << i) */
3025 ashlhi3_out (rtx insn
, rtx operands
[], int *len
)
3027 if (GET_CODE (operands
[2]) == CONST_INT
)
3029 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
3030 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
3037 switch (INTVAL (operands
[2]))
3040 if (INTVAL (operands
[2]) < 16)
3044 return (AS1 (clr
,%B0
) CR_TAB
3048 if (optimize_size
&& scratch
)
3053 return (AS1 (swap
,%A0
) CR_TAB
3054 AS1 (swap
,%B0
) CR_TAB
3055 AS2 (andi
,%B0
,0xf0) CR_TAB
3056 AS2 (eor
,%B0
,%A0
) CR_TAB
3057 AS2 (andi
,%A0
,0xf0) CR_TAB
3063 return (AS1 (swap
,%A0
) CR_TAB
3064 AS1 (swap
,%B0
) CR_TAB
3065 AS2 (ldi
,%3,0xf0) CR_TAB
3066 AS2 (and,%B0
,%3) CR_TAB
3067 AS2 (eor
,%B0
,%A0
) CR_TAB
3068 AS2 (and,%A0
,%3) CR_TAB
3071 break; /* optimize_size ? 6 : 8 */
3075 break; /* scratch ? 5 : 6 */
3079 return (AS1 (lsl
,%A0
) CR_TAB
3080 AS1 (rol
,%B0
) CR_TAB
3081 AS1 (swap
,%A0
) CR_TAB
3082 AS1 (swap
,%B0
) CR_TAB
3083 AS2 (andi
,%B0
,0xf0) CR_TAB
3084 AS2 (eor
,%B0
,%A0
) CR_TAB
3085 AS2 (andi
,%A0
,0xf0) CR_TAB
3091 return (AS1 (lsl
,%A0
) CR_TAB
3092 AS1 (rol
,%B0
) CR_TAB
3093 AS1 (swap
,%A0
) CR_TAB
3094 AS1 (swap
,%B0
) CR_TAB
3095 AS2 (ldi
,%3,0xf0) CR_TAB
3096 AS2 (and,%B0
,%3) CR_TAB
3097 AS2 (eor
,%B0
,%A0
) CR_TAB
3098 AS2 (and,%A0
,%3) CR_TAB
3105 break; /* scratch ? 5 : 6 */
3107 return (AS1 (clr
,__tmp_reg__
) CR_TAB
3108 AS1 (lsr
,%B0
) CR_TAB
3109 AS1 (ror
,%A0
) CR_TAB
3110 AS1 (ror
,__tmp_reg__
) CR_TAB
3111 AS1 (lsr
,%B0
) CR_TAB
3112 AS1 (ror
,%A0
) CR_TAB
3113 AS1 (ror
,__tmp_reg__
) CR_TAB
3114 AS2 (mov
,%B0
,%A0
) CR_TAB
3115 AS2 (mov
,%A0
,__tmp_reg__
));
3119 return (AS1 (lsr
,%B0
) CR_TAB
3120 AS2 (mov
,%B0
,%A0
) CR_TAB
3121 AS1 (clr
,%A0
) CR_TAB
3122 AS1 (ror
,%B0
) CR_TAB
3126 if (true_regnum (operands
[0]) + 1 == true_regnum (operands
[1]))
3127 return *len
= 1, AS1 (clr
,%A0
);
3129 return *len
= 2, (AS2 (mov
,%B0
,%A1
) CR_TAB
3134 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3135 AS1 (clr
,%A0
) CR_TAB
3140 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3141 AS1 (clr
,%A0
) CR_TAB
3142 AS1 (lsl
,%B0
) CR_TAB
3147 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3148 AS1 (clr
,%A0
) CR_TAB
3149 AS1 (lsl
,%B0
) CR_TAB
3150 AS1 (lsl
,%B0
) CR_TAB
3157 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3158 AS1 (clr
,%A0
) CR_TAB
3159 AS1 (swap
,%B0
) CR_TAB
3160 AS2 (andi
,%B0
,0xf0));
3165 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3166 AS1 (clr
,%A0
) CR_TAB
3167 AS1 (swap
,%B0
) CR_TAB
3168 AS2 (ldi
,%3,0xf0) CR_TAB
3172 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3173 AS1 (clr
,%A0
) CR_TAB
3174 AS1 (lsl
,%B0
) CR_TAB
3175 AS1 (lsl
,%B0
) CR_TAB
3176 AS1 (lsl
,%B0
) CR_TAB
3183 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3184 AS1 (clr
,%A0
) CR_TAB
3185 AS1 (swap
,%B0
) CR_TAB
3186 AS1 (lsl
,%B0
) CR_TAB
3187 AS2 (andi
,%B0
,0xe0));
3189 if (AVR_ENHANCED
&& scratch
)
3192 return (AS2 (ldi
,%3,0x20) CR_TAB
3193 AS2 (mul
,%A0
,%3) CR_TAB
3194 AS2 (mov
,%B0
,r0
) CR_TAB
3195 AS1 (clr
,%A0
) CR_TAB
3196 AS1 (clr
,__zero_reg__
));
3198 if (optimize_size
&& scratch
)
3203 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3204 AS1 (clr
,%A0
) CR_TAB
3205 AS1 (swap
,%B0
) CR_TAB
3206 AS1 (lsl
,%B0
) CR_TAB
3207 AS2 (ldi
,%3,0xe0) CR_TAB
3213 return ("set" CR_TAB
3214 AS2 (bld
,r1
,5) CR_TAB
3215 AS2 (mul
,%A0
,r1
) CR_TAB
3216 AS2 (mov
,%B0
,r0
) CR_TAB
3217 AS1 (clr
,%A0
) CR_TAB
3218 AS1 (clr
,__zero_reg__
));
3221 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3222 AS1 (clr
,%A0
) CR_TAB
3223 AS1 (lsl
,%B0
) CR_TAB
3224 AS1 (lsl
,%B0
) CR_TAB
3225 AS1 (lsl
,%B0
) CR_TAB
3226 AS1 (lsl
,%B0
) CR_TAB
3230 if (AVR_ENHANCED
&& ldi_ok
)
3233 return (AS2 (ldi
,%B0
,0x40) CR_TAB
3234 AS2 (mul
,%A0
,%B0
) CR_TAB
3235 AS2 (mov
,%B0
,r0
) CR_TAB
3236 AS1 (clr
,%A0
) CR_TAB
3237 AS1 (clr
,__zero_reg__
));
3239 if (AVR_ENHANCED
&& scratch
)
3242 return (AS2 (ldi
,%3,0x40) CR_TAB
3243 AS2 (mul
,%A0
,%3) CR_TAB
3244 AS2 (mov
,%B0
,r0
) CR_TAB
3245 AS1 (clr
,%A0
) CR_TAB
3246 AS1 (clr
,__zero_reg__
));
3248 if (optimize_size
&& ldi_ok
)
3251 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3252 AS2 (ldi
,%A0
,6) "\n1:\t"
3253 AS1 (lsl
,%B0
) CR_TAB
3254 AS1 (dec
,%A0
) CR_TAB
3257 if (optimize_size
&& scratch
)
3260 return (AS1 (clr
,%B0
) CR_TAB
3261 AS1 (lsr
,%A0
) CR_TAB
3262 AS1 (ror
,%B0
) CR_TAB
3263 AS1 (lsr
,%A0
) CR_TAB
3264 AS1 (ror
,%B0
) CR_TAB
3269 return (AS1 (clr
,%B0
) CR_TAB
3270 AS1 (lsr
,%A0
) CR_TAB
3271 AS1 (ror
,%B0
) CR_TAB
3276 out_shift_with_cnt ((AS1 (lsl
,%A0
) CR_TAB
3278 insn
, operands
, len
, 2);
3283 /* 32bit shift left ((long)x << i) */
3286 ashlsi3_out (rtx insn
, rtx operands
[], int *len
)
3288 if (GET_CODE (operands
[2]) == CONST_INT
)
3296 switch (INTVAL (operands
[2]))
3299 if (INTVAL (operands
[2]) < 32)
3303 return *len
= 3, (AS1 (clr
,%D0
) CR_TAB
3304 AS1 (clr
,%C0
) CR_TAB
3305 AS2 (movw
,%A0
,%C0
));
3307 return (AS1 (clr
,%D0
) CR_TAB
3308 AS1 (clr
,%C0
) CR_TAB
3309 AS1 (clr
,%B0
) CR_TAB
3314 int reg0
= true_regnum (operands
[0]);
3315 int reg1
= true_regnum (operands
[1]);
3318 return (AS2 (mov
,%D0
,%C1
) CR_TAB
3319 AS2 (mov
,%C0
,%B1
) CR_TAB
3320 AS2 (mov
,%B0
,%A1
) CR_TAB
3322 else if (reg0
+ 1 == reg1
)
3325 return AS1 (clr
,%A0
);
3328 return (AS1 (clr
,%A0
) CR_TAB
3329 AS2 (mov
,%B0
,%A1
) CR_TAB
3330 AS2 (mov
,%C0
,%B1
) CR_TAB
3336 int reg0
= true_regnum (operands
[0]);
3337 int reg1
= true_regnum (operands
[1]);
3339 if (AVR_ENHANCED
&& (reg0
+ 2 != reg1
))
3342 return (AS2 (movw
,%C0
,%A1
) CR_TAB
3343 AS1 (clr
,%B0
) CR_TAB
3346 if (reg0
+ 1 >= reg1
)
3347 return (AS2 (mov
,%D0
,%B1
) CR_TAB
3348 AS2 (mov
,%C0
,%A1
) CR_TAB
3349 AS1 (clr
,%B0
) CR_TAB
3351 if (reg0
+ 2 == reg1
)
3354 return (AS1 (clr
,%B0
) CR_TAB
3358 return (AS2 (mov
,%C0
,%A1
) CR_TAB
3359 AS2 (mov
,%D0
,%B1
) CR_TAB
3360 AS1 (clr
,%B0
) CR_TAB
3366 if (true_regnum (operands
[0]) + 3 != true_regnum (operands
[1]))
3367 return (AS2 (mov
,%D0
,%A1
) CR_TAB
3368 AS1 (clr
,%C0
) CR_TAB
3369 AS1 (clr
,%B0
) CR_TAB
3374 return (AS1 (clr
,%C0
) CR_TAB
3375 AS1 (clr
,%B0
) CR_TAB
3381 return (AS1 (clr
,%D0
) CR_TAB
3382 AS1 (lsr
,%A0
) CR_TAB
3383 AS1 (ror
,%D0
) CR_TAB
3384 AS1 (clr
,%C0
) CR_TAB
3385 AS1 (clr
,%B0
) CR_TAB
3390 out_shift_with_cnt ((AS1 (lsl
,%A0
) CR_TAB
3391 AS1 (rol
,%B0
) CR_TAB
3392 AS1 (rol
,%C0
) CR_TAB
3394 insn
, operands
, len
, 4);
3398 /* 8bit arithmetic shift right ((signed char)x >> i) */
3401 ashrqi3_out (rtx insn
, rtx operands
[], int *len
)
3403 if (GET_CODE (operands
[2]) == CONST_INT
)
3410 switch (INTVAL (operands
[2]))
3414 return AS1 (asr
,%0);
3418 return (AS1 (asr
,%0) CR_TAB
3423 return (AS1 (asr
,%0) CR_TAB
3429 return (AS1 (asr
,%0) CR_TAB
3436 return (AS1 (asr
,%0) CR_TAB
3444 return (AS2 (bst
,%0,6) CR_TAB
3446 AS2 (sbc
,%0,%0) CR_TAB
3450 if (INTVAL (operands
[2]) < 8)
3457 return (AS1 (lsl
,%0) CR_TAB
3461 else if (CONSTANT_P (operands
[2]))
3462 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
3464 out_shift_with_cnt (AS1 (asr
,%0),
3465 insn
, operands
, len
, 1);
3470 /* 16bit arithmetic shift right ((signed short)x >> i) */
3473 ashrhi3_out (rtx insn
, rtx operands
[], int *len
)
3475 if (GET_CODE (operands
[2]) == CONST_INT
)
3477 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
3478 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
3485 switch (INTVAL (operands
[2]))
3489 /* XXX try to optimize this too? */
3494 break; /* scratch ? 5 : 6 */
3496 return (AS2 (mov
,__tmp_reg__
,%A0
) CR_TAB
3497 AS2 (mov
,%A0
,%B0
) CR_TAB
3498 AS1 (lsl
,__tmp_reg__
) CR_TAB
3499 AS1 (rol
,%A0
) CR_TAB
3500 AS2 (sbc
,%B0
,%B0
) CR_TAB
3501 AS1 (lsl
,__tmp_reg__
) CR_TAB
3502 AS1 (rol
,%A0
) CR_TAB
3507 return (AS1 (lsl
,%A0
) CR_TAB
3508 AS2 (mov
,%A0
,%B0
) CR_TAB
3509 AS1 (rol
,%A0
) CR_TAB
3514 int reg0
= true_regnum (operands
[0]);
3515 int reg1
= true_regnum (operands
[1]);
3518 return *len
= 3, (AS2 (mov
,%A0
,%B0
) CR_TAB
3519 AS1 (lsl
,%B0
) CR_TAB
3521 else if (reg0
== reg1
+ 1)
3522 return *len
= 3, (AS1 (clr
,%B0
) CR_TAB
3523 AS2 (sbrc
,%A0
,7) CR_TAB
3526 return *len
= 4, (AS2 (mov
,%A0
,%B1
) CR_TAB
3527 AS1 (clr
,%B0
) CR_TAB
3528 AS2 (sbrc
,%A0
,7) CR_TAB
3534 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3535 AS1 (lsl
,%B0
) CR_TAB
3536 AS2 (sbc
,%B0
,%B0
) CR_TAB
3541 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3542 AS1 (lsl
,%B0
) CR_TAB
3543 AS2 (sbc
,%B0
,%B0
) CR_TAB
3544 AS1 (asr
,%A0
) CR_TAB
3548 if (AVR_ENHANCED
&& ldi_ok
)
3551 return (AS2 (ldi
,%A0
,0x20) CR_TAB
3552 AS2 (muls
,%B0
,%A0
) CR_TAB
3553 AS2 (mov
,%A0
,r1
) CR_TAB
3554 AS2 (sbc
,%B0
,%B0
) CR_TAB
3555 AS1 (clr
,__zero_reg__
));
3557 if (optimize_size
&& scratch
)
3560 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3561 AS1 (lsl
,%B0
) CR_TAB
3562 AS2 (sbc
,%B0
,%B0
) CR_TAB
3563 AS1 (asr
,%A0
) CR_TAB
3564 AS1 (asr
,%A0
) CR_TAB
3568 if (AVR_ENHANCED
&& ldi_ok
)
3571 return (AS2 (ldi
,%A0
,0x10) CR_TAB
3572 AS2 (muls
,%B0
,%A0
) CR_TAB
3573 AS2 (mov
,%A0
,r1
) CR_TAB
3574 AS2 (sbc
,%B0
,%B0
) CR_TAB
3575 AS1 (clr
,__zero_reg__
));
3577 if (optimize_size
&& scratch
)
3580 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3581 AS1 (lsl
,%B0
) CR_TAB
3582 AS2 (sbc
,%B0
,%B0
) CR_TAB
3583 AS1 (asr
,%A0
) CR_TAB
3584 AS1 (asr
,%A0
) CR_TAB
3585 AS1 (asr
,%A0
) CR_TAB
3589 if (AVR_ENHANCED
&& ldi_ok
)
3592 return (AS2 (ldi
,%A0
,0x08) CR_TAB
3593 AS2 (muls
,%B0
,%A0
) CR_TAB
3594 AS2 (mov
,%A0
,r1
) CR_TAB
3595 AS2 (sbc
,%B0
,%B0
) CR_TAB
3596 AS1 (clr
,__zero_reg__
));
3599 break; /* scratch ? 5 : 7 */
3601 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3602 AS1 (lsl
,%B0
) CR_TAB
3603 AS2 (sbc
,%B0
,%B0
) CR_TAB
3604 AS1 (asr
,%A0
) CR_TAB
3605 AS1 (asr
,%A0
) CR_TAB
3606 AS1 (asr
,%A0
) CR_TAB
3607 AS1 (asr
,%A0
) CR_TAB
3612 return (AS1 (lsl
,%B0
) CR_TAB
3613 AS2 (sbc
,%A0
,%A0
) CR_TAB
3614 AS1 (lsl
,%B0
) CR_TAB
3615 AS2 (mov
,%B0
,%A0
) CR_TAB
3619 if (INTVAL (operands
[2]) < 16)
3625 return *len
= 3, (AS1 (lsl
,%B0
) CR_TAB
3626 AS2 (sbc
,%A0
,%A0
) CR_TAB
3631 out_shift_with_cnt ((AS1 (asr
,%B0
) CR_TAB
3633 insn
, operands
, len
, 2);
3638 /* 32bit arithmetic shift right ((signed long)x >> i) */
3641 ashrsi3_out (rtx insn
, rtx operands
[], int *len
)
3643 if (GET_CODE (operands
[2]) == CONST_INT
)
3651 switch (INTVAL (operands
[2]))
3655 int reg0
= true_regnum (operands
[0]);
3656 int reg1
= true_regnum (operands
[1]);
3659 return (AS2 (mov
,%A0
,%B1
) CR_TAB
3660 AS2 (mov
,%B0
,%C1
) CR_TAB
3661 AS2 (mov
,%C0
,%D1
) CR_TAB
3662 AS1 (clr
,%D0
) CR_TAB
3663 AS2 (sbrc
,%C0
,7) CR_TAB
3665 else if (reg0
== reg1
+ 1)
3668 return (AS1 (clr
,%D0
) CR_TAB
3669 AS2 (sbrc
,%C0
,7) CR_TAB
3673 return (AS1 (clr
,%D0
) CR_TAB
3674 AS2 (sbrc
,%D1
,7) CR_TAB
3675 AS1 (dec
,%D0
) CR_TAB
3676 AS2 (mov
,%C0
,%D1
) CR_TAB
3677 AS2 (mov
,%B0
,%C1
) CR_TAB
3683 int reg0
= true_regnum (operands
[0]);
3684 int reg1
= true_regnum (operands
[1]);
3686 if (AVR_ENHANCED
&& (reg0
!= reg1
+ 2))
3689 return (AS2 (movw
,%A0
,%C1
) CR_TAB
3690 AS1 (clr
,%D0
) CR_TAB
3691 AS2 (sbrc
,%B0
,7) CR_TAB
3692 AS1 (com
,%D0
) CR_TAB
3695 if (reg0
<= reg1
+ 1)
3696 return (AS2 (mov
,%A0
,%C1
) CR_TAB
3697 AS2 (mov
,%B0
,%D1
) CR_TAB
3698 AS1 (clr
,%D0
) CR_TAB
3699 AS2 (sbrc
,%B0
,7) CR_TAB
3700 AS1 (com
,%D0
) CR_TAB
3702 else if (reg0
== reg1
+ 2)
3703 return *len
= 4, (AS1 (clr
,%D0
) CR_TAB
3704 AS2 (sbrc
,%B0
,7) CR_TAB
3705 AS1 (com
,%D0
) CR_TAB
3708 return (AS2 (mov
,%B0
,%D1
) CR_TAB
3709 AS2 (mov
,%A0
,%C1
) CR_TAB
3710 AS1 (clr
,%D0
) CR_TAB
3711 AS2 (sbrc
,%B0
,7) CR_TAB
3712 AS1 (com
,%D0
) CR_TAB
3717 if (true_regnum (operands
[0]) != true_regnum (operands
[1]) + 3)
3718 return *len
= 6, (AS2 (mov
,%A0
,%D1
) CR_TAB
3719 AS1 (clr
,%D0
) CR_TAB
3720 AS2 (sbrc
,%A0
,7) CR_TAB
3721 AS1 (com
,%D0
) CR_TAB
3722 AS2 (mov
,%B0
,%D0
) CR_TAB
3725 return *len
= 5, (AS1 (clr
,%D0
) CR_TAB
3726 AS2 (sbrc
,%A0
,7) CR_TAB
3727 AS1 (com
,%D0
) CR_TAB
3728 AS2 (mov
,%B0
,%D0
) CR_TAB
3732 if (INTVAL (operands
[2]) < 32)
3739 return *len
= 4, (AS1 (lsl
,%D0
) CR_TAB
3740 AS2 (sbc
,%A0
,%A0
) CR_TAB
3741 AS2 (mov
,%B0
,%A0
) CR_TAB
3742 AS2 (movw
,%C0
,%A0
));
3744 return *len
= 5, (AS1 (lsl
,%D0
) CR_TAB
3745 AS2 (sbc
,%A0
,%A0
) CR_TAB
3746 AS2 (mov
,%B0
,%A0
) CR_TAB
3747 AS2 (mov
,%C0
,%A0
) CR_TAB
3752 out_shift_with_cnt ((AS1 (asr
,%D0
) CR_TAB
3753 AS1 (ror
,%C0
) CR_TAB
3754 AS1 (ror
,%B0
) CR_TAB
3756 insn
, operands
, len
, 4);
3760 /* 8bit logic shift right ((unsigned char)x >> i) */
3763 lshrqi3_out (rtx insn
, rtx operands
[], int *len
)
3765 if (GET_CODE (operands
[2]) == CONST_INT
)
3772 switch (INTVAL (operands
[2]))
3775 if (INTVAL (operands
[2]) < 8)
3779 return AS1 (clr
,%0);
3783 return AS1 (lsr
,%0);
3787 return (AS1 (lsr
,%0) CR_TAB
3791 return (AS1 (lsr
,%0) CR_TAB
3796 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3799 return (AS1 (swap
,%0) CR_TAB
3800 AS2 (andi
,%0,0x0f));
3803 return (AS1 (lsr
,%0) CR_TAB
3809 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3812 return (AS1 (swap
,%0) CR_TAB
3817 return (AS1 (lsr
,%0) CR_TAB
3824 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3827 return (AS1 (swap
,%0) CR_TAB
3833 return (AS1 (lsr
,%0) CR_TAB
3842 return (AS1 (rol
,%0) CR_TAB
3847 else if (CONSTANT_P (operands
[2]))
3848 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
3850 out_shift_with_cnt (AS1 (lsr
,%0),
3851 insn
, operands
, len
, 1);
3855 /* 16bit logic shift right ((unsigned short)x >> i) */
3858 lshrhi3_out (rtx insn
, rtx operands
[], int *len
)
3860 if (GET_CODE (operands
[2]) == CONST_INT
)
3862 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
3863 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
3870 switch (INTVAL (operands
[2]))
3873 if (INTVAL (operands
[2]) < 16)
3877 return (AS1 (clr
,%B0
) CR_TAB
3881 if (optimize_size
&& scratch
)
3886 return (AS1 (swap
,%B0
) CR_TAB
3887 AS1 (swap
,%A0
) CR_TAB
3888 AS2 (andi
,%A0
,0x0f) CR_TAB
3889 AS2 (eor
,%A0
,%B0
) CR_TAB
3890 AS2 (andi
,%B0
,0x0f) CR_TAB
3896 return (AS1 (swap
,%B0
) CR_TAB
3897 AS1 (swap
,%A0
) CR_TAB
3898 AS2 (ldi
,%3,0x0f) CR_TAB
3899 AS2 (and,%A0
,%3) CR_TAB
3900 AS2 (eor
,%A0
,%B0
) CR_TAB
3901 AS2 (and,%B0
,%3) CR_TAB
3904 break; /* optimize_size ? 6 : 8 */
3908 break; /* scratch ? 5 : 6 */
3912 return (AS1 (lsr
,%B0
) CR_TAB
3913 AS1 (ror
,%A0
) CR_TAB
3914 AS1 (swap
,%B0
) CR_TAB
3915 AS1 (swap
,%A0
) CR_TAB
3916 AS2 (andi
,%A0
,0x0f) CR_TAB
3917 AS2 (eor
,%A0
,%B0
) CR_TAB
3918 AS2 (andi
,%B0
,0x0f) CR_TAB
3924 return (AS1 (lsr
,%B0
) CR_TAB
3925 AS1 (ror
,%A0
) CR_TAB
3926 AS1 (swap
,%B0
) CR_TAB
3927 AS1 (swap
,%A0
) CR_TAB
3928 AS2 (ldi
,%3,0x0f) CR_TAB
3929 AS2 (and,%A0
,%3) CR_TAB
3930 AS2 (eor
,%A0
,%B0
) CR_TAB
3931 AS2 (and,%B0
,%3) CR_TAB
3938 break; /* scratch ? 5 : 6 */
3940 return (AS1 (clr
,__tmp_reg__
) CR_TAB
3941 AS1 (lsl
,%A0
) CR_TAB
3942 AS1 (rol
,%B0
) CR_TAB
3943 AS1 (rol
,__tmp_reg__
) CR_TAB
3944 AS1 (lsl
,%A0
) CR_TAB
3945 AS1 (rol
,%B0
) CR_TAB
3946 AS1 (rol
,__tmp_reg__
) CR_TAB
3947 AS2 (mov
,%A0
,%B0
) CR_TAB
3948 AS2 (mov
,%B0
,__tmp_reg__
));
3952 return (AS1 (lsl
,%A0
) CR_TAB
3953 AS2 (mov
,%A0
,%B0
) CR_TAB
3954 AS1 (rol
,%A0
) CR_TAB
3955 AS2 (sbc
,%B0
,%B0
) CR_TAB
3959 if (true_regnum (operands
[0]) != true_regnum (operands
[1]) + 1)
3960 return *len
= 2, (AS2 (mov
,%A0
,%B1
) CR_TAB
3963 return *len
= 1, AS1 (clr
,%B0
);
3967 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3968 AS1 (clr
,%B0
) CR_TAB
3973 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3974 AS1 (clr
,%B0
) CR_TAB
3975 AS1 (lsr
,%A0
) CR_TAB
3980 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3981 AS1 (clr
,%B0
) CR_TAB
3982 AS1 (lsr
,%A0
) CR_TAB
3983 AS1 (lsr
,%A0
) CR_TAB
3990 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3991 AS1 (clr
,%B0
) CR_TAB
3992 AS1 (swap
,%A0
) CR_TAB
3993 AS2 (andi
,%A0
,0x0f));
3998 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3999 AS1 (clr
,%B0
) CR_TAB
4000 AS1 (swap
,%A0
) CR_TAB
4001 AS2 (ldi
,%3,0x0f) CR_TAB
4005 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4006 AS1 (clr
,%B0
) CR_TAB
4007 AS1 (lsr
,%A0
) CR_TAB
4008 AS1 (lsr
,%A0
) CR_TAB
4009 AS1 (lsr
,%A0
) CR_TAB
4016 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4017 AS1 (clr
,%B0
) CR_TAB
4018 AS1 (swap
,%A0
) CR_TAB
4019 AS1 (lsr
,%A0
) CR_TAB
4020 AS2 (andi
,%A0
,0x07));
4022 if (AVR_ENHANCED
&& scratch
)
4025 return (AS2 (ldi
,%3,0x08) CR_TAB
4026 AS2 (mul
,%B0
,%3) CR_TAB
4027 AS2 (mov
,%A0
,r1
) CR_TAB
4028 AS1 (clr
,%B0
) CR_TAB
4029 AS1 (clr
,__zero_reg__
));
4031 if (optimize_size
&& scratch
)
4036 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4037 AS1 (clr
,%B0
) CR_TAB
4038 AS1 (swap
,%A0
) CR_TAB
4039 AS1 (lsr
,%A0
) CR_TAB
4040 AS2 (ldi
,%3,0x07) CR_TAB
4046 return ("set" CR_TAB
4047 AS2 (bld
,r1
,3) CR_TAB
4048 AS2 (mul
,%B0
,r1
) CR_TAB
4049 AS2 (mov
,%A0
,r1
) CR_TAB
4050 AS1 (clr
,%B0
) CR_TAB
4051 AS1 (clr
,__zero_reg__
));
4054 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4055 AS1 (clr
,%B0
) CR_TAB
4056 AS1 (lsr
,%A0
) CR_TAB
4057 AS1 (lsr
,%A0
) CR_TAB
4058 AS1 (lsr
,%A0
) CR_TAB
4059 AS1 (lsr
,%A0
) CR_TAB
4063 if (AVR_ENHANCED
&& ldi_ok
)
4066 return (AS2 (ldi
,%A0
,0x04) CR_TAB
4067 AS2 (mul
,%B0
,%A0
) CR_TAB
4068 AS2 (mov
,%A0
,r1
) CR_TAB
4069 AS1 (clr
,%B0
) CR_TAB
4070 AS1 (clr
,__zero_reg__
));
4072 if (AVR_ENHANCED
&& scratch
)
4075 return (AS2 (ldi
,%3,0x04) CR_TAB
4076 AS2 (mul
,%B0
,%3) CR_TAB
4077 AS2 (mov
,%A0
,r1
) CR_TAB
4078 AS1 (clr
,%B0
) CR_TAB
4079 AS1 (clr
,__zero_reg__
));
4081 if (optimize_size
&& ldi_ok
)
4084 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4085 AS2 (ldi
,%B0
,6) "\n1:\t"
4086 AS1 (lsr
,%A0
) CR_TAB
4087 AS1 (dec
,%B0
) CR_TAB
4090 if (optimize_size
&& scratch
)
4093 return (AS1 (clr
,%A0
) CR_TAB
4094 AS1 (lsl
,%B0
) CR_TAB
4095 AS1 (rol
,%A0
) CR_TAB
4096 AS1 (lsl
,%B0
) CR_TAB
4097 AS1 (rol
,%A0
) CR_TAB
4102 return (AS1 (clr
,%A0
) CR_TAB
4103 AS1 (lsl
,%B0
) CR_TAB
4104 AS1 (rol
,%A0
) CR_TAB
4109 out_shift_with_cnt ((AS1 (lsr
,%B0
) CR_TAB
4111 insn
, operands
, len
, 2);
4115 /* 32bit logic shift right ((unsigned int)x >> i) */
4118 lshrsi3_out (rtx insn
, rtx operands
[], int *len
)
4120 if (GET_CODE (operands
[2]) == CONST_INT
)
4128 switch (INTVAL (operands
[2]))
4131 if (INTVAL (operands
[2]) < 32)
4135 return *len
= 3, (AS1 (clr
,%D0
) CR_TAB
4136 AS1 (clr
,%C0
) CR_TAB
4137 AS2 (movw
,%A0
,%C0
));
4139 return (AS1 (clr
,%D0
) CR_TAB
4140 AS1 (clr
,%C0
) CR_TAB
4141 AS1 (clr
,%B0
) CR_TAB
4146 int reg0
= true_regnum (operands
[0]);
4147 int reg1
= true_regnum (operands
[1]);
4150 return (AS2 (mov
,%A0
,%B1
) CR_TAB
4151 AS2 (mov
,%B0
,%C1
) CR_TAB
4152 AS2 (mov
,%C0
,%D1
) CR_TAB
4154 else if (reg0
== reg1
+ 1)
4155 return *len
= 1, AS1 (clr
,%D0
);
4157 return (AS1 (clr
,%D0
) CR_TAB
4158 AS2 (mov
,%C0
,%D1
) CR_TAB
4159 AS2 (mov
,%B0
,%C1
) CR_TAB
4165 int reg0
= true_regnum (operands
[0]);
4166 int reg1
= true_regnum (operands
[1]);
4168 if (AVR_ENHANCED
&& (reg0
!= reg1
+ 2))
4171 return (AS2 (movw
,%A0
,%C1
) CR_TAB
4172 AS1 (clr
,%C0
) CR_TAB
4175 if (reg0
<= reg1
+ 1)
4176 return (AS2 (mov
,%A0
,%C1
) CR_TAB
4177 AS2 (mov
,%B0
,%D1
) CR_TAB
4178 AS1 (clr
,%C0
) CR_TAB
4180 else if (reg0
== reg1
+ 2)
4181 return *len
= 2, (AS1 (clr
,%C0
) CR_TAB
4184 return (AS2 (mov
,%B0
,%D1
) CR_TAB
4185 AS2 (mov
,%A0
,%C1
) CR_TAB
4186 AS1 (clr
,%C0
) CR_TAB
4191 if (true_regnum (operands
[0]) != true_regnum (operands
[1]) + 3)
4192 return *len
= 4, (AS2 (mov
,%A0
,%D1
) CR_TAB
4193 AS1 (clr
,%B0
) CR_TAB
4194 AS1 (clr
,%C0
) CR_TAB
4197 return *len
= 3, (AS1 (clr
,%B0
) CR_TAB
4198 AS1 (clr
,%C0
) CR_TAB
4203 return (AS1 (clr
,%A0
) CR_TAB
4204 AS2 (sbrc
,%D0
,7) CR_TAB
4205 AS1 (inc
,%A0
) CR_TAB
4206 AS1 (clr
,%B0
) CR_TAB
4207 AS1 (clr
,%C0
) CR_TAB
4212 out_shift_with_cnt ((AS1 (lsr
,%D0
) CR_TAB
4213 AS1 (ror
,%C0
) CR_TAB
4214 AS1 (ror
,%B0
) CR_TAB
4216 insn
, operands
, len
, 4);
4220 /* Modifies the length assigned to instruction INSN
4221 LEN is the initially computed length of the insn. */
4224 adjust_insn_length (rtx insn
, int len
)
4226 rtx patt
= PATTERN (insn
);
4229 if (GET_CODE (patt
) == SET
)
4232 op
[1] = SET_SRC (patt
);
4233 op
[0] = SET_DEST (patt
);
4234 if (general_operand (op
[1], VOIDmode
)
4235 && general_operand (op
[0], VOIDmode
))
4237 switch (GET_MODE (op
[0]))
4240 output_movqi (insn
, op
, &len
);
4243 output_movhi (insn
, op
, &len
);
4247 output_movsisf (insn
, op
, &len
);
4253 else if (op
[0] == cc0_rtx
&& REG_P (op
[1]))
4255 switch (GET_MODE (op
[1]))
4257 case HImode
: out_tsthi (insn
,&len
); break;
4258 case SImode
: out_tstsi (insn
,&len
); break;
4262 else if (GET_CODE (op
[1]) == AND
)
4264 if (GET_CODE (XEXP (op
[1],1)) == CONST_INT
)
4266 HOST_WIDE_INT mask
= INTVAL (XEXP (op
[1],1));
4267 if (GET_MODE (op
[1]) == SImode
)
4268 len
= (((mask
& 0xff) != 0xff)
4269 + ((mask
& 0xff00) != 0xff00)
4270 + ((mask
& 0xff0000L
) != 0xff0000L
)
4271 + ((mask
& 0xff000000L
) != 0xff000000L
));
4272 else if (GET_MODE (op
[1]) == HImode
)
4273 len
= (((mask
& 0xff) != 0xff)
4274 + ((mask
& 0xff00) != 0xff00));
4277 else if (GET_CODE (op
[1]) == IOR
)
4279 if (GET_CODE (XEXP (op
[1],1)) == CONST_INT
)
4281 HOST_WIDE_INT mask
= INTVAL (XEXP (op
[1],1));
4282 if (GET_MODE (op
[1]) == SImode
)
4283 len
= (((mask
& 0xff) != 0)
4284 + ((mask
& 0xff00) != 0)
4285 + ((mask
& 0xff0000L
) != 0)
4286 + ((mask
& 0xff000000L
) != 0));
4287 else if (GET_MODE (op
[1]) == HImode
)
4288 len
= (((mask
& 0xff) != 0)
4289 + ((mask
& 0xff00) != 0));
4293 set
= single_set (insn
);
4298 op
[1] = SET_SRC (set
);
4299 op
[0] = SET_DEST (set
);
4301 if (GET_CODE (patt
) == PARALLEL
4302 && general_operand (op
[1], VOIDmode
)
4303 && general_operand (op
[0], VOIDmode
))
4305 if (XVECLEN (patt
, 0) == 2)
4306 op
[2] = XVECEXP (patt
, 0, 1);
4308 switch (GET_MODE (op
[0]))
4314 output_reload_inhi (insn
, op
, &len
);
4318 output_reload_insisf (insn
, op
, &len
);
4324 else if (GET_CODE (op
[1]) == ASHIFT
4325 || GET_CODE (op
[1]) == ASHIFTRT
4326 || GET_CODE (op
[1]) == LSHIFTRT
)
4330 ops
[1] = XEXP (op
[1],0);
4331 ops
[2] = XEXP (op
[1],1);
4332 switch (GET_CODE (op
[1]))
4335 switch (GET_MODE (op
[0]))
4337 case QImode
: ashlqi3_out (insn
,ops
,&len
); break;
4338 case HImode
: ashlhi3_out (insn
,ops
,&len
); break;
4339 case SImode
: ashlsi3_out (insn
,ops
,&len
); break;
4344 switch (GET_MODE (op
[0]))
4346 case QImode
: ashrqi3_out (insn
,ops
,&len
); break;
4347 case HImode
: ashrhi3_out (insn
,ops
,&len
); break;
4348 case SImode
: ashrsi3_out (insn
,ops
,&len
); break;
4353 switch (GET_MODE (op
[0]))
4355 case QImode
: lshrqi3_out (insn
,ops
,&len
); break;
4356 case HImode
: lshrhi3_out (insn
,ops
,&len
); break;
4357 case SImode
: lshrsi3_out (insn
,ops
,&len
); break;
4369 /* Return nonzero if register REG dead after INSN. */
4372 reg_unused_after (rtx insn
, rtx reg
)
4374 return (dead_or_set_p (insn
, reg
)
4375 || (REG_P(reg
) && _reg_unused_after (insn
, reg
)));
4378 /* Return nonzero if REG is not used after INSN.
4379 We assume REG is a reload reg, and therefore does
4380 not live past labels. It may live past calls or jumps though. */
4383 _reg_unused_after (rtx insn
, rtx reg
)
4388 /* If the reg is set by this instruction, then it is safe for our
4389 case. Disregard the case where this is a store to memory, since
4390 we are checking a register used in the store address. */
4391 set
= single_set (insn
);
4392 if (set
&& GET_CODE (SET_DEST (set
)) != MEM
4393 && reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
4396 while ((insn
= NEXT_INSN (insn
)))
4399 code
= GET_CODE (insn
);
4402 /* If this is a label that existed before reload, then the register
4403 if dead here. However, if this is a label added by reorg, then
4404 the register may still be live here. We can't tell the difference,
4405 so we just ignore labels completely. */
4406 if (code
== CODE_LABEL
)
4414 if (code
== JUMP_INSN
)
4417 /* If this is a sequence, we must handle them all at once.
4418 We could have for instance a call that sets the target register,
4419 and an insn in a delay slot that uses the register. In this case,
4420 we must return 0. */
4421 else if (code
== INSN
&& GET_CODE (PATTERN (insn
)) == SEQUENCE
)
4426 for (i
= 0; i
< XVECLEN (PATTERN (insn
), 0); i
++)
4428 rtx this_insn
= XVECEXP (PATTERN (insn
), 0, i
);
4429 rtx set
= single_set (this_insn
);
4431 if (GET_CODE (this_insn
) == CALL_INSN
)
4433 else if (GET_CODE (this_insn
) == JUMP_INSN
)
4435 if (INSN_ANNULLED_BRANCH_P (this_insn
))
4440 if (set
&& reg_overlap_mentioned_p (reg
, SET_SRC (set
)))
4442 if (set
&& reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
4444 if (GET_CODE (SET_DEST (set
)) != MEM
)
4450 && reg_overlap_mentioned_p (reg
, PATTERN (this_insn
)))
4455 else if (code
== JUMP_INSN
)
4459 if (code
== CALL_INSN
)
4462 for (tem
= CALL_INSN_FUNCTION_USAGE (insn
); tem
; tem
= XEXP (tem
, 1))
4463 if (GET_CODE (XEXP (tem
, 0)) == USE
4464 && REG_P (XEXP (XEXP (tem
, 0), 0))
4465 && reg_overlap_mentioned_p (reg
, XEXP (XEXP (tem
, 0), 0)))
4467 if (call_used_regs
[REGNO (reg
)])
4471 set
= single_set (insn
);
4473 if (set
&& reg_overlap_mentioned_p (reg
, SET_SRC (set
)))
4475 if (set
&& reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
4476 return GET_CODE (SET_DEST (set
)) != MEM
;
4477 if (set
== 0 && reg_overlap_mentioned_p (reg
, PATTERN (insn
)))
4483 /* Target hook for assembling integer objects. The AVR version needs
4484 special handling for references to certain labels. */
4487 avr_assemble_integer (rtx x
, unsigned int size
, int aligned_p
)
4489 if (size
== POINTER_SIZE
/ BITS_PER_UNIT
&& aligned_p
4490 && ((GET_CODE (x
) == SYMBOL_REF
&& SYMBOL_REF_FUNCTION_P (x
))
4491 || GET_CODE (x
) == LABEL_REF
))
4493 fputs ("\t.word\tpm(", asm_out_file
);
4494 output_addr_const (asm_out_file
, x
);
4495 fputs (")\n", asm_out_file
);
4498 return default_assemble_integer (x
, size
, aligned_p
);
4501 /* The routine used to output NUL terminated strings. We use a special
4502 version of this for most svr4 targets because doing so makes the
4503 generated assembly code more compact (and thus faster to assemble)
4504 as well as more readable, especially for targets like the i386
4505 (where the only alternative is to output character sequences as
4506 comma separated lists of numbers). */
4509 gas_output_limited_string(FILE *file
, const char *str
)
4511 const unsigned char *_limited_str
= (unsigned char *) str
;
4513 fprintf (file
, "%s\"", STRING_ASM_OP
);
4514 for (; (ch
= *_limited_str
); _limited_str
++)
4517 switch (escape
= ESCAPES
[ch
])
4523 fprintf (file
, "\\%03o", ch
);
4527 putc (escape
, file
);
4531 fprintf (file
, "\"\n");
4534 /* The routine used to output sequences of byte values. We use a special
4535 version of this for most svr4 targets because doing so makes the
4536 generated assembly code more compact (and thus faster to assemble)
4537 as well as more readable. Note that if we find subparts of the
4538 character sequence which end with NUL (and which are shorter than
4539 STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
4542 gas_output_ascii(FILE *file
, const char *str
, size_t length
)
4544 const unsigned char *_ascii_bytes
= (const unsigned char *) str
;
4545 const unsigned char *limit
= _ascii_bytes
+ length
;
4546 unsigned bytes_in_chunk
= 0;
4547 for (; _ascii_bytes
< limit
; _ascii_bytes
++)
4549 const unsigned char *p
;
4550 if (bytes_in_chunk
>= 60)
4552 fprintf (file
, "\"\n");
4555 for (p
= _ascii_bytes
; p
< limit
&& *p
!= '\0'; p
++)
4557 if (p
< limit
&& (p
- _ascii_bytes
) <= (signed)STRING_LIMIT
)
4559 if (bytes_in_chunk
> 0)
4561 fprintf (file
, "\"\n");
4564 gas_output_limited_string (file
, (char*)_ascii_bytes
);
4571 if (bytes_in_chunk
== 0)
4572 fprintf (file
, "\t.ascii\t\"");
4573 switch (escape
= ESCAPES
[ch
= *_ascii_bytes
])
4580 fprintf (file
, "\\%03o", ch
);
4581 bytes_in_chunk
+= 4;
4585 putc (escape
, file
);
4586 bytes_in_chunk
+= 2;
4591 if (bytes_in_chunk
> 0)
4592 fprintf (file
, "\"\n");
4595 /* Return value is nonzero if pseudos that have been
4596 assigned to registers of class CLASS would likely be spilled
4597 because registers of CLASS are needed for spill registers. */
4600 class_likely_spilled_p (int c
)
4602 return (c
!= ALL_REGS
&& c
!= ADDW_REGS
);
4605 /* Valid attributes:
4606 progmem - put data to program memory;
4607 signal - make a function to be hardware interrupt. After function
4608 prologue interrupts are disabled;
4609 interrupt - make a function to be hardware interrupt. After function
4610 prologue interrupts are enabled;
4611 naked - don't generate function prologue/epilogue and `ret' command.
4613 Only `progmem' attribute valid for type. */
4615 const struct attribute_spec avr_attribute_table
[] =
4617 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4618 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute
},
4619 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute
},
4620 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute
},
4621 { "naked", 0, 0, true, false, false, avr_handle_fndecl_attribute
},
4622 { NULL
, 0, 0, false, false, false, NULL
}
4625 /* Handle a "progmem" attribute; arguments as in
4626 struct attribute_spec.handler. */
4628 avr_handle_progmem_attribute (tree
*node
, tree name
,
4629 tree args ATTRIBUTE_UNUSED
,
4630 int flags ATTRIBUTE_UNUSED
,
4635 if (TREE_CODE (*node
) == TYPE_DECL
)
4637 /* This is really a decl attribute, not a type attribute,
4638 but try to handle it for GCC 3.0 backwards compatibility. */
4640 tree type
= TREE_TYPE (*node
);
4641 tree attr
= tree_cons (name
, args
, TYPE_ATTRIBUTES (type
));
4642 tree newtype
= build_type_attribute_variant (type
, attr
);
4644 TYPE_MAIN_VARIANT (newtype
) = TYPE_MAIN_VARIANT (type
);
4645 TREE_TYPE (*node
) = newtype
;
4646 *no_add_attrs
= true;
4648 else if (TREE_STATIC (*node
) || DECL_EXTERNAL (*node
))
4650 if (DECL_INITIAL (*node
) == NULL_TREE
&& !DECL_EXTERNAL (*node
))
4652 warning (0, "only initialized variables can be placed into "
4653 "program memory area");
4654 *no_add_attrs
= true;
4659 warning (OPT_Wattributes
, "%qs attribute ignored",
4660 IDENTIFIER_POINTER (name
));
4661 *no_add_attrs
= true;
4668 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4669 struct attribute_spec.handler. */
4672 avr_handle_fndecl_attribute (tree
*node
, tree name
,
4673 tree args ATTRIBUTE_UNUSED
,
4674 int flags ATTRIBUTE_UNUSED
,
4677 if (TREE_CODE (*node
) != FUNCTION_DECL
)
4679 warning (OPT_Wattributes
, "%qs attribute only applies to functions",
4680 IDENTIFIER_POINTER (name
));
4681 *no_add_attrs
= true;
4685 const char *func_name
= IDENTIFIER_POINTER (DECL_NAME (*node
));
4686 const char *attr
= IDENTIFIER_POINTER (name
);
4688 /* If the function has the 'signal' or 'interrupt' attribute, test to
4689 make sure that the name of the function is "__vector_NN" so as to
4690 catch when the user misspells the interrupt vector name. */
4692 if (strncmp (attr
, "interrupt", strlen ("interrupt")) == 0)
4694 if (strncmp (func_name
, "__vector", strlen ("__vector")) != 0)
4696 warning (0, "%qs appears to be a misspelled interrupt handler",
4700 else if (strncmp (attr
, "signal", strlen ("signal")) == 0)
4702 if (strncmp (func_name
, "__vector", strlen ("__vector")) != 0)
4704 warning (0, "%qs appears to be a misspelled signal handler",
4713 /* Look for attribute `progmem' in DECL
4714 if found return 1, otherwise 0. */
4717 avr_progmem_p (tree decl
, tree attributes
)
4721 if (TREE_CODE (decl
) != VAR_DECL
)
4725 != lookup_attribute ("progmem", attributes
))
4731 while (TREE_CODE (a
) == ARRAY_TYPE
);
4733 if (a
== error_mark_node
)
4736 if (NULL_TREE
!= lookup_attribute ("progmem", TYPE_ATTRIBUTES (a
)))
4742 /* Add the section attribute if the variable is in progmem. */
4745 avr_insert_attributes (tree node
, tree
*attributes
)
4747 if (TREE_CODE (node
) == VAR_DECL
4748 && (TREE_STATIC (node
) || DECL_EXTERNAL (node
))
4749 && avr_progmem_p (node
, *attributes
))
4751 static const char dsec
[] = ".progmem.data";
4752 *attributes
= tree_cons (get_identifier ("section"),
4753 build_tree_list (NULL
, build_string (strlen (dsec
), dsec
)),
4756 /* ??? This seems sketchy. Why can't the user declare the
4757 thing const in the first place? */
4758 TREE_READONLY (node
) = 1;
4762 /* A get_unnamed_section callback for switching to progmem_section. */
4765 avr_output_progmem_section_asm_op (const void *arg ATTRIBUTE_UNUSED
)
4767 fprintf (asm_out_file
,
4768 "\t.section .progmem.gcc_sw_table, \"%s\", @progbits\n",
4769 AVR_MEGA
? "a" : "ax");
4770 /* Should already be aligned, this is just to be safe if it isn't. */
4771 fprintf (asm_out_file
, "\t.p2align 1\n");
4774 /* Implement TARGET_ASM_INIT_SECTIONS. */
4777 avr_asm_init_sections (void)
4779 progmem_section
= get_unnamed_section (AVR_MEGA
? 0 : SECTION_CODE
,
4780 avr_output_progmem_section_asm_op
,
4782 readonly_data_section
= data_section
;
4786 avr_section_type_flags (tree decl
, const char *name
, int reloc
)
4788 unsigned int flags
= default_section_type_flags (decl
, name
, reloc
);
4790 if (strncmp (name
, ".noinit", 7) == 0)
4792 if (decl
&& TREE_CODE (decl
) == VAR_DECL
4793 && DECL_INITIAL (decl
) == NULL_TREE
)
4794 flags
|= SECTION_BSS
; /* @nobits */
4796 warning (0, "only uninitialized variables can be placed in the "
4803 /* Outputs some appropriate text to go at the start of an assembler
4807 avr_file_start (void)
4810 error ("MCU %qs supported for assembler only", avr_mcu_name
);
4812 default_file_start ();
4814 fprintf (asm_out_file
, "\t.arch %s\n", avr_mcu_name
);
4815 fputs ("__SREG__ = 0x3f\n"
4817 "__SP_L__ = 0x3d\n", asm_out_file
);
4819 fputs ("__tmp_reg__ = 0\n"
4820 "__zero_reg__ = 1\n", asm_out_file
);
4822 /* FIXME: output these only if there is anything in the .data / .bss
4823 sections - some code size could be saved by not linking in the
4824 initialization code from libgcc if one or both sections are empty. */
4825 fputs ("\t.global __do_copy_data\n", asm_out_file
);
4826 fputs ("\t.global __do_clear_bss\n", asm_out_file
);
4828 commands_in_file
= 0;
4829 commands_in_prologues
= 0;
4830 commands_in_epilogues
= 0;
4833 /* Outputs to the stdio stream FILE some
4834 appropriate text to go at the end of an assembler file. */
4839 fputs ("/* File ", asm_out_file
);
4840 output_quoted_string (asm_out_file
, main_input_filename
);
4841 fprintf (asm_out_file
,
4842 ": code %4d = 0x%04x (%4d), prologues %3d, epilogues %3d */\n",
4845 commands_in_file
- commands_in_prologues
- commands_in_epilogues
,
4846 commands_in_prologues
, commands_in_epilogues
);
4849 /* Choose the order in which to allocate hard registers for
4850 pseudo-registers local to a basic block.
4852 Store the desired register order in the array `reg_alloc_order'.
4853 Element 0 should be the register to allocate first; element 1, the
4854 next register; and so on. */
4857 order_regs_for_local_alloc (void)
4860 static const int order_0
[] = {
4868 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4872 static const int order_1
[] = {
4880 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4884 static const int order_2
[] = {
4893 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4898 const int *order
= (TARGET_ORDER_1
? order_1
:
4899 TARGET_ORDER_2
? order_2
:
4901 for (i
=0; i
< ARRAY_SIZE (order_0
); ++i
)
4902 reg_alloc_order
[i
] = order
[i
];
4906 /* Mutually recursive subroutine of avr_rtx_cost for calculating the
4907 cost of an RTX operand given its context. X is the rtx of the
4908 operand, MODE is its mode, and OUTER is the rtx_code of this
4909 operand's parent operator. */
4912 avr_operand_rtx_cost (rtx x
, enum machine_mode mode
, enum rtx_code outer
)
4914 enum rtx_code code
= GET_CODE (x
);
4925 return COSTS_N_INSNS (GET_MODE_SIZE (mode
));
4932 avr_rtx_costs (x
, code
, outer
, &total
);
4936 /* The AVR backend's rtx_cost function. X is rtx expression whose cost
4937 is to be calculated. Return true if the complete cost has been
4938 computed, and false if subexpressions should be scanned. In either
4939 case, *TOTAL contains the cost result. */
4942 avr_rtx_costs (rtx x
, int code
, int outer_code
, int *total
)
4944 enum machine_mode mode
= GET_MODE (x
);
4951 /* Immediate constants are as cheap as registers. */
4959 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
4967 *total
= COSTS_N_INSNS (1);
4971 *total
= COSTS_N_INSNS (3);
4975 *total
= COSTS_N_INSNS (7);
4981 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
4989 *total
= COSTS_N_INSNS (1);
4995 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
4999 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
5000 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5004 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
)
5005 - GET_MODE_SIZE (GET_MODE (XEXP (x
, 0))));
5006 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5010 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
) + 2
5011 - GET_MODE_SIZE (GET_MODE (XEXP (x
, 0))));
5012 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5019 *total
= COSTS_N_INSNS (1);
5020 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5021 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5025 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5027 *total
= COSTS_N_INSNS (2);
5028 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5030 else if (INTVAL (XEXP (x
, 1)) >= -63 && INTVAL (XEXP (x
, 1)) <= 63)
5031 *total
= COSTS_N_INSNS (1);
5033 *total
= COSTS_N_INSNS (2);
5037 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5039 *total
= COSTS_N_INSNS (4);
5040 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5042 else if (INTVAL (XEXP (x
, 1)) >= -63 && INTVAL (XEXP (x
, 1)) <= 63)
5043 *total
= COSTS_N_INSNS (1);
5045 *total
= COSTS_N_INSNS (4);
5051 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5057 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
5058 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5059 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5060 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5064 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
5065 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5066 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5074 *total
= COSTS_N_INSNS (optimize_size
? 3 : 4);
5075 else if (optimize_size
)
5076 *total
= COSTS_N_INSNS (AVR_MEGA
? 2 : 1);
5082 *total
= COSTS_N_INSNS (optimize_size
? 7 : 10);
5083 else if (optimize_size
)
5084 *total
= COSTS_N_INSNS (AVR_MEGA
? 2 : 1);
5091 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5092 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5100 *total
= COSTS_N_INSNS (AVR_MEGA
? 2 : 1);
5103 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5104 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5111 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5113 *total
= COSTS_N_INSNS (optimize_size
? 4 : 17);
5114 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5118 val
= INTVAL (XEXP (x
, 1));
5120 *total
= COSTS_N_INSNS (3);
5121 else if (val
>= 0 && val
<= 7)
5122 *total
= COSTS_N_INSNS (val
);
5124 *total
= COSTS_N_INSNS (1);
5129 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5131 *total
= COSTS_N_INSNS (optimize_size
? 5 : 41);
5132 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5135 switch (INTVAL (XEXP (x
, 1)))
5142 *total
= COSTS_N_INSNS (2);
5145 *total
= COSTS_N_INSNS (3);
5151 *total
= COSTS_N_INSNS (4);
5156 *total
= COSTS_N_INSNS (5);
5159 *total
= COSTS_N_INSNS (optimize_size
? 5 : 8);
5162 *total
= COSTS_N_INSNS (optimize_size
? 5 : 9);
5165 *total
= COSTS_N_INSNS (optimize_size
? 5 : 10);
5168 *total
= COSTS_N_INSNS (optimize_size
? 5 : 41);
5169 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5174 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5176 *total
= COSTS_N_INSNS (optimize_size
? 7 : 113);
5177 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5180 switch (INTVAL (XEXP (x
, 1)))
5186 *total
= COSTS_N_INSNS (3);
5191 *total
= COSTS_N_INSNS (4);
5194 *total
= COSTS_N_INSNS (6);
5197 *total
= COSTS_N_INSNS (optimize_size
? 7 : 8);
5200 *total
= COSTS_N_INSNS (optimize_size
? 7 : 113);
5201 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5208 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5215 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5217 *total
= COSTS_N_INSNS (optimize_size
? 4 : 17);
5218 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5222 val
= INTVAL (XEXP (x
, 1));
5224 *total
= COSTS_N_INSNS (4);
5226 *total
= COSTS_N_INSNS (2);
5227 else if (val
>= 0 && val
<= 7)
5228 *total
= COSTS_N_INSNS (val
);
5230 *total
= COSTS_N_INSNS (1);
5235 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5237 *total
= COSTS_N_INSNS (optimize_size
? 5 : 41);
5238 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5241 switch (INTVAL (XEXP (x
, 1)))
5247 *total
= COSTS_N_INSNS (2);
5250 *total
= COSTS_N_INSNS (3);
5256 *total
= COSTS_N_INSNS (4);
5260 *total
= COSTS_N_INSNS (5);
5263 *total
= COSTS_N_INSNS (optimize_size
? 5 : 6);
5266 *total
= COSTS_N_INSNS (optimize_size
? 5 : 7);
5270 *total
= COSTS_N_INSNS (optimize_size
? 5 : 8);
5273 *total
= COSTS_N_INSNS (optimize_size
? 5 : 41);
5274 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5279 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5281 *total
= COSTS_N_INSNS (optimize_size
? 7 : 113);
5282 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5285 switch (INTVAL (XEXP (x
, 1)))
5291 *total
= COSTS_N_INSNS (4);
5296 *total
= COSTS_N_INSNS (6);
5299 *total
= COSTS_N_INSNS (optimize_size
? 7 : 8);
5302 *total
= COSTS_N_INSNS (AVR_ENHANCED
? 4 : 5);
5305 *total
= COSTS_N_INSNS (optimize_size
? 7 : 113);
5306 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5313 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5320 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5322 *total
= COSTS_N_INSNS (optimize_size
? 4 : 17);
5323 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5327 val
= INTVAL (XEXP (x
, 1));
5329 *total
= COSTS_N_INSNS (3);
5330 else if (val
>= 0 && val
<= 7)
5331 *total
= COSTS_N_INSNS (val
);
5333 *total
= COSTS_N_INSNS (1);
5338 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5340 *total
= COSTS_N_INSNS (optimize_size
? 5 : 41);
5341 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5344 switch (INTVAL (XEXP (x
, 1)))
5351 *total
= COSTS_N_INSNS (2);
5354 *total
= COSTS_N_INSNS (3);
5359 *total
= COSTS_N_INSNS (4);
5363 *total
= COSTS_N_INSNS (5);
5369 *total
= COSTS_N_INSNS (optimize_size
? 5 : 6);
5372 *total
= COSTS_N_INSNS (optimize_size
? 5 : 7);
5376 *total
= COSTS_N_INSNS (optimize_size
? 5 : 9);
5379 *total
= COSTS_N_INSNS (optimize_size
? 5 : 41);
5380 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5385 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5387 *total
= COSTS_N_INSNS (optimize_size
? 7 : 113);
5388 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5391 switch (INTVAL (XEXP (x
, 1)))
5397 *total
= COSTS_N_INSNS (4);
5400 *total
= COSTS_N_INSNS (optimize_size
? 7 : 8);
5405 *total
= COSTS_N_INSNS (4);
5408 *total
= COSTS_N_INSNS (6);
5411 *total
= COSTS_N_INSNS (optimize_size
? 7 : 113);
5412 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5419 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5423 switch (GET_MODE (XEXP (x
, 0)))
5426 *total
= COSTS_N_INSNS (1);
5427 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5428 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5432 *total
= COSTS_N_INSNS (2);
5433 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5434 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5435 else if (INTVAL (XEXP (x
, 1)) != 0)
5436 *total
+= COSTS_N_INSNS (1);
5440 *total
= COSTS_N_INSNS (4);
5441 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5442 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
);
5443 else if (INTVAL (XEXP (x
, 1)) != 0)
5444 *total
+= COSTS_N_INSNS (3);
5450 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
);
5459 /* Calculate the cost of a memory address. */
5462 avr_address_cost (rtx x
)
5464 if (GET_CODE (x
) == PLUS
5465 && GET_CODE (XEXP (x
,1)) == CONST_INT
5466 && (REG_P (XEXP (x
,0)) || GET_CODE (XEXP (x
,0)) == SUBREG
)
5467 && INTVAL (XEXP (x
,1)) >= 61)
5469 if (CONSTANT_ADDRESS_P (x
))
5471 if (avr_io_address_p (x
, 1))
5478 /* EXTRA_CONSTRAINT helper */
5481 extra_constraint (rtx x
, int c
)
5484 && GET_CODE (x
) == MEM
5485 && GET_CODE (XEXP (x
,0)) == PLUS
)
5487 if (TARGET_ALL_DEBUG
)
5489 fprintf (stderr
, ("extra_constraint:\n"
5490 "reload_completed: %d\n"
5491 "reload_in_progress: %d\n"),
5492 reload_completed
, reload_in_progress
);
5495 if (GET_CODE (x
) == MEM
5496 && GET_CODE (XEXP (x
,0)) == PLUS
5497 && REG_P (XEXP (XEXP (x
,0), 0))
5498 && GET_CODE (XEXP (XEXP (x
,0), 1)) == CONST_INT
5499 && (INTVAL (XEXP (XEXP (x
,0), 1))
5500 <= MAX_LD_OFFSET (GET_MODE (x
))))
5502 rtx xx
= XEXP (XEXP (x
,0), 0);
5503 int regno
= REGNO (xx
);
5504 if (TARGET_ALL_DEBUG
)
5506 fprintf (stderr
, ("extra_constraint:\n"
5507 "reload_completed: %d\n"
5508 "reload_in_progress: %d\n"),
5509 reload_completed
, reload_in_progress
);
5512 if (regno
>= FIRST_PSEUDO_REGISTER
)
5513 return 1; /* allocate pseudos */
5514 else if (regno
== REG_Z
|| regno
== REG_Y
)
5515 return 1; /* strictly check */
5516 else if (xx
== frame_pointer_rtx
5517 || xx
== arg_pointer_rtx
)
5518 return 1; /* XXX frame & arg pointer checks */
5524 /* Convert condition code CONDITION to the valid AVR condition code. */
5527 avr_normalize_condition (RTX_CODE condition
)
5544 /* This function optimizes conditional jumps. */
5551 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
5553 if (! (GET_CODE (insn
) == INSN
5554 || GET_CODE (insn
) == CALL_INSN
5555 || GET_CODE (insn
) == JUMP_INSN
)
5556 || !single_set (insn
))
5559 pattern
= PATTERN (insn
);
5561 if (GET_CODE (pattern
) == PARALLEL
)
5562 pattern
= XVECEXP (pattern
, 0, 0);
5563 if (GET_CODE (pattern
) == SET
5564 && SET_DEST (pattern
) == cc0_rtx
5565 && compare_diff_p (insn
))
5567 if (GET_CODE (SET_SRC (pattern
)) == COMPARE
)
5569 /* Now we work under compare insn. */
5571 pattern
= SET_SRC (pattern
);
5572 if (true_regnum (XEXP (pattern
,0)) >= 0
5573 && true_regnum (XEXP (pattern
,1)) >= 0 )
5575 rtx x
= XEXP (pattern
,0);
5576 rtx next
= next_real_insn (insn
);
5577 rtx pat
= PATTERN (next
);
5578 rtx src
= SET_SRC (pat
);
5579 rtx t
= XEXP (src
,0);
5580 PUT_CODE (t
, swap_condition (GET_CODE (t
)));
5581 XEXP (pattern
,0) = XEXP (pattern
,1);
5582 XEXP (pattern
,1) = x
;
5583 INSN_CODE (next
) = -1;
5585 else if (true_regnum (XEXP (pattern
,0)) >= 0
5586 && GET_CODE (XEXP (pattern
,1)) == CONST_INT
)
5588 rtx x
= XEXP (pattern
,1);
5589 rtx next
= next_real_insn (insn
);
5590 rtx pat
= PATTERN (next
);
5591 rtx src
= SET_SRC (pat
);
5592 rtx t
= XEXP (src
,0);
5593 enum machine_mode mode
= GET_MODE (XEXP (pattern
, 0));
5595 if (avr_simplify_comparison_p (mode
, GET_CODE (t
), x
))
5597 XEXP (pattern
, 1) = gen_int_mode (INTVAL (x
) + 1, mode
);
5598 PUT_CODE (t
, avr_normalize_condition (GET_CODE (t
)));
5599 INSN_CODE (next
) = -1;
5600 INSN_CODE (insn
) = -1;
5604 else if (true_regnum (SET_SRC (pattern
)) >= 0)
5606 /* This is a tst insn */
5607 rtx next
= next_real_insn (insn
);
5608 rtx pat
= PATTERN (next
);
5609 rtx src
= SET_SRC (pat
);
5610 rtx t
= XEXP (src
,0);
5612 PUT_CODE (t
, swap_condition (GET_CODE (t
)));
5613 SET_SRC (pattern
) = gen_rtx_NEG (GET_MODE (SET_SRC (pattern
)),
5615 INSN_CODE (next
) = -1;
5616 INSN_CODE (insn
) = -1;
5622 /* Returns register number for function return value.*/
5625 avr_ret_register (void)
5630 /* Ceate an RTX representing the place where a
5631 library function returns a value of mode MODE. */
5634 avr_libcall_value (enum machine_mode mode
)
5636 int offs
= GET_MODE_SIZE (mode
);
5639 return gen_rtx_REG (mode
, RET_REGISTER
+ 2 - offs
);
5642 /* Create an RTX representing the place where a
5643 function returns a value of data type VALTYPE. */
5646 avr_function_value (tree type
, tree func ATTRIBUTE_UNUSED
)
5650 if (TYPE_MODE (type
) != BLKmode
)
5651 return avr_libcall_value (TYPE_MODE (type
));
5653 offs
= int_size_in_bytes (type
);
5656 if (offs
> 2 && offs
< GET_MODE_SIZE (SImode
))
5657 offs
= GET_MODE_SIZE (SImode
);
5658 else if (offs
> GET_MODE_SIZE (SImode
) && offs
< GET_MODE_SIZE (DImode
))
5659 offs
= GET_MODE_SIZE (DImode
);
5661 return gen_rtx_REG (BLKmode
, RET_REGISTER
+ 2 - offs
);
5664 /* Returns nonzero if the number MASK has only one bit set. */
5667 mask_one_bit_p (HOST_WIDE_INT mask
)
5670 unsigned HOST_WIDE_INT n
=mask
;
5671 for (i
= 0; i
< 32; ++i
)
5673 if (n
& 0x80000000L
)
5675 if (n
& 0x7fffffffL
)
5686 /* Places additional restrictions on the register class to
5687 use when it is necessary to copy value X into a register
5691 preferred_reload_class (rtx x ATTRIBUTE_UNUSED
, enum reg_class
class)
5697 test_hard_reg_class (enum reg_class
class, rtx x
)
5699 int regno
= true_regnum (x
);
5703 if (TEST_HARD_REG_CLASS (class, regno
))
5711 jump_over_one_insn_p (rtx insn
, rtx dest
)
5713 int uid
= INSN_UID (GET_CODE (dest
) == LABEL_REF
5716 int jump_addr
= INSN_ADDRESSES (INSN_UID (insn
));
5717 int dest_addr
= INSN_ADDRESSES (uid
);
5718 return dest_addr
- jump_addr
== get_attr_length (insn
) + 1;
5721 /* Returns 1 if a value of mode MODE can be stored starting with hard
5722 register number REGNO. On the enhanced core, anything larger than
5723 1 byte must start in even numbered register for "movw" to work
5724 (this way we don't have to check for odd registers everywhere). */
5727 avr_hard_regno_mode_ok (int regno
, enum machine_mode mode
)
5729 /* The only thing that can go into registers r28:r29 is a Pmode. */
5730 if (regno
== REG_Y
&& mode
== Pmode
)
5733 /* Otherwise disallow all regno/mode combinations that span r28:r29. */
5734 if (regno
<= (REG_Y
+ 1) && (regno
+ GET_MODE_SIZE (mode
)) >= (REG_Y
+ 1))
5740 /* Modes larger than QImode occupy consecutive registers. */
5741 if (regno
+ GET_MODE_SIZE (mode
) > FIRST_PSEUDO_REGISTER
)
5744 /* All modes larger than QImode should start in an even register. */
5745 return !(regno
& 1);
5748 /* Returns 1 if X is a valid address for an I/O register of size SIZE
5749 (1 or 2). Used for lds/sts -> in/out optimization. Add 0x20 to SIZE
5750 to check for the lower half of I/O space (for cbi/sbi/sbic/sbis). */
5753 avr_io_address_p (rtx x
, int size
)
5755 return (optimize
> 0 && GET_CODE (x
) == CONST_INT
5756 && INTVAL (x
) >= 0x20 && INTVAL (x
) <= 0x60 - size
);
5759 /* Returns nonzero (bit number + 1) if X, or -X, is a constant power of 2. */
5762 const_int_pow2_p (rtx x
)
5764 if (GET_CODE (x
) == CONST_INT
)
5766 HOST_WIDE_INT d
= INTVAL (x
);
5767 HOST_WIDE_INT abs_d
= (d
>= 0) ? d
: -d
;
5768 return exact_log2 (abs_d
) + 1;
5774 output_reload_inhi (rtx insn ATTRIBUTE_UNUSED
, rtx
*operands
, int *len
)
5780 if (GET_CODE (operands
[1]) == CONST_INT
)
5782 int val
= INTVAL (operands
[1]);
5783 if ((val
& 0xff) == 0)
5786 return (AS2 (mov
,%A0
,__zero_reg__
) CR_TAB
5787 AS2 (ldi
,%2,hi8(%1)) CR_TAB
5790 else if ((val
& 0xff00) == 0)
5793 return (AS2 (ldi
,%2,lo8(%1)) CR_TAB
5794 AS2 (mov
,%A0
,%2) CR_TAB
5795 AS2 (mov
,%B0
,__zero_reg__
));
5797 else if ((val
& 0xff) == ((val
& 0xff00) >> 8))
5800 return (AS2 (ldi
,%2,lo8(%1)) CR_TAB
5801 AS2 (mov
,%A0
,%2) CR_TAB
5806 return (AS2 (ldi
,%2,lo8(%1)) CR_TAB
5807 AS2 (mov
,%A0
,%2) CR_TAB
5808 AS2 (ldi
,%2,hi8(%1)) CR_TAB
5814 output_reload_insisf (rtx insn ATTRIBUTE_UNUSED
, rtx
*operands
, int *len
)
5816 rtx src
= operands
[1];
5817 int cnst
= (GET_CODE (src
) == CONST_INT
);
5822 *len
= 4 + ((INTVAL (src
) & 0xff) != 0)
5823 + ((INTVAL (src
) & 0xff00) != 0)
5824 + ((INTVAL (src
) & 0xff0000) != 0)
5825 + ((INTVAL (src
) & 0xff000000) != 0);
5832 if (cnst
&& ((INTVAL (src
) & 0xff) == 0))
5833 output_asm_insn (AS2 (mov
, %A0
, __zero_reg__
), operands
);
5836 output_asm_insn (AS2 (ldi
, %2, lo8(%1)), operands
);
5837 output_asm_insn (AS2 (mov
, %A0
, %2), operands
);
5839 if (cnst
&& ((INTVAL (src
) & 0xff00) == 0))
5840 output_asm_insn (AS2 (mov
, %B0
, __zero_reg__
), operands
);
5843 output_asm_insn (AS2 (ldi
, %2, hi8(%1)), operands
);
5844 output_asm_insn (AS2 (mov
, %B0
, %2), operands
);
5846 if (cnst
&& ((INTVAL (src
) & 0xff0000) == 0))
5847 output_asm_insn (AS2 (mov
, %C0
, __zero_reg__
), operands
);
5850 output_asm_insn (AS2 (ldi
, %2, hlo8(%1)), operands
);
5851 output_asm_insn (AS2 (mov
, %C0
, %2), operands
);
5853 if (cnst
&& ((INTVAL (src
) & 0xff000000) == 0))
5854 output_asm_insn (AS2 (mov
, %D0
, __zero_reg__
), operands
);
5857 output_asm_insn (AS2 (ldi
, %2, hhi8(%1)), operands
);
5858 output_asm_insn (AS2 (mov
, %D0
, %2), operands
);
5864 avr_output_bld (rtx operands
[], int bit_nr
)
5866 static char s
[] = "bld %A0,0";
5868 s
[5] = 'A' + (bit_nr
>> 3);
5869 s
[8] = '0' + (bit_nr
& 7);
5870 output_asm_insn (s
, operands
);
5874 avr_output_addr_vec_elt (FILE *stream
, int value
)
5876 switch_to_section (progmem_section
);
5878 fprintf (stream
, "\t.word pm(.L%d)\n", value
);
5880 fprintf (stream
, "\trjmp .L%d\n", value
);
5885 /* Returns 1 if SCRATCH are safe to be allocated as a scratch
5886 registers (for a define_peephole2) in the current function. */
5889 avr_peep2_scratch_safe (rtx scratch
)
5891 if ((interrupt_function_p (current_function_decl
)
5892 || signal_function_p (current_function_decl
))
5893 && leaf_function_p ())
5895 int first_reg
= true_regnum (scratch
);
5896 int last_reg
= first_reg
+ GET_MODE_SIZE (GET_MODE (scratch
)) - 1;
5899 for (reg
= first_reg
; reg
<= last_reg
; reg
++)
5901 if (!regs_ever_live
[reg
])
5908 /* Output a branch that tests a single bit of a register (QI, HI or SImode)
5909 or memory location in the I/O space (QImode only).
5911 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
5912 Operand 1: register operand to test, or CONST_INT memory address.
5913 Operand 2: bit number (for QImode operand) or mask (HImode, SImode).
5914 Operand 3: label to jump to if the test is true. */
5917 avr_out_sbxx_branch (rtx insn
, rtx operands
[])
5919 enum rtx_code comp
= GET_CODE (operands
[0]);
5920 int long_jump
= (get_attr_length (insn
) >= 4);
5921 int reverse
= long_jump
|| jump_over_one_insn_p (insn
, operands
[3]);
5925 else if (comp
== LT
)
5929 comp
= reverse_condition (comp
);
5931 if (GET_CODE (operands
[1]) == CONST_INT
)
5933 if (INTVAL (operands
[1]) < 0x40)
5936 output_asm_insn (AS2 (sbis
,%1-0x20,%2), operands
);
5938 output_asm_insn (AS2 (sbic
,%1-0x20,%2), operands
);
5942 output_asm_insn (AS2 (in
,__tmp_reg__
,%1-0x20), operands
);
5944 output_asm_insn (AS2 (sbrs
,__tmp_reg__
,%2), operands
);
5946 output_asm_insn (AS2 (sbrc
,__tmp_reg__
,%2), operands
);
5949 else /* GET_CODE (operands[1]) == REG */
5951 if (GET_MODE (operands
[1]) == QImode
)
5954 output_asm_insn (AS2 (sbrs
,%1,%2), operands
);
5956 output_asm_insn (AS2 (sbrc
,%1,%2), operands
);
5958 else /* HImode or SImode */
5960 static char buf
[] = "sbrc %A1,0";
5961 int bit_nr
= exact_log2 (INTVAL (operands
[2])
5962 & GET_MODE_MASK (GET_MODE (operands
[1])));
5964 buf
[3] = (comp
== EQ
) ? 's' : 'c';
5965 buf
[6] = 'A' + (bit_nr
>> 3);
5966 buf
[9] = '0' + (bit_nr
& 7);
5967 output_asm_insn (buf
, operands
);
5972 return (AS1 (rjmp
,.+4) CR_TAB
5975 return AS1 (rjmp
,%3);
5979 /* Worker function for TARGET_ASM_CONSTRUCTOR. */
5982 avr_asm_out_ctor (rtx symbol
, int priority
)
5984 fputs ("\t.global __do_global_ctors\n", asm_out_file
);
5985 default_ctor_section_asm_out_constructor (symbol
, priority
);
5988 /* Worker function for TARGET_ASM_DESTRUCTOR. */
5991 avr_asm_out_dtor (rtx symbol
, int priority
)
5993 fputs ("\t.global __do_global_dtors\n", asm_out_file
);
5994 default_dtor_section_asm_out_destructor (symbol
, priority
);
5997 /* Worker function for TARGET_RETURN_IN_MEMORY. */
6000 avr_return_in_memory (tree type
, tree fntype ATTRIBUTE_UNUSED
)
6002 if (TYPE_MODE (type
) == BLKmode
)
6004 HOST_WIDE_INT size
= int_size_in_bytes (type
);
6005 return (size
== -1 || size
> 8);