gcc/ChangeLog
[official-gcc.git] / gcc / config / avr / avr.c
blob9f5bc88ce308deff6647d3d80af58b94b58d31ec
1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2 Copyright (C) 1998-2015 Free Software Foundation, Inc.
3 Contributed by Denis Chertykov (chertykov@gmail.com)
5 This file is part of GCC.
7 GCC 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 3, or (at your option)
10 any later version.
12 GCC 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 GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "backend.h"
25 #include "cfghooks.h"
26 #include "tree.h"
27 #include "rtl.h"
28 #include "df.h"
29 #include "regs.h"
30 #include "insn-config.h"
31 #include "conditions.h"
32 #include "insn-attr.h"
33 #include "insn-codes.h"
34 #include "flags.h"
35 #include "reload.h"
36 #include "alias.h"
37 #include "fold-const.h"
38 #include "varasm.h"
39 #include "print-tree.h"
40 #include "calls.h"
41 #include "stor-layout.h"
42 #include "stringpool.h"
43 #include "output.h"
44 #include "expmed.h"
45 #include "dojump.h"
46 #include "explow.h"
47 #include "emit-rtl.h"
48 #include "stmt.h"
49 #include "expr.h"
50 #include "c-family/c-common.h"
51 #include "diagnostic-core.h"
52 #include "recog.h"
53 #include "optabs.h"
54 #include "langhooks.h"
55 #include "tm_p.h"
56 #include "target.h"
57 #include "params.h"
58 #include "cfgrtl.h"
59 #include "cfganal.h"
60 #include "lcm.h"
61 #include "cfgbuild.h"
62 #include "cfgcleanup.h"
63 #include "builtins.h"
64 #include "context.h"
65 #include "tree-pass.h"
67 /* This file should be included last. */
68 #include "target-def.h"
70 /* Maximal allowed offset for an address in the LD command */
71 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
73 /* Return true if STR starts with PREFIX and false, otherwise. */
74 #define STR_PREFIX_P(STR,PREFIX) (0 == strncmp (STR, PREFIX, strlen (PREFIX)))
76 /* The 4 bits starting at SECTION_MACH_DEP are reserved to store the
77 address space where data is to be located.
78 As the only non-generic address spaces are all located in flash,
79 this can be used to test if data shall go into some .progmem* section.
80 This must be the rightmost field of machine dependent section flags. */
81 #define AVR_SECTION_PROGMEM (0xf * SECTION_MACH_DEP)
83 /* Similar 4-bit region for SYMBOL_REF_FLAGS. */
84 #define AVR_SYMBOL_FLAG_PROGMEM (0xf * SYMBOL_FLAG_MACH_DEP)
86 /* Similar 4-bit region in SYMBOL_REF_FLAGS:
87 Set address-space AS in SYMBOL_REF_FLAGS of SYM */
88 #define AVR_SYMBOL_SET_ADDR_SPACE(SYM,AS) \
89 do { \
90 SYMBOL_REF_FLAGS (sym) &= ~AVR_SYMBOL_FLAG_PROGMEM; \
91 SYMBOL_REF_FLAGS (sym) |= (AS) * SYMBOL_FLAG_MACH_DEP; \
92 } while (0)
94 /* Read address-space from SYMBOL_REF_FLAGS of SYM */
95 #define AVR_SYMBOL_GET_ADDR_SPACE(SYM) \
96 ((SYMBOL_REF_FLAGS (sym) & AVR_SYMBOL_FLAG_PROGMEM) \
97 / SYMBOL_FLAG_MACH_DEP)
99 #define TINY_ADIW(REG1, REG2, I) \
100 "subi " #REG1 ",lo8(-(" #I "))" CR_TAB \
101 "sbci " #REG2 ",hi8(-(" #I "))"
103 #define TINY_SBIW(REG1, REG2, I) \
104 "subi " #REG1 ",lo8((" #I "))" CR_TAB \
105 "sbci " #REG2 ",hi8((" #I "))"
107 #define AVR_TMP_REGNO (AVR_TINY ? TMP_REGNO_TINY : TMP_REGNO)
108 #define AVR_ZERO_REGNO (AVR_TINY ? ZERO_REGNO_TINY : ZERO_REGNO)
110 /* Known address spaces. The order must be the same as in the respective
111 enum from avr.h (or designated initialized must be used). */
112 const avr_addrspace_t avr_addrspace[ADDR_SPACE_COUNT] =
114 { ADDR_SPACE_RAM, 0, 2, "", 0, NULL },
115 { ADDR_SPACE_FLASH, 1, 2, "__flash", 0, ".progmem.data" },
116 { ADDR_SPACE_FLASH1, 1, 2, "__flash1", 1, ".progmem1.data" },
117 { ADDR_SPACE_FLASH2, 1, 2, "__flash2", 2, ".progmem2.data" },
118 { ADDR_SPACE_FLASH3, 1, 2, "__flash3", 3, ".progmem3.data" },
119 { ADDR_SPACE_FLASH4, 1, 2, "__flash4", 4, ".progmem4.data" },
120 { ADDR_SPACE_FLASH5, 1, 2, "__flash5", 5, ".progmem5.data" },
121 { ADDR_SPACE_MEMX, 1, 3, "__memx", 0, ".progmemx.data" },
125 /* Holding RAM addresses of some SFRs used by the compiler and that
126 are unique over all devices in an architecture like 'avr4'. */
128 typedef struct
130 /* SREG: The processor status */
131 int sreg;
133 /* RAMPX, RAMPY, RAMPD and CCP of XMEGA */
134 int ccp;
135 int rampd;
136 int rampx;
137 int rampy;
139 /* RAMPZ: The high byte of 24-bit address used with ELPM */
140 int rampz;
142 /* SP: The stack pointer and its low and high byte */
143 int sp_l;
144 int sp_h;
145 } avr_addr_t;
147 static avr_addr_t avr_addr;
150 /* Prototypes for local helper functions. */
152 static const char* out_movqi_r_mr (rtx_insn *, rtx[], int*);
153 static const char* out_movhi_r_mr (rtx_insn *, rtx[], int*);
154 static const char* out_movsi_r_mr (rtx_insn *, rtx[], int*);
155 static const char* out_movqi_mr_r (rtx_insn *, rtx[], int*);
156 static const char* out_movhi_mr_r (rtx_insn *, rtx[], int*);
157 static const char* out_movsi_mr_r (rtx_insn *, rtx[], int*);
159 static int get_sequence_length (rtx_insn *insns);
160 static int sequent_regs_live (void);
161 static const char *ptrreg_to_str (int);
162 static const char *cond_string (enum rtx_code);
163 static int avr_num_arg_regs (machine_mode, const_tree);
164 static int avr_operand_rtx_cost (rtx, machine_mode, enum rtx_code,
165 int, bool);
166 static void output_reload_in_const (rtx*, rtx, int*, bool);
167 static struct machine_function * avr_init_machine_status (void);
170 /* Prototypes for hook implementors if needed before their implementation. */
172 static bool avr_rtx_costs (rtx, machine_mode, int, int, int*, bool);
175 /* Allocate registers from r25 to r8 for parameters for function calls. */
176 #define FIRST_CUM_REG 26
178 /* Last call saved register */
179 #define LAST_CALLEE_SAVED_REG (AVR_TINY ? 19 : 17)
181 /* Implicit target register of LPM instruction (R0) */
182 extern GTY(()) rtx lpm_reg_rtx;
183 rtx lpm_reg_rtx;
185 /* (Implicit) address register of LPM instruction (R31:R30 = Z) */
186 extern GTY(()) rtx lpm_addr_reg_rtx;
187 rtx lpm_addr_reg_rtx;
189 /* Temporary register RTX (reg:QI TMP_REGNO) */
190 extern GTY(()) rtx tmp_reg_rtx;
191 rtx tmp_reg_rtx;
193 /* Zeroed register RTX (reg:QI ZERO_REGNO) */
194 extern GTY(()) rtx zero_reg_rtx;
195 rtx zero_reg_rtx;
197 /* RTXs for all general purpose registers as QImode */
198 extern GTY(()) rtx all_regs_rtx[32];
199 rtx all_regs_rtx[32];
201 /* SREG, the processor status */
202 extern GTY(()) rtx sreg_rtx;
203 rtx sreg_rtx;
205 /* RAMP* special function registers */
206 extern GTY(()) rtx rampd_rtx;
207 extern GTY(()) rtx rampx_rtx;
208 extern GTY(()) rtx rampy_rtx;
209 extern GTY(()) rtx rampz_rtx;
210 rtx rampd_rtx;
211 rtx rampx_rtx;
212 rtx rampy_rtx;
213 rtx rampz_rtx;
215 /* RTX containing the strings "" and "e", respectively */
216 static GTY(()) rtx xstring_empty;
217 static GTY(()) rtx xstring_e;
219 /* Current architecture. */
220 const avr_arch_t *avr_arch;
222 /* Section to put switch tables in. */
223 static GTY(()) section *progmem_swtable_section;
225 /* Unnamed sections associated to __attribute__((progmem)) aka. PROGMEM
226 or to address space __flash* or __memx. Only used as singletons inside
227 avr_asm_select_section, but it must not be local there because of GTY. */
228 static GTY(()) section *progmem_section[ADDR_SPACE_COUNT];
230 /* Condition for insns/expanders from avr-dimode.md. */
231 bool avr_have_dimode = true;
233 /* To track if code will use .bss and/or .data. */
234 bool avr_need_clear_bss_p = false;
235 bool avr_need_copy_data_p = false;
238 /* Transform UP into lowercase and write the result to LO.
239 You must provide enough space for LO. Return LO. */
241 static char*
242 avr_tolower (char *lo, const char *up)
244 char *lo0 = lo;
246 for (; *up; up++, lo++)
247 *lo = TOLOWER (*up);
249 *lo = '\0';
251 return lo0;
255 /* Custom function to count number of set bits. */
257 static inline int
258 avr_popcount (unsigned int val)
260 int pop = 0;
262 while (val)
264 val &= val-1;
265 pop++;
268 return pop;
272 /* Constraint helper function. XVAL is a CONST_INT or a CONST_DOUBLE.
273 Return true if the least significant N_BYTES bytes of XVAL all have a
274 popcount in POP_MASK and false, otherwise. POP_MASK represents a subset
275 of integers which contains an integer N iff bit N of POP_MASK is set. */
277 bool
278 avr_popcount_each_byte (rtx xval, int n_bytes, int pop_mask)
280 int i;
282 machine_mode mode = GET_MODE (xval);
284 if (VOIDmode == mode)
285 mode = SImode;
287 for (i = 0; i < n_bytes; i++)
289 rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
290 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
292 if (0 == (pop_mask & (1 << avr_popcount (val8))))
293 return false;
296 return true;
300 /* Access some RTX as INT_MODE. If X is a CONST_FIXED we can get
301 the bit representation of X by "casting" it to CONST_INT. */
304 avr_to_int_mode (rtx x)
306 machine_mode mode = GET_MODE (x);
308 return VOIDmode == mode
310 : simplify_gen_subreg (int_mode_for_mode (mode), x, mode, 0);
314 static const pass_data avr_pass_data_recompute_notes =
316 RTL_PASS, // type
317 "", // name (will be patched)
318 OPTGROUP_NONE, // optinfo_flags
319 TV_DF_SCAN, // tv_id
320 0, // properties_required
321 0, // properties_provided
322 0, // properties_destroyed
323 0, // todo_flags_start
324 TODO_df_finish | TODO_df_verify // todo_flags_finish
328 class avr_pass_recompute_notes : public rtl_opt_pass
330 public:
331 avr_pass_recompute_notes (gcc::context *ctxt, const char *name)
332 : rtl_opt_pass (avr_pass_data_recompute_notes, ctxt)
334 this->name = name;
337 virtual unsigned int execute (function*)
339 df_note_add_problem ();
340 df_analyze ();
342 return 0;
344 }; // avr_pass_recompute_notes
347 static void
348 avr_register_passes (void)
350 /* This avr-specific pass (re)computes insn notes, in particular REG_DEAD
351 notes which are used by `avr.c::reg_unused_after' and branch offset
352 computations. These notes must be correct, i.e. there must be no
353 dangling REG_DEAD notes; otherwise wrong code might result, cf. PR64331.
355 DF needs (correct) CFG, hence right before free_cfg is the last
356 opportunity to rectify notes. */
358 register_pass (new avr_pass_recompute_notes (g, "avr-notes-free-cfg"),
359 PASS_POS_INSERT_BEFORE, "*free_cfg", 1);
363 /* Set `avr_arch' as specified by `-mmcu='.
364 Return true on success. */
366 static bool
367 avr_set_core_architecture (void)
369 /* Search for mcu core architecture. */
371 if (!avr_mmcu)
372 avr_mmcu = AVR_MMCU_DEFAULT;
374 avr_arch = &avr_arch_types[0];
376 for (const avr_mcu_t *mcu = avr_mcu_types; ; mcu++)
378 if (NULL == mcu->name)
380 /* Reached the end of `avr_mcu_types'. This should actually never
381 happen as options are provided by device-specs. It could be a
382 typo in a device-specs or calling the compiler proper directly
383 with -mmcu=<device>. */
385 error ("unknown core architecture %qs specified with %qs",
386 avr_mmcu, "-mmcu=");
387 avr_inform_core_architectures ();
388 break;
390 else if (0 == strcmp (mcu->name, avr_mmcu)
391 // Is this a proper architecture ?
392 && NULL == mcu->macro)
394 avr_arch = &avr_arch_types[mcu->arch_id];
395 if (avr_n_flash < 0)
396 avr_n_flash = mcu->n_flash;
398 return true;
402 return false;
406 /* Implement `TARGET_OPTION_OVERRIDE'. */
408 static void
409 avr_option_override (void)
411 /* Disable -fdelete-null-pointer-checks option for AVR target.
412 This option compiler assumes that dereferencing of a null pointer
413 would halt the program. For AVR this assumption is not true and
414 programs can safely dereference null pointers. Changes made by this
415 option may not work properly for AVR. So disable this option. */
417 flag_delete_null_pointer_checks = 0;
419 /* caller-save.c looks for call-clobbered hard registers that are assigned
420 to pseudos that cross calls and tries so save-restore them around calls
421 in order to reduce the number of stack slots needed.
423 This might lead to situations where reload is no more able to cope
424 with the challenge of AVR's very few address registers and fails to
425 perform the requested spills. */
427 if (avr_strict_X)
428 flag_caller_saves = 0;
430 /* Unwind tables currently require a frame pointer for correctness,
431 see toplev.c:process_options(). */
433 if ((flag_unwind_tables
434 || flag_non_call_exceptions
435 || flag_asynchronous_unwind_tables)
436 && !ACCUMULATE_OUTGOING_ARGS)
438 flag_omit_frame_pointer = 0;
441 if (flag_pic == 1)
442 warning (OPT_fpic, "-fpic is not supported");
443 if (flag_pic == 2)
444 warning (OPT_fPIC, "-fPIC is not supported");
445 if (flag_pie == 1)
446 warning (OPT_fpie, "-fpie is not supported");
447 if (flag_pie == 2)
448 warning (OPT_fPIE, "-fPIE is not supported");
450 if (!avr_set_core_architecture())
451 return;
453 /* RAM addresses of some SFRs common to all devices in respective arch. */
455 /* SREG: Status Register containing flags like I (global IRQ) */
456 avr_addr.sreg = 0x3F + avr_arch->sfr_offset;
458 /* RAMPZ: Address' high part when loading via ELPM */
459 avr_addr.rampz = 0x3B + avr_arch->sfr_offset;
461 avr_addr.rampy = 0x3A + avr_arch->sfr_offset;
462 avr_addr.rampx = 0x39 + avr_arch->sfr_offset;
463 avr_addr.rampd = 0x38 + avr_arch->sfr_offset;
464 avr_addr.ccp = (AVR_TINY ? 0x3C : 0x34) + avr_arch->sfr_offset;
466 /* SP: Stack Pointer (SP_H:SP_L) */
467 avr_addr.sp_l = 0x3D + avr_arch->sfr_offset;
468 avr_addr.sp_h = avr_addr.sp_l + 1;
470 init_machine_status = avr_init_machine_status;
472 avr_log_set_avr_log();
474 /* Register some avr-specific pass(es). There is no canonical place for
475 pass registration. This function is convenient. */
477 avr_register_passes ();
480 /* Function to set up the backend function structure. */
482 static struct machine_function *
483 avr_init_machine_status (void)
485 return ggc_cleared_alloc<machine_function> ();
489 /* Implement `INIT_EXPANDERS'. */
490 /* The function works like a singleton. */
492 void
493 avr_init_expanders (void)
495 int regno;
497 for (regno = 0; regno < 32; regno ++)
498 all_regs_rtx[regno] = gen_rtx_REG (QImode, regno);
500 lpm_reg_rtx = all_regs_rtx[LPM_REGNO];
501 tmp_reg_rtx = all_regs_rtx[AVR_TMP_REGNO];
502 zero_reg_rtx = all_regs_rtx[AVR_ZERO_REGNO];
504 lpm_addr_reg_rtx = gen_rtx_REG (HImode, REG_Z);
506 sreg_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.sreg));
507 rampd_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampd));
508 rampx_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampx));
509 rampy_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampy));
510 rampz_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampz));
512 xstring_empty = gen_rtx_CONST_STRING (VOIDmode, "");
513 xstring_e = gen_rtx_CONST_STRING (VOIDmode, "e");
515 /* TINY core does not have regs r10-r16, but avr-dimode.md expects them
516 to be present */
517 if (AVR_TINY)
518 avr_have_dimode = false;
522 /* Implement `REGNO_REG_CLASS'. */
523 /* Return register class for register R. */
525 enum reg_class
526 avr_regno_reg_class (int r)
528 static const enum reg_class reg_class_tab[] =
530 R0_REG,
531 /* r1 - r15 */
532 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
533 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
534 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
535 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
536 /* r16 - r23 */
537 SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
538 SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
539 /* r24, r25 */
540 ADDW_REGS, ADDW_REGS,
541 /* X: r26, 27 */
542 POINTER_X_REGS, POINTER_X_REGS,
543 /* Y: r28, r29 */
544 POINTER_Y_REGS, POINTER_Y_REGS,
545 /* Z: r30, r31 */
546 POINTER_Z_REGS, POINTER_Z_REGS,
547 /* SP: SPL, SPH */
548 STACK_REG, STACK_REG
551 if (r <= 33)
552 return reg_class_tab[r];
554 return ALL_REGS;
558 /* Implement `TARGET_SCALAR_MODE_SUPPORTED_P'. */
560 static bool
561 avr_scalar_mode_supported_p (machine_mode mode)
563 if (ALL_FIXED_POINT_MODE_P (mode))
564 return true;
566 if (PSImode == mode)
567 return true;
569 return default_scalar_mode_supported_p (mode);
573 /* Return TRUE if DECL is a VAR_DECL located in flash and FALSE, otherwise. */
575 static bool
576 avr_decl_flash_p (tree decl)
578 if (TREE_CODE (decl) != VAR_DECL
579 || TREE_TYPE (decl) == error_mark_node)
581 return false;
584 return !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (decl)));
588 /* Return TRUE if DECL is a VAR_DECL located in the 24-bit flash
589 address space and FALSE, otherwise. */
591 static bool
592 avr_decl_memx_p (tree decl)
594 if (TREE_CODE (decl) != VAR_DECL
595 || TREE_TYPE (decl) == error_mark_node)
597 return false;
600 return (ADDR_SPACE_MEMX == TYPE_ADDR_SPACE (TREE_TYPE (decl)));
604 /* Return TRUE if X is a MEM rtx located in flash and FALSE, otherwise. */
606 bool
607 avr_mem_flash_p (rtx x)
609 return (MEM_P (x)
610 && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x)));
614 /* Return TRUE if X is a MEM rtx located in the 24-bit flash
615 address space and FALSE, otherwise. */
617 bool
618 avr_mem_memx_p (rtx x)
620 return (MEM_P (x)
621 && ADDR_SPACE_MEMX == MEM_ADDR_SPACE (x));
625 /* A helper for the subsequent function attribute used to dig for
626 attribute 'name' in a FUNCTION_DECL or FUNCTION_TYPE */
628 static inline int
629 avr_lookup_function_attribute1 (const_tree func, const char *name)
631 if (FUNCTION_DECL == TREE_CODE (func))
633 if (NULL_TREE != lookup_attribute (name, DECL_ATTRIBUTES (func)))
635 return true;
638 func = TREE_TYPE (func);
641 gcc_assert (TREE_CODE (func) == FUNCTION_TYPE
642 || TREE_CODE (func) == METHOD_TYPE);
644 return NULL_TREE != lookup_attribute (name, TYPE_ATTRIBUTES (func));
647 /* Return nonzero if FUNC is a naked function. */
649 static int
650 avr_naked_function_p (tree func)
652 return avr_lookup_function_attribute1 (func, "naked");
655 /* Return nonzero if FUNC is an interrupt function as specified
656 by the "interrupt" attribute. */
658 static int
659 avr_interrupt_function_p (tree func)
661 return avr_lookup_function_attribute1 (func, "interrupt");
664 /* Return nonzero if FUNC is a signal function as specified
665 by the "signal" attribute. */
667 static int
668 avr_signal_function_p (tree func)
670 return avr_lookup_function_attribute1 (func, "signal");
673 /* Return nonzero if FUNC is an OS_task function. */
675 static int
676 avr_OS_task_function_p (tree func)
678 return avr_lookup_function_attribute1 (func, "OS_task");
681 /* Return nonzero if FUNC is an OS_main function. */
683 static int
684 avr_OS_main_function_p (tree func)
686 return avr_lookup_function_attribute1 (func, "OS_main");
690 /* Implement `TARGET_SET_CURRENT_FUNCTION'. */
691 /* Sanity cheching for above function attributes. */
693 static void
694 avr_set_current_function (tree decl)
696 location_t loc;
697 const char *isr;
699 if (decl == NULL_TREE
700 || current_function_decl == NULL_TREE
701 || current_function_decl == error_mark_node
702 || ! cfun->machine
703 || cfun->machine->attributes_checked_p)
704 return;
706 loc = DECL_SOURCE_LOCATION (decl);
708 cfun->machine->is_naked = avr_naked_function_p (decl);
709 cfun->machine->is_signal = avr_signal_function_p (decl);
710 cfun->machine->is_interrupt = avr_interrupt_function_p (decl);
711 cfun->machine->is_OS_task = avr_OS_task_function_p (decl);
712 cfun->machine->is_OS_main = avr_OS_main_function_p (decl);
714 isr = cfun->machine->is_interrupt ? "interrupt" : "signal";
716 /* Too much attributes make no sense as they request conflicting features. */
718 if (cfun->machine->is_OS_task + cfun->machine->is_OS_main
719 + (cfun->machine->is_signal || cfun->machine->is_interrupt) > 1)
720 error_at (loc, "function attributes %qs, %qs and %qs are mutually"
721 " exclusive", "OS_task", "OS_main", isr);
723 /* 'naked' will hide effects of 'OS_task' and 'OS_main'. */
725 if (cfun->machine->is_naked
726 && (cfun->machine->is_OS_task || cfun->machine->is_OS_main))
727 warning_at (loc, OPT_Wattributes, "function attributes %qs and %qs have"
728 " no effect on %qs function", "OS_task", "OS_main", "naked");
730 if (cfun->machine->is_interrupt || cfun->machine->is_signal)
732 tree args = TYPE_ARG_TYPES (TREE_TYPE (decl));
733 tree ret = TREE_TYPE (TREE_TYPE (decl));
734 const char *name;
736 name = DECL_ASSEMBLER_NAME_SET_P (decl)
737 ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))
738 : IDENTIFIER_POINTER (DECL_NAME (decl));
740 /* Skip a leading '*' that might still prefix the assembler name,
741 e.g. in non-LTO runs. */
743 name = default_strip_name_encoding (name);
745 /* Silently ignore 'signal' if 'interrupt' is present. AVR-LibC startet
746 using this when it switched from SIGNAL and INTERRUPT to ISR. */
748 if (cfun->machine->is_interrupt)
749 cfun->machine->is_signal = 0;
751 /* Interrupt handlers must be void __vector (void) functions. */
753 if (args && TREE_CODE (TREE_VALUE (args)) != VOID_TYPE)
754 error_at (loc, "%qs function cannot have arguments", isr);
756 if (TREE_CODE (ret) != VOID_TYPE)
757 error_at (loc, "%qs function cannot return a value", isr);
759 /* If the function has the 'signal' or 'interrupt' attribute, ensure
760 that the name of the function is "__vector_NN" so as to catch
761 when the user misspells the vector name. */
763 if (!STR_PREFIX_P (name, "__vector"))
764 warning_at (loc, 0, "%qs appears to be a misspelled %s handler",
765 name, isr);
768 /* Don't print the above diagnostics more than once. */
770 cfun->machine->attributes_checked_p = 1;
774 /* Implement `ACCUMULATE_OUTGOING_ARGS'. */
777 avr_accumulate_outgoing_args (void)
779 if (!cfun)
780 return TARGET_ACCUMULATE_OUTGOING_ARGS;
782 /* FIXME: For setjmp and in avr_builtin_setjmp_frame_value we don't know
783 what offset is correct. In some cases it is relative to
784 virtual_outgoing_args_rtx and in others it is relative to
785 virtual_stack_vars_rtx. For example code see
786 gcc.c-torture/execute/built-in-setjmp.c
787 gcc.c-torture/execute/builtins/sprintf-chk.c */
789 return (TARGET_ACCUMULATE_OUTGOING_ARGS
790 && !(cfun->calls_setjmp
791 || cfun->has_nonlocal_label));
795 /* Report contribution of accumulated outgoing arguments to stack size. */
797 static inline int
798 avr_outgoing_args_size (void)
800 return ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0;
804 /* Implement `STARTING_FRAME_OFFSET'. */
805 /* This is the offset from the frame pointer register to the first stack slot
806 that contains a variable living in the frame. */
809 avr_starting_frame_offset (void)
811 return 1 + avr_outgoing_args_size ();
815 /* Return the number of hard registers to push/pop in the prologue/epilogue
816 of the current function, and optionally store these registers in SET. */
818 static int
819 avr_regs_to_save (HARD_REG_SET *set)
821 int reg, count;
822 int int_or_sig_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
824 if (set)
825 CLEAR_HARD_REG_SET (*set);
826 count = 0;
828 /* No need to save any registers if the function never returns or
829 has the "OS_task" or "OS_main" attribute. */
831 if (TREE_THIS_VOLATILE (current_function_decl)
832 || cfun->machine->is_OS_task
833 || cfun->machine->is_OS_main)
834 return 0;
836 for (reg = 0; reg < 32; reg++)
838 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
839 any global register variables. */
841 if (fixed_regs[reg])
842 continue;
844 if ((int_or_sig_p && !crtl->is_leaf && call_used_regs[reg])
845 || (df_regs_ever_live_p (reg)
846 && (int_or_sig_p || !call_used_regs[reg])
847 /* Don't record frame pointer registers here. They are treated
848 indivitually in prologue. */
849 && !(frame_pointer_needed
850 && (reg == REG_Y || reg == (REG_Y+1)))))
852 if (set)
853 SET_HARD_REG_BIT (*set, reg);
854 count++;
857 return count;
861 /* Implement `TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS' */
863 static bool
864 avr_allocate_stack_slots_for_args (void)
866 return !cfun->machine->is_naked;
870 /* Return true if register FROM can be eliminated via register TO. */
872 static bool
873 avr_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
875 return ((frame_pointer_needed && to == FRAME_POINTER_REGNUM)
876 || !frame_pointer_needed);
880 /* Implement `TARGET_WARN_FUNC_RETURN'. */
882 static bool
883 avr_warn_func_return (tree decl)
885 /* Naked functions are implemented entirely in assembly, including the
886 return sequence, so suppress warnings about this. */
888 return !avr_naked_function_p (decl);
891 /* Compute offset between arg_pointer and frame_pointer. */
894 avr_initial_elimination_offset (int from, int to)
896 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
897 return 0;
898 else
900 int offset = frame_pointer_needed ? 2 : 0;
901 int avr_pc_size = AVR_HAVE_EIJMP_EICALL ? 3 : 2;
903 offset += avr_regs_to_save (NULL);
904 return (get_frame_size () + avr_outgoing_args_size()
905 + avr_pc_size + 1 + offset);
910 /* Helper for the function below. */
912 static void
913 avr_adjust_type_node (tree *node, machine_mode mode, int sat_p)
915 *node = make_node (FIXED_POINT_TYPE);
916 TYPE_SATURATING (*node) = sat_p;
917 TYPE_UNSIGNED (*node) = UNSIGNED_FIXED_POINT_MODE_P (mode);
918 TYPE_IBIT (*node) = GET_MODE_IBIT (mode);
919 TYPE_FBIT (*node) = GET_MODE_FBIT (mode);
920 TYPE_PRECISION (*node) = GET_MODE_BITSIZE (mode);
921 TYPE_ALIGN (*node) = 8;
922 SET_TYPE_MODE (*node, mode);
924 layout_type (*node);
928 /* Implement `TARGET_BUILD_BUILTIN_VA_LIST'. */
930 static tree
931 avr_build_builtin_va_list (void)
933 /* avr-modes.def adjusts [U]TA to be 64-bit modes with 48 fractional bits.
934 This is more appropriate for the 8-bit machine AVR than 128-bit modes.
935 The ADJUST_IBIT/FBIT are handled in toplev:init_adjust_machine_modes()
936 which is auto-generated by genmodes, but the compiler assigns [U]DAmode
937 to the long long accum modes instead of the desired [U]TAmode.
939 Fix this now, right after node setup in tree.c:build_common_tree_nodes().
940 This must run before c-cppbuiltin.c:builtin_define_fixed_point_constants()
941 which built-in defines macros like __ULLACCUM_FBIT__ that are used by
942 libgcc to detect IBIT and FBIT. */
944 avr_adjust_type_node (&ta_type_node, TAmode, 0);
945 avr_adjust_type_node (&uta_type_node, UTAmode, 0);
946 avr_adjust_type_node (&sat_ta_type_node, TAmode, 1);
947 avr_adjust_type_node (&sat_uta_type_node, UTAmode, 1);
949 unsigned_long_long_accum_type_node = uta_type_node;
950 long_long_accum_type_node = ta_type_node;
951 sat_unsigned_long_long_accum_type_node = sat_uta_type_node;
952 sat_long_long_accum_type_node = sat_ta_type_node;
954 /* Dispatch to the default handler. */
956 return std_build_builtin_va_list ();
960 /* Implement `TARGET_BUILTIN_SETJMP_FRAME_VALUE'. */
961 /* Actual start of frame is virtual_stack_vars_rtx this is offset from
962 frame pointer by +STARTING_FRAME_OFFSET.
963 Using saved frame = virtual_stack_vars_rtx - STARTING_FRAME_OFFSET
964 avoids creating add/sub of offset in nonlocal goto and setjmp. */
966 static rtx
967 avr_builtin_setjmp_frame_value (void)
969 rtx xval = gen_reg_rtx (Pmode);
970 emit_insn (gen_subhi3 (xval, virtual_stack_vars_rtx,
971 gen_int_mode (STARTING_FRAME_OFFSET, Pmode)));
972 return xval;
976 /* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3-byte PC).
977 This is return address of function. */
980 avr_return_addr_rtx (int count, rtx tem)
982 rtx r;
984 /* Can only return this function's return address. Others not supported. */
985 if (count)
986 return NULL;
988 if (AVR_3_BYTE_PC)
990 r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+2");
991 warning (0, "%<builtin_return_address%> contains only 2 bytes"
992 " of address");
994 else
995 r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+1");
997 r = gen_rtx_PLUS (Pmode, tem, r);
998 r = gen_frame_mem (Pmode, memory_address (Pmode, r));
999 r = gen_rtx_ROTATE (HImode, r, GEN_INT (8));
1000 return r;
1003 /* Return 1 if the function epilogue is just a single "ret". */
1006 avr_simple_epilogue (void)
1008 return (! frame_pointer_needed
1009 && get_frame_size () == 0
1010 && avr_outgoing_args_size() == 0
1011 && avr_regs_to_save (NULL) == 0
1012 && ! cfun->machine->is_interrupt
1013 && ! cfun->machine->is_signal
1014 && ! cfun->machine->is_naked
1015 && ! TREE_THIS_VOLATILE (current_function_decl));
1018 /* This function checks sequence of live registers. */
1020 static int
1021 sequent_regs_live (void)
1023 int reg;
1024 int live_seq = 0;
1025 int cur_seq = 0;
1027 for (reg = 0; reg <= LAST_CALLEE_SAVED_REG; ++reg)
1029 if (fixed_regs[reg])
1031 /* Don't recognize sequences that contain global register
1032 variables. */
1034 if (live_seq != 0)
1035 return 0;
1036 else
1037 continue;
1040 if (!call_used_regs[reg])
1042 if (df_regs_ever_live_p (reg))
1044 ++live_seq;
1045 ++cur_seq;
1047 else
1048 cur_seq = 0;
1052 if (!frame_pointer_needed)
1054 if (df_regs_ever_live_p (REG_Y))
1056 ++live_seq;
1057 ++cur_seq;
1059 else
1060 cur_seq = 0;
1062 if (df_regs_ever_live_p (REG_Y+1))
1064 ++live_seq;
1065 ++cur_seq;
1067 else
1068 cur_seq = 0;
1070 else
1072 cur_seq += 2;
1073 live_seq += 2;
1075 return (cur_seq == live_seq) ? live_seq : 0;
1078 /* Obtain the length sequence of insns. */
1081 get_sequence_length (rtx_insn *insns)
1083 rtx_insn *insn;
1084 int length;
1086 for (insn = insns, length = 0; insn; insn = NEXT_INSN (insn))
1087 length += get_attr_length (insn);
1089 return length;
1093 /* Implement `INCOMING_RETURN_ADDR_RTX'. */
1096 avr_incoming_return_addr_rtx (void)
1098 /* The return address is at the top of the stack. Note that the push
1099 was via post-decrement, which means the actual address is off by one. */
1100 return gen_frame_mem (HImode, plus_constant (Pmode, stack_pointer_rtx, 1));
1103 /* Helper for expand_prologue. Emit a push of a byte register. */
1105 static void
1106 emit_push_byte (unsigned regno, bool frame_related_p)
1108 rtx mem, reg;
1109 rtx_insn *insn;
1111 mem = gen_rtx_POST_DEC (HImode, stack_pointer_rtx);
1112 mem = gen_frame_mem (QImode, mem);
1113 reg = gen_rtx_REG (QImode, regno);
1115 insn = emit_insn (gen_rtx_SET (mem, reg));
1116 if (frame_related_p)
1117 RTX_FRAME_RELATED_P (insn) = 1;
1119 cfun->machine->stack_usage++;
1123 /* Helper for expand_prologue. Emit a push of a SFR via tmp_reg.
1124 SFR is a MEM representing the memory location of the SFR.
1125 If CLR_P then clear the SFR after the push using zero_reg. */
1127 static void
1128 emit_push_sfr (rtx sfr, bool frame_related_p, bool clr_p)
1130 rtx_insn *insn;
1132 gcc_assert (MEM_P (sfr));
1134 /* IN __tmp_reg__, IO(SFR) */
1135 insn = emit_move_insn (tmp_reg_rtx, sfr);
1136 if (frame_related_p)
1137 RTX_FRAME_RELATED_P (insn) = 1;
1139 /* PUSH __tmp_reg__ */
1140 emit_push_byte (AVR_TMP_REGNO, frame_related_p);
1142 if (clr_p)
1144 /* OUT IO(SFR), __zero_reg__ */
1145 insn = emit_move_insn (sfr, const0_rtx);
1146 if (frame_related_p)
1147 RTX_FRAME_RELATED_P (insn) = 1;
1151 static void
1152 avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
1154 rtx_insn *insn;
1155 bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1156 int live_seq = sequent_regs_live ();
1158 HOST_WIDE_INT size_max
1159 = (HOST_WIDE_INT) GET_MODE_MASK (AVR_HAVE_8BIT_SP ? QImode : Pmode);
1161 bool minimize = (TARGET_CALL_PROLOGUES
1162 && size < size_max
1163 && live_seq
1164 && !isr_p
1165 && !cfun->machine->is_OS_task
1166 && !cfun->machine->is_OS_main
1167 && !AVR_TINY);
1169 if (minimize
1170 && (frame_pointer_needed
1171 || avr_outgoing_args_size() > 8
1172 || (AVR_2_BYTE_PC && live_seq > 6)
1173 || live_seq > 7))
1175 rtx pattern;
1176 int first_reg, reg, offset;
1178 emit_move_insn (gen_rtx_REG (HImode, REG_X),
1179 gen_int_mode (size, HImode));
1181 pattern = gen_call_prologue_saves (gen_int_mode (live_seq, HImode),
1182 gen_int_mode (live_seq+size, HImode));
1183 insn = emit_insn (pattern);
1184 RTX_FRAME_RELATED_P (insn) = 1;
1186 /* Describe the effect of the unspec_volatile call to prologue_saves.
1187 Note that this formulation assumes that add_reg_note pushes the
1188 notes to the front. Thus we build them in the reverse order of
1189 how we want dwarf2out to process them. */
1191 /* The function does always set frame_pointer_rtx, but whether that
1192 is going to be permanent in the function is frame_pointer_needed. */
1194 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1195 gen_rtx_SET ((frame_pointer_needed
1196 ? frame_pointer_rtx
1197 : stack_pointer_rtx),
1198 plus_constant (Pmode, stack_pointer_rtx,
1199 -(size + live_seq))));
1201 /* Note that live_seq always contains r28+r29, but the other
1202 registers to be saved are all below 18. */
1204 first_reg = (LAST_CALLEE_SAVED_REG + 1) - (live_seq - 2);
1206 for (reg = 29, offset = -live_seq + 1;
1207 reg >= first_reg;
1208 reg = (reg == 28 ? LAST_CALLEE_SAVED_REG : reg - 1), ++offset)
1210 rtx m, r;
1212 m = gen_rtx_MEM (QImode, plus_constant (Pmode, stack_pointer_rtx,
1213 offset));
1214 r = gen_rtx_REG (QImode, reg);
1215 add_reg_note (insn, REG_CFA_OFFSET, gen_rtx_SET (m, r));
1218 cfun->machine->stack_usage += size + live_seq;
1220 else /* !minimize */
1222 int reg;
1224 for (reg = 0; reg < 32; ++reg)
1225 if (TEST_HARD_REG_BIT (set, reg))
1226 emit_push_byte (reg, true);
1228 if (frame_pointer_needed
1229 && (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main)))
1231 /* Push frame pointer. Always be consistent about the
1232 ordering of pushes -- epilogue_restores expects the
1233 register pair to be pushed low byte first. */
1235 emit_push_byte (REG_Y, true);
1236 emit_push_byte (REG_Y + 1, true);
1239 if (frame_pointer_needed
1240 && size == 0)
1242 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
1243 RTX_FRAME_RELATED_P (insn) = 1;
1246 if (size != 0)
1248 /* Creating a frame can be done by direct manipulation of the
1249 stack or via the frame pointer. These two methods are:
1250 fp = sp
1251 fp -= size
1252 sp = fp
1254 sp -= size
1255 fp = sp (*)
1256 the optimum method depends on function type, stack and
1257 frame size. To avoid a complex logic, both methods are
1258 tested and shortest is selected.
1260 There is also the case where SIZE != 0 and no frame pointer is
1261 needed; this can occur if ACCUMULATE_OUTGOING_ARGS is on.
1262 In that case, insn (*) is not needed in that case.
1263 We use the X register as scratch. This is save because in X
1264 is call-clobbered.
1265 In an interrupt routine, the case of SIZE != 0 together with
1266 !frame_pointer_needed can only occur if the function is not a
1267 leaf function and thus X has already been saved. */
1269 int irq_state = -1;
1270 HOST_WIDE_INT size_cfa = size, neg_size;
1271 rtx_insn *fp_plus_insns;
1272 rtx fp, my_fp;
1274 gcc_assert (frame_pointer_needed
1275 || !isr_p
1276 || !crtl->is_leaf);
1278 fp = my_fp = (frame_pointer_needed
1279 ? frame_pointer_rtx
1280 : gen_rtx_REG (Pmode, REG_X));
1282 if (AVR_HAVE_8BIT_SP)
1284 /* The high byte (r29) does not change:
1285 Prefer SUBI (1 cycle) over SBIW (2 cycles, same size). */
1287 my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
1290 /* Cut down size and avoid size = 0 so that we don't run
1291 into ICE like PR52488 in the remainder. */
1293 if (size > size_max)
1295 /* Don't error so that insane code from newlib still compiles
1296 and does not break building newlib. As PR51345 is implemented
1297 now, there are multilib variants with -msp8.
1299 If user wants sanity checks he can use -Wstack-usage=
1300 or similar options.
1302 For CFA we emit the original, non-saturated size so that
1303 the generic machinery is aware of the real stack usage and
1304 will print the above diagnostic as expected. */
1306 size = size_max;
1309 size = trunc_int_for_mode (size, GET_MODE (my_fp));
1310 neg_size = trunc_int_for_mode (-size, GET_MODE (my_fp));
1312 /************ Method 1: Adjust frame pointer ************/
1314 start_sequence ();
1316 /* Normally, the dwarf2out frame-related-expr interpreter does
1317 not expect to have the CFA change once the frame pointer is
1318 set up. Thus, we avoid marking the move insn below and
1319 instead indicate that the entire operation is complete after
1320 the frame pointer subtraction is done. */
1322 insn = emit_move_insn (fp, stack_pointer_rtx);
1323 if (frame_pointer_needed)
1325 RTX_FRAME_RELATED_P (insn) = 1;
1326 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1327 gen_rtx_SET (fp, stack_pointer_rtx));
1330 insn = emit_move_insn (my_fp, plus_constant (GET_MODE (my_fp),
1331 my_fp, neg_size));
1333 if (frame_pointer_needed)
1335 RTX_FRAME_RELATED_P (insn) = 1;
1336 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1337 gen_rtx_SET (fp, plus_constant (Pmode, fp,
1338 -size_cfa)));
1341 /* Copy to stack pointer. Note that since we've already
1342 changed the CFA to the frame pointer this operation
1343 need not be annotated if frame pointer is needed.
1344 Always move through unspec, see PR50063.
1345 For meaning of irq_state see movhi_sp_r insn. */
1347 if (cfun->machine->is_interrupt)
1348 irq_state = 1;
1350 if (TARGET_NO_INTERRUPTS
1351 || cfun->machine->is_signal
1352 || cfun->machine->is_OS_main)
1353 irq_state = 0;
1355 if (AVR_HAVE_8BIT_SP)
1356 irq_state = 2;
1358 insn = emit_insn (gen_movhi_sp_r (stack_pointer_rtx,
1359 fp, GEN_INT (irq_state)));
1360 if (!frame_pointer_needed)
1362 RTX_FRAME_RELATED_P (insn) = 1;
1363 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1364 gen_rtx_SET (stack_pointer_rtx,
1365 plus_constant (Pmode,
1366 stack_pointer_rtx,
1367 -size_cfa)));
1370 fp_plus_insns = get_insns ();
1371 end_sequence ();
1373 /************ Method 2: Adjust Stack pointer ************/
1375 /* Stack adjustment by means of RCALL . and/or PUSH __TMP_REG__
1376 can only handle specific offsets. */
1378 if (avr_sp_immediate_operand (gen_int_mode (-size, HImode), HImode))
1380 rtx_insn *sp_plus_insns;
1382 start_sequence ();
1384 insn = emit_move_insn (stack_pointer_rtx,
1385 plus_constant (Pmode, stack_pointer_rtx,
1386 -size));
1387 RTX_FRAME_RELATED_P (insn) = 1;
1388 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1389 gen_rtx_SET (stack_pointer_rtx,
1390 plus_constant (Pmode,
1391 stack_pointer_rtx,
1392 -size_cfa)));
1393 if (frame_pointer_needed)
1395 insn = emit_move_insn (fp, stack_pointer_rtx);
1396 RTX_FRAME_RELATED_P (insn) = 1;
1399 sp_plus_insns = get_insns ();
1400 end_sequence ();
1402 /************ Use shortest method ************/
1404 emit_insn (get_sequence_length (sp_plus_insns)
1405 < get_sequence_length (fp_plus_insns)
1406 ? sp_plus_insns
1407 : fp_plus_insns);
1409 else
1411 emit_insn (fp_plus_insns);
1414 cfun->machine->stack_usage += size_cfa;
1415 } /* !minimize && size != 0 */
1416 } /* !minimize */
1420 /* Output function prologue. */
1422 void
1423 avr_expand_prologue (void)
1425 HARD_REG_SET set;
1426 HOST_WIDE_INT size;
1428 size = get_frame_size() + avr_outgoing_args_size();
1430 cfun->machine->stack_usage = 0;
1432 /* Prologue: naked. */
1433 if (cfun->machine->is_naked)
1435 return;
1438 avr_regs_to_save (&set);
1440 if (cfun->machine->is_interrupt || cfun->machine->is_signal)
1442 /* Enable interrupts. */
1443 if (cfun->machine->is_interrupt)
1444 emit_insn (gen_enable_interrupt ());
1446 /* Push zero reg. */
1447 emit_push_byte (AVR_ZERO_REGNO, true);
1449 /* Push tmp reg. */
1450 emit_push_byte (AVR_TMP_REGNO, true);
1452 /* Push SREG. */
1453 /* ??? There's no dwarf2 column reserved for SREG. */
1454 emit_push_sfr (sreg_rtx, false, false /* clr */);
1456 /* Clear zero reg. */
1457 emit_move_insn (zero_reg_rtx, const0_rtx);
1459 /* Prevent any attempt to delete the setting of ZERO_REG! */
1460 emit_use (zero_reg_rtx);
1462 /* Push and clear RAMPD/X/Y/Z if present and low-part register is used.
1463 ??? There are no dwarf2 columns reserved for RAMPD/X/Y/Z. */
1465 if (AVR_HAVE_RAMPD)
1466 emit_push_sfr (rampd_rtx, false /* frame-related */, true /* clr */);
1468 if (AVR_HAVE_RAMPX
1469 && TEST_HARD_REG_BIT (set, REG_X)
1470 && TEST_HARD_REG_BIT (set, REG_X + 1))
1472 emit_push_sfr (rampx_rtx, false /* frame-related */, true /* clr */);
1475 if (AVR_HAVE_RAMPY
1476 && (frame_pointer_needed
1477 || (TEST_HARD_REG_BIT (set, REG_Y)
1478 && TEST_HARD_REG_BIT (set, REG_Y + 1))))
1480 emit_push_sfr (rampy_rtx, false /* frame-related */, true /* clr */);
1483 if (AVR_HAVE_RAMPZ
1484 && TEST_HARD_REG_BIT (set, REG_Z)
1485 && TEST_HARD_REG_BIT (set, REG_Z + 1))
1487 emit_push_sfr (rampz_rtx, false /* frame-related */, AVR_HAVE_RAMPD);
1489 } /* is_interrupt is_signal */
1491 avr_prologue_setup_frame (size, set);
1493 if (flag_stack_usage_info)
1494 current_function_static_stack_size = cfun->machine->stack_usage;
1498 /* Implement `TARGET_ASM_FUNCTION_END_PROLOGUE'. */
1499 /* Output summary at end of function prologue. */
1501 static void
1502 avr_asm_function_end_prologue (FILE *file)
1504 if (cfun->machine->is_naked)
1506 fputs ("/* prologue: naked */\n", file);
1508 else
1510 if (cfun->machine->is_interrupt)
1512 fputs ("/* prologue: Interrupt */\n", file);
1514 else if (cfun->machine->is_signal)
1516 fputs ("/* prologue: Signal */\n", file);
1518 else
1519 fputs ("/* prologue: function */\n", file);
1522 if (ACCUMULATE_OUTGOING_ARGS)
1523 fprintf (file, "/* outgoing args size = %d */\n",
1524 avr_outgoing_args_size());
1526 fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n",
1527 get_frame_size());
1528 fprintf (file, "/* stack size = %d */\n",
1529 cfun->machine->stack_usage);
1530 /* Create symbol stack offset here so all functions have it. Add 1 to stack
1531 usage for offset so that SP + .L__stack_offset = return address. */
1532 fprintf (file, ".L__stack_usage = %d\n", cfun->machine->stack_usage);
1536 /* Implement `EPILOGUE_USES'. */
1539 avr_epilogue_uses (int regno ATTRIBUTE_UNUSED)
1541 if (reload_completed
1542 && cfun->machine
1543 && (cfun->machine->is_interrupt || cfun->machine->is_signal))
1544 return 1;
1545 return 0;
1548 /* Helper for avr_expand_epilogue. Emit a pop of a byte register. */
1550 static void
1551 emit_pop_byte (unsigned regno)
1553 rtx mem, reg;
1555 mem = gen_rtx_PRE_INC (HImode, stack_pointer_rtx);
1556 mem = gen_frame_mem (QImode, mem);
1557 reg = gen_rtx_REG (QImode, regno);
1559 emit_insn (gen_rtx_SET (reg, mem));
1562 /* Output RTL epilogue. */
1564 void
1565 avr_expand_epilogue (bool sibcall_p)
1567 int reg;
1568 int live_seq;
1569 HARD_REG_SET set;
1570 int minimize;
1571 HOST_WIDE_INT size;
1572 bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1574 size = get_frame_size() + avr_outgoing_args_size();
1576 /* epilogue: naked */
1577 if (cfun->machine->is_naked)
1579 gcc_assert (!sibcall_p);
1581 emit_jump_insn (gen_return ());
1582 return;
1585 avr_regs_to_save (&set);
1586 live_seq = sequent_regs_live ();
1588 minimize = (TARGET_CALL_PROLOGUES
1589 && live_seq
1590 && !isr_p
1591 && !cfun->machine->is_OS_task
1592 && !cfun->machine->is_OS_main
1593 && !AVR_TINY);
1595 if (minimize
1596 && (live_seq > 4
1597 || frame_pointer_needed
1598 || size))
1600 /* Get rid of frame. */
1602 if (!frame_pointer_needed)
1604 emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
1607 if (size)
1609 emit_move_insn (frame_pointer_rtx,
1610 plus_constant (Pmode, frame_pointer_rtx, size));
1613 emit_insn (gen_epilogue_restores (gen_int_mode (live_seq, HImode)));
1614 return;
1617 if (size)
1619 /* Try two methods to adjust stack and select shortest. */
1621 int irq_state = -1;
1622 rtx fp, my_fp;
1623 rtx_insn *fp_plus_insns;
1624 HOST_WIDE_INT size_max;
1626 gcc_assert (frame_pointer_needed
1627 || !isr_p
1628 || !crtl->is_leaf);
1630 fp = my_fp = (frame_pointer_needed
1631 ? frame_pointer_rtx
1632 : gen_rtx_REG (Pmode, REG_X));
1634 if (AVR_HAVE_8BIT_SP)
1636 /* The high byte (r29) does not change:
1637 Prefer SUBI (1 cycle) over SBIW (2 cycles). */
1639 my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
1642 /* For rationale see comment in prologue generation. */
1644 size_max = (HOST_WIDE_INT) GET_MODE_MASK (GET_MODE (my_fp));
1645 if (size > size_max)
1646 size = size_max;
1647 size = trunc_int_for_mode (size, GET_MODE (my_fp));
1649 /********** Method 1: Adjust fp register **********/
1651 start_sequence ();
1653 if (!frame_pointer_needed)
1654 emit_move_insn (fp, stack_pointer_rtx);
1656 emit_move_insn (my_fp, plus_constant (GET_MODE (my_fp), my_fp, size));
1658 /* Copy to stack pointer. */
1660 if (TARGET_NO_INTERRUPTS)
1661 irq_state = 0;
1663 if (AVR_HAVE_8BIT_SP)
1664 irq_state = 2;
1666 emit_insn (gen_movhi_sp_r (stack_pointer_rtx, fp,
1667 GEN_INT (irq_state)));
1669 fp_plus_insns = get_insns ();
1670 end_sequence ();
1672 /********** Method 2: Adjust Stack pointer **********/
1674 if (avr_sp_immediate_operand (gen_int_mode (size, HImode), HImode))
1676 rtx_insn *sp_plus_insns;
1678 start_sequence ();
1680 emit_move_insn (stack_pointer_rtx,
1681 plus_constant (Pmode, stack_pointer_rtx, size));
1683 sp_plus_insns = get_insns ();
1684 end_sequence ();
1686 /************ Use shortest method ************/
1688 emit_insn (get_sequence_length (sp_plus_insns)
1689 < get_sequence_length (fp_plus_insns)
1690 ? sp_plus_insns
1691 : fp_plus_insns);
1693 else
1694 emit_insn (fp_plus_insns);
1695 } /* size != 0 */
1697 if (frame_pointer_needed
1698 && !(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
1700 /* Restore previous frame_pointer. See avr_expand_prologue for
1701 rationale for not using pophi. */
1703 emit_pop_byte (REG_Y + 1);
1704 emit_pop_byte (REG_Y);
1707 /* Restore used registers. */
1709 for (reg = 31; reg >= 0; --reg)
1710 if (TEST_HARD_REG_BIT (set, reg))
1711 emit_pop_byte (reg);
1713 if (isr_p)
1715 /* Restore RAMPZ/Y/X/D using tmp_reg as scratch.
1716 The conditions to restore them must be tha same as in prologue. */
1718 if (AVR_HAVE_RAMPZ
1719 && TEST_HARD_REG_BIT (set, REG_Z)
1720 && TEST_HARD_REG_BIT (set, REG_Z + 1))
1722 emit_pop_byte (TMP_REGNO);
1723 emit_move_insn (rampz_rtx, tmp_reg_rtx);
1726 if (AVR_HAVE_RAMPY
1727 && (frame_pointer_needed
1728 || (TEST_HARD_REG_BIT (set, REG_Y)
1729 && TEST_HARD_REG_BIT (set, REG_Y + 1))))
1731 emit_pop_byte (TMP_REGNO);
1732 emit_move_insn (rampy_rtx, tmp_reg_rtx);
1735 if (AVR_HAVE_RAMPX
1736 && TEST_HARD_REG_BIT (set, REG_X)
1737 && TEST_HARD_REG_BIT (set, REG_X + 1))
1739 emit_pop_byte (TMP_REGNO);
1740 emit_move_insn (rampx_rtx, tmp_reg_rtx);
1743 if (AVR_HAVE_RAMPD)
1745 emit_pop_byte (TMP_REGNO);
1746 emit_move_insn (rampd_rtx, tmp_reg_rtx);
1749 /* Restore SREG using tmp_reg as scratch. */
1751 emit_pop_byte (AVR_TMP_REGNO);
1752 emit_move_insn (sreg_rtx, tmp_reg_rtx);
1754 /* Restore tmp REG. */
1755 emit_pop_byte (AVR_TMP_REGNO);
1757 /* Restore zero REG. */
1758 emit_pop_byte (AVR_ZERO_REGNO);
1761 if (!sibcall_p)
1762 emit_jump_insn (gen_return ());
1766 /* Implement `TARGET_ASM_FUNCTION_BEGIN_EPILOGUE'. */
1768 static void
1769 avr_asm_function_begin_epilogue (FILE *file)
1771 fprintf (file, "/* epilogue start */\n");
1775 /* Implement `TARGET_CANNOT_MODITY_JUMPS_P'. */
1777 static bool
1778 avr_cannot_modify_jumps_p (void)
1781 /* Naked Functions must not have any instructions after
1782 their epilogue, see PR42240 */
1784 if (reload_completed
1785 && cfun->machine
1786 && cfun->machine->is_naked)
1788 return true;
1791 return false;
1795 /* Implement `TARGET_MODE_DEPENDENT_ADDRESS_P'. */
1797 static bool
1798 avr_mode_dependent_address_p (const_rtx addr ATTRIBUTE_UNUSED, addr_space_t as)
1800 /* FIXME: Non-generic addresses are not mode-dependent in themselves.
1801 This hook just serves to hack around PR rtl-optimization/52543 by
1802 claiming that non-generic addresses were mode-dependent so that
1803 lower-subreg.c will skip these addresses. lower-subreg.c sets up fake
1804 RTXes to probe SET and MEM costs and assumes that MEM is always in the
1805 generic address space which is not true. */
1807 return !ADDR_SPACE_GENERIC_P (as);
1811 /* Helper function for `avr_legitimate_address_p'. */
1813 static inline bool
1814 avr_reg_ok_for_addr_p (rtx reg, addr_space_t as,
1815 RTX_CODE outer_code, bool strict)
1817 return (REG_P (reg)
1818 && (avr_regno_mode_code_ok_for_base_p (REGNO (reg), QImode,
1819 as, outer_code, UNKNOWN)
1820 || (!strict
1821 && REGNO (reg) >= FIRST_PSEUDO_REGISTER)));
1825 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
1826 machine for a memory operand of mode MODE. */
1828 static bool
1829 avr_legitimate_address_p (machine_mode mode, rtx x, bool strict)
1831 bool ok = CONSTANT_ADDRESS_P (x);
1833 switch (GET_CODE (x))
1835 case REG:
1836 ok = avr_reg_ok_for_addr_p (x, ADDR_SPACE_GENERIC,
1837 MEM, strict);
1839 if (strict
1840 && GET_MODE_SIZE (mode) > 4
1841 && REG_X == REGNO (x))
1843 ok = false;
1845 break;
1847 case POST_INC:
1848 case PRE_DEC:
1849 ok = avr_reg_ok_for_addr_p (XEXP (x, 0), ADDR_SPACE_GENERIC,
1850 GET_CODE (x), strict);
1851 break;
1853 case PLUS:
1855 rtx reg = XEXP (x, 0);
1856 rtx op1 = XEXP (x, 1);
1858 if (REG_P (reg)
1859 && CONST_INT_P (op1)
1860 && INTVAL (op1) >= 0)
1862 bool fit = IN_RANGE (INTVAL (op1), 0, MAX_LD_OFFSET (mode));
1864 if (fit)
1866 ok = (! strict
1867 || avr_reg_ok_for_addr_p (reg, ADDR_SPACE_GENERIC,
1868 PLUS, strict));
1870 if (reg == frame_pointer_rtx
1871 || reg == arg_pointer_rtx)
1873 ok = true;
1876 else if (frame_pointer_needed
1877 && reg == frame_pointer_rtx)
1879 ok = true;
1883 break;
1885 default:
1886 break;
1889 if (AVR_TINY
1890 && CONSTANT_ADDRESS_P (x))
1892 /* avrtiny's load / store instructions only cover addresses 0..0xbf:
1893 IN / OUT range is 0..0x3f and LDS / STS can access 0x40..0xbf. */
1895 ok = (CONST_INT_P (x)
1896 && IN_RANGE (INTVAL (x), 0, 0xc0 - GET_MODE_SIZE (mode)));
1899 if (avr_log.legitimate_address_p)
1901 avr_edump ("\n%?: ret=%d, mode=%m strict=%d "
1902 "reload_completed=%d reload_in_progress=%d %s:",
1903 ok, mode, strict, reload_completed, reload_in_progress,
1904 reg_renumber ? "(reg_renumber)" : "");
1906 if (GET_CODE (x) == PLUS
1907 && REG_P (XEXP (x, 0))
1908 && CONST_INT_P (XEXP (x, 1))
1909 && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
1910 && reg_renumber)
1912 avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
1913 true_regnum (XEXP (x, 0)));
1916 avr_edump ("\n%r\n", x);
1919 return ok;
1923 /* Former implementation of TARGET_LEGITIMIZE_ADDRESS,
1924 now only a helper for avr_addr_space_legitimize_address. */
1925 /* Attempts to replace X with a valid
1926 memory address for an operand of mode MODE */
1928 static rtx
1929 avr_legitimize_address (rtx x, rtx oldx, machine_mode mode)
1931 bool big_offset_p = false;
1933 x = oldx;
1935 if (GET_CODE (oldx) == PLUS
1936 && REG_P (XEXP (oldx, 0)))
1938 if (REG_P (XEXP (oldx, 1)))
1939 x = force_reg (GET_MODE (oldx), oldx);
1940 else if (CONST_INT_P (XEXP (oldx, 1)))
1942 int offs = INTVAL (XEXP (oldx, 1));
1943 if (frame_pointer_rtx != XEXP (oldx, 0)
1944 && offs > MAX_LD_OFFSET (mode))
1946 big_offset_p = true;
1947 x = force_reg (GET_MODE (oldx), oldx);
1952 if (avr_log.legitimize_address)
1954 avr_edump ("\n%?: mode=%m\n %r\n", mode, oldx);
1956 if (x != oldx)
1957 avr_edump (" %s --> %r\n", big_offset_p ? "(big offset)" : "", x);
1960 return x;
1964 /* Implement `LEGITIMIZE_RELOAD_ADDRESS'. */
1965 /* This will allow register R26/27 to be used where it is no worse than normal
1966 base pointers R28/29 or R30/31. For example, if base offset is greater
1967 than 63 bytes or for R++ or --R addressing. */
1970 avr_legitimize_reload_address (rtx *px, machine_mode mode,
1971 int opnum, int type, int addr_type,
1972 int ind_levels ATTRIBUTE_UNUSED,
1973 rtx (*mk_memloc)(rtx,int))
1975 rtx x = *px;
1977 if (avr_log.legitimize_reload_address)
1978 avr_edump ("\n%?:%m %r\n", mode, x);
1980 if (1 && (GET_CODE (x) == POST_INC
1981 || GET_CODE (x) == PRE_DEC))
1983 push_reload (XEXP (x, 0), XEXP (x, 0), &XEXP (x, 0), &XEXP (x, 0),
1984 POINTER_REGS, GET_MODE (x), GET_MODE (x), 0, 0,
1985 opnum, RELOAD_OTHER);
1987 if (avr_log.legitimize_reload_address)
1988 avr_edump (" RCLASS.1 = %R\n IN = %r\n OUT = %r\n",
1989 POINTER_REGS, XEXP (x, 0), XEXP (x, 0));
1991 return x;
1994 if (GET_CODE (x) == PLUS
1995 && REG_P (XEXP (x, 0))
1996 && 0 == reg_equiv_constant (REGNO (XEXP (x, 0)))
1997 && CONST_INT_P (XEXP (x, 1))
1998 && INTVAL (XEXP (x, 1)) >= 1)
2000 bool fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
2002 if (fit)
2004 if (reg_equiv_address (REGNO (XEXP (x, 0))) != 0)
2006 int regno = REGNO (XEXP (x, 0));
2007 rtx mem = mk_memloc (x, regno);
2009 push_reload (XEXP (mem, 0), NULL_RTX, &XEXP (mem, 0), NULL,
2010 POINTER_REGS, Pmode, VOIDmode, 0, 0,
2011 1, (enum reload_type) addr_type);
2013 if (avr_log.legitimize_reload_address)
2014 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
2015 POINTER_REGS, XEXP (mem, 0), NULL_RTX);
2017 push_reload (mem, NULL_RTX, &XEXP (x, 0), NULL,
2018 BASE_POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
2019 opnum, (enum reload_type) type);
2021 if (avr_log.legitimize_reload_address)
2022 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
2023 BASE_POINTER_REGS, mem, NULL_RTX);
2025 return x;
2028 else if (! (frame_pointer_needed
2029 && XEXP (x, 0) == frame_pointer_rtx))
2031 push_reload (x, NULL_RTX, px, NULL,
2032 POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
2033 opnum, (enum reload_type) type);
2035 if (avr_log.legitimize_reload_address)
2036 avr_edump (" RCLASS.3 = %R\n IN = %r\n OUT = %r\n",
2037 POINTER_REGS, x, NULL_RTX);
2039 return x;
2043 return NULL_RTX;
2047 /* Implement `TARGET_SECONDARY_RELOAD' */
2049 static reg_class_t
2050 avr_secondary_reload (bool in_p, rtx x,
2051 reg_class_t reload_class ATTRIBUTE_UNUSED,
2052 machine_mode mode, secondary_reload_info *sri)
2054 if (in_p
2055 && MEM_P (x)
2056 && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x))
2057 && ADDR_SPACE_MEMX != MEM_ADDR_SPACE (x))
2059 /* For the non-generic 16-bit spaces we need a d-class scratch. */
2061 switch (mode)
2063 default:
2064 gcc_unreachable();
2066 case QImode: sri->icode = CODE_FOR_reload_inqi; break;
2067 case QQmode: sri->icode = CODE_FOR_reload_inqq; break;
2068 case UQQmode: sri->icode = CODE_FOR_reload_inuqq; break;
2070 case HImode: sri->icode = CODE_FOR_reload_inhi; break;
2071 case HQmode: sri->icode = CODE_FOR_reload_inhq; break;
2072 case HAmode: sri->icode = CODE_FOR_reload_inha; break;
2073 case UHQmode: sri->icode = CODE_FOR_reload_inuhq; break;
2074 case UHAmode: sri->icode = CODE_FOR_reload_inuha; break;
2076 case PSImode: sri->icode = CODE_FOR_reload_inpsi; break;
2078 case SImode: sri->icode = CODE_FOR_reload_insi; break;
2079 case SFmode: sri->icode = CODE_FOR_reload_insf; break;
2080 case SQmode: sri->icode = CODE_FOR_reload_insq; break;
2081 case SAmode: sri->icode = CODE_FOR_reload_insa; break;
2082 case USQmode: sri->icode = CODE_FOR_reload_inusq; break;
2083 case USAmode: sri->icode = CODE_FOR_reload_inusa; break;
2087 return NO_REGS;
2091 /* Helper function to print assembler resp. track instruction
2092 sequence lengths. Always return "".
2094 If PLEN == NULL:
2095 Output assembler code from template TPL with operands supplied
2096 by OPERANDS. This is just forwarding to output_asm_insn.
2098 If PLEN != NULL:
2099 If N_WORDS >= 0 Add N_WORDS to *PLEN.
2100 If N_WORDS < 0 Set *PLEN to -N_WORDS.
2101 Don't output anything.
2104 static const char*
2105 avr_asm_len (const char* tpl, rtx* operands, int* plen, int n_words)
2107 if (NULL == plen)
2109 output_asm_insn (tpl, operands);
2111 else
2113 if (n_words < 0)
2114 *plen = -n_words;
2115 else
2116 *plen += n_words;
2119 return "";
2123 /* Return a pointer register name as a string. */
2125 static const char*
2126 ptrreg_to_str (int regno)
2128 switch (regno)
2130 case REG_X: return "X";
2131 case REG_Y: return "Y";
2132 case REG_Z: return "Z";
2133 default:
2134 output_operand_lossage ("address operand requires constraint for"
2135 " X, Y, or Z register");
2137 return NULL;
2140 /* Return the condition name as a string.
2141 Used in conditional jump constructing */
2143 static const char*
2144 cond_string (enum rtx_code code)
2146 switch (code)
2148 case NE:
2149 return "ne";
2150 case EQ:
2151 return "eq";
2152 case GE:
2153 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
2154 return "pl";
2155 else
2156 return "ge";
2157 case LT:
2158 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
2159 return "mi";
2160 else
2161 return "lt";
2162 case GEU:
2163 return "sh";
2164 case LTU:
2165 return "lo";
2166 default:
2167 gcc_unreachable ();
2170 return "";
2174 /* Implement `TARGET_PRINT_OPERAND_ADDRESS'. */
2175 /* Output ADDR to FILE as address. */
2177 static void
2178 avr_print_operand_address (FILE *file, rtx addr)
2180 switch (GET_CODE (addr))
2182 case REG:
2183 fprintf (file, ptrreg_to_str (REGNO (addr)));
2184 break;
2186 case PRE_DEC:
2187 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
2188 break;
2190 case POST_INC:
2191 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
2192 break;
2194 default:
2195 if (CONSTANT_ADDRESS_P (addr)
2196 && text_segment_operand (addr, VOIDmode))
2198 rtx x = addr;
2199 if (GET_CODE (x) == CONST)
2200 x = XEXP (x, 0);
2201 if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x,1)) == CONST_INT)
2203 /* Assembler gs() will implant word address. Make offset
2204 a byte offset inside gs() for assembler. This is
2205 needed because the more logical (constant+gs(sym)) is not
2206 accepted by gas. For 128K and smaller devices this is ok.
2207 For large devices it will create a trampoline to offset
2208 from symbol which may not be what the user really wanted. */
2210 fprintf (file, "gs(");
2211 output_addr_const (file, XEXP (x,0));
2212 fprintf (file, "+" HOST_WIDE_INT_PRINT_DEC ")",
2213 2 * INTVAL (XEXP (x, 1)));
2214 if (AVR_3_BYTE_PC)
2215 if (warning (0, "pointer offset from symbol maybe incorrect"))
2217 output_addr_const (stderr, addr);
2218 fprintf(stderr,"\n");
2221 else
2223 fprintf (file, "gs(");
2224 output_addr_const (file, addr);
2225 fprintf (file, ")");
2228 else
2229 output_addr_const (file, addr);
2234 /* Implement `TARGET_PRINT_OPERAND_PUNCT_VALID_P'. */
2236 static bool
2237 avr_print_operand_punct_valid_p (unsigned char code)
2239 return code == '~' || code == '!';
2243 /* Implement `TARGET_PRINT_OPERAND'. */
2244 /* Output X as assembler operand to file FILE.
2245 For a description of supported %-codes, see top of avr.md. */
2247 static void
2248 avr_print_operand (FILE *file, rtx x, int code)
2250 int abcd = 0, ef = 0, ij = 0;
2252 if (code >= 'A' && code <= 'D')
2253 abcd = code - 'A';
2254 else if (code == 'E' || code == 'F')
2255 ef = code - 'E';
2256 else if (code == 'I' || code == 'J')
2257 ij = code - 'I';
2259 if (code == '~')
2261 if (!AVR_HAVE_JMP_CALL)
2262 fputc ('r', file);
2264 else if (code == '!')
2266 if (AVR_HAVE_EIJMP_EICALL)
2267 fputc ('e', file);
2269 else if (code == 't'
2270 || code == 'T')
2272 static int t_regno = -1;
2273 static int t_nbits = -1;
2275 if (REG_P (x) && t_regno < 0 && code == 'T')
2277 t_regno = REGNO (x);
2278 t_nbits = GET_MODE_BITSIZE (GET_MODE (x));
2280 else if (CONST_INT_P (x) && t_regno >= 0
2281 && IN_RANGE (INTVAL (x), 0, t_nbits - 1))
2283 int bpos = INTVAL (x);
2285 fprintf (file, "%s", reg_names[t_regno + bpos / 8]);
2286 if (code == 'T')
2287 fprintf (file, ",%d", bpos % 8);
2289 t_regno = -1;
2291 else
2292 fatal_insn ("operands to %T/%t must be reg + const_int:", x);
2294 else if (code == 'E' || code == 'F')
2296 rtx op = XEXP(x, 0);
2297 fprintf (file, reg_names[REGNO (op) + ef]);
2299 else if (code == 'I' || code == 'J')
2301 rtx op = XEXP(XEXP(x, 0), 0);
2302 fprintf (file, reg_names[REGNO (op) + ij]);
2304 else if (REG_P (x))
2306 if (x == zero_reg_rtx)
2307 fprintf (file, "__zero_reg__");
2308 else if (code == 'r' && REGNO (x) < 32)
2309 fprintf (file, "%d", (int) REGNO (x));
2310 else
2311 fprintf (file, reg_names[REGNO (x) + abcd]);
2313 else if (CONST_INT_P (x))
2315 HOST_WIDE_INT ival = INTVAL (x);
2317 if ('i' != code)
2318 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival + abcd);
2319 else if (low_io_address_operand (x, VOIDmode)
2320 || high_io_address_operand (x, VOIDmode))
2322 if (AVR_HAVE_RAMPZ && ival == avr_addr.rampz)
2323 fprintf (file, "__RAMPZ__");
2324 else if (AVR_HAVE_RAMPY && ival == avr_addr.rampy)
2325 fprintf (file, "__RAMPY__");
2326 else if (AVR_HAVE_RAMPX && ival == avr_addr.rampx)
2327 fprintf (file, "__RAMPX__");
2328 else if (AVR_HAVE_RAMPD && ival == avr_addr.rampd)
2329 fprintf (file, "__RAMPD__");
2330 else if ((AVR_XMEGA || AVR_TINY) && ival == avr_addr.ccp)
2331 fprintf (file, "__CCP__");
2332 else if (ival == avr_addr.sreg) fprintf (file, "__SREG__");
2333 else if (ival == avr_addr.sp_l) fprintf (file, "__SP_L__");
2334 else if (ival == avr_addr.sp_h) fprintf (file, "__SP_H__");
2335 else
2337 fprintf (file, HOST_WIDE_INT_PRINT_HEX,
2338 ival - avr_arch->sfr_offset);
2341 else
2342 fatal_insn ("bad address, not an I/O address:", x);
2344 else if (MEM_P (x))
2346 rtx addr = XEXP (x, 0);
2348 if (code == 'm')
2350 if (!CONSTANT_P (addr))
2351 fatal_insn ("bad address, not a constant:", addr);
2352 /* Assembler template with m-code is data - not progmem section */
2353 if (text_segment_operand (addr, VOIDmode))
2354 if (warning (0, "accessing data memory with"
2355 " program memory address"))
2357 output_addr_const (stderr, addr);
2358 fprintf(stderr,"\n");
2360 output_addr_const (file, addr);
2362 else if (code == 'i')
2364 avr_print_operand (file, addr, 'i');
2366 else if (code == 'o')
2368 if (GET_CODE (addr) != PLUS)
2369 fatal_insn ("bad address, not (reg+disp):", addr);
2371 avr_print_operand (file, XEXP (addr, 1), 0);
2373 else if (code == 'b')
2375 if (GET_CODE (addr) != PLUS)
2376 fatal_insn ("bad address, not (reg+disp):", addr);
2378 avr_print_operand_address (file, XEXP (addr, 0));
2380 else if (code == 'p' || code == 'r')
2382 if (GET_CODE (addr) != POST_INC && GET_CODE (addr) != PRE_DEC)
2383 fatal_insn ("bad address, not post_inc or pre_dec:", addr);
2385 if (code == 'p')
2386 avr_print_operand_address (file, XEXP (addr, 0)); /* X, Y, Z */
2387 else
2388 avr_print_operand (file, XEXP (addr, 0), 0); /* r26, r28, r30 */
2390 else if (GET_CODE (addr) == PLUS)
2392 avr_print_operand_address (file, XEXP (addr,0));
2393 if (REGNO (XEXP (addr, 0)) == REG_X)
2394 fatal_insn ("internal compiler error. Bad address:"
2395 ,addr);
2396 fputc ('+', file);
2397 avr_print_operand (file, XEXP (addr,1), code);
2399 else
2400 avr_print_operand_address (file, addr);
2402 else if (code == 'i')
2404 if (GET_CODE (x) == SYMBOL_REF && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO))
2405 avr_print_operand_address
2406 (file, plus_constant (HImode, x, -avr_arch->sfr_offset));
2407 else
2408 fatal_insn ("bad address, not an I/O address:", x);
2410 else if (code == 'x')
2412 /* Constant progmem address - like used in jmp or call */
2413 if (0 == text_segment_operand (x, VOIDmode))
2414 if (warning (0, "accessing program memory"
2415 " with data memory address"))
2417 output_addr_const (stderr, x);
2418 fprintf(stderr,"\n");
2420 /* Use normal symbol for direct address no linker trampoline needed */
2421 output_addr_const (file, x);
2423 else if (CONST_FIXED_P (x))
2425 HOST_WIDE_INT ival = INTVAL (avr_to_int_mode (x));
2426 if (code != 0)
2427 output_operand_lossage ("Unsupported code '%c' for fixed-point:",
2428 code);
2429 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);
2431 else if (GET_CODE (x) == CONST_DOUBLE)
2433 long val;
2434 REAL_VALUE_TYPE rv;
2435 if (GET_MODE (x) != SFmode)
2436 fatal_insn ("internal compiler error. Unknown mode:", x);
2437 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
2438 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
2439 fprintf (file, "0x%lx", val);
2441 else if (GET_CODE (x) == CONST_STRING)
2442 fputs (XSTR (x, 0), file);
2443 else if (code == 'j')
2444 fputs (cond_string (GET_CODE (x)), file);
2445 else if (code == 'k')
2446 fputs (cond_string (reverse_condition (GET_CODE (x))), file);
2447 else
2448 avr_print_operand_address (file, x);
2452 /* Worker function for `NOTICE_UPDATE_CC'. */
2453 /* Update the condition code in the INSN. */
2455 void
2456 avr_notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx_insn *insn)
2458 rtx set;
2459 enum attr_cc cc = get_attr_cc (insn);
2461 switch (cc)
2463 default:
2464 break;
2466 case CC_PLUS:
2467 case CC_LDI:
2469 rtx *op = recog_data.operand;
2470 int len_dummy, icc;
2472 /* Extract insn's operands. */
2473 extract_constrain_insn_cached (insn);
2475 switch (cc)
2477 default:
2478 gcc_unreachable();
2480 case CC_PLUS:
2481 avr_out_plus (insn, op, &len_dummy, &icc);
2482 cc = (enum attr_cc) icc;
2483 break;
2485 case CC_LDI:
2487 cc = (op[1] == CONST0_RTX (GET_MODE (op[0]))
2488 && reg_overlap_mentioned_p (op[0], zero_reg_rtx))
2489 /* Loading zero-reg with 0 uses CLR and thus clobbers cc0. */
2490 ? CC_CLOBBER
2491 /* Any other "r,rL" combination does not alter cc0. */
2492 : CC_NONE;
2494 break;
2495 } /* inner switch */
2497 break;
2499 } /* outer swicth */
2501 switch (cc)
2503 default:
2504 /* Special values like CC_OUT_PLUS from above have been
2505 mapped to "standard" CC_* values so we never come here. */
2507 gcc_unreachable();
2508 break;
2510 case CC_NONE:
2511 /* Insn does not affect CC at all. */
2512 break;
2514 case CC_SET_N:
2515 CC_STATUS_INIT;
2516 break;
2518 case CC_SET_ZN:
2519 set = single_set (insn);
2520 CC_STATUS_INIT;
2521 if (set)
2523 cc_status.flags |= CC_NO_OVERFLOW;
2524 cc_status.value1 = SET_DEST (set);
2526 break;
2528 case CC_SET_VZN:
2529 /* Insn like INC, DEC, NEG that set Z,N,V. We currently don't make use
2530 of this combination, cf. also PR61055. */
2531 CC_STATUS_INIT;
2532 break;
2534 case CC_SET_CZN:
2535 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
2536 The V flag may or may not be known but that's ok because
2537 alter_cond will change tests to use EQ/NE. */
2538 set = single_set (insn);
2539 CC_STATUS_INIT;
2540 if (set)
2542 cc_status.value1 = SET_DEST (set);
2543 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
2545 break;
2547 case CC_COMPARE:
2548 set = single_set (insn);
2549 CC_STATUS_INIT;
2550 if (set)
2551 cc_status.value1 = SET_SRC (set);
2552 break;
2554 case CC_CLOBBER:
2555 /* Insn doesn't leave CC in a usable state. */
2556 CC_STATUS_INIT;
2557 break;
2561 /* Choose mode for jump insn:
2562 1 - relative jump in range -63 <= x <= 62 ;
2563 2 - relative jump in range -2046 <= x <= 2045 ;
2564 3 - absolute jump (only for ATmega[16]03). */
2567 avr_jump_mode (rtx x, rtx_insn *insn)
2569 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_CODE (x) == LABEL_REF
2570 ? XEXP (x, 0) : x));
2571 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
2572 int jump_distance = cur_addr - dest_addr;
2574 if (-63 <= jump_distance && jump_distance <= 62)
2575 return 1;
2576 else if (-2046 <= jump_distance && jump_distance <= 2045)
2577 return 2;
2578 else if (AVR_HAVE_JMP_CALL)
2579 return 3;
2581 return 2;
2584 /* Return an AVR condition jump commands.
2585 X is a comparison RTX.
2586 LEN is a number returned by avr_jump_mode function.
2587 If REVERSE nonzero then condition code in X must be reversed. */
2589 const char*
2590 ret_cond_branch (rtx x, int len, int reverse)
2592 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
2594 switch (cond)
2596 case GT:
2597 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
2598 return (len == 1 ? ("breq .+2" CR_TAB
2599 "brpl %0") :
2600 len == 2 ? ("breq .+4" CR_TAB
2601 "brmi .+2" CR_TAB
2602 "rjmp %0") :
2603 ("breq .+6" CR_TAB
2604 "brmi .+4" CR_TAB
2605 "jmp %0"));
2607 else
2608 return (len == 1 ? ("breq .+2" CR_TAB
2609 "brge %0") :
2610 len == 2 ? ("breq .+4" CR_TAB
2611 "brlt .+2" CR_TAB
2612 "rjmp %0") :
2613 ("breq .+6" CR_TAB
2614 "brlt .+4" CR_TAB
2615 "jmp %0"));
2616 case GTU:
2617 return (len == 1 ? ("breq .+2" CR_TAB
2618 "brsh %0") :
2619 len == 2 ? ("breq .+4" CR_TAB
2620 "brlo .+2" CR_TAB
2621 "rjmp %0") :
2622 ("breq .+6" CR_TAB
2623 "brlo .+4" CR_TAB
2624 "jmp %0"));
2625 case LE:
2626 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
2627 return (len == 1 ? ("breq %0" CR_TAB
2628 "brmi %0") :
2629 len == 2 ? ("breq .+2" CR_TAB
2630 "brpl .+2" CR_TAB
2631 "rjmp %0") :
2632 ("breq .+2" CR_TAB
2633 "brpl .+4" CR_TAB
2634 "jmp %0"));
2635 else
2636 return (len == 1 ? ("breq %0" CR_TAB
2637 "brlt %0") :
2638 len == 2 ? ("breq .+2" CR_TAB
2639 "brge .+2" CR_TAB
2640 "rjmp %0") :
2641 ("breq .+2" CR_TAB
2642 "brge .+4" CR_TAB
2643 "jmp %0"));
2644 case LEU:
2645 return (len == 1 ? ("breq %0" CR_TAB
2646 "brlo %0") :
2647 len == 2 ? ("breq .+2" CR_TAB
2648 "brsh .+2" CR_TAB
2649 "rjmp %0") :
2650 ("breq .+2" CR_TAB
2651 "brsh .+4" CR_TAB
2652 "jmp %0"));
2653 default:
2654 if (reverse)
2656 switch (len)
2658 case 1:
2659 return "br%k1 %0";
2660 case 2:
2661 return ("br%j1 .+2" CR_TAB
2662 "rjmp %0");
2663 default:
2664 return ("br%j1 .+4" CR_TAB
2665 "jmp %0");
2668 else
2670 switch (len)
2672 case 1:
2673 return "br%j1 %0";
2674 case 2:
2675 return ("br%k1 .+2" CR_TAB
2676 "rjmp %0");
2677 default:
2678 return ("br%k1 .+4" CR_TAB
2679 "jmp %0");
2683 return "";
2687 /* Worker function for `FINAL_PRESCAN_INSN'. */
2688 /* Output insn cost for next insn. */
2690 void
2691 avr_final_prescan_insn (rtx_insn *insn, rtx *operand ATTRIBUTE_UNUSED,
2692 int num_operands ATTRIBUTE_UNUSED)
2694 if (avr_log.rtx_costs)
2696 rtx set = single_set (insn);
2698 if (set)
2699 fprintf (asm_out_file, "/* DEBUG: cost = %d. */\n",
2700 set_src_cost (SET_SRC (set), GET_MODE (SET_DEST (set)),
2701 optimize_insn_for_speed_p ()));
2702 else
2703 fprintf (asm_out_file, "/* DEBUG: pattern-cost = %d. */\n",
2704 rtx_cost (PATTERN (insn), VOIDmode, INSN, 0,
2705 optimize_insn_for_speed_p()));
2709 /* Return 0 if undefined, 1 if always true or always false. */
2712 avr_simplify_comparison_p (machine_mode mode, RTX_CODE op, rtx x)
2714 unsigned int max = (mode == QImode ? 0xff :
2715 mode == HImode ? 0xffff :
2716 mode == PSImode ? 0xffffff :
2717 mode == SImode ? 0xffffffff : 0);
2718 if (max && op && CONST_INT_P (x))
2720 if (unsigned_condition (op) != op)
2721 max >>= 1;
2723 if (max != (INTVAL (x) & max)
2724 && INTVAL (x) != 0xff)
2725 return 1;
2727 return 0;
2731 /* Worker function for `FUNCTION_ARG_REGNO_P'. */
2732 /* Returns nonzero if REGNO is the number of a hard
2733 register in which function arguments are sometimes passed. */
2736 avr_function_arg_regno_p(int r)
2738 return (AVR_TINY ? r >= 20 && r <= 25 : r >= 8 && r <= 25);
2742 /* Worker function for `INIT_CUMULATIVE_ARGS'. */
2743 /* Initializing the variable cum for the state at the beginning
2744 of the argument list. */
2746 void
2747 avr_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
2748 tree fndecl ATTRIBUTE_UNUSED)
2750 cum->nregs = AVR_TINY ? 6 : 18;
2751 cum->regno = FIRST_CUM_REG;
2752 if (!libname && stdarg_p (fntype))
2753 cum->nregs = 0;
2755 /* Assume the calle may be tail called */
2757 cfun->machine->sibcall_fails = 0;
2760 /* Returns the number of registers to allocate for a function argument. */
2762 static int
2763 avr_num_arg_regs (machine_mode mode, const_tree type)
2765 int size;
2767 if (mode == BLKmode)
2768 size = int_size_in_bytes (type);
2769 else
2770 size = GET_MODE_SIZE (mode);
2772 /* Align all function arguments to start in even-numbered registers.
2773 Odd-sized arguments leave holes above them. */
2775 return (size + 1) & ~1;
2779 /* Implement `TARGET_FUNCTION_ARG'. */
2780 /* Controls whether a function argument is passed
2781 in a register, and which register. */
2783 static rtx
2784 avr_function_arg (cumulative_args_t cum_v, machine_mode mode,
2785 const_tree type, bool named ATTRIBUTE_UNUSED)
2787 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2788 int bytes = avr_num_arg_regs (mode, type);
2790 if (cum->nregs && bytes <= cum->nregs)
2791 return gen_rtx_REG (mode, cum->regno - bytes);
2793 return NULL_RTX;
2797 /* Implement `TARGET_FUNCTION_ARG_ADVANCE'. */
2798 /* Update the summarizer variable CUM to advance past an argument
2799 in the argument list. */
2801 static void
2802 avr_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
2803 const_tree type, bool named ATTRIBUTE_UNUSED)
2805 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2806 int bytes = avr_num_arg_regs (mode, type);
2808 cum->nregs -= bytes;
2809 cum->regno -= bytes;
2811 /* A parameter is being passed in a call-saved register. As the original
2812 contents of these regs has to be restored before leaving the function,
2813 a function must not pass arguments in call-saved regs in order to get
2814 tail-called. */
2816 if (cum->regno >= 8
2817 && cum->nregs >= 0
2818 && !call_used_regs[cum->regno])
2820 /* FIXME: We ship info on failing tail-call in struct machine_function.
2821 This uses internals of calls.c:expand_call() and the way args_so_far
2822 is used. targetm.function_ok_for_sibcall() needs to be extended to
2823 pass &args_so_far, too. At present, CUMULATIVE_ARGS is target
2824 dependent so that such an extension is not wanted. */
2826 cfun->machine->sibcall_fails = 1;
2829 /* Test if all registers needed by the ABI are actually available. If the
2830 user has fixed a GPR needed to pass an argument, an (implicit) function
2831 call will clobber that fixed register. See PR45099 for an example. */
2833 if (cum->regno >= 8
2834 && cum->nregs >= 0)
2836 int regno;
2838 for (regno = cum->regno; regno < cum->regno + bytes; regno++)
2839 if (fixed_regs[regno])
2840 warning (0, "fixed register %s used to pass parameter to function",
2841 reg_names[regno]);
2844 if (cum->nregs <= 0)
2846 cum->nregs = 0;
2847 cum->regno = FIRST_CUM_REG;
2851 /* Implement `TARGET_FUNCTION_OK_FOR_SIBCALL' */
2852 /* Decide whether we can make a sibling call to a function. DECL is the
2853 declaration of the function being targeted by the call and EXP is the
2854 CALL_EXPR representing the call. */
2856 static bool
2857 avr_function_ok_for_sibcall (tree decl_callee, tree exp_callee)
2859 tree fntype_callee;
2861 /* Tail-calling must fail if callee-saved regs are used to pass
2862 function args. We must not tail-call when `epilogue_restores'
2863 is used. Unfortunately, we cannot tell at this point if that
2864 actually will happen or not, and we cannot step back from
2865 tail-calling. Thus, we inhibit tail-calling with -mcall-prologues. */
2867 if (cfun->machine->sibcall_fails
2868 || TARGET_CALL_PROLOGUES)
2870 return false;
2873 fntype_callee = TREE_TYPE (CALL_EXPR_FN (exp_callee));
2875 if (decl_callee)
2877 decl_callee = TREE_TYPE (decl_callee);
2879 else
2881 decl_callee = fntype_callee;
2883 while (FUNCTION_TYPE != TREE_CODE (decl_callee)
2884 && METHOD_TYPE != TREE_CODE (decl_callee))
2886 decl_callee = TREE_TYPE (decl_callee);
2890 /* Ensure that caller and callee have compatible epilogues */
2892 if (cfun->machine->is_interrupt
2893 || cfun->machine->is_signal
2894 || cfun->machine->is_naked
2895 || avr_naked_function_p (decl_callee)
2896 /* FIXME: For OS_task and OS_main, this might be over-conservative. */
2897 || (avr_OS_task_function_p (decl_callee)
2898 != cfun->machine->is_OS_task)
2899 || (avr_OS_main_function_p (decl_callee)
2900 != cfun->machine->is_OS_main))
2902 return false;
2905 return true;
2908 /***********************************************************************
2909 Functions for outputting various mov's for a various modes
2910 ************************************************************************/
2912 /* Return true if a value of mode MODE is read from flash by
2913 __load_* function from libgcc. */
2915 bool
2916 avr_load_libgcc_p (rtx op)
2918 machine_mode mode = GET_MODE (op);
2919 int n_bytes = GET_MODE_SIZE (mode);
2921 return (n_bytes > 2
2922 && !AVR_HAVE_LPMX
2923 && avr_mem_flash_p (op));
2926 /* Return true if a value of mode MODE is read by __xload_* function. */
2928 bool
2929 avr_xload_libgcc_p (machine_mode mode)
2931 int n_bytes = GET_MODE_SIZE (mode);
2933 return (n_bytes > 1
2934 || avr_n_flash > 1);
2938 /* Fixme: This is a hack because secondary reloads don't works as expected.
2940 Find an unused d-register to be used as scratch in INSN.
2941 EXCLUDE is either NULL_RTX or some register. In the case where EXCLUDE
2942 is a register, skip all possible return values that overlap EXCLUDE.
2943 The policy for the returned register is similar to that of
2944 `reg_unused_after', i.e. the returned register may overlap the SET_DEST
2945 of INSN.
2947 Return a QImode d-register or NULL_RTX if nothing found. */
2949 static rtx
2950 avr_find_unused_d_reg (rtx_insn *insn, rtx exclude)
2952 int regno;
2953 bool isr_p = (avr_interrupt_function_p (current_function_decl)
2954 || avr_signal_function_p (current_function_decl));
2956 for (regno = 16; regno < 32; regno++)
2958 rtx reg = all_regs_rtx[regno];
2960 if ((exclude
2961 && reg_overlap_mentioned_p (exclude, reg))
2962 || fixed_regs[regno])
2964 continue;
2967 /* Try non-live register */
2969 if (!df_regs_ever_live_p (regno)
2970 && (TREE_THIS_VOLATILE (current_function_decl)
2971 || cfun->machine->is_OS_task
2972 || cfun->machine->is_OS_main
2973 || (!isr_p && call_used_regs[regno])))
2975 return reg;
2978 /* Any live register can be used if it is unused after.
2979 Prologue/epilogue will care for it as needed. */
2981 if (df_regs_ever_live_p (regno)
2982 && reg_unused_after (insn, reg))
2984 return reg;
2988 return NULL_RTX;
2992 /* Helper function for the next function in the case where only restricted
2993 version of LPM instruction is available. */
2995 static const char*
2996 avr_out_lpm_no_lpmx (rtx_insn *insn, rtx *xop, int *plen)
2998 rtx dest = xop[0];
2999 rtx addr = xop[1];
3000 int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
3001 int regno_dest;
3003 regno_dest = REGNO (dest);
3005 /* The implicit target register of LPM. */
3006 xop[3] = lpm_reg_rtx;
3008 switch (GET_CODE (addr))
3010 default:
3011 gcc_unreachable();
3013 case REG:
3015 gcc_assert (REG_Z == REGNO (addr));
3017 switch (n_bytes)
3019 default:
3020 gcc_unreachable();
3022 case 1:
3023 avr_asm_len ("%4lpm", xop, plen, 1);
3025 if (regno_dest != LPM_REGNO)
3026 avr_asm_len ("mov %0,%3", xop, plen, 1);
3028 return "";
3030 case 2:
3031 if (REGNO (dest) == REG_Z)
3032 return avr_asm_len ("%4lpm" CR_TAB
3033 "push %3" CR_TAB
3034 "adiw %2,1" CR_TAB
3035 "%4lpm" CR_TAB
3036 "mov %B0,%3" CR_TAB
3037 "pop %A0", xop, plen, 6);
3039 avr_asm_len ("%4lpm" CR_TAB
3040 "mov %A0,%3" CR_TAB
3041 "adiw %2,1" CR_TAB
3042 "%4lpm" CR_TAB
3043 "mov %B0,%3", xop, plen, 5);
3045 if (!reg_unused_after (insn, addr))
3046 avr_asm_len ("sbiw %2,1", xop, plen, 1);
3048 break; /* 2 */
3051 break; /* REG */
3053 case POST_INC:
3055 gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
3056 && n_bytes <= 4);
3058 if (regno_dest == LPM_REGNO)
3059 avr_asm_len ("%4lpm" CR_TAB
3060 "adiw %2,1", xop, plen, 2);
3061 else
3062 avr_asm_len ("%4lpm" CR_TAB
3063 "mov %A0,%3" CR_TAB
3064 "adiw %2,1", xop, plen, 3);
3066 if (n_bytes >= 2)
3067 avr_asm_len ("%4lpm" CR_TAB
3068 "mov %B0,%3" CR_TAB
3069 "adiw %2,1", xop, plen, 3);
3071 if (n_bytes >= 3)
3072 avr_asm_len ("%4lpm" CR_TAB
3073 "mov %C0,%3" CR_TAB
3074 "adiw %2,1", xop, plen, 3);
3076 if (n_bytes >= 4)
3077 avr_asm_len ("%4lpm" CR_TAB
3078 "mov %D0,%3" CR_TAB
3079 "adiw %2,1", xop, plen, 3);
3081 break; /* POST_INC */
3083 } /* switch CODE (addr) */
3085 return "";
3089 /* If PLEN == NULL: Ouput instructions to load a value from a memory location
3090 OP[1] in AS1 to register OP[0].
3091 If PLEN != 0 set *PLEN to the length in words of the instruction sequence.
3092 Return "". */
3094 const char*
3095 avr_out_lpm (rtx_insn *insn, rtx *op, int *plen)
3097 rtx xop[7];
3098 rtx dest = op[0];
3099 rtx src = SET_SRC (single_set (insn));
3100 rtx addr;
3101 int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
3102 int segment;
3103 RTX_CODE code;
3104 addr_space_t as = MEM_ADDR_SPACE (src);
3106 if (plen)
3107 *plen = 0;
3109 if (MEM_P (dest))
3111 warning (0, "writing to address space %qs not supported",
3112 avr_addrspace[MEM_ADDR_SPACE (dest)].name);
3114 return "";
3117 addr = XEXP (src, 0);
3118 code = GET_CODE (addr);
3120 gcc_assert (REG_P (dest));
3121 gcc_assert (REG == code || POST_INC == code);
3123 xop[0] = dest;
3124 xop[1] = addr;
3125 xop[2] = lpm_addr_reg_rtx;
3126 xop[4] = xstring_empty;
3127 xop[5] = tmp_reg_rtx;
3128 xop[6] = XEXP (rampz_rtx, 0);
3130 segment = avr_addrspace[as].segment;
3132 /* Set RAMPZ as needed. */
3134 if (segment)
3136 xop[4] = GEN_INT (segment);
3137 xop[3] = avr_find_unused_d_reg (insn, lpm_addr_reg_rtx);
3139 if (xop[3] != NULL_RTX)
3141 avr_asm_len ("ldi %3,%4" CR_TAB
3142 "out %i6,%3", xop, plen, 2);
3144 else if (segment == 1)
3146 avr_asm_len ("clr %5" CR_TAB
3147 "inc %5" CR_TAB
3148 "out %i6,%5", xop, plen, 3);
3150 else
3152 avr_asm_len ("mov %5,%2" CR_TAB
3153 "ldi %2,%4" CR_TAB
3154 "out %i6,%2" CR_TAB
3155 "mov %2,%5", xop, plen, 4);
3158 xop[4] = xstring_e;
3160 if (!AVR_HAVE_ELPMX)
3161 return avr_out_lpm_no_lpmx (insn, xop, plen);
3163 else if (!AVR_HAVE_LPMX)
3165 return avr_out_lpm_no_lpmx (insn, xop, plen);
3168 /* We have [E]LPMX: Output reading from Flash the comfortable way. */
3170 switch (GET_CODE (addr))
3172 default:
3173 gcc_unreachable();
3175 case REG:
3177 gcc_assert (REG_Z == REGNO (addr));
3179 switch (n_bytes)
3181 default:
3182 gcc_unreachable();
3184 case 1:
3185 return avr_asm_len ("%4lpm %0,%a2", xop, plen, 1);
3187 case 2:
3188 if (REGNO (dest) == REG_Z)
3189 return avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3190 "%4lpm %B0,%a2" CR_TAB
3191 "mov %A0,%5", xop, plen, 3);
3192 else
3194 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3195 "%4lpm %B0,%a2", xop, plen, 2);
3197 if (!reg_unused_after (insn, addr))
3198 avr_asm_len ("sbiw %2,1", xop, plen, 1);
3201 break; /* 2 */
3203 case 3:
3205 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3206 "%4lpm %B0,%a2+" CR_TAB
3207 "%4lpm %C0,%a2", xop, plen, 3);
3209 if (!reg_unused_after (insn, addr))
3210 avr_asm_len ("sbiw %2,2", xop, plen, 1);
3212 break; /* 3 */
3214 case 4:
3216 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3217 "%4lpm %B0,%a2+", xop, plen, 2);
3219 if (REGNO (dest) == REG_Z - 2)
3220 return avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3221 "%4lpm %C0,%a2" CR_TAB
3222 "mov %D0,%5", xop, plen, 3);
3223 else
3225 avr_asm_len ("%4lpm %C0,%a2+" CR_TAB
3226 "%4lpm %D0,%a2", xop, plen, 2);
3228 if (!reg_unused_after (insn, addr))
3229 avr_asm_len ("sbiw %2,3", xop, plen, 1);
3232 break; /* 4 */
3233 } /* n_bytes */
3235 break; /* REG */
3237 case POST_INC:
3239 gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
3240 && n_bytes <= 4);
3242 avr_asm_len ("%4lpm %A0,%a2+", xop, plen, 1);
3243 if (n_bytes >= 2) avr_asm_len ("%4lpm %B0,%a2+", xop, plen, 1);
3244 if (n_bytes >= 3) avr_asm_len ("%4lpm %C0,%a2+", xop, plen, 1);
3245 if (n_bytes >= 4) avr_asm_len ("%4lpm %D0,%a2+", xop, plen, 1);
3247 break; /* POST_INC */
3249 } /* switch CODE (addr) */
3251 if (xop[4] == xstring_e && AVR_HAVE_RAMPD)
3253 /* Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM. */
3255 xop[0] = zero_reg_rtx;
3256 avr_asm_len ("out %i6,%0", xop, plen, 1);
3259 return "";
3263 /* Worker function for xload_8 insn. */
3265 const char*
3266 avr_out_xload (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
3268 rtx xop[4];
3270 xop[0] = op[0];
3271 xop[1] = op[1];
3272 xop[2] = lpm_addr_reg_rtx;
3273 xop[3] = AVR_HAVE_LPMX ? op[0] : lpm_reg_rtx;
3275 avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, -1);
3277 avr_asm_len ("sbrc %1,7" CR_TAB
3278 "ld %3,%a2", xop, plen, 2);
3280 if (REGNO (xop[0]) != REGNO (xop[3]))
3281 avr_asm_len ("mov %0,%3", xop, plen, 1);
3283 return "";
3287 const char*
3288 output_movqi (rtx_insn *insn, rtx operands[], int *plen)
3290 rtx dest = operands[0];
3291 rtx src = operands[1];
3293 if (avr_mem_flash_p (src)
3294 || avr_mem_flash_p (dest))
3296 return avr_out_lpm (insn, operands, plen);
3299 gcc_assert (1 == GET_MODE_SIZE (GET_MODE (dest)));
3301 if (REG_P (dest))
3303 if (REG_P (src)) /* mov r,r */
3305 if (test_hard_reg_class (STACK_REG, dest))
3306 return avr_asm_len ("out %0,%1", operands, plen, -1);
3307 else if (test_hard_reg_class (STACK_REG, src))
3308 return avr_asm_len ("in %0,%1", operands, plen, -1);
3310 return avr_asm_len ("mov %0,%1", operands, plen, -1);
3312 else if (CONSTANT_P (src))
3314 output_reload_in_const (operands, NULL_RTX, plen, false);
3315 return "";
3317 else if (MEM_P (src))
3318 return out_movqi_r_mr (insn, operands, plen); /* mov r,m */
3320 else if (MEM_P (dest))
3322 rtx xop[2];
3324 xop[0] = dest;
3325 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
3327 return out_movqi_mr_r (insn, xop, plen);
3330 return "";
3334 const char *
3335 output_movhi (rtx_insn *insn, rtx xop[], int *plen)
3337 rtx dest = xop[0];
3338 rtx src = xop[1];
3340 gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 2);
3342 if (avr_mem_flash_p (src)
3343 || avr_mem_flash_p (dest))
3345 return avr_out_lpm (insn, xop, plen);
3348 gcc_assert (2 == GET_MODE_SIZE (GET_MODE (dest)));
3350 if (REG_P (dest))
3352 if (REG_P (src)) /* mov r,r */
3354 if (test_hard_reg_class (STACK_REG, dest))
3356 if (AVR_HAVE_8BIT_SP)
3357 return avr_asm_len ("out __SP_L__,%A1", xop, plen, -1);
3359 if (AVR_XMEGA)
3360 return avr_asm_len ("out __SP_L__,%A1" CR_TAB
3361 "out __SP_H__,%B1", xop, plen, -2);
3363 /* Use simple load of SP if no interrupts are used. */
3365 return TARGET_NO_INTERRUPTS
3366 ? avr_asm_len ("out __SP_H__,%B1" CR_TAB
3367 "out __SP_L__,%A1", xop, plen, -2)
3368 : avr_asm_len ("in __tmp_reg__,__SREG__" CR_TAB
3369 "cli" CR_TAB
3370 "out __SP_H__,%B1" CR_TAB
3371 "out __SREG__,__tmp_reg__" CR_TAB
3372 "out __SP_L__,%A1", xop, plen, -5);
3374 else if (test_hard_reg_class (STACK_REG, src))
3376 return !AVR_HAVE_SPH
3377 ? avr_asm_len ("in %A0,__SP_L__" CR_TAB
3378 "clr %B0", xop, plen, -2)
3380 : avr_asm_len ("in %A0,__SP_L__" CR_TAB
3381 "in %B0,__SP_H__", xop, plen, -2);
3384 return AVR_HAVE_MOVW
3385 ? avr_asm_len ("movw %0,%1", xop, plen, -1)
3387 : avr_asm_len ("mov %A0,%A1" CR_TAB
3388 "mov %B0,%B1", xop, plen, -2);
3389 } /* REG_P (src) */
3390 else if (CONSTANT_P (src))
3392 return output_reload_inhi (xop, NULL, plen);
3394 else if (MEM_P (src))
3396 return out_movhi_r_mr (insn, xop, plen); /* mov r,m */
3399 else if (MEM_P (dest))
3401 rtx xop[2];
3403 xop[0] = dest;
3404 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
3406 return out_movhi_mr_r (insn, xop, plen);
3409 fatal_insn ("invalid insn:", insn);
3411 return "";
3415 /* Same as out_movqi_r_mr, but TINY does not have ADIW or SBIW */
3417 static const char*
3418 avr_out_movqi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
3420 rtx dest = op[0];
3421 rtx src = op[1];
3422 rtx x = XEXP (src, 0);
3424 avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
3425 "ld %0,%b1" , op, plen, -3);
3427 if (!reg_overlap_mentioned_p (dest, XEXP (x,0))
3428 && !reg_unused_after (insn, XEXP (x,0)))
3429 avr_asm_len (TINY_SBIW (%I1, %J1, %o1), op, plen, 2);
3431 return "";
3434 static const char*
3435 out_movqi_r_mr (rtx_insn *insn, rtx op[], int *plen)
3437 rtx dest = op[0];
3438 rtx src = op[1];
3439 rtx x = XEXP (src, 0);
3441 if (CONSTANT_ADDRESS_P (x))
3443 int n_words = AVR_TINY ? 1 : 2;
3444 return optimize > 0 && io_address_operand (x, QImode)
3445 ? avr_asm_len ("in %0,%i1", op, plen, -1)
3446 : avr_asm_len ("lds %0,%m1", op, plen, -n_words);
3449 if (GET_CODE (x) == PLUS
3450 && REG_P (XEXP (x, 0))
3451 && CONST_INT_P (XEXP (x, 1)))
3453 /* memory access by reg+disp */
3455 int disp = INTVAL (XEXP (x, 1));
3457 if (AVR_TINY)
3458 return avr_out_movqi_r_mr_reg_disp_tiny (insn, op, plen);
3460 if (disp - GET_MODE_SIZE (GET_MODE (src)) >= 63)
3462 if (REGNO (XEXP (x, 0)) != REG_Y)
3463 fatal_insn ("incorrect insn:",insn);
3465 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
3466 return avr_asm_len ("adiw r28,%o1-63" CR_TAB
3467 "ldd %0,Y+63" CR_TAB
3468 "sbiw r28,%o1-63", op, plen, -3);
3470 return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
3471 "sbci r29,hi8(-%o1)" CR_TAB
3472 "ld %0,Y" CR_TAB
3473 "subi r28,lo8(%o1)" CR_TAB
3474 "sbci r29,hi8(%o1)", op, plen, -5);
3476 else if (REGNO (XEXP (x, 0)) == REG_X)
3478 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
3479 it but I have this situation with extremal optimizing options. */
3481 avr_asm_len ("adiw r26,%o1" CR_TAB
3482 "ld %0,X", op, plen, -2);
3484 if (!reg_overlap_mentioned_p (dest, XEXP (x,0))
3485 && !reg_unused_after (insn, XEXP (x,0)))
3487 avr_asm_len ("sbiw r26,%o1", op, plen, 1);
3490 return "";
3493 return avr_asm_len ("ldd %0,%1", op, plen, -1);
3496 return avr_asm_len ("ld %0,%1", op, plen, -1);
3500 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
3502 static const char*
3503 avr_out_movhi_r_mr_reg_no_disp_tiny (rtx op[], int *plen)
3505 rtx dest = op[0];
3506 rtx src = op[1];
3507 rtx base = XEXP (src, 0);
3509 int reg_dest = true_regnum (dest);
3510 int reg_base = true_regnum (base);
3512 if (reg_dest == reg_base) /* R = (R) */
3513 return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
3514 "ld %B0,%1" CR_TAB
3515 "mov %A0,__tmp_reg__", op, plen, -3);
3517 return avr_asm_len ("ld %A0,%1" CR_TAB
3518 TINY_ADIW (%E1, %F1, 1) CR_TAB
3519 "ld %B0,%1" CR_TAB
3520 TINY_SBIW (%E1, %F1, 1), op, plen, -6);
3524 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
3526 static const char*
3527 avr_out_movhi_r_mr_reg_disp_tiny (rtx op[], int *plen)
3529 rtx dest = op[0];
3530 rtx src = op[1];
3531 rtx base = XEXP (src, 0);
3533 int reg_dest = true_regnum (dest);
3534 int reg_base = true_regnum (XEXP (base, 0));
3536 if (reg_base == reg_dest)
3538 return avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
3539 "ld __tmp_reg__,%b1+" CR_TAB
3540 "ld %B0,%b1" CR_TAB
3541 "mov %A0,__tmp_reg__", op, plen, -5);
3543 else
3545 return avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
3546 "ld %A0,%b1+" CR_TAB
3547 "ld %B0,%b1" CR_TAB
3548 TINY_SBIW (%I1, %J1, %o1+1), op, plen, -6);
3553 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
3555 static const char*
3556 avr_out_movhi_r_mr_pre_dec_tiny (rtx_insn *insn, rtx op[], int *plen)
3558 int mem_volatile_p = 0;
3559 rtx dest = op[0];
3560 rtx src = op[1];
3561 rtx base = XEXP (src, 0);
3563 /* "volatile" forces reading low byte first, even if less efficient,
3564 for correct operation with 16-bit I/O registers. */
3565 mem_volatile_p = MEM_VOLATILE_P (src);
3567 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
3568 fatal_insn ("incorrect insn:", insn);
3570 if (!mem_volatile_p)
3571 return avr_asm_len ("ld %B0,%1" CR_TAB
3572 "ld %A0,%1", op, plen, -2);
3574 return avr_asm_len (TINY_SBIW (%I1, %J1, 2) CR_TAB
3575 "ld %A0,%p1+" CR_TAB
3576 "ld %B0,%p1" CR_TAB
3577 TINY_SBIW (%I1, %J1, 1), op, plen, -6);
3581 static const char*
3582 out_movhi_r_mr (rtx_insn *insn, rtx op[], int *plen)
3584 rtx dest = op[0];
3585 rtx src = op[1];
3586 rtx base = XEXP (src, 0);
3587 int reg_dest = true_regnum (dest);
3588 int reg_base = true_regnum (base);
3589 /* "volatile" forces reading low byte first, even if less efficient,
3590 for correct operation with 16-bit I/O registers. */
3591 int mem_volatile_p = MEM_VOLATILE_P (src);
3593 if (reg_base > 0)
3595 if (AVR_TINY)
3596 return avr_out_movhi_r_mr_reg_no_disp_tiny (op, plen);
3598 if (reg_dest == reg_base) /* R = (R) */
3599 return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
3600 "ld %B0,%1" CR_TAB
3601 "mov %A0,__tmp_reg__", op, plen, -3);
3603 if (reg_base != REG_X)
3604 return avr_asm_len ("ld %A0,%1" CR_TAB
3605 "ldd %B0,%1+1", op, plen, -2);
3607 avr_asm_len ("ld %A0,X+" CR_TAB
3608 "ld %B0,X", op, plen, -2);
3610 if (!reg_unused_after (insn, base))
3611 avr_asm_len ("sbiw r26,1", op, plen, 1);
3613 return "";
3615 else if (GET_CODE (base) == PLUS) /* (R + i) */
3617 int disp = INTVAL (XEXP (base, 1));
3618 int reg_base = true_regnum (XEXP (base, 0));
3620 if (AVR_TINY)
3621 return avr_out_movhi_r_mr_reg_disp_tiny (op, plen);
3623 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
3625 if (REGNO (XEXP (base, 0)) != REG_Y)
3626 fatal_insn ("incorrect insn:",insn);
3628 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (src))
3629 ? avr_asm_len ("adiw r28,%o1-62" CR_TAB
3630 "ldd %A0,Y+62" CR_TAB
3631 "ldd %B0,Y+63" CR_TAB
3632 "sbiw r28,%o1-62", op, plen, -4)
3634 : avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
3635 "sbci r29,hi8(-%o1)" CR_TAB
3636 "ld %A0,Y" CR_TAB
3637 "ldd %B0,Y+1" CR_TAB
3638 "subi r28,lo8(%o1)" CR_TAB
3639 "sbci r29,hi8(%o1)", op, plen, -6);
3642 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
3643 it but I have this situation with extremal
3644 optimization options. */
3646 if (reg_base == REG_X)
3647 return reg_base == reg_dest
3648 ? avr_asm_len ("adiw r26,%o1" CR_TAB
3649 "ld __tmp_reg__,X+" CR_TAB
3650 "ld %B0,X" CR_TAB
3651 "mov %A0,__tmp_reg__", op, plen, -4)
3653 : avr_asm_len ("adiw r26,%o1" CR_TAB
3654 "ld %A0,X+" CR_TAB
3655 "ld %B0,X" CR_TAB
3656 "sbiw r26,%o1+1", op, plen, -4);
3658 return reg_base == reg_dest
3659 ? avr_asm_len ("ldd __tmp_reg__,%A1" CR_TAB
3660 "ldd %B0,%B1" CR_TAB
3661 "mov %A0,__tmp_reg__", op, plen, -3)
3663 : avr_asm_len ("ldd %A0,%A1" CR_TAB
3664 "ldd %B0,%B1", op, plen, -2);
3666 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
3668 if (AVR_TINY)
3669 return avr_out_movhi_r_mr_pre_dec_tiny (insn, op, plen);
3671 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
3672 fatal_insn ("incorrect insn:", insn);
3674 if (!mem_volatile_p)
3675 return avr_asm_len ("ld %B0,%1" CR_TAB
3676 "ld %A0,%1", op, plen, -2);
3678 return REGNO (XEXP (base, 0)) == REG_X
3679 ? avr_asm_len ("sbiw r26,2" CR_TAB
3680 "ld %A0,X+" CR_TAB
3681 "ld %B0,X" CR_TAB
3682 "sbiw r26,1", op, plen, -4)
3684 : avr_asm_len ("sbiw %r1,2" CR_TAB
3685 "ld %A0,%p1" CR_TAB
3686 "ldd %B0,%p1+1", op, plen, -3);
3688 else if (GET_CODE (base) == POST_INC) /* (R++) */
3690 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
3691 fatal_insn ("incorrect insn:", insn);
3693 return avr_asm_len ("ld %A0,%1" CR_TAB
3694 "ld %B0,%1", op, plen, -2);
3696 else if (CONSTANT_ADDRESS_P (base))
3698 int n_words = AVR_TINY ? 2 : 4;
3699 return optimize > 0 && io_address_operand (base, HImode)
3700 ? avr_asm_len ("in %A0,%i1" CR_TAB
3701 "in %B0,%i1+1", op, plen, -2)
3703 : avr_asm_len ("lds %A0,%m1" CR_TAB
3704 "lds %B0,%m1+1", op, plen, -n_words);
3707 fatal_insn ("unknown move insn:",insn);
3708 return "";
3711 static const char*
3712 avr_out_movsi_r_mr_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *l)
3714 rtx dest = op[0];
3715 rtx src = op[1];
3716 rtx base = XEXP (src, 0);
3717 int reg_dest = true_regnum (dest);
3718 int reg_base = true_regnum (base);
3720 if (reg_dest == reg_base)
3722 /* "ld r26,-X" is undefined */
3723 return *l = 9, (TINY_ADIW (%E1, %F1, 3) CR_TAB
3724 "ld %D0,%1" CR_TAB
3725 "ld %C0,-%1" CR_TAB
3726 "ld __tmp_reg__,-%1" CR_TAB
3727 TINY_SBIW (%E1, %F1, 1) CR_TAB
3728 "ld %A0,%1" CR_TAB
3729 "mov %B0,__tmp_reg__");
3731 else if (reg_dest == reg_base - 2)
3733 return *l = 5, ("ld %A0,%1+" CR_TAB
3734 "ld %B0,%1+" CR_TAB
3735 "ld __tmp_reg__,%1+" CR_TAB
3736 "ld %D0,%1" CR_TAB
3737 "mov %C0,__tmp_reg__");
3739 else if (reg_unused_after (insn, base))
3741 return *l = 4, ("ld %A0,%1+" CR_TAB
3742 "ld %B0,%1+" CR_TAB
3743 "ld %C0,%1+" CR_TAB
3744 "ld %D0,%1");
3746 else
3748 return *l = 6, ("ld %A0,%1+" CR_TAB
3749 "ld %B0,%1+" CR_TAB
3750 "ld %C0,%1+" CR_TAB
3751 "ld %D0,%1" CR_TAB
3752 TINY_SBIW (%E1, %F1, 3));
3757 static const char*
3758 avr_out_movsi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *l)
3760 rtx dest = op[0];
3761 rtx src = op[1];
3762 rtx base = XEXP (src, 0);
3763 int reg_dest = true_regnum (dest);
3764 int reg_base = true_regnum (XEXP (base, 0));
3766 if (reg_dest == reg_base)
3768 /* "ld r26,-X" is undefined */
3769 return *l = 9, (TINY_ADIW (%I1, %J1, %o1+3) CR_TAB
3770 "ld %D0,%b1" CR_TAB
3771 "ld %C0,-%b1" CR_TAB
3772 "ld __tmp_reg__,-%b1" CR_TAB
3773 TINY_SBIW (%I1, %J1, 1) CR_TAB
3774 "ld %A0,%b1" CR_TAB
3775 "mov %B0,__tmp_reg__");
3777 else if (reg_dest == reg_base - 2)
3779 return *l = 7, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
3780 "ld %A0,%b1+" CR_TAB
3781 "ld %B0,%b1+" CR_TAB
3782 "ld __tmp_reg__,%b1+" CR_TAB
3783 "ld %D0,%b1" CR_TAB
3784 "mov %C0,__tmp_reg__");
3786 else if (reg_unused_after (insn, XEXP (base, 0)))
3788 return *l = 6, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
3789 "ld %A0,%b1+" CR_TAB
3790 "ld %B0,%b1+" CR_TAB
3791 "ld %C0,%b1+" CR_TAB
3792 "ld %D0,%b1");
3794 else
3796 return *l = 8, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
3797 "ld %A0,%b1+" CR_TAB
3798 "ld %B0,%b1+" CR_TAB
3799 "ld %C0,%b1+" CR_TAB
3800 "ld %D0,%b1" CR_TAB
3801 TINY_SBIW (%I1, %J1, %o1+3));
3805 static const char*
3806 out_movsi_r_mr (rtx_insn *insn, rtx op[], int *l)
3808 rtx dest = op[0];
3809 rtx src = op[1];
3810 rtx base = XEXP (src, 0);
3811 int reg_dest = true_regnum (dest);
3812 int reg_base = true_regnum (base);
3813 int tmp;
3815 if (!l)
3816 l = &tmp;
3818 if (reg_base > 0)
3820 if (AVR_TINY)
3821 return avr_out_movsi_r_mr_reg_no_disp_tiny (insn, op, l);
3823 if (reg_base == REG_X) /* (R26) */
3825 if (reg_dest == REG_X)
3826 /* "ld r26,-X" is undefined */
3827 return *l=7, ("adiw r26,3" CR_TAB
3828 "ld r29,X" CR_TAB
3829 "ld r28,-X" CR_TAB
3830 "ld __tmp_reg__,-X" CR_TAB
3831 "sbiw r26,1" CR_TAB
3832 "ld r26,X" CR_TAB
3833 "mov r27,__tmp_reg__");
3834 else if (reg_dest == REG_X - 2)
3835 return *l=5, ("ld %A0,X+" CR_TAB
3836 "ld %B0,X+" CR_TAB
3837 "ld __tmp_reg__,X+" CR_TAB
3838 "ld %D0,X" CR_TAB
3839 "mov %C0,__tmp_reg__");
3840 else if (reg_unused_after (insn, base))
3841 return *l=4, ("ld %A0,X+" CR_TAB
3842 "ld %B0,X+" CR_TAB
3843 "ld %C0,X+" CR_TAB
3844 "ld %D0,X");
3845 else
3846 return *l=5, ("ld %A0,X+" CR_TAB
3847 "ld %B0,X+" CR_TAB
3848 "ld %C0,X+" CR_TAB
3849 "ld %D0,X" CR_TAB
3850 "sbiw r26,3");
3852 else
3854 if (reg_dest == reg_base)
3855 return *l=5, ("ldd %D0,%1+3" CR_TAB
3856 "ldd %C0,%1+2" CR_TAB
3857 "ldd __tmp_reg__,%1+1" CR_TAB
3858 "ld %A0,%1" CR_TAB
3859 "mov %B0,__tmp_reg__");
3860 else if (reg_base == reg_dest + 2)
3861 return *l=5, ("ld %A0,%1" CR_TAB
3862 "ldd %B0,%1+1" CR_TAB
3863 "ldd __tmp_reg__,%1+2" CR_TAB
3864 "ldd %D0,%1+3" CR_TAB
3865 "mov %C0,__tmp_reg__");
3866 else
3867 return *l=4, ("ld %A0,%1" CR_TAB
3868 "ldd %B0,%1+1" CR_TAB
3869 "ldd %C0,%1+2" CR_TAB
3870 "ldd %D0,%1+3");
3873 else if (GET_CODE (base) == PLUS) /* (R + i) */
3875 int disp = INTVAL (XEXP (base, 1));
3877 if (AVR_TINY)
3878 return avr_out_movsi_r_mr_reg_disp_tiny (insn, op, l);
3880 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
3882 if (REGNO (XEXP (base, 0)) != REG_Y)
3883 fatal_insn ("incorrect insn:",insn);
3885 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
3886 return *l = 6, ("adiw r28,%o1-60" CR_TAB
3887 "ldd %A0,Y+60" CR_TAB
3888 "ldd %B0,Y+61" CR_TAB
3889 "ldd %C0,Y+62" CR_TAB
3890 "ldd %D0,Y+63" CR_TAB
3891 "sbiw r28,%o1-60");
3893 return *l = 8, ("subi r28,lo8(-%o1)" CR_TAB
3894 "sbci r29,hi8(-%o1)" CR_TAB
3895 "ld %A0,Y" CR_TAB
3896 "ldd %B0,Y+1" CR_TAB
3897 "ldd %C0,Y+2" CR_TAB
3898 "ldd %D0,Y+3" CR_TAB
3899 "subi r28,lo8(%o1)" CR_TAB
3900 "sbci r29,hi8(%o1)");
3903 reg_base = true_regnum (XEXP (base, 0));
3904 if (reg_base == REG_X)
3906 /* R = (X + d) */
3907 if (reg_dest == REG_X)
3909 *l = 7;
3910 /* "ld r26,-X" is undefined */
3911 return ("adiw r26,%o1+3" CR_TAB
3912 "ld r29,X" CR_TAB
3913 "ld r28,-X" CR_TAB
3914 "ld __tmp_reg__,-X" CR_TAB
3915 "sbiw r26,1" CR_TAB
3916 "ld r26,X" CR_TAB
3917 "mov r27,__tmp_reg__");
3919 *l = 6;
3920 if (reg_dest == REG_X - 2)
3921 return ("adiw r26,%o1" CR_TAB
3922 "ld r24,X+" CR_TAB
3923 "ld r25,X+" CR_TAB
3924 "ld __tmp_reg__,X+" CR_TAB
3925 "ld r27,X" CR_TAB
3926 "mov r26,__tmp_reg__");
3928 return ("adiw r26,%o1" CR_TAB
3929 "ld %A0,X+" CR_TAB
3930 "ld %B0,X+" CR_TAB
3931 "ld %C0,X+" CR_TAB
3932 "ld %D0,X" CR_TAB
3933 "sbiw r26,%o1+3");
3935 if (reg_dest == reg_base)
3936 return *l=5, ("ldd %D0,%D1" CR_TAB
3937 "ldd %C0,%C1" CR_TAB
3938 "ldd __tmp_reg__,%B1" CR_TAB
3939 "ldd %A0,%A1" CR_TAB
3940 "mov %B0,__tmp_reg__");
3941 else if (reg_dest == reg_base - 2)
3942 return *l=5, ("ldd %A0,%A1" CR_TAB
3943 "ldd %B0,%B1" CR_TAB
3944 "ldd __tmp_reg__,%C1" CR_TAB
3945 "ldd %D0,%D1" CR_TAB
3946 "mov %C0,__tmp_reg__");
3947 return *l=4, ("ldd %A0,%A1" CR_TAB
3948 "ldd %B0,%B1" CR_TAB
3949 "ldd %C0,%C1" CR_TAB
3950 "ldd %D0,%D1");
3952 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
3953 return *l=4, ("ld %D0,%1" CR_TAB
3954 "ld %C0,%1" CR_TAB
3955 "ld %B0,%1" CR_TAB
3956 "ld %A0,%1");
3957 else if (GET_CODE (base) == POST_INC) /* (R++) */
3958 return *l=4, ("ld %A0,%1" CR_TAB
3959 "ld %B0,%1" CR_TAB
3960 "ld %C0,%1" CR_TAB
3961 "ld %D0,%1");
3962 else if (CONSTANT_ADDRESS_P (base))
3964 if (io_address_operand (base, SImode))
3966 *l = 4;
3967 return ("in %A0,%i1" CR_TAB
3968 "in %B0,%i1+1" CR_TAB
3969 "in %C0,%i1+2" CR_TAB
3970 "in %D0,%i1+3");
3972 else
3974 *l = AVR_TINY ? 4 : 8;
3975 return ("lds %A0,%m1" CR_TAB
3976 "lds %B0,%m1+1" CR_TAB
3977 "lds %C0,%m1+2" CR_TAB
3978 "lds %D0,%m1+3");
3982 fatal_insn ("unknown move insn:",insn);
3983 return "";
3986 static const char*
3987 avr_out_movsi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *l)
3989 rtx dest = op[0];
3990 rtx src = op[1];
3991 rtx base = XEXP (dest, 0);
3992 int reg_base = true_regnum (base);
3993 int reg_src = true_regnum (src);
3995 if (reg_base == reg_src)
3997 /* "ld r26,-X" is undefined */
3998 if (reg_unused_after (insn, base))
4000 return *l = 7, ("mov __tmp_reg__, %B1" CR_TAB
4001 "st %0,%A1" CR_TAB
4002 TINY_ADIW (%E0, %F0, 1) CR_TAB
4003 "st %0+,__tmp_reg__" CR_TAB
4004 "st %0+,%C1" CR_TAB
4005 "st %0+,%D1");
4007 else
4009 return *l = 9, ("mov __tmp_reg__, %B1" CR_TAB
4010 "st %0,%A1" CR_TAB
4011 TINY_ADIW (%E0, %F0, 1) CR_TAB
4012 "st %0+,__tmp_reg__" CR_TAB
4013 "st %0+,%C1" CR_TAB
4014 "st %0+,%D1" CR_TAB
4015 TINY_SBIW (%E0, %F0, 3));
4018 else if (reg_base == reg_src + 2)
4020 if (reg_unused_after (insn, base))
4021 return *l = 7, ("mov __zero_reg__,%C1" CR_TAB
4022 "mov __tmp_reg__,%D1" CR_TAB
4023 "st %0+,%A1" CR_TAB
4024 "st %0+,%B1" CR_TAB
4025 "st %0+,__zero_reg__" CR_TAB
4026 "st %0,__tmp_reg__" CR_TAB
4027 "clr __zero_reg__");
4028 else
4029 return *l = 9, ("mov __zero_reg__,%C1" CR_TAB
4030 "mov __tmp_reg__,%D1" CR_TAB
4031 "st %0+,%A1" CR_TAB
4032 "st %0+,%B1" CR_TAB
4033 "st %0+,__zero_reg__" CR_TAB
4034 "st %0,__tmp_reg__" CR_TAB
4035 "clr __zero_reg__" CR_TAB
4036 TINY_SBIW (%E0, %F0, 3));
4039 return *l = 6, ("st %0+,%A1" CR_TAB
4040 "st %0+,%B1" CR_TAB
4041 "st %0+,%C1" CR_TAB
4042 "st %0,%D1" CR_TAB
4043 TINY_SBIW (%E0, %F0, 3));
4046 static const char*
4047 avr_out_movsi_mr_r_reg_disp_tiny (rtx op[], int *l)
4049 rtx dest = op[0];
4050 rtx src = op[1];
4051 rtx base = XEXP (dest, 0);
4052 int reg_base = REGNO (XEXP (base, 0));
4053 int reg_src =true_regnum (src);
4055 if (reg_base == reg_src)
4057 *l = 11;
4058 return ("mov __tmp_reg__,%A2" CR_TAB
4059 "mov __zero_reg__,%B2" CR_TAB
4060 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4061 "st %b0+,__tmp_reg__" CR_TAB
4062 "st %b0+,__zero_reg__" CR_TAB
4063 "st %b0+,%C2" CR_TAB
4064 "st %b0,%D2" CR_TAB
4065 "clr __zero_reg__" CR_TAB
4066 TINY_SBIW (%I0, %J0, %o0+3));
4068 else if (reg_src == reg_base - 2)
4070 *l = 11;
4071 return ("mov __tmp_reg__,%C2" CR_TAB
4072 "mov __zero_reg__,%D2" CR_TAB
4073 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4074 "st %b0+,%A0" CR_TAB
4075 "st %b0+,%B0" CR_TAB
4076 "st %b0+,__tmp_reg__" CR_TAB
4077 "st %b0,__zero_reg__" CR_TAB
4078 "clr __zero_reg__" CR_TAB
4079 TINY_SBIW (%I0, %J0, %o0+3));
4081 *l = 8;
4082 return (TINY_ADIW (%I0, %J0, %o0) CR_TAB
4083 "st %b0+,%A1" CR_TAB
4084 "st %b0+,%B1" CR_TAB
4085 "st %b0+,%C1" CR_TAB
4086 "st %b0,%D1" CR_TAB
4087 TINY_SBIW (%I0, %J0, %o0+3));
4090 static const char*
4091 out_movsi_mr_r (rtx_insn *insn, rtx op[], int *l)
4093 rtx dest = op[0];
4094 rtx src = op[1];
4095 rtx base = XEXP (dest, 0);
4096 int reg_base = true_regnum (base);
4097 int reg_src = true_regnum (src);
4098 int tmp;
4100 if (!l)
4101 l = &tmp;
4103 if (CONSTANT_ADDRESS_P (base))
4105 if (io_address_operand (base, SImode))
4107 return *l=4,("out %i0, %A1" CR_TAB
4108 "out %i0+1,%B1" CR_TAB
4109 "out %i0+2,%C1" CR_TAB
4110 "out %i0+3,%D1");
4112 else
4114 *l = AVR_TINY ? 4 : 8;
4115 return ("sts %m0,%A1" CR_TAB
4116 "sts %m0+1,%B1" CR_TAB
4117 "sts %m0+2,%C1" CR_TAB
4118 "sts %m0+3,%D1");
4122 if (reg_base > 0) /* (r) */
4124 if (AVR_TINY)
4125 return avr_out_movsi_mr_r_reg_no_disp_tiny (insn, op, l);
4127 if (reg_base == REG_X) /* (R26) */
4129 if (reg_src == REG_X)
4131 /* "st X+,r26" is undefined */
4132 if (reg_unused_after (insn, base))
4133 return *l=6, ("mov __tmp_reg__,r27" CR_TAB
4134 "st X,r26" CR_TAB
4135 "adiw r26,1" CR_TAB
4136 "st X+,__tmp_reg__" CR_TAB
4137 "st X+,r28" CR_TAB
4138 "st X,r29");
4139 else
4140 return *l=7, ("mov __tmp_reg__,r27" CR_TAB
4141 "st X,r26" CR_TAB
4142 "adiw r26,1" CR_TAB
4143 "st X+,__tmp_reg__" CR_TAB
4144 "st X+,r28" CR_TAB
4145 "st X,r29" CR_TAB
4146 "sbiw r26,3");
4148 else if (reg_base == reg_src + 2)
4150 if (reg_unused_after (insn, base))
4151 return *l=7, ("mov __zero_reg__,%C1" CR_TAB
4152 "mov __tmp_reg__,%D1" CR_TAB
4153 "st %0+,%A1" CR_TAB
4154 "st %0+,%B1" CR_TAB
4155 "st %0+,__zero_reg__" CR_TAB
4156 "st %0,__tmp_reg__" CR_TAB
4157 "clr __zero_reg__");
4158 else
4159 return *l=8, ("mov __zero_reg__,%C1" CR_TAB
4160 "mov __tmp_reg__,%D1" CR_TAB
4161 "st %0+,%A1" CR_TAB
4162 "st %0+,%B1" CR_TAB
4163 "st %0+,__zero_reg__" CR_TAB
4164 "st %0,__tmp_reg__" CR_TAB
4165 "clr __zero_reg__" CR_TAB
4166 "sbiw r26,3");
4168 return *l=5, ("st %0+,%A1" CR_TAB
4169 "st %0+,%B1" CR_TAB
4170 "st %0+,%C1" CR_TAB
4171 "st %0,%D1" CR_TAB
4172 "sbiw r26,3");
4174 else
4175 return *l=4, ("st %0,%A1" CR_TAB
4176 "std %0+1,%B1" CR_TAB
4177 "std %0+2,%C1" CR_TAB
4178 "std %0+3,%D1");
4180 else if (GET_CODE (base) == PLUS) /* (R + i) */
4182 int disp = INTVAL (XEXP (base, 1));
4184 if (AVR_TINY)
4185 return avr_out_movsi_mr_r_reg_disp_tiny (op, l);
4187 reg_base = REGNO (XEXP (base, 0));
4188 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
4190 if (reg_base != REG_Y)
4191 fatal_insn ("incorrect insn:",insn);
4193 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
4194 return *l = 6, ("adiw r28,%o0-60" CR_TAB
4195 "std Y+60,%A1" CR_TAB
4196 "std Y+61,%B1" CR_TAB
4197 "std Y+62,%C1" CR_TAB
4198 "std Y+63,%D1" CR_TAB
4199 "sbiw r28,%o0-60");
4201 return *l = 8, ("subi r28,lo8(-%o0)" CR_TAB
4202 "sbci r29,hi8(-%o0)" CR_TAB
4203 "st Y,%A1" CR_TAB
4204 "std Y+1,%B1" CR_TAB
4205 "std Y+2,%C1" CR_TAB
4206 "std Y+3,%D1" CR_TAB
4207 "subi r28,lo8(%o0)" CR_TAB
4208 "sbci r29,hi8(%o0)");
4210 if (reg_base == REG_X)
4212 /* (X + d) = R */
4213 if (reg_src == REG_X)
4215 *l = 9;
4216 return ("mov __tmp_reg__,r26" CR_TAB
4217 "mov __zero_reg__,r27" CR_TAB
4218 "adiw r26,%o0" CR_TAB
4219 "st X+,__tmp_reg__" CR_TAB
4220 "st X+,__zero_reg__" CR_TAB
4221 "st X+,r28" CR_TAB
4222 "st X,r29" CR_TAB
4223 "clr __zero_reg__" CR_TAB
4224 "sbiw r26,%o0+3");
4226 else if (reg_src == REG_X - 2)
4228 *l = 9;
4229 return ("mov __tmp_reg__,r26" CR_TAB
4230 "mov __zero_reg__,r27" CR_TAB
4231 "adiw r26,%o0" CR_TAB
4232 "st X+,r24" CR_TAB
4233 "st X+,r25" CR_TAB
4234 "st X+,__tmp_reg__" CR_TAB
4235 "st X,__zero_reg__" CR_TAB
4236 "clr __zero_reg__" CR_TAB
4237 "sbiw r26,%o0+3");
4239 *l = 6;
4240 return ("adiw r26,%o0" CR_TAB
4241 "st X+,%A1" CR_TAB
4242 "st X+,%B1" CR_TAB
4243 "st X+,%C1" CR_TAB
4244 "st X,%D1" CR_TAB
4245 "sbiw r26,%o0+3");
4247 return *l=4, ("std %A0,%A1" CR_TAB
4248 "std %B0,%B1" CR_TAB
4249 "std %C0,%C1" CR_TAB
4250 "std %D0,%D1");
4252 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4253 return *l=4, ("st %0,%D1" CR_TAB
4254 "st %0,%C1" CR_TAB
4255 "st %0,%B1" CR_TAB
4256 "st %0,%A1");
4257 else if (GET_CODE (base) == POST_INC) /* (R++) */
4258 return *l=4, ("st %0,%A1" CR_TAB
4259 "st %0,%B1" CR_TAB
4260 "st %0,%C1" CR_TAB
4261 "st %0,%D1");
4262 fatal_insn ("unknown move insn:",insn);
4263 return "";
4266 const char *
4267 output_movsisf (rtx_insn *insn, rtx operands[], int *l)
4269 int dummy;
4270 rtx dest = operands[0];
4271 rtx src = operands[1];
4272 int *real_l = l;
4274 if (avr_mem_flash_p (src)
4275 || avr_mem_flash_p (dest))
4277 return avr_out_lpm (insn, operands, real_l);
4280 if (!l)
4281 l = &dummy;
4283 gcc_assert (4 == GET_MODE_SIZE (GET_MODE (dest)));
4284 if (REG_P (dest))
4286 if (REG_P (src)) /* mov r,r */
4288 if (true_regnum (dest) > true_regnum (src))
4290 if (AVR_HAVE_MOVW)
4292 *l = 2;
4293 return ("movw %C0,%C1" CR_TAB
4294 "movw %A0,%A1");
4296 *l = 4;
4297 return ("mov %D0,%D1" CR_TAB
4298 "mov %C0,%C1" CR_TAB
4299 "mov %B0,%B1" CR_TAB
4300 "mov %A0,%A1");
4302 else
4304 if (AVR_HAVE_MOVW)
4306 *l = 2;
4307 return ("movw %A0,%A1" CR_TAB
4308 "movw %C0,%C1");
4310 *l = 4;
4311 return ("mov %A0,%A1" CR_TAB
4312 "mov %B0,%B1" CR_TAB
4313 "mov %C0,%C1" CR_TAB
4314 "mov %D0,%D1");
4317 else if (CONSTANT_P (src))
4319 return output_reload_insisf (operands, NULL_RTX, real_l);
4321 else if (MEM_P (src))
4322 return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
4324 else if (MEM_P (dest))
4326 const char *templ;
4328 if (src == CONST0_RTX (GET_MODE (dest)))
4329 operands[1] = zero_reg_rtx;
4331 templ = out_movsi_mr_r (insn, operands, real_l);
4333 if (!real_l)
4334 output_asm_insn (templ, operands);
4336 operands[1] = src;
4337 return "";
4339 fatal_insn ("invalid insn:", insn);
4340 return "";
4344 /* Handle loads of 24-bit types from memory to register. */
4346 static const char*
4347 avr_out_load_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
4349 rtx dest = op[0];
4350 rtx src = op[1];
4351 rtx base = XEXP (src, 0);
4352 int reg_dest = true_regnum (dest);
4353 int reg_base = true_regnum (base);
4355 if (reg_base == reg_dest)
4357 return avr_asm_len (TINY_ADIW (%E1, %F1, 2) CR_TAB
4358 "ld %C0,%1" CR_TAB
4359 "ld __tmp_reg__,-%1" CR_TAB
4360 TINY_SBIW (%E1, %F1, 1) CR_TAB
4361 "ld %A0,%1" CR_TAB
4362 "mov %B0,__tmp_reg__", op, plen, -8);
4364 else
4366 avr_asm_len ("ld %A0,%1+" CR_TAB
4367 "ld %B0,%1+" CR_TAB
4368 "ld %C0,%1", op, plen, -3);
4370 if (reg_dest != reg_base - 2 &&
4371 !reg_unused_after (insn, base))
4373 avr_asm_len (TINY_SBIW (%E1, %F1, 2), op, plen, 2);
4375 return "";
4379 static const char*
4380 avr_out_load_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
4382 rtx dest = op[0];
4383 rtx src = op[1];
4384 rtx base = XEXP (src, 0);
4385 int reg_dest = true_regnum (dest);
4386 int reg_base = true_regnum (base);
4388 reg_base = true_regnum (XEXP (base, 0));
4389 if (reg_base == reg_dest)
4391 return avr_asm_len (TINY_ADIW (%I1, %J1, %o1+2) CR_TAB
4392 "ld %C0,%b1" CR_TAB
4393 "ld __tmp_reg__,-%b1" CR_TAB
4394 TINY_SBIW (%I1, %J1, 1) CR_TAB
4395 "ld %A0,%b1" CR_TAB
4396 "mov %B0,__tmp_reg__", op, plen, -8);
4398 else
4400 avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4401 "ld %A0,%b1+" CR_TAB
4402 "ld %B0,%b1+" CR_TAB
4403 "ld %C0,%b1", op, plen, -5);
4405 if (reg_dest != (reg_base - 2)
4406 && !reg_unused_after (insn, XEXP (base, 0)))
4407 avr_asm_len (TINY_SBIW (%I1, %J1, %o1+2), op, plen, 2);
4409 return "";
4413 static const char*
4414 avr_out_load_psi (rtx_insn *insn, rtx *op, int *plen)
4416 rtx dest = op[0];
4417 rtx src = op[1];
4418 rtx base = XEXP (src, 0);
4419 int reg_dest = true_regnum (dest);
4420 int reg_base = true_regnum (base);
4422 if (reg_base > 0)
4424 if (AVR_TINY)
4425 return avr_out_load_psi_reg_no_disp_tiny (insn, op, plen);
4427 if (reg_base == REG_X) /* (R26) */
4429 if (reg_dest == REG_X)
4430 /* "ld r26,-X" is undefined */
4431 return avr_asm_len ("adiw r26,2" CR_TAB
4432 "ld r28,X" CR_TAB
4433 "ld __tmp_reg__,-X" CR_TAB
4434 "sbiw r26,1" CR_TAB
4435 "ld r26,X" CR_TAB
4436 "mov r27,__tmp_reg__", op, plen, -6);
4437 else
4439 avr_asm_len ("ld %A0,X+" CR_TAB
4440 "ld %B0,X+" CR_TAB
4441 "ld %C0,X", op, plen, -3);
4443 if (reg_dest != REG_X - 2
4444 && !reg_unused_after (insn, base))
4446 avr_asm_len ("sbiw r26,2", op, plen, 1);
4449 return "";
4452 else /* reg_base != REG_X */
4454 if (reg_dest == reg_base)
4455 return avr_asm_len ("ldd %C0,%1+2" CR_TAB
4456 "ldd __tmp_reg__,%1+1" CR_TAB
4457 "ld %A0,%1" CR_TAB
4458 "mov %B0,__tmp_reg__", op, plen, -4);
4459 else
4460 return avr_asm_len ("ld %A0,%1" CR_TAB
4461 "ldd %B0,%1+1" CR_TAB
4462 "ldd %C0,%1+2", op, plen, -3);
4465 else if (GET_CODE (base) == PLUS) /* (R + i) */
4467 int disp = INTVAL (XEXP (base, 1));
4469 if (AVR_TINY)
4470 return avr_out_load_psi_reg_disp_tiny (insn, op, plen);
4472 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
4474 if (REGNO (XEXP (base, 0)) != REG_Y)
4475 fatal_insn ("incorrect insn:",insn);
4477 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
4478 return avr_asm_len ("adiw r28,%o1-61" CR_TAB
4479 "ldd %A0,Y+61" CR_TAB
4480 "ldd %B0,Y+62" CR_TAB
4481 "ldd %C0,Y+63" CR_TAB
4482 "sbiw r28,%o1-61", op, plen, -5);
4484 return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
4485 "sbci r29,hi8(-%o1)" CR_TAB
4486 "ld %A0,Y" CR_TAB
4487 "ldd %B0,Y+1" CR_TAB
4488 "ldd %C0,Y+2" CR_TAB
4489 "subi r28,lo8(%o1)" CR_TAB
4490 "sbci r29,hi8(%o1)", op, plen, -7);
4493 reg_base = true_regnum (XEXP (base, 0));
4494 if (reg_base == REG_X)
4496 /* R = (X + d) */
4497 if (reg_dest == REG_X)
4499 /* "ld r26,-X" is undefined */
4500 return avr_asm_len ("adiw r26,%o1+2" CR_TAB
4501 "ld r28,X" CR_TAB
4502 "ld __tmp_reg__,-X" CR_TAB
4503 "sbiw r26,1" CR_TAB
4504 "ld r26,X" CR_TAB
4505 "mov r27,__tmp_reg__", op, plen, -6);
4508 avr_asm_len ("adiw r26,%o1" CR_TAB
4509 "ld %A0,X+" CR_TAB
4510 "ld %B0,X+" CR_TAB
4511 "ld %C0,X", op, plen, -4);
4513 if (reg_dest != REG_W
4514 && !reg_unused_after (insn, XEXP (base, 0)))
4515 avr_asm_len ("sbiw r26,%o1+2", op, plen, 1);
4517 return "";
4520 if (reg_dest == reg_base)
4521 return avr_asm_len ("ldd %C0,%C1" CR_TAB
4522 "ldd __tmp_reg__,%B1" CR_TAB
4523 "ldd %A0,%A1" CR_TAB
4524 "mov %B0,__tmp_reg__", op, plen, -4);
4526 return avr_asm_len ("ldd %A0,%A1" CR_TAB
4527 "ldd %B0,%B1" CR_TAB
4528 "ldd %C0,%C1", op, plen, -3);
4530 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4531 return avr_asm_len ("ld %C0,%1" CR_TAB
4532 "ld %B0,%1" CR_TAB
4533 "ld %A0,%1", op, plen, -3);
4534 else if (GET_CODE (base) == POST_INC) /* (R++) */
4535 return avr_asm_len ("ld %A0,%1" CR_TAB
4536 "ld %B0,%1" CR_TAB
4537 "ld %C0,%1", op, plen, -3);
4539 else if (CONSTANT_ADDRESS_P (base))
4541 int n_words = AVR_TINY ? 3 : 6;
4542 return avr_asm_len ("lds %A0,%m1" CR_TAB
4543 "lds %B0,%m1+1" CR_TAB
4544 "lds %C0,%m1+2", op, plen , -n_words);
4547 fatal_insn ("unknown move insn:",insn);
4548 return "";
4552 static const char*
4553 avr_out_store_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
4555 rtx dest = op[0];
4556 rtx src = op[1];
4557 rtx base = XEXP (dest, 0);
4558 int reg_base = true_regnum (base);
4559 int reg_src = true_regnum (src);
4561 if (reg_base == reg_src)
4563 avr_asm_len ("st %0,%A1" CR_TAB
4564 "mov __tmp_reg__,%B1" CR_TAB
4565 TINY_ADIW (%E0, %F0, 1) CR_TAB /* st X+, r27 is undefined */
4566 "st %0+,__tmp_reg__" CR_TAB
4567 "st %0,%C1", op, plen, -6);
4570 else if (reg_src == reg_base - 2)
4572 avr_asm_len ("st %0,%A1" CR_TAB
4573 "mov __tmp_reg__,%C1" CR_TAB
4574 TINY_ADIW (%E0, %F0, 1) CR_TAB
4575 "st %0+,%B1" CR_TAB
4576 "st %0,__tmp_reg__", op, plen, 6);
4578 else
4580 avr_asm_len ("st %0+,%A1" CR_TAB
4581 "st %0+,%B1" CR_TAB
4582 "st %0,%C1", op, plen, -3);
4585 if (!reg_unused_after (insn, base))
4586 avr_asm_len (TINY_SBIW (%E0, %F0, 2), op, plen, 2);
4588 return "";
4591 static const char*
4592 avr_out_store_psi_reg_disp_tiny (rtx *op, int *plen)
4594 rtx dest = op[0];
4595 rtx src = op[1];
4596 rtx base = XEXP (dest, 0);
4597 int reg_base = REGNO (XEXP (base, 0));
4598 int reg_src = true_regnum (src);
4600 if (reg_src == reg_base)
4602 return avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
4603 "mov __zero_reg__,%B1" CR_TAB
4604 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4605 "st %b0+,__tmp_reg__" CR_TAB
4606 "st %b0+,__zero_reg__" CR_TAB
4607 "st %b0,%C1" CR_TAB
4608 "clr __zero_reg__" CR_TAB
4609 TINY_SBIW (%I0, %J0, %o0+2), op, plen, -10);
4611 else if (reg_src == reg_base - 2)
4613 return avr_asm_len ("mov __tmp_reg__,%C1" CR_TAB
4614 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4615 "st %b0+,%A1" CR_TAB
4616 "st %b0+,%B1" CR_TAB
4617 "st %b0,__tmp_reg__" CR_TAB
4618 TINY_SBIW (%I0, %J0, %o0+2), op, plen, -8);
4621 return avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
4622 "st %b0+,%A1" CR_TAB
4623 "st %b0+,%B1" CR_TAB
4624 "st %b0,%C1" CR_TAB
4625 TINY_SBIW (%I0, %J0, %o0+2), op, plen, -7);
4628 /* Handle store of 24-bit type from register or zero to memory. */
4630 static const char*
4631 avr_out_store_psi (rtx_insn *insn, rtx *op, int *plen)
4633 rtx dest = op[0];
4634 rtx src = op[1];
4635 rtx base = XEXP (dest, 0);
4636 int reg_base = true_regnum (base);
4638 if (CONSTANT_ADDRESS_P (base))
4640 int n_words = AVR_TINY ? 3 : 6;
4641 return avr_asm_len ("sts %m0,%A1" CR_TAB
4642 "sts %m0+1,%B1" CR_TAB
4643 "sts %m0+2,%C1", op, plen, -n_words);
4646 if (reg_base > 0) /* (r) */
4648 if (AVR_TINY)
4649 return avr_out_store_psi_reg_no_disp_tiny (insn, op, plen);
4651 if (reg_base == REG_X) /* (R26) */
4653 gcc_assert (!reg_overlap_mentioned_p (base, src));
4655 avr_asm_len ("st %0+,%A1" CR_TAB
4656 "st %0+,%B1" CR_TAB
4657 "st %0,%C1", op, plen, -3);
4659 if (!reg_unused_after (insn, base))
4660 avr_asm_len ("sbiw r26,2", op, plen, 1);
4662 return "";
4664 else
4665 return avr_asm_len ("st %0,%A1" CR_TAB
4666 "std %0+1,%B1" CR_TAB
4667 "std %0+2,%C1", op, plen, -3);
4669 else if (GET_CODE (base) == PLUS) /* (R + i) */
4671 int disp = INTVAL (XEXP (base, 1));
4673 if (AVR_TINY)
4674 return avr_out_store_psi_reg_disp_tiny (op, plen);
4676 reg_base = REGNO (XEXP (base, 0));
4678 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
4680 if (reg_base != REG_Y)
4681 fatal_insn ("incorrect insn:",insn);
4683 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
4684 return avr_asm_len ("adiw r28,%o0-61" CR_TAB
4685 "std Y+61,%A1" CR_TAB
4686 "std Y+62,%B1" CR_TAB
4687 "std Y+63,%C1" CR_TAB
4688 "sbiw r28,%o0-61", op, plen, -5);
4690 return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
4691 "sbci r29,hi8(-%o0)" CR_TAB
4692 "st Y,%A1" CR_TAB
4693 "std Y+1,%B1" CR_TAB
4694 "std Y+2,%C1" CR_TAB
4695 "subi r28,lo8(%o0)" CR_TAB
4696 "sbci r29,hi8(%o0)", op, plen, -7);
4698 if (reg_base == REG_X)
4700 /* (X + d) = R */
4701 gcc_assert (!reg_overlap_mentioned_p (XEXP (base, 0), src));
4703 avr_asm_len ("adiw r26,%o0" CR_TAB
4704 "st X+,%A1" CR_TAB
4705 "st X+,%B1" CR_TAB
4706 "st X,%C1", op, plen, -4);
4708 if (!reg_unused_after (insn, XEXP (base, 0)))
4709 avr_asm_len ("sbiw r26,%o0+2", op, plen, 1);
4711 return "";
4714 return avr_asm_len ("std %A0,%A1" CR_TAB
4715 "std %B0,%B1" CR_TAB
4716 "std %C0,%C1", op, plen, -3);
4718 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4719 return avr_asm_len ("st %0,%C1" CR_TAB
4720 "st %0,%B1" CR_TAB
4721 "st %0,%A1", op, plen, -3);
4722 else if (GET_CODE (base) == POST_INC) /* (R++) */
4723 return avr_asm_len ("st %0,%A1" CR_TAB
4724 "st %0,%B1" CR_TAB
4725 "st %0,%C1", op, plen, -3);
4727 fatal_insn ("unknown move insn:",insn);
4728 return "";
4732 /* Move around 24-bit stuff. */
4734 const char *
4735 avr_out_movpsi (rtx_insn *insn, rtx *op, int *plen)
4737 rtx dest = op[0];
4738 rtx src = op[1];
4740 if (avr_mem_flash_p (src)
4741 || avr_mem_flash_p (dest))
4743 return avr_out_lpm (insn, op, plen);
4746 if (register_operand (dest, VOIDmode))
4748 if (register_operand (src, VOIDmode)) /* mov r,r */
4750 if (true_regnum (dest) > true_regnum (src))
4752 avr_asm_len ("mov %C0,%C1", op, plen, -1);
4754 if (AVR_HAVE_MOVW)
4755 return avr_asm_len ("movw %A0,%A1", op, plen, 1);
4756 else
4757 return avr_asm_len ("mov %B0,%B1" CR_TAB
4758 "mov %A0,%A1", op, plen, 2);
4760 else
4762 if (AVR_HAVE_MOVW)
4763 avr_asm_len ("movw %A0,%A1", op, plen, -1);
4764 else
4765 avr_asm_len ("mov %A0,%A1" CR_TAB
4766 "mov %B0,%B1", op, plen, -2);
4768 return avr_asm_len ("mov %C0,%C1", op, plen, 1);
4771 else if (CONSTANT_P (src))
4773 return avr_out_reload_inpsi (op, NULL_RTX, plen);
4775 else if (MEM_P (src))
4776 return avr_out_load_psi (insn, op, plen); /* mov r,m */
4778 else if (MEM_P (dest))
4780 rtx xop[2];
4782 xop[0] = dest;
4783 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
4785 return avr_out_store_psi (insn, xop, plen);
4788 fatal_insn ("invalid insn:", insn);
4789 return "";
4792 static const char*
4793 avr_out_movqi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
4795 rtx dest = op[0];
4796 rtx src = op[1];
4797 rtx x = XEXP (dest, 0);
4799 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
4801 avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
4802 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4803 "st %b0,__tmp_reg__", op, plen, -4);
4805 else
4807 avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
4808 "st %b0,%1" , op, plen, -3);
4811 if (!reg_unused_after (insn, XEXP (x,0)))
4812 avr_asm_len (TINY_SBIW (%I0, %J0, %o0), op, plen, 2);
4814 return "";
4817 static const char*
4818 out_movqi_mr_r (rtx_insn *insn, rtx op[], int *plen)
4820 rtx dest = op[0];
4821 rtx src = op[1];
4822 rtx x = XEXP (dest, 0);
4824 if (CONSTANT_ADDRESS_P (x))
4826 int n_words = AVR_TINY ? 1 : 2;
4827 return optimize > 0 && io_address_operand (x, QImode)
4828 ? avr_asm_len ("out %i0,%1", op, plen, -1)
4829 : avr_asm_len ("sts %m0,%1", op, plen, -n_words);
4831 else if (GET_CODE (x) == PLUS
4832 && REG_P (XEXP (x, 0))
4833 && CONST_INT_P (XEXP (x, 1)))
4835 /* memory access by reg+disp */
4837 int disp = INTVAL (XEXP (x, 1));
4839 if (AVR_TINY)
4840 return avr_out_movqi_mr_r_reg_disp_tiny (insn, op, plen);
4842 if (disp - GET_MODE_SIZE (GET_MODE (dest)) >= 63)
4844 if (REGNO (XEXP (x, 0)) != REG_Y)
4845 fatal_insn ("incorrect insn:",insn);
4847 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
4848 return avr_asm_len ("adiw r28,%o0-63" CR_TAB
4849 "std Y+63,%1" CR_TAB
4850 "sbiw r28,%o0-63", op, plen, -3);
4852 return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
4853 "sbci r29,hi8(-%o0)" CR_TAB
4854 "st Y,%1" CR_TAB
4855 "subi r28,lo8(%o0)" CR_TAB
4856 "sbci r29,hi8(%o0)", op, plen, -5);
4858 else if (REGNO (XEXP (x,0)) == REG_X)
4860 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
4862 avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
4863 "adiw r26,%o0" CR_TAB
4864 "st X,__tmp_reg__", op, plen, -3);
4866 else
4868 avr_asm_len ("adiw r26,%o0" CR_TAB
4869 "st X,%1", op, plen, -2);
4872 if (!reg_unused_after (insn, XEXP (x,0)))
4873 avr_asm_len ("sbiw r26,%o0", op, plen, 1);
4875 return "";
4878 return avr_asm_len ("std %0,%1", op, plen, -1);
4881 return avr_asm_len ("st %0,%1", op, plen, -1);
4885 /* Helper for the next function for XMEGA. It does the same
4886 but with low byte first. */
4888 static const char*
4889 avr_out_movhi_mr_r_xmega (rtx_insn *insn, rtx op[], int *plen)
4891 rtx dest = op[0];
4892 rtx src = op[1];
4893 rtx base = XEXP (dest, 0);
4894 int reg_base = true_regnum (base);
4895 int reg_src = true_regnum (src);
4897 /* "volatile" forces writing low byte first, even if less efficient,
4898 for correct operation with 16-bit I/O registers like SP. */
4899 int mem_volatile_p = MEM_VOLATILE_P (dest);
4901 if (CONSTANT_ADDRESS_P (base))
4903 int n_words = AVR_TINY ? 2 : 4;
4904 return optimize > 0 && io_address_operand (base, HImode)
4905 ? avr_asm_len ("out %i0,%A1" CR_TAB
4906 "out %i0+1,%B1", op, plen, -2)
4908 : avr_asm_len ("sts %m0,%A1" CR_TAB
4909 "sts %m0+1,%B1", op, plen, -n_words);
4912 if (reg_base > 0)
4914 if (reg_base != REG_X)
4915 return avr_asm_len ("st %0,%A1" CR_TAB
4916 "std %0+1,%B1", op, plen, -2);
4918 if (reg_src == REG_X)
4919 /* "st X+,r26" and "st -X,r26" are undefined. */
4920 avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
4921 "st X,r26" CR_TAB
4922 "adiw r26,1" CR_TAB
4923 "st X,__tmp_reg__", op, plen, -4);
4924 else
4925 avr_asm_len ("st X+,%A1" CR_TAB
4926 "st X,%B1", op, plen, -2);
4928 return reg_unused_after (insn, base)
4929 ? ""
4930 : avr_asm_len ("sbiw r26,1", op, plen, 1);
4932 else if (GET_CODE (base) == PLUS)
4934 int disp = INTVAL (XEXP (base, 1));
4935 reg_base = REGNO (XEXP (base, 0));
4936 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
4938 if (reg_base != REG_Y)
4939 fatal_insn ("incorrect insn:",insn);
4941 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
4942 ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
4943 "std Y+62,%A1" CR_TAB
4944 "std Y+63,%B1" CR_TAB
4945 "sbiw r28,%o0-62", op, plen, -4)
4947 : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
4948 "sbci r29,hi8(-%o0)" CR_TAB
4949 "st Y,%A1" CR_TAB
4950 "std Y+1,%B1" CR_TAB
4951 "subi r28,lo8(%o0)" CR_TAB
4952 "sbci r29,hi8(%o0)", op, plen, -6);
4955 if (reg_base != REG_X)
4956 return avr_asm_len ("std %A0,%A1" CR_TAB
4957 "std %B0,%B1", op, plen, -2);
4958 /* (X + d) = R */
4959 return reg_src == REG_X
4960 ? avr_asm_len ("mov __tmp_reg__,r26" CR_TAB
4961 "mov __zero_reg__,r27" CR_TAB
4962 "adiw r26,%o0" CR_TAB
4963 "st X+,__tmp_reg__" CR_TAB
4964 "st X,__zero_reg__" CR_TAB
4965 "clr __zero_reg__" CR_TAB
4966 "sbiw r26,%o0+1", op, plen, -7)
4968 : avr_asm_len ("adiw r26,%o0" CR_TAB
4969 "st X+,%A1" CR_TAB
4970 "st X,%B1" CR_TAB
4971 "sbiw r26,%o0+1", op, plen, -4);
4973 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4975 if (!mem_volatile_p)
4976 return avr_asm_len ("st %0,%B1" CR_TAB
4977 "st %0,%A1", op, plen, -2);
4979 return REGNO (XEXP (base, 0)) == REG_X
4980 ? avr_asm_len ("sbiw r26,2" CR_TAB
4981 "st X+,%A1" CR_TAB
4982 "st X,%B1" CR_TAB
4983 "sbiw r26,1", op, plen, -4)
4985 : avr_asm_len ("sbiw %r0,2" CR_TAB
4986 "st %p0,%A1" CR_TAB
4987 "std %p0+1,%B1", op, plen, -3);
4989 else if (GET_CODE (base) == POST_INC) /* (R++) */
4991 return avr_asm_len ("st %0,%A1" CR_TAB
4992 "st %0,%B1", op, plen, -2);
4995 fatal_insn ("unknown move insn:",insn);
4996 return "";
4999 static const char*
5000 avr_out_movhi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5002 rtx dest = op[0];
5003 rtx src = op[1];
5004 rtx base = XEXP (dest, 0);
5005 int reg_base = true_regnum (base);
5006 int reg_src = true_regnum (src);
5007 int mem_volatile_p = MEM_VOLATILE_P (dest);
5009 if (reg_base == reg_src)
5011 return !mem_volatile_p && reg_unused_after (insn, src)
5012 ? avr_asm_len ("mov __tmp_reg__,%B1" CR_TAB
5013 "st %0,%A1" CR_TAB
5014 TINY_ADIW (%E0, %F0, 1) CR_TAB
5015 "st %0,__tmp_reg__", op, plen, -5)
5016 : avr_asm_len ("mov __tmp_reg__,%B1" CR_TAB
5017 TINY_ADIW (%E0, %F0, 1) CR_TAB
5018 "st %0,__tmp_reg__" CR_TAB
5019 TINY_SBIW (%E0, %F0, 1) CR_TAB
5020 "st %0, %A1", op, plen, -7);
5023 return !mem_volatile_p && reg_unused_after (insn, base)
5024 ? avr_asm_len ("st %0+,%A1" CR_TAB
5025 "st %0,%B1", op, plen, -2)
5026 : avr_asm_len (TINY_ADIW (%E0, %F0, 1) CR_TAB
5027 "st %0,%B1" CR_TAB
5028 "st -%0,%A1", op, plen, -4);
5031 static const char*
5032 avr_out_movhi_mr_r_reg_disp_tiny (rtx op[], int *plen)
5034 rtx dest = op[0];
5035 rtx src = op[1];
5036 rtx base = XEXP (dest, 0);
5037 int reg_base = REGNO (XEXP (base, 0));
5038 int reg_src = true_regnum (src);
5040 return reg_src == reg_base
5041 ? avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
5042 "mov __zero_reg__,%B1" CR_TAB
5043 TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
5044 "st %b0,__zero_reg__" CR_TAB
5045 "st -%b0,__tmp_reg__" CR_TAB
5046 "clr __zero_reg__" CR_TAB
5047 TINY_SBIW (%I0, %J0, %o0), op, plen, -9)
5049 : avr_asm_len (TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
5050 "st %b0,%B1" CR_TAB
5051 "st -%b0,%A1" CR_TAB
5052 TINY_SBIW (%I0, %J0, %o0), op, plen, -6);
5055 static const char*
5056 avr_out_movhi_mr_r_post_inc_tiny (rtx op[], int *plen)
5058 return avr_asm_len (TINY_ADIW (%I0, %J0, 1) CR_TAB
5059 "st %p0,%B1" CR_TAB
5060 "st -%p0,%A1" CR_TAB
5061 TINY_ADIW (%I0, %J0, 2), op, plen, -6);
5064 static const char*
5065 out_movhi_mr_r (rtx_insn *insn, rtx op[], int *plen)
5067 rtx dest = op[0];
5068 rtx src = op[1];
5069 rtx base = XEXP (dest, 0);
5070 int reg_base = true_regnum (base);
5071 int reg_src = true_regnum (src);
5072 int mem_volatile_p;
5074 /* "volatile" forces writing high-byte first (no-xmega) resp.
5075 low-byte first (xmega) even if less efficient, for correct
5076 operation with 16-bit I/O registers like. */
5078 if (AVR_XMEGA)
5079 return avr_out_movhi_mr_r_xmega (insn, op, plen);
5081 mem_volatile_p = MEM_VOLATILE_P (dest);
5083 if (CONSTANT_ADDRESS_P (base))
5085 int n_words = AVR_TINY ? 2 : 4;
5086 return optimize > 0 && io_address_operand (base, HImode)
5087 ? avr_asm_len ("out %i0+1,%B1" CR_TAB
5088 "out %i0,%A1", op, plen, -2)
5090 : avr_asm_len ("sts %m0+1,%B1" CR_TAB
5091 "sts %m0,%A1", op, plen, -n_words);
5094 if (reg_base > 0)
5096 if (AVR_TINY)
5097 return avr_out_movhi_mr_r_reg_no_disp_tiny (insn, op, plen);
5099 if (reg_base != REG_X)
5100 return avr_asm_len ("std %0+1,%B1" CR_TAB
5101 "st %0,%A1", op, plen, -2);
5103 if (reg_src == REG_X)
5104 /* "st X+,r26" and "st -X,r26" are undefined. */
5105 return !mem_volatile_p && reg_unused_after (insn, src)
5106 ? avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5107 "st X,r26" CR_TAB
5108 "adiw r26,1" CR_TAB
5109 "st X,__tmp_reg__", op, plen, -4)
5111 : avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5112 "adiw r26,1" CR_TAB
5113 "st X,__tmp_reg__" CR_TAB
5114 "sbiw r26,1" CR_TAB
5115 "st X,r26", op, plen, -5);
5117 return !mem_volatile_p && reg_unused_after (insn, base)
5118 ? avr_asm_len ("st X+,%A1" CR_TAB
5119 "st X,%B1", op, plen, -2)
5120 : avr_asm_len ("adiw r26,1" CR_TAB
5121 "st X,%B1" CR_TAB
5122 "st -X,%A1", op, plen, -3);
5124 else if (GET_CODE (base) == PLUS)
5126 int disp = INTVAL (XEXP (base, 1));
5128 if (AVR_TINY)
5129 return avr_out_movhi_mr_r_reg_disp_tiny (op, plen);
5131 reg_base = REGNO (XEXP (base, 0));
5132 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5134 if (reg_base != REG_Y)
5135 fatal_insn ("incorrect insn:",insn);
5137 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
5138 ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
5139 "std Y+63,%B1" CR_TAB
5140 "std Y+62,%A1" CR_TAB
5141 "sbiw r28,%o0-62", op, plen, -4)
5143 : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5144 "sbci r29,hi8(-%o0)" CR_TAB
5145 "std Y+1,%B1" CR_TAB
5146 "st Y,%A1" CR_TAB
5147 "subi r28,lo8(%o0)" CR_TAB
5148 "sbci r29,hi8(%o0)", op, plen, -6);
5151 if (reg_base != REG_X)
5152 return avr_asm_len ("std %B0,%B1" CR_TAB
5153 "std %A0,%A1", op, plen, -2);
5154 /* (X + d) = R */
5155 return reg_src == REG_X
5156 ? avr_asm_len ("mov __tmp_reg__,r26" CR_TAB
5157 "mov __zero_reg__,r27" CR_TAB
5158 "adiw r26,%o0+1" CR_TAB
5159 "st X,__zero_reg__" CR_TAB
5160 "st -X,__tmp_reg__" CR_TAB
5161 "clr __zero_reg__" CR_TAB
5162 "sbiw r26,%o0", op, plen, -7)
5164 : avr_asm_len ("adiw r26,%o0+1" CR_TAB
5165 "st X,%B1" CR_TAB
5166 "st -X,%A1" CR_TAB
5167 "sbiw r26,%o0", op, plen, -4);
5169 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5171 return avr_asm_len ("st %0,%B1" CR_TAB
5172 "st %0,%A1", op, plen, -2);
5174 else if (GET_CODE (base) == POST_INC) /* (R++) */
5176 if (!mem_volatile_p)
5177 return avr_asm_len ("st %0,%A1" CR_TAB
5178 "st %0,%B1", op, plen, -2);
5180 if (AVR_TINY)
5181 return avr_out_movhi_mr_r_post_inc_tiny (op, plen);
5183 return REGNO (XEXP (base, 0)) == REG_X
5184 ? avr_asm_len ("adiw r26,1" CR_TAB
5185 "st X,%B1" CR_TAB
5186 "st -X,%A1" CR_TAB
5187 "adiw r26,2", op, plen, -4)
5189 : avr_asm_len ("std %p0+1,%B1" CR_TAB
5190 "st %p0,%A1" CR_TAB
5191 "adiw %r0,2", op, plen, -3);
5193 fatal_insn ("unknown move insn:",insn);
5194 return "";
5197 /* Return 1 if frame pointer for current function required. */
5199 static bool
5200 avr_frame_pointer_required_p (void)
5202 return (cfun->calls_alloca
5203 || cfun->calls_setjmp
5204 || cfun->has_nonlocal_label
5205 || crtl->args.info.nregs == 0
5206 || get_frame_size () > 0);
5209 /* Returns the condition of compare insn INSN, or UNKNOWN. */
5211 static RTX_CODE
5212 compare_condition (rtx_insn *insn)
5214 rtx_insn *next = next_real_insn (insn);
5216 if (next && JUMP_P (next))
5218 rtx pat = PATTERN (next);
5219 rtx src = SET_SRC (pat);
5221 if (IF_THEN_ELSE == GET_CODE (src))
5222 return GET_CODE (XEXP (src, 0));
5225 return UNKNOWN;
5229 /* Returns true iff INSN is a tst insn that only tests the sign. */
5231 static bool
5232 compare_sign_p (rtx_insn *insn)
5234 RTX_CODE cond = compare_condition (insn);
5235 return (cond == GE || cond == LT);
5239 /* Returns true iff the next insn is a JUMP_INSN with a condition
5240 that needs to be swapped (GT, GTU, LE, LEU). */
5242 static bool
5243 compare_diff_p (rtx_insn *insn)
5245 RTX_CODE cond = compare_condition (insn);
5246 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
5249 /* Returns true iff INSN is a compare insn with the EQ or NE condition. */
5251 static bool
5252 compare_eq_p (rtx_insn *insn)
5254 RTX_CODE cond = compare_condition (insn);
5255 return (cond == EQ || cond == NE);
5259 /* Output compare instruction
5261 compare (XOP[0], XOP[1])
5263 for a register XOP[0] and a compile-time constant XOP[1]. Return "".
5264 XOP[2] is an 8-bit scratch register as needed.
5266 PLEN == NULL: Output instructions.
5267 PLEN != NULL: Set *PLEN to the length (in words) of the sequence.
5268 Don't output anything. */
5270 const char*
5271 avr_out_compare (rtx_insn *insn, rtx *xop, int *plen)
5273 /* Register to compare and value to compare against. */
5274 rtx xreg = xop[0];
5275 rtx xval = xop[1];
5277 /* MODE of the comparison. */
5278 machine_mode mode;
5280 /* Number of bytes to operate on. */
5281 int i, n_bytes = GET_MODE_SIZE (GET_MODE (xreg));
5283 /* Value (0..0xff) held in clobber register xop[2] or -1 if unknown. */
5284 int clobber_val = -1;
5286 /* Map fixed mode operands to integer operands with the same binary
5287 representation. They are easier to handle in the remainder. */
5289 if (CONST_FIXED_P (xval))
5291 xreg = avr_to_int_mode (xop[0]);
5292 xval = avr_to_int_mode (xop[1]);
5295 mode = GET_MODE (xreg);
5297 gcc_assert (REG_P (xreg));
5298 gcc_assert ((CONST_INT_P (xval) && n_bytes <= 4)
5299 || (const_double_operand (xval, VOIDmode) && n_bytes == 8));
5301 if (plen)
5302 *plen = 0;
5304 /* Comparisons == +/-1 and != +/-1 can be done similar to camparing
5305 against 0 by ORing the bytes. This is one instruction shorter.
5306 Notice that 64-bit comparisons are always against reg:ALL8 18 (ACC_A)
5307 and therefore don't use this. */
5309 if (!test_hard_reg_class (LD_REGS, xreg)
5310 && compare_eq_p (insn)
5311 && reg_unused_after (insn, xreg))
5313 if (xval == const1_rtx)
5315 avr_asm_len ("dec %A0" CR_TAB
5316 "or %A0,%B0", xop, plen, 2);
5318 if (n_bytes >= 3)
5319 avr_asm_len ("or %A0,%C0", xop, plen, 1);
5321 if (n_bytes >= 4)
5322 avr_asm_len ("or %A0,%D0", xop, plen, 1);
5324 return "";
5326 else if (xval == constm1_rtx)
5328 if (n_bytes >= 4)
5329 avr_asm_len ("and %A0,%D0", xop, plen, 1);
5331 if (n_bytes >= 3)
5332 avr_asm_len ("and %A0,%C0", xop, plen, 1);
5334 return avr_asm_len ("and %A0,%B0" CR_TAB
5335 "com %A0", xop, plen, 2);
5339 for (i = 0; i < n_bytes; i++)
5341 /* We compare byte-wise. */
5342 rtx reg8 = simplify_gen_subreg (QImode, xreg, mode, i);
5343 rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
5345 /* 8-bit value to compare with this byte. */
5346 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
5348 /* Registers R16..R31 can operate with immediate. */
5349 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
5351 xop[0] = reg8;
5352 xop[1] = gen_int_mode (val8, QImode);
5354 /* Word registers >= R24 can use SBIW/ADIW with 0..63. */
5356 if (i == 0
5357 && test_hard_reg_class (ADDW_REGS, reg8))
5359 int val16 = trunc_int_for_mode (INTVAL (xval), HImode);
5361 if (IN_RANGE (val16, 0, 63)
5362 && (val8 == 0
5363 || reg_unused_after (insn, xreg)))
5365 if (AVR_TINY)
5366 avr_asm_len (TINY_SBIW (%A0, %B0, %1), xop, plen, 2);
5367 else
5368 avr_asm_len ("sbiw %0,%1", xop, plen, 1);
5370 i++;
5371 continue;
5374 if (n_bytes == 2
5375 && IN_RANGE (val16, -63, -1)
5376 && compare_eq_p (insn)
5377 && reg_unused_after (insn, xreg))
5379 return AVR_TINY
5380 ? avr_asm_len (TINY_ADIW (%A0, %B0, %n1), xop, plen, 2)
5381 : avr_asm_len ("adiw %0,%n1", xop, plen, 1);
5385 /* Comparing against 0 is easy. */
5387 if (val8 == 0)
5389 avr_asm_len (i == 0
5390 ? "cp %0,__zero_reg__"
5391 : "cpc %0,__zero_reg__", xop, plen, 1);
5392 continue;
5395 /* Upper registers can compare and subtract-with-carry immediates.
5396 Notice that compare instructions do the same as respective subtract
5397 instruction; the only difference is that comparisons don't write
5398 the result back to the target register. */
5400 if (ld_reg_p)
5402 if (i == 0)
5404 avr_asm_len ("cpi %0,%1", xop, plen, 1);
5405 continue;
5407 else if (reg_unused_after (insn, xreg))
5409 avr_asm_len ("sbci %0,%1", xop, plen, 1);
5410 continue;
5414 /* Must load the value into the scratch register. */
5416 gcc_assert (REG_P (xop[2]));
5418 if (clobber_val != (int) val8)
5419 avr_asm_len ("ldi %2,%1", xop, plen, 1);
5420 clobber_val = (int) val8;
5422 avr_asm_len (i == 0
5423 ? "cp %0,%2"
5424 : "cpc %0,%2", xop, plen, 1);
5427 return "";
5431 /* Prepare operands of compare_const_di2 to be used with avr_out_compare. */
5433 const char*
5434 avr_out_compare64 (rtx_insn *insn, rtx *op, int *plen)
5436 rtx xop[3];
5438 xop[0] = gen_rtx_REG (DImode, 18);
5439 xop[1] = op[0];
5440 xop[2] = op[1];
5442 return avr_out_compare (insn, xop, plen);
5445 /* Output test instruction for HImode. */
5447 const char*
5448 avr_out_tsthi (rtx_insn *insn, rtx *op, int *plen)
5450 if (compare_sign_p (insn))
5452 avr_asm_len ("tst %B0", op, plen, -1);
5454 else if (reg_unused_after (insn, op[0])
5455 && compare_eq_p (insn))
5457 /* Faster than sbiw if we can clobber the operand. */
5458 avr_asm_len ("or %A0,%B0", op, plen, -1);
5460 else
5462 avr_out_compare (insn, op, plen);
5465 return "";
5469 /* Output test instruction for PSImode. */
5471 const char*
5472 avr_out_tstpsi (rtx_insn *insn, rtx *op, int *plen)
5474 if (compare_sign_p (insn))
5476 avr_asm_len ("tst %C0", op, plen, -1);
5478 else if (reg_unused_after (insn, op[0])
5479 && compare_eq_p (insn))
5481 /* Faster than sbiw if we can clobber the operand. */
5482 avr_asm_len ("or %A0,%B0" CR_TAB
5483 "or %A0,%C0", op, plen, -2);
5485 else
5487 avr_out_compare (insn, op, plen);
5490 return "";
5494 /* Output test instruction for SImode. */
5496 const char*
5497 avr_out_tstsi (rtx_insn *insn, rtx *op, int *plen)
5499 if (compare_sign_p (insn))
5501 avr_asm_len ("tst %D0", op, plen, -1);
5503 else if (reg_unused_after (insn, op[0])
5504 && compare_eq_p (insn))
5506 /* Faster than sbiw if we can clobber the operand. */
5507 avr_asm_len ("or %A0,%B0" CR_TAB
5508 "or %A0,%C0" CR_TAB
5509 "or %A0,%D0", op, plen, -3);
5511 else
5513 avr_out_compare (insn, op, plen);
5516 return "";
5520 /* Generate asm equivalent for various shifts. This only handles cases
5521 that are not already carefully hand-optimized in ?sh??i3_out.
5523 OPERANDS[0] resp. %0 in TEMPL is the operand to be shifted.
5524 OPERANDS[2] is the shift count as CONST_INT, MEM or REG.
5525 OPERANDS[3] is a QImode scratch register from LD regs if
5526 available and SCRATCH, otherwise (no scratch available)
5528 TEMPL is an assembler template that shifts by one position.
5529 T_LEN is the length of this template. */
5531 void
5532 out_shift_with_cnt (const char *templ, rtx_insn *insn, rtx operands[],
5533 int *plen, int t_len)
5535 bool second_label = true;
5536 bool saved_in_tmp = false;
5537 bool use_zero_reg = false;
5538 rtx op[5];
5540 op[0] = operands[0];
5541 op[1] = operands[1];
5542 op[2] = operands[2];
5543 op[3] = operands[3];
5545 if (plen)
5546 *plen = 0;
5548 if (CONST_INT_P (operands[2]))
5550 bool scratch = (GET_CODE (PATTERN (insn)) == PARALLEL
5551 && REG_P (operands[3]));
5552 int count = INTVAL (operands[2]);
5553 int max_len = 10; /* If larger than this, always use a loop. */
5555 if (count <= 0)
5556 return;
5558 if (count < 8 && !scratch)
5559 use_zero_reg = true;
5561 if (optimize_size)
5562 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
5564 if (t_len * count <= max_len)
5566 /* Output shifts inline with no loop - faster. */
5568 while (count-- > 0)
5569 avr_asm_len (templ, op, plen, t_len);
5571 return;
5574 if (scratch)
5576 avr_asm_len ("ldi %3,%2", op, plen, 1);
5578 else if (use_zero_reg)
5580 /* Hack to save one word: use __zero_reg__ as loop counter.
5581 Set one bit, then shift in a loop until it is 0 again. */
5583 op[3] = zero_reg_rtx;
5585 avr_asm_len ("set" CR_TAB
5586 "bld %3,%2-1", op, plen, 2);
5588 else
5590 /* No scratch register available, use one from LD_REGS (saved in
5591 __tmp_reg__) that doesn't overlap with registers to shift. */
5593 op[3] = all_regs_rtx[((REGNO (op[0]) - 1) & 15) + 16];
5594 op[4] = tmp_reg_rtx;
5595 saved_in_tmp = true;
5597 avr_asm_len ("mov %4,%3" CR_TAB
5598 "ldi %3,%2", op, plen, 2);
5601 second_label = false;
5603 else if (MEM_P (op[2]))
5605 rtx op_mov[2];
5607 op_mov[0] = op[3] = tmp_reg_rtx;
5608 op_mov[1] = op[2];
5610 out_movqi_r_mr (insn, op_mov, plen);
5612 else if (register_operand (op[2], QImode))
5614 op[3] = op[2];
5616 if (!reg_unused_after (insn, op[2])
5617 || reg_overlap_mentioned_p (op[0], op[2]))
5619 op[3] = tmp_reg_rtx;
5620 avr_asm_len ("mov %3,%2", op, plen, 1);
5623 else
5624 fatal_insn ("bad shift insn:", insn);
5626 if (second_label)
5627 avr_asm_len ("rjmp 2f", op, plen, 1);
5629 avr_asm_len ("1:", op, plen, 0);
5630 avr_asm_len (templ, op, plen, t_len);
5632 if (second_label)
5633 avr_asm_len ("2:", op, plen, 0);
5635 avr_asm_len (use_zero_reg ? "lsr %3" : "dec %3", op, plen, 1);
5636 avr_asm_len (second_label ? "brpl 1b" : "brne 1b", op, plen, 1);
5638 if (saved_in_tmp)
5639 avr_asm_len ("mov %3,%4", op, plen, 1);
5643 /* 8bit shift left ((char)x << i) */
5645 const char *
5646 ashlqi3_out (rtx_insn *insn, rtx operands[], int *len)
5648 if (GET_CODE (operands[2]) == CONST_INT)
5650 int k;
5652 if (!len)
5653 len = &k;
5655 switch (INTVAL (operands[2]))
5657 default:
5658 if (INTVAL (operands[2]) < 8)
5659 break;
5661 *len = 1;
5662 return "clr %0";
5664 case 1:
5665 *len = 1;
5666 return "lsl %0";
5668 case 2:
5669 *len = 2;
5670 return ("lsl %0" CR_TAB
5671 "lsl %0");
5673 case 3:
5674 *len = 3;
5675 return ("lsl %0" CR_TAB
5676 "lsl %0" CR_TAB
5677 "lsl %0");
5679 case 4:
5680 if (test_hard_reg_class (LD_REGS, operands[0]))
5682 *len = 2;
5683 return ("swap %0" CR_TAB
5684 "andi %0,0xf0");
5686 *len = 4;
5687 return ("lsl %0" CR_TAB
5688 "lsl %0" CR_TAB
5689 "lsl %0" CR_TAB
5690 "lsl %0");
5692 case 5:
5693 if (test_hard_reg_class (LD_REGS, operands[0]))
5695 *len = 3;
5696 return ("swap %0" CR_TAB
5697 "lsl %0" CR_TAB
5698 "andi %0,0xe0");
5700 *len = 5;
5701 return ("lsl %0" CR_TAB
5702 "lsl %0" CR_TAB
5703 "lsl %0" CR_TAB
5704 "lsl %0" CR_TAB
5705 "lsl %0");
5707 case 6:
5708 if (test_hard_reg_class (LD_REGS, operands[0]))
5710 *len = 4;
5711 return ("swap %0" CR_TAB
5712 "lsl %0" CR_TAB
5713 "lsl %0" CR_TAB
5714 "andi %0,0xc0");
5716 *len = 6;
5717 return ("lsl %0" CR_TAB
5718 "lsl %0" CR_TAB
5719 "lsl %0" CR_TAB
5720 "lsl %0" CR_TAB
5721 "lsl %0" CR_TAB
5722 "lsl %0");
5724 case 7:
5725 *len = 3;
5726 return ("ror %0" CR_TAB
5727 "clr %0" CR_TAB
5728 "ror %0");
5731 else if (CONSTANT_P (operands[2]))
5732 fatal_insn ("internal compiler error. Incorrect shift:", insn);
5734 out_shift_with_cnt ("lsl %0",
5735 insn, operands, len, 1);
5736 return "";
5740 /* 16bit shift left ((short)x << i) */
5742 const char *
5743 ashlhi3_out (rtx_insn *insn, rtx operands[], int *len)
5745 if (GET_CODE (operands[2]) == CONST_INT)
5747 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
5748 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
5749 int k;
5750 int *t = len;
5752 if (!len)
5753 len = &k;
5755 switch (INTVAL (operands[2]))
5757 default:
5758 if (INTVAL (operands[2]) < 16)
5759 break;
5761 *len = 2;
5762 return ("clr %B0" CR_TAB
5763 "clr %A0");
5765 case 4:
5766 if (optimize_size && scratch)
5767 break; /* 5 */
5768 if (ldi_ok)
5770 *len = 6;
5771 return ("swap %A0" CR_TAB
5772 "swap %B0" CR_TAB
5773 "andi %B0,0xf0" CR_TAB
5774 "eor %B0,%A0" CR_TAB
5775 "andi %A0,0xf0" CR_TAB
5776 "eor %B0,%A0");
5778 if (scratch)
5780 *len = 7;
5781 return ("swap %A0" CR_TAB
5782 "swap %B0" CR_TAB
5783 "ldi %3,0xf0" CR_TAB
5784 "and %B0,%3" CR_TAB
5785 "eor %B0,%A0" CR_TAB
5786 "and %A0,%3" CR_TAB
5787 "eor %B0,%A0");
5789 break; /* optimize_size ? 6 : 8 */
5791 case 5:
5792 if (optimize_size)
5793 break; /* scratch ? 5 : 6 */
5794 if (ldi_ok)
5796 *len = 8;
5797 return ("lsl %A0" CR_TAB
5798 "rol %B0" CR_TAB
5799 "swap %A0" CR_TAB
5800 "swap %B0" CR_TAB
5801 "andi %B0,0xf0" CR_TAB
5802 "eor %B0,%A0" CR_TAB
5803 "andi %A0,0xf0" CR_TAB
5804 "eor %B0,%A0");
5806 if (scratch)
5808 *len = 9;
5809 return ("lsl %A0" CR_TAB
5810 "rol %B0" CR_TAB
5811 "swap %A0" CR_TAB
5812 "swap %B0" CR_TAB
5813 "ldi %3,0xf0" CR_TAB
5814 "and %B0,%3" CR_TAB
5815 "eor %B0,%A0" CR_TAB
5816 "and %A0,%3" CR_TAB
5817 "eor %B0,%A0");
5819 break; /* 10 */
5821 case 6:
5822 if (optimize_size)
5823 break; /* scratch ? 5 : 6 */
5824 *len = 9;
5825 return ("clr __tmp_reg__" CR_TAB
5826 "lsr %B0" CR_TAB
5827 "ror %A0" CR_TAB
5828 "ror __tmp_reg__" CR_TAB
5829 "lsr %B0" CR_TAB
5830 "ror %A0" CR_TAB
5831 "ror __tmp_reg__" CR_TAB
5832 "mov %B0,%A0" CR_TAB
5833 "mov %A0,__tmp_reg__");
5835 case 7:
5836 *len = 5;
5837 return ("lsr %B0" CR_TAB
5838 "mov %B0,%A0" CR_TAB
5839 "clr %A0" CR_TAB
5840 "ror %B0" CR_TAB
5841 "ror %A0");
5843 case 8:
5844 return *len = 2, ("mov %B0,%A1" CR_TAB
5845 "clr %A0");
5847 case 9:
5848 *len = 3;
5849 return ("mov %B0,%A0" CR_TAB
5850 "clr %A0" CR_TAB
5851 "lsl %B0");
5853 case 10:
5854 *len = 4;
5855 return ("mov %B0,%A0" CR_TAB
5856 "clr %A0" CR_TAB
5857 "lsl %B0" CR_TAB
5858 "lsl %B0");
5860 case 11:
5861 *len = 5;
5862 return ("mov %B0,%A0" CR_TAB
5863 "clr %A0" CR_TAB
5864 "lsl %B0" CR_TAB
5865 "lsl %B0" CR_TAB
5866 "lsl %B0");
5868 case 12:
5869 if (ldi_ok)
5871 *len = 4;
5872 return ("mov %B0,%A0" CR_TAB
5873 "clr %A0" CR_TAB
5874 "swap %B0" CR_TAB
5875 "andi %B0,0xf0");
5877 if (scratch)
5879 *len = 5;
5880 return ("mov %B0,%A0" CR_TAB
5881 "clr %A0" CR_TAB
5882 "swap %B0" CR_TAB
5883 "ldi %3,0xf0" CR_TAB
5884 "and %B0,%3");
5886 *len = 6;
5887 return ("mov %B0,%A0" CR_TAB
5888 "clr %A0" CR_TAB
5889 "lsl %B0" CR_TAB
5890 "lsl %B0" CR_TAB
5891 "lsl %B0" CR_TAB
5892 "lsl %B0");
5894 case 13:
5895 if (ldi_ok)
5897 *len = 5;
5898 return ("mov %B0,%A0" CR_TAB
5899 "clr %A0" CR_TAB
5900 "swap %B0" CR_TAB
5901 "lsl %B0" CR_TAB
5902 "andi %B0,0xe0");
5904 if (AVR_HAVE_MUL && scratch)
5906 *len = 5;
5907 return ("ldi %3,0x20" CR_TAB
5908 "mul %A0,%3" CR_TAB
5909 "mov %B0,r0" CR_TAB
5910 "clr %A0" CR_TAB
5911 "clr __zero_reg__");
5913 if (optimize_size && scratch)
5914 break; /* 5 */
5915 if (scratch)
5917 *len = 6;
5918 return ("mov %B0,%A0" CR_TAB
5919 "clr %A0" CR_TAB
5920 "swap %B0" CR_TAB
5921 "lsl %B0" CR_TAB
5922 "ldi %3,0xe0" CR_TAB
5923 "and %B0,%3");
5925 if (AVR_HAVE_MUL)
5927 *len = 6;
5928 return ("set" CR_TAB
5929 "bld r1,5" CR_TAB
5930 "mul %A0,r1" CR_TAB
5931 "mov %B0,r0" CR_TAB
5932 "clr %A0" CR_TAB
5933 "clr __zero_reg__");
5935 *len = 7;
5936 return ("mov %B0,%A0" CR_TAB
5937 "clr %A0" CR_TAB
5938 "lsl %B0" CR_TAB
5939 "lsl %B0" CR_TAB
5940 "lsl %B0" CR_TAB
5941 "lsl %B0" CR_TAB
5942 "lsl %B0");
5944 case 14:
5945 if (AVR_HAVE_MUL && ldi_ok)
5947 *len = 5;
5948 return ("ldi %B0,0x40" CR_TAB
5949 "mul %A0,%B0" CR_TAB
5950 "mov %B0,r0" CR_TAB
5951 "clr %A0" CR_TAB
5952 "clr __zero_reg__");
5954 if (AVR_HAVE_MUL && scratch)
5956 *len = 5;
5957 return ("ldi %3,0x40" CR_TAB
5958 "mul %A0,%3" CR_TAB
5959 "mov %B0,r0" CR_TAB
5960 "clr %A0" CR_TAB
5961 "clr __zero_reg__");
5963 if (optimize_size && ldi_ok)
5965 *len = 5;
5966 return ("mov %B0,%A0" CR_TAB
5967 "ldi %A0,6" "\n1:\t"
5968 "lsl %B0" CR_TAB
5969 "dec %A0" CR_TAB
5970 "brne 1b");
5972 if (optimize_size && scratch)
5973 break; /* 5 */
5974 *len = 6;
5975 return ("clr %B0" CR_TAB
5976 "lsr %A0" CR_TAB
5977 "ror %B0" CR_TAB
5978 "lsr %A0" CR_TAB
5979 "ror %B0" CR_TAB
5980 "clr %A0");
5982 case 15:
5983 *len = 4;
5984 return ("clr %B0" CR_TAB
5985 "lsr %A0" CR_TAB
5986 "ror %B0" CR_TAB
5987 "clr %A0");
5989 len = t;
5991 out_shift_with_cnt ("lsl %A0" CR_TAB
5992 "rol %B0", insn, operands, len, 2);
5993 return "";
5997 /* 24-bit shift left */
5999 const char*
6000 avr_out_ashlpsi3 (rtx_insn *insn, rtx *op, int *plen)
6002 if (plen)
6003 *plen = 0;
6005 if (CONST_INT_P (op[2]))
6007 switch (INTVAL (op[2]))
6009 default:
6010 if (INTVAL (op[2]) < 24)
6011 break;
6013 return avr_asm_len ("clr %A0" CR_TAB
6014 "clr %B0" CR_TAB
6015 "clr %C0", op, plen, 3);
6017 case 8:
6019 int reg0 = REGNO (op[0]);
6020 int reg1 = REGNO (op[1]);
6022 if (reg0 >= reg1)
6023 return avr_asm_len ("mov %C0,%B1" CR_TAB
6024 "mov %B0,%A1" CR_TAB
6025 "clr %A0", op, plen, 3);
6026 else
6027 return avr_asm_len ("clr %A0" CR_TAB
6028 "mov %B0,%A1" CR_TAB
6029 "mov %C0,%B1", op, plen, 3);
6032 case 16:
6034 int reg0 = REGNO (op[0]);
6035 int reg1 = REGNO (op[1]);
6037 if (reg0 + 2 != reg1)
6038 avr_asm_len ("mov %C0,%A0", op, plen, 1);
6040 return avr_asm_len ("clr %B0" CR_TAB
6041 "clr %A0", op, plen, 2);
6044 case 23:
6045 return avr_asm_len ("clr %C0" CR_TAB
6046 "lsr %A0" CR_TAB
6047 "ror %C0" CR_TAB
6048 "clr %B0" CR_TAB
6049 "clr %A0", op, plen, 5);
6053 out_shift_with_cnt ("lsl %A0" CR_TAB
6054 "rol %B0" CR_TAB
6055 "rol %C0", insn, op, plen, 3);
6056 return "";
6060 /* 32bit shift left ((long)x << i) */
6062 const char *
6063 ashlsi3_out (rtx_insn *insn, rtx operands[], int *len)
6065 if (GET_CODE (operands[2]) == CONST_INT)
6067 int k;
6068 int *t = len;
6070 if (!len)
6071 len = &k;
6073 switch (INTVAL (operands[2]))
6075 default:
6076 if (INTVAL (operands[2]) < 32)
6077 break;
6079 if (AVR_HAVE_MOVW)
6080 return *len = 3, ("clr %D0" CR_TAB
6081 "clr %C0" CR_TAB
6082 "movw %A0,%C0");
6083 *len = 4;
6084 return ("clr %D0" CR_TAB
6085 "clr %C0" CR_TAB
6086 "clr %B0" CR_TAB
6087 "clr %A0");
6089 case 8:
6091 int reg0 = true_regnum (operands[0]);
6092 int reg1 = true_regnum (operands[1]);
6093 *len = 4;
6094 if (reg0 >= reg1)
6095 return ("mov %D0,%C1" CR_TAB
6096 "mov %C0,%B1" CR_TAB
6097 "mov %B0,%A1" CR_TAB
6098 "clr %A0");
6099 else
6100 return ("clr %A0" CR_TAB
6101 "mov %B0,%A1" CR_TAB
6102 "mov %C0,%B1" CR_TAB
6103 "mov %D0,%C1");
6106 case 16:
6108 int reg0 = true_regnum (operands[0]);
6109 int reg1 = true_regnum (operands[1]);
6110 if (reg0 + 2 == reg1)
6111 return *len = 2, ("clr %B0" CR_TAB
6112 "clr %A0");
6113 if (AVR_HAVE_MOVW)
6114 return *len = 3, ("movw %C0,%A1" CR_TAB
6115 "clr %B0" CR_TAB
6116 "clr %A0");
6117 else
6118 return *len = 4, ("mov %C0,%A1" CR_TAB
6119 "mov %D0,%B1" CR_TAB
6120 "clr %B0" CR_TAB
6121 "clr %A0");
6124 case 24:
6125 *len = 4;
6126 return ("mov %D0,%A1" CR_TAB
6127 "clr %C0" CR_TAB
6128 "clr %B0" CR_TAB
6129 "clr %A0");
6131 case 31:
6132 *len = 6;
6133 return ("clr %D0" CR_TAB
6134 "lsr %A0" CR_TAB
6135 "ror %D0" CR_TAB
6136 "clr %C0" CR_TAB
6137 "clr %B0" CR_TAB
6138 "clr %A0");
6140 len = t;
6142 out_shift_with_cnt ("lsl %A0" CR_TAB
6143 "rol %B0" CR_TAB
6144 "rol %C0" CR_TAB
6145 "rol %D0", insn, operands, len, 4);
6146 return "";
6149 /* 8bit arithmetic shift right ((signed char)x >> i) */
6151 const char *
6152 ashrqi3_out (rtx_insn *insn, rtx operands[], int *len)
6154 if (GET_CODE (operands[2]) == CONST_INT)
6156 int k;
6158 if (!len)
6159 len = &k;
6161 switch (INTVAL (operands[2]))
6163 case 1:
6164 *len = 1;
6165 return "asr %0";
6167 case 2:
6168 *len = 2;
6169 return ("asr %0" CR_TAB
6170 "asr %0");
6172 case 3:
6173 *len = 3;
6174 return ("asr %0" CR_TAB
6175 "asr %0" CR_TAB
6176 "asr %0");
6178 case 4:
6179 *len = 4;
6180 return ("asr %0" CR_TAB
6181 "asr %0" CR_TAB
6182 "asr %0" CR_TAB
6183 "asr %0");
6185 case 5:
6186 *len = 5;
6187 return ("asr %0" CR_TAB
6188 "asr %0" CR_TAB
6189 "asr %0" CR_TAB
6190 "asr %0" CR_TAB
6191 "asr %0");
6193 case 6:
6194 *len = 4;
6195 return ("bst %0,6" CR_TAB
6196 "lsl %0" CR_TAB
6197 "sbc %0,%0" CR_TAB
6198 "bld %0,0");
6200 default:
6201 if (INTVAL (operands[2]) < 8)
6202 break;
6204 /* fall through */
6206 case 7:
6207 *len = 2;
6208 return ("lsl %0" CR_TAB
6209 "sbc %0,%0");
6212 else if (CONSTANT_P (operands[2]))
6213 fatal_insn ("internal compiler error. Incorrect shift:", insn);
6215 out_shift_with_cnt ("asr %0",
6216 insn, operands, len, 1);
6217 return "";
6221 /* 16bit arithmetic shift right ((signed short)x >> i) */
6223 const char *
6224 ashrhi3_out (rtx_insn *insn, rtx operands[], int *len)
6226 if (GET_CODE (operands[2]) == CONST_INT)
6228 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
6229 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
6230 int k;
6231 int *t = len;
6233 if (!len)
6234 len = &k;
6236 switch (INTVAL (operands[2]))
6238 case 4:
6239 case 5:
6240 /* XXX try to optimize this too? */
6241 break;
6243 case 6:
6244 if (optimize_size)
6245 break; /* scratch ? 5 : 6 */
6246 *len = 8;
6247 return ("mov __tmp_reg__,%A0" CR_TAB
6248 "mov %A0,%B0" CR_TAB
6249 "lsl __tmp_reg__" CR_TAB
6250 "rol %A0" CR_TAB
6251 "sbc %B0,%B0" CR_TAB
6252 "lsl __tmp_reg__" CR_TAB
6253 "rol %A0" CR_TAB
6254 "rol %B0");
6256 case 7:
6257 *len = 4;
6258 return ("lsl %A0" CR_TAB
6259 "mov %A0,%B0" CR_TAB
6260 "rol %A0" CR_TAB
6261 "sbc %B0,%B0");
6263 case 8:
6265 int reg0 = true_regnum (operands[0]);
6266 int reg1 = true_regnum (operands[1]);
6268 if (reg0 == reg1)
6269 return *len = 3, ("mov %A0,%B0" CR_TAB
6270 "lsl %B0" CR_TAB
6271 "sbc %B0,%B0");
6272 else
6273 return *len = 4, ("mov %A0,%B1" CR_TAB
6274 "clr %B0" CR_TAB
6275 "sbrc %A0,7" CR_TAB
6276 "dec %B0");
6279 case 9:
6280 *len = 4;
6281 return ("mov %A0,%B0" CR_TAB
6282 "lsl %B0" CR_TAB
6283 "sbc %B0,%B0" CR_TAB
6284 "asr %A0");
6286 case 10:
6287 *len = 5;
6288 return ("mov %A0,%B0" CR_TAB
6289 "lsl %B0" CR_TAB
6290 "sbc %B0,%B0" CR_TAB
6291 "asr %A0" CR_TAB
6292 "asr %A0");
6294 case 11:
6295 if (AVR_HAVE_MUL && ldi_ok)
6297 *len = 5;
6298 return ("ldi %A0,0x20" CR_TAB
6299 "muls %B0,%A0" CR_TAB
6300 "mov %A0,r1" CR_TAB
6301 "sbc %B0,%B0" CR_TAB
6302 "clr __zero_reg__");
6304 if (optimize_size && scratch)
6305 break; /* 5 */
6306 *len = 6;
6307 return ("mov %A0,%B0" CR_TAB
6308 "lsl %B0" CR_TAB
6309 "sbc %B0,%B0" CR_TAB
6310 "asr %A0" CR_TAB
6311 "asr %A0" CR_TAB
6312 "asr %A0");
6314 case 12:
6315 if (AVR_HAVE_MUL && ldi_ok)
6317 *len = 5;
6318 return ("ldi %A0,0x10" CR_TAB
6319 "muls %B0,%A0" CR_TAB
6320 "mov %A0,r1" CR_TAB
6321 "sbc %B0,%B0" CR_TAB
6322 "clr __zero_reg__");
6324 if (optimize_size && scratch)
6325 break; /* 5 */
6326 *len = 7;
6327 return ("mov %A0,%B0" CR_TAB
6328 "lsl %B0" CR_TAB
6329 "sbc %B0,%B0" CR_TAB
6330 "asr %A0" CR_TAB
6331 "asr %A0" CR_TAB
6332 "asr %A0" CR_TAB
6333 "asr %A0");
6335 case 13:
6336 if (AVR_HAVE_MUL && ldi_ok)
6338 *len = 5;
6339 return ("ldi %A0,0x08" CR_TAB
6340 "muls %B0,%A0" CR_TAB
6341 "mov %A0,r1" CR_TAB
6342 "sbc %B0,%B0" CR_TAB
6343 "clr __zero_reg__");
6345 if (optimize_size)
6346 break; /* scratch ? 5 : 7 */
6347 *len = 8;
6348 return ("mov %A0,%B0" CR_TAB
6349 "lsl %B0" CR_TAB
6350 "sbc %B0,%B0" CR_TAB
6351 "asr %A0" CR_TAB
6352 "asr %A0" CR_TAB
6353 "asr %A0" CR_TAB
6354 "asr %A0" CR_TAB
6355 "asr %A0");
6357 case 14:
6358 *len = 5;
6359 return ("lsl %B0" CR_TAB
6360 "sbc %A0,%A0" CR_TAB
6361 "lsl %B0" CR_TAB
6362 "mov %B0,%A0" CR_TAB
6363 "rol %A0");
6365 default:
6366 if (INTVAL (operands[2]) < 16)
6367 break;
6369 /* fall through */
6371 case 15:
6372 return *len = 3, ("lsl %B0" CR_TAB
6373 "sbc %A0,%A0" CR_TAB
6374 "mov %B0,%A0");
6376 len = t;
6378 out_shift_with_cnt ("asr %B0" CR_TAB
6379 "ror %A0", insn, operands, len, 2);
6380 return "";
6384 /* 24-bit arithmetic shift right */
6386 const char*
6387 avr_out_ashrpsi3 (rtx_insn *insn, rtx *op, int *plen)
6389 int dest = REGNO (op[0]);
6390 int src = REGNO (op[1]);
6392 if (CONST_INT_P (op[2]))
6394 if (plen)
6395 *plen = 0;
6397 switch (INTVAL (op[2]))
6399 case 8:
6400 if (dest <= src)
6401 return avr_asm_len ("mov %A0,%B1" CR_TAB
6402 "mov %B0,%C1" CR_TAB
6403 "clr %C0" CR_TAB
6404 "sbrc %B0,7" CR_TAB
6405 "dec %C0", op, plen, 5);
6406 else
6407 return avr_asm_len ("clr %C0" CR_TAB
6408 "sbrc %C1,7" CR_TAB
6409 "dec %C0" CR_TAB
6410 "mov %B0,%C1" CR_TAB
6411 "mov %A0,%B1", op, plen, 5);
6413 case 16:
6414 if (dest != src + 2)
6415 avr_asm_len ("mov %A0,%C1", op, plen, 1);
6417 return avr_asm_len ("clr %B0" CR_TAB
6418 "sbrc %A0,7" CR_TAB
6419 "com %B0" CR_TAB
6420 "mov %C0,%B0", op, plen, 4);
6422 default:
6423 if (INTVAL (op[2]) < 24)
6424 break;
6426 /* fall through */
6428 case 23:
6429 return avr_asm_len ("lsl %C0" CR_TAB
6430 "sbc %A0,%A0" CR_TAB
6431 "mov %B0,%A0" CR_TAB
6432 "mov %C0,%A0", op, plen, 4);
6433 } /* switch */
6436 out_shift_with_cnt ("asr %C0" CR_TAB
6437 "ror %B0" CR_TAB
6438 "ror %A0", insn, op, plen, 3);
6439 return "";
6443 /* 32-bit arithmetic shift right ((signed long)x >> i) */
6445 const char *
6446 ashrsi3_out (rtx_insn *insn, rtx operands[], int *len)
6448 if (GET_CODE (operands[2]) == CONST_INT)
6450 int k;
6451 int *t = len;
6453 if (!len)
6454 len = &k;
6456 switch (INTVAL (operands[2]))
6458 case 8:
6460 int reg0 = true_regnum (operands[0]);
6461 int reg1 = true_regnum (operands[1]);
6462 *len=6;
6463 if (reg0 <= reg1)
6464 return ("mov %A0,%B1" CR_TAB
6465 "mov %B0,%C1" CR_TAB
6466 "mov %C0,%D1" CR_TAB
6467 "clr %D0" CR_TAB
6468 "sbrc %C0,7" CR_TAB
6469 "dec %D0");
6470 else
6471 return ("clr %D0" CR_TAB
6472 "sbrc %D1,7" CR_TAB
6473 "dec %D0" CR_TAB
6474 "mov %C0,%D1" CR_TAB
6475 "mov %B0,%C1" CR_TAB
6476 "mov %A0,%B1");
6479 case 16:
6481 int reg0 = true_regnum (operands[0]);
6482 int reg1 = true_regnum (operands[1]);
6484 if (reg0 == reg1 + 2)
6485 return *len = 4, ("clr %D0" CR_TAB
6486 "sbrc %B0,7" CR_TAB
6487 "com %D0" CR_TAB
6488 "mov %C0,%D0");
6489 if (AVR_HAVE_MOVW)
6490 return *len = 5, ("movw %A0,%C1" CR_TAB
6491 "clr %D0" CR_TAB
6492 "sbrc %B0,7" CR_TAB
6493 "com %D0" CR_TAB
6494 "mov %C0,%D0");
6495 else
6496 return *len = 6, ("mov %B0,%D1" CR_TAB
6497 "mov %A0,%C1" CR_TAB
6498 "clr %D0" CR_TAB
6499 "sbrc %B0,7" CR_TAB
6500 "com %D0" CR_TAB
6501 "mov %C0,%D0");
6504 case 24:
6505 return *len = 6, ("mov %A0,%D1" CR_TAB
6506 "clr %D0" CR_TAB
6507 "sbrc %A0,7" CR_TAB
6508 "com %D0" CR_TAB
6509 "mov %B0,%D0" CR_TAB
6510 "mov %C0,%D0");
6512 default:
6513 if (INTVAL (operands[2]) < 32)
6514 break;
6516 /* fall through */
6518 case 31:
6519 if (AVR_HAVE_MOVW)
6520 return *len = 4, ("lsl %D0" CR_TAB
6521 "sbc %A0,%A0" CR_TAB
6522 "mov %B0,%A0" CR_TAB
6523 "movw %C0,%A0");
6524 else
6525 return *len = 5, ("lsl %D0" CR_TAB
6526 "sbc %A0,%A0" CR_TAB
6527 "mov %B0,%A0" CR_TAB
6528 "mov %C0,%A0" CR_TAB
6529 "mov %D0,%A0");
6531 len = t;
6533 out_shift_with_cnt ("asr %D0" CR_TAB
6534 "ror %C0" CR_TAB
6535 "ror %B0" CR_TAB
6536 "ror %A0", insn, operands, len, 4);
6537 return "";
6540 /* 8-bit logic shift right ((unsigned char)x >> i) */
6542 const char *
6543 lshrqi3_out (rtx_insn *insn, rtx operands[], int *len)
6545 if (GET_CODE (operands[2]) == CONST_INT)
6547 int k;
6549 if (!len)
6550 len = &k;
6552 switch (INTVAL (operands[2]))
6554 default:
6555 if (INTVAL (operands[2]) < 8)
6556 break;
6558 *len = 1;
6559 return "clr %0";
6561 case 1:
6562 *len = 1;
6563 return "lsr %0";
6565 case 2:
6566 *len = 2;
6567 return ("lsr %0" CR_TAB
6568 "lsr %0");
6569 case 3:
6570 *len = 3;
6571 return ("lsr %0" CR_TAB
6572 "lsr %0" CR_TAB
6573 "lsr %0");
6575 case 4:
6576 if (test_hard_reg_class (LD_REGS, operands[0]))
6578 *len=2;
6579 return ("swap %0" CR_TAB
6580 "andi %0,0x0f");
6582 *len = 4;
6583 return ("lsr %0" CR_TAB
6584 "lsr %0" CR_TAB
6585 "lsr %0" CR_TAB
6586 "lsr %0");
6588 case 5:
6589 if (test_hard_reg_class (LD_REGS, operands[0]))
6591 *len = 3;
6592 return ("swap %0" CR_TAB
6593 "lsr %0" CR_TAB
6594 "andi %0,0x7");
6596 *len = 5;
6597 return ("lsr %0" CR_TAB
6598 "lsr %0" CR_TAB
6599 "lsr %0" CR_TAB
6600 "lsr %0" CR_TAB
6601 "lsr %0");
6603 case 6:
6604 if (test_hard_reg_class (LD_REGS, operands[0]))
6606 *len = 4;
6607 return ("swap %0" CR_TAB
6608 "lsr %0" CR_TAB
6609 "lsr %0" CR_TAB
6610 "andi %0,0x3");
6612 *len = 6;
6613 return ("lsr %0" CR_TAB
6614 "lsr %0" CR_TAB
6615 "lsr %0" CR_TAB
6616 "lsr %0" CR_TAB
6617 "lsr %0" CR_TAB
6618 "lsr %0");
6620 case 7:
6621 *len = 3;
6622 return ("rol %0" CR_TAB
6623 "clr %0" CR_TAB
6624 "rol %0");
6627 else if (CONSTANT_P (operands[2]))
6628 fatal_insn ("internal compiler error. Incorrect shift:", insn);
6630 out_shift_with_cnt ("lsr %0",
6631 insn, operands, len, 1);
6632 return "";
6635 /* 16-bit logic shift right ((unsigned short)x >> i) */
6637 const char *
6638 lshrhi3_out (rtx_insn *insn, rtx operands[], int *len)
6640 if (GET_CODE (operands[2]) == CONST_INT)
6642 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
6643 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
6644 int k;
6645 int *t = len;
6647 if (!len)
6648 len = &k;
6650 switch (INTVAL (operands[2]))
6652 default:
6653 if (INTVAL (operands[2]) < 16)
6654 break;
6656 *len = 2;
6657 return ("clr %B0" CR_TAB
6658 "clr %A0");
6660 case 4:
6661 if (optimize_size && scratch)
6662 break; /* 5 */
6663 if (ldi_ok)
6665 *len = 6;
6666 return ("swap %B0" CR_TAB
6667 "swap %A0" CR_TAB
6668 "andi %A0,0x0f" CR_TAB
6669 "eor %A0,%B0" CR_TAB
6670 "andi %B0,0x0f" CR_TAB
6671 "eor %A0,%B0");
6673 if (scratch)
6675 *len = 7;
6676 return ("swap %B0" CR_TAB
6677 "swap %A0" CR_TAB
6678 "ldi %3,0x0f" CR_TAB
6679 "and %A0,%3" CR_TAB
6680 "eor %A0,%B0" CR_TAB
6681 "and %B0,%3" CR_TAB
6682 "eor %A0,%B0");
6684 break; /* optimize_size ? 6 : 8 */
6686 case 5:
6687 if (optimize_size)
6688 break; /* scratch ? 5 : 6 */
6689 if (ldi_ok)
6691 *len = 8;
6692 return ("lsr %B0" CR_TAB
6693 "ror %A0" CR_TAB
6694 "swap %B0" CR_TAB
6695 "swap %A0" CR_TAB
6696 "andi %A0,0x0f" CR_TAB
6697 "eor %A0,%B0" CR_TAB
6698 "andi %B0,0x0f" CR_TAB
6699 "eor %A0,%B0");
6701 if (scratch)
6703 *len = 9;
6704 return ("lsr %B0" CR_TAB
6705 "ror %A0" CR_TAB
6706 "swap %B0" CR_TAB
6707 "swap %A0" CR_TAB
6708 "ldi %3,0x0f" CR_TAB
6709 "and %A0,%3" CR_TAB
6710 "eor %A0,%B0" CR_TAB
6711 "and %B0,%3" CR_TAB
6712 "eor %A0,%B0");
6714 break; /* 10 */
6716 case 6:
6717 if (optimize_size)
6718 break; /* scratch ? 5 : 6 */
6719 *len = 9;
6720 return ("clr __tmp_reg__" CR_TAB
6721 "lsl %A0" CR_TAB
6722 "rol %B0" CR_TAB
6723 "rol __tmp_reg__" CR_TAB
6724 "lsl %A0" CR_TAB
6725 "rol %B0" CR_TAB
6726 "rol __tmp_reg__" CR_TAB
6727 "mov %A0,%B0" CR_TAB
6728 "mov %B0,__tmp_reg__");
6730 case 7:
6731 *len = 5;
6732 return ("lsl %A0" CR_TAB
6733 "mov %A0,%B0" CR_TAB
6734 "rol %A0" CR_TAB
6735 "sbc %B0,%B0" CR_TAB
6736 "neg %B0");
6738 case 8:
6739 return *len = 2, ("mov %A0,%B1" CR_TAB
6740 "clr %B0");
6742 case 9:
6743 *len = 3;
6744 return ("mov %A0,%B0" CR_TAB
6745 "clr %B0" CR_TAB
6746 "lsr %A0");
6748 case 10:
6749 *len = 4;
6750 return ("mov %A0,%B0" CR_TAB
6751 "clr %B0" CR_TAB
6752 "lsr %A0" CR_TAB
6753 "lsr %A0");
6755 case 11:
6756 *len = 5;
6757 return ("mov %A0,%B0" CR_TAB
6758 "clr %B0" CR_TAB
6759 "lsr %A0" CR_TAB
6760 "lsr %A0" CR_TAB
6761 "lsr %A0");
6763 case 12:
6764 if (ldi_ok)
6766 *len = 4;
6767 return ("mov %A0,%B0" CR_TAB
6768 "clr %B0" CR_TAB
6769 "swap %A0" CR_TAB
6770 "andi %A0,0x0f");
6772 if (scratch)
6774 *len = 5;
6775 return ("mov %A0,%B0" CR_TAB
6776 "clr %B0" CR_TAB
6777 "swap %A0" CR_TAB
6778 "ldi %3,0x0f" CR_TAB
6779 "and %A0,%3");
6781 *len = 6;
6782 return ("mov %A0,%B0" CR_TAB
6783 "clr %B0" CR_TAB
6784 "lsr %A0" CR_TAB
6785 "lsr %A0" CR_TAB
6786 "lsr %A0" CR_TAB
6787 "lsr %A0");
6789 case 13:
6790 if (ldi_ok)
6792 *len = 5;
6793 return ("mov %A0,%B0" CR_TAB
6794 "clr %B0" CR_TAB
6795 "swap %A0" CR_TAB
6796 "lsr %A0" CR_TAB
6797 "andi %A0,0x07");
6799 if (AVR_HAVE_MUL && scratch)
6801 *len = 5;
6802 return ("ldi %3,0x08" CR_TAB
6803 "mul %B0,%3" CR_TAB
6804 "mov %A0,r1" CR_TAB
6805 "clr %B0" CR_TAB
6806 "clr __zero_reg__");
6808 if (optimize_size && scratch)
6809 break; /* 5 */
6810 if (scratch)
6812 *len = 6;
6813 return ("mov %A0,%B0" CR_TAB
6814 "clr %B0" CR_TAB
6815 "swap %A0" CR_TAB
6816 "lsr %A0" CR_TAB
6817 "ldi %3,0x07" CR_TAB
6818 "and %A0,%3");
6820 if (AVR_HAVE_MUL)
6822 *len = 6;
6823 return ("set" CR_TAB
6824 "bld r1,3" CR_TAB
6825 "mul %B0,r1" CR_TAB
6826 "mov %A0,r1" CR_TAB
6827 "clr %B0" CR_TAB
6828 "clr __zero_reg__");
6830 *len = 7;
6831 return ("mov %A0,%B0" CR_TAB
6832 "clr %B0" CR_TAB
6833 "lsr %A0" CR_TAB
6834 "lsr %A0" CR_TAB
6835 "lsr %A0" CR_TAB
6836 "lsr %A0" CR_TAB
6837 "lsr %A0");
6839 case 14:
6840 if (AVR_HAVE_MUL && ldi_ok)
6842 *len = 5;
6843 return ("ldi %A0,0x04" CR_TAB
6844 "mul %B0,%A0" CR_TAB
6845 "mov %A0,r1" CR_TAB
6846 "clr %B0" CR_TAB
6847 "clr __zero_reg__");
6849 if (AVR_HAVE_MUL && scratch)
6851 *len = 5;
6852 return ("ldi %3,0x04" CR_TAB
6853 "mul %B0,%3" CR_TAB
6854 "mov %A0,r1" CR_TAB
6855 "clr %B0" CR_TAB
6856 "clr __zero_reg__");
6858 if (optimize_size && ldi_ok)
6860 *len = 5;
6861 return ("mov %A0,%B0" CR_TAB
6862 "ldi %B0,6" "\n1:\t"
6863 "lsr %A0" CR_TAB
6864 "dec %B0" CR_TAB
6865 "brne 1b");
6867 if (optimize_size && scratch)
6868 break; /* 5 */
6869 *len = 6;
6870 return ("clr %A0" CR_TAB
6871 "lsl %B0" CR_TAB
6872 "rol %A0" CR_TAB
6873 "lsl %B0" CR_TAB
6874 "rol %A0" CR_TAB
6875 "clr %B0");
6877 case 15:
6878 *len = 4;
6879 return ("clr %A0" CR_TAB
6880 "lsl %B0" CR_TAB
6881 "rol %A0" CR_TAB
6882 "clr %B0");
6884 len = t;
6886 out_shift_with_cnt ("lsr %B0" CR_TAB
6887 "ror %A0", insn, operands, len, 2);
6888 return "";
6892 /* 24-bit logic shift right */
6894 const char*
6895 avr_out_lshrpsi3 (rtx_insn *insn, rtx *op, int *plen)
6897 int dest = REGNO (op[0]);
6898 int src = REGNO (op[1]);
6900 if (CONST_INT_P (op[2]))
6902 if (plen)
6903 *plen = 0;
6905 switch (INTVAL (op[2]))
6907 case 8:
6908 if (dest <= src)
6909 return avr_asm_len ("mov %A0,%B1" CR_TAB
6910 "mov %B0,%C1" CR_TAB
6911 "clr %C0", op, plen, 3);
6912 else
6913 return avr_asm_len ("clr %C0" CR_TAB
6914 "mov %B0,%C1" CR_TAB
6915 "mov %A0,%B1", op, plen, 3);
6917 case 16:
6918 if (dest != src + 2)
6919 avr_asm_len ("mov %A0,%C1", op, plen, 1);
6921 return avr_asm_len ("clr %B0" CR_TAB
6922 "clr %C0", op, plen, 2);
6924 default:
6925 if (INTVAL (op[2]) < 24)
6926 break;
6928 /* fall through */
6930 case 23:
6931 return avr_asm_len ("clr %A0" CR_TAB
6932 "sbrc %C0,7" CR_TAB
6933 "inc %A0" CR_TAB
6934 "clr %B0" CR_TAB
6935 "clr %C0", op, plen, 5);
6936 } /* switch */
6939 out_shift_with_cnt ("lsr %C0" CR_TAB
6940 "ror %B0" CR_TAB
6941 "ror %A0", insn, op, plen, 3);
6942 return "";
6946 /* 32-bit logic shift right ((unsigned int)x >> i) */
6948 const char *
6949 lshrsi3_out (rtx_insn *insn, rtx operands[], int *len)
6951 if (GET_CODE (operands[2]) == CONST_INT)
6953 int k;
6954 int *t = len;
6956 if (!len)
6957 len = &k;
6959 switch (INTVAL (operands[2]))
6961 default:
6962 if (INTVAL (operands[2]) < 32)
6963 break;
6965 if (AVR_HAVE_MOVW)
6966 return *len = 3, ("clr %D0" CR_TAB
6967 "clr %C0" CR_TAB
6968 "movw %A0,%C0");
6969 *len = 4;
6970 return ("clr %D0" CR_TAB
6971 "clr %C0" CR_TAB
6972 "clr %B0" CR_TAB
6973 "clr %A0");
6975 case 8:
6977 int reg0 = true_regnum (operands[0]);
6978 int reg1 = true_regnum (operands[1]);
6979 *len = 4;
6980 if (reg0 <= reg1)
6981 return ("mov %A0,%B1" CR_TAB
6982 "mov %B0,%C1" CR_TAB
6983 "mov %C0,%D1" CR_TAB
6984 "clr %D0");
6985 else
6986 return ("clr %D0" CR_TAB
6987 "mov %C0,%D1" CR_TAB
6988 "mov %B0,%C1" CR_TAB
6989 "mov %A0,%B1");
6992 case 16:
6994 int reg0 = true_regnum (operands[0]);
6995 int reg1 = true_regnum (operands[1]);
6997 if (reg0 == reg1 + 2)
6998 return *len = 2, ("clr %C0" CR_TAB
6999 "clr %D0");
7000 if (AVR_HAVE_MOVW)
7001 return *len = 3, ("movw %A0,%C1" CR_TAB
7002 "clr %C0" CR_TAB
7003 "clr %D0");
7004 else
7005 return *len = 4, ("mov %B0,%D1" CR_TAB
7006 "mov %A0,%C1" CR_TAB
7007 "clr %C0" CR_TAB
7008 "clr %D0");
7011 case 24:
7012 return *len = 4, ("mov %A0,%D1" CR_TAB
7013 "clr %B0" CR_TAB
7014 "clr %C0" CR_TAB
7015 "clr %D0");
7017 case 31:
7018 *len = 6;
7019 return ("clr %A0" CR_TAB
7020 "sbrc %D0,7" CR_TAB
7021 "inc %A0" CR_TAB
7022 "clr %B0" CR_TAB
7023 "clr %C0" CR_TAB
7024 "clr %D0");
7026 len = t;
7028 out_shift_with_cnt ("lsr %D0" CR_TAB
7029 "ror %C0" CR_TAB
7030 "ror %B0" CR_TAB
7031 "ror %A0", insn, operands, len, 4);
7032 return "";
7036 /* Output addition of register XOP[0] and compile time constant XOP[2].
7037 CODE == PLUS: perform addition by using ADD instructions or
7038 CODE == MINUS: perform addition by using SUB instructions:
7040 XOP[0] = XOP[0] + XOP[2]
7042 Or perform addition/subtraction with register XOP[2] depending on CODE:
7044 XOP[0] = XOP[0] +/- XOP[2]
7046 If PLEN == NULL, print assembler instructions to perform the operation;
7047 otherwise, set *PLEN to the length of the instruction sequence (in words)
7048 printed with PLEN == NULL. XOP[3] is an 8-bit scratch register or NULL_RTX.
7049 Set *PCC to effect on cc0 according to respective CC_* insn attribute.
7051 CODE_SAT == UNKNOWN: Perform ordinary, non-saturating operation.
7052 CODE_SAT != UNKNOWN: Perform operation and saturate according to CODE_SAT.
7053 If CODE_SAT != UNKNOWN then SIGN contains the sign of the summand resp.
7054 the subtrahend in the original insn, provided it is a compile time constant.
7055 In all other cases, SIGN is 0.
7057 If OUT_LABEL is true, print the final 0: label which is needed for
7058 saturated addition / subtraction. The only case where OUT_LABEL = false
7059 is useful is for saturated addition / subtraction performed during
7060 fixed-point rounding, cf. `avr_out_round'. */
7062 static void
7063 avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc,
7064 enum rtx_code code_sat, int sign, bool out_label)
7066 /* MODE of the operation. */
7067 machine_mode mode = GET_MODE (xop[0]);
7069 /* INT_MODE of the same size. */
7070 machine_mode imode = int_mode_for_mode (mode);
7072 /* Number of bytes to operate on. */
7073 int i, n_bytes = GET_MODE_SIZE (mode);
7075 /* Value (0..0xff) held in clobber register op[3] or -1 if unknown. */
7076 int clobber_val = -1;
7078 /* op[0]: 8-bit destination register
7079 op[1]: 8-bit const int
7080 op[2]: 8-bit scratch register */
7081 rtx op[3];
7083 /* Started the operation? Before starting the operation we may skip
7084 adding 0. This is no more true after the operation started because
7085 carry must be taken into account. */
7086 bool started = false;
7088 /* Value to add. There are two ways to add VAL: R += VAL and R -= -VAL. */
7089 rtx xval = xop[2];
7091 /* Output a BRVC instruction. Only needed with saturation. */
7092 bool out_brvc = true;
7094 if (plen)
7095 *plen = 0;
7097 if (REG_P (xop[2]))
7099 *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_CLOBBER;
7101 for (i = 0; i < n_bytes; i++)
7103 /* We operate byte-wise on the destination. */
7104 op[0] = simplify_gen_subreg (QImode, xop[0], mode, i);
7105 op[1] = simplify_gen_subreg (QImode, xop[2], mode, i);
7107 if (i == 0)
7108 avr_asm_len (code == PLUS ? "add %0,%1" : "sub %0,%1",
7109 op, plen, 1);
7110 else
7111 avr_asm_len (code == PLUS ? "adc %0,%1" : "sbc %0,%1",
7112 op, plen, 1);
7115 if (reg_overlap_mentioned_p (xop[0], xop[2]))
7117 gcc_assert (REGNO (xop[0]) == REGNO (xop[2]));
7119 if (MINUS == code)
7120 return;
7123 goto saturate;
7126 /* Except in the case of ADIW with 16-bit register (see below)
7127 addition does not set cc0 in a usable way. */
7129 *pcc = (MINUS == code) ? CC_SET_CZN : CC_CLOBBER;
7131 if (CONST_FIXED_P (xval))
7132 xval = avr_to_int_mode (xval);
7134 /* Adding/Subtracting zero is a no-op. */
7136 if (xval == const0_rtx)
7138 *pcc = CC_NONE;
7139 return;
7142 if (MINUS == code)
7143 xval = simplify_unary_operation (NEG, imode, xval, imode);
7145 op[2] = xop[3];
7147 if (SS_PLUS == code_sat && MINUS == code
7148 && sign < 0
7149 && 0x80 == (INTVAL (simplify_gen_subreg (QImode, xval, imode, n_bytes-1))
7150 & GET_MODE_MASK (QImode)))
7152 /* We compute x + 0x80 by means of SUB instructions. We negated the
7153 constant subtrahend above and are left with x - (-128) so that we
7154 need something like SUBI r,128 which does not exist because SUBI sets
7155 V according to the sign of the subtrahend. Notice the only case
7156 where this must be done is when NEG overflowed in case [2s] because
7157 the V computation needs the right sign of the subtrahend. */
7159 rtx msb = simplify_gen_subreg (QImode, xop[0], mode, n_bytes-1);
7161 avr_asm_len ("subi %0,128" CR_TAB
7162 "brmi 0f", &msb, plen, 2);
7163 out_brvc = false;
7165 goto saturate;
7168 for (i = 0; i < n_bytes; i++)
7170 /* We operate byte-wise on the destination. */
7171 rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
7172 rtx xval8 = simplify_gen_subreg (QImode, xval, imode, i);
7174 /* 8-bit value to operate with this byte. */
7175 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
7177 /* Registers R16..R31 can operate with immediate. */
7178 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
7180 op[0] = reg8;
7181 op[1] = gen_int_mode (val8, QImode);
7183 /* To get usable cc0 no low-bytes must have been skipped. */
7185 if (i && !started)
7186 *pcc = CC_CLOBBER;
7188 if (!started
7189 && i % 2 == 0
7190 && i + 2 <= n_bytes
7191 && test_hard_reg_class (ADDW_REGS, reg8))
7193 rtx xval16 = simplify_gen_subreg (HImode, xval, imode, i);
7194 unsigned int val16 = UINTVAL (xval16) & GET_MODE_MASK (HImode);
7196 /* Registers R24, X, Y, Z can use ADIW/SBIW with constants < 64
7197 i.e. operate word-wise. */
7199 if (val16 < 64)
7201 if (val16 != 0)
7203 started = true;
7204 avr_asm_len (code == PLUS ? "adiw %0,%1" : "sbiw %0,%1",
7205 op, plen, 1);
7207 if (n_bytes == 2 && PLUS == code)
7208 *pcc = CC_SET_CZN;
7211 i++;
7212 continue;
7216 if (val8 == 0)
7218 if (started)
7219 avr_asm_len (code == PLUS
7220 ? "adc %0,__zero_reg__" : "sbc %0,__zero_reg__",
7221 op, plen, 1);
7222 continue;
7224 else if ((val8 == 1 || val8 == 0xff)
7225 && UNKNOWN == code_sat
7226 && !started
7227 && i == n_bytes - 1)
7229 avr_asm_len ((code == PLUS) ^ (val8 == 1) ? "dec %0" : "inc %0",
7230 op, plen, 1);
7231 *pcc = CC_CLOBBER;
7232 break;
7235 switch (code)
7237 case PLUS:
7239 gcc_assert (plen != NULL || (op[2] && REG_P (op[2])));
7241 if (plen != NULL && UNKNOWN != code_sat)
7243 /* This belongs to the x + 0x80 corner case. The code with
7244 ADD instruction is not smaller, thus make this case
7245 expensive so that the caller won't pick it. */
7247 *plen += 10;
7248 break;
7251 if (clobber_val != (int) val8)
7252 avr_asm_len ("ldi %2,%1", op, plen, 1);
7253 clobber_val = (int) val8;
7255 avr_asm_len (started ? "adc %0,%2" : "add %0,%2", op, plen, 1);
7257 break; /* PLUS */
7259 case MINUS:
7261 if (ld_reg_p)
7262 avr_asm_len (started ? "sbci %0,%1" : "subi %0,%1", op, plen, 1);
7263 else
7265 gcc_assert (plen != NULL || REG_P (op[2]));
7267 if (clobber_val != (int) val8)
7268 avr_asm_len ("ldi %2,%1", op, plen, 1);
7269 clobber_val = (int) val8;
7271 avr_asm_len (started ? "sbc %0,%2" : "sub %0,%2", op, plen, 1);
7274 break; /* MINUS */
7276 default:
7277 /* Unknown code */
7278 gcc_unreachable();
7281 started = true;
7283 } /* for all sub-bytes */
7285 saturate:
7287 if (UNKNOWN == code_sat)
7288 return;
7290 *pcc = (int) CC_CLOBBER;
7292 /* Vanilla addition/subtraction is done. We are left with saturation.
7294 We have to compute A = A <op> B where A is a register and
7295 B is a register or a non-zero compile time constant CONST.
7296 A is register class "r" if unsigned && B is REG. Otherwise, A is in "d".
7297 B stands for the original operand $2 in INSN. In the case of B = CONST,
7298 SIGN in { -1, 1 } is the sign of B. Otherwise, SIGN is 0.
7300 CODE is the instruction flavor we use in the asm sequence to perform <op>.
7303 unsigned
7304 operation | code | sat if | b is | sat value | case
7305 -----------------+-------+----------+--------------+-----------+-------
7306 + as a + b | add | C == 1 | const, reg | u+ = 0xff | [1u]
7307 + as a - (-b) | sub | C == 0 | const | u+ = 0xff | [2u]
7308 - as a - b | sub | C == 1 | const, reg | u- = 0 | [3u]
7309 - as a + (-b) | add | C == 0 | const | u- = 0 | [4u]
7312 signed
7313 operation | code | sat if | b is | sat value | case
7314 -----------------+-------+----------+--------------+-----------+-------
7315 + as a + b | add | V == 1 | const, reg | s+ | [1s]
7316 + as a - (-b) | sub | V == 1 | const | s+ | [2s]
7317 - as a - b | sub | V == 1 | const, reg | s- | [3s]
7318 - as a + (-b) | add | V == 1 | const | s- | [4s]
7320 s+ = b < 0 ? -0x80 : 0x7f
7321 s- = b < 0 ? 0x7f : -0x80
7323 The cases a - b actually perform a - (-(-b)) if B is CONST.
7326 op[0] = simplify_gen_subreg (QImode, xop[0], mode, n_bytes-1);
7327 op[1] = n_bytes > 1
7328 ? simplify_gen_subreg (QImode, xop[0], mode, n_bytes-2)
7329 : NULL_RTX;
7331 bool need_copy = true;
7332 int len_call = 1 + AVR_HAVE_JMP_CALL;
7334 switch (code_sat)
7336 default:
7337 gcc_unreachable();
7339 case SS_PLUS:
7340 case SS_MINUS:
7342 if (out_brvc)
7343 avr_asm_len ("brvc 0f", op, plen, 1);
7345 if (reg_overlap_mentioned_p (xop[0], xop[2]))
7347 /* [1s,reg] */
7349 if (n_bytes == 1)
7350 avr_asm_len ("ldi %0,0x7f" CR_TAB
7351 "adc %0,__zero_reg__", op, plen, 2);
7352 else
7353 avr_asm_len ("ldi %0,0x7f" CR_TAB
7354 "ldi %1,0xff" CR_TAB
7355 "adc %1,__zero_reg__" CR_TAB
7356 "adc %0,__zero_reg__", op, plen, 4);
7358 else if (sign == 0 && PLUS == code)
7360 /* [1s,reg] */
7362 op[2] = simplify_gen_subreg (QImode, xop[2], mode, n_bytes-1);
7364 if (n_bytes == 1)
7365 avr_asm_len ("ldi %0,0x80" CR_TAB
7366 "sbrs %2,7" CR_TAB
7367 "dec %0", op, plen, 3);
7368 else
7369 avr_asm_len ("ldi %0,0x80" CR_TAB
7370 "cp %2,%0" CR_TAB
7371 "sbc %1,%1" CR_TAB
7372 "sbci %0,0", op, plen, 4);
7374 else if (sign == 0 && MINUS == code)
7376 /* [3s,reg] */
7378 op[2] = simplify_gen_subreg (QImode, xop[2], mode, n_bytes-1);
7380 if (n_bytes == 1)
7381 avr_asm_len ("ldi %0,0x7f" CR_TAB
7382 "sbrs %2,7" CR_TAB
7383 "inc %0", op, plen, 3);
7384 else
7385 avr_asm_len ("ldi %0,0x7f" CR_TAB
7386 "cp %0,%2" CR_TAB
7387 "sbc %1,%1" CR_TAB
7388 "sbci %0,-1", op, plen, 4);
7390 else if ((sign < 0) ^ (SS_MINUS == code_sat))
7392 /* [1s,const,B < 0] [2s,B < 0] */
7393 /* [3s,const,B > 0] [4s,B > 0] */
7395 if (n_bytes == 8)
7397 avr_asm_len ("%~call __clr_8", op, plen, len_call);
7398 need_copy = false;
7401 avr_asm_len ("ldi %0,0x80", op, plen, 1);
7402 if (n_bytes > 1 && need_copy)
7403 avr_asm_len ("clr %1", op, plen, 1);
7405 else if ((sign > 0) ^ (SS_MINUS == code_sat))
7407 /* [1s,const,B > 0] [2s,B > 0] */
7408 /* [3s,const,B < 0] [4s,B < 0] */
7410 if (n_bytes == 8)
7412 avr_asm_len ("sec" CR_TAB
7413 "%~call __sbc_8", op, plen, 1 + len_call);
7414 need_copy = false;
7417 avr_asm_len ("ldi %0,0x7f", op, plen, 1);
7418 if (n_bytes > 1 && need_copy)
7419 avr_asm_len ("ldi %1,0xff", op, plen, 1);
7421 else
7422 gcc_unreachable();
7424 break;
7426 case US_PLUS:
7427 /* [1u] : [2u] */
7429 avr_asm_len (PLUS == code ? "brcc 0f" : "brcs 0f", op, plen, 1);
7431 if (n_bytes == 8)
7433 if (MINUS == code)
7434 avr_asm_len ("sec", op, plen, 1);
7435 avr_asm_len ("%~call __sbc_8", op, plen, len_call);
7437 need_copy = false;
7439 else
7441 if (MINUS == code && !test_hard_reg_class (LD_REGS, op[0]))
7442 avr_asm_len ("sec" CR_TAB
7443 "sbc %0,%0", op, plen, 2);
7444 else
7445 avr_asm_len (PLUS == code ? "sbc %0,%0" : "ldi %0,0xff",
7446 op, plen, 1);
7448 break; /* US_PLUS */
7450 case US_MINUS:
7451 /* [4u] : [3u] */
7453 avr_asm_len (PLUS == code ? "brcs 0f" : "brcc 0f", op, plen, 1);
7455 if (n_bytes == 8)
7457 avr_asm_len ("%~call __clr_8", op, plen, len_call);
7458 need_copy = false;
7460 else
7461 avr_asm_len ("clr %0", op, plen, 1);
7463 break;
7466 /* We set the MSB in the unsigned case and the 2 MSBs in the signed case.
7467 Now copy the right value to the LSBs. */
7469 if (need_copy && n_bytes > 1)
7471 if (US_MINUS == code_sat || US_PLUS == code_sat)
7473 avr_asm_len ("mov %1,%0", op, plen, 1);
7475 if (n_bytes > 2)
7477 op[0] = xop[0];
7478 if (AVR_HAVE_MOVW)
7479 avr_asm_len ("movw %0,%1", op, plen, 1);
7480 else
7481 avr_asm_len ("mov %A0,%1" CR_TAB
7482 "mov %B0,%1", op, plen, 2);
7485 else if (n_bytes > 2)
7487 op[0] = xop[0];
7488 avr_asm_len ("mov %A0,%1" CR_TAB
7489 "mov %B0,%1", op, plen, 2);
7493 if (need_copy && n_bytes == 8)
7495 if (AVR_HAVE_MOVW)
7496 avr_asm_len ("movw %r0+2,%0" CR_TAB
7497 "movw %r0+4,%0", xop, plen, 2);
7498 else
7499 avr_asm_len ("mov %r0+2,%0" CR_TAB
7500 "mov %r0+3,%0" CR_TAB
7501 "mov %r0+4,%0" CR_TAB
7502 "mov %r0+5,%0", xop, plen, 4);
7505 if (out_label)
7506 avr_asm_len ("0:", op, plen, 0);
7510 /* Output addition/subtraction of register XOP[0] and a constant XOP[2] that
7511 is ont a compile-time constant:
7513 XOP[0] = XOP[0] +/- XOP[2]
7515 This is a helper for the function below. The only insns that need this
7516 are additions/subtraction for pointer modes, i.e. HImode and PSImode. */
7518 static const char*
7519 avr_out_plus_symbol (rtx *xop, enum rtx_code code, int *plen, int *pcc)
7521 machine_mode mode = GET_MODE (xop[0]);
7523 /* Only pointer modes want to add symbols. */
7525 gcc_assert (mode == HImode || mode == PSImode);
7527 *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_SET_N;
7529 avr_asm_len (PLUS == code
7530 ? "subi %A0,lo8(-(%2))" CR_TAB "sbci %B0,hi8(-(%2))"
7531 : "subi %A0,lo8(%2)" CR_TAB "sbci %B0,hi8(%2)",
7532 xop, plen, -2);
7534 if (PSImode == mode)
7535 avr_asm_len (PLUS == code
7536 ? "sbci %C0,hlo8(-(%2))"
7537 : "sbci %C0,hlo8(%2)", xop, plen, 1);
7538 return "";
7542 /* Prepare operands of addition/subtraction to be used with avr_out_plus_1.
7544 INSN is a single_set insn or an insn pattern with a binary operation as
7545 SET_SRC that is one of: PLUS, SS_PLUS, US_PLUS, MINUS, SS_MINUS, US_MINUS.
7547 XOP are the operands of INSN. In the case of 64-bit operations with
7548 constant XOP[] has just one element: The summand/subtrahend in XOP[0].
7549 The non-saturating insns up to 32 bits may or may not supply a "d" class
7550 scratch as XOP[3].
7552 If PLEN == NULL output the instructions.
7553 If PLEN != NULL set *PLEN to the length of the sequence in words.
7555 PCC is a pointer to store the instructions' effect on cc0.
7556 PCC may be NULL.
7558 PLEN and PCC default to NULL.
7560 OUT_LABEL defaults to TRUE. For a description, see AVR_OUT_PLUS_1.
7562 Return "" */
7564 const char*
7565 avr_out_plus (rtx insn, rtx *xop, int *plen, int *pcc, bool out_label)
7567 int cc_plus, cc_minus, cc_dummy;
7568 int len_plus, len_minus;
7569 rtx op[4];
7570 rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
7571 rtx xdest = SET_DEST (xpattern);
7572 machine_mode mode = GET_MODE (xdest);
7573 machine_mode imode = int_mode_for_mode (mode);
7574 int n_bytes = GET_MODE_SIZE (mode);
7575 enum rtx_code code_sat = GET_CODE (SET_SRC (xpattern));
7576 enum rtx_code code
7577 = (PLUS == code_sat || SS_PLUS == code_sat || US_PLUS == code_sat
7578 ? PLUS : MINUS);
7580 if (!pcc)
7581 pcc = &cc_dummy;
7583 /* PLUS and MINUS don't saturate: Use modular wrap-around. */
7585 if (PLUS == code_sat || MINUS == code_sat)
7586 code_sat = UNKNOWN;
7588 if (n_bytes <= 4 && REG_P (xop[2]))
7590 avr_out_plus_1 (xop, plen, code, pcc, code_sat, 0, out_label);
7591 return "";
7594 if (8 == n_bytes)
7596 op[0] = gen_rtx_REG (DImode, ACC_A);
7597 op[1] = gen_rtx_REG (DImode, ACC_A);
7598 op[2] = avr_to_int_mode (xop[0]);
7600 else
7602 if (!REG_P (xop[2])
7603 && !CONST_INT_P (xop[2])
7604 && !CONST_FIXED_P (xop[2]))
7606 return avr_out_plus_symbol (xop, code, plen, pcc);
7609 op[0] = avr_to_int_mode (xop[0]);
7610 op[1] = avr_to_int_mode (xop[1]);
7611 op[2] = avr_to_int_mode (xop[2]);
7614 /* Saturations and 64-bit operations don't have a clobber operand.
7615 For the other cases, the caller will provide a proper XOP[3]. */
7617 xpattern = INSN_P (insn) ? PATTERN (insn) : insn;
7618 op[3] = PARALLEL == GET_CODE (xpattern) ? xop[3] : NULL_RTX;
7620 /* Saturation will need the sign of the original operand. */
7622 rtx xmsb = simplify_gen_subreg (QImode, op[2], imode, n_bytes-1);
7623 int sign = INTVAL (xmsb) < 0 ? -1 : 1;
7625 /* If we subtract and the subtrahend is a constant, then negate it
7626 so that avr_out_plus_1 can be used. */
7628 if (MINUS == code)
7629 op[2] = simplify_unary_operation (NEG, imode, op[2], imode);
7631 /* Work out the shortest sequence. */
7633 avr_out_plus_1 (op, &len_minus, MINUS, &cc_minus, code_sat, sign, out_label);
7634 avr_out_plus_1 (op, &len_plus, PLUS, &cc_plus, code_sat, sign, out_label);
7636 if (plen)
7638 *plen = (len_minus <= len_plus) ? len_minus : len_plus;
7639 *pcc = (len_minus <= len_plus) ? cc_minus : cc_plus;
7641 else if (len_minus <= len_plus)
7642 avr_out_plus_1 (op, NULL, MINUS, pcc, code_sat, sign, out_label);
7643 else
7644 avr_out_plus_1 (op, NULL, PLUS, pcc, code_sat, sign, out_label);
7646 return "";
7650 /* Output bit operation (IOR, AND, XOR) with register XOP[0] and compile
7651 time constant XOP[2]:
7653 XOP[0] = XOP[0] <op> XOP[2]
7655 and return "". If PLEN == NULL, print assembler instructions to perform the
7656 operation; otherwise, set *PLEN to the length of the instruction sequence
7657 (in words) printed with PLEN == NULL. XOP[3] is either an 8-bit clobber
7658 register or SCRATCH if no clobber register is needed for the operation.
7659 INSN is an INSN_P or a pattern of an insn. */
7661 const char*
7662 avr_out_bitop (rtx insn, rtx *xop, int *plen)
7664 /* CODE and MODE of the operation. */
7665 rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
7666 enum rtx_code code = GET_CODE (SET_SRC (xpattern));
7667 machine_mode mode = GET_MODE (xop[0]);
7669 /* Number of bytes to operate on. */
7670 int i, n_bytes = GET_MODE_SIZE (mode);
7672 /* Value of T-flag (0 or 1) or -1 if unknow. */
7673 int set_t = -1;
7675 /* Value (0..0xff) held in clobber register op[3] or -1 if unknown. */
7676 int clobber_val = -1;
7678 /* op[0]: 8-bit destination register
7679 op[1]: 8-bit const int
7680 op[2]: 8-bit clobber register or SCRATCH
7681 op[3]: 8-bit register containing 0xff or NULL_RTX */
7682 rtx op[4];
7684 op[2] = xop[3];
7685 op[3] = NULL_RTX;
7687 if (plen)
7688 *plen = 0;
7690 for (i = 0; i < n_bytes; i++)
7692 /* We operate byte-wise on the destination. */
7693 rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
7694 rtx xval8 = simplify_gen_subreg (QImode, xop[2], mode, i);
7696 /* 8-bit value to operate with this byte. */
7697 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
7699 /* Number of bits set in the current byte of the constant. */
7700 int pop8 = avr_popcount (val8);
7702 /* Registers R16..R31 can operate with immediate. */
7703 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
7705 op[0] = reg8;
7706 op[1] = GEN_INT (val8);
7708 switch (code)
7710 case IOR:
7712 if (0 == pop8)
7713 continue;
7714 else if (ld_reg_p)
7715 avr_asm_len ("ori %0,%1", op, plen, 1);
7716 else if (1 == pop8)
7718 if (set_t != 1)
7719 avr_asm_len ("set", op, plen, 1);
7720 set_t = 1;
7722 op[1] = GEN_INT (exact_log2 (val8));
7723 avr_asm_len ("bld %0,%1", op, plen, 1);
7725 else if (8 == pop8)
7727 if (op[3] != NULL_RTX)
7728 avr_asm_len ("mov %0,%3", op, plen, 1);
7729 else
7730 avr_asm_len ("clr %0" CR_TAB
7731 "dec %0", op, plen, 2);
7733 op[3] = op[0];
7735 else
7737 if (clobber_val != (int) val8)
7738 avr_asm_len ("ldi %2,%1", op, plen, 1);
7739 clobber_val = (int) val8;
7741 avr_asm_len ("or %0,%2", op, plen, 1);
7744 continue; /* IOR */
7746 case AND:
7748 if (8 == pop8)
7749 continue;
7750 else if (0 == pop8)
7751 avr_asm_len ("clr %0", op, plen, 1);
7752 else if (ld_reg_p)
7753 avr_asm_len ("andi %0,%1", op, plen, 1);
7754 else if (7 == pop8)
7756 if (set_t != 0)
7757 avr_asm_len ("clt", op, plen, 1);
7758 set_t = 0;
7760 op[1] = GEN_INT (exact_log2 (GET_MODE_MASK (QImode) & ~val8));
7761 avr_asm_len ("bld %0,%1", op, plen, 1);
7763 else
7765 if (clobber_val != (int) val8)
7766 avr_asm_len ("ldi %2,%1", op, plen, 1);
7767 clobber_val = (int) val8;
7769 avr_asm_len ("and %0,%2", op, plen, 1);
7772 continue; /* AND */
7774 case XOR:
7776 if (0 == pop8)
7777 continue;
7778 else if (8 == pop8)
7779 avr_asm_len ("com %0", op, plen, 1);
7780 else if (ld_reg_p && val8 == (1 << 7))
7781 avr_asm_len ("subi %0,%1", op, plen, 1);
7782 else
7784 if (clobber_val != (int) val8)
7785 avr_asm_len ("ldi %2,%1", op, plen, 1);
7786 clobber_val = (int) val8;
7788 avr_asm_len ("eor %0,%2", op, plen, 1);
7791 continue; /* XOR */
7793 default:
7794 /* Unknown rtx_code */
7795 gcc_unreachable();
7797 } /* for all sub-bytes */
7799 return "";
7803 /* Output sign extension from XOP[1] to XOP[0] and return "".
7804 If PLEN == NULL, print assembler instructions to perform the operation;
7805 otherwise, set *PLEN to the length of the instruction sequence (in words)
7806 as printed with PLEN == NULL. */
7808 const char*
7809 avr_out_sign_extend (rtx_insn *insn, rtx *xop, int *plen)
7811 // Size in bytes of source resp. destination operand.
7812 unsigned n_src = GET_MODE_SIZE (GET_MODE (xop[1]));
7813 unsigned n_dest = GET_MODE_SIZE (GET_MODE (xop[0]));
7814 rtx r_msb = all_regs_rtx[REGNO (xop[1]) + n_src - 1];
7816 if (plen)
7817 *plen = 0;
7819 // Copy destination to source
7821 if (REGNO (xop[0]) != REGNO (xop[1]))
7823 gcc_assert (n_src <= 2);
7825 if (n_src == 2)
7826 avr_asm_len (AVR_HAVE_MOVW
7827 ? "movw %0,%1"
7828 : "mov %B0,%B1", xop, plen, 1);
7829 if (n_src == 1 || !AVR_HAVE_MOVW)
7830 avr_asm_len ("mov %A0,%A1", xop, plen, 1);
7833 // Set Carry to the sign bit MSB.7...
7835 if (REGNO (xop[0]) == REGNO (xop[1])
7836 || !reg_unused_after (insn, r_msb))
7838 avr_asm_len ("mov __tmp_reg__,%0", &r_msb, plen, 1);
7839 r_msb = tmp_reg_rtx;
7842 avr_asm_len ("lsl %0", &r_msb, plen, 1);
7844 // ...and propagate it to all the new sign bits
7846 for (unsigned n = n_src; n < n_dest; n++)
7847 avr_asm_len ("sbc %0,%0", &all_regs_rtx[REGNO (xop[0]) + n], plen, 1);
7849 return "";
7853 /* PLEN == NULL: Output code to add CONST_INT OP[0] to SP.
7854 PLEN != NULL: Set *PLEN to the length of that sequence.
7855 Return "". */
7857 const char*
7858 avr_out_addto_sp (rtx *op, int *plen)
7860 int pc_len = AVR_2_BYTE_PC ? 2 : 3;
7861 int addend = INTVAL (op[0]);
7863 if (plen)
7864 *plen = 0;
7866 if (addend < 0)
7868 if (flag_verbose_asm || flag_print_asm_name)
7869 avr_asm_len (ASM_COMMENT_START "SP -= %n0", op, plen, 0);
7871 while (addend <= -pc_len)
7873 addend += pc_len;
7874 avr_asm_len ("rcall .", op, plen, 1);
7877 while (addend++ < 0)
7878 avr_asm_len ("push __zero_reg__", op, plen, 1);
7880 else if (addend > 0)
7882 if (flag_verbose_asm || flag_print_asm_name)
7883 avr_asm_len (ASM_COMMENT_START "SP += %0", op, plen, 0);
7885 while (addend-- > 0)
7886 avr_asm_len ("pop __tmp_reg__", op, plen, 1);
7889 return "";
7893 /* Outputs instructions needed for fixed point type conversion.
7894 This includes converting between any fixed point type, as well
7895 as converting to any integer type. Conversion between integer
7896 types is not supported.
7898 Converting signed fractional types requires a bit shift if converting
7899 to or from any unsigned fractional type because the decimal place is
7900 shifted by 1 bit. When the destination is a signed fractional, the sign
7901 is stored in either the carry or T bit. */
7903 const char*
7904 avr_out_fract (rtx_insn *insn, rtx operands[], bool intsigned, int *plen)
7906 size_t i;
7907 rtx xop[6];
7908 RTX_CODE shift = UNKNOWN;
7909 bool sign_in_carry = false;
7910 bool msb_in_carry = false;
7911 bool lsb_in_tmp_reg = false;
7912 bool lsb_in_carry = false;
7913 bool frac_rounded = false;
7914 const char *code_ashift = "lsl %0";
7917 #define MAY_CLOBBER(RR) \
7918 /* Shorthand used below. */ \
7919 ((sign_bytes \
7920 && IN_RANGE (RR, dest.regno_msb - sign_bytes + 1, dest.regno_msb)) \
7921 || (offset && IN_RANGE (RR, dest.regno, dest.regno_msb)) \
7922 || (reg_unused_after (insn, all_regs_rtx[RR]) \
7923 && !IN_RANGE (RR, dest.regno, dest.regno_msb)))
7925 struct
7927 /* bytes : Length of operand in bytes.
7928 ibyte : Length of integral part in bytes.
7929 fbyte, fbit : Length of fractional part in bytes, bits. */
7931 bool sbit;
7932 unsigned fbit, bytes, ibyte, fbyte;
7933 unsigned regno, regno_msb;
7934 } dest, src, *val[2] = { &dest, &src };
7936 if (plen)
7937 *plen = 0;
7939 /* Step 0: Determine information on source and destination operand we
7940 ====== will need in the remainder. */
7942 for (i = 0; i < sizeof (val) / sizeof (*val); i++)
7944 machine_mode mode;
7946 xop[i] = operands[i];
7948 mode = GET_MODE (xop[i]);
7950 val[i]->bytes = GET_MODE_SIZE (mode);
7951 val[i]->regno = REGNO (xop[i]);
7952 val[i]->regno_msb = REGNO (xop[i]) + val[i]->bytes - 1;
7954 if (SCALAR_INT_MODE_P (mode))
7956 val[i]->sbit = intsigned;
7957 val[i]->fbit = 0;
7959 else if (ALL_SCALAR_FIXED_POINT_MODE_P (mode))
7961 val[i]->sbit = SIGNED_SCALAR_FIXED_POINT_MODE_P (mode);
7962 val[i]->fbit = GET_MODE_FBIT (mode);
7964 else
7965 fatal_insn ("unsupported fixed-point conversion", insn);
7967 val[i]->fbyte = (1 + val[i]->fbit) / BITS_PER_UNIT;
7968 val[i]->ibyte = val[i]->bytes - val[i]->fbyte;
7971 // Byte offset of the decimal point taking into account different place
7972 // of the decimal point in input and output and different register numbers
7973 // of input and output.
7974 int offset = dest.regno - src.regno + dest.fbyte - src.fbyte;
7976 // Number of destination bytes that will come from sign / zero extension.
7977 int sign_bytes = (dest.ibyte - src.ibyte) * (dest.ibyte > src.ibyte);
7979 // Number of bytes at the low end to be filled with zeros.
7980 int zero_bytes = (dest.fbyte - src.fbyte) * (dest.fbyte > src.fbyte);
7982 // Do we have a 16-Bit register that is cleared?
7983 rtx clrw = NULL_RTX;
7985 bool sign_extend = src.sbit && sign_bytes;
7987 if (0 == dest.fbit % 8 && 7 == src.fbit % 8)
7988 shift = ASHIFT;
7989 else if (7 == dest.fbit % 8 && 0 == src.fbit % 8)
7990 shift = ASHIFTRT;
7991 else if (dest.fbit % 8 == src.fbit % 8)
7992 shift = UNKNOWN;
7993 else
7994 gcc_unreachable();
7996 /* If we need to round the fraction part, we might need to save/round it
7997 before clobbering any of it in Step 1. Also, we might want to do
7998 the rounding now to make use of LD_REGS. */
7999 if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8000 && SCALAR_ACCUM_MODE_P (GET_MODE (xop[1]))
8001 && !TARGET_FRACT_CONV_TRUNC)
8003 bool overlap
8004 = (src.regno <=
8005 (offset ? dest.regno_msb - sign_bytes : dest.regno + zero_bytes - 1)
8006 && dest.regno - offset -1 >= dest.regno);
8007 unsigned s0 = dest.regno - offset -1;
8008 bool use_src = true;
8009 unsigned sn;
8010 unsigned copied_msb = src.regno_msb;
8011 bool have_carry = false;
8013 if (src.ibyte > dest.ibyte)
8014 copied_msb -= src.ibyte - dest.ibyte;
8016 for (sn = s0; sn <= copied_msb; sn++)
8017 if (!IN_RANGE (sn, dest.regno, dest.regno_msb)
8018 && !reg_unused_after (insn, all_regs_rtx[sn]))
8019 use_src = false;
8020 if (use_src && TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], s0))
8022 avr_asm_len ("tst %0" CR_TAB "brpl 0f",
8023 &all_regs_rtx[src.regno_msb], plen, 2);
8024 sn = src.regno;
8025 if (sn < s0)
8027 if (TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], sn))
8028 avr_asm_len ("cpi %0,1", &all_regs_rtx[sn], plen, 1);
8029 else
8030 avr_asm_len ("sec" CR_TAB
8031 "cpc %0,__zero_reg__",
8032 &all_regs_rtx[sn], plen, 2);
8033 have_carry = true;
8035 while (++sn < s0)
8036 avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8038 avr_asm_len (have_carry ? "sbci %0,128" : "subi %0,129",
8039 &all_regs_rtx[s0], plen, 1);
8040 for (sn = src.regno + src.fbyte; sn <= copied_msb; sn++)
8041 avr_asm_len ("sbci %0,255", &all_regs_rtx[sn], plen, 1);
8042 avr_asm_len ("\n0:", NULL, plen, 0);
8043 frac_rounded = true;
8045 else if (use_src && overlap)
8047 avr_asm_len ("clr __tmp_reg__" CR_TAB
8048 "sbrc %1,0" CR_TAB
8049 "dec __tmp_reg__", xop, plen, 1);
8050 sn = src.regno;
8051 if (sn < s0)
8053 avr_asm_len ("add %0,__tmp_reg__", &all_regs_rtx[sn], plen, 1);
8054 have_carry = true;
8057 while (++sn < s0)
8058 avr_asm_len ("adc %0,__tmp_reg__", &all_regs_rtx[sn], plen, 1);
8060 if (have_carry)
8061 avr_asm_len ("clt" CR_TAB
8062 "bld __tmp_reg__,7" CR_TAB
8063 "adc %0,__tmp_reg__",
8064 &all_regs_rtx[s0], plen, 1);
8065 else
8066 avr_asm_len ("lsr __tmp_reg" CR_TAB
8067 "add %0,__tmp_reg__",
8068 &all_regs_rtx[s0], plen, 2);
8069 for (sn = src.regno + src.fbyte; sn <= copied_msb; sn++)
8070 avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8071 frac_rounded = true;
8073 else if (overlap)
8075 bool use_src
8076 = (TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], s0)
8077 && (IN_RANGE (s0, dest.regno, dest.regno_msb)
8078 || reg_unused_after (insn, all_regs_rtx[s0])));
8079 xop[2] = all_regs_rtx[s0];
8080 unsigned sn = src.regno;
8081 if (!use_src || sn == s0)
8082 avr_asm_len ("mov __tmp_reg__,%2", xop, plen, 1);
8083 /* We need to consider to-be-discarded bits
8084 if the value is negative. */
8085 if (sn < s0)
8087 avr_asm_len ("tst %0" CR_TAB
8088 "brpl 0f",
8089 &all_regs_rtx[src.regno_msb], plen, 2);
8090 /* Test to-be-discarded bytes for any nozero bits.
8091 ??? Could use OR or SBIW to test two registers at once. */
8092 if (sn < s0)
8093 avr_asm_len ("cp %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8095 while (++sn < s0)
8096 avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8097 /* Set bit 0 in __tmp_reg__ if any of the lower bits was set. */
8098 if (use_src)
8099 avr_asm_len ("breq 0f" CR_TAB
8100 "ori %2,1"
8101 "\n0:\t" "mov __tmp_reg__,%2",
8102 xop, plen, 3);
8103 else
8104 avr_asm_len ("breq 0f" CR_TAB
8105 "set" CR_TAB
8106 "bld __tmp_reg__,0\n0:",
8107 xop, plen, 3);
8109 lsb_in_tmp_reg = true;
8113 /* Step 1: Clear bytes at the low end and copy payload bits from source
8114 ====== to destination. */
8116 int step = offset < 0 ? 1 : -1;
8117 unsigned d0 = offset < 0 ? dest.regno : dest.regno_msb;
8119 // We cleared at least that number of registers.
8120 int clr_n = 0;
8122 for (; d0 >= dest.regno && d0 <= dest.regno_msb; d0 += step)
8124 // Next regno of destination is needed for MOVW
8125 unsigned d1 = d0 + step;
8127 // Current and next regno of source
8128 signed s0 = d0 - offset;
8129 signed s1 = s0 + step;
8131 // Must current resp. next regno be CLRed? This applies to the low
8132 // bytes of the destination that have no associated source bytes.
8133 bool clr0 = s0 < (signed) src.regno;
8134 bool clr1 = s1 < (signed) src.regno && d1 >= dest.regno;
8136 // First gather what code to emit (if any) and additional step to
8137 // apply if a MOVW is in use. xop[2] is destination rtx and xop[3]
8138 // is the source rtx for the current loop iteration.
8139 const char *code = NULL;
8140 int stepw = 0;
8142 if (clr0)
8144 if (AVR_HAVE_MOVW && clr1 && clrw)
8146 xop[2] = all_regs_rtx[d0 & ~1];
8147 xop[3] = clrw;
8148 code = "movw %2,%3";
8149 stepw = step;
8151 else
8153 xop[2] = all_regs_rtx[d0];
8154 code = "clr %2";
8156 if (++clr_n >= 2
8157 && !clrw
8158 && d0 % 2 == (step > 0))
8160 clrw = all_regs_rtx[d0 & ~1];
8164 else if (offset && s0 <= (signed) src.regno_msb)
8166 int movw = AVR_HAVE_MOVW && offset % 2 == 0
8167 && d0 % 2 == (offset > 0)
8168 && d1 <= dest.regno_msb && d1 >= dest.regno
8169 && s1 <= (signed) src.regno_msb && s1 >= (signed) src.regno;
8171 xop[2] = all_regs_rtx[d0 & ~movw];
8172 xop[3] = all_regs_rtx[s0 & ~movw];
8173 code = movw ? "movw %2,%3" : "mov %2,%3";
8174 stepw = step * movw;
8177 if (code)
8179 if (sign_extend && shift != ASHIFT && !sign_in_carry
8180 && (d0 == src.regno_msb || d0 + stepw == src.regno_msb))
8182 /* We are going to override the sign bit. If we sign-extend,
8183 store the sign in the Carry flag. This is not needed if
8184 the destination will be ASHIFT in the remainder because
8185 the ASHIFT will set Carry without extra instruction. */
8187 avr_asm_len ("lsl %0", &all_regs_rtx[src.regno_msb], plen, 1);
8188 sign_in_carry = true;
8191 unsigned src_msb = dest.regno_msb - sign_bytes - offset + 1;
8193 if (!sign_extend && shift == ASHIFTRT && !msb_in_carry
8194 && src.ibyte > dest.ibyte
8195 && (d0 == src_msb || d0 + stepw == src_msb))
8197 /* We are going to override the MSB. If we shift right,
8198 store the MSB in the Carry flag. This is only needed if
8199 we don't sign-extend becaue with sign-extension the MSB
8200 (the sign) will be produced by the sign extension. */
8202 avr_asm_len ("lsr %0", &all_regs_rtx[src_msb], plen, 1);
8203 msb_in_carry = true;
8206 unsigned src_lsb = dest.regno - offset -1;
8208 if (shift == ASHIFT && src.fbyte > dest.fbyte && !lsb_in_carry
8209 && !lsb_in_tmp_reg
8210 && (d0 == src_lsb || d0 + stepw == src_lsb))
8212 /* We are going to override the new LSB; store it into carry. */
8214 avr_asm_len ("lsl %0", &all_regs_rtx[src_lsb], plen, 1);
8215 code_ashift = "rol %0";
8216 lsb_in_carry = true;
8219 avr_asm_len (code, xop, plen, 1);
8220 d0 += stepw;
8224 /* Step 2: Shift destination left by 1 bit position. This might be needed
8225 ====== for signed input and unsigned output. */
8227 if (shift == ASHIFT && src.fbyte > dest.fbyte && !lsb_in_carry)
8229 unsigned s0 = dest.regno - offset -1;
8231 /* n1169 4.1.4 says:
8232 "Conversions from a fixed-point to an integer type round toward zero."
8233 Hence, converting a fract type to integer only gives a non-zero result
8234 for -1. */
8235 if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8236 && SCALAR_FRACT_MODE_P (GET_MODE (xop[1]))
8237 && !TARGET_FRACT_CONV_TRUNC)
8239 gcc_assert (s0 == src.regno_msb);
8240 /* Check if the input is -1. We do that by checking if negating
8241 the input causes an integer overflow. */
8242 unsigned sn = src.regno;
8243 avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx[sn++], plen, 1);
8244 while (sn <= s0)
8245 avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx[sn++], plen, 1);
8247 /* Overflow goes with set carry. Clear carry otherwise. */
8248 avr_asm_len ("brvs 0f" CR_TAB
8249 "clc\n0:", NULL, plen, 2);
8251 /* Likewise, when converting from accumulator types to integer, we
8252 need to round up negative values. */
8253 else if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8254 && SCALAR_ACCUM_MODE_P (GET_MODE (xop[1]))
8255 && !TARGET_FRACT_CONV_TRUNC
8256 && !frac_rounded)
8258 bool have_carry = false;
8260 xop[2] = all_regs_rtx[s0];
8261 if (!lsb_in_tmp_reg && !MAY_CLOBBER (s0))
8262 avr_asm_len ("mov __tmp_reg__,%2", xop, plen, 1);
8263 avr_asm_len ("tst %0" CR_TAB "brpl 0f",
8264 &all_regs_rtx[src.regno_msb], plen, 2);
8265 if (!lsb_in_tmp_reg)
8267 unsigned sn = src.regno;
8268 if (sn < s0)
8270 avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx[sn],
8271 plen, 1);
8272 have_carry = true;
8274 while (++sn < s0)
8275 avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx[sn], plen, 1);
8276 lsb_in_tmp_reg = !MAY_CLOBBER (s0);
8278 /* Add in C and the rounding value 127. */
8279 /* If the destination msb is a sign byte, and in LD_REGS,
8280 grab it as a temporary. */
8281 if (sign_bytes
8282 && TEST_HARD_REG_BIT (reg_class_contents[LD_REGS],
8283 dest.regno_msb))
8285 xop[3] = all_regs_rtx[dest.regno_msb];
8286 avr_asm_len ("ldi %3,127", xop, plen, 1);
8287 avr_asm_len ((have_carry && lsb_in_tmp_reg ? "adc __tmp_reg__,%3"
8288 : have_carry ? "adc %2,%3"
8289 : lsb_in_tmp_reg ? "add __tmp_reg__,%3"
8290 : "add %2,%3"),
8291 xop, plen, 1);
8293 else
8295 /* Fall back to use __zero_reg__ as a temporary. */
8296 avr_asm_len ("dec __zero_reg__", NULL, plen, 1);
8297 if (have_carry)
8298 avr_asm_len ("clt" CR_TAB
8299 "bld __zero_reg__,7", NULL, plen, 2);
8300 else
8301 avr_asm_len ("lsr __zero_reg__", NULL, plen, 1);
8302 avr_asm_len (have_carry && lsb_in_tmp_reg
8303 ? "adc __tmp_reg__,__zero_reg__"
8304 : have_carry ? "adc %2,__zero_reg__"
8305 : lsb_in_tmp_reg ? "add __tmp_reg__,__zero_reg__"
8306 : "add %2,__zero_reg__",
8307 xop, plen, 1);
8308 avr_asm_len ("eor __zero_reg__,__zero_reg__", NULL, plen, 1);
8311 for (d0 = dest.regno + zero_bytes;
8312 d0 <= dest.regno_msb - sign_bytes; d0++)
8313 avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx[d0], plen, 1);
8315 avr_asm_len (lsb_in_tmp_reg
8316 ? "\n0:\t" "lsl __tmp_reg__"
8317 : "\n0:\t" "lsl %2",
8318 xop, plen, 1);
8320 else if (MAY_CLOBBER (s0))
8321 avr_asm_len ("lsl %0", &all_regs_rtx[s0], plen, 1);
8322 else
8323 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
8324 "lsl __tmp_reg__", &all_regs_rtx[s0], plen, 2);
8326 code_ashift = "rol %0";
8327 lsb_in_carry = true;
8330 if (shift == ASHIFT)
8332 for (d0 = dest.regno + zero_bytes;
8333 d0 <= dest.regno_msb - sign_bytes; d0++)
8335 avr_asm_len (code_ashift, &all_regs_rtx[d0], plen, 1);
8336 code_ashift = "rol %0";
8339 lsb_in_carry = false;
8340 sign_in_carry = true;
8343 /* Step 4a: Store MSB in carry if we don't already have it or will produce
8344 ======= it in sign-extension below. */
8346 if (!sign_extend && shift == ASHIFTRT && !msb_in_carry
8347 && src.ibyte > dest.ibyte)
8349 unsigned s0 = dest.regno_msb - sign_bytes - offset + 1;
8351 if (MAY_CLOBBER (s0))
8352 avr_asm_len ("lsr %0", &all_regs_rtx[s0], plen, 1);
8353 else
8354 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
8355 "lsr __tmp_reg__", &all_regs_rtx[s0], plen, 2);
8357 msb_in_carry = true;
8360 /* Step 3: Sign-extend or zero-extend the destination as needed.
8361 ====== */
8363 if (sign_extend && !sign_in_carry)
8365 unsigned s0 = src.regno_msb;
8367 if (MAY_CLOBBER (s0))
8368 avr_asm_len ("lsl %0", &all_regs_rtx[s0], plen, 1);
8369 else
8370 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
8371 "lsl __tmp_reg__", &all_regs_rtx[s0], plen, 2);
8373 sign_in_carry = true;
8376 gcc_assert (sign_in_carry + msb_in_carry + lsb_in_carry <= 1);
8378 unsigned copies = 0;
8379 rtx movw = sign_extend ? NULL_RTX : clrw;
8381 for (d0 = dest.regno_msb - sign_bytes + 1; d0 <= dest.regno_msb; d0++)
8383 if (AVR_HAVE_MOVW && movw
8384 && d0 % 2 == 0 && d0 + 1 <= dest.regno_msb)
8386 xop[2] = all_regs_rtx[d0];
8387 xop[3] = movw;
8388 avr_asm_len ("movw %2,%3", xop, plen, 1);
8389 d0++;
8391 else
8393 avr_asm_len (sign_extend ? "sbc %0,%0" : "clr %0",
8394 &all_regs_rtx[d0], plen, 1);
8396 if (++copies >= 2 && !movw && d0 % 2 == 1)
8397 movw = all_regs_rtx[d0-1];
8399 } /* for */
8402 /* Step 4: Right shift the destination. This might be needed for
8403 ====== conversions from unsigned to signed. */
8405 if (shift == ASHIFTRT)
8407 const char *code_ashiftrt = "lsr %0";
8409 if (sign_extend || msb_in_carry)
8410 code_ashiftrt = "ror %0";
8412 if (src.sbit && src.ibyte == dest.ibyte)
8413 code_ashiftrt = "asr %0";
8415 for (d0 = dest.regno_msb - sign_bytes;
8416 d0 >= dest.regno + zero_bytes - 1 && d0 >= dest.regno; d0--)
8418 avr_asm_len (code_ashiftrt, &all_regs_rtx[d0], plen, 1);
8419 code_ashiftrt = "ror %0";
8423 #undef MAY_CLOBBER
8425 return "";
8429 /* Output fixed-point rounding. XOP[0] = XOP[1] is the operand to round.
8430 XOP[2] is the rounding point, a CONST_INT. The function prints the
8431 instruction sequence if PLEN = NULL and computes the length in words
8432 of the sequence if PLEN != NULL. Most of this function deals with
8433 preparing operands for calls to `avr_out_plus' and `avr_out_bitop'. */
8435 const char*
8436 avr_out_round (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *xop, int *plen)
8438 machine_mode mode = GET_MODE (xop[0]);
8439 machine_mode imode = int_mode_for_mode (mode);
8440 // The smallest fractional bit not cleared by the rounding is 2^(-RP).
8441 int fbit = (int) GET_MODE_FBIT (mode);
8442 double_int i_add = double_int_zero.set_bit (fbit-1 - INTVAL (xop[2]));
8443 wide_int wi_add = wi::set_bit_in_zero (fbit-1 - INTVAL (xop[2]),
8444 GET_MODE_PRECISION (imode));
8445 // Lengths of PLUS and AND parts.
8446 int len_add = 0, *plen_add = plen ? &len_add : NULL;
8447 int len_and = 0, *plen_and = plen ? &len_and : NULL;
8449 // Add-Saturate 1/2 * 2^(-RP). Don't print the label "0:" when printing
8450 // the saturated addition so that we can emit the "rjmp 1f" before the
8451 // "0:" below.
8453 rtx xadd = const_fixed_from_double_int (i_add, mode);
8454 rtx xpattern, xsrc, op[4];
8456 xsrc = SIGNED_FIXED_POINT_MODE_P (mode)
8457 ? gen_rtx_SS_PLUS (mode, xop[1], xadd)
8458 : gen_rtx_US_PLUS (mode, xop[1], xadd);
8459 xpattern = gen_rtx_SET (xop[0], xsrc);
8461 op[0] = xop[0];
8462 op[1] = xop[1];
8463 op[2] = xadd;
8464 avr_out_plus (xpattern, op, plen_add, NULL, false /* Don't print "0:" */);
8466 avr_asm_len ("rjmp 1f" CR_TAB
8467 "0:", NULL, plen_add, 1);
8469 // Keep all bits from RP and higher: ... 2^(-RP)
8470 // Clear all bits from RP+1 and lower: 2^(-RP-1) ...
8471 // Rounding point ^^^^^^^
8472 // Added above ^^^^^^^^^
8473 rtx xreg = simplify_gen_subreg (imode, xop[0], mode, 0);
8474 rtx xmask = immed_wide_int_const (-wi_add - wi_add, imode);
8476 xpattern = gen_rtx_SET (xreg, gen_rtx_AND (imode, xreg, xmask));
8478 op[0] = xreg;
8479 op[1] = xreg;
8480 op[2] = xmask;
8481 op[3] = gen_rtx_SCRATCH (QImode);
8482 avr_out_bitop (xpattern, op, plen_and);
8483 avr_asm_len ("1:", NULL, plen, 0);
8485 if (plen)
8486 *plen = len_add + len_and;
8488 return "";
8492 /* Create RTL split patterns for byte sized rotate expressions. This
8493 produces a series of move instructions and considers overlap situations.
8494 Overlapping non-HImode operands need a scratch register. */
8496 bool
8497 avr_rotate_bytes (rtx operands[])
8499 int i, j;
8500 machine_mode mode = GET_MODE (operands[0]);
8501 bool overlapped = reg_overlap_mentioned_p (operands[0], operands[1]);
8502 bool same_reg = rtx_equal_p (operands[0], operands[1]);
8503 int num = INTVAL (operands[2]);
8504 rtx scratch = operands[3];
8505 /* Work out if byte or word move is needed. Odd byte rotates need QImode.
8506 Word move if no scratch is needed, otherwise use size of scratch. */
8507 machine_mode move_mode = QImode;
8508 int move_size, offset, size;
8510 if (num & 0xf)
8511 move_mode = QImode;
8512 else if ((mode == SImode && !same_reg) || !overlapped)
8513 move_mode = HImode;
8514 else
8515 move_mode = GET_MODE (scratch);
8517 /* Force DI rotate to use QI moves since other DI moves are currently split
8518 into QI moves so forward propagation works better. */
8519 if (mode == DImode)
8520 move_mode = QImode;
8521 /* Make scratch smaller if needed. */
8522 if (SCRATCH != GET_CODE (scratch)
8523 && HImode == GET_MODE (scratch)
8524 && QImode == move_mode)
8525 scratch = simplify_gen_subreg (move_mode, scratch, HImode, 0);
8527 move_size = GET_MODE_SIZE (move_mode);
8528 /* Number of bytes/words to rotate. */
8529 offset = (num >> 3) / move_size;
8530 /* Number of moves needed. */
8531 size = GET_MODE_SIZE (mode) / move_size;
8532 /* Himode byte swap is special case to avoid a scratch register. */
8533 if (mode == HImode && same_reg)
8535 /* HImode byte swap, using xor. This is as quick as using scratch. */
8536 rtx src, dst;
8537 src = simplify_gen_subreg (move_mode, operands[1], mode, 0);
8538 dst = simplify_gen_subreg (move_mode, operands[0], mode, 1);
8539 if (!rtx_equal_p (dst, src))
8541 emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
8542 emit_move_insn (src, gen_rtx_XOR (QImode, src, dst));
8543 emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
8546 else
8548 #define MAX_SIZE 8 /* GET_MODE_SIZE (DImode) / GET_MODE_SIZE (QImode) */
8549 /* Create linked list of moves to determine move order. */
8550 struct {
8551 rtx src, dst;
8552 int links;
8553 } move[MAX_SIZE + 8];
8554 int blocked, moves;
8556 gcc_assert (size <= MAX_SIZE);
8557 /* Generate list of subreg moves. */
8558 for (i = 0; i < size; i++)
8560 int from = i;
8561 int to = (from + offset) % size;
8562 move[i].src = simplify_gen_subreg (move_mode, operands[1],
8563 mode, from * move_size);
8564 move[i].dst = simplify_gen_subreg (move_mode, operands[0],
8565 mode, to * move_size);
8566 move[i].links = -1;
8568 /* Mark dependence where a dst of one move is the src of another move.
8569 The first move is a conflict as it must wait until second is
8570 performed. We ignore moves to self - we catch this later. */
8571 if (overlapped)
8572 for (i = 0; i < size; i++)
8573 if (reg_overlap_mentioned_p (move[i].dst, operands[1]))
8574 for (j = 0; j < size; j++)
8575 if (j != i && rtx_equal_p (move[j].src, move[i].dst))
8577 /* The dst of move i is the src of move j. */
8578 move[i].links = j;
8579 break;
8582 blocked = -1;
8583 moves = 0;
8584 /* Go through move list and perform non-conflicting moves. As each
8585 non-overlapping move is made, it may remove other conflicts
8586 so the process is repeated until no conflicts remain. */
8589 blocked = -1;
8590 moves = 0;
8591 /* Emit move where dst is not also a src or we have used that
8592 src already. */
8593 for (i = 0; i < size; i++)
8594 if (move[i].src != NULL_RTX)
8596 if (move[i].links == -1
8597 || move[move[i].links].src == NULL_RTX)
8599 moves++;
8600 /* Ignore NOP moves to self. */
8601 if (!rtx_equal_p (move[i].dst, move[i].src))
8602 emit_move_insn (move[i].dst, move[i].src);
8604 /* Remove conflict from list. */
8605 move[i].src = NULL_RTX;
8607 else
8608 blocked = i;
8611 /* Check for deadlock. This is when no moves occurred and we have
8612 at least one blocked move. */
8613 if (moves == 0 && blocked != -1)
8615 /* Need to use scratch register to break deadlock.
8616 Add move to put dst of blocked move into scratch.
8617 When this move occurs, it will break chain deadlock.
8618 The scratch register is substituted for real move. */
8620 gcc_assert (SCRATCH != GET_CODE (scratch));
8622 move[size].src = move[blocked].dst;
8623 move[size].dst = scratch;
8624 /* Scratch move is never blocked. */
8625 move[size].links = -1;
8626 /* Make sure we have valid link. */
8627 gcc_assert (move[blocked].links != -1);
8628 /* Replace src of blocking move with scratch reg. */
8629 move[move[blocked].links].src = scratch;
8630 /* Make dependent on scratch move occurring. */
8631 move[blocked].links = size;
8632 size=size+1;
8635 while (blocked != -1);
8637 return true;
8641 /* Worker function for `ADJUST_INSN_LENGTH'. */
8642 /* Modifies the length assigned to instruction INSN
8643 LEN is the initially computed length of the insn. */
8646 avr_adjust_insn_length (rtx_insn *insn, int len)
8648 rtx *op = recog_data.operand;
8649 enum attr_adjust_len adjust_len;
8651 /* Some complex insns don't need length adjustment and therefore
8652 the length need not/must not be adjusted for these insns.
8653 It is easier to state this in an insn attribute "adjust_len" than
8654 to clutter up code here... */
8656 if (!NONDEBUG_INSN_P (insn)
8657 || -1 == recog_memoized (insn))
8659 return len;
8662 /* Read from insn attribute "adjust_len" if/how length is to be adjusted. */
8664 adjust_len = get_attr_adjust_len (insn);
8666 if (adjust_len == ADJUST_LEN_NO)
8668 /* Nothing to adjust: The length from attribute "length" is fine.
8669 This is the default. */
8671 return len;
8674 /* Extract insn's operands. */
8676 extract_constrain_insn_cached (insn);
8678 /* Dispatch to right function. */
8680 switch (adjust_len)
8682 case ADJUST_LEN_RELOAD_IN16: output_reload_inhi (op, op[2], &len); break;
8683 case ADJUST_LEN_RELOAD_IN24: avr_out_reload_inpsi (op, op[2], &len); break;
8684 case ADJUST_LEN_RELOAD_IN32: output_reload_insisf (op, op[2], &len); break;
8686 case ADJUST_LEN_OUT_BITOP: avr_out_bitop (insn, op, &len); break;
8688 case ADJUST_LEN_PLUS: avr_out_plus (insn, op, &len); break;
8689 case ADJUST_LEN_ADDTO_SP: avr_out_addto_sp (op, &len); break;
8691 case ADJUST_LEN_MOV8: output_movqi (insn, op, &len); break;
8692 case ADJUST_LEN_MOV16: output_movhi (insn, op, &len); break;
8693 case ADJUST_LEN_MOV24: avr_out_movpsi (insn, op, &len); break;
8694 case ADJUST_LEN_MOV32: output_movsisf (insn, op, &len); break;
8695 case ADJUST_LEN_MOVMEM: avr_out_movmem (insn, op, &len); break;
8696 case ADJUST_LEN_XLOAD: avr_out_xload (insn, op, &len); break;
8697 case ADJUST_LEN_LPM: avr_out_lpm (insn, op, &len); break;
8698 case ADJUST_LEN_SEXT: avr_out_sign_extend (insn, op, &len); break;
8700 case ADJUST_LEN_SFRACT: avr_out_fract (insn, op, true, &len); break;
8701 case ADJUST_LEN_UFRACT: avr_out_fract (insn, op, false, &len); break;
8702 case ADJUST_LEN_ROUND: avr_out_round (insn, op, &len); break;
8704 case ADJUST_LEN_TSTHI: avr_out_tsthi (insn, op, &len); break;
8705 case ADJUST_LEN_TSTPSI: avr_out_tstpsi (insn, op, &len); break;
8706 case ADJUST_LEN_TSTSI: avr_out_tstsi (insn, op, &len); break;
8707 case ADJUST_LEN_COMPARE: avr_out_compare (insn, op, &len); break;
8708 case ADJUST_LEN_COMPARE64: avr_out_compare64 (insn, op, &len); break;
8710 case ADJUST_LEN_LSHRQI: lshrqi3_out (insn, op, &len); break;
8711 case ADJUST_LEN_LSHRHI: lshrhi3_out (insn, op, &len); break;
8712 case ADJUST_LEN_LSHRSI: lshrsi3_out (insn, op, &len); break;
8714 case ADJUST_LEN_ASHRQI: ashrqi3_out (insn, op, &len); break;
8715 case ADJUST_LEN_ASHRHI: ashrhi3_out (insn, op, &len); break;
8716 case ADJUST_LEN_ASHRSI: ashrsi3_out (insn, op, &len); break;
8718 case ADJUST_LEN_ASHLQI: ashlqi3_out (insn, op, &len); break;
8719 case ADJUST_LEN_ASHLHI: ashlhi3_out (insn, op, &len); break;
8720 case ADJUST_LEN_ASHLSI: ashlsi3_out (insn, op, &len); break;
8722 case ADJUST_LEN_ASHLPSI: avr_out_ashlpsi3 (insn, op, &len); break;
8723 case ADJUST_LEN_ASHRPSI: avr_out_ashrpsi3 (insn, op, &len); break;
8724 case ADJUST_LEN_LSHRPSI: avr_out_lshrpsi3 (insn, op, &len); break;
8726 case ADJUST_LEN_CALL: len = AVR_HAVE_JMP_CALL ? 2 : 1; break;
8728 case ADJUST_LEN_INSERT_BITS: avr_out_insert_bits (op, &len); break;
8730 default:
8731 gcc_unreachable();
8734 return len;
8737 /* Return nonzero if register REG dead after INSN. */
8740 reg_unused_after (rtx_insn *insn, rtx reg)
8742 return (dead_or_set_p (insn, reg)
8743 || (REG_P(reg) && _reg_unused_after (insn, reg)));
8746 /* Return nonzero if REG is not used after INSN.
8747 We assume REG is a reload reg, and therefore does
8748 not live past labels. It may live past calls or jumps though. */
8751 _reg_unused_after (rtx_insn *insn, rtx reg)
8753 enum rtx_code code;
8754 rtx set;
8756 /* If the reg is set by this instruction, then it is safe for our
8757 case. Disregard the case where this is a store to memory, since
8758 we are checking a register used in the store address. */
8759 set = single_set (insn);
8760 if (set && GET_CODE (SET_DEST (set)) != MEM
8761 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
8762 return 1;
8764 while ((insn = NEXT_INSN (insn)))
8766 rtx set;
8767 code = GET_CODE (insn);
8769 #if 0
8770 /* If this is a label that existed before reload, then the register
8771 if dead here. However, if this is a label added by reorg, then
8772 the register may still be live here. We can't tell the difference,
8773 so we just ignore labels completely. */
8774 if (code == CODE_LABEL)
8775 return 1;
8776 /* else */
8777 #endif
8779 if (!INSN_P (insn))
8780 continue;
8782 if (code == JUMP_INSN)
8783 return 0;
8785 /* If this is a sequence, we must handle them all at once.
8786 We could have for instance a call that sets the target register,
8787 and an insn in a delay slot that uses the register. In this case,
8788 we must return 0. */
8789 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
8791 rtx_sequence *seq = as_a <rtx_sequence *> (PATTERN (insn));
8792 int i;
8793 int retval = 0;
8795 for (i = 0; i < seq->len (); i++)
8797 rtx_insn *this_insn = seq->insn (i);
8798 rtx set = single_set (this_insn);
8800 if (CALL_P (this_insn))
8801 code = CALL_INSN;
8802 else if (JUMP_P (this_insn))
8804 if (INSN_ANNULLED_BRANCH_P (this_insn))
8805 return 0;
8806 code = JUMP_INSN;
8809 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
8810 return 0;
8811 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
8813 if (GET_CODE (SET_DEST (set)) != MEM)
8814 retval = 1;
8815 else
8816 return 0;
8818 if (set == 0
8819 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
8820 return 0;
8822 if (retval == 1)
8823 return 1;
8824 else if (code == JUMP_INSN)
8825 return 0;
8828 if (code == CALL_INSN)
8830 rtx tem;
8831 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
8832 if (GET_CODE (XEXP (tem, 0)) == USE
8833 && REG_P (XEXP (XEXP (tem, 0), 0))
8834 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
8835 return 0;
8836 if (call_used_regs[REGNO (reg)])
8837 return 1;
8840 set = single_set (insn);
8842 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
8843 return 0;
8844 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
8845 return GET_CODE (SET_DEST (set)) != MEM;
8846 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
8847 return 0;
8849 return 1;
8853 /* Implement `TARGET_ASM_INTEGER'. */
8854 /* Target hook for assembling integer objects. The AVR version needs
8855 special handling for references to certain labels. */
8857 static bool
8858 avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
8860 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
8861 && text_segment_operand (x, VOIDmode))
8863 fputs ("\t.word\tgs(", asm_out_file);
8864 output_addr_const (asm_out_file, x);
8865 fputs (")\n", asm_out_file);
8867 return true;
8869 else if (GET_MODE (x) == PSImode)
8871 /* This needs binutils 2.23+, see PR binutils/13503 */
8873 fputs ("\t.byte\tlo8(", asm_out_file);
8874 output_addr_const (asm_out_file, x);
8875 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
8877 fputs ("\t.byte\thi8(", asm_out_file);
8878 output_addr_const (asm_out_file, x);
8879 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
8881 fputs ("\t.byte\thh8(", asm_out_file);
8882 output_addr_const (asm_out_file, x);
8883 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
8885 return true;
8887 else if (CONST_FIXED_P (x))
8889 unsigned n;
8891 /* varasm fails to handle big fixed modes that don't fit in hwi. */
8893 for (n = 0; n < size; n++)
8895 rtx xn = simplify_gen_subreg (QImode, x, GET_MODE (x), n);
8896 default_assemble_integer (xn, 1, aligned_p);
8899 return true;
8902 return default_assemble_integer (x, size, aligned_p);
8906 /* Implement `TARGET_CLASS_LIKELY_SPILLED_P'. */
8907 /* Return value is nonzero if pseudos that have been
8908 assigned to registers of class CLASS would likely be spilled
8909 because registers of CLASS are needed for spill registers. */
8911 static bool
8912 avr_class_likely_spilled_p (reg_class_t c)
8914 return (c != ALL_REGS &&
8915 (AVR_TINY ? 1 : c != ADDW_REGS));
8919 /* Valid attributes:
8920 progmem - Put data to program memory.
8921 signal - Make a function to be hardware interrupt.
8922 After function prologue interrupts remain disabled.
8923 interrupt - Make a function to be hardware interrupt. Before function
8924 prologue interrupts are enabled by means of SEI.
8925 naked - Don't generate function prologue/epilogue and RET
8926 instruction. */
8928 /* Handle a "progmem" attribute; arguments as in
8929 struct attribute_spec.handler. */
8931 static tree
8932 avr_handle_progmem_attribute (tree *node, tree name,
8933 tree args ATTRIBUTE_UNUSED,
8934 int flags ATTRIBUTE_UNUSED,
8935 bool *no_add_attrs)
8937 if (DECL_P (*node))
8939 if (TREE_CODE (*node) == TYPE_DECL)
8941 /* This is really a decl attribute, not a type attribute,
8942 but try to handle it for GCC 3.0 backwards compatibility. */
8944 tree type = TREE_TYPE (*node);
8945 tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
8946 tree newtype = build_type_attribute_variant (type, attr);
8948 TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
8949 TREE_TYPE (*node) = newtype;
8950 *no_add_attrs = true;
8952 else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
8954 *no_add_attrs = false;
8956 else
8958 warning (OPT_Wattributes, "%qE attribute ignored",
8959 name);
8960 *no_add_attrs = true;
8964 return NULL_TREE;
8967 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
8968 struct attribute_spec.handler. */
8970 static tree
8971 avr_handle_fndecl_attribute (tree *node, tree name,
8972 tree args ATTRIBUTE_UNUSED,
8973 int flags ATTRIBUTE_UNUSED,
8974 bool *no_add_attrs)
8976 if (TREE_CODE (*node) != FUNCTION_DECL)
8978 warning (OPT_Wattributes, "%qE attribute only applies to functions",
8979 name);
8980 *no_add_attrs = true;
8983 return NULL_TREE;
8986 static tree
8987 avr_handle_fntype_attribute (tree *node, tree name,
8988 tree args ATTRIBUTE_UNUSED,
8989 int flags ATTRIBUTE_UNUSED,
8990 bool *no_add_attrs)
8992 if (TREE_CODE (*node) != FUNCTION_TYPE)
8994 warning (OPT_Wattributes, "%qE attribute only applies to functions",
8995 name);
8996 *no_add_attrs = true;
8999 return NULL_TREE;
9002 static tree
9003 avr_handle_addr_attribute (tree *node, tree name, tree args,
9004 int flags ATTRIBUTE_UNUSED, bool *no_add)
9006 bool io_p = (strncmp (IDENTIFIER_POINTER (name), "io", 2) == 0);
9007 location_t loc = DECL_SOURCE_LOCATION (*node);
9009 if (TREE_CODE (*node) != VAR_DECL)
9011 warning_at (loc, 0, "%qE attribute only applies to variables", name);
9012 *no_add = true;
9015 if (args != NULL_TREE)
9017 if (TREE_CODE (TREE_VALUE (args)) == NON_LVALUE_EXPR)
9018 TREE_VALUE (args) = TREE_OPERAND (TREE_VALUE (args), 0);
9019 tree arg = TREE_VALUE (args);
9020 if (TREE_CODE (arg) != INTEGER_CST)
9022 warning (0, "%qE attribute allows only an integer constant argument",
9023 name);
9024 *no_add = true;
9026 else if (io_p
9027 && (!tree_fits_shwi_p (arg)
9028 || !(strcmp (IDENTIFIER_POINTER (name), "io_low") == 0
9029 ? low_io_address_operand : io_address_operand)
9030 (GEN_INT (TREE_INT_CST_LOW (arg)), QImode)))
9032 warning_at (loc, 0, "%qE attribute address out of range", name);
9033 *no_add = true;
9035 else
9037 tree attribs = DECL_ATTRIBUTES (*node);
9038 const char *names[] = { "io", "io_low", "address", NULL } ;
9039 for (const char **p = names; *p; p++)
9041 tree other = lookup_attribute (*p, attribs);
9042 if (other && TREE_VALUE (other))
9044 warning_at (loc, 0,
9045 "both %s and %qE attribute provide address",
9046 *p, name);
9047 *no_add = true;
9048 break;
9054 if (*no_add == false && io_p && !TREE_THIS_VOLATILE (*node))
9055 warning_at (loc, 0, "%qE attribute on non-volatile variable", name);
9057 return NULL_TREE;
9061 avr_eval_addr_attrib (rtx x)
9063 if (GET_CODE (x) == SYMBOL_REF
9064 && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_ADDRESS))
9066 tree decl = SYMBOL_REF_DECL (x);
9067 tree attr = NULL_TREE;
9069 if (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO)
9071 attr = lookup_attribute ("io", DECL_ATTRIBUTES (decl));
9072 if (!attr || !TREE_VALUE (attr))
9073 attr = lookup_attribute ("io_low", DECL_ATTRIBUTES (decl));
9074 gcc_assert (attr);
9076 if (!attr || !TREE_VALUE (attr))
9077 attr = lookup_attribute ("address", DECL_ATTRIBUTES (decl));
9078 gcc_assert (attr && TREE_VALUE (attr) && TREE_VALUE (TREE_VALUE (attr)));
9079 return GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))));
9081 return x;
9085 /* AVR attributes. */
9086 static const struct attribute_spec
9087 avr_attribute_table[] =
9089 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
9090 affects_type_identity } */
9091 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute,
9092 false },
9093 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute,
9094 false },
9095 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute,
9096 false },
9097 { "naked", 0, 0, false, true, true, avr_handle_fntype_attribute,
9098 false },
9099 { "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute,
9100 false },
9101 { "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute,
9102 false },
9103 { "io", 0, 1, false, false, false, avr_handle_addr_attribute,
9104 false },
9105 { "io_low", 0, 1, false, false, false, avr_handle_addr_attribute,
9106 false },
9107 { "address", 1, 1, false, false, false, avr_handle_addr_attribute,
9108 false },
9109 { NULL, 0, 0, false, false, false, NULL, false }
9113 /* Look if DECL shall be placed in program memory space by
9114 means of attribute `progmem' or some address-space qualifier.
9115 Return non-zero if DECL is data that must end up in Flash and
9116 zero if the data lives in RAM (.bss, .data, .rodata, ...).
9118 Return 2 if DECL is located in 24-bit flash address-space
9119 Return 1 if DECL is located in 16-bit flash address-space
9120 Return -1 if attribute `progmem' occurs in DECL or ATTRIBUTES
9121 Return 0 otherwise */
9124 avr_progmem_p (tree decl, tree attributes)
9126 tree a;
9128 if (TREE_CODE (decl) != VAR_DECL)
9129 return 0;
9131 if (avr_decl_memx_p (decl))
9132 return 2;
9134 if (avr_decl_flash_p (decl))
9135 return 1;
9137 if (NULL_TREE
9138 != lookup_attribute ("progmem", attributes))
9139 return -1;
9141 a = decl;
9144 a = TREE_TYPE(a);
9145 while (TREE_CODE (a) == ARRAY_TYPE);
9147 if (a == error_mark_node)
9148 return 0;
9150 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
9151 return -1;
9153 return 0;
9157 /* Scan type TYP for pointer references to address space ASn.
9158 Return ADDR_SPACE_GENERIC (i.e. 0) if all pointers targeting
9159 the AS are also declared to be CONST.
9160 Otherwise, return the respective address space, i.e. a value != 0. */
9162 static addr_space_t
9163 avr_nonconst_pointer_addrspace (tree typ)
9165 while (ARRAY_TYPE == TREE_CODE (typ))
9166 typ = TREE_TYPE (typ);
9168 if (POINTER_TYPE_P (typ))
9170 addr_space_t as;
9171 tree target = TREE_TYPE (typ);
9173 /* Pointer to function: Test the function's return type. */
9175 if (FUNCTION_TYPE == TREE_CODE (target))
9176 return avr_nonconst_pointer_addrspace (TREE_TYPE (target));
9178 /* "Ordinary" pointers... */
9180 while (TREE_CODE (target) == ARRAY_TYPE)
9181 target = TREE_TYPE (target);
9183 /* Pointers to non-generic address space must be const.
9184 Refuse address spaces outside the device's flash. */
9186 as = TYPE_ADDR_SPACE (target);
9188 if (!ADDR_SPACE_GENERIC_P (as)
9189 && (!TYPE_READONLY (target)
9190 || avr_addrspace[as].segment >= avr_n_flash
9191 /* Also refuse __memx address space if we can't support it. */
9192 || (!AVR_HAVE_LPM && avr_addrspace[as].pointer_size > 2)))
9194 return as;
9197 /* Scan pointer's target type. */
9199 return avr_nonconst_pointer_addrspace (target);
9202 return ADDR_SPACE_GENERIC;
9206 /* Sanity check NODE so that all pointers targeting non-generic address spaces
9207 go along with CONST qualifier. Writing to these address spaces should
9208 be detected and complained about as early as possible. */
9210 static bool
9211 avr_pgm_check_var_decl (tree node)
9213 const char *reason = NULL;
9215 addr_space_t as = ADDR_SPACE_GENERIC;
9217 gcc_assert (as == 0);
9219 if (avr_log.progmem)
9220 avr_edump ("%?: %t\n", node);
9222 switch (TREE_CODE (node))
9224 default:
9225 break;
9227 case VAR_DECL:
9228 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
9229 reason = "variable";
9230 break;
9232 case PARM_DECL:
9233 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
9234 reason = "function parameter";
9235 break;
9237 case FIELD_DECL:
9238 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
9239 reason = "structure field";
9240 break;
9242 case FUNCTION_DECL:
9243 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (TREE_TYPE (node))),
9245 reason = "return type of function";
9246 break;
9248 case POINTER_TYPE:
9249 if (as = avr_nonconst_pointer_addrspace (node), as)
9250 reason = "pointer";
9251 break;
9254 if (reason)
9256 if (avr_addrspace[as].segment >= avr_n_flash)
9258 if (TYPE_P (node))
9259 error ("%qT uses address space %qs beyond flash of %d KiB",
9260 node, avr_addrspace[as].name, 64 * avr_n_flash);
9261 else
9262 error ("%s %q+D uses address space %qs beyond flash of %d KiB",
9263 reason, node, avr_addrspace[as].name, 64 * avr_n_flash);
9265 else
9267 if (TYPE_P (node))
9268 error ("pointer targeting address space %qs must be const in %qT",
9269 avr_addrspace[as].name, node);
9270 else
9271 error ("pointer targeting address space %qs must be const"
9272 " in %s %q+D",
9273 avr_addrspace[as].name, reason, node);
9277 return reason == NULL;
9281 /* Add the section attribute if the variable is in progmem. */
9283 static void
9284 avr_insert_attributes (tree node, tree *attributes)
9286 avr_pgm_check_var_decl (node);
9288 if (TREE_CODE (node) == VAR_DECL
9289 && (TREE_STATIC (node) || DECL_EXTERNAL (node))
9290 && avr_progmem_p (node, *attributes))
9292 addr_space_t as;
9293 tree node0 = node;
9295 /* For C++, we have to peel arrays in order to get correct
9296 determination of readonlyness. */
9299 node0 = TREE_TYPE (node0);
9300 while (TREE_CODE (node0) == ARRAY_TYPE);
9302 if (error_mark_node == node0)
9303 return;
9305 as = TYPE_ADDR_SPACE (TREE_TYPE (node));
9307 if (avr_addrspace[as].segment >= avr_n_flash)
9309 error ("variable %q+D located in address space %qs beyond flash "
9310 "of %d KiB", node, avr_addrspace[as].name, 64 * avr_n_flash);
9312 else if (!AVR_HAVE_LPM && avr_addrspace[as].pointer_size > 2)
9314 error ("variable %q+D located in address space %qs"
9315 " which is not supported for architecture %qs",
9316 node, avr_addrspace[as].name, avr_arch->name);
9319 if (!TYPE_READONLY (node0)
9320 && !TREE_READONLY (node))
9322 const char *reason = "__attribute__((progmem))";
9324 if (!ADDR_SPACE_GENERIC_P (as))
9325 reason = avr_addrspace[as].name;
9327 if (avr_log.progmem)
9328 avr_edump ("\n%?: %t\n%t\n", node, node0);
9330 error ("variable %q+D must be const in order to be put into"
9331 " read-only section by means of %qs", node, reason);
9337 /* Implement `ASM_OUTPUT_ALIGNED_DECL_LOCAL'. */
9338 /* Implement `ASM_OUTPUT_ALIGNED_DECL_COMMON'. */
9339 /* Track need of __do_clear_bss. */
9341 void
9342 avr_asm_output_aligned_decl_common (FILE * stream,
9343 tree decl,
9344 const char *name,
9345 unsigned HOST_WIDE_INT size,
9346 unsigned int align, bool local_p)
9348 rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
9349 rtx symbol;
9351 if (mem != NULL_RTX && MEM_P (mem)
9352 && GET_CODE ((symbol = XEXP (mem, 0))) == SYMBOL_REF
9353 && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
9356 if (!local_p)
9358 fprintf (stream, "\t.globl\t");
9359 assemble_name (stream, name);
9360 fprintf (stream, "\n");
9362 if (SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS)
9364 assemble_name (stream, name);
9365 fprintf (stream, " = %ld\n",
9366 (long) INTVAL (avr_eval_addr_attrib (symbol)));
9368 else if (local_p)
9369 error_at (DECL_SOURCE_LOCATION (decl),
9370 "static IO declaration for %q+D needs an address", decl);
9371 return;
9374 /* __gnu_lto_v1 etc. are just markers for the linker injected by toplev.c.
9375 There is no need to trigger __do_clear_bss code for them. */
9377 if (!STR_PREFIX_P (name, "__gnu_lto"))
9378 avr_need_clear_bss_p = true;
9380 if (local_p)
9381 ASM_OUTPUT_ALIGNED_LOCAL (stream, name, size, align);
9382 else
9383 ASM_OUTPUT_ALIGNED_COMMON (stream, name, size, align);
9386 void
9387 avr_asm_asm_output_aligned_bss (FILE *file, tree decl, const char *name,
9388 unsigned HOST_WIDE_INT size, int align,
9389 void (*default_func)
9390 (FILE *, tree, const char *,
9391 unsigned HOST_WIDE_INT, int))
9393 rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
9394 rtx symbol;
9396 if (mem != NULL_RTX && MEM_P (mem)
9397 && GET_CODE ((symbol = XEXP (mem, 0))) == SYMBOL_REF
9398 && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
9400 if (!(SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS))
9401 error_at (DECL_SOURCE_LOCATION (decl),
9402 "IO definition for %q+D needs an address", decl);
9403 avr_asm_output_aligned_decl_common (file, decl, name, size, align, false);
9405 else
9406 default_func (file, decl, name, size, align);
9410 /* Unnamed section callback for data_section
9411 to track need of __do_copy_data. */
9413 static void
9414 avr_output_data_section_asm_op (const void *data)
9416 avr_need_copy_data_p = true;
9418 /* Dispatch to default. */
9419 output_section_asm_op (data);
9423 /* Unnamed section callback for bss_section
9424 to track need of __do_clear_bss. */
9426 static void
9427 avr_output_bss_section_asm_op (const void *data)
9429 avr_need_clear_bss_p = true;
9431 /* Dispatch to default. */
9432 output_section_asm_op (data);
9436 /* Unnamed section callback for progmem*.data sections. */
9438 static void
9439 avr_output_progmem_section_asm_op (const void *data)
9441 fprintf (asm_out_file, "\t.section\t%s,\"a\",@progbits\n",
9442 (const char*) data);
9446 /* Implement `TARGET_ASM_INIT_SECTIONS'. */
9448 static void
9449 avr_asm_init_sections (void)
9451 /* Set up a section for jump tables. Alignment is handled by
9452 ASM_OUTPUT_BEFORE_CASE_LABEL. */
9454 if (AVR_HAVE_JMP_CALL)
9456 progmem_swtable_section
9457 = get_unnamed_section (0, output_section_asm_op,
9458 "\t.section\t.progmem.gcc_sw_table"
9459 ",\"a\",@progbits");
9461 else
9463 progmem_swtable_section
9464 = get_unnamed_section (SECTION_CODE, output_section_asm_op,
9465 "\t.section\t.progmem.gcc_sw_table"
9466 ",\"ax\",@progbits");
9469 /* Override section callbacks to keep track of `avr_need_clear_bss_p'
9470 resp. `avr_need_copy_data_p'. */
9472 readonly_data_section->unnamed.callback = avr_output_data_section_asm_op;
9473 data_section->unnamed.callback = avr_output_data_section_asm_op;
9474 bss_section->unnamed.callback = avr_output_bss_section_asm_op;
9478 /* Implement `TARGET_ASM_FUNCTION_RODATA_SECTION'. */
9480 static section*
9481 avr_asm_function_rodata_section (tree decl)
9483 /* If a function is unused and optimized out by -ffunction-sections
9484 and --gc-sections, ensure that the same will happen for its jump
9485 tables by putting them into individual sections. */
9487 unsigned int flags;
9488 section * frodata;
9490 /* Get the frodata section from the default function in varasm.c
9491 but treat function-associated data-like jump tables as code
9492 rather than as user defined data. AVR has no constant pools. */
9494 int fdata = flag_data_sections;
9496 flag_data_sections = flag_function_sections;
9497 frodata = default_function_rodata_section (decl);
9498 flag_data_sections = fdata;
9499 flags = frodata->common.flags;
9502 if (frodata != readonly_data_section
9503 && flags & SECTION_NAMED)
9505 /* Adjust section flags and replace section name prefix. */
9507 unsigned int i;
9509 static const char* const prefix[] =
9511 ".rodata", ".progmem.gcc_sw_table",
9512 ".gnu.linkonce.r.", ".gnu.linkonce.t."
9515 for (i = 0; i < sizeof (prefix) / sizeof (*prefix); i += 2)
9517 const char * old_prefix = prefix[i];
9518 const char * new_prefix = prefix[i+1];
9519 const char * name = frodata->named.name;
9521 if (STR_PREFIX_P (name, old_prefix))
9523 const char *rname = ACONCAT ((new_prefix,
9524 name + strlen (old_prefix), NULL));
9525 flags &= ~SECTION_CODE;
9526 flags |= AVR_HAVE_JMP_CALL ? 0 : SECTION_CODE;
9528 return get_section (rname, flags, frodata->named.decl);
9533 return progmem_swtable_section;
9537 /* Implement `TARGET_ASM_NAMED_SECTION'. */
9538 /* Track need of __do_clear_bss, __do_copy_data for named sections. */
9540 static void
9541 avr_asm_named_section (const char *name, unsigned int flags, tree decl)
9543 if (flags & AVR_SECTION_PROGMEM)
9545 addr_space_t as = (flags & AVR_SECTION_PROGMEM) / SECTION_MACH_DEP;
9546 const char *old_prefix = ".rodata";
9547 const char *new_prefix = avr_addrspace[as].section_name;
9549 if (STR_PREFIX_P (name, old_prefix))
9551 const char *sname = ACONCAT ((new_prefix,
9552 name + strlen (old_prefix), NULL));
9553 default_elf_asm_named_section (sname, flags, decl);
9554 return;
9557 default_elf_asm_named_section (new_prefix, flags, decl);
9558 return;
9561 if (!avr_need_copy_data_p)
9562 avr_need_copy_data_p = (STR_PREFIX_P (name, ".data")
9563 || STR_PREFIX_P (name, ".rodata")
9564 || STR_PREFIX_P (name, ".gnu.linkonce.d"));
9566 if (!avr_need_clear_bss_p)
9567 avr_need_clear_bss_p = STR_PREFIX_P (name, ".bss");
9569 default_elf_asm_named_section (name, flags, decl);
9573 /* Implement `TARGET_SECTION_TYPE_FLAGS'. */
9575 static unsigned int
9576 avr_section_type_flags (tree decl, const char *name, int reloc)
9578 unsigned int flags = default_section_type_flags (decl, name, reloc);
9580 if (STR_PREFIX_P (name, ".noinit"))
9582 if (decl && TREE_CODE (decl) == VAR_DECL
9583 && DECL_INITIAL (decl) == NULL_TREE)
9584 flags |= SECTION_BSS; /* @nobits */
9585 else
9586 warning (0, "only uninitialized variables can be placed in the "
9587 ".noinit section");
9590 if (decl && DECL_P (decl)
9591 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
9593 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
9595 /* Attribute progmem puts data in generic address space.
9596 Set section flags as if it was in __flash to get the right
9597 section prefix in the remainder. */
9599 if (ADDR_SPACE_GENERIC_P (as))
9600 as = ADDR_SPACE_FLASH;
9602 flags |= as * SECTION_MACH_DEP;
9603 flags &= ~SECTION_WRITE;
9604 flags &= ~SECTION_BSS;
9607 return flags;
9611 /* Implement `TARGET_ENCODE_SECTION_INFO'. */
9613 static void
9614 avr_encode_section_info (tree decl, rtx rtl, int new_decl_p)
9616 /* In avr_handle_progmem_attribute, DECL_INITIAL is not yet
9617 readily available, see PR34734. So we postpone the warning
9618 about uninitialized data in program memory section until here. */
9620 if (new_decl_p
9621 && decl && DECL_P (decl)
9622 && NULL_TREE == DECL_INITIAL (decl)
9623 && !DECL_EXTERNAL (decl)
9624 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
9626 warning (OPT_Wuninitialized,
9627 "uninitialized variable %q+D put into "
9628 "program memory area", decl);
9631 default_encode_section_info (decl, rtl, new_decl_p);
9633 if (decl && DECL_P (decl)
9634 && TREE_CODE (decl) != FUNCTION_DECL
9635 && MEM_P (rtl)
9636 && SYMBOL_REF == GET_CODE (XEXP (rtl, 0)))
9638 rtx sym = XEXP (rtl, 0);
9639 tree type = TREE_TYPE (decl);
9640 tree attr = DECL_ATTRIBUTES (decl);
9641 if (type == error_mark_node)
9642 return;
9644 addr_space_t as = TYPE_ADDR_SPACE (type);
9646 /* PSTR strings are in generic space but located in flash:
9647 patch address space. */
9649 if (-1 == avr_progmem_p (decl, attr))
9650 as = ADDR_SPACE_FLASH;
9652 AVR_SYMBOL_SET_ADDR_SPACE (sym, as);
9654 tree io_low_attr = lookup_attribute ("io_low", attr);
9655 tree io_attr = lookup_attribute ("io", attr);
9656 tree addr_attr;
9657 if (io_low_attr
9658 && TREE_VALUE (io_low_attr) && TREE_VALUE (TREE_VALUE (io_low_attr)))
9659 addr_attr = io_attr;
9660 else if (io_attr
9661 && TREE_VALUE (io_attr) && TREE_VALUE (TREE_VALUE (io_attr)))
9662 addr_attr = io_attr;
9663 else
9664 addr_attr = lookup_attribute ("address", attr);
9665 if (io_low_attr
9666 || (io_attr && addr_attr
9667 && low_io_address_operand
9668 (GEN_INT (TREE_INT_CST_LOW
9669 (TREE_VALUE (TREE_VALUE (addr_attr)))), QImode)))
9670 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO_LOW;
9671 if (io_attr || io_low_attr)
9672 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO;
9673 /* If we have an (io) address attribute specification, but the variable
9674 is external, treat the address as only a tentative definition
9675 to be used to determine if an io port is in the lower range, but
9676 don't use the exact value for constant propagation. */
9677 if (addr_attr && !DECL_EXTERNAL (decl))
9678 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_ADDRESS;
9683 /* Implement `TARGET_ASM_SELECT_SECTION' */
9685 static section *
9686 avr_asm_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
9688 section * sect = default_elf_select_section (decl, reloc, align);
9690 if (decl && DECL_P (decl)
9691 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
9693 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
9695 /* __progmem__ goes in generic space but shall be allocated to
9696 .progmem.data */
9698 if (ADDR_SPACE_GENERIC_P (as))
9699 as = ADDR_SPACE_FLASH;
9701 if (sect->common.flags & SECTION_NAMED)
9703 const char * name = sect->named.name;
9704 const char * old_prefix = ".rodata";
9705 const char * new_prefix = avr_addrspace[as].section_name;
9707 if (STR_PREFIX_P (name, old_prefix))
9709 const char *sname = ACONCAT ((new_prefix,
9710 name + strlen (old_prefix), NULL));
9711 return get_section (sname, sect->common.flags, sect->named.decl);
9715 if (!progmem_section[as])
9717 progmem_section[as]
9718 = get_unnamed_section (0, avr_output_progmem_section_asm_op,
9719 avr_addrspace[as].section_name);
9722 return progmem_section[as];
9725 return sect;
9728 /* Implement `TARGET_ASM_FILE_START'. */
9729 /* Outputs some text at the start of each assembler file. */
9731 static void
9732 avr_file_start (void)
9734 int sfr_offset = avr_arch->sfr_offset;
9736 if (avr_arch->asm_only)
9737 error ("architecture %qs supported for assembler only", avr_mmcu);
9739 default_file_start ();
9741 /* Print I/O addresses of some SFRs used with IN and OUT. */
9743 if (AVR_HAVE_SPH)
9744 fprintf (asm_out_file, "__SP_H__ = 0x%02x\n", avr_addr.sp_h - sfr_offset);
9746 fprintf (asm_out_file, "__SP_L__ = 0x%02x\n", avr_addr.sp_l - sfr_offset);
9747 fprintf (asm_out_file, "__SREG__ = 0x%02x\n", avr_addr.sreg - sfr_offset);
9748 if (AVR_HAVE_RAMPZ)
9749 fprintf (asm_out_file, "__RAMPZ__ = 0x%02x\n", avr_addr.rampz - sfr_offset);
9750 if (AVR_HAVE_RAMPY)
9751 fprintf (asm_out_file, "__RAMPY__ = 0x%02x\n", avr_addr.rampy - sfr_offset);
9752 if (AVR_HAVE_RAMPX)
9753 fprintf (asm_out_file, "__RAMPX__ = 0x%02x\n", avr_addr.rampx - sfr_offset);
9754 if (AVR_HAVE_RAMPD)
9755 fprintf (asm_out_file, "__RAMPD__ = 0x%02x\n", avr_addr.rampd - sfr_offset);
9756 if (AVR_XMEGA || AVR_TINY)
9757 fprintf (asm_out_file, "__CCP__ = 0x%02x\n", avr_addr.ccp - sfr_offset);
9758 fprintf (asm_out_file, "__tmp_reg__ = %d\n", AVR_TMP_REGNO);
9759 fprintf (asm_out_file, "__zero_reg__ = %d\n", AVR_ZERO_REGNO);
9763 /* Implement `TARGET_ASM_FILE_END'. */
9764 /* Outputs to the stdio stream FILE some
9765 appropriate text to go at the end of an assembler file. */
9767 static void
9768 avr_file_end (void)
9770 /* Output these only if there is anything in the
9771 .data* / .rodata* / .gnu.linkonce.* resp. .bss* or COMMON
9772 input section(s) - some code size can be saved by not
9773 linking in the initialization code from libgcc if resp.
9774 sections are empty, see PR18145. */
9776 if (avr_need_copy_data_p)
9777 fputs (".global __do_copy_data\n", asm_out_file);
9779 if (avr_need_clear_bss_p)
9780 fputs (".global __do_clear_bss\n", asm_out_file);
9784 /* Worker function for `ADJUST_REG_ALLOC_ORDER'. */
9785 /* Choose the order in which to allocate hard registers for
9786 pseudo-registers local to a basic block.
9788 Store the desired register order in the array `reg_alloc_order'.
9789 Element 0 should be the register to allocate first; element 1, the
9790 next register; and so on. */
9792 void
9793 avr_adjust_reg_alloc_order (void)
9795 unsigned int i;
9796 static const int order_0[] =
9798 24, 25,
9799 18, 19, 20, 21, 22, 23,
9800 30, 31,
9801 26, 27, 28, 29,
9802 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
9803 0, 1,
9804 32, 33, 34, 35
9806 static const int tiny_order_0[] = {
9807 20, 21,
9808 22, 23,
9809 24, 25,
9810 30, 31,
9811 26, 27,
9812 28, 29,
9813 19, 18,
9814 16, 17,
9815 32, 33, 34, 35,
9816 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
9818 static const int order_1[] =
9820 18, 19, 20, 21, 22, 23, 24, 25,
9821 30, 31,
9822 26, 27, 28, 29,
9823 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
9824 0, 1,
9825 32, 33, 34, 35
9827 static const int tiny_order_1[] = {
9828 22, 23,
9829 24, 25,
9830 30, 31,
9831 26, 27,
9832 28, 29,
9833 21, 20, 19, 18,
9834 16, 17,
9835 32, 33, 34, 35,
9836 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
9838 static const int order_2[] =
9840 25, 24, 23, 22, 21, 20, 19, 18,
9841 30, 31,
9842 26, 27, 28, 29,
9843 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
9844 1, 0,
9845 32, 33, 34, 35
9848 /* Select specific register allocation order.
9849 Tiny Core (ATtiny4/5/9/10/20/40) devices have only 16 registers,
9850 so different allocation order should be used. */
9852 const int *order = (TARGET_ORDER_1 ? (AVR_TINY ? tiny_order_1 : order_1)
9853 : TARGET_ORDER_2 ? (AVR_TINY ? tiny_order_0 : order_2)
9854 : (AVR_TINY ? tiny_order_0 : order_0));
9856 for (i = 0; i < ARRAY_SIZE (order_0); ++i)
9857 reg_alloc_order[i] = order[i];
9861 /* Implement `TARGET_REGISTER_MOVE_COST' */
9863 static int
9864 avr_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
9865 reg_class_t from, reg_class_t to)
9867 return (from == STACK_REG ? 6
9868 : to == STACK_REG ? 12
9869 : 2);
9873 /* Implement `TARGET_MEMORY_MOVE_COST' */
9875 static int
9876 avr_memory_move_cost (machine_mode mode,
9877 reg_class_t rclass ATTRIBUTE_UNUSED,
9878 bool in ATTRIBUTE_UNUSED)
9880 return (mode == QImode ? 2
9881 : mode == HImode ? 4
9882 : mode == SImode ? 8
9883 : mode == SFmode ? 8
9884 : 16);
9888 /* Mutually recursive subroutine of avr_rtx_cost for calculating the
9889 cost of an RTX operand given its context. X is the rtx of the
9890 operand, MODE is its mode, and OUTER is the rtx_code of this
9891 operand's parent operator. */
9893 static int
9894 avr_operand_rtx_cost (rtx x, machine_mode mode, enum rtx_code outer,
9895 int opno, bool speed)
9897 enum rtx_code code = GET_CODE (x);
9898 int total;
9900 switch (code)
9902 case REG:
9903 case SUBREG:
9904 return 0;
9906 case CONST_INT:
9907 case CONST_FIXED:
9908 case CONST_DOUBLE:
9909 return COSTS_N_INSNS (GET_MODE_SIZE (mode));
9911 default:
9912 break;
9915 total = 0;
9916 avr_rtx_costs (x, mode, outer, opno, &total, speed);
9917 return total;
9920 /* Worker function for AVR backend's rtx_cost function.
9921 X is rtx expression whose cost is to be calculated.
9922 Return true if the complete cost has been computed.
9923 Return false if subexpressions should be scanned.
9924 In either case, *TOTAL contains the cost result. */
9926 static bool
9927 avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED,
9928 int opno ATTRIBUTE_UNUSED, int *total, bool speed)
9930 enum rtx_code code = GET_CODE (x);
9931 HOST_WIDE_INT val;
9933 switch (code)
9935 case CONST_INT:
9936 case CONST_FIXED:
9937 case CONST_DOUBLE:
9938 case SYMBOL_REF:
9939 case CONST:
9940 case LABEL_REF:
9941 /* Immediate constants are as cheap as registers. */
9942 *total = 0;
9943 return true;
9945 case MEM:
9946 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
9947 return true;
9949 case NEG:
9950 switch (mode)
9952 case QImode:
9953 case SFmode:
9954 *total = COSTS_N_INSNS (1);
9955 break;
9957 case HImode:
9958 case PSImode:
9959 case SImode:
9960 *total = COSTS_N_INSNS (2 * GET_MODE_SIZE (mode) - 1);
9961 break;
9963 default:
9964 return false;
9966 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
9967 return true;
9969 case ABS:
9970 switch (mode)
9972 case QImode:
9973 case SFmode:
9974 *total = COSTS_N_INSNS (1);
9975 break;
9977 default:
9978 return false;
9980 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
9981 return true;
9983 case NOT:
9984 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
9985 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
9986 return true;
9988 case ZERO_EXTEND:
9989 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
9990 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
9991 *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
9992 code, 0, speed);
9993 return true;
9995 case SIGN_EXTEND:
9996 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
9997 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
9998 *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
9999 code, 0, speed);
10000 return true;
10002 case PLUS:
10003 switch (mode)
10005 case QImode:
10006 if (AVR_HAVE_MUL
10007 && MULT == GET_CODE (XEXP (x, 0))
10008 && register_operand (XEXP (x, 1), QImode))
10010 /* multiply-add */
10011 *total = COSTS_N_INSNS (speed ? 4 : 3);
10012 /* multiply-add with constant: will be split and load constant. */
10013 if (CONST_INT_P (XEXP (XEXP (x, 0), 1)))
10014 *total = COSTS_N_INSNS (1) + *total;
10015 return true;
10017 *total = COSTS_N_INSNS (1);
10018 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10019 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10020 break;
10022 case HImode:
10023 if (AVR_HAVE_MUL
10024 && (MULT == GET_CODE (XEXP (x, 0))
10025 || ASHIFT == GET_CODE (XEXP (x, 0)))
10026 && register_operand (XEXP (x, 1), HImode)
10027 && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))
10028 || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))))
10030 /* multiply-add */
10031 *total = COSTS_N_INSNS (speed ? 5 : 4);
10032 /* multiply-add with constant: will be split and load constant. */
10033 if (CONST_INT_P (XEXP (XEXP (x, 0), 1)))
10034 *total = COSTS_N_INSNS (1) + *total;
10035 return true;
10037 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10039 *total = COSTS_N_INSNS (2);
10040 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10041 speed);
10043 else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
10044 *total = COSTS_N_INSNS (1);
10045 else
10046 *total = COSTS_N_INSNS (2);
10047 break;
10049 case PSImode:
10050 if (!CONST_INT_P (XEXP (x, 1)))
10052 *total = COSTS_N_INSNS (3);
10053 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10054 speed);
10056 else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
10057 *total = COSTS_N_INSNS (2);
10058 else
10059 *total = COSTS_N_INSNS (3);
10060 break;
10062 case SImode:
10063 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10065 *total = COSTS_N_INSNS (4);
10066 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10067 speed);
10069 else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
10070 *total = COSTS_N_INSNS (1);
10071 else
10072 *total = COSTS_N_INSNS (4);
10073 break;
10075 default:
10076 return false;
10078 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10079 return true;
10081 case MINUS:
10082 if (AVR_HAVE_MUL
10083 && QImode == mode
10084 && register_operand (XEXP (x, 0), QImode)
10085 && MULT == GET_CODE (XEXP (x, 1)))
10087 /* multiply-sub */
10088 *total = COSTS_N_INSNS (speed ? 4 : 3);
10089 /* multiply-sub with constant: will be split and load constant. */
10090 if (CONST_INT_P (XEXP (XEXP (x, 1), 1)))
10091 *total = COSTS_N_INSNS (1) + *total;
10092 return true;
10094 if (AVR_HAVE_MUL
10095 && HImode == mode
10096 && register_operand (XEXP (x, 0), HImode)
10097 && (MULT == GET_CODE (XEXP (x, 1))
10098 || ASHIFT == GET_CODE (XEXP (x, 1)))
10099 && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))
10100 || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))))
10102 /* multiply-sub */
10103 *total = COSTS_N_INSNS (speed ? 5 : 4);
10104 /* multiply-sub with constant: will be split and load constant. */
10105 if (CONST_INT_P (XEXP (XEXP (x, 1), 1)))
10106 *total = COSTS_N_INSNS (1) + *total;
10107 return true;
10109 /* FALLTHRU */
10110 case AND:
10111 case IOR:
10112 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10113 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10114 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10115 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10116 return true;
10118 case XOR:
10119 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10120 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10121 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10122 return true;
10124 case MULT:
10125 switch (mode)
10127 case QImode:
10128 if (AVR_HAVE_MUL)
10129 *total = COSTS_N_INSNS (!speed ? 3 : 4);
10130 else if (!speed)
10131 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
10132 else
10133 return false;
10134 break;
10136 case HImode:
10137 if (AVR_HAVE_MUL)
10139 rtx op0 = XEXP (x, 0);
10140 rtx op1 = XEXP (x, 1);
10141 enum rtx_code code0 = GET_CODE (op0);
10142 enum rtx_code code1 = GET_CODE (op1);
10143 bool ex0 = SIGN_EXTEND == code0 || ZERO_EXTEND == code0;
10144 bool ex1 = SIGN_EXTEND == code1 || ZERO_EXTEND == code1;
10146 if (ex0
10147 && (u8_operand (op1, HImode)
10148 || s8_operand (op1, HImode)))
10150 *total = COSTS_N_INSNS (!speed ? 4 : 6);
10151 return true;
10153 if (ex0
10154 && register_operand (op1, HImode))
10156 *total = COSTS_N_INSNS (!speed ? 5 : 8);
10157 return true;
10159 else if (ex0 || ex1)
10161 *total = COSTS_N_INSNS (!speed ? 3 : 5);
10162 return true;
10164 else if (register_operand (op0, HImode)
10165 && (u8_operand (op1, HImode)
10166 || s8_operand (op1, HImode)))
10168 *total = COSTS_N_INSNS (!speed ? 6 : 9);
10169 return true;
10171 else
10172 *total = COSTS_N_INSNS (!speed ? 7 : 10);
10174 else if (!speed)
10175 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
10176 else
10177 return false;
10178 break;
10180 case PSImode:
10181 if (!speed)
10182 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
10183 else
10184 *total = 10;
10185 break;
10187 case SImode:
10188 if (AVR_HAVE_MUL)
10190 if (!speed)
10192 /* Add some additional costs besides CALL like moves etc. */
10194 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
10196 else
10198 /* Just a rough estimate. Even with -O2 we don't want bulky
10199 code expanded inline. */
10201 *total = COSTS_N_INSNS (25);
10204 else
10206 if (speed)
10207 *total = COSTS_N_INSNS (300);
10208 else
10209 /* Add some additional costs besides CALL like moves etc. */
10210 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
10213 return true;
10215 default:
10216 return false;
10218 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10219 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10220 return true;
10222 case DIV:
10223 case MOD:
10224 case UDIV:
10225 case UMOD:
10226 if (!speed)
10227 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
10228 else
10229 *total = COSTS_N_INSNS (15 * GET_MODE_SIZE (mode));
10230 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10231 /* For div/mod with const-int divisor we have at least the cost of
10232 loading the divisor. */
10233 if (CONST_INT_P (XEXP (x, 1)))
10234 *total += COSTS_N_INSNS (GET_MODE_SIZE (mode));
10235 /* Add some overall penaly for clobbering and moving around registers */
10236 *total += COSTS_N_INSNS (2);
10237 return true;
10239 case ROTATE:
10240 switch (mode)
10242 case QImode:
10243 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 4)
10244 *total = COSTS_N_INSNS (1);
10246 break;
10248 case HImode:
10249 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 8)
10250 *total = COSTS_N_INSNS (3);
10252 break;
10254 case SImode:
10255 if (CONST_INT_P (XEXP (x, 1)))
10256 switch (INTVAL (XEXP (x, 1)))
10258 case 8:
10259 case 24:
10260 *total = COSTS_N_INSNS (5);
10261 break;
10262 case 16:
10263 *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 6);
10264 break;
10266 break;
10268 default:
10269 return false;
10271 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10272 return true;
10274 case ASHIFT:
10275 switch (mode)
10277 case QImode:
10278 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10280 *total = COSTS_N_INSNS (!speed ? 4 : 17);
10281 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10282 speed);
10284 else
10286 val = INTVAL (XEXP (x, 1));
10287 if (val == 7)
10288 *total = COSTS_N_INSNS (3);
10289 else if (val >= 0 && val <= 7)
10290 *total = COSTS_N_INSNS (val);
10291 else
10292 *total = COSTS_N_INSNS (1);
10294 break;
10296 case HImode:
10297 if (AVR_HAVE_MUL)
10299 if (const_2_to_7_operand (XEXP (x, 1), HImode)
10300 && (SIGN_EXTEND == GET_CODE (XEXP (x, 0))
10301 || ZERO_EXTEND == GET_CODE (XEXP (x, 0))))
10303 *total = COSTS_N_INSNS (!speed ? 4 : 6);
10304 return true;
10308 if (const1_rtx == (XEXP (x, 1))
10309 && SIGN_EXTEND == GET_CODE (XEXP (x, 0)))
10311 *total = COSTS_N_INSNS (2);
10312 return true;
10315 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10317 *total = COSTS_N_INSNS (!speed ? 5 : 41);
10318 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10319 speed);
10321 else
10322 switch (INTVAL (XEXP (x, 1)))
10324 case 0:
10325 *total = 0;
10326 break;
10327 case 1:
10328 case 8:
10329 *total = COSTS_N_INSNS (2);
10330 break;
10331 case 9:
10332 *total = COSTS_N_INSNS (3);
10333 break;
10334 case 2:
10335 case 3:
10336 case 10:
10337 case 15:
10338 *total = COSTS_N_INSNS (4);
10339 break;
10340 case 7:
10341 case 11:
10342 case 12:
10343 *total = COSTS_N_INSNS (5);
10344 break;
10345 case 4:
10346 *total = COSTS_N_INSNS (!speed ? 5 : 8);
10347 break;
10348 case 6:
10349 *total = COSTS_N_INSNS (!speed ? 5 : 9);
10350 break;
10351 case 5:
10352 *total = COSTS_N_INSNS (!speed ? 5 : 10);
10353 break;
10354 default:
10355 *total = COSTS_N_INSNS (!speed ? 5 : 41);
10356 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10357 speed);
10359 break;
10361 case PSImode:
10362 if (!CONST_INT_P (XEXP (x, 1)))
10364 *total = COSTS_N_INSNS (!speed ? 6 : 73);
10366 else
10367 switch (INTVAL (XEXP (x, 1)))
10369 case 0:
10370 *total = 0;
10371 break;
10372 case 1:
10373 case 8:
10374 case 16:
10375 *total = COSTS_N_INSNS (3);
10376 break;
10377 case 23:
10378 *total = COSTS_N_INSNS (5);
10379 break;
10380 default:
10381 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
10382 break;
10384 break;
10386 case SImode:
10387 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10389 *total = COSTS_N_INSNS (!speed ? 7 : 113);
10390 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10391 speed);
10393 else
10394 switch (INTVAL (XEXP (x, 1)))
10396 case 0:
10397 *total = 0;
10398 break;
10399 case 24:
10400 *total = COSTS_N_INSNS (3);
10401 break;
10402 case 1:
10403 case 8:
10404 case 16:
10405 *total = COSTS_N_INSNS (4);
10406 break;
10407 case 31:
10408 *total = COSTS_N_INSNS (6);
10409 break;
10410 case 2:
10411 *total = COSTS_N_INSNS (!speed ? 7 : 8);
10412 break;
10413 default:
10414 *total = COSTS_N_INSNS (!speed ? 7 : 113);
10415 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10416 speed);
10418 break;
10420 default:
10421 return false;
10423 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10424 return true;
10426 case ASHIFTRT:
10427 switch (mode)
10429 case QImode:
10430 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10432 *total = COSTS_N_INSNS (!speed ? 4 : 17);
10433 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10434 speed);
10436 else
10438 val = INTVAL (XEXP (x, 1));
10439 if (val == 6)
10440 *total = COSTS_N_INSNS (4);
10441 else if (val == 7)
10442 *total = COSTS_N_INSNS (2);
10443 else if (val >= 0 && val <= 7)
10444 *total = COSTS_N_INSNS (val);
10445 else
10446 *total = COSTS_N_INSNS (1);
10448 break;
10450 case HImode:
10451 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10453 *total = COSTS_N_INSNS (!speed ? 5 : 41);
10454 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10455 speed);
10457 else
10458 switch (INTVAL (XEXP (x, 1)))
10460 case 0:
10461 *total = 0;
10462 break;
10463 case 1:
10464 *total = COSTS_N_INSNS (2);
10465 break;
10466 case 15:
10467 *total = COSTS_N_INSNS (3);
10468 break;
10469 case 2:
10470 case 7:
10471 case 8:
10472 case 9:
10473 *total = COSTS_N_INSNS (4);
10474 break;
10475 case 10:
10476 case 14:
10477 *total = COSTS_N_INSNS (5);
10478 break;
10479 case 11:
10480 *total = COSTS_N_INSNS (!speed ? 5 : 6);
10481 break;
10482 case 12:
10483 *total = COSTS_N_INSNS (!speed ? 5 : 7);
10484 break;
10485 case 6:
10486 case 13:
10487 *total = COSTS_N_INSNS (!speed ? 5 : 8);
10488 break;
10489 default:
10490 *total = COSTS_N_INSNS (!speed ? 5 : 41);
10491 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10492 speed);
10494 break;
10496 case PSImode:
10497 if (!CONST_INT_P (XEXP (x, 1)))
10499 *total = COSTS_N_INSNS (!speed ? 6 : 73);
10501 else
10502 switch (INTVAL (XEXP (x, 1)))
10504 case 0:
10505 *total = 0;
10506 break;
10507 case 1:
10508 *total = COSTS_N_INSNS (3);
10509 break;
10510 case 16:
10511 case 8:
10512 *total = COSTS_N_INSNS (5);
10513 break;
10514 case 23:
10515 *total = COSTS_N_INSNS (4);
10516 break;
10517 default:
10518 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
10519 break;
10521 break;
10523 case SImode:
10524 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10526 *total = COSTS_N_INSNS (!speed ? 7 : 113);
10527 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10528 speed);
10530 else
10531 switch (INTVAL (XEXP (x, 1)))
10533 case 0:
10534 *total = 0;
10535 break;
10536 case 1:
10537 *total = COSTS_N_INSNS (4);
10538 break;
10539 case 8:
10540 case 16:
10541 case 24:
10542 *total = COSTS_N_INSNS (6);
10543 break;
10544 case 2:
10545 *total = COSTS_N_INSNS (!speed ? 7 : 8);
10546 break;
10547 case 31:
10548 *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 5);
10549 break;
10550 default:
10551 *total = COSTS_N_INSNS (!speed ? 7 : 113);
10552 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10553 speed);
10555 break;
10557 default:
10558 return false;
10560 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10561 return true;
10563 case LSHIFTRT:
10564 switch (mode)
10566 case QImode:
10567 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10569 *total = COSTS_N_INSNS (!speed ? 4 : 17);
10570 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10571 speed);
10573 else
10575 val = INTVAL (XEXP (x, 1));
10576 if (val == 7)
10577 *total = COSTS_N_INSNS (3);
10578 else if (val >= 0 && val <= 7)
10579 *total = COSTS_N_INSNS (val);
10580 else
10581 *total = COSTS_N_INSNS (1);
10583 break;
10585 case HImode:
10586 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10588 *total = COSTS_N_INSNS (!speed ? 5 : 41);
10589 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10590 speed);
10592 else
10593 switch (INTVAL (XEXP (x, 1)))
10595 case 0:
10596 *total = 0;
10597 break;
10598 case 1:
10599 case 8:
10600 *total = COSTS_N_INSNS (2);
10601 break;
10602 case 9:
10603 *total = COSTS_N_INSNS (3);
10604 break;
10605 case 2:
10606 case 10:
10607 case 15:
10608 *total = COSTS_N_INSNS (4);
10609 break;
10610 case 7:
10611 case 11:
10612 *total = COSTS_N_INSNS (5);
10613 break;
10614 case 3:
10615 case 12:
10616 case 13:
10617 case 14:
10618 *total = COSTS_N_INSNS (!speed ? 5 : 6);
10619 break;
10620 case 4:
10621 *total = COSTS_N_INSNS (!speed ? 5 : 7);
10622 break;
10623 case 5:
10624 case 6:
10625 *total = COSTS_N_INSNS (!speed ? 5 : 9);
10626 break;
10627 default:
10628 *total = COSTS_N_INSNS (!speed ? 5 : 41);
10629 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10630 speed);
10632 break;
10634 case PSImode:
10635 if (!CONST_INT_P (XEXP (x, 1)))
10637 *total = COSTS_N_INSNS (!speed ? 6 : 73);
10639 else
10640 switch (INTVAL (XEXP (x, 1)))
10642 case 0:
10643 *total = 0;
10644 break;
10645 case 1:
10646 case 8:
10647 case 16:
10648 *total = COSTS_N_INSNS (3);
10649 break;
10650 case 23:
10651 *total = COSTS_N_INSNS (5);
10652 break;
10653 default:
10654 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
10655 break;
10657 break;
10659 case SImode:
10660 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10662 *total = COSTS_N_INSNS (!speed ? 7 : 113);
10663 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10664 speed);
10666 else
10667 switch (INTVAL (XEXP (x, 1)))
10669 case 0:
10670 *total = 0;
10671 break;
10672 case 1:
10673 *total = COSTS_N_INSNS (4);
10674 break;
10675 case 2:
10676 *total = COSTS_N_INSNS (!speed ? 7 : 8);
10677 break;
10678 case 8:
10679 case 16:
10680 case 24:
10681 *total = COSTS_N_INSNS (4);
10682 break;
10683 case 31:
10684 *total = COSTS_N_INSNS (6);
10685 break;
10686 default:
10687 *total = COSTS_N_INSNS (!speed ? 7 : 113);
10688 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10689 speed);
10691 break;
10693 default:
10694 return false;
10696 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10697 return true;
10699 case COMPARE:
10700 switch (GET_MODE (XEXP (x, 0)))
10702 case QImode:
10703 *total = COSTS_N_INSNS (1);
10704 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10705 *total += avr_operand_rtx_cost (XEXP (x, 1), QImode, code,
10706 1, speed);
10707 break;
10709 case HImode:
10710 *total = COSTS_N_INSNS (2);
10711 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10712 *total += avr_operand_rtx_cost (XEXP (x, 1), HImode, code,
10713 1, speed);
10714 else if (INTVAL (XEXP (x, 1)) != 0)
10715 *total += COSTS_N_INSNS (1);
10716 break;
10718 case PSImode:
10719 *total = COSTS_N_INSNS (3);
10720 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) != 0)
10721 *total += COSTS_N_INSNS (2);
10722 break;
10724 case SImode:
10725 *total = COSTS_N_INSNS (4);
10726 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10727 *total += avr_operand_rtx_cost (XEXP (x, 1), SImode, code,
10728 1, speed);
10729 else if (INTVAL (XEXP (x, 1)) != 0)
10730 *total += COSTS_N_INSNS (3);
10731 break;
10733 default:
10734 return false;
10736 *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
10737 code, 0, speed);
10738 return true;
10740 case TRUNCATE:
10741 if (AVR_HAVE_MUL
10742 && LSHIFTRT == GET_CODE (XEXP (x, 0))
10743 && MULT == GET_CODE (XEXP (XEXP (x, 0), 0))
10744 && CONST_INT_P (XEXP (XEXP (x, 0), 1)))
10746 if (QImode == mode || HImode == mode)
10748 *total = COSTS_N_INSNS (2);
10749 return true;
10752 break;
10754 default:
10755 break;
10757 return false;
10761 /* Implement `TARGET_RTX_COSTS'. */
10763 static bool
10764 avr_rtx_costs (rtx x, machine_mode mode, int outer_code,
10765 int opno, int *total, bool speed)
10767 bool done = avr_rtx_costs_1 (x, mode, outer_code,
10768 opno, total, speed);
10770 if (avr_log.rtx_costs)
10772 avr_edump ("\n%?=%b (%s) total=%d, outer=%C:\n%r\n",
10773 done, speed ? "speed" : "size", *total, outer_code, x);
10776 return done;
10780 /* Implement `TARGET_ADDRESS_COST'. */
10782 static int
10783 avr_address_cost (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
10784 addr_space_t as ATTRIBUTE_UNUSED,
10785 bool speed ATTRIBUTE_UNUSED)
10787 int cost = 4;
10789 if (GET_CODE (x) == PLUS
10790 && CONST_INT_P (XEXP (x, 1))
10791 && (REG_P (XEXP (x, 0))
10792 || GET_CODE (XEXP (x, 0)) == SUBREG))
10794 if (INTVAL (XEXP (x, 1)) >= 61)
10795 cost = 18;
10797 else if (CONSTANT_ADDRESS_P (x))
10799 if (optimize > 0
10800 && io_address_operand (x, QImode))
10801 cost = 2;
10804 if (avr_log.address_cost)
10805 avr_edump ("\n%?: %d = %r\n", cost, x);
10807 return cost;
10810 /* Test for extra memory constraint 'Q'.
10811 It's a memory address based on Y or Z pointer with valid displacement. */
10814 extra_constraint_Q (rtx x)
10816 int ok = 0;
10818 if (GET_CODE (XEXP (x,0)) == PLUS
10819 && REG_P (XEXP (XEXP (x,0), 0))
10820 && GET_CODE (XEXP (XEXP (x,0), 1)) == CONST_INT
10821 && (INTVAL (XEXP (XEXP (x,0), 1))
10822 <= MAX_LD_OFFSET (GET_MODE (x))))
10824 rtx xx = XEXP (XEXP (x,0), 0);
10825 int regno = REGNO (xx);
10827 ok = (/* allocate pseudos */
10828 regno >= FIRST_PSEUDO_REGISTER
10829 /* strictly check */
10830 || regno == REG_Z || regno == REG_Y
10831 /* XXX frame & arg pointer checks */
10832 || xx == frame_pointer_rtx
10833 || xx == arg_pointer_rtx);
10835 if (avr_log.constraints)
10836 avr_edump ("\n%?=%d reload_completed=%d reload_in_progress=%d\n %r\n",
10837 ok, reload_completed, reload_in_progress, x);
10840 return ok;
10843 /* Convert condition code CONDITION to the valid AVR condition code. */
10845 RTX_CODE
10846 avr_normalize_condition (RTX_CODE condition)
10848 switch (condition)
10850 case GT:
10851 return GE;
10852 case GTU:
10853 return GEU;
10854 case LE:
10855 return LT;
10856 case LEU:
10857 return LTU;
10858 default:
10859 gcc_unreachable ();
10863 /* Helper function for `avr_reorg'. */
10865 static rtx
10866 avr_compare_pattern (rtx_insn *insn)
10868 rtx pattern = single_set (insn);
10870 if (pattern
10871 && NONJUMP_INSN_P (insn)
10872 && SET_DEST (pattern) == cc0_rtx
10873 && GET_CODE (SET_SRC (pattern)) == COMPARE)
10875 machine_mode mode0 = GET_MODE (XEXP (SET_SRC (pattern), 0));
10876 machine_mode mode1 = GET_MODE (XEXP (SET_SRC (pattern), 1));
10878 /* The 64-bit comparisons have fixed operands ACC_A and ACC_B.
10879 They must not be swapped, thus skip them. */
10881 if ((mode0 == VOIDmode || GET_MODE_SIZE (mode0) <= 4)
10882 && (mode1 == VOIDmode || GET_MODE_SIZE (mode1) <= 4))
10883 return pattern;
10886 return NULL_RTX;
10889 /* Helper function for `avr_reorg'. */
10891 /* Expansion of switch/case decision trees leads to code like
10893 cc0 = compare (Reg, Num)
10894 if (cc0 == 0)
10895 goto L1
10897 cc0 = compare (Reg, Num)
10898 if (cc0 > 0)
10899 goto L2
10901 The second comparison is superfluous and can be deleted.
10902 The second jump condition can be transformed from a
10903 "difficult" one to a "simple" one because "cc0 > 0" and
10904 "cc0 >= 0" will have the same effect here.
10906 This function relies on the way switch/case is being expaned
10907 as binary decision tree. For example code see PR 49903.
10909 Return TRUE if optimization performed.
10910 Return FALSE if nothing changed.
10912 INSN1 is a comparison, i.e. avr_compare_pattern != 0.
10914 We don't want to do this in text peephole because it is
10915 tedious to work out jump offsets there and the second comparison
10916 might have been transormed by `avr_reorg'.
10918 RTL peephole won't do because peephole2 does not scan across
10919 basic blocks. */
10921 static bool
10922 avr_reorg_remove_redundant_compare (rtx_insn *insn1)
10924 rtx comp1, ifelse1, xcond1;
10925 rtx_insn *branch1;
10926 rtx comp2, ifelse2, xcond2;
10927 rtx_insn *branch2, *insn2;
10928 enum rtx_code code;
10929 rtx_insn *jump;
10930 rtx target, cond;
10932 /* Look out for: compare1 - branch1 - compare2 - branch2 */
10934 branch1 = next_nonnote_nondebug_insn (insn1);
10935 if (!branch1 || !JUMP_P (branch1))
10936 return false;
10938 insn2 = next_nonnote_nondebug_insn (branch1);
10939 if (!insn2 || !avr_compare_pattern (insn2))
10940 return false;
10942 branch2 = next_nonnote_nondebug_insn (insn2);
10943 if (!branch2 || !JUMP_P (branch2))
10944 return false;
10946 comp1 = avr_compare_pattern (insn1);
10947 comp2 = avr_compare_pattern (insn2);
10948 xcond1 = single_set (branch1);
10949 xcond2 = single_set (branch2);
10951 if (!comp1 || !comp2
10952 || !rtx_equal_p (comp1, comp2)
10953 || !xcond1 || SET_DEST (xcond1) != pc_rtx
10954 || !xcond2 || SET_DEST (xcond2) != pc_rtx
10955 || IF_THEN_ELSE != GET_CODE (SET_SRC (xcond1))
10956 || IF_THEN_ELSE != GET_CODE (SET_SRC (xcond2)))
10958 return false;
10961 comp1 = SET_SRC (comp1);
10962 ifelse1 = SET_SRC (xcond1);
10963 ifelse2 = SET_SRC (xcond2);
10965 /* comp<n> is COMPARE now and ifelse<n> is IF_THEN_ELSE. */
10967 if (EQ != GET_CODE (XEXP (ifelse1, 0))
10968 || !REG_P (XEXP (comp1, 0))
10969 || !CONST_INT_P (XEXP (comp1, 1))
10970 || XEXP (ifelse1, 2) != pc_rtx
10971 || XEXP (ifelse2, 2) != pc_rtx
10972 || LABEL_REF != GET_CODE (XEXP (ifelse1, 1))
10973 || LABEL_REF != GET_CODE (XEXP (ifelse2, 1))
10974 || !COMPARISON_P (XEXP (ifelse2, 0))
10975 || cc0_rtx != XEXP (XEXP (ifelse1, 0), 0)
10976 || cc0_rtx != XEXP (XEXP (ifelse2, 0), 0)
10977 || const0_rtx != XEXP (XEXP (ifelse1, 0), 1)
10978 || const0_rtx != XEXP (XEXP (ifelse2, 0), 1))
10980 return false;
10983 /* We filtered the insn sequence to look like
10985 (set (cc0)
10986 (compare (reg:M N)
10987 (const_int VAL)))
10988 (set (pc)
10989 (if_then_else (eq (cc0)
10990 (const_int 0))
10991 (label_ref L1)
10992 (pc)))
10994 (set (cc0)
10995 (compare (reg:M N)
10996 (const_int VAL)))
10997 (set (pc)
10998 (if_then_else (CODE (cc0)
10999 (const_int 0))
11000 (label_ref L2)
11001 (pc)))
11004 code = GET_CODE (XEXP (ifelse2, 0));
11006 /* Map GT/GTU to GE/GEU which is easier for AVR.
11007 The first two instructions compare/branch on EQ
11008 so we may replace the difficult
11010 if (x == VAL) goto L1;
11011 if (x > VAL) goto L2;
11013 with easy
11015 if (x == VAL) goto L1;
11016 if (x >= VAL) goto L2;
11018 Similarly, replace LE/LEU by LT/LTU. */
11020 switch (code)
11022 case EQ:
11023 case LT: case LTU:
11024 case GE: case GEU:
11025 break;
11027 case LE: case LEU:
11028 case GT: case GTU:
11029 code = avr_normalize_condition (code);
11030 break;
11032 default:
11033 return false;
11036 /* Wrap the branches into UNSPECs so they won't be changed or
11037 optimized in the remainder. */
11039 target = XEXP (XEXP (ifelse1, 1), 0);
11040 cond = XEXP (ifelse1, 0);
11041 jump = emit_jump_insn_after (gen_branch_unspec (target, cond), insn1);
11043 JUMP_LABEL (jump) = JUMP_LABEL (branch1);
11045 target = XEXP (XEXP (ifelse2, 1), 0);
11046 cond = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
11047 jump = emit_jump_insn_after (gen_branch_unspec (target, cond), insn2);
11049 JUMP_LABEL (jump) = JUMP_LABEL (branch2);
11051 /* The comparisons in insn1 and insn2 are exactly the same;
11052 insn2 is superfluous so delete it. */
11054 delete_insn (insn2);
11055 delete_insn (branch1);
11056 delete_insn (branch2);
11058 return true;
11062 /* Implement `TARGET_MACHINE_DEPENDENT_REORG'. */
11063 /* Optimize conditional jumps. */
11065 static void
11066 avr_reorg (void)
11068 rtx_insn *insn = get_insns();
11070 for (insn = next_real_insn (insn); insn; insn = next_real_insn (insn))
11072 rtx pattern = avr_compare_pattern (insn);
11074 if (!pattern)
11075 continue;
11077 if (optimize
11078 && avr_reorg_remove_redundant_compare (insn))
11080 continue;
11083 if (compare_diff_p (insn))
11085 /* Now we work under compare insn with difficult branch. */
11087 rtx_insn *next = next_real_insn (insn);
11088 rtx pat = PATTERN (next);
11090 pattern = SET_SRC (pattern);
11092 if (true_regnum (XEXP (pattern, 0)) >= 0
11093 && true_regnum (XEXP (pattern, 1)) >= 0)
11095 rtx x = XEXP (pattern, 0);
11096 rtx src = SET_SRC (pat);
11097 rtx t = XEXP (src,0);
11098 PUT_CODE (t, swap_condition (GET_CODE (t)));
11099 XEXP (pattern, 0) = XEXP (pattern, 1);
11100 XEXP (pattern, 1) = x;
11101 INSN_CODE (next) = -1;
11103 else if (true_regnum (XEXP (pattern, 0)) >= 0
11104 && XEXP (pattern, 1) == const0_rtx)
11106 /* This is a tst insn, we can reverse it. */
11107 rtx src = SET_SRC (pat);
11108 rtx t = XEXP (src,0);
11110 PUT_CODE (t, swap_condition (GET_CODE (t)));
11111 XEXP (pattern, 1) = XEXP (pattern, 0);
11112 XEXP (pattern, 0) = const0_rtx;
11113 INSN_CODE (next) = -1;
11114 INSN_CODE (insn) = -1;
11116 else if (true_regnum (XEXP (pattern, 0)) >= 0
11117 && CONST_INT_P (XEXP (pattern, 1)))
11119 rtx x = XEXP (pattern, 1);
11120 rtx src = SET_SRC (pat);
11121 rtx t = XEXP (src,0);
11122 machine_mode mode = GET_MODE (XEXP (pattern, 0));
11124 if (avr_simplify_comparison_p (mode, GET_CODE (t), x))
11126 XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
11127 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
11128 INSN_CODE (next) = -1;
11129 INSN_CODE (insn) = -1;
11136 /* Returns register number for function return value.*/
11138 static inline unsigned int
11139 avr_ret_register (void)
11141 return 24;
11145 /* Implement `TARGET_FUNCTION_VALUE_REGNO_P'. */
11147 static bool
11148 avr_function_value_regno_p (const unsigned int regno)
11150 return (regno == avr_ret_register ());
11154 /* Implement `TARGET_LIBCALL_VALUE'. */
11155 /* Create an RTX representing the place where a
11156 library function returns a value of mode MODE. */
11158 static rtx
11159 avr_libcall_value (machine_mode mode,
11160 const_rtx func ATTRIBUTE_UNUSED)
11162 int offs = GET_MODE_SIZE (mode);
11164 if (offs <= 4)
11165 offs = (offs + 1) & ~1;
11167 return gen_rtx_REG (mode, avr_ret_register () + 2 - offs);
11171 /* Implement `TARGET_FUNCTION_VALUE'. */
11172 /* Create an RTX representing the place where a
11173 function returns a value of data type VALTYPE. */
11175 static rtx
11176 avr_function_value (const_tree type,
11177 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
11178 bool outgoing ATTRIBUTE_UNUSED)
11180 unsigned int offs;
11182 if (TYPE_MODE (type) != BLKmode)
11183 return avr_libcall_value (TYPE_MODE (type), NULL_RTX);
11185 offs = int_size_in_bytes (type);
11186 if (offs < 2)
11187 offs = 2;
11188 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
11189 offs = GET_MODE_SIZE (SImode);
11190 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
11191 offs = GET_MODE_SIZE (DImode);
11193 return gen_rtx_REG (BLKmode, avr_ret_register () + 2 - offs);
11197 test_hard_reg_class (enum reg_class rclass, rtx x)
11199 int regno = true_regnum (x);
11200 if (regno < 0)
11201 return 0;
11203 if (TEST_HARD_REG_CLASS (rclass, regno))
11204 return 1;
11206 return 0;
11210 /* Helper for jump_over_one_insn_p: Test if INSN is a 2-word instruction
11211 and thus is suitable to be skipped by CPSE, SBRC, etc. */
11213 static bool
11214 avr_2word_insn_p (rtx_insn *insn)
11216 if (TARGET_SKIP_BUG
11217 || !insn
11218 || 2 != get_attr_length (insn))
11220 return false;
11223 switch (INSN_CODE (insn))
11225 default:
11226 return false;
11228 case CODE_FOR_movqi_insn:
11229 case CODE_FOR_movuqq_insn:
11230 case CODE_FOR_movqq_insn:
11232 rtx set = single_set (insn);
11233 rtx src = SET_SRC (set);
11234 rtx dest = SET_DEST (set);
11236 /* Factor out LDS and STS from movqi_insn. */
11238 if (MEM_P (dest)
11239 && (REG_P (src) || src == CONST0_RTX (GET_MODE (dest))))
11241 return CONSTANT_ADDRESS_P (XEXP (dest, 0));
11243 else if (REG_P (dest)
11244 && MEM_P (src))
11246 return CONSTANT_ADDRESS_P (XEXP (src, 0));
11249 return false;
11252 case CODE_FOR_call_insn:
11253 case CODE_FOR_call_value_insn:
11254 return true;
11260 jump_over_one_insn_p (rtx_insn *insn, rtx dest)
11262 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
11263 ? XEXP (dest, 0)
11264 : dest);
11265 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
11266 int dest_addr = INSN_ADDRESSES (uid);
11267 int jump_offset = dest_addr - jump_addr - get_attr_length (insn);
11269 return (jump_offset == 1
11270 || (jump_offset == 2
11271 && avr_2word_insn_p (next_active_insn (insn))));
11275 /* Worker function for `HARD_REGNO_MODE_OK'. */
11276 /* Returns 1 if a value of mode MODE can be stored starting with hard
11277 register number REGNO. On the enhanced core, anything larger than
11278 1 byte must start in even numbered register for "movw" to work
11279 (this way we don't have to check for odd registers everywhere). */
11282 avr_hard_regno_mode_ok (int regno, machine_mode mode)
11284 /* NOTE: 8-bit values must not be disallowed for R28 or R29.
11285 Disallowing QI et al. in these regs might lead to code like
11286 (set (subreg:QI (reg:HI 28) n) ...)
11287 which will result in wrong code because reload does not
11288 handle SUBREGs of hard regsisters like this.
11289 This could be fixed in reload. However, it appears
11290 that fixing reload is not wanted by reload people. */
11292 /* Any GENERAL_REGS register can hold 8-bit values. */
11294 if (GET_MODE_SIZE (mode) == 1)
11295 return 1;
11297 /* FIXME: Ideally, the following test is not needed.
11298 However, it turned out that it can reduce the number
11299 of spill fails. AVR and it's poor endowment with
11300 address registers is extreme stress test for reload. */
11302 if (GET_MODE_SIZE (mode) >= 4
11303 && regno >= REG_X)
11304 return 0;
11306 /* All modes larger than 8 bits should start in an even register. */
11308 return !(regno & 1);
11312 /* Implement `HARD_REGNO_CALL_PART_CLOBBERED'. */
11315 avr_hard_regno_call_part_clobbered (unsigned regno, machine_mode mode)
11317 /* FIXME: This hook gets called with MODE:REGNO combinations that don't
11318 represent valid hard registers like, e.g. HI:29. Returning TRUE
11319 for such registers can lead to performance degradation as mentioned
11320 in PR53595. Thus, report invalid hard registers as FALSE. */
11322 if (!avr_hard_regno_mode_ok (regno, mode))
11323 return 0;
11325 /* Return true if any of the following boundaries is crossed:
11326 17/18 or 19/20 (if AVR_TINY), 27/28 and 29/30. */
11328 return ((regno <= LAST_CALLEE_SAVED_REG &&
11329 regno + GET_MODE_SIZE (mode) > (LAST_CALLEE_SAVED_REG + 1))
11330 || (regno < REG_Y && regno + GET_MODE_SIZE (mode) > REG_Y)
11331 || (regno < REG_Z && regno + GET_MODE_SIZE (mode) > REG_Z));
11335 /* Implement `MODE_CODE_BASE_REG_CLASS'. */
11337 enum reg_class
11338 avr_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED,
11339 addr_space_t as, RTX_CODE outer_code,
11340 RTX_CODE index_code ATTRIBUTE_UNUSED)
11342 if (!ADDR_SPACE_GENERIC_P (as))
11344 return POINTER_Z_REGS;
11347 if (!avr_strict_X)
11348 return reload_completed ? BASE_POINTER_REGS : POINTER_REGS;
11350 return PLUS == outer_code ? BASE_POINTER_REGS : POINTER_REGS;
11354 /* Implement `REGNO_MODE_CODE_OK_FOR_BASE_P'. */
11356 bool
11357 avr_regno_mode_code_ok_for_base_p (int regno,
11358 machine_mode mode ATTRIBUTE_UNUSED,
11359 addr_space_t as ATTRIBUTE_UNUSED,
11360 RTX_CODE outer_code,
11361 RTX_CODE index_code ATTRIBUTE_UNUSED)
11363 bool ok = false;
11365 if (!ADDR_SPACE_GENERIC_P (as))
11367 if (regno < FIRST_PSEUDO_REGISTER
11368 && regno == REG_Z)
11370 return true;
11373 if (reg_renumber)
11375 regno = reg_renumber[regno];
11377 if (regno == REG_Z)
11379 return true;
11383 return false;
11386 if (regno < FIRST_PSEUDO_REGISTER
11387 && (regno == REG_X
11388 || regno == REG_Y
11389 || regno == REG_Z
11390 || regno == ARG_POINTER_REGNUM))
11392 ok = true;
11394 else if (reg_renumber)
11396 regno = reg_renumber[regno];
11398 if (regno == REG_X
11399 || regno == REG_Y
11400 || regno == REG_Z
11401 || regno == ARG_POINTER_REGNUM)
11403 ok = true;
11407 if (avr_strict_X
11408 && PLUS == outer_code
11409 && regno == REG_X)
11411 ok = false;
11414 return ok;
11418 /* A helper for `output_reload_insisf' and `output_reload_inhi'. */
11419 /* Set 32-bit register OP[0] to compile-time constant OP[1].
11420 CLOBBER_REG is a QI clobber register or NULL_RTX.
11421 LEN == NULL: output instructions.
11422 LEN != NULL: set *LEN to the length of the instruction sequence
11423 (in words) printed with LEN = NULL.
11424 If CLEAR_P is true, OP[0] had been cleard to Zero already.
11425 If CLEAR_P is false, nothing is known about OP[0].
11427 The effect on cc0 is as follows:
11429 Load 0 to any register except ZERO_REG : NONE
11430 Load ld register with any value : NONE
11431 Anything else: : CLOBBER */
11433 static void
11434 output_reload_in_const (rtx *op, rtx clobber_reg, int *len, bool clear_p)
11436 rtx src = op[1];
11437 rtx dest = op[0];
11438 rtx xval, xdest[4];
11439 int ival[4];
11440 int clobber_val = 1234;
11441 bool cooked_clobber_p = false;
11442 bool set_p = false;
11443 machine_mode mode = GET_MODE (dest);
11444 int n, n_bytes = GET_MODE_SIZE (mode);
11446 gcc_assert (REG_P (dest)
11447 && CONSTANT_P (src));
11449 if (len)
11450 *len = 0;
11452 /* (REG:SI 14) is special: It's neither in LD_REGS nor in NO_LD_REGS
11453 but has some subregs that are in LD_REGS. Use the MSB (REG:QI 17). */
11455 if (REGNO (dest) < 16
11456 && REGNO (dest) + GET_MODE_SIZE (mode) > 16)
11458 clobber_reg = all_regs_rtx[REGNO (dest) + n_bytes - 1];
11461 /* We might need a clobber reg but don't have one. Look at the value to
11462 be loaded more closely. A clobber is only needed if it is a symbol
11463 or contains a byte that is neither 0, -1 or a power of 2. */
11465 if (NULL_RTX == clobber_reg
11466 && !test_hard_reg_class (LD_REGS, dest)
11467 && (! (CONST_INT_P (src) || CONST_FIXED_P (src) || CONST_DOUBLE_P (src))
11468 || !avr_popcount_each_byte (src, n_bytes,
11469 (1 << 0) | (1 << 1) | (1 << 8))))
11471 /* We have no clobber register but need one. Cook one up.
11472 That's cheaper than loading from constant pool. */
11474 cooked_clobber_p = true;
11475 clobber_reg = all_regs_rtx[REG_Z + 1];
11476 avr_asm_len ("mov __tmp_reg__,%0", &clobber_reg, len, 1);
11479 /* Now start filling DEST from LSB to MSB. */
11481 for (n = 0; n < n_bytes; n++)
11483 int ldreg_p;
11484 bool done_byte = false;
11485 int j;
11486 rtx xop[3];
11488 /* Crop the n-th destination byte. */
11490 xdest[n] = simplify_gen_subreg (QImode, dest, mode, n);
11491 ldreg_p = test_hard_reg_class (LD_REGS, xdest[n]);
11493 if (!CONST_INT_P (src)
11494 && !CONST_FIXED_P (src)
11495 && !CONST_DOUBLE_P (src))
11497 static const char* const asm_code[][2] =
11499 { "ldi %2,lo8(%1)" CR_TAB "mov %0,%2", "ldi %0,lo8(%1)" },
11500 { "ldi %2,hi8(%1)" CR_TAB "mov %0,%2", "ldi %0,hi8(%1)" },
11501 { "ldi %2,hlo8(%1)" CR_TAB "mov %0,%2", "ldi %0,hlo8(%1)" },
11502 { "ldi %2,hhi8(%1)" CR_TAB "mov %0,%2", "ldi %0,hhi8(%1)" }
11505 xop[0] = xdest[n];
11506 xop[1] = src;
11507 xop[2] = clobber_reg;
11509 avr_asm_len (asm_code[n][ldreg_p], xop, len, ldreg_p ? 1 : 2);
11511 continue;
11514 /* Crop the n-th source byte. */
11516 xval = simplify_gen_subreg (QImode, src, mode, n);
11517 ival[n] = INTVAL (xval);
11519 /* Look if we can reuse the low word by means of MOVW. */
11521 if (n == 2
11522 && n_bytes >= 4
11523 && AVR_HAVE_MOVW)
11525 rtx lo16 = simplify_gen_subreg (HImode, src, mode, 0);
11526 rtx hi16 = simplify_gen_subreg (HImode, src, mode, 2);
11528 if (INTVAL (lo16) == INTVAL (hi16))
11530 if (0 != INTVAL (lo16)
11531 || !clear_p)
11533 avr_asm_len ("movw %C0,%A0", &op[0], len, 1);
11536 break;
11540 /* Don't use CLR so that cc0 is set as expected. */
11542 if (ival[n] == 0)
11544 if (!clear_p)
11545 avr_asm_len (ldreg_p ? "ldi %0,0"
11546 : AVR_ZERO_REGNO == REGNO (xdest[n]) ? "clr %0"
11547 : "mov %0,__zero_reg__",
11548 &xdest[n], len, 1);
11549 continue;
11552 if (clobber_val == ival[n]
11553 && REGNO (clobber_reg) == REGNO (xdest[n]))
11555 continue;
11558 /* LD_REGS can use LDI to move a constant value */
11560 if (ldreg_p)
11562 xop[0] = xdest[n];
11563 xop[1] = xval;
11564 avr_asm_len ("ldi %0,lo8(%1)", xop, len, 1);
11565 continue;
11568 /* Try to reuse value already loaded in some lower byte. */
11570 for (j = 0; j < n; j++)
11571 if (ival[j] == ival[n])
11573 xop[0] = xdest[n];
11574 xop[1] = xdest[j];
11576 avr_asm_len ("mov %0,%1", xop, len, 1);
11577 done_byte = true;
11578 break;
11581 if (done_byte)
11582 continue;
11584 /* Need no clobber reg for -1: Use CLR/DEC */
11586 if (-1 == ival[n])
11588 if (!clear_p)
11589 avr_asm_len ("clr %0", &xdest[n], len, 1);
11591 avr_asm_len ("dec %0", &xdest[n], len, 1);
11592 continue;
11594 else if (1 == ival[n])
11596 if (!clear_p)
11597 avr_asm_len ("clr %0", &xdest[n], len, 1);
11599 avr_asm_len ("inc %0", &xdest[n], len, 1);
11600 continue;
11603 /* Use T flag or INC to manage powers of 2 if we have
11604 no clobber reg. */
11606 if (NULL_RTX == clobber_reg
11607 && single_one_operand (xval, QImode))
11609 xop[0] = xdest[n];
11610 xop[1] = GEN_INT (exact_log2 (ival[n] & GET_MODE_MASK (QImode)));
11612 gcc_assert (constm1_rtx != xop[1]);
11614 if (!set_p)
11616 set_p = true;
11617 avr_asm_len ("set", xop, len, 1);
11620 if (!clear_p)
11621 avr_asm_len ("clr %0", xop, len, 1);
11623 avr_asm_len ("bld %0,%1", xop, len, 1);
11624 continue;
11627 /* We actually need the LD_REGS clobber reg. */
11629 gcc_assert (NULL_RTX != clobber_reg);
11631 xop[0] = xdest[n];
11632 xop[1] = xval;
11633 xop[2] = clobber_reg;
11634 clobber_val = ival[n];
11636 avr_asm_len ("ldi %2,lo8(%1)" CR_TAB
11637 "mov %0,%2", xop, len, 2);
11640 /* If we cooked up a clobber reg above, restore it. */
11642 if (cooked_clobber_p)
11644 avr_asm_len ("mov %0,__tmp_reg__", &clobber_reg, len, 1);
11649 /* Reload the constant OP[1] into the HI register OP[0].
11650 CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
11651 into a NO_LD_REGS register. If CLOBBER_REG is NULL_RTX we either don't
11652 need a clobber reg or have to cook one up.
11654 PLEN == NULL: Output instructions.
11655 PLEN != NULL: Output nothing. Set *PLEN to number of words occupied
11656 by the insns printed.
11658 Return "". */
11660 const char*
11661 output_reload_inhi (rtx *op, rtx clobber_reg, int *plen)
11663 output_reload_in_const (op, clobber_reg, plen, false);
11664 return "";
11668 /* Reload a SI or SF compile time constant OP[1] into the register OP[0].
11669 CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
11670 into a NO_LD_REGS register. If CLOBBER_REG is NULL_RTX we either don't
11671 need a clobber reg or have to cook one up.
11673 LEN == NULL: Output instructions.
11675 LEN != NULL: Output nothing. Set *LEN to number of words occupied
11676 by the insns printed.
11678 Return "". */
11680 const char *
11681 output_reload_insisf (rtx *op, rtx clobber_reg, int *len)
11683 if (AVR_HAVE_MOVW
11684 && !test_hard_reg_class (LD_REGS, op[0])
11685 && (CONST_INT_P (op[1])
11686 || CONST_FIXED_P (op[1])
11687 || CONST_DOUBLE_P (op[1])))
11689 int len_clr, len_noclr;
11691 /* In some cases it is better to clear the destination beforehand, e.g.
11693 CLR R2 CLR R3 MOVW R4,R2 INC R2
11695 is shorther than
11697 CLR R2 INC R2 CLR R3 CLR R4 CLR R5
11699 We find it too tedious to work that out in the print function.
11700 Instead, we call the print function twice to get the lengths of
11701 both methods and use the shortest one. */
11703 output_reload_in_const (op, clobber_reg, &len_clr, true);
11704 output_reload_in_const (op, clobber_reg, &len_noclr, false);
11706 if (len_noclr - len_clr == 4)
11708 /* Default needs 4 CLR instructions: clear register beforehand. */
11710 avr_asm_len ("mov %A0,__zero_reg__" CR_TAB
11711 "mov %B0,__zero_reg__" CR_TAB
11712 "movw %C0,%A0", &op[0], len, 3);
11714 output_reload_in_const (op, clobber_reg, len, true);
11716 if (len)
11717 *len += 3;
11719 return "";
11723 /* Default: destination not pre-cleared. */
11725 output_reload_in_const (op, clobber_reg, len, false);
11726 return "";
11729 const char*
11730 avr_out_reload_inpsi (rtx *op, rtx clobber_reg, int *len)
11732 output_reload_in_const (op, clobber_reg, len, false);
11733 return "";
11737 /* Worker function for `ASM_OUTPUT_ADDR_VEC_ELT'. */
11739 void
11740 avr_output_addr_vec_elt (FILE *stream, int value)
11742 if (AVR_HAVE_JMP_CALL)
11743 fprintf (stream, "\t.word gs(.L%d)\n", value);
11744 else
11745 fprintf (stream, "\trjmp .L%d\n", value);
11748 static void
11749 avr_conditional_register_usage(void)
11751 if (AVR_TINY)
11753 unsigned int i;
11755 const int tiny_reg_alloc_order[] = {
11756 24, 25,
11757 22, 23,
11758 30, 31,
11759 26, 27,
11760 28, 29,
11761 21, 20, 19, 18,
11762 16, 17,
11763 32, 33, 34, 35,
11764 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
11767 /* Set R0-R17 as fixed registers. Reset R0-R17 in call used register list
11768 - R0-R15 are not available in Tiny Core devices
11769 - R16 and R17 are fixed registers. */
11771 for (i = 0; i <= 17; i++)
11773 fixed_regs[i] = 1;
11774 call_used_regs[i] = 1;
11777 /* Set R18 to R21 as callee saved registers
11778 - R18, R19, R20 and R21 are the callee saved registers in
11779 Tiny Core devices */
11781 for (i = 18; i <= LAST_CALLEE_SAVED_REG; i++)
11783 call_used_regs[i] = 0;
11786 /* Update register allocation order for Tiny Core devices */
11788 for (i = 0; i < ARRAY_SIZE (tiny_reg_alloc_order); i++)
11790 reg_alloc_order[i] = tiny_reg_alloc_order[i];
11793 CLEAR_HARD_REG_SET (reg_class_contents[(int) ADDW_REGS]);
11794 CLEAR_HARD_REG_SET (reg_class_contents[(int) NO_LD_REGS]);
11798 /* Implement `TARGET_HARD_REGNO_SCRATCH_OK'. */
11799 /* Returns true if SCRATCH are safe to be allocated as a scratch
11800 registers (for a define_peephole2) in the current function. */
11802 static bool
11803 avr_hard_regno_scratch_ok (unsigned int regno)
11805 /* Interrupt functions can only use registers that have already been saved
11806 by the prologue, even if they would normally be call-clobbered. */
11808 if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
11809 && !df_regs_ever_live_p (regno))
11810 return false;
11812 /* Don't allow hard registers that might be part of the frame pointer.
11813 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
11814 and don't care for a frame pointer that spans more than one register. */
11816 if ((!reload_completed || frame_pointer_needed)
11817 && (regno == REG_Y || regno == REG_Y + 1))
11819 return false;
11822 return true;
11826 /* Worker function for `HARD_REGNO_RENAME_OK'. */
11827 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
11830 avr_hard_regno_rename_ok (unsigned int old_reg,
11831 unsigned int new_reg)
11833 /* Interrupt functions can only use registers that have already been
11834 saved by the prologue, even if they would normally be
11835 call-clobbered. */
11837 if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
11838 && !df_regs_ever_live_p (new_reg))
11839 return 0;
11841 /* Don't allow hard registers that might be part of the frame pointer.
11842 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
11843 and don't care for a frame pointer that spans more than one register. */
11845 if ((!reload_completed || frame_pointer_needed)
11846 && (old_reg == REG_Y || old_reg == REG_Y + 1
11847 || new_reg == REG_Y || new_reg == REG_Y + 1))
11849 return 0;
11852 return 1;
11855 /* Output a branch that tests a single bit of a register (QI, HI, SI or DImode)
11856 or memory location in the I/O space (QImode only).
11858 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
11859 Operand 1: register operand to test, or CONST_INT memory address.
11860 Operand 2: bit number.
11861 Operand 3: label to jump to if the test is true. */
11863 const char*
11864 avr_out_sbxx_branch (rtx_insn *insn, rtx operands[])
11866 enum rtx_code comp = GET_CODE (operands[0]);
11867 bool long_jump = get_attr_length (insn) >= 4;
11868 bool reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
11870 if (comp == GE)
11871 comp = EQ;
11872 else if (comp == LT)
11873 comp = NE;
11875 if (reverse)
11876 comp = reverse_condition (comp);
11878 switch (GET_CODE (operands[1]))
11880 default:
11881 gcc_unreachable();
11883 case CONST_INT:
11884 case CONST:
11885 case SYMBOL_REF:
11887 if (low_io_address_operand (operands[1], QImode))
11889 if (comp == EQ)
11890 output_asm_insn ("sbis %i1,%2", operands);
11891 else
11892 output_asm_insn ("sbic %i1,%2", operands);
11894 else
11896 gcc_assert (io_address_operand (operands[1], QImode));
11897 output_asm_insn ("in __tmp_reg__,%i1", operands);
11898 if (comp == EQ)
11899 output_asm_insn ("sbrs __tmp_reg__,%2", operands);
11900 else
11901 output_asm_insn ("sbrc __tmp_reg__,%2", operands);
11904 break; /* CONST_INT */
11906 case REG:
11908 if (comp == EQ)
11909 output_asm_insn ("sbrs %T1%T2", operands);
11910 else
11911 output_asm_insn ("sbrc %T1%T2", operands);
11913 break; /* REG */
11914 } /* switch */
11916 if (long_jump)
11917 return ("rjmp .+4" CR_TAB
11918 "jmp %x3");
11920 if (!reverse)
11921 return "rjmp %x3";
11923 return "";
11926 /* Worker function for `TARGET_ASM_CONSTRUCTOR'. */
11928 static void
11929 avr_asm_out_ctor (rtx symbol, int priority)
11931 fputs ("\t.global __do_global_ctors\n", asm_out_file);
11932 default_ctor_section_asm_out_constructor (symbol, priority);
11936 /* Worker function for `TARGET_ASM_DESTRUCTOR'. */
11938 static void
11939 avr_asm_out_dtor (rtx symbol, int priority)
11941 fputs ("\t.global __do_global_dtors\n", asm_out_file);
11942 default_dtor_section_asm_out_destructor (symbol, priority);
11946 /* Worker function for `TARGET_RETURN_IN_MEMORY'. */
11948 static bool
11949 avr_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
11951 HOST_WIDE_INT size = int_size_in_bytes (type);
11952 HOST_WIDE_INT ret_size_limit = AVR_TINY ? 4 : 8;
11954 /* In avr, there are 8 return registers. But, for Tiny Core
11955 (ATtiny4/5/9/10/20/40) devices, only 4 registers are available.
11956 Return true if size is unknown or greater than the limit. */
11958 if (size == -1 || size > ret_size_limit)
11960 return true;
11962 else
11964 return false;
11969 /* Implement `CASE_VALUES_THRESHOLD'. */
11970 /* Supply the default for --param case-values-threshold=0 */
11972 static unsigned int
11973 avr_case_values_threshold (void)
11975 /* The exact break-even point between a jump table and an if-else tree
11976 depends on several factors not available here like, e.g. if 8-bit
11977 comparisons can be used in the if-else tree or not, on the
11978 range of the case values, if the case value can be reused, on the
11979 register allocation, etc. '7' appears to be a good choice. */
11981 return 7;
11985 /* Implement `TARGET_ADDR_SPACE_ADDRESS_MODE'. */
11987 static machine_mode
11988 avr_addr_space_address_mode (addr_space_t as)
11990 return avr_addrspace[as].pointer_size == 3 ? PSImode : HImode;
11994 /* Implement `TARGET_ADDR_SPACE_POINTER_MODE'. */
11996 static machine_mode
11997 avr_addr_space_pointer_mode (addr_space_t as)
11999 return avr_addr_space_address_mode (as);
12003 /* Helper for following function. */
12005 static bool
12006 avr_reg_ok_for_pgm_addr (rtx reg, bool strict)
12008 gcc_assert (REG_P (reg));
12010 if (strict)
12012 return REGNO (reg) == REG_Z;
12015 /* Avoid combine to propagate hard regs. */
12017 if (can_create_pseudo_p()
12018 && REGNO (reg) < REG_Z)
12020 return false;
12023 return true;
12027 /* Implement `TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P'. */
12029 static bool
12030 avr_addr_space_legitimate_address_p (machine_mode mode, rtx x,
12031 bool strict, addr_space_t as)
12033 bool ok = false;
12035 switch (as)
12037 default:
12038 gcc_unreachable();
12040 case ADDR_SPACE_GENERIC:
12041 return avr_legitimate_address_p (mode, x, strict);
12043 case ADDR_SPACE_FLASH:
12044 case ADDR_SPACE_FLASH1:
12045 case ADDR_SPACE_FLASH2:
12046 case ADDR_SPACE_FLASH3:
12047 case ADDR_SPACE_FLASH4:
12048 case ADDR_SPACE_FLASH5:
12050 switch (GET_CODE (x))
12052 case REG:
12053 ok = avr_reg_ok_for_pgm_addr (x, strict);
12054 break;
12056 case POST_INC:
12057 ok = avr_reg_ok_for_pgm_addr (XEXP (x, 0), strict);
12058 break;
12060 default:
12061 break;
12064 break; /* FLASH */
12066 case ADDR_SPACE_MEMX:
12067 if (REG_P (x))
12068 ok = (!strict
12069 && can_create_pseudo_p());
12071 if (LO_SUM == GET_CODE (x))
12073 rtx hi = XEXP (x, 0);
12074 rtx lo = XEXP (x, 1);
12076 ok = (REG_P (hi)
12077 && (!strict || REGNO (hi) < FIRST_PSEUDO_REGISTER)
12078 && REG_P (lo)
12079 && REGNO (lo) == REG_Z);
12082 break; /* MEMX */
12085 if (avr_log.legitimate_address_p)
12087 avr_edump ("\n%?: ret=%b, mode=%m strict=%d "
12088 "reload_completed=%d reload_in_progress=%d %s:",
12089 ok, mode, strict, reload_completed, reload_in_progress,
12090 reg_renumber ? "(reg_renumber)" : "");
12092 if (GET_CODE (x) == PLUS
12093 && REG_P (XEXP (x, 0))
12094 && CONST_INT_P (XEXP (x, 1))
12095 && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
12096 && reg_renumber)
12098 avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
12099 true_regnum (XEXP (x, 0)));
12102 avr_edump ("\n%r\n", x);
12105 return ok;
12109 /* Implement `TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS'. */
12111 static rtx
12112 avr_addr_space_legitimize_address (rtx x, rtx old_x,
12113 machine_mode mode, addr_space_t as)
12115 if (ADDR_SPACE_GENERIC_P (as))
12116 return avr_legitimize_address (x, old_x, mode);
12118 if (avr_log.legitimize_address)
12120 avr_edump ("\n%?: mode=%m\n %r\n", mode, old_x);
12123 return old_x;
12127 /* Implement `TARGET_ADDR_SPACE_CONVERT'. */
12129 static rtx
12130 avr_addr_space_convert (rtx src, tree type_from, tree type_to)
12132 addr_space_t as_from = TYPE_ADDR_SPACE (TREE_TYPE (type_from));
12133 addr_space_t as_to = TYPE_ADDR_SPACE (TREE_TYPE (type_to));
12135 if (avr_log.progmem)
12136 avr_edump ("\n%!: op = %r\nfrom = %t\nto = %t\n",
12137 src, type_from, type_to);
12139 /* Up-casting from 16-bit to 24-bit pointer. */
12141 if (as_from != ADDR_SPACE_MEMX
12142 && as_to == ADDR_SPACE_MEMX)
12144 int msb;
12145 rtx sym = src;
12146 rtx reg = gen_reg_rtx (PSImode);
12148 while (CONST == GET_CODE (sym) || PLUS == GET_CODE (sym))
12149 sym = XEXP (sym, 0);
12151 /* Look at symbol flags: avr_encode_section_info set the flags
12152 also if attribute progmem was seen so that we get the right
12153 promotion for, e.g. PSTR-like strings that reside in generic space
12154 but are located in flash. In that case we patch the incoming
12155 address space. */
12157 if (SYMBOL_REF == GET_CODE (sym)
12158 && ADDR_SPACE_FLASH == AVR_SYMBOL_GET_ADDR_SPACE (sym))
12160 as_from = ADDR_SPACE_FLASH;
12163 /* Linearize memory: RAM has bit 23 set. */
12165 msb = ADDR_SPACE_GENERIC_P (as_from)
12166 ? 0x80
12167 : avr_addrspace[as_from].segment;
12169 src = force_reg (Pmode, src);
12171 emit_insn (msb == 0
12172 ? gen_zero_extendhipsi2 (reg, src)
12173 : gen_n_extendhipsi2 (reg, gen_int_mode (msb, QImode), src));
12175 return reg;
12178 /* Down-casting from 24-bit to 16-bit throws away the high byte. */
12180 if (as_from == ADDR_SPACE_MEMX
12181 && as_to != ADDR_SPACE_MEMX)
12183 rtx new_src = gen_reg_rtx (Pmode);
12185 src = force_reg (PSImode, src);
12187 emit_move_insn (new_src,
12188 simplify_gen_subreg (Pmode, src, PSImode, 0));
12189 return new_src;
12192 return src;
12196 /* Implement `TARGET_ADDR_SPACE_SUBSET_P'. */
12198 static bool
12199 avr_addr_space_subset_p (addr_space_t subset ATTRIBUTE_UNUSED,
12200 addr_space_t superset ATTRIBUTE_UNUSED)
12202 /* Allow any kind of pointer mess. */
12204 return true;
12208 /* Implement `TARGET_CONVERT_TO_TYPE'. */
12210 static tree
12211 avr_convert_to_type (tree type, tree expr)
12213 /* Print a diagnose for pointer conversion that changes the address
12214 space of the pointer target to a non-enclosing address space,
12215 provided -Waddr-space-convert is on.
12217 FIXME: Filter out cases where the target object is known to
12218 be located in the right memory, like in
12220 (const __flash*) PSTR ("text")
12222 Also try to distinguish between explicit casts requested by
12223 the user and implicit casts like
12225 void f (const __flash char*);
12227 void g (const char *p)
12229 f ((const __flash*) p);
12232 under the assumption that an explicit casts means that the user
12233 knows what he is doing, e.g. interface with PSTR or old style
12234 code with progmem and pgm_read_xxx.
12237 if (avr_warn_addr_space_convert
12238 && expr != error_mark_node
12239 && POINTER_TYPE_P (type)
12240 && POINTER_TYPE_P (TREE_TYPE (expr)))
12242 addr_space_t as_old = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (expr)));
12243 addr_space_t as_new = TYPE_ADDR_SPACE (TREE_TYPE (type));
12245 if (avr_log.progmem)
12246 avr_edump ("%?: type = %t\nexpr = %t\n\n", type, expr);
12248 if (as_new != ADDR_SPACE_MEMX
12249 && as_new != as_old)
12251 location_t loc = EXPR_LOCATION (expr);
12252 const char *name_old = avr_addrspace[as_old].name;
12253 const char *name_new = avr_addrspace[as_new].name;
12255 warning (OPT_Waddr_space_convert,
12256 "conversion from address space %qs to address space %qs",
12257 ADDR_SPACE_GENERIC_P (as_old) ? "generic" : name_old,
12258 ADDR_SPACE_GENERIC_P (as_new) ? "generic" : name_new);
12260 return fold_build1_loc (loc, ADDR_SPACE_CONVERT_EXPR, type, expr);
12264 return NULL_TREE;
12268 /* PR63633: The middle-end might come up with hard regs as input operands.
12270 RMASK is a bit mask representing a subset of hard registers R0...R31:
12271 Rn is an element of that set iff bit n of RMASK is set.
12272 OPMASK describes a subset of OP[]: If bit n of OPMASK is 1 then
12273 OP[n] has to be fixed; otherwise OP[n] is left alone.
12275 For each element of OPMASK which is a hard register overlapping RMASK,
12276 replace OP[n] with a newly created pseudo register
12278 HREG == 0: Also emit a move insn that copies the contents of that
12279 hard register into the new pseudo.
12281 HREG != 0: Also set HREG[n] to the hard register. */
12283 static void
12284 avr_fix_operands (rtx *op, rtx *hreg, unsigned opmask, unsigned rmask)
12286 for (; opmask; opmask >>= 1, op++)
12288 rtx reg = *op;
12290 if (hreg)
12291 *hreg = NULL_RTX;
12293 if ((opmask & 1)
12294 && REG_P (reg)
12295 && REGNO (reg) < FIRST_PSEUDO_REGISTER
12296 // This hard-reg overlaps other prohibited hard regs?
12297 && (rmask & regmask (GET_MODE (reg), REGNO (reg))))
12299 *op = gen_reg_rtx (GET_MODE (reg));
12300 if (hreg == NULL)
12301 emit_move_insn (*op, reg);
12302 else
12303 *hreg = reg;
12306 if (hreg)
12307 hreg++;
12312 void
12313 avr_fix_inputs (rtx *op, unsigned opmask, unsigned rmask)
12315 avr_fix_operands (op, NULL, opmask, rmask);
12319 /* Helper for the function below: If bit n of MASK is set and
12320 HREG[n] != NULL, then emit a move insn to copy OP[n] to HREG[n].
12321 Otherwise do nothing for that n. Return TRUE. */
12323 static bool
12324 avr_move_fixed_operands (rtx *op, rtx *hreg, unsigned mask)
12326 for (; mask; mask >>= 1, op++, hreg++)
12327 if ((mask & 1)
12328 && *hreg)
12329 emit_move_insn (*hreg, *op);
12331 return true;
12335 /* PR63633: The middle-end might come up with hard regs as output operands.
12337 GEN is a sequence generating function like gen_mulsi3 with 3 operands OP[].
12338 RMASK is a bit mask representing a subset of hard registers R0...R31:
12339 Rn is an element of that set iff bit n of RMASK is set.
12340 OPMASK describes a subset of OP[]: If bit n of OPMASK is 1 then
12341 OP[n] has to be fixed; otherwise OP[n] is left alone.
12343 Emit the insn sequence as generated by GEN() with all elements of OPMASK
12344 which are hard registers overlapping RMASK replaced by newly created
12345 pseudo registers. After the sequence has been emitted, emit insns that
12346 move the contents of respective pseudos to their hard regs. */
12348 bool
12349 avr_emit3_fix_outputs (rtx (*gen)(rtx,rtx,rtx), rtx *op,
12350 unsigned opmask, unsigned rmask)
12352 const int n = 3;
12353 rtx hreg[n];
12355 /* It is letigimate for GEN to call this function, and in order not to
12356 get self-recursive we use the following static kludge. This is the
12357 only way not to duplicate all expanders and to avoid ugly and
12358 hard-to-maintain C-code instead of the much more appreciated RTL
12359 representation as supplied by define_expand. */
12360 static bool lock = false;
12362 gcc_assert (opmask < (1u << n));
12364 if (lock)
12365 return false;
12367 avr_fix_operands (op, hreg, opmask, rmask);
12369 lock = true;
12370 emit_insn (gen (op[0], op[1], op[2]));
12371 lock = false;
12373 return avr_move_fixed_operands (op, hreg, opmask);
12377 /* Worker function for movmemhi expander.
12378 XOP[0] Destination as MEM:BLK
12379 XOP[1] Source " "
12380 XOP[2] # Bytes to copy
12382 Return TRUE if the expansion is accomplished.
12383 Return FALSE if the operand compination is not supported. */
12385 bool
12386 avr_emit_movmemhi (rtx *xop)
12388 HOST_WIDE_INT count;
12389 machine_mode loop_mode;
12390 addr_space_t as = MEM_ADDR_SPACE (xop[1]);
12391 rtx loop_reg, addr1, a_src, a_dest, insn, xas;
12392 rtx a_hi8 = NULL_RTX;
12394 if (avr_mem_flash_p (xop[0]))
12395 return false;
12397 if (!CONST_INT_P (xop[2]))
12398 return false;
12400 count = INTVAL (xop[2]);
12401 if (count <= 0)
12402 return false;
12404 a_src = XEXP (xop[1], 0);
12405 a_dest = XEXP (xop[0], 0);
12407 if (PSImode == GET_MODE (a_src))
12409 gcc_assert (as == ADDR_SPACE_MEMX);
12411 loop_mode = (count < 0x100) ? QImode : HImode;
12412 loop_reg = gen_rtx_REG (loop_mode, 24);
12413 emit_move_insn (loop_reg, gen_int_mode (count, loop_mode));
12415 addr1 = simplify_gen_subreg (HImode, a_src, PSImode, 0);
12416 a_hi8 = simplify_gen_subreg (QImode, a_src, PSImode, 2);
12418 else
12420 int segment = avr_addrspace[as].segment;
12422 if (segment
12423 && avr_n_flash > 1)
12425 a_hi8 = GEN_INT (segment);
12426 emit_move_insn (rampz_rtx, a_hi8 = copy_to_mode_reg (QImode, a_hi8));
12428 else if (!ADDR_SPACE_GENERIC_P (as))
12430 as = ADDR_SPACE_FLASH;
12433 addr1 = a_src;
12435 loop_mode = (count <= 0x100) ? QImode : HImode;
12436 loop_reg = copy_to_mode_reg (loop_mode, gen_int_mode (count, loop_mode));
12439 xas = GEN_INT (as);
12441 /* FIXME: Register allocator might come up with spill fails if it is left
12442 on its own. Thus, we allocate the pointer registers by hand:
12443 Z = source address
12444 X = destination address */
12446 emit_move_insn (lpm_addr_reg_rtx, addr1);
12447 emit_move_insn (gen_rtx_REG (HImode, REG_X), a_dest);
12449 /* FIXME: Register allocator does a bad job and might spill address
12450 register(s) inside the loop leading to additional move instruction
12451 to/from stack which could clobber tmp_reg. Thus, do *not* emit
12452 load and store as separate insns. Instead, we perform the copy
12453 by means of one monolithic insn. */
12455 gcc_assert (TMP_REGNO == LPM_REGNO);
12457 if (as != ADDR_SPACE_MEMX)
12459 /* Load instruction ([E]LPM or LD) is known at compile time:
12460 Do the copy-loop inline. */
12462 rtx (*fun) (rtx, rtx, rtx)
12463 = QImode == loop_mode ? gen_movmem_qi : gen_movmem_hi;
12465 insn = fun (xas, loop_reg, loop_reg);
12467 else
12469 rtx (*fun) (rtx, rtx)
12470 = QImode == loop_mode ? gen_movmemx_qi : gen_movmemx_hi;
12472 emit_move_insn (gen_rtx_REG (QImode, 23), a_hi8);
12474 insn = fun (xas, GEN_INT (avr_addr.rampz));
12477 set_mem_addr_space (SET_SRC (XVECEXP (insn, 0, 0)), as);
12478 emit_insn (insn);
12480 return true;
12484 /* Print assembler for movmem_qi, movmem_hi insns...
12485 $0 : Address Space
12486 $1, $2 : Loop register
12487 Z : Source address
12488 X : Destination address
12491 const char*
12492 avr_out_movmem (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
12494 addr_space_t as = (addr_space_t) INTVAL (op[0]);
12495 machine_mode loop_mode = GET_MODE (op[1]);
12496 bool sbiw_p = test_hard_reg_class (ADDW_REGS, op[1]);
12497 rtx xop[3];
12499 if (plen)
12500 *plen = 0;
12502 xop[0] = op[0];
12503 xop[1] = op[1];
12504 xop[2] = tmp_reg_rtx;
12506 /* Loop label */
12508 avr_asm_len ("0:", xop, plen, 0);
12510 /* Load with post-increment */
12512 switch (as)
12514 default:
12515 gcc_unreachable();
12517 case ADDR_SPACE_GENERIC:
12519 avr_asm_len ("ld %2,Z+", xop, plen, 1);
12520 break;
12522 case ADDR_SPACE_FLASH:
12524 if (AVR_HAVE_LPMX)
12525 avr_asm_len ("lpm %2,Z+", xop, plen, 1);
12526 else
12527 avr_asm_len ("lpm" CR_TAB
12528 "adiw r30,1", xop, plen, 2);
12529 break;
12531 case ADDR_SPACE_FLASH1:
12532 case ADDR_SPACE_FLASH2:
12533 case ADDR_SPACE_FLASH3:
12534 case ADDR_SPACE_FLASH4:
12535 case ADDR_SPACE_FLASH5:
12537 if (AVR_HAVE_ELPMX)
12538 avr_asm_len ("elpm %2,Z+", xop, plen, 1);
12539 else
12540 avr_asm_len ("elpm" CR_TAB
12541 "adiw r30,1", xop, plen, 2);
12542 break;
12545 /* Store with post-increment */
12547 avr_asm_len ("st X+,%2", xop, plen, 1);
12549 /* Decrement loop-counter and set Z-flag */
12551 if (QImode == loop_mode)
12553 avr_asm_len ("dec %1", xop, plen, 1);
12555 else if (sbiw_p)
12557 avr_asm_len ("sbiw %1,1", xop, plen, 1);
12559 else
12561 avr_asm_len ("subi %A1,1" CR_TAB
12562 "sbci %B1,0", xop, plen, 2);
12565 /* Loop until zero */
12567 return avr_asm_len ("brne 0b", xop, plen, 1);
12572 /* Helper for __builtin_avr_delay_cycles */
12574 static rtx
12575 avr_mem_clobber (void)
12577 rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
12578 MEM_VOLATILE_P (mem) = 1;
12579 return mem;
12582 static void
12583 avr_expand_delay_cycles (rtx operands0)
12585 unsigned HOST_WIDE_INT cycles = UINTVAL (operands0) & GET_MODE_MASK (SImode);
12586 unsigned HOST_WIDE_INT cycles_used;
12587 unsigned HOST_WIDE_INT loop_count;
12589 if (IN_RANGE (cycles, 83886082, 0xFFFFFFFF))
12591 loop_count = ((cycles - 9) / 6) + 1;
12592 cycles_used = ((loop_count - 1) * 6) + 9;
12593 emit_insn (gen_delay_cycles_4 (gen_int_mode (loop_count, SImode),
12594 avr_mem_clobber()));
12595 cycles -= cycles_used;
12598 if (IN_RANGE (cycles, 262145, 83886081))
12600 loop_count = ((cycles - 7) / 5) + 1;
12601 if (loop_count > 0xFFFFFF)
12602 loop_count = 0xFFFFFF;
12603 cycles_used = ((loop_count - 1) * 5) + 7;
12604 emit_insn (gen_delay_cycles_3 (gen_int_mode (loop_count, SImode),
12605 avr_mem_clobber()));
12606 cycles -= cycles_used;
12609 if (IN_RANGE (cycles, 768, 262144))
12611 loop_count = ((cycles - 5) / 4) + 1;
12612 if (loop_count > 0xFFFF)
12613 loop_count = 0xFFFF;
12614 cycles_used = ((loop_count - 1) * 4) + 5;
12615 emit_insn (gen_delay_cycles_2 (gen_int_mode (loop_count, HImode),
12616 avr_mem_clobber()));
12617 cycles -= cycles_used;
12620 if (IN_RANGE (cycles, 6, 767))
12622 loop_count = cycles / 3;
12623 if (loop_count > 255)
12624 loop_count = 255;
12625 cycles_used = loop_count * 3;
12626 emit_insn (gen_delay_cycles_1 (gen_int_mode (loop_count, QImode),
12627 avr_mem_clobber()));
12628 cycles -= cycles_used;
12631 while (cycles >= 2)
12633 emit_insn (gen_nopv (GEN_INT(2)));
12634 cycles -= 2;
12637 if (cycles == 1)
12639 emit_insn (gen_nopv (GEN_INT(1)));
12640 cycles--;
12645 /* Compute the image of x under f, i.e. perform x --> f(x) */
12647 static int
12648 avr_map (unsigned int f, int x)
12650 return x < 8 ? (f >> (4 * x)) & 0xf : 0;
12654 /* Return some metrics of map A. */
12656 enum
12658 /* Number of fixed points in { 0 ... 7 } */
12659 MAP_FIXED_0_7,
12661 /* Size of preimage of non-fixed points in { 0 ... 7 } */
12662 MAP_NONFIXED_0_7,
12664 /* Mask representing the fixed points in { 0 ... 7 } */
12665 MAP_MASK_FIXED_0_7,
12667 /* Size of the preimage of { 0 ... 7 } */
12668 MAP_PREIMAGE_0_7,
12670 /* Mask that represents the preimage of { f } */
12671 MAP_MASK_PREIMAGE_F
12674 static unsigned
12675 avr_map_metric (unsigned int a, int mode)
12677 unsigned i, metric = 0;
12679 for (i = 0; i < 8; i++)
12681 unsigned ai = avr_map (a, i);
12683 if (mode == MAP_FIXED_0_7)
12684 metric += ai == i;
12685 else if (mode == MAP_NONFIXED_0_7)
12686 metric += ai < 8 && ai != i;
12687 else if (mode == MAP_MASK_FIXED_0_7)
12688 metric |= ((unsigned) (ai == i)) << i;
12689 else if (mode == MAP_PREIMAGE_0_7)
12690 metric += ai < 8;
12691 else if (mode == MAP_MASK_PREIMAGE_F)
12692 metric |= ((unsigned) (ai == 0xf)) << i;
12693 else
12694 gcc_unreachable();
12697 return metric;
12701 /* Return true if IVAL has a 0xf in its hexadecimal representation
12702 and false, otherwise. Only nibbles 0..7 are taken into account.
12703 Used as constraint helper for C0f and Cxf. */
12705 bool
12706 avr_has_nibble_0xf (rtx ival)
12708 unsigned int map = UINTVAL (ival) & GET_MODE_MASK (SImode);
12709 return 0 != avr_map_metric (map, MAP_MASK_PREIMAGE_F);
12713 /* We have a set of bits that are mapped by a function F.
12714 Try to decompose F by means of a second function G so that
12716 F = F o G^-1 o G
12720 cost (F o G^-1) + cost (G) < cost (F)
12722 Example: Suppose builtin insert_bits supplies us with the map
12723 F = 0x3210ffff. Instead of doing 4 bit insertions to get the high
12724 nibble of the result, we can just as well rotate the bits before inserting
12725 them and use the map 0x7654ffff which is cheaper than the original map.
12726 For this example G = G^-1 = 0x32107654 and F o G^-1 = 0x7654ffff. */
12728 typedef struct
12730 /* tree code of binary function G */
12731 enum tree_code code;
12733 /* The constant second argument of G */
12734 int arg;
12736 /* G^-1, the inverse of G (*, arg) */
12737 unsigned ginv;
12739 /* The cost of appplying G (*, arg) */
12740 int cost;
12742 /* The composition F o G^-1 (*, arg) for some function F */
12743 unsigned int map;
12745 /* For debug purpose only */
12746 const char *str;
12747 } avr_map_op_t;
12749 static const avr_map_op_t avr_map_op[] =
12751 { LROTATE_EXPR, 0, 0x76543210, 0, 0, "id" },
12752 { LROTATE_EXPR, 1, 0x07654321, 2, 0, "<<<" },
12753 { LROTATE_EXPR, 2, 0x10765432, 4, 0, "<<<" },
12754 { LROTATE_EXPR, 3, 0x21076543, 4, 0, "<<<" },
12755 { LROTATE_EXPR, 4, 0x32107654, 1, 0, "<<<" },
12756 { LROTATE_EXPR, 5, 0x43210765, 3, 0, "<<<" },
12757 { LROTATE_EXPR, 6, 0x54321076, 5, 0, "<<<" },
12758 { LROTATE_EXPR, 7, 0x65432107, 3, 0, "<<<" },
12759 { RSHIFT_EXPR, 1, 0x6543210c, 1, 0, ">>" },
12760 { RSHIFT_EXPR, 1, 0x7543210c, 1, 0, ">>" },
12761 { RSHIFT_EXPR, 2, 0x543210cc, 2, 0, ">>" },
12762 { RSHIFT_EXPR, 2, 0x643210cc, 2, 0, ">>" },
12763 { RSHIFT_EXPR, 2, 0x743210cc, 2, 0, ">>" },
12764 { LSHIFT_EXPR, 1, 0xc7654321, 1, 0, "<<" },
12765 { LSHIFT_EXPR, 2, 0xcc765432, 2, 0, "<<" }
12769 /* Try to decompose F as F = (F o G^-1) o G as described above.
12770 The result is a struct representing F o G^-1 and G.
12771 If result.cost < 0 then such a decomposition does not exist. */
12773 static avr_map_op_t
12774 avr_map_decompose (unsigned int f, const avr_map_op_t *g, bool val_const_p)
12776 int i;
12777 bool val_used_p = 0 != avr_map_metric (f, MAP_MASK_PREIMAGE_F);
12778 avr_map_op_t f_ginv = *g;
12779 unsigned int ginv = g->ginv;
12781 f_ginv.cost = -1;
12783 /* Step 1: Computing F o G^-1 */
12785 for (i = 7; i >= 0; i--)
12787 int x = avr_map (f, i);
12789 if (x <= 7)
12791 x = avr_map (ginv, x);
12793 /* The bit is no element of the image of G: no avail (cost = -1) */
12795 if (x > 7)
12796 return f_ginv;
12799 f_ginv.map = (f_ginv.map << 4) + x;
12802 /* Step 2: Compute the cost of the operations.
12803 The overall cost of doing an operation prior to the insertion is
12804 the cost of the insertion plus the cost of the operation. */
12806 /* Step 2a: Compute cost of F o G^-1 */
12808 if (0 == avr_map_metric (f_ginv.map, MAP_NONFIXED_0_7))
12810 /* The mapping consists only of fixed points and can be folded
12811 to AND/OR logic in the remainder. Reasonable cost is 3. */
12813 f_ginv.cost = 2 + (val_used_p && !val_const_p);
12815 else
12817 rtx xop[4];
12819 /* Get the cost of the insn by calling the output worker with some
12820 fake values. Mimic effect of reloading xop[3]: Unused operands
12821 are mapped to 0 and used operands are reloaded to xop[0]. */
12823 xop[0] = all_regs_rtx[24];
12824 xop[1] = gen_int_mode (f_ginv.map, SImode);
12825 xop[2] = all_regs_rtx[25];
12826 xop[3] = val_used_p ? xop[0] : const0_rtx;
12828 avr_out_insert_bits (xop, &f_ginv.cost);
12830 f_ginv.cost += val_const_p && val_used_p ? 1 : 0;
12833 /* Step 2b: Add cost of G */
12835 f_ginv.cost += g->cost;
12837 if (avr_log.builtin)
12838 avr_edump (" %s%d=%d", g->str, g->arg, f_ginv.cost);
12840 return f_ginv;
12844 /* Insert bits from XOP[1] into XOP[0] according to MAP.
12845 XOP[0] and XOP[1] don't overlap.
12846 If FIXP_P = true: Move all bits according to MAP using BLD/BST sequences.
12847 If FIXP_P = false: Just move the bit if its position in the destination
12848 is different to its source position. */
12850 static void
12851 avr_move_bits (rtx *xop, unsigned int map, bool fixp_p, int *plen)
12853 int bit_dest, b;
12855 /* T-flag contains this bit of the source, i.e. of XOP[1] */
12856 int t_bit_src = -1;
12858 /* We order the operations according to the requested source bit b. */
12860 for (b = 0; b < 8; b++)
12861 for (bit_dest = 0; bit_dest < 8; bit_dest++)
12863 int bit_src = avr_map (map, bit_dest);
12865 if (b != bit_src
12866 || bit_src >= 8
12867 /* Same position: No need to copy as requested by FIXP_P. */
12868 || (bit_dest == bit_src && !fixp_p))
12869 continue;
12871 if (t_bit_src != bit_src)
12873 /* Source bit is not yet in T: Store it to T. */
12875 t_bit_src = bit_src;
12877 xop[3] = GEN_INT (bit_src);
12878 avr_asm_len ("bst %T1%T3", xop, plen, 1);
12881 /* Load destination bit with T. */
12883 xop[3] = GEN_INT (bit_dest);
12884 avr_asm_len ("bld %T0%T3", xop, plen, 1);
12889 /* PLEN == 0: Print assembler code for `insert_bits'.
12890 PLEN != 0: Compute code length in bytes.
12892 OP[0]: Result
12893 OP[1]: The mapping composed of nibbles. If nibble no. N is
12894 0: Bit N of result is copied from bit OP[2].0
12895 ... ...
12896 7: Bit N of result is copied from bit OP[2].7
12897 0xf: Bit N of result is copied from bit OP[3].N
12898 OP[2]: Bits to be inserted
12899 OP[3]: Target value */
12901 const char*
12902 avr_out_insert_bits (rtx *op, int *plen)
12904 unsigned int map = UINTVAL (op[1]) & GET_MODE_MASK (SImode);
12905 unsigned mask_fixed;
12906 bool fixp_p = true;
12907 rtx xop[4];
12909 xop[0] = op[0];
12910 xop[1] = op[2];
12911 xop[2] = op[3];
12913 gcc_assert (REG_P (xop[2]) || CONST_INT_P (xop[2]));
12915 if (plen)
12916 *plen = 0;
12917 else if (flag_print_asm_name)
12918 fprintf (asm_out_file, ASM_COMMENT_START "map = 0x%08x\n", map);
12920 /* If MAP has fixed points it might be better to initialize the result
12921 with the bits to be inserted instead of moving all bits by hand. */
12923 mask_fixed = avr_map_metric (map, MAP_MASK_FIXED_0_7);
12925 if (REGNO (xop[0]) == REGNO (xop[1]))
12927 /* Avoid early-clobber conflicts */
12929 avr_asm_len ("mov __tmp_reg__,%1", xop, plen, 1);
12930 xop[1] = tmp_reg_rtx;
12931 fixp_p = false;
12934 if (avr_map_metric (map, MAP_MASK_PREIMAGE_F))
12936 /* XOP[2] is used and reloaded to XOP[0] already */
12938 int n_fix = 0, n_nofix = 0;
12940 gcc_assert (REG_P (xop[2]));
12942 /* Get the code size of the bit insertions; once with all bits
12943 moved and once with fixed points omitted. */
12945 avr_move_bits (xop, map, true, &n_fix);
12946 avr_move_bits (xop, map, false, &n_nofix);
12948 if (fixp_p && n_fix - n_nofix > 3)
12950 xop[3] = gen_int_mode (~mask_fixed, QImode);
12952 avr_asm_len ("eor %0,%1" CR_TAB
12953 "andi %0,%3" CR_TAB
12954 "eor %0,%1", xop, plen, 3);
12955 fixp_p = false;
12958 else
12960 /* XOP[2] is unused */
12962 if (fixp_p && mask_fixed)
12964 avr_asm_len ("mov %0,%1", xop, plen, 1);
12965 fixp_p = false;
12969 /* Move/insert remaining bits. */
12971 avr_move_bits (xop, map, fixp_p, plen);
12973 return "";
12977 /* IDs for all the AVR builtins. */
12979 enum avr_builtin_id
12981 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
12982 AVR_BUILTIN_ ## NAME,
12983 #include "builtins.def"
12984 #undef DEF_BUILTIN
12986 AVR_BUILTIN_COUNT
12989 struct GTY(()) avr_builtin_description
12991 enum insn_code icode;
12992 int n_args;
12993 tree fndecl;
12997 /* Notice that avr_bdesc[] and avr_builtin_id are initialized in such a way
12998 that a built-in's ID can be used to access the built-in by means of
12999 avr_bdesc[ID] */
13001 static GTY(()) struct avr_builtin_description
13002 avr_bdesc[AVR_BUILTIN_COUNT] =
13004 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE, LIBNAME) \
13005 { (enum insn_code) CODE_FOR_ ## ICODE, N_ARGS, NULL_TREE },
13006 #include "builtins.def"
13007 #undef DEF_BUILTIN
13011 /* Implement `TARGET_BUILTIN_DECL'. */
13013 static tree
13014 avr_builtin_decl (unsigned id, bool initialize_p ATTRIBUTE_UNUSED)
13016 if (id < AVR_BUILTIN_COUNT)
13017 return avr_bdesc[id].fndecl;
13019 return error_mark_node;
13023 static void
13024 avr_init_builtin_int24 (void)
13026 tree int24_type = make_signed_type (GET_MODE_BITSIZE (PSImode));
13027 tree uint24_type = make_unsigned_type (GET_MODE_BITSIZE (PSImode));
13029 lang_hooks.types.register_builtin_type (int24_type, "__int24");
13030 lang_hooks.types.register_builtin_type (uint24_type, "__uint24");
13034 /* Implement `TARGET_INIT_BUILTINS' */
13035 /* Set up all builtin functions for this target. */
13037 static void
13038 avr_init_builtins (void)
13040 tree void_ftype_void
13041 = build_function_type_list (void_type_node, NULL_TREE);
13042 tree uchar_ftype_uchar
13043 = build_function_type_list (unsigned_char_type_node,
13044 unsigned_char_type_node,
13045 NULL_TREE);
13046 tree uint_ftype_uchar_uchar
13047 = build_function_type_list (unsigned_type_node,
13048 unsigned_char_type_node,
13049 unsigned_char_type_node,
13050 NULL_TREE);
13051 tree int_ftype_char_char
13052 = build_function_type_list (integer_type_node,
13053 char_type_node,
13054 char_type_node,
13055 NULL_TREE);
13056 tree int_ftype_char_uchar
13057 = build_function_type_list (integer_type_node,
13058 char_type_node,
13059 unsigned_char_type_node,
13060 NULL_TREE);
13061 tree void_ftype_ulong
13062 = build_function_type_list (void_type_node,
13063 long_unsigned_type_node,
13064 NULL_TREE);
13066 tree uchar_ftype_ulong_uchar_uchar
13067 = build_function_type_list (unsigned_char_type_node,
13068 long_unsigned_type_node,
13069 unsigned_char_type_node,
13070 unsigned_char_type_node,
13071 NULL_TREE);
13073 tree const_memx_void_node
13074 = build_qualified_type (void_type_node,
13075 TYPE_QUAL_CONST
13076 | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_MEMX));
13078 tree const_memx_ptr_type_node
13079 = build_pointer_type_for_mode (const_memx_void_node, PSImode, false);
13081 tree char_ftype_const_memx_ptr
13082 = build_function_type_list (char_type_node,
13083 const_memx_ptr_type_node,
13084 NULL);
13086 #define ITYP(T) \
13087 lang_hooks.types.type_for_size (TYPE_PRECISION (T), TYPE_UNSIGNED (T))
13089 #define FX_FTYPE_FX(fx) \
13090 tree fx##r_ftype_##fx##r \
13091 = build_function_type_list (node_##fx##r, node_##fx##r, NULL); \
13092 tree fx##k_ftype_##fx##k \
13093 = build_function_type_list (node_##fx##k, node_##fx##k, NULL)
13095 #define FX_FTYPE_FX_INT(fx) \
13096 tree fx##r_ftype_##fx##r_int \
13097 = build_function_type_list (node_##fx##r, node_##fx##r, \
13098 integer_type_node, NULL); \
13099 tree fx##k_ftype_##fx##k_int \
13100 = build_function_type_list (node_##fx##k, node_##fx##k, \
13101 integer_type_node, NULL)
13103 #define INT_FTYPE_FX(fx) \
13104 tree int_ftype_##fx##r \
13105 = build_function_type_list (integer_type_node, node_##fx##r, NULL); \
13106 tree int_ftype_##fx##k \
13107 = build_function_type_list (integer_type_node, node_##fx##k, NULL)
13109 #define INTX_FTYPE_FX(fx) \
13110 tree int##fx##r_ftype_##fx##r \
13111 = build_function_type_list (ITYP (node_##fx##r), node_##fx##r, NULL); \
13112 tree int##fx##k_ftype_##fx##k \
13113 = build_function_type_list (ITYP (node_##fx##k), node_##fx##k, NULL)
13115 #define FX_FTYPE_INTX(fx) \
13116 tree fx##r_ftype_int##fx##r \
13117 = build_function_type_list (node_##fx##r, ITYP (node_##fx##r), NULL); \
13118 tree fx##k_ftype_int##fx##k \
13119 = build_function_type_list (node_##fx##k, ITYP (node_##fx##k), NULL)
13121 tree node_hr = short_fract_type_node;
13122 tree node_nr = fract_type_node;
13123 tree node_lr = long_fract_type_node;
13124 tree node_llr = long_long_fract_type_node;
13126 tree node_uhr = unsigned_short_fract_type_node;
13127 tree node_unr = unsigned_fract_type_node;
13128 tree node_ulr = unsigned_long_fract_type_node;
13129 tree node_ullr = unsigned_long_long_fract_type_node;
13131 tree node_hk = short_accum_type_node;
13132 tree node_nk = accum_type_node;
13133 tree node_lk = long_accum_type_node;
13134 tree node_llk = long_long_accum_type_node;
13136 tree node_uhk = unsigned_short_accum_type_node;
13137 tree node_unk = unsigned_accum_type_node;
13138 tree node_ulk = unsigned_long_accum_type_node;
13139 tree node_ullk = unsigned_long_long_accum_type_node;
13142 /* For absfx builtins. */
13144 FX_FTYPE_FX (h);
13145 FX_FTYPE_FX (n);
13146 FX_FTYPE_FX (l);
13147 FX_FTYPE_FX (ll);
13149 /* For roundfx builtins. */
13151 FX_FTYPE_FX_INT (h);
13152 FX_FTYPE_FX_INT (n);
13153 FX_FTYPE_FX_INT (l);
13154 FX_FTYPE_FX_INT (ll);
13156 FX_FTYPE_FX_INT (uh);
13157 FX_FTYPE_FX_INT (un);
13158 FX_FTYPE_FX_INT (ul);
13159 FX_FTYPE_FX_INT (ull);
13161 /* For countlsfx builtins. */
13163 INT_FTYPE_FX (h);
13164 INT_FTYPE_FX (n);
13165 INT_FTYPE_FX (l);
13166 INT_FTYPE_FX (ll);
13168 INT_FTYPE_FX (uh);
13169 INT_FTYPE_FX (un);
13170 INT_FTYPE_FX (ul);
13171 INT_FTYPE_FX (ull);
13173 /* For bitsfx builtins. */
13175 INTX_FTYPE_FX (h);
13176 INTX_FTYPE_FX (n);
13177 INTX_FTYPE_FX (l);
13178 INTX_FTYPE_FX (ll);
13180 INTX_FTYPE_FX (uh);
13181 INTX_FTYPE_FX (un);
13182 INTX_FTYPE_FX (ul);
13183 INTX_FTYPE_FX (ull);
13185 /* For fxbits builtins. */
13187 FX_FTYPE_INTX (h);
13188 FX_FTYPE_INTX (n);
13189 FX_FTYPE_INTX (l);
13190 FX_FTYPE_INTX (ll);
13192 FX_FTYPE_INTX (uh);
13193 FX_FTYPE_INTX (un);
13194 FX_FTYPE_INTX (ul);
13195 FX_FTYPE_INTX (ull);
13198 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
13200 int id = AVR_BUILTIN_ ## NAME; \
13201 const char *Name = "__builtin_avr_" #NAME; \
13202 char *name = (char*) alloca (1 + strlen (Name)); \
13204 gcc_assert (id < AVR_BUILTIN_COUNT); \
13205 avr_bdesc[id].fndecl \
13206 = add_builtin_function (avr_tolower (name, Name), TYPE, id, \
13207 BUILT_IN_MD, LIBNAME, NULL_TREE); \
13209 #include "builtins.def"
13210 #undef DEF_BUILTIN
13212 avr_init_builtin_int24 ();
13216 /* Subroutine of avr_expand_builtin to expand vanilla builtins
13217 with non-void result and 1 ... 3 arguments. */
13219 static rtx
13220 avr_default_expand_builtin (enum insn_code icode, tree exp, rtx target)
13222 rtx pat, xop[3];
13223 int n, n_args = call_expr_nargs (exp);
13224 machine_mode tmode = insn_data[icode].operand[0].mode;
13226 gcc_assert (n_args >= 1 && n_args <= 3);
13228 if (target == NULL_RTX
13229 || GET_MODE (target) != tmode
13230 || !insn_data[icode].operand[0].predicate (target, tmode))
13232 target = gen_reg_rtx (tmode);
13235 for (n = 0; n < n_args; n++)
13237 tree arg = CALL_EXPR_ARG (exp, n);
13238 rtx op = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
13239 machine_mode opmode = GET_MODE (op);
13240 machine_mode mode = insn_data[icode].operand[n+1].mode;
13242 if ((opmode == SImode || opmode == VOIDmode) && mode == HImode)
13244 opmode = HImode;
13245 op = gen_lowpart (HImode, op);
13248 /* In case the insn wants input operands in modes different from
13249 the result, abort. */
13251 gcc_assert (opmode == mode || opmode == VOIDmode);
13253 if (!insn_data[icode].operand[n+1].predicate (op, mode))
13254 op = copy_to_mode_reg (mode, op);
13256 xop[n] = op;
13259 switch (n_args)
13261 case 1: pat = GEN_FCN (icode) (target, xop[0]); break;
13262 case 2: pat = GEN_FCN (icode) (target, xop[0], xop[1]); break;
13263 case 3: pat = GEN_FCN (icode) (target, xop[0], xop[1], xop[2]); break;
13265 default:
13266 gcc_unreachable();
13269 if (pat == NULL_RTX)
13270 return NULL_RTX;
13272 emit_insn (pat);
13274 return target;
13278 /* Implement `TARGET_EXPAND_BUILTIN'. */
13279 /* Expand an expression EXP that calls a built-in function,
13280 with result going to TARGET if that's convenient
13281 (and in mode MODE if that's convenient).
13282 SUBTARGET may be used as the target for computing one of EXP's operands.
13283 IGNORE is nonzero if the value is to be ignored. */
13285 static rtx
13286 avr_expand_builtin (tree exp, rtx target,
13287 rtx subtarget ATTRIBUTE_UNUSED,
13288 machine_mode mode ATTRIBUTE_UNUSED,
13289 int ignore)
13291 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
13292 const char *bname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
13293 unsigned int id = DECL_FUNCTION_CODE (fndecl);
13294 const struct avr_builtin_description *d = &avr_bdesc[id];
13295 tree arg0;
13296 rtx op0;
13298 gcc_assert (id < AVR_BUILTIN_COUNT);
13300 switch (id)
13302 case AVR_BUILTIN_NOP:
13303 emit_insn (gen_nopv (GEN_INT(1)));
13304 return 0;
13306 case AVR_BUILTIN_DELAY_CYCLES:
13308 arg0 = CALL_EXPR_ARG (exp, 0);
13309 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
13311 if (!CONST_INT_P (op0))
13312 error ("%s expects a compile time integer constant", bname);
13313 else
13314 avr_expand_delay_cycles (op0);
13316 return NULL_RTX;
13319 case AVR_BUILTIN_INSERT_BITS:
13321 arg0 = CALL_EXPR_ARG (exp, 0);
13322 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
13324 if (!CONST_INT_P (op0))
13326 error ("%s expects a compile time long integer constant"
13327 " as first argument", bname);
13328 return target;
13331 break;
13334 case AVR_BUILTIN_ROUNDHR: case AVR_BUILTIN_ROUNDUHR:
13335 case AVR_BUILTIN_ROUNDR: case AVR_BUILTIN_ROUNDUR:
13336 case AVR_BUILTIN_ROUNDLR: case AVR_BUILTIN_ROUNDULR:
13337 case AVR_BUILTIN_ROUNDLLR: case AVR_BUILTIN_ROUNDULLR:
13339 case AVR_BUILTIN_ROUNDHK: case AVR_BUILTIN_ROUNDUHK:
13340 case AVR_BUILTIN_ROUNDK: case AVR_BUILTIN_ROUNDUK:
13341 case AVR_BUILTIN_ROUNDLK: case AVR_BUILTIN_ROUNDULK:
13342 case AVR_BUILTIN_ROUNDLLK: case AVR_BUILTIN_ROUNDULLK:
13344 /* Warn about odd rounding. Rounding points >= FBIT will have
13345 no effect. */
13347 if (TREE_CODE (CALL_EXPR_ARG (exp, 1)) != INTEGER_CST)
13348 break;
13350 int rbit = (int) TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1));
13352 if (rbit >= (int) GET_MODE_FBIT (mode))
13354 warning (OPT_Wextra, "rounding to %d bits has no effect for "
13355 "fixed-point value with %d fractional bits",
13356 rbit, GET_MODE_FBIT (mode));
13358 return expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX, mode,
13359 EXPAND_NORMAL);
13361 else if (rbit <= - (int) GET_MODE_IBIT (mode))
13363 warning (0, "rounding result will always be 0");
13364 return CONST0_RTX (mode);
13367 /* The rounding points RP satisfies now: -IBIT < RP < FBIT.
13369 TR 18037 only specifies results for RP > 0. However, the
13370 remaining cases of -IBIT < RP <= 0 can easily be supported
13371 without any additional overhead. */
13373 break; /* round */
13376 /* No fold found and no insn: Call support function from libgcc. */
13378 if (d->icode == CODE_FOR_nothing
13379 && DECL_ASSEMBLER_NAME (get_callee_fndecl (exp)) != NULL_TREE)
13381 return expand_call (exp, target, ignore);
13384 /* No special treatment needed: vanilla expand. */
13386 gcc_assert (d->icode != CODE_FOR_nothing);
13387 gcc_assert (d->n_args == call_expr_nargs (exp));
13389 if (d->n_args == 0)
13391 emit_insn ((GEN_FCN (d->icode)) (target));
13392 return NULL_RTX;
13395 return avr_default_expand_builtin (d->icode, exp, target);
13399 /* Helper for `avr_fold_builtin' that folds absfx (FIXED_CST). */
13401 static tree
13402 avr_fold_absfx (tree tval)
13404 if (FIXED_CST != TREE_CODE (tval))
13405 return NULL_TREE;
13407 /* Our fixed-points have no padding: Use double_int payload directly. */
13409 FIXED_VALUE_TYPE fval = TREE_FIXED_CST (tval);
13410 unsigned int bits = GET_MODE_BITSIZE (fval.mode);
13411 double_int ival = fval.data.sext (bits);
13413 if (!ival.is_negative())
13414 return tval;
13416 /* ISO/IEC TR 18037, 7.18a.6.2: The absfx functions are saturating. */
13418 fval.data = (ival == double_int::min_value (bits, false).sext (bits))
13419 ? double_int::max_value (bits, false)
13420 : -ival;
13422 return build_fixed (TREE_TYPE (tval), fval);
13426 /* Implement `TARGET_FOLD_BUILTIN'. */
13428 static tree
13429 avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg,
13430 bool ignore ATTRIBUTE_UNUSED)
13432 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
13433 tree val_type = TREE_TYPE (TREE_TYPE (fndecl));
13435 if (!optimize)
13436 return NULL_TREE;
13438 switch (fcode)
13440 default:
13441 break;
13443 case AVR_BUILTIN_SWAP:
13445 return fold_build2 (LROTATE_EXPR, val_type, arg[0],
13446 build_int_cst (val_type, 4));
13449 case AVR_BUILTIN_ABSHR:
13450 case AVR_BUILTIN_ABSR:
13451 case AVR_BUILTIN_ABSLR:
13452 case AVR_BUILTIN_ABSLLR:
13454 case AVR_BUILTIN_ABSHK:
13455 case AVR_BUILTIN_ABSK:
13456 case AVR_BUILTIN_ABSLK:
13457 case AVR_BUILTIN_ABSLLK:
13458 /* GCC is not good with folding ABS for fixed-point. Do it by hand. */
13460 return avr_fold_absfx (arg[0]);
13462 case AVR_BUILTIN_BITSHR: case AVR_BUILTIN_HRBITS:
13463 case AVR_BUILTIN_BITSHK: case AVR_BUILTIN_HKBITS:
13464 case AVR_BUILTIN_BITSUHR: case AVR_BUILTIN_UHRBITS:
13465 case AVR_BUILTIN_BITSUHK: case AVR_BUILTIN_UHKBITS:
13467 case AVR_BUILTIN_BITSR: case AVR_BUILTIN_RBITS:
13468 case AVR_BUILTIN_BITSK: case AVR_BUILTIN_KBITS:
13469 case AVR_BUILTIN_BITSUR: case AVR_BUILTIN_URBITS:
13470 case AVR_BUILTIN_BITSUK: case AVR_BUILTIN_UKBITS:
13472 case AVR_BUILTIN_BITSLR: case AVR_BUILTIN_LRBITS:
13473 case AVR_BUILTIN_BITSLK: case AVR_BUILTIN_LKBITS:
13474 case AVR_BUILTIN_BITSULR: case AVR_BUILTIN_ULRBITS:
13475 case AVR_BUILTIN_BITSULK: case AVR_BUILTIN_ULKBITS:
13477 case AVR_BUILTIN_BITSLLR: case AVR_BUILTIN_LLRBITS:
13478 case AVR_BUILTIN_BITSLLK: case AVR_BUILTIN_LLKBITS:
13479 case AVR_BUILTIN_BITSULLR: case AVR_BUILTIN_ULLRBITS:
13480 case AVR_BUILTIN_BITSULLK: case AVR_BUILTIN_ULLKBITS:
13482 gcc_assert (TYPE_PRECISION (val_type)
13483 == TYPE_PRECISION (TREE_TYPE (arg[0])));
13485 return build1 (VIEW_CONVERT_EXPR, val_type, arg[0]);
13487 case AVR_BUILTIN_INSERT_BITS:
13489 tree tbits = arg[1];
13490 tree tval = arg[2];
13491 tree tmap;
13492 tree map_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
13493 unsigned int map;
13494 bool changed = false;
13495 unsigned i;
13496 avr_map_op_t best_g;
13498 if (TREE_CODE (arg[0]) != INTEGER_CST)
13500 /* No constant as first argument: Don't fold this and run into
13501 error in avr_expand_builtin. */
13503 break;
13506 tmap = wide_int_to_tree (map_type, arg[0]);
13507 map = TREE_INT_CST_LOW (tmap);
13509 if (TREE_CODE (tval) != INTEGER_CST
13510 && 0 == avr_map_metric (map, MAP_MASK_PREIMAGE_F))
13512 /* There are no F in the map, i.e. 3rd operand is unused.
13513 Replace that argument with some constant to render
13514 respective input unused. */
13516 tval = build_int_cst (val_type, 0);
13517 changed = true;
13520 if (TREE_CODE (tbits) != INTEGER_CST
13521 && 0 == avr_map_metric (map, MAP_PREIMAGE_0_7))
13523 /* Similar for the bits to be inserted. If they are unused,
13524 we can just as well pass 0. */
13526 tbits = build_int_cst (val_type, 0);
13529 if (TREE_CODE (tbits) == INTEGER_CST)
13531 /* Inserting bits known at compile time is easy and can be
13532 performed by AND and OR with appropriate masks. */
13534 int bits = TREE_INT_CST_LOW (tbits);
13535 int mask_ior = 0, mask_and = 0xff;
13537 for (i = 0; i < 8; i++)
13539 int mi = avr_map (map, i);
13541 if (mi < 8)
13543 if (bits & (1 << mi)) mask_ior |= (1 << i);
13544 else mask_and &= ~(1 << i);
13548 tval = fold_build2 (BIT_IOR_EXPR, val_type, tval,
13549 build_int_cst (val_type, mask_ior));
13550 return fold_build2 (BIT_AND_EXPR, val_type, tval,
13551 build_int_cst (val_type, mask_and));
13554 if (changed)
13555 return build_call_expr (fndecl, 3, tmap, tbits, tval);
13557 /* If bits don't change their position we can use vanilla logic
13558 to merge the two arguments. */
13560 if (0 == avr_map_metric (map, MAP_NONFIXED_0_7))
13562 int mask_f = avr_map_metric (map, MAP_MASK_PREIMAGE_F);
13563 tree tres, tmask = build_int_cst (val_type, mask_f ^ 0xff);
13565 tres = fold_build2 (BIT_XOR_EXPR, val_type, tbits, tval);
13566 tres = fold_build2 (BIT_AND_EXPR, val_type, tres, tmask);
13567 return fold_build2 (BIT_XOR_EXPR, val_type, tres, tval);
13570 /* Try to decomposing map to reduce overall cost. */
13572 if (avr_log.builtin)
13573 avr_edump ("\n%?: %x\n%?: ROL cost: ", map);
13575 best_g = avr_map_op[0];
13576 best_g.cost = 1000;
13578 for (i = 0; i < sizeof (avr_map_op) / sizeof (*avr_map_op); i++)
13580 avr_map_op_t g
13581 = avr_map_decompose (map, avr_map_op + i,
13582 TREE_CODE (tval) == INTEGER_CST);
13584 if (g.cost >= 0 && g.cost < best_g.cost)
13585 best_g = g;
13588 if (avr_log.builtin)
13589 avr_edump ("\n");
13591 if (best_g.arg == 0)
13592 /* No optimization found */
13593 break;
13595 /* Apply operation G to the 2nd argument. */
13597 if (avr_log.builtin)
13598 avr_edump ("%?: using OP(%s%d, %x) cost %d\n",
13599 best_g.str, best_g.arg, best_g.map, best_g.cost);
13601 /* Do right-shifts arithmetically: They copy the MSB instead of
13602 shifting in a non-usable value (0) as with logic right-shift. */
13604 tbits = fold_convert (signed_char_type_node, tbits);
13605 tbits = fold_build2 (best_g.code, signed_char_type_node, tbits,
13606 build_int_cst (val_type, best_g.arg));
13607 tbits = fold_convert (val_type, tbits);
13609 /* Use map o G^-1 instead of original map to undo the effect of G. */
13611 tmap = wide_int_to_tree (map_type, best_g.map);
13613 return build_call_expr (fndecl, 3, tmap, tbits, tval);
13614 } /* AVR_BUILTIN_INSERT_BITS */
13617 return NULL_TREE;
13622 /* Initialize the GCC target structure. */
13624 #undef TARGET_ASM_ALIGNED_HI_OP
13625 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
13626 #undef TARGET_ASM_ALIGNED_SI_OP
13627 #define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
13628 #undef TARGET_ASM_UNALIGNED_HI_OP
13629 #define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
13630 #undef TARGET_ASM_UNALIGNED_SI_OP
13631 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
13632 #undef TARGET_ASM_INTEGER
13633 #define TARGET_ASM_INTEGER avr_assemble_integer
13634 #undef TARGET_ASM_FILE_START
13635 #define TARGET_ASM_FILE_START avr_file_start
13636 #undef TARGET_ASM_FILE_END
13637 #define TARGET_ASM_FILE_END avr_file_end
13639 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
13640 #define TARGET_ASM_FUNCTION_END_PROLOGUE avr_asm_function_end_prologue
13641 #undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
13642 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE avr_asm_function_begin_epilogue
13644 #undef TARGET_FUNCTION_VALUE
13645 #define TARGET_FUNCTION_VALUE avr_function_value
13646 #undef TARGET_LIBCALL_VALUE
13647 #define TARGET_LIBCALL_VALUE avr_libcall_value
13648 #undef TARGET_FUNCTION_VALUE_REGNO_P
13649 #define TARGET_FUNCTION_VALUE_REGNO_P avr_function_value_regno_p
13651 #undef TARGET_ATTRIBUTE_TABLE
13652 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
13653 #undef TARGET_INSERT_ATTRIBUTES
13654 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
13655 #undef TARGET_SECTION_TYPE_FLAGS
13656 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
13658 #undef TARGET_ASM_NAMED_SECTION
13659 #define TARGET_ASM_NAMED_SECTION avr_asm_named_section
13660 #undef TARGET_ASM_INIT_SECTIONS
13661 #define TARGET_ASM_INIT_SECTIONS avr_asm_init_sections
13662 #undef TARGET_ENCODE_SECTION_INFO
13663 #define TARGET_ENCODE_SECTION_INFO avr_encode_section_info
13664 #undef TARGET_ASM_SELECT_SECTION
13665 #define TARGET_ASM_SELECT_SECTION avr_asm_select_section
13667 #undef TARGET_REGISTER_MOVE_COST
13668 #define TARGET_REGISTER_MOVE_COST avr_register_move_cost
13669 #undef TARGET_MEMORY_MOVE_COST
13670 #define TARGET_MEMORY_MOVE_COST avr_memory_move_cost
13671 #undef TARGET_RTX_COSTS
13672 #define TARGET_RTX_COSTS avr_rtx_costs
13673 #undef TARGET_ADDRESS_COST
13674 #define TARGET_ADDRESS_COST avr_address_cost
13675 #undef TARGET_MACHINE_DEPENDENT_REORG
13676 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
13677 #undef TARGET_FUNCTION_ARG
13678 #define TARGET_FUNCTION_ARG avr_function_arg
13679 #undef TARGET_FUNCTION_ARG_ADVANCE
13680 #define TARGET_FUNCTION_ARG_ADVANCE avr_function_arg_advance
13682 #undef TARGET_SET_CURRENT_FUNCTION
13683 #define TARGET_SET_CURRENT_FUNCTION avr_set_current_function
13685 #undef TARGET_RETURN_IN_MEMORY
13686 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
13688 #undef TARGET_STRICT_ARGUMENT_NAMING
13689 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
13691 #undef TARGET_BUILTIN_SETJMP_FRAME_VALUE
13692 #define TARGET_BUILTIN_SETJMP_FRAME_VALUE avr_builtin_setjmp_frame_value
13694 #undef TARGET_CONDITIONAL_REGISTER_USAGE
13695 #define TARGET_CONDITIONAL_REGISTER_USAGE avr_conditional_register_usage
13697 #undef TARGET_HARD_REGNO_SCRATCH_OK
13698 #define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok
13699 #undef TARGET_CASE_VALUES_THRESHOLD
13700 #define TARGET_CASE_VALUES_THRESHOLD avr_case_values_threshold
13702 #undef TARGET_FRAME_POINTER_REQUIRED
13703 #define TARGET_FRAME_POINTER_REQUIRED avr_frame_pointer_required_p
13704 #undef TARGET_CAN_ELIMINATE
13705 #define TARGET_CAN_ELIMINATE avr_can_eliminate
13707 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
13708 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS avr_allocate_stack_slots_for_args
13710 #undef TARGET_WARN_FUNC_RETURN
13711 #define TARGET_WARN_FUNC_RETURN avr_warn_func_return
13713 #undef TARGET_CLASS_LIKELY_SPILLED_P
13714 #define TARGET_CLASS_LIKELY_SPILLED_P avr_class_likely_spilled_p
13716 #undef TARGET_OPTION_OVERRIDE
13717 #define TARGET_OPTION_OVERRIDE avr_option_override
13719 #undef TARGET_CANNOT_MODIFY_JUMPS_P
13720 #define TARGET_CANNOT_MODIFY_JUMPS_P avr_cannot_modify_jumps_p
13722 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
13723 #define TARGET_FUNCTION_OK_FOR_SIBCALL avr_function_ok_for_sibcall
13725 #undef TARGET_INIT_BUILTINS
13726 #define TARGET_INIT_BUILTINS avr_init_builtins
13728 #undef TARGET_BUILTIN_DECL
13729 #define TARGET_BUILTIN_DECL avr_builtin_decl
13731 #undef TARGET_EXPAND_BUILTIN
13732 #define TARGET_EXPAND_BUILTIN avr_expand_builtin
13734 #undef TARGET_FOLD_BUILTIN
13735 #define TARGET_FOLD_BUILTIN avr_fold_builtin
13737 #undef TARGET_ASM_FUNCTION_RODATA_SECTION
13738 #define TARGET_ASM_FUNCTION_RODATA_SECTION avr_asm_function_rodata_section
13740 #undef TARGET_SCALAR_MODE_SUPPORTED_P
13741 #define TARGET_SCALAR_MODE_SUPPORTED_P avr_scalar_mode_supported_p
13743 #undef TARGET_BUILD_BUILTIN_VA_LIST
13744 #define TARGET_BUILD_BUILTIN_VA_LIST avr_build_builtin_va_list
13746 #undef TARGET_FIXED_POINT_SUPPORTED_P
13747 #define TARGET_FIXED_POINT_SUPPORTED_P hook_bool_void_true
13749 #undef TARGET_CONVERT_TO_TYPE
13750 #define TARGET_CONVERT_TO_TYPE avr_convert_to_type
13752 #undef TARGET_ADDR_SPACE_SUBSET_P
13753 #define TARGET_ADDR_SPACE_SUBSET_P avr_addr_space_subset_p
13755 #undef TARGET_ADDR_SPACE_CONVERT
13756 #define TARGET_ADDR_SPACE_CONVERT avr_addr_space_convert
13758 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
13759 #define TARGET_ADDR_SPACE_ADDRESS_MODE avr_addr_space_address_mode
13761 #undef TARGET_ADDR_SPACE_POINTER_MODE
13762 #define TARGET_ADDR_SPACE_POINTER_MODE avr_addr_space_pointer_mode
13764 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
13765 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
13766 avr_addr_space_legitimate_address_p
13768 #undef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
13769 #define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS avr_addr_space_legitimize_address
13771 #undef TARGET_MODE_DEPENDENT_ADDRESS_P
13772 #define TARGET_MODE_DEPENDENT_ADDRESS_P avr_mode_dependent_address_p
13774 #undef TARGET_SECONDARY_RELOAD
13775 #define TARGET_SECONDARY_RELOAD avr_secondary_reload
13777 #undef TARGET_PRINT_OPERAND
13778 #define TARGET_PRINT_OPERAND avr_print_operand
13779 #undef TARGET_PRINT_OPERAND_ADDRESS
13780 #define TARGET_PRINT_OPERAND_ADDRESS avr_print_operand_address
13781 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
13782 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P avr_print_operand_punct_valid_p
13784 struct gcc_target targetm = TARGET_INITIALIZER;
13787 #include "gt-avr.h"