1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2 Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3 Contributed by Denis Chertykov (denisc@overta.ru)
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
26 #include "hard-reg-set.h"
28 #include "insn-config.h"
29 #include "conditions.h"
31 #include "insn-attr.h"
42 #include "target-def.h"
44 /* Maximal allowed offset for an address in the LD command */
45 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
47 static int avr_naked_function_p
PARAMS ((tree
));
48 static int interrupt_function_p
PARAMS ((tree
));
49 static int signal_function_p
PARAMS ((tree
));
50 static int sequent_regs_live
PARAMS ((void));
51 static const char * ptrreg_to_str
PARAMS ((int));
52 static const char * cond_string
PARAMS ((enum rtx_code
));
53 static int avr_num_arg_regs
PARAMS ((enum machine_mode
, tree
));
54 static int out_adj_frame_ptr
PARAMS ((FILE *, int));
55 static int out_set_stack_ptr
PARAMS ((FILE *, int, int));
56 static RTX_CODE compare_condition
PARAMS ((rtx insn
));
57 static int compare_sign_p
PARAMS ((rtx insn
));
58 static int reg_was_0
PARAMS ((rtx insn
, rtx op
));
59 static int io_address_p
PARAMS ((rtx x
, int size
));
60 void debug_hard_reg_set
PARAMS ((HARD_REG_SET set
));
61 static tree avr_handle_progmem_attribute
PARAMS ((tree
*, tree
, tree
, int, bool *));
62 static tree avr_handle_fndecl_attribute
PARAMS ((tree
*, tree
, tree
, int, bool *));
63 const struct attribute_spec avr_attribute_table
[];
64 static bool avr_assemble_integer
PARAMS ((rtx
, unsigned int, int));
65 static void avr_output_function_prologue
PARAMS ((FILE *, HOST_WIDE_INT
));
66 static void avr_output_function_epilogue
PARAMS ((FILE *, HOST_WIDE_INT
));
68 /* Allocate registers from r25 to r8 for parameters for function calls */
69 #define FIRST_CUM_REG 26
71 /* Temporary register RTX (gen_rtx (REG,QImode,TMP_REGNO)) */
74 /* Zeroed register RTX (gen_rtx (REG,QImode,ZERO_REGNO)) */
77 /* RTX for register which will be used for loading immediate values to
81 /* AVR register names {"r0", "r1", ..., "r31"} */
82 static const char *const avr_regnames
[] = REGISTER_NAMES
;
84 /* This holds the last insn address. */
85 static int last_insn_address
= 0;
87 /* Commands count in the compiled file */
88 static int commands_in_file
;
90 /* Commands in the functions prologues in the compiled file */
91 static int commands_in_prologues
;
93 /* Commands in the functions epilogues in the compiled file */
94 static int commands_in_epilogues
;
96 /* Prologue/Epilogue size in words */
97 static int prologue_size
;
98 static int epilogue_size
;
100 /* Size of all jump tables in the current function, in words. */
101 static int jump_tables_size
;
103 /* Initial stack value specified by the `-minit-stack=' option */
104 const char *avr_init_stack
= "__stack";
106 /* Default MCU name */
107 const char *avr_mcu_name
= "avr2";
109 /* More than 8K of program memory: use "call" and "jmp". */
112 /* Enhanced core: use "movw", "mul", ... */
113 int avr_enhanced_p
= 0;
124 const char *const name
;
125 const enum avr_arch arch
;
128 /* List of all known AVR MCU types - if updated, it has to be kept
129 in sync in several places (FIXME: is there a better way?):
131 - avr.h (CPP_SPEC, LINK_SPEC, CRT_BINUTILS_SPECS)
132 - t-avr (MULTILIB_MATCHES)
133 - gas/config/tc-avr.c
136 static const struct mcu_type_s avr_mcu_types
[] = {
137 /* Classic, <= 8K. */
139 { "at90s2313", AVR2
},
140 { "at90s2323", AVR2
},
141 { "attiny22", AVR2
},
142 { "at90s2333", AVR2
},
143 { "at90s2343", AVR2
},
144 { "at90s4414", AVR2
},
145 { "at90s4433", AVR2
},
146 { "at90s4434", AVR2
},
147 { "at90s8515", AVR2
},
148 { "at90c8534", AVR2
},
149 { "at90s8535", AVR2
},
152 { "atmega103", AVR3
},
153 { "atmega603", AVR3
},
154 /* Enhanced, <= 8K. */
156 { "atmega83", AVR4
},
157 { "atmega85", AVR4
},
158 /* Enhanced, > 8K. */
160 { "atmega161", AVR5
},
161 { "atmega163", AVR5
},
162 { "atmega32", AVR5
},
164 /* Assembler only. */
166 { "at90s1200", AVR1
},
167 { "attiny10", AVR1
},
168 { "attiny11", AVR1
},
169 { "attiny12", AVR1
},
170 { "attiny15", AVR1
},
171 { "attiny28", AVR1
},
175 int avr_case_values_threshold
= 30000;
177 /* Initialize the GCC target structure. */
178 #undef TARGET_ASM_ALIGNED_HI_OP
179 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
180 #undef TARGET_ASM_INTEGER
181 #define TARGET_ASM_INTEGER avr_assemble_integer
183 #undef TARGET_ASM_FUNCTION_PROLOGUE
184 #define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
185 #undef TARGET_ASM_FUNCTION_EPILOGUE
186 #define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
187 #undef TARGET_ATTRIBUTE_TABLE
188 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
190 struct gcc_target targetm
= TARGET_INITIALIZER
;
193 avr_override_options ()
195 const struct mcu_type_s
*t
;
197 for (t
= avr_mcu_types
; t
->name
; t
++)
198 if (strcmp (t
->name
, avr_mcu_name
) == 0)
203 fprintf (stderr
, "unknown MCU `%s' specified\nKnown MCU names:\n",
205 for (t
= avr_mcu_types
; t
->name
; t
++)
206 fprintf (stderr
," %s\n", t
->name
);
213 error ("MCU `%s' not supported", avr_mcu_name
);
214 /* ... fall through ... */
215 case AVR2
: avr_enhanced_p
= 0; avr_mega_p
= 0; break;
216 case AVR3
: avr_enhanced_p
= 0; avr_mega_p
= 1; break;
217 case AVR4
: avr_enhanced_p
= 1; avr_mega_p
= 0; break;
218 case AVR5
: avr_enhanced_p
= 1; avr_mega_p
= 1; break;
221 if (optimize
&& !TARGET_NO_TABLEJUMP
)
222 avr_case_values_threshold
= (!AVR_MEGA
|| TARGET_CALL_PROLOGUES
) ? 8 : 17;
226 /* Initialize TMP_REG_RTX and ZERO_REG_RTX */
230 tmp_reg_rtx
= xmalloc (sizeof (struct rtx_def
) + 1 * sizeof (rtunion
));
231 memset (tmp_reg_rtx
, 0, sizeof (struct rtx_def
) + 1 * sizeof (rtunion
));
232 PUT_CODE (tmp_reg_rtx
, REG
);
233 PUT_MODE (tmp_reg_rtx
, QImode
);
234 XINT (tmp_reg_rtx
, 0) = TMP_REGNO
;
236 zero_reg_rtx
= xmalloc (sizeof (struct rtx_def
) + 1 * sizeof (rtunion
));
237 memset (zero_reg_rtx
, 0, sizeof (struct rtx_def
) + 1 * sizeof (rtunion
));
238 PUT_CODE (zero_reg_rtx
, REG
);
239 PUT_MODE (zero_reg_rtx
, QImode
);
240 XINT (zero_reg_rtx
, 0) = ZERO_REGNO
;
242 ldi_reg_rtx
= xmalloc (sizeof (struct rtx_def
) + 1 * sizeof (rtunion
));
243 memset (ldi_reg_rtx
, 0, sizeof (struct rtx_def
) + 1 * sizeof (rtunion
));
244 PUT_CODE (ldi_reg_rtx
, REG
);
245 PUT_MODE (ldi_reg_rtx
, QImode
);
246 XINT (ldi_reg_rtx
, 0) = LDI_REG_REGNO
;
249 /* return register class from register number */
251 static const int reg_class_tab
[]={
252 GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,
253 GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,
254 GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,GENERAL_REGS
,
255 GENERAL_REGS
, /* r0 - r15 */
256 LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,LD_REGS
,
257 LD_REGS
, /* r16 - 23 */
258 ADDW_REGS
,ADDW_REGS
, /* r24,r25 */
259 POINTER_X_REGS
,POINTER_X_REGS
, /* r26,27 */
260 POINTER_Y_REGS
,POINTER_Y_REGS
, /* r28,r29 */
261 POINTER_Z_REGS
,POINTER_Z_REGS
, /* r30,r31 */
262 STACK_REG
,STACK_REG
/* SPL,SPH */
265 /* Return register class for register R */
268 avr_regno_reg_class (r
)
272 return reg_class_tab
[r
];
277 /* A C expression which defines the machine-dependent operand
278 constraint letters for register classes. If C is such a
279 letter, the value should be the register class corresponding to
280 it. Otherwise, the value should be `NO_REGS'. The register
281 letter `r', corresponding to class `GENERAL_REGS', will not be
282 passed to this macro; you do not need to handle it. */
285 avr_reg_class_from_letter (c
)
290 case 't' : return R0_REG
;
291 case 'b' : return BASE_POINTER_REGS
;
292 case 'e' : return POINTER_REGS
;
293 case 'w' : return ADDW_REGS
;
294 case 'd' : return LD_REGS
;
295 case 'l' : return NO_LD_REGS
;
296 case 'a' : return SIMPLE_LD_REGS
;
297 case 'x' : return POINTER_X_REGS
;
298 case 'y' : return POINTER_Y_REGS
;
299 case 'z' : return POINTER_Z_REGS
;
300 case 'q' : return STACK_REG
;
306 /* Return non-zero if FUNC is a naked function. */
309 avr_naked_function_p (func
)
314 if (TREE_CODE (func
) != FUNCTION_DECL
)
317 a
= lookup_attribute ("naked", DECL_ATTRIBUTES (func
));
318 return a
!= NULL_TREE
;
321 /* Return nonzero if FUNC is an interrupt function as specified
322 by the "interrupt" attribute. */
325 interrupt_function_p (func
)
330 if (TREE_CODE (func
) != FUNCTION_DECL
)
333 a
= lookup_attribute ("interrupt", DECL_ATTRIBUTES (func
));
334 return a
!= NULL_TREE
;
337 /* Return nonzero if FUNC is a signal function as specified
338 by the "signal" attribute. */
341 signal_function_p (func
)
346 if (TREE_CODE (func
) != FUNCTION_DECL
)
349 a
= lookup_attribute ("signal", DECL_ATTRIBUTES (func
));
350 return a
!= NULL_TREE
;
353 /* Compute offset between arg_pointer and frame_pointer */
356 initial_elimination_offset (from
, to
)
361 if (from
== FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
365 int interrupt_func_p
= interrupt_function_p (current_function_decl
);
366 int signal_func_p
= signal_function_p (current_function_decl
);
367 int leaf_func_p
= leaf_function_p ();
368 int offset
= frame_pointer_needed
? 2 : 0;
370 for (reg
= 0; reg
< 32; ++reg
)
372 if ((!leaf_func_p
&& (call_used_regs
[reg
]
373 && (interrupt_func_p
|| signal_func_p
)))
374 || (regs_ever_live
[reg
]
375 && (!call_used_regs
[reg
] || interrupt_func_p
|| signal_func_p
)
376 && ! (frame_pointer_needed
377 && (reg
== REG_Y
|| reg
== (REG_Y
+1)))))
382 return get_frame_size () + 2 + 1 + offset
;
387 /* This function checks sequence of live registers */
396 for (reg
= 0; reg
< 18; ++reg
)
398 if (!call_used_regs
[reg
])
400 if (regs_ever_live
[reg
])
410 if (!frame_pointer_needed
)
412 if (regs_ever_live
[REG_Y
])
420 if (regs_ever_live
[REG_Y
+1])
433 return (cur_seq
== live_seq
) ? live_seq
: 0;
437 /* Output to FILE the asm instructions to adjust the frame pointer by
438 ADJ (r29:r28 -= ADJ;) which can be positive (prologue) or negative
439 (epilogue). Returns the number of instructions generated. */
442 out_adj_frame_ptr (file
, adj
)
450 if (TARGET_TINY_STACK
)
452 if (adj
< -63 || adj
> 63)
453 warning ("large frame pointer change (%d) with -mtiny-stack", adj
);
455 /* The high byte (r29) doesn't change - prefer "subi" (1 cycle)
456 over "sbiw" (2 cycles, same size). */
458 fprintf (file
, (AS2 (subi
, r28
, %d
) CR_TAB
), adj
);
461 else if (adj
< -63 || adj
> 63)
463 fprintf (file
, (AS2 (subi
, r28
, lo8(%d
)) CR_TAB
464 AS2 (sbci
, r29
, hi8(%d
)) CR_TAB
),
470 fprintf (file
, (AS2 (adiw
, r28
, %d
) CR_TAB
), -adj
);
475 fprintf (file
, (AS2 (sbiw
, r28
, %d
) CR_TAB
), adj
);
483 /* Output to FILE the asm instructions to copy r29:r28 to SPH:SPL,
484 handling various cases of interrupt enable flag state BEFORE and AFTER
485 (0=disabled, 1=enabled, -1=unknown/unchanged) and target_flags.
486 Returns the number of instructions generated. */
489 out_set_stack_ptr (file
, before
, after
)
494 int do_sph
, do_cli
, do_save
, do_sei
, lock_sph
, size
;
496 /* The logic here is so that -mno-interrupts actually means
497 "it is safe to write SPH in one instruction, then SPL in the
498 next instruction, without disabling interrupts first".
499 The after != -1 case (interrupt/signal) is not affected. */
501 do_sph
= !TARGET_TINY_STACK
;
502 lock_sph
= do_sph
&& !TARGET_NO_INTERRUPTS
;
503 do_cli
= (before
!= 0 && (after
== 0 || lock_sph
));
504 do_save
= (do_cli
&& before
== -1 && after
== -1);
505 do_sei
= ((do_cli
|| before
!= 1) && after
== 1);
510 fprintf (file
, AS2 (in
, __tmp_reg__
, __SREG__
) CR_TAB
);
516 fprintf (file
, "cli" CR_TAB
);
520 /* Do SPH first - maybe this will disable interrupts for one instruction
521 someday (a suggestion has been sent to avr@atmel.com for consideration
522 in future devices - that would make -mno-interrupts always safe). */
525 fprintf (file
, AS2 (out
, __SP_H__
, r29
) CR_TAB
);
529 /* Set/restore the I flag now - interrupts will be really enabled only
530 after the next instruction. This is not clearly documented, but
531 believed to be true for all AVR devices. */
534 fprintf (file
, AS2 (out
, __SREG__
, __tmp_reg__
) CR_TAB
);
539 fprintf (file
, "sei" CR_TAB
);
543 fprintf (file
, AS2 (out
, __SP_L__
, r28
) "\n");
549 /* Output function prologue */
552 avr_output_function_prologue (file
, size
)
557 int interrupt_func_p
;
564 if (avr_naked_function_p (current_function_decl
))
566 fprintf (file
, "/* prologue: naked */\n");
570 interrupt_func_p
= interrupt_function_p (current_function_decl
);
571 signal_func_p
= signal_function_p (current_function_decl
);
572 leaf_func_p
= leaf_function_p ();
573 main_p
= MAIN_NAME_P (DECL_NAME (current_function_decl
));
574 live_seq
= sequent_regs_live ();
575 minimize
= (TARGET_CALL_PROLOGUES
576 && !interrupt_func_p
&& !signal_func_p
&& live_seq
);
578 last_insn_address
= 0;
579 jump_tables_size
= 0;
581 fprintf (file
, "/* prologue: frame size=%d */\n", size
);
583 if (interrupt_func_p
)
585 fprintf (file
,"\tsei\n");
588 if (interrupt_func_p
| signal_func_p
)
591 AS1 (push
,__zero_reg__
) CR_TAB
592 AS1 (push
,__tmp_reg__
) CR_TAB
593 AS2 (in
,__tmp_reg__
,__SREG__
) CR_TAB
594 AS1 (push
,__tmp_reg__
) CR_TAB
595 AS1 (clr
,__zero_reg__
) "\n");
601 AS2 (ldi
,r28
,lo8(%s
- %d
)) CR_TAB
602 AS2 (ldi
,r29
,hi8(%s
- %d
)) CR_TAB
603 AS2 (out
,__SP_H__
,r29
) CR_TAB
604 AS2 (out
,__SP_L__
,r28
) "\n"),
605 avr_init_stack
, size
, avr_init_stack
, size
);
609 else if (minimize
&& (frame_pointer_needed
|| live_seq
> 6))
612 AS2 (ldi
, r26
, lo8(%d
)) CR_TAB
613 AS2 (ldi
, r27
, hi8(%d
)) CR_TAB
), size
, size
);
615 fprintf (file
, (AS2 (ldi
, r30
, pm_lo8(.L_
%s_body
)) CR_TAB
616 AS2 (ldi
, r31
, pm_hi8(.L_
%s_body
)) CR_TAB
)
617 ,current_function_name
, current_function_name
);
623 fprintf (file
, AS1 (jmp
,__prologue_saves__
+%d
) "\n",
624 (18 - live_seq
) * 2);
629 fprintf (file
, AS1 (rjmp
,__prologue_saves__
+%d
) "\n",
630 (18 - live_seq
) * 2);
633 fprintf (file
, ".L_%s_body:\n", current_function_name
);
637 for (reg
= 0; reg
< 32; ++reg
)
640 && (call_used_regs
[reg
]
641 && (interrupt_func_p
|| signal_func_p
)
642 && !(reg
== TMP_REGNO
|| reg
== ZERO_REGNO
)))
643 || (regs_ever_live
[reg
]
644 && (!call_used_regs
[reg
]
645 || interrupt_func_p
|| signal_func_p
)
646 && ! (frame_pointer_needed
647 && (reg
== REG_Y
|| reg
== (REG_Y
+1)))))
649 fprintf (file
, "\t" AS1 (push
,%s
) "\n", avr_regnames
[reg
]);
653 if (frame_pointer_needed
)
657 AS1 (push
,r28
) CR_TAB
658 AS1 (push
,r29
) CR_TAB
659 AS2 (in
,r28
,__SP_L__
) CR_TAB
660 AS2 (in
,r29
,__SP_H__
) "\n");
665 prologue_size
+= out_adj_frame_ptr (file
, size
);
667 if (interrupt_func_p
)
669 prologue_size
+= out_set_stack_ptr (file
, 1, 1);
671 else if (signal_func_p
)
673 prologue_size
+= out_set_stack_ptr (file
, 0, 0);
677 prologue_size
+= out_set_stack_ptr (file
, -1, -1);
683 fprintf (file
, "/* prologue end (size=%d) */\n", prologue_size
);
686 /* Output function epilogue */
689 avr_output_function_epilogue (file
, size
)
694 int interrupt_func_p
;
702 if (avr_naked_function_p (current_function_decl
))
704 fprintf (file
, "/* epilogue: naked */\n");
708 interrupt_func_p
= interrupt_function_p (current_function_decl
);
709 signal_func_p
= signal_function_p (current_function_decl
);
710 leaf_func_p
= leaf_function_p ();
711 main_p
= MAIN_NAME_P (DECL_NAME (current_function_decl
));
712 function_size
= (INSN_ADDRESSES (INSN_UID (get_last_insn ()))
713 - INSN_ADDRESSES (INSN_UID (get_insns ())));
714 function_size
+= jump_tables_size
;
715 live_seq
= sequent_regs_live ();
716 minimize
= (TARGET_CALL_PROLOGUES
717 && !interrupt_func_p
&& !signal_func_p
&& live_seq
);
720 fprintf (file
, "/* epilogue: frame size=%d */\n", size
);
723 fprintf (file
, "__stop_progIi__:\n\trjmp __stop_progIi__\n");
726 else if (minimize
&& (frame_pointer_needed
|| live_seq
> 4))
728 fprintf (file
, ("\t" AS2 (ldi
, r30
, %d
) CR_TAB
), live_seq
);
730 if (frame_pointer_needed
)
732 epilogue_size
+= out_adj_frame_ptr (file
, -size
);
736 fprintf (file
, (AS2 (in
, r28
, __SP_L__
) CR_TAB
737 AS2 (in
, r29
, __SP_H__
) CR_TAB
));
743 fprintf (file
, AS1 (jmp
,__epilogue_restores__
+%d
) "\n",
744 (18 - live_seq
) * 2);
749 fprintf (file
, AS1 (rjmp
,__epilogue_restores__
+%d
) "\n",
750 (18 - live_seq
) * 2);
756 if (frame_pointer_needed
)
761 epilogue_size
+= out_adj_frame_ptr (file
, -size
);
763 if (interrupt_func_p
| signal_func_p
)
765 epilogue_size
+= out_set_stack_ptr (file
, -1, 0);
769 epilogue_size
+= out_set_stack_ptr (file
, -1, -1);
778 for (reg
= 31; reg
>= 0; --reg
)
781 && (call_used_regs
[reg
]
782 && (interrupt_func_p
|| signal_func_p
)
783 && !(reg
== TMP_REGNO
|| reg
== ZERO_REGNO
)))
784 || (regs_ever_live
[reg
]
785 && (!call_used_regs
[reg
]
786 || interrupt_func_p
|| signal_func_p
)
787 && ! (frame_pointer_needed
788 && (reg
== REG_Y
|| reg
== (REG_Y
+1)))))
790 fprintf (file
, "\t" AS1 (pop
,%s
) "\n", avr_regnames
[reg
]);
795 if (interrupt_func_p
| signal_func_p
)
798 AS1 (pop
,__tmp_reg__
) CR_TAB
799 AS2 (out
,__SREG__
,__tmp_reg__
) CR_TAB
800 AS1 (pop
,__tmp_reg__
) CR_TAB
801 AS1 (pop
,__zero_reg__
) "\n");
803 fprintf (file
, "\treti\n");
806 fprintf (file
, "\tret\n");
810 fprintf (file
, "/* epilogue end (size=%d) */\n", epilogue_size
);
811 fprintf (file
, "/* function %s size %d (%d) */\n", current_function_name
,
812 prologue_size
+ function_size
+ epilogue_size
, function_size
);
813 commands_in_file
+= prologue_size
+ function_size
+ epilogue_size
;
814 commands_in_prologues
+= prologue_size
;
815 commands_in_epilogues
+= epilogue_size
;
819 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
820 machine for a memory operand of mode MODE. */
823 legitimate_address_p (mode
, x
, strict
)
824 enum machine_mode mode
;
828 enum reg_class r
= NO_REGS
;
830 if (TARGET_ALL_DEBUG
)
832 fprintf (stderr
, "mode: (%s) %s %s %s %s:",
834 strict
? "(strict)": "",
835 reload_completed
? "(reload_completed)": "",
836 reload_in_progress
? "(reload_in_progress)": "",
837 reg_renumber
? "(reg_renumber)" : "");
838 if (GET_CODE (x
) == PLUS
839 && REG_P (XEXP (x
, 0))
840 && GET_CODE (XEXP (x
, 1)) == CONST_INT
841 && INTVAL (XEXP (x
, 1)) >= 0
842 && INTVAL (XEXP (x
, 1)) <= MAX_LD_OFFSET (mode
)
845 fprintf (stderr
, "(r%d ---> r%d)", REGNO (XEXP (x
, 0)),
846 true_regnum (XEXP (x
, 0)));
849 if (REG_P (x
) && (strict
? REG_OK_FOR_BASE_STRICT_P (x
)
850 : REG_OK_FOR_BASE_NOSTRICT_P (x
)))
852 else if (CONSTANT_ADDRESS_P (x
))
854 else if (GET_CODE (x
) == PLUS
855 && REG_P (XEXP (x
, 0))
856 && GET_CODE (XEXP (x
, 1)) == CONST_INT
857 && INTVAL (XEXP (x
, 1)) >= 0)
859 int fit
= INTVAL (XEXP (x
, 1)) <= MAX_LD_OFFSET (mode
);
863 || REGNO (XEXP (x
,0)) == REG_Y
864 || REGNO (XEXP (x
,0)) == REG_Z
)
865 r
= BASE_POINTER_REGS
;
866 if (XEXP (x
,0) == frame_pointer_rtx
867 || XEXP (x
,0) == arg_pointer_rtx
)
868 r
= BASE_POINTER_REGS
;
870 else if (frame_pointer_needed
&& XEXP (x
,0) == frame_pointer_rtx
)
873 else if ((GET_CODE (x
) == PRE_DEC
|| GET_CODE (x
) == POST_INC
)
874 && REG_P (XEXP (x
, 0))
875 && (strict
? REG_OK_FOR_BASE_STRICT_P (XEXP (x
, 0))
876 : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x
, 0))))
880 if (TARGET_ALL_DEBUG
)
882 fprintf (stderr
, " ret = %c\n", r
);
884 return r
== NO_REGS
? 0 : (int)r
;
887 /* Attempts to replace X with a valid
888 memory address for an operand of mode MODE */
891 legitimize_address (x
, oldx
, mode
)
894 enum machine_mode mode
;
897 if (TARGET_ALL_DEBUG
)
899 fprintf (stderr
, "legitimize_address mode: %s", GET_MODE_NAME(mode
));
903 if (GET_CODE (oldx
) == PLUS
904 && REG_P (XEXP (oldx
,0)))
906 if (REG_P (XEXP (oldx
,1)))
907 x
= force_reg (GET_MODE (oldx
), oldx
);
908 else if (GET_CODE (XEXP (oldx
, 1)) == CONST_INT
)
910 int offs
= INTVAL (XEXP (oldx
,1));
911 if (frame_pointer_rtx
!= XEXP (oldx
,0))
912 if (offs
> MAX_LD_OFFSET (mode
))
914 if (TARGET_ALL_DEBUG
)
915 fprintf (stderr
, "force_reg (big offset)\n");
916 x
= force_reg (GET_MODE (oldx
), oldx
);
924 /* Return a pointer register name as a string */
927 ptrreg_to_str (regno
)
932 case REG_X
: return "X";
933 case REG_Y
: return "Y";
934 case REG_Z
: return "Z";
941 /* Return the condition name as a string.
942 Used in conditional jump constructing */
955 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
960 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
973 /* Output ADDR to FILE as address */
976 print_operand_address (file
, addr
)
980 switch (GET_CODE (addr
))
983 fprintf (file
, ptrreg_to_str (REGNO (addr
)));
987 fprintf (file
, "-%s", ptrreg_to_str (REGNO (XEXP (addr
, 0))));
991 fprintf (file
, "%s+", ptrreg_to_str (REGNO (XEXP (addr
, 0))));
995 if (CONSTANT_ADDRESS_P (addr
)
996 && (SYMBOL_REF_FLAG (addr
) || GET_CODE (addr
) == LABEL_REF
))
998 fprintf (file
, "pm(");
999 output_addr_const (file
,addr
);
1000 fprintf (file
,")");
1003 output_addr_const (file
, addr
);
1008 /* Output X as assembler operand to file FILE */
1011 print_operand (file
, x
, code
)
1018 if (code
>= 'A' && code
<= 'D')
1028 if (x
== zero_reg_rtx
)
1029 fprintf (file
, "__zero_reg__");
1031 fprintf (file
, reg_names
[true_regnum (x
) + abcd
]);
1033 else if (GET_CODE (x
) == CONST_INT
)
1034 fprintf (file
, "%d", INTVAL (x
) + abcd
);
1035 else if (GET_CODE (x
) == MEM
)
1037 rtx addr
= XEXP (x
,0);
1039 if (CONSTANT_P (addr
) && abcd
)
1042 output_address (addr
);
1043 fprintf (file
, ")+%d", abcd
);
1045 else if (code
== 'o')
1047 if (GET_CODE (addr
) != PLUS
)
1048 fatal_insn ("bad address, not (reg+disp):", addr
);
1050 print_operand (file
, XEXP (addr
, 1), 0);
1052 else if (GET_CODE (addr
) == PLUS
)
1054 print_operand_address (file
, XEXP (addr
,0));
1055 if (REGNO (XEXP (addr
, 0)) == REG_X
)
1056 fatal_insn ("internal compiler error. Bad address:"
1059 print_operand (file
, XEXP (addr
,1), code
);
1062 print_operand_address (file
, addr
);
1064 else if (GET_CODE (x
) == CONST_DOUBLE
)
1068 if (GET_MODE (x
) != SFmode
)
1069 fatal_insn ("internal compiler error. Unknown mode:", x
);
1070 REAL_VALUE_FROM_CONST_DOUBLE (rv
, x
);
1071 REAL_VALUE_TO_TARGET_SINGLE (rv
, val
);
1072 asm_fprintf (file
, "0x%lx", val
);
1074 else if (code
== 'j')
1075 asm_fprintf (file
, cond_string (GET_CODE (x
)));
1076 else if (code
== 'k')
1077 asm_fprintf (file
, cond_string (reverse_condition (GET_CODE (x
))));
1079 print_operand_address (file
, x
);
1082 /* Recognize operand OP of mode MODE used in call instructions */
1085 call_insn_operand (op
, mode
)
1087 enum machine_mode mode ATTRIBUTE_UNUSED
;
1089 if (GET_CODE (op
) == MEM
)
1091 rtx inside
= XEXP (op
, 0);
1092 if (register_operand (inside
, Pmode
))
1094 if (CONSTANT_ADDRESS_P (inside
))
1100 /* Update the condition code in the INSN. */
1103 notice_update_cc (body
, insn
)
1104 rtx body ATTRIBUTE_UNUSED
;
1109 switch (get_attr_cc (insn
))
1112 /* Insn does not affect CC at all. */
1120 set
= single_set (insn
);
1124 cc_status
.flags
|= CC_NO_OVERFLOW
;
1125 cc_status
.value1
= SET_DEST (set
);
1130 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
1131 The V flag may or may not be known but that's ok because
1132 alter_cond will change tests to use EQ/NE. */
1133 set
= single_set (insn
);
1137 cc_status
.value1
= SET_DEST (set
);
1138 cc_status
.flags
|= CC_OVERFLOW_UNUSABLE
;
1143 set
= single_set (insn
);
1146 cc_status
.value1
= SET_SRC (set
);
1150 /* Insn doesn't leave CC in a usable state. */
1153 /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1154 set
= single_set (insn
);
1157 rtx src
= SET_SRC (set
);
1159 if (GET_CODE (src
) == ASHIFTRT
1160 && GET_MODE (src
) == QImode
)
1162 rtx x
= XEXP (src
, 1);
1164 if (GET_CODE (x
) == CONST_INT
1167 cc_status
.value1
= SET_DEST (set
);
1168 cc_status
.flags
|= CC_OVERFLOW_UNUSABLE
;
1176 /* Return maximum number of consecutive registers of
1177 class CLASS needed to hold a value of mode MODE. */
1180 class_max_nregs (class, mode
)
1181 enum reg_class
class ATTRIBUTE_UNUSED
;
1182 enum machine_mode mode
;
1184 return ((GET_MODE_SIZE (mode
) + UNITS_PER_WORD
- 1) / UNITS_PER_WORD
);
1187 /* Choose mode for jump insn:
1188 1 - relative jump in range -63 <= x <= 62 ;
1189 2 - relative jump in range -2046 <= x <= 2045 ;
1190 3 - absolute jump (only for ATmega[16]03). */
1193 avr_jump_mode (x
, insn
)
1194 rtx x
; /* jump operand */
1195 rtx insn
; /* jump insn */
1197 int dest_addr
= INSN_ADDRESSES (INSN_UID (GET_MODE (x
) == LABEL_REF
1198 ? XEXP (x
, 0) : x
));
1199 int cur_addr
= INSN_ADDRESSES (INSN_UID (insn
));
1200 int jump_distance
= cur_addr
- dest_addr
;
1202 if (-63 <= jump_distance
&& jump_distance
<= 62)
1204 else if (-2046 <= jump_distance
&& jump_distance
<= 2045)
1212 /* return an AVR condition jump commands.
1213 X is a comparison RTX.
1214 LEN is a number returned by avr_jump_mode function.
1215 if REVERSE nonzero then condition code in X must be reversed. */
1218 ret_cond_branch (x
, len
, reverse
)
1223 RTX_CODE cond
= reverse
? reverse_condition (GET_CODE (x
)) : GET_CODE (x
);
1228 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1229 return (len
== 1 ? (AS1 (breq
,_PC_
+2) CR_TAB
1231 len
== 2 ? (AS1 (breq
,_PC_
+4) CR_TAB
1232 AS1 (brmi
,_PC_
+2) CR_TAB
1234 (AS1 (breq
,_PC_
+6) CR_TAB
1235 AS1 (brmi
,_PC_
+4) CR_TAB
1239 return (len
== 1 ? (AS1 (breq
,_PC_
+2) CR_TAB
1241 len
== 2 ? (AS1 (breq
,_PC_
+4) CR_TAB
1242 AS1 (brlt
,_PC_
+2) CR_TAB
1244 (AS1 (breq
,_PC_
+6) CR_TAB
1245 AS1 (brlt
,_PC_
+4) CR_TAB
1248 return (len
== 1 ? (AS1 (breq
,_PC_
+2) CR_TAB
1250 len
== 2 ? (AS1 (breq
,_PC_
+4) CR_TAB
1251 AS1 (brlo
,_PC_
+2) CR_TAB
1253 (AS1 (breq
,_PC_
+6) CR_TAB
1254 AS1 (brlo
,_PC_
+4) CR_TAB
1257 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
1258 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1260 len
== 2 ? (AS1 (breq
,_PC_
+2) CR_TAB
1261 AS1 (brpl
,_PC_
+2) CR_TAB
1263 (AS1 (breq
,_PC_
+2) CR_TAB
1264 AS1 (brpl
,_PC_
+4) CR_TAB
1267 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1269 len
== 2 ? (AS1 (breq
,_PC_
+2) CR_TAB
1270 AS1 (brge
,_PC_
+2) CR_TAB
1272 (AS1 (breq
,_PC_
+2) CR_TAB
1273 AS1 (brge
,_PC_
+4) CR_TAB
1276 return (len
== 1 ? (AS1 (breq
,%0) CR_TAB
1278 len
== 2 ? (AS1 (breq
,_PC_
+2) CR_TAB
1279 AS1 (brsh
,_PC_
+2) CR_TAB
1281 (AS1 (breq
,_PC_
+2) CR_TAB
1282 AS1 (brsh
,_PC_
+4) CR_TAB
1290 return AS1 (br
%k1
,%0);
1292 return (AS1 (br
%j1
,_PC_
+2) CR_TAB
1295 return (AS1 (br
%j1
,_PC_
+4) CR_TAB
1304 return AS1 (br
%j1
,%0);
1306 return (AS1 (br
%k1
,_PC_
+2) CR_TAB
1309 return (AS1 (br
%k1
,_PC_
+4) CR_TAB
1317 /* Predicate function for immediate operand which fits to byte (8bit) */
1320 byte_immediate_operand (op
, mode
)
1322 enum machine_mode mode ATTRIBUTE_UNUSED
;
1324 return (GET_CODE (op
) == CONST_INT
1325 && INTVAL (op
) <= 0xff && INTVAL (op
) >= 0);
1328 /* Output all insn addresses and their sizes into the assembly language
1329 output file. This is helpful for debugging whether the length attributes
1330 in the md file are correct.
1331 Output insn cost for next insn. */
1334 final_prescan_insn (insn
, operand
, num_operands
)
1335 rtx insn
, *operand ATTRIBUTE_UNUSED
;
1336 int num_operands ATTRIBUTE_UNUSED
;
1338 int uid
= INSN_UID (insn
);
1340 if (TARGET_INSN_SIZE_DUMP
|| TARGET_ALL_DEBUG
)
1342 fprintf (asm_out_file
, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
1343 INSN_ADDRESSES (uid
),
1344 INSN_ADDRESSES (uid
) - last_insn_address
,
1345 rtx_cost (PATTERN (insn
), INSN
));
1347 last_insn_address
= INSN_ADDRESSES (uid
);
1349 if (TARGET_RTL_DUMP
)
1351 fprintf (asm_out_file
, "/*****************\n");
1352 print_rtl_single (asm_out_file
, insn
);
1353 fprintf (asm_out_file
, "*****************/\n");
1357 /* Return 0 if undefined, 1 if always true or always false. */
1360 avr_simplify_comparision_p (mode
, operator, x
)
1361 enum machine_mode mode
;
1365 unsigned int max
= (mode
== QImode
? 0xff :
1366 mode
== HImode
? 0xffff :
1367 mode
== SImode
? 0xffffffff : 0);
1368 if (max
&& operator && GET_CODE (x
) == CONST_INT
)
1370 if (unsigned_condition (operator) != operator)
1373 if (max
!= (INTVAL (x
) & max
)
1374 && INTVAL (x
) != 0xff)
1381 /* Returns nonzero if REGNO is the number of a hard
1382 register in which function arguments are sometimes passed. */
1385 function_arg_regno_p(r
)
1388 return (r
>= 8 && r
<= 25);
1391 /* Initializing the variable cum for the state at the beginning
1392 of the argument list. */
1395 init_cumulative_args (cum
, fntype
, libname
, indirect
)
1396 CUMULATIVE_ARGS
*cum
;
1399 int indirect ATTRIBUTE_UNUSED
;
1402 cum
->regno
= FIRST_CUM_REG
;
1405 int stdarg
= (TYPE_ARG_TYPES (fntype
) != 0
1406 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype
)))
1407 != void_type_node
));
1413 /* Returns the number of registers to allocate for a function argument. */
1416 avr_num_arg_regs (mode
, type
)
1417 enum machine_mode mode
;
1422 if (mode
== BLKmode
)
1423 size
= int_size_in_bytes (type
);
1425 size
= GET_MODE_SIZE (mode
);
1427 /* Align all function arguments to start in even-numbered registers.
1428 Odd-sized arguments leave holes above them. */
1430 return (size
+ 1) & ~1;
1433 /* Controls whether a function argument is passed
1434 in a register, and which register. */
1437 function_arg (cum
, mode
, type
, named
)
1438 CUMULATIVE_ARGS
*cum
;
1439 enum machine_mode mode
;
1441 int named ATTRIBUTE_UNUSED
;
1443 int bytes
= avr_num_arg_regs (mode
, type
);
1445 if (cum
->nregs
&& bytes
<= cum
->nregs
)
1446 return gen_rtx (REG
, mode
, cum
->regno
- bytes
);
1451 /* Update the summarizer variable CUM to advance past an argument
1452 in the argument list. */
1455 function_arg_advance (cum
, mode
, type
, named
)
1456 CUMULATIVE_ARGS
*cum
; /* current arg information */
1457 enum machine_mode mode
; /* current arg mode */
1458 tree type
; /* type of the argument or 0 if lib support */
1459 int named ATTRIBUTE_UNUSED
; /* whether or not the argument was named */
1461 int bytes
= avr_num_arg_regs (mode
, type
);
1463 cum
->nregs
-= bytes
;
1464 cum
->regno
-= bytes
;
1466 if (cum
->nregs
<= 0)
1469 cum
->regno
= FIRST_CUM_REG
;
1473 /***********************************************************************
1474 Functions for outputting various mov's for a various modes
1475 ************************************************************************/
1477 output_movqi (insn
, operands
, l
)
1483 rtx dest
= operands
[0];
1484 rtx src
= operands
[1];
1492 if (register_operand (dest
, QImode
))
1494 if (register_operand (src
, QImode
)) /* mov r,r */
1496 if (test_hard_reg_class (STACK_REG
, dest
))
1497 return AS2 (out
,%0,%1);
1498 else if (test_hard_reg_class (STACK_REG
, src
))
1499 return AS2 (in
,%0,%1);
1501 return AS2 (mov
,%0,%1);
1503 else if (CONSTANT_P (src
))
1505 if (test_hard_reg_class (LD_REGS
, dest
)) /* ldi d,i */
1506 return AS2 (ldi
,%0,lo8(%1));
1508 if (GET_CODE (src
) == CONST_INT
)
1510 if (src
== const0_rtx
) /* mov r,L */
1511 return AS1 (clr
,%0);
1512 else if (src
== const1_rtx
)
1514 if (reg_was_0 (insn
, dest
))
1515 return AS1 (inc
,%0 ; reg_was_0
);
1518 return (AS1 (clr
,%0) CR_TAB
1521 else if (src
== constm1_rtx
)
1523 /* Immediate constants -1 to any register */
1524 if (reg_was_0 (insn
, dest
))
1525 return AS1 (dec
,%0 ; reg_was_0
);
1528 return (AS1 (clr
,%0) CR_TAB
1533 int bit_nr
= exact_log2 (INTVAL (src
));
1537 if (reg_was_0 (insn
, dest
))
1541 output_asm_insn ("set ; reg_was_0", operands
);
1547 output_asm_insn ((AS1 (clr
,%0) CR_TAB
1551 avr_output_bld (operands
, bit_nr
);
1558 /* Last resort, larger than loading from memory. */
1560 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1561 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
1562 AS2 (mov
,%0,r31
) CR_TAB
1563 AS2 (mov
,r31
,__tmp_reg__
));
1565 else if (GET_CODE (src
) == MEM
)
1566 return out_movqi_r_mr (insn
, operands
, real_l
); /* mov r,m */
1568 else if (GET_CODE (dest
) == MEM
)
1570 const char *template;
1572 if (src
== const0_rtx
)
1573 operands
[1] = zero_reg_rtx
;
1575 template = out_movqi_mr_r (insn
, operands
, real_l
);
1578 output_asm_insn (template, operands
);
1587 output_movhi (insn
, operands
, l
)
1593 rtx dest
= operands
[0];
1594 rtx src
= operands
[1];
1600 if (register_operand (dest
, HImode
))
1602 if (register_operand (src
, HImode
)) /* mov r,r */
1604 if (test_hard_reg_class (STACK_REG
, dest
))
1606 if (TARGET_TINY_STACK
)
1609 return AS2 (out
,__SP_L__
,%A1
);
1611 else if (TARGET_NO_INTERRUPTS
)
1614 return (AS2 (out
,__SP_H__
,%B1
) CR_TAB
1615 AS2 (out
,__SP_L__
,%A1
));
1619 return (AS2 (in
,__tmp_reg__
,__SREG__
) CR_TAB
1621 AS2 (out
,__SP_H__
,%B1
) CR_TAB
1622 AS2 (out
,__SREG__
,__tmp_reg__
) CR_TAB
1623 AS2 (out
,__SP_L__
,%A1
));
1625 else if (test_hard_reg_class (STACK_REG
, src
))
1628 return (AS2 (in
,%A0
,__SP_L__
) CR_TAB
1629 AS2 (in
,%B0
,__SP_H__
));
1635 return (AS2 (movw
,%0,%1));
1638 if (true_regnum (dest
) > true_regnum (src
))
1641 return (AS2 (mov
,%B0
,%B1
) CR_TAB
1647 return (AS2 (mov
,%A0
,%A1
) CR_TAB
1651 else if (CONSTANT_P (src
))
1653 if (test_hard_reg_class (LD_REGS
, dest
)) /* ldi d,i */
1655 if (byte_immediate_operand (src
, HImode
)
1656 && reg_was_0 (insn
, dest
))
1659 return (AS2 (ldi
,%A0
,lo8(%1) ; reg_was_0
));
1663 return (AS2 (ldi
,%A0
,lo8(%1)) CR_TAB
1664 AS2 (ldi
,%B0
,hi8(%1)));
1667 if (GET_CODE (src
) == CONST_INT
)
1669 if (src
== const0_rtx
) /* mov r,L */
1672 return (AS1 (clr
,%A0
) CR_TAB
1675 else if (src
== const1_rtx
)
1677 if (reg_was_0 (insn
, dest
))
1680 return AS1 (inc
,%0 ; reg_was_0
);
1684 return (AS1 (clr
,%A0
) CR_TAB
1685 AS1 (clr
,%B0
) CR_TAB
1688 else if (src
== constm1_rtx
)
1690 /* Immediate constants -1 to any register */
1691 if (reg_was_0 (insn
, dest
))
1694 return (AS1 (dec
,%A0
; reg_was_0
) CR_TAB
1699 return (AS1 (clr
,%0) CR_TAB
1700 AS1 (dec
,%A0
) CR_TAB
1705 int bit_nr
= exact_log2 (INTVAL (src
));
1709 if (reg_was_0 (insn
, dest
))
1713 output_asm_insn ("set ; reg_was_0", operands
);
1719 output_asm_insn ((AS1 (clr
,%A0
) CR_TAB
1720 AS1 (clr
,%B0
) CR_TAB
1724 avr_output_bld (operands
, bit_nr
);
1730 if ((INTVAL (src
) & 0xff) == 0)
1733 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1734 AS1 (clr
,%A0
) CR_TAB
1735 AS2 (ldi
,r31
,hi8(%1)) CR_TAB
1736 AS2 (mov
,%B0
,r31
) CR_TAB
1737 AS2 (mov
,r31
,__tmp_reg__
));
1739 else if ((INTVAL (src
) & 0xff00) == 0)
1742 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1743 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
1744 AS2 (mov
,%A0
,r31
) CR_TAB
1745 AS1 (clr
,%B0
) CR_TAB
1746 AS2 (mov
,r31
,__tmp_reg__
));
1750 /* Last resort, equal to loading from memory. */
1752 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
1753 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
1754 AS2 (mov
,%A0
,r31
) CR_TAB
1755 AS2 (ldi
,r31
,hi8(%1)) CR_TAB
1756 AS2 (mov
,%B0
,r31
) CR_TAB
1757 AS2 (mov
,r31
,__tmp_reg__
));
1759 else if (GET_CODE (src
) == MEM
)
1760 return out_movhi_r_mr (insn
, operands
, real_l
); /* mov r,m */
1762 else if (GET_CODE (dest
) == MEM
)
1764 const char *template;
1766 if (src
== const0_rtx
)
1767 operands
[1] = zero_reg_rtx
;
1769 template = out_movhi_mr_r (insn
, operands
, real_l
);
1772 output_asm_insn (template, operands
);
1777 fatal_insn ("invalid insn:", insn
);
1782 out_movqi_r_mr (insn
, op
, l
)
1785 int *l
; /* instruction length */
1789 rtx x
= XEXP (src
, 0);
1795 if (CONSTANT_ADDRESS_P (x
))
1797 if (io_address_p (x
, 1))
1800 return AS2 (in
,%0,%1-0x20);
1803 return AS2 (lds
,%0,%1);
1805 /* memory access by reg+disp */
1806 else if (GET_CODE (x
) == PLUS
1807 && REG_P (XEXP (x
,0))
1808 && GET_CODE (XEXP (x
,1)) == CONST_INT
)
1810 if ((INTVAL (XEXP (x
,1)) - GET_MODE_SIZE (GET_MODE (src
))) >= 63)
1812 int disp
= INTVAL (XEXP (x
,1));
1813 if (REGNO (XEXP (x
,0)) != REG_Y
)
1814 fatal_insn ("incorrect insn:",insn
);
1816 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
1817 return *l
= 3, (AS2 (adiw
,r28
,%o1
-63) CR_TAB
1818 AS2 (ldd
,%0,Y
+63) CR_TAB
1819 AS2 (sbiw
,r28
,%o1
-63));
1821 return *l
= 5, (AS2 (subi
,r28
,lo8(-%o1
)) CR_TAB
1822 AS2 (sbci
,r29
,hi8(-%o1
)) CR_TAB
1823 AS2 (ld
,%0,Y
) CR_TAB
1824 AS2 (subi
,r28
,lo8(%o1
)) CR_TAB
1825 AS2 (sbci
,r29
,hi8(%o1
)));
1827 else if (REGNO (XEXP (x
,0)) == REG_X
)
1829 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
1830 it but I have this situation with extremal optimizing options. */
1831 if (reg_overlap_mentioned_p (dest
, XEXP (x
,0))
1832 || reg_unused_after (insn
, XEXP (x
,0)))
1833 return *l
= 2, (AS2 (adiw
,r26
,%o1
) CR_TAB
1836 return *l
= 3, (AS2 (adiw
,r26
,%o1
) CR_TAB
1837 AS2 (ld
,%0,X
) CR_TAB
1838 AS2 (sbiw
,r26
,%o1
));
1841 return AS2 (ldd
,%0,%1);
1844 return AS2 (ld
,%0,%1);
1848 out_movhi_r_mr (insn
, op
, l
)
1851 int *l
; /* instruction length */
1855 rtx base
= XEXP (src
, 0);
1856 int reg_dest
= true_regnum (dest
);
1857 int reg_base
= true_regnum (base
);
1865 if (reg_dest
== reg_base
) /* R = (R) */
1868 return (AS2 (ld
,__tmp_reg__
,%1+) CR_TAB
1869 AS2 (ld
,%B0
,%1) CR_TAB
1870 AS2 (mov
,%A0
,__tmp_reg__
));
1872 else if (reg_base
== REG_X
) /* (R26) */
1874 if (reg_unused_after (insn
, base
))
1877 return (AS2 (ld
,%A0
,X
+) CR_TAB
1881 return (AS2 (ld
,%A0
,X
+) CR_TAB
1882 AS2 (ld
,%B0
,X
) CR_TAB
1888 return (AS2 (ld
,%A0
,%1) CR_TAB
1889 AS2 (ldd
,%B0
,%1+1));
1892 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
1894 int disp
= INTVAL (XEXP (base
, 1));
1895 int reg_base
= true_regnum (XEXP (base
, 0));
1897 if (disp
> MAX_LD_OFFSET (GET_MODE (src
)))
1899 if (REGNO (XEXP (base
, 0)) != REG_Y
)
1900 fatal_insn ("incorrect insn:",insn
);
1902 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
1903 return *l
= 4, (AS2 (adiw
,r28
,%o1
-62) CR_TAB
1904 AS2 (ldd
,%A0
,Y
+62) CR_TAB
1905 AS2 (ldd
,%B0
,Y
+63) CR_TAB
1906 AS2 (sbiw
,r28
,%o1
-62));
1908 return *l
= 6, (AS2 (subi
,r28
,lo8(-%o1
)) CR_TAB
1909 AS2 (sbci
,r29
,hi8(-%o1
)) CR_TAB
1910 AS2 (ld
,%A0
,Y
) CR_TAB
1911 AS2 (ldd
,%B0
,Y
+1) CR_TAB
1912 AS2 (subi
,r28
,lo8(%o1
)) CR_TAB
1913 AS2 (sbci
,r29
,hi8(%o1
)));
1915 if (reg_base
== REG_X
)
1917 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
1918 it but I have this situation with extremal
1919 optimization options. */
1922 if (reg_base
== reg_dest
)
1923 return (AS2 (adiw
,r26
,%o1
) CR_TAB
1924 AS2 (ld
,__tmp_reg__
,X
+) CR_TAB
1925 AS2 (ld
,%B0
,X
) CR_TAB
1926 AS2 (mov
,%A0
,__tmp_reg__
));
1928 return (AS2 (adiw
,r26
,%o1
) CR_TAB
1929 AS2 (ld
,%A0
,X
+) CR_TAB
1930 AS2 (ld
,%B0
,X
) CR_TAB
1931 AS2 (sbiw
,r26
,%o1
+1));
1934 if (reg_base
== reg_dest
)
1937 return (AS2 (ldd
,__tmp_reg__
,%A1
) CR_TAB
1938 AS2 (ldd
,%B0
,%B1
) CR_TAB
1939 AS2 (mov
,%A0
,__tmp_reg__
));
1943 return (AS2 (ldd
,%A0
,%A1
) CR_TAB
1946 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
1948 if (reg_overlap_mentioned_p (dest
, XEXP (base
, 0)))
1949 fatal_insn ("incorrect insn:", insn
);
1952 return (AS2 (ld
,%B0
,%1) CR_TAB
1955 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
1957 if (reg_overlap_mentioned_p (dest
, XEXP (base
, 0)))
1958 fatal_insn ("incorrect insn:", insn
);
1961 return (AS2 (ld
,%A0
,%1) CR_TAB
1964 else if (CONSTANT_ADDRESS_P (base
))
1966 if (io_address_p (base
, 2))
1969 return (AS2 (in
,%A0
,%A1
-0x20) CR_TAB
1970 AS2 (in
,%B0
,%B1
-0x20));
1973 return (AS2 (lds
,%A0
,%A1
) CR_TAB
1977 fatal_insn ("unknown move insn:",insn
);
1982 out_movsi_r_mr (insn
, op
, l
)
1985 int *l
; /* instruction length */
1989 rtx base
= XEXP (src
, 0);
1990 int reg_dest
= true_regnum (dest
);
1991 int reg_base
= true_regnum (base
);
1999 if (reg_base
== REG_X
) /* (R26) */
2001 if (reg_dest
== REG_X
)
2002 /* "ld r26,-X" is undefined */
2003 return *l
=7, (AS2 (adiw
,r26
,3) CR_TAB
2004 AS2 (ld
,r29
,X
) CR_TAB
2005 AS2 (ld
,r28
,-X
) CR_TAB
2006 AS2 (ld
,__tmp_reg__
,-X
) CR_TAB
2007 AS2 (sbiw
,r26
,1) CR_TAB
2008 AS2 (ld
,r26
,X
) CR_TAB
2009 AS2 (mov
,r27
,__tmp_reg__
));
2010 else if (reg_dest
== REG_X
- 2)
2011 return *l
=5, (AS2 (ld
,%A0
,X
+) CR_TAB
2012 AS2 (ld
,%B0
,X
+) CR_TAB
2013 AS2 (ld
,__tmp_reg__
,X
+) CR_TAB
2014 AS2 (ld
,%D0
,X
) CR_TAB
2015 AS2 (mov
,%C0
,__tmp_reg__
));
2016 else if (reg_unused_after (insn
, base
))
2017 return *l
=4, (AS2 (ld
,%A0
,X
+) CR_TAB
2018 AS2 (ld
,%B0
,X
+) CR_TAB
2019 AS2 (ld
,%C0
,X
+) CR_TAB
2022 return *l
=5, (AS2 (ld
,%A0
,X
+) CR_TAB
2023 AS2 (ld
,%B0
,X
+) CR_TAB
2024 AS2 (ld
,%C0
,X
+) CR_TAB
2025 AS2 (ld
,%D0
,X
) CR_TAB
2030 if (reg_dest
== reg_base
)
2031 return *l
=5, (AS2 (ldd
,%D0
,%1+3) CR_TAB
2032 AS2 (ldd
,%C0
,%1+2) CR_TAB
2033 AS2 (ldd
,__tmp_reg__
,%1+1) CR_TAB
2034 AS2 (ld
,%A0
,%1) CR_TAB
2035 AS2 (mov
,%B0
,__tmp_reg__
));
2036 else if (reg_base
== reg_dest
+ 2)
2037 return *l
=5, (AS2 (ld
,%A0
,%1) CR_TAB
2038 AS2 (ldd
,%B0
,%1+1) CR_TAB
2039 AS2 (ldd
,__tmp_reg__
,%1+2) CR_TAB
2040 AS2 (ldd
,%D0
,%1+3) CR_TAB
2041 AS2 (mov
,%C0
,__tmp_reg__
));
2043 return *l
=4, (AS2 (ld
,%A0
,%1) CR_TAB
2044 AS2 (ldd
,%B0
,%1+1) CR_TAB
2045 AS2 (ldd
,%C0
,%1+2) CR_TAB
2046 AS2 (ldd
,%D0
,%1+3));
2049 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
2051 int disp
= INTVAL (XEXP (base
, 1));
2053 if (disp
> MAX_LD_OFFSET (GET_MODE (src
)))
2055 if (REGNO (XEXP (base
, 0)) != REG_Y
)
2056 fatal_insn ("incorrect insn:",insn
);
2058 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
2059 return *l
= 6, (AS2 (adiw
,r28
,%o1
-60) CR_TAB
2060 AS2 (ldd
,%A0
,Y
+60) CR_TAB
2061 AS2 (ldd
,%B0
,Y
+61) CR_TAB
2062 AS2 (ldd
,%C0
,Y
+62) CR_TAB
2063 AS2 (ldd
,%D0
,Y
+63) CR_TAB
2064 AS2 (sbiw
,r28
,%o1
-60));
2066 return *l
= 8, (AS2 (subi
,r28
,lo8(-%o1
)) CR_TAB
2067 AS2 (sbci
,r29
,hi8(-%o1
)) CR_TAB
2068 AS2 (ld
,%A0
,Y
) CR_TAB
2069 AS2 (ldd
,%B0
,Y
+1) CR_TAB
2070 AS2 (ldd
,%C0
,Y
+2) CR_TAB
2071 AS2 (ldd
,%D0
,Y
+3) CR_TAB
2072 AS2 (subi
,r28
,lo8(%o1
)) CR_TAB
2073 AS2 (sbci
,r29
,hi8(%o1
)));
2076 reg_base
= true_regnum (XEXP (base
, 0));
2077 if (reg_base
== REG_X
)
2080 if (reg_dest
== REG_X
)
2083 /* "ld r26,-X" is undefined */
2084 return (AS2 (adiw
,r26
,%o1
+3) CR_TAB
2085 AS2 (ld
,r29
,X
) CR_TAB
2086 AS2 (ld
,r28
,-X
) CR_TAB
2087 AS2 (ld
,__tmp_reg__
,-X
) CR_TAB
2088 AS2 (sbiw
,r26
,1) CR_TAB
2089 AS2 (ld
,r26
,X
) CR_TAB
2090 AS2 (mov
,r27
,__tmp_reg__
));
2093 if (reg_dest
== REG_X
- 2)
2094 return (AS2 (adiw
,r26
,%o1
) CR_TAB
2095 AS2 (ld
,r24
,X
+) CR_TAB
2096 AS2 (ld
,r25
,X
+) CR_TAB
2097 AS2 (ld
,__tmp_reg__
,X
+) CR_TAB
2098 AS2 (ld
,r27
,X
) CR_TAB
2099 AS2 (mov
,r26
,__tmp_reg__
));
2101 return (AS2 (adiw
,r26
,%o1
) CR_TAB
2102 AS2 (ld
,%A0
,X
+) CR_TAB
2103 AS2 (ld
,%B0
,X
+) CR_TAB
2104 AS2 (ld
,%C0
,X
+) CR_TAB
2105 AS2 (ld
,%D0
,X
) CR_TAB
2106 AS2 (sbiw
,r26
,%o1
+3));
2108 if (reg_dest
== reg_base
)
2109 return *l
=5, (AS2 (ldd
,%D0
,%D1
) CR_TAB
2110 AS2 (ldd
,%C0
,%C1
) CR_TAB
2111 AS2 (ldd
,__tmp_reg__
,%B1
) CR_TAB
2112 AS2 (ldd
,%A0
,%A1
) CR_TAB
2113 AS2 (mov
,%B0
,__tmp_reg__
));
2114 else if (reg_dest
== reg_base
- 2)
2115 return *l
=5, (AS2 (ldd
,%A0
,%A1
) CR_TAB
2116 AS2 (ldd
,%B0
,%B1
) CR_TAB
2117 AS2 (ldd
,__tmp_reg__
,%C1
) CR_TAB
2118 AS2 (ldd
,%D0
,%D1
) CR_TAB
2119 AS2 (mov
,%C0
,__tmp_reg__
));
2120 return *l
=4, (AS2 (ldd
,%A0
,%A1
) CR_TAB
2121 AS2 (ldd
,%B0
,%B1
) CR_TAB
2122 AS2 (ldd
,%C0
,%C1
) CR_TAB
2125 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2126 return *l
=4, (AS2 (ld
,%D0
,%1) CR_TAB
2127 AS2 (ld
,%C0
,%1) CR_TAB
2128 AS2 (ld
,%B0
,%1) CR_TAB
2130 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2131 return *l
=4, (AS2 (ld
,%A0
,%1) CR_TAB
2132 AS2 (ld
,%B0
,%1) CR_TAB
2133 AS2 (ld
,%C0
,%1) CR_TAB
2135 else if (CONSTANT_ADDRESS_P (base
))
2136 return *l
=8, (AS2 (lds
,%A0
,%A1
) CR_TAB
2137 AS2 (lds
,%B0
,%B1
) CR_TAB
2138 AS2 (lds
,%C0
,%C1
) CR_TAB
2141 fatal_insn ("unknown move insn:",insn
);
2146 out_movsi_mr_r (insn
, op
, l
)
2153 rtx base
= XEXP (dest
, 0);
2154 int reg_base
= true_regnum (base
);
2155 int reg_src
= true_regnum (src
);
2161 if (CONSTANT_ADDRESS_P (base
))
2162 return *l
=8,(AS2 (sts
,%A0
,%A1
) CR_TAB
2163 AS2 (sts
,%B0
,%B1
) CR_TAB
2164 AS2 (sts
,%C0
,%C1
) CR_TAB
2166 if (reg_base
> 0) /* (r) */
2168 if (reg_base
== REG_X
) /* (R26) */
2170 if (reg_src
== REG_X
)
2172 /* "st X+,r26" is undefined */
2173 if (reg_unused_after (insn
, base
))
2174 return *l
=6, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2175 AS2 (st
,X
,r26
) CR_TAB
2176 AS2 (adiw
,r26
,1) CR_TAB
2177 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2178 AS2 (st
,X
+,r28
) CR_TAB
2181 return *l
=7, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2182 AS2 (st
,X
,r26
) CR_TAB
2183 AS2 (adiw
,r26
,1) CR_TAB
2184 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2185 AS2 (st
,X
+,r28
) CR_TAB
2186 AS2 (st
,X
,r29
) CR_TAB
2189 else if (reg_base
== reg_src
+ 2)
2191 if (reg_unused_after (insn
, base
))
2192 return *l
=7, (AS2 (mov
,__zero_reg__
,%C1
) CR_TAB
2193 AS2 (mov
,__tmp_reg__
,%D1
) CR_TAB
2194 AS2 (st
,%0+,%A1
) CR_TAB
2195 AS2 (st
,%0+,%B1
) CR_TAB
2196 AS2 (st
,%0+,__zero_reg__
) CR_TAB
2197 AS2 (st
,%0,__tmp_reg__
) CR_TAB
2198 AS1 (clr
,__zero_reg__
));
2200 return *l
=8, (AS2 (mov
,__zero_reg__
,%C1
) CR_TAB
2201 AS2 (mov
,__tmp_reg__
,%D1
) CR_TAB
2202 AS2 (st
,%0+,%A1
) CR_TAB
2203 AS2 (st
,%0+,%B1
) CR_TAB
2204 AS2 (st
,%0+,__zero_reg__
) CR_TAB
2205 AS2 (st
,%0,__tmp_reg__
) CR_TAB
2206 AS1 (clr
,__zero_reg__
) CR_TAB
2209 return *l
=5, (AS2 (st
,%0+,%A1
) CR_TAB
2210 AS2 (st
,%0+,%B1
) CR_TAB
2211 AS2 (st
,%0+,%C1
) CR_TAB
2212 AS2 (st
,%0,%D1
) CR_TAB
2216 return *l
=4, (AS2 (st
,%0,%A1
) CR_TAB
2217 AS2 (std
,%0+1,%B1
) CR_TAB
2218 AS2 (std
,%0+2,%C1
) CR_TAB
2219 AS2 (std
,%0+3,%D1
));
2221 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
2223 int disp
= INTVAL (XEXP (base
, 1));
2224 reg_base
= REGNO (XEXP (base
, 0));
2225 if (disp
> MAX_LD_OFFSET (GET_MODE (dest
)))
2227 if (reg_base
!= REG_Y
)
2228 fatal_insn ("incorrect insn:",insn
);
2230 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
2231 return *l
= 6, (AS2 (adiw
,r28
,%o0
-60) CR_TAB
2232 AS2 (std
,Y
+60,%A1
) CR_TAB
2233 AS2 (std
,Y
+61,%B1
) CR_TAB
2234 AS2 (std
,Y
+62,%C1
) CR_TAB
2235 AS2 (std
,Y
+63,%D1
) CR_TAB
2236 AS2 (sbiw
,r28
,%o0
-60));
2238 return *l
= 8, (AS2 (subi
,r28
,lo8(-%o0
)) CR_TAB
2239 AS2 (sbci
,r29
,hi8(-%o0
)) CR_TAB
2240 AS2 (st
,Y
,%A1
) CR_TAB
2241 AS2 (std
,Y
+1,%B1
) CR_TAB
2242 AS2 (std
,Y
+2,%C1
) CR_TAB
2243 AS2 (std
,Y
+3,%D1
) CR_TAB
2244 AS2 (subi
,r28
,lo8(%o0
)) CR_TAB
2245 AS2 (sbci
,r29
,hi8(%o0
)));
2247 if (reg_base
== REG_X
)
2250 if (reg_src
== REG_X
)
2253 return (AS2 (mov
,__tmp_reg__
,r26
) CR_TAB
2254 AS2 (mov
,__zero_reg__
,r27
) CR_TAB
2255 AS2 (adiw
,r26
,%o0
) CR_TAB
2256 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2257 AS2 (st
,X
+,__zero_reg__
) CR_TAB
2258 AS2 (st
,X
+,r28
) CR_TAB
2259 AS2 (st
,X
,r29
) CR_TAB
2260 AS1 (clr
,__zero_reg__
) CR_TAB
2261 AS2 (sbiw
,r26
,%o0
+3));
2263 else if (reg_src
== REG_X
- 2)
2266 return (AS2 (mov
,__tmp_reg__
,r26
) CR_TAB
2267 AS2 (mov
,__zero_reg__
,r27
) CR_TAB
2268 AS2 (adiw
,r26
,%o0
) CR_TAB
2269 AS2 (st
,X
+,r24
) CR_TAB
2270 AS2 (st
,X
+,r25
) CR_TAB
2271 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2272 AS2 (st
,X
,__zero_reg__
) CR_TAB
2273 AS1 (clr
,__zero_reg__
) CR_TAB
2274 AS2 (sbiw
,r26
,%o0
+3));
2277 return (AS2 (adiw
,r26
,%o0
) CR_TAB
2278 AS2 (st
,X
+,%A1
) CR_TAB
2279 AS2 (st
,X
+,%B1
) CR_TAB
2280 AS2 (st
,X
+,%C1
) CR_TAB
2281 AS2 (st
,X
,%D1
) CR_TAB
2282 AS2 (sbiw
,r26
,%o0
+3));
2284 return *l
=4, (AS2 (std
,%A0
,%A1
) CR_TAB
2285 AS2 (std
,%B0
,%B1
) CR_TAB
2286 AS2 (std
,%C0
,%C1
) CR_TAB
2289 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2290 return *l
=4, (AS2 (st
,%0,%D1
) CR_TAB
2291 AS2 (st
,%0,%C1
) CR_TAB
2292 AS2 (st
,%0,%B1
) CR_TAB
2294 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2295 return *l
=4, (AS2 (st
,%0,%A1
) CR_TAB
2296 AS2 (st
,%0,%B1
) CR_TAB
2297 AS2 (st
,%0,%C1
) CR_TAB
2299 fatal_insn ("unknown move insn:",insn
);
2304 output_movsisf(insn
, operands
, l
)
2310 rtx dest
= operands
[0];
2311 rtx src
= operands
[1];
2317 if (register_operand (dest
, VOIDmode
))
2319 if (register_operand (src
, VOIDmode
)) /* mov r,r */
2321 if (true_regnum (dest
) > true_regnum (src
))
2326 return (AS2 (movw
,%C0
,%C1
) CR_TAB
2327 AS2 (movw
,%A0
,%A1
));
2330 return (AS2 (mov
,%D0
,%D1
) CR_TAB
2331 AS2 (mov
,%C0
,%C1
) CR_TAB
2332 AS2 (mov
,%B0
,%B1
) CR_TAB
2340 return (AS2 (movw
,%A0
,%A1
) CR_TAB
2341 AS2 (movw
,%C0
,%C1
));
2344 return (AS2 (mov
,%A0
,%A1
) CR_TAB
2345 AS2 (mov
,%B0
,%B1
) CR_TAB
2346 AS2 (mov
,%C0
,%C1
) CR_TAB
2350 else if (CONSTANT_P (src
))
2352 if (test_hard_reg_class (LD_REGS
, dest
)) /* ldi d,i */
2354 if (byte_immediate_operand (src
, SImode
)
2355 && reg_was_0 (insn
, dest
))
2358 return (AS2 (ldi
,%A0
,lo8(%1) ; reg_was_0
));
2362 return (AS2 (ldi
,%A0
,lo8(%1)) CR_TAB
2363 AS2 (ldi
,%B0
,hi8(%1)) CR_TAB
2364 AS2 (ldi
,%C0
,hlo8(%1)) CR_TAB
2365 AS2 (ldi
,%D0
,hhi8(%1)));
2368 if (GET_CODE (src
) == CONST_INT
)
2370 const char *const clr_op0
=
2371 AVR_ENHANCED
? (AS1 (clr
,%A0
) CR_TAB
2372 AS1 (clr
,%B0
) CR_TAB
2374 : (AS1 (clr
,%A0
) CR_TAB
2375 AS1 (clr
,%B0
) CR_TAB
2376 AS1 (clr
,%C0
) CR_TAB
2379 if (src
== const0_rtx
) /* mov r,L */
2381 *l
= AVR_ENHANCED
? 3 : 4;
2384 else if (src
== const1_rtx
)
2386 if (reg_was_0 (insn
, dest
))
2389 return AS1 (inc
,%A0
; reg_was_0
);
2392 output_asm_insn (clr_op0
, operands
);
2393 *l
= AVR_ENHANCED
? 4 : 5;
2394 return AS1 (inc
,%A0
);
2396 else if (src
== constm1_rtx
)
2398 /* Immediate constants -1 to any register */
2399 if (reg_was_0 (insn
, dest
))
2404 return (AS1 (dec
,%A0
) CR_TAB
2405 AS1 (dec
,%B0
) CR_TAB
2406 AS2 (movw
,%C0
,%A0
));
2409 return (AS1 (dec
,%D0
; reg_was_0
) CR_TAB
2410 AS1 (dec
,%C0
) CR_TAB
2411 AS1 (dec
,%B0
) CR_TAB
2417 return (AS1 (clr
,%A0
) CR_TAB
2418 AS1 (dec
,%A0
) CR_TAB
2419 AS2 (mov
,%B0
,%A0
) CR_TAB
2420 AS2 (movw
,%C0
,%A0
));
2423 return (AS1 (clr
,%A0
) CR_TAB
2424 AS1 (dec
,%A0
) CR_TAB
2425 AS2 (mov
,%B0
,%A0
) CR_TAB
2426 AS2 (mov
,%C0
,%A0
) CR_TAB
2431 int bit_nr
= exact_log2 (INTVAL (src
));
2435 if (reg_was_0 (insn
, dest
))
2439 output_asm_insn ("set ; reg_was_0", operands
);
2443 *l
= AVR_ENHANCED
? 5 : 6;
2446 output_asm_insn (clr_op0
, operands
);
2447 output_asm_insn ("set", operands
);
2451 avr_output_bld (operands
, bit_nr
);
2458 /* Last resort, better than loading from memory. */
2460 return (AS2 (mov
,__tmp_reg__
,r31
) CR_TAB
2461 AS2 (ldi
,r31
,lo8(%1)) CR_TAB
2462 AS2 (mov
,%A0
,r31
) CR_TAB
2463 AS2 (ldi
,r31
,hi8(%1)) CR_TAB
2464 AS2 (mov
,%B0
,r31
) CR_TAB
2465 AS2 (ldi
,r31
,hlo8(%1)) CR_TAB
2466 AS2 (mov
,%C0
,r31
) CR_TAB
2467 AS2 (ldi
,r31
,hhi8(%1)) CR_TAB
2468 AS2 (mov
,%D0
,r31
) CR_TAB
2469 AS2 (mov
,r31
,__tmp_reg__
));
2471 else if (GET_CODE (src
) == MEM
)
2472 return out_movsi_r_mr (insn
, operands
, real_l
); /* mov r,m */
2474 else if (GET_CODE (dest
) == MEM
)
2476 const char *template;
2478 if (src
== const0_rtx
)
2479 operands
[1] = zero_reg_rtx
;
2481 template = out_movsi_mr_r (insn
, operands
, real_l
);
2484 output_asm_insn (template, operands
);
2489 fatal_insn ("invalid insn:", insn
);
2494 out_movqi_mr_r (insn
, op
, l
)
2497 int *l
; /* instruction length */
2501 rtx x
= XEXP (dest
, 0);
2507 if (CONSTANT_ADDRESS_P (x
))
2509 if (io_address_p (x
, 1))
2512 return AS2 (out
,%0-0x20,%1);
2515 return AS2 (sts
,%0,%1);
2517 /* memory access by reg+disp */
2518 else if (GET_CODE (x
) == PLUS
2519 && REG_P (XEXP (x
,0))
2520 && GET_CODE (XEXP (x
,1)) == CONST_INT
)
2522 if ((INTVAL (XEXP (x
,1)) - GET_MODE_SIZE (GET_MODE (dest
))) >= 63)
2524 int disp
= INTVAL (XEXP (x
,1));
2525 if (REGNO (XEXP (x
,0)) != REG_Y
)
2526 fatal_insn ("incorrect insn:",insn
);
2528 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
2529 return *l
= 3, (AS2 (adiw
,r28
,%o0
-63) CR_TAB
2530 AS2 (std
,Y
+63,%1) CR_TAB
2531 AS2 (sbiw
,r28
,%o0
-63));
2533 return *l
= 5, (AS2 (subi
,r28
,lo8(-%o0
)) CR_TAB
2534 AS2 (sbci
,r29
,hi8(-%o0
)) CR_TAB
2535 AS2 (st
,Y
,%1) CR_TAB
2536 AS2 (subi
,r28
,lo8(%o0
)) CR_TAB
2537 AS2 (sbci
,r29
,hi8(%o0
)));
2539 else if (REGNO (XEXP (x
,0)) == REG_X
)
2541 if (reg_overlap_mentioned_p (src
, XEXP (x
, 0)))
2543 if (reg_unused_after (insn
, XEXP (x
,0)))
2544 return *l
= 3, (AS2 (mov
,__tmp_reg__
,%1) CR_TAB
2545 AS2 (adiw
,r26
,%o0
) CR_TAB
2546 AS2 (st
,X
,__tmp_reg__
));
2548 return *l
= 4, (AS2 (mov
,__tmp_reg__
,%1) CR_TAB
2549 AS2 (adiw
,r26
,%o0
) CR_TAB
2550 AS2 (st
,X
,__tmp_reg__
) CR_TAB
2551 AS2 (sbiw
,r26
,%o0
));
2555 if (reg_unused_after (insn
, XEXP (x
,0)))
2556 return *l
= 2, (AS2 (adiw
,r26
,%o0
) CR_TAB
2559 return *l
= 3, (AS2 (adiw
,r26
,%o0
) CR_TAB
2560 AS2 (st
,X
,%1) CR_TAB
2561 AS2 (sbiw
,r26
,%o0
));
2565 return AS2 (std
,%0,%1);
2568 return AS2 (st
,%0,%1);
2572 out_movhi_mr_r (insn
, op
, l
)
2579 rtx base
= XEXP (dest
, 0);
2580 int reg_base
= true_regnum (base
);
2581 int reg_src
= true_regnum (src
);
2585 if (CONSTANT_ADDRESS_P (base
))
2587 if (io_address_p (base
, 2))
2590 return (AS2 (out
,%B0
-0x20,%B1
) CR_TAB
2591 AS2 (out
,%A0
-0x20,%A1
));
2593 return *l
= 4, (AS2 (sts
,%B0
,%B1
) CR_TAB
2598 if (reg_base
== REG_X
)
2600 if (reg_src
== REG_X
)
2602 /* "st X+,r26" is undefined */
2603 if (reg_unused_after (insn
, src
))
2604 return *l
=4, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2605 AS2 (st
,X
,r26
) CR_TAB
2606 AS2 (adiw
,r26
,1) CR_TAB
2607 AS2 (st
,X
,__tmp_reg__
));
2609 return *l
=5, (AS2 (mov
,__tmp_reg__
,r27
) CR_TAB
2610 AS2 (st
,X
,r26
) CR_TAB
2611 AS2 (adiw
,r26
,1) CR_TAB
2612 AS2 (st
,X
,__tmp_reg__
) CR_TAB
2617 if (reg_unused_after (insn
, base
))
2618 return *l
=2, (AS2 (st
,X
+,%A1
) CR_TAB
2621 return *l
=3, (AS2 (st
,X
+,%A1
) CR_TAB
2622 AS2 (st
,X
,%B1
) CR_TAB
2627 return *l
=2, (AS2 (st
,%0,%A1
) CR_TAB
2628 AS2 (std
,%0+1,%B1
));
2630 else if (GET_CODE (base
) == PLUS
)
2632 int disp
= INTVAL (XEXP (base
, 1));
2633 reg_base
= REGNO (XEXP (base
, 0));
2634 if (disp
> MAX_LD_OFFSET (GET_MODE (dest
)))
2636 if (reg_base
!= REG_Y
)
2637 fatal_insn ("incorrect insn:",insn
);
2639 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
2640 return *l
= 4, (AS2 (adiw
,r28
,%o0
-62) CR_TAB
2641 AS2 (std
,Y
+62,%A1
) CR_TAB
2642 AS2 (std
,Y
+63,%B1
) CR_TAB
2643 AS2 (sbiw
,r28
,%o0
-62));
2645 return *l
= 6, (AS2 (subi
,r28
,lo8(-%o0
)) CR_TAB
2646 AS2 (sbci
,r29
,hi8(-%o0
)) CR_TAB
2647 AS2 (st
,Y
,%A1
) CR_TAB
2648 AS2 (std
,Y
+1,%B1
) CR_TAB
2649 AS2 (subi
,r28
,lo8(%o0
)) CR_TAB
2650 AS2 (sbci
,r29
,hi8(%o0
)));
2652 if (reg_base
== REG_X
)
2655 if (reg_src
== REG_X
)
2658 return (AS2 (mov
,__tmp_reg__
,r26
) CR_TAB
2659 AS2 (mov
,__zero_reg__
,r27
) CR_TAB
2660 AS2 (adiw
,r26
,%o0
) CR_TAB
2661 AS2 (st
,X
+,__tmp_reg__
) CR_TAB
2662 AS2 (st
,X
,__zero_reg__
) CR_TAB
2663 AS1 (clr
,__zero_reg__
) CR_TAB
2664 AS2 (sbiw
,r26
,%o0
+1));
2667 return (AS2 (adiw
,r26
,%o0
) CR_TAB
2668 AS2 (st
,X
+,%A1
) CR_TAB
2669 AS2 (st
,X
,%B1
) CR_TAB
2670 AS2 (sbiw
,r26
,%o0
+1));
2672 return *l
=2, (AS2 (std
,%A0
,%A1
) CR_TAB
2675 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
2676 return *l
=2, (AS2 (st
,%0,%B1
) CR_TAB
2678 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
2679 return *l
=2, (AS2 (st
,%0,%A1
) CR_TAB
2681 fatal_insn ("unknown move insn:",insn
);
2685 /* Return 1 if frame pointer for current function required */
2688 frame_pointer_required_p ()
2690 return (current_function_calls_alloca
2691 || current_function_args_info
.nregs
== 0
2692 || current_function_varargs
2693 || get_frame_size () > 0);
2696 /* Returns the condition of compare insn INSN, or UNKNOWN. */
2699 compare_condition (insn
)
2702 rtx next
= next_real_insn (insn
);
2703 RTX_CODE cond
= UNKNOWN
;
2704 if (next
&& GET_CODE (next
) == JUMP_INSN
)
2706 rtx pat
= PATTERN (next
);
2707 rtx src
= SET_SRC (pat
);
2708 rtx t
= XEXP (src
, 0);
2709 cond
= GET_CODE (t
);
2714 /* Returns nonzero if INSN is a tst insn that only tests the sign. */
2717 compare_sign_p (insn
)
2720 RTX_CODE cond
= compare_condition (insn
);
2721 return (cond
== GE
|| cond
== LT
);
2724 /* Returns nonzero if the next insn is a JUMP_INSN with a condition
2725 that needs to be swapped (GT, GTU, LE, LEU). */
2728 compare_diff_p (insn
)
2731 RTX_CODE cond
= compare_condition (insn
);
2732 return (cond
== GT
|| cond
== GTU
|| cond
== LE
|| cond
== LEU
) ? cond
: 0;
2735 /* Returns nonzero if INSN is a compare insn with the EQ or NE condition. */
2741 RTX_CODE cond
= compare_condition (insn
);
2742 return (cond
== EQ
|| cond
== NE
);
2746 /* Output test instruction for HImode */
2753 if (compare_sign_p (insn
))
2756 return AS1 (tst
,%B0
);
2758 if (reg_unused_after (insn
, SET_SRC (PATTERN (insn
)))
2759 && compare_eq_p (insn
))
2761 /* faster than sbiw if we can clobber the operand */
2763 return AS2 (or,%A0
,%B0
);
2765 if (test_hard_reg_class (ADDW_REGS
, SET_SRC (PATTERN (insn
))))
2768 return AS2 (sbiw
,%0,0);
2771 return (AS2 (cp
,%A0
,__zero_reg__
) CR_TAB
2772 AS2 (cpc
,%B0
,__zero_reg__
));
2776 /* Output test instruction for SImode */
2783 if (compare_sign_p (insn
))
2786 return AS1 (tst
,%D0
);
2788 if (test_hard_reg_class (ADDW_REGS
, SET_SRC (PATTERN (insn
))))
2791 return (AS2 (sbiw
,%A0
,0) CR_TAB
2792 AS2 (cpc
,%C0
,__zero_reg__
) CR_TAB
2793 AS2 (cpc
,%D0
,__zero_reg__
));
2796 return (AS2 (cp
,%A0
,__zero_reg__
) CR_TAB
2797 AS2 (cpc
,%B0
,__zero_reg__
) CR_TAB
2798 AS2 (cpc
,%C0
,__zero_reg__
) CR_TAB
2799 AS2 (cpc
,%D0
,__zero_reg__
));
2803 /* Generate asm equivalent for various shifts.
2804 Shift count is a CONST_INT, MEM or REG.
2805 This only handles cases that are not already
2806 carefully hand-optimized in ?sh??i3_out. */
2809 out_shift_with_cnt (template, insn
, operands
, len
, t_len
)
2810 const char *template;
2814 int t_len
; /* Length of template. */
2818 int second_label
= 1;
2819 int saved_in_tmp
= 0;
2820 int use_zero_reg
= 0;
2822 op
[0] = operands
[0];
2823 op
[1] = operands
[1];
2824 op
[2] = operands
[2];
2825 op
[3] = operands
[3];
2831 if (GET_CODE (operands
[2]) == CONST_INT
)
2833 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
2834 int count
= INTVAL (operands
[2]);
2835 int max_len
= 10; /* If larger than this, always use a loop. */
2837 if (count
< 8 && !scratch
)
2841 max_len
= t_len
+ (scratch
? 3 : (use_zero_reg
? 4 : 5));
2843 if (t_len
* count
<= max_len
)
2845 /* Output shifts inline with no loop - faster. */
2847 *len
= t_len
* count
;
2851 output_asm_insn (template, op
);
2860 strcat (str
, AS2 (ldi
,%3,%2));
2862 else if (use_zero_reg
)
2864 /* Hack to save one word: use __zero_reg__ as loop counter.
2865 Set one bit, then shift in a loop until it is 0 again. */
2867 op
[3] = zero_reg_rtx
;
2871 strcat (str
, ("set" CR_TAB
2872 AS2 (bld
,%3,%2-1)));
2876 /* No scratch register available, use one from LD_REGS (saved in
2877 __tmp_reg__) that doesn't overlap with registers to shift. */
2879 op
[3] = gen_rtx (REG
, QImode
,
2880 ((true_regnum (operands
[0]) - 1) & 15) + 16);
2881 op
[4] = tmp_reg_rtx
;
2885 *len
= 3; /* Includes "mov %3,%4" after the loop. */
2887 strcat (str
, (AS2 (mov
,%4,%3) CR_TAB
2893 else if (GET_CODE (operands
[2]) == MEM
)
2897 op
[3] = op_mov
[0] = tmp_reg_rtx
;
2901 out_movqi_r_mr (insn
, op_mov
, len
);
2903 output_asm_insn (out_movqi_r_mr (insn
, op_mov
, NULL
), op_mov
);
2905 else if (register_operand (operands
[2], QImode
))
2907 if (reg_unused_after (insn
, operands
[2]))
2911 op
[3] = tmp_reg_rtx
;
2913 strcat (str
, (AS2 (mov
,%3,%2) CR_TAB
));
2917 fatal_insn ("bad shift insn:", insn
);
2924 strcat (str
, AS1 (rjmp
,2f
));
2928 *len
+= t_len
+ 2; /* template + dec + brXX */
2931 strcat (str
, "\n1:\t");
2932 strcat (str
, template);
2933 strcat (str
, second_label
? "\n2:\t" : "\n\t");
2934 strcat (str
, use_zero_reg
? AS1 (lsr
,%3) : AS1 (dec
,%3));
2935 strcat (str
, CR_TAB
);
2936 strcat (str
, second_label
? AS1 (brpl
,1b
) : AS1 (brne
,1b
));
2938 strcat (str
, (CR_TAB
AS2 (mov
,%3,%4)));
2939 output_asm_insn (str
, op
);
2944 /* 8bit shift left ((char)x << i) */
2947 ashlqi3_out (insn
, operands
, len
)
2950 int *len
; /* insn length (may be NULL) */
2952 if (GET_CODE (operands
[2]) == CONST_INT
)
2959 switch (INTVAL (operands
[2]))
2963 return AS1 (clr
,%0);
2967 return AS1 (lsl
,%0);
2971 return (AS1 (lsl
,%0) CR_TAB
2976 return (AS1 (lsl
,%0) CR_TAB
2981 if (test_hard_reg_class (LD_REGS
, operands
[0]))
2984 return (AS1 (swap
,%0) CR_TAB
2985 AS2 (andi
,%0,0xf0));
2988 return (AS1 (lsl
,%0) CR_TAB
2994 if (test_hard_reg_class (LD_REGS
, operands
[0]))
2997 return (AS1 (swap
,%0) CR_TAB
2999 AS2 (andi
,%0,0xe0));
3002 return (AS1 (lsl
,%0) CR_TAB
3009 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3012 return (AS1 (swap
,%0) CR_TAB
3015 AS2 (andi
,%0,0xc0));
3018 return (AS1 (lsl
,%0) CR_TAB
3027 return (AS1 (ror
,%0) CR_TAB
3032 else if (CONSTANT_P (operands
[2]))
3033 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
3035 out_shift_with_cnt (AS1 (lsl
,%0),
3036 insn
, operands
, len
, 1);
3041 /* 16bit shift left ((short)x << i) */
3044 ashlhi3_out (insn
, operands
, len
)
3049 if (GET_CODE (operands
[2]) == CONST_INT
)
3051 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
3052 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
3059 switch (INTVAL (operands
[2]))
3062 if (optimize_size
&& scratch
)
3067 return (AS1 (swap
,%A0
) CR_TAB
3068 AS1 (swap
,%B0
) CR_TAB
3069 AS2 (andi
,%B0
,0xf0) CR_TAB
3070 AS2 (eor
,%B0
,%A0
) CR_TAB
3071 AS2 (andi
,%A0
,0xf0) CR_TAB
3077 return (AS1 (swap
,%A0
) CR_TAB
3078 AS1 (swap
,%B0
) CR_TAB
3079 AS2 (ldi
,%3,0xf0) CR_TAB
3080 AS2 (and,%B0
,%3) CR_TAB
3081 AS2 (eor
,%B0
,%A0
) CR_TAB
3082 AS2 (and,%A0
,%3) CR_TAB
3085 break; /* optimize_size ? 6 : 8 */
3089 break; /* scratch ? 5 : 6 */
3093 return (AS1 (lsl
,%A0
) CR_TAB
3094 AS1 (rol
,%B0
) CR_TAB
3095 AS1 (swap
,%A0
) CR_TAB
3096 AS1 (swap
,%B0
) CR_TAB
3097 AS2 (andi
,%B0
,0xf0) CR_TAB
3098 AS2 (eor
,%B0
,%A0
) CR_TAB
3099 AS2 (andi
,%A0
,0xf0) CR_TAB
3105 return (AS1 (lsl
,%A0
) CR_TAB
3106 AS1 (rol
,%B0
) CR_TAB
3107 AS1 (swap
,%A0
) CR_TAB
3108 AS1 (swap
,%B0
) CR_TAB
3109 AS2 (ldi
,%3,0xf0) CR_TAB
3110 AS2 (and,%B0
,%3) CR_TAB
3111 AS2 (eor
,%B0
,%A0
) CR_TAB
3112 AS2 (and,%A0
,%3) CR_TAB
3119 break; /* scratch ? 5 : 6 */
3121 return (AS1 (clr
,__tmp_reg__
) CR_TAB
3122 AS1 (lsr
,%B0
) CR_TAB
3123 AS1 (ror
,%A0
) CR_TAB
3124 AS1 (ror
,__tmp_reg__
) CR_TAB
3125 AS1 (lsr
,%B0
) CR_TAB
3126 AS1 (ror
,%A0
) CR_TAB
3127 AS1 (ror
,__tmp_reg__
) CR_TAB
3128 AS2 (mov
,%B0
,%A0
) CR_TAB
3129 AS2 (mov
,%A0
,__tmp_reg__
));
3133 return (AS1 (lsr
,%B0
) CR_TAB
3134 AS2 (mov
,%B0
,%A0
) CR_TAB
3135 AS1 (clr
,%A0
) CR_TAB
3136 AS1 (ror
,%B0
) CR_TAB
3140 if (true_regnum (operands
[0]) + 1 == true_regnum (operands
[1]))
3141 return *len
= 1, AS1 (clr
,%A0
);
3143 return *len
= 2, (AS2 (mov
,%B0
,%A1
) CR_TAB
3148 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3149 AS1 (clr
,%A0
) CR_TAB
3154 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3155 AS1 (clr
,%A0
) CR_TAB
3156 AS1 (lsl
,%B0
) CR_TAB
3161 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3162 AS1 (clr
,%A0
) CR_TAB
3163 AS1 (lsl
,%B0
) CR_TAB
3164 AS1 (lsl
,%B0
) CR_TAB
3171 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3172 AS1 (clr
,%A0
) CR_TAB
3173 AS1 (swap
,%B0
) CR_TAB
3174 AS2 (andi
,%B0
,0xf0));
3179 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3180 AS1 (clr
,%A0
) CR_TAB
3181 AS1 (swap
,%B0
) CR_TAB
3182 AS2 (ldi
,%3,0xf0) CR_TAB
3186 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3187 AS1 (clr
,%A0
) CR_TAB
3188 AS1 (lsl
,%B0
) CR_TAB
3189 AS1 (lsl
,%B0
) CR_TAB
3190 AS1 (lsl
,%B0
) CR_TAB
3197 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3198 AS1 (clr
,%A0
) CR_TAB
3199 AS1 (swap
,%B0
) CR_TAB
3200 AS1 (lsl
,%B0
) CR_TAB
3201 AS2 (andi
,%B0
,0xe0));
3203 if (AVR_ENHANCED
&& scratch
)
3206 return (AS2 (ldi
,%3,0x20) CR_TAB
3207 AS2 (mul
,%A0
,%3) CR_TAB
3208 AS2 (mov
,%B0
,r0
) CR_TAB
3209 AS1 (clr
,%A0
) CR_TAB
3210 AS1 (clr
,__zero_reg__
));
3212 if (optimize_size
&& scratch
)
3217 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3218 AS1 (clr
,%A0
) CR_TAB
3219 AS1 (swap
,%B0
) CR_TAB
3220 AS1 (lsl
,%B0
) CR_TAB
3221 AS2 (ldi
,%3,0xe0) CR_TAB
3227 return ("set" CR_TAB
3228 AS2 (bld
,r1
,5) CR_TAB
3229 AS2 (mul
,%A0
,r1
) CR_TAB
3230 AS2 (mov
,%B0
,r0
) CR_TAB
3231 AS1 (clr
,%A0
) CR_TAB
3232 AS1 (clr
,__zero_reg__
));
3235 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3236 AS1 (clr
,%A0
) CR_TAB
3237 AS1 (lsl
,%B0
) CR_TAB
3238 AS1 (lsl
,%B0
) CR_TAB
3239 AS1 (lsl
,%B0
) CR_TAB
3240 AS1 (lsl
,%B0
) CR_TAB
3244 if (AVR_ENHANCED
&& ldi_ok
)
3247 return (AS2 (ldi
,%B0
,0x40) CR_TAB
3248 AS2 (mul
,%A0
,%B0
) CR_TAB
3249 AS2 (mov
,%B0
,r0
) CR_TAB
3250 AS1 (clr
,%A0
) CR_TAB
3251 AS1 (clr
,__zero_reg__
));
3253 if (AVR_ENHANCED
&& scratch
)
3256 return (AS2 (ldi
,%3,0x40) CR_TAB
3257 AS2 (mul
,%A0
,%3) CR_TAB
3258 AS2 (mov
,%B0
,r0
) CR_TAB
3259 AS1 (clr
,%A0
) CR_TAB
3260 AS1 (clr
,__zero_reg__
));
3262 if (optimize_size
&& ldi_ok
)
3265 return (AS2 (mov
,%B0
,%A0
) CR_TAB
3266 AS2 (ldi
,%A0
,6) "\n1:\t"
3267 AS1 (lsl
,%B0
) CR_TAB
3268 AS1 (dec
,%A0
) CR_TAB
3271 if (optimize_size
&& scratch
)
3274 return (AS1 (clr
,%B0
) CR_TAB
3275 AS1 (lsr
,%A0
) CR_TAB
3276 AS1 (ror
,%B0
) CR_TAB
3277 AS1 (lsr
,%A0
) CR_TAB
3278 AS1 (ror
,%B0
) CR_TAB
3283 return (AS1 (clr
,%B0
) CR_TAB
3284 AS1 (lsr
,%A0
) CR_TAB
3285 AS1 (ror
,%B0
) CR_TAB
3290 out_shift_with_cnt ((AS1 (lsl
,%A0
) CR_TAB
3292 insn
, operands
, len
, 2);
3297 /* 32bit shift left ((long)x << i) */
3300 ashlsi3_out (insn
, operands
, len
)
3305 if (GET_CODE (operands
[2]) == CONST_INT
)
3313 switch (INTVAL (operands
[2]))
3317 int reg0
= true_regnum (operands
[0]);
3318 int reg1
= true_regnum (operands
[1]);
3321 return (AS2 (mov
,%D0
,%C1
) CR_TAB
3322 AS2 (mov
,%C0
,%B1
) CR_TAB
3323 AS2 (mov
,%B0
,%A1
) CR_TAB
3325 else if (reg0
+ 1 == reg1
)
3328 return AS1 (clr
,%A0
);
3331 return (AS1 (clr
,%A0
) CR_TAB
3332 AS2 (mov
,%B0
,%A1
) CR_TAB
3333 AS2 (mov
,%C0
,%B1
) CR_TAB
3339 int reg0
= true_regnum (operands
[0]);
3340 int reg1
= true_regnum (operands
[1]);
3342 if (AVR_ENHANCED
&& (reg0
+ 2 != reg1
))
3345 return (AS2 (movw
,%C0
,%A1
) CR_TAB
3346 AS1 (clr
,%B0
) CR_TAB
3349 if (reg0
+ 1 >= reg1
)
3350 return (AS2 (mov
,%D0
,%B1
) CR_TAB
3351 AS2 (mov
,%C0
,%A1
) CR_TAB
3352 AS1 (clr
,%B0
) CR_TAB
3354 if (reg0
+ 2 == reg1
)
3357 return (AS1 (clr
,%B0
) CR_TAB
3361 return (AS2 (mov
,%C0
,%A1
) CR_TAB
3362 AS2 (mov
,%D0
,%B1
) CR_TAB
3363 AS1 (clr
,%B0
) CR_TAB
3369 if (true_regnum (operands
[0]) + 3 != true_regnum (operands
[1]))
3370 return (AS2 (mov
,%D0
,%A1
) CR_TAB
3371 AS1 (clr
,%C0
) CR_TAB
3372 AS1 (clr
,%B0
) CR_TAB
3377 return (AS1 (clr
,%C0
) CR_TAB
3378 AS1 (clr
,%B0
) CR_TAB
3384 return (AS1 (clr
,%D0
) CR_TAB
3385 AS1 (lsr
,%A0
) CR_TAB
3386 AS1 (ror
,%D0
) CR_TAB
3387 AS1 (clr
,%C0
) CR_TAB
3388 AS1 (clr
,%B0
) CR_TAB
3393 out_shift_with_cnt ((AS1 (lsl
,%A0
) CR_TAB
3394 AS1 (rol
,%B0
) CR_TAB
3395 AS1 (rol
,%C0
) CR_TAB
3397 insn
, operands
, len
, 4);
3401 /* 8bit arithmetic shift right ((signed char)x >> i) */
3404 ashrqi3_out (insn
, operands
, len
)
3407 int *len
; /* insn length */
3409 if (GET_CODE (operands
[2]) == CONST_INT
)
3416 switch (INTVAL (operands
[2]))
3420 return AS1 (asr
,%0);
3424 return (AS1 (asr
,%0) CR_TAB
3429 return (AS1 (asr
,%0) CR_TAB
3435 return (AS1 (asr
,%0) CR_TAB
3442 return (AS1 (asr
,%0) CR_TAB
3450 return (AS2 (bst
,%0,6) CR_TAB
3452 AS2 (sbc
,%0,%0) CR_TAB
3458 return (AS1 (lsl
,%0) CR_TAB
3462 else if (CONSTANT_P (operands
[2]))
3463 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
3465 out_shift_with_cnt (AS1 (asr
,%0),
3466 insn
, operands
, len
, 1);
3471 /* 16bit arithmetic shift right ((signed short)x >> i) */
3474 ashrhi3_out (insn
, operands
, len
)
3479 if (GET_CODE (operands
[2]) == CONST_INT
)
3481 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
3482 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
3489 switch (INTVAL (operands
[2]))
3493 /* XXX try to optimize this too? */
3498 break; /* scratch ? 5 : 6 */
3500 return (AS2 (mov
,__tmp_reg__
,%A0
) CR_TAB
3501 AS2 (mov
,%A0
,%B0
) CR_TAB
3502 AS1 (lsl
,__tmp_reg__
) CR_TAB
3503 AS1 (rol
,%A0
) CR_TAB
3504 AS2 (sbc
,%B0
,%B0
) CR_TAB
3505 AS1 (lsl
,__tmp_reg__
) CR_TAB
3506 AS1 (rol
,%A0
) CR_TAB
3511 return (AS1 (lsl
,%A0
) CR_TAB
3512 AS2 (mov
,%A0
,%B0
) CR_TAB
3513 AS1 (rol
,%A0
) CR_TAB
3518 int reg0
= true_regnum (operands
[0]);
3519 int reg1
= true_regnum (operands
[1]);
3522 return *len
= 3, (AS2 (mov
,%A0
,%B0
) CR_TAB
3523 AS1 (lsl
,%B0
) CR_TAB
3525 else if (reg0
== reg1
+ 1)
3526 return *len
= 3, (AS1 (clr
,%B0
) CR_TAB
3527 AS2 (sbrc
,%A0
,7) CR_TAB
3530 return *len
= 4, (AS2 (mov
,%A0
,%B1
) CR_TAB
3531 AS1 (clr
,%B0
) CR_TAB
3532 AS2 (sbrc
,%A0
,7) CR_TAB
3538 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3539 AS1 (lsl
,%B0
) CR_TAB
3540 AS2 (sbc
,%B0
,%B0
) CR_TAB
3545 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3546 AS1 (lsl
,%B0
) CR_TAB
3547 AS2 (sbc
,%B0
,%B0
) CR_TAB
3548 AS1 (asr
,%A0
) CR_TAB
3552 if (AVR_ENHANCED
&& ldi_ok
)
3555 return (AS2 (ldi
,%A0
,0x20) CR_TAB
3556 AS2 (muls
,%B0
,%A0
) CR_TAB
3557 AS2 (mov
,%A0
,r1
) CR_TAB
3558 AS2 (sbc
,%B0
,%B0
) CR_TAB
3559 AS1 (clr
,__zero_reg__
));
3561 if (optimize_size
&& scratch
)
3564 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3565 AS1 (lsl
,%B0
) CR_TAB
3566 AS2 (sbc
,%B0
,%B0
) CR_TAB
3567 AS1 (asr
,%A0
) CR_TAB
3568 AS1 (asr
,%A0
) CR_TAB
3572 if (AVR_ENHANCED
&& ldi_ok
)
3575 return (AS2 (ldi
,%A0
,0x10) CR_TAB
3576 AS2 (muls
,%B0
,%A0
) CR_TAB
3577 AS2 (mov
,%A0
,r1
) CR_TAB
3578 AS2 (sbc
,%B0
,%B0
) CR_TAB
3579 AS1 (clr
,__zero_reg__
));
3581 if (optimize_size
&& scratch
)
3584 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3585 AS1 (lsl
,%B0
) CR_TAB
3586 AS2 (sbc
,%B0
,%B0
) CR_TAB
3587 AS1 (asr
,%A0
) CR_TAB
3588 AS1 (asr
,%A0
) CR_TAB
3589 AS1 (asr
,%A0
) CR_TAB
3593 if (AVR_ENHANCED
&& ldi_ok
)
3596 return (AS2 (ldi
,%A0
,0x08) CR_TAB
3597 AS2 (muls
,%B0
,%A0
) CR_TAB
3598 AS2 (mov
,%A0
,r1
) CR_TAB
3599 AS2 (sbc
,%B0
,%B0
) CR_TAB
3600 AS1 (clr
,__zero_reg__
));
3603 break; /* scratch ? 5 : 7 */
3605 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3606 AS1 (lsl
,%B0
) CR_TAB
3607 AS2 (sbc
,%B0
,%B0
) CR_TAB
3608 AS1 (asr
,%A0
) CR_TAB
3609 AS1 (asr
,%A0
) CR_TAB
3610 AS1 (asr
,%A0
) CR_TAB
3611 AS1 (asr
,%A0
) CR_TAB
3616 return (AS1 (lsl
,%B0
) CR_TAB
3617 AS2 (sbc
,%A0
,%A0
) CR_TAB
3618 AS1 (lsl
,%B0
) CR_TAB
3619 AS2 (mov
,%B0
,%A0
) CR_TAB
3623 return *len
= 3, (AS1 (lsl
,%B0
) CR_TAB
3624 AS2 (sbc
,%A0
,%A0
) CR_TAB
3629 out_shift_with_cnt ((AS1 (asr
,%B0
) CR_TAB
3631 insn
, operands
, len
, 2);
3636 /* 32bit arithmetic shift right ((signed long)x >> i) */
3639 ashrsi3_out (insn
, operands
, len
)
3644 if (GET_CODE (operands
[2]) == CONST_INT
)
3652 switch (INTVAL (operands
[2]))
3656 int reg0
= true_regnum (operands
[0]);
3657 int reg1
= true_regnum (operands
[1]);
3660 return (AS2 (mov
,%A0
,%B1
) CR_TAB
3661 AS2 (mov
,%B0
,%C1
) CR_TAB
3662 AS2 (mov
,%C0
,%D1
) CR_TAB
3663 AS1 (clr
,%D0
) CR_TAB
3664 AS2 (sbrc
,%C0
,7) CR_TAB
3666 else if (reg0
== reg1
+ 1)
3669 return (AS1 (clr
,%D0
) CR_TAB
3670 AS2 (sbrc
,%C0
,7) CR_TAB
3674 return (AS1 (clr
,%D0
) CR_TAB
3675 AS2 (sbrc
,%D1
,7) CR_TAB
3676 AS1 (dec
,%D0
) CR_TAB
3677 AS2 (mov
,%C0
,%D1
) CR_TAB
3678 AS2 (mov
,%B0
,%C1
) CR_TAB
3684 int reg0
= true_regnum (operands
[0]);
3685 int reg1
= true_regnum (operands
[1]);
3687 if (AVR_ENHANCED
&& (reg0
!= reg1
+ 2))
3690 return (AS2 (movw
,%A0
,%C1
) CR_TAB
3691 AS1 (clr
,%D0
) CR_TAB
3692 AS2 (sbrc
,%B0
,7) CR_TAB
3693 AS1 (com
,%D0
) CR_TAB
3696 if (reg0
<= reg1
+ 1)
3697 return (AS2 (mov
,%A0
,%C1
) CR_TAB
3698 AS2 (mov
,%B0
,%D1
) CR_TAB
3699 AS1 (clr
,%D0
) CR_TAB
3700 AS2 (sbrc
,%B0
,7) CR_TAB
3701 AS1 (com
,%D0
) CR_TAB
3703 else if (reg0
== reg1
+ 2)
3704 return *len
= 4, (AS1 (clr
,%D0
) CR_TAB
3705 AS2 (sbrc
,%B0
,7) CR_TAB
3706 AS1 (com
,%D0
) CR_TAB
3709 return (AS2 (mov
,%B0
,%D1
) CR_TAB
3710 AS2 (mov
,%A0
,%C1
) CR_TAB
3711 AS1 (clr
,%D0
) CR_TAB
3712 AS2 (sbrc
,%B0
,7) CR_TAB
3713 AS1 (com
,%D0
) CR_TAB
3718 if (true_regnum (operands
[0]) != true_regnum (operands
[1]) + 3)
3719 return *len
= 6, (AS2 (mov
,%A0
,%D1
) CR_TAB
3720 AS1 (clr
,%D0
) CR_TAB
3721 AS2 (sbrc
,%A0
,7) CR_TAB
3722 AS1 (com
,%D0
) CR_TAB
3723 AS2 (mov
,%B0
,%D0
) CR_TAB
3726 return *len
= 5, (AS1 (clr
,%D0
) CR_TAB
3727 AS2 (sbrc
,%A0
,7) CR_TAB
3728 AS1 (com
,%D0
) CR_TAB
3729 AS2 (mov
,%B0
,%D0
) CR_TAB
3734 return *len
= 4, (AS1 (lsl
,%D0
) CR_TAB
3735 AS2 (sbc
,%A0
,%A0
) CR_TAB
3736 AS2 (mov
,%B0
,%A0
) CR_TAB
3737 AS2 (movw
,%C0
,%A0
));
3739 return *len
= 5, (AS1 (lsl
,%D0
) CR_TAB
3740 AS2 (sbc
,%A0
,%A0
) CR_TAB
3741 AS2 (mov
,%B0
,%A0
) CR_TAB
3742 AS2 (mov
,%C0
,%A0
) CR_TAB
3747 out_shift_with_cnt ((AS1 (asr
,%D0
) CR_TAB
3748 AS1 (ror
,%C0
) CR_TAB
3749 AS1 (ror
,%B0
) CR_TAB
3751 insn
, operands
, len
, 4);
3755 /* 8bit logic shift right ((unsigned char)x >> i) */
3758 lshrqi3_out (insn
, operands
, len
)
3763 if (GET_CODE (operands
[2]) == CONST_INT
)
3770 switch (INTVAL (operands
[2]))
3774 return AS1 (clr
,%0);
3778 return AS1 (lsr
,%0);
3782 return (AS1 (lsr
,%0) CR_TAB
3786 return (AS1 (lsr
,%0) CR_TAB
3791 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3794 return (AS1 (swap
,%0) CR_TAB
3795 AS2 (andi
,%0,0x0f));
3798 return (AS1 (lsr
,%0) CR_TAB
3804 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3807 return (AS1 (swap
,%0) CR_TAB
3812 return (AS1 (lsr
,%0) CR_TAB
3819 if (test_hard_reg_class (LD_REGS
, operands
[0]))
3822 return (AS1 (swap
,%0) CR_TAB
3828 return (AS1 (lsr
,%0) CR_TAB
3837 return (AS1 (rol
,%0) CR_TAB
3842 else if (CONSTANT_P (operands
[2]))
3843 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
3845 out_shift_with_cnt (AS1 (lsr
,%0),
3846 insn
, operands
, len
, 1);
3850 /* 16bit logic shift right ((unsigned short)x >> i) */
3853 lshrhi3_out (insn
, operands
, len
)
3858 if (GET_CODE (operands
[2]) == CONST_INT
)
3860 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
3861 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
3868 switch (INTVAL (operands
[2]))
3871 if (optimize_size
&& scratch
)
3876 return (AS1 (swap
,%B0
) CR_TAB
3877 AS1 (swap
,%A0
) CR_TAB
3878 AS2 (andi
,%A0
,0x0f) CR_TAB
3879 AS2 (eor
,%A0
,%B0
) CR_TAB
3880 AS2 (andi
,%B0
,0x0f) CR_TAB
3886 return (AS1 (swap
,%B0
) CR_TAB
3887 AS1 (swap
,%A0
) CR_TAB
3888 AS2 (ldi
,%3,0x0f) CR_TAB
3889 AS2 (and,%A0
,%3) CR_TAB
3890 AS2 (eor
,%A0
,%B0
) CR_TAB
3891 AS2 (and,%B0
,%3) CR_TAB
3894 break; /* optimize_size ? 6 : 8 */
3898 break; /* scratch ? 5 : 6 */
3902 return (AS1 (lsr
,%B0
) CR_TAB
3903 AS1 (ror
,%A0
) CR_TAB
3904 AS1 (swap
,%B0
) CR_TAB
3905 AS1 (swap
,%A0
) CR_TAB
3906 AS2 (andi
,%A0
,0x0f) CR_TAB
3907 AS2 (eor
,%A0
,%B0
) CR_TAB
3908 AS2 (andi
,%B0
,0x0f) CR_TAB
3914 return (AS1 (lsr
,%B0
) CR_TAB
3915 AS1 (ror
,%A0
) CR_TAB
3916 AS1 (swap
,%B0
) CR_TAB
3917 AS1 (swap
,%A0
) CR_TAB
3918 AS2 (ldi
,%3,0x0f) CR_TAB
3919 AS2 (and,%A0
,%3) CR_TAB
3920 AS2 (eor
,%A0
,%B0
) CR_TAB
3921 AS2 (and,%B0
,%3) CR_TAB
3928 break; /* scratch ? 5 : 6 */
3930 return (AS1 (clr
,__tmp_reg__
) CR_TAB
3931 AS1 (lsl
,%A0
) CR_TAB
3932 AS1 (rol
,%B0
) CR_TAB
3933 AS1 (rol
,__tmp_reg__
) CR_TAB
3934 AS1 (lsl
,%A0
) CR_TAB
3935 AS1 (rol
,%B0
) CR_TAB
3936 AS1 (rol
,__tmp_reg__
) CR_TAB
3937 AS2 (mov
,%A0
,%B0
) CR_TAB
3938 AS2 (mov
,%B0
,__tmp_reg__
));
3942 return (AS1 (lsl
,%A0
) CR_TAB
3943 AS2 (mov
,%A0
,%B0
) CR_TAB
3944 AS1 (rol
,%A0
) CR_TAB
3945 AS2 (sbc
,%B0
,%B0
) CR_TAB
3949 if (true_regnum (operands
[0]) != true_regnum (operands
[1]) + 1)
3950 return *len
= 2, (AS2 (mov
,%A0
,%B1
) CR_TAB
3953 return *len
= 1, AS1 (clr
,%B0
);
3957 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3958 AS1 (clr
,%B0
) CR_TAB
3963 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3964 AS1 (clr
,%B0
) CR_TAB
3965 AS1 (lsr
,%A0
) CR_TAB
3970 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3971 AS1 (clr
,%B0
) CR_TAB
3972 AS1 (lsr
,%A0
) CR_TAB
3973 AS1 (lsr
,%A0
) CR_TAB
3980 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3981 AS1 (clr
,%B0
) CR_TAB
3982 AS1 (swap
,%A0
) CR_TAB
3983 AS2 (andi
,%A0
,0x0f));
3988 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3989 AS1 (clr
,%B0
) CR_TAB
3990 AS1 (swap
,%A0
) CR_TAB
3991 AS2 (ldi
,%3,0x0f) CR_TAB
3995 return (AS2 (mov
,%A0
,%B0
) CR_TAB
3996 AS1 (clr
,%B0
) CR_TAB
3997 AS1 (lsr
,%A0
) CR_TAB
3998 AS1 (lsr
,%A0
) CR_TAB
3999 AS1 (lsr
,%A0
) CR_TAB
4006 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4007 AS1 (clr
,%B0
) CR_TAB
4008 AS1 (swap
,%A0
) CR_TAB
4009 AS1 (lsr
,%A0
) CR_TAB
4010 AS2 (andi
,%A0
,0x07));
4012 if (AVR_ENHANCED
&& scratch
)
4015 return (AS2 (ldi
,%3,0x08) CR_TAB
4016 AS2 (mul
,%B0
,%3) CR_TAB
4017 AS2 (mov
,%A0
,r1
) CR_TAB
4018 AS1 (clr
,%B0
) CR_TAB
4019 AS1 (clr
,__zero_reg__
));
4021 if (optimize_size
&& scratch
)
4026 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4027 AS1 (clr
,%B0
) CR_TAB
4028 AS1 (swap
,%A0
) CR_TAB
4029 AS1 (lsr
,%A0
) CR_TAB
4030 AS2 (ldi
,%3,0x07) CR_TAB
4036 return ("set" CR_TAB
4037 AS2 (bld
,r1
,3) CR_TAB
4038 AS2 (mul
,%B0
,r1
) CR_TAB
4039 AS2 (mov
,%A0
,r1
) CR_TAB
4040 AS1 (clr
,%B0
) CR_TAB
4041 AS1 (clr
,__zero_reg__
));
4044 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4045 AS1 (clr
,%B0
) CR_TAB
4046 AS1 (lsr
,%A0
) CR_TAB
4047 AS1 (lsr
,%A0
) CR_TAB
4048 AS1 (lsr
,%A0
) CR_TAB
4049 AS1 (lsr
,%A0
) CR_TAB
4053 if (AVR_ENHANCED
&& ldi_ok
)
4056 return (AS2 (ldi
,%A0
,0x04) CR_TAB
4057 AS2 (mul
,%B0
,%A0
) CR_TAB
4058 AS2 (mov
,%A0
,r1
) CR_TAB
4059 AS1 (clr
,%B0
) CR_TAB
4060 AS1 (clr
,__zero_reg__
));
4062 if (AVR_ENHANCED
&& scratch
)
4065 return (AS2 (ldi
,%3,0x04) CR_TAB
4066 AS2 (mul
,%B0
,%3) CR_TAB
4067 AS2 (mov
,%A0
,r1
) CR_TAB
4068 AS1 (clr
,%B0
) CR_TAB
4069 AS1 (clr
,__zero_reg__
));
4071 if (optimize_size
&& ldi_ok
)
4074 return (AS2 (mov
,%A0
,%B0
) CR_TAB
4075 AS2 (ldi
,%B0
,6) "\n1:\t"
4076 AS1 (lsr
,%A0
) CR_TAB
4077 AS1 (dec
,%B0
) CR_TAB
4080 if (optimize_size
&& scratch
)
4083 return (AS1 (clr
,%A0
) CR_TAB
4084 AS1 (lsl
,%B0
) CR_TAB
4085 AS1 (rol
,%A0
) CR_TAB
4086 AS1 (lsl
,%B0
) CR_TAB
4087 AS1 (rol
,%A0
) CR_TAB
4092 return (AS1 (clr
,%A0
) CR_TAB
4093 AS1 (lsl
,%B0
) CR_TAB
4094 AS1 (rol
,%A0
) CR_TAB
4099 out_shift_with_cnt ((AS1 (lsr
,%B0
) CR_TAB
4101 insn
, operands
, len
, 2);
4105 /* 32bit logic shift right ((unsigned int)x >> i) */
4108 lshrsi3_out (insn
, operands
, len
)
4113 if (GET_CODE (operands
[2]) == CONST_INT
)
4121 switch (INTVAL (operands
[2]))
4125 int reg0
= true_regnum (operands
[0]);
4126 int reg1
= true_regnum (operands
[1]);
4129 return (AS2 (mov
,%A0
,%B1
) CR_TAB
4130 AS2 (mov
,%B0
,%C1
) CR_TAB
4131 AS2 (mov
,%C0
,%D1
) CR_TAB
4133 else if (reg0
== reg1
+ 1)
4134 return *len
= 1, AS1 (clr
,%D0
);
4136 return (AS1 (clr
,%D0
) CR_TAB
4137 AS2 (mov
,%C0
,%D1
) CR_TAB
4138 AS2 (mov
,%B0
,%C1
) CR_TAB
4144 int reg0
= true_regnum (operands
[0]);
4145 int reg1
= true_regnum (operands
[1]);
4147 if (AVR_ENHANCED
&& (reg0
!= reg1
+ 2))
4150 return (AS2 (movw
,%A0
,%C1
) CR_TAB
4151 AS1 (clr
,%C0
) CR_TAB
4154 if (reg0
<= reg1
+ 1)
4155 return (AS2 (mov
,%A0
,%C1
) CR_TAB
4156 AS2 (mov
,%B0
,%D1
) CR_TAB
4157 AS1 (clr
,%C0
) CR_TAB
4159 else if (reg0
== reg1
+ 2)
4160 return *len
= 2, (AS1 (clr
,%C0
) CR_TAB
4163 return (AS2 (mov
,%B0
,%D1
) CR_TAB
4164 AS2 (mov
,%A0
,%C1
) CR_TAB
4165 AS1 (clr
,%C0
) CR_TAB
4170 if (true_regnum (operands
[0]) != true_regnum (operands
[1]) + 3)
4171 return *len
= 4, (AS2 (mov
,%A0
,%D1
) CR_TAB
4172 AS1 (clr
,%B0
) CR_TAB
4173 AS1 (clr
,%C0
) CR_TAB
4176 return *len
= 3, (AS1 (clr
,%B0
) CR_TAB
4177 AS1 (clr
,%C0
) CR_TAB
4182 return (AS1 (clr
,%A0
) CR_TAB
4183 AS2 (sbrc
,%D0
,7) CR_TAB
4184 AS1 (inc
,%A0
) CR_TAB
4185 AS1 (clr
,%B0
) CR_TAB
4186 AS1 (clr
,%C0
) CR_TAB
4191 out_shift_with_cnt ((AS1 (lsr
,%D0
) CR_TAB
4192 AS1 (ror
,%C0
) CR_TAB
4193 AS1 (ror
,%B0
) CR_TAB
4195 insn
, operands
, len
, 4);
4199 /* Modifies the length assigned to instruction INSN
4200 LEN is the initially computed length of the insn. */
4203 adjust_insn_length (insn
, len
)
4207 rtx patt
= PATTERN (insn
);
4210 if (GET_CODE (patt
) == SET
)
4213 op
[1] = SET_SRC (patt
);
4214 op
[0] = SET_DEST (patt
);
4215 if (general_operand (op
[1], VOIDmode
)
4216 && general_operand (op
[0], VOIDmode
))
4218 switch (GET_MODE (op
[0]))
4221 output_movqi (insn
, op
, &len
);
4224 output_movhi (insn
, op
, &len
);
4228 output_movsisf (insn
, op
, &len
);
4234 else if (op
[0] == cc0_rtx
&& REG_P (op
[1]))
4236 switch (GET_MODE (op
[1]))
4238 case HImode
: out_tsthi (insn
,&len
); break;
4239 case SImode
: out_tstsi (insn
,&len
); break;
4243 else if (GET_CODE (op
[1]) == AND
)
4245 if (GET_CODE (XEXP (op
[1],1)) == CONST_INT
)
4247 HOST_WIDE_INT mask
= INTVAL (XEXP (op
[1],1));
4248 if (GET_MODE (op
[1]) == SImode
)
4249 len
= (((mask
& 0xff) != 0xff)
4250 + ((mask
& 0xff00) != 0xff00)
4251 + ((mask
& 0xff0000L
) != 0xff0000L
)
4252 + ((mask
& 0xff000000L
) != 0xff000000L
));
4253 else if (GET_MODE (op
[1]) == HImode
)
4254 len
= (((mask
& 0xff) != 0xff)
4255 + ((mask
& 0xff00) != 0xff00));
4258 else if (GET_CODE (op
[1]) == IOR
)
4260 if (GET_CODE (XEXP (op
[1],1)) == CONST_INT
)
4262 HOST_WIDE_INT mask
= INTVAL (XEXP (op
[1],1));
4263 if (GET_MODE (op
[1]) == SImode
)
4264 len
= (((mask
& 0xff) != 0)
4265 + ((mask
& 0xff00) != 0)
4266 + ((mask
& 0xff0000L
) != 0)
4267 + ((mask
& 0xff000000L
) != 0));
4268 else if (GET_MODE (op
[1]) == HImode
)
4269 len
= (((mask
& 0xff) != 0)
4270 + ((mask
& 0xff00) != 0));
4274 set
= single_set (insn
);
4279 op
[1] = SET_SRC (set
);
4280 op
[0] = SET_DEST (set
);
4282 if (GET_CODE (patt
) == PARALLEL
4283 && general_operand (op
[1], VOIDmode
)
4284 && general_operand (op
[0], VOIDmode
))
4286 if (XVECLEN (patt
, 0) == 2)
4287 op
[2] = XVECEXP (patt
, 0, 1);
4289 switch (GET_MODE (op
[0]))
4295 output_reload_inhi (insn
, op
, &len
);
4299 output_reload_insisf (insn
, op
, &len
);
4305 else if (GET_CODE (op
[1]) == ASHIFT
4306 || GET_CODE (op
[1]) == ASHIFTRT
4307 || GET_CODE (op
[1]) == LSHIFTRT
)
4311 ops
[1] = XEXP (op
[1],0);
4312 ops
[2] = XEXP (op
[1],1);
4313 switch (GET_CODE (op
[1]))
4316 switch (GET_MODE (op
[0]))
4318 case QImode
: ashlqi3_out (insn
,ops
,&len
); break;
4319 case HImode
: ashlhi3_out (insn
,ops
,&len
); break;
4320 case SImode
: ashlsi3_out (insn
,ops
,&len
); break;
4325 switch (GET_MODE (op
[0]))
4327 case QImode
: ashrqi3_out (insn
,ops
,&len
); break;
4328 case HImode
: ashrhi3_out (insn
,ops
,&len
); break;
4329 case SImode
: ashrsi3_out (insn
,ops
,&len
); break;
4334 switch (GET_MODE (op
[0]))
4336 case QImode
: lshrqi3_out (insn
,ops
,&len
); break;
4337 case HImode
: lshrhi3_out (insn
,ops
,&len
); break;
4338 case SImode
: lshrsi3_out (insn
,ops
,&len
); break;
4350 /* Return non-zero if register REG dead after INSN */
4353 reg_unused_after (insn
, reg
)
4357 return (dead_or_set_p (insn
, reg
)
4358 || (REG_P(reg
) && _reg_unused_after (insn
, reg
)));
4361 /* Return non-zero if REG is not used after INSN.
4362 We assume REG is a reload reg, and therefore does
4363 not live past labels. It may live past calls or jumps though. */
4366 _reg_unused_after (insn
, reg
)
4373 /* If the reg is set by this instruction, then it is safe for our
4374 case. Disregard the case where this is a store to memory, since
4375 we are checking a register used in the store address. */
4376 set
= single_set (insn
);
4377 if (set
&& GET_CODE (SET_DEST (set
)) != MEM
4378 && reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
4381 while ((insn
= NEXT_INSN (insn
)))
4383 code
= GET_CODE (insn
);
4386 /* If this is a label that existed before reload, then the register
4387 if dead here. However, if this is a label added by reorg, then
4388 the register may still be live here. We can't tell the difference,
4389 so we just ignore labels completely. */
4390 if (code
== CODE_LABEL
)
4395 if (code
== JUMP_INSN
)
4398 /* If this is a sequence, we must handle them all at once.
4399 We could have for instance a call that sets the target register,
4400 and an insn in a delay slot that uses the register. In this case,
4401 we must return 0. */
4402 else if (code
== INSN
&& GET_CODE (PATTERN (insn
)) == SEQUENCE
)
4407 for (i
= 0; i
< XVECLEN (PATTERN (insn
), 0); i
++)
4409 rtx this_insn
= XVECEXP (PATTERN (insn
), 0, i
);
4410 rtx set
= single_set (this_insn
);
4412 if (GET_CODE (this_insn
) == CALL_INSN
)
4414 else if (GET_CODE (this_insn
) == JUMP_INSN
)
4416 if (INSN_ANNULLED_BRANCH_P (this_insn
))
4421 if (set
&& reg_overlap_mentioned_p (reg
, SET_SRC (set
)))
4423 if (set
&& reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
4425 if (GET_CODE (SET_DEST (set
)) != MEM
)
4431 && reg_overlap_mentioned_p (reg
, PATTERN (this_insn
)))
4436 else if (code
== JUMP_INSN
)
4440 if (code
== CALL_INSN
)
4443 for (tem
= CALL_INSN_FUNCTION_USAGE (insn
); tem
; tem
= XEXP (tem
, 1))
4444 if (GET_CODE (XEXP (tem
, 0)) == USE
4445 && REG_P (XEXP (XEXP (tem
, 0), 0))
4446 && reg_overlap_mentioned_p (reg
, XEXP (XEXP (tem
, 0), 0)))
4448 if (call_used_regs
[REGNO (reg
)])
4452 if (GET_RTX_CLASS (code
) == 'i')
4454 rtx set
= single_set (insn
);
4456 if (set
&& reg_overlap_mentioned_p (reg
, SET_SRC (set
)))
4458 if (set
&& reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
4459 return GET_CODE (SET_DEST (set
)) != MEM
;
4460 if (set
== 0 && reg_overlap_mentioned_p (reg
, PATTERN (insn
)))
4467 /* Target hook for assembling integer objects. The AVR version needs
4468 special handling for references to certain labels. */
4471 avr_assemble_integer (x
, size
, aligned_p
)
4476 if (size
== POINTER_SIZE
/ BITS_PER_UNIT
&& aligned_p
4477 && ((GET_CODE (x
) == SYMBOL_REF
&& SYMBOL_REF_FLAG (x
))
4478 || GET_CODE (x
) == LABEL_REF
))
4480 fputs ("\t.word\tpm(", asm_out_file
);
4481 output_addr_const (asm_out_file
, x
);
4482 fputs (")\n", asm_out_file
);
4485 return default_assemble_integer (x
, size
, aligned_p
);
4488 /* Sets section name for declaration DECL */
4491 unique_section (decl
, reloc
)
4493 int reloc ATTRIBUTE_UNUSED
;
4496 const char *name
, *prefix
;
4498 name
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
));
4499 /* Strip off any encoding in name. */
4500 STRIP_NAME_ENCODING (name
, name
);
4502 if (TREE_CODE (decl
) == FUNCTION_DECL
)
4504 if (flag_function_sections
)
4512 if (flag_function_sections
)
4514 len
= strlen (name
) + strlen (prefix
);
4515 string
= alloca (len
+ 1);
4516 sprintf (string
, "%s%s", prefix
, name
);
4517 DECL_SECTION_NAME (decl
) = build_string (len
, string
);
4522 /* The routine used to output NUL terminated strings. We use a special
4523 version of this for most svr4 targets because doing so makes the
4524 generated assembly code more compact (and thus faster to assemble)
4525 as well as more readable, especially for targets like the i386
4526 (where the only alternative is to output character sequences as
4527 comma separated lists of numbers). */
4530 gas_output_limited_string(file
, str
)
4534 const unsigned char *_limited_str
= (unsigned char *) str
;
4536 fprintf (file
, "%s\"", STRING_ASM_OP
);
4537 for (; (ch
= *_limited_str
); _limited_str
++)
4540 switch (escape
= ESCAPES
[ch
])
4546 fprintf (file
, "\\%03o", ch
);
4550 putc (escape
, file
);
4554 fprintf (file
, "\"\n");
4557 /* The routine used to output sequences of byte values. We use a special
4558 version of this for most svr4 targets because doing so makes the
4559 generated assembly code more compact (and thus faster to assemble)
4560 as well as more readable. Note that if we find subparts of the
4561 character sequence which end with NUL (and which are shorter than
4562 STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
4565 gas_output_ascii(file
, str
, length
)
4570 const unsigned char *_ascii_bytes
= (const unsigned char *) str
;
4571 const unsigned char *limit
= _ascii_bytes
+ length
;
4572 unsigned bytes_in_chunk
= 0;
4573 for (; _ascii_bytes
< limit
; _ascii_bytes
++)
4575 const unsigned char *p
;
4576 if (bytes_in_chunk
>= 60)
4578 fprintf (file
, "\"\n");
4581 for (p
= _ascii_bytes
; p
< limit
&& *p
!= '\0'; p
++)
4583 if (p
< limit
&& (p
- _ascii_bytes
) <= (signed)STRING_LIMIT
)
4585 if (bytes_in_chunk
> 0)
4587 fprintf (file
, "\"\n");
4590 gas_output_limited_string (file
, (char*)_ascii_bytes
);
4597 if (bytes_in_chunk
== 0)
4598 fprintf (file
, "\t.ascii\t\"");
4599 switch (escape
= ESCAPES
[ch
= *_ascii_bytes
])
4606 fprintf (file
, "\\%03o", ch
);
4607 bytes_in_chunk
+= 4;
4611 putc (escape
, file
);
4612 bytes_in_chunk
+= 2;
4617 if (bytes_in_chunk
> 0)
4618 fprintf (file
, "\"\n");
4621 /* Return value is nonzero if pseudos that have been
4622 assigned to registers of class CLASS would likely be spilled
4623 because registers of CLASS are needed for spill registers. */
4626 class_likely_spilled_p (c
)
4629 return (c
!= ALL_REGS
&& c
!= ADDW_REGS
);
4632 /* Valid attributes:
4633 progmem - put data to program memory;
4634 signal - make a function to be hardware interrupt. After function
4635 prologue interrupts are disabled;
4636 interrupt - make a function to be hardware interrupt. After function
4637 prologue interrupts are enabled;
4638 naked - don't generate function prologue/epilogue and `ret' command.
4640 Only `progmem' attribute valid for type. */
4642 const struct attribute_spec avr_attribute_table
[] =
4644 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4645 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute
},
4646 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute
},
4647 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute
},
4648 { "naked", 0, 0, true, false, false, avr_handle_fndecl_attribute
},
4649 { NULL
, 0, 0, false, false, false, NULL
}
4652 /* Handle a "progmem" attribute; arguments as in
4653 struct attribute_spec.handler. */
4655 avr_handle_progmem_attribute (node
, name
, args
, flags
, no_add_attrs
)
4658 tree args ATTRIBUTE_UNUSED
;
4659 int flags ATTRIBUTE_UNUSED
;
4664 if (TREE_STATIC (*node
) || DECL_EXTERNAL (*node
))
4666 if (DECL_INITIAL (*node
) == NULL_TREE
&& !DECL_EXTERNAL (*node
))
4668 warning ("only initialized variables can be placed into "
4669 "program memory area");
4670 *no_add_attrs
= true;
4675 warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name
));
4676 *no_add_attrs
= true;
4683 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4684 struct attribute_spec.handler. */
4686 avr_handle_fndecl_attribute (node
, name
, args
, flags
, no_add_attrs
)
4689 tree args ATTRIBUTE_UNUSED
;
4690 int flags ATTRIBUTE_UNUSED
;
4693 if (TREE_CODE (*node
) != FUNCTION_DECL
)
4695 warning ("`%s' attribute only applies to functions",
4696 IDENTIFIER_POINTER (name
));
4697 *no_add_attrs
= true;
4703 /* Look for attribute `progmem' in DECL
4704 if found return 1, otherwise 0. */
4707 avr_progmem_p (decl
)
4712 if (TREE_CODE (decl
) != VAR_DECL
)
4716 != lookup_attribute ("progmem", DECL_ATTRIBUTES (decl
)))
4722 while (TREE_CODE (a
) == ARRAY_TYPE
);
4724 if (a
== error_mark_node
)
4727 if (NULL_TREE
!= lookup_attribute ("progmem", TYPE_ATTRIBUTES (a
)))
4733 /* Encode section information about tree DECL */
4736 encode_section_info (decl
)
4739 if (TREE_CODE (decl
) == FUNCTION_DECL
)
4740 SYMBOL_REF_FLAG (XEXP (DECL_RTL (decl
), 0)) = 1;
4741 else if ((TREE_STATIC (decl
) || DECL_EXTERNAL (decl
))
4742 && TREE_CODE (decl
) == VAR_DECL
4743 && avr_progmem_p (decl
))
4745 static const char *const dsec
= ".progmem.data";
4746 DECL_SECTION_NAME (decl
) = build_string (strlen (dsec
), dsec
);
4747 TREE_READONLY (decl
) = 1;
4751 /* Outputs to the stdio stream FILE some
4752 appropriate text to go at the start of an assembler file. */
4755 asm_file_start (file
)
4758 output_file_directive (file
, main_input_filename
);
4759 fprintf (file
, "\t.arch %s\n", avr_mcu_name
);
4760 fputs ("__SREG__ = 0x3f\n"
4762 "__SP_L__ = 0x3d\n", file
);
4764 fputs ("__tmp_reg__ = 0\n"
4765 "__zero_reg__ = 1\n"
4766 "_PC_ = 2\n", file
);
4768 commands_in_file
= 0;
4769 commands_in_prologues
= 0;
4770 commands_in_epilogues
= 0;
4773 /* Outputs to the stdio stream FILE some
4774 appropriate text to go at the end of an assembler file. */
4781 "/* File %s: code %4d = 0x%04x (%4d), prologues %3d, epilogues %3d */\n",
4782 main_input_filename
,
4785 commands_in_file
- commands_in_prologues
- commands_in_epilogues
,
4786 commands_in_prologues
, commands_in_epilogues
);
4789 /* Choose the order in which to allocate hard registers for
4790 pseudo-registers local to a basic block.
4792 Store the desired register order in the array `reg_alloc_order'.
4793 Element 0 should be the register to allocate first; element 1, the
4794 next register; and so on. */
4797 order_regs_for_local_alloc ()
4800 static const int order_0
[] = {
4808 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4812 static const int order_1
[] = {
4820 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4824 static const int order_2
[] = {
4833 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4838 const int *order
= (TARGET_ORDER_1
? order_1
:
4839 TARGET_ORDER_2
? order_2
:
4841 for (i
=0; i
< ARRAY_SIZE (order_0
); ++i
)
4842 reg_alloc_order
[i
] = order
[i
];
4845 /* Calculate the cost of X code of the expression in which it is contained,
4846 found in OUTER_CODE */
4849 default_rtx_costs (X
, code
, outer_code
)
4852 enum rtx_code outer_code
;
4859 cost
= 2 * GET_MODE_SIZE (GET_MODE (X
));
4862 if (outer_code
!= SET
)
4864 if (GET_CODE (XEXP (X
,0)) == SYMBOL_REF
)
4865 cost
+= 2 * GET_MODE_SIZE (GET_MODE (X
));
4867 cost
+= GET_MODE_SIZE (GET_MODE (X
));
4873 if (outer_code
== SET
)
4874 cost
= GET_MODE_SIZE (GET_MODE (X
));
4876 cost
= -GET_MODE_SIZE (GET_MODE (X
));
4879 if (outer_code
== SET
)
4880 cost
= GET_MODE_SIZE (GET_MODE (X
));
4886 if (outer_code
== SET
)
4888 if (X
== stack_pointer_rtx
)
4890 else if (GET_CODE (XEXP (X
,1)) == CONST_INT
)
4891 cost
= (INTVAL (XEXP (X
,1)) <= 63 ? 1 :
4892 GET_MODE_SIZE (GET_MODE (X
)));
4894 cost
= GET_MODE_SIZE (GET_MODE (X
));
4898 if (GET_CODE (XEXP (X
,1)) == CONST_INT
)
4899 cost
= GET_MODE_SIZE (GET_MODE (XEXP (X
,0)));
4907 /* Calculate the cost of a memory address */
4910 avr_address_cost (x
)
4913 if (GET_CODE (x
) == PLUS
4914 && GET_CODE (XEXP (x
,1)) == CONST_INT
4915 && (REG_P (XEXP (x
,0)) || GET_CODE (XEXP (x
,0)) == SUBREG
)
4916 && INTVAL (XEXP (x
,1)) >= 61)
4918 if (CONSTANT_ADDRESS_P (x
))
4920 if (io_address_p (x
, 1))
4927 /* EXTRA_CONSTRAINT helper */
4930 extra_constraint (x
, c
)
4935 && GET_CODE (x
) == MEM
4936 && GET_CODE (XEXP (x
,0)) == PLUS
)
4938 if (TARGET_ALL_DEBUG
)
4940 fprintf (stderr
, ("extra_constraint:\n"
4941 "reload_completed: %d\n"
4942 "reload_in_progress: %d\n"),
4943 reload_completed
, reload_in_progress
);
4946 if (GET_CODE (x
) == MEM
4947 && GET_CODE (XEXP (x
,0)) == PLUS
4948 && REG_P (XEXP (XEXP (x
,0), 0))
4949 && GET_CODE (XEXP (XEXP (x
,0), 1)) == CONST_INT
4950 && (INTVAL (XEXP (XEXP (x
,0), 1))
4951 <= MAX_LD_OFFSET (GET_MODE (x
))))
4953 rtx xx
= XEXP (XEXP (x
,0), 0);
4954 int regno
= REGNO (xx
);
4955 if (TARGET_ALL_DEBUG
)
4957 fprintf (stderr
, ("extra_constraint:\n"
4958 "reload_completed: %d\n"
4959 "reload_in_progress: %d\n"),
4960 reload_completed
, reload_in_progress
);
4963 if (regno
>= FIRST_PSEUDO_REGISTER
)
4964 return 1; /* allocate pseudos */
4965 else if (regno
== REG_Z
|| regno
== REG_Y
)
4966 return 1; /* strictly check */
4967 else if (xx
== frame_pointer_rtx
4968 || xx
== arg_pointer_rtx
)
4969 return 1; /* XXX frame & arg pointer checks */
4975 /* Convert condition code CONDITION to the valid AVR condition code */
4978 avr_normalize_condition (condition
)
4996 /* This fnction optimizes conditional jumps */
4999 machine_dependent_reorg (first_insn
)
5004 for (insn
= first_insn
; insn
; insn
= NEXT_INSN (insn
))
5006 if (! (GET_CODE (insn
) == INSN
5007 || GET_CODE (insn
) == CALL_INSN
5008 || GET_CODE (insn
) == JUMP_INSN
)
5009 || !single_set (insn
))
5012 pattern
= PATTERN (insn
);
5014 if (GET_CODE (pattern
) == PARALLEL
)
5015 pattern
= XVECEXP (pattern
, 0, 0);
5016 if (GET_CODE (pattern
) == SET
5017 && SET_DEST (pattern
) == cc0_rtx
5018 && compare_diff_p (insn
))
5020 if (GET_CODE (SET_SRC (pattern
)) == COMPARE
)
5022 /* Now we work under compare insn */
5024 pattern
= SET_SRC (pattern
);
5025 if (true_regnum (XEXP (pattern
,0)) >= 0
5026 && true_regnum (XEXP (pattern
,1)) >= 0 )
5028 rtx x
= XEXP (pattern
,0);
5029 rtx next
= next_real_insn (insn
);
5030 rtx pat
= PATTERN (next
);
5031 rtx src
= SET_SRC (pat
);
5032 rtx t
= XEXP (src
,0);
5033 PUT_CODE (t
, swap_condition (GET_CODE (t
)));
5034 XEXP (pattern
,0) = XEXP (pattern
,1);
5035 XEXP (pattern
,1) = x
;
5036 INSN_CODE (next
) = -1;
5038 else if (true_regnum (XEXP (pattern
,0)) >= 0
5039 && GET_CODE (XEXP (pattern
,1)) == CONST_INT
)
5041 rtx x
= XEXP (pattern
,1);
5042 rtx next
= next_real_insn (insn
);
5043 rtx pat
= PATTERN (next
);
5044 rtx src
= SET_SRC (pat
);
5045 rtx t
= XEXP (src
,0);
5047 if (avr_simplify_comparision_p (GET_MODE (XEXP (pattern
,0)),
5050 XEXP (pattern
,1) = GEN_INT (INTVAL (x
)+1);
5051 PUT_CODE (t
, avr_normalize_condition (GET_CODE (t
)));
5052 INSN_CODE (next
) = -1;
5053 INSN_CODE (insn
) = -1;
5057 else if (true_regnum (SET_SRC (pattern
)) >= 0)
5059 /* This is a tst insn */
5060 rtx next
= next_real_insn (insn
);
5061 rtx pat
= PATTERN (next
);
5062 rtx src
= SET_SRC (pat
);
5063 rtx t
= XEXP (src
,0);
5065 PUT_CODE (t
, swap_condition (GET_CODE (t
)));
5066 SET_SRC (pattern
) = gen_rtx (NEG
,
5067 GET_MODE (SET_SRC (pattern
)),
5069 INSN_CODE (next
) = -1;
5070 INSN_CODE (insn
) = -1;
5076 /* Returns register number for function return value.*/
5084 /* Ceate an RTX representing the place where a
5085 library function returns a value of mode MODE. */
5088 avr_libcall_value (mode
)
5089 enum machine_mode mode
;
5091 int offs
= GET_MODE_SIZE (mode
);
5094 return gen_rtx (REG
, mode
, RET_REGISTER
+ 2 - offs
);
5097 /* Create an RTX representing the place where a
5098 function returns a value of data type VALTYPE. */
5101 avr_function_value (type
, func
)
5103 tree func ATTRIBUTE_UNUSED
;
5107 if (TYPE_MODE (type
) != BLKmode
)
5108 return avr_libcall_value (TYPE_MODE (type
));
5110 offs
= int_size_in_bytes (type
);
5113 if (offs
> 2 && offs
< GET_MODE_SIZE (SImode
))
5114 offs
= GET_MODE_SIZE (SImode
);
5115 else if (offs
> GET_MODE_SIZE (SImode
) && offs
< GET_MODE_SIZE (DImode
))
5116 offs
= GET_MODE_SIZE (DImode
);
5118 return gen_rtx (REG
, BLKmode
, RET_REGISTER
+ 2 - offs
);
5121 /* Returns non-zero if the number MASK has only one bit set. */
5124 mask_one_bit_p (mask
)
5128 unsigned HOST_WIDE_INT n
=mask
;
5129 for (i
= 0; i
< 32; ++i
)
5131 if (n
& 0x80000000L
)
5133 if (n
& 0x7fffffffL
)
5144 /* Places additional restrictions on the register class to
5145 use when it is necessary to copy value X into a register
5149 preferred_reload_class (x
, class)
5150 rtx x ATTRIBUTE_UNUSED
;
5151 enum reg_class
class;
5157 test_hard_reg_class (class, x
)
5158 enum reg_class
class;
5161 int regno
= true_regnum (x
);
5164 return TEST_HARD_REG_CLASS (class, regno
);
5168 debug_hard_reg_set (set
)
5172 for (i
=0; i
< FIRST_PSEUDO_REGISTER
; ++i
)
5174 if (TEST_HARD_REG_BIT (set
, i
))
5176 fprintf (stderr
, "r%-2d ", i
);
5179 fprintf (stderr
, "\n");
5183 jump_over_one_insn_p (insn
, dest
)
5187 int uid
= INSN_UID (GET_CODE (dest
) == LABEL_REF
5190 int jump_addr
= INSN_ADDRESSES (INSN_UID (insn
));
5191 int dest_addr
= INSN_ADDRESSES (uid
);
5192 return dest_addr
- jump_addr
== 2;
5195 /* Returns 1 if a value of mode MODE can be stored starting with hard
5196 register number REGNO. On the enhanced core, anything larger than
5197 1 byte must start in even numbered register for "movw" to work
5198 (this way we don't have to check for odd registers everywhere). */
5201 avr_hard_regno_mode_ok (regno
, mode
)
5203 enum machine_mode mode
;
5207 /* if (regno < 24 && !AVR_ENHANCED)
5209 return !(regno
& 1);
5212 /* Returns 1 if we know register operand OP was 0 before INSN. */
5215 reg_was_0 (insn
, op
)
5220 return (optimize
> 0 && insn
&& op
&& REG_P (op
)
5221 && (link
= find_reg_note (insn
, REG_WAS_0
, 0))
5222 /* Make sure the insn that stored the 0 is still present. */
5223 && ! INSN_DELETED_P (XEXP (link
, 0))
5224 && GET_CODE (XEXP (link
, 0)) != NOTE
5225 /* Make sure cross jumping didn't happen here. */
5226 && no_labels_between_p (XEXP (link
, 0), insn
)
5227 /* Make sure the reg hasn't been clobbered. */
5228 && ! reg_set_between_p (op
, XEXP (link
, 0), insn
));
5231 /* Returns 1 if X is a valid address for an I/O register of size SIZE
5232 (1 or 2). Used for lds/sts -> in/out optimization. */
5235 io_address_p (x
, size
)
5239 return (optimize
> 0 && GET_CODE (x
) == CONST_INT
5240 && INTVAL (x
) >= 0x20 && INTVAL (x
) <= 0x60 - size
);
5243 /* Returns nonzero (bit number + 1) if X, or -X, is a constant power of 2. */
5246 const_int_pow2_p (x
)
5249 if (GET_CODE (x
) == CONST_INT
)
5251 HOST_WIDE_INT d
= INTVAL (x
);
5252 HOST_WIDE_INT abs_d
= (d
>= 0) ? d
: -d
;
5253 return exact_log2 (abs_d
) + 1;
5259 output_reload_inhi (insn
, operands
, len
)
5260 rtx insn ATTRIBUTE_UNUSED
;
5268 if (GET_CODE (operands
[1]) == CONST_INT
)
5270 int val
= INTVAL (operands
[1]);
5271 if ((val
& 0xff) == 0)
5274 return (AS2 (mov
,%A0
,__zero_reg__
) CR_TAB
5275 AS2 (ldi
,%2,hi8(%1)) CR_TAB
5278 else if ((val
& 0xff00) == 0)
5281 return (AS2 (ldi
,%2,lo8(%1)) CR_TAB
5282 AS2 (mov
,%A0
,%2) CR_TAB
5283 AS2 (mov
,%B0
,__zero_reg__
));
5285 else if ((val
& 0xff) == ((val
& 0xff00) >> 8))
5288 return (AS2 (ldi
,%2,lo8(%1)) CR_TAB
5289 AS2 (mov
,%A0
,%2) CR_TAB
5294 return (AS2 (ldi
,%2,lo8(%1)) CR_TAB
5295 AS2 (mov
,%A0
,%2) CR_TAB
5296 AS2 (ldi
,%2,hi8(%1)) CR_TAB
5302 output_reload_insisf (insn
, operands
, len
)
5303 rtx insn ATTRIBUTE_UNUSED
;
5307 rtx src
= operands
[1];
5308 int cnst
= (GET_CODE (src
) == CONST_INT
);
5313 *len
= 4 + ((INTVAL (src
) & 0xff) != 0)
5314 + ((INTVAL (src
) & 0xff00) != 0)
5315 + ((INTVAL (src
) & 0xff0000) != 0)
5316 + ((INTVAL (src
) & 0xff000000) != 0);
5323 if (cnst
&& ((INTVAL (src
) & 0xff) == 0))
5324 output_asm_insn (AS2 (mov
, %A0
, __zero_reg__
), operands
);
5327 output_asm_insn (AS2 (ldi
, %2, lo8(%1)), operands
);
5328 output_asm_insn (AS2 (mov
, %A0
, %2), operands
);
5330 if (cnst
&& ((INTVAL (src
) & 0xff00) == 0))
5331 output_asm_insn (AS2 (mov
, %B0
, __zero_reg__
), operands
);
5334 output_asm_insn (AS2 (ldi
, %2, hi8(%1)), operands
);
5335 output_asm_insn (AS2 (mov
, %B0
, %2), operands
);
5337 if (cnst
&& ((INTVAL (src
) & 0xff0000) == 0))
5338 output_asm_insn (AS2 (mov
, %C0
, __zero_reg__
), operands
);
5341 output_asm_insn (AS2 (ldi
, %2, hlo8(%1)), operands
);
5342 output_asm_insn (AS2 (mov
, %C0
, %2), operands
);
5344 if (cnst
&& ((INTVAL (src
) & 0xff000000) == 0))
5345 output_asm_insn (AS2 (mov
, %D0
, __zero_reg__
), operands
);
5348 output_asm_insn (AS2 (ldi
, %2, hhi8(%1)), operands
);
5349 output_asm_insn (AS2 (mov
, %D0
, %2), operands
);
5355 avr_output_bld (operands
, bit_nr
)
5359 static char s
[] = "bld %A0,0";
5361 s
[5] = 'A' + (bit_nr
>> 3);
5362 s
[8] = '0' + (bit_nr
& 7);
5363 output_asm_insn (s
, operands
);
5367 avr_output_addr_vec_elt (stream
, value
)
5372 fprintf (stream
, "\t.word pm(.L%d)\n", value
);
5374 fprintf (stream
, "\trjmp .L%d\n", value
);
5379 /* Returns 1 if SCRATCH are safe to be allocated as a scratch
5380 registers (for a define_peephole2) in the current function. */
5383 avr_peep2_scratch_safe (scratch
)
5386 if ((interrupt_function_p (current_function_decl
)
5387 || signal_function_p (current_function_decl
))
5388 && leaf_function_p ())
5390 int first_reg
= true_regnum (scratch
);
5391 int last_reg
= first_reg
+ GET_MODE_SIZE (GET_MODE (scratch
)) - 1;
5394 for (reg
= first_reg
; reg
<= last_reg
; reg
++)
5396 if (!regs_ever_live
[reg
])