1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2 Copyright (C) 1998-2017 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)
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/>. */
24 #include "coretypes.h"
29 #include "stringpool.h"
32 #include "c-family/c-common.h"
41 #include "conditions.h"
42 #include "insn-attr.h"
46 #include "stor-layout.h"
50 #include "langhooks.h"
55 #include "tree-pass.h"
56 #include "print-rtl.h"
59 /* This file should be included last. */
60 #include "target-def.h"
62 /* Maximal allowed offset for an address in the LD command */
63 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
65 /* Return true if STR starts with PREFIX and false, otherwise. */
66 #define STR_PREFIX_P(STR,PREFIX) (0 == strncmp (STR, PREFIX, strlen (PREFIX)))
68 /* The 4 bits starting at SECTION_MACH_DEP are reserved to store the
69 address space where data is to be located.
70 As the only non-generic address spaces are all located in flash,
71 this can be used to test if data shall go into some .progmem* section.
72 This must be the rightmost field of machine dependent section flags. */
73 #define AVR_SECTION_PROGMEM (0xf * SECTION_MACH_DEP)
75 /* Similar 4-bit region for SYMBOL_REF_FLAGS. */
76 #define AVR_SYMBOL_FLAG_PROGMEM (0xf * SYMBOL_FLAG_MACH_DEP)
78 /* Similar 4-bit region in SYMBOL_REF_FLAGS:
79 Set address-space AS in SYMBOL_REF_FLAGS of SYM */
80 #define AVR_SYMBOL_SET_ADDR_SPACE(SYM,AS) \
82 SYMBOL_REF_FLAGS (sym) &= ~AVR_SYMBOL_FLAG_PROGMEM; \
83 SYMBOL_REF_FLAGS (sym) |= (AS) * SYMBOL_FLAG_MACH_DEP; \
86 /* Read address-space from SYMBOL_REF_FLAGS of SYM */
87 #define AVR_SYMBOL_GET_ADDR_SPACE(SYM) \
88 ((SYMBOL_REF_FLAGS (sym) & AVR_SYMBOL_FLAG_PROGMEM) \
89 / SYMBOL_FLAG_MACH_DEP)
91 /* (AVR_TINY only): Symbol has attribute progmem */
92 #define AVR_SYMBOL_FLAG_TINY_PM \
93 (SYMBOL_FLAG_MACH_DEP << 7)
95 /* (AVR_TINY only): Symbol has attribute absdata */
96 #define AVR_SYMBOL_FLAG_TINY_ABSDATA \
97 (SYMBOL_FLAG_MACH_DEP << 8)
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'. */
130 /* SREG: The processor status */
133 /* RAMPX, RAMPY, RAMPD and CCP of XMEGA */
139 /* RAMPZ: The high byte of 24-bit address used with ELPM */
142 /* SP: The stack pointer and its low and high byte */
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
,
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
;
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
;
193 /* Zeroed register RTX (reg:QI ZERO_REGNO) */
194 extern GTY(()) 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
;
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
;
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 /* Unnamed sections associated to __attribute__((progmem)) aka. PROGMEM
223 or to address space __flash* or __memx. Only used as singletons inside
224 avr_asm_select_section, but it must not be local there because of GTY. */
225 static GTY(()) section
*progmem_section
[ADDR_SPACE_COUNT
];
227 /* Condition for insns/expanders from avr-dimode.md. */
228 bool avr_have_dimode
= true;
230 /* To track if code will use .bss and/or .data. */
231 bool avr_need_clear_bss_p
= false;
232 bool avr_need_copy_data_p
= false;
235 /* Transform UP into lowercase and write the result to LO.
236 You must provide enough space for LO. Return LO. */
239 avr_tolower (char *lo
, const char *up
)
243 for (; *up
; up
++, lo
++)
252 /* Constraint helper function. XVAL is a CONST_INT or a CONST_DOUBLE.
253 Return true if the least significant N_BYTES bytes of XVAL all have a
254 popcount in POP_MASK and false, otherwise. POP_MASK represents a subset
255 of integers which contains an integer N iff bit N of POP_MASK is set. */
258 avr_popcount_each_byte (rtx xval
, int n_bytes
, int pop_mask
)
260 machine_mode mode
= GET_MODE (xval
);
262 if (VOIDmode
== mode
)
265 for (int i
= 0; i
< n_bytes
; i
++)
267 rtx xval8
= simplify_gen_subreg (QImode
, xval
, mode
, i
);
268 unsigned int val8
= UINTVAL (xval8
) & GET_MODE_MASK (QImode
);
270 if (0 == (pop_mask
& (1 << popcount_hwi (val8
))))
278 /* Access some RTX as INT_MODE. If X is a CONST_FIXED we can get
279 the bit representation of X by "casting" it to CONST_INT. */
282 avr_to_int_mode (rtx x
)
284 machine_mode mode
= GET_MODE (x
);
286 return VOIDmode
== mode
288 : simplify_gen_subreg (int_mode_for_mode (mode
).require (), x
, mode
, 0);
293 static const pass_data avr_pass_data_recompute_notes
=
296 "", // name (will be patched)
297 OPTGROUP_NONE
, // optinfo_flags
299 0, // properties_required
300 0, // properties_provided
301 0, // properties_destroyed
302 0, // todo_flags_start
303 TODO_df_finish
| TODO_df_verify
// todo_flags_finish
307 class avr_pass_recompute_notes
: public rtl_opt_pass
310 avr_pass_recompute_notes (gcc::context
*ctxt
, const char *name
)
311 : rtl_opt_pass (avr_pass_data_recompute_notes
, ctxt
)
316 virtual unsigned int execute (function
*)
318 df_note_add_problem ();
323 }; // avr_pass_recompute_notes
325 static const pass_data avr_pass_data_casesi
=
328 "", // name (will be patched)
329 OPTGROUP_NONE
, // optinfo_flags
331 0, // properties_required
332 0, // properties_provided
333 0, // properties_destroyed
334 0, // todo_flags_start
335 0 // todo_flags_finish
339 class avr_pass_casesi
: public rtl_opt_pass
342 avr_pass_casesi (gcc::context
*ctxt
, const char *name
)
343 : rtl_opt_pass (avr_pass_data_casesi
, ctxt
)
348 void avr_rest_of_handle_casesi (function
*);
350 virtual bool gate (function
*) { return optimize
> 0; }
352 virtual unsigned int execute (function
*func
)
354 avr_rest_of_handle_casesi (func
);
358 }; // avr_pass_casesi
363 make_avr_pass_recompute_notes (gcc::context
*ctxt
)
365 return new avr_pass_recompute_notes (ctxt
, "avr-notes-free-cfg");
369 make_avr_pass_casesi (gcc::context
*ctxt
)
371 return new avr_pass_casesi (ctxt
, "avr-casesi");
375 /* Make one parallel insn with all the patterns from insns i[0]..i[5]. */
378 avr_parallel_insn_from_insns (rtx_insn
*i
[6])
380 rtvec vec
= gen_rtvec (6, PATTERN (i
[0]), PATTERN (i
[1]), PATTERN (i
[2]),
381 PATTERN (i
[3]), PATTERN (i
[4]), PATTERN (i
[5]));
383 emit (gen_rtx_PARALLEL (VOIDmode
, vec
));
384 rtx_insn
*insn
= get_insns();
391 /* Return true if we see an insn stream generated by casesi expander together
392 with an extension to SImode of the switch value.
394 If this is the case, fill in the insns from casesi to INSNS[1..5] and
395 the SImode extension to INSNS[0]. Moreover, extract the operands of
396 pattern casesi_<mode>_sequence forged from the sequence to recog_data. */
399 avr_is_casesi_sequence (basic_block bb
, rtx_insn
*insn
, rtx_insn
*insns
[6])
403 /* A first and quick test for a casesi sequences. As a side effect of
404 the test, harvest respective insns to INSNS[0..5]. */
406 if (!(JUMP_P (insns
[5] = insn
)
407 // casesi is the only insn that comes up with UNSPEC_INDEX_JMP,
408 // hence the following test ensures that we are actually dealing
409 // with code from casesi.
410 && (set_5
= single_set (insns
[5]))
411 && UNSPEC
== GET_CODE (SET_SRC (set_5
))
412 && UNSPEC_INDEX_JMP
== XINT (SET_SRC (set_5
), 1)
414 && (insns
[4] = prev_real_insn (insns
[5]))
415 && (insns
[3] = prev_real_insn (insns
[4]))
416 && (insns
[2] = prev_real_insn (insns
[3]))
417 && (insns
[1] = prev_real_insn (insns
[2]))
419 // Insn prior to casesi.
420 && (insns
[0] = prev_real_insn (insns
[1]))
421 && (set_0
= single_set (insns
[0]))
422 && extend_operator (SET_SRC (set_0
), SImode
)))
429 fprintf (dump_file
, ";; Sequence from casesi in "
430 "[bb %d]:\n\n", bb
->index
);
431 for (int i
= 0; i
< 6; i
++)
432 print_rtl_single (dump_file
, insns
[i
]);
435 /* We have to deal with quite some operands. Extracting them by hand
436 would be tedious, therefore wrap the insn patterns into a parallel,
437 run recog against it and then use insn extract to get the operands. */
439 rtx_insn
*xinsn
= avr_parallel_insn_from_insns (insns
);
441 INSN_CODE (xinsn
) = recog (PATTERN (xinsn
), xinsn
, NULL
/* num_clobbers */);
443 /* Failing to recognize means that someone changed the casesi expander or
444 that some passes prior to this one performed some unexpected changes.
445 Gracefully drop such situations instead of aborting. */
447 if (INSN_CODE (xinsn
) < 0)
450 fprintf (dump_file
, ";; Sequence not recognized, giving up.\n\n");
455 gcc_assert (CODE_FOR_casesi_qi_sequence
== INSN_CODE (xinsn
)
456 || CODE_FOR_casesi_hi_sequence
== INSN_CODE (xinsn
));
458 extract_insn (xinsn
);
460 // Assert on the anatomy of xinsn's operands we are going to work with.
462 gcc_assert (11 == recog_data
.n_operands
);
463 gcc_assert (4 == recog_data
.n_dups
);
467 fprintf (dump_file
, ";; Operands extracted:\n");
468 for (int i
= 0; i
< recog_data
.n_operands
; i
++)
469 avr_fdump (dump_file
, ";; $%d = %r\n", i
, recog_data
.operand
[i
]);
470 fprintf (dump_file
, "\n");
477 /* Perform some extra checks on operands of casesi_<mode>_sequence.
478 Not all operand dependencies can be described by means of predicates.
479 This function performs left over checks and should always return true.
480 Returning false means that someone changed the casesi expander but did
481 not adjust casesi_<mode>_sequence. */
484 avr_casei_sequence_check_operands (rtx
*xop
)
486 rtx sub_5
= NULL_RTX
;
488 if (AVR_HAVE_EIJMP_EICALL
489 // The last clobber op of the tablejump.
490 && xop
[8] == all_regs_rtx
[24])
492 // $6 is: (subreg:SI ($5) 0)
496 if (!AVR_HAVE_EIJMP_EICALL
497 // $6 is: (plus:HI (subreg:SI ($5) 0)
499 && PLUS
== GET_CODE (xop
[6])
500 && LABEL_REF
== GET_CODE (XEXP (xop
[6], 1))
501 && rtx_equal_p (xop
[3], XEXP (XEXP (xop
[6], 1), 0))
502 // The last clobber op of the tablejump.
503 && xop
[8] == const0_rtx
)
505 sub_5
= XEXP (xop
[6], 0);
510 && 0 == SUBREG_BYTE (sub_5
)
511 && rtx_equal_p (xop
[5], SUBREG_REG (sub_5
)))
515 fprintf (dump_file
, "\n;; Failed condition for casesi_<mode>_sequence\n\n");
521 /* INSNS[1..5] is a sequence as generated by casesi and INSNS[0] is an
522 extension of an 8-bit or 16-bit integer to SImode. XOP contains the
523 operands of INSNS as extracted by insn_extract from pattern
524 casesi_<mode>_sequence:
526 $0: SImode reg switch value as result of $9.
527 $1: Negative of smallest index in switch.
528 $2: Number of entries in switch.
530 $4: Label if out-of-bounds.
532 $6: 3-byte PC: subreg:HI ($5) + label_ref ($3)
533 2-byte PC: subreg:HI ($5)
534 $7: HI reg index into table (Z or pseudo)
535 $8: R24 or const0_rtx (to be clobbered)
536 $9: Extension to SImode of an 8-bit or 16-bit integer register $10.
537 $10: QImode or HImode register input of $9.
539 Try to optimize this sequence, i.e. use the original HImode / QImode
540 switch value instead of SImode. */
543 avr_optimize_casesi (rtx_insn
*insns
[6], rtx
*xop
)
545 // Original mode of the switch value; this is QImode or HImode.
546 machine_mode mode
= GET_MODE (xop
[10]);
548 // How the original switch value was extended to SImode; this is
549 // SIGN_EXTEND or ZERO_EXTEND.
550 enum rtx_code code
= GET_CODE (xop
[9]);
552 // Lower index, upper index (plus one) and range of case calues.
553 HOST_WIDE_INT low_idx
= -INTVAL (xop
[1]);
554 HOST_WIDE_INT num_idx
= INTVAL (xop
[2]);
555 HOST_WIDE_INT hig_idx
= low_idx
+ num_idx
;
557 // Maximum ranges of (un)signed QImode resp. HImode.
558 unsigned umax
= QImode
== mode
? 0xff : 0xffff;
559 int imax
= QImode
== mode
? 0x7f : 0x7fff;
560 int imin
= -imax
- 1;
562 // Testing the case range and whether it fits into the range of the
563 // (un)signed mode. This test should actually always pass because it
564 // makes no sense to have case values outside the mode range. Notice
565 // that case labels which are unreachable because they are outside the
566 // mode of the switch value (e.g. "case -1" for uint8_t) have already
567 // been thrown away by the middle-end.
569 if (SIGN_EXTEND
== code
575 else if (ZERO_EXTEND
== code
577 && (unsigned) hig_idx
<= umax
)
584 fprintf (dump_file
, ";; Case ranges too big, giving up.\n\n");
588 // Do normalization of switch value $10 and out-of-bound check in its
589 // original mode instead of in SImode. Use a newly created pseudo.
590 // This will replace insns[1..2].
594 rtx_insn
*seq1
, *seq2
, *last1
, *last2
;
596 rtx reg
= copy_to_mode_reg (mode
, xop
[10]);
598 rtx (*gen_add
)(rtx
,rtx
,rtx
) = QImode
== mode
? gen_addqi3
: gen_addhi3
;
599 rtx (*gen_cmp
)(rtx
,rtx
) = QImode
== mode
? gen_cmpqi3
: gen_cmphi3
;
601 emit_insn (gen_add (reg
, reg
, gen_int_mode (-low_idx
, mode
)));
602 emit_insn (gen_cmp (reg
, gen_int_mode (num_idx
, mode
)));
605 last1
= get_last_insn();
608 emit_insn_before (seq1
, insns
[1]);
610 // After the out-of-bounds test and corresponding branch, use a
611 // 16-bit index. If QImode is used, extend it to HImode first.
612 // This will replace insns[4].
617 reg
= force_reg (HImode
, gen_rtx_fmt_e (code
, HImode
, reg
));
619 rtx pat_4
= AVR_3_BYTE_PC
620 ? gen_movhi (xop
[7], reg
)
621 : gen_addhi3 (xop
[7], reg
, gen_rtx_LABEL_REF (VOIDmode
, xop
[3]));
626 last2
= get_last_insn();
629 emit_insn_after (seq2
, insns
[4]);
633 fprintf (dump_file
, ";; New insns: ");
635 for (rtx_insn
*insn
= seq1
; ; insn
= NEXT_INSN (insn
))
637 fprintf (dump_file
, "%d, ", INSN_UID (insn
));
641 for (rtx_insn
*insn
= seq2
; ; insn
= NEXT_INSN (insn
))
643 fprintf (dump_file
, "%d%s", INSN_UID (insn
),
644 insn
== last2
? ".\n\n" : ", ");
649 fprintf (dump_file
, ";; Deleting insns: %d, %d, %d.\n\n",
650 INSN_UID (insns
[1]), INSN_UID (insns
[2]), INSN_UID (insns
[4]));
653 // Pseudodelete the SImode and subreg of SImode insns. We don't care
654 // about the extension insns[0]: Its result is now unused and other
655 // passes will clean it up.
657 SET_INSN_DELETED (insns
[1]);
658 SET_INSN_DELETED (insns
[2]);
659 SET_INSN_DELETED (insns
[4]);
664 avr_pass_casesi::avr_rest_of_handle_casesi (function
*func
)
668 FOR_EACH_BB_FN (bb
, func
)
670 rtx_insn
*insn
, *insns
[6];
672 FOR_BB_INSNS (bb
, insn
)
674 if (avr_is_casesi_sequence (bb
, insn
, insns
))
676 avr_optimize_casesi (insns
, recog_data
.operand
);
683 /* Set `avr_arch' as specified by `-mmcu='.
684 Return true on success. */
687 avr_set_core_architecture (void)
689 /* Search for mcu core architecture. */
692 avr_mmcu
= AVR_MMCU_DEFAULT
;
694 avr_arch
= &avr_arch_types
[0];
696 for (const avr_mcu_t
*mcu
= avr_mcu_types
; ; mcu
++)
698 if (NULL
== mcu
->name
)
700 /* Reached the end of `avr_mcu_types'. This should actually never
701 happen as options are provided by device-specs. It could be a
702 typo in a device-specs or calling the compiler proper directly
703 with -mmcu=<device>. */
705 error ("unknown core architecture %qs specified with %qs",
707 avr_inform_core_architectures ();
710 else if (0 == strcmp (mcu
->name
, avr_mmcu
)
711 // Is this a proper architecture ?
712 && NULL
== mcu
->macro
)
714 avr_arch
= &avr_arch_types
[mcu
->arch_id
];
716 avr_n_flash
= 1 + (mcu
->flash_size
- 1) / 0x10000;
726 /* Implement `TARGET_OPTION_OVERRIDE'. */
729 avr_option_override (void)
731 /* Disable -fdelete-null-pointer-checks option for AVR target.
732 This option compiler assumes that dereferencing of a null pointer
733 would halt the program. For AVR this assumption is not true and
734 programs can safely dereference null pointers. Changes made by this
735 option may not work properly for AVR. So disable this option. */
737 flag_delete_null_pointer_checks
= 0;
739 /* caller-save.c looks for call-clobbered hard registers that are assigned
740 to pseudos that cross calls and tries so save-restore them around calls
741 in order to reduce the number of stack slots needed.
743 This might lead to situations where reload is no more able to cope
744 with the challenge of AVR's very few address registers and fails to
745 perform the requested spills. */
748 flag_caller_saves
= 0;
750 /* Allow optimizer to introduce store data races. This used to be the
751 default - it was changed because bigger targets did not see any
752 performance decrease. For the AVR though, disallowing data races
753 introduces additional code in LIM and increases reg pressure. */
755 maybe_set_param_value (PARAM_ALLOW_STORE_DATA_RACES
, 1,
756 global_options
.x_param_values
,
757 global_options_set
.x_param_values
);
759 /* Unwind tables currently require a frame pointer for correctness,
760 see toplev.c:process_options(). */
762 if ((flag_unwind_tables
763 || flag_non_call_exceptions
764 || flag_asynchronous_unwind_tables
)
765 && !ACCUMULATE_OUTGOING_ARGS
)
767 flag_omit_frame_pointer
= 0;
771 warning (OPT_fpic
, "-fpic is not supported");
773 warning (OPT_fPIC
, "-fPIC is not supported");
775 warning (OPT_fpie
, "-fpie is not supported");
777 warning (OPT_fPIE
, "-fPIE is not supported");
779 #if !defined (HAVE_AS_AVR_MGCCISR_OPTION)
780 avr_gasisr_prologues
= 0;
783 if (!avr_set_core_architecture())
786 /* RAM addresses of some SFRs common to all devices in respective arch. */
788 /* SREG: Status Register containing flags like I (global IRQ) */
789 avr_addr
.sreg
= 0x3F + avr_arch
->sfr_offset
;
791 /* RAMPZ: Address' high part when loading via ELPM */
792 avr_addr
.rampz
= 0x3B + avr_arch
->sfr_offset
;
794 avr_addr
.rampy
= 0x3A + avr_arch
->sfr_offset
;
795 avr_addr
.rampx
= 0x39 + avr_arch
->sfr_offset
;
796 avr_addr
.rampd
= 0x38 + avr_arch
->sfr_offset
;
797 avr_addr
.ccp
= (AVR_TINY
? 0x3C : 0x34) + avr_arch
->sfr_offset
;
799 /* SP: Stack Pointer (SP_H:SP_L) */
800 avr_addr
.sp_l
= 0x3D + avr_arch
->sfr_offset
;
801 avr_addr
.sp_h
= avr_addr
.sp_l
+ 1;
803 init_machine_status
= avr_init_machine_status
;
805 avr_log_set_avr_log();
808 /* Function to set up the backend function structure. */
810 static struct machine_function
*
811 avr_init_machine_status (void)
813 return ggc_cleared_alloc
<machine_function
> ();
817 /* Implement `INIT_EXPANDERS'. */
818 /* The function works like a singleton. */
821 avr_init_expanders (void)
823 for (int regno
= 0; regno
< 32; regno
++)
824 all_regs_rtx
[regno
] = gen_rtx_REG (QImode
, regno
);
826 lpm_reg_rtx
= all_regs_rtx
[LPM_REGNO
];
827 tmp_reg_rtx
= all_regs_rtx
[AVR_TMP_REGNO
];
828 zero_reg_rtx
= all_regs_rtx
[AVR_ZERO_REGNO
];
830 lpm_addr_reg_rtx
= gen_rtx_REG (HImode
, REG_Z
);
832 sreg_rtx
= gen_rtx_MEM (QImode
, GEN_INT (avr_addr
.sreg
));
833 rampd_rtx
= gen_rtx_MEM (QImode
, GEN_INT (avr_addr
.rampd
));
834 rampx_rtx
= gen_rtx_MEM (QImode
, GEN_INT (avr_addr
.rampx
));
835 rampy_rtx
= gen_rtx_MEM (QImode
, GEN_INT (avr_addr
.rampy
));
836 rampz_rtx
= gen_rtx_MEM (QImode
, GEN_INT (avr_addr
.rampz
));
838 xstring_empty
= gen_rtx_CONST_STRING (VOIDmode
, "");
839 xstring_e
= gen_rtx_CONST_STRING (VOIDmode
, "e");
841 /* TINY core does not have regs r10-r16, but avr-dimode.md expects them
844 avr_have_dimode
= false;
848 /* Implement `REGNO_REG_CLASS'. */
849 /* Return register class for register R. */
852 avr_regno_reg_class (int r
)
854 static const enum reg_class reg_class_tab
[] =
858 NO_LD_REGS
, NO_LD_REGS
, NO_LD_REGS
,
859 NO_LD_REGS
, NO_LD_REGS
, NO_LD_REGS
, NO_LD_REGS
,
860 NO_LD_REGS
, NO_LD_REGS
, NO_LD_REGS
, NO_LD_REGS
,
861 NO_LD_REGS
, NO_LD_REGS
, NO_LD_REGS
, NO_LD_REGS
,
863 SIMPLE_LD_REGS
, SIMPLE_LD_REGS
, SIMPLE_LD_REGS
, SIMPLE_LD_REGS
,
864 SIMPLE_LD_REGS
, SIMPLE_LD_REGS
, SIMPLE_LD_REGS
, SIMPLE_LD_REGS
,
866 ADDW_REGS
, ADDW_REGS
,
868 POINTER_X_REGS
, POINTER_X_REGS
,
870 POINTER_Y_REGS
, POINTER_Y_REGS
,
872 POINTER_Z_REGS
, POINTER_Z_REGS
,
878 return reg_class_tab
[r
];
884 /* Implement `TARGET_SCALAR_MODE_SUPPORTED_P'. */
887 avr_scalar_mode_supported_p (scalar_mode mode
)
889 if (ALL_FIXED_POINT_MODE_P (mode
))
895 return default_scalar_mode_supported_p (mode
);
899 /* Return TRUE if DECL is a VAR_DECL located in flash and FALSE, otherwise. */
902 avr_decl_flash_p (tree decl
)
904 if (TREE_CODE (decl
) != VAR_DECL
905 || TREE_TYPE (decl
) == error_mark_node
)
910 return !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (decl
)));
914 /* Return TRUE if DECL is a VAR_DECL located in the 24-bit flash
915 address space and FALSE, otherwise. */
918 avr_decl_memx_p (tree decl
)
920 if (TREE_CODE (decl
) != VAR_DECL
921 || TREE_TYPE (decl
) == error_mark_node
)
926 return (ADDR_SPACE_MEMX
== TYPE_ADDR_SPACE (TREE_TYPE (decl
)));
930 /* Return TRUE if X is a MEM rtx located in flash and FALSE, otherwise. */
933 avr_mem_flash_p (rtx x
)
936 && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x
)));
940 /* Return TRUE if X is a MEM rtx located in the 24-bit flash
941 address space and FALSE, otherwise. */
944 avr_mem_memx_p (rtx x
)
947 && ADDR_SPACE_MEMX
== MEM_ADDR_SPACE (x
));
951 /* A helper for the subsequent function attribute used to dig for
952 attribute 'name' in a FUNCTION_DECL or FUNCTION_TYPE */
955 avr_lookup_function_attribute1 (const_tree func
, const char *name
)
957 if (FUNCTION_DECL
== TREE_CODE (func
))
959 if (NULL_TREE
!= lookup_attribute (name
, DECL_ATTRIBUTES (func
)))
964 func
= TREE_TYPE (func
);
967 gcc_assert (TREE_CODE (func
) == FUNCTION_TYPE
968 || TREE_CODE (func
) == METHOD_TYPE
);
970 return NULL_TREE
!= lookup_attribute (name
, TYPE_ATTRIBUTES (func
));
973 /* Return nonzero if FUNC is a naked function. */
976 avr_naked_function_p (tree func
)
978 return avr_lookup_function_attribute1 (func
, "naked");
981 /* Return nonzero if FUNC is an interrupt function as specified
982 by the "interrupt" attribute. */
985 avr_interrupt_function_p (tree func
)
987 return avr_lookup_function_attribute1 (func
, "interrupt");
990 /* Return nonzero if FUNC is a signal function as specified
991 by the "signal" attribute. */
994 avr_signal_function_p (tree func
)
996 return avr_lookup_function_attribute1 (func
, "signal");
999 /* Return nonzero if FUNC is an OS_task function. */
1002 avr_OS_task_function_p (tree func
)
1004 return avr_lookup_function_attribute1 (func
, "OS_task");
1007 /* Return nonzero if FUNC is an OS_main function. */
1010 avr_OS_main_function_p (tree func
)
1012 return avr_lookup_function_attribute1 (func
, "OS_main");
1016 /* Return nonzero if FUNC is a no_gccisr function as specified
1017 by the "no_gccisr" attribute. */
1020 avr_no_gccisr_function_p (tree func
)
1022 return avr_lookup_function_attribute1 (func
, "no_gccisr");
1025 /* Implement `TARGET_SET_CURRENT_FUNCTION'. */
1026 /* Sanity cheching for above function attributes. */
1029 avr_set_current_function (tree decl
)
1034 if (decl
== NULL_TREE
1035 || current_function_decl
== NULL_TREE
1036 || current_function_decl
== error_mark_node
1038 || cfun
->machine
->attributes_checked_p
)
1041 loc
= DECL_SOURCE_LOCATION (decl
);
1043 cfun
->machine
->is_naked
= avr_naked_function_p (decl
);
1044 cfun
->machine
->is_signal
= avr_signal_function_p (decl
);
1045 cfun
->machine
->is_interrupt
= avr_interrupt_function_p (decl
);
1046 cfun
->machine
->is_OS_task
= avr_OS_task_function_p (decl
);
1047 cfun
->machine
->is_OS_main
= avr_OS_main_function_p (decl
);
1048 cfun
->machine
->is_no_gccisr
= avr_no_gccisr_function_p (decl
);
1050 isr
= cfun
->machine
->is_interrupt
? "interrupt" : "signal";
1052 /* Too much attributes make no sense as they request conflicting features. */
1054 if (cfun
->machine
->is_OS_task
+ cfun
->machine
->is_OS_main
1055 + (cfun
->machine
->is_signal
|| cfun
->machine
->is_interrupt
) > 1)
1056 error_at (loc
, "function attributes %qs, %qs and %qs are mutually"
1057 " exclusive", "OS_task", "OS_main", isr
);
1059 /* 'naked' will hide effects of 'OS_task' and 'OS_main'. */
1061 if (cfun
->machine
->is_naked
1062 && (cfun
->machine
->is_OS_task
|| cfun
->machine
->is_OS_main
))
1063 warning_at (loc
, OPT_Wattributes
, "function attributes %qs and %qs have"
1064 " no effect on %qs function", "OS_task", "OS_main", "naked");
1066 if (cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
)
1068 tree args
= TYPE_ARG_TYPES (TREE_TYPE (decl
));
1069 tree ret
= TREE_TYPE (TREE_TYPE (decl
));
1072 name
= DECL_ASSEMBLER_NAME_SET_P (decl
)
1073 ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl
))
1074 : IDENTIFIER_POINTER (DECL_NAME (decl
));
1076 /* Skip a leading '*' that might still prefix the assembler name,
1077 e.g. in non-LTO runs. */
1079 name
= default_strip_name_encoding (name
);
1081 /* Interrupt handlers must be void __vector (void) functions. */
1083 if (args
&& TREE_CODE (TREE_VALUE (args
)) != VOID_TYPE
)
1084 error_at (loc
, "%qs function cannot have arguments", isr
);
1086 if (TREE_CODE (ret
) != VOID_TYPE
)
1087 error_at (loc
, "%qs function cannot return a value", isr
);
1089 #if defined WITH_AVRLIBC
1090 /* Silently ignore 'signal' if 'interrupt' is present. AVR-LibC startet
1091 using this when it switched from SIGNAL and INTERRUPT to ISR. */
1093 if (cfun
->machine
->is_interrupt
)
1094 cfun
->machine
->is_signal
= 0;
1096 /* If the function has the 'signal' or 'interrupt' attribute, ensure
1097 that the name of the function is "__vector_NN" so as to catch
1098 when the user misspells the vector name. */
1100 if (!STR_PREFIX_P (name
, "__vector"))
1101 warning_at (loc
, OPT_Wmisspelled_isr
, "%qs appears to be a misspelled "
1102 "%qs handler, missing %<__vector%> prefix", name
, isr
);
1103 #endif // AVR-LibC naming conventions
1106 #if defined WITH_AVRLIBC
1107 // Common problem is using "ISR" without first including avr/interrupt.h.
1108 const char *name
= IDENTIFIER_POINTER (DECL_NAME (decl
));
1109 name
= default_strip_name_encoding (name
);
1110 if (0 == strcmp ("ISR", name
)
1111 || 0 == strcmp ("INTERRUPT", name
)
1112 || 0 == strcmp ("SIGNAL", name
))
1114 warning_at (loc
, OPT_Wmisspelled_isr
, "%qs is a reserved identifier"
1115 " in AVR-LibC. Consider %<#include <avr/interrupt.h>%>"
1116 " before using the %qs macro", name
, name
);
1118 #endif // AVR-LibC naming conventions
1120 /* Don't print the above diagnostics more than once. */
1122 cfun
->machine
->attributes_checked_p
= 1;
1126 /* Implement `ACCUMULATE_OUTGOING_ARGS'. */
1129 avr_accumulate_outgoing_args (void)
1132 return TARGET_ACCUMULATE_OUTGOING_ARGS
;
1134 /* FIXME: For setjmp and in avr_builtin_setjmp_frame_value we don't know
1135 what offset is correct. In some cases it is relative to
1136 virtual_outgoing_args_rtx and in others it is relative to
1137 virtual_stack_vars_rtx. For example code see
1138 gcc.c-torture/execute/built-in-setjmp.c
1139 gcc.c-torture/execute/builtins/sprintf-chk.c */
1141 return (TARGET_ACCUMULATE_OUTGOING_ARGS
1142 && !(cfun
->calls_setjmp
1143 || cfun
->has_nonlocal_label
));
1147 /* Report contribution of accumulated outgoing arguments to stack size. */
1150 avr_outgoing_args_size (void)
1152 return ACCUMULATE_OUTGOING_ARGS
? crtl
->outgoing_args_size
: 0;
1156 /* Implement `STARTING_FRAME_OFFSET'. */
1157 /* This is the offset from the frame pointer register to the first stack slot
1158 that contains a variable living in the frame. */
1161 avr_starting_frame_offset (void)
1163 return 1 + avr_outgoing_args_size ();
1167 /* Return the number of hard registers to push/pop in the prologue/epilogue
1168 of the current function, and optionally store these registers in SET. */
1171 avr_regs_to_save (HARD_REG_SET
*set
)
1174 int int_or_sig_p
= cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
;
1177 CLEAR_HARD_REG_SET (*set
);
1180 /* No need to save any registers if the function never returns or
1181 has the "OS_task" or "OS_main" attribute. */
1183 if (TREE_THIS_VOLATILE (current_function_decl
)
1184 || cfun
->machine
->is_OS_task
1185 || cfun
->machine
->is_OS_main
)
1188 for (int reg
= 0; reg
< 32; reg
++)
1190 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
1191 any global register variables. */
1193 if (fixed_regs
[reg
])
1196 if ((int_or_sig_p
&& !crtl
->is_leaf
&& call_used_regs
[reg
])
1197 || (df_regs_ever_live_p (reg
)
1198 && (int_or_sig_p
|| !call_used_regs
[reg
])
1199 /* Don't record frame pointer registers here. They are treated
1200 indivitually in prologue. */
1201 && !(frame_pointer_needed
1202 && (reg
== REG_Y
|| reg
== REG_Y
+ 1))))
1205 SET_HARD_REG_BIT (*set
, reg
);
1213 /* Implement `TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS' */
1216 avr_allocate_stack_slots_for_args (void)
1218 return !cfun
->machine
->is_naked
;
1222 /* Return true if register FROM can be eliminated via register TO. */
1225 avr_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to
)
1227 return ((frame_pointer_needed
&& to
== FRAME_POINTER_REGNUM
)
1228 || !frame_pointer_needed
);
1232 /* Implement `TARGET_WARN_FUNC_RETURN'. */
1235 avr_warn_func_return (tree decl
)
1237 /* Naked functions are implemented entirely in assembly, including the
1238 return sequence, so suppress warnings about this. */
1240 return !avr_naked_function_p (decl
);
1243 /* Compute offset between arg_pointer and frame_pointer. */
1246 avr_initial_elimination_offset (int from
, int to
)
1248 if (from
== FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
1252 int offset
= frame_pointer_needed
? 2 : 0;
1253 int avr_pc_size
= AVR_HAVE_EIJMP_EICALL
? 3 : 2;
1255 // If FROM is ARG_POINTER_REGNUM, we are not in an ISR as ISRs
1256 // might not have arguments. Hence the following is not affected
1257 // by gasisr prologues.
1258 offset
+= avr_regs_to_save (NULL
);
1259 return (get_frame_size () + avr_outgoing_args_size()
1260 + avr_pc_size
+ 1 + offset
);
1265 /* Helper for the function below. */
1268 avr_adjust_type_node (tree
*node
, machine_mode mode
, int sat_p
)
1270 *node
= make_node (FIXED_POINT_TYPE
);
1271 TYPE_SATURATING (*node
) = sat_p
;
1272 TYPE_UNSIGNED (*node
) = UNSIGNED_FIXED_POINT_MODE_P (mode
);
1273 TYPE_IBIT (*node
) = GET_MODE_IBIT (mode
);
1274 TYPE_FBIT (*node
) = GET_MODE_FBIT (mode
);
1275 TYPE_PRECISION (*node
) = GET_MODE_BITSIZE (mode
);
1276 SET_TYPE_ALIGN (*node
, 8);
1277 SET_TYPE_MODE (*node
, mode
);
1279 layout_type (*node
);
1283 /* Implement `TARGET_BUILD_BUILTIN_VA_LIST'. */
1286 avr_build_builtin_va_list (void)
1288 /* avr-modes.def adjusts [U]TA to be 64-bit modes with 48 fractional bits.
1289 This is more appropriate for the 8-bit machine AVR than 128-bit modes.
1290 The ADJUST_IBIT/FBIT are handled in toplev:init_adjust_machine_modes()
1291 which is auto-generated by genmodes, but the compiler assigns [U]DAmode
1292 to the long long accum modes instead of the desired [U]TAmode.
1294 Fix this now, right after node setup in tree.c:build_common_tree_nodes().
1295 This must run before c-cppbuiltin.c:builtin_define_fixed_point_constants()
1296 which built-in defines macros like __ULLACCUM_FBIT__ that are used by
1297 libgcc to detect IBIT and FBIT. */
1299 avr_adjust_type_node (&ta_type_node
, TAmode
, 0);
1300 avr_adjust_type_node (&uta_type_node
, UTAmode
, 0);
1301 avr_adjust_type_node (&sat_ta_type_node
, TAmode
, 1);
1302 avr_adjust_type_node (&sat_uta_type_node
, UTAmode
, 1);
1304 unsigned_long_long_accum_type_node
= uta_type_node
;
1305 long_long_accum_type_node
= ta_type_node
;
1306 sat_unsigned_long_long_accum_type_node
= sat_uta_type_node
;
1307 sat_long_long_accum_type_node
= sat_ta_type_node
;
1309 /* Dispatch to the default handler. */
1311 return std_build_builtin_va_list ();
1315 /* Implement `TARGET_BUILTIN_SETJMP_FRAME_VALUE'. */
1316 /* Actual start of frame is virtual_stack_vars_rtx this is offset from
1317 frame pointer by +STARTING_FRAME_OFFSET.
1318 Using saved frame = virtual_stack_vars_rtx - STARTING_FRAME_OFFSET
1319 avoids creating add/sub of offset in nonlocal goto and setjmp. */
1322 avr_builtin_setjmp_frame_value (void)
1324 rtx xval
= gen_reg_rtx (Pmode
);
1325 emit_insn (gen_subhi3 (xval
, virtual_stack_vars_rtx
,
1326 gen_int_mode (STARTING_FRAME_OFFSET
, Pmode
)));
1331 /* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3-byte PC).
1332 This is return address of function. */
1335 avr_return_addr_rtx (int count
, rtx tem
)
1339 /* Can only return this function's return address. Others not supported. */
1345 r
= gen_rtx_SYMBOL_REF (Pmode
, ".L__stack_usage+2");
1346 warning (0, "%<builtin_return_address%> contains only 2 bytes"
1350 r
= gen_rtx_SYMBOL_REF (Pmode
, ".L__stack_usage+1");
1352 cfun
->machine
->use_L__stack_usage
= 1;
1354 r
= gen_rtx_PLUS (Pmode
, tem
, r
);
1355 r
= gen_frame_mem (Pmode
, memory_address (Pmode
, r
));
1356 r
= gen_rtx_ROTATE (HImode
, r
, GEN_INT (8));
1360 /* Return 1 if the function epilogue is just a single "ret". */
1363 avr_simple_epilogue (void)
1365 return (! frame_pointer_needed
1366 && get_frame_size () == 0
1367 && avr_outgoing_args_size() == 0
1368 && avr_regs_to_save (NULL
) == 0
1369 && ! cfun
->machine
->is_interrupt
1370 && ! cfun
->machine
->is_signal
1371 && ! cfun
->machine
->is_naked
1372 && ! TREE_THIS_VOLATILE (current_function_decl
));
1375 /* This function checks sequence of live registers. */
1378 sequent_regs_live (void)
1383 for (int reg
= 0; reg
<= LAST_CALLEE_SAVED_REG
; ++reg
)
1385 if (fixed_regs
[reg
])
1387 /* Don't recognize sequences that contain global register
1396 if (!call_used_regs
[reg
])
1398 if (df_regs_ever_live_p (reg
))
1408 if (!frame_pointer_needed
)
1410 if (df_regs_ever_live_p (REG_Y
))
1418 if (df_regs_ever_live_p (REG_Y
+ 1))
1431 return (cur_seq
== live_seq
) ? live_seq
: 0;
1435 static const pass_data avr_pass_data_pre_proep
=
1438 "", // name (will be patched)
1439 OPTGROUP_NONE
, // optinfo_flags
1440 TV_DF_SCAN
, // tv_id
1441 0, // properties_required
1442 0, // properties_provided
1443 0, // properties_destroyed
1444 0, // todo_flags_start
1445 0 // todo_flags_finish
1449 class avr_pass_pre_proep
: public rtl_opt_pass
1452 avr_pass_pre_proep (gcc::context
*ctxt
, const char *name
)
1453 : rtl_opt_pass (avr_pass_data_pre_proep
, ctxt
)
1458 void compute_maybe_gasisr (function
*);
1460 virtual unsigned int execute (function
*fun
)
1462 if (avr_gasisr_prologues
1463 // Whether this function is an ISR worth scanning at all.
1464 && !fun
->machine
->is_no_gccisr
1465 && (fun
->machine
->is_interrupt
1466 || fun
->machine
->is_signal
)
1467 && !cfun
->machine
->is_naked
1468 // Paranoia: Non-local gotos and labels that might escape.
1469 && !cfun
->calls_setjmp
1470 && !cfun
->has_nonlocal_label
1471 && !cfun
->has_forced_label_in_static
)
1473 compute_maybe_gasisr (fun
);
1479 }; // avr_pass_pre_proep
1484 make_avr_pass_pre_proep (gcc::context
*ctxt
)
1486 return new avr_pass_pre_proep (ctxt
, "avr-pre-proep");
1490 /* Set fun->machine->gasisr.maybe provided we don't find anything that
1491 prohibits GAS generating parts of ISR prologues / epilogues for us. */
1494 avr_pass_pre_proep::compute_maybe_gasisr (function
*fun
)
1496 // Don't use BB iterators so that we see JUMP_TABLE_DATA.
1498 for (rtx_insn
*insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
1500 // Transparent calls always use [R]CALL and are filtered out by GAS.
1501 // ISRs don't use -mcall-prologues, hence what remains to be filtered
1502 // out are open coded (tail) calls.
1507 // __tablejump2__ clobbers something and is targeted by JMP so
1508 // that GAS won't see its usage.
1510 if (AVR_HAVE_JMP_CALL
1511 && JUMP_TABLE_DATA_P (insn
))
1514 // Non-local gotos not seen in *FUN.
1517 && find_reg_note (insn
, REG_NON_LOCAL_GOTO
, NULL_RTX
))
1521 fun
->machine
->gasisr
.maybe
= 1;
1525 /* Obtain the length sequence of insns. */
1528 get_sequence_length (rtx_insn
*insns
)
1532 for (rtx_insn
*insn
= insns
; insn
; insn
= NEXT_INSN (insn
))
1533 length
+= get_attr_length (insn
);
1539 /* Implement `INCOMING_RETURN_ADDR_RTX'. */
1542 avr_incoming_return_addr_rtx (void)
1544 /* The return address is at the top of the stack. Note that the push
1545 was via post-decrement, which means the actual address is off by one. */
1546 return gen_frame_mem (HImode
, plus_constant (Pmode
, stack_pointer_rtx
, 1));
1550 /* Unset a bit in *SET. If successful, return the respective bit number.
1551 Otherwise, return -1 and *SET is unaltered. */
1554 avr_hregs_split_reg (HARD_REG_SET
*set
)
1556 for (int regno
= 0; regno
< 32; regno
++)
1557 if (TEST_HARD_REG_BIT (*set
, regno
))
1559 // Don't remove a register from *SET which might indicate that
1560 // some RAMP* register might need ISR prologue / epilogue treatment.
1563 && (REG_X
== regno
|| REG_X
+ 1 == regno
)
1564 && TEST_HARD_REG_BIT (*set
, REG_X
)
1565 && TEST_HARD_REG_BIT (*set
, REG_X
+ 1))
1569 && !frame_pointer_needed
1570 && (REG_Y
== regno
|| REG_Y
+ 1 == regno
)
1571 && TEST_HARD_REG_BIT (*set
, REG_Y
)
1572 && TEST_HARD_REG_BIT (*set
, REG_Y
+ 1))
1576 && (REG_Z
== regno
|| REG_Z
+ 1 == regno
)
1577 && TEST_HARD_REG_BIT (*set
, REG_Z
)
1578 && TEST_HARD_REG_BIT (*set
, REG_Z
+ 1))
1581 CLEAR_HARD_REG_BIT (*set
, regno
);
1589 /* Helper for expand_prologue. Emit a push of a byte register. */
1592 emit_push_byte (unsigned regno
, bool frame_related_p
)
1597 mem
= gen_rtx_POST_DEC (HImode
, stack_pointer_rtx
);
1598 mem
= gen_frame_mem (QImode
, mem
);
1599 reg
= gen_rtx_REG (QImode
, regno
);
1601 insn
= emit_insn (gen_rtx_SET (mem
, reg
));
1602 if (frame_related_p
)
1603 RTX_FRAME_RELATED_P (insn
) = 1;
1605 cfun
->machine
->stack_usage
++;
1609 /* Helper for expand_prologue. Emit a push of a SFR via register TREG.
1610 SFR is a MEM representing the memory location of the SFR.
1611 If CLR_P then clear the SFR after the push using zero_reg. */
1614 emit_push_sfr (rtx sfr
, bool frame_related_p
, bool clr_p
, int treg
)
1618 gcc_assert (MEM_P (sfr
));
1620 /* IN treg, IO(SFR) */
1621 insn
= emit_move_insn (all_regs_rtx
[treg
], sfr
);
1622 if (frame_related_p
)
1623 RTX_FRAME_RELATED_P (insn
) = 1;
1626 emit_push_byte (treg
, frame_related_p
);
1630 /* OUT IO(SFR), __zero_reg__ */
1631 insn
= emit_move_insn (sfr
, const0_rtx
);
1632 if (frame_related_p
)
1633 RTX_FRAME_RELATED_P (insn
) = 1;
1638 avr_prologue_setup_frame (HOST_WIDE_INT size
, HARD_REG_SET set
)
1641 bool isr_p
= cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
;
1642 int live_seq
= sequent_regs_live ();
1644 HOST_WIDE_INT size_max
1645 = (HOST_WIDE_INT
) GET_MODE_MASK (AVR_HAVE_8BIT_SP
? QImode
: Pmode
);
1647 bool minimize
= (TARGET_CALL_PROLOGUES
1651 && !cfun
->machine
->is_OS_task
1652 && !cfun
->machine
->is_OS_main
1656 && (frame_pointer_needed
1657 || avr_outgoing_args_size() > 8
1658 || (AVR_2_BYTE_PC
&& live_seq
> 6)
1662 int first_reg
, reg
, offset
;
1664 emit_move_insn (gen_rtx_REG (HImode
, REG_X
),
1665 gen_int_mode (size
, HImode
));
1667 pattern
= gen_call_prologue_saves (gen_int_mode (live_seq
, HImode
),
1668 gen_int_mode (live_seq
+size
, HImode
));
1669 insn
= emit_insn (pattern
);
1670 RTX_FRAME_RELATED_P (insn
) = 1;
1672 /* Describe the effect of the unspec_volatile call to prologue_saves.
1673 Note that this formulation assumes that add_reg_note pushes the
1674 notes to the front. Thus we build them in the reverse order of
1675 how we want dwarf2out to process them. */
1677 /* The function does always set frame_pointer_rtx, but whether that
1678 is going to be permanent in the function is frame_pointer_needed. */
1680 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
1681 gen_rtx_SET ((frame_pointer_needed
1683 : stack_pointer_rtx
),
1684 plus_constant (Pmode
, stack_pointer_rtx
,
1685 -(size
+ live_seq
))));
1687 /* Note that live_seq always contains r28+r29, but the other
1688 registers to be saved are all below 18. */
1690 first_reg
= (LAST_CALLEE_SAVED_REG
+ 1) - (live_seq
- 2);
1692 for (reg
= 29, offset
= -live_seq
+ 1;
1694 reg
= (reg
== 28 ? LAST_CALLEE_SAVED_REG
: reg
- 1), ++offset
)
1698 m
= gen_rtx_MEM (QImode
, plus_constant (Pmode
, stack_pointer_rtx
,
1700 r
= gen_rtx_REG (QImode
, reg
);
1701 add_reg_note (insn
, REG_CFA_OFFSET
, gen_rtx_SET (m
, r
));
1704 cfun
->machine
->stack_usage
+= size
+ live_seq
;
1706 else /* !minimize */
1708 for (int reg
= 0; reg
< 32; ++reg
)
1709 if (TEST_HARD_REG_BIT (set
, reg
))
1710 emit_push_byte (reg
, true);
1712 if (frame_pointer_needed
1713 && (!(cfun
->machine
->is_OS_task
|| cfun
->machine
->is_OS_main
)))
1715 /* Push frame pointer. Always be consistent about the
1716 ordering of pushes -- epilogue_restores expects the
1717 register pair to be pushed low byte first. */
1719 emit_push_byte (REG_Y
, true);
1720 emit_push_byte (REG_Y
+ 1, true);
1723 if (frame_pointer_needed
1726 insn
= emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
1727 RTX_FRAME_RELATED_P (insn
) = 1;
1732 /* Creating a frame can be done by direct manipulation of the
1733 stack or via the frame pointer. These two methods are:
1740 the optimum method depends on function type, stack and
1741 frame size. To avoid a complex logic, both methods are
1742 tested and shortest is selected.
1744 There is also the case where SIZE != 0 and no frame pointer is
1745 needed; this can occur if ACCUMULATE_OUTGOING_ARGS is on.
1746 In that case, insn (*) is not needed in that case.
1747 We use the X register as scratch. This is save because in X
1749 In an interrupt routine, the case of SIZE != 0 together with
1750 !frame_pointer_needed can only occur if the function is not a
1751 leaf function and thus X has already been saved. */
1754 HOST_WIDE_INT size_cfa
= size
, neg_size
;
1755 rtx_insn
*fp_plus_insns
;
1758 gcc_assert (frame_pointer_needed
1762 fp
= my_fp
= (frame_pointer_needed
1764 : gen_rtx_REG (Pmode
, REG_X
));
1766 if (AVR_HAVE_8BIT_SP
)
1768 /* The high byte (r29) does not change:
1769 Prefer SUBI (1 cycle) over SBIW (2 cycles, same size). */
1771 my_fp
= all_regs_rtx
[FRAME_POINTER_REGNUM
];
1774 /* Cut down size and avoid size = 0 so that we don't run
1775 into ICE like PR52488 in the remainder. */
1777 if (size
> size_max
)
1779 /* Don't error so that insane code from newlib still compiles
1780 and does not break building newlib. As PR51345 is implemented
1781 now, there are multilib variants with -msp8.
1783 If user wants sanity checks he can use -Wstack-usage=
1786 For CFA we emit the original, non-saturated size so that
1787 the generic machinery is aware of the real stack usage and
1788 will print the above diagnostic as expected. */
1793 size
= trunc_int_for_mode (size
, GET_MODE (my_fp
));
1794 neg_size
= trunc_int_for_mode (-size
, GET_MODE (my_fp
));
1796 /************ Method 1: Adjust frame pointer ************/
1800 /* Normally, the dwarf2out frame-related-expr interpreter does
1801 not expect to have the CFA change once the frame pointer is
1802 set up. Thus, we avoid marking the move insn below and
1803 instead indicate that the entire operation is complete after
1804 the frame pointer subtraction is done. */
1806 insn
= emit_move_insn (fp
, stack_pointer_rtx
);
1807 if (frame_pointer_needed
)
1809 RTX_FRAME_RELATED_P (insn
) = 1;
1810 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
1811 gen_rtx_SET (fp
, stack_pointer_rtx
));
1814 insn
= emit_move_insn (my_fp
, plus_constant (GET_MODE (my_fp
),
1817 if (frame_pointer_needed
)
1819 RTX_FRAME_RELATED_P (insn
) = 1;
1820 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
1821 gen_rtx_SET (fp
, plus_constant (Pmode
, fp
,
1825 /* Copy to stack pointer. Note that since we've already
1826 changed the CFA to the frame pointer this operation
1827 need not be annotated if frame pointer is needed.
1828 Always move through unspec, see PR50063.
1829 For meaning of irq_state see movhi_sp_r insn. */
1831 if (cfun
->machine
->is_interrupt
)
1834 if (TARGET_NO_INTERRUPTS
1835 || cfun
->machine
->is_signal
1836 || cfun
->machine
->is_OS_main
)
1839 if (AVR_HAVE_8BIT_SP
)
1842 insn
= emit_insn (gen_movhi_sp_r (stack_pointer_rtx
,
1843 fp
, GEN_INT (irq_state
)));
1844 if (!frame_pointer_needed
)
1846 RTX_FRAME_RELATED_P (insn
) = 1;
1847 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
1848 gen_rtx_SET (stack_pointer_rtx
,
1849 plus_constant (Pmode
,
1854 fp_plus_insns
= get_insns ();
1857 /************ Method 2: Adjust Stack pointer ************/
1859 /* Stack adjustment by means of RCALL . and/or PUSH __TMP_REG__
1860 can only handle specific offsets. */
1862 int n_rcall
= size
/ (AVR_3_BYTE_PC
? 3 : 2);
1864 if (avr_sp_immediate_operand (gen_int_mode (-size
, HImode
), HImode
)
1865 // Don't use more than 3 RCALLs.
1868 rtx_insn
*sp_plus_insns
;
1872 insn
= emit_move_insn (stack_pointer_rtx
,
1873 plus_constant (Pmode
, stack_pointer_rtx
,
1875 RTX_FRAME_RELATED_P (insn
) = 1;
1876 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
1877 gen_rtx_SET (stack_pointer_rtx
,
1878 plus_constant (Pmode
,
1881 if (frame_pointer_needed
)
1883 insn
= emit_move_insn (fp
, stack_pointer_rtx
);
1884 RTX_FRAME_RELATED_P (insn
) = 1;
1887 sp_plus_insns
= get_insns ();
1890 /************ Use shortest method ************/
1892 emit_insn (get_sequence_length (sp_plus_insns
)
1893 < get_sequence_length (fp_plus_insns
)
1899 emit_insn (fp_plus_insns
);
1902 cfun
->machine
->stack_usage
+= size_cfa
;
1903 } /* !minimize && size != 0 */
1908 /* Output function prologue. */
1911 avr_expand_prologue (void)
1916 size
= get_frame_size() + avr_outgoing_args_size();
1918 cfun
->machine
->stack_usage
= 0;
1920 /* Prologue: naked. */
1921 if (cfun
->machine
->is_naked
)
1926 avr_regs_to_save (&set
);
1928 if (cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
)
1930 int treg
= AVR_TMP_REGNO
;
1931 /* Enable interrupts. */
1932 if (cfun
->machine
->is_interrupt
)
1933 emit_insn (gen_enable_interrupt ());
1935 if (cfun
->machine
->gasisr
.maybe
)
1937 /* Let GAS PR21472 emit prologue preamble for us which handles SREG,
1938 ZERO_REG and TMP_REG and one additional, optional register for
1939 us in an optimal way. This even scans through inline asm. */
1941 cfun
->machine
->gasisr
.yes
= 1;
1943 // The optional reg or TMP_REG if we don't need one. If we need one,
1944 // remove that reg from SET so that it's not puhed / popped twice.
1945 // We also use it below instead of TMP_REG in some places.
1947 treg
= avr_hregs_split_reg (&set
);
1949 treg
= AVR_TMP_REGNO
;
1950 cfun
->machine
->gasisr
.regno
= treg
;
1952 // The worst case of pushes. The exact number can be inferred
1953 // at assembly time by magic expression __gcc_isr.n_pushed.
1954 cfun
->machine
->stack_usage
+= 3 + (treg
!= AVR_TMP_REGNO
);
1956 // Emit a Prologue chunk. Epilogue chunk(s) might follow.
1957 // The final Done chunk is emit by final postscan.
1958 emit_insn (gen_gasisr (GEN_INT (GASISR_Prologue
), GEN_INT (treg
)));
1960 else // !TARGET_GASISR_PROLOGUES: Classic, dumb prologue preamble.
1962 /* Push zero reg. */
1963 emit_push_byte (AVR_ZERO_REGNO
, true);
1966 emit_push_byte (AVR_TMP_REGNO
, true);
1969 /* ??? There's no dwarf2 column reserved for SREG. */
1970 emit_push_sfr (sreg_rtx
, false, false /* clr */, AVR_TMP_REGNO
);
1972 /* Clear zero reg. */
1973 emit_move_insn (zero_reg_rtx
, const0_rtx
);
1975 /* Prevent any attempt to delete the setting of ZERO_REG! */
1976 emit_use (zero_reg_rtx
);
1979 /* Push and clear RAMPD/X/Y/Z if present and low-part register is used.
1980 ??? There are no dwarf2 columns reserved for RAMPD/X/Y/Z. */
1983 emit_push_sfr (rampd_rtx
, false /* frame */, true /* clr */, treg
);
1986 && TEST_HARD_REG_BIT (set
, REG_X
)
1987 && TEST_HARD_REG_BIT (set
, REG_X
+ 1))
1989 emit_push_sfr (rampx_rtx
, false /* frame */, true /* clr */, treg
);
1993 && (frame_pointer_needed
1994 || (TEST_HARD_REG_BIT (set
, REG_Y
)
1995 && TEST_HARD_REG_BIT (set
, REG_Y
+ 1))))
1997 emit_push_sfr (rampy_rtx
, false /* frame */, true /* clr */, treg
);
2001 && TEST_HARD_REG_BIT (set
, REG_Z
)
2002 && TEST_HARD_REG_BIT (set
, REG_Z
+ 1))
2004 emit_push_sfr (rampz_rtx
, false /* frame */, AVR_HAVE_RAMPD
, treg
);
2006 } /* is_interrupt is_signal */
2008 avr_prologue_setup_frame (size
, set
);
2010 if (flag_stack_usage_info
)
2011 current_function_static_stack_size
2012 = cfun
->machine
->stack_usage
+ INCOMING_FRAME_SP_OFFSET
;
2016 /* Implement `TARGET_ASM_FUNCTION_END_PROLOGUE'. */
2017 /* Output summary at end of function prologue. */
2020 avr_asm_function_end_prologue (FILE *file
)
2022 if (cfun
->machine
->is_naked
)
2024 fputs ("/* prologue: naked */\n", file
);
2028 if (cfun
->machine
->is_interrupt
)
2030 fputs ("/* prologue: Interrupt */\n", file
);
2032 else if (cfun
->machine
->is_signal
)
2034 fputs ("/* prologue: Signal */\n", file
);
2037 fputs ("/* prologue: function */\n", file
);
2040 if (ACCUMULATE_OUTGOING_ARGS
)
2041 fprintf (file
, "/* outgoing args size = %d */\n",
2042 avr_outgoing_args_size());
2044 fprintf (file
, "/* frame size = " HOST_WIDE_INT_PRINT_DEC
" */\n",
2047 if (!cfun
->machine
->gasisr
.yes
)
2049 fprintf (file
, "/* stack size = %d */\n", cfun
->machine
->stack_usage
);
2050 // Create symbol stack offset so all functions have it. Add 1 to stack
2051 // usage for offset so that SP + .L__stack_offset = return address.
2052 fprintf (file
, ".L__stack_usage = %d\n", cfun
->machine
->stack_usage
);
2056 int used_by_gasisr
= 3 + (cfun
->machine
->gasisr
.regno
!= AVR_TMP_REGNO
);
2057 int to
= cfun
->machine
->stack_usage
;
2058 int from
= to
- used_by_gasisr
;
2059 // Number of pushed regs is only known at assembly-time.
2060 fprintf (file
, "/* stack size = %d...%d */\n", from
, to
);
2061 fprintf (file
, ".L__stack_usage = %d + __gcc_isr.n_pushed\n", from
);
2066 /* Implement `EPILOGUE_USES'. */
2069 avr_epilogue_uses (int regno ATTRIBUTE_UNUSED
)
2071 if (reload_completed
2073 && (cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
))
2078 /* Helper for avr_expand_epilogue. Emit a pop of a byte register. */
2081 emit_pop_byte (unsigned regno
)
2085 mem
= gen_rtx_PRE_INC (HImode
, stack_pointer_rtx
);
2086 mem
= gen_frame_mem (QImode
, mem
);
2087 reg
= gen_rtx_REG (QImode
, regno
);
2089 emit_insn (gen_rtx_SET (reg
, mem
));
2092 /* Output RTL epilogue. */
2095 avr_expand_epilogue (bool sibcall_p
)
2101 bool isr_p
= cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
;
2103 size
= get_frame_size() + avr_outgoing_args_size();
2105 /* epilogue: naked */
2106 if (cfun
->machine
->is_naked
)
2108 gcc_assert (!sibcall_p
);
2110 emit_jump_insn (gen_return ());
2114 avr_regs_to_save (&set
);
2115 live_seq
= sequent_regs_live ();
2117 minimize
= (TARGET_CALL_PROLOGUES
2120 && !cfun
->machine
->is_OS_task
2121 && !cfun
->machine
->is_OS_main
2126 || frame_pointer_needed
2129 /* Get rid of frame. */
2131 if (!frame_pointer_needed
)
2133 emit_move_insn (frame_pointer_rtx
, stack_pointer_rtx
);
2138 emit_move_insn (frame_pointer_rtx
,
2139 plus_constant (Pmode
, frame_pointer_rtx
, size
));
2142 emit_insn (gen_epilogue_restores (gen_int_mode (live_seq
, HImode
)));
2148 /* Try two methods to adjust stack and select shortest. */
2152 rtx_insn
*fp_plus_insns
;
2153 HOST_WIDE_INT size_max
;
2155 gcc_assert (frame_pointer_needed
2159 fp
= my_fp
= (frame_pointer_needed
2161 : gen_rtx_REG (Pmode
, REG_X
));
2163 if (AVR_HAVE_8BIT_SP
)
2165 /* The high byte (r29) does not change:
2166 Prefer SUBI (1 cycle) over SBIW (2 cycles). */
2168 my_fp
= all_regs_rtx
[FRAME_POINTER_REGNUM
];
2171 /* For rationale see comment in prologue generation. */
2173 size_max
= (HOST_WIDE_INT
) GET_MODE_MASK (GET_MODE (my_fp
));
2174 if (size
> size_max
)
2176 size
= trunc_int_for_mode (size
, GET_MODE (my_fp
));
2178 /********** Method 1: Adjust fp register **********/
2182 if (!frame_pointer_needed
)
2183 emit_move_insn (fp
, stack_pointer_rtx
);
2185 emit_move_insn (my_fp
, plus_constant (GET_MODE (my_fp
), my_fp
, size
));
2187 /* Copy to stack pointer. */
2189 if (TARGET_NO_INTERRUPTS
)
2192 if (AVR_HAVE_8BIT_SP
)
2195 emit_insn (gen_movhi_sp_r (stack_pointer_rtx
, fp
,
2196 GEN_INT (irq_state
)));
2198 fp_plus_insns
= get_insns ();
2201 /********** Method 2: Adjust Stack pointer **********/
2203 if (avr_sp_immediate_operand (gen_int_mode (size
, HImode
), HImode
))
2205 rtx_insn
*sp_plus_insns
;
2209 emit_move_insn (stack_pointer_rtx
,
2210 plus_constant (Pmode
, stack_pointer_rtx
, size
));
2212 sp_plus_insns
= get_insns ();
2215 /************ Use shortest method ************/
2217 emit_insn (get_sequence_length (sp_plus_insns
)
2218 < get_sequence_length (fp_plus_insns
)
2223 emit_insn (fp_plus_insns
);
2226 if (frame_pointer_needed
2227 && !(cfun
->machine
->is_OS_task
|| cfun
->machine
->is_OS_main
))
2229 /* Restore previous frame_pointer. See avr_expand_prologue for
2230 rationale for not using pophi. */
2232 emit_pop_byte (REG_Y
+ 1);
2233 emit_pop_byte (REG_Y
);
2236 /* Restore used registers. */
2238 int treg
= AVR_TMP_REGNO
;
2241 && cfun
->machine
->gasisr
.yes
)
2243 treg
= cfun
->machine
->gasisr
.regno
;
2244 CLEAR_HARD_REG_BIT (set
, treg
);
2247 for (int reg
= 31; reg
>= 0; --reg
)
2248 if (TEST_HARD_REG_BIT (set
, reg
))
2249 emit_pop_byte (reg
);
2253 /* Restore RAMPZ/Y/X/D using tmp_reg as scratch.
2254 The conditions to restore them must be tha same as in prologue. */
2257 && TEST_HARD_REG_BIT (set
, REG_Z
)
2258 && TEST_HARD_REG_BIT (set
, REG_Z
+ 1))
2260 emit_pop_byte (treg
);
2261 emit_move_insn (rampz_rtx
, all_regs_rtx
[treg
]);
2265 && (frame_pointer_needed
2266 || (TEST_HARD_REG_BIT (set
, REG_Y
)
2267 && TEST_HARD_REG_BIT (set
, REG_Y
+ 1))))
2269 emit_pop_byte (treg
);
2270 emit_move_insn (rampy_rtx
, all_regs_rtx
[treg
]);
2274 && TEST_HARD_REG_BIT (set
, REG_X
)
2275 && TEST_HARD_REG_BIT (set
, REG_X
+ 1))
2277 emit_pop_byte (treg
);
2278 emit_move_insn (rampx_rtx
, all_regs_rtx
[treg
]);
2283 emit_pop_byte (treg
);
2284 emit_move_insn (rampd_rtx
, all_regs_rtx
[treg
]);
2287 if (cfun
->machine
->gasisr
.yes
)
2289 // Emit an Epilogue chunk.
2290 emit_insn (gen_gasisr (GEN_INT (GASISR_Epilogue
),
2291 GEN_INT (cfun
->machine
->gasisr
.regno
)));
2293 else // !TARGET_GASISR_PROLOGUES
2295 /* Restore SREG using tmp_reg as scratch. */
2297 emit_pop_byte (AVR_TMP_REGNO
);
2298 emit_move_insn (sreg_rtx
, tmp_reg_rtx
);
2300 /* Restore tmp REG. */
2301 emit_pop_byte (AVR_TMP_REGNO
);
2303 /* Restore zero REG. */
2304 emit_pop_byte (AVR_ZERO_REGNO
);
2309 emit_jump_insn (gen_return ());
2313 /* Implement `TARGET_ASM_FUNCTION_BEGIN_EPILOGUE'. */
2316 avr_asm_function_begin_epilogue (FILE *file
)
2319 fprintf (file
, "/* epilogue start */\n");
2323 /* Implement `TARGET_CANNOT_MODITY_JUMPS_P'. */
2326 avr_cannot_modify_jumps_p (void)
2328 /* Naked Functions must not have any instructions after
2329 their epilogue, see PR42240 */
2331 if (reload_completed
2333 && cfun
->machine
->is_naked
)
2342 /* Implement `TARGET_MODE_DEPENDENT_ADDRESS_P'. */
2345 avr_mode_dependent_address_p (const_rtx addr ATTRIBUTE_UNUSED
, addr_space_t as
)
2347 /* FIXME: Non-generic addresses are not mode-dependent in themselves.
2348 This hook just serves to hack around PR rtl-optimization/52543 by
2349 claiming that non-generic addresses were mode-dependent so that
2350 lower-subreg.c will skip these addresses. lower-subreg.c sets up fake
2351 RTXes to probe SET and MEM costs and assumes that MEM is always in the
2352 generic address space which is not true. */
2354 return !ADDR_SPACE_GENERIC_P (as
);
2358 /* Return true if rtx X is a CONST_INT, CONST or SYMBOL_REF
2359 address with the `absdata' variable attribute, i.e. respective
2360 data can be read / written by LDS / STS instruction.
2361 This is used only for AVR_TINY. */
2364 avr_address_tiny_absdata_p (rtx x
, machine_mode mode
)
2366 if (CONST
== GET_CODE (x
))
2367 x
= XEXP (XEXP (x
, 0), 0);
2369 if (SYMBOL_REF_P (x
))
2370 return SYMBOL_REF_FLAGS (x
) & AVR_SYMBOL_FLAG_TINY_ABSDATA
;
2373 && IN_RANGE (INTVAL (x
), 0, 0xc0 - GET_MODE_SIZE (mode
)))
2380 /* Helper function for `avr_legitimate_address_p'. */
2383 avr_reg_ok_for_addr_p (rtx reg
, addr_space_t as
,
2384 RTX_CODE outer_code
, bool strict
)
2387 && (avr_regno_mode_code_ok_for_base_p (REGNO (reg
), QImode
,
2388 as
, outer_code
, UNKNOWN
)
2390 && REGNO (reg
) >= FIRST_PSEUDO_REGISTER
)));
2394 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
2395 machine for a memory operand of mode MODE. */
2398 avr_legitimate_address_p (machine_mode mode
, rtx x
, bool strict
)
2400 bool ok
= CONSTANT_ADDRESS_P (x
);
2402 switch (GET_CODE (x
))
2405 ok
= avr_reg_ok_for_addr_p (x
, ADDR_SPACE_GENERIC
,
2409 && GET_MODE_SIZE (mode
) > 4
2410 && REG_X
== REGNO (x
))
2418 ok
= avr_reg_ok_for_addr_p (XEXP (x
, 0), ADDR_SPACE_GENERIC
,
2419 GET_CODE (x
), strict
);
2424 rtx reg
= XEXP (x
, 0);
2425 rtx op1
= XEXP (x
, 1);
2428 && CONST_INT_P (op1
)
2429 && INTVAL (op1
) >= 0)
2431 bool fit
= IN_RANGE (INTVAL (op1
), 0, MAX_LD_OFFSET (mode
));
2436 || avr_reg_ok_for_addr_p (reg
, ADDR_SPACE_GENERIC
,
2439 if (reg
== frame_pointer_rtx
2440 || reg
== arg_pointer_rtx
)
2445 else if (frame_pointer_needed
2446 && reg
== frame_pointer_rtx
)
2459 && CONSTANT_ADDRESS_P (x
))
2461 /* avrtiny's load / store instructions only cover addresses 0..0xbf:
2462 IN / OUT range is 0..0x3f and LDS / STS can access 0x40..0xbf. */
2464 ok
= avr_address_tiny_absdata_p (x
, mode
);
2467 if (avr_log
.legitimate_address_p
)
2469 avr_edump ("\n%?: ret=%d, mode=%m strict=%d "
2470 "reload_completed=%d reload_in_progress=%d %s:",
2471 ok
, mode
, strict
, reload_completed
, reload_in_progress
,
2472 reg_renumber
? "(reg_renumber)" : "");
2474 if (GET_CODE (x
) == PLUS
2475 && REG_P (XEXP (x
, 0))
2476 && CONST_INT_P (XEXP (x
, 1))
2477 && IN_RANGE (INTVAL (XEXP (x
, 1)), 0, MAX_LD_OFFSET (mode
))
2480 avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x
, 0)),
2481 true_regnum (XEXP (x
, 0)));
2484 avr_edump ("\n%r\n", x
);
2491 /* Former implementation of TARGET_LEGITIMIZE_ADDRESS,
2492 now only a helper for avr_addr_space_legitimize_address. */
2493 /* Attempts to replace X with a valid
2494 memory address for an operand of mode MODE */
2497 avr_legitimize_address (rtx x
, rtx oldx
, machine_mode mode
)
2499 bool big_offset_p
= false;
2505 if (CONSTANT_ADDRESS_P (x
)
2506 && ! avr_address_tiny_absdata_p (x
, mode
))
2508 x
= force_reg (Pmode
, x
);
2512 if (GET_CODE (oldx
) == PLUS
2513 && REG_P (XEXP (oldx
, 0)))
2515 if (REG_P (XEXP (oldx
, 1)))
2516 x
= force_reg (GET_MODE (oldx
), oldx
);
2517 else if (CONST_INT_P (XEXP (oldx
, 1)))
2519 int offs
= INTVAL (XEXP (oldx
, 1));
2520 if (frame_pointer_rtx
!= XEXP (oldx
, 0)
2521 && offs
> MAX_LD_OFFSET (mode
))
2523 big_offset_p
= true;
2524 x
= force_reg (GET_MODE (oldx
), oldx
);
2529 if (avr_log
.legitimize_address
)
2531 avr_edump ("\n%?: mode=%m\n %r\n", mode
, oldx
);
2534 avr_edump (" %s --> %r\n", big_offset_p
? "(big offset)" : "", x
);
2541 /* Implement `LEGITIMIZE_RELOAD_ADDRESS'. */
2542 /* This will allow register R26/27 to be used where it is no worse than normal
2543 base pointers R28/29 or R30/31. For example, if base offset is greater
2544 than 63 bytes or for R++ or --R addressing. */
2547 avr_legitimize_reload_address (rtx
*px
, machine_mode mode
,
2548 int opnum
, int type
, int addr_type
,
2549 int ind_levels ATTRIBUTE_UNUSED
,
2550 rtx (*mk_memloc
)(rtx
,int))
2554 if (avr_log
.legitimize_reload_address
)
2555 avr_edump ("\n%?:%m %r\n", mode
, x
);
2557 if (1 && (GET_CODE (x
) == POST_INC
2558 || GET_CODE (x
) == PRE_DEC
))
2560 push_reload (XEXP (x
, 0), XEXP (x
, 0), &XEXP (x
, 0), &XEXP (x
, 0),
2561 POINTER_REGS
, GET_MODE (x
), GET_MODE (x
), 0, 0,
2562 opnum
, RELOAD_OTHER
);
2564 if (avr_log
.legitimize_reload_address
)
2565 avr_edump (" RCLASS.1 = %R\n IN = %r\n OUT = %r\n",
2566 POINTER_REGS
, XEXP (x
, 0), XEXP (x
, 0));
2571 if (GET_CODE (x
) == PLUS
2572 && REG_P (XEXP (x
, 0))
2573 && 0 == reg_equiv_constant (REGNO (XEXP (x
, 0)))
2574 && CONST_INT_P (XEXP (x
, 1))
2575 && INTVAL (XEXP (x
, 1)) >= 1)
2577 bool fit
= INTVAL (XEXP (x
, 1)) <= MAX_LD_OFFSET (mode
);
2581 if (reg_equiv_address (REGNO (XEXP (x
, 0))) != 0)
2583 int regno
= REGNO (XEXP (x
, 0));
2584 rtx mem
= mk_memloc (x
, regno
);
2586 push_reload (XEXP (mem
, 0), NULL_RTX
, &XEXP (mem
, 0), NULL
,
2587 POINTER_REGS
, Pmode
, VOIDmode
, 0, 0,
2588 1, (enum reload_type
) addr_type
);
2590 if (avr_log
.legitimize_reload_address
)
2591 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
2592 POINTER_REGS
, XEXP (mem
, 0), NULL_RTX
);
2594 push_reload (mem
, NULL_RTX
, &XEXP (x
, 0), NULL
,
2595 BASE_POINTER_REGS
, GET_MODE (x
), VOIDmode
, 0, 0,
2596 opnum
, (enum reload_type
) type
);
2598 if (avr_log
.legitimize_reload_address
)
2599 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
2600 BASE_POINTER_REGS
, mem
, NULL_RTX
);
2605 else if (! (frame_pointer_needed
2606 && XEXP (x
, 0) == frame_pointer_rtx
))
2608 push_reload (x
, NULL_RTX
, px
, NULL
,
2609 POINTER_REGS
, GET_MODE (x
), VOIDmode
, 0, 0,
2610 opnum
, (enum reload_type
) type
);
2612 if (avr_log
.legitimize_reload_address
)
2613 avr_edump (" RCLASS.3 = %R\n IN = %r\n OUT = %r\n",
2614 POINTER_REGS
, x
, NULL_RTX
);
2624 /* Helper function to print assembler resp. track instruction
2625 sequence lengths. Always return "".
2628 Output assembler code from template TPL with operands supplied
2629 by OPERANDS. This is just forwarding to output_asm_insn.
2632 If N_WORDS >= 0 Add N_WORDS to *PLEN.
2633 If N_WORDS < 0 Set *PLEN to -N_WORDS.
2634 Don't output anything.
2638 avr_asm_len (const char* tpl
, rtx
* operands
, int* plen
, int n_words
)
2642 output_asm_insn (tpl
, operands
);
2656 /* Return a pointer register name as a string. */
2659 ptrreg_to_str (int regno
)
2663 case REG_X
: return "X";
2664 case REG_Y
: return "Y";
2665 case REG_Z
: return "Z";
2667 output_operand_lossage ("address operand requires constraint for"
2668 " X, Y, or Z register");
2673 /* Return the condition name as a string.
2674 Used in conditional jump constructing */
2677 cond_string (enum rtx_code code
)
2686 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
2691 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
2707 /* Return true if rtx X is a CONST or SYMBOL_REF with progmem.
2708 This must be used for AVR_TINY only because on other cores
2709 the flash memory is not visible in the RAM address range and
2710 cannot be read by, say, LD instruction. */
2713 avr_address_tiny_pm_p (rtx x
)
2715 if (CONST
== GET_CODE (x
))
2716 x
= XEXP (XEXP (x
, 0), 0);
2718 if (SYMBOL_REF_P (x
))
2719 return SYMBOL_REF_FLAGS (x
) & AVR_SYMBOL_FLAG_TINY_PM
;
2724 /* Implement `TARGET_PRINT_OPERAND_ADDRESS'. */
2725 /* Output ADDR to FILE as address. */
2728 avr_print_operand_address (FILE *file
, machine_mode
/*mode*/, rtx addr
)
2731 && avr_address_tiny_pm_p (addr
))
2733 addr
= plus_constant (Pmode
, addr
, avr_arch
->flash_pm_offset
);
2736 switch (GET_CODE (addr
))
2739 fprintf (file
, "%s", ptrreg_to_str (REGNO (addr
)));
2743 fprintf (file
, "-%s", ptrreg_to_str (REGNO (XEXP (addr
, 0))));
2747 fprintf (file
, "%s+", ptrreg_to_str (REGNO (XEXP (addr
, 0))));
2751 if (CONSTANT_ADDRESS_P (addr
)
2752 && text_segment_operand (addr
, VOIDmode
))
2755 if (GET_CODE (x
) == CONST
)
2757 if (GET_CODE (x
) == PLUS
&& CONST_INT_P (XEXP (x
, 1)))
2759 /* Assembler gs() will implant word address. Make offset
2760 a byte offset inside gs() for assembler. This is
2761 needed because the more logical (constant+gs(sym)) is not
2762 accepted by gas. For 128K and smaller devices this is ok.
2763 For large devices it will create a trampoline to offset
2764 from symbol which may not be what the user really wanted. */
2766 fprintf (file
, "gs(");
2767 output_addr_const (file
, XEXP (x
, 0));
2768 fprintf (file
, "+" HOST_WIDE_INT_PRINT_DEC
")",
2769 2 * INTVAL (XEXP (x
, 1)));
2771 if (warning (0, "pointer offset from symbol maybe incorrect"))
2773 output_addr_const (stderr
, addr
);
2774 fprintf (stderr
, "\n");
2779 fprintf (file
, "gs(");
2780 output_addr_const (file
, addr
);
2781 fprintf (file
, ")");
2785 output_addr_const (file
, addr
);
2790 /* Implement `TARGET_PRINT_OPERAND_PUNCT_VALID_P'. */
2793 avr_print_operand_punct_valid_p (unsigned char code
)
2795 return code
== '~' || code
== '!';
2799 /* Implement `TARGET_PRINT_OPERAND'. */
2800 /* Output X as assembler operand to file FILE.
2801 For a description of supported %-codes, see top of avr.md. */
2804 avr_print_operand (FILE *file
, rtx x
, int code
)
2806 int abcd
= 0, ef
= 0, ij
= 0;
2808 if (code
>= 'A' && code
<= 'D')
2810 else if (code
== 'E' || code
== 'F')
2812 else if (code
== 'I' || code
== 'J')
2817 if (!AVR_HAVE_JMP_CALL
)
2820 else if (code
== '!')
2822 if (AVR_HAVE_EIJMP_EICALL
)
2825 else if (code
== 't'
2828 static int t_regno
= -1;
2829 static int t_nbits
= -1;
2831 if (REG_P (x
) && t_regno
< 0 && code
== 'T')
2833 t_regno
= REGNO (x
);
2834 t_nbits
= GET_MODE_BITSIZE (GET_MODE (x
));
2836 else if (CONST_INT_P (x
) && t_regno
>= 0
2837 && IN_RANGE (INTVAL (x
), 0, t_nbits
- 1))
2839 int bpos
= INTVAL (x
);
2841 fprintf (file
, "%s", reg_names
[t_regno
+ bpos
/ 8]);
2843 fprintf (file
, ",%d", bpos
% 8);
2848 fatal_insn ("operands to %T/%t must be reg + const_int:", x
);
2850 else if (code
== 'E' || code
== 'F')
2852 rtx op
= XEXP (x
, 0);
2853 fprintf (file
, "%s", reg_names
[REGNO (op
) + ef
]);
2855 else if (code
== 'I' || code
== 'J')
2857 rtx op
= XEXP (XEXP (x
, 0), 0);
2858 fprintf (file
, "%s", reg_names
[REGNO (op
) + ij
]);
2862 if (x
== zero_reg_rtx
)
2863 fprintf (file
, "__zero_reg__");
2864 else if (code
== 'r' && REGNO (x
) < 32)
2865 fprintf (file
, "%d", (int) REGNO (x
));
2867 fprintf (file
, "%s", reg_names
[REGNO (x
) + abcd
]);
2869 else if (CONST_INT_P (x
))
2871 HOST_WIDE_INT ival
= INTVAL (x
);
2874 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, ival
+ abcd
);
2875 else if (low_io_address_operand (x
, VOIDmode
)
2876 || high_io_address_operand (x
, VOIDmode
))
2878 if (AVR_HAVE_RAMPZ
&& ival
== avr_addr
.rampz
)
2879 fprintf (file
, "__RAMPZ__");
2880 else if (AVR_HAVE_RAMPY
&& ival
== avr_addr
.rampy
)
2881 fprintf (file
, "__RAMPY__");
2882 else if (AVR_HAVE_RAMPX
&& ival
== avr_addr
.rampx
)
2883 fprintf (file
, "__RAMPX__");
2884 else if (AVR_HAVE_RAMPD
&& ival
== avr_addr
.rampd
)
2885 fprintf (file
, "__RAMPD__");
2886 else if ((AVR_XMEGA
|| AVR_TINY
) && ival
== avr_addr
.ccp
)
2887 fprintf (file
, "__CCP__");
2888 else if (ival
== avr_addr
.sreg
) fprintf (file
, "__SREG__");
2889 else if (ival
== avr_addr
.sp_l
) fprintf (file
, "__SP_L__");
2890 else if (ival
== avr_addr
.sp_h
) fprintf (file
, "__SP_H__");
2893 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
,
2894 ival
- avr_arch
->sfr_offset
);
2898 fatal_insn ("bad address, not an I/O address:", x
);
2902 rtx addr
= XEXP (x
, 0);
2906 if (!CONSTANT_P (addr
))
2907 fatal_insn ("bad address, not a constant:", addr
);
2908 /* Assembler template with m-code is data - not progmem section */
2909 if (text_segment_operand (addr
, VOIDmode
))
2910 if (warning (0, "accessing data memory with"
2911 " program memory address"))
2913 output_addr_const (stderr
, addr
);
2914 fprintf(stderr
,"\n");
2916 output_addr_const (file
, addr
);
2918 else if (code
== 'i')
2920 avr_print_operand (file
, addr
, 'i');
2922 else if (code
== 'o')
2924 if (GET_CODE (addr
) != PLUS
)
2925 fatal_insn ("bad address, not (reg+disp):", addr
);
2927 avr_print_operand (file
, XEXP (addr
, 1), 0);
2929 else if (code
== 'b')
2931 if (GET_CODE (addr
) != PLUS
)
2932 fatal_insn ("bad address, not (reg+disp):", addr
);
2934 avr_print_operand_address (file
, VOIDmode
, XEXP (addr
, 0));
2936 else if (code
== 'p' || code
== 'r')
2938 if (GET_CODE (addr
) != POST_INC
&& GET_CODE (addr
) != PRE_DEC
)
2939 fatal_insn ("bad address, not post_inc or pre_dec:", addr
);
2943 avr_print_operand_address (file
, VOIDmode
, XEXP (addr
, 0));
2945 avr_print_operand (file
, XEXP (addr
, 0), 0); /* r26, r28, r30 */
2947 else if (GET_CODE (addr
) == PLUS
)
2949 avr_print_operand_address (file
, VOIDmode
, XEXP (addr
, 0));
2950 if (REGNO (XEXP (addr
, 0)) == REG_X
)
2951 fatal_insn ("internal compiler error. Bad address:"
2954 avr_print_operand (file
, XEXP (addr
, 1), code
);
2957 avr_print_operand_address (file
, VOIDmode
, addr
);
2959 else if (code
== 'i')
2961 if (SYMBOL_REF_P (x
) && (SYMBOL_REF_FLAGS (x
) & SYMBOL_FLAG_IO
))
2962 avr_print_operand_address
2963 (file
, VOIDmode
, plus_constant (HImode
, x
, -avr_arch
->sfr_offset
));
2965 fatal_insn ("bad address, not an I/O address:", x
);
2967 else if (code
== 'x')
2969 /* Constant progmem address - like used in jmp or call */
2970 if (0 == text_segment_operand (x
, VOIDmode
))
2971 if (warning (0, "accessing program memory"
2972 " with data memory address"))
2974 output_addr_const (stderr
, x
);
2975 fprintf(stderr
,"\n");
2977 /* Use normal symbol for direct address no linker trampoline needed */
2978 output_addr_const (file
, x
);
2980 else if (CONST_FIXED_P (x
))
2982 HOST_WIDE_INT ival
= INTVAL (avr_to_int_mode (x
));
2984 output_operand_lossage ("Unsupported code '%c' for fixed-point:",
2986 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, ival
);
2988 else if (CONST_DOUBLE_P (x
))
2991 if (GET_MODE (x
) != SFmode
)
2992 fatal_insn ("internal compiler error. Unknown mode:", x
);
2993 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x
), val
);
2994 fprintf (file
, "0x%lx", val
);
2996 else if (GET_CODE (x
) == CONST_STRING
)
2997 fputs (XSTR (x
, 0), file
);
2998 else if (code
== 'j')
2999 fputs (cond_string (GET_CODE (x
)), file
);
3000 else if (code
== 'k')
3001 fputs (cond_string (reverse_condition (GET_CODE (x
))), file
);
3003 avr_print_operand_address (file
, VOIDmode
, x
);
3007 /* Implement TARGET_USE_BY_PIECES_INFRASTRUCTURE_P. */
3009 /* Prefer sequence of loads/stores for moves of size upto
3010 two - two pairs of load/store instructions are always better
3011 than the 5 instruction sequence for a loop (1 instruction
3012 for loop counter setup, and 4 for the body of the loop). */
3015 avr_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size
,
3016 unsigned int align ATTRIBUTE_UNUSED
,
3017 enum by_pieces_operation op
,
3020 if (op
!= MOVE_BY_PIECES
3021 || (speed_p
&& size
> MOVE_MAX_PIECES
))
3022 return default_use_by_pieces_infrastructure_p (size
, align
, op
, speed_p
);
3024 return size
<= MOVE_MAX_PIECES
;
3028 /* Worker function for `NOTICE_UPDATE_CC'. */
3029 /* Update the condition code in the INSN. */
3032 avr_notice_update_cc (rtx body ATTRIBUTE_UNUSED
, rtx_insn
*insn
)
3035 enum attr_cc cc
= get_attr_cc (insn
);
3045 rtx
*op
= recog_data
.operand
;
3048 /* Extract insn's operands. */
3049 extract_constrain_insn_cached (insn
);
3057 avr_out_plus (insn
, op
, &len_dummy
, &icc
);
3058 cc
= (enum attr_cc
) icc
;
3063 cc
= (op
[1] == CONST0_RTX (GET_MODE (op
[0]))
3064 && reg_overlap_mentioned_p (op
[0], zero_reg_rtx
))
3065 /* Loading zero-reg with 0 uses CLR and thus clobbers cc0. */
3067 /* Any other "r,rL" combination does not alter cc0. */
3071 } /* inner switch */
3075 } /* outer swicth */
3080 /* Special values like CC_OUT_PLUS from above have been
3081 mapped to "standard" CC_* values so we never come here. */
3087 /* Insn does not affect CC at all, but it might set some registers
3088 that are stored in cc_status. If such a register is affected by
3089 the current insn, for example by means of a SET or a CLOBBER,
3090 then we must reset cc_status; cf. PR77326.
3092 Unfortunately, set_of cannot be used as reg_overlap_mentioned_p
3093 will abort on COMPARE (which might be found in cc_status.value1/2).
3094 Thus work out the registers set by the insn and regs mentioned
3095 in cc_status.value1/2. */
3097 if (cc_status
.value1
3098 || cc_status
.value2
)
3100 HARD_REG_SET regs_used
;
3101 HARD_REG_SET regs_set
;
3102 CLEAR_HARD_REG_SET (regs_used
);
3104 if (cc_status
.value1
3105 && !CONSTANT_P (cc_status
.value1
))
3107 find_all_hard_regs (cc_status
.value1
, ®s_used
);
3110 if (cc_status
.value2
3111 && !CONSTANT_P (cc_status
.value2
))
3113 find_all_hard_regs (cc_status
.value2
, ®s_used
);
3116 find_all_hard_reg_sets (insn
, ®s_set
, false);
3118 if (hard_reg_set_intersect_p (regs_used
, regs_set
))
3131 set
= single_set (insn
);
3135 cc_status
.flags
|= CC_NO_OVERFLOW
;
3136 cc_status
.value1
= SET_DEST (set
);
3141 /* Insn like INC, DEC, NEG that set Z,N,V. We currently don't make use
3142 of this combination, cf. also PR61055. */
3147 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
3148 The V flag may or may not be known but that's ok because
3149 alter_cond will change tests to use EQ/NE. */
3150 set
= single_set (insn
);
3154 cc_status
.value1
= SET_DEST (set
);
3155 cc_status
.flags
|= CC_OVERFLOW_UNUSABLE
;
3160 set
= single_set (insn
);
3163 cc_status
.value1
= SET_SRC (set
);
3167 /* Insn doesn't leave CC in a usable state. */
3173 /* Choose mode for jump insn:
3174 1 - relative jump in range -63 <= x <= 62 ;
3175 2 - relative jump in range -2046 <= x <= 2045 ;
3176 3 - absolute jump (only for ATmega[16]03). */
3179 avr_jump_mode (rtx x
, rtx_insn
*insn
)
3181 int dest_addr
= INSN_ADDRESSES (INSN_UID (GET_CODE (x
) == LABEL_REF
3182 ? XEXP (x
, 0) : x
));
3183 int cur_addr
= INSN_ADDRESSES (INSN_UID (insn
));
3184 int jump_distance
= cur_addr
- dest_addr
;
3186 if (IN_RANGE (jump_distance
, -63, 62))
3188 else if (IN_RANGE (jump_distance
, -2046, 2045))
3190 else if (AVR_HAVE_JMP_CALL
)
3196 /* Return an AVR condition jump commands.
3197 X is a comparison RTX.
3198 LEN is a number returned by avr_jump_mode function.
3199 If REVERSE nonzero then condition code in X must be reversed. */
3202 ret_cond_branch (rtx x
, int len
, int reverse
)
3204 RTX_CODE cond
= reverse
? reverse_condition (GET_CODE (x
)) : GET_CODE (x
);
3209 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
3210 return (len
== 1 ? ("breq .+2" CR_TAB
3212 len
== 2 ? ("breq .+4" CR_TAB
3220 return (len
== 1 ? ("breq .+2" CR_TAB
3222 len
== 2 ? ("breq .+4" CR_TAB
3229 return (len
== 1 ? ("breq .+2" CR_TAB
3231 len
== 2 ? ("breq .+4" CR_TAB
3238 if (cc_prev_status
.flags
& CC_OVERFLOW_UNUSABLE
)
3239 return (len
== 1 ? ("breq %0" CR_TAB
3241 len
== 2 ? ("breq .+2" CR_TAB
3248 return (len
== 1 ? ("breq %0" CR_TAB
3250 len
== 2 ? ("breq .+2" CR_TAB
3257 return (len
== 1 ? ("breq %0" CR_TAB
3259 len
== 2 ? ("breq .+2" CR_TAB
3273 return ("br%j1 .+2" CR_TAB
3276 return ("br%j1 .+4" CR_TAB
3287 return ("br%k1 .+2" CR_TAB
3290 return ("br%k1 .+4" CR_TAB
3299 /* Worker function for `FINAL_PRESCAN_INSN'. */
3300 /* Output insn cost for next insn. */
3303 avr_final_prescan_insn (rtx_insn
*insn
, rtx
*operand ATTRIBUTE_UNUSED
,
3304 int num_operands ATTRIBUTE_UNUSED
)
3306 if (avr_log
.rtx_costs
)
3308 rtx set
= single_set (insn
);
3311 fprintf (asm_out_file
, "/* DEBUG: cost = %d. */\n",
3312 set_src_cost (SET_SRC (set
), GET_MODE (SET_DEST (set
)),
3313 optimize_insn_for_speed_p ()));
3315 fprintf (asm_out_file
, "/* DEBUG: pattern-cost = %d. */\n",
3316 rtx_cost (PATTERN (insn
), VOIDmode
, INSN
, 0,
3317 optimize_insn_for_speed_p()));
3320 if (avr_log
.insn_addresses
)
3321 fprintf (asm_out_file
, ";; ADDR = %d\n",
3322 (int) INSN_ADDRESSES (INSN_UID (insn
)));
3326 /* Implement `TARGET_ASM_FINAL_POSTSCAN_INSN'. */
3327 /* When GAS generates (parts of) ISR prologue / epilogue for us, we must
3328 hint GAS about the end of the code to scan. There migh be code located
3329 after the last epilogue. */
3332 avr_asm_final_postscan_insn (FILE *stream
, rtx_insn
*insn
, rtx
*, int)
3334 if (cfun
->machine
->gasisr
.yes
3335 && !next_real_insn (insn
))
3338 fprintf (stream
, "\t__gcc_isr %d,r%d\n", GASISR_Done
,
3339 cfun
->machine
->gasisr
.regno
);
3344 /* Return 0 if undefined, 1 if always true or always false. */
3347 avr_simplify_comparison_p (machine_mode mode
, RTX_CODE op
, rtx x
)
3349 unsigned int max
= (mode
== QImode
? 0xff :
3350 mode
== HImode
? 0xffff :
3351 mode
== PSImode
? 0xffffff :
3352 mode
== SImode
? 0xffffffff : 0);
3353 if (max
&& op
&& CONST_INT_P (x
))
3355 if (unsigned_condition (op
) != op
)
3358 if (max
!= (INTVAL (x
) & max
)
3359 && INTVAL (x
) != 0xff)
3366 /* Worker function for `FUNCTION_ARG_REGNO_P'. */
3367 /* Returns nonzero if REGNO is the number of a hard
3368 register in which function arguments are sometimes passed. */
3371 avr_function_arg_regno_p (int r
)
3373 return AVR_TINY
? IN_RANGE (r
, 20, 25) : IN_RANGE (r
, 8, 25);
3377 /* Worker function for `INIT_CUMULATIVE_ARGS'. */
3378 /* Initializing the variable cum for the state at the beginning
3379 of the argument list. */
3382 avr_init_cumulative_args (CUMULATIVE_ARGS
*cum
, tree fntype
, rtx libname
,
3383 tree fndecl ATTRIBUTE_UNUSED
)
3385 cum
->nregs
= AVR_TINY
? 6 : 18;
3386 cum
->regno
= FIRST_CUM_REG
;
3387 if (!libname
&& stdarg_p (fntype
))
3390 /* Assume the calle may be tail called */
3392 cfun
->machine
->sibcall_fails
= 0;
3395 /* Returns the number of registers to allocate for a function argument. */
3398 avr_num_arg_regs (machine_mode mode
, const_tree type
)
3402 if (mode
== BLKmode
)
3403 size
= int_size_in_bytes (type
);
3405 size
= GET_MODE_SIZE (mode
);
3407 /* Align all function arguments to start in even-numbered registers.
3408 Odd-sized arguments leave holes above them. */
3410 return (size
+ 1) & ~1;
3414 /* Implement `TARGET_FUNCTION_ARG'. */
3415 /* Controls whether a function argument is passed
3416 in a register, and which register. */
3419 avr_function_arg (cumulative_args_t cum_v
, machine_mode mode
,
3420 const_tree type
, bool named ATTRIBUTE_UNUSED
)
3422 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
3423 int bytes
= avr_num_arg_regs (mode
, type
);
3425 if (cum
->nregs
&& bytes
<= cum
->nregs
)
3426 return gen_rtx_REG (mode
, cum
->regno
- bytes
);
3432 /* Implement `TARGET_FUNCTION_ARG_ADVANCE'. */
3433 /* Update the summarizer variable CUM to advance past an argument
3434 in the argument list. */
3437 avr_function_arg_advance (cumulative_args_t cum_v
, machine_mode mode
,
3438 const_tree type
, bool named ATTRIBUTE_UNUSED
)
3440 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
3441 int bytes
= avr_num_arg_regs (mode
, type
);
3443 cum
->nregs
-= bytes
;
3444 cum
->regno
-= bytes
;
3446 /* A parameter is being passed in a call-saved register. As the original
3447 contents of these regs has to be restored before leaving the function,
3448 a function must not pass arguments in call-saved regs in order to get
3453 && !call_used_regs
[cum
->regno
])
3455 /* FIXME: We ship info on failing tail-call in struct machine_function.
3456 This uses internals of calls.c:expand_call() and the way args_so_far
3457 is used. targetm.function_ok_for_sibcall() needs to be extended to
3458 pass &args_so_far, too. At present, CUMULATIVE_ARGS is target
3459 dependent so that such an extension is not wanted. */
3461 cfun
->machine
->sibcall_fails
= 1;
3464 /* Test if all registers needed by the ABI are actually available. If the
3465 user has fixed a GPR needed to pass an argument, an (implicit) function
3466 call will clobber that fixed register. See PR45099 for an example. */
3471 for (int regno
= cum
->regno
; regno
< cum
->regno
+ bytes
; regno
++)
3472 if (fixed_regs
[regno
])
3473 warning (0, "fixed register %s used to pass parameter to function",
3477 if (cum
->nregs
<= 0)
3480 cum
->regno
= FIRST_CUM_REG
;
3484 /* Implement `TARGET_FUNCTION_OK_FOR_SIBCALL' */
3485 /* Decide whether we can make a sibling call to a function. DECL is the
3486 declaration of the function being targeted by the call and EXP is the
3487 CALL_EXPR representing the call. */
3490 avr_function_ok_for_sibcall (tree decl_callee
, tree exp_callee
)
3494 /* Tail-calling must fail if callee-saved regs are used to pass
3495 function args. We must not tail-call when `epilogue_restores'
3496 is used. Unfortunately, we cannot tell at this point if that
3497 actually will happen or not, and we cannot step back from
3498 tail-calling. Thus, we inhibit tail-calling with -mcall-prologues. */
3500 if (cfun
->machine
->sibcall_fails
3501 || TARGET_CALL_PROLOGUES
)
3506 fntype_callee
= TREE_TYPE (CALL_EXPR_FN (exp_callee
));
3510 decl_callee
= TREE_TYPE (decl_callee
);
3514 decl_callee
= fntype_callee
;
3516 while (FUNCTION_TYPE
!= TREE_CODE (decl_callee
)
3517 && METHOD_TYPE
!= TREE_CODE (decl_callee
))
3519 decl_callee
= TREE_TYPE (decl_callee
);
3523 /* Ensure that caller and callee have compatible epilogues */
3525 if (cfun
->machine
->is_interrupt
3526 || cfun
->machine
->is_signal
3527 || cfun
->machine
->is_naked
3528 || avr_naked_function_p (decl_callee
)
3529 /* FIXME: For OS_task and OS_main, this might be over-conservative. */
3530 || (avr_OS_task_function_p (decl_callee
)
3531 != cfun
->machine
->is_OS_task
)
3532 || (avr_OS_main_function_p (decl_callee
)
3533 != cfun
->machine
->is_OS_main
))
3541 /***********************************************************************
3542 Functions for outputting various mov's for a various modes
3543 ************************************************************************/
3545 /* Return true if a value of mode MODE is read from flash by
3546 __load_* function from libgcc. */
3549 avr_load_libgcc_p (rtx op
)
3551 machine_mode mode
= GET_MODE (op
);
3552 int n_bytes
= GET_MODE_SIZE (mode
);
3556 && avr_mem_flash_p (op
));
3559 /* Return true if a value of mode MODE is read by __xload_* function. */
3562 avr_xload_libgcc_p (machine_mode mode
)
3564 int n_bytes
= GET_MODE_SIZE (mode
);
3567 || avr_n_flash
> 1);
3571 /* Fixme: This is a hack because secondary reloads don't works as expected.
3573 Find an unused d-register to be used as scratch in INSN.
3574 EXCLUDE is either NULL_RTX or some register. In the case where EXCLUDE
3575 is a register, skip all possible return values that overlap EXCLUDE.
3576 The policy for the returned register is similar to that of
3577 `reg_unused_after', i.e. the returned register may overlap the SET_DEST
3580 Return a QImode d-register or NULL_RTX if nothing found. */
3583 avr_find_unused_d_reg (rtx_insn
*insn
, rtx exclude
)
3585 bool isr_p
= (avr_interrupt_function_p (current_function_decl
)
3586 || avr_signal_function_p (current_function_decl
));
3588 for (int regno
= 16; regno
< 32; regno
++)
3590 rtx reg
= all_regs_rtx
[regno
];
3593 && reg_overlap_mentioned_p (exclude
, reg
))
3594 || fixed_regs
[regno
])
3599 /* Try non-live register */
3601 if (!df_regs_ever_live_p (regno
)
3602 && (TREE_THIS_VOLATILE (current_function_decl
)
3603 || cfun
->machine
->is_OS_task
3604 || cfun
->machine
->is_OS_main
3605 || (!isr_p
&& call_used_regs
[regno
])))
3610 /* Any live register can be used if it is unused after.
3611 Prologue/epilogue will care for it as needed. */
3613 if (df_regs_ever_live_p (regno
)
3614 && reg_unused_after (insn
, reg
))
3624 /* Helper function for the next function in the case where only restricted
3625 version of LPM instruction is available. */
3628 avr_out_lpm_no_lpmx (rtx_insn
*insn
, rtx
*xop
, int *plen
)
3632 int n_bytes
= GET_MODE_SIZE (GET_MODE (dest
));
3635 regno_dest
= REGNO (dest
);
3637 /* The implicit target register of LPM. */
3638 xop
[3] = lpm_reg_rtx
;
3640 switch (GET_CODE (addr
))
3647 gcc_assert (REG_Z
== REGNO (addr
));
3655 avr_asm_len ("%4lpm", xop
, plen
, 1);
3657 if (regno_dest
!= LPM_REGNO
)
3658 avr_asm_len ("mov %0,%3", xop
, plen
, 1);
3663 if (REGNO (dest
) == REG_Z
)
3664 return avr_asm_len ("%4lpm" CR_TAB
3669 "pop %A0", xop
, plen
, 6);
3671 avr_asm_len ("%4lpm" CR_TAB
3675 "mov %B0,%3", xop
, plen
, 5);
3677 if (!reg_unused_after (insn
, addr
))
3678 avr_asm_len ("sbiw %2,1", xop
, plen
, 1);
3687 gcc_assert (REG_Z
== REGNO (XEXP (addr
, 0))
3690 if (regno_dest
== LPM_REGNO
)
3691 avr_asm_len ("%4lpm" CR_TAB
3692 "adiw %2,1", xop
, plen
, 2);
3694 avr_asm_len ("%4lpm" CR_TAB
3696 "adiw %2,1", xop
, plen
, 3);
3699 avr_asm_len ("%4lpm" CR_TAB
3701 "adiw %2,1", xop
, plen
, 3);
3704 avr_asm_len ("%4lpm" CR_TAB
3706 "adiw %2,1", xop
, plen
, 3);
3709 avr_asm_len ("%4lpm" CR_TAB
3711 "adiw %2,1", xop
, plen
, 3);
3713 break; /* POST_INC */
3715 } /* switch CODE (addr) */
3721 /* If PLEN == NULL: Ouput instructions to load a value from a memory location
3722 OP[1] in AS1 to register OP[0].
3723 If PLEN != 0 set *PLEN to the length in words of the instruction sequence.
3727 avr_out_lpm (rtx_insn
*insn
, rtx
*op
, int *plen
)
3731 rtx src
= SET_SRC (single_set (insn
));
3733 int n_bytes
= GET_MODE_SIZE (GET_MODE (dest
));
3736 addr_space_t as
= MEM_ADDR_SPACE (src
);
3743 warning (0, "writing to address space %qs not supported",
3744 avr_addrspace
[MEM_ADDR_SPACE (dest
)].name
);
3749 addr
= XEXP (src
, 0);
3750 code
= GET_CODE (addr
);
3752 gcc_assert (REG_P (dest
));
3753 gcc_assert (REG
== code
|| POST_INC
== code
);
3757 xop
[2] = lpm_addr_reg_rtx
;
3758 xop
[4] = xstring_empty
;
3759 xop
[5] = tmp_reg_rtx
;
3760 xop
[6] = XEXP (rampz_rtx
, 0);
3762 segment
= avr_addrspace
[as
].segment
;
3764 /* Set RAMPZ as needed. */
3768 xop
[4] = GEN_INT (segment
);
3769 xop
[3] = avr_find_unused_d_reg (insn
, lpm_addr_reg_rtx
);
3771 if (xop
[3] != NULL_RTX
)
3773 avr_asm_len ("ldi %3,%4" CR_TAB
3774 "out %i6,%3", xop
, plen
, 2);
3776 else if (segment
== 1)
3778 avr_asm_len ("clr %5" CR_TAB
3780 "out %i6,%5", xop
, plen
, 3);
3784 avr_asm_len ("mov %5,%2" CR_TAB
3787 "mov %2,%5", xop
, plen
, 4);
3792 if (!AVR_HAVE_ELPMX
)
3793 return avr_out_lpm_no_lpmx (insn
, xop
, plen
);
3795 else if (!AVR_HAVE_LPMX
)
3797 return avr_out_lpm_no_lpmx (insn
, xop
, plen
);
3800 /* We have [E]LPMX: Output reading from Flash the comfortable way. */
3802 switch (GET_CODE (addr
))
3809 gcc_assert (REG_Z
== REGNO (addr
));
3817 return avr_asm_len ("%4lpm %0,%a2", xop
, plen
, 1);
3820 if (REGNO (dest
) == REG_Z
)
3821 return avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3822 "%4lpm %B0,%a2" CR_TAB
3823 "mov %A0,%5", xop
, plen
, 3);
3826 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3827 "%4lpm %B0,%a2", xop
, plen
, 2);
3829 if (!reg_unused_after (insn
, addr
))
3830 avr_asm_len ("sbiw %2,1", xop
, plen
, 1);
3837 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3838 "%4lpm %B0,%a2+" CR_TAB
3839 "%4lpm %C0,%a2", xop
, plen
, 3);
3841 if (!reg_unused_after (insn
, addr
))
3842 avr_asm_len ("sbiw %2,2", xop
, plen
, 1);
3848 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3849 "%4lpm %B0,%a2+", xop
, plen
, 2);
3851 if (REGNO (dest
) == REG_Z
- 2)
3852 return avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3853 "%4lpm %C0,%a2" CR_TAB
3854 "mov %D0,%5", xop
, plen
, 3);
3857 avr_asm_len ("%4lpm %C0,%a2+" CR_TAB
3858 "%4lpm %D0,%a2", xop
, plen
, 2);
3860 if (!reg_unused_after (insn
, addr
))
3861 avr_asm_len ("sbiw %2,3", xop
, plen
, 1);
3871 gcc_assert (REG_Z
== REGNO (XEXP (addr
, 0))
3874 avr_asm_len ("%4lpm %A0,%a2+", xop
, plen
, 1);
3875 if (n_bytes
>= 2) avr_asm_len ("%4lpm %B0,%a2+", xop
, plen
, 1);
3876 if (n_bytes
>= 3) avr_asm_len ("%4lpm %C0,%a2+", xop
, plen
, 1);
3877 if (n_bytes
>= 4) avr_asm_len ("%4lpm %D0,%a2+", xop
, plen
, 1);
3879 break; /* POST_INC */
3881 } /* switch CODE (addr) */
3883 if (xop
[4] == xstring_e
&& AVR_HAVE_RAMPD
)
3885 /* Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM. */
3887 xop
[0] = zero_reg_rtx
;
3888 avr_asm_len ("out %i6,%0", xop
, plen
, 1);
3895 /* Worker function for xload_8 insn. */
3898 avr_out_xload (rtx_insn
*insn ATTRIBUTE_UNUSED
, rtx
*op
, int *plen
)
3904 xop
[2] = lpm_addr_reg_rtx
;
3905 xop
[3] = AVR_HAVE_LPMX
? op
[0] : lpm_reg_rtx
;
3907 avr_asm_len (AVR_HAVE_LPMX
? "lpm %3,%a2" : "lpm", xop
, plen
, -1);
3909 avr_asm_len ("sbrc %1,7" CR_TAB
3910 "ld %3,%a2", xop
, plen
, 2);
3912 if (REGNO (xop
[0]) != REGNO (xop
[3]))
3913 avr_asm_len ("mov %0,%3", xop
, plen
, 1);
3920 output_movqi (rtx_insn
*insn
, rtx operands
[], int *plen
)
3922 rtx dest
= operands
[0];
3923 rtx src
= operands
[1];
3925 if (avr_mem_flash_p (src
)
3926 || avr_mem_flash_p (dest
))
3928 return avr_out_lpm (insn
, operands
, plen
);
3931 gcc_assert (1 == GET_MODE_SIZE (GET_MODE (dest
)));
3935 if (REG_P (src
)) /* mov r,r */
3937 if (test_hard_reg_class (STACK_REG
, dest
))
3938 return avr_asm_len ("out %0,%1", operands
, plen
, -1);
3939 else if (test_hard_reg_class (STACK_REG
, src
))
3940 return avr_asm_len ("in %0,%1", operands
, plen
, -1);
3942 return avr_asm_len ("mov %0,%1", operands
, plen
, -1);
3944 else if (CONSTANT_P (src
))
3946 output_reload_in_const (operands
, NULL_RTX
, plen
, false);
3949 else if (MEM_P (src
))
3950 return out_movqi_r_mr (insn
, operands
, plen
); /* mov r,m */
3952 else if (MEM_P (dest
))
3957 xop
[1] = src
== CONST0_RTX (GET_MODE (dest
)) ? zero_reg_rtx
: src
;
3959 return out_movqi_mr_r (insn
, xop
, plen
);
3967 output_movhi (rtx_insn
*insn
, rtx xop
[], int *plen
)
3972 gcc_assert (GET_MODE_SIZE (GET_MODE (dest
)) == 2);
3974 if (avr_mem_flash_p (src
)
3975 || avr_mem_flash_p (dest
))
3977 return avr_out_lpm (insn
, xop
, plen
);
3982 if (REG_P (src
)) /* mov r,r */
3984 if (test_hard_reg_class (STACK_REG
, dest
))
3986 if (AVR_HAVE_8BIT_SP
)
3987 return avr_asm_len ("out __SP_L__,%A1", xop
, plen
, -1);
3990 return avr_asm_len ("out __SP_L__,%A1" CR_TAB
3991 "out __SP_H__,%B1", xop
, plen
, -2);
3993 /* Use simple load of SP if no interrupts are used. */
3995 return TARGET_NO_INTERRUPTS
3996 ? avr_asm_len ("out __SP_H__,%B1" CR_TAB
3997 "out __SP_L__,%A1", xop
, plen
, -2)
3998 : avr_asm_len ("in __tmp_reg__,__SREG__" CR_TAB
4000 "out __SP_H__,%B1" CR_TAB
4001 "out __SREG__,__tmp_reg__" CR_TAB
4002 "out __SP_L__,%A1", xop
, plen
, -5);
4004 else if (test_hard_reg_class (STACK_REG
, src
))
4006 return !AVR_HAVE_SPH
4007 ? avr_asm_len ("in %A0,__SP_L__" CR_TAB
4008 "clr %B0", xop
, plen
, -2)
4010 : avr_asm_len ("in %A0,__SP_L__" CR_TAB
4011 "in %B0,__SP_H__", xop
, plen
, -2);
4014 return AVR_HAVE_MOVW
4015 ? avr_asm_len ("movw %0,%1", xop
, plen
, -1)
4017 : avr_asm_len ("mov %A0,%A1" CR_TAB
4018 "mov %B0,%B1", xop
, plen
, -2);
4020 else if (CONSTANT_P (src
))
4022 return output_reload_inhi (xop
, NULL
, plen
);
4024 else if (MEM_P (src
))
4026 return out_movhi_r_mr (insn
, xop
, plen
); /* mov r,m */
4029 else if (MEM_P (dest
))
4034 xop
[1] = src
== CONST0_RTX (GET_MODE (dest
)) ? zero_reg_rtx
: src
;
4036 return out_movhi_mr_r (insn
, xop
, plen
);
4039 fatal_insn ("invalid insn:", insn
);
4045 /* Same as out_movqi_r_mr, but TINY does not have ADIW or SBIW */
4048 avr_out_movqi_r_mr_reg_disp_tiny (rtx_insn
*insn
, rtx op
[], int *plen
)
4052 rtx x
= XEXP (src
, 0);
4054 avr_asm_len (TINY_ADIW (%I1
, %J1
, %o1
) CR_TAB
4055 "ld %0,%b1" , op
, plen
, -3);
4057 if (!reg_overlap_mentioned_p (dest
, XEXP (x
, 0))
4058 && !reg_unused_after (insn
, XEXP (x
, 0)))
4059 avr_asm_len (TINY_SBIW (%I1
, %J1
, %o1
), op
, plen
, 2);
4065 out_movqi_r_mr (rtx_insn
*insn
, rtx op
[], int *plen
)
4069 rtx x
= XEXP (src
, 0);
4071 if (CONSTANT_ADDRESS_P (x
))
4073 int n_words
= AVR_TINY
? 1 : 2;
4074 return io_address_operand (x
, QImode
)
4075 ? avr_asm_len ("in %0,%i1", op
, plen
, -1)
4076 : avr_asm_len ("lds %0,%m1", op
, plen
, -n_words
);
4079 if (GET_CODE (x
) == PLUS
4080 && REG_P (XEXP (x
, 0))
4081 && CONST_INT_P (XEXP (x
, 1)))
4083 /* memory access by reg+disp */
4085 int disp
= INTVAL (XEXP (x
, 1));
4088 return avr_out_movqi_r_mr_reg_disp_tiny (insn
, op
, plen
);
4090 if (disp
- GET_MODE_SIZE (GET_MODE (src
)) >= 63)
4092 if (REGNO (XEXP (x
, 0)) != REG_Y
)
4093 fatal_insn ("incorrect insn:",insn
);
4095 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
4096 return avr_asm_len ("adiw r28,%o1-63" CR_TAB
4097 "ldd %0,Y+63" CR_TAB
4098 "sbiw r28,%o1-63", op
, plen
, -3);
4100 return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
4101 "sbci r29,hi8(-%o1)" CR_TAB
4103 "subi r28,lo8(%o1)" CR_TAB
4104 "sbci r29,hi8(%o1)", op
, plen
, -5);
4106 else if (REGNO (XEXP (x
, 0)) == REG_X
)
4108 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
4109 it but I have this situation with extremal optimizing options. */
4111 avr_asm_len ("adiw r26,%o1" CR_TAB
4112 "ld %0,X", op
, plen
, -2);
4114 if (!reg_overlap_mentioned_p (dest
, XEXP (x
, 0))
4115 && !reg_unused_after (insn
, XEXP (x
, 0)))
4117 avr_asm_len ("sbiw r26,%o1", op
, plen
, 1);
4123 return avr_asm_len ("ldd %0,%1", op
, plen
, -1);
4126 return avr_asm_len ("ld %0,%1", op
, plen
, -1);
4130 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
4133 avr_out_movhi_r_mr_reg_no_disp_tiny (rtx_insn
*insn
, rtx op
[], int *plen
)
4137 rtx base
= XEXP (src
, 0);
4139 int reg_dest
= true_regnum (dest
);
4140 int reg_base
= true_regnum (base
);
4142 if (reg_dest
== reg_base
) /* R = (R) */
4143 return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
4145 "mov %A0,__tmp_reg__", op
, plen
, -3);
4147 avr_asm_len ("ld %A0,%1+" CR_TAB
4148 "ld %B0,%1", op
, plen
, -2);
4150 if (!reg_unused_after (insn
, base
))
4151 avr_asm_len (TINY_SBIW (%E1
, %F1
, 1), op
, plen
, 2);
4157 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
4160 avr_out_movhi_r_mr_reg_disp_tiny (rtx_insn
*insn
, rtx op
[], int *plen
)
4164 rtx base
= XEXP (src
, 0);
4166 int reg_dest
= true_regnum (dest
);
4167 int reg_base
= true_regnum (XEXP (base
, 0));
4169 if (reg_base
== reg_dest
)
4171 return avr_asm_len (TINY_ADIW (%I1
, %J1
, %o1
) CR_TAB
4172 "ld __tmp_reg__,%b1+" CR_TAB
4174 "mov %A0,__tmp_reg__", op
, plen
, -5);
4178 avr_asm_len (TINY_ADIW (%I1
, %J1
, %o1
) CR_TAB
4179 "ld %A0,%b1+" CR_TAB
4180 "ld %B0,%b1", op
, plen
, -4);
4182 if (!reg_unused_after (insn
, XEXP (base
, 0)))
4183 avr_asm_len (TINY_SBIW (%I1
, %J1
, %o1
+1), op
, plen
, 2);
4190 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
4193 avr_out_movhi_r_mr_pre_dec_tiny (rtx_insn
*insn
, rtx op
[], int *plen
)
4195 int mem_volatile_p
= 0;
4198 rtx base
= XEXP (src
, 0);
4200 /* "volatile" forces reading low byte first, even if less efficient,
4201 for correct operation with 16-bit I/O registers. */
4202 mem_volatile_p
= MEM_VOLATILE_P (src
);
4204 if (reg_overlap_mentioned_p (dest
, XEXP (base
, 0)))
4205 fatal_insn ("incorrect insn:", insn
);
4207 if (!mem_volatile_p
)
4208 return avr_asm_len ("ld %B0,%1" CR_TAB
4209 "ld %A0,%1", op
, plen
, -2);
4211 return avr_asm_len (TINY_SBIW (%I1
, %J1
, 2) CR_TAB
4212 "ld %A0,%p1+" CR_TAB
4214 TINY_SBIW (%I1
, %J1
, 1), op
, plen
, -6);
4219 out_movhi_r_mr (rtx_insn
*insn
, rtx op
[], int *plen
)
4223 rtx base
= XEXP (src
, 0);
4224 int reg_dest
= true_regnum (dest
);
4225 int reg_base
= true_regnum (base
);
4226 /* "volatile" forces reading low byte first, even if less efficient,
4227 for correct operation with 16-bit I/O registers. */
4228 int mem_volatile_p
= MEM_VOLATILE_P (src
);
4233 return avr_out_movhi_r_mr_reg_no_disp_tiny (insn
, op
, plen
);
4235 if (reg_dest
== reg_base
) /* R = (R) */
4236 return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
4238 "mov %A0,__tmp_reg__", op
, plen
, -3);
4240 if (reg_base
!= REG_X
)
4241 return avr_asm_len ("ld %A0,%1" CR_TAB
4242 "ldd %B0,%1+1", op
, plen
, -2);
4244 avr_asm_len ("ld %A0,X+" CR_TAB
4245 "ld %B0,X", op
, plen
, -2);
4247 if (!reg_unused_after (insn
, base
))
4248 avr_asm_len ("sbiw r26,1", op
, plen
, 1);
4252 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
4254 int disp
= INTVAL (XEXP (base
, 1));
4255 int reg_base
= true_regnum (XEXP (base
, 0));
4258 return avr_out_movhi_r_mr_reg_disp_tiny (insn
, op
, plen
);
4260 if (disp
> MAX_LD_OFFSET (GET_MODE (src
)))
4262 if (REGNO (XEXP (base
, 0)) != REG_Y
)
4263 fatal_insn ("incorrect insn:",insn
);
4265 return disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
))
4266 ? avr_asm_len ("adiw r28,%o1-62" CR_TAB
4267 "ldd %A0,Y+62" CR_TAB
4268 "ldd %B0,Y+63" CR_TAB
4269 "sbiw r28,%o1-62", op
, plen
, -4)
4271 : avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
4272 "sbci r29,hi8(-%o1)" CR_TAB
4274 "ldd %B0,Y+1" CR_TAB
4275 "subi r28,lo8(%o1)" CR_TAB
4276 "sbci r29,hi8(%o1)", op
, plen
, -6);
4279 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
4280 it but I have this situation with extremal
4281 optimization options. */
4283 if (reg_base
== REG_X
)
4285 if (reg_base
== reg_dest
)
4286 return avr_asm_len ("adiw r26,%o1" CR_TAB
4287 "ld __tmp_reg__,X+" CR_TAB
4289 "mov %A0,__tmp_reg__", op
, plen
, -4);
4291 avr_asm_len ("adiw r26,%o1" CR_TAB
4293 "ld %B0,X", op
, plen
, -3);
4295 if (!reg_unused_after (insn
, XEXP (base
, 0)))
4296 avr_asm_len ("sbiw r26,%o1+1", op
, plen
, 1);
4301 return reg_base
== reg_dest
4302 ? avr_asm_len ("ldd __tmp_reg__,%A1" CR_TAB
4303 "ldd %B0,%B1" CR_TAB
4304 "mov %A0,__tmp_reg__", op
, plen
, -3)
4306 : avr_asm_len ("ldd %A0,%A1" CR_TAB
4307 "ldd %B0,%B1", op
, plen
, -2);
4309 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
4312 return avr_out_movhi_r_mr_pre_dec_tiny (insn
, op
, plen
);
4314 if (reg_overlap_mentioned_p (dest
, XEXP (base
, 0)))
4315 fatal_insn ("incorrect insn:", insn
);
4317 if (!mem_volatile_p
)
4318 return avr_asm_len ("ld %B0,%1" CR_TAB
4319 "ld %A0,%1", op
, plen
, -2);
4321 return REGNO (XEXP (base
, 0)) == REG_X
4322 ? avr_asm_len ("sbiw r26,2" CR_TAB
4325 "sbiw r26,1", op
, plen
, -4)
4327 : avr_asm_len ("sbiw %r1,2" CR_TAB
4329 "ldd %B0,%p1+1", op
, plen
, -3);
4331 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
4333 if (reg_overlap_mentioned_p (dest
, XEXP (base
, 0)))
4334 fatal_insn ("incorrect insn:", insn
);
4336 return avr_asm_len ("ld %A0,%1" CR_TAB
4337 "ld %B0,%1", op
, plen
, -2);
4339 else if (CONSTANT_ADDRESS_P (base
))
4341 int n_words
= AVR_TINY
? 2 : 4;
4342 return io_address_operand (base
, HImode
)
4343 ? avr_asm_len ("in %A0,%i1" CR_TAB
4344 "in %B0,%i1+1", op
, plen
, -2)
4346 : avr_asm_len ("lds %A0,%m1" CR_TAB
4347 "lds %B0,%m1+1", op
, plen
, -n_words
);
4350 fatal_insn ("unknown move insn:",insn
);
4355 avr_out_movsi_r_mr_reg_no_disp_tiny (rtx_insn
*insn
, rtx op
[], int *l
)
4359 rtx base
= XEXP (src
, 0);
4360 int reg_dest
= true_regnum (dest
);
4361 int reg_base
= true_regnum (base
);
4363 if (reg_dest
== reg_base
)
4365 /* "ld r26,-X" is undefined */
4366 return *l
= 9, (TINY_ADIW (%E1
, %F1
, 3) CR_TAB
4369 "ld __tmp_reg__,-%1" CR_TAB
4370 TINY_SBIW (%E1
, %F1
, 1) CR_TAB
4372 "mov %B0,__tmp_reg__");
4374 else if (reg_dest
== reg_base
- 2)
4376 return *l
= 5, ("ld %A0,%1+" CR_TAB
4378 "ld __tmp_reg__,%1+" CR_TAB
4380 "mov %C0,__tmp_reg__");
4382 else if (reg_unused_after (insn
, base
))
4384 return *l
= 4, ("ld %A0,%1+" CR_TAB
4391 return *l
= 6, ("ld %A0,%1+" CR_TAB
4395 TINY_SBIW (%E1
, %F1
, 3));
4401 avr_out_movsi_r_mr_reg_disp_tiny (rtx_insn
*insn
, rtx op
[], int *l
)
4405 rtx base
= XEXP (src
, 0);
4406 int reg_dest
= true_regnum (dest
);
4407 int reg_base
= true_regnum (XEXP (base
, 0));
4409 if (reg_dest
== reg_base
)
4411 /* "ld r26,-X" is undefined */
4412 return *l
= 9, (TINY_ADIW (%I1
, %J1
, %o1
+3) CR_TAB
4414 "ld %C0,-%b1" CR_TAB
4415 "ld __tmp_reg__,-%b1" CR_TAB
4416 TINY_SBIW (%I1
, %J1
, 1) CR_TAB
4418 "mov %B0,__tmp_reg__");
4420 else if (reg_dest
== reg_base
- 2)
4422 return *l
= 7, (TINY_ADIW (%I1
, %J1
, %o1
) CR_TAB
4423 "ld %A0,%b1+" CR_TAB
4424 "ld %B0,%b1+" CR_TAB
4425 "ld __tmp_reg__,%b1+" CR_TAB
4427 "mov %C0,__tmp_reg__");
4429 else if (reg_unused_after (insn
, XEXP (base
, 0)))
4431 return *l
= 6, (TINY_ADIW (%I1
, %J1
, %o1
) CR_TAB
4432 "ld %A0,%b1+" CR_TAB
4433 "ld %B0,%b1+" CR_TAB
4434 "ld %C0,%b1+" CR_TAB
4439 return *l
= 8, (TINY_ADIW (%I1
, %J1
, %o1
) CR_TAB
4440 "ld %A0,%b1+" CR_TAB
4441 "ld %B0,%b1+" CR_TAB
4442 "ld %C0,%b1+" CR_TAB
4444 TINY_SBIW (%I1
, %J1
, %o1
+3));
4449 out_movsi_r_mr (rtx_insn
*insn
, rtx op
[], int *l
)
4453 rtx base
= XEXP (src
, 0);
4454 int reg_dest
= true_regnum (dest
);
4455 int reg_base
= true_regnum (base
);
4464 return avr_out_movsi_r_mr_reg_no_disp_tiny (insn
, op
, l
);
4466 if (reg_base
== REG_X
) /* (R26) */
4468 if (reg_dest
== REG_X
)
4469 /* "ld r26,-X" is undefined */
4470 return *l
=7, ("adiw r26,3" CR_TAB
4473 "ld __tmp_reg__,-X" CR_TAB
4476 "mov r27,__tmp_reg__");
4477 else if (reg_dest
== REG_X
- 2)
4478 return *l
=5, ("ld %A0,X+" CR_TAB
4480 "ld __tmp_reg__,X+" CR_TAB
4482 "mov %C0,__tmp_reg__");
4483 else if (reg_unused_after (insn
, base
))
4484 return *l
=4, ("ld %A0,X+" CR_TAB
4489 return *l
=5, ("ld %A0,X+" CR_TAB
4497 if (reg_dest
== reg_base
)
4498 return *l
=5, ("ldd %D0,%1+3" CR_TAB
4499 "ldd %C0,%1+2" CR_TAB
4500 "ldd __tmp_reg__,%1+1" CR_TAB
4502 "mov %B0,__tmp_reg__");
4503 else if (reg_base
== reg_dest
+ 2)
4504 return *l
=5, ("ld %A0,%1" CR_TAB
4505 "ldd %B0,%1+1" CR_TAB
4506 "ldd __tmp_reg__,%1+2" CR_TAB
4507 "ldd %D0,%1+3" CR_TAB
4508 "mov %C0,__tmp_reg__");
4510 return *l
=4, ("ld %A0,%1" CR_TAB
4511 "ldd %B0,%1+1" CR_TAB
4512 "ldd %C0,%1+2" CR_TAB
4516 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
4518 int disp
= INTVAL (XEXP (base
, 1));
4521 return avr_out_movsi_r_mr_reg_disp_tiny (insn
, op
, l
);
4523 if (disp
> MAX_LD_OFFSET (GET_MODE (src
)))
4525 if (REGNO (XEXP (base
, 0)) != REG_Y
)
4526 fatal_insn ("incorrect insn:",insn
);
4528 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
4529 return *l
= 6, ("adiw r28,%o1-60" CR_TAB
4530 "ldd %A0,Y+60" CR_TAB
4531 "ldd %B0,Y+61" CR_TAB
4532 "ldd %C0,Y+62" CR_TAB
4533 "ldd %D0,Y+63" CR_TAB
4536 return *l
= 8, ("subi r28,lo8(-%o1)" CR_TAB
4537 "sbci r29,hi8(-%o1)" CR_TAB
4539 "ldd %B0,Y+1" CR_TAB
4540 "ldd %C0,Y+2" CR_TAB
4541 "ldd %D0,Y+3" CR_TAB
4542 "subi r28,lo8(%o1)" CR_TAB
4543 "sbci r29,hi8(%o1)");
4546 reg_base
= true_regnum (XEXP (base
, 0));
4547 if (reg_base
== REG_X
)
4550 if (reg_dest
== REG_X
)
4553 /* "ld r26,-X" is undefined */
4554 return ("adiw r26,%o1+3" CR_TAB
4557 "ld __tmp_reg__,-X" CR_TAB
4560 "mov r27,__tmp_reg__");
4563 if (reg_dest
== REG_X
- 2)
4564 return ("adiw r26,%o1" CR_TAB
4567 "ld __tmp_reg__,X+" CR_TAB
4569 "mov r26,__tmp_reg__");
4571 return ("adiw r26,%o1" CR_TAB
4578 if (reg_dest
== reg_base
)
4579 return *l
=5, ("ldd %D0,%D1" CR_TAB
4580 "ldd %C0,%C1" CR_TAB
4581 "ldd __tmp_reg__,%B1" CR_TAB
4582 "ldd %A0,%A1" CR_TAB
4583 "mov %B0,__tmp_reg__");
4584 else if (reg_dest
== reg_base
- 2)
4585 return *l
=5, ("ldd %A0,%A1" CR_TAB
4586 "ldd %B0,%B1" CR_TAB
4587 "ldd __tmp_reg__,%C1" CR_TAB
4588 "ldd %D0,%D1" CR_TAB
4589 "mov %C0,__tmp_reg__");
4590 return *l
=4, ("ldd %A0,%A1" CR_TAB
4591 "ldd %B0,%B1" CR_TAB
4592 "ldd %C0,%C1" CR_TAB
4595 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
4596 return *l
=4, ("ld %D0,%1" CR_TAB
4600 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
4601 return *l
=4, ("ld %A0,%1" CR_TAB
4605 else if (CONSTANT_ADDRESS_P (base
))
4607 if (io_address_operand (base
, SImode
))
4610 return ("in %A0,%i1" CR_TAB
4611 "in %B0,%i1+1" CR_TAB
4612 "in %C0,%i1+2" CR_TAB
4617 *l
= AVR_TINY
? 4 : 8;
4618 return ("lds %A0,%m1" CR_TAB
4619 "lds %B0,%m1+1" CR_TAB
4620 "lds %C0,%m1+2" CR_TAB
4625 fatal_insn ("unknown move insn:",insn
);
4630 avr_out_movsi_mr_r_reg_no_disp_tiny (rtx_insn
*insn
, rtx op
[], int *l
)
4634 rtx base
= XEXP (dest
, 0);
4635 int reg_base
= true_regnum (base
);
4636 int reg_src
= true_regnum (src
);
4638 if (reg_base
== reg_src
)
4640 /* "ld r26,-X" is undefined */
4641 if (reg_unused_after (insn
, base
))
4643 return *l
= 7, ("mov __tmp_reg__, %B1" CR_TAB
4645 TINY_ADIW (%E0
, %F0
, 1) CR_TAB
4646 "st %0+,__tmp_reg__" CR_TAB
4652 return *l
= 9, ("mov __tmp_reg__, %B1" CR_TAB
4654 TINY_ADIW (%E0
, %F0
, 1) CR_TAB
4655 "st %0+,__tmp_reg__" CR_TAB
4658 TINY_SBIW (%E0
, %F0
, 3));
4661 else if (reg_base
== reg_src
+ 2)
4663 if (reg_unused_after (insn
, base
))
4664 return *l
= 7, ("mov __zero_reg__,%C1" CR_TAB
4665 "mov __tmp_reg__,%D1" CR_TAB
4668 "st %0+,__zero_reg__" CR_TAB
4669 "st %0,__tmp_reg__" CR_TAB
4670 "clr __zero_reg__");
4672 return *l
= 9, ("mov __zero_reg__,%C1" CR_TAB
4673 "mov __tmp_reg__,%D1" CR_TAB
4676 "st %0+,__zero_reg__" CR_TAB
4677 "st %0,__tmp_reg__" CR_TAB
4678 "clr __zero_reg__" CR_TAB
4679 TINY_SBIW (%E0
, %F0
, 3));
4682 return *l
= 6, ("st %0+,%A1" CR_TAB
4686 TINY_SBIW (%E0
, %F0
, 3));
4690 avr_out_movsi_mr_r_reg_disp_tiny (rtx op
[], int *l
)
4694 rtx base
= XEXP (dest
, 0);
4695 int reg_base
= REGNO (XEXP (base
, 0));
4696 int reg_src
=true_regnum (src
);
4698 if (reg_base
== reg_src
)
4701 return ("mov __tmp_reg__,%A2" CR_TAB
4702 "mov __zero_reg__,%B2" CR_TAB
4703 TINY_ADIW (%I0
, %J0
, %o0
) CR_TAB
4704 "st %b0+,__tmp_reg__" CR_TAB
4705 "st %b0+,__zero_reg__" CR_TAB
4706 "st %b0+,%C2" CR_TAB
4708 "clr __zero_reg__" CR_TAB
4709 TINY_SBIW (%I0
, %J0
, %o0
+3));
4711 else if (reg_src
== reg_base
- 2)
4714 return ("mov __tmp_reg__,%C2" CR_TAB
4715 "mov __zero_reg__,%D2" CR_TAB
4716 TINY_ADIW (%I0
, %J0
, %o0
) CR_TAB
4717 "st %b0+,%A0" CR_TAB
4718 "st %b0+,%B0" CR_TAB
4719 "st %b0+,__tmp_reg__" CR_TAB
4720 "st %b0,__zero_reg__" CR_TAB
4721 "clr __zero_reg__" CR_TAB
4722 TINY_SBIW (%I0
, %J0
, %o0
+3));
4725 return (TINY_ADIW (%I0
, %J0
, %o0
) CR_TAB
4726 "st %b0+,%A1" CR_TAB
4727 "st %b0+,%B1" CR_TAB
4728 "st %b0+,%C1" CR_TAB
4730 TINY_SBIW (%I0
, %J0
, %o0
+3));
4734 out_movsi_mr_r (rtx_insn
*insn
, rtx op
[], int *l
)
4738 rtx base
= XEXP (dest
, 0);
4739 int reg_base
= true_regnum (base
);
4740 int reg_src
= true_regnum (src
);
4746 if (CONSTANT_ADDRESS_P (base
))
4748 if (io_address_operand (base
, SImode
))
4750 return *l
=4,("out %i0, %A1" CR_TAB
4751 "out %i0+1,%B1" CR_TAB
4752 "out %i0+2,%C1" CR_TAB
4757 *l
= AVR_TINY
? 4 : 8;
4758 return ("sts %m0,%A1" CR_TAB
4759 "sts %m0+1,%B1" CR_TAB
4760 "sts %m0+2,%C1" CR_TAB
4765 if (reg_base
> 0) /* (r) */
4768 return avr_out_movsi_mr_r_reg_no_disp_tiny (insn
, op
, l
);
4770 if (reg_base
== REG_X
) /* (R26) */
4772 if (reg_src
== REG_X
)
4774 /* "st X+,r26" is undefined */
4775 if (reg_unused_after (insn
, base
))
4776 return *l
=6, ("mov __tmp_reg__,r27" CR_TAB
4779 "st X+,__tmp_reg__" CR_TAB
4783 return *l
=7, ("mov __tmp_reg__,r27" CR_TAB
4786 "st X+,__tmp_reg__" CR_TAB
4791 else if (reg_base
== reg_src
+ 2)
4793 if (reg_unused_after (insn
, base
))
4794 return *l
=7, ("mov __zero_reg__,%C1" CR_TAB
4795 "mov __tmp_reg__,%D1" CR_TAB
4798 "st %0+,__zero_reg__" CR_TAB
4799 "st %0,__tmp_reg__" CR_TAB
4800 "clr __zero_reg__");
4802 return *l
=8, ("mov __zero_reg__,%C1" CR_TAB
4803 "mov __tmp_reg__,%D1" CR_TAB
4806 "st %0+,__zero_reg__" CR_TAB
4807 "st %0,__tmp_reg__" CR_TAB
4808 "clr __zero_reg__" CR_TAB
4811 return *l
=5, ("st %0+,%A1" CR_TAB
4818 return *l
=4, ("st %0,%A1" CR_TAB
4819 "std %0+1,%B1" CR_TAB
4820 "std %0+2,%C1" CR_TAB
4823 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
4825 int disp
= INTVAL (XEXP (base
, 1));
4828 return avr_out_movsi_mr_r_reg_disp_tiny (op
, l
);
4830 reg_base
= REGNO (XEXP (base
, 0));
4831 if (disp
> MAX_LD_OFFSET (GET_MODE (dest
)))
4833 if (reg_base
!= REG_Y
)
4834 fatal_insn ("incorrect insn:",insn
);
4836 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
4837 return *l
= 6, ("adiw r28,%o0-60" CR_TAB
4838 "std Y+60,%A1" CR_TAB
4839 "std Y+61,%B1" CR_TAB
4840 "std Y+62,%C1" CR_TAB
4841 "std Y+63,%D1" CR_TAB
4844 return *l
= 8, ("subi r28,lo8(-%o0)" CR_TAB
4845 "sbci r29,hi8(-%o0)" CR_TAB
4847 "std Y+1,%B1" CR_TAB
4848 "std Y+2,%C1" CR_TAB
4849 "std Y+3,%D1" CR_TAB
4850 "subi r28,lo8(%o0)" CR_TAB
4851 "sbci r29,hi8(%o0)");
4853 if (reg_base
== REG_X
)
4856 if (reg_src
== REG_X
)
4859 return ("mov __tmp_reg__,r26" CR_TAB
4860 "mov __zero_reg__,r27" CR_TAB
4861 "adiw r26,%o0" CR_TAB
4862 "st X+,__tmp_reg__" CR_TAB
4863 "st X+,__zero_reg__" CR_TAB
4866 "clr __zero_reg__" CR_TAB
4869 else if (reg_src
== REG_X
- 2)
4872 return ("mov __tmp_reg__,r26" CR_TAB
4873 "mov __zero_reg__,r27" CR_TAB
4874 "adiw r26,%o0" CR_TAB
4877 "st X+,__tmp_reg__" CR_TAB
4878 "st X,__zero_reg__" CR_TAB
4879 "clr __zero_reg__" CR_TAB
4883 return ("adiw r26,%o0" CR_TAB
4890 return *l
=4, ("std %A0,%A1" CR_TAB
4891 "std %B0,%B1" CR_TAB
4892 "std %C0,%C1" CR_TAB
4895 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
4896 return *l
=4, ("st %0,%D1" CR_TAB
4900 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
4901 return *l
=4, ("st %0,%A1" CR_TAB
4905 fatal_insn ("unknown move insn:",insn
);
4910 output_movsisf (rtx_insn
*insn
, rtx operands
[], int *l
)
4913 rtx dest
= operands
[0];
4914 rtx src
= operands
[1];
4917 if (avr_mem_flash_p (src
)
4918 || avr_mem_flash_p (dest
))
4920 return avr_out_lpm (insn
, operands
, real_l
);
4926 gcc_assert (4 == GET_MODE_SIZE (GET_MODE (dest
)));
4930 if (REG_P (src
)) /* mov r,r */
4932 if (true_regnum (dest
) > true_regnum (src
))
4937 return ("movw %C0,%C1" CR_TAB
4941 return ("mov %D0,%D1" CR_TAB
4942 "mov %C0,%C1" CR_TAB
4943 "mov %B0,%B1" CR_TAB
4951 return ("movw %A0,%A1" CR_TAB
4955 return ("mov %A0,%A1" CR_TAB
4956 "mov %B0,%B1" CR_TAB
4957 "mov %C0,%C1" CR_TAB
4961 else if (CONSTANT_P (src
))
4963 return output_reload_insisf (operands
, NULL_RTX
, real_l
);
4965 else if (MEM_P (src
))
4966 return out_movsi_r_mr (insn
, operands
, real_l
); /* mov r,m */
4968 else if (MEM_P (dest
))
4972 if (src
== CONST0_RTX (GET_MODE (dest
)))
4973 operands
[1] = zero_reg_rtx
;
4975 templ
= out_movsi_mr_r (insn
, operands
, real_l
);
4978 output_asm_insn (templ
, operands
);
4983 fatal_insn ("invalid insn:", insn
);
4988 /* Handle loads of 24-bit types from memory to register. */
4991 avr_out_load_psi_reg_no_disp_tiny (rtx_insn
*insn
, rtx
*op
, int *plen
)
4995 rtx base
= XEXP (src
, 0);
4996 int reg_dest
= true_regnum (dest
);
4997 int reg_base
= true_regnum (base
);
4999 if (reg_base
== reg_dest
)
5001 return avr_asm_len (TINY_ADIW (%E1
, %F1
, 2) CR_TAB
5003 "ld __tmp_reg__,-%1" CR_TAB
5004 TINY_SBIW (%E1
, %F1
, 1) CR_TAB
5006 "mov %B0,__tmp_reg__", op
, plen
, -8);
5010 avr_asm_len ("ld %A0,%1+" CR_TAB
5012 "ld %C0,%1", op
, plen
, -3);
5014 if (reg_dest
!= reg_base
- 2
5015 && !reg_unused_after (insn
, base
))
5017 avr_asm_len (TINY_SBIW (%E1
, %F1
, 2), op
, plen
, 2);
5024 avr_out_load_psi_reg_disp_tiny (rtx_insn
*insn
, rtx
*op
, int *plen
)
5028 rtx base
= XEXP (src
, 0);
5029 int reg_dest
= true_regnum (dest
);
5030 int reg_base
= true_regnum (base
);
5032 reg_base
= true_regnum (XEXP (base
, 0));
5033 if (reg_base
== reg_dest
)
5035 return avr_asm_len (TINY_ADIW (%I1
, %J1
, %o1
+2) CR_TAB
5037 "ld __tmp_reg__,-%b1" CR_TAB
5038 TINY_SBIW (%I1
, %J1
, 1) CR_TAB
5040 "mov %B0,__tmp_reg__", op
, plen
, -8);
5044 avr_asm_len (TINY_ADIW (%I1
, %J1
, %o1
) CR_TAB
5045 "ld %A0,%b1+" CR_TAB
5046 "ld %B0,%b1+" CR_TAB
5047 "ld %C0,%b1", op
, plen
, -5);
5049 if (reg_dest
!= reg_base
- 2
5050 && !reg_unused_after (insn
, XEXP (base
, 0)))
5051 avr_asm_len (TINY_SBIW (%I1
, %J1
, %o1
+2), op
, plen
, 2);
5058 avr_out_load_psi (rtx_insn
*insn
, rtx
*op
, int *plen
)
5062 rtx base
= XEXP (src
, 0);
5063 int reg_dest
= true_regnum (dest
);
5064 int reg_base
= true_regnum (base
);
5069 return avr_out_load_psi_reg_no_disp_tiny (insn
, op
, plen
);
5071 if (reg_base
== REG_X
) /* (R26) */
5073 if (reg_dest
== REG_X
)
5074 /* "ld r26,-X" is undefined */
5075 return avr_asm_len ("adiw r26,2" CR_TAB
5077 "ld __tmp_reg__,-X" CR_TAB
5080 "mov r27,__tmp_reg__", op
, plen
, -6);
5083 avr_asm_len ("ld %A0,X+" CR_TAB
5085 "ld %C0,X", op
, plen
, -3);
5087 if (reg_dest
!= REG_X
- 2
5088 && !reg_unused_after (insn
, base
))
5090 avr_asm_len ("sbiw r26,2", op
, plen
, 1);
5096 else /* reg_base != REG_X */
5098 if (reg_dest
== reg_base
)
5099 return avr_asm_len ("ldd %C0,%1+2" CR_TAB
5100 "ldd __tmp_reg__,%1+1" CR_TAB
5102 "mov %B0,__tmp_reg__", op
, plen
, -4);
5104 return avr_asm_len ("ld %A0,%1" CR_TAB
5105 "ldd %B0,%1+1" CR_TAB
5106 "ldd %C0,%1+2", op
, plen
, -3);
5109 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
5111 int disp
= INTVAL (XEXP (base
, 1));
5114 return avr_out_load_psi_reg_disp_tiny (insn
, op
, plen
);
5116 if (disp
> MAX_LD_OFFSET (GET_MODE (src
)))
5118 if (REGNO (XEXP (base
, 0)) != REG_Y
)
5119 fatal_insn ("incorrect insn:",insn
);
5121 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (src
)))
5122 return avr_asm_len ("adiw r28,%o1-61" CR_TAB
5123 "ldd %A0,Y+61" CR_TAB
5124 "ldd %B0,Y+62" CR_TAB
5125 "ldd %C0,Y+63" CR_TAB
5126 "sbiw r28,%o1-61", op
, plen
, -5);
5128 return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
5129 "sbci r29,hi8(-%o1)" CR_TAB
5131 "ldd %B0,Y+1" CR_TAB
5132 "ldd %C0,Y+2" CR_TAB
5133 "subi r28,lo8(%o1)" CR_TAB
5134 "sbci r29,hi8(%o1)", op
, plen
, -7);
5137 reg_base
= true_regnum (XEXP (base
, 0));
5138 if (reg_base
== REG_X
)
5141 if (reg_dest
== REG_X
)
5143 /* "ld r26,-X" is undefined */
5144 return avr_asm_len ("adiw r26,%o1+2" CR_TAB
5146 "ld __tmp_reg__,-X" CR_TAB
5149 "mov r27,__tmp_reg__", op
, plen
, -6);
5152 avr_asm_len ("adiw r26,%o1" CR_TAB
5155 "ld %C0,X", op
, plen
, -4);
5157 if (reg_dest
!= REG_W
5158 && !reg_unused_after (insn
, XEXP (base
, 0)))
5159 avr_asm_len ("sbiw r26,%o1+2", op
, plen
, 1);
5164 if (reg_dest
== reg_base
)
5165 return avr_asm_len ("ldd %C0,%C1" CR_TAB
5166 "ldd __tmp_reg__,%B1" CR_TAB
5167 "ldd %A0,%A1" CR_TAB
5168 "mov %B0,__tmp_reg__", op
, plen
, -4);
5170 return avr_asm_len ("ldd %A0,%A1" CR_TAB
5171 "ldd %B0,%B1" CR_TAB
5172 "ldd %C0,%C1", op
, plen
, -3);
5174 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
5175 return avr_asm_len ("ld %C0,%1" CR_TAB
5177 "ld %A0,%1", op
, plen
, -3);
5178 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
5179 return avr_asm_len ("ld %A0,%1" CR_TAB
5181 "ld %C0,%1", op
, plen
, -3);
5183 else if (CONSTANT_ADDRESS_P (base
))
5185 int n_words
= AVR_TINY
? 3 : 6;
5186 return avr_asm_len ("lds %A0,%m1" CR_TAB
5187 "lds %B0,%m1+1" CR_TAB
5188 "lds %C0,%m1+2", op
, plen
, -n_words
);
5191 fatal_insn ("unknown move insn:",insn
);
5197 avr_out_store_psi_reg_no_disp_tiny (rtx_insn
*insn
, rtx
*op
, int *plen
)
5201 rtx base
= XEXP (dest
, 0);
5202 int reg_base
= true_regnum (base
);
5203 int reg_src
= true_regnum (src
);
5205 if (reg_base
== reg_src
)
5207 avr_asm_len ("st %0,%A1" CR_TAB
5208 "mov __tmp_reg__,%B1" CR_TAB
5209 TINY_ADIW (%E0
, %F0
, 1) CR_TAB
/* st X+, r27 is undefined */
5210 "st %0+,__tmp_reg__" CR_TAB
5211 "st %0,%C1", op
, plen
, -6);
5214 else if (reg_src
== reg_base
- 2)
5216 avr_asm_len ("st %0,%A1" CR_TAB
5217 "mov __tmp_reg__,%C1" CR_TAB
5218 TINY_ADIW (%E0
, %F0
, 1) CR_TAB
5220 "st %0,__tmp_reg__", op
, plen
, 6);
5224 avr_asm_len ("st %0+,%A1" CR_TAB
5226 "st %0,%C1", op
, plen
, -3);
5229 if (!reg_unused_after (insn
, base
))
5230 avr_asm_len (TINY_SBIW (%E0
, %F0
, 2), op
, plen
, 2);
5236 avr_out_store_psi_reg_disp_tiny (rtx_insn
*insn
, rtx
*op
, int *plen
)
5240 rtx base
= XEXP (dest
, 0);
5241 int reg_base
= REGNO (XEXP (base
, 0));
5242 int reg_src
= true_regnum (src
);
5244 if (reg_src
== reg_base
)
5245 avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
5246 "mov __zero_reg__,%B1" CR_TAB
5247 TINY_ADIW (%I0
, %J0
, %o0
) CR_TAB
5248 "st %b0+,__tmp_reg__" CR_TAB
5249 "st %b0+,__zero_reg__" CR_TAB
5251 "clr __zero_reg__", op
, plen
, -8);
5252 else if (reg_src
== reg_base
- 2)
5253 avr_asm_len ("mov __tmp_reg__,%C1" CR_TAB
5254 TINY_ADIW (%I0
, %J0
, %o0
) CR_TAB
5255 "st %b0+,%A1" CR_TAB
5256 "st %b0+,%B1" CR_TAB
5257 "st %b0,__tmp_reg__", op
, plen
, -6);
5259 avr_asm_len (TINY_ADIW (%I0
, %J0
, %o0
) CR_TAB
5260 "st %b0+,%A1" CR_TAB
5261 "st %b0+,%B1" CR_TAB
5262 "st %b0,%C1", op
, plen
, -5);
5264 if (!reg_unused_after (insn
, XEXP (base
, 0)))
5265 avr_asm_len (TINY_SBIW (%I0
, %J0
, %o0
+2), op
, plen
, 2);
5270 /* Handle store of 24-bit type from register or zero to memory. */
5273 avr_out_store_psi (rtx_insn
*insn
, rtx
*op
, int *plen
)
5277 rtx base
= XEXP (dest
, 0);
5278 int reg_base
= true_regnum (base
);
5280 if (CONSTANT_ADDRESS_P (base
))
5282 int n_words
= AVR_TINY
? 3 : 6;
5283 return avr_asm_len ("sts %m0,%A1" CR_TAB
5284 "sts %m0+1,%B1" CR_TAB
5285 "sts %m0+2,%C1", op
, plen
, -n_words
);
5288 if (reg_base
> 0) /* (r) */
5291 return avr_out_store_psi_reg_no_disp_tiny (insn
, op
, plen
);
5293 if (reg_base
== REG_X
) /* (R26) */
5295 gcc_assert (!reg_overlap_mentioned_p (base
, src
));
5297 avr_asm_len ("st %0+,%A1" CR_TAB
5299 "st %0,%C1", op
, plen
, -3);
5301 if (!reg_unused_after (insn
, base
))
5302 avr_asm_len ("sbiw r26,2", op
, plen
, 1);
5307 return avr_asm_len ("st %0,%A1" CR_TAB
5308 "std %0+1,%B1" CR_TAB
5309 "std %0+2,%C1", op
, plen
, -3);
5311 else if (GET_CODE (base
) == PLUS
) /* (R + i) */
5313 int disp
= INTVAL (XEXP (base
, 1));
5316 return avr_out_store_psi_reg_disp_tiny (insn
, op
, plen
);
5318 reg_base
= REGNO (XEXP (base
, 0));
5320 if (disp
> MAX_LD_OFFSET (GET_MODE (dest
)))
5322 if (reg_base
!= REG_Y
)
5323 fatal_insn ("incorrect insn:",insn
);
5325 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
5326 return avr_asm_len ("adiw r28,%o0-61" CR_TAB
5327 "std Y+61,%A1" CR_TAB
5328 "std Y+62,%B1" CR_TAB
5329 "std Y+63,%C1" CR_TAB
5330 "sbiw r28,%o0-61", op
, plen
, -5);
5332 return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5333 "sbci r29,hi8(-%o0)" CR_TAB
5335 "std Y+1,%B1" CR_TAB
5336 "std Y+2,%C1" CR_TAB
5337 "subi r28,lo8(%o0)" CR_TAB
5338 "sbci r29,hi8(%o0)", op
, plen
, -7);
5340 if (reg_base
== REG_X
)
5343 gcc_assert (!reg_overlap_mentioned_p (XEXP (base
, 0), src
));
5345 avr_asm_len ("adiw r26,%o0" CR_TAB
5348 "st X,%C1", op
, plen
, -4);
5350 if (!reg_unused_after (insn
, XEXP (base
, 0)))
5351 avr_asm_len ("sbiw r26,%o0+2", op
, plen
, 1);
5356 return avr_asm_len ("std %A0,%A1" CR_TAB
5357 "std %B0,%B1" CR_TAB
5358 "std %C0,%C1", op
, plen
, -3);
5360 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
5361 return avr_asm_len ("st %0,%C1" CR_TAB
5363 "st %0,%A1", op
, plen
, -3);
5364 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
5365 return avr_asm_len ("st %0,%A1" CR_TAB
5367 "st %0,%C1", op
, plen
, -3);
5369 fatal_insn ("unknown move insn:",insn
);
5374 /* Move around 24-bit stuff. */
5377 avr_out_movpsi (rtx_insn
*insn
, rtx
*op
, int *plen
)
5382 if (avr_mem_flash_p (src
)
5383 || avr_mem_flash_p (dest
))
5385 return avr_out_lpm (insn
, op
, plen
);
5388 if (register_operand (dest
, VOIDmode
))
5390 if (register_operand (src
, VOIDmode
)) /* mov r,r */
5392 if (true_regnum (dest
) > true_regnum (src
))
5394 avr_asm_len ("mov %C0,%C1", op
, plen
, -1);
5397 return avr_asm_len ("movw %A0,%A1", op
, plen
, 1);
5399 return avr_asm_len ("mov %B0,%B1" CR_TAB
5400 "mov %A0,%A1", op
, plen
, 2);
5405 avr_asm_len ("movw %A0,%A1", op
, plen
, -1);
5407 avr_asm_len ("mov %A0,%A1" CR_TAB
5408 "mov %B0,%B1", op
, plen
, -2);
5410 return avr_asm_len ("mov %C0,%C1", op
, plen
, 1);
5413 else if (CONSTANT_P (src
))
5415 return avr_out_reload_inpsi (op
, NULL_RTX
, plen
);
5417 else if (MEM_P (src
))
5418 return avr_out_load_psi (insn
, op
, plen
); /* mov r,m */
5420 else if (MEM_P (dest
))
5425 xop
[1] = src
== CONST0_RTX (GET_MODE (dest
)) ? zero_reg_rtx
: src
;
5427 return avr_out_store_psi (insn
, xop
, plen
);
5430 fatal_insn ("invalid insn:", insn
);
5435 avr_out_movqi_mr_r_reg_disp_tiny (rtx_insn
*insn
, rtx op
[], int *plen
)
5439 rtx x
= XEXP (dest
, 0);
5441 if (reg_overlap_mentioned_p (src
, XEXP (x
, 0)))
5443 avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
5444 TINY_ADIW (%I0
, %J0
, %o0
) CR_TAB
5445 "st %b0,__tmp_reg__", op
, plen
, -4);
5449 avr_asm_len (TINY_ADIW (%I0
, %J0
, %o0
) CR_TAB
5450 "st %b0,%1", op
, plen
, -3);
5453 if (!reg_unused_after (insn
, XEXP (x
, 0)))
5454 avr_asm_len (TINY_SBIW (%I0
, %J0
, %o0
), op
, plen
, 2);
5460 out_movqi_mr_r (rtx_insn
*insn
, rtx op
[], int *plen
)
5464 rtx x
= XEXP (dest
, 0);
5466 if (CONSTANT_ADDRESS_P (x
))
5468 int n_words
= AVR_TINY
? 1 : 2;
5469 return io_address_operand (x
, QImode
)
5470 ? avr_asm_len ("out %i0,%1", op
, plen
, -1)
5471 : avr_asm_len ("sts %m0,%1", op
, plen
, -n_words
);
5473 else if (GET_CODE (x
) == PLUS
5474 && REG_P (XEXP (x
, 0))
5475 && CONST_INT_P (XEXP (x
, 1)))
5477 /* memory access by reg+disp */
5479 int disp
= INTVAL (XEXP (x
, 1));
5482 return avr_out_movqi_mr_r_reg_disp_tiny (insn
, op
, plen
);
5484 if (disp
- GET_MODE_SIZE (GET_MODE (dest
)) >= 63)
5486 if (REGNO (XEXP (x
, 0)) != REG_Y
)
5487 fatal_insn ("incorrect insn:",insn
);
5489 if (disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
)))
5490 return avr_asm_len ("adiw r28,%o0-63" CR_TAB
5491 "std Y+63,%1" CR_TAB
5492 "sbiw r28,%o0-63", op
, plen
, -3);
5494 return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5495 "sbci r29,hi8(-%o0)" CR_TAB
5497 "subi r28,lo8(%o0)" CR_TAB
5498 "sbci r29,hi8(%o0)", op
, plen
, -5);
5500 else if (REGNO (XEXP (x
, 0)) == REG_X
)
5502 if (reg_overlap_mentioned_p (src
, XEXP (x
, 0)))
5504 avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
5505 "adiw r26,%o0" CR_TAB
5506 "st X,__tmp_reg__", op
, plen
, -3);
5510 avr_asm_len ("adiw r26,%o0" CR_TAB
5511 "st X,%1", op
, plen
, -2);
5514 if (!reg_unused_after (insn
, XEXP (x
, 0)))
5515 avr_asm_len ("sbiw r26,%o0", op
, plen
, 1);
5520 return avr_asm_len ("std %0,%1", op
, plen
, -1);
5523 return avr_asm_len ("st %0,%1", op
, plen
, -1);
5527 /* Helper for the next function for XMEGA. It does the same
5528 but with low byte first. */
5531 avr_out_movhi_mr_r_xmega (rtx_insn
*insn
, rtx op
[], int *plen
)
5535 rtx base
= XEXP (dest
, 0);
5536 int reg_base
= true_regnum (base
);
5537 int reg_src
= true_regnum (src
);
5539 /* "volatile" forces writing low byte first, even if less efficient,
5540 for correct operation with 16-bit I/O registers like SP. */
5541 int mem_volatile_p
= MEM_VOLATILE_P (dest
);
5543 if (CONSTANT_ADDRESS_P (base
))
5545 return io_address_operand (base
, HImode
)
5546 ? avr_asm_len ("out %i0,%A1" CR_TAB
5547 "out %i0+1,%B1", op
, plen
, -2)
5549 : avr_asm_len ("sts %m0,%A1" CR_TAB
5550 "sts %m0+1,%B1", op
, plen
, -4);
5555 if (reg_base
!= REG_X
)
5556 return avr_asm_len ("st %0,%A1" CR_TAB
5557 "std %0+1,%B1", op
, plen
, -2);
5559 if (reg_src
== REG_X
)
5560 /* "st X+,r26" and "st -X,r26" are undefined. */
5561 avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5564 "st X,__tmp_reg__", op
, plen
, -4);
5566 avr_asm_len ("st X+,%A1" CR_TAB
5567 "st X,%B1", op
, plen
, -2);
5569 return reg_unused_after (insn
, base
)
5571 : avr_asm_len ("sbiw r26,1", op
, plen
, 1);
5573 else if (GET_CODE (base
) == PLUS
)
5575 int disp
= INTVAL (XEXP (base
, 1));
5576 reg_base
= REGNO (XEXP (base
, 0));
5577 if (disp
> MAX_LD_OFFSET (GET_MODE (dest
)))
5579 if (reg_base
!= REG_Y
)
5580 fatal_insn ("incorrect insn:",insn
);
5582 return disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
))
5583 ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
5584 "std Y+62,%A1" CR_TAB
5585 "std Y+63,%B1" CR_TAB
5586 "sbiw r28,%o0-62", op
, plen
, -4)
5588 : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5589 "sbci r29,hi8(-%o0)" CR_TAB
5591 "std Y+1,%B1" CR_TAB
5592 "subi r28,lo8(%o0)" CR_TAB
5593 "sbci r29,hi8(%o0)", op
, plen
, -6);
5596 if (reg_base
!= REG_X
)
5597 return avr_asm_len ("std %A0,%A1" CR_TAB
5598 "std %B0,%B1", op
, plen
, -2);
5600 return reg_src
== REG_X
5601 ? avr_asm_len ("mov __tmp_reg__,r26" CR_TAB
5602 "mov __zero_reg__,r27" CR_TAB
5603 "adiw r26,%o0" CR_TAB
5604 "st X+,__tmp_reg__" CR_TAB
5605 "st X,__zero_reg__" CR_TAB
5606 "clr __zero_reg__" CR_TAB
5607 "sbiw r26,%o0+1", op
, plen
, -7)
5609 : avr_asm_len ("adiw r26,%o0" CR_TAB
5612 "sbiw r26,%o0+1", op
, plen
, -4);
5614 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
5616 if (!mem_volatile_p
)
5617 return avr_asm_len ("st %0,%B1" CR_TAB
5618 "st %0,%A1", op
, plen
, -2);
5620 return REGNO (XEXP (base
, 0)) == REG_X
5621 ? avr_asm_len ("sbiw r26,2" CR_TAB
5624 "sbiw r26,1", op
, plen
, -4)
5626 : avr_asm_len ("sbiw %r0,2" CR_TAB
5628 "std %p0+1,%B1", op
, plen
, -3);
5630 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
5632 return avr_asm_len ("st %0,%A1" CR_TAB
5633 "st %0,%B1", op
, plen
, -2);
5636 fatal_insn ("unknown move insn:",insn
);
5641 avr_out_movhi_mr_r_reg_no_disp_tiny (rtx_insn
*insn
, rtx op
[], int *plen
)
5645 rtx base
= XEXP (dest
, 0);
5646 int reg_base
= true_regnum (base
);
5647 int reg_src
= true_regnum (src
);
5648 int mem_volatile_p
= MEM_VOLATILE_P (dest
);
5650 if (reg_base
== reg_src
)
5652 return !mem_volatile_p
&& reg_unused_after (insn
, src
)
5653 ? avr_asm_len ("mov __tmp_reg__,%B1" CR_TAB
5655 TINY_ADIW (%E0
, %F0
, 1) CR_TAB
5656 "st %0,__tmp_reg__", op
, plen
, -5)
5657 : avr_asm_len ("mov __tmp_reg__,%B1" CR_TAB
5658 TINY_ADIW (%E0
, %F0
, 1) CR_TAB
5659 "st %0,__tmp_reg__" CR_TAB
5660 TINY_SBIW (%E0
, %F0
, 1) CR_TAB
5661 "st %0, %A1", op
, plen
, -7);
5664 return !mem_volatile_p
&& reg_unused_after (insn
, base
)
5665 ? avr_asm_len ("st %0+,%A1" CR_TAB
5666 "st %0,%B1", op
, plen
, -2)
5667 : avr_asm_len (TINY_ADIW (%E0
, %F0
, 1) CR_TAB
5669 "st -%0,%A1", op
, plen
, -4);
5673 avr_out_movhi_mr_r_reg_disp_tiny (rtx_insn
*insn
, rtx op
[], int *plen
)
5677 rtx base
= XEXP (dest
, 0);
5678 int reg_base
= REGNO (XEXP (base
, 0));
5679 int reg_src
= true_regnum (src
);
5681 if (reg_src
== reg_base
)
5682 avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
5683 "mov __zero_reg__,%B1" CR_TAB
5684 TINY_ADIW (%I0
, %J0
, %o0
+1) CR_TAB
5685 "st %b0,__zero_reg__" CR_TAB
5686 "st -%b0,__tmp_reg__" CR_TAB
5687 "clr __zero_reg__", op
, plen
, -7);
5689 avr_asm_len (TINY_ADIW (%I0
, %J0
, %o0
+1) CR_TAB
5691 "st -%b0,%A1", op
, plen
, -4);
5693 if (!reg_unused_after (insn
, XEXP (base
, 0)))
5694 avr_asm_len (TINY_SBIW (%I0
, %J0
, %o0
), op
, plen
, 2);
5700 avr_out_movhi_mr_r_post_inc_tiny (rtx op
[], int *plen
)
5702 return avr_asm_len (TINY_ADIW (%I0
, %J0
, 1) CR_TAB
5704 "st -%p0,%A1" CR_TAB
5705 TINY_ADIW (%I0
, %J0
, 2), op
, plen
, -6);
5709 out_movhi_mr_r (rtx_insn
*insn
, rtx op
[], int *plen
)
5713 rtx base
= XEXP (dest
, 0);
5714 int reg_base
= true_regnum (base
);
5715 int reg_src
= true_regnum (src
);
5718 /* "volatile" forces writing high-byte first (no-xmega) resp.
5719 low-byte first (xmega) even if less efficient, for correct
5720 operation with 16-bit I/O registers like. */
5723 return avr_out_movhi_mr_r_xmega (insn
, op
, plen
);
5725 mem_volatile_p
= MEM_VOLATILE_P (dest
);
5727 if (CONSTANT_ADDRESS_P (base
))
5729 int n_words
= AVR_TINY
? 2 : 4;
5730 return io_address_operand (base
, HImode
)
5731 ? avr_asm_len ("out %i0+1,%B1" CR_TAB
5732 "out %i0,%A1", op
, plen
, -2)
5734 : avr_asm_len ("sts %m0+1,%B1" CR_TAB
5735 "sts %m0,%A1", op
, plen
, -n_words
);
5741 return avr_out_movhi_mr_r_reg_no_disp_tiny (insn
, op
, plen
);
5743 if (reg_base
!= REG_X
)
5744 return avr_asm_len ("std %0+1,%B1" CR_TAB
5745 "st %0,%A1", op
, plen
, -2);
5747 if (reg_src
== REG_X
)
5748 /* "st X+,r26" and "st -X,r26" are undefined. */
5749 return !mem_volatile_p
&& reg_unused_after (insn
, src
)
5750 ? avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5753 "st X,__tmp_reg__", op
, plen
, -4)
5755 : avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5757 "st X,__tmp_reg__" CR_TAB
5759 "st X,r26", op
, plen
, -5);
5761 return !mem_volatile_p
&& reg_unused_after (insn
, base
)
5762 ? avr_asm_len ("st X+,%A1" CR_TAB
5763 "st X,%B1", op
, plen
, -2)
5764 : avr_asm_len ("adiw r26,1" CR_TAB
5766 "st -X,%A1", op
, plen
, -3);
5768 else if (GET_CODE (base
) == PLUS
)
5770 int disp
= INTVAL (XEXP (base
, 1));
5773 return avr_out_movhi_mr_r_reg_disp_tiny (insn
, op
, plen
);
5775 reg_base
= REGNO (XEXP (base
, 0));
5776 if (disp
> MAX_LD_OFFSET (GET_MODE (dest
)))
5778 if (reg_base
!= REG_Y
)
5779 fatal_insn ("incorrect insn:",insn
);
5781 return disp
<= 63 + MAX_LD_OFFSET (GET_MODE (dest
))
5782 ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
5783 "std Y+63,%B1" CR_TAB
5784 "std Y+62,%A1" CR_TAB
5785 "sbiw r28,%o0-62", op
, plen
, -4)
5787 : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5788 "sbci r29,hi8(-%o0)" CR_TAB
5789 "std Y+1,%B1" CR_TAB
5791 "subi r28,lo8(%o0)" CR_TAB
5792 "sbci r29,hi8(%o0)", op
, plen
, -6);
5795 if (reg_base
!= REG_X
)
5796 return avr_asm_len ("std %B0,%B1" CR_TAB
5797 "std %A0,%A1", op
, plen
, -2);
5799 return reg_src
== REG_X
5800 ? avr_asm_len ("mov __tmp_reg__,r26" CR_TAB
5801 "mov __zero_reg__,r27" CR_TAB
5802 "adiw r26,%o0+1" CR_TAB
5803 "st X,__zero_reg__" CR_TAB
5804 "st -X,__tmp_reg__" CR_TAB
5805 "clr __zero_reg__" CR_TAB
5806 "sbiw r26,%o0", op
, plen
, -7)
5808 : avr_asm_len ("adiw r26,%o0+1" CR_TAB
5811 "sbiw r26,%o0", op
, plen
, -4);
5813 else if (GET_CODE (base
) == PRE_DEC
) /* (--R) */
5815 return avr_asm_len ("st %0,%B1" CR_TAB
5816 "st %0,%A1", op
, plen
, -2);
5818 else if (GET_CODE (base
) == POST_INC
) /* (R++) */
5820 if (!mem_volatile_p
)
5821 return avr_asm_len ("st %0,%A1" CR_TAB
5822 "st %0,%B1", op
, plen
, -2);
5825 return avr_out_movhi_mr_r_post_inc_tiny (op
, plen
);
5827 return REGNO (XEXP (base
, 0)) == REG_X
5828 ? avr_asm_len ("adiw r26,1" CR_TAB
5831 "adiw r26,2", op
, plen
, -4)
5833 : avr_asm_len ("std %p0+1,%B1" CR_TAB
5835 "adiw %r0,2", op
, plen
, -3);
5837 fatal_insn ("unknown move insn:",insn
);
5841 /* Return 1 if frame pointer for current function required. */
5844 avr_frame_pointer_required_p (void)
5846 return (cfun
->calls_alloca
5847 || cfun
->calls_setjmp
5848 || cfun
->has_nonlocal_label
5849 || crtl
->args
.info
.nregs
== 0
5850 || get_frame_size () > 0);
5853 /* Returns the condition of compare insn INSN, or UNKNOWN. */
5856 compare_condition (rtx_insn
*insn
)
5858 rtx_insn
*next
= next_real_insn (insn
);
5860 if (next
&& JUMP_P (next
))
5862 rtx pat
= PATTERN (next
);
5863 rtx src
= SET_SRC (pat
);
5865 if (IF_THEN_ELSE
== GET_CODE (src
))
5866 return GET_CODE (XEXP (src
, 0));
5873 /* Returns true iff INSN is a tst insn that only tests the sign. */
5876 compare_sign_p (rtx_insn
*insn
)
5878 RTX_CODE cond
= compare_condition (insn
);
5879 return (cond
== GE
|| cond
== LT
);
5883 /* Returns true iff the next insn is a JUMP_INSN with a condition
5884 that needs to be swapped (GT, GTU, LE, LEU). */
5887 compare_diff_p (rtx_insn
*insn
)
5889 RTX_CODE cond
= compare_condition (insn
);
5890 return (cond
== GT
|| cond
== GTU
|| cond
== LE
|| cond
== LEU
) ? cond
: 0;
5893 /* Returns true iff INSN is a compare insn with the EQ or NE condition. */
5896 compare_eq_p (rtx_insn
*insn
)
5898 RTX_CODE cond
= compare_condition (insn
);
5899 return (cond
== EQ
|| cond
== NE
);
5903 /* Output compare instruction
5905 compare (XOP[0], XOP[1])
5907 for a register XOP[0] and a compile-time constant XOP[1]. Return "".
5908 XOP[2] is an 8-bit scratch register as needed.
5910 PLEN == NULL: Output instructions.
5911 PLEN != NULL: Set *PLEN to the length (in words) of the sequence.
5912 Don't output anything. */
5915 avr_out_compare (rtx_insn
*insn
, rtx
*xop
, int *plen
)
5917 /* Register to compare and value to compare against. */
5921 /* MODE of the comparison. */
5924 /* Number of bytes to operate on. */
5925 int n_bytes
= GET_MODE_SIZE (GET_MODE (xreg
));
5927 /* Value (0..0xff) held in clobber register xop[2] or -1 if unknown. */
5928 int clobber_val
= -1;
5930 /* Map fixed mode operands to integer operands with the same binary
5931 representation. They are easier to handle in the remainder. */
5933 if (CONST_FIXED_P (xval
))
5935 xreg
= avr_to_int_mode (xop
[0]);
5936 xval
= avr_to_int_mode (xop
[1]);
5939 mode
= GET_MODE (xreg
);
5941 gcc_assert (REG_P (xreg
));
5942 gcc_assert ((CONST_INT_P (xval
) && n_bytes
<= 4)
5943 || (const_double_operand (xval
, VOIDmode
) && n_bytes
== 8));
5948 /* Comparisons == +/-1 and != +/-1 can be done similar to camparing
5949 against 0 by ORing the bytes. This is one instruction shorter.
5950 Notice that 64-bit comparisons are always against reg:ALL8 18 (ACC_A)
5951 and therefore don't use this. */
5953 if (!test_hard_reg_class (LD_REGS
, xreg
)
5954 && compare_eq_p (insn
)
5955 && reg_unused_after (insn
, xreg
))
5957 if (xval
== const1_rtx
)
5959 avr_asm_len ("dec %A0" CR_TAB
5960 "or %A0,%B0", xop
, plen
, 2);
5963 avr_asm_len ("or %A0,%C0", xop
, plen
, 1);
5966 avr_asm_len ("or %A0,%D0", xop
, plen
, 1);
5970 else if (xval
== constm1_rtx
)
5973 avr_asm_len ("and %A0,%D0", xop
, plen
, 1);
5976 avr_asm_len ("and %A0,%C0", xop
, plen
, 1);
5978 return avr_asm_len ("and %A0,%B0" CR_TAB
5979 "com %A0", xop
, plen
, 2);
5983 /* Comparisons == -1 and != -1 of a d-register that's used after the
5984 comparison. (If it's unused after we use CPI / SBCI or ADIW sequence
5985 from below.) Instead of CPI Rlo,-1 / LDI Rx,-1 / CPC Rhi,Rx we can
5986 use CPI Rlo,-1 / CPC Rhi,Rlo which is 1 instruction shorter:
5987 If CPI is true then Rlo contains -1 and we can use Rlo instead of Rx
5988 when CPC'ing the high part. If CPI is false then CPC cannot render
5989 the result to true. This also works for the more generic case where
5990 the constant is of the form 0xabab. */
5993 && xval
!= const0_rtx
5994 && test_hard_reg_class (LD_REGS
, xreg
)
5995 && compare_eq_p (insn
)
5996 && !reg_unused_after (insn
, xreg
))
5998 rtx xlo8
= simplify_gen_subreg (QImode
, xval
, mode
, 0);
5999 rtx xhi8
= simplify_gen_subreg (QImode
, xval
, mode
, 1);
6001 if (INTVAL (xlo8
) == INTVAL (xhi8
))
6006 return avr_asm_len ("cpi %A0,%1" CR_TAB
6007 "cpc %B0,%A0", xop
, plen
, 2);
6011 for (int i
= 0; i
< n_bytes
; i
++)
6013 /* We compare byte-wise. */
6014 rtx reg8
= simplify_gen_subreg (QImode
, xreg
, mode
, i
);
6015 rtx xval8
= simplify_gen_subreg (QImode
, xval
, mode
, i
);
6017 /* 8-bit value to compare with this byte. */
6018 unsigned int val8
= UINTVAL (xval8
) & GET_MODE_MASK (QImode
);
6020 /* Registers R16..R31 can operate with immediate. */
6021 bool ld_reg_p
= test_hard_reg_class (LD_REGS
, reg8
);
6024 xop
[1] = gen_int_mode (val8
, QImode
);
6026 /* Word registers >= R24 can use SBIW/ADIW with 0..63. */
6029 && test_hard_reg_class (ADDW_REGS
, reg8
))
6031 int val16
= trunc_int_for_mode (INTVAL (xval
), HImode
);
6033 if (IN_RANGE (val16
, 0, 63)
6035 || reg_unused_after (insn
, xreg
)))
6038 avr_asm_len (TINY_SBIW (%A0
, %B0
, %1), xop
, plen
, 2);
6040 avr_asm_len ("sbiw %0,%1", xop
, plen
, 1);
6047 && IN_RANGE (val16
, -63, -1)
6048 && compare_eq_p (insn
)
6049 && reg_unused_after (insn
, xreg
))
6052 ? avr_asm_len (TINY_ADIW (%A0
, %B0
, %n1
), xop
, plen
, 2)
6053 : avr_asm_len ("adiw %0,%n1", xop
, plen
, 1);
6057 /* Comparing against 0 is easy. */
6062 ? "cp %0,__zero_reg__"
6063 : "cpc %0,__zero_reg__", xop
, plen
, 1);
6067 /* Upper registers can compare and subtract-with-carry immediates.
6068 Notice that compare instructions do the same as respective subtract
6069 instruction; the only difference is that comparisons don't write
6070 the result back to the target register. */
6076 avr_asm_len ("cpi %0,%1", xop
, plen
, 1);
6079 else if (reg_unused_after (insn
, xreg
))
6081 avr_asm_len ("sbci %0,%1", xop
, plen
, 1);
6086 /* Must load the value into the scratch register. */
6088 gcc_assert (REG_P (xop
[2]));
6090 if (clobber_val
!= (int) val8
)
6091 avr_asm_len ("ldi %2,%1", xop
, plen
, 1);
6092 clobber_val
= (int) val8
;
6096 : "cpc %0,%2", xop
, plen
, 1);
6103 /* Prepare operands of compare_const_di2 to be used with avr_out_compare. */
6106 avr_out_compare64 (rtx_insn
*insn
, rtx
*op
, int *plen
)
6110 xop
[0] = gen_rtx_REG (DImode
, 18);
6114 return avr_out_compare (insn
, xop
, plen
);
6117 /* Output test instruction for HImode. */
6120 avr_out_tsthi (rtx_insn
*insn
, rtx
*op
, int *plen
)
6122 if (compare_sign_p (insn
))
6124 avr_asm_len ("tst %B0", op
, plen
, -1);
6126 else if (reg_unused_after (insn
, op
[0])
6127 && compare_eq_p (insn
))
6129 /* Faster than sbiw if we can clobber the operand. */
6130 avr_asm_len ("or %A0,%B0", op
, plen
, -1);
6134 avr_out_compare (insn
, op
, plen
);
6141 /* Output test instruction for PSImode. */
6144 avr_out_tstpsi (rtx_insn
*insn
, rtx
*op
, int *plen
)
6146 if (compare_sign_p (insn
))
6148 avr_asm_len ("tst %C0", op
, plen
, -1);
6150 else if (reg_unused_after (insn
, op
[0])
6151 && compare_eq_p (insn
))
6153 /* Faster than sbiw if we can clobber the operand. */
6154 avr_asm_len ("or %A0,%B0" CR_TAB
6155 "or %A0,%C0", op
, plen
, -2);
6159 avr_out_compare (insn
, op
, plen
);
6166 /* Output test instruction for SImode. */
6169 avr_out_tstsi (rtx_insn
*insn
, rtx
*op
, int *plen
)
6171 if (compare_sign_p (insn
))
6173 avr_asm_len ("tst %D0", op
, plen
, -1);
6175 else if (reg_unused_after (insn
, op
[0])
6176 && compare_eq_p (insn
))
6178 /* Faster than sbiw if we can clobber the operand. */
6179 avr_asm_len ("or %A0,%B0" CR_TAB
6181 "or %A0,%D0", op
, plen
, -3);
6185 avr_out_compare (insn
, op
, plen
);
6192 /* Generate asm equivalent for various shifts. This only handles cases
6193 that are not already carefully hand-optimized in ?sh??i3_out.
6195 OPERANDS[0] resp. %0 in TEMPL is the operand to be shifted.
6196 OPERANDS[2] is the shift count as CONST_INT, MEM or REG.
6197 OPERANDS[3] is a QImode scratch register from LD regs if
6198 available and SCRATCH, otherwise (no scratch available)
6200 TEMPL is an assembler template that shifts by one position.
6201 T_LEN is the length of this template. */
6204 out_shift_with_cnt (const char *templ
, rtx_insn
*insn
, rtx operands
[],
6205 int *plen
, int t_len
)
6207 bool second_label
= true;
6208 bool saved_in_tmp
= false;
6209 bool use_zero_reg
= false;
6212 op
[0] = operands
[0];
6213 op
[1] = operands
[1];
6214 op
[2] = operands
[2];
6215 op
[3] = operands
[3];
6220 if (CONST_INT_P (operands
[2]))
6222 bool scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
6223 && REG_P (operands
[3]));
6224 int count
= INTVAL (operands
[2]);
6225 int max_len
= 10; /* If larger than this, always use a loop. */
6230 if (count
< 8 && !scratch
)
6231 use_zero_reg
= true;
6234 max_len
= t_len
+ (scratch
? 3 : (use_zero_reg
? 4 : 5));
6236 if (t_len
* count
<= max_len
)
6238 /* Output shifts inline with no loop - faster. */
6241 avr_asm_len (templ
, op
, plen
, t_len
);
6248 avr_asm_len ("ldi %3,%2", op
, plen
, 1);
6250 else if (use_zero_reg
)
6252 /* Hack to save one word: use __zero_reg__ as loop counter.
6253 Set one bit, then shift in a loop until it is 0 again. */
6255 op
[3] = zero_reg_rtx
;
6257 avr_asm_len ("set" CR_TAB
6258 "bld %3,%2-1", op
, plen
, 2);
6262 /* No scratch register available, use one from LD_REGS (saved in
6263 __tmp_reg__) that doesn't overlap with registers to shift. */
6265 op
[3] = all_regs_rtx
[((REGNO (op
[0]) - 1) & 15) + 16];
6266 op
[4] = tmp_reg_rtx
;
6267 saved_in_tmp
= true;
6269 avr_asm_len ("mov %4,%3" CR_TAB
6270 "ldi %3,%2", op
, plen
, 2);
6273 second_label
= false;
6275 else if (MEM_P (op
[2]))
6279 op_mov
[0] = op
[3] = tmp_reg_rtx
;
6282 out_movqi_r_mr (insn
, op_mov
, plen
);
6284 else if (register_operand (op
[2], QImode
))
6288 if (!reg_unused_after (insn
, op
[2])
6289 || reg_overlap_mentioned_p (op
[0], op
[2]))
6291 op
[3] = tmp_reg_rtx
;
6292 avr_asm_len ("mov %3,%2", op
, plen
, 1);
6296 fatal_insn ("bad shift insn:", insn
);
6299 avr_asm_len ("rjmp 2f", op
, plen
, 1);
6301 avr_asm_len ("1:", op
, plen
, 0);
6302 avr_asm_len (templ
, op
, plen
, t_len
);
6305 avr_asm_len ("2:", op
, plen
, 0);
6307 avr_asm_len (use_zero_reg
? "lsr %3" : "dec %3", op
, plen
, 1);
6308 avr_asm_len (second_label
? "brpl 1b" : "brne 1b", op
, plen
, 1);
6311 avr_asm_len ("mov %3,%4", op
, plen
, 1);
6315 /* 8bit shift left ((char)x << i) */
6318 ashlqi3_out (rtx_insn
*insn
, rtx operands
[], int *len
)
6320 if (CONST_INT_P (operands
[2]))
6327 switch (INTVAL (operands
[2]))
6330 if (INTVAL (operands
[2]) < 8)
6342 return ("lsl %0" CR_TAB
6347 return ("lsl %0" CR_TAB
6352 if (test_hard_reg_class (LD_REGS
, operands
[0]))
6355 return ("swap %0" CR_TAB
6359 return ("lsl %0" CR_TAB
6365 if (test_hard_reg_class (LD_REGS
, operands
[0]))
6368 return ("swap %0" CR_TAB
6373 return ("lsl %0" CR_TAB
6380 if (test_hard_reg_class (LD_REGS
, operands
[0]))
6383 return ("swap %0" CR_TAB
6389 return ("lsl %0" CR_TAB
6398 return ("ror %0" CR_TAB
6403 else if (CONSTANT_P (operands
[2]))
6404 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
6406 out_shift_with_cnt ("lsl %0",
6407 insn
, operands
, len
, 1);
6412 /* 16bit shift left ((short)x << i) */
6415 ashlhi3_out (rtx_insn
*insn
, rtx operands
[], int *len
)
6417 if (CONST_INT_P (operands
[2]))
6419 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
6420 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
6427 switch (INTVAL (operands
[2]))
6430 if (INTVAL (operands
[2]) < 16)
6434 return ("clr %B0" CR_TAB
6438 if (optimize_size
&& scratch
)
6443 return ("swap %A0" CR_TAB
6445 "andi %B0,0xf0" CR_TAB
6446 "eor %B0,%A0" CR_TAB
6447 "andi %A0,0xf0" CR_TAB
6453 return ("swap %A0" CR_TAB
6455 "ldi %3,0xf0" CR_TAB
6457 "eor %B0,%A0" CR_TAB
6461 break; /* optimize_size ? 6 : 8 */
6465 break; /* scratch ? 5 : 6 */
6469 return ("lsl %A0" CR_TAB
6473 "andi %B0,0xf0" CR_TAB
6474 "eor %B0,%A0" CR_TAB
6475 "andi %A0,0xf0" CR_TAB
6481 return ("lsl %A0" CR_TAB
6485 "ldi %3,0xf0" CR_TAB
6487 "eor %B0,%A0" CR_TAB
6495 break; /* scratch ? 5 : 6 */
6497 return ("clr __tmp_reg__" CR_TAB
6500 "ror __tmp_reg__" CR_TAB
6503 "ror __tmp_reg__" CR_TAB
6504 "mov %B0,%A0" CR_TAB
6505 "mov %A0,__tmp_reg__");
6509 return ("lsr %B0" CR_TAB
6510 "mov %B0,%A0" CR_TAB
6516 return *len
= 2, ("mov %B0,%A1" CR_TAB
6521 return ("mov %B0,%A0" CR_TAB
6527 return ("mov %B0,%A0" CR_TAB
6534 return ("mov %B0,%A0" CR_TAB
6544 return ("mov %B0,%A0" CR_TAB
6552 return ("mov %B0,%A0" CR_TAB
6555 "ldi %3,0xf0" CR_TAB
6559 return ("mov %B0,%A0" CR_TAB
6570 return ("mov %B0,%A0" CR_TAB
6576 if (AVR_HAVE_MUL
&& scratch
)
6579 return ("ldi %3,0x20" CR_TAB
6583 "clr __zero_reg__");
6585 if (optimize_size
&& scratch
)
6590 return ("mov %B0,%A0" CR_TAB
6594 "ldi %3,0xe0" CR_TAB
6600 return ("set" CR_TAB
6605 "clr __zero_reg__");
6608 return ("mov %B0,%A0" CR_TAB
6617 if (AVR_HAVE_MUL
&& ldi_ok
)
6620 return ("ldi %B0,0x40" CR_TAB
6621 "mul %A0,%B0" CR_TAB
6624 "clr __zero_reg__");
6626 if (AVR_HAVE_MUL
&& scratch
)
6629 return ("ldi %3,0x40" CR_TAB
6633 "clr __zero_reg__");
6635 if (optimize_size
&& ldi_ok
)
6638 return ("mov %B0,%A0" CR_TAB
6639 "ldi %A0,6" "\n1:\t"
6644 if (optimize_size
&& scratch
)
6647 return ("clr %B0" CR_TAB
6656 return ("clr %B0" CR_TAB
6663 out_shift_with_cnt ("lsl %A0" CR_TAB
6664 "rol %B0", insn
, operands
, len
, 2);
6669 /* 24-bit shift left */
6672 avr_out_ashlpsi3 (rtx_insn
*insn
, rtx
*op
, int *plen
)
6677 if (CONST_INT_P (op
[2]))
6679 switch (INTVAL (op
[2]))
6682 if (INTVAL (op
[2]) < 24)
6685 return avr_asm_len ("clr %A0" CR_TAB
6687 "clr %C0", op
, plen
, 3);
6691 int reg0
= REGNO (op
[0]);
6692 int reg1
= REGNO (op
[1]);
6695 return avr_asm_len ("mov %C0,%B1" CR_TAB
6696 "mov %B0,%A1" CR_TAB
6697 "clr %A0", op
, plen
, 3);
6699 return avr_asm_len ("clr %A0" CR_TAB
6700 "mov %B0,%A1" CR_TAB
6701 "mov %C0,%B1", op
, plen
, 3);
6706 int reg0
= REGNO (op
[0]);
6707 int reg1
= REGNO (op
[1]);
6709 if (reg0
+ 2 != reg1
)
6710 avr_asm_len ("mov %C0,%A0", op
, plen
, 1);
6712 return avr_asm_len ("clr %B0" CR_TAB
6713 "clr %A0", op
, plen
, 2);
6717 return avr_asm_len ("clr %C0" CR_TAB
6721 "clr %A0", op
, plen
, 5);
6725 out_shift_with_cnt ("lsl %A0" CR_TAB
6727 "rol %C0", insn
, op
, plen
, 3);
6732 /* 32bit shift left ((long)x << i) */
6735 ashlsi3_out (rtx_insn
*insn
, rtx operands
[], int *len
)
6737 if (CONST_INT_P (operands
[2]))
6745 switch (INTVAL (operands
[2]))
6748 if (INTVAL (operands
[2]) < 32)
6752 return *len
= 3, ("clr %D0" CR_TAB
6756 return ("clr %D0" CR_TAB
6763 int reg0
= true_regnum (operands
[0]);
6764 int reg1
= true_regnum (operands
[1]);
6767 return ("mov %D0,%C1" CR_TAB
6768 "mov %C0,%B1" CR_TAB
6769 "mov %B0,%A1" CR_TAB
6772 return ("clr %A0" CR_TAB
6773 "mov %B0,%A1" CR_TAB
6774 "mov %C0,%B1" CR_TAB
6780 int reg0
= true_regnum (operands
[0]);
6781 int reg1
= true_regnum (operands
[1]);
6782 if (reg0
+ 2 == reg1
)
6783 return *len
= 2, ("clr %B0" CR_TAB
6786 return *len
= 3, ("movw %C0,%A1" CR_TAB
6790 return *len
= 4, ("mov %C0,%A1" CR_TAB
6791 "mov %D0,%B1" CR_TAB
6798 return ("mov %D0,%A1" CR_TAB
6805 return ("clr %D0" CR_TAB
6814 out_shift_with_cnt ("lsl %A0" CR_TAB
6817 "rol %D0", insn
, operands
, len
, 4);
6821 /* 8bit arithmetic shift right ((signed char)x >> i) */
6824 ashrqi3_out (rtx_insn
*insn
, rtx operands
[], int *len
)
6826 if (CONST_INT_P (operands
[2]))
6833 switch (INTVAL (operands
[2]))
6841 return ("asr %0" CR_TAB
6846 return ("asr %0" CR_TAB
6852 return ("asr %0" CR_TAB
6859 return ("asr %0" CR_TAB
6867 return ("bst %0,6" CR_TAB
6873 if (INTVAL (operands
[2]) < 8)
6880 return ("lsl %0" CR_TAB
6884 else if (CONSTANT_P (operands
[2]))
6885 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
6887 out_shift_with_cnt ("asr %0",
6888 insn
, operands
, len
, 1);
6893 /* 16bit arithmetic shift right ((signed short)x >> i) */
6896 ashrhi3_out (rtx_insn
*insn
, rtx operands
[], int *len
)
6898 if (CONST_INT_P (operands
[2]))
6900 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
6901 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
6908 switch (INTVAL (operands
[2]))
6912 /* XXX try to optimize this too? */
6917 break; /* scratch ? 5 : 6 */
6919 return ("mov __tmp_reg__,%A0" CR_TAB
6920 "mov %A0,%B0" CR_TAB
6921 "lsl __tmp_reg__" CR_TAB
6923 "sbc %B0,%B0" CR_TAB
6924 "lsl __tmp_reg__" CR_TAB
6930 return ("lsl %A0" CR_TAB
6931 "mov %A0,%B0" CR_TAB
6937 int reg0
= true_regnum (operands
[0]);
6938 int reg1
= true_regnum (operands
[1]);
6941 return *len
= 3, ("mov %A0,%B0" CR_TAB
6945 return *len
= 4, ("mov %A0,%B1" CR_TAB
6953 return ("mov %A0,%B0" CR_TAB
6955 "sbc %B0,%B0" CR_TAB
6960 return ("mov %A0,%B0" CR_TAB
6962 "sbc %B0,%B0" CR_TAB
6967 if (AVR_HAVE_MUL
&& ldi_ok
)
6970 return ("ldi %A0,0x20" CR_TAB
6971 "muls %B0,%A0" CR_TAB
6973 "sbc %B0,%B0" CR_TAB
6974 "clr __zero_reg__");
6976 if (optimize_size
&& scratch
)
6979 return ("mov %A0,%B0" CR_TAB
6981 "sbc %B0,%B0" CR_TAB
6987 if (AVR_HAVE_MUL
&& ldi_ok
)
6990 return ("ldi %A0,0x10" CR_TAB
6991 "muls %B0,%A0" CR_TAB
6993 "sbc %B0,%B0" CR_TAB
6994 "clr __zero_reg__");
6996 if (optimize_size
&& scratch
)
6999 return ("mov %A0,%B0" CR_TAB
7001 "sbc %B0,%B0" CR_TAB
7008 if (AVR_HAVE_MUL
&& ldi_ok
)
7011 return ("ldi %A0,0x08" CR_TAB
7012 "muls %B0,%A0" CR_TAB
7014 "sbc %B0,%B0" CR_TAB
7015 "clr __zero_reg__");
7018 break; /* scratch ? 5 : 7 */
7020 return ("mov %A0,%B0" CR_TAB
7022 "sbc %B0,%B0" CR_TAB
7031 return ("lsl %B0" CR_TAB
7032 "sbc %A0,%A0" CR_TAB
7034 "mov %B0,%A0" CR_TAB
7038 if (INTVAL (operands
[2]) < 16)
7044 return *len
= 3, ("lsl %B0" CR_TAB
7045 "sbc %A0,%A0" CR_TAB
7050 out_shift_with_cnt ("asr %B0" CR_TAB
7051 "ror %A0", insn
, operands
, len
, 2);
7056 /* 24-bit arithmetic shift right */
7059 avr_out_ashrpsi3 (rtx_insn
*insn
, rtx
*op
, int *plen
)
7061 int dest
= REGNO (op
[0]);
7062 int src
= REGNO (op
[1]);
7064 if (CONST_INT_P (op
[2]))
7069 switch (INTVAL (op
[2]))
7073 return avr_asm_len ("mov %A0,%B1" CR_TAB
7074 "mov %B0,%C1" CR_TAB
7077 "dec %C0", op
, plen
, 5);
7079 return avr_asm_len ("clr %C0" CR_TAB
7082 "mov %B0,%C1" CR_TAB
7083 "mov %A0,%B1", op
, plen
, 5);
7086 if (dest
!= src
+ 2)
7087 avr_asm_len ("mov %A0,%C1", op
, plen
, 1);
7089 return avr_asm_len ("clr %B0" CR_TAB
7092 "mov %C0,%B0", op
, plen
, 4);
7095 if (INTVAL (op
[2]) < 24)
7101 return avr_asm_len ("lsl %C0" CR_TAB
7102 "sbc %A0,%A0" CR_TAB
7103 "mov %B0,%A0" CR_TAB
7104 "mov %C0,%A0", op
, plen
, 4);
7108 out_shift_with_cnt ("asr %C0" CR_TAB
7110 "ror %A0", insn
, op
, plen
, 3);
7115 /* 32-bit arithmetic shift right ((signed long)x >> i) */
7118 ashrsi3_out (rtx_insn
*insn
, rtx operands
[], int *len
)
7120 if (CONST_INT_P (operands
[2]))
7128 switch (INTVAL (operands
[2]))
7132 int reg0
= true_regnum (operands
[0]);
7133 int reg1
= true_regnum (operands
[1]);
7136 return ("mov %A0,%B1" CR_TAB
7137 "mov %B0,%C1" CR_TAB
7138 "mov %C0,%D1" CR_TAB
7143 return ("clr %D0" CR_TAB
7146 "mov %C0,%D1" CR_TAB
7147 "mov %B0,%C1" CR_TAB
7153 int reg0
= true_regnum (operands
[0]);
7154 int reg1
= true_regnum (operands
[1]);
7156 if (reg0
== reg1
+ 2)
7157 return *len
= 4, ("clr %D0" CR_TAB
7162 return *len
= 5, ("movw %A0,%C1" CR_TAB
7168 return *len
= 6, ("mov %B0,%D1" CR_TAB
7169 "mov %A0,%C1" CR_TAB
7177 return *len
= 6, ("mov %A0,%D1" CR_TAB
7181 "mov %B0,%D0" CR_TAB
7185 if (INTVAL (operands
[2]) < 32)
7192 return *len
= 4, ("lsl %D0" CR_TAB
7193 "sbc %A0,%A0" CR_TAB
7194 "mov %B0,%A0" CR_TAB
7197 return *len
= 5, ("lsl %D0" CR_TAB
7198 "sbc %A0,%A0" CR_TAB
7199 "mov %B0,%A0" CR_TAB
7200 "mov %C0,%A0" CR_TAB
7205 out_shift_with_cnt ("asr %D0" CR_TAB
7208 "ror %A0", insn
, operands
, len
, 4);
7212 /* 8-bit logic shift right ((unsigned char)x >> i) */
7215 lshrqi3_out (rtx_insn
*insn
, rtx operands
[], int *len
)
7217 if (CONST_INT_P (operands
[2]))
7224 switch (INTVAL (operands
[2]))
7227 if (INTVAL (operands
[2]) < 8)
7239 return ("lsr %0" CR_TAB
7243 return ("lsr %0" CR_TAB
7248 if (test_hard_reg_class (LD_REGS
, operands
[0]))
7251 return ("swap %0" CR_TAB
7255 return ("lsr %0" CR_TAB
7261 if (test_hard_reg_class (LD_REGS
, operands
[0]))
7264 return ("swap %0" CR_TAB
7269 return ("lsr %0" CR_TAB
7276 if (test_hard_reg_class (LD_REGS
, operands
[0]))
7279 return ("swap %0" CR_TAB
7285 return ("lsr %0" CR_TAB
7294 return ("rol %0" CR_TAB
7299 else if (CONSTANT_P (operands
[2]))
7300 fatal_insn ("internal compiler error. Incorrect shift:", insn
);
7302 out_shift_with_cnt ("lsr %0",
7303 insn
, operands
, len
, 1);
7307 /* 16-bit logic shift right ((unsigned short)x >> i) */
7310 lshrhi3_out (rtx_insn
*insn
, rtx operands
[], int *len
)
7312 if (CONST_INT_P (operands
[2]))
7314 int scratch
= (GET_CODE (PATTERN (insn
)) == PARALLEL
);
7315 int ldi_ok
= test_hard_reg_class (LD_REGS
, operands
[0]);
7322 switch (INTVAL (operands
[2]))
7325 if (INTVAL (operands
[2]) < 16)
7329 return ("clr %B0" CR_TAB
7333 if (optimize_size
&& scratch
)
7338 return ("swap %B0" CR_TAB
7340 "andi %A0,0x0f" CR_TAB
7341 "eor %A0,%B0" CR_TAB
7342 "andi %B0,0x0f" CR_TAB
7348 return ("swap %B0" CR_TAB
7350 "ldi %3,0x0f" CR_TAB
7352 "eor %A0,%B0" CR_TAB
7356 break; /* optimize_size ? 6 : 8 */
7360 break; /* scratch ? 5 : 6 */
7364 return ("lsr %B0" CR_TAB
7368 "andi %A0,0x0f" CR_TAB
7369 "eor %A0,%B0" CR_TAB
7370 "andi %B0,0x0f" CR_TAB
7376 return ("lsr %B0" CR_TAB
7380 "ldi %3,0x0f" CR_TAB
7382 "eor %A0,%B0" CR_TAB
7390 break; /* scratch ? 5 : 6 */
7392 return ("clr __tmp_reg__" CR_TAB
7395 "rol __tmp_reg__" CR_TAB
7398 "rol __tmp_reg__" CR_TAB
7399 "mov %A0,%B0" CR_TAB
7400 "mov %B0,__tmp_reg__");
7404 return ("lsl %A0" CR_TAB
7405 "mov %A0,%B0" CR_TAB
7407 "sbc %B0,%B0" CR_TAB
7411 return *len
= 2, ("mov %A0,%B1" CR_TAB
7416 return ("mov %A0,%B0" CR_TAB
7422 return ("mov %A0,%B0" CR_TAB
7429 return ("mov %A0,%B0" CR_TAB
7439 return ("mov %A0,%B0" CR_TAB
7447 return ("mov %A0,%B0" CR_TAB
7450 "ldi %3,0x0f" CR_TAB
7454 return ("mov %A0,%B0" CR_TAB
7465 return ("mov %A0,%B0" CR_TAB
7471 if (AVR_HAVE_MUL
&& scratch
)
7474 return ("ldi %3,0x08" CR_TAB
7478 "clr __zero_reg__");
7480 if (optimize_size
&& scratch
)
7485 return ("mov %A0,%B0" CR_TAB
7489 "ldi %3,0x07" CR_TAB
7495 return ("set" CR_TAB
7500 "clr __zero_reg__");
7503 return ("mov %A0,%B0" CR_TAB
7512 if (AVR_HAVE_MUL
&& ldi_ok
)
7515 return ("ldi %A0,0x04" CR_TAB
7516 "mul %B0,%A0" CR_TAB
7519 "clr __zero_reg__");
7521 if (AVR_HAVE_MUL
&& scratch
)
7524 return ("ldi %3,0x04" CR_TAB
7528 "clr __zero_reg__");
7530 if (optimize_size
&& ldi_ok
)
7533 return ("mov %A0,%B0" CR_TAB
7534 "ldi %B0,6" "\n1:\t"
7539 if (optimize_size
&& scratch
)
7542 return ("clr %A0" CR_TAB
7551 return ("clr %A0" CR_TAB
7558 out_shift_with_cnt ("lsr %B0" CR_TAB
7559 "ror %A0", insn
, operands
, len
, 2);
7564 /* 24-bit logic shift right */
7567 avr_out_lshrpsi3 (rtx_insn
*insn
, rtx
*op
, int *plen
)
7569 int dest
= REGNO (op
[0]);
7570 int src
= REGNO (op
[1]);
7572 if (CONST_INT_P (op
[2]))
7577 switch (INTVAL (op
[2]))
7581 return avr_asm_len ("mov %A0,%B1" CR_TAB
7582 "mov %B0,%C1" CR_TAB
7583 "clr %C0", op
, plen
, 3);
7585 return avr_asm_len ("clr %C0" CR_TAB
7586 "mov %B0,%C1" CR_TAB
7587 "mov %A0,%B1", op
, plen
, 3);
7590 if (dest
!= src
+ 2)
7591 avr_asm_len ("mov %A0,%C1", op
, plen
, 1);
7593 return avr_asm_len ("clr %B0" CR_TAB
7594 "clr %C0", op
, plen
, 2);
7597 if (INTVAL (op
[2]) < 24)
7603 return avr_asm_len ("clr %A0" CR_TAB
7607 "clr %C0", op
, plen
, 5);
7611 out_shift_with_cnt ("lsr %C0" CR_TAB
7613 "ror %A0", insn
, op
, plen
, 3);
7618 /* 32-bit logic shift right ((unsigned int)x >> i) */
7621 lshrsi3_out (rtx_insn
*insn
, rtx operands
[], int *len
)
7623 if (CONST_INT_P (operands
[2]))
7631 switch (INTVAL (operands
[2]))
7634 if (INTVAL (operands
[2]) < 32)
7638 return *len
= 3, ("clr %D0" CR_TAB
7642 return ("clr %D0" CR_TAB
7649 int reg0
= true_regnum (operands
[0]);
7650 int reg1
= true_regnum (operands
[1]);
7653 return ("mov %A0,%B1" CR_TAB
7654 "mov %B0,%C1" CR_TAB
7655 "mov %C0,%D1" CR_TAB
7658 return ("clr %D0" CR_TAB
7659 "mov %C0,%D1" CR_TAB
7660 "mov %B0,%C1" CR_TAB
7666 int reg0
= true_regnum (operands
[0]);
7667 int reg1
= true_regnum (operands
[1]);
7669 if (reg0
== reg1
+ 2)
7670 return *len
= 2, ("clr %C0" CR_TAB
7673 return *len
= 3, ("movw %A0,%C1" CR_TAB
7677 return *len
= 4, ("mov %B0,%D1" CR_TAB
7678 "mov %A0,%C1" CR_TAB
7684 return *len
= 4, ("mov %A0,%D1" CR_TAB
7691 return ("clr %A0" CR_TAB
7700 out_shift_with_cnt ("lsr %D0" CR_TAB
7703 "ror %A0", insn
, operands
, len
, 4);
7708 /* Output addition of register XOP[0] and compile time constant XOP[2].
7709 CODE == PLUS: perform addition by using ADD instructions or
7710 CODE == MINUS: perform addition by using SUB instructions:
7712 XOP[0] = XOP[0] + XOP[2]
7714 Or perform addition/subtraction with register XOP[2] depending on CODE:
7716 XOP[0] = XOP[0] +/- XOP[2]
7718 If PLEN == NULL, print assembler instructions to perform the operation;
7719 otherwise, set *PLEN to the length of the instruction sequence (in words)
7720 printed with PLEN == NULL. XOP[3] is an 8-bit scratch register or NULL_RTX.
7721 Set *PCC to effect on cc0 according to respective CC_* insn attribute.
7723 CODE_SAT == UNKNOWN: Perform ordinary, non-saturating operation.
7724 CODE_SAT != UNKNOWN: Perform operation and saturate according to CODE_SAT.
7725 If CODE_SAT != UNKNOWN then SIGN contains the sign of the summand resp.
7726 the subtrahend in the original insn, provided it is a compile time constant.
7727 In all other cases, SIGN is 0.
7729 If OUT_LABEL is true, print the final 0: label which is needed for
7730 saturated addition / subtraction. The only case where OUT_LABEL = false
7731 is useful is for saturated addition / subtraction performed during
7732 fixed-point rounding, cf. `avr_out_round'. */
7735 avr_out_plus_1 (rtx
*xop
, int *plen
, enum rtx_code code
, int *pcc
,
7736 enum rtx_code code_sat
, int sign
, bool out_label
)
7738 /* MODE of the operation. */
7739 machine_mode mode
= GET_MODE (xop
[0]);
7741 /* INT_MODE of the same size. */
7742 scalar_int_mode imode
= int_mode_for_mode (mode
).require ();
7744 /* Number of bytes to operate on. */
7745 int n_bytes
= GET_MODE_SIZE (mode
);
7747 /* Value (0..0xff) held in clobber register op[3] or -1 if unknown. */
7748 int clobber_val
= -1;
7750 /* op[0]: 8-bit destination register
7751 op[1]: 8-bit const int
7752 op[2]: 8-bit scratch register */
7755 /* Started the operation? Before starting the operation we may skip
7756 adding 0. This is no more true after the operation started because
7757 carry must be taken into account. */
7758 bool started
= false;
7760 /* Value to add. There are two ways to add VAL: R += VAL and R -= -VAL. */
7763 /* Output a BRVC instruction. Only needed with saturation. */
7764 bool out_brvc
= true;
7771 *pcc
= MINUS
== code
? (int) CC_SET_CZN
: (int) CC_CLOBBER
;
7773 for (int i
= 0; i
< n_bytes
; i
++)
7775 /* We operate byte-wise on the destination. */
7776 op
[0] = simplify_gen_subreg (QImode
, xop
[0], mode
, i
);
7777 op
[1] = simplify_gen_subreg (QImode
, xop
[2], mode
, i
);
7780 avr_asm_len (code
== PLUS
? "add %0,%1" : "sub %0,%1",
7783 avr_asm_len (code
== PLUS
? "adc %0,%1" : "sbc %0,%1",
7787 if (reg_overlap_mentioned_p (xop
[0], xop
[2]))
7789 gcc_assert (REGNO (xop
[0]) == REGNO (xop
[2]));
7798 /* Except in the case of ADIW with 16-bit register (see below)
7799 addition does not set cc0 in a usable way. */
7801 *pcc
= (MINUS
== code
) ? CC_SET_CZN
: CC_CLOBBER
;
7803 if (CONST_FIXED_P (xval
))
7804 xval
= avr_to_int_mode (xval
);
7806 /* Adding/Subtracting zero is a no-op. */
7808 if (xval
== const0_rtx
)
7815 xval
= simplify_unary_operation (NEG
, imode
, xval
, imode
);
7819 if (SS_PLUS
== code_sat
&& MINUS
== code
7821 && 0x80 == (INTVAL (simplify_gen_subreg (QImode
, xval
, imode
, n_bytes
-1))
7822 & GET_MODE_MASK (QImode
)))
7824 /* We compute x + 0x80 by means of SUB instructions. We negated the
7825 constant subtrahend above and are left with x - (-128) so that we
7826 need something like SUBI r,128 which does not exist because SUBI sets
7827 V according to the sign of the subtrahend. Notice the only case
7828 where this must be done is when NEG overflowed in case [2s] because
7829 the V computation needs the right sign of the subtrahend. */
7831 rtx msb
= simplify_gen_subreg (QImode
, xop
[0], mode
, n_bytes
- 1);
7833 avr_asm_len ("subi %0,128" CR_TAB
7834 "brmi 0f", &msb
, plen
, 2);
7840 for (int i
= 0; i
< n_bytes
; i
++)
7842 /* We operate byte-wise on the destination. */
7843 rtx reg8
= simplify_gen_subreg (QImode
, xop
[0], mode
, i
);
7844 rtx xval8
= simplify_gen_subreg (QImode
, xval
, imode
, i
);
7846 /* 8-bit value to operate with this byte. */
7847 unsigned int val8
= UINTVAL (xval8
) & GET_MODE_MASK (QImode
);
7849 /* Registers R16..R31 can operate with immediate. */
7850 bool ld_reg_p
= test_hard_reg_class (LD_REGS
, reg8
);
7853 op
[1] = gen_int_mode (val8
, QImode
);
7855 /* To get usable cc0 no low-bytes must have been skipped. */
7863 && test_hard_reg_class (ADDW_REGS
, reg8
))
7865 rtx xval16
= simplify_gen_subreg (HImode
, xval
, imode
, i
);
7866 unsigned int val16
= UINTVAL (xval16
) & GET_MODE_MASK (HImode
);
7868 /* Registers R24, X, Y, Z can use ADIW/SBIW with constants < 64
7869 i.e. operate word-wise. */
7876 avr_asm_len (code
== PLUS
? "adiw %0,%1" : "sbiw %0,%1",
7879 if (n_bytes
== 2 && PLUS
== code
)
7891 avr_asm_len (code
== PLUS
7892 ? "adc %0,__zero_reg__" : "sbc %0,__zero_reg__",
7896 else if ((val8
== 1 || val8
== 0xff)
7897 && UNKNOWN
== code_sat
7899 && i
== n_bytes
- 1)
7901 avr_asm_len ((code
== PLUS
) ^ (val8
== 1) ? "dec %0" : "inc %0",
7911 gcc_assert (plen
!= NULL
|| (op
[2] && REG_P (op
[2])));
7913 if (plen
!= NULL
&& UNKNOWN
!= code_sat
)
7915 /* This belongs to the x + 0x80 corner case. The code with
7916 ADD instruction is not smaller, thus make this case
7917 expensive so that the caller won't pick it. */
7923 if (clobber_val
!= (int) val8
)
7924 avr_asm_len ("ldi %2,%1", op
, plen
, 1);
7925 clobber_val
= (int) val8
;
7927 avr_asm_len (started
? "adc %0,%2" : "add %0,%2", op
, plen
, 1);
7934 avr_asm_len (started
? "sbci %0,%1" : "subi %0,%1", op
, plen
, 1);
7937 gcc_assert (plen
!= NULL
|| REG_P (op
[2]));
7939 if (clobber_val
!= (int) val8
)
7940 avr_asm_len ("ldi %2,%1", op
, plen
, 1);
7941 clobber_val
= (int) val8
;
7943 avr_asm_len (started
? "sbc %0,%2" : "sub %0,%2", op
, plen
, 1);
7955 } /* for all sub-bytes */
7959 if (UNKNOWN
== code_sat
)
7962 *pcc
= (int) CC_CLOBBER
;
7964 /* Vanilla addition/subtraction is done. We are left with saturation.
7966 We have to compute A = A <op> B where A is a register and
7967 B is a register or a non-zero compile time constant CONST.
7968 A is register class "r" if unsigned && B is REG. Otherwise, A is in "d".
7969 B stands for the original operand $2 in INSN. In the case of B = CONST,
7970 SIGN in { -1, 1 } is the sign of B. Otherwise, SIGN is 0.
7972 CODE is the instruction flavor we use in the asm sequence to perform <op>.
7976 operation | code | sat if | b is | sat value | case
7977 -----------------+-------+----------+--------------+-----------+-------
7978 + as a + b | add | C == 1 | const, reg | u+ = 0xff | [1u]
7979 + as a - (-b) | sub | C == 0 | const | u+ = 0xff | [2u]
7980 - as a - b | sub | C == 1 | const, reg | u- = 0 | [3u]
7981 - as a + (-b) | add | C == 0 | const | u- = 0 | [4u]
7985 operation | code | sat if | b is | sat value | case
7986 -----------------+-------+----------+--------------+-----------+-------
7987 + as a + b | add | V == 1 | const, reg | s+ | [1s]
7988 + as a - (-b) | sub | V == 1 | const | s+ | [2s]
7989 - as a - b | sub | V == 1 | const, reg | s- | [3s]
7990 - as a + (-b) | add | V == 1 | const | s- | [4s]
7992 s+ = b < 0 ? -0x80 : 0x7f
7993 s- = b < 0 ? 0x7f : -0x80
7995 The cases a - b actually perform a - (-(-b)) if B is CONST.
7998 op
[0] = simplify_gen_subreg (QImode
, xop
[0], mode
, n_bytes
-1);
8000 ? simplify_gen_subreg (QImode
, xop
[0], mode
, n_bytes
-2)
8003 bool need_copy
= true;
8004 int len_call
= 1 + AVR_HAVE_JMP_CALL
;
8015 avr_asm_len ("brvc 0f", op
, plen
, 1);
8017 if (reg_overlap_mentioned_p (xop
[0], xop
[2]))
8022 avr_asm_len ("ldi %0,0x7f" CR_TAB
8023 "adc %0,__zero_reg__", op
, plen
, 2);
8025 avr_asm_len ("ldi %0,0x7f" CR_TAB
8026 "ldi %1,0xff" CR_TAB
8027 "adc %1,__zero_reg__" CR_TAB
8028 "adc %0,__zero_reg__", op
, plen
, 4);
8030 else if (sign
== 0 && PLUS
== code
)
8034 op
[2] = simplify_gen_subreg (QImode
, xop
[2], mode
, n_bytes
-1);
8037 avr_asm_len ("ldi %0,0x80" CR_TAB
8039 "dec %0", op
, plen
, 3);
8041 avr_asm_len ("ldi %0,0x80" CR_TAB
8044 "sbci %0,0", op
, plen
, 4);
8046 else if (sign
== 0 && MINUS
== code
)
8050 op
[2] = simplify_gen_subreg (QImode
, xop
[2], mode
, n_bytes
-1);
8053 avr_asm_len ("ldi %0,0x7f" CR_TAB
8055 "inc %0", op
, plen
, 3);
8057 avr_asm_len ("ldi %0,0x7f" CR_TAB
8060 "sbci %0,-1", op
, plen
, 4);
8062 else if ((sign
< 0) ^ (SS_MINUS
== code_sat
))
8064 /* [1s,const,B < 0] [2s,B < 0] */
8065 /* [3s,const,B > 0] [4s,B > 0] */
8069 avr_asm_len ("%~call __clr_8", op
, plen
, len_call
);
8073 avr_asm_len ("ldi %0,0x80", op
, plen
, 1);
8074 if (n_bytes
> 1 && need_copy
)
8075 avr_asm_len ("clr %1", op
, plen
, 1);
8077 else if ((sign
> 0) ^ (SS_MINUS
== code_sat
))
8079 /* [1s,const,B > 0] [2s,B > 0] */
8080 /* [3s,const,B < 0] [4s,B < 0] */
8084 avr_asm_len ("sec" CR_TAB
8085 "%~call __sbc_8", op
, plen
, 1 + len_call
);
8089 avr_asm_len ("ldi %0,0x7f", op
, plen
, 1);
8090 if (n_bytes
> 1 && need_copy
)
8091 avr_asm_len ("ldi %1,0xff", op
, plen
, 1);
8101 avr_asm_len (PLUS
== code
? "brcc 0f" : "brcs 0f", op
, plen
, 1);
8106 avr_asm_len ("sec", op
, plen
, 1);
8107 avr_asm_len ("%~call __sbc_8", op
, plen
, len_call
);
8113 if (MINUS
== code
&& !test_hard_reg_class (LD_REGS
, op
[0]))
8114 avr_asm_len ("sec" CR_TAB
8115 "sbc %0,%0", op
, plen
, 2);
8117 avr_asm_len (PLUS
== code
? "sbc %0,%0" : "ldi %0,0xff",
8120 break; /* US_PLUS */
8125 avr_asm_len (PLUS
== code
? "brcs 0f" : "brcc 0f", op
, plen
, 1);
8129 avr_asm_len ("%~call __clr_8", op
, plen
, len_call
);
8133 avr_asm_len ("clr %0", op
, plen
, 1);
8138 /* We set the MSB in the unsigned case and the 2 MSBs in the signed case.
8139 Now copy the right value to the LSBs. */
8141 if (need_copy
&& n_bytes
> 1)
8143 if (US_MINUS
== code_sat
|| US_PLUS
== code_sat
)
8145 avr_asm_len ("mov %1,%0", op
, plen
, 1);
8151 avr_asm_len ("movw %0,%1", op
, plen
, 1);
8153 avr_asm_len ("mov %A0,%1" CR_TAB
8154 "mov %B0,%1", op
, plen
, 2);
8157 else if (n_bytes
> 2)
8160 avr_asm_len ("mov %A0,%1" CR_TAB
8161 "mov %B0,%1", op
, plen
, 2);
8165 if (need_copy
&& n_bytes
== 8)
8168 avr_asm_len ("movw %r0+2,%0" CR_TAB
8169 "movw %r0+4,%0", xop
, plen
, 2);
8171 avr_asm_len ("mov %r0+2,%0" CR_TAB
8172 "mov %r0+3,%0" CR_TAB
8173 "mov %r0+4,%0" CR_TAB
8174 "mov %r0+5,%0", xop
, plen
, 4);
8178 avr_asm_len ("0:", op
, plen
, 0);
8182 /* Output addition/subtraction of register XOP[0] and a constant XOP[2] that
8183 is ont a compile-time constant:
8185 XOP[0] = XOP[0] +/- XOP[2]
8187 This is a helper for the function below. The only insns that need this
8188 are additions/subtraction for pointer modes, i.e. HImode and PSImode. */
8191 avr_out_plus_symbol (rtx
*xop
, enum rtx_code code
, int *plen
, int *pcc
)
8193 machine_mode mode
= GET_MODE (xop
[0]);
8195 /* Only pointer modes want to add symbols. */
8197 gcc_assert (mode
== HImode
|| mode
== PSImode
);
8199 *pcc
= MINUS
== code
? (int) CC_SET_CZN
: (int) CC_SET_N
;
8201 avr_asm_len (PLUS
== code
8202 ? "subi %A0,lo8(-(%2))" CR_TAB
"sbci %B0,hi8(-(%2))"
8203 : "subi %A0,lo8(%2)" CR_TAB
"sbci %B0,hi8(%2)",
8206 if (PSImode
== mode
)
8207 avr_asm_len (PLUS
== code
8208 ? "sbci %C0,hlo8(-(%2))"
8209 : "sbci %C0,hlo8(%2)", xop
, plen
, 1);
8214 /* Prepare operands of addition/subtraction to be used with avr_out_plus_1.
8216 INSN is a single_set insn or an insn pattern with a binary operation as
8217 SET_SRC that is one of: PLUS, SS_PLUS, US_PLUS, MINUS, SS_MINUS, US_MINUS.
8219 XOP are the operands of INSN. In the case of 64-bit operations with
8220 constant XOP[] has just one element: The summand/subtrahend in XOP[0].
8221 The non-saturating insns up to 32 bits may or may not supply a "d" class
8224 If PLEN == NULL output the instructions.
8225 If PLEN != NULL set *PLEN to the length of the sequence in words.
8227 PCC is a pointer to store the instructions' effect on cc0.
8230 PLEN and PCC default to NULL.
8232 OUT_LABEL defaults to TRUE. For a description, see AVR_OUT_PLUS_1.
8237 avr_out_plus (rtx insn
, rtx
*xop
, int *plen
, int *pcc
, bool out_label
)
8239 int cc_plus
, cc_minus
, cc_dummy
;
8240 int len_plus
, len_minus
;
8242 rtx xpattern
= INSN_P (insn
) ? single_set (as_a
<rtx_insn
*> (insn
)) : insn
;
8243 rtx xdest
= SET_DEST (xpattern
);
8244 machine_mode mode
= GET_MODE (xdest
);
8245 scalar_int_mode imode
= int_mode_for_mode (mode
).require ();
8246 int n_bytes
= GET_MODE_SIZE (mode
);
8247 enum rtx_code code_sat
= GET_CODE (SET_SRC (xpattern
));
8249 = (PLUS
== code_sat
|| SS_PLUS
== code_sat
|| US_PLUS
== code_sat
8255 /* PLUS and MINUS don't saturate: Use modular wrap-around. */
8257 if (PLUS
== code_sat
|| MINUS
== code_sat
)
8260 if (n_bytes
<= 4 && REG_P (xop
[2]))
8262 avr_out_plus_1 (xop
, plen
, code
, pcc
, code_sat
, 0, out_label
);
8268 op
[0] = gen_rtx_REG (DImode
, ACC_A
);
8269 op
[1] = gen_rtx_REG (DImode
, ACC_A
);
8270 op
[2] = avr_to_int_mode (xop
[0]);
8275 && !CONST_INT_P (xop
[2])
8276 && !CONST_FIXED_P (xop
[2]))
8278 return avr_out_plus_symbol (xop
, code
, plen
, pcc
);
8281 op
[0] = avr_to_int_mode (xop
[0]);
8282 op
[1] = avr_to_int_mode (xop
[1]);
8283 op
[2] = avr_to_int_mode (xop
[2]);
8286 /* Saturations and 64-bit operations don't have a clobber operand.
8287 For the other cases, the caller will provide a proper XOP[3]. */
8289 xpattern
= INSN_P (insn
) ? PATTERN (insn
) : insn
;
8290 op
[3] = PARALLEL
== GET_CODE (xpattern
) ? xop
[3] : NULL_RTX
;
8292 /* Saturation will need the sign of the original operand. */
8294 rtx xmsb
= simplify_gen_subreg (QImode
, op
[2], imode
, n_bytes
-1);
8295 int sign
= INTVAL (xmsb
) < 0 ? -1 : 1;
8297 /* If we subtract and the subtrahend is a constant, then negate it
8298 so that avr_out_plus_1 can be used. */
8301 op
[2] = simplify_unary_operation (NEG
, imode
, op
[2], imode
);
8303 /* Work out the shortest sequence. */
8305 avr_out_plus_1 (op
, &len_minus
, MINUS
, &cc_minus
, code_sat
, sign
, out_label
);
8306 avr_out_plus_1 (op
, &len_plus
, PLUS
, &cc_plus
, code_sat
, sign
, out_label
);
8310 *plen
= (len_minus
<= len_plus
) ? len_minus
: len_plus
;
8311 *pcc
= (len_minus
<= len_plus
) ? cc_minus
: cc_plus
;
8313 else if (len_minus
<= len_plus
)
8314 avr_out_plus_1 (op
, NULL
, MINUS
, pcc
, code_sat
, sign
, out_label
);
8316 avr_out_plus_1 (op
, NULL
, PLUS
, pcc
, code_sat
, sign
, out_label
);
8322 /* Output bit operation (IOR, AND, XOR) with register XOP[0] and compile
8323 time constant XOP[2]:
8325 XOP[0] = XOP[0] <op> XOP[2]
8327 and return "". If PLEN == NULL, print assembler instructions to perform the
8328 operation; otherwise, set *PLEN to the length of the instruction sequence
8329 (in words) printed with PLEN == NULL. XOP[3] is either an 8-bit clobber
8330 register or SCRATCH if no clobber register is needed for the operation.
8331 INSN is an INSN_P or a pattern of an insn. */
8334 avr_out_bitop (rtx insn
, rtx
*xop
, int *plen
)
8336 /* CODE and MODE of the operation. */
8337 rtx xpattern
= INSN_P (insn
) ? single_set (as_a
<rtx_insn
*> (insn
)) : insn
;
8338 enum rtx_code code
= GET_CODE (SET_SRC (xpattern
));
8339 machine_mode mode
= GET_MODE (xop
[0]);
8341 /* Number of bytes to operate on. */
8342 int n_bytes
= GET_MODE_SIZE (mode
);
8344 /* Value of T-flag (0 or 1) or -1 if unknow. */
8347 /* Value (0..0xff) held in clobber register op[3] or -1 if unknown. */
8348 int clobber_val
= -1;
8350 /* op[0]: 8-bit destination register
8351 op[1]: 8-bit const int
8352 op[2]: 8-bit clobber register, SCRATCH or NULL_RTX.
8353 op[3]: 8-bit register containing 0xff or NULL_RTX */
8356 op
[2] = QImode
== mode
? NULL_RTX
: xop
[3];
8362 for (int i
= 0; i
< n_bytes
; i
++)
8364 /* We operate byte-wise on the destination. */
8365 rtx reg8
= simplify_gen_subreg (QImode
, xop
[0], mode
, i
);
8366 rtx xval8
= simplify_gen_subreg (QImode
, xop
[2], mode
, i
);
8368 /* 8-bit value to operate with this byte. */
8369 unsigned int val8
= UINTVAL (xval8
) & GET_MODE_MASK (QImode
);
8371 /* Number of bits set in the current byte of the constant. */
8372 int pop8
= popcount_hwi (val8
);
8374 /* Registers R16..R31 can operate with immediate. */
8375 bool ld_reg_p
= test_hard_reg_class (LD_REGS
, reg8
);
8378 op
[1] = GEN_INT (val8
);
8387 avr_asm_len ("ori %0,%1", op
, plen
, 1);
8391 avr_asm_len ("set", op
, plen
, 1);
8394 op
[1] = GEN_INT (exact_log2 (val8
));
8395 avr_asm_len ("bld %0,%1", op
, plen
, 1);
8399 if (op
[3] != NULL_RTX
)
8400 avr_asm_len ("mov %0,%3", op
, plen
, 1);
8402 avr_asm_len ("clr %0" CR_TAB
8403 "dec %0", op
, plen
, 2);
8409 if (clobber_val
!= (int) val8
)
8410 avr_asm_len ("ldi %2,%1", op
, plen
, 1);
8411 clobber_val
= (int) val8
;
8413 avr_asm_len ("or %0,%2", op
, plen
, 1);
8423 avr_asm_len ("clr %0", op
, plen
, 1);
8425 avr_asm_len ("andi %0,%1", op
, plen
, 1);
8429 avr_asm_len ("clt", op
, plen
, 1);
8432 op
[1] = GEN_INT (exact_log2 (GET_MODE_MASK (QImode
) & ~val8
));
8433 avr_asm_len ("bld %0,%1", op
, plen
, 1);
8437 if (clobber_val
!= (int) val8
)
8438 avr_asm_len ("ldi %2,%1", op
, plen
, 1);
8439 clobber_val
= (int) val8
;
8441 avr_asm_len ("and %0,%2", op
, plen
, 1);
8451 avr_asm_len ("com %0", op
, plen
, 1);
8452 else if (ld_reg_p
&& val8
== (1 << 7))
8453 avr_asm_len ("subi %0,%1", op
, plen
, 1);
8456 if (clobber_val
!= (int) val8
)
8457 avr_asm_len ("ldi %2,%1", op
, plen
, 1);
8458 clobber_val
= (int) val8
;
8460 avr_asm_len ("eor %0,%2", op
, plen
, 1);
8466 /* Unknown rtx_code */
8469 } /* for all sub-bytes */
8475 /* Output sign extension from XOP[1] to XOP[0] and return "".
8476 If PLEN == NULL, print assembler instructions to perform the operation;
8477 otherwise, set *PLEN to the length of the instruction sequence (in words)
8478 as printed with PLEN == NULL. */
8481 avr_out_sign_extend (rtx_insn
*insn
, rtx
*xop
, int *plen
)
8483 // Size in bytes of source resp. destination operand.
8484 unsigned n_src
= GET_MODE_SIZE (GET_MODE (xop
[1]));
8485 unsigned n_dest
= GET_MODE_SIZE (GET_MODE (xop
[0]));
8486 rtx r_msb
= all_regs_rtx
[REGNO (xop
[1]) + n_src
- 1];
8491 // Copy destination to source
8493 if (REGNO (xop
[0]) != REGNO (xop
[1]))
8495 gcc_assert (n_src
<= 2);
8498 avr_asm_len (AVR_HAVE_MOVW
8500 : "mov %B0,%B1", xop
, plen
, 1);
8501 if (n_src
== 1 || !AVR_HAVE_MOVW
)
8502 avr_asm_len ("mov %A0,%A1", xop
, plen
, 1);
8505 // Set Carry to the sign bit MSB.7...
8507 if (REGNO (xop
[0]) == REGNO (xop
[1])
8508 || !reg_unused_after (insn
, r_msb
))
8510 avr_asm_len ("mov __tmp_reg__,%0", &r_msb
, plen
, 1);
8511 r_msb
= tmp_reg_rtx
;
8514 avr_asm_len ("lsl %0", &r_msb
, plen
, 1);
8516 // ...and propagate it to all the new sign bits
8518 for (unsigned n
= n_src
; n
< n_dest
; n
++)
8519 avr_asm_len ("sbc %0,%0", &all_regs_rtx
[REGNO (xop
[0]) + n
], plen
, 1);
8525 /* PLEN == NULL: Output code to add CONST_INT OP[0] to SP.
8526 PLEN != NULL: Set *PLEN to the length of that sequence.
8530 avr_out_addto_sp (rtx
*op
, int *plen
)
8532 int pc_len
= AVR_2_BYTE_PC
? 2 : 3;
8533 int addend
= INTVAL (op
[0]);
8540 if (flag_verbose_asm
|| flag_print_asm_name
)
8541 avr_asm_len (ASM_COMMENT_START
"SP -= %n0", op
, plen
, 0);
8543 while (addend
<= -pc_len
)
8546 avr_asm_len ("rcall .", op
, plen
, 1);
8549 while (addend
++ < 0)
8550 avr_asm_len ("push __tmp_reg__", op
, plen
, 1);
8552 else if (addend
> 0)
8554 if (flag_verbose_asm
|| flag_print_asm_name
)
8555 avr_asm_len (ASM_COMMENT_START
"SP += %0", op
, plen
, 0);
8557 while (addend
-- > 0)
8558 avr_asm_len ("pop __tmp_reg__", op
, plen
, 1);
8565 /* Output instructions to insert an inverted bit into OPERANDS[0]:
8566 $0.$1 = ~$2.$3 if XBITNO = NULL
8567 $0.$1 = ~$2.XBITNO if XBITNO != NULL.
8568 If PLEN = NULL then output the respective instruction sequence which
8569 is a combination of BST / BLD and some instruction(s) to invert the bit.
8570 If PLEN != NULL then store the length of the sequence (in words) in *PLEN.
8574 avr_out_insert_notbit (rtx_insn
*insn
, rtx operands
[], rtx xbitno
, int *plen
)
8576 rtx op
[4] = { operands
[0], operands
[1], operands
[2],
8577 xbitno
== NULL_RTX
? operands
[3] : xbitno
};
8579 if (INTVAL (op
[1]) == 7
8580 && test_hard_reg_class (LD_REGS
, op
[0]))
8582 /* If the inserted bit number is 7 and we have a d-reg, then invert
8583 the bit after the insertion by means of SUBI *,0x80. */
8585 if (INTVAL (op
[3]) == 7
8586 && REGNO (op
[0]) == REGNO (op
[2]))
8588 avr_asm_len ("subi %0,0x80", op
, plen
, -1);
8592 avr_asm_len ("bst %2,%3" CR_TAB
8594 "subi %0,0x80", op
, plen
, -3);
8597 else if (test_hard_reg_class (LD_REGS
, op
[0])
8598 && (INTVAL (op
[1]) != INTVAL (op
[3])
8599 || !reg_overlap_mentioned_p (op
[0], op
[2])))
8601 /* If the destination bit is in a d-reg we can jump depending
8602 on the source bit and use ANDI / ORI. This just applies if we
8603 have not an early-clobber situation with the bit. */
8605 avr_asm_len ("andi %0,~(1<<%1)" CR_TAB
8607 "ori %0,1<<%1", op
, plen
, -3);
8611 /* Otherwise, invert the bit by means of COM before we store it with
8612 BST and then undo the COM if needed. */
8614 avr_asm_len ("com %2" CR_TAB
8615 "bst %2,%3", op
, plen
, -2);
8617 if (!reg_unused_after (insn
, op
[2])
8618 // A simple 'reg_unused_after' is not enough because that function
8619 // assumes that the destination register is overwritten completely
8620 // and hence is in order for our purpose. This is not the case
8621 // with BLD which just changes one bit of the destination.
8622 || reg_overlap_mentioned_p (op
[0], op
[2]))
8624 /* Undo the COM from above. */
8625 avr_asm_len ("com %2", op
, plen
, 1);
8628 avr_asm_len ("bld %0,%1", op
, plen
, 1);
8635 /* Outputs instructions needed for fixed point type conversion.
8636 This includes converting between any fixed point type, as well
8637 as converting to any integer type. Conversion between integer
8638 types is not supported.
8640 Converting signed fractional types requires a bit shift if converting
8641 to or from any unsigned fractional type because the decimal place is
8642 shifted by 1 bit. When the destination is a signed fractional, the sign
8643 is stored in either the carry or T bit. */
8646 avr_out_fract (rtx_insn
*insn
, rtx operands
[], bool intsigned
, int *plen
)
8649 RTX_CODE shift
= UNKNOWN
;
8650 bool sign_in_carry
= false;
8651 bool msb_in_carry
= false;
8652 bool lsb_in_tmp_reg
= false;
8653 bool lsb_in_carry
= false;
8654 bool frac_rounded
= false;
8655 const char *code_ashift
= "lsl %0";
8658 #define MAY_CLOBBER(RR) \
8659 /* Shorthand used below. */ \
8661 && IN_RANGE (RR, dest.regno_msb - sign_bytes + 1, dest.regno_msb)) \
8662 || (offset && IN_RANGE (RR, dest.regno, dest.regno_msb)) \
8663 || (reg_unused_after (insn, all_regs_rtx[RR]) \
8664 && !IN_RANGE (RR, dest.regno, dest.regno_msb)))
8668 /* bytes : Length of operand in bytes.
8669 ibyte : Length of integral part in bytes.
8670 fbyte, fbit : Length of fractional part in bytes, bits. */
8673 unsigned fbit
, bytes
, ibyte
, fbyte
;
8674 unsigned regno
, regno_msb
;
8675 } dest
, src
, *val
[2] = { &dest
, &src
};
8680 /* Step 0: Determine information on source and destination operand we
8681 ====== will need in the remainder. */
8683 for (size_t i
= 0; i
< ARRAY_SIZE (val
); i
++)
8687 xop
[i
] = operands
[i
];
8689 mode
= GET_MODE (xop
[i
]);
8691 val
[i
]->bytes
= GET_MODE_SIZE (mode
);
8692 val
[i
]->regno
= REGNO (xop
[i
]);
8693 val
[i
]->regno_msb
= REGNO (xop
[i
]) + val
[i
]->bytes
- 1;
8695 if (SCALAR_INT_MODE_P (mode
))
8697 val
[i
]->sbit
= intsigned
;
8700 else if (ALL_SCALAR_FIXED_POINT_MODE_P (mode
))
8702 val
[i
]->sbit
= SIGNED_SCALAR_FIXED_POINT_MODE_P (mode
);
8703 val
[i
]->fbit
= GET_MODE_FBIT (mode
);
8706 fatal_insn ("unsupported fixed-point conversion", insn
);
8708 val
[i
]->fbyte
= (1 + val
[i
]->fbit
) / BITS_PER_UNIT
;
8709 val
[i
]->ibyte
= val
[i
]->bytes
- val
[i
]->fbyte
;
8712 // Byte offset of the decimal point taking into account different place
8713 // of the decimal point in input and output and different register numbers
8714 // of input and output.
8715 int offset
= dest
.regno
- src
.regno
+ dest
.fbyte
- src
.fbyte
;
8717 // Number of destination bytes that will come from sign / zero extension.
8718 int sign_bytes
= (dest
.ibyte
- src
.ibyte
) * (dest
.ibyte
> src
.ibyte
);
8720 // Number of bytes at the low end to be filled with zeros.
8721 int zero_bytes
= (dest
.fbyte
- src
.fbyte
) * (dest
.fbyte
> src
.fbyte
);
8723 // Do we have a 16-Bit register that is cleared?
8724 rtx clrw
= NULL_RTX
;
8726 bool sign_extend
= src
.sbit
&& sign_bytes
;
8728 if (0 == dest
.fbit
% 8 && 7 == src
.fbit
% 8)
8730 else if (7 == dest
.fbit
% 8 && 0 == src
.fbit
% 8)
8732 else if (dest
.fbit
% 8 == src
.fbit
% 8)
8737 /* If we need to round the fraction part, we might need to save/round it
8738 before clobbering any of it in Step 1. Also, we might want to do
8739 the rounding now to make use of LD_REGS. */
8740 if (SCALAR_INT_MODE_P (GET_MODE (xop
[0]))
8741 && SCALAR_ACCUM_MODE_P (GET_MODE (xop
[1]))
8742 && !TARGET_FRACT_CONV_TRUNC
)
8746 (offset
? dest
.regno_msb
- sign_bytes
: dest
.regno
+ zero_bytes
- 1)
8747 && dest
.regno
- offset
-1 >= dest
.regno
);
8748 unsigned s0
= dest
.regno
- offset
-1;
8749 bool use_src
= true;
8751 unsigned copied_msb
= src
.regno_msb
;
8752 bool have_carry
= false;
8754 if (src
.ibyte
> dest
.ibyte
)
8755 copied_msb
-= src
.ibyte
- dest
.ibyte
;
8757 for (sn
= s0
; sn
<= copied_msb
; sn
++)
8758 if (!IN_RANGE (sn
, dest
.regno
, dest
.regno_msb
)
8759 && !reg_unused_after (insn
, all_regs_rtx
[sn
]))
8761 if (use_src
&& TEST_HARD_REG_BIT (reg_class_contents
[LD_REGS
], s0
))
8763 avr_asm_len ("tst %0" CR_TAB
"brpl 0f",
8764 &all_regs_rtx
[src
.regno_msb
], plen
, 2);
8768 if (TEST_HARD_REG_BIT (reg_class_contents
[LD_REGS
], sn
))
8769 avr_asm_len ("cpi %0,1", &all_regs_rtx
[sn
], plen
, 1);
8771 avr_asm_len ("sec" CR_TAB
8772 "cpc %0,__zero_reg__",
8773 &all_regs_rtx
[sn
], plen
, 2);
8777 avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx
[sn
], plen
, 1);
8779 avr_asm_len (have_carry
? "sbci %0,128" : "subi %0,129",
8780 &all_regs_rtx
[s0
], plen
, 1);
8781 for (sn
= src
.regno
+ src
.fbyte
; sn
<= copied_msb
; sn
++)
8782 avr_asm_len ("sbci %0,255", &all_regs_rtx
[sn
], plen
, 1);
8783 avr_asm_len ("\n0:", NULL
, plen
, 0);
8784 frac_rounded
= true;
8786 else if (use_src
&& overlap
)
8788 avr_asm_len ("clr __tmp_reg__" CR_TAB
8790 "dec __tmp_reg__", xop
, plen
, 1);
8794 avr_asm_len ("add %0,__tmp_reg__", &all_regs_rtx
[sn
], plen
, 1);
8799 avr_asm_len ("adc %0,__tmp_reg__", &all_regs_rtx
[sn
], plen
, 1);
8802 avr_asm_len ("clt" CR_TAB
8803 "bld __tmp_reg__,7" CR_TAB
8804 "adc %0,__tmp_reg__",
8805 &all_regs_rtx
[s0
], plen
, 1);
8807 avr_asm_len ("lsr __tmp_reg" CR_TAB
8808 "add %0,__tmp_reg__",
8809 &all_regs_rtx
[s0
], plen
, 2);
8810 for (sn
= src
.regno
+ src
.fbyte
; sn
<= copied_msb
; sn
++)
8811 avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx
[sn
], plen
, 1);
8812 frac_rounded
= true;
8817 = (TEST_HARD_REG_BIT (reg_class_contents
[LD_REGS
], s0
)
8818 && (IN_RANGE (s0
, dest
.regno
, dest
.regno_msb
)
8819 || reg_unused_after (insn
, all_regs_rtx
[s0
])));
8820 xop
[2] = all_regs_rtx
[s0
];
8821 unsigned sn
= src
.regno
;
8822 if (!use_src
|| sn
== s0
)
8823 avr_asm_len ("mov __tmp_reg__,%2", xop
, plen
, 1);
8824 /* We need to consider to-be-discarded bits
8825 if the value is negative. */
8828 avr_asm_len ("tst %0" CR_TAB
8830 &all_regs_rtx
[src
.regno_msb
], plen
, 2);
8831 /* Test to-be-discarded bytes for any nozero bits.
8832 ??? Could use OR or SBIW to test two registers at once. */
8834 avr_asm_len ("cp %0,__zero_reg__", &all_regs_rtx
[sn
], plen
, 1);
8837 avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx
[sn
], plen
, 1);
8838 /* Set bit 0 in __tmp_reg__ if any of the lower bits was set. */
8840 avr_asm_len ("breq 0f" CR_TAB
8842 "\n0:\t" "mov __tmp_reg__,%2",
8845 avr_asm_len ("breq 0f" CR_TAB
8847 "bld __tmp_reg__,0\n0:",
8850 lsb_in_tmp_reg
= true;
8854 /* Step 1: Clear bytes at the low end and copy payload bits from source
8855 ====== to destination. */
8857 int step
= offset
< 0 ? 1 : -1;
8858 unsigned d0
= offset
< 0 ? dest
.regno
: dest
.regno_msb
;
8860 // We cleared at least that number of registers.
8863 for (; d0
>= dest
.regno
&& d0
<= dest
.regno_msb
; d0
+= step
)
8865 // Next regno of destination is needed for MOVW
8866 unsigned d1
= d0
+ step
;
8868 // Current and next regno of source
8869 signed s0
= d0
- offset
;
8870 signed s1
= s0
+ step
;
8872 // Must current resp. next regno be CLRed? This applies to the low
8873 // bytes of the destination that have no associated source bytes.
8874 bool clr0
= s0
< (signed) src
.regno
;
8875 bool clr1
= s1
< (signed) src
.regno
&& d1
>= dest
.regno
;
8877 // First gather what code to emit (if any) and additional step to
8878 // apply if a MOVW is in use. xop[2] is destination rtx and xop[3]
8879 // is the source rtx for the current loop iteration.
8880 const char *code
= NULL
;
8885 if (AVR_HAVE_MOVW
&& clr1
&& clrw
)
8887 xop
[2] = all_regs_rtx
[d0
& ~1];
8889 code
= "movw %2,%3";
8894 xop
[2] = all_regs_rtx
[d0
];
8899 && d0
% 2 == (step
> 0))
8901 clrw
= all_regs_rtx
[d0
& ~1];
8905 else if (offset
&& s0
<= (signed) src
.regno_msb
)
8907 int movw
= AVR_HAVE_MOVW
&& offset
% 2 == 0
8908 && d0
% 2 == (offset
> 0)
8909 && d1
<= dest
.regno_msb
&& d1
>= dest
.regno
8910 && s1
<= (signed) src
.regno_msb
&& s1
>= (signed) src
.regno
;
8912 xop
[2] = all_regs_rtx
[d0
& ~movw
];
8913 xop
[3] = all_regs_rtx
[s0
& ~movw
];
8914 code
= movw
? "movw %2,%3" : "mov %2,%3";
8915 stepw
= step
* movw
;
8920 if (sign_extend
&& shift
!= ASHIFT
&& !sign_in_carry
8921 && (d0
== src
.regno_msb
|| d0
+ stepw
== src
.regno_msb
))
8923 /* We are going to override the sign bit. If we sign-extend,
8924 store the sign in the Carry flag. This is not needed if
8925 the destination will be ASHIFT in the remainder because
8926 the ASHIFT will set Carry without extra instruction. */
8928 avr_asm_len ("lsl %0", &all_regs_rtx
[src
.regno_msb
], plen
, 1);
8929 sign_in_carry
= true;
8932 unsigned src_msb
= dest
.regno_msb
- sign_bytes
- offset
+ 1;
8934 if (!sign_extend
&& shift
== ASHIFTRT
&& !msb_in_carry
8935 && src
.ibyte
> dest
.ibyte
8936 && (d0
== src_msb
|| d0
+ stepw
== src_msb
))
8938 /* We are going to override the MSB. If we shift right,
8939 store the MSB in the Carry flag. This is only needed if
8940 we don't sign-extend becaue with sign-extension the MSB
8941 (the sign) will be produced by the sign extension. */
8943 avr_asm_len ("lsr %0", &all_regs_rtx
[src_msb
], plen
, 1);
8944 msb_in_carry
= true;
8947 unsigned src_lsb
= dest
.regno
- offset
-1;
8949 if (shift
== ASHIFT
&& src
.fbyte
> dest
.fbyte
&& !lsb_in_carry
8951 && (d0
== src_lsb
|| d0
+ stepw
== src_lsb
))
8953 /* We are going to override the new LSB; store it into carry. */
8955 avr_asm_len ("lsl %0", &all_regs_rtx
[src_lsb
], plen
, 1);
8956 code_ashift
= "rol %0";
8957 lsb_in_carry
= true;
8960 avr_asm_len (code
, xop
, plen
, 1);
8965 /* Step 2: Shift destination left by 1 bit position. This might be needed
8966 ====== for signed input and unsigned output. */
8968 if (shift
== ASHIFT
&& src
.fbyte
> dest
.fbyte
&& !lsb_in_carry
)
8970 unsigned s0
= dest
.regno
- offset
-1;
8972 /* n1169 4.1.4 says:
8973 "Conversions from a fixed-point to an integer type round toward zero."
8974 Hence, converting a fract type to integer only gives a non-zero result
8976 if (SCALAR_INT_MODE_P (GET_MODE (xop
[0]))
8977 && SCALAR_FRACT_MODE_P (GET_MODE (xop
[1]))
8978 && !TARGET_FRACT_CONV_TRUNC
)
8980 gcc_assert (s0
== src
.regno_msb
);
8981 /* Check if the input is -1. We do that by checking if negating
8982 the input causes an integer overflow. */
8983 unsigned sn
= src
.regno
;
8984 avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx
[sn
++], plen
, 1);
8986 avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx
[sn
++], plen
, 1);
8988 /* Overflow goes with set carry. Clear carry otherwise. */
8989 avr_asm_len ("brvs 0f" CR_TAB
8990 "clc\n0:", NULL
, plen
, 2);
8992 /* Likewise, when converting from accumulator types to integer, we
8993 need to round up negative values. */
8994 else if (SCALAR_INT_MODE_P (GET_MODE (xop
[0]))
8995 && SCALAR_ACCUM_MODE_P (GET_MODE (xop
[1]))
8996 && !TARGET_FRACT_CONV_TRUNC
8999 bool have_carry
= false;
9001 xop
[2] = all_regs_rtx
[s0
];
9002 if (!lsb_in_tmp_reg
&& !MAY_CLOBBER (s0
))
9003 avr_asm_len ("mov __tmp_reg__,%2", xop
, plen
, 1);
9004 avr_asm_len ("tst %0" CR_TAB
"brpl 0f",
9005 &all_regs_rtx
[src
.regno_msb
], plen
, 2);
9006 if (!lsb_in_tmp_reg
)
9008 unsigned sn
= src
.regno
;
9011 avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx
[sn
],
9016 avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx
[sn
], plen
, 1);
9017 lsb_in_tmp_reg
= !MAY_CLOBBER (s0
);
9019 /* Add in C and the rounding value 127. */
9020 /* If the destination msb is a sign byte, and in LD_REGS,
9021 grab it as a temporary. */
9023 && TEST_HARD_REG_BIT (reg_class_contents
[LD_REGS
],
9026 xop
[3] = all_regs_rtx
[dest
.regno_msb
];
9027 avr_asm_len ("ldi %3,127", xop
, plen
, 1);
9028 avr_asm_len ((have_carry
&& lsb_in_tmp_reg
? "adc __tmp_reg__,%3"
9029 : have_carry
? "adc %2,%3"
9030 : lsb_in_tmp_reg
? "add __tmp_reg__,%3"
9036 /* Fall back to use __zero_reg__ as a temporary. */
9037 avr_asm_len ("dec __zero_reg__", NULL
, plen
, 1);
9039 avr_asm_len ("clt" CR_TAB
9040 "bld __zero_reg__,7", NULL
, plen
, 2);
9042 avr_asm_len ("lsr __zero_reg__", NULL
, plen
, 1);
9043 avr_asm_len (have_carry
&& lsb_in_tmp_reg
9044 ? "adc __tmp_reg__,__zero_reg__"
9045 : have_carry
? "adc %2,__zero_reg__"
9046 : lsb_in_tmp_reg
? "add __tmp_reg__,__zero_reg__"
9047 : "add %2,__zero_reg__",
9049 avr_asm_len ("eor __zero_reg__,__zero_reg__", NULL
, plen
, 1);
9052 for (d0
= dest
.regno
+ zero_bytes
;
9053 d0
<= dest
.regno_msb
- sign_bytes
; d0
++)
9054 avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx
[d0
], plen
, 1);
9056 avr_asm_len (lsb_in_tmp_reg
9057 ? "\n0:\t" "lsl __tmp_reg__"
9058 : "\n0:\t" "lsl %2",
9061 else if (MAY_CLOBBER (s0
))
9062 avr_asm_len ("lsl %0", &all_regs_rtx
[s0
], plen
, 1);
9064 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
9065 "lsl __tmp_reg__", &all_regs_rtx
[s0
], plen
, 2);
9067 code_ashift
= "rol %0";
9068 lsb_in_carry
= true;
9071 if (shift
== ASHIFT
)
9073 for (d0
= dest
.regno
+ zero_bytes
;
9074 d0
<= dest
.regno_msb
- sign_bytes
; d0
++)
9076 avr_asm_len (code_ashift
, &all_regs_rtx
[d0
], plen
, 1);
9077 code_ashift
= "rol %0";
9080 lsb_in_carry
= false;
9081 sign_in_carry
= true;
9084 /* Step 4a: Store MSB in carry if we don't already have it or will produce
9085 ======= it in sign-extension below. */
9087 if (!sign_extend
&& shift
== ASHIFTRT
&& !msb_in_carry
9088 && src
.ibyte
> dest
.ibyte
)
9090 unsigned s0
= dest
.regno_msb
- sign_bytes
- offset
+ 1;
9092 if (MAY_CLOBBER (s0
))
9093 avr_asm_len ("lsr %0", &all_regs_rtx
[s0
], plen
, 1);
9095 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
9096 "lsr __tmp_reg__", &all_regs_rtx
[s0
], plen
, 2);
9098 msb_in_carry
= true;
9101 /* Step 3: Sign-extend or zero-extend the destination as needed.
9104 if (sign_extend
&& !sign_in_carry
)
9106 unsigned s0
= src
.regno_msb
;
9108 if (MAY_CLOBBER (s0
))
9109 avr_asm_len ("lsl %0", &all_regs_rtx
[s0
], plen
, 1);
9111 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
9112 "lsl __tmp_reg__", &all_regs_rtx
[s0
], plen
, 2);
9114 sign_in_carry
= true;
9117 gcc_assert (sign_in_carry
+ msb_in_carry
+ lsb_in_carry
<= 1);
9119 unsigned copies
= 0;
9120 rtx movw
= sign_extend
? NULL_RTX
: clrw
;
9122 for (d0
= dest
.regno_msb
- sign_bytes
+ 1; d0
<= dest
.regno_msb
; d0
++)
9124 if (AVR_HAVE_MOVW
&& movw
9125 && d0
% 2 == 0 && d0
+ 1 <= dest
.regno_msb
)
9127 xop
[2] = all_regs_rtx
[d0
];
9129 avr_asm_len ("movw %2,%3", xop
, plen
, 1);
9134 avr_asm_len (sign_extend
? "sbc %0,%0" : "clr %0",
9135 &all_regs_rtx
[d0
], plen
, 1);
9137 if (++copies
>= 2 && !movw
&& d0
% 2 == 1)
9138 movw
= all_regs_rtx
[d0
-1];
9143 /* Step 4: Right shift the destination. This might be needed for
9144 ====== conversions from unsigned to signed. */
9146 if (shift
== ASHIFTRT
)
9148 const char *code_ashiftrt
= "lsr %0";
9150 if (sign_extend
|| msb_in_carry
)
9151 code_ashiftrt
= "ror %0";
9153 if (src
.sbit
&& src
.ibyte
== dest
.ibyte
)
9154 code_ashiftrt
= "asr %0";
9156 for (d0
= dest
.regno_msb
- sign_bytes
;
9157 d0
>= dest
.regno
+ zero_bytes
- 1 && d0
>= dest
.regno
; d0
--)
9159 avr_asm_len (code_ashiftrt
, &all_regs_rtx
[d0
], plen
, 1);
9160 code_ashiftrt
= "ror %0";
9170 /* Output fixed-point rounding. XOP[0] = XOP[1] is the operand to round.
9171 XOP[2] is the rounding point, a CONST_INT. The function prints the
9172 instruction sequence if PLEN = NULL and computes the length in words
9173 of the sequence if PLEN != NULL. Most of this function deals with
9174 preparing operands for calls to `avr_out_plus' and `avr_out_bitop'. */
9177 avr_out_round (rtx_insn
*insn ATTRIBUTE_UNUSED
, rtx
*xop
, int *plen
)
9179 scalar_mode mode
= as_a
<scalar_mode
> (GET_MODE (xop
[0]));
9180 scalar_int_mode imode
= int_mode_for_mode (mode
).require ();
9181 // The smallest fractional bit not cleared by the rounding is 2^(-RP).
9182 int fbit
= (int) GET_MODE_FBIT (mode
);
9183 double_int i_add
= double_int_zero
.set_bit (fbit
-1 - INTVAL (xop
[2]));
9184 wide_int wi_add
= wi::set_bit_in_zero (fbit
-1 - INTVAL (xop
[2]),
9185 GET_MODE_PRECISION (imode
));
9186 // Lengths of PLUS and AND parts.
9187 int len_add
= 0, *plen_add
= plen
? &len_add
: NULL
;
9188 int len_and
= 0, *plen_and
= plen
? &len_and
: NULL
;
9190 // Add-Saturate 1/2 * 2^(-RP). Don't print the label "0:" when printing
9191 // the saturated addition so that we can emit the "rjmp 1f" before the
9194 rtx xadd
= const_fixed_from_double_int (i_add
, mode
);
9195 rtx xpattern
, xsrc
, op
[4];
9197 xsrc
= SIGNED_FIXED_POINT_MODE_P (mode
)
9198 ? gen_rtx_SS_PLUS (mode
, xop
[1], xadd
)
9199 : gen_rtx_US_PLUS (mode
, xop
[1], xadd
);
9200 xpattern
= gen_rtx_SET (xop
[0], xsrc
);
9205 avr_out_plus (xpattern
, op
, plen_add
, NULL
, false /* Don't print "0:" */);
9207 avr_asm_len ("rjmp 1f" CR_TAB
9208 "0:", NULL
, plen_add
, 1);
9210 // Keep all bits from RP and higher: ... 2^(-RP)
9211 // Clear all bits from RP+1 and lower: 2^(-RP-1) ...
9212 // Rounding point ^^^^^^^
9213 // Added above ^^^^^^^^^
9214 rtx xreg
= simplify_gen_subreg (imode
, xop
[0], mode
, 0);
9215 rtx xmask
= immed_wide_int_const (-wi_add
- wi_add
, imode
);
9217 xpattern
= gen_rtx_SET (xreg
, gen_rtx_AND (imode
, xreg
, xmask
));
9222 op
[3] = gen_rtx_SCRATCH (QImode
);
9223 avr_out_bitop (xpattern
, op
, plen_and
);
9224 avr_asm_len ("1:", NULL
, plen
, 0);
9227 *plen
= len_add
+ len_and
;
9233 /* Create RTL split patterns for byte sized rotate expressions. This
9234 produces a series of move instructions and considers overlap situations.
9235 Overlapping non-HImode operands need a scratch register. */
9238 avr_rotate_bytes (rtx operands
[])
9240 machine_mode mode
= GET_MODE (operands
[0]);
9241 bool overlapped
= reg_overlap_mentioned_p (operands
[0], operands
[1]);
9242 bool same_reg
= rtx_equal_p (operands
[0], operands
[1]);
9243 int num
= INTVAL (operands
[2]);
9244 rtx scratch
= operands
[3];
9245 /* Work out if byte or word move is needed. Odd byte rotates need QImode.
9246 Word move if no scratch is needed, otherwise use size of scratch. */
9247 machine_mode move_mode
= QImode
;
9248 int move_size
, offset
, size
;
9252 else if ((mode
== SImode
&& !same_reg
) || !overlapped
)
9255 move_mode
= GET_MODE (scratch
);
9257 /* Force DI rotate to use QI moves since other DI moves are currently split
9258 into QI moves so forward propagation works better. */
9261 /* Make scratch smaller if needed. */
9262 if (SCRATCH
!= GET_CODE (scratch
)
9263 && HImode
== GET_MODE (scratch
)
9264 && QImode
== move_mode
)
9265 scratch
= simplify_gen_subreg (move_mode
, scratch
, HImode
, 0);
9267 move_size
= GET_MODE_SIZE (move_mode
);
9268 /* Number of bytes/words to rotate. */
9269 offset
= (num
>> 3) / move_size
;
9270 /* Number of moves needed. */
9271 size
= GET_MODE_SIZE (mode
) / move_size
;
9272 /* Himode byte swap is special case to avoid a scratch register. */
9273 if (mode
== HImode
&& same_reg
)
9275 /* HImode byte swap, using xor. This is as quick as using scratch. */
9277 src
= simplify_gen_subreg (move_mode
, operands
[1], mode
, 0);
9278 dst
= simplify_gen_subreg (move_mode
, operands
[0], mode
, 1);
9279 if (!rtx_equal_p (dst
, src
))
9281 emit_move_insn (dst
, gen_rtx_XOR (QImode
, dst
, src
));
9282 emit_move_insn (src
, gen_rtx_XOR (QImode
, src
, dst
));
9283 emit_move_insn (dst
, gen_rtx_XOR (QImode
, dst
, src
));
9288 #define MAX_SIZE 8 /* GET_MODE_SIZE (DImode) / GET_MODE_SIZE (QImode) */
9289 /* Create linked list of moves to determine move order. */
9293 } move
[MAX_SIZE
+ 8];
9296 gcc_assert (size
<= MAX_SIZE
);
9297 /* Generate list of subreg moves. */
9298 for (int i
= 0; i
< size
; i
++)
9301 int to
= (from
+ offset
) % size
;
9302 move
[i
].src
= simplify_gen_subreg (move_mode
, operands
[1],
9303 mode
, from
* move_size
);
9304 move
[i
].dst
= simplify_gen_subreg (move_mode
, operands
[0],
9305 mode
, to
* move_size
);
9308 /* Mark dependence where a dst of one move is the src of another move.
9309 The first move is a conflict as it must wait until second is
9310 performed. We ignore moves to self - we catch this later. */
9312 for (int i
= 0; i
< size
; i
++)
9313 if (reg_overlap_mentioned_p (move
[i
].dst
, operands
[1]))
9314 for (int j
= 0; j
< size
; j
++)
9315 if (j
!= i
&& rtx_equal_p (move
[j
].src
, move
[i
].dst
))
9317 /* The dst of move i is the src of move j. */
9324 /* Go through move list and perform non-conflicting moves. As each
9325 non-overlapping move is made, it may remove other conflicts
9326 so the process is repeated until no conflicts remain. */
9331 /* Emit move where dst is not also a src or we have used that
9333 for (int i
= 0; i
< size
; i
++)
9334 if (move
[i
].src
!= NULL_RTX
)
9336 if (move
[i
].links
== -1
9337 || move
[move
[i
].links
].src
== NULL_RTX
)
9340 /* Ignore NOP moves to self. */
9341 if (!rtx_equal_p (move
[i
].dst
, move
[i
].src
))
9342 emit_move_insn (move
[i
].dst
, move
[i
].src
);
9344 /* Remove conflict from list. */
9345 move
[i
].src
= NULL_RTX
;
9351 /* Check for deadlock. This is when no moves occurred and we have
9352 at least one blocked move. */
9353 if (moves
== 0 && blocked
!= -1)
9355 /* Need to use scratch register to break deadlock.
9356 Add move to put dst of blocked move into scratch.
9357 When this move occurs, it will break chain deadlock.
9358 The scratch register is substituted for real move. */
9360 gcc_assert (SCRATCH
!= GET_CODE (scratch
));
9362 move
[size
].src
= move
[blocked
].dst
;
9363 move
[size
].dst
= scratch
;
9364 /* Scratch move is never blocked. */
9365 move
[size
].links
= -1;
9366 /* Make sure we have valid link. */
9367 gcc_assert (move
[blocked
].links
!= -1);
9368 /* Replace src of blocking move with scratch reg. */
9369 move
[move
[blocked
].links
].src
= scratch
;
9370 /* Make dependent on scratch move occurring. */
9371 move
[blocked
].links
= size
;
9375 while (blocked
!= -1);
9381 /* Worker function for `ADJUST_INSN_LENGTH'. */
9382 /* Modifies the length assigned to instruction INSN
9383 LEN is the initially computed length of the insn. */
9386 avr_adjust_insn_length (rtx_insn
*insn
, int len
)
9388 rtx
*op
= recog_data
.operand
;
9389 enum attr_adjust_len adjust_len
;
9391 /* As we pretend jump tables in .text, fix branch offsets crossing jump
9394 if (JUMP_TABLE_DATA_P (insn
))
9397 /* Some complex insns don't need length adjustment and therefore
9398 the length need not/must not be adjusted for these insns.
9399 It is easier to state this in an insn attribute "adjust_len" than
9400 to clutter up code here... */
9402 if (!NONDEBUG_INSN_P (insn
)
9403 || -1 == recog_memoized (insn
))
9408 /* Read from insn attribute "adjust_len" if/how length is to be adjusted. */
9410 adjust_len
= get_attr_adjust_len (insn
);
9412 if (adjust_len
== ADJUST_LEN_NO
)
9414 /* Nothing to adjust: The length from attribute "length" is fine.
9415 This is the default. */
9420 /* Extract insn's operands. */
9422 extract_constrain_insn_cached (insn
);
9424 /* Dispatch to right function. */
9428 case ADJUST_LEN_RELOAD_IN16
: output_reload_inhi (op
, op
[2], &len
); break;
9429 case ADJUST_LEN_RELOAD_IN24
: avr_out_reload_inpsi (op
, op
[2], &len
); break;
9430 case ADJUST_LEN_RELOAD_IN32
: output_reload_insisf (op
, op
[2], &len
); break;
9432 case ADJUST_LEN_OUT_BITOP
: avr_out_bitop (insn
, op
, &len
); break;
9434 case ADJUST_LEN_PLUS
: avr_out_plus (insn
, op
, &len
); break;
9435 case ADJUST_LEN_ADDTO_SP
: avr_out_addto_sp (op
, &len
); break;
9437 case ADJUST_LEN_MOV8
: output_movqi (insn
, op
, &len
); break;
9438 case ADJUST_LEN_MOV16
: output_movhi (insn
, op
, &len
); break;
9439 case ADJUST_LEN_MOV24
: avr_out_movpsi (insn
, op
, &len
); break;
9440 case ADJUST_LEN_MOV32
: output_movsisf (insn
, op
, &len
); break;
9441 case ADJUST_LEN_MOVMEM
: avr_out_movmem (insn
, op
, &len
); break;
9442 case ADJUST_LEN_XLOAD
: avr_out_xload (insn
, op
, &len
); break;
9443 case ADJUST_LEN_SEXT
: avr_out_sign_extend (insn
, op
, &len
); break;
9445 case ADJUST_LEN_SFRACT
: avr_out_fract (insn
, op
, true, &len
); break;
9446 case ADJUST_LEN_UFRACT
: avr_out_fract (insn
, op
, false, &len
); break;
9447 case ADJUST_LEN_ROUND
: avr_out_round (insn
, op
, &len
); break;
9449 case ADJUST_LEN_TSTHI
: avr_out_tsthi (insn
, op
, &len
); break;
9450 case ADJUST_LEN_TSTPSI
: avr_out_tstpsi (insn
, op
, &len
); break;
9451 case ADJUST_LEN_TSTSI
: avr_out_tstsi (insn
, op
, &len
); break;
9452 case ADJUST_LEN_COMPARE
: avr_out_compare (insn
, op
, &len
); break;
9453 case ADJUST_LEN_COMPARE64
: avr_out_compare64 (insn
, op
, &len
); break;
9455 case ADJUST_LEN_LSHRQI
: lshrqi3_out (insn
, op
, &len
); break;
9456 case ADJUST_LEN_LSHRHI
: lshrhi3_out (insn
, op
, &len
); break;
9457 case ADJUST_LEN_LSHRSI
: lshrsi3_out (insn
, op
, &len
); break;
9459 case ADJUST_LEN_ASHRQI
: ashrqi3_out (insn
, op
, &len
); break;
9460 case ADJUST_LEN_ASHRHI
: ashrhi3_out (insn
, op
, &len
); break;
9461 case ADJUST_LEN_ASHRSI
: ashrsi3_out (insn
, op
, &len
); break;
9463 case ADJUST_LEN_ASHLQI
: ashlqi3_out (insn
, op
, &len
); break;
9464 case ADJUST_LEN_ASHLHI
: ashlhi3_out (insn
, op
, &len
); break;
9465 case ADJUST_LEN_ASHLSI
: ashlsi3_out (insn
, op
, &len
); break;
9467 case ADJUST_LEN_ASHLPSI
: avr_out_ashlpsi3 (insn
, op
, &len
); break;
9468 case ADJUST_LEN_ASHRPSI
: avr_out_ashrpsi3 (insn
, op
, &len
); break;
9469 case ADJUST_LEN_LSHRPSI
: avr_out_lshrpsi3 (insn
, op
, &len
); break;
9471 case ADJUST_LEN_CALL
: len
= AVR_HAVE_JMP_CALL
? 2 : 1; break;
9473 case ADJUST_LEN_INSERT_BITS
: avr_out_insert_bits (op
, &len
); break;
9475 case ADJUST_LEN_INSV_NOTBIT
:
9476 avr_out_insert_notbit (insn
, op
, NULL_RTX
, &len
);
9478 case ADJUST_LEN_INSV_NOTBIT_0
:
9479 avr_out_insert_notbit (insn
, op
, const0_rtx
, &len
);
9481 case ADJUST_LEN_INSV_NOTBIT_7
:
9482 avr_out_insert_notbit (insn
, op
, GEN_INT (7), &len
);
9492 /* Return nonzero if register REG dead after INSN. */
9495 reg_unused_after (rtx_insn
*insn
, rtx reg
)
9497 return (dead_or_set_p (insn
, reg
)
9498 || (REG_P (reg
) && _reg_unused_after (insn
, reg
)));
9501 /* Return nonzero if REG is not used after INSN.
9502 We assume REG is a reload reg, and therefore does
9503 not live past labels. It may live past calls or jumps though. */
9506 _reg_unused_after (rtx_insn
*insn
, rtx reg
)
9511 /* If the reg is set by this instruction, then it is safe for our
9512 case. Disregard the case where this is a store to memory, since
9513 we are checking a register used in the store address. */
9514 set
= single_set (insn
);
9515 if (set
&& !MEM_P (SET_DEST (set
))
9516 && reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
9519 while ((insn
= NEXT_INSN (insn
)))
9522 code
= GET_CODE (insn
);
9525 /* If this is a label that existed before reload, then the register
9526 if dead here. However, if this is a label added by reorg, then
9527 the register may still be live here. We can't tell the difference,
9528 so we just ignore labels completely. */
9529 if (code
== CODE_LABEL
)
9537 if (code
== JUMP_INSN
)
9540 /* If this is a sequence, we must handle them all at once.
9541 We could have for instance a call that sets the target register,
9542 and an insn in a delay slot that uses the register. In this case,
9543 we must return 0. */
9544 else if (code
== INSN
&& GET_CODE (PATTERN (insn
)) == SEQUENCE
)
9546 rtx_sequence
*seq
= as_a
<rtx_sequence
*> (PATTERN (insn
));
9549 for (int i
= 0; i
< seq
->len (); i
++)
9551 rtx_insn
*this_insn
= seq
->insn (i
);
9552 rtx set
= single_set (this_insn
);
9554 if (CALL_P (this_insn
))
9556 else if (JUMP_P (this_insn
))
9558 if (INSN_ANNULLED_BRANCH_P (this_insn
))
9563 if (set
&& reg_overlap_mentioned_p (reg
, SET_SRC (set
)))
9565 if (set
&& reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
9567 if (!MEM_P (SET_DEST (set
)))
9573 && reg_overlap_mentioned_p (reg
, PATTERN (this_insn
)))
9578 else if (code
== JUMP_INSN
)
9582 if (code
== CALL_INSN
)
9585 for (tem
= CALL_INSN_FUNCTION_USAGE (insn
); tem
; tem
= XEXP (tem
, 1))
9586 if (GET_CODE (XEXP (tem
, 0)) == USE
9587 && REG_P (XEXP (XEXP (tem
, 0), 0))
9588 && reg_overlap_mentioned_p (reg
, XEXP (XEXP (tem
, 0), 0)))
9590 if (call_used_regs
[REGNO (reg
)])
9594 set
= single_set (insn
);
9596 if (set
&& reg_overlap_mentioned_p (reg
, SET_SRC (set
)))
9598 if (set
&& reg_overlap_mentioned_p (reg
, SET_DEST (set
)))
9599 return !MEM_P (SET_DEST (set
));
9600 if (set
== 0 && reg_overlap_mentioned_p (reg
, PATTERN (insn
)))
9607 /* Implement `TARGET_ASM_INTEGER'. */
9608 /* Target hook for assembling integer objects. The AVR version needs
9609 special handling for references to certain labels. */
9612 avr_assemble_integer (rtx x
, unsigned int size
, int aligned_p
)
9614 if (size
== POINTER_SIZE
/ BITS_PER_UNIT
&& aligned_p
9615 && text_segment_operand (x
, VOIDmode
))
9617 fputs ("\t.word\tgs(", asm_out_file
);
9618 output_addr_const (asm_out_file
, x
);
9619 fputs (")\n", asm_out_file
);
9623 else if (GET_MODE (x
) == PSImode
)
9625 /* This needs binutils 2.23+, see PR binutils/13503 */
9627 fputs ("\t.byte\tlo8(", asm_out_file
);
9628 output_addr_const (asm_out_file
, x
);
9629 fputs (")" ASM_COMMENT_START
"need binutils PR13503\n", asm_out_file
);
9631 fputs ("\t.byte\thi8(", asm_out_file
);
9632 output_addr_const (asm_out_file
, x
);
9633 fputs (")" ASM_COMMENT_START
"need binutils PR13503\n", asm_out_file
);
9635 fputs ("\t.byte\thh8(", asm_out_file
);
9636 output_addr_const (asm_out_file
, x
);
9637 fputs (")" ASM_COMMENT_START
"need binutils PR13503\n", asm_out_file
);
9641 else if (CONST_FIXED_P (x
))
9643 /* varasm fails to handle big fixed modes that don't fit in hwi. */
9645 for (unsigned n
= 0; n
< size
; n
++)
9647 rtx xn
= simplify_gen_subreg (QImode
, x
, GET_MODE (x
), n
);
9648 default_assemble_integer (xn
, 1, aligned_p
);
9655 && avr_address_tiny_pm_p (x
))
9657 x
= plus_constant (Pmode
, x
, avr_arch
->flash_pm_offset
);
9660 return default_assemble_integer (x
, size
, aligned_p
);
9664 /* Implement `TARGET_CLASS_LIKELY_SPILLED_P'. */
9665 /* Return value is nonzero if pseudos that have been
9666 assigned to registers of class CLASS would likely be spilled
9667 because registers of CLASS are needed for spill registers. */
9670 avr_class_likely_spilled_p (reg_class_t c
)
9672 return (c
!= ALL_REGS
&&
9673 (AVR_TINY
? 1 : c
!= ADDW_REGS
));
9677 /* Valid attributes:
9678 progmem - Put data to program memory.
9679 signal - Make a function to be hardware interrupt.
9680 After function prologue interrupts remain disabled.
9681 interrupt - Make a function to be hardware interrupt. Before function
9682 prologue interrupts are enabled by means of SEI.
9683 naked - Don't generate function prologue/epilogue and RET
9686 /* Handle a "progmem" attribute; arguments as in
9687 struct attribute_spec.handler. */
9690 avr_handle_progmem_attribute (tree
*node
, tree name
,
9691 tree args ATTRIBUTE_UNUSED
,
9692 int flags ATTRIBUTE_UNUSED
,
9697 if (TREE_CODE (*node
) == TYPE_DECL
)
9699 /* This is really a decl attribute, not a type attribute,
9700 but try to handle it for GCC 3.0 backwards compatibility. */
9702 tree type
= TREE_TYPE (*node
);
9703 tree attr
= tree_cons (name
, args
, TYPE_ATTRIBUTES (type
));
9704 tree newtype
= build_type_attribute_variant (type
, attr
);
9706 TYPE_MAIN_VARIANT (newtype
) = TYPE_MAIN_VARIANT (type
);
9707 TREE_TYPE (*node
) = newtype
;
9708 *no_add_attrs
= true;
9710 else if (TREE_STATIC (*node
) || DECL_EXTERNAL (*node
))
9712 *no_add_attrs
= false;
9716 warning (OPT_Wattributes
, "%qE attribute ignored",
9718 *no_add_attrs
= true;
9725 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
9726 struct attribute_spec.handler. */
9729 avr_handle_fndecl_attribute (tree
*node
, tree name
,
9730 tree args ATTRIBUTE_UNUSED
,
9731 int flags ATTRIBUTE_UNUSED
,
9734 if (TREE_CODE (*node
) != FUNCTION_DECL
)
9736 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
9738 *no_add_attrs
= true;
9745 avr_handle_fntype_attribute (tree
*node
, tree name
,
9746 tree args ATTRIBUTE_UNUSED
,
9747 int flags ATTRIBUTE_UNUSED
,
9750 if (TREE_CODE (*node
) != FUNCTION_TYPE
)
9752 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
9754 *no_add_attrs
= true;
9761 avr_handle_absdata_attribute (tree
*node
, tree name
, tree
/* args */,
9762 int /* flags */, bool *no_add
)
9764 location_t loc
= DECL_SOURCE_LOCATION (*node
);
9768 if (TREE_CODE (*node
) != VAR_DECL
9769 || (!TREE_STATIC (*node
) && !DECL_EXTERNAL (*node
)))
9771 warning_at (loc
, OPT_Wattributes
, "%qE attribute only applies to"
9772 " variables in static storage", name
);
9778 warning_at (loc
, OPT_Wattributes
, "%qE attribute only supported"
9779 " for reduced Tiny cores", name
);
9787 avr_handle_addr_attribute (tree
*node
, tree name
, tree args
,
9788 int flags ATTRIBUTE_UNUSED
, bool *no_add
)
9790 bool io_p
= (strncmp (IDENTIFIER_POINTER (name
), "io", 2) == 0);
9791 location_t loc
= DECL_SOURCE_LOCATION (*node
);
9795 warning_at (loc
, OPT_Wattributes
, "%qE attribute only applies to "
9801 if (args
!= NULL_TREE
)
9803 if (TREE_CODE (TREE_VALUE (args
)) == NON_LVALUE_EXPR
)
9804 TREE_VALUE (args
) = TREE_OPERAND (TREE_VALUE (args
), 0);
9805 tree arg
= TREE_VALUE (args
);
9806 if (TREE_CODE (arg
) != INTEGER_CST
)
9808 warning_at (loc
, OPT_Wattributes
, "%qE attribute allows only an "
9809 "integer constant argument", name
);
9813 && (!tree_fits_shwi_p (arg
)
9814 || !(strcmp (IDENTIFIER_POINTER (name
), "io_low") == 0
9815 ? low_io_address_operand
: io_address_operand
)
9816 (GEN_INT (TREE_INT_CST_LOW (arg
)), QImode
)))
9818 warning_at (loc
, OPT_Wattributes
, "%qE attribute address "
9819 "out of range", name
);
9824 tree attribs
= DECL_ATTRIBUTES (*node
);
9825 const char *names
[] = { "io", "io_low", "address", NULL
};
9826 for (const char **p
= names
; *p
; p
++)
9828 tree other
= lookup_attribute (*p
, attribs
);
9829 if (other
&& TREE_VALUE (other
))
9831 warning_at (loc
, OPT_Wattributes
,
9832 "both %s and %qE attribute provide address",
9841 if (*no_add
== false && io_p
&& !TREE_THIS_VOLATILE (*node
))
9842 warning_at (loc
, OPT_Wattributes
, "%qE attribute on non-volatile variable",
9849 avr_eval_addr_attrib (rtx x
)
9851 if (SYMBOL_REF_P (x
)
9852 && (SYMBOL_REF_FLAGS (x
) & SYMBOL_FLAG_ADDRESS
))
9854 tree decl
= SYMBOL_REF_DECL (x
);
9855 tree attr
= NULL_TREE
;
9857 if (SYMBOL_REF_FLAGS (x
) & SYMBOL_FLAG_IO
)
9859 attr
= lookup_attribute ("io", DECL_ATTRIBUTES (decl
));
9860 if (!attr
|| !TREE_VALUE (attr
))
9861 attr
= lookup_attribute ("io_low", DECL_ATTRIBUTES (decl
));
9864 if (!attr
|| !TREE_VALUE (attr
))
9865 attr
= lookup_attribute ("address", DECL_ATTRIBUTES (decl
));
9866 gcc_assert (attr
&& TREE_VALUE (attr
) && TREE_VALUE (TREE_VALUE (attr
)));
9867 return GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr
))));
9873 /* AVR attributes. */
9874 static const struct attribute_spec
9875 avr_attribute_table
[] =
9877 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
9878 affects_type_identity } */
9879 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute
,
9881 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute
,
9883 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute
,
9885 { "no_gccisr", 0, 0, true, false, false, avr_handle_fndecl_attribute
,
9887 { "naked", 0, 0, false, true, true, avr_handle_fntype_attribute
,
9889 { "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute
,
9891 { "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute
,
9893 { "io", 0, 1, true, false, false, avr_handle_addr_attribute
,
9895 { "io_low", 0, 1, true, false, false, avr_handle_addr_attribute
,
9897 { "address", 1, 1, true, false, false, avr_handle_addr_attribute
,
9899 { "absdata", 0, 0, true, false, false, avr_handle_absdata_attribute
,
9901 { NULL
, 0, 0, false, false, false, NULL
, false }
9905 /* Return true if we support address space AS for the architecture in effect
9906 and false, otherwise. If LOC is not UNKNOWN_LOCATION then also issue
9907 a respective error. */
9910 avr_addr_space_supported_p (addr_space_t as
, location_t loc
)
9914 if (loc
!= UNKNOWN_LOCATION
)
9915 error_at (loc
, "address spaces are not supported for reduced "
9919 else if (avr_addrspace
[as
].segment
>= avr_n_flash
)
9921 if (loc
!= UNKNOWN_LOCATION
)
9922 error_at (loc
, "address space %qs not supported for devices with "
9923 "flash size up to %d KiB", avr_addrspace
[as
].name
,
9932 /* Implement `TARGET_ADDR_SPACE_DIAGNOSE_USAGE'. */
9935 avr_addr_space_diagnose_usage (addr_space_t as
, location_t loc
)
9937 (void) avr_addr_space_supported_p (as
, loc
);
9941 /* Look if DECL shall be placed in program memory space by
9942 means of attribute `progmem' or some address-space qualifier.
9943 Return non-zero if DECL is data that must end up in Flash and
9944 zero if the data lives in RAM (.bss, .data, .rodata, ...).
9946 Return 2 if DECL is located in 24-bit flash address-space
9947 Return 1 if DECL is located in 16-bit flash address-space
9948 Return -1 if attribute `progmem' occurs in DECL or ATTRIBUTES
9949 Return 0 otherwise */
9952 avr_progmem_p (tree decl
, tree attributes
)
9956 if (TREE_CODE (decl
) != VAR_DECL
)
9959 if (avr_decl_memx_p (decl
))
9962 if (avr_decl_flash_p (decl
))
9966 != lookup_attribute ("progmem", attributes
))
9973 while (TREE_CODE (a
) == ARRAY_TYPE
);
9975 if (a
== error_mark_node
)
9978 if (NULL_TREE
!= lookup_attribute ("progmem", TYPE_ATTRIBUTES (a
)))
9985 /* Return true if DECL has attribute `absdata' set. This function should
9986 only be used for AVR_TINY. */
9989 avr_decl_absdata_p (tree decl
, tree attributes
)
9991 return (TREE_CODE (decl
) == VAR_DECL
9992 && NULL_TREE
!= lookup_attribute ("absdata", attributes
));
9996 /* Scan type TYP for pointer references to address space ASn.
9997 Return ADDR_SPACE_GENERIC (i.e. 0) if all pointers targeting
9998 the AS are also declared to be CONST.
9999 Otherwise, return the respective address space, i.e. a value != 0. */
10001 static addr_space_t
10002 avr_nonconst_pointer_addrspace (tree typ
)
10004 while (ARRAY_TYPE
== TREE_CODE (typ
))
10005 typ
= TREE_TYPE (typ
);
10007 if (POINTER_TYPE_P (typ
))
10010 tree target
= TREE_TYPE (typ
);
10012 /* Pointer to function: Test the function's return type. */
10014 if (FUNCTION_TYPE
== TREE_CODE (target
))
10015 return avr_nonconst_pointer_addrspace (TREE_TYPE (target
));
10017 /* "Ordinary" pointers... */
10019 while (TREE_CODE (target
) == ARRAY_TYPE
)
10020 target
= TREE_TYPE (target
);
10022 /* Pointers to non-generic address space must be const. */
10024 as
= TYPE_ADDR_SPACE (target
);
10026 if (!ADDR_SPACE_GENERIC_P (as
)
10027 && !TYPE_READONLY (target
)
10028 && avr_addr_space_supported_p (as
))
10033 /* Scan pointer's target type. */
10035 return avr_nonconst_pointer_addrspace (target
);
10038 return ADDR_SPACE_GENERIC
;
10042 /* Sanity check NODE so that all pointers targeting non-generic address spaces
10043 go along with CONST qualifier. Writing to these address spaces should
10044 be detected and complained about as early as possible. */
10047 avr_pgm_check_var_decl (tree node
)
10049 const char *reason
= NULL
;
10051 addr_space_t as
= ADDR_SPACE_GENERIC
;
10053 gcc_assert (as
== 0);
10055 if (avr_log
.progmem
)
10056 avr_edump ("%?: %t\n", node
);
10058 switch (TREE_CODE (node
))
10064 if (as
= avr_nonconst_pointer_addrspace (TREE_TYPE (node
)), as
)
10065 reason
= _("variable");
10069 if (as
= avr_nonconst_pointer_addrspace (TREE_TYPE (node
)), as
)
10070 reason
= _("function parameter");
10074 if (as
= avr_nonconst_pointer_addrspace (TREE_TYPE (node
)), as
)
10075 reason
= _("structure field");
10078 case FUNCTION_DECL
:
10079 if (as
= avr_nonconst_pointer_addrspace (TREE_TYPE (TREE_TYPE (node
))),
10081 reason
= _("return type of function");
10085 if (as
= avr_nonconst_pointer_addrspace (node
), as
)
10086 reason
= _("pointer");
10093 error ("pointer targeting address space %qs must be const in %qT",
10094 avr_addrspace
[as
].name
, node
);
10096 error ("pointer targeting address space %qs must be const"
10098 avr_addrspace
[as
].name
, reason
, node
);
10101 return reason
== NULL
;
10105 /* Add the section attribute if the variable is in progmem. */
10108 avr_insert_attributes (tree node
, tree
*attributes
)
10110 avr_pgm_check_var_decl (node
);
10112 if (TREE_CODE (node
) == VAR_DECL
10113 && (TREE_STATIC (node
) || DECL_EXTERNAL (node
))
10114 && avr_progmem_p (node
, *attributes
))
10119 /* For C++, we have to peel arrays in order to get correct
10120 determination of readonlyness. */
10123 node0
= TREE_TYPE (node0
);
10124 while (TREE_CODE (node0
) == ARRAY_TYPE
);
10126 if (error_mark_node
== node0
)
10129 as
= TYPE_ADDR_SPACE (TREE_TYPE (node
));
10131 if (!TYPE_READONLY (node0
)
10132 && !TREE_READONLY (node
))
10134 const char *reason
= "__attribute__((progmem))";
10136 if (!ADDR_SPACE_GENERIC_P (as
))
10137 reason
= avr_addrspace
[as
].name
;
10139 if (avr_log
.progmem
)
10140 avr_edump ("\n%?: %t\n%t\n", node
, node0
);
10142 error ("variable %q+D must be const in order to be put into"
10143 " read-only section by means of %qs", node
, reason
);
10149 /* Implement `ASM_OUTPUT_ALIGNED_DECL_LOCAL'. */
10150 /* Implement `ASM_OUTPUT_ALIGNED_DECL_COMMON'. */
10151 /* Track need of __do_clear_bss. */
10154 avr_asm_output_aligned_decl_common (FILE * stream
,
10157 unsigned HOST_WIDE_INT size
,
10158 unsigned int align
, bool local_p
)
10160 rtx mem
= decl
== NULL_TREE
? NULL_RTX
: DECL_RTL (decl
);
10163 if (mem
!= NULL_RTX
&& MEM_P (mem
)
10164 && SYMBOL_REF_P ((symbol
= XEXP (mem
, 0)))
10165 && (SYMBOL_REF_FLAGS (symbol
) & (SYMBOL_FLAG_IO
| SYMBOL_FLAG_ADDRESS
)))
10169 fprintf (stream
, "\t.globl\t");
10170 assemble_name (stream
, name
);
10171 fprintf (stream
, "\n");
10173 if (SYMBOL_REF_FLAGS (symbol
) & SYMBOL_FLAG_ADDRESS
)
10175 assemble_name (stream
, name
);
10176 fprintf (stream
, " = %ld\n",
10177 (long) INTVAL (avr_eval_addr_attrib (symbol
)));
10180 error_at (DECL_SOURCE_LOCATION (decl
),
10181 "static IO declaration for %q+D needs an address", decl
);
10185 /* __gnu_lto_v1 etc. are just markers for the linker injected by toplev.c.
10186 There is no need to trigger __do_clear_bss code for them. */
10188 if (!STR_PREFIX_P (name
, "__gnu_lto"))
10189 avr_need_clear_bss_p
= true;
10192 ASM_OUTPUT_ALIGNED_LOCAL (stream
, name
, size
, align
);
10194 ASM_OUTPUT_ALIGNED_COMMON (stream
, name
, size
, align
);
10198 avr_asm_asm_output_aligned_bss (FILE *file
, tree decl
, const char *name
,
10199 unsigned HOST_WIDE_INT size
, int align
,
10200 void (*default_func
)
10201 (FILE *, tree
, const char *,
10202 unsigned HOST_WIDE_INT
, int))
10204 rtx mem
= decl
== NULL_TREE
? NULL_RTX
: DECL_RTL (decl
);
10207 if (mem
!= NULL_RTX
&& MEM_P (mem
)
10208 && SYMBOL_REF_P ((symbol
= XEXP (mem
, 0)))
10209 && (SYMBOL_REF_FLAGS (symbol
) & (SYMBOL_FLAG_IO
| SYMBOL_FLAG_ADDRESS
)))
10211 if (!(SYMBOL_REF_FLAGS (symbol
) & SYMBOL_FLAG_ADDRESS
))
10212 error_at (DECL_SOURCE_LOCATION (decl
),
10213 "IO definition for %q+D needs an address", decl
);
10214 avr_asm_output_aligned_decl_common (file
, decl
, name
, size
, align
, false);
10217 default_func (file
, decl
, name
, size
, align
);
10221 /* Unnamed section callback for data_section
10222 to track need of __do_copy_data. */
10225 avr_output_data_section_asm_op (const void *data
)
10227 avr_need_copy_data_p
= true;
10229 /* Dispatch to default. */
10230 output_section_asm_op (data
);
10234 /* Unnamed section callback for bss_section
10235 to track need of __do_clear_bss. */
10238 avr_output_bss_section_asm_op (const void *data
)
10240 avr_need_clear_bss_p
= true;
10242 /* Dispatch to default. */
10243 output_section_asm_op (data
);
10247 /* Unnamed section callback for progmem*.data sections. */
10250 avr_output_progmem_section_asm_op (const void *data
)
10252 fprintf (asm_out_file
, "\t.section\t%s,\"a\",@progbits\n",
10253 (const char*) data
);
10257 /* Implement `TARGET_ASM_INIT_SECTIONS'. */
10260 avr_asm_init_sections (void)
10262 /* Override section callbacks to keep track of `avr_need_clear_bss_p'
10263 resp. `avr_need_copy_data_p'. If flash is not mapped to RAM then
10264 we have also to track .rodata because it is located in RAM then. */
10266 #if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
10267 if (0 == avr_arch
->flash_pm_offset
)
10269 readonly_data_section
->unnamed
.callback
= avr_output_data_section_asm_op
;
10270 data_section
->unnamed
.callback
= avr_output_data_section_asm_op
;
10271 bss_section
->unnamed
.callback
= avr_output_bss_section_asm_op
;
10275 /* Implement `TARGET_ASM_NAMED_SECTION'. */
10276 /* Track need of __do_clear_bss, __do_copy_data for named sections. */
10279 avr_asm_named_section (const char *name
, unsigned int flags
, tree decl
)
10281 if (flags
& AVR_SECTION_PROGMEM
)
10283 addr_space_t as
= (flags
& AVR_SECTION_PROGMEM
) / SECTION_MACH_DEP
;
10284 const char *old_prefix
= ".rodata";
10285 const char *new_prefix
= avr_addrspace
[as
].section_name
;
10287 if (STR_PREFIX_P (name
, old_prefix
))
10289 const char *sname
= ACONCAT ((new_prefix
,
10290 name
+ strlen (old_prefix
), NULL
));
10291 default_elf_asm_named_section (sname
, flags
, decl
);
10295 default_elf_asm_named_section (new_prefix
, flags
, decl
);
10299 if (!avr_need_copy_data_p
)
10300 avr_need_copy_data_p
= (STR_PREFIX_P (name
, ".data")
10301 || STR_PREFIX_P (name
, ".gnu.linkonce.d"));
10303 if (!avr_need_copy_data_p
10304 #if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
10305 && 0 == avr_arch
->flash_pm_offset
10308 avr_need_copy_data_p
= (STR_PREFIX_P (name
, ".rodata")
10309 || STR_PREFIX_P (name
, ".gnu.linkonce.r"));
10311 if (!avr_need_clear_bss_p
)
10312 avr_need_clear_bss_p
= STR_PREFIX_P (name
, ".bss");
10314 default_elf_asm_named_section (name
, flags
, decl
);
10318 /* Implement `TARGET_SECTION_TYPE_FLAGS'. */
10320 static unsigned int
10321 avr_section_type_flags (tree decl
, const char *name
, int reloc
)
10323 unsigned int flags
= default_section_type_flags (decl
, name
, reloc
);
10325 if (STR_PREFIX_P (name
, ".noinit"))
10327 if (decl
&& TREE_CODE (decl
) == VAR_DECL
10328 && DECL_INITIAL (decl
) == NULL_TREE
)
10329 flags
|= SECTION_BSS
; /* @nobits */
10331 warning (0, "only uninitialized variables can be placed in the "
10332 ".noinit section");
10335 if (decl
&& DECL_P (decl
)
10336 && avr_progmem_p (decl
, DECL_ATTRIBUTES (decl
)))
10338 addr_space_t as
= TYPE_ADDR_SPACE (TREE_TYPE (decl
));
10340 /* Attribute progmem puts data in generic address space.
10341 Set section flags as if it was in __flash to get the right
10342 section prefix in the remainder. */
10344 if (ADDR_SPACE_GENERIC_P (as
))
10345 as
= ADDR_SPACE_FLASH
;
10347 flags
|= as
* SECTION_MACH_DEP
;
10348 flags
&= ~SECTION_WRITE
;
10349 flags
&= ~SECTION_BSS
;
10356 /* A helper for the next function. NODE is a decl that is associated with
10357 a symbol. Return TRUE if the respective object may be accessed by LDS.
10358 There might still be other reasons for why LDS is not appropriate.
10359 This function is only appropriate for AVR_TINY. */
10362 avr_decl_maybe_lds_p (tree node
)
10365 || TREE_CODE (node
) != VAR_DECL
10366 || DECL_SECTION_NAME (node
) != NULL
)
10369 /* Don't use LDS for objects that go to .rodata. The current default
10370 linker description file still locates .rodata in RAM, but this is not
10371 a must. A better linker script would just keep .rodata in flash and
10372 add an offset of 0x4000 to the VMA. Hence avoid LDS for such data. */
10374 if (TREE_READONLY (node
))
10377 // C++ requires peeling arrays.
10380 node
= TREE_TYPE (node
);
10381 while (ARRAY_TYPE
== TREE_CODE (node
));
10383 return (node
!= error_mark_node
10384 && !TYPE_READONLY (node
));
10388 /* Implement `TARGET_ENCODE_SECTION_INFO'. */
10391 avr_encode_section_info (tree decl
, rtx rtl
, int new_decl_p
)
10393 tree addr_attr
= NULL_TREE
;
10395 /* In avr_handle_progmem_attribute, DECL_INITIAL is not yet
10396 readily available, see PR34734. So we postpone the warning
10397 about uninitialized data in program memory section until here. */
10400 && decl
&& DECL_P (decl
)
10401 && !DECL_EXTERNAL (decl
)
10402 && avr_progmem_p (decl
, DECL_ATTRIBUTES (decl
)))
10404 if (!TREE_READONLY (decl
))
10406 // This might happen with C++ if stuff needs constructing.
10407 error ("variable %q+D with dynamic initialization put "
10408 "into program memory area", decl
);
10410 else if (NULL_TREE
== DECL_INITIAL (decl
))
10412 // Don't warn for (implicit) aliases like in PR80462.
10413 tree asmname
= DECL_ASSEMBLER_NAME (decl
);
10414 varpool_node
*node
= varpool_node::get_for_asmname (asmname
);
10415 bool alias_p
= node
&& node
->alias
;
10418 warning (OPT_Wuninitialized
, "uninitialized variable %q+D put "
10419 "into program memory area", decl
);
10423 default_encode_section_info (decl
, rtl
, new_decl_p
);
10425 if (decl
&& DECL_P (decl
)
10426 && TREE_CODE (decl
) != FUNCTION_DECL
10428 && SYMBOL_REF_P (XEXP (rtl
, 0)))
10430 rtx sym
= XEXP (rtl
, 0);
10431 tree type
= TREE_TYPE (decl
);
10432 tree attr
= DECL_ATTRIBUTES (decl
);
10433 if (type
== error_mark_node
)
10436 addr_space_t as
= TYPE_ADDR_SPACE (type
);
10438 /* PSTR strings are in generic space but located in flash:
10439 patch address space. */
10442 && -1 == avr_progmem_p (decl
, attr
))
10443 as
= ADDR_SPACE_FLASH
;
10445 AVR_SYMBOL_SET_ADDR_SPACE (sym
, as
);
10447 tree io_low_attr
= lookup_attribute ("io_low", attr
);
10448 tree io_attr
= lookup_attribute ("io", attr
);
10451 && TREE_VALUE (io_low_attr
) && TREE_VALUE (TREE_VALUE (io_low_attr
)))
10452 addr_attr
= io_attr
;
10454 && TREE_VALUE (io_attr
) && TREE_VALUE (TREE_VALUE (io_attr
)))
10455 addr_attr
= io_attr
;
10457 addr_attr
= lookup_attribute ("address", attr
);
10459 || (io_attr
&& addr_attr
10460 && low_io_address_operand
10461 (GEN_INT (TREE_INT_CST_LOW
10462 (TREE_VALUE (TREE_VALUE (addr_attr
)))), QImode
)))
10463 SYMBOL_REF_FLAGS (sym
) |= SYMBOL_FLAG_IO_LOW
;
10464 if (io_attr
|| io_low_attr
)
10465 SYMBOL_REF_FLAGS (sym
) |= SYMBOL_FLAG_IO
;
10466 /* If we have an (io) address attribute specification, but the variable
10467 is external, treat the address as only a tentative definition
10468 to be used to determine if an io port is in the lower range, but
10469 don't use the exact value for constant propagation. */
10470 if (addr_attr
&& !DECL_EXTERNAL (decl
))
10471 SYMBOL_REF_FLAGS (sym
) |= SYMBOL_FLAG_ADDRESS
;
10476 && VAR_DECL
== TREE_CODE (decl
)
10478 && SYMBOL_REF_P (XEXP (rtl
, 0)))
10480 rtx sym
= XEXP (rtl
, 0);
10481 bool progmem_p
= -1 == avr_progmem_p (decl
, DECL_ATTRIBUTES (decl
));
10485 // Tag symbols for addition of 0x4000 (avr_arch->flash_pm_offset).
10486 SYMBOL_REF_FLAGS (sym
) |= AVR_SYMBOL_FLAG_TINY_PM
;
10489 if (avr_decl_absdata_p (decl
, DECL_ATTRIBUTES (decl
))
10493 && avr_decl_maybe_lds_p (decl
))
10495 // If addr_attr is non-null, it has an argument. Peek into it.
10496 && TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (addr_attr
))) < 0xc0))
10498 // May be accessed by LDS / STS.
10499 SYMBOL_REF_FLAGS (sym
) |= AVR_SYMBOL_FLAG_TINY_ABSDATA
;
10503 && avr_decl_absdata_p (decl
, DECL_ATTRIBUTES (decl
)))
10505 error ("%q+D has incompatible attributes %qs and %qs",
10506 decl
, "progmem", "absdata");
10512 /* Implement `TARGET_ASM_SELECT_SECTION' */
10515 avr_asm_select_section (tree decl
, int reloc
, unsigned HOST_WIDE_INT align
)
10517 section
* sect
= default_elf_select_section (decl
, reloc
, align
);
10519 if (decl
&& DECL_P (decl
)
10520 && avr_progmem_p (decl
, DECL_ATTRIBUTES (decl
)))
10522 addr_space_t as
= TYPE_ADDR_SPACE (TREE_TYPE (decl
));
10524 /* __progmem__ goes in generic space but shall be allocated to
10527 if (ADDR_SPACE_GENERIC_P (as
))
10528 as
= ADDR_SPACE_FLASH
;
10530 if (sect
->common
.flags
& SECTION_NAMED
)
10532 const char * name
= sect
->named
.name
;
10533 const char * old_prefix
= ".rodata";
10534 const char * new_prefix
= avr_addrspace
[as
].section_name
;
10536 if (STR_PREFIX_P (name
, old_prefix
))
10538 const char *sname
= ACONCAT ((new_prefix
,
10539 name
+ strlen (old_prefix
), NULL
));
10540 return get_section (sname
,
10541 sect
->common
.flags
& ~SECTION_DECLARED
,
10546 if (!progmem_section
[as
])
10548 progmem_section
[as
]
10549 = get_unnamed_section (0, avr_output_progmem_section_asm_op
,
10550 avr_addrspace
[as
].section_name
);
10553 return progmem_section
[as
];
10559 /* Implement `TARGET_ASM_FILE_START'. */
10560 /* Outputs some text at the start of each assembler file. */
10563 avr_file_start (void)
10565 int sfr_offset
= avr_arch
->sfr_offset
;
10567 if (avr_arch
->asm_only
)
10568 error ("architecture %qs supported for assembler only", avr_mmcu
);
10570 default_file_start ();
10572 /* Print I/O addresses of some SFRs used with IN and OUT. */
10575 fprintf (asm_out_file
, "__SP_H__ = 0x%02x\n", avr_addr
.sp_h
- sfr_offset
);
10577 fprintf (asm_out_file
, "__SP_L__ = 0x%02x\n", avr_addr
.sp_l
- sfr_offset
);
10578 fprintf (asm_out_file
, "__SREG__ = 0x%02x\n", avr_addr
.sreg
- sfr_offset
);
10579 if (AVR_HAVE_RAMPZ
)
10580 fprintf (asm_out_file
, "__RAMPZ__ = 0x%02x\n", avr_addr
.rampz
- sfr_offset
);
10581 if (AVR_HAVE_RAMPY
)
10582 fprintf (asm_out_file
, "__RAMPY__ = 0x%02x\n", avr_addr
.rampy
- sfr_offset
);
10583 if (AVR_HAVE_RAMPX
)
10584 fprintf (asm_out_file
, "__RAMPX__ = 0x%02x\n", avr_addr
.rampx
- sfr_offset
);
10585 if (AVR_HAVE_RAMPD
)
10586 fprintf (asm_out_file
, "__RAMPD__ = 0x%02x\n", avr_addr
.rampd
- sfr_offset
);
10587 if (AVR_XMEGA
|| AVR_TINY
)
10588 fprintf (asm_out_file
, "__CCP__ = 0x%02x\n", avr_addr
.ccp
- sfr_offset
);
10589 fprintf (asm_out_file
, "__tmp_reg__ = %d\n", AVR_TMP_REGNO
);
10590 fprintf (asm_out_file
, "__zero_reg__ = %d\n", AVR_ZERO_REGNO
);
10594 /* Implement `TARGET_ASM_FILE_END'. */
10595 /* Outputs to the stdio stream FILE some
10596 appropriate text to go at the end of an assembler file. */
10599 avr_file_end (void)
10601 /* Output these only if there is anything in the
10602 .data* / .rodata* / .gnu.linkonce.* resp. .bss* or COMMON
10603 input section(s) - some code size can be saved by not
10604 linking in the initialization code from libgcc if resp.
10605 sections are empty, see PR18145. */
10607 if (avr_need_copy_data_p
)
10608 fputs (".global __do_copy_data\n", asm_out_file
);
10610 if (avr_need_clear_bss_p
)
10611 fputs (".global __do_clear_bss\n", asm_out_file
);
10615 /* Worker function for `ADJUST_REG_ALLOC_ORDER'. */
10616 /* Choose the order in which to allocate hard registers for
10617 pseudo-registers local to a basic block.
10619 Store the desired register order in the array `reg_alloc_order'.
10620 Element 0 should be the register to allocate first; element 1, the
10621 next register; and so on. */
10624 avr_adjust_reg_alloc_order (void)
10626 static const int order_0
[] =
10629 18, 19, 20, 21, 22, 23,
10632 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
10636 static const int tiny_order_0
[] = {
10646 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
10648 static const int order_1
[] =
10650 18, 19, 20, 21, 22, 23, 24, 25,
10653 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
10657 static const int tiny_order_1
[] = {
10666 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
10668 static const int order_2
[] =
10670 25, 24, 23, 22, 21, 20, 19, 18,
10673 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
10678 /* Select specific register allocation order.
10679 Tiny Core (ATtiny4/5/9/10/20/40) devices have only 16 registers,
10680 so different allocation order should be used. */
10682 const int *order
= (TARGET_ORDER_1
? (AVR_TINY
? tiny_order_1
: order_1
)
10683 : TARGET_ORDER_2
? (AVR_TINY
? tiny_order_0
: order_2
)
10684 : (AVR_TINY
? tiny_order_0
: order_0
));
10686 for (size_t i
= 0; i
< ARRAY_SIZE (order_0
); ++i
)
10687 reg_alloc_order
[i
] = order
[i
];
10691 /* Implement `TARGET_REGISTER_MOVE_COST' */
10694 avr_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED
,
10695 reg_class_t from
, reg_class_t to
)
10697 return (from
== STACK_REG
? 6
10698 : to
== STACK_REG
? 12
10703 /* Implement `TARGET_MEMORY_MOVE_COST' */
10706 avr_memory_move_cost (machine_mode mode
,
10707 reg_class_t rclass ATTRIBUTE_UNUSED
,
10708 bool in ATTRIBUTE_UNUSED
)
10710 return (mode
== QImode
? 2
10711 : mode
== HImode
? 4
10712 : mode
== SImode
? 8
10713 : mode
== SFmode
? 8
10718 /* Cost for mul highpart. X is a LSHIFTRT, i.e. the outer TRUNCATE is
10719 already stripped off. */
10722 avr_mul_highpart_cost (rtx x
, int)
10725 && LSHIFTRT
== GET_CODE (x
)
10726 && MULT
== GET_CODE (XEXP (x
, 0))
10727 && CONST_INT_P (XEXP (x
, 1)))
10729 // This is the wider mode.
10730 machine_mode mode
= GET_MODE (x
);
10732 // The middle-end might still have PR81444, i.e. it is calling the cost
10733 // functions with strange modes. Fix this now by also considering
10734 // PSImode (should actually be SImode instead).
10735 if (HImode
== mode
|| PSImode
== mode
|| SImode
== mode
)
10737 return COSTS_N_INSNS (2);
10745 /* Mutually recursive subroutine of avr_rtx_cost for calculating the
10746 cost of an RTX operand given its context. X is the rtx of the
10747 operand, MODE is its mode, and OUTER is the rtx_code of this
10748 operand's parent operator. */
10751 avr_operand_rtx_cost (rtx x
, machine_mode mode
, enum rtx_code outer
,
10752 int opno
, bool speed
)
10754 enum rtx_code code
= GET_CODE (x
);
10766 return COSTS_N_INSNS (GET_MODE_SIZE (mode
));
10773 avr_rtx_costs (x
, mode
, outer
, opno
, &total
, speed
);
10777 /* Worker function for AVR backend's rtx_cost function.
10778 X is rtx expression whose cost is to be calculated.
10779 Return true if the complete cost has been computed.
10780 Return false if subexpressions should be scanned.
10781 In either case, *TOTAL contains the cost result. */
10784 avr_rtx_costs_1 (rtx x
, machine_mode mode
, int outer_code
,
10785 int opno ATTRIBUTE_UNUSED
, int *total
, bool speed
)
10787 enum rtx_code code
= GET_CODE (x
);
10798 /* Immediate constants are as cheap as registers. */
10803 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
10811 *total
= COSTS_N_INSNS (1);
10817 *total
= COSTS_N_INSNS (2 * GET_MODE_SIZE (mode
) - 1);
10823 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
10831 *total
= COSTS_N_INSNS (1);
10837 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
10841 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
10842 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
10846 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
)
10847 - GET_MODE_SIZE (GET_MODE (XEXP (x
, 0))));
10848 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), GET_MODE (XEXP (x
, 0)),
10853 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
) + 2
10854 - GET_MODE_SIZE (GET_MODE (XEXP (x
, 0))));
10855 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), GET_MODE (XEXP (x
, 0)),
10864 && MULT
== GET_CODE (XEXP (x
, 0))
10865 && register_operand (XEXP (x
, 1), QImode
))
10868 *total
= COSTS_N_INSNS (speed
? 4 : 3);
10869 /* multiply-add with constant: will be split and load constant. */
10870 if (CONST_INT_P (XEXP (XEXP (x
, 0), 1)))
10871 *total
= COSTS_N_INSNS (1) + *total
;
10874 *total
= COSTS_N_INSNS (1);
10875 if (!CONST_INT_P (XEXP (x
, 1)))
10876 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1, speed
);
10881 && (MULT
== GET_CODE (XEXP (x
, 0))
10882 || ASHIFT
== GET_CODE (XEXP (x
, 0)))
10883 && register_operand (XEXP (x
, 1), HImode
)
10884 && (ZERO_EXTEND
== GET_CODE (XEXP (XEXP (x
, 0), 0))
10885 || SIGN_EXTEND
== GET_CODE (XEXP (XEXP (x
, 0), 0))))
10888 *total
= COSTS_N_INSNS (speed
? 5 : 4);
10889 /* multiply-add with constant: will be split and load constant. */
10890 if (CONST_INT_P (XEXP (XEXP (x
, 0), 1)))
10891 *total
= COSTS_N_INSNS (1) + *total
;
10894 if (!CONST_INT_P (XEXP (x
, 1)))
10896 *total
= COSTS_N_INSNS (2);
10897 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
10900 else if (IN_RANGE (INTVAL (XEXP (x
, 1)), -63, 63))
10901 *total
= COSTS_N_INSNS (1);
10903 *total
= COSTS_N_INSNS (2);
10907 if (!CONST_INT_P (XEXP (x
, 1)))
10909 *total
= COSTS_N_INSNS (3);
10910 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
10913 else if (IN_RANGE (INTVAL (XEXP (x
, 1)), -63, 63))
10914 *total
= COSTS_N_INSNS (2);
10916 *total
= COSTS_N_INSNS (3);
10920 if (!CONST_INT_P (XEXP (x
, 1)))
10922 *total
= COSTS_N_INSNS (4);
10923 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
10926 else if (IN_RANGE (INTVAL (XEXP (x
, 1)), -63, 63))
10927 *total
= COSTS_N_INSNS (1);
10929 *total
= COSTS_N_INSNS (4);
10935 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
10941 && register_operand (XEXP (x
, 0), QImode
)
10942 && MULT
== GET_CODE (XEXP (x
, 1)))
10945 *total
= COSTS_N_INSNS (speed
? 4 : 3);
10946 /* multiply-sub with constant: will be split and load constant. */
10947 if (CONST_INT_P (XEXP (XEXP (x
, 1), 1)))
10948 *total
= COSTS_N_INSNS (1) + *total
;
10953 && register_operand (XEXP (x
, 0), HImode
)
10954 && (MULT
== GET_CODE (XEXP (x
, 1))
10955 || ASHIFT
== GET_CODE (XEXP (x
, 1)))
10956 && (ZERO_EXTEND
== GET_CODE (XEXP (XEXP (x
, 1), 0))
10957 || SIGN_EXTEND
== GET_CODE (XEXP (XEXP (x
, 1), 0))))
10960 *total
= COSTS_N_INSNS (speed
? 5 : 4);
10961 /* multiply-sub with constant: will be split and load constant. */
10962 if (CONST_INT_P (XEXP (XEXP (x
, 1), 1)))
10963 *total
= COSTS_N_INSNS (1) + *total
;
10971 && ASHIFT
== GET_CODE (XEXP (x
, 0)))
10973 *total
= COSTS_N_INSNS (2);
10974 // Just a rough estimate. If we see no sign- or zero-extend,
10975 // then increase the cost a little bit.
10976 if (REG_P (XEXP (XEXP (x
, 0), 0)))
10977 *total
+= COSTS_N_INSNS (1);
10978 if (REG_P (XEXP (x
, 1)))
10979 *total
+= COSTS_N_INSNS (1);
10982 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
10983 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
10984 if (!CONST_INT_P (XEXP (x
, 1)))
10985 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1, speed
);
10989 *total
= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
10990 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
10991 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1, speed
);
10999 *total
= COSTS_N_INSNS (!speed
? 3 : 4);
11001 *total
= COSTS_N_INSNS (AVR_HAVE_JMP_CALL
? 2 : 1);
11009 rtx op0
= XEXP (x
, 0);
11010 rtx op1
= XEXP (x
, 1);
11011 enum rtx_code code0
= GET_CODE (op0
);
11012 enum rtx_code code1
= GET_CODE (op1
);
11013 bool ex0
= SIGN_EXTEND
== code0
|| ZERO_EXTEND
== code0
;
11014 bool ex1
= SIGN_EXTEND
== code1
|| ZERO_EXTEND
== code1
;
11017 && (u8_operand (op1
, HImode
)
11018 || s8_operand (op1
, HImode
)))
11020 *total
= COSTS_N_INSNS (!speed
? 4 : 6);
11024 && register_operand (op1
, HImode
))
11026 *total
= COSTS_N_INSNS (!speed
? 5 : 8);
11029 else if (ex0
|| ex1
)
11031 *total
= COSTS_N_INSNS (!speed
? 3 : 5);
11034 else if (register_operand (op0
, HImode
)
11035 && (u8_operand (op1
, HImode
)
11036 || s8_operand (op1
, HImode
)))
11038 *total
= COSTS_N_INSNS (!speed
? 6 : 9);
11042 *total
= COSTS_N_INSNS (!speed
? 7 : 10);
11045 *total
= COSTS_N_INSNS (AVR_HAVE_JMP_CALL
? 2 : 1);
11052 *total
= COSTS_N_INSNS (AVR_HAVE_JMP_CALL
? 2 : 1);
11063 /* Add some additional costs besides CALL like moves etc. */
11065 *total
= COSTS_N_INSNS (AVR_HAVE_JMP_CALL
? 5 : 4);
11069 /* Just a rough estimate. Even with -O2 we don't want bulky
11070 code expanded inline. */
11072 *total
= COSTS_N_INSNS (25);
11078 *total
= COSTS_N_INSNS (300);
11080 /* Add some additional costs besides CALL like moves etc. */
11081 *total
= COSTS_N_INSNS (AVR_HAVE_JMP_CALL
? 5 : 4);
11084 if (mode
== DImode
)
11092 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
11093 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1, speed
);
11101 *total
= COSTS_N_INSNS (AVR_HAVE_JMP_CALL
? 2 : 1);
11103 *total
= COSTS_N_INSNS (15 * GET_MODE_SIZE (mode
));
11104 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
11105 /* For div/mod with const-int divisor we have at least the cost of
11106 loading the divisor. */
11107 if (CONST_INT_P (XEXP (x
, 1)))
11108 *total
+= COSTS_N_INSNS (GET_MODE_SIZE (mode
));
11109 /* Add some overall penaly for clobbering and moving around registers */
11110 *total
+= COSTS_N_INSNS (2);
11117 if (CONST_INT_P (XEXP (x
, 1)) && INTVAL (XEXP (x
, 1)) == 4)
11118 *total
= COSTS_N_INSNS (1);
11123 if (CONST_INT_P (XEXP (x
, 1)) && INTVAL (XEXP (x
, 1)) == 8)
11124 *total
= COSTS_N_INSNS (3);
11129 if (CONST_INT_P (XEXP (x
, 1)))
11130 switch (INTVAL (XEXP (x
, 1)))
11134 *total
= COSTS_N_INSNS (5);
11137 *total
= COSTS_N_INSNS (AVR_HAVE_MOVW
? 4 : 6);
11145 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
11152 if (!CONST_INT_P (XEXP (x
, 1)))
11154 *total
= COSTS_N_INSNS (!speed
? 4 : 17);
11155 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
11160 val
= INTVAL (XEXP (x
, 1));
11162 *total
= COSTS_N_INSNS (3);
11163 else if (val
>= 0 && val
<= 7)
11164 *total
= COSTS_N_INSNS (val
);
11166 *total
= COSTS_N_INSNS (1);
11173 if (const_2_to_7_operand (XEXP (x
, 1), HImode
)
11174 && (SIGN_EXTEND
== GET_CODE (XEXP (x
, 0))
11175 || ZERO_EXTEND
== GET_CODE (XEXP (x
, 0))))
11177 *total
= COSTS_N_INSNS (!speed
? 4 : 6);
11182 if (const1_rtx
== (XEXP (x
, 1))
11183 && SIGN_EXTEND
== GET_CODE (XEXP (x
, 0)))
11185 *total
= COSTS_N_INSNS (2);
11189 if (!CONST_INT_P (XEXP (x
, 1)))
11191 *total
= COSTS_N_INSNS (!speed
? 5 : 41);
11192 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
11196 switch (INTVAL (XEXP (x
, 1)))
11203 *total
= COSTS_N_INSNS (2);
11206 *total
= COSTS_N_INSNS (3);
11212 *total
= COSTS_N_INSNS (4);
11217 *total
= COSTS_N_INSNS (5);
11220 *total
= COSTS_N_INSNS (!speed
? 5 : 8);
11223 *total
= COSTS_N_INSNS (!speed
? 5 : 9);
11226 *total
= COSTS_N_INSNS (!speed
? 5 : 10);
11229 *total
= COSTS_N_INSNS (!speed
? 5 : 41);
11230 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
11236 if (!CONST_INT_P (XEXP (x
, 1)))
11238 *total
= COSTS_N_INSNS (!speed
? 6 : 73);
11241 switch (INTVAL (XEXP (x
, 1)))
11249 *total
= COSTS_N_INSNS (3);
11252 *total
= COSTS_N_INSNS (5);
11255 *total
= COSTS_N_INSNS (!speed
? 5 : 3 * INTVAL (XEXP (x
, 1)));
11261 if (!CONST_INT_P (XEXP (x
, 1)))
11263 *total
= COSTS_N_INSNS (!speed
? 7 : 113);
11264 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
11268 switch (INTVAL (XEXP (x
, 1)))
11274 *total
= COSTS_N_INSNS (3);
11279 *total
= COSTS_N_INSNS (4);
11282 *total
= COSTS_N_INSNS (6);
11285 *total
= COSTS_N_INSNS (!speed
? 7 : 8);
11288 *total
= COSTS_N_INSNS (!speed
? 7 : 113);
11289 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
11297 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
11304 if (!CONST_INT_P (XEXP (x
, 1)))
11306 *total
= COSTS_N_INSNS (!speed
? 4 : 17);
11307 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
11312 val
= INTVAL (XEXP (x
, 1));
11314 *total
= COSTS_N_INSNS (4);
11316 *total
= COSTS_N_INSNS (2);
11317 else if (val
>= 0 && val
<= 7)
11318 *total
= COSTS_N_INSNS (val
);
11320 *total
= COSTS_N_INSNS (1);
11325 if (!CONST_INT_P (XEXP (x
, 1)))
11327 *total
= COSTS_N_INSNS (!speed
? 5 : 41);
11328 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
11332 switch (INTVAL (XEXP (x
, 1)))
11338 *total
= COSTS_N_INSNS (2);
11341 *total
= COSTS_N_INSNS (3);
11347 *total
= COSTS_N_INSNS (4);
11351 *total
= COSTS_N_INSNS (5);
11354 *total
= COSTS_N_INSNS (!speed
? 5 : 6);
11357 *total
= COSTS_N_INSNS (!speed
? 5 : 7);
11361 *total
= COSTS_N_INSNS (!speed
? 5 : 8);
11364 *total
= COSTS_N_INSNS (!speed
? 5 : 41);
11365 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
11371 if (!CONST_INT_P (XEXP (x
, 1)))
11373 *total
= COSTS_N_INSNS (!speed
? 6 : 73);
11376 switch (INTVAL (XEXP (x
, 1)))
11382 *total
= COSTS_N_INSNS (3);
11386 *total
= COSTS_N_INSNS (5);
11389 *total
= COSTS_N_INSNS (4);
11392 *total
= COSTS_N_INSNS (!speed
? 5 : 3 * INTVAL (XEXP (x
, 1)));
11398 if (!CONST_INT_P (XEXP (x
, 1)))
11400 *total
= COSTS_N_INSNS (!speed
? 7 : 113);
11401 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
11405 switch (INTVAL (XEXP (x
, 1)))
11411 *total
= COSTS_N_INSNS (4);
11416 *total
= COSTS_N_INSNS (6);
11419 *total
= COSTS_N_INSNS (!speed
? 7 : 8);
11422 *total
= COSTS_N_INSNS (AVR_HAVE_MOVW
? 4 : 5);
11425 *total
= COSTS_N_INSNS (!speed
? 7 : 113);
11426 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
11434 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
11438 if (outer_code
== TRUNCATE
)
11440 *total
= avr_mul_highpart_cost (x
, speed
);
11447 if (!CONST_INT_P (XEXP (x
, 1)))
11449 *total
= COSTS_N_INSNS (!speed
? 4 : 17);
11450 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
11455 val
= INTVAL (XEXP (x
, 1));
11457 *total
= COSTS_N_INSNS (3);
11458 else if (val
>= 0 && val
<= 7)
11459 *total
= COSTS_N_INSNS (val
);
11461 *total
= COSTS_N_INSNS (1);
11466 if (!CONST_INT_P (XEXP (x
, 1)))
11468 *total
= COSTS_N_INSNS (!speed
? 5 : 41);
11469 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
11473 switch (INTVAL (XEXP (x
, 1)))
11480 *total
= COSTS_N_INSNS (2);
11483 *total
= COSTS_N_INSNS (3);
11488 *total
= COSTS_N_INSNS (4);
11492 *total
= COSTS_N_INSNS (5);
11498 *total
= COSTS_N_INSNS (!speed
? 5 : 6);
11501 *total
= COSTS_N_INSNS (!speed
? 5 : 7);
11505 *total
= COSTS_N_INSNS (!speed
? 5 : 9);
11508 *total
= COSTS_N_INSNS (!speed
? 5 : 41);
11509 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
11515 if (!CONST_INT_P (XEXP (x
, 1)))
11517 *total
= COSTS_N_INSNS (!speed
? 6 : 73);
11520 switch (INTVAL (XEXP (x
, 1)))
11528 *total
= COSTS_N_INSNS (3);
11531 *total
= COSTS_N_INSNS (5);
11534 *total
= COSTS_N_INSNS (!speed
? 5 : 3 * INTVAL (XEXP (x
, 1)));
11540 if (!CONST_INT_P (XEXP (x
, 1)))
11542 *total
= COSTS_N_INSNS (!speed
? 7 : 113);
11543 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
11547 switch (INTVAL (XEXP (x
, 1)))
11553 *total
= COSTS_N_INSNS (4);
11556 *total
= COSTS_N_INSNS (!speed
? 7 : 8);
11561 *total
= COSTS_N_INSNS (4);
11564 *total
= COSTS_N_INSNS (6);
11567 *total
= COSTS_N_INSNS (!speed
? 7 : 113);
11568 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), mode
, code
, 1,
11576 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), mode
, code
, 0, speed
);
11580 switch (GET_MODE (XEXP (x
, 0)))
11583 *total
= COSTS_N_INSNS (1);
11584 if (!CONST_INT_P (XEXP (x
, 1)))
11585 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), QImode
, code
,
11590 *total
= COSTS_N_INSNS (2);
11591 if (!CONST_INT_P (XEXP (x
, 1)))
11592 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), HImode
, code
,
11594 else if (INTVAL (XEXP (x
, 1)) != 0)
11595 *total
+= COSTS_N_INSNS (1);
11599 *total
= COSTS_N_INSNS (3);
11600 if (CONST_INT_P (XEXP (x
, 1)) && INTVAL (XEXP (x
, 1)) != 0)
11601 *total
+= COSTS_N_INSNS (2);
11605 *total
= COSTS_N_INSNS (4);
11606 if (!CONST_INT_P (XEXP (x
, 1)))
11607 *total
+= avr_operand_rtx_cost (XEXP (x
, 1), SImode
, code
,
11609 else if (INTVAL (XEXP (x
, 1)) != 0)
11610 *total
+= COSTS_N_INSNS (3);
11616 *total
+= avr_operand_rtx_cost (XEXP (x
, 0), GET_MODE (XEXP (x
, 0)),
11621 if (LSHIFTRT
== GET_CODE (XEXP (x
, 0)))
11623 *total
= avr_mul_highpart_cost (XEXP (x
, 0), speed
);
11635 /* Implement `TARGET_RTX_COSTS'. */
11638 avr_rtx_costs (rtx x
, machine_mode mode
, int outer_code
,
11639 int opno
, int *total
, bool speed
)
11641 bool done
= avr_rtx_costs_1 (x
, mode
, outer_code
, opno
, total
, speed
);
11643 if (avr_log
.rtx_costs
)
11645 avr_edump ("\n%?=%b (%s) total=%d, outer=%C:\n%r\n",
11646 done
, speed
? "speed" : "size", *total
, outer_code
, x
);
11653 /* Implement `TARGET_ADDRESS_COST'. */
11656 avr_address_cost (rtx x
, machine_mode mode ATTRIBUTE_UNUSED
,
11657 addr_space_t as ATTRIBUTE_UNUSED
,
11658 bool speed ATTRIBUTE_UNUSED
)
11662 if (GET_CODE (x
) == PLUS
11663 && CONST_INT_P (XEXP (x
, 1))
11664 && (REG_P (XEXP (x
, 0))
11665 || SUBREG_P (XEXP (x
, 0))))
11667 if (INTVAL (XEXP (x
, 1)) > MAX_LD_OFFSET(mode
))
11670 else if (CONSTANT_ADDRESS_P (x
))
11672 if (io_address_operand (x
, QImode
))
11676 && avr_address_tiny_absdata_p (x
, QImode
))
11680 if (avr_log
.address_cost
)
11681 avr_edump ("\n%?: %d = %r\n", cost
, x
);
11686 /* Test for extra memory constraint 'Q'.
11687 It's a memory address based on Y or Z pointer with valid displacement. */
11690 extra_constraint_Q (rtx x
)
11693 rtx plus
= XEXP (x
, 0);
11695 if (GET_CODE (plus
) == PLUS
11696 && REG_P (XEXP (plus
, 0))
11697 && CONST_INT_P (XEXP (plus
, 1))
11698 && (INTVAL (XEXP (plus
, 1))
11699 <= MAX_LD_OFFSET (GET_MODE (x
))))
11701 rtx xx
= XEXP (plus
, 0);
11702 int regno
= REGNO (xx
);
11704 ok
= (/* allocate pseudos */
11705 regno
>= FIRST_PSEUDO_REGISTER
11706 /* strictly check */
11707 || regno
== REG_Z
|| regno
== REG_Y
11708 /* XXX frame & arg pointer checks */
11709 || xx
== frame_pointer_rtx
11710 || xx
== arg_pointer_rtx
);
11712 if (avr_log
.constraints
)
11713 avr_edump ("\n%?=%d reload_completed=%d reload_in_progress=%d\n %r\n",
11714 ok
, reload_completed
, reload_in_progress
, x
);
11720 /* Convert condition code CONDITION to the valid AVR condition code. */
11723 avr_normalize_condition (RTX_CODE condition
)
11736 gcc_unreachable ();
11740 /* Helper function for `avr_reorg'. */
11743 avr_compare_pattern (rtx_insn
*insn
)
11745 rtx pattern
= single_set (insn
);
11748 && NONJUMP_INSN_P (insn
)
11749 && SET_DEST (pattern
) == cc0_rtx
11750 && GET_CODE (SET_SRC (pattern
)) == COMPARE
)
11752 machine_mode mode0
= GET_MODE (XEXP (SET_SRC (pattern
), 0));
11753 machine_mode mode1
= GET_MODE (XEXP (SET_SRC (pattern
), 1));
11755 /* The 64-bit comparisons have fixed operands ACC_A and ACC_B.
11756 They must not be swapped, thus skip them. */
11758 if ((mode0
== VOIDmode
|| GET_MODE_SIZE (mode0
) <= 4)
11759 && (mode1
== VOIDmode
|| GET_MODE_SIZE (mode1
) <= 4))
11766 /* Helper function for `avr_reorg'. */
11768 /* Expansion of switch/case decision trees leads to code like
11770 cc0 = compare (Reg, Num)
11774 cc0 = compare (Reg, Num)
11778 The second comparison is superfluous and can be deleted.
11779 The second jump condition can be transformed from a
11780 "difficult" one to a "simple" one because "cc0 > 0" and
11781 "cc0 >= 0" will have the same effect here.
11783 This function relies on the way switch/case is being expaned
11784 as binary decision tree. For example code see PR 49903.
11786 Return TRUE if optimization performed.
11787 Return FALSE if nothing changed.
11789 INSN1 is a comparison, i.e. avr_compare_pattern != 0.
11791 We don't want to do this in text peephole because it is
11792 tedious to work out jump offsets there and the second comparison
11793 might have been transormed by `avr_reorg'.
11795 RTL peephole won't do because peephole2 does not scan across
11799 avr_reorg_remove_redundant_compare (rtx_insn
*insn1
)
11801 rtx comp1
, ifelse1
, xcond1
;
11803 rtx comp2
, ifelse2
, xcond2
;
11804 rtx_insn
*branch2
, *insn2
;
11805 enum rtx_code code
;
11809 /* Look out for: compare1 - branch1 - compare2 - branch2 */
11811 branch1
= next_nonnote_nondebug_insn (insn1
);
11812 if (!branch1
|| !JUMP_P (branch1
))
11815 insn2
= next_nonnote_nondebug_insn (branch1
);
11816 if (!insn2
|| !avr_compare_pattern (insn2
))
11819 branch2
= next_nonnote_nondebug_insn (insn2
);
11820 if (!branch2
|| !JUMP_P (branch2
))
11823 comp1
= avr_compare_pattern (insn1
);
11824 comp2
= avr_compare_pattern (insn2
);
11825 xcond1
= single_set (branch1
);
11826 xcond2
= single_set (branch2
);
11828 if (!comp1
|| !comp2
11829 || !rtx_equal_p (comp1
, comp2
)
11830 || !xcond1
|| SET_DEST (xcond1
) != pc_rtx
11831 || !xcond2
|| SET_DEST (xcond2
) != pc_rtx
11832 || IF_THEN_ELSE
!= GET_CODE (SET_SRC (xcond1
))
11833 || IF_THEN_ELSE
!= GET_CODE (SET_SRC (xcond2
)))
11838 comp1
= SET_SRC (comp1
);
11839 ifelse1
= SET_SRC (xcond1
);
11840 ifelse2
= SET_SRC (xcond2
);
11842 /* comp<n> is COMPARE now and ifelse<n> is IF_THEN_ELSE. */
11844 if (EQ
!= GET_CODE (XEXP (ifelse1
, 0))
11845 || !REG_P (XEXP (comp1
, 0))
11846 || !CONST_INT_P (XEXP (comp1
, 1))
11847 || XEXP (ifelse1
, 2) != pc_rtx
11848 || XEXP (ifelse2
, 2) != pc_rtx
11849 || LABEL_REF
!= GET_CODE (XEXP (ifelse1
, 1))
11850 || LABEL_REF
!= GET_CODE (XEXP (ifelse2
, 1))
11851 || !COMPARISON_P (XEXP (ifelse2
, 0))
11852 || cc0_rtx
!= XEXP (XEXP (ifelse1
, 0), 0)
11853 || cc0_rtx
!= XEXP (XEXP (ifelse2
, 0), 0)
11854 || const0_rtx
!= XEXP (XEXP (ifelse1
, 0), 1)
11855 || const0_rtx
!= XEXP (XEXP (ifelse2
, 0), 1))
11860 /* We filtered the insn sequence to look like
11866 (if_then_else (eq (cc0)
11875 (if_then_else (CODE (cc0)
11881 code
= GET_CODE (XEXP (ifelse2
, 0));
11883 /* Map GT/GTU to GE/GEU which is easier for AVR.
11884 The first two instructions compare/branch on EQ
11885 so we may replace the difficult
11887 if (x == VAL) goto L1;
11888 if (x > VAL) goto L2;
11892 if (x == VAL) goto L1;
11893 if (x >= VAL) goto L2;
11895 Similarly, replace LE/LEU by LT/LTU. */
11906 code
= avr_normalize_condition (code
);
11913 /* Wrap the branches into UNSPECs so they won't be changed or
11914 optimized in the remainder. */
11916 target
= XEXP (XEXP (ifelse1
, 1), 0);
11917 cond
= XEXP (ifelse1
, 0);
11918 jump
= emit_jump_insn_after (gen_branch_unspec (target
, cond
), insn1
);
11920 JUMP_LABEL (jump
) = JUMP_LABEL (branch1
);
11922 target
= XEXP (XEXP (ifelse2
, 1), 0);
11923 cond
= gen_rtx_fmt_ee (code
, VOIDmode
, cc0_rtx
, const0_rtx
);
11924 jump
= emit_jump_insn_after (gen_branch_unspec (target
, cond
), insn2
);
11926 JUMP_LABEL (jump
) = JUMP_LABEL (branch2
);
11928 /* The comparisons in insn1 and insn2 are exactly the same;
11929 insn2 is superfluous so delete it. */
11931 delete_insn (insn2
);
11932 delete_insn (branch1
);
11933 delete_insn (branch2
);
11939 /* Implement `TARGET_MACHINE_DEPENDENT_REORG'. */
11940 /* Optimize conditional jumps. */
11945 rtx_insn
*insn
= get_insns();
11947 for (insn
= next_real_insn (insn
); insn
; insn
= next_real_insn (insn
))
11949 rtx pattern
= avr_compare_pattern (insn
);
11955 && avr_reorg_remove_redundant_compare (insn
))
11960 if (compare_diff_p (insn
))
11962 /* Now we work under compare insn with difficult branch. */
11964 rtx_insn
*next
= next_real_insn (insn
);
11965 rtx pat
= PATTERN (next
);
11967 pattern
= SET_SRC (pattern
);
11969 if (true_regnum (XEXP (pattern
, 0)) >= 0
11970 && true_regnum (XEXP (pattern
, 1)) >= 0)
11972 rtx x
= XEXP (pattern
, 0);
11973 rtx src
= SET_SRC (pat
);
11974 rtx t
= XEXP (src
, 0);
11975 PUT_CODE (t
, swap_condition (GET_CODE (t
)));
11976 XEXP (pattern
, 0) = XEXP (pattern
, 1);
11977 XEXP (pattern
, 1) = x
;
11978 INSN_CODE (next
) = -1;
11980 else if (true_regnum (XEXP (pattern
, 0)) >= 0
11981 && XEXP (pattern
, 1) == const0_rtx
)
11983 /* This is a tst insn, we can reverse it. */
11984 rtx src
= SET_SRC (pat
);
11985 rtx t
= XEXP (src
, 0);
11987 PUT_CODE (t
, swap_condition (GET_CODE (t
)));
11988 XEXP (pattern
, 1) = XEXP (pattern
, 0);
11989 XEXP (pattern
, 0) = const0_rtx
;
11990 INSN_CODE (next
) = -1;
11991 INSN_CODE (insn
) = -1;
11993 else if (true_regnum (XEXP (pattern
, 0)) >= 0
11994 && CONST_INT_P (XEXP (pattern
, 1)))
11996 rtx x
= XEXP (pattern
, 1);
11997 rtx src
= SET_SRC (pat
);
11998 rtx t
= XEXP (src
, 0);
11999 machine_mode mode
= GET_MODE (XEXP (pattern
, 0));
12001 if (avr_simplify_comparison_p (mode
, GET_CODE (t
), x
))
12003 XEXP (pattern
, 1) = gen_int_mode (INTVAL (x
) + 1, mode
);
12004 PUT_CODE (t
, avr_normalize_condition (GET_CODE (t
)));
12005 INSN_CODE (next
) = -1;
12006 INSN_CODE (insn
) = -1;
12013 /* Returns register number for function return value.*/
12015 static inline unsigned int
12016 avr_ret_register (void)
12022 /* Implement `TARGET_FUNCTION_VALUE_REGNO_P'. */
12025 avr_function_value_regno_p (const unsigned int regno
)
12027 return (regno
== avr_ret_register ());
12031 /* Implement `TARGET_LIBCALL_VALUE'. */
12032 /* Create an RTX representing the place where a
12033 library function returns a value of mode MODE. */
12036 avr_libcall_value (machine_mode mode
,
12037 const_rtx func ATTRIBUTE_UNUSED
)
12039 int offs
= GET_MODE_SIZE (mode
);
12042 offs
= (offs
+ 1) & ~1;
12044 return gen_rtx_REG (mode
, avr_ret_register () + 2 - offs
);
12048 /* Implement `TARGET_FUNCTION_VALUE'. */
12049 /* Create an RTX representing the place where a
12050 function returns a value of data type VALTYPE. */
12053 avr_function_value (const_tree type
,
12054 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
12055 bool outgoing ATTRIBUTE_UNUSED
)
12059 if (TYPE_MODE (type
) != BLKmode
)
12060 return avr_libcall_value (TYPE_MODE (type
), NULL_RTX
);
12062 offs
= int_size_in_bytes (type
);
12065 if (offs
> 2 && offs
< GET_MODE_SIZE (SImode
))
12066 offs
= GET_MODE_SIZE (SImode
);
12067 else if (offs
> GET_MODE_SIZE (SImode
) && offs
< GET_MODE_SIZE (DImode
))
12068 offs
= GET_MODE_SIZE (DImode
);
12070 return gen_rtx_REG (BLKmode
, avr_ret_register () + 2 - offs
);
12074 test_hard_reg_class (enum reg_class rclass
, rtx x
)
12076 int regno
= true_regnum (x
);
12080 if (TEST_HARD_REG_CLASS (rclass
, regno
))
12087 /* Helper for jump_over_one_insn_p: Test if INSN is a 2-word instruction
12088 and thus is suitable to be skipped by CPSE, SBRC, etc. */
12091 avr_2word_insn_p (rtx_insn
*insn
)
12093 if (TARGET_SKIP_BUG
12095 || 2 != get_attr_length (insn
))
12100 switch (INSN_CODE (insn
))
12105 case CODE_FOR_movqi_insn
:
12106 case CODE_FOR_movuqq_insn
:
12107 case CODE_FOR_movqq_insn
:
12109 rtx set
= single_set (insn
);
12110 rtx src
= SET_SRC (set
);
12111 rtx dest
= SET_DEST (set
);
12113 /* Factor out LDS and STS from movqi_insn. */
12116 && (REG_P (src
) || src
== CONST0_RTX (GET_MODE (dest
))))
12118 return CONSTANT_ADDRESS_P (XEXP (dest
, 0));
12120 else if (REG_P (dest
)
12123 return CONSTANT_ADDRESS_P (XEXP (src
, 0));
12129 case CODE_FOR_call_insn
:
12130 case CODE_FOR_call_value_insn
:
12137 jump_over_one_insn_p (rtx_insn
*insn
, rtx dest
)
12139 int uid
= INSN_UID (GET_CODE (dest
) == LABEL_REF
12142 int jump_addr
= INSN_ADDRESSES (INSN_UID (insn
));
12143 int dest_addr
= INSN_ADDRESSES (uid
);
12144 int jump_offset
= dest_addr
- jump_addr
- get_attr_length (insn
);
12146 return (jump_offset
== 1
12147 || (jump_offset
== 2
12148 && avr_2word_insn_p (next_active_insn (insn
))));
12152 /* Implement TARGET_HARD_REGNO_MODE_OK. On the enhanced core, anything
12153 larger than 1 byte must start in even numbered register for "movw" to
12154 work (this way we don't have to check for odd registers everywhere). */
12157 avr_hard_regno_mode_ok (unsigned int regno
, machine_mode mode
)
12159 /* NOTE: 8-bit values must not be disallowed for R28 or R29.
12160 Disallowing QI et al. in these regs might lead to code like
12161 (set (subreg:QI (reg:HI 28) n) ...)
12162 which will result in wrong code because reload does not
12163 handle SUBREGs of hard regsisters like this.
12164 This could be fixed in reload. However, it appears
12165 that fixing reload is not wanted by reload people. */
12167 /* Any GENERAL_REGS register can hold 8-bit values. */
12169 if (GET_MODE_SIZE (mode
) == 1)
12172 /* FIXME: Ideally, the following test is not needed.
12173 However, it turned out that it can reduce the number
12174 of spill fails. AVR and it's poor endowment with
12175 address registers is extreme stress test for reload. */
12177 if (GET_MODE_SIZE (mode
) >= 4
12181 /* All modes larger than 8 bits should start in an even register. */
12183 return !(regno
& 1);
12187 /* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED. */
12190 avr_hard_regno_call_part_clobbered (unsigned regno
, machine_mode mode
)
12192 /* FIXME: This hook gets called with MODE:REGNO combinations that don't
12193 represent valid hard registers like, e.g. HI:29. Returning TRUE
12194 for such registers can lead to performance degradation as mentioned
12195 in PR53595. Thus, report invalid hard registers as FALSE. */
12197 if (!avr_hard_regno_mode_ok (regno
, mode
))
12200 /* Return true if any of the following boundaries is crossed:
12201 17/18 or 19/20 (if AVR_TINY), 27/28 and 29/30. */
12203 return ((regno
<= LAST_CALLEE_SAVED_REG
12204 && regno
+ GET_MODE_SIZE (mode
) > 1 + LAST_CALLEE_SAVED_REG
)
12205 || (regno
< REG_Y
&& regno
+ GET_MODE_SIZE (mode
) > REG_Y
)
12206 || (regno
< REG_Z
&& regno
+ GET_MODE_SIZE (mode
) > REG_Z
));
12210 /* Implement `MODE_CODE_BASE_REG_CLASS'. */
12213 avr_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED
,
12214 addr_space_t as
, RTX_CODE outer_code
,
12215 RTX_CODE index_code ATTRIBUTE_UNUSED
)
12217 if (!ADDR_SPACE_GENERIC_P (as
))
12219 return POINTER_Z_REGS
;
12223 return reload_completed
? BASE_POINTER_REGS
: POINTER_REGS
;
12225 return PLUS
== outer_code
? BASE_POINTER_REGS
: POINTER_REGS
;
12229 /* Implement `REGNO_MODE_CODE_OK_FOR_BASE_P'. */
12232 avr_regno_mode_code_ok_for_base_p (int regno
,
12233 machine_mode mode ATTRIBUTE_UNUSED
,
12234 addr_space_t as ATTRIBUTE_UNUSED
,
12235 RTX_CODE outer_code
,
12236 RTX_CODE index_code ATTRIBUTE_UNUSED
)
12240 if (!ADDR_SPACE_GENERIC_P (as
))
12242 if (regno
< FIRST_PSEUDO_REGISTER
12250 regno
= reg_renumber
[regno
];
12252 if (regno
== REG_Z
)
12261 if (regno
< FIRST_PSEUDO_REGISTER
12265 || regno
== ARG_POINTER_REGNUM
))
12269 else if (reg_renumber
)
12271 regno
= reg_renumber
[regno
];
12276 || regno
== ARG_POINTER_REGNUM
)
12283 && PLUS
== outer_code
12293 /* A helper for `output_reload_insisf' and `output_reload_inhi'. */
12294 /* Set 32-bit register OP[0] to compile-time constant OP[1].
12295 CLOBBER_REG is a QI clobber register or NULL_RTX.
12296 LEN == NULL: output instructions.
12297 LEN != NULL: set *LEN to the length of the instruction sequence
12298 (in words) printed with LEN = NULL.
12299 If CLEAR_P is true, OP[0] had been cleard to Zero already.
12300 If CLEAR_P is false, nothing is known about OP[0].
12302 The effect on cc0 is as follows:
12304 Load 0 to any register except ZERO_REG : NONE
12305 Load ld register with any value : NONE
12306 Anything else: : CLOBBER */
12309 output_reload_in_const (rtx
*op
, rtx clobber_reg
, int *len
, bool clear_p
)
12313 rtx xval
, xdest
[4];
12315 int clobber_val
= 1234;
12316 bool cooked_clobber_p
= false;
12317 bool set_p
= false;
12318 machine_mode mode
= GET_MODE (dest
);
12319 int n_bytes
= GET_MODE_SIZE (mode
);
12321 gcc_assert (REG_P (dest
)
12322 && CONSTANT_P (src
));
12327 /* (REG:SI 14) is special: It's neither in LD_REGS nor in NO_LD_REGS
12328 but has some subregs that are in LD_REGS. Use the MSB (REG:QI 17). */
12330 if (REGNO (dest
) < 16
12331 && REGNO (dest
) + GET_MODE_SIZE (mode
) > 16)
12333 clobber_reg
= all_regs_rtx
[REGNO (dest
) + n_bytes
- 1];
12336 /* We might need a clobber reg but don't have one. Look at the value to
12337 be loaded more closely. A clobber is only needed if it is a symbol
12338 or contains a byte that is neither 0, -1 or a power of 2. */
12340 if (NULL_RTX
== clobber_reg
12341 && !test_hard_reg_class (LD_REGS
, dest
)
12342 && (! (CONST_INT_P (src
) || CONST_FIXED_P (src
) || CONST_DOUBLE_P (src
))
12343 || !avr_popcount_each_byte (src
, n_bytes
,
12344 (1 << 0) | (1 << 1) | (1 << 8))))
12346 /* We have no clobber register but need one. Cook one up.
12347 That's cheaper than loading from constant pool. */
12349 cooked_clobber_p
= true;
12350 clobber_reg
= all_regs_rtx
[REG_Z
+ 1];
12351 avr_asm_len ("mov __tmp_reg__,%0", &clobber_reg
, len
, 1);
12354 /* Now start filling DEST from LSB to MSB. */
12356 for (int n
= 0; n
< n_bytes
; n
++)
12359 bool done_byte
= false;
12362 /* Crop the n-th destination byte. */
12364 xdest
[n
] = simplify_gen_subreg (QImode
, dest
, mode
, n
);
12365 ldreg_p
= test_hard_reg_class (LD_REGS
, xdest
[n
]);
12367 if (!CONST_INT_P (src
)
12368 && !CONST_FIXED_P (src
)
12369 && !CONST_DOUBLE_P (src
))
12371 static const char* const asm_code
[][2] =
12373 { "ldi %2,lo8(%1)" CR_TAB
"mov %0,%2", "ldi %0,lo8(%1)" },
12374 { "ldi %2,hi8(%1)" CR_TAB
"mov %0,%2", "ldi %0,hi8(%1)" },
12375 { "ldi %2,hlo8(%1)" CR_TAB
"mov %0,%2", "ldi %0,hlo8(%1)" },
12376 { "ldi %2,hhi8(%1)" CR_TAB
"mov %0,%2", "ldi %0,hhi8(%1)" }
12381 xop
[2] = clobber_reg
;
12383 avr_asm_len (asm_code
[n
][ldreg_p
], xop
, len
, ldreg_p
? 1 : 2);
12388 /* Crop the n-th source byte. */
12390 xval
= simplify_gen_subreg (QImode
, src
, mode
, n
);
12391 ival
[n
] = INTVAL (xval
);
12393 /* Look if we can reuse the low word by means of MOVW. */
12399 rtx lo16
= simplify_gen_subreg (HImode
, src
, mode
, 0);
12400 rtx hi16
= simplify_gen_subreg (HImode
, src
, mode
, 2);
12402 if (INTVAL (lo16
) == INTVAL (hi16
))
12404 if (0 != INTVAL (lo16
)
12407 avr_asm_len ("movw %C0,%A0", &op
[0], len
, 1);
12414 /* Don't use CLR so that cc0 is set as expected. */
12419 avr_asm_len (ldreg_p
? "ldi %0,0"
12420 : AVR_ZERO_REGNO
== REGNO (xdest
[n
]) ? "clr %0"
12421 : "mov %0,__zero_reg__",
12422 &xdest
[n
], len
, 1);
12426 if (clobber_val
== ival
[n
]
12427 && REGNO (clobber_reg
) == REGNO (xdest
[n
]))
12432 /* LD_REGS can use LDI to move a constant value */
12438 avr_asm_len ("ldi %0,lo8(%1)", xop
, len
, 1);
12442 /* Try to reuse value already loaded in some lower byte. */
12444 for (int j
= 0; j
< n
; j
++)
12445 if (ival
[j
] == ival
[n
])
12450 avr_asm_len ("mov %0,%1", xop
, len
, 1);
12458 /* Need no clobber reg for -1: Use CLR/DEC */
12463 avr_asm_len ("clr %0", &xdest
[n
], len
, 1);
12465 avr_asm_len ("dec %0", &xdest
[n
], len
, 1);
12468 else if (1 == ival
[n
])
12471 avr_asm_len ("clr %0", &xdest
[n
], len
, 1);
12473 avr_asm_len ("inc %0", &xdest
[n
], len
, 1);
12477 /* Use T flag or INC to manage powers of 2 if we have
12480 if (NULL_RTX
== clobber_reg
12481 && single_one_operand (xval
, QImode
))
12484 xop
[1] = GEN_INT (exact_log2 (ival
[n
] & GET_MODE_MASK (QImode
)));
12486 gcc_assert (constm1_rtx
!= xop
[1]);
12491 avr_asm_len ("set", xop
, len
, 1);
12495 avr_asm_len ("clr %0", xop
, len
, 1);
12497 avr_asm_len ("bld %0,%1", xop
, len
, 1);
12501 /* We actually need the LD_REGS clobber reg. */
12503 gcc_assert (NULL_RTX
!= clobber_reg
);
12507 xop
[2] = clobber_reg
;
12508 clobber_val
= ival
[n
];
12510 avr_asm_len ("ldi %2,lo8(%1)" CR_TAB
12511 "mov %0,%2", xop
, len
, 2);
12514 /* If we cooked up a clobber reg above, restore it. */
12516 if (cooked_clobber_p
)
12518 avr_asm_len ("mov %0,__tmp_reg__", &clobber_reg
, len
, 1);
12523 /* Reload the constant OP[1] into the HI register OP[0].
12524 CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
12525 into a NO_LD_REGS register. If CLOBBER_REG is NULL_RTX we either don't
12526 need a clobber reg or have to cook one up.
12528 PLEN == NULL: Output instructions.
12529 PLEN != NULL: Output nothing. Set *PLEN to number of words occupied
12530 by the insns printed.
12535 output_reload_inhi (rtx
*op
, rtx clobber_reg
, int *plen
)
12537 output_reload_in_const (op
, clobber_reg
, plen
, false);
12542 /* Reload a SI or SF compile time constant OP[1] into the register OP[0].
12543 CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
12544 into a NO_LD_REGS register. If CLOBBER_REG is NULL_RTX we either don't
12545 need a clobber reg or have to cook one up.
12547 LEN == NULL: Output instructions.
12549 LEN != NULL: Output nothing. Set *LEN to number of words occupied
12550 by the insns printed.
12555 output_reload_insisf (rtx
*op
, rtx clobber_reg
, int *len
)
12558 && !test_hard_reg_class (LD_REGS
, op
[0])
12559 && (CONST_INT_P (op
[1])
12560 || CONST_FIXED_P (op
[1])
12561 || CONST_DOUBLE_P (op
[1])))
12563 int len_clr
, len_noclr
;
12565 /* In some cases it is better to clear the destination beforehand, e.g.
12567 CLR R2 CLR R3 MOVW R4,R2 INC R2
12571 CLR R2 INC R2 CLR R3 CLR R4 CLR R5
12573 We find it too tedious to work that out in the print function.
12574 Instead, we call the print function twice to get the lengths of
12575 both methods and use the shortest one. */
12577 output_reload_in_const (op
, clobber_reg
, &len_clr
, true);
12578 output_reload_in_const (op
, clobber_reg
, &len_noclr
, false);
12580 if (len_noclr
- len_clr
== 4)
12582 /* Default needs 4 CLR instructions: clear register beforehand. */
12584 avr_asm_len ("mov %A0,__zero_reg__" CR_TAB
12585 "mov %B0,__zero_reg__" CR_TAB
12586 "movw %C0,%A0", &op
[0], len
, 3);
12588 output_reload_in_const (op
, clobber_reg
, len
, true);
12597 /* Default: destination not pre-cleared. */
12599 output_reload_in_const (op
, clobber_reg
, len
, false);
12604 avr_out_reload_inpsi (rtx
*op
, rtx clobber_reg
, int *len
)
12606 output_reload_in_const (op
, clobber_reg
, len
, false);
12611 /* Worker function for `ASM_OUTPUT_ADDR_VEC'. */
12612 /* Emit jump tables out-of-line so that branches crossing the table
12613 get shorter offsets. If we have JUMP + CALL, then put the tables
12614 in a dedicated non-.text section so that CALLs get better chance to
12615 be relaxed to RCALLs.
12617 We emit the tables by hand because `function_rodata_section' does not
12618 work as expected, cf. PR71151, and we do *NOT* want the table to be
12619 in .rodata, hence setting JUMP_TABLES_IN_TEXT_SECTION = 0 is of limited
12620 use; and setting it to 1 attributes table lengths to branch offsets...
12621 Moreover, fincal.c keeps switching section before each table entry
12622 which we find too fragile as to rely on section caching. */
12625 avr_output_addr_vec (rtx_insn
*labl
, rtx table
)
12627 FILE *stream
= asm_out_file
;
12631 // Switch to appropriate (sub)section.
12633 if (DECL_SECTION_NAME (current_function_decl
)
12634 && symtab_node::get (current_function_decl
)
12635 && ! symtab_node::get (current_function_decl
)->implicit_section
)
12637 // .subsection will emit the code after the function and in the
12638 // section as chosen by the user.
12640 switch_to_section (current_function_section ());
12641 fprintf (stream
, "\t.subsection\t1\n");
12645 // Since PR63223 there is no restriction where to put the table; it
12646 // may even reside above 128 KiB. We put it in a section as high as
12647 // possible and avoid progmem in order not to waste flash <= 64 KiB.
12649 const char *sec_name
= ".jumptables.gcc";
12651 // The table belongs to its host function, therefore use fine
12652 // grained sections so that, if that function is removed by
12653 // --gc-sections, the child table(s) may also be removed. */
12655 tree asm_name
= DECL_ASSEMBLER_NAME (current_function_decl
);
12656 const char *fname
= IDENTIFIER_POINTER (asm_name
);
12657 fname
= targetm
.strip_name_encoding (fname
);
12658 sec_name
= ACONCAT ((sec_name
, ".", fname
, NULL
));
12660 fprintf (stream
, "\t.section\t%s,\"%s\",@progbits\n", sec_name
,
12661 AVR_HAVE_JMP_CALL
? "a" : "ax");
12664 // Output the label that preceeds the table.
12666 ASM_OUTPUT_ALIGN (stream
, 1);
12667 targetm
.asm_out
.internal_label (stream
, "L", CODE_LABEL_NUMBER (labl
));
12669 // Output the table's content.
12671 int vlen
= XVECLEN (table
, 0);
12673 for (int idx
= 0; idx
< vlen
; idx
++)
12675 int value
= CODE_LABEL_NUMBER (XEXP (XVECEXP (table
, 0, idx
), 0));
12677 if (AVR_HAVE_JMP_CALL
)
12678 fprintf (stream
, "\t.word gs(.L%d)\n", value
);
12680 fprintf (stream
, "\trjmp .L%d\n", value
);
12683 // Switch back to original section. As we clobbered the section above,
12684 // forget the current section before switching back.
12687 switch_to_section (current_function_section ());
12691 /* Implement `TARGET_CONDITIONAL_REGISTER_USAGE'. */
12694 avr_conditional_register_usage (void)
12698 const int tiny_reg_alloc_order
[] = {
12707 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
12710 /* Set R0-R17 as fixed registers. Reset R0-R17 in call used register list
12711 - R0-R15 are not available in Tiny Core devices
12712 - R16 and R17 are fixed registers. */
12714 for (size_t i
= 0; i
<= 17; i
++)
12717 call_used_regs
[i
] = 1;
12720 /* Set R18 to R21 as callee saved registers
12721 - R18, R19, R20 and R21 are the callee saved registers in
12722 Tiny Core devices */
12724 for (size_t i
= 18; i
<= LAST_CALLEE_SAVED_REG
; i
++)
12726 call_used_regs
[i
] = 0;
12729 /* Update register allocation order for Tiny Core devices */
12731 for (size_t i
= 0; i
< ARRAY_SIZE (tiny_reg_alloc_order
); i
++)
12733 reg_alloc_order
[i
] = tiny_reg_alloc_order
[i
];
12736 CLEAR_HARD_REG_SET (reg_class_contents
[(int) ADDW_REGS
]);
12737 CLEAR_HARD_REG_SET (reg_class_contents
[(int) NO_LD_REGS
]);
12741 /* Implement `TARGET_HARD_REGNO_SCRATCH_OK'. */
12742 /* Returns true if SCRATCH are safe to be allocated as a scratch
12743 registers (for a define_peephole2) in the current function. */
12746 avr_hard_regno_scratch_ok (unsigned int regno
)
12748 /* Interrupt functions can only use registers that have already been saved
12749 by the prologue, even if they would normally be call-clobbered. */
12751 if ((cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
)
12752 && !df_regs_ever_live_p (regno
))
12755 /* Don't allow hard registers that might be part of the frame pointer.
12756 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
12757 and don't care for a frame pointer that spans more than one register. */
12759 if ((!reload_completed
|| frame_pointer_needed
)
12760 && (regno
== REG_Y
|| regno
== REG_Y
+ 1))
12769 /* Worker function for `HARD_REGNO_RENAME_OK'. */
12770 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
12773 avr_hard_regno_rename_ok (unsigned int old_reg
,
12774 unsigned int new_reg
)
12776 /* Interrupt functions can only use registers that have already been
12777 saved by the prologue, even if they would normally be
12780 if ((cfun
->machine
->is_interrupt
|| cfun
->machine
->is_signal
)
12781 && !df_regs_ever_live_p (new_reg
))
12784 /* Don't allow hard registers that might be part of the frame pointer.
12785 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
12786 and don't care for a frame pointer that spans more than one register. */
12788 if ((!reload_completed
|| frame_pointer_needed
)
12789 && (old_reg
== REG_Y
|| old_reg
== REG_Y
+ 1
12790 || new_reg
== REG_Y
|| new_reg
== REG_Y
+ 1))
12798 /* Output a branch that tests a single bit of a register (QI, HI, SI or DImode)
12799 or memory location in the I/O space (QImode only).
12801 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
12802 Operand 1: register operand to test, or CONST_INT memory address.
12803 Operand 2: bit number.
12804 Operand 3: label to jump to if the test is true. */
12807 avr_out_sbxx_branch (rtx_insn
*insn
, rtx operands
[])
12809 enum rtx_code comp
= GET_CODE (operands
[0]);
12810 bool long_jump
= get_attr_length (insn
) >= 4;
12811 bool reverse
= long_jump
|| jump_over_one_insn_p (insn
, operands
[3]);
12815 else if (comp
== LT
)
12819 comp
= reverse_condition (comp
);
12821 switch (GET_CODE (operands
[1]))
12830 if (low_io_address_operand (operands
[1], QImode
))
12833 output_asm_insn ("sbis %i1,%2", operands
);
12835 output_asm_insn ("sbic %i1,%2", operands
);
12839 gcc_assert (io_address_operand (operands
[1], QImode
));
12840 output_asm_insn ("in __tmp_reg__,%i1", operands
);
12842 output_asm_insn ("sbrs __tmp_reg__,%2", operands
);
12844 output_asm_insn ("sbrc __tmp_reg__,%2", operands
);
12847 break; /* CONST_INT */
12852 output_asm_insn ("sbrs %T1%T2", operands
);
12854 output_asm_insn ("sbrc %T1%T2", operands
);
12860 return ("rjmp .+4" CR_TAB
12869 /* Worker function for `TARGET_ASM_CONSTRUCTOR'. */
12872 avr_asm_out_ctor (rtx symbol
, int priority
)
12874 fputs ("\t.global __do_global_ctors\n", asm_out_file
);
12875 default_ctor_section_asm_out_constructor (symbol
, priority
);
12879 /* Worker function for `TARGET_ASM_DESTRUCTOR'. */
12882 avr_asm_out_dtor (rtx symbol
, int priority
)
12884 fputs ("\t.global __do_global_dtors\n", asm_out_file
);
12885 default_dtor_section_asm_out_destructor (symbol
, priority
);
12889 /* Worker function for `TARGET_RETURN_IN_MEMORY'. */
12892 avr_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
12894 HOST_WIDE_INT size
= int_size_in_bytes (type
);
12895 HOST_WIDE_INT ret_size_limit
= AVR_TINY
? 4 : 8;
12897 /* In avr, there are 8 return registers. But, for Tiny Core
12898 (ATtiny4/5/9/10/20/40) devices, only 4 registers are available.
12899 Return true if size is unknown or greater than the limit. */
12901 if (size
== -1 || size
> ret_size_limit
)
12912 /* Implement `CASE_VALUES_THRESHOLD'. */
12913 /* Supply the default for --param case-values-threshold=0 */
12915 static unsigned int
12916 avr_case_values_threshold (void)
12918 /* The exact break-even point between a jump table and an if-else tree
12919 depends on several factors not available here like, e.g. if 8-bit
12920 comparisons can be used in the if-else tree or not, on the
12921 range of the case values, if the case value can be reused, on the
12922 register allocation, etc. '7' appears to be a good choice. */
12928 /* Implement `TARGET_ADDR_SPACE_ADDRESS_MODE'. */
12930 static scalar_int_mode
12931 avr_addr_space_address_mode (addr_space_t as
)
12933 return avr_addrspace
[as
].pointer_size
== 3 ? PSImode
: HImode
;
12937 /* Implement `TARGET_ADDR_SPACE_POINTER_MODE'. */
12939 static scalar_int_mode
12940 avr_addr_space_pointer_mode (addr_space_t as
)
12942 return avr_addr_space_address_mode (as
);
12946 /* Helper for following function. */
12949 avr_reg_ok_for_pgm_addr (rtx reg
, bool strict
)
12951 gcc_assert (REG_P (reg
));
12955 return REGNO (reg
) == REG_Z
;
12958 /* Avoid combine to propagate hard regs. */
12960 if (can_create_pseudo_p()
12961 && REGNO (reg
) < REG_Z
)
12970 /* Implement `TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P'. */
12973 avr_addr_space_legitimate_address_p (machine_mode mode
, rtx x
,
12974 bool strict
, addr_space_t as
)
12983 case ADDR_SPACE_GENERIC
:
12984 return avr_legitimate_address_p (mode
, x
, strict
);
12986 case ADDR_SPACE_FLASH
:
12987 case ADDR_SPACE_FLASH1
:
12988 case ADDR_SPACE_FLASH2
:
12989 case ADDR_SPACE_FLASH3
:
12990 case ADDR_SPACE_FLASH4
:
12991 case ADDR_SPACE_FLASH5
:
12993 switch (GET_CODE (x
))
12996 ok
= avr_reg_ok_for_pgm_addr (x
, strict
);
13000 ok
= avr_reg_ok_for_pgm_addr (XEXP (x
, 0), strict
);
13009 case ADDR_SPACE_MEMX
:
13012 && can_create_pseudo_p());
13014 if (LO_SUM
== GET_CODE (x
))
13016 rtx hi
= XEXP (x
, 0);
13017 rtx lo
= XEXP (x
, 1);
13020 && (!strict
|| REGNO (hi
) < FIRST_PSEUDO_REGISTER
)
13022 && REGNO (lo
) == REG_Z
);
13028 if (avr_log
.legitimate_address_p
)
13030 avr_edump ("\n%?: ret=%b, mode=%m strict=%d "
13031 "reload_completed=%d reload_in_progress=%d %s:",
13032 ok
, mode
, strict
, reload_completed
, reload_in_progress
,
13033 reg_renumber
? "(reg_renumber)" : "");
13035 if (GET_CODE (x
) == PLUS
13036 && REG_P (XEXP (x
, 0))
13037 && CONST_INT_P (XEXP (x
, 1))
13038 && IN_RANGE (INTVAL (XEXP (x
, 1)), 0, MAX_LD_OFFSET (mode
))
13041 avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x
, 0)),
13042 true_regnum (XEXP (x
, 0)));
13045 avr_edump ("\n%r\n", x
);
13052 /* Implement `TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS'. */
13055 avr_addr_space_legitimize_address (rtx x
, rtx old_x
,
13056 machine_mode mode
, addr_space_t as
)
13058 if (ADDR_SPACE_GENERIC_P (as
))
13059 return avr_legitimize_address (x
, old_x
, mode
);
13061 if (avr_log
.legitimize_address
)
13063 avr_edump ("\n%?: mode=%m\n %r\n", mode
, old_x
);
13070 /* Implement `TARGET_ADDR_SPACE_CONVERT'. */
13073 avr_addr_space_convert (rtx src
, tree type_from
, tree type_to
)
13075 addr_space_t as_from
= TYPE_ADDR_SPACE (TREE_TYPE (type_from
));
13076 addr_space_t as_to
= TYPE_ADDR_SPACE (TREE_TYPE (type_to
));
13078 if (avr_log
.progmem
)
13079 avr_edump ("\n%!: op = %r\nfrom = %t\nto = %t\n",
13080 src
, type_from
, type_to
);
13082 /* Up-casting from 16-bit to 24-bit pointer. */
13084 if (as_from
!= ADDR_SPACE_MEMX
13085 && as_to
== ADDR_SPACE_MEMX
)
13089 rtx reg
= gen_reg_rtx (PSImode
);
13091 while (CONST
== GET_CODE (sym
) || PLUS
== GET_CODE (sym
))
13092 sym
= XEXP (sym
, 0);
13094 /* Look at symbol flags: avr_encode_section_info set the flags
13095 also if attribute progmem was seen so that we get the right
13096 promotion for, e.g. PSTR-like strings that reside in generic space
13097 but are located in flash. In that case we patch the incoming
13100 if (SYMBOL_REF_P (sym
)
13101 && ADDR_SPACE_FLASH
== AVR_SYMBOL_GET_ADDR_SPACE (sym
))
13103 as_from
= ADDR_SPACE_FLASH
;
13106 /* Linearize memory: RAM has bit 23 set. */
13108 msb
= ADDR_SPACE_GENERIC_P (as_from
)
13110 : avr_addrspace
[as_from
].segment
;
13112 src
= force_reg (Pmode
, src
);
13114 emit_insn (msb
== 0
13115 ? gen_zero_extendhipsi2 (reg
, src
)
13116 : gen_n_extendhipsi2 (reg
, gen_int_mode (msb
, QImode
), src
));
13121 /* Down-casting from 24-bit to 16-bit throws away the high byte. */
13123 if (as_from
== ADDR_SPACE_MEMX
13124 && as_to
!= ADDR_SPACE_MEMX
)
13126 rtx new_src
= gen_reg_rtx (Pmode
);
13128 src
= force_reg (PSImode
, src
);
13130 emit_move_insn (new_src
,
13131 simplify_gen_subreg (Pmode
, src
, PSImode
, 0));
13139 /* Implement `TARGET_ADDR_SPACE_SUBSET_P'. */
13142 avr_addr_space_subset_p (addr_space_t subset ATTRIBUTE_UNUSED
,
13143 addr_space_t superset ATTRIBUTE_UNUSED
)
13145 /* Allow any kind of pointer mess. */
13151 /* Implement `TARGET_CONVERT_TO_TYPE'. */
13154 avr_convert_to_type (tree type
, tree expr
)
13156 /* Print a diagnose for pointer conversion that changes the address
13157 space of the pointer target to a non-enclosing address space,
13158 provided -Waddr-space-convert is on.
13160 FIXME: Filter out cases where the target object is known to
13161 be located in the right memory, like in
13163 (const __flash*) PSTR ("text")
13165 Also try to distinguish between explicit casts requested by
13166 the user and implicit casts like
13168 void f (const __flash char*);
13170 void g (const char *p)
13172 f ((const __flash*) p);
13175 under the assumption that an explicit casts means that the user
13176 knows what he is doing, e.g. interface with PSTR or old style
13177 code with progmem and pgm_read_xxx.
13180 if (avr_warn_addr_space_convert
13181 && expr
!= error_mark_node
13182 && POINTER_TYPE_P (type
)
13183 && POINTER_TYPE_P (TREE_TYPE (expr
)))
13185 addr_space_t as_old
= TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (expr
)));
13186 addr_space_t as_new
= TYPE_ADDR_SPACE (TREE_TYPE (type
));
13188 if (avr_log
.progmem
)
13189 avr_edump ("%?: type = %t\nexpr = %t\n\n", type
, expr
);
13191 if (as_new
!= ADDR_SPACE_MEMX
13192 && as_new
!= as_old
)
13194 location_t loc
= EXPR_LOCATION (expr
);
13195 const char *name_old
= avr_addrspace
[as_old
].name
;
13196 const char *name_new
= avr_addrspace
[as_new
].name
;
13198 warning (OPT_Waddr_space_convert
,
13199 "conversion from address space %qs to address space %qs",
13200 ADDR_SPACE_GENERIC_P (as_old
) ? "generic" : name_old
,
13201 ADDR_SPACE_GENERIC_P (as_new
) ? "generic" : name_new
);
13203 return fold_build1_loc (loc
, ADDR_SPACE_CONVERT_EXPR
, type
, expr
);
13211 /* Implement `TARGET_LEGITIMATE_COMBINED_INSN'. */
13213 /* PR78883: Filter out paradoxical SUBREGs of MEM which are not handled
13214 properly by following passes. As INSN_SCHEDULING is off and hence
13215 general_operand accepts such expressions, ditch them now. */
13218 avr_legitimate_combined_insn (rtx_insn
*insn
)
13220 subrtx_iterator::array_type array
;
13222 FOR_EACH_SUBRTX (iter
, array
, PATTERN (insn
), NONCONST
)
13224 const_rtx op
= *iter
;
13227 && MEM_P (SUBREG_REG (op
))
13228 && (GET_MODE_SIZE (GET_MODE (op
))
13229 > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op
)))))
13239 /* PR63633: The middle-end might come up with hard regs as input operands.
13241 RMASK is a bit mask representing a subset of hard registers R0...R31:
13242 Rn is an element of that set iff bit n of RMASK is set.
13243 OPMASK describes a subset of OP[]: If bit n of OPMASK is 1 then
13244 OP[n] has to be fixed; otherwise OP[n] is left alone.
13246 For each element of OPMASK which is a hard register overlapping RMASK,
13247 replace OP[n] with a newly created pseudo register
13249 HREG == 0: Also emit a move insn that copies the contents of that
13250 hard register into the new pseudo.
13252 HREG != 0: Also set HREG[n] to the hard register. */
13255 avr_fix_operands (rtx
*op
, rtx
*hreg
, unsigned opmask
, unsigned rmask
)
13257 for (; opmask
; opmask
>>= 1, op
++)
13266 && REGNO (reg
) < FIRST_PSEUDO_REGISTER
13267 // This hard-reg overlaps other prohibited hard regs?
13268 && (rmask
& regmask (GET_MODE (reg
), REGNO (reg
))))
13270 *op
= gen_reg_rtx (GET_MODE (reg
));
13272 emit_move_insn (*op
, reg
);
13284 avr_fix_inputs (rtx
*op
, unsigned opmask
, unsigned rmask
)
13286 avr_fix_operands (op
, NULL
, opmask
, rmask
);
13290 /* Helper for the function below: If bit n of MASK is set and
13291 HREG[n] != NULL, then emit a move insn to copy OP[n] to HREG[n].
13292 Otherwise do nothing for that n. Return TRUE. */
13295 avr_move_fixed_operands (rtx
*op
, rtx
*hreg
, unsigned mask
)
13297 for (; mask
; mask
>>= 1, op
++, hreg
++)
13300 emit_move_insn (*hreg
, *op
);
13306 /* PR63633: The middle-end might come up with hard regs as output operands.
13308 GEN is a sequence generating function like gen_mulsi3 with 3 operands OP[].
13309 RMASK is a bit mask representing a subset of hard registers R0...R31:
13310 Rn is an element of that set iff bit n of RMASK is set.
13311 OPMASK describes a subset of OP[]: If bit n of OPMASK is 1 then
13312 OP[n] has to be fixed; otherwise OP[n] is left alone.
13314 Emit the insn sequence as generated by GEN() with all elements of OPMASK
13315 which are hard registers overlapping RMASK replaced by newly created
13316 pseudo registers. After the sequence has been emitted, emit insns that
13317 move the contents of respective pseudos to their hard regs. */
13320 avr_emit3_fix_outputs (rtx (*gen
)(rtx
,rtx
,rtx
), rtx
*op
,
13321 unsigned opmask
, unsigned rmask
)
13326 /* It is letigimate for GEN to call this function, and in order not to
13327 get self-recursive we use the following static kludge. This is the
13328 only way not to duplicate all expanders and to avoid ugly and
13329 hard-to-maintain C-code instead of the much more appreciated RTL
13330 representation as supplied by define_expand. */
13331 static bool lock
= false;
13333 gcc_assert (opmask
< (1u << n
));
13338 avr_fix_operands (op
, hreg
, opmask
, rmask
);
13341 emit_insn (gen (op
[0], op
[1], op
[2]));
13344 return avr_move_fixed_operands (op
, hreg
, opmask
);
13348 /* Worker function for movmemhi expander.
13349 XOP[0] Destination as MEM:BLK
13351 XOP[2] # Bytes to copy
13353 Return TRUE if the expansion is accomplished.
13354 Return FALSE if the operand compination is not supported. */
13357 avr_emit_movmemhi (rtx
*xop
)
13359 HOST_WIDE_INT count
;
13360 machine_mode loop_mode
;
13361 addr_space_t as
= MEM_ADDR_SPACE (xop
[1]);
13362 rtx loop_reg
, addr1
, a_src
, a_dest
, insn
, xas
;
13363 rtx a_hi8
= NULL_RTX
;
13365 if (avr_mem_flash_p (xop
[0]))
13368 if (!CONST_INT_P (xop
[2]))
13371 count
= INTVAL (xop
[2]);
13375 a_src
= XEXP (xop
[1], 0);
13376 a_dest
= XEXP (xop
[0], 0);
13378 if (PSImode
== GET_MODE (a_src
))
13380 gcc_assert (as
== ADDR_SPACE_MEMX
);
13382 loop_mode
= (count
< 0x100) ? QImode
: HImode
;
13383 loop_reg
= gen_rtx_REG (loop_mode
, 24);
13384 emit_move_insn (loop_reg
, gen_int_mode (count
, loop_mode
));
13386 addr1
= simplify_gen_subreg (HImode
, a_src
, PSImode
, 0);
13387 a_hi8
= simplify_gen_subreg (QImode
, a_src
, PSImode
, 2);
13391 int segment
= avr_addrspace
[as
].segment
;
13394 && avr_n_flash
> 1)
13396 a_hi8
= GEN_INT (segment
);
13397 emit_move_insn (rampz_rtx
, a_hi8
= copy_to_mode_reg (QImode
, a_hi8
));
13399 else if (!ADDR_SPACE_GENERIC_P (as
))
13401 as
= ADDR_SPACE_FLASH
;
13406 loop_mode
= (count
<= 0x100) ? QImode
: HImode
;
13407 loop_reg
= copy_to_mode_reg (loop_mode
, gen_int_mode (count
, loop_mode
));
13410 xas
= GEN_INT (as
);
13412 /* FIXME: Register allocator might come up with spill fails if it is left
13413 on its own. Thus, we allocate the pointer registers by hand:
13415 X = destination address */
13417 emit_move_insn (lpm_addr_reg_rtx
, addr1
);
13418 emit_move_insn (gen_rtx_REG (HImode
, REG_X
), a_dest
);
13420 /* FIXME: Register allocator does a bad job and might spill address
13421 register(s) inside the loop leading to additional move instruction
13422 to/from stack which could clobber tmp_reg. Thus, do *not* emit
13423 load and store as separate insns. Instead, we perform the copy
13424 by means of one monolithic insn. */
13426 gcc_assert (TMP_REGNO
== LPM_REGNO
);
13428 if (as
!= ADDR_SPACE_MEMX
)
13430 /* Load instruction ([E]LPM or LD) is known at compile time:
13431 Do the copy-loop inline. */
13433 rtx (*fun
) (rtx
, rtx
, rtx
)
13434 = QImode
== loop_mode
? gen_movmem_qi
: gen_movmem_hi
;
13436 insn
= fun (xas
, loop_reg
, loop_reg
);
13440 rtx (*fun
) (rtx
, rtx
)
13441 = QImode
== loop_mode
? gen_movmemx_qi
: gen_movmemx_hi
;
13443 emit_move_insn (gen_rtx_REG (QImode
, 23), a_hi8
);
13445 insn
= fun (xas
, GEN_INT (avr_addr
.rampz
));
13448 set_mem_addr_space (SET_SRC (XVECEXP (insn
, 0, 0)), as
);
13455 /* Print assembler for movmem_qi, movmem_hi insns...
13457 $1, $2 : Loop register
13459 X : Destination address
13463 avr_out_movmem (rtx_insn
*insn ATTRIBUTE_UNUSED
, rtx
*op
, int *plen
)
13465 addr_space_t as
= (addr_space_t
) INTVAL (op
[0]);
13466 machine_mode loop_mode
= GET_MODE (op
[1]);
13467 bool sbiw_p
= test_hard_reg_class (ADDW_REGS
, op
[1]);
13475 xop
[2] = tmp_reg_rtx
;
13479 avr_asm_len ("0:", xop
, plen
, 0);
13481 /* Load with post-increment */
13488 case ADDR_SPACE_GENERIC
:
13490 avr_asm_len ("ld %2,Z+", xop
, plen
, 1);
13493 case ADDR_SPACE_FLASH
:
13496 avr_asm_len ("lpm %2,Z+", xop
, plen
, 1);
13498 avr_asm_len ("lpm" CR_TAB
13499 "adiw r30,1", xop
, plen
, 2);
13502 case ADDR_SPACE_FLASH1
:
13503 case ADDR_SPACE_FLASH2
:
13504 case ADDR_SPACE_FLASH3
:
13505 case ADDR_SPACE_FLASH4
:
13506 case ADDR_SPACE_FLASH5
:
13508 if (AVR_HAVE_ELPMX
)
13509 avr_asm_len ("elpm %2,Z+", xop
, plen
, 1);
13511 avr_asm_len ("elpm" CR_TAB
13512 "adiw r30,1", xop
, plen
, 2);
13516 /* Store with post-increment */
13518 avr_asm_len ("st X+,%2", xop
, plen
, 1);
13520 /* Decrement loop-counter and set Z-flag */
13522 if (QImode
== loop_mode
)
13524 avr_asm_len ("dec %1", xop
, plen
, 1);
13528 avr_asm_len ("sbiw %1,1", xop
, plen
, 1);
13532 avr_asm_len ("subi %A1,1" CR_TAB
13533 "sbci %B1,0", xop
, plen
, 2);
13536 /* Loop until zero */
13538 return avr_asm_len ("brne 0b", xop
, plen
, 1);
13543 /* Helper for __builtin_avr_delay_cycles */
13546 avr_mem_clobber (void)
13548 rtx mem
= gen_rtx_MEM (BLKmode
, gen_rtx_SCRATCH (Pmode
));
13549 MEM_VOLATILE_P (mem
) = 1;
13554 avr_expand_delay_cycles (rtx operands0
)
13556 unsigned HOST_WIDE_INT cycles
= UINTVAL (operands0
) & GET_MODE_MASK (SImode
);
13557 unsigned HOST_WIDE_INT cycles_used
;
13558 unsigned HOST_WIDE_INT loop_count
;
13560 if (IN_RANGE (cycles
, 83886082, 0xFFFFFFFF))
13562 loop_count
= ((cycles
- 9) / 6) + 1;
13563 cycles_used
= ((loop_count
- 1) * 6) + 9;
13564 emit_insn (gen_delay_cycles_4 (gen_int_mode (loop_count
, SImode
),
13565 avr_mem_clobber()));
13566 cycles
-= cycles_used
;
13569 if (IN_RANGE (cycles
, 262145, 83886081))
13571 loop_count
= ((cycles
- 7) / 5) + 1;
13572 if (loop_count
> 0xFFFFFF)
13573 loop_count
= 0xFFFFFF;
13574 cycles_used
= ((loop_count
- 1) * 5) + 7;
13575 emit_insn (gen_delay_cycles_3 (gen_int_mode (loop_count
, SImode
),
13576 avr_mem_clobber()));
13577 cycles
-= cycles_used
;
13580 if (IN_RANGE (cycles
, 768, 262144))
13582 loop_count
= ((cycles
- 5) / 4) + 1;
13583 if (loop_count
> 0xFFFF)
13584 loop_count
= 0xFFFF;
13585 cycles_used
= ((loop_count
- 1) * 4) + 5;
13586 emit_insn (gen_delay_cycles_2 (gen_int_mode (loop_count
, HImode
),
13587 avr_mem_clobber()));
13588 cycles
-= cycles_used
;
13591 if (IN_RANGE (cycles
, 6, 767))
13593 loop_count
= cycles
/ 3;
13594 if (loop_count
> 255)
13596 cycles_used
= loop_count
* 3;
13597 emit_insn (gen_delay_cycles_1 (gen_int_mode (loop_count
, QImode
),
13598 avr_mem_clobber()));
13599 cycles
-= cycles_used
;
13602 while (cycles
>= 2)
13604 emit_insn (gen_nopv (GEN_INT (2)));
13610 emit_insn (gen_nopv (GEN_INT (1)));
13617 avr_expand_nops (rtx operands0
)
13619 unsigned HOST_WIDE_INT n_nops
= UINTVAL (operands0
) & GET_MODE_MASK (HImode
);
13623 emit_insn (gen_nopv (const1_rtx
));
13628 /* Compute the image of x under f, i.e. perform x --> f(x) */
13631 avr_map (unsigned int f
, int x
)
13633 return x
< 8 ? (f
>> (4 * x
)) & 0xf : 0;
13637 /* Return some metrics of map A. */
13641 /* Number of fixed points in { 0 ... 7 } */
13644 /* Size of preimage of non-fixed points in { 0 ... 7 } */
13647 /* Mask representing the fixed points in { 0 ... 7 } */
13648 MAP_MASK_FIXED_0_7
,
13650 /* Size of the preimage of { 0 ... 7 } */
13653 /* Mask that represents the preimage of { f } */
13654 MAP_MASK_PREIMAGE_F
13658 avr_map_metric (unsigned int a
, int mode
)
13660 unsigned metric
= 0;
13662 for (unsigned i
= 0; i
< 8; i
++)
13664 unsigned ai
= avr_map (a
, i
);
13666 if (mode
== MAP_FIXED_0_7
)
13668 else if (mode
== MAP_NONFIXED_0_7
)
13669 metric
+= ai
< 8 && ai
!= i
;
13670 else if (mode
== MAP_MASK_FIXED_0_7
)
13671 metric
|= ((unsigned) (ai
== i
)) << i
;
13672 else if (mode
== MAP_PREIMAGE_0_7
)
13674 else if (mode
== MAP_MASK_PREIMAGE_F
)
13675 metric
|= ((unsigned) (ai
== 0xf)) << i
;
13684 /* Return true if IVAL has a 0xf in its hexadecimal representation
13685 and false, otherwise. Only nibbles 0..7 are taken into account.
13686 Used as constraint helper for C0f and Cxf. */
13689 avr_has_nibble_0xf (rtx ival
)
13691 unsigned int map
= UINTVAL (ival
) & GET_MODE_MASK (SImode
);
13692 return 0 != avr_map_metric (map
, MAP_MASK_PREIMAGE_F
);
13696 /* We have a set of bits that are mapped by a function F.
13697 Try to decompose F by means of a second function G so that
13703 cost (F o G^-1) + cost (G) < cost (F)
13705 Example: Suppose builtin insert_bits supplies us with the map
13706 F = 0x3210ffff. Instead of doing 4 bit insertions to get the high
13707 nibble of the result, we can just as well rotate the bits before inserting
13708 them and use the map 0x7654ffff which is cheaper than the original map.
13709 For this example G = G^-1 = 0x32107654 and F o G^-1 = 0x7654ffff. */
13713 /* tree code of binary function G */
13714 enum tree_code code
;
13716 /* The constant second argument of G */
13719 /* G^-1, the inverse of G (*, arg) */
13722 /* The cost of applying G (*, arg) */
13725 /* The composition F o G^-1 (*, arg) for some function F */
13728 /* For debug purpose only */
13732 static const avr_map_op_t avr_map_op
[] =
13734 { LROTATE_EXPR
, 0, 0x76543210, 0, 0, "id" },
13735 { LROTATE_EXPR
, 1, 0x07654321, 2, 0, "<<<" },
13736 { LROTATE_EXPR
, 2, 0x10765432, 4, 0, "<<<" },
13737 { LROTATE_EXPR
, 3, 0x21076543, 4, 0, "<<<" },
13738 { LROTATE_EXPR
, 4, 0x32107654, 1, 0, "<<<" },
13739 { LROTATE_EXPR
, 5, 0x43210765, 3, 0, "<<<" },
13740 { LROTATE_EXPR
, 6, 0x54321076, 5, 0, "<<<" },
13741 { LROTATE_EXPR
, 7, 0x65432107, 3, 0, "<<<" },
13742 { RSHIFT_EXPR
, 1, 0x6543210c, 1, 0, ">>" },
13743 { RSHIFT_EXPR
, 1, 0x7543210c, 1, 0, ">>" },
13744 { RSHIFT_EXPR
, 2, 0x543210cc, 2, 0, ">>" },
13745 { RSHIFT_EXPR
, 2, 0x643210cc, 2, 0, ">>" },
13746 { RSHIFT_EXPR
, 2, 0x743210cc, 2, 0, ">>" },
13747 { LSHIFT_EXPR
, 1, 0xc7654321, 1, 0, "<<" },
13748 { LSHIFT_EXPR
, 2, 0xcc765432, 2, 0, "<<" }
13752 /* Try to decompose F as F = (F o G^-1) o G as described above.
13753 The result is a struct representing F o G^-1 and G.
13754 If result.cost < 0 then such a decomposition does not exist. */
13756 static avr_map_op_t
13757 avr_map_decompose (unsigned int f
, const avr_map_op_t
*g
, bool val_const_p
)
13759 bool val_used_p
= 0 != avr_map_metric (f
, MAP_MASK_PREIMAGE_F
);
13760 avr_map_op_t f_ginv
= *g
;
13761 unsigned int ginv
= g
->ginv
;
13765 /* Step 1: Computing F o G^-1 */
13767 for (int i
= 7; i
>= 0; i
--)
13769 int x
= avr_map (f
, i
);
13773 x
= avr_map (ginv
, x
);
13775 /* The bit is no element of the image of G: no avail (cost = -1) */
13781 f_ginv
.map
= (f_ginv
.map
<< 4) + x
;
13784 /* Step 2: Compute the cost of the operations.
13785 The overall cost of doing an operation prior to the insertion is
13786 the cost of the insertion plus the cost of the operation. */
13788 /* Step 2a: Compute cost of F o G^-1 */
13790 if (0 == avr_map_metric (f_ginv
.map
, MAP_NONFIXED_0_7
))
13792 /* The mapping consists only of fixed points and can be folded
13793 to AND/OR logic in the remainder. Reasonable cost is 3. */
13795 f_ginv
.cost
= 2 + (val_used_p
&& !val_const_p
);
13801 /* Get the cost of the insn by calling the output worker with some
13802 fake values. Mimic effect of reloading xop[3]: Unused operands
13803 are mapped to 0 and used operands are reloaded to xop[0]. */
13805 xop
[0] = all_regs_rtx
[24];
13806 xop
[1] = gen_int_mode (f_ginv
.map
, SImode
);
13807 xop
[2] = all_regs_rtx
[25];
13808 xop
[3] = val_used_p
? xop
[0] : const0_rtx
;
13810 avr_out_insert_bits (xop
, &f_ginv
.cost
);
13812 f_ginv
.cost
+= val_const_p
&& val_used_p
? 1 : 0;
13815 /* Step 2b: Add cost of G */
13817 f_ginv
.cost
+= g
->cost
;
13819 if (avr_log
.builtin
)
13820 avr_edump (" %s%d=%d", g
->str
, g
->arg
, f_ginv
.cost
);
13826 /* Insert bits from XOP[1] into XOP[0] according to MAP.
13827 XOP[0] and XOP[1] don't overlap.
13828 If FIXP_P = true: Move all bits according to MAP using BLD/BST sequences.
13829 If FIXP_P = false: Just move the bit if its position in the destination
13830 is different to its source position. */
13833 avr_move_bits (rtx
*xop
, unsigned int map
, bool fixp_p
, int *plen
)
13835 /* T-flag contains this bit of the source, i.e. of XOP[1] */
13836 int t_bit_src
= -1;
13838 /* We order the operations according to the requested source bit b. */
13840 for (int b
= 0; b
< 8; b
++)
13841 for (int bit_dest
= 0; bit_dest
< 8; bit_dest
++)
13843 int bit_src
= avr_map (map
, bit_dest
);
13847 /* Same position: No need to copy as requested by FIXP_P. */
13848 || (bit_dest
== bit_src
&& !fixp_p
))
13851 if (t_bit_src
!= bit_src
)
13853 /* Source bit is not yet in T: Store it to T. */
13855 t_bit_src
= bit_src
;
13857 xop
[3] = GEN_INT (bit_src
);
13858 avr_asm_len ("bst %T1%T3", xop
, plen
, 1);
13861 /* Load destination bit with T. */
13863 xop
[3] = GEN_INT (bit_dest
);
13864 avr_asm_len ("bld %T0%T3", xop
, plen
, 1);
13869 /* PLEN == 0: Print assembler code for `insert_bits'.
13870 PLEN != 0: Compute code length in bytes.
13873 OP[1]: The mapping composed of nibbles. If nibble no. N is
13874 0: Bit N of result is copied from bit OP[2].0
13876 7: Bit N of result is copied from bit OP[2].7
13877 0xf: Bit N of result is copied from bit OP[3].N
13878 OP[2]: Bits to be inserted
13879 OP[3]: Target value */
13882 avr_out_insert_bits (rtx
*op
, int *plen
)
13884 unsigned int map
= UINTVAL (op
[1]) & GET_MODE_MASK (SImode
);
13885 unsigned mask_fixed
;
13886 bool fixp_p
= true;
13893 gcc_assert (REG_P (xop
[2]) || CONST_INT_P (xop
[2]));
13897 else if (flag_print_asm_name
)
13898 fprintf (asm_out_file
, ASM_COMMENT_START
"map = 0x%08x\n", map
);
13900 /* If MAP has fixed points it might be better to initialize the result
13901 with the bits to be inserted instead of moving all bits by hand. */
13903 mask_fixed
= avr_map_metric (map
, MAP_MASK_FIXED_0_7
);
13905 if (REGNO (xop
[0]) == REGNO (xop
[1]))
13907 /* Avoid early-clobber conflicts */
13909 avr_asm_len ("mov __tmp_reg__,%1", xop
, plen
, 1);
13910 xop
[1] = tmp_reg_rtx
;
13914 if (avr_map_metric (map
, MAP_MASK_PREIMAGE_F
))
13916 /* XOP[2] is used and reloaded to XOP[0] already */
13918 int n_fix
= 0, n_nofix
= 0;
13920 gcc_assert (REG_P (xop
[2]));
13922 /* Get the code size of the bit insertions; once with all bits
13923 moved and once with fixed points omitted. */
13925 avr_move_bits (xop
, map
, true, &n_fix
);
13926 avr_move_bits (xop
, map
, false, &n_nofix
);
13928 if (fixp_p
&& n_fix
- n_nofix
> 3)
13930 xop
[3] = gen_int_mode (~mask_fixed
, QImode
);
13932 avr_asm_len ("eor %0,%1" CR_TAB
13933 "andi %0,%3" CR_TAB
13934 "eor %0,%1", xop
, plen
, 3);
13940 /* XOP[2] is unused */
13942 if (fixp_p
&& mask_fixed
)
13944 avr_asm_len ("mov %0,%1", xop
, plen
, 1);
13949 /* Move/insert remaining bits. */
13951 avr_move_bits (xop
, map
, fixp_p
, plen
);
13957 /* IDs for all the AVR builtins. */
13959 enum avr_builtin_id
13961 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
13962 AVR_BUILTIN_ ## NAME,
13963 #include "builtins.def"
13969 struct GTY(()) avr_builtin_description
13971 enum insn_code icode
;
13977 /* Notice that avr_bdesc[] and avr_builtin_id are initialized in such a way
13978 that a built-in's ID can be used to access the built-in by means of
13981 static GTY(()) struct avr_builtin_description
13982 avr_bdesc
[AVR_BUILTIN_COUNT
] =
13984 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE, LIBNAME) \
13985 { (enum insn_code) CODE_FOR_ ## ICODE, N_ARGS, NULL_TREE },
13986 #include "builtins.def"
13991 /* Implement `TARGET_BUILTIN_DECL'. */
13994 avr_builtin_decl (unsigned id
, bool initialize_p ATTRIBUTE_UNUSED
)
13996 if (id
< AVR_BUILTIN_COUNT
)
13997 return avr_bdesc
[id
].fndecl
;
13999 return error_mark_node
;
14004 avr_init_builtin_int24 (void)
14006 tree int24_type
= make_signed_type (GET_MODE_BITSIZE (PSImode
));
14007 tree uint24_type
= make_unsigned_type (GET_MODE_BITSIZE (PSImode
));
14009 lang_hooks
.types
.register_builtin_type (int24_type
, "__int24");
14010 lang_hooks
.types
.register_builtin_type (uint24_type
, "__uint24");
14014 /* Implement `TARGET_INIT_BUILTINS' */
14015 /* Set up all builtin functions for this target. */
14018 avr_init_builtins (void)
14020 tree void_ftype_void
14021 = build_function_type_list (void_type_node
, NULL_TREE
);
14022 tree uchar_ftype_uchar
14023 = build_function_type_list (unsigned_char_type_node
,
14024 unsigned_char_type_node
,
14026 tree uint_ftype_uchar_uchar
14027 = build_function_type_list (unsigned_type_node
,
14028 unsigned_char_type_node
,
14029 unsigned_char_type_node
,
14031 tree int_ftype_char_char
14032 = build_function_type_list (integer_type_node
,
14036 tree int_ftype_char_uchar
14037 = build_function_type_list (integer_type_node
,
14039 unsigned_char_type_node
,
14041 tree void_ftype_ulong
14042 = build_function_type_list (void_type_node
,
14043 long_unsigned_type_node
,
14046 tree uchar_ftype_ulong_uchar_uchar
14047 = build_function_type_list (unsigned_char_type_node
,
14048 long_unsigned_type_node
,
14049 unsigned_char_type_node
,
14050 unsigned_char_type_node
,
14053 tree const_memx_void_node
14054 = build_qualified_type (void_type_node
,
14056 | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_MEMX
));
14058 tree const_memx_ptr_type_node
14059 = build_pointer_type_for_mode (const_memx_void_node
, PSImode
, false);
14061 tree char_ftype_const_memx_ptr
14062 = build_function_type_list (char_type_node
,
14063 const_memx_ptr_type_node
,
14067 lang_hooks.types.type_for_size (TYPE_PRECISION (T), TYPE_UNSIGNED (T))
14069 #define FX_FTYPE_FX(fx) \
14070 tree fx##r_ftype_##fx##r \
14071 = build_function_type_list (node_##fx##r, node_##fx##r, NULL); \
14072 tree fx##k_ftype_##fx##k \
14073 = build_function_type_list (node_##fx##k, node_##fx##k, NULL)
14075 #define FX_FTYPE_FX_INT(fx) \
14076 tree fx##r_ftype_##fx##r_int \
14077 = build_function_type_list (node_##fx##r, node_##fx##r, \
14078 integer_type_node, NULL); \
14079 tree fx##k_ftype_##fx##k_int \
14080 = build_function_type_list (node_##fx##k, node_##fx##k, \
14081 integer_type_node, NULL)
14083 #define INT_FTYPE_FX(fx) \
14084 tree int_ftype_##fx##r \
14085 = build_function_type_list (integer_type_node, node_##fx##r, NULL); \
14086 tree int_ftype_##fx##k \
14087 = build_function_type_list (integer_type_node, node_##fx##k, NULL)
14089 #define INTX_FTYPE_FX(fx) \
14090 tree int##fx##r_ftype_##fx##r \
14091 = build_function_type_list (ITYP (node_##fx##r), node_##fx##r, NULL); \
14092 tree int##fx##k_ftype_##fx##k \
14093 = build_function_type_list (ITYP (node_##fx##k), node_##fx##k, NULL)
14095 #define FX_FTYPE_INTX(fx) \
14096 tree fx##r_ftype_int##fx##r \
14097 = build_function_type_list (node_##fx##r, ITYP (node_##fx##r), NULL); \
14098 tree fx##k_ftype_int##fx##k \
14099 = build_function_type_list (node_##fx##k, ITYP (node_##fx##k), NULL)
14101 tree node_hr
= short_fract_type_node
;
14102 tree node_nr
= fract_type_node
;
14103 tree node_lr
= long_fract_type_node
;
14104 tree node_llr
= long_long_fract_type_node
;
14106 tree node_uhr
= unsigned_short_fract_type_node
;
14107 tree node_unr
= unsigned_fract_type_node
;
14108 tree node_ulr
= unsigned_long_fract_type_node
;
14109 tree node_ullr
= unsigned_long_long_fract_type_node
;
14111 tree node_hk
= short_accum_type_node
;
14112 tree node_nk
= accum_type_node
;
14113 tree node_lk
= long_accum_type_node
;
14114 tree node_llk
= long_long_accum_type_node
;
14116 tree node_uhk
= unsigned_short_accum_type_node
;
14117 tree node_unk
= unsigned_accum_type_node
;
14118 tree node_ulk
= unsigned_long_accum_type_node
;
14119 tree node_ullk
= unsigned_long_long_accum_type_node
;
14122 /* For absfx builtins. */
14129 /* For roundfx builtins. */
14131 FX_FTYPE_FX_INT (h
);
14132 FX_FTYPE_FX_INT (n
);
14133 FX_FTYPE_FX_INT (l
);
14134 FX_FTYPE_FX_INT (ll
);
14136 FX_FTYPE_FX_INT (uh
);
14137 FX_FTYPE_FX_INT (un
);
14138 FX_FTYPE_FX_INT (ul
);
14139 FX_FTYPE_FX_INT (ull
);
14141 /* For countlsfx builtins. */
14151 INT_FTYPE_FX (ull
);
14153 /* For bitsfx builtins. */
14158 INTX_FTYPE_FX (ll
);
14160 INTX_FTYPE_FX (uh
);
14161 INTX_FTYPE_FX (un
);
14162 INTX_FTYPE_FX (ul
);
14163 INTX_FTYPE_FX (ull
);
14165 /* For fxbits builtins. */
14170 FX_FTYPE_INTX (ll
);
14172 FX_FTYPE_INTX (uh
);
14173 FX_FTYPE_INTX (un
);
14174 FX_FTYPE_INTX (ul
);
14175 FX_FTYPE_INTX (ull
);
14178 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
14180 int id = AVR_BUILTIN_ ## NAME; \
14181 const char *Name = "__builtin_avr_" #NAME; \
14182 char *name = (char*) alloca (1 + strlen (Name)); \
14184 gcc_assert (id < AVR_BUILTIN_COUNT); \
14185 avr_bdesc[id].fndecl \
14186 = add_builtin_function (avr_tolower (name, Name), TYPE, id, \
14187 BUILT_IN_MD, LIBNAME, NULL_TREE); \
14189 #include "builtins.def"
14192 avr_init_builtin_int24 ();
14196 /* Subroutine of avr_expand_builtin to expand vanilla builtins
14197 with non-void result and 1 ... 3 arguments. */
14200 avr_default_expand_builtin (enum insn_code icode
, tree exp
, rtx target
)
14203 int n_args
= call_expr_nargs (exp
);
14204 machine_mode tmode
= insn_data
[icode
].operand
[0].mode
;
14206 gcc_assert (n_args
>= 1 && n_args
<= 3);
14208 if (target
== NULL_RTX
14209 || GET_MODE (target
) != tmode
14210 || !insn_data
[icode
].operand
[0].predicate (target
, tmode
))
14212 target
= gen_reg_rtx (tmode
);
14215 for (int n
= 0; n
< n_args
; n
++)
14217 tree arg
= CALL_EXPR_ARG (exp
, n
);
14218 rtx op
= expand_expr (arg
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
14219 machine_mode opmode
= GET_MODE (op
);
14220 machine_mode mode
= insn_data
[icode
].operand
[n
+ 1].mode
;
14222 if ((opmode
== SImode
|| opmode
== VOIDmode
) && mode
== HImode
)
14225 op
= gen_lowpart (HImode
, op
);
14228 /* In case the insn wants input operands in modes different from
14229 the result, abort. */
14231 gcc_assert (opmode
== mode
|| opmode
== VOIDmode
);
14233 if (!insn_data
[icode
].operand
[n
+ 1].predicate (op
, mode
))
14234 op
= copy_to_mode_reg (mode
, op
);
14241 case 1: pat
= GEN_FCN (icode
) (target
, xop
[0]); break;
14242 case 2: pat
= GEN_FCN (icode
) (target
, xop
[0], xop
[1]); break;
14243 case 3: pat
= GEN_FCN (icode
) (target
, xop
[0], xop
[1], xop
[2]); break;
14249 if (pat
== NULL_RTX
)
14258 /* Implement `TARGET_EXPAND_BUILTIN'. */
14259 /* Expand an expression EXP that calls a built-in function,
14260 with result going to TARGET if that's convenient
14261 (and in mode MODE if that's convenient).
14262 SUBTARGET may be used as the target for computing one of EXP's operands.
14263 IGNORE is nonzero if the value is to be ignored. */
14266 avr_expand_builtin (tree exp
, rtx target
,
14267 rtx subtarget ATTRIBUTE_UNUSED
,
14268 machine_mode mode ATTRIBUTE_UNUSED
,
14271 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
14272 const char *bname
= IDENTIFIER_POINTER (DECL_NAME (fndecl
));
14273 unsigned int id
= DECL_FUNCTION_CODE (fndecl
);
14274 const struct avr_builtin_description
*d
= &avr_bdesc
[id
];
14278 gcc_assert (id
< AVR_BUILTIN_COUNT
);
14282 case AVR_BUILTIN_NOP
:
14283 emit_insn (gen_nopv (GEN_INT (1)));
14286 case AVR_BUILTIN_DELAY_CYCLES
:
14288 arg0
= CALL_EXPR_ARG (exp
, 0);
14289 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
14291 if (!CONST_INT_P (op0
))
14292 error ("%s expects a compile time integer constant", bname
);
14294 avr_expand_delay_cycles (op0
);
14299 case AVR_BUILTIN_NOPS
:
14301 arg0
= CALL_EXPR_ARG (exp
, 0);
14302 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
14304 if (!CONST_INT_P (op0
))
14305 error ("%s expects a compile time integer constant", bname
);
14307 avr_expand_nops (op0
);
14312 case AVR_BUILTIN_INSERT_BITS
:
14314 arg0
= CALL_EXPR_ARG (exp
, 0);
14315 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
14317 if (!CONST_INT_P (op0
))
14319 error ("%s expects a compile time long integer constant"
14320 " as first argument", bname
);
14327 case AVR_BUILTIN_ROUNDHR
: case AVR_BUILTIN_ROUNDUHR
:
14328 case AVR_BUILTIN_ROUNDR
: case AVR_BUILTIN_ROUNDUR
:
14329 case AVR_BUILTIN_ROUNDLR
: case AVR_BUILTIN_ROUNDULR
:
14330 case AVR_BUILTIN_ROUNDLLR
: case AVR_BUILTIN_ROUNDULLR
:
14332 case AVR_BUILTIN_ROUNDHK
: case AVR_BUILTIN_ROUNDUHK
:
14333 case AVR_BUILTIN_ROUNDK
: case AVR_BUILTIN_ROUNDUK
:
14334 case AVR_BUILTIN_ROUNDLK
: case AVR_BUILTIN_ROUNDULK
:
14335 case AVR_BUILTIN_ROUNDLLK
: case AVR_BUILTIN_ROUNDULLK
:
14337 /* Warn about odd rounding. Rounding points >= FBIT will have
14340 if (TREE_CODE (CALL_EXPR_ARG (exp
, 1)) != INTEGER_CST
)
14343 int rbit
= (int) TREE_INT_CST_LOW (CALL_EXPR_ARG (exp
, 1));
14345 if (rbit
>= (int) GET_MODE_FBIT (mode
))
14347 warning (OPT_Wextra
, "rounding to %d bits has no effect for "
14348 "fixed-point value with %d fractional bits",
14349 rbit
, GET_MODE_FBIT (mode
));
14351 return expand_expr (CALL_EXPR_ARG (exp
, 0), NULL_RTX
, mode
,
14354 else if (rbit
<= - (int) GET_MODE_IBIT (mode
))
14356 warning (0, "rounding result will always be 0");
14357 return CONST0_RTX (mode
);
14360 /* The rounding points RP satisfies now: -IBIT < RP < FBIT.
14362 TR 18037 only specifies results for RP > 0. However, the
14363 remaining cases of -IBIT < RP <= 0 can easily be supported
14364 without any additional overhead. */
14369 /* No fold found and no insn: Call support function from libgcc. */
14371 if (d
->icode
== CODE_FOR_nothing
14372 && DECL_ASSEMBLER_NAME (get_callee_fndecl (exp
)) != NULL_TREE
)
14374 return expand_call (exp
, target
, ignore
);
14377 /* No special treatment needed: vanilla expand. */
14379 gcc_assert (d
->icode
!= CODE_FOR_nothing
);
14380 gcc_assert (d
->n_args
== call_expr_nargs (exp
));
14382 if (d
->n_args
== 0)
14384 emit_insn ((GEN_FCN (d
->icode
)) (target
));
14388 return avr_default_expand_builtin (d
->icode
, exp
, target
);
14392 /* Helper for `avr_fold_builtin' that folds absfx (FIXED_CST). */
14395 avr_fold_absfx (tree tval
)
14397 if (FIXED_CST
!= TREE_CODE (tval
))
14400 /* Our fixed-points have no padding: Use double_int payload directly. */
14402 FIXED_VALUE_TYPE fval
= TREE_FIXED_CST (tval
);
14403 unsigned int bits
= GET_MODE_BITSIZE (fval
.mode
);
14404 double_int ival
= fval
.data
.sext (bits
);
14406 if (!ival
.is_negative())
14409 /* ISO/IEC TR 18037, 7.18a.6.2: The absfx functions are saturating. */
14411 fval
.data
= (ival
== double_int::min_value (bits
, false).sext (bits
))
14412 ? double_int::max_value (bits
, false)
14415 return build_fixed (TREE_TYPE (tval
), fval
);
14419 /* Implement `TARGET_FOLD_BUILTIN'. */
14422 avr_fold_builtin (tree fndecl
, int n_args ATTRIBUTE_UNUSED
, tree
*arg
,
14423 bool ignore ATTRIBUTE_UNUSED
)
14425 unsigned int fcode
= DECL_FUNCTION_CODE (fndecl
);
14426 tree val_type
= TREE_TYPE (TREE_TYPE (fndecl
));
14436 case AVR_BUILTIN_SWAP
:
14438 return fold_build2 (LROTATE_EXPR
, val_type
, arg
[0],
14439 build_int_cst (val_type
, 4));
14442 case AVR_BUILTIN_ABSHR
:
14443 case AVR_BUILTIN_ABSR
:
14444 case AVR_BUILTIN_ABSLR
:
14445 case AVR_BUILTIN_ABSLLR
:
14447 case AVR_BUILTIN_ABSHK
:
14448 case AVR_BUILTIN_ABSK
:
14449 case AVR_BUILTIN_ABSLK
:
14450 case AVR_BUILTIN_ABSLLK
:
14451 /* GCC is not good with folding ABS for fixed-point. Do it by hand. */
14453 return avr_fold_absfx (arg
[0]);
14455 case AVR_BUILTIN_BITSHR
: case AVR_BUILTIN_HRBITS
:
14456 case AVR_BUILTIN_BITSHK
: case AVR_BUILTIN_HKBITS
:
14457 case AVR_BUILTIN_BITSUHR
: case AVR_BUILTIN_UHRBITS
:
14458 case AVR_BUILTIN_BITSUHK
: case AVR_BUILTIN_UHKBITS
:
14460 case AVR_BUILTIN_BITSR
: case AVR_BUILTIN_RBITS
:
14461 case AVR_BUILTIN_BITSK
: case AVR_BUILTIN_KBITS
:
14462 case AVR_BUILTIN_BITSUR
: case AVR_BUILTIN_URBITS
:
14463 case AVR_BUILTIN_BITSUK
: case AVR_BUILTIN_UKBITS
:
14465 case AVR_BUILTIN_BITSLR
: case AVR_BUILTIN_LRBITS
:
14466 case AVR_BUILTIN_BITSLK
: case AVR_BUILTIN_LKBITS
:
14467 case AVR_BUILTIN_BITSULR
: case AVR_BUILTIN_ULRBITS
:
14468 case AVR_BUILTIN_BITSULK
: case AVR_BUILTIN_ULKBITS
:
14470 case AVR_BUILTIN_BITSLLR
: case AVR_BUILTIN_LLRBITS
:
14471 case AVR_BUILTIN_BITSLLK
: case AVR_BUILTIN_LLKBITS
:
14472 case AVR_BUILTIN_BITSULLR
: case AVR_BUILTIN_ULLRBITS
:
14473 case AVR_BUILTIN_BITSULLK
: case AVR_BUILTIN_ULLKBITS
:
14475 gcc_assert (TYPE_PRECISION (val_type
)
14476 == TYPE_PRECISION (TREE_TYPE (arg
[0])));
14478 return build1 (VIEW_CONVERT_EXPR
, val_type
, arg
[0]);
14480 case AVR_BUILTIN_INSERT_BITS
:
14482 tree tbits
= arg
[1];
14483 tree tval
= arg
[2];
14485 tree map_type
= TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl
)));
14487 bool changed
= false;
14488 avr_map_op_t best_g
;
14490 if (TREE_CODE (arg
[0]) != INTEGER_CST
)
14492 /* No constant as first argument: Don't fold this and run into
14493 error in avr_expand_builtin. */
14498 tmap
= wide_int_to_tree (map_type
, arg
[0]);
14499 map
= TREE_INT_CST_LOW (tmap
);
14501 if (TREE_CODE (tval
) != INTEGER_CST
14502 && 0 == avr_map_metric (map
, MAP_MASK_PREIMAGE_F
))
14504 /* There are no F in the map, i.e. 3rd operand is unused.
14505 Replace that argument with some constant to render
14506 respective input unused. */
14508 tval
= build_int_cst (val_type
, 0);
14512 if (TREE_CODE (tbits
) != INTEGER_CST
14513 && 0 == avr_map_metric (map
, MAP_PREIMAGE_0_7
))
14515 /* Similar for the bits to be inserted. If they are unused,
14516 we can just as well pass 0. */
14518 tbits
= build_int_cst (val_type
, 0);
14521 if (TREE_CODE (tbits
) == INTEGER_CST
)
14523 /* Inserting bits known at compile time is easy and can be
14524 performed by AND and OR with appropriate masks. */
14526 int bits
= TREE_INT_CST_LOW (tbits
);
14527 int mask_ior
= 0, mask_and
= 0xff;
14529 for (size_t i
= 0; i
< 8; i
++)
14531 int mi
= avr_map (map
, i
);
14535 if (bits
& (1 << mi
)) mask_ior
|= (1 << i
);
14536 else mask_and
&= ~(1 << i
);
14540 tval
= fold_build2 (BIT_IOR_EXPR
, val_type
, tval
,
14541 build_int_cst (val_type
, mask_ior
));
14542 return fold_build2 (BIT_AND_EXPR
, val_type
, tval
,
14543 build_int_cst (val_type
, mask_and
));
14547 return build_call_expr (fndecl
, 3, tmap
, tbits
, tval
);
14549 /* If bits don't change their position we can use vanilla logic
14550 to merge the two arguments. */
14552 if (0 == avr_map_metric (map
, MAP_NONFIXED_0_7
))
14554 int mask_f
= avr_map_metric (map
, MAP_MASK_PREIMAGE_F
);
14555 tree tres
, tmask
= build_int_cst (val_type
, mask_f
^ 0xff);
14557 tres
= fold_build2 (BIT_XOR_EXPR
, val_type
, tbits
, tval
);
14558 tres
= fold_build2 (BIT_AND_EXPR
, val_type
, tres
, tmask
);
14559 return fold_build2 (BIT_XOR_EXPR
, val_type
, tres
, tval
);
14562 /* Try to decomposing map to reduce overall cost. */
14564 if (avr_log
.builtin
)
14565 avr_edump ("\n%?: %x\n%?: ROL cost: ", map
);
14567 best_g
= avr_map_op
[0];
14568 best_g
.cost
= 1000;
14570 for (size_t i
= 0; i
< ARRAY_SIZE (avr_map_op
); i
++)
14573 = avr_map_decompose (map
, avr_map_op
+ i
,
14574 TREE_CODE (tval
) == INTEGER_CST
);
14576 if (g
.cost
>= 0 && g
.cost
< best_g
.cost
)
14580 if (avr_log
.builtin
)
14583 if (best_g
.arg
== 0)
14584 /* No optimization found */
14587 /* Apply operation G to the 2nd argument. */
14589 if (avr_log
.builtin
)
14590 avr_edump ("%?: using OP(%s%d, %x) cost %d\n",
14591 best_g
.str
, best_g
.arg
, best_g
.map
, best_g
.cost
);
14593 /* Do right-shifts arithmetically: They copy the MSB instead of
14594 shifting in a non-usable value (0) as with logic right-shift. */
14596 tbits
= fold_convert (signed_char_type_node
, tbits
);
14597 tbits
= fold_build2 (best_g
.code
, signed_char_type_node
, tbits
,
14598 build_int_cst (val_type
, best_g
.arg
));
14599 tbits
= fold_convert (val_type
, tbits
);
14601 /* Use map o G^-1 instead of original map to undo the effect of G. */
14603 tmap
= wide_int_to_tree (map_type
, best_g
.map
);
14605 return build_call_expr (fndecl
, 3, tmap
, tbits
, tval
);
14606 } /* AVR_BUILTIN_INSERT_BITS */
14614 /* Initialize the GCC target structure. */
14616 #undef TARGET_ASM_ALIGNED_HI_OP
14617 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
14618 #undef TARGET_ASM_ALIGNED_SI_OP
14619 #define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
14620 #undef TARGET_ASM_UNALIGNED_HI_OP
14621 #define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
14622 #undef TARGET_ASM_UNALIGNED_SI_OP
14623 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
14624 #undef TARGET_ASM_INTEGER
14625 #define TARGET_ASM_INTEGER avr_assemble_integer
14626 #undef TARGET_ASM_FILE_START
14627 #define TARGET_ASM_FILE_START avr_file_start
14628 #undef TARGET_ASM_FILE_END
14629 #define TARGET_ASM_FILE_END avr_file_end
14631 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
14632 #define TARGET_ASM_FUNCTION_END_PROLOGUE avr_asm_function_end_prologue
14633 #undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
14634 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE avr_asm_function_begin_epilogue
14636 #undef TARGET_FUNCTION_VALUE
14637 #define TARGET_FUNCTION_VALUE avr_function_value
14638 #undef TARGET_LIBCALL_VALUE
14639 #define TARGET_LIBCALL_VALUE avr_libcall_value
14640 #undef TARGET_FUNCTION_VALUE_REGNO_P
14641 #define TARGET_FUNCTION_VALUE_REGNO_P avr_function_value_regno_p
14643 #undef TARGET_ATTRIBUTE_TABLE
14644 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
14645 #undef TARGET_INSERT_ATTRIBUTES
14646 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
14647 #undef TARGET_SECTION_TYPE_FLAGS
14648 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
14650 #undef TARGET_ASM_NAMED_SECTION
14651 #define TARGET_ASM_NAMED_SECTION avr_asm_named_section
14652 #undef TARGET_ASM_INIT_SECTIONS
14653 #define TARGET_ASM_INIT_SECTIONS avr_asm_init_sections
14654 #undef TARGET_ENCODE_SECTION_INFO
14655 #define TARGET_ENCODE_SECTION_INFO avr_encode_section_info
14656 #undef TARGET_ASM_SELECT_SECTION
14657 #define TARGET_ASM_SELECT_SECTION avr_asm_select_section
14659 #undef TARGET_ASM_FINAL_POSTSCAN_INSN
14660 #define TARGET_ASM_FINAL_POSTSCAN_INSN avr_asm_final_postscan_insn
14662 #undef TARGET_REGISTER_MOVE_COST
14663 #define TARGET_REGISTER_MOVE_COST avr_register_move_cost
14664 #undef TARGET_MEMORY_MOVE_COST
14665 #define TARGET_MEMORY_MOVE_COST avr_memory_move_cost
14666 #undef TARGET_RTX_COSTS
14667 #define TARGET_RTX_COSTS avr_rtx_costs
14668 #undef TARGET_ADDRESS_COST
14669 #define TARGET_ADDRESS_COST avr_address_cost
14670 #undef TARGET_MACHINE_DEPENDENT_REORG
14671 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
14672 #undef TARGET_FUNCTION_ARG
14673 #define TARGET_FUNCTION_ARG avr_function_arg
14674 #undef TARGET_FUNCTION_ARG_ADVANCE
14675 #define TARGET_FUNCTION_ARG_ADVANCE avr_function_arg_advance
14677 #undef TARGET_SET_CURRENT_FUNCTION
14678 #define TARGET_SET_CURRENT_FUNCTION avr_set_current_function
14680 #undef TARGET_RETURN_IN_MEMORY
14681 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
14683 #undef TARGET_STRICT_ARGUMENT_NAMING
14684 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
14686 #undef TARGET_BUILTIN_SETJMP_FRAME_VALUE
14687 #define TARGET_BUILTIN_SETJMP_FRAME_VALUE avr_builtin_setjmp_frame_value
14689 #undef TARGET_CONDITIONAL_REGISTER_USAGE
14690 #define TARGET_CONDITIONAL_REGISTER_USAGE avr_conditional_register_usage
14692 #undef TARGET_HARD_REGNO_MODE_OK
14693 #define TARGET_HARD_REGNO_MODE_OK avr_hard_regno_mode_ok
14694 #undef TARGET_HARD_REGNO_SCRATCH_OK
14695 #define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok
14696 #undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED
14697 #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
14698 avr_hard_regno_call_part_clobbered
14700 #undef TARGET_CASE_VALUES_THRESHOLD
14701 #define TARGET_CASE_VALUES_THRESHOLD avr_case_values_threshold
14703 #undef TARGET_FRAME_POINTER_REQUIRED
14704 #define TARGET_FRAME_POINTER_REQUIRED avr_frame_pointer_required_p
14705 #undef TARGET_CAN_ELIMINATE
14706 #define TARGET_CAN_ELIMINATE avr_can_eliminate
14708 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
14709 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS avr_allocate_stack_slots_for_args
14711 #undef TARGET_WARN_FUNC_RETURN
14712 #define TARGET_WARN_FUNC_RETURN avr_warn_func_return
14714 #undef TARGET_CLASS_LIKELY_SPILLED_P
14715 #define TARGET_CLASS_LIKELY_SPILLED_P avr_class_likely_spilled_p
14717 #undef TARGET_OPTION_OVERRIDE
14718 #define TARGET_OPTION_OVERRIDE avr_option_override
14720 #undef TARGET_CANNOT_MODIFY_JUMPS_P
14721 #define TARGET_CANNOT_MODIFY_JUMPS_P avr_cannot_modify_jumps_p
14723 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
14724 #define TARGET_FUNCTION_OK_FOR_SIBCALL avr_function_ok_for_sibcall
14726 #undef TARGET_INIT_BUILTINS
14727 #define TARGET_INIT_BUILTINS avr_init_builtins
14729 #undef TARGET_BUILTIN_DECL
14730 #define TARGET_BUILTIN_DECL avr_builtin_decl
14732 #undef TARGET_EXPAND_BUILTIN
14733 #define TARGET_EXPAND_BUILTIN avr_expand_builtin
14735 #undef TARGET_FOLD_BUILTIN
14736 #define TARGET_FOLD_BUILTIN avr_fold_builtin
14738 #undef TARGET_SCALAR_MODE_SUPPORTED_P
14739 #define TARGET_SCALAR_MODE_SUPPORTED_P avr_scalar_mode_supported_p
14741 #undef TARGET_BUILD_BUILTIN_VA_LIST
14742 #define TARGET_BUILD_BUILTIN_VA_LIST avr_build_builtin_va_list
14744 #undef TARGET_FIXED_POINT_SUPPORTED_P
14745 #define TARGET_FIXED_POINT_SUPPORTED_P hook_bool_void_true
14747 #undef TARGET_CONVERT_TO_TYPE
14748 #define TARGET_CONVERT_TO_TYPE avr_convert_to_type
14750 #undef TARGET_LRA_P
14751 #define TARGET_LRA_P hook_bool_void_false
14753 #undef TARGET_ADDR_SPACE_SUBSET_P
14754 #define TARGET_ADDR_SPACE_SUBSET_P avr_addr_space_subset_p
14756 #undef TARGET_ADDR_SPACE_CONVERT
14757 #define TARGET_ADDR_SPACE_CONVERT avr_addr_space_convert
14759 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
14760 #define TARGET_ADDR_SPACE_ADDRESS_MODE avr_addr_space_address_mode
14762 #undef TARGET_ADDR_SPACE_POINTER_MODE
14763 #define TARGET_ADDR_SPACE_POINTER_MODE avr_addr_space_pointer_mode
14765 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
14766 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
14767 avr_addr_space_legitimate_address_p
14769 #undef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
14770 #define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS avr_addr_space_legitimize_address
14772 #undef TARGET_ADDR_SPACE_DIAGNOSE_USAGE
14773 #define TARGET_ADDR_SPACE_DIAGNOSE_USAGE avr_addr_space_diagnose_usage
14775 #undef TARGET_MODE_DEPENDENT_ADDRESS_P
14776 #define TARGET_MODE_DEPENDENT_ADDRESS_P avr_mode_dependent_address_p
14778 #undef TARGET_PRINT_OPERAND
14779 #define TARGET_PRINT_OPERAND avr_print_operand
14780 #undef TARGET_PRINT_OPERAND_ADDRESS
14781 #define TARGET_PRINT_OPERAND_ADDRESS avr_print_operand_address
14782 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
14783 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P avr_print_operand_punct_valid_p
14785 #undef TARGET_USE_BY_PIECES_INFRASTRUCTURE_P
14786 #define TARGET_USE_BY_PIECES_INFRASTRUCTURE_P \
14787 avr_use_by_pieces_infrastructure_p
14789 #undef TARGET_LEGITIMATE_COMBINED_INSN
14790 #define TARGET_LEGITIMATE_COMBINED_INSN avr_legitimate_combined_insn
14792 struct gcc_target targetm
= TARGET_INITIALIZER
;
14795 #include "gt-avr.h"