Add initial version of C++17 <memory_resource> header
[official-gcc.git] / gcc / config / avr / avr.c
blob81c35e7fbc2b06bc06cc7fb7406694bbe48860e5
1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2 Copyright (C) 1998-2018 Free Software Foundation, Inc.
3 Contributed by Denis Chertykov (chertykov@gmail.com)
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #define IN_TARGET_CODE 1
23 #include "config.h"
24 #include "system.h"
25 #include "intl.h"
26 #include "coretypes.h"
27 #include "backend.h"
28 #include "target.h"
29 #include "rtl.h"
30 #include "tree.h"
31 #include "stringpool.h"
32 #include "attribs.h"
33 #include "cgraph.h"
34 #include "c-family/c-common.h"
35 #include "cfghooks.h"
36 #include "df.h"
37 #include "memmodel.h"
38 #include "tm_p.h"
39 #include "optabs.h"
40 #include "regs.h"
41 #include "emit-rtl.h"
42 #include "recog.h"
43 #include "conditions.h"
44 #include "insn-attr.h"
45 #include "reload.h"
46 #include "varasm.h"
47 #include "calls.h"
48 #include "stor-layout.h"
49 #include "output.h"
50 #include "explow.h"
51 #include "expr.h"
52 #include "langhooks.h"
53 #include "cfgrtl.h"
54 #include "params.h"
55 #include "builtins.h"
56 #include "context.h"
57 #include "tree-pass.h"
58 #include "print-rtl.h"
59 #include "rtl-iter.h"
61 /* This file should be included last. */
62 #include "target-def.h"
64 /* Maximal allowed offset for an address in the LD command */
65 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
67 /* Return true if STR starts with PREFIX and false, otherwise. */
68 #define STR_PREFIX_P(STR,PREFIX) (strncmp (STR, PREFIX, strlen (PREFIX)) == 0)
70 /* The 4 bits starting at SECTION_MACH_DEP are reserved to store the
71 address space where data is to be located.
72 As the only non-generic address spaces are all located in flash,
73 this can be used to test if data shall go into some .progmem* section.
74 This must be the rightmost field of machine dependent section flags. */
75 #define AVR_SECTION_PROGMEM (0xf * SECTION_MACH_DEP)
77 /* Similar 4-bit region for SYMBOL_REF_FLAGS. */
78 #define AVR_SYMBOL_FLAG_PROGMEM (0xf * SYMBOL_FLAG_MACH_DEP)
80 /* Similar 4-bit region in SYMBOL_REF_FLAGS:
81 Set address-space AS in SYMBOL_REF_FLAGS of SYM */
82 #define AVR_SYMBOL_SET_ADDR_SPACE(SYM,AS) \
83 do { \
84 SYMBOL_REF_FLAGS (sym) &= ~AVR_SYMBOL_FLAG_PROGMEM; \
85 SYMBOL_REF_FLAGS (sym) |= (AS) * SYMBOL_FLAG_MACH_DEP; \
86 } while (0)
88 /* Read address-space from SYMBOL_REF_FLAGS of SYM */
89 #define AVR_SYMBOL_GET_ADDR_SPACE(SYM) \
90 ((SYMBOL_REF_FLAGS (sym) & AVR_SYMBOL_FLAG_PROGMEM) \
91 / SYMBOL_FLAG_MACH_DEP)
93 /* (AVR_TINY only): Symbol has attribute progmem */
94 #define AVR_SYMBOL_FLAG_TINY_PM \
95 (SYMBOL_FLAG_MACH_DEP << 7)
97 /* (AVR_TINY only): Symbol has attribute absdata */
98 #define AVR_SYMBOL_FLAG_TINY_ABSDATA \
99 (SYMBOL_FLAG_MACH_DEP << 8)
101 #define TINY_ADIW(REG1, REG2, I) \
102 "subi " #REG1 ",lo8(-(" #I "))" CR_TAB \
103 "sbci " #REG2 ",hi8(-(" #I "))"
105 #define TINY_SBIW(REG1, REG2, I) \
106 "subi " #REG1 ",lo8((" #I "))" CR_TAB \
107 "sbci " #REG2 ",hi8((" #I "))"
109 #define AVR_TMP_REGNO (AVR_TINY ? TMP_REGNO_TINY : TMP_REGNO)
110 #define AVR_ZERO_REGNO (AVR_TINY ? ZERO_REGNO_TINY : ZERO_REGNO)
112 /* Known address spaces. The order must be the same as in the respective
113 enum from avr.h (or designated initialized must be used). */
114 const avr_addrspace_t avr_addrspace[ADDR_SPACE_COUNT] =
116 { ADDR_SPACE_RAM, 0, 2, "", 0, NULL },
117 { ADDR_SPACE_FLASH, 1, 2, "__flash", 0, ".progmem.data" },
118 { ADDR_SPACE_FLASH1, 1, 2, "__flash1", 1, ".progmem1.data" },
119 { ADDR_SPACE_FLASH2, 1, 2, "__flash2", 2, ".progmem2.data" },
120 { ADDR_SPACE_FLASH3, 1, 2, "__flash3", 3, ".progmem3.data" },
121 { ADDR_SPACE_FLASH4, 1, 2, "__flash4", 4, ".progmem4.data" },
122 { ADDR_SPACE_FLASH5, 1, 2, "__flash5", 5, ".progmem5.data" },
123 { ADDR_SPACE_MEMX, 1, 3, "__memx", 0, ".progmemx.data" },
127 /* Holding RAM addresses of some SFRs used by the compiler and that
128 are unique over all devices in an architecture like 'avr4'. */
130 typedef struct
132 /* SREG: The processor status */
133 int sreg;
135 /* RAMPX, RAMPY, RAMPD and CCP of XMEGA */
136 int ccp;
137 int rampd;
138 int rampx;
139 int rampy;
141 /* RAMPZ: The high byte of 24-bit address used with ELPM */
142 int rampz;
144 /* SP: The stack pointer and its low and high byte */
145 int sp_l;
146 int sp_h;
147 } avr_addr_t;
149 static avr_addr_t avr_addr;
152 /* Prototypes for local helper functions. */
154 static const char* out_movqi_r_mr (rtx_insn *, rtx[], int*);
155 static const char* out_movhi_r_mr (rtx_insn *, rtx[], int*);
156 static const char* out_movsi_r_mr (rtx_insn *, rtx[], int*);
157 static const char* out_movqi_mr_r (rtx_insn *, rtx[], int*);
158 static const char* out_movhi_mr_r (rtx_insn *, rtx[], int*);
159 static const char* out_movsi_mr_r (rtx_insn *, rtx[], int*);
161 static int get_sequence_length (rtx_insn *insns);
162 static int sequent_regs_live (void);
163 static const char *ptrreg_to_str (int);
164 static const char *cond_string (enum rtx_code);
165 static int avr_num_arg_regs (machine_mode, const_tree);
166 static int avr_operand_rtx_cost (rtx, machine_mode, enum rtx_code,
167 int, bool);
168 static void output_reload_in_const (rtx*, rtx, int*, bool);
169 static struct machine_function * avr_init_machine_status (void);
172 /* Prototypes for hook implementors if needed before their implementation. */
174 static bool avr_rtx_costs (rtx, machine_mode, int, int, int*, bool);
177 /* Allocate registers from r25 to r8 for parameters for function calls. */
178 #define FIRST_CUM_REG 26
180 /* Last call saved register */
181 #define LAST_CALLEE_SAVED_REG (AVR_TINY ? 19 : 17)
183 /* Implicit target register of LPM instruction (R0) */
184 extern GTY(()) rtx lpm_reg_rtx;
185 rtx lpm_reg_rtx;
187 /* (Implicit) address register of LPM instruction (R31:R30 = Z) */
188 extern GTY(()) rtx lpm_addr_reg_rtx;
189 rtx lpm_addr_reg_rtx;
191 /* Temporary register RTX (reg:QI TMP_REGNO) */
192 extern GTY(()) rtx tmp_reg_rtx;
193 rtx tmp_reg_rtx;
195 /* Zeroed register RTX (reg:QI ZERO_REGNO) */
196 extern GTY(()) rtx zero_reg_rtx;
197 rtx zero_reg_rtx;
199 /* RTXs for all general purpose registers as QImode */
200 extern GTY(()) rtx all_regs_rtx[32];
201 rtx all_regs_rtx[32];
203 /* SREG, the processor status */
204 extern GTY(()) rtx sreg_rtx;
205 rtx sreg_rtx;
207 /* RAMP* special function registers */
208 extern GTY(()) rtx rampd_rtx;
209 extern GTY(()) rtx rampx_rtx;
210 extern GTY(()) rtx rampy_rtx;
211 extern GTY(()) rtx rampz_rtx;
212 rtx rampd_rtx;
213 rtx rampx_rtx;
214 rtx rampy_rtx;
215 rtx rampz_rtx;
217 /* RTX containing the strings "" and "e", respectively */
218 static GTY(()) rtx xstring_empty;
219 static GTY(()) rtx xstring_e;
221 /* Current architecture. */
222 const avr_arch_t *avr_arch;
224 /* Unnamed sections associated to __attribute__((progmem)) aka. PROGMEM
225 or to address space __flash* or __memx. Only used as singletons inside
226 avr_asm_select_section, but it must not be local there because of GTY. */
227 static GTY(()) section *progmem_section[ADDR_SPACE_COUNT];
229 /* Condition for insns/expanders from avr-dimode.md. */
230 bool avr_have_dimode = true;
232 /* To track if code will use .bss and/or .data. */
233 bool avr_need_clear_bss_p = false;
234 bool avr_need_copy_data_p = false;
237 /* Transform UP into lowercase and write the result to LO.
238 You must provide enough space for LO. Return LO. */
240 static char*
241 avr_tolower (char *lo, const char *up)
243 char *lo0 = lo;
245 for (; *up; up++, lo++)
246 *lo = TOLOWER (*up);
248 *lo = '\0';
250 return lo0;
254 /* Constraint helper function. XVAL is a CONST_INT or a CONST_DOUBLE.
255 Return true if the least significant N_BYTES bytes of XVAL all have a
256 popcount in POP_MASK and false, otherwise. POP_MASK represents a subset
257 of integers which contains an integer N iff bit N of POP_MASK is set. */
259 bool
260 avr_popcount_each_byte (rtx xval, int n_bytes, int pop_mask)
262 machine_mode mode = GET_MODE (xval);
264 if (VOIDmode == mode)
265 mode = SImode;
267 for (int i = 0; i < n_bytes; i++)
269 rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
270 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
272 if ((pop_mask & (1 << popcount_hwi (val8))) == 0)
273 return false;
276 return true;
280 /* Access some RTX as INT_MODE. If X is a CONST_FIXED we can get
281 the bit representation of X by "casting" it to CONST_INT. */
284 avr_to_int_mode (rtx x)
286 machine_mode mode = GET_MODE (x);
288 return VOIDmode == mode
290 : simplify_gen_subreg (int_mode_for_mode (mode).require (), x, mode, 0);
293 namespace {
295 static const pass_data avr_pass_data_recompute_notes =
297 RTL_PASS, // type
298 "", // name (will be patched)
299 OPTGROUP_NONE, // optinfo_flags
300 TV_DF_SCAN, // tv_id
301 0, // properties_required
302 0, // properties_provided
303 0, // properties_destroyed
304 0, // todo_flags_start
305 TODO_df_finish | TODO_df_verify // todo_flags_finish
309 class avr_pass_recompute_notes : public rtl_opt_pass
311 public:
312 avr_pass_recompute_notes (gcc::context *ctxt, const char *name)
313 : rtl_opt_pass (avr_pass_data_recompute_notes, ctxt)
315 this->name = name;
318 virtual unsigned int execute (function*)
320 df_note_add_problem ();
321 df_analyze ();
323 return 0;
325 }; // avr_pass_recompute_notes
327 static const pass_data avr_pass_data_casesi =
329 RTL_PASS, // type
330 "", // name (will be patched)
331 OPTGROUP_NONE, // optinfo_flags
332 TV_DF_SCAN, // tv_id
333 0, // properties_required
334 0, // properties_provided
335 0, // properties_destroyed
336 0, // todo_flags_start
337 0 // todo_flags_finish
341 class avr_pass_casesi : public rtl_opt_pass
343 public:
344 avr_pass_casesi (gcc::context *ctxt, const char *name)
345 : rtl_opt_pass (avr_pass_data_casesi, ctxt)
347 this->name = name;
350 void avr_rest_of_handle_casesi (function*);
352 virtual bool gate (function*) { return optimize > 0; }
354 virtual unsigned int execute (function *func)
356 avr_rest_of_handle_casesi (func);
358 return 0;
360 }; // avr_pass_casesi
362 } // anon namespace
364 rtl_opt_pass*
365 make_avr_pass_recompute_notes (gcc::context *ctxt)
367 return new avr_pass_recompute_notes (ctxt, "avr-notes-free-cfg");
370 rtl_opt_pass*
371 make_avr_pass_casesi (gcc::context *ctxt)
373 return new avr_pass_casesi (ctxt, "avr-casesi");
377 /* Make one parallel insn with all the patterns from insns i[0]..i[5]. */
379 static rtx_insn*
380 avr_parallel_insn_from_insns (rtx_insn *i[6])
382 rtvec vec = gen_rtvec (6, PATTERN (i[0]), PATTERN (i[1]), PATTERN (i[2]),
383 PATTERN (i[3]), PATTERN (i[4]), PATTERN (i[5]));
384 start_sequence();
385 emit (gen_rtx_PARALLEL (VOIDmode, vec));
386 rtx_insn *insn = get_insns();
387 end_sequence();
389 return insn;
393 /* Return true if we see an insn stream generated by casesi expander together
394 with an extension to SImode of the switch value.
396 If this is the case, fill in the insns from casesi to INSNS[1..5] and
397 the SImode extension to INSNS[0]. Moreover, extract the operands of
398 pattern casesi_<mode>_sequence forged from the sequence to recog_data. */
400 static bool
401 avr_is_casesi_sequence (basic_block bb, rtx_insn *insn, rtx_insn *insns[6])
403 rtx set_5, set_0;
405 /* A first and quick test for a casesi sequences. As a side effect of
406 the test, harvest respective insns to INSNS[0..5]. */
408 if (!(JUMP_P (insns[5] = insn)
409 // casesi is the only insn that comes up with UNSPEC_INDEX_JMP,
410 // hence the following test ensures that we are actually dealing
411 // with code from casesi.
412 && (set_5 = single_set (insns[5]))
413 && UNSPEC == GET_CODE (SET_SRC (set_5))
414 && UNSPEC_INDEX_JMP == XINT (SET_SRC (set_5), 1)
416 && (insns[4] = prev_real_insn (insns[5]))
417 && (insns[3] = prev_real_insn (insns[4]))
418 && (insns[2] = prev_real_insn (insns[3]))
419 && (insns[1] = prev_real_insn (insns[2]))
421 // Insn prior to casesi.
422 && (insns[0] = prev_real_insn (insns[1]))
423 && (set_0 = single_set (insns[0]))
424 && extend_operator (SET_SRC (set_0), SImode)))
426 return false;
429 if (dump_file)
431 fprintf (dump_file, ";; Sequence from casesi in "
432 "[bb %d]:\n\n", bb->index);
433 for (int i = 0; i < 6; i++)
434 print_rtl_single (dump_file, insns[i]);
437 /* We have to deal with quite some operands. Extracting them by hand
438 would be tedious, therefore wrap the insn patterns into a parallel,
439 run recog against it and then use insn extract to get the operands. */
441 rtx_insn *xinsn = avr_parallel_insn_from_insns (insns);
443 INSN_CODE (xinsn) = recog (PATTERN (xinsn), xinsn, NULL /* num_clobbers */);
445 /* Failing to recognize means that someone changed the casesi expander or
446 that some passes prior to this one performed some unexpected changes.
447 Gracefully drop such situations instead of aborting. */
449 if (INSN_CODE (xinsn) < 0)
451 if (dump_file)
452 fprintf (dump_file, ";; Sequence not recognized, giving up.\n\n");
454 return false;
457 gcc_assert (CODE_FOR_casesi_qi_sequence == INSN_CODE (xinsn)
458 || CODE_FOR_casesi_hi_sequence == INSN_CODE (xinsn));
460 extract_insn (xinsn);
462 // Assert on the anatomy of xinsn's operands we are going to work with.
464 gcc_assert (recog_data.n_operands == 11);
465 gcc_assert (recog_data.n_dups == 4);
467 if (dump_file)
469 fprintf (dump_file, ";; Operands extracted:\n");
470 for (int i = 0; i < recog_data.n_operands; i++)
471 avr_fdump (dump_file, ";; $%d = %r\n", i, recog_data.operand[i]);
472 fprintf (dump_file, "\n");
475 return true;
479 /* Perform some extra checks on operands of casesi_<mode>_sequence.
480 Not all operand dependencies can be described by means of predicates.
481 This function performs left over checks and should always return true.
482 Returning false means that someone changed the casesi expander but did
483 not adjust casesi_<mode>_sequence. */
485 bool
486 avr_casei_sequence_check_operands (rtx *xop)
488 rtx sub_5 = NULL_RTX;
490 if (AVR_HAVE_EIJMP_EICALL
491 // The last clobber op of the tablejump.
492 && xop[8] == all_regs_rtx[24])
494 // $6 is: (subreg:SI ($5) 0)
495 sub_5 = xop[6];
498 if (!AVR_HAVE_EIJMP_EICALL
499 // $6 is: (plus:HI (subreg:SI ($5) 0)
500 // (label_ref ($3)))
501 && PLUS == GET_CODE (xop[6])
502 && LABEL_REF == GET_CODE (XEXP (xop[6], 1))
503 && rtx_equal_p (xop[3], XEXP (XEXP (xop[6], 1), 0))
504 // The last clobber op of the tablejump.
505 && xop[8] == const0_rtx)
507 sub_5 = XEXP (xop[6], 0);
510 if (sub_5
511 && SUBREG_P (sub_5)
512 && SUBREG_BYTE (sub_5) == 0
513 && rtx_equal_p (xop[5], SUBREG_REG (sub_5)))
514 return true;
516 if (dump_file)
517 fprintf (dump_file, "\n;; Failed condition for casesi_<mode>_sequence\n\n");
519 return false;
523 /* INSNS[1..5] is a sequence as generated by casesi and INSNS[0] is an
524 extension of an 8-bit or 16-bit integer to SImode. XOP contains the
525 operands of INSNS as extracted by insn_extract from pattern
526 casesi_<mode>_sequence:
528 $0: SImode reg switch value as result of $9.
529 $1: Negative of smallest index in switch.
530 $2: Number of entries in switch.
531 $3: Label to table.
532 $4: Label if out-of-bounds.
533 $5: $0 + $1.
534 $6: 3-byte PC: subreg:HI ($5) + label_ref ($3)
535 2-byte PC: subreg:HI ($5)
536 $7: HI reg index into table (Z or pseudo)
537 $8: R24 or const0_rtx (to be clobbered)
538 $9: Extension to SImode of an 8-bit or 16-bit integer register $10.
539 $10: QImode or HImode register input of $9.
541 Try to optimize this sequence, i.e. use the original HImode / QImode
542 switch value instead of SImode. */
544 static void
545 avr_optimize_casesi (rtx_insn *insns[6], rtx *xop)
547 // Original mode of the switch value; this is QImode or HImode.
548 machine_mode mode = GET_MODE (xop[10]);
550 // How the original switch value was extended to SImode; this is
551 // SIGN_EXTEND or ZERO_EXTEND.
552 enum rtx_code code = GET_CODE (xop[9]);
554 // Lower index, upper index (plus one) and range of case calues.
555 HOST_WIDE_INT low_idx = -INTVAL (xop[1]);
556 HOST_WIDE_INT num_idx = INTVAL (xop[2]);
557 HOST_WIDE_INT hig_idx = low_idx + num_idx;
559 // Maximum ranges of (un)signed QImode resp. HImode.
560 unsigned umax = QImode == mode ? 0xff : 0xffff;
561 int imax = QImode == mode ? 0x7f : 0x7fff;
562 int imin = -imax - 1;
564 // Testing the case range and whether it fits into the range of the
565 // (un)signed mode. This test should actually always pass because it
566 // makes no sense to have case values outside the mode range. Notice
567 // that case labels which are unreachable because they are outside the
568 // mode of the switch value (e.g. "case -1" for uint8_t) have already
569 // been thrown away by the middle-end.
571 if (SIGN_EXTEND == code
572 && low_idx >= imin
573 && hig_idx <= imax)
575 // ok
577 else if (ZERO_EXTEND == code
578 && low_idx >= 0
579 && (unsigned) hig_idx <= umax)
581 // ok
583 else
585 if (dump_file)
586 fprintf (dump_file, ";; Case ranges too big, giving up.\n\n");
587 return;
590 // Do normalization of switch value $10 and out-of-bound check in its
591 // original mode instead of in SImode. Use a newly created pseudo.
592 // This will replace insns[1..2].
594 start_sequence();
596 rtx_insn *seq1, *seq2, *last1, *last2;
598 rtx reg = copy_to_mode_reg (mode, xop[10]);
600 rtx (*gen_add)(rtx,rtx,rtx) = QImode == mode ? gen_addqi3 : gen_addhi3;
601 rtx (*gen_cmp)(rtx,rtx) = QImode == mode ? gen_cmpqi3 : gen_cmphi3;
603 emit_insn (gen_add (reg, reg, gen_int_mode (-low_idx, mode)));
604 emit_insn (gen_cmp (reg, gen_int_mode (num_idx, mode)));
606 seq1 = get_insns();
607 last1 = get_last_insn();
608 end_sequence();
610 emit_insn_before (seq1, insns[1]);
612 // After the out-of-bounds test and corresponding branch, use a
613 // 16-bit index. If QImode is used, extend it to HImode first.
614 // This will replace insns[4].
616 start_sequence();
618 if (QImode == mode)
619 reg = force_reg (HImode, gen_rtx_fmt_e (code, HImode, reg));
621 rtx pat_4 = AVR_3_BYTE_PC
622 ? gen_movhi (xop[7], reg)
623 : gen_addhi3 (xop[7], reg, gen_rtx_LABEL_REF (VOIDmode, xop[3]));
625 emit_insn (pat_4);
627 seq2 = get_insns();
628 last2 = get_last_insn();
629 end_sequence();
631 emit_insn_after (seq2, insns[4]);
633 if (dump_file)
635 fprintf (dump_file, ";; New insns: ");
637 for (rtx_insn *insn = seq1; ; insn = NEXT_INSN (insn))
639 fprintf (dump_file, "%d, ", INSN_UID (insn));
640 if (insn == last1)
641 break;
643 for (rtx_insn *insn = seq2; ; insn = NEXT_INSN (insn))
645 fprintf (dump_file, "%d%s", INSN_UID (insn),
646 insn == last2 ? ".\n\n" : ", ");
647 if (insn == last2)
648 break;
651 fprintf (dump_file, ";; Deleting insns: %d, %d, %d.\n\n",
652 INSN_UID (insns[1]), INSN_UID (insns[2]), INSN_UID (insns[4]));
655 // Pseudodelete the SImode and subreg of SImode insns. We don't care
656 // about the extension insns[0]: Its result is now unused and other
657 // passes will clean it up.
659 SET_INSN_DELETED (insns[1]);
660 SET_INSN_DELETED (insns[2]);
661 SET_INSN_DELETED (insns[4]);
665 void
666 avr_pass_casesi::avr_rest_of_handle_casesi (function *func)
668 basic_block bb;
670 FOR_EACH_BB_FN (bb, func)
672 rtx_insn *insn, *insns[6];
674 FOR_BB_INSNS (bb, insn)
676 if (avr_is_casesi_sequence (bb, insn, insns))
678 avr_optimize_casesi (insns, recog_data.operand);
685 /* Set `avr_arch' as specified by `-mmcu='.
686 Return true on success. */
688 static bool
689 avr_set_core_architecture (void)
691 /* Search for mcu core architecture. */
693 if (!avr_mmcu)
694 avr_mmcu = AVR_MMCU_DEFAULT;
696 avr_arch = &avr_arch_types[0];
698 for (const avr_mcu_t *mcu = avr_mcu_types; ; mcu++)
700 if (mcu->name == NULL)
702 /* Reached the end of `avr_mcu_types'. This should actually never
703 happen as options are provided by device-specs. It could be a
704 typo in a device-specs or calling the compiler proper directly
705 with -mmcu=<device>. */
707 error ("unknown core architecture %qs specified with %qs",
708 avr_mmcu, "-mmcu=");
709 avr_inform_core_architectures ();
710 break;
712 else if (strcmp (mcu->name, avr_mmcu) == 0
713 // Is this a proper architecture ?
714 && mcu->macro == NULL)
716 avr_arch = &avr_arch_types[mcu->arch_id];
717 if (avr_n_flash < 0)
718 avr_n_flash = 1 + (mcu->flash_size - 1) / 0x10000;
720 return true;
724 return false;
728 /* Implement `TARGET_OPTION_OVERRIDE'. */
730 static void
731 avr_option_override (void)
733 /* caller-save.c looks for call-clobbered hard registers that are assigned
734 to pseudos that cross calls and tries so save-restore them around calls
735 in order to reduce the number of stack slots needed.
737 This might lead to situations where reload is no more able to cope
738 with the challenge of AVR's very few address registers and fails to
739 perform the requested spills. */
741 if (avr_strict_X)
742 flag_caller_saves = 0;
744 /* Allow optimizer to introduce store data races. This used to be the
745 default - it was changed because bigger targets did not see any
746 performance decrease. For the AVR though, disallowing data races
747 introduces additional code in LIM and increases reg pressure. */
749 maybe_set_param_value (PARAM_ALLOW_STORE_DATA_RACES, 1,
750 global_options.x_param_values,
751 global_options_set.x_param_values);
753 /* Unwind tables currently require a frame pointer for correctness,
754 see toplev.c:process_options(). */
756 if ((flag_unwind_tables
757 || flag_non_call_exceptions
758 || flag_asynchronous_unwind_tables)
759 && !ACCUMULATE_OUTGOING_ARGS)
761 flag_omit_frame_pointer = 0;
764 if (flag_pic == 1)
765 warning (OPT_fpic, "-fpic is not supported");
766 if (flag_pic == 2)
767 warning (OPT_fPIC, "-fPIC is not supported");
768 if (flag_pie == 1)
769 warning (OPT_fpie, "-fpie is not supported");
770 if (flag_pie == 2)
771 warning (OPT_fPIE, "-fPIE is not supported");
773 #if !defined (HAVE_AS_AVR_MGCCISR_OPTION)
774 avr_gasisr_prologues = 0;
775 #endif
777 if (!avr_set_core_architecture())
778 return;
780 /* RAM addresses of some SFRs common to all devices in respective arch. */
782 /* SREG: Status Register containing flags like I (global IRQ) */
783 avr_addr.sreg = 0x3F + avr_arch->sfr_offset;
785 /* RAMPZ: Address' high part when loading via ELPM */
786 avr_addr.rampz = 0x3B + avr_arch->sfr_offset;
788 avr_addr.rampy = 0x3A + avr_arch->sfr_offset;
789 avr_addr.rampx = 0x39 + avr_arch->sfr_offset;
790 avr_addr.rampd = 0x38 + avr_arch->sfr_offset;
791 avr_addr.ccp = (AVR_TINY ? 0x3C : 0x34) + avr_arch->sfr_offset;
793 /* SP: Stack Pointer (SP_H:SP_L) */
794 avr_addr.sp_l = 0x3D + avr_arch->sfr_offset;
795 avr_addr.sp_h = avr_addr.sp_l + 1;
797 init_machine_status = avr_init_machine_status;
799 avr_log_set_avr_log();
802 /* Function to set up the backend function structure. */
804 static struct machine_function *
805 avr_init_machine_status (void)
807 return ggc_cleared_alloc<machine_function> ();
811 /* Implement `INIT_EXPANDERS'. */
812 /* The function works like a singleton. */
814 void
815 avr_init_expanders (void)
817 for (int regno = 0; regno < 32; regno ++)
818 all_regs_rtx[regno] = gen_rtx_REG (QImode, regno);
820 lpm_reg_rtx = all_regs_rtx[LPM_REGNO];
821 tmp_reg_rtx = all_regs_rtx[AVR_TMP_REGNO];
822 zero_reg_rtx = all_regs_rtx[AVR_ZERO_REGNO];
824 lpm_addr_reg_rtx = gen_rtx_REG (HImode, REG_Z);
826 sreg_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.sreg));
827 rampd_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampd));
828 rampx_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampx));
829 rampy_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampy));
830 rampz_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampz));
832 xstring_empty = gen_rtx_CONST_STRING (VOIDmode, "");
833 xstring_e = gen_rtx_CONST_STRING (VOIDmode, "e");
835 /* TINY core does not have regs r10-r16, but avr-dimode.md expects them
836 to be present */
837 if (AVR_TINY)
838 avr_have_dimode = false;
842 /* Implement `REGNO_REG_CLASS'. */
843 /* Return register class for register R. */
845 enum reg_class
846 avr_regno_reg_class (int r)
848 static const enum reg_class reg_class_tab[] =
850 R0_REG,
851 /* r1 - r15 */
852 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
853 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
854 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
855 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
856 /* r16 - r23 */
857 SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
858 SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
859 /* r24, r25 */
860 ADDW_REGS, ADDW_REGS,
861 /* X: r26, 27 */
862 POINTER_X_REGS, POINTER_X_REGS,
863 /* Y: r28, r29 */
864 POINTER_Y_REGS, POINTER_Y_REGS,
865 /* Z: r30, r31 */
866 POINTER_Z_REGS, POINTER_Z_REGS,
867 /* SP: SPL, SPH */
868 STACK_REG, STACK_REG
871 if (r <= 33)
872 return reg_class_tab[r];
874 return ALL_REGS;
878 /* Implement `TARGET_SCALAR_MODE_SUPPORTED_P'. */
880 static bool
881 avr_scalar_mode_supported_p (scalar_mode mode)
883 if (ALL_FIXED_POINT_MODE_P (mode))
884 return true;
886 if (PSImode == mode)
887 return true;
889 return default_scalar_mode_supported_p (mode);
893 /* Return TRUE if DECL is a VAR_DECL located in flash and FALSE, otherwise. */
895 static bool
896 avr_decl_flash_p (tree decl)
898 if (TREE_CODE (decl) != VAR_DECL
899 || TREE_TYPE (decl) == error_mark_node)
901 return false;
904 return !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (decl)));
908 /* Return TRUE if DECL is a VAR_DECL located in the 24-bit flash
909 address space and FALSE, otherwise. */
911 static bool
912 avr_decl_memx_p (tree decl)
914 if (TREE_CODE (decl) != VAR_DECL
915 || TREE_TYPE (decl) == error_mark_node)
917 return false;
920 return (ADDR_SPACE_MEMX == TYPE_ADDR_SPACE (TREE_TYPE (decl)));
924 /* Return TRUE if X is a MEM rtx located in flash and FALSE, otherwise. */
926 bool
927 avr_mem_flash_p (rtx x)
929 return (MEM_P (x)
930 && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x)));
934 /* Return TRUE if X is a MEM rtx located in the 24-bit flash
935 address space and FALSE, otherwise. */
937 bool
938 avr_mem_memx_p (rtx x)
940 return (MEM_P (x)
941 && ADDR_SPACE_MEMX == MEM_ADDR_SPACE (x));
945 /* A helper for the subsequent function attribute used to dig for
946 attribute 'name' in a FUNCTION_DECL or FUNCTION_TYPE */
948 static inline int
949 avr_lookup_function_attribute1 (const_tree func, const char *name)
951 if (FUNCTION_DECL == TREE_CODE (func))
953 if (NULL_TREE != lookup_attribute (name, DECL_ATTRIBUTES (func)))
955 return true;
958 func = TREE_TYPE (func);
961 gcc_assert (TREE_CODE (func) == FUNCTION_TYPE
962 || TREE_CODE (func) == METHOD_TYPE);
964 return NULL_TREE != lookup_attribute (name, TYPE_ATTRIBUTES (func));
967 /* Return nonzero if FUNC is a naked function. */
969 static int
970 avr_naked_function_p (tree func)
972 return avr_lookup_function_attribute1 (func, "naked");
975 /* Return nonzero if FUNC is an interrupt function as specified
976 by the "interrupt" attribute. */
978 static int
979 avr_interrupt_function_p (tree func)
981 return avr_lookup_function_attribute1 (func, "interrupt");
984 /* Return nonzero if FUNC is a signal function as specified
985 by the "signal" attribute. */
987 static int
988 avr_signal_function_p (tree func)
990 return avr_lookup_function_attribute1 (func, "signal");
993 /* Return nonzero if FUNC is an OS_task function. */
995 static int
996 avr_OS_task_function_p (tree func)
998 return avr_lookup_function_attribute1 (func, "OS_task");
1001 /* Return nonzero if FUNC is an OS_main function. */
1003 static int
1004 avr_OS_main_function_p (tree func)
1006 return avr_lookup_function_attribute1 (func, "OS_main");
1010 /* Return nonzero if FUNC is a no_gccisr function as specified
1011 by the "no_gccisr" attribute. */
1013 static int
1014 avr_no_gccisr_function_p (tree func)
1016 return avr_lookup_function_attribute1 (func, "no_gccisr");
1019 /* Implement `TARGET_SET_CURRENT_FUNCTION'. */
1020 /* Sanity cheching for above function attributes. */
1022 static void
1023 avr_set_current_function (tree decl)
1025 if (decl == NULL_TREE
1026 || current_function_decl == NULL_TREE
1027 || current_function_decl == error_mark_node
1028 || ! cfun->machine
1029 || cfun->machine->attributes_checked_p)
1030 return;
1032 location_t loc = DECL_SOURCE_LOCATION (decl);
1034 cfun->machine->is_naked = avr_naked_function_p (decl);
1035 cfun->machine->is_signal = avr_signal_function_p (decl);
1036 cfun->machine->is_interrupt = avr_interrupt_function_p (decl);
1037 cfun->machine->is_OS_task = avr_OS_task_function_p (decl);
1038 cfun->machine->is_OS_main = avr_OS_main_function_p (decl);
1039 cfun->machine->is_no_gccisr = avr_no_gccisr_function_p (decl);
1041 const char *isr = cfun->machine->is_interrupt ? "interrupt" : "signal";
1043 /* Too much attributes make no sense as they request conflicting features. */
1045 if (cfun->machine->is_OS_task
1046 && (cfun->machine->is_signal || cfun->machine->is_interrupt))
1047 error_at (loc, "function attributes %qs and %qs are mutually exclusive",
1048 "OS_task", isr);
1050 if (cfun->machine->is_OS_main
1051 && (cfun->machine->is_signal || cfun->machine->is_interrupt))
1052 error_at (loc, "function attributes %qs and %qs are mutually exclusive",
1053 "OS_main", isr);
1055 if (cfun->machine->is_interrupt || cfun->machine->is_signal)
1057 tree args = TYPE_ARG_TYPES (TREE_TYPE (decl));
1058 tree ret = TREE_TYPE (TREE_TYPE (decl));
1059 const char *name;
1061 name = DECL_ASSEMBLER_NAME_SET_P (decl)
1062 ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))
1063 : IDENTIFIER_POINTER (DECL_NAME (decl));
1065 /* Skip a leading '*' that might still prefix the assembler name,
1066 e.g. in non-LTO runs. */
1068 name = default_strip_name_encoding (name);
1070 /* Interrupt handlers must be void __vector (void) functions. */
1072 if (args && TREE_CODE (TREE_VALUE (args)) != VOID_TYPE)
1073 error_at (loc, "%qs function cannot have arguments", isr);
1075 if (TREE_CODE (ret) != VOID_TYPE)
1076 error_at (loc, "%qs function cannot return a value", isr);
1078 #if defined WITH_AVRLIBC
1079 /* Silently ignore 'signal' if 'interrupt' is present. AVR-LibC startet
1080 using this when it switched from SIGNAL and INTERRUPT to ISR. */
1082 if (cfun->machine->is_interrupt)
1083 cfun->machine->is_signal = 0;
1085 /* If the function has the 'signal' or 'interrupt' attribute, ensure
1086 that the name of the function is "__vector_NN" so as to catch
1087 when the user misspells the vector name. */
1089 if (!STR_PREFIX_P (name, "__vector"))
1090 warning_at (loc, OPT_Wmisspelled_isr, "%qs appears to be a misspelled "
1091 "%qs handler, missing %<__vector%> prefix", name, isr);
1092 #endif // AVR-LibC naming conventions
1095 #if defined WITH_AVRLIBC
1096 // Common problem is using "ISR" without first including avr/interrupt.h.
1097 const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
1098 name = default_strip_name_encoding (name);
1099 if (strcmp ("ISR", name) == 0
1100 || strcmp ("INTERRUPT", name) == 0
1101 || strcmp ("SIGNAL", name) == 0)
1103 warning_at (loc, OPT_Wmisspelled_isr, "%qs is a reserved identifier"
1104 " in AVR-LibC. Consider %<#include <avr/interrupt.h>%>"
1105 " before using the %qs macro", name, name);
1107 #endif // AVR-LibC naming conventions
1109 /* Don't print the above diagnostics more than once. */
1111 cfun->machine->attributes_checked_p = 1;
1115 /* Implement `ACCUMULATE_OUTGOING_ARGS'. */
1118 avr_accumulate_outgoing_args (void)
1120 if (!cfun)
1121 return TARGET_ACCUMULATE_OUTGOING_ARGS;
1123 /* FIXME: For setjmp and in avr_builtin_setjmp_frame_value we don't know
1124 what offset is correct. In some cases it is relative to
1125 virtual_outgoing_args_rtx and in others it is relative to
1126 virtual_stack_vars_rtx. For example code see
1127 gcc.c-torture/execute/built-in-setjmp.c
1128 gcc.c-torture/execute/builtins/sprintf-chk.c */
1130 return (TARGET_ACCUMULATE_OUTGOING_ARGS
1131 && !(cfun->calls_setjmp
1132 || cfun->has_nonlocal_label));
1136 /* Report contribution of accumulated outgoing arguments to stack size. */
1138 static inline int
1139 avr_outgoing_args_size (void)
1141 return (ACCUMULATE_OUTGOING_ARGS
1142 ? (HOST_WIDE_INT) crtl->outgoing_args_size : 0);
1146 /* Implement TARGET_STARTING_FRAME_OFFSET. */
1147 /* This is the offset from the frame pointer register to the first stack slot
1148 that contains a variable living in the frame. */
1150 static HOST_WIDE_INT
1151 avr_starting_frame_offset (void)
1153 return 1 + avr_outgoing_args_size ();
1157 /* Return the number of hard registers to push/pop in the prologue/epilogue
1158 of the current function, and optionally store these registers in SET. */
1160 static int
1161 avr_regs_to_save (HARD_REG_SET *set)
1163 int count;
1164 int int_or_sig_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1166 if (set)
1167 CLEAR_HARD_REG_SET (*set);
1168 count = 0;
1170 /* No need to save any registers if the function never returns or
1171 has the "OS_task" or "OS_main" attribute. */
1173 if (TREE_THIS_VOLATILE (current_function_decl)
1174 || cfun->machine->is_OS_task
1175 || cfun->machine->is_OS_main)
1176 return 0;
1178 for (int reg = 0; reg < 32; reg++)
1180 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
1181 any global register variables. */
1183 if (fixed_regs[reg])
1184 continue;
1186 if ((int_or_sig_p && !crtl->is_leaf && call_used_regs[reg])
1187 || (df_regs_ever_live_p (reg)
1188 && (int_or_sig_p || !call_used_regs[reg])
1189 /* Don't record frame pointer registers here. They are treated
1190 indivitually in prologue. */
1191 && !(frame_pointer_needed
1192 && (reg == REG_Y || reg == REG_Y + 1))))
1194 if (set)
1195 SET_HARD_REG_BIT (*set, reg);
1196 count++;
1199 return count;
1203 /* Implement `TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS' */
1205 static bool
1206 avr_allocate_stack_slots_for_args (void)
1208 return !cfun->machine->is_naked;
1212 /* Return true if register FROM can be eliminated via register TO. */
1214 static bool
1215 avr_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
1217 return ((frame_pointer_needed && to == FRAME_POINTER_REGNUM)
1218 || !frame_pointer_needed);
1222 /* Implement `TARGET_WARN_FUNC_RETURN'. */
1224 static bool
1225 avr_warn_func_return (tree decl)
1227 /* Naked functions are implemented entirely in assembly, including the
1228 return sequence, so suppress warnings about this. */
1230 return !avr_naked_function_p (decl);
1233 /* Compute offset between arg_pointer and frame_pointer. */
1236 avr_initial_elimination_offset (int from, int to)
1238 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
1239 return 0;
1240 else
1242 int offset = frame_pointer_needed ? 2 : 0;
1243 int avr_pc_size = AVR_HAVE_EIJMP_EICALL ? 3 : 2;
1245 // If FROM is ARG_POINTER_REGNUM, we are not in an ISR as ISRs
1246 // might not have arguments. Hence the following is not affected
1247 // by gasisr prologues.
1248 offset += avr_regs_to_save (NULL);
1249 return (get_frame_size () + avr_outgoing_args_size()
1250 + avr_pc_size + 1 + offset);
1255 /* Helper for the function below. */
1257 static void
1258 avr_adjust_type_node (tree *node, machine_mode mode, int sat_p)
1260 *node = make_node (FIXED_POINT_TYPE);
1261 TYPE_SATURATING (*node) = sat_p;
1262 TYPE_UNSIGNED (*node) = UNSIGNED_FIXED_POINT_MODE_P (mode);
1263 TYPE_IBIT (*node) = GET_MODE_IBIT (mode);
1264 TYPE_FBIT (*node) = GET_MODE_FBIT (mode);
1265 TYPE_PRECISION (*node) = GET_MODE_BITSIZE (mode);
1266 SET_TYPE_ALIGN (*node, 8);
1267 SET_TYPE_MODE (*node, mode);
1269 layout_type (*node);
1273 /* Implement `TARGET_BUILD_BUILTIN_VA_LIST'. */
1275 static tree
1276 avr_build_builtin_va_list (void)
1278 /* avr-modes.def adjusts [U]TA to be 64-bit modes with 48 fractional bits.
1279 This is more appropriate for the 8-bit machine AVR than 128-bit modes.
1280 The ADJUST_IBIT/FBIT are handled in toplev:init_adjust_machine_modes()
1281 which is auto-generated by genmodes, but the compiler assigns [U]DAmode
1282 to the long long accum modes instead of the desired [U]TAmode.
1284 Fix this now, right after node setup in tree.c:build_common_tree_nodes().
1285 This must run before c-cppbuiltin.c:builtin_define_fixed_point_constants()
1286 which built-in defines macros like __ULLACCUM_FBIT__ that are used by
1287 libgcc to detect IBIT and FBIT. */
1289 avr_adjust_type_node (&ta_type_node, TAmode, 0);
1290 avr_adjust_type_node (&uta_type_node, UTAmode, 0);
1291 avr_adjust_type_node (&sat_ta_type_node, TAmode, 1);
1292 avr_adjust_type_node (&sat_uta_type_node, UTAmode, 1);
1294 unsigned_long_long_accum_type_node = uta_type_node;
1295 long_long_accum_type_node = ta_type_node;
1296 sat_unsigned_long_long_accum_type_node = sat_uta_type_node;
1297 sat_long_long_accum_type_node = sat_ta_type_node;
1299 /* Dispatch to the default handler. */
1301 return std_build_builtin_va_list ();
1305 /* Implement `TARGET_BUILTIN_SETJMP_FRAME_VALUE'. */
1306 /* Actual start of frame is virtual_stack_vars_rtx this is offset from
1307 frame pointer by +TARGET_STARTING_FRAME_OFFSET.
1308 Using saved frame = virtual_stack_vars_rtx - TARGET_STARTING_FRAME_OFFSET
1309 avoids creating add/sub of offset in nonlocal goto and setjmp. */
1311 static rtx
1312 avr_builtin_setjmp_frame_value (void)
1314 rtx xval = gen_reg_rtx (Pmode);
1315 emit_insn (gen_subhi3 (xval, virtual_stack_vars_rtx,
1316 gen_int_mode (avr_starting_frame_offset (), Pmode)));
1317 return xval;
1321 /* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3-byte PC).
1322 This is return address of function. */
1325 avr_return_addr_rtx (int count, rtx tem)
1327 rtx r;
1329 /* Can only return this function's return address. Others not supported. */
1330 if (count)
1331 return NULL;
1333 if (AVR_3_BYTE_PC)
1335 r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+2");
1336 warning (0, "%<builtin_return_address%> contains only 2 bytes"
1337 " of address");
1339 else
1340 r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+1");
1342 cfun->machine->use_L__stack_usage = 1;
1344 r = gen_rtx_PLUS (Pmode, tem, r);
1345 r = gen_frame_mem (Pmode, memory_address (Pmode, r));
1346 r = gen_rtx_ROTATE (HImode, r, GEN_INT (8));
1347 return r;
1350 /* Return 1 if the function epilogue is just a single "ret". */
1353 avr_simple_epilogue (void)
1355 return (! frame_pointer_needed
1356 && get_frame_size () == 0
1357 && avr_outgoing_args_size() == 0
1358 && avr_regs_to_save (NULL) == 0
1359 && ! cfun->machine->is_interrupt
1360 && ! cfun->machine->is_signal
1361 && ! cfun->machine->is_naked
1362 && ! TREE_THIS_VOLATILE (current_function_decl));
1365 /* This function checks sequence of live registers. */
1367 static int
1368 sequent_regs_live (void)
1370 int live_seq = 0;
1371 int cur_seq = 0;
1373 for (int reg = 0; reg <= LAST_CALLEE_SAVED_REG; ++reg)
1375 if (fixed_regs[reg])
1377 /* Don't recognize sequences that contain global register
1378 variables. */
1380 if (live_seq != 0)
1381 return 0;
1382 else
1383 continue;
1386 if (!call_used_regs[reg])
1388 if (df_regs_ever_live_p (reg))
1390 ++live_seq;
1391 ++cur_seq;
1393 else
1394 cur_seq = 0;
1398 if (!frame_pointer_needed)
1400 if (df_regs_ever_live_p (REG_Y))
1402 ++live_seq;
1403 ++cur_seq;
1405 else
1406 cur_seq = 0;
1408 if (df_regs_ever_live_p (REG_Y + 1))
1410 ++live_seq;
1411 ++cur_seq;
1413 else
1414 cur_seq = 0;
1416 else
1418 cur_seq += 2;
1419 live_seq += 2;
1421 return (cur_seq == live_seq) ? live_seq : 0;
1424 namespace {
1425 static const pass_data avr_pass_data_pre_proep =
1427 RTL_PASS, // type
1428 "", // name (will be patched)
1429 OPTGROUP_NONE, // optinfo_flags
1430 TV_DF_SCAN, // tv_id
1431 0, // properties_required
1432 0, // properties_provided
1433 0, // properties_destroyed
1434 0, // todo_flags_start
1435 0 // todo_flags_finish
1439 class avr_pass_pre_proep : public rtl_opt_pass
1441 public:
1442 avr_pass_pre_proep (gcc::context *ctxt, const char *name)
1443 : rtl_opt_pass (avr_pass_data_pre_proep, ctxt)
1445 this->name = name;
1448 void compute_maybe_gasisr (function*);
1450 virtual unsigned int execute (function *fun)
1452 if (avr_gasisr_prologues
1453 // Whether this function is an ISR worth scanning at all.
1454 && !fun->machine->is_no_gccisr
1455 && (fun->machine->is_interrupt
1456 || fun->machine->is_signal)
1457 && !cfun->machine->is_naked
1458 // Paranoia: Non-local gotos and labels that might escape.
1459 && !cfun->calls_setjmp
1460 && !cfun->has_nonlocal_label
1461 && !cfun->has_forced_label_in_static)
1463 compute_maybe_gasisr (fun);
1466 return 0;
1469 }; // avr_pass_pre_proep
1471 } // anon namespace
1473 rtl_opt_pass*
1474 make_avr_pass_pre_proep (gcc::context *ctxt)
1476 return new avr_pass_pre_proep (ctxt, "avr-pre-proep");
1480 /* Set fun->machine->gasisr.maybe provided we don't find anything that
1481 prohibits GAS generating parts of ISR prologues / epilogues for us. */
1483 void
1484 avr_pass_pre_proep::compute_maybe_gasisr (function *fun)
1486 // Don't use BB iterators so that we see JUMP_TABLE_DATA.
1488 for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
1490 // Transparent calls always use [R]CALL and are filtered out by GAS.
1491 // ISRs don't use -mcall-prologues, hence what remains to be filtered
1492 // out are open coded (tail) calls.
1494 if (CALL_P (insn))
1495 return;
1497 // __tablejump2__ clobbers something and is targeted by JMP so
1498 // that GAS won't see its usage.
1500 if (AVR_HAVE_JMP_CALL
1501 && JUMP_TABLE_DATA_P (insn))
1502 return;
1504 // Non-local gotos not seen in *FUN.
1506 if (JUMP_P (insn)
1507 && find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
1508 return;
1511 fun->machine->gasisr.maybe = 1;
1515 /* Obtain the length sequence of insns. */
1518 get_sequence_length (rtx_insn *insns)
1520 int length = 0;
1522 for (rtx_insn *insn = insns; insn; insn = NEXT_INSN (insn))
1523 length += get_attr_length (insn);
1525 return length;
1529 /* Implement `INCOMING_RETURN_ADDR_RTX'. */
1532 avr_incoming_return_addr_rtx (void)
1534 /* The return address is at the top of the stack. Note that the push
1535 was via post-decrement, which means the actual address is off by one. */
1536 return gen_frame_mem (HImode, plus_constant (Pmode, stack_pointer_rtx, 1));
1540 /* Unset a bit in *SET. If successful, return the respective bit number.
1541 Otherwise, return -1 and *SET is unaltered. */
1543 static int
1544 avr_hregs_split_reg (HARD_REG_SET *set)
1546 for (int regno = 0; regno < 32; regno++)
1547 if (TEST_HARD_REG_BIT (*set, regno))
1549 // Don't remove a register from *SET which might indicate that
1550 // some RAMP* register might need ISR prologue / epilogue treatment.
1552 if (AVR_HAVE_RAMPX
1553 && (REG_X == regno || REG_X + 1 == regno)
1554 && TEST_HARD_REG_BIT (*set, REG_X)
1555 && TEST_HARD_REG_BIT (*set, REG_X + 1))
1556 continue;
1558 if (AVR_HAVE_RAMPY
1559 && !frame_pointer_needed
1560 && (REG_Y == regno || REG_Y + 1 == regno)
1561 && TEST_HARD_REG_BIT (*set, REG_Y)
1562 && TEST_HARD_REG_BIT (*set, REG_Y + 1))
1563 continue;
1565 if (AVR_HAVE_RAMPZ
1566 && (REG_Z == regno || REG_Z + 1 == regno)
1567 && TEST_HARD_REG_BIT (*set, REG_Z)
1568 && TEST_HARD_REG_BIT (*set, REG_Z + 1))
1569 continue;
1571 CLEAR_HARD_REG_BIT (*set, regno);
1572 return regno;
1575 return -1;
1579 /* Helper for expand_prologue. Emit a push of a byte register. */
1581 static void
1582 emit_push_byte (unsigned regno, bool frame_related_p)
1584 rtx mem, reg;
1585 rtx_insn *insn;
1587 mem = gen_rtx_POST_DEC (HImode, stack_pointer_rtx);
1588 mem = gen_frame_mem (QImode, mem);
1589 reg = gen_rtx_REG (QImode, regno);
1591 insn = emit_insn (gen_rtx_SET (mem, reg));
1592 if (frame_related_p)
1593 RTX_FRAME_RELATED_P (insn) = 1;
1595 cfun->machine->stack_usage++;
1599 /* Helper for expand_prologue. Emit a push of a SFR via register TREG.
1600 SFR is a MEM representing the memory location of the SFR.
1601 If CLR_P then clear the SFR after the push using zero_reg. */
1603 static void
1604 emit_push_sfr (rtx sfr, bool frame_related_p, bool clr_p, int treg)
1606 rtx_insn *insn;
1608 gcc_assert (MEM_P (sfr));
1610 /* IN treg, IO(SFR) */
1611 insn = emit_move_insn (all_regs_rtx[treg], sfr);
1612 if (frame_related_p)
1613 RTX_FRAME_RELATED_P (insn) = 1;
1615 /* PUSH treg */
1616 emit_push_byte (treg, frame_related_p);
1618 if (clr_p)
1620 /* OUT IO(SFR), __zero_reg__ */
1621 insn = emit_move_insn (sfr, const0_rtx);
1622 if (frame_related_p)
1623 RTX_FRAME_RELATED_P (insn) = 1;
1627 static void
1628 avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
1630 rtx_insn *insn;
1631 bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1632 int live_seq = sequent_regs_live ();
1634 HOST_WIDE_INT size_max
1635 = (HOST_WIDE_INT) GET_MODE_MASK (AVR_HAVE_8BIT_SP ? QImode : Pmode);
1637 bool minimize = (TARGET_CALL_PROLOGUES
1638 && size < size_max
1639 && live_seq
1640 && !isr_p
1641 && !cfun->machine->is_OS_task
1642 && !cfun->machine->is_OS_main
1643 && !AVR_TINY);
1645 if (minimize
1646 && (frame_pointer_needed
1647 || avr_outgoing_args_size() > 8
1648 || (AVR_2_BYTE_PC && live_seq > 6)
1649 || live_seq > 7))
1651 rtx pattern;
1652 int first_reg, reg, offset;
1654 emit_move_insn (gen_rtx_REG (HImode, REG_X),
1655 gen_int_mode (size, HImode));
1657 pattern = gen_call_prologue_saves (gen_int_mode (live_seq, HImode),
1658 gen_int_mode (live_seq+size, HImode));
1659 insn = emit_insn (pattern);
1660 RTX_FRAME_RELATED_P (insn) = 1;
1662 /* Describe the effect of the unspec_volatile call to prologue_saves.
1663 Note that this formulation assumes that add_reg_note pushes the
1664 notes to the front. Thus we build them in the reverse order of
1665 how we want dwarf2out to process them. */
1667 /* The function does always set frame_pointer_rtx, but whether that
1668 is going to be permanent in the function is frame_pointer_needed. */
1670 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1671 gen_rtx_SET ((frame_pointer_needed
1672 ? frame_pointer_rtx
1673 : stack_pointer_rtx),
1674 plus_constant (Pmode, stack_pointer_rtx,
1675 -(size + live_seq))));
1677 /* Note that live_seq always contains r28+r29, but the other
1678 registers to be saved are all below 18. */
1680 first_reg = (LAST_CALLEE_SAVED_REG + 1) - (live_seq - 2);
1682 for (reg = 29, offset = -live_seq + 1;
1683 reg >= first_reg;
1684 reg = (reg == 28 ? LAST_CALLEE_SAVED_REG : reg - 1), ++offset)
1686 rtx m, r;
1688 m = gen_rtx_MEM (QImode, plus_constant (Pmode, stack_pointer_rtx,
1689 offset));
1690 r = gen_rtx_REG (QImode, reg);
1691 add_reg_note (insn, REG_CFA_OFFSET, gen_rtx_SET (m, r));
1694 cfun->machine->stack_usage += size + live_seq;
1696 else /* !minimize */
1698 for (int reg = 0; reg < 32; ++reg)
1699 if (TEST_HARD_REG_BIT (set, reg))
1700 emit_push_byte (reg, true);
1702 if (frame_pointer_needed
1703 && (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main)))
1705 /* Push frame pointer. Always be consistent about the
1706 ordering of pushes -- epilogue_restores expects the
1707 register pair to be pushed low byte first. */
1709 emit_push_byte (REG_Y, true);
1710 emit_push_byte (REG_Y + 1, true);
1713 if (frame_pointer_needed
1714 && size == 0)
1716 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
1717 RTX_FRAME_RELATED_P (insn) = 1;
1720 if (size != 0)
1722 /* Creating a frame can be done by direct manipulation of the
1723 stack or via the frame pointer. These two methods are:
1724 fp = sp
1725 fp -= size
1726 sp = fp
1728 sp -= size
1729 fp = sp (*)
1730 the optimum method depends on function type, stack and
1731 frame size. To avoid a complex logic, both methods are
1732 tested and shortest is selected.
1734 There is also the case where SIZE != 0 and no frame pointer is
1735 needed; this can occur if ACCUMULATE_OUTGOING_ARGS is on.
1736 In that case, insn (*) is not needed in that case.
1737 We use the X register as scratch. This is save because in X
1738 is call-clobbered.
1739 In an interrupt routine, the case of SIZE != 0 together with
1740 !frame_pointer_needed can only occur if the function is not a
1741 leaf function and thus X has already been saved. */
1743 int irq_state = -1;
1744 HOST_WIDE_INT size_cfa = size, neg_size;
1745 rtx_insn *fp_plus_insns;
1746 rtx fp, my_fp;
1748 gcc_assert (frame_pointer_needed
1749 || !isr_p
1750 || !crtl->is_leaf);
1752 fp = my_fp = (frame_pointer_needed
1753 ? frame_pointer_rtx
1754 : gen_rtx_REG (Pmode, REG_X));
1756 if (AVR_HAVE_8BIT_SP)
1758 /* The high byte (r29) does not change:
1759 Prefer SUBI (1 cycle) over SBIW (2 cycles, same size). */
1761 my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
1764 /* Cut down size and avoid size = 0 so that we don't run
1765 into ICE like PR52488 in the remainder. */
1767 if (size > size_max)
1769 /* Don't error so that insane code from newlib still compiles
1770 and does not break building newlib. As PR51345 is implemented
1771 now, there are multilib variants with -msp8.
1773 If user wants sanity checks he can use -Wstack-usage=
1774 or similar options.
1776 For CFA we emit the original, non-saturated size so that
1777 the generic machinery is aware of the real stack usage and
1778 will print the above diagnostic as expected. */
1780 size = size_max;
1783 size = trunc_int_for_mode (size, GET_MODE (my_fp));
1784 neg_size = trunc_int_for_mode (-size, GET_MODE (my_fp));
1786 /************ Method 1: Adjust frame pointer ************/
1788 start_sequence ();
1790 /* Normally, the dwarf2out frame-related-expr interpreter does
1791 not expect to have the CFA change once the frame pointer is
1792 set up. Thus, we avoid marking the move insn below and
1793 instead indicate that the entire operation is complete after
1794 the frame pointer subtraction is done. */
1796 insn = emit_move_insn (fp, stack_pointer_rtx);
1797 if (frame_pointer_needed)
1799 RTX_FRAME_RELATED_P (insn) = 1;
1800 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1801 gen_rtx_SET (fp, stack_pointer_rtx));
1804 insn = emit_move_insn (my_fp, plus_constant (GET_MODE (my_fp),
1805 my_fp, neg_size));
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, plus_constant (Pmode, fp,
1812 -size_cfa)));
1815 /* Copy to stack pointer. Note that since we've already
1816 changed the CFA to the frame pointer this operation
1817 need not be annotated if frame pointer is needed.
1818 Always move through unspec, see PR50063.
1819 For meaning of irq_state see movhi_sp_r insn. */
1821 if (cfun->machine->is_interrupt)
1822 irq_state = 1;
1824 if (TARGET_NO_INTERRUPTS
1825 || cfun->machine->is_signal
1826 || cfun->machine->is_OS_main)
1827 irq_state = 0;
1829 if (AVR_HAVE_8BIT_SP)
1830 irq_state = 2;
1832 insn = emit_insn (gen_movhi_sp_r (stack_pointer_rtx,
1833 fp, GEN_INT (irq_state)));
1834 if (!frame_pointer_needed)
1836 RTX_FRAME_RELATED_P (insn) = 1;
1837 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1838 gen_rtx_SET (stack_pointer_rtx,
1839 plus_constant (Pmode,
1840 stack_pointer_rtx,
1841 -size_cfa)));
1844 fp_plus_insns = get_insns ();
1845 end_sequence ();
1847 /************ Method 2: Adjust Stack pointer ************/
1849 /* Stack adjustment by means of RCALL . and/or PUSH __TMP_REG__
1850 can only handle specific offsets. */
1852 int n_rcall = size / (AVR_3_BYTE_PC ? 3 : 2);
1854 if (avr_sp_immediate_operand (gen_int_mode (-size, HImode), HImode)
1855 // Don't use more than 3 RCALLs.
1856 && n_rcall <= 3)
1858 rtx_insn *sp_plus_insns;
1860 start_sequence ();
1862 insn = emit_move_insn (stack_pointer_rtx,
1863 plus_constant (Pmode, stack_pointer_rtx,
1864 -size));
1865 RTX_FRAME_RELATED_P (insn) = 1;
1866 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1867 gen_rtx_SET (stack_pointer_rtx,
1868 plus_constant (Pmode,
1869 stack_pointer_rtx,
1870 -size_cfa)));
1871 if (frame_pointer_needed)
1873 insn = emit_move_insn (fp, stack_pointer_rtx);
1874 RTX_FRAME_RELATED_P (insn) = 1;
1877 sp_plus_insns = get_insns ();
1878 end_sequence ();
1880 /************ Use shortest method ************/
1882 emit_insn (get_sequence_length (sp_plus_insns)
1883 < get_sequence_length (fp_plus_insns)
1884 ? sp_plus_insns
1885 : fp_plus_insns);
1887 else
1889 emit_insn (fp_plus_insns);
1892 cfun->machine->stack_usage += size_cfa;
1893 } /* !minimize && size != 0 */
1894 } /* !minimize */
1898 /* Output function prologue. */
1900 void
1901 avr_expand_prologue (void)
1903 HARD_REG_SET set;
1904 HOST_WIDE_INT size;
1906 size = get_frame_size() + avr_outgoing_args_size();
1908 cfun->machine->stack_usage = 0;
1910 /* Prologue: naked. */
1911 if (cfun->machine->is_naked)
1913 return;
1916 avr_regs_to_save (&set);
1918 if (cfun->machine->is_interrupt || cfun->machine->is_signal)
1920 int treg = AVR_TMP_REGNO;
1921 /* Enable interrupts. */
1922 if (cfun->machine->is_interrupt)
1923 emit_insn (gen_enable_interrupt ());
1925 if (cfun->machine->gasisr.maybe)
1927 /* Let GAS PR21472 emit prologue preamble for us which handles SREG,
1928 ZERO_REG and TMP_REG and one additional, optional register for
1929 us in an optimal way. This even scans through inline asm. */
1931 cfun->machine->gasisr.yes = 1;
1933 // The optional reg or TMP_REG if we don't need one. If we need one,
1934 // remove that reg from SET so that it's not puhed / popped twice.
1935 // We also use it below instead of TMP_REG in some places.
1937 treg = avr_hregs_split_reg (&set);
1938 if (treg < 0)
1939 treg = AVR_TMP_REGNO;
1940 cfun->machine->gasisr.regno = treg;
1942 // The worst case of pushes. The exact number can be inferred
1943 // at assembly time by magic expression __gcc_isr.n_pushed.
1944 cfun->machine->stack_usage += 3 + (treg != AVR_TMP_REGNO);
1946 // Emit a Prologue chunk. Epilogue chunk(s) might follow.
1947 // The final Done chunk is emit by final postscan.
1948 emit_insn (gen_gasisr (GEN_INT (GASISR_Prologue), GEN_INT (treg)));
1950 else // !TARGET_GASISR_PROLOGUES: Classic, dumb prologue preamble.
1952 /* Push zero reg. */
1953 emit_push_byte (AVR_ZERO_REGNO, true);
1955 /* Push tmp reg. */
1956 emit_push_byte (AVR_TMP_REGNO, true);
1958 /* Push SREG. */
1959 /* ??? There's no dwarf2 column reserved for SREG. */
1960 emit_push_sfr (sreg_rtx, false, false /* clr */, AVR_TMP_REGNO);
1962 /* Clear zero reg. */
1963 emit_move_insn (zero_reg_rtx, const0_rtx);
1965 /* Prevent any attempt to delete the setting of ZERO_REG! */
1966 emit_use (zero_reg_rtx);
1969 /* Push and clear RAMPD/X/Y/Z if present and low-part register is used.
1970 ??? There are no dwarf2 columns reserved for RAMPD/X/Y/Z. */
1972 if (AVR_HAVE_RAMPD)
1973 emit_push_sfr (rampd_rtx, false /* frame */, true /* clr */, treg);
1975 if (AVR_HAVE_RAMPX
1976 && TEST_HARD_REG_BIT (set, REG_X)
1977 && TEST_HARD_REG_BIT (set, REG_X + 1))
1979 emit_push_sfr (rampx_rtx, false /* frame */, true /* clr */, treg);
1982 if (AVR_HAVE_RAMPY
1983 && (frame_pointer_needed
1984 || (TEST_HARD_REG_BIT (set, REG_Y)
1985 && TEST_HARD_REG_BIT (set, REG_Y + 1))))
1987 emit_push_sfr (rampy_rtx, false /* frame */, true /* clr */, treg);
1990 if (AVR_HAVE_RAMPZ
1991 && TEST_HARD_REG_BIT (set, REG_Z)
1992 && TEST_HARD_REG_BIT (set, REG_Z + 1))
1994 emit_push_sfr (rampz_rtx, false /* frame */, AVR_HAVE_RAMPD, treg);
1996 } /* is_interrupt is_signal */
1998 avr_prologue_setup_frame (size, set);
2000 if (flag_stack_usage_info)
2001 current_function_static_stack_size
2002 = cfun->machine->stack_usage + INCOMING_FRAME_SP_OFFSET;
2006 /* Implement `TARGET_ASM_FUNCTION_END_PROLOGUE'. */
2007 /* Output summary at end of function prologue. */
2009 static void
2010 avr_asm_function_end_prologue (FILE *file)
2012 if (cfun->machine->is_naked)
2014 fputs ("/* prologue: naked */\n", file);
2016 else
2018 if (cfun->machine->is_interrupt)
2020 fputs ("/* prologue: Interrupt */\n", file);
2022 else if (cfun->machine->is_signal)
2024 fputs ("/* prologue: Signal */\n", file);
2026 else
2027 fputs ("/* prologue: function */\n", file);
2030 if (ACCUMULATE_OUTGOING_ARGS)
2031 fprintf (file, "/* outgoing args size = %d */\n",
2032 avr_outgoing_args_size());
2034 fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n",
2035 (HOST_WIDE_INT) get_frame_size());
2037 if (!cfun->machine->gasisr.yes)
2039 fprintf (file, "/* stack size = %d */\n", cfun->machine->stack_usage);
2040 // Create symbol stack offset so all functions have it. Add 1 to stack
2041 // usage for offset so that SP + .L__stack_offset = return address.
2042 fprintf (file, ".L__stack_usage = %d\n", cfun->machine->stack_usage);
2044 else
2046 int used_by_gasisr = 3 + (cfun->machine->gasisr.regno != AVR_TMP_REGNO);
2047 int to = cfun->machine->stack_usage;
2048 int from = to - used_by_gasisr;
2049 // Number of pushed regs is only known at assembly-time.
2050 fprintf (file, "/* stack size = %d...%d */\n", from , to);
2051 fprintf (file, ".L__stack_usage = %d + __gcc_isr.n_pushed\n", from);
2056 /* Implement `EPILOGUE_USES'. */
2059 avr_epilogue_uses (int regno ATTRIBUTE_UNUSED)
2061 if (reload_completed
2062 && cfun->machine
2063 && (cfun->machine->is_interrupt || cfun->machine->is_signal))
2064 return 1;
2065 return 0;
2068 /* Helper for avr_expand_epilogue. Emit a pop of a byte register. */
2070 static void
2071 emit_pop_byte (unsigned regno)
2073 rtx mem, reg;
2075 mem = gen_rtx_PRE_INC (HImode, stack_pointer_rtx);
2076 mem = gen_frame_mem (QImode, mem);
2077 reg = gen_rtx_REG (QImode, regno);
2079 emit_insn (gen_rtx_SET (reg, mem));
2082 /* Output RTL epilogue. */
2084 void
2085 avr_expand_epilogue (bool sibcall_p)
2087 int live_seq;
2088 HARD_REG_SET set;
2089 int minimize;
2090 HOST_WIDE_INT size;
2091 bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
2093 size = get_frame_size() + avr_outgoing_args_size();
2095 /* epilogue: naked */
2096 if (cfun->machine->is_naked)
2098 gcc_assert (!sibcall_p);
2100 emit_jump_insn (gen_return ());
2101 return;
2104 avr_regs_to_save (&set);
2105 live_seq = sequent_regs_live ();
2107 minimize = (TARGET_CALL_PROLOGUES
2108 && live_seq
2109 && !isr_p
2110 && !cfun->machine->is_OS_task
2111 && !cfun->machine->is_OS_main
2112 && !AVR_TINY);
2114 if (minimize
2115 && (live_seq > 4
2116 || frame_pointer_needed
2117 || size))
2119 /* Get rid of frame. */
2121 if (!frame_pointer_needed)
2123 emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
2126 if (size)
2128 emit_move_insn (frame_pointer_rtx,
2129 plus_constant (Pmode, frame_pointer_rtx, size));
2132 emit_insn (gen_epilogue_restores (gen_int_mode (live_seq, HImode)));
2133 return;
2136 if (size)
2138 /* Try two methods to adjust stack and select shortest. */
2140 int irq_state = -1;
2141 rtx fp, my_fp;
2142 rtx_insn *fp_plus_insns;
2143 HOST_WIDE_INT size_max;
2145 gcc_assert (frame_pointer_needed
2146 || !isr_p
2147 || !crtl->is_leaf);
2149 fp = my_fp = (frame_pointer_needed
2150 ? frame_pointer_rtx
2151 : gen_rtx_REG (Pmode, REG_X));
2153 if (AVR_HAVE_8BIT_SP)
2155 /* The high byte (r29) does not change:
2156 Prefer SUBI (1 cycle) over SBIW (2 cycles). */
2158 my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
2161 /* For rationale see comment in prologue generation. */
2163 size_max = (HOST_WIDE_INT) GET_MODE_MASK (GET_MODE (my_fp));
2164 if (size > size_max)
2165 size = size_max;
2166 size = trunc_int_for_mode (size, GET_MODE (my_fp));
2168 /********** Method 1: Adjust fp register **********/
2170 start_sequence ();
2172 if (!frame_pointer_needed)
2173 emit_move_insn (fp, stack_pointer_rtx);
2175 emit_move_insn (my_fp, plus_constant (GET_MODE (my_fp), my_fp, size));
2177 /* Copy to stack pointer. */
2179 if (TARGET_NO_INTERRUPTS)
2180 irq_state = 0;
2182 if (AVR_HAVE_8BIT_SP)
2183 irq_state = 2;
2185 emit_insn (gen_movhi_sp_r (stack_pointer_rtx, fp,
2186 GEN_INT (irq_state)));
2188 fp_plus_insns = get_insns ();
2189 end_sequence ();
2191 /********** Method 2: Adjust Stack pointer **********/
2193 if (avr_sp_immediate_operand (gen_int_mode (size, HImode), HImode))
2195 rtx_insn *sp_plus_insns;
2197 start_sequence ();
2199 emit_move_insn (stack_pointer_rtx,
2200 plus_constant (Pmode, stack_pointer_rtx, size));
2202 sp_plus_insns = get_insns ();
2203 end_sequence ();
2205 /************ Use shortest method ************/
2207 emit_insn (get_sequence_length (sp_plus_insns)
2208 < get_sequence_length (fp_plus_insns)
2209 ? sp_plus_insns
2210 : fp_plus_insns);
2212 else
2213 emit_insn (fp_plus_insns);
2214 } /* size != 0 */
2216 if (frame_pointer_needed
2217 && !(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
2219 /* Restore previous frame_pointer. See avr_expand_prologue for
2220 rationale for not using pophi. */
2222 emit_pop_byte (REG_Y + 1);
2223 emit_pop_byte (REG_Y);
2226 /* Restore used registers. */
2228 int treg = AVR_TMP_REGNO;
2230 if (isr_p
2231 && cfun->machine->gasisr.yes)
2233 treg = cfun->machine->gasisr.regno;
2234 CLEAR_HARD_REG_BIT (set, treg);
2237 for (int reg = 31; reg >= 0; --reg)
2238 if (TEST_HARD_REG_BIT (set, reg))
2239 emit_pop_byte (reg);
2241 if (isr_p)
2243 /* Restore RAMPZ/Y/X/D using tmp_reg as scratch.
2244 The conditions to restore them must be tha same as in prologue. */
2246 if (AVR_HAVE_RAMPZ
2247 && TEST_HARD_REG_BIT (set, REG_Z)
2248 && TEST_HARD_REG_BIT (set, REG_Z + 1))
2250 emit_pop_byte (treg);
2251 emit_move_insn (rampz_rtx, all_regs_rtx[treg]);
2254 if (AVR_HAVE_RAMPY
2255 && (frame_pointer_needed
2256 || (TEST_HARD_REG_BIT (set, REG_Y)
2257 && TEST_HARD_REG_BIT (set, REG_Y + 1))))
2259 emit_pop_byte (treg);
2260 emit_move_insn (rampy_rtx, all_regs_rtx[treg]);
2263 if (AVR_HAVE_RAMPX
2264 && TEST_HARD_REG_BIT (set, REG_X)
2265 && TEST_HARD_REG_BIT (set, REG_X + 1))
2267 emit_pop_byte (treg);
2268 emit_move_insn (rampx_rtx, all_regs_rtx[treg]);
2271 if (AVR_HAVE_RAMPD)
2273 emit_pop_byte (treg);
2274 emit_move_insn (rampd_rtx, all_regs_rtx[treg]);
2277 if (cfun->machine->gasisr.yes)
2279 // Emit an Epilogue chunk.
2280 emit_insn (gen_gasisr (GEN_INT (GASISR_Epilogue),
2281 GEN_INT (cfun->machine->gasisr.regno)));
2283 else // !TARGET_GASISR_PROLOGUES
2285 /* Restore SREG using tmp_reg as scratch. */
2287 emit_pop_byte (AVR_TMP_REGNO);
2288 emit_move_insn (sreg_rtx, tmp_reg_rtx);
2290 /* Restore tmp REG. */
2291 emit_pop_byte (AVR_TMP_REGNO);
2293 /* Restore zero REG. */
2294 emit_pop_byte (AVR_ZERO_REGNO);
2298 if (!sibcall_p)
2299 emit_jump_insn (gen_return ());
2303 /* Implement `TARGET_ASM_FUNCTION_BEGIN_EPILOGUE'. */
2305 static void
2306 avr_asm_function_begin_epilogue (FILE *file)
2308 app_disable();
2309 fprintf (file, "/* epilogue start */\n");
2313 /* Implement `TARGET_CANNOT_MODITY_JUMPS_P'. */
2315 static bool
2316 avr_cannot_modify_jumps_p (void)
2318 /* Naked Functions must not have any instructions after
2319 their epilogue, see PR42240 */
2321 if (reload_completed
2322 && cfun->machine
2323 && cfun->machine->is_naked)
2325 return true;
2328 return false;
2332 /* Implement `TARGET_MODE_DEPENDENT_ADDRESS_P'. */
2334 static bool
2335 avr_mode_dependent_address_p (const_rtx addr ATTRIBUTE_UNUSED, addr_space_t as)
2337 /* FIXME: Non-generic addresses are not mode-dependent in themselves.
2338 This hook just serves to hack around PR rtl-optimization/52543 by
2339 claiming that non-generic addresses were mode-dependent so that
2340 lower-subreg.c will skip these addresses. lower-subreg.c sets up fake
2341 RTXes to probe SET and MEM costs and assumes that MEM is always in the
2342 generic address space which is not true. */
2344 return !ADDR_SPACE_GENERIC_P (as);
2348 /* Return true if rtx X is a CONST_INT, CONST or SYMBOL_REF
2349 address with the `absdata' variable attribute, i.e. respective
2350 data can be read / written by LDS / STS instruction.
2351 This is used only for AVR_TINY. */
2353 static bool
2354 avr_address_tiny_absdata_p (rtx x, machine_mode mode)
2356 if (CONST == GET_CODE (x))
2357 x = XEXP (XEXP (x, 0), 0);
2359 if (SYMBOL_REF_P (x))
2360 return SYMBOL_REF_FLAGS (x) & AVR_SYMBOL_FLAG_TINY_ABSDATA;
2362 if (CONST_INT_P (x)
2363 && IN_RANGE (INTVAL (x), 0, 0xc0 - GET_MODE_SIZE (mode)))
2364 return true;
2366 return false;
2370 /* Helper function for `avr_legitimate_address_p'. */
2372 static inline bool
2373 avr_reg_ok_for_addr_p (rtx reg, addr_space_t as,
2374 RTX_CODE outer_code, bool strict)
2376 return (REG_P (reg)
2377 && (avr_regno_mode_code_ok_for_base_p (REGNO (reg), QImode,
2378 as, outer_code, UNKNOWN)
2379 || (!strict
2380 && REGNO (reg) >= FIRST_PSEUDO_REGISTER)));
2384 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
2385 machine for a memory operand of mode MODE. */
2387 static bool
2388 avr_legitimate_address_p (machine_mode mode, rtx x, bool strict)
2390 bool ok = CONSTANT_ADDRESS_P (x);
2392 switch (GET_CODE (x))
2394 case REG:
2395 ok = avr_reg_ok_for_addr_p (x, ADDR_SPACE_GENERIC,
2396 MEM, strict);
2398 if (strict
2399 && GET_MODE_SIZE (mode) > 4
2400 && REG_X == REGNO (x))
2402 ok = false;
2404 break;
2406 case POST_INC:
2407 case PRE_DEC:
2408 ok = avr_reg_ok_for_addr_p (XEXP (x, 0), ADDR_SPACE_GENERIC,
2409 GET_CODE (x), strict);
2410 break;
2412 case PLUS:
2414 rtx reg = XEXP (x, 0);
2415 rtx op1 = XEXP (x, 1);
2417 if (REG_P (reg)
2418 && CONST_INT_P (op1)
2419 && INTVAL (op1) >= 0)
2421 bool fit = IN_RANGE (INTVAL (op1), 0, MAX_LD_OFFSET (mode));
2423 if (fit)
2425 ok = (! strict
2426 || avr_reg_ok_for_addr_p (reg, ADDR_SPACE_GENERIC,
2427 PLUS, strict));
2429 if (reg == frame_pointer_rtx
2430 || reg == arg_pointer_rtx)
2432 ok = true;
2435 else if (frame_pointer_needed
2436 && reg == frame_pointer_rtx)
2438 ok = true;
2442 break;
2444 default:
2445 break;
2448 if (AVR_TINY
2449 && CONSTANT_ADDRESS_P (x))
2451 /* avrtiny's load / store instructions only cover addresses 0..0xbf:
2452 IN / OUT range is 0..0x3f and LDS / STS can access 0x40..0xbf. */
2454 ok = avr_address_tiny_absdata_p (x, mode);
2457 if (avr_log.legitimate_address_p)
2459 avr_edump ("\n%?: ret=%d, mode=%m strict=%d "
2460 "reload_completed=%d reload_in_progress=%d %s:",
2461 ok, mode, strict, reload_completed, reload_in_progress,
2462 reg_renumber ? "(reg_renumber)" : "");
2464 if (GET_CODE (x) == PLUS
2465 && REG_P (XEXP (x, 0))
2466 && CONST_INT_P (XEXP (x, 1))
2467 && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
2468 && reg_renumber)
2470 avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
2471 true_regnum (XEXP (x, 0)));
2474 avr_edump ("\n%r\n", x);
2477 return ok;
2481 /* Former implementation of TARGET_LEGITIMIZE_ADDRESS,
2482 now only a helper for avr_addr_space_legitimize_address. */
2483 /* Attempts to replace X with a valid
2484 memory address for an operand of mode MODE */
2486 static rtx
2487 avr_legitimize_address (rtx x, rtx oldx, machine_mode mode)
2489 bool big_offset_p = false;
2491 x = oldx;
2493 if (AVR_TINY)
2495 if (CONSTANT_ADDRESS_P (x)
2496 && ! avr_address_tiny_absdata_p (x, mode))
2498 x = force_reg (Pmode, x);
2502 if (GET_CODE (oldx) == PLUS
2503 && REG_P (XEXP (oldx, 0)))
2505 if (REG_P (XEXP (oldx, 1)))
2506 x = force_reg (GET_MODE (oldx), oldx);
2507 else if (CONST_INT_P (XEXP (oldx, 1)))
2509 int offs = INTVAL (XEXP (oldx, 1));
2510 if (frame_pointer_rtx != XEXP (oldx, 0)
2511 && offs > MAX_LD_OFFSET (mode))
2513 big_offset_p = true;
2514 x = force_reg (GET_MODE (oldx), oldx);
2519 if (avr_log.legitimize_address)
2521 avr_edump ("\n%?: mode=%m\n %r\n", mode, oldx);
2523 if (x != oldx)
2524 avr_edump (" %s --> %r\n", big_offset_p ? "(big offset)" : "", x);
2527 return x;
2531 /* Implement `LEGITIMIZE_RELOAD_ADDRESS'. */
2532 /* This will allow register R26/27 to be used where it is no worse than normal
2533 base pointers R28/29 or R30/31. For example, if base offset is greater
2534 than 63 bytes or for R++ or --R addressing. */
2537 avr_legitimize_reload_address (rtx *px, machine_mode mode,
2538 int opnum, int type, int addr_type,
2539 int ind_levels ATTRIBUTE_UNUSED,
2540 rtx (*mk_memloc)(rtx,int))
2542 rtx x = *px;
2544 if (avr_log.legitimize_reload_address)
2545 avr_edump ("\n%?:%m %r\n", mode, x);
2547 if (1 && (GET_CODE (x) == POST_INC
2548 || GET_CODE (x) == PRE_DEC))
2550 push_reload (XEXP (x, 0), XEXP (x, 0), &XEXP (x, 0), &XEXP (x, 0),
2551 POINTER_REGS, GET_MODE (x), GET_MODE (x), 0, 0,
2552 opnum, RELOAD_OTHER);
2554 if (avr_log.legitimize_reload_address)
2555 avr_edump (" RCLASS.1 = %R\n IN = %r\n OUT = %r\n",
2556 POINTER_REGS, XEXP (x, 0), XEXP (x, 0));
2558 return x;
2561 if (GET_CODE (x) == PLUS
2562 && REG_P (XEXP (x, 0))
2563 && reg_equiv_constant (REGNO (XEXP (x, 0))) == 0
2564 && CONST_INT_P (XEXP (x, 1))
2565 && INTVAL (XEXP (x, 1)) >= 1)
2567 bool fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
2569 if (fit)
2571 if (reg_equiv_address (REGNO (XEXP (x, 0))) != 0)
2573 int regno = REGNO (XEXP (x, 0));
2574 rtx mem = mk_memloc (x, regno);
2576 push_reload (XEXP (mem, 0), NULL_RTX, &XEXP (mem, 0), NULL,
2577 POINTER_REGS, Pmode, VOIDmode, 0, 0,
2578 1, (enum reload_type) addr_type);
2580 if (avr_log.legitimize_reload_address)
2581 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
2582 POINTER_REGS, XEXP (mem, 0), NULL_RTX);
2584 push_reload (mem, NULL_RTX, &XEXP (x, 0), NULL,
2585 BASE_POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
2586 opnum, (enum reload_type) type);
2588 if (avr_log.legitimize_reload_address)
2589 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
2590 BASE_POINTER_REGS, mem, NULL_RTX);
2592 return x;
2595 else if (! (frame_pointer_needed
2596 && XEXP (x, 0) == frame_pointer_rtx))
2598 push_reload (x, NULL_RTX, px, NULL,
2599 POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
2600 opnum, (enum reload_type) type);
2602 if (avr_log.legitimize_reload_address)
2603 avr_edump (" RCLASS.3 = %R\n IN = %r\n OUT = %r\n",
2604 POINTER_REGS, x, NULL_RTX);
2606 return x;
2610 return NULL_RTX;
2614 /* Helper function to print assembler resp. track instruction
2615 sequence lengths. Always return "".
2617 If PLEN == NULL:
2618 Output assembler code from template TPL with operands supplied
2619 by OPERANDS. This is just forwarding to output_asm_insn.
2621 If PLEN != NULL:
2622 If N_WORDS >= 0 Add N_WORDS to *PLEN.
2623 If N_WORDS < 0 Set *PLEN to -N_WORDS.
2624 Don't output anything.
2627 static const char*
2628 avr_asm_len (const char* tpl, rtx* operands, int* plen, int n_words)
2630 if (plen == NULL)
2631 output_asm_insn (tpl, operands);
2632 else
2634 if (n_words < 0)
2635 *plen = -n_words;
2636 else
2637 *plen += n_words;
2640 return "";
2644 /* Return a pointer register name as a string. */
2646 static const char*
2647 ptrreg_to_str (int regno)
2649 switch (regno)
2651 case REG_X: return "X";
2652 case REG_Y: return "Y";
2653 case REG_Z: return "Z";
2654 default:
2655 output_operand_lossage ("address operand requires constraint for"
2656 " X, Y, or Z register");
2658 return NULL;
2661 /* Return the condition name as a string.
2662 Used in conditional jump constructing */
2664 static const char*
2665 cond_string (enum rtx_code code)
2667 switch (code)
2669 case NE:
2670 return "ne";
2671 case EQ:
2672 return "eq";
2673 case GE:
2674 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
2675 return "pl";
2676 else
2677 return "ge";
2678 case LT:
2679 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
2680 return "mi";
2681 else
2682 return "lt";
2683 case GEU:
2684 return "sh";
2685 case LTU:
2686 return "lo";
2687 default:
2688 gcc_unreachable ();
2691 return "";
2695 /* Return true if rtx X is a CONST or SYMBOL_REF with progmem.
2696 This must be used for AVR_TINY only because on other cores
2697 the flash memory is not visible in the RAM address range and
2698 cannot be read by, say, LD instruction. */
2700 static bool
2701 avr_address_tiny_pm_p (rtx x)
2703 if (CONST == GET_CODE (x))
2704 x = XEXP (XEXP (x, 0), 0);
2706 if (SYMBOL_REF_P (x))
2707 return SYMBOL_REF_FLAGS (x) & AVR_SYMBOL_FLAG_TINY_PM;
2709 return false;
2712 /* Implement `TARGET_PRINT_OPERAND_ADDRESS'. */
2713 /* Output ADDR to FILE as address. */
2715 static void
2716 avr_print_operand_address (FILE *file, machine_mode /*mode*/, rtx addr)
2718 if (AVR_TINY
2719 && avr_address_tiny_pm_p (addr))
2721 addr = plus_constant (Pmode, addr, avr_arch->flash_pm_offset);
2724 switch (GET_CODE (addr))
2726 case REG:
2727 fprintf (file, "%s", ptrreg_to_str (REGNO (addr)));
2728 break;
2730 case PRE_DEC:
2731 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
2732 break;
2734 case POST_INC:
2735 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
2736 break;
2738 default:
2739 if (CONSTANT_ADDRESS_P (addr)
2740 && text_segment_operand (addr, VOIDmode))
2742 rtx x = addr;
2743 if (GET_CODE (x) == CONST)
2744 x = XEXP (x, 0);
2745 if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1)))
2747 /* Assembler gs() will implant word address. Make offset
2748 a byte offset inside gs() for assembler. This is
2749 needed because the more logical (constant+gs(sym)) is not
2750 accepted by gas. For 128K and smaller devices this is ok.
2751 For large devices it will create a trampoline to offset
2752 from symbol which may not be what the user really wanted. */
2754 fprintf (file, "gs(");
2755 output_addr_const (file, XEXP (x, 0));
2756 fprintf (file, "+" HOST_WIDE_INT_PRINT_DEC ")",
2757 2 * INTVAL (XEXP (x, 1)));
2758 if (AVR_3_BYTE_PC)
2759 if (warning (0, "pointer offset from symbol maybe incorrect"))
2761 output_addr_const (stderr, addr);
2762 fprintf (stderr, "\n");
2765 else
2767 fprintf (file, "gs(");
2768 output_addr_const (file, addr);
2769 fprintf (file, ")");
2772 else
2773 output_addr_const (file, addr);
2778 /* Implement `TARGET_PRINT_OPERAND_PUNCT_VALID_P'. */
2780 static bool
2781 avr_print_operand_punct_valid_p (unsigned char code)
2783 return code == '~' || code == '!';
2787 /* Implement `TARGET_PRINT_OPERAND'. */
2788 /* Output X as assembler operand to file FILE.
2789 For a description of supported %-codes, see top of avr.md. */
2791 static void
2792 avr_print_operand (FILE *file, rtx x, int code)
2794 int abcd = 0, ef = 0, ij = 0;
2796 if (code >= 'A' && code <= 'D')
2797 abcd = code - 'A';
2798 else if (code == 'E' || code == 'F')
2799 ef = code - 'E';
2800 else if (code == 'I' || code == 'J')
2801 ij = code - 'I';
2803 if (code == '~')
2805 if (!AVR_HAVE_JMP_CALL)
2806 fputc ('r', file);
2808 else if (code == '!')
2810 if (AVR_HAVE_EIJMP_EICALL)
2811 fputc ('e', file);
2813 else if (code == 't'
2814 || code == 'T')
2816 static int t_regno = -1;
2817 static int t_nbits = -1;
2819 if (REG_P (x) && t_regno < 0 && code == 'T')
2821 t_regno = REGNO (x);
2822 t_nbits = GET_MODE_BITSIZE (GET_MODE (x));
2824 else if (CONST_INT_P (x) && t_regno >= 0
2825 && IN_RANGE (INTVAL (x), 0, t_nbits - 1))
2827 int bpos = INTVAL (x);
2829 fprintf (file, "%s", reg_names[t_regno + bpos / 8]);
2830 if (code == 'T')
2831 fprintf (file, ",%d", bpos % 8);
2833 t_regno = -1;
2835 else
2836 fatal_insn ("operands to %T/%t must be reg + const_int:", x);
2838 else if (code == 'E' || code == 'F')
2840 rtx op = XEXP (x, 0);
2841 fprintf (file, "%s", reg_names[REGNO (op) + ef]);
2843 else if (code == 'I' || code == 'J')
2845 rtx op = XEXP (XEXP (x, 0), 0);
2846 fprintf (file, "%s", reg_names[REGNO (op) + ij]);
2848 else if (REG_P (x))
2850 if (x == zero_reg_rtx)
2851 fprintf (file, "__zero_reg__");
2852 else if (code == 'r' && REGNO (x) < 32)
2853 fprintf (file, "%d", (int) REGNO (x));
2854 else
2855 fprintf (file, "%s", reg_names[REGNO (x) + abcd]);
2857 else if (CONST_INT_P (x))
2859 HOST_WIDE_INT ival = INTVAL (x);
2861 if ('i' != code)
2862 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival + abcd);
2863 else if (low_io_address_operand (x, VOIDmode)
2864 || high_io_address_operand (x, VOIDmode))
2866 if (AVR_HAVE_RAMPZ && ival == avr_addr.rampz)
2867 fprintf (file, "__RAMPZ__");
2868 else if (AVR_HAVE_RAMPY && ival == avr_addr.rampy)
2869 fprintf (file, "__RAMPY__");
2870 else if (AVR_HAVE_RAMPX && ival == avr_addr.rampx)
2871 fprintf (file, "__RAMPX__");
2872 else if (AVR_HAVE_RAMPD && ival == avr_addr.rampd)
2873 fprintf (file, "__RAMPD__");
2874 else if ((AVR_XMEGA || AVR_TINY) && ival == avr_addr.ccp)
2875 fprintf (file, "__CCP__");
2876 else if (ival == avr_addr.sreg) fprintf (file, "__SREG__");
2877 else if (ival == avr_addr.sp_l) fprintf (file, "__SP_L__");
2878 else if (ival == avr_addr.sp_h) fprintf (file, "__SP_H__");
2879 else
2881 fprintf (file, HOST_WIDE_INT_PRINT_HEX,
2882 ival - avr_arch->sfr_offset);
2885 else
2886 fatal_insn ("bad address, not an I/O address:", x);
2888 else if (MEM_P (x))
2890 rtx addr = XEXP (x, 0);
2892 if (code == 'm')
2894 if (!CONSTANT_P (addr))
2895 fatal_insn ("bad address, not a constant:", addr);
2896 /* Assembler template with m-code is data - not progmem section */
2897 if (text_segment_operand (addr, VOIDmode))
2898 if (warning (0, "accessing data memory with"
2899 " program memory address"))
2901 output_addr_const (stderr, addr);
2902 fprintf(stderr,"\n");
2904 output_addr_const (file, addr);
2906 else if (code == 'i')
2908 avr_print_operand (file, addr, 'i');
2910 else if (code == 'o')
2912 if (GET_CODE (addr) != PLUS)
2913 fatal_insn ("bad address, not (reg+disp):", addr);
2915 avr_print_operand (file, XEXP (addr, 1), 0);
2917 else if (code == 'b')
2919 if (GET_CODE (addr) != PLUS)
2920 fatal_insn ("bad address, not (reg+disp):", addr);
2922 avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
2924 else if (code == 'p' || code == 'r')
2926 if (GET_CODE (addr) != POST_INC && GET_CODE (addr) != PRE_DEC)
2927 fatal_insn ("bad address, not post_inc or pre_dec:", addr);
2929 if (code == 'p')
2930 /* X, Y, Z */
2931 avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
2932 else
2933 avr_print_operand (file, XEXP (addr, 0), 0); /* r26, r28, r30 */
2935 else if (GET_CODE (addr) == PLUS)
2937 avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
2938 if (REGNO (XEXP (addr, 0)) == REG_X)
2939 fatal_insn ("internal compiler error. Bad address:"
2940 ,addr);
2941 fputc ('+', file);
2942 avr_print_operand (file, XEXP (addr, 1), code);
2944 else
2945 avr_print_operand_address (file, VOIDmode, addr);
2947 else if (code == 'i')
2949 if (SYMBOL_REF_P (x) && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO))
2950 avr_print_operand_address
2951 (file, VOIDmode, plus_constant (HImode, x, -avr_arch->sfr_offset));
2952 else
2953 fatal_insn ("bad address, not an I/O address:", x);
2955 else if (code == 'x')
2957 /* Constant progmem address - like used in jmp or call */
2958 if (text_segment_operand (x, VOIDmode) == 0)
2959 if (warning (0, "accessing program memory"
2960 " with data memory address"))
2962 output_addr_const (stderr, x);
2963 fprintf(stderr,"\n");
2965 /* Use normal symbol for direct address no linker trampoline needed */
2966 output_addr_const (file, x);
2968 else if (CONST_FIXED_P (x))
2970 HOST_WIDE_INT ival = INTVAL (avr_to_int_mode (x));
2971 if (code != 0)
2972 output_operand_lossage ("Unsupported code '%c' for fixed-point:",
2973 code);
2974 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);
2976 else if (CONST_DOUBLE_P (x))
2978 long val;
2979 if (GET_MODE (x) != SFmode)
2980 fatal_insn ("internal compiler error. Unknown mode:", x);
2981 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), val);
2982 fprintf (file, "0x%lx", val);
2984 else if (GET_CODE (x) == CONST_STRING)
2985 fputs (XSTR (x, 0), file);
2986 else if (code == 'j')
2987 fputs (cond_string (GET_CODE (x)), file);
2988 else if (code == 'k')
2989 fputs (cond_string (reverse_condition (GET_CODE (x))), file);
2990 else
2991 avr_print_operand_address (file, VOIDmode, x);
2995 /* Implement TARGET_USE_BY_PIECES_INFRASTRUCTURE_P. */
2997 /* Prefer sequence of loads/stores for moves of size upto
2998 two - two pairs of load/store instructions are always better
2999 than the 5 instruction sequence for a loop (1 instruction
3000 for loop counter setup, and 4 for the body of the loop). */
3002 static bool
3003 avr_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size,
3004 unsigned int align ATTRIBUTE_UNUSED,
3005 enum by_pieces_operation op,
3006 bool speed_p)
3008 if (op != MOVE_BY_PIECES
3009 || (speed_p && size > MOVE_MAX_PIECES))
3010 return default_use_by_pieces_infrastructure_p (size, align, op, speed_p);
3012 return size <= MOVE_MAX_PIECES;
3016 /* Worker function for `NOTICE_UPDATE_CC'. */
3017 /* Update the condition code in the INSN. */
3019 void
3020 avr_notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx_insn *insn)
3022 rtx set;
3023 enum attr_cc cc = get_attr_cc (insn);
3025 switch (cc)
3027 default:
3028 break;
3030 case CC_PLUS:
3031 case CC_LDI:
3033 rtx *op = recog_data.operand;
3034 int len_dummy, icc;
3036 /* Extract insn's operands. */
3037 extract_constrain_insn_cached (insn);
3039 switch (cc)
3041 default:
3042 gcc_unreachable();
3044 case CC_PLUS:
3045 avr_out_plus (insn, op, &len_dummy, &icc);
3046 cc = (enum attr_cc) icc;
3047 break;
3049 case CC_LDI:
3051 cc = (op[1] == CONST0_RTX (GET_MODE (op[0]))
3052 && reg_overlap_mentioned_p (op[0], zero_reg_rtx))
3053 /* Loading zero-reg with 0 uses CLR and thus clobbers cc0. */
3054 ? CC_CLOBBER
3055 /* Any other "r,rL" combination does not alter cc0. */
3056 : CC_NONE;
3058 break;
3059 } /* inner switch */
3061 break;
3063 } /* outer swicth */
3065 switch (cc)
3067 default:
3068 /* Special values like CC_OUT_PLUS from above have been
3069 mapped to "standard" CC_* values so we never come here. */
3071 gcc_unreachable();
3072 break;
3074 case CC_NONE:
3075 /* Insn does not affect CC at all, but it might set some registers
3076 that are stored in cc_status. If such a register is affected by
3077 the current insn, for example by means of a SET or a CLOBBER,
3078 then we must reset cc_status; cf. PR77326.
3080 Unfortunately, set_of cannot be used as reg_overlap_mentioned_p
3081 will abort on COMPARE (which might be found in cc_status.value1/2).
3082 Thus work out the registers set by the insn and regs mentioned
3083 in cc_status.value1/2. */
3085 if (cc_status.value1
3086 || cc_status.value2)
3088 HARD_REG_SET regs_used;
3089 HARD_REG_SET regs_set;
3090 CLEAR_HARD_REG_SET (regs_used);
3092 if (cc_status.value1
3093 && !CONSTANT_P (cc_status.value1))
3095 find_all_hard_regs (cc_status.value1, &regs_used);
3098 if (cc_status.value2
3099 && !CONSTANT_P (cc_status.value2))
3101 find_all_hard_regs (cc_status.value2, &regs_used);
3104 find_all_hard_reg_sets (insn, &regs_set, false);
3106 if (hard_reg_set_intersect_p (regs_used, regs_set))
3108 CC_STATUS_INIT;
3112 break; // CC_NONE
3114 case CC_SET_N:
3115 CC_STATUS_INIT;
3116 break;
3118 case CC_SET_ZN:
3119 set = single_set (insn);
3120 CC_STATUS_INIT;
3121 if (set)
3123 cc_status.flags |= CC_NO_OVERFLOW;
3124 cc_status.value1 = SET_DEST (set);
3126 break;
3128 case CC_SET_VZN:
3129 /* Insn like INC, DEC, NEG that set Z,N,V. We currently don't make use
3130 of this combination, cf. also PR61055. */
3131 CC_STATUS_INIT;
3132 break;
3134 case CC_SET_CZN:
3135 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
3136 The V flag may or may not be known but that's ok because
3137 alter_cond will change tests to use EQ/NE. */
3138 set = single_set (insn);
3139 CC_STATUS_INIT;
3140 if (set)
3142 cc_status.value1 = SET_DEST (set);
3143 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
3145 break;
3147 case CC_COMPARE:
3148 set = single_set (insn);
3149 CC_STATUS_INIT;
3150 if (set)
3151 cc_status.value1 = SET_SRC (set);
3152 break;
3154 case CC_CLOBBER:
3155 /* Insn doesn't leave CC in a usable state. */
3156 CC_STATUS_INIT;
3157 break;
3161 /* Choose mode for jump insn:
3162 1 - relative jump in range -63 <= x <= 62 ;
3163 2 - relative jump in range -2046 <= x <= 2045 ;
3164 3 - absolute jump (only for ATmega[16]03). */
3167 avr_jump_mode (rtx x, rtx_insn *insn)
3169 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_CODE (x) == LABEL_REF
3170 ? XEXP (x, 0) : x));
3171 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
3172 int jump_distance = cur_addr - dest_addr;
3174 if (IN_RANGE (jump_distance, -63, 62))
3175 return 1;
3176 else if (IN_RANGE (jump_distance, -2046, 2045))
3177 return 2;
3178 else if (AVR_HAVE_JMP_CALL)
3179 return 3;
3181 return 2;
3184 /* Return an AVR condition jump commands.
3185 X is a comparison RTX.
3186 LEN is a number returned by avr_jump_mode function.
3187 If REVERSE nonzero then condition code in X must be reversed. */
3189 const char*
3190 ret_cond_branch (rtx x, int len, int reverse)
3192 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
3194 switch (cond)
3196 case GT:
3197 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
3198 return (len == 1 ? ("breq .+2" CR_TAB
3199 "brpl %0") :
3200 len == 2 ? ("breq .+4" CR_TAB
3201 "brmi .+2" CR_TAB
3202 "rjmp %0") :
3203 ("breq .+6" CR_TAB
3204 "brmi .+4" CR_TAB
3205 "jmp %0"));
3207 else
3208 return (len == 1 ? ("breq .+2" CR_TAB
3209 "brge %0") :
3210 len == 2 ? ("breq .+4" CR_TAB
3211 "brlt .+2" CR_TAB
3212 "rjmp %0") :
3213 ("breq .+6" CR_TAB
3214 "brlt .+4" CR_TAB
3215 "jmp %0"));
3216 case GTU:
3217 return (len == 1 ? ("breq .+2" CR_TAB
3218 "brsh %0") :
3219 len == 2 ? ("breq .+4" CR_TAB
3220 "brlo .+2" CR_TAB
3221 "rjmp %0") :
3222 ("breq .+6" CR_TAB
3223 "brlo .+4" CR_TAB
3224 "jmp %0"));
3225 case LE:
3226 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
3227 return (len == 1 ? ("breq %0" CR_TAB
3228 "brmi %0") :
3229 len == 2 ? ("breq .+2" CR_TAB
3230 "brpl .+2" CR_TAB
3231 "rjmp %0") :
3232 ("breq .+2" CR_TAB
3233 "brpl .+4" CR_TAB
3234 "jmp %0"));
3235 else
3236 return (len == 1 ? ("breq %0" CR_TAB
3237 "brlt %0") :
3238 len == 2 ? ("breq .+2" CR_TAB
3239 "brge .+2" CR_TAB
3240 "rjmp %0") :
3241 ("breq .+2" CR_TAB
3242 "brge .+4" CR_TAB
3243 "jmp %0"));
3244 case LEU:
3245 return (len == 1 ? ("breq %0" CR_TAB
3246 "brlo %0") :
3247 len == 2 ? ("breq .+2" CR_TAB
3248 "brsh .+2" CR_TAB
3249 "rjmp %0") :
3250 ("breq .+2" CR_TAB
3251 "brsh .+4" CR_TAB
3252 "jmp %0"));
3253 default:
3254 if (reverse)
3256 switch (len)
3258 case 1:
3259 return "br%k1 %0";
3260 case 2:
3261 return ("br%j1 .+2" CR_TAB
3262 "rjmp %0");
3263 default:
3264 return ("br%j1 .+4" CR_TAB
3265 "jmp %0");
3268 else
3270 switch (len)
3272 case 1:
3273 return "br%j1 %0";
3274 case 2:
3275 return ("br%k1 .+2" CR_TAB
3276 "rjmp %0");
3277 default:
3278 return ("br%k1 .+4" CR_TAB
3279 "jmp %0");
3283 return "";
3287 /* Worker function for `FINAL_PRESCAN_INSN'. */
3288 /* Output insn cost for next insn. */
3290 void
3291 avr_final_prescan_insn (rtx_insn *insn, rtx *operand ATTRIBUTE_UNUSED,
3292 int num_operands ATTRIBUTE_UNUSED)
3294 if (avr_log.rtx_costs)
3296 rtx set = single_set (insn);
3298 if (set)
3299 fprintf (asm_out_file, "/* DEBUG: cost = %d. */\n",
3300 set_src_cost (SET_SRC (set), GET_MODE (SET_DEST (set)),
3301 optimize_insn_for_speed_p ()));
3302 else
3303 fprintf (asm_out_file, "/* DEBUG: pattern-cost = %d. */\n",
3304 rtx_cost (PATTERN (insn), VOIDmode, INSN, 0,
3305 optimize_insn_for_speed_p()));
3308 if (avr_log.insn_addresses)
3309 fprintf (asm_out_file, ";; ADDR = %d\n",
3310 (int) INSN_ADDRESSES (INSN_UID (insn)));
3314 /* Implement `TARGET_ASM_FINAL_POSTSCAN_INSN'. */
3315 /* When GAS generates (parts of) ISR prologue / epilogue for us, we must
3316 hint GAS about the end of the code to scan. There migh be code located
3317 after the last epilogue. */
3319 static void
3320 avr_asm_final_postscan_insn (FILE *stream, rtx_insn *insn, rtx*, int)
3322 if (cfun->machine->gasisr.yes
3323 && !next_real_insn (insn))
3325 app_disable();
3326 fprintf (stream, "\t__gcc_isr %d,r%d\n", GASISR_Done,
3327 cfun->machine->gasisr.regno);
3332 /* Return 0 if undefined, 1 if always true or always false. */
3335 avr_simplify_comparison_p (machine_mode mode, RTX_CODE op, rtx x)
3337 unsigned int max = (mode == QImode ? 0xff :
3338 mode == HImode ? 0xffff :
3339 mode == PSImode ? 0xffffff :
3340 mode == SImode ? 0xffffffff : 0);
3341 if (max && op && CONST_INT_P (x))
3343 if (unsigned_condition (op) != op)
3344 max >>= 1;
3346 if (max != (INTVAL (x) & max)
3347 && INTVAL (x) != 0xff)
3348 return 1;
3350 return 0;
3354 /* Worker function for `FUNCTION_ARG_REGNO_P'. */
3355 /* Returns nonzero if REGNO is the number of a hard
3356 register in which function arguments are sometimes passed. */
3359 avr_function_arg_regno_p (int r)
3361 return AVR_TINY ? IN_RANGE (r, 20, 25) : IN_RANGE (r, 8, 25);
3365 /* Worker function for `INIT_CUMULATIVE_ARGS'. */
3366 /* Initializing the variable cum for the state at the beginning
3367 of the argument list. */
3369 void
3370 avr_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
3371 tree fndecl ATTRIBUTE_UNUSED)
3373 cum->nregs = AVR_TINY ? 6 : 18;
3374 cum->regno = FIRST_CUM_REG;
3375 if (!libname && stdarg_p (fntype))
3376 cum->nregs = 0;
3378 /* Assume the calle may be tail called */
3380 cfun->machine->sibcall_fails = 0;
3383 /* Returns the number of registers to allocate for a function argument. */
3385 static int
3386 avr_num_arg_regs (machine_mode mode, const_tree type)
3388 int size;
3390 if (mode == BLKmode)
3391 size = int_size_in_bytes (type);
3392 else
3393 size = GET_MODE_SIZE (mode);
3395 /* Align all function arguments to start in even-numbered registers.
3396 Odd-sized arguments leave holes above them. */
3398 return (size + 1) & ~1;
3402 /* Implement `TARGET_FUNCTION_ARG'. */
3403 /* Controls whether a function argument is passed
3404 in a register, and which register. */
3406 static rtx
3407 avr_function_arg (cumulative_args_t cum_v, machine_mode mode,
3408 const_tree type, bool named ATTRIBUTE_UNUSED)
3410 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
3411 int bytes = avr_num_arg_regs (mode, type);
3413 if (cum->nregs && bytes <= cum->nregs)
3414 return gen_rtx_REG (mode, cum->regno - bytes);
3416 return NULL_RTX;
3420 /* Implement `TARGET_FUNCTION_ARG_ADVANCE'. */
3421 /* Update the summarizer variable CUM to advance past an argument
3422 in the argument list. */
3424 static void
3425 avr_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
3426 const_tree type, bool named ATTRIBUTE_UNUSED)
3428 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
3429 int bytes = avr_num_arg_regs (mode, type);
3431 cum->nregs -= bytes;
3432 cum->regno -= bytes;
3434 /* A parameter is being passed in a call-saved register. As the original
3435 contents of these regs has to be restored before leaving the function,
3436 a function must not pass arguments in call-saved regs in order to get
3437 tail-called. */
3439 if (cum->regno >= 8
3440 && cum->nregs >= 0
3441 && !call_used_regs[cum->regno])
3443 /* FIXME: We ship info on failing tail-call in struct machine_function.
3444 This uses internals of calls.c:expand_call() and the way args_so_far
3445 is used. targetm.function_ok_for_sibcall() needs to be extended to
3446 pass &args_so_far, too. At present, CUMULATIVE_ARGS is target
3447 dependent so that such an extension is not wanted. */
3449 cfun->machine->sibcall_fails = 1;
3452 /* Test if all registers needed by the ABI are actually available. If the
3453 user has fixed a GPR needed to pass an argument, an (implicit) function
3454 call will clobber that fixed register. See PR45099 for an example. */
3456 if (cum->regno >= 8
3457 && cum->nregs >= 0)
3459 for (int regno = cum->regno; regno < cum->regno + bytes; regno++)
3460 if (fixed_regs[regno])
3461 warning (0, "fixed register %s used to pass parameter to function",
3462 reg_names[regno]);
3465 if (cum->nregs <= 0)
3467 cum->nregs = 0;
3468 cum->regno = FIRST_CUM_REG;
3472 /* Implement `TARGET_FUNCTION_OK_FOR_SIBCALL' */
3473 /* Decide whether we can make a sibling call to a function. DECL is the
3474 declaration of the function being targeted by the call and EXP is the
3475 CALL_EXPR representing the call. */
3477 static bool
3478 avr_function_ok_for_sibcall (tree decl_callee, tree exp_callee)
3480 tree fntype_callee;
3482 /* Tail-calling must fail if callee-saved regs are used to pass
3483 function args. We must not tail-call when `epilogue_restores'
3484 is used. Unfortunately, we cannot tell at this point if that
3485 actually will happen or not, and we cannot step back from
3486 tail-calling. Thus, we inhibit tail-calling with -mcall-prologues. */
3488 if (cfun->machine->sibcall_fails
3489 || TARGET_CALL_PROLOGUES)
3491 return false;
3494 fntype_callee = TREE_TYPE (CALL_EXPR_FN (exp_callee));
3496 if (decl_callee)
3498 decl_callee = TREE_TYPE (decl_callee);
3500 else
3502 decl_callee = fntype_callee;
3504 while (FUNCTION_TYPE != TREE_CODE (decl_callee)
3505 && METHOD_TYPE != TREE_CODE (decl_callee))
3507 decl_callee = TREE_TYPE (decl_callee);
3511 /* Ensure that caller and callee have compatible epilogues */
3513 if (cfun->machine->is_interrupt
3514 || cfun->machine->is_signal
3515 || cfun->machine->is_naked
3516 || avr_naked_function_p (decl_callee))
3518 return false;
3521 return true;
3524 /***********************************************************************
3525 Functions for outputting various mov's for a various modes
3526 ************************************************************************/
3528 /* Return true if a value of mode MODE is read from flash by
3529 __load_* function from libgcc. */
3531 bool
3532 avr_load_libgcc_p (rtx op)
3534 machine_mode mode = GET_MODE (op);
3535 int n_bytes = GET_MODE_SIZE (mode);
3537 return (n_bytes > 2
3538 && !AVR_HAVE_LPMX
3539 && avr_mem_flash_p (op));
3542 /* Return true if a value of mode MODE is read by __xload_* function. */
3544 bool
3545 avr_xload_libgcc_p (machine_mode mode)
3547 int n_bytes = GET_MODE_SIZE (mode);
3549 return (n_bytes > 1
3550 || avr_n_flash > 1);
3554 /* Fixme: This is a hack because secondary reloads don't works as expected.
3556 Find an unused d-register to be used as scratch in INSN.
3557 EXCLUDE is either NULL_RTX or some register. In the case where EXCLUDE
3558 is a register, skip all possible return values that overlap EXCLUDE.
3559 The policy for the returned register is similar to that of
3560 `reg_unused_after', i.e. the returned register may overlap the SET_DEST
3561 of INSN.
3563 Return a QImode d-register or NULL_RTX if nothing found. */
3565 static rtx
3566 avr_find_unused_d_reg (rtx_insn *insn, rtx exclude)
3568 bool isr_p = (avr_interrupt_function_p (current_function_decl)
3569 || avr_signal_function_p (current_function_decl));
3571 for (int regno = 16; regno < 32; regno++)
3573 rtx reg = all_regs_rtx[regno];
3575 if ((exclude
3576 && reg_overlap_mentioned_p (exclude, reg))
3577 || fixed_regs[regno])
3579 continue;
3582 /* Try non-live register */
3584 if (!df_regs_ever_live_p (regno)
3585 && (TREE_THIS_VOLATILE (current_function_decl)
3586 || cfun->machine->is_OS_task
3587 || cfun->machine->is_OS_main
3588 || (!isr_p && call_used_regs[regno])))
3590 return reg;
3593 /* Any live register can be used if it is unused after.
3594 Prologue/epilogue will care for it as needed. */
3596 if (df_regs_ever_live_p (regno)
3597 && reg_unused_after (insn, reg))
3599 return reg;
3603 return NULL_RTX;
3607 /* Helper function for the next function in the case where only restricted
3608 version of LPM instruction is available. */
3610 static const char*
3611 avr_out_lpm_no_lpmx (rtx_insn *insn, rtx *xop, int *plen)
3613 rtx dest = xop[0];
3614 rtx addr = xop[1];
3615 int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
3616 int regno_dest;
3618 regno_dest = REGNO (dest);
3620 /* The implicit target register of LPM. */
3621 xop[3] = lpm_reg_rtx;
3623 switch (GET_CODE (addr))
3625 default:
3626 gcc_unreachable();
3628 case REG:
3630 gcc_assert (REG_Z == REGNO (addr));
3632 switch (n_bytes)
3634 default:
3635 gcc_unreachable();
3637 case 1:
3638 avr_asm_len ("%4lpm", xop, plen, 1);
3640 if (regno_dest != LPM_REGNO)
3641 avr_asm_len ("mov %0,%3", xop, plen, 1);
3643 return "";
3645 case 2:
3646 if (REGNO (dest) == REG_Z)
3647 return avr_asm_len ("%4lpm" CR_TAB
3648 "push %3" CR_TAB
3649 "adiw %2,1" CR_TAB
3650 "%4lpm" CR_TAB
3651 "mov %B0,%3" CR_TAB
3652 "pop %A0", xop, plen, 6);
3654 avr_asm_len ("%4lpm" CR_TAB
3655 "mov %A0,%3" CR_TAB
3656 "adiw %2,1" CR_TAB
3657 "%4lpm" CR_TAB
3658 "mov %B0,%3", xop, plen, 5);
3660 if (!reg_unused_after (insn, addr))
3661 avr_asm_len ("sbiw %2,1", xop, plen, 1);
3663 break; /* 2 */
3666 break; /* REG */
3668 case POST_INC:
3670 gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
3671 && n_bytes <= 4);
3673 if (regno_dest == LPM_REGNO)
3674 avr_asm_len ("%4lpm" CR_TAB
3675 "adiw %2,1", xop, plen, 2);
3676 else
3677 avr_asm_len ("%4lpm" CR_TAB
3678 "mov %A0,%3" CR_TAB
3679 "adiw %2,1", xop, plen, 3);
3681 if (n_bytes >= 2)
3682 avr_asm_len ("%4lpm" CR_TAB
3683 "mov %B0,%3" CR_TAB
3684 "adiw %2,1", xop, plen, 3);
3686 if (n_bytes >= 3)
3687 avr_asm_len ("%4lpm" CR_TAB
3688 "mov %C0,%3" CR_TAB
3689 "adiw %2,1", xop, plen, 3);
3691 if (n_bytes >= 4)
3692 avr_asm_len ("%4lpm" CR_TAB
3693 "mov %D0,%3" CR_TAB
3694 "adiw %2,1", xop, plen, 3);
3696 break; /* POST_INC */
3698 } /* switch CODE (addr) */
3700 return "";
3704 /* If PLEN == NULL: Ouput instructions to load a value from a memory location
3705 OP[1] in AS1 to register OP[0].
3706 If PLEN != 0 set *PLEN to the length in words of the instruction sequence.
3707 Return "". */
3709 const char*
3710 avr_out_lpm (rtx_insn *insn, rtx *op, int *plen)
3712 rtx xop[7];
3713 rtx dest = op[0];
3714 rtx src = SET_SRC (single_set (insn));
3715 rtx addr;
3716 int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
3717 int segment;
3718 RTX_CODE code;
3719 addr_space_t as = MEM_ADDR_SPACE (src);
3721 if (plen)
3722 *plen = 0;
3724 if (MEM_P (dest))
3726 warning (0, "writing to address space %qs not supported",
3727 avr_addrspace[MEM_ADDR_SPACE (dest)].name);
3729 return "";
3732 addr = XEXP (src, 0);
3733 code = GET_CODE (addr);
3735 gcc_assert (REG_P (dest));
3736 gcc_assert (REG == code || POST_INC == code);
3738 xop[0] = dest;
3739 xop[1] = addr;
3740 xop[2] = lpm_addr_reg_rtx;
3741 xop[4] = xstring_empty;
3742 xop[5] = tmp_reg_rtx;
3743 xop[6] = XEXP (rampz_rtx, 0);
3745 segment = avr_addrspace[as].segment;
3747 /* Set RAMPZ as needed. */
3749 if (segment)
3751 xop[4] = GEN_INT (segment);
3752 xop[3] = avr_find_unused_d_reg (insn, lpm_addr_reg_rtx);
3754 if (xop[3] != NULL_RTX)
3756 avr_asm_len ("ldi %3,%4" CR_TAB
3757 "out %i6,%3", xop, plen, 2);
3759 else if (segment == 1)
3761 avr_asm_len ("clr %5" CR_TAB
3762 "inc %5" CR_TAB
3763 "out %i6,%5", xop, plen, 3);
3765 else
3767 avr_asm_len ("mov %5,%2" CR_TAB
3768 "ldi %2,%4" CR_TAB
3769 "out %i6,%2" CR_TAB
3770 "mov %2,%5", xop, plen, 4);
3773 xop[4] = xstring_e;
3775 if (!AVR_HAVE_ELPMX)
3776 return avr_out_lpm_no_lpmx (insn, xop, plen);
3778 else if (!AVR_HAVE_LPMX)
3780 return avr_out_lpm_no_lpmx (insn, xop, plen);
3783 /* We have [E]LPMX: Output reading from Flash the comfortable way. */
3785 switch (GET_CODE (addr))
3787 default:
3788 gcc_unreachable();
3790 case REG:
3792 gcc_assert (REG_Z == REGNO (addr));
3794 switch (n_bytes)
3796 default:
3797 gcc_unreachable();
3799 case 1:
3800 return avr_asm_len ("%4lpm %0,%a2", xop, plen, 1);
3802 case 2:
3803 if (REGNO (dest) == REG_Z)
3804 return avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3805 "%4lpm %B0,%a2" CR_TAB
3806 "mov %A0,%5", xop, plen, 3);
3807 else
3809 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3810 "%4lpm %B0,%a2", xop, plen, 2);
3812 if (!reg_unused_after (insn, addr))
3813 avr_asm_len ("sbiw %2,1", xop, plen, 1);
3816 break; /* 2 */
3818 case 3:
3820 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3821 "%4lpm %B0,%a2+" CR_TAB
3822 "%4lpm %C0,%a2", xop, plen, 3);
3824 if (!reg_unused_after (insn, addr))
3825 avr_asm_len ("sbiw %2,2", xop, plen, 1);
3827 break; /* 3 */
3829 case 4:
3831 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3832 "%4lpm %B0,%a2+", xop, plen, 2);
3834 if (REGNO (dest) == REG_Z - 2)
3835 return avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3836 "%4lpm %C0,%a2" CR_TAB
3837 "mov %D0,%5", xop, plen, 3);
3838 else
3840 avr_asm_len ("%4lpm %C0,%a2+" CR_TAB
3841 "%4lpm %D0,%a2", xop, plen, 2);
3843 if (!reg_unused_after (insn, addr))
3844 avr_asm_len ("sbiw %2,3", xop, plen, 1);
3847 break; /* 4 */
3848 } /* n_bytes */
3850 break; /* REG */
3852 case POST_INC:
3854 gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
3855 && n_bytes <= 4);
3857 avr_asm_len ("%4lpm %A0,%a2+", xop, plen, 1);
3858 if (n_bytes >= 2) avr_asm_len ("%4lpm %B0,%a2+", xop, plen, 1);
3859 if (n_bytes >= 3) avr_asm_len ("%4lpm %C0,%a2+", xop, plen, 1);
3860 if (n_bytes >= 4) avr_asm_len ("%4lpm %D0,%a2+", xop, plen, 1);
3862 break; /* POST_INC */
3864 } /* switch CODE (addr) */
3866 if (xop[4] == xstring_e && AVR_HAVE_RAMPD)
3868 /* Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM. */
3870 xop[0] = zero_reg_rtx;
3871 avr_asm_len ("out %i6,%0", xop, plen, 1);
3874 return "";
3878 /* Worker function for xload_8 insn. */
3880 const char*
3881 avr_out_xload (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
3883 rtx xop[4];
3885 xop[0] = op[0];
3886 xop[1] = op[1];
3887 xop[2] = lpm_addr_reg_rtx;
3888 xop[3] = AVR_HAVE_LPMX ? op[0] : lpm_reg_rtx;
3890 avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, -1);
3892 avr_asm_len ("sbrc %1,7" CR_TAB
3893 "ld %3,%a2", xop, plen, 2);
3895 if (REGNO (xop[0]) != REGNO (xop[3]))
3896 avr_asm_len ("mov %0,%3", xop, plen, 1);
3898 return "";
3902 const char*
3903 output_movqi (rtx_insn *insn, rtx operands[], int *plen)
3905 rtx dest = operands[0];
3906 rtx src = operands[1];
3908 if (avr_mem_flash_p (src)
3909 || avr_mem_flash_p (dest))
3911 return avr_out_lpm (insn, operands, plen);
3914 gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 1);
3916 if (REG_P (dest))
3918 if (REG_P (src)) /* mov r,r */
3920 if (test_hard_reg_class (STACK_REG, dest))
3921 return avr_asm_len ("out %0,%1", operands, plen, -1);
3922 else if (test_hard_reg_class (STACK_REG, src))
3923 return avr_asm_len ("in %0,%1", operands, plen, -1);
3925 return avr_asm_len ("mov %0,%1", operands, plen, -1);
3927 else if (CONSTANT_P (src))
3929 output_reload_in_const (operands, NULL_RTX, plen, false);
3930 return "";
3932 else if (MEM_P (src))
3933 return out_movqi_r_mr (insn, operands, plen); /* mov r,m */
3935 else if (MEM_P (dest))
3937 rtx xop[2];
3939 xop[0] = dest;
3940 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
3942 return out_movqi_mr_r (insn, xop, plen);
3945 return "";
3949 const char *
3950 output_movhi (rtx_insn *insn, rtx xop[], int *plen)
3952 rtx dest = xop[0];
3953 rtx src = xop[1];
3955 gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 2);
3957 if (avr_mem_flash_p (src)
3958 || avr_mem_flash_p (dest))
3960 return avr_out_lpm (insn, xop, plen);
3963 if (REG_P (dest))
3965 if (REG_P (src)) /* mov r,r */
3967 if (test_hard_reg_class (STACK_REG, dest))
3969 if (AVR_HAVE_8BIT_SP)
3970 return avr_asm_len ("out __SP_L__,%A1", xop, plen, -1);
3972 if (AVR_XMEGA)
3973 return avr_asm_len ("out __SP_L__,%A1" CR_TAB
3974 "out __SP_H__,%B1", xop, plen, -2);
3976 /* Use simple load of SP if no interrupts are used. */
3978 return TARGET_NO_INTERRUPTS
3979 ? avr_asm_len ("out __SP_H__,%B1" CR_TAB
3980 "out __SP_L__,%A1", xop, plen, -2)
3981 : avr_asm_len ("in __tmp_reg__,__SREG__" CR_TAB
3982 "cli" CR_TAB
3983 "out __SP_H__,%B1" CR_TAB
3984 "out __SREG__,__tmp_reg__" CR_TAB
3985 "out __SP_L__,%A1", xop, plen, -5);
3987 else if (test_hard_reg_class (STACK_REG, src))
3989 return !AVR_HAVE_SPH
3990 ? avr_asm_len ("in %A0,__SP_L__" CR_TAB
3991 "clr %B0", xop, plen, -2)
3993 : avr_asm_len ("in %A0,__SP_L__" CR_TAB
3994 "in %B0,__SP_H__", xop, plen, -2);
3997 return AVR_HAVE_MOVW
3998 ? avr_asm_len ("movw %0,%1", xop, plen, -1)
4000 : avr_asm_len ("mov %A0,%A1" CR_TAB
4001 "mov %B0,%B1", xop, plen, -2);
4002 } /* REG_P (src) */
4003 else if (CONSTANT_P (src))
4005 return output_reload_inhi (xop, NULL, plen);
4007 else if (MEM_P (src))
4009 return out_movhi_r_mr (insn, xop, plen); /* mov r,m */
4012 else if (MEM_P (dest))
4014 rtx xop[2];
4016 xop[0] = dest;
4017 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
4019 return out_movhi_mr_r (insn, xop, plen);
4022 fatal_insn ("invalid insn:", insn);
4024 return "";
4028 /* Same as out_movqi_r_mr, but TINY does not have ADIW or SBIW */
4030 static const char*
4031 avr_out_movqi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
4033 rtx dest = op[0];
4034 rtx src = op[1];
4035 rtx x = XEXP (src, 0);
4037 avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4038 "ld %0,%b1" , op, plen, -3);
4040 if (!reg_overlap_mentioned_p (dest, XEXP (x, 0))
4041 && !reg_unused_after (insn, XEXP (x, 0)))
4042 avr_asm_len (TINY_SBIW (%I1, %J1, %o1), op, plen, 2);
4044 return "";
4047 static const char*
4048 out_movqi_r_mr (rtx_insn *insn, rtx op[], int *plen)
4050 rtx dest = op[0];
4051 rtx src = op[1];
4052 rtx x = XEXP (src, 0);
4054 if (CONSTANT_ADDRESS_P (x))
4056 int n_words = AVR_TINY ? 1 : 2;
4057 return io_address_operand (x, QImode)
4058 ? avr_asm_len ("in %0,%i1", op, plen, -1)
4059 : avr_asm_len ("lds %0,%m1", op, plen, -n_words);
4062 if (GET_CODE (x) == PLUS
4063 && REG_P (XEXP (x, 0))
4064 && CONST_INT_P (XEXP (x, 1)))
4066 /* memory access by reg+disp */
4068 int disp = INTVAL (XEXP (x, 1));
4070 if (AVR_TINY)
4071 return avr_out_movqi_r_mr_reg_disp_tiny (insn, op, plen);
4073 if (disp - GET_MODE_SIZE (GET_MODE (src)) >= 63)
4075 if (REGNO (XEXP (x, 0)) != REG_Y)
4076 fatal_insn ("incorrect insn:",insn);
4078 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
4079 return avr_asm_len ("adiw r28,%o1-63" CR_TAB
4080 "ldd %0,Y+63" CR_TAB
4081 "sbiw r28,%o1-63", op, plen, -3);
4083 return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
4084 "sbci r29,hi8(-%o1)" CR_TAB
4085 "ld %0,Y" CR_TAB
4086 "subi r28,lo8(%o1)" CR_TAB
4087 "sbci r29,hi8(%o1)", op, plen, -5);
4089 else if (REGNO (XEXP (x, 0)) == REG_X)
4091 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
4092 it but I have this situation with extremal optimizing options. */
4094 avr_asm_len ("adiw r26,%o1" CR_TAB
4095 "ld %0,X", op, plen, -2);
4097 if (!reg_overlap_mentioned_p (dest, XEXP (x, 0))
4098 && !reg_unused_after (insn, XEXP (x, 0)))
4100 avr_asm_len ("sbiw r26,%o1", op, plen, 1);
4103 return "";
4106 return avr_asm_len ("ldd %0,%1", op, plen, -1);
4109 return avr_asm_len ("ld %0,%1", op, plen, -1);
4113 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
4115 static const char*
4116 avr_out_movhi_r_mr_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
4118 rtx dest = op[0];
4119 rtx src = op[1];
4120 rtx base = XEXP (src, 0);
4122 int reg_dest = true_regnum (dest);
4123 int reg_base = true_regnum (base);
4125 if (reg_dest == reg_base) /* R = (R) */
4126 return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
4127 "ld %B0,%1" CR_TAB
4128 "mov %A0,__tmp_reg__", op, plen, -3);
4130 avr_asm_len ("ld %A0,%1+" CR_TAB
4131 "ld %B0,%1", op, plen, -2);
4133 if (!reg_unused_after (insn, base))
4134 avr_asm_len (TINY_SBIW (%E1, %F1, 1), op, plen, 2);
4136 return "";
4140 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
4142 static const char*
4143 avr_out_movhi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
4145 rtx dest = op[0];
4146 rtx src = op[1];
4147 rtx base = XEXP (src, 0);
4149 int reg_dest = true_regnum (dest);
4150 int reg_base = true_regnum (XEXP (base, 0));
4152 if (reg_base == reg_dest)
4154 return avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4155 "ld __tmp_reg__,%b1+" CR_TAB
4156 "ld %B0,%b1" CR_TAB
4157 "mov %A0,__tmp_reg__", op, plen, -5);
4159 else
4161 avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4162 "ld %A0,%b1+" CR_TAB
4163 "ld %B0,%b1", op, plen, -4);
4165 if (!reg_unused_after (insn, XEXP (base, 0)))
4166 avr_asm_len (TINY_SBIW (%I1, %J1, %o1+1), op, plen, 2);
4168 return "";
4173 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
4175 static const char*
4176 avr_out_movhi_r_mr_pre_dec_tiny (rtx_insn *insn, rtx op[], int *plen)
4178 int mem_volatile_p = 0;
4179 rtx dest = op[0];
4180 rtx src = op[1];
4181 rtx base = XEXP (src, 0);
4183 /* "volatile" forces reading low byte first, even if less efficient,
4184 for correct operation with 16-bit I/O registers. */
4185 mem_volatile_p = MEM_VOLATILE_P (src);
4187 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
4188 fatal_insn ("incorrect insn:", insn);
4190 if (!mem_volatile_p)
4191 return avr_asm_len ("ld %B0,%1" CR_TAB
4192 "ld %A0,%1", op, plen, -2);
4194 return avr_asm_len (TINY_SBIW (%I1, %J1, 2) CR_TAB
4195 "ld %A0,%p1+" CR_TAB
4196 "ld %B0,%p1" CR_TAB
4197 TINY_SBIW (%I1, %J1, 1), op, plen, -6);
4201 static const char*
4202 out_movhi_r_mr (rtx_insn *insn, rtx op[], int *plen)
4204 rtx dest = op[0];
4205 rtx src = op[1];
4206 rtx base = XEXP (src, 0);
4207 int reg_dest = true_regnum (dest);
4208 int reg_base = true_regnum (base);
4209 /* "volatile" forces reading low byte first, even if less efficient,
4210 for correct operation with 16-bit I/O registers. */
4211 int mem_volatile_p = MEM_VOLATILE_P (src);
4213 if (reg_base > 0)
4215 if (AVR_TINY)
4216 return avr_out_movhi_r_mr_reg_no_disp_tiny (insn, op, plen);
4218 if (reg_dest == reg_base) /* R = (R) */
4219 return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
4220 "ld %B0,%1" CR_TAB
4221 "mov %A0,__tmp_reg__", op, plen, -3);
4223 if (reg_base != REG_X)
4224 return avr_asm_len ("ld %A0,%1" CR_TAB
4225 "ldd %B0,%1+1", op, plen, -2);
4227 avr_asm_len ("ld %A0,X+" CR_TAB
4228 "ld %B0,X", op, plen, -2);
4230 if (!reg_unused_after (insn, base))
4231 avr_asm_len ("sbiw r26,1", op, plen, 1);
4233 return "";
4235 else if (GET_CODE (base) == PLUS) /* (R + i) */
4237 int disp = INTVAL (XEXP (base, 1));
4238 int reg_base = true_regnum (XEXP (base, 0));
4240 if (AVR_TINY)
4241 return avr_out_movhi_r_mr_reg_disp_tiny (insn, op, plen);
4243 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
4245 if (REGNO (XEXP (base, 0)) != REG_Y)
4246 fatal_insn ("incorrect insn:",insn);
4248 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (src))
4249 ? avr_asm_len ("adiw r28,%o1-62" CR_TAB
4250 "ldd %A0,Y+62" CR_TAB
4251 "ldd %B0,Y+63" CR_TAB
4252 "sbiw r28,%o1-62", op, plen, -4)
4254 : avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
4255 "sbci r29,hi8(-%o1)" CR_TAB
4256 "ld %A0,Y" CR_TAB
4257 "ldd %B0,Y+1" CR_TAB
4258 "subi r28,lo8(%o1)" CR_TAB
4259 "sbci r29,hi8(%o1)", op, plen, -6);
4262 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
4263 it but I have this situation with extremal
4264 optimization options. */
4266 if (reg_base == REG_X)
4268 if (reg_base == reg_dest)
4269 return avr_asm_len ("adiw r26,%o1" CR_TAB
4270 "ld __tmp_reg__,X+" CR_TAB
4271 "ld %B0,X" CR_TAB
4272 "mov %A0,__tmp_reg__", op, plen, -4);
4274 avr_asm_len ("adiw r26,%o1" CR_TAB
4275 "ld %A0,X+" CR_TAB
4276 "ld %B0,X", op, plen, -3);
4278 if (!reg_unused_after (insn, XEXP (base, 0)))
4279 avr_asm_len ("sbiw r26,%o1+1", op, plen, 1);
4281 return "";
4284 return reg_base == reg_dest
4285 ? avr_asm_len ("ldd __tmp_reg__,%A1" CR_TAB
4286 "ldd %B0,%B1" CR_TAB
4287 "mov %A0,__tmp_reg__", op, plen, -3)
4289 : avr_asm_len ("ldd %A0,%A1" CR_TAB
4290 "ldd %B0,%B1", op, plen, -2);
4292 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4294 if (AVR_TINY)
4295 return avr_out_movhi_r_mr_pre_dec_tiny (insn, op, plen);
4297 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
4298 fatal_insn ("incorrect insn:", insn);
4300 if (!mem_volatile_p)
4301 return avr_asm_len ("ld %B0,%1" CR_TAB
4302 "ld %A0,%1", op, plen, -2);
4304 return REGNO (XEXP (base, 0)) == REG_X
4305 ? avr_asm_len ("sbiw r26,2" CR_TAB
4306 "ld %A0,X+" CR_TAB
4307 "ld %B0,X" CR_TAB
4308 "sbiw r26,1", op, plen, -4)
4310 : avr_asm_len ("sbiw %r1,2" CR_TAB
4311 "ld %A0,%p1" CR_TAB
4312 "ldd %B0,%p1+1", op, plen, -3);
4314 else if (GET_CODE (base) == POST_INC) /* (R++) */
4316 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
4317 fatal_insn ("incorrect insn:", insn);
4319 return avr_asm_len ("ld %A0,%1" CR_TAB
4320 "ld %B0,%1", op, plen, -2);
4322 else if (CONSTANT_ADDRESS_P (base))
4324 int n_words = AVR_TINY ? 2 : 4;
4325 return io_address_operand (base, HImode)
4326 ? avr_asm_len ("in %A0,%i1" CR_TAB
4327 "in %B0,%i1+1", op, plen, -2)
4329 : avr_asm_len ("lds %A0,%m1" CR_TAB
4330 "lds %B0,%m1+1", op, plen, -n_words);
4333 fatal_insn ("unknown move insn:",insn);
4334 return "";
4337 static const char*
4338 avr_out_movsi_r_mr_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *l)
4340 rtx dest = op[0];
4341 rtx src = op[1];
4342 rtx base = XEXP (src, 0);
4343 int reg_dest = true_regnum (dest);
4344 int reg_base = true_regnum (base);
4346 if (reg_dest == reg_base)
4348 /* "ld r26,-X" is undefined */
4349 return *l = 9, (TINY_ADIW (%E1, %F1, 3) CR_TAB
4350 "ld %D0,%1" CR_TAB
4351 "ld %C0,-%1" CR_TAB
4352 "ld __tmp_reg__,-%1" CR_TAB
4353 TINY_SBIW (%E1, %F1, 1) CR_TAB
4354 "ld %A0,%1" CR_TAB
4355 "mov %B0,__tmp_reg__");
4357 else if (reg_dest == reg_base - 2)
4359 return *l = 5, ("ld %A0,%1+" CR_TAB
4360 "ld %B0,%1+" CR_TAB
4361 "ld __tmp_reg__,%1+" CR_TAB
4362 "ld %D0,%1" CR_TAB
4363 "mov %C0,__tmp_reg__");
4365 else if (reg_unused_after (insn, base))
4367 return *l = 4, ("ld %A0,%1+" CR_TAB
4368 "ld %B0,%1+" CR_TAB
4369 "ld %C0,%1+" CR_TAB
4370 "ld %D0,%1");
4372 else
4374 return *l = 6, ("ld %A0,%1+" CR_TAB
4375 "ld %B0,%1+" CR_TAB
4376 "ld %C0,%1+" CR_TAB
4377 "ld %D0,%1" CR_TAB
4378 TINY_SBIW (%E1, %F1, 3));
4383 static const char*
4384 avr_out_movsi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *l)
4386 rtx dest = op[0];
4387 rtx src = op[1];
4388 rtx base = XEXP (src, 0);
4389 int reg_dest = true_regnum (dest);
4390 int reg_base = true_regnum (XEXP (base, 0));
4392 if (reg_dest == reg_base)
4394 /* "ld r26,-X" is undefined */
4395 return *l = 9, (TINY_ADIW (%I1, %J1, %o1+3) CR_TAB
4396 "ld %D0,%b1" CR_TAB
4397 "ld %C0,-%b1" CR_TAB
4398 "ld __tmp_reg__,-%b1" CR_TAB
4399 TINY_SBIW (%I1, %J1, 1) CR_TAB
4400 "ld %A0,%b1" CR_TAB
4401 "mov %B0,__tmp_reg__");
4403 else if (reg_dest == reg_base - 2)
4405 return *l = 7, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4406 "ld %A0,%b1+" CR_TAB
4407 "ld %B0,%b1+" CR_TAB
4408 "ld __tmp_reg__,%b1+" CR_TAB
4409 "ld %D0,%b1" CR_TAB
4410 "mov %C0,__tmp_reg__");
4412 else if (reg_unused_after (insn, XEXP (base, 0)))
4414 return *l = 6, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4415 "ld %A0,%b1+" CR_TAB
4416 "ld %B0,%b1+" CR_TAB
4417 "ld %C0,%b1+" CR_TAB
4418 "ld %D0,%b1");
4420 else
4422 return *l = 8, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4423 "ld %A0,%b1+" CR_TAB
4424 "ld %B0,%b1+" CR_TAB
4425 "ld %C0,%b1+" CR_TAB
4426 "ld %D0,%b1" CR_TAB
4427 TINY_SBIW (%I1, %J1, %o1+3));
4431 static const char*
4432 out_movsi_r_mr (rtx_insn *insn, rtx op[], int *l)
4434 rtx dest = op[0];
4435 rtx src = op[1];
4436 rtx base = XEXP (src, 0);
4437 int reg_dest = true_regnum (dest);
4438 int reg_base = true_regnum (base);
4439 int tmp;
4441 if (!l)
4442 l = &tmp;
4444 if (reg_base > 0)
4446 if (AVR_TINY)
4447 return avr_out_movsi_r_mr_reg_no_disp_tiny (insn, op, l);
4449 if (reg_base == REG_X) /* (R26) */
4451 if (reg_dest == REG_X)
4452 /* "ld r26,-X" is undefined */
4453 return *l=7, ("adiw r26,3" CR_TAB
4454 "ld r29,X" CR_TAB
4455 "ld r28,-X" CR_TAB
4456 "ld __tmp_reg__,-X" CR_TAB
4457 "sbiw r26,1" CR_TAB
4458 "ld r26,X" CR_TAB
4459 "mov r27,__tmp_reg__");
4460 else if (reg_dest == REG_X - 2)
4461 return *l=5, ("ld %A0,X+" CR_TAB
4462 "ld %B0,X+" CR_TAB
4463 "ld __tmp_reg__,X+" CR_TAB
4464 "ld %D0,X" CR_TAB
4465 "mov %C0,__tmp_reg__");
4466 else if (reg_unused_after (insn, base))
4467 return *l=4, ("ld %A0,X+" CR_TAB
4468 "ld %B0,X+" CR_TAB
4469 "ld %C0,X+" CR_TAB
4470 "ld %D0,X");
4471 else
4472 return *l=5, ("ld %A0,X+" CR_TAB
4473 "ld %B0,X+" CR_TAB
4474 "ld %C0,X+" CR_TAB
4475 "ld %D0,X" CR_TAB
4476 "sbiw r26,3");
4478 else
4480 if (reg_dest == reg_base)
4481 return *l=5, ("ldd %D0,%1+3" CR_TAB
4482 "ldd %C0,%1+2" CR_TAB
4483 "ldd __tmp_reg__,%1+1" CR_TAB
4484 "ld %A0,%1" CR_TAB
4485 "mov %B0,__tmp_reg__");
4486 else if (reg_base == reg_dest + 2)
4487 return *l=5, ("ld %A0,%1" CR_TAB
4488 "ldd %B0,%1+1" CR_TAB
4489 "ldd __tmp_reg__,%1+2" CR_TAB
4490 "ldd %D0,%1+3" CR_TAB
4491 "mov %C0,__tmp_reg__");
4492 else
4493 return *l=4, ("ld %A0,%1" CR_TAB
4494 "ldd %B0,%1+1" CR_TAB
4495 "ldd %C0,%1+2" CR_TAB
4496 "ldd %D0,%1+3");
4499 else if (GET_CODE (base) == PLUS) /* (R + i) */
4501 int disp = INTVAL (XEXP (base, 1));
4503 if (AVR_TINY)
4504 return avr_out_movsi_r_mr_reg_disp_tiny (insn, op, l);
4506 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
4508 if (REGNO (XEXP (base, 0)) != REG_Y)
4509 fatal_insn ("incorrect insn:",insn);
4511 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
4512 return *l = 6, ("adiw r28,%o1-60" CR_TAB
4513 "ldd %A0,Y+60" CR_TAB
4514 "ldd %B0,Y+61" CR_TAB
4515 "ldd %C0,Y+62" CR_TAB
4516 "ldd %D0,Y+63" CR_TAB
4517 "sbiw r28,%o1-60");
4519 return *l = 8, ("subi r28,lo8(-%o1)" CR_TAB
4520 "sbci r29,hi8(-%o1)" CR_TAB
4521 "ld %A0,Y" CR_TAB
4522 "ldd %B0,Y+1" CR_TAB
4523 "ldd %C0,Y+2" CR_TAB
4524 "ldd %D0,Y+3" CR_TAB
4525 "subi r28,lo8(%o1)" CR_TAB
4526 "sbci r29,hi8(%o1)");
4529 reg_base = true_regnum (XEXP (base, 0));
4530 if (reg_base == REG_X)
4532 /* R = (X + d) */
4533 if (reg_dest == REG_X)
4535 *l = 7;
4536 /* "ld r26,-X" is undefined */
4537 return ("adiw r26,%o1+3" CR_TAB
4538 "ld r29,X" CR_TAB
4539 "ld r28,-X" CR_TAB
4540 "ld __tmp_reg__,-X" CR_TAB
4541 "sbiw r26,1" CR_TAB
4542 "ld r26,X" CR_TAB
4543 "mov r27,__tmp_reg__");
4545 *l = 6;
4546 if (reg_dest == REG_X - 2)
4547 return ("adiw r26,%o1" CR_TAB
4548 "ld r24,X+" CR_TAB
4549 "ld r25,X+" CR_TAB
4550 "ld __tmp_reg__,X+" CR_TAB
4551 "ld r27,X" CR_TAB
4552 "mov r26,__tmp_reg__");
4554 return ("adiw r26,%o1" CR_TAB
4555 "ld %A0,X+" CR_TAB
4556 "ld %B0,X+" CR_TAB
4557 "ld %C0,X+" CR_TAB
4558 "ld %D0,X" CR_TAB
4559 "sbiw r26,%o1+3");
4561 if (reg_dest == reg_base)
4562 return *l=5, ("ldd %D0,%D1" CR_TAB
4563 "ldd %C0,%C1" CR_TAB
4564 "ldd __tmp_reg__,%B1" CR_TAB
4565 "ldd %A0,%A1" CR_TAB
4566 "mov %B0,__tmp_reg__");
4567 else if (reg_dest == reg_base - 2)
4568 return *l=5, ("ldd %A0,%A1" CR_TAB
4569 "ldd %B0,%B1" CR_TAB
4570 "ldd __tmp_reg__,%C1" CR_TAB
4571 "ldd %D0,%D1" CR_TAB
4572 "mov %C0,__tmp_reg__");
4573 return *l=4, ("ldd %A0,%A1" CR_TAB
4574 "ldd %B0,%B1" CR_TAB
4575 "ldd %C0,%C1" CR_TAB
4576 "ldd %D0,%D1");
4578 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4579 return *l=4, ("ld %D0,%1" CR_TAB
4580 "ld %C0,%1" CR_TAB
4581 "ld %B0,%1" CR_TAB
4582 "ld %A0,%1");
4583 else if (GET_CODE (base) == POST_INC) /* (R++) */
4584 return *l=4, ("ld %A0,%1" CR_TAB
4585 "ld %B0,%1" CR_TAB
4586 "ld %C0,%1" CR_TAB
4587 "ld %D0,%1");
4588 else if (CONSTANT_ADDRESS_P (base))
4590 if (io_address_operand (base, SImode))
4592 *l = 4;
4593 return ("in %A0,%i1" CR_TAB
4594 "in %B0,%i1+1" CR_TAB
4595 "in %C0,%i1+2" CR_TAB
4596 "in %D0,%i1+3");
4598 else
4600 *l = AVR_TINY ? 4 : 8;
4601 return ("lds %A0,%m1" CR_TAB
4602 "lds %B0,%m1+1" CR_TAB
4603 "lds %C0,%m1+2" CR_TAB
4604 "lds %D0,%m1+3");
4608 fatal_insn ("unknown move insn:",insn);
4609 return "";
4612 static const char*
4613 avr_out_movsi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *l)
4615 rtx dest = op[0];
4616 rtx src = op[1];
4617 rtx base = XEXP (dest, 0);
4618 int reg_base = true_regnum (base);
4619 int reg_src = true_regnum (src);
4621 if (reg_base == reg_src)
4623 /* "ld r26,-X" is undefined */
4624 if (reg_unused_after (insn, base))
4626 return *l = 7, ("mov __tmp_reg__, %B1" CR_TAB
4627 "st %0,%A1" CR_TAB
4628 TINY_ADIW (%E0, %F0, 1) CR_TAB
4629 "st %0+,__tmp_reg__" CR_TAB
4630 "st %0+,%C1" CR_TAB
4631 "st %0+,%D1");
4633 else
4635 return *l = 9, ("mov __tmp_reg__, %B1" CR_TAB
4636 "st %0,%A1" CR_TAB
4637 TINY_ADIW (%E0, %F0, 1) CR_TAB
4638 "st %0+,__tmp_reg__" CR_TAB
4639 "st %0+,%C1" CR_TAB
4640 "st %0+,%D1" CR_TAB
4641 TINY_SBIW (%E0, %F0, 3));
4644 else if (reg_base == reg_src + 2)
4646 if (reg_unused_after (insn, base))
4647 return *l = 7, ("mov __zero_reg__,%C1" CR_TAB
4648 "mov __tmp_reg__,%D1" CR_TAB
4649 "st %0+,%A1" CR_TAB
4650 "st %0+,%B1" CR_TAB
4651 "st %0+,__zero_reg__" CR_TAB
4652 "st %0,__tmp_reg__" CR_TAB
4653 "clr __zero_reg__");
4654 else
4655 return *l = 9, ("mov __zero_reg__,%C1" CR_TAB
4656 "mov __tmp_reg__,%D1" CR_TAB
4657 "st %0+,%A1" CR_TAB
4658 "st %0+,%B1" CR_TAB
4659 "st %0+,__zero_reg__" CR_TAB
4660 "st %0,__tmp_reg__" CR_TAB
4661 "clr __zero_reg__" CR_TAB
4662 TINY_SBIW (%E0, %F0, 3));
4665 return *l = 6, ("st %0+,%A1" CR_TAB
4666 "st %0+,%B1" CR_TAB
4667 "st %0+,%C1" CR_TAB
4668 "st %0,%D1" CR_TAB
4669 TINY_SBIW (%E0, %F0, 3));
4672 static const char*
4673 avr_out_movsi_mr_r_reg_disp_tiny (rtx op[], int *l)
4675 rtx dest = op[0];
4676 rtx src = op[1];
4677 rtx base = XEXP (dest, 0);
4678 int reg_base = REGNO (XEXP (base, 0));
4679 int reg_src =true_regnum (src);
4681 if (reg_base == reg_src)
4683 *l = 11;
4684 return ("mov __tmp_reg__,%A2" CR_TAB
4685 "mov __zero_reg__,%B2" CR_TAB
4686 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4687 "st %b0+,__tmp_reg__" CR_TAB
4688 "st %b0+,__zero_reg__" CR_TAB
4689 "st %b0+,%C2" CR_TAB
4690 "st %b0,%D2" CR_TAB
4691 "clr __zero_reg__" CR_TAB
4692 TINY_SBIW (%I0, %J0, %o0+3));
4694 else if (reg_src == reg_base - 2)
4696 *l = 11;
4697 return ("mov __tmp_reg__,%C2" CR_TAB
4698 "mov __zero_reg__,%D2" CR_TAB
4699 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4700 "st %b0+,%A0" CR_TAB
4701 "st %b0+,%B0" CR_TAB
4702 "st %b0+,__tmp_reg__" CR_TAB
4703 "st %b0,__zero_reg__" CR_TAB
4704 "clr __zero_reg__" CR_TAB
4705 TINY_SBIW (%I0, %J0, %o0+3));
4707 *l = 8;
4708 return (TINY_ADIW (%I0, %J0, %o0) CR_TAB
4709 "st %b0+,%A1" CR_TAB
4710 "st %b0+,%B1" CR_TAB
4711 "st %b0+,%C1" CR_TAB
4712 "st %b0,%D1" CR_TAB
4713 TINY_SBIW (%I0, %J0, %o0+3));
4716 static const char*
4717 out_movsi_mr_r (rtx_insn *insn, rtx op[], int *l)
4719 rtx dest = op[0];
4720 rtx src = op[1];
4721 rtx base = XEXP (dest, 0);
4722 int reg_base = true_regnum (base);
4723 int reg_src = true_regnum (src);
4724 int tmp;
4726 if (!l)
4727 l = &tmp;
4729 if (CONSTANT_ADDRESS_P (base))
4731 if (io_address_operand (base, SImode))
4733 return *l=4,("out %i0, %A1" CR_TAB
4734 "out %i0+1,%B1" CR_TAB
4735 "out %i0+2,%C1" CR_TAB
4736 "out %i0+3,%D1");
4738 else
4740 *l = AVR_TINY ? 4 : 8;
4741 return ("sts %m0,%A1" CR_TAB
4742 "sts %m0+1,%B1" CR_TAB
4743 "sts %m0+2,%C1" CR_TAB
4744 "sts %m0+3,%D1");
4748 if (reg_base > 0) /* (r) */
4750 if (AVR_TINY)
4751 return avr_out_movsi_mr_r_reg_no_disp_tiny (insn, op, l);
4753 if (reg_base == REG_X) /* (R26) */
4755 if (reg_src == REG_X)
4757 /* "st X+,r26" is undefined */
4758 if (reg_unused_after (insn, base))
4759 return *l=6, ("mov __tmp_reg__,r27" CR_TAB
4760 "st X,r26" CR_TAB
4761 "adiw r26,1" CR_TAB
4762 "st X+,__tmp_reg__" CR_TAB
4763 "st X+,r28" CR_TAB
4764 "st X,r29");
4765 else
4766 return *l=7, ("mov __tmp_reg__,r27" CR_TAB
4767 "st X,r26" CR_TAB
4768 "adiw r26,1" CR_TAB
4769 "st X+,__tmp_reg__" CR_TAB
4770 "st X+,r28" CR_TAB
4771 "st X,r29" CR_TAB
4772 "sbiw r26,3");
4774 else if (reg_base == reg_src + 2)
4776 if (reg_unused_after (insn, base))
4777 return *l=7, ("mov __zero_reg__,%C1" CR_TAB
4778 "mov __tmp_reg__,%D1" CR_TAB
4779 "st %0+,%A1" CR_TAB
4780 "st %0+,%B1" CR_TAB
4781 "st %0+,__zero_reg__" CR_TAB
4782 "st %0,__tmp_reg__" CR_TAB
4783 "clr __zero_reg__");
4784 else
4785 return *l=8, ("mov __zero_reg__,%C1" CR_TAB
4786 "mov __tmp_reg__,%D1" CR_TAB
4787 "st %0+,%A1" CR_TAB
4788 "st %0+,%B1" CR_TAB
4789 "st %0+,__zero_reg__" CR_TAB
4790 "st %0,__tmp_reg__" CR_TAB
4791 "clr __zero_reg__" CR_TAB
4792 "sbiw r26,3");
4794 return *l=5, ("st %0+,%A1" CR_TAB
4795 "st %0+,%B1" CR_TAB
4796 "st %0+,%C1" CR_TAB
4797 "st %0,%D1" CR_TAB
4798 "sbiw r26,3");
4800 else
4801 return *l=4, ("st %0,%A1" CR_TAB
4802 "std %0+1,%B1" CR_TAB
4803 "std %0+2,%C1" CR_TAB
4804 "std %0+3,%D1");
4806 else if (GET_CODE (base) == PLUS) /* (R + i) */
4808 int disp = INTVAL (XEXP (base, 1));
4810 if (AVR_TINY)
4811 return avr_out_movsi_mr_r_reg_disp_tiny (op, l);
4813 reg_base = REGNO (XEXP (base, 0));
4814 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
4816 if (reg_base != REG_Y)
4817 fatal_insn ("incorrect insn:",insn);
4819 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
4820 return *l = 6, ("adiw r28,%o0-60" CR_TAB
4821 "std Y+60,%A1" CR_TAB
4822 "std Y+61,%B1" CR_TAB
4823 "std Y+62,%C1" CR_TAB
4824 "std Y+63,%D1" CR_TAB
4825 "sbiw r28,%o0-60");
4827 return *l = 8, ("subi r28,lo8(-%o0)" CR_TAB
4828 "sbci r29,hi8(-%o0)" CR_TAB
4829 "st Y,%A1" CR_TAB
4830 "std Y+1,%B1" CR_TAB
4831 "std Y+2,%C1" CR_TAB
4832 "std Y+3,%D1" CR_TAB
4833 "subi r28,lo8(%o0)" CR_TAB
4834 "sbci r29,hi8(%o0)");
4836 if (reg_base == REG_X)
4838 /* (X + d) = R */
4839 if (reg_src == REG_X)
4841 *l = 9;
4842 return ("mov __tmp_reg__,r26" CR_TAB
4843 "mov __zero_reg__,r27" CR_TAB
4844 "adiw r26,%o0" CR_TAB
4845 "st X+,__tmp_reg__" CR_TAB
4846 "st X+,__zero_reg__" CR_TAB
4847 "st X+,r28" CR_TAB
4848 "st X,r29" CR_TAB
4849 "clr __zero_reg__" CR_TAB
4850 "sbiw r26,%o0+3");
4852 else if (reg_src == REG_X - 2)
4854 *l = 9;
4855 return ("mov __tmp_reg__,r26" CR_TAB
4856 "mov __zero_reg__,r27" CR_TAB
4857 "adiw r26,%o0" CR_TAB
4858 "st X+,r24" CR_TAB
4859 "st X+,r25" CR_TAB
4860 "st X+,__tmp_reg__" CR_TAB
4861 "st X,__zero_reg__" CR_TAB
4862 "clr __zero_reg__" CR_TAB
4863 "sbiw r26,%o0+3");
4865 *l = 6;
4866 return ("adiw r26,%o0" CR_TAB
4867 "st X+,%A1" CR_TAB
4868 "st X+,%B1" CR_TAB
4869 "st X+,%C1" CR_TAB
4870 "st X,%D1" CR_TAB
4871 "sbiw r26,%o0+3");
4873 return *l=4, ("std %A0,%A1" CR_TAB
4874 "std %B0,%B1" CR_TAB
4875 "std %C0,%C1" CR_TAB
4876 "std %D0,%D1");
4878 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4879 return *l=4, ("st %0,%D1" CR_TAB
4880 "st %0,%C1" CR_TAB
4881 "st %0,%B1" CR_TAB
4882 "st %0,%A1");
4883 else if (GET_CODE (base) == POST_INC) /* (R++) */
4884 return *l=4, ("st %0,%A1" CR_TAB
4885 "st %0,%B1" CR_TAB
4886 "st %0,%C1" CR_TAB
4887 "st %0,%D1");
4888 fatal_insn ("unknown move insn:",insn);
4889 return "";
4892 const char *
4893 output_movsisf (rtx_insn *insn, rtx operands[], int *l)
4895 int dummy;
4896 rtx dest = operands[0];
4897 rtx src = operands[1];
4898 int *real_l = l;
4900 if (avr_mem_flash_p (src)
4901 || avr_mem_flash_p (dest))
4903 return avr_out_lpm (insn, operands, real_l);
4906 if (!l)
4907 l = &dummy;
4909 gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 4);
4911 if (REG_P (dest))
4913 if (REG_P (src)) /* mov r,r */
4915 if (true_regnum (dest) > true_regnum (src))
4917 if (AVR_HAVE_MOVW)
4919 *l = 2;
4920 return ("movw %C0,%C1" CR_TAB
4921 "movw %A0,%A1");
4923 *l = 4;
4924 return ("mov %D0,%D1" CR_TAB
4925 "mov %C0,%C1" CR_TAB
4926 "mov %B0,%B1" CR_TAB
4927 "mov %A0,%A1");
4929 else
4931 if (AVR_HAVE_MOVW)
4933 *l = 2;
4934 return ("movw %A0,%A1" CR_TAB
4935 "movw %C0,%C1");
4937 *l = 4;
4938 return ("mov %A0,%A1" CR_TAB
4939 "mov %B0,%B1" CR_TAB
4940 "mov %C0,%C1" CR_TAB
4941 "mov %D0,%D1");
4944 else if (CONSTANT_P (src))
4946 return output_reload_insisf (operands, NULL_RTX, real_l);
4948 else if (MEM_P (src))
4949 return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
4951 else if (MEM_P (dest))
4953 const char *templ;
4955 if (src == CONST0_RTX (GET_MODE (dest)))
4956 operands[1] = zero_reg_rtx;
4958 templ = out_movsi_mr_r (insn, operands, real_l);
4960 if (!real_l)
4961 output_asm_insn (templ, operands);
4963 operands[1] = src;
4964 return "";
4966 fatal_insn ("invalid insn:", insn);
4967 return "";
4971 /* Handle loads of 24-bit types from memory to register. */
4973 static const char*
4974 avr_out_load_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
4976 rtx dest = op[0];
4977 rtx src = op[1];
4978 rtx base = XEXP (src, 0);
4979 int reg_dest = true_regnum (dest);
4980 int reg_base = true_regnum (base);
4982 if (reg_base == reg_dest)
4984 return avr_asm_len (TINY_ADIW (%E1, %F1, 2) CR_TAB
4985 "ld %C0,%1" CR_TAB
4986 "ld __tmp_reg__,-%1" CR_TAB
4987 TINY_SBIW (%E1, %F1, 1) CR_TAB
4988 "ld %A0,%1" CR_TAB
4989 "mov %B0,__tmp_reg__", op, plen, -8);
4991 else
4993 avr_asm_len ("ld %A0,%1+" CR_TAB
4994 "ld %B0,%1+" CR_TAB
4995 "ld %C0,%1", op, plen, -3);
4997 if (reg_dest != reg_base - 2
4998 && !reg_unused_after (insn, base))
5000 avr_asm_len (TINY_SBIW (%E1, %F1, 2), op, plen, 2);
5002 return "";
5006 static const char*
5007 avr_out_load_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
5009 rtx dest = op[0];
5010 rtx src = op[1];
5011 rtx base = XEXP (src, 0);
5012 int reg_dest = true_regnum (dest);
5013 int reg_base = true_regnum (base);
5015 reg_base = true_regnum (XEXP (base, 0));
5016 if (reg_base == reg_dest)
5018 return avr_asm_len (TINY_ADIW (%I1, %J1, %o1+2) CR_TAB
5019 "ld %C0,%b1" CR_TAB
5020 "ld __tmp_reg__,-%b1" CR_TAB
5021 TINY_SBIW (%I1, %J1, 1) CR_TAB
5022 "ld %A0,%b1" CR_TAB
5023 "mov %B0,__tmp_reg__", op, plen, -8);
5025 else
5027 avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
5028 "ld %A0,%b1+" CR_TAB
5029 "ld %B0,%b1+" CR_TAB
5030 "ld %C0,%b1", op, plen, -5);
5032 if (reg_dest != reg_base - 2
5033 && !reg_unused_after (insn, XEXP (base, 0)))
5034 avr_asm_len (TINY_SBIW (%I1, %J1, %o1+2), op, plen, 2);
5036 return "";
5040 static const char*
5041 avr_out_load_psi (rtx_insn *insn, rtx *op, int *plen)
5043 rtx dest = op[0];
5044 rtx src = op[1];
5045 rtx base = XEXP (src, 0);
5046 int reg_dest = true_regnum (dest);
5047 int reg_base = true_regnum (base);
5049 if (reg_base > 0)
5051 if (AVR_TINY)
5052 return avr_out_load_psi_reg_no_disp_tiny (insn, op, plen);
5054 if (reg_base == REG_X) /* (R26) */
5056 if (reg_dest == REG_X)
5057 /* "ld r26,-X" is undefined */
5058 return avr_asm_len ("adiw r26,2" CR_TAB
5059 "ld r28,X" CR_TAB
5060 "ld __tmp_reg__,-X" CR_TAB
5061 "sbiw r26,1" CR_TAB
5062 "ld r26,X" CR_TAB
5063 "mov r27,__tmp_reg__", op, plen, -6);
5064 else
5066 avr_asm_len ("ld %A0,X+" CR_TAB
5067 "ld %B0,X+" CR_TAB
5068 "ld %C0,X", op, plen, -3);
5070 if (reg_dest != REG_X - 2
5071 && !reg_unused_after (insn, base))
5073 avr_asm_len ("sbiw r26,2", op, plen, 1);
5076 return "";
5079 else /* reg_base != REG_X */
5081 if (reg_dest == reg_base)
5082 return avr_asm_len ("ldd %C0,%1+2" CR_TAB
5083 "ldd __tmp_reg__,%1+1" CR_TAB
5084 "ld %A0,%1" CR_TAB
5085 "mov %B0,__tmp_reg__", op, plen, -4);
5086 else
5087 return avr_asm_len ("ld %A0,%1" CR_TAB
5088 "ldd %B0,%1+1" CR_TAB
5089 "ldd %C0,%1+2", op, plen, -3);
5092 else if (GET_CODE (base) == PLUS) /* (R + i) */
5094 int disp = INTVAL (XEXP (base, 1));
5096 if (AVR_TINY)
5097 return avr_out_load_psi_reg_disp_tiny (insn, op, plen);
5099 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
5101 if (REGNO (XEXP (base, 0)) != REG_Y)
5102 fatal_insn ("incorrect insn:",insn);
5104 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
5105 return avr_asm_len ("adiw r28,%o1-61" CR_TAB
5106 "ldd %A0,Y+61" CR_TAB
5107 "ldd %B0,Y+62" CR_TAB
5108 "ldd %C0,Y+63" CR_TAB
5109 "sbiw r28,%o1-61", op, plen, -5);
5111 return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
5112 "sbci r29,hi8(-%o1)" CR_TAB
5113 "ld %A0,Y" CR_TAB
5114 "ldd %B0,Y+1" CR_TAB
5115 "ldd %C0,Y+2" CR_TAB
5116 "subi r28,lo8(%o1)" CR_TAB
5117 "sbci r29,hi8(%o1)", op, plen, -7);
5120 reg_base = true_regnum (XEXP (base, 0));
5121 if (reg_base == REG_X)
5123 /* R = (X + d) */
5124 if (reg_dest == REG_X)
5126 /* "ld r26,-X" is undefined */
5127 return avr_asm_len ("adiw r26,%o1+2" CR_TAB
5128 "ld r28,X" CR_TAB
5129 "ld __tmp_reg__,-X" CR_TAB
5130 "sbiw r26,1" CR_TAB
5131 "ld r26,X" CR_TAB
5132 "mov r27,__tmp_reg__", op, plen, -6);
5135 avr_asm_len ("adiw r26,%o1" CR_TAB
5136 "ld %A0,X+" CR_TAB
5137 "ld %B0,X+" CR_TAB
5138 "ld %C0,X", op, plen, -4);
5140 if (reg_dest != REG_W
5141 && !reg_unused_after (insn, XEXP (base, 0)))
5142 avr_asm_len ("sbiw r26,%o1+2", op, plen, 1);
5144 return "";
5147 if (reg_dest == reg_base)
5148 return avr_asm_len ("ldd %C0,%C1" CR_TAB
5149 "ldd __tmp_reg__,%B1" CR_TAB
5150 "ldd %A0,%A1" CR_TAB
5151 "mov %B0,__tmp_reg__", op, plen, -4);
5153 return avr_asm_len ("ldd %A0,%A1" CR_TAB
5154 "ldd %B0,%B1" CR_TAB
5155 "ldd %C0,%C1", op, plen, -3);
5157 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5158 return avr_asm_len ("ld %C0,%1" CR_TAB
5159 "ld %B0,%1" CR_TAB
5160 "ld %A0,%1", op, plen, -3);
5161 else if (GET_CODE (base) == POST_INC) /* (R++) */
5162 return avr_asm_len ("ld %A0,%1" CR_TAB
5163 "ld %B0,%1" CR_TAB
5164 "ld %C0,%1", op, plen, -3);
5166 else if (CONSTANT_ADDRESS_P (base))
5168 int n_words = AVR_TINY ? 3 : 6;
5169 return avr_asm_len ("lds %A0,%m1" CR_TAB
5170 "lds %B0,%m1+1" CR_TAB
5171 "lds %C0,%m1+2", op, plen , -n_words);
5174 fatal_insn ("unknown move insn:",insn);
5175 return "";
5179 static const char*
5180 avr_out_store_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
5182 rtx dest = op[0];
5183 rtx src = op[1];
5184 rtx base = XEXP (dest, 0);
5185 int reg_base = true_regnum (base);
5186 int reg_src = true_regnum (src);
5188 if (reg_base == reg_src)
5190 avr_asm_len ("st %0,%A1" CR_TAB
5191 "mov __tmp_reg__,%B1" CR_TAB
5192 TINY_ADIW (%E0, %F0, 1) CR_TAB /* st X+, r27 is undefined */
5193 "st %0+,__tmp_reg__" CR_TAB
5194 "st %0,%C1", op, plen, -6);
5197 else if (reg_src == reg_base - 2)
5199 avr_asm_len ("st %0,%A1" CR_TAB
5200 "mov __tmp_reg__,%C1" CR_TAB
5201 TINY_ADIW (%E0, %F0, 1) CR_TAB
5202 "st %0+,%B1" CR_TAB
5203 "st %0,__tmp_reg__", op, plen, 6);
5205 else
5207 avr_asm_len ("st %0+,%A1" CR_TAB
5208 "st %0+,%B1" CR_TAB
5209 "st %0,%C1", op, plen, -3);
5212 if (!reg_unused_after (insn, base))
5213 avr_asm_len (TINY_SBIW (%E0, %F0, 2), op, plen, 2);
5215 return "";
5218 static const char*
5219 avr_out_store_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
5221 rtx dest = op[0];
5222 rtx src = op[1];
5223 rtx base = XEXP (dest, 0);
5224 int reg_base = REGNO (XEXP (base, 0));
5225 int reg_src = true_regnum (src);
5227 if (reg_src == reg_base)
5228 avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
5229 "mov __zero_reg__,%B1" CR_TAB
5230 TINY_ADIW (%I0, %J0, %o0) CR_TAB
5231 "st %b0+,__tmp_reg__" CR_TAB
5232 "st %b0+,__zero_reg__" CR_TAB
5233 "st %b0,%C1" CR_TAB
5234 "clr __zero_reg__", op, plen, -8);
5235 else if (reg_src == reg_base - 2)
5236 avr_asm_len ("mov __tmp_reg__,%C1" CR_TAB
5237 TINY_ADIW (%I0, %J0, %o0) CR_TAB
5238 "st %b0+,%A1" CR_TAB
5239 "st %b0+,%B1" CR_TAB
5240 "st %b0,__tmp_reg__", op, plen, -6);
5241 else
5242 avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
5243 "st %b0+,%A1" CR_TAB
5244 "st %b0+,%B1" CR_TAB
5245 "st %b0,%C1", op, plen, -5);
5247 if (!reg_unused_after (insn, XEXP (base, 0)))
5248 avr_asm_len (TINY_SBIW (%I0, %J0, %o0+2), op, plen, 2);
5250 return "";
5253 /* Handle store of 24-bit type from register or zero to memory. */
5255 static const char*
5256 avr_out_store_psi (rtx_insn *insn, rtx *op, int *plen)
5258 rtx dest = op[0];
5259 rtx src = op[1];
5260 rtx base = XEXP (dest, 0);
5261 int reg_base = true_regnum (base);
5263 if (CONSTANT_ADDRESS_P (base))
5265 int n_words = AVR_TINY ? 3 : 6;
5266 return avr_asm_len ("sts %m0,%A1" CR_TAB
5267 "sts %m0+1,%B1" CR_TAB
5268 "sts %m0+2,%C1", op, plen, -n_words);
5271 if (reg_base > 0) /* (r) */
5273 if (AVR_TINY)
5274 return avr_out_store_psi_reg_no_disp_tiny (insn, op, plen);
5276 if (reg_base == REG_X) /* (R26) */
5278 gcc_assert (!reg_overlap_mentioned_p (base, src));
5280 avr_asm_len ("st %0+,%A1" CR_TAB
5281 "st %0+,%B1" CR_TAB
5282 "st %0,%C1", op, plen, -3);
5284 if (!reg_unused_after (insn, base))
5285 avr_asm_len ("sbiw r26,2", op, plen, 1);
5287 return "";
5289 else
5290 return avr_asm_len ("st %0,%A1" CR_TAB
5291 "std %0+1,%B1" CR_TAB
5292 "std %0+2,%C1", op, plen, -3);
5294 else if (GET_CODE (base) == PLUS) /* (R + i) */
5296 int disp = INTVAL (XEXP (base, 1));
5298 if (AVR_TINY)
5299 return avr_out_store_psi_reg_disp_tiny (insn, op, plen);
5301 reg_base = REGNO (XEXP (base, 0));
5303 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5305 if (reg_base != REG_Y)
5306 fatal_insn ("incorrect insn:",insn);
5308 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
5309 return avr_asm_len ("adiw r28,%o0-61" CR_TAB
5310 "std Y+61,%A1" CR_TAB
5311 "std Y+62,%B1" CR_TAB
5312 "std Y+63,%C1" CR_TAB
5313 "sbiw r28,%o0-61", op, plen, -5);
5315 return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5316 "sbci r29,hi8(-%o0)" CR_TAB
5317 "st Y,%A1" CR_TAB
5318 "std Y+1,%B1" CR_TAB
5319 "std Y+2,%C1" CR_TAB
5320 "subi r28,lo8(%o0)" CR_TAB
5321 "sbci r29,hi8(%o0)", op, plen, -7);
5323 if (reg_base == REG_X)
5325 /* (X + d) = R */
5326 gcc_assert (!reg_overlap_mentioned_p (XEXP (base, 0), src));
5328 avr_asm_len ("adiw r26,%o0" CR_TAB
5329 "st X+,%A1" CR_TAB
5330 "st X+,%B1" CR_TAB
5331 "st X,%C1", op, plen, -4);
5333 if (!reg_unused_after (insn, XEXP (base, 0)))
5334 avr_asm_len ("sbiw r26,%o0+2", op, plen, 1);
5336 return "";
5339 return avr_asm_len ("std %A0,%A1" CR_TAB
5340 "std %B0,%B1" CR_TAB
5341 "std %C0,%C1", op, plen, -3);
5343 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5344 return avr_asm_len ("st %0,%C1" CR_TAB
5345 "st %0,%B1" CR_TAB
5346 "st %0,%A1", op, plen, -3);
5347 else if (GET_CODE (base) == POST_INC) /* (R++) */
5348 return avr_asm_len ("st %0,%A1" CR_TAB
5349 "st %0,%B1" CR_TAB
5350 "st %0,%C1", op, plen, -3);
5352 fatal_insn ("unknown move insn:",insn);
5353 return "";
5357 /* Move around 24-bit stuff. */
5359 const char *
5360 avr_out_movpsi (rtx_insn *insn, rtx *op, int *plen)
5362 rtx dest = op[0];
5363 rtx src = op[1];
5365 if (avr_mem_flash_p (src)
5366 || avr_mem_flash_p (dest))
5368 return avr_out_lpm (insn, op, plen);
5371 if (register_operand (dest, VOIDmode))
5373 if (register_operand (src, VOIDmode)) /* mov r,r */
5375 if (true_regnum (dest) > true_regnum (src))
5377 avr_asm_len ("mov %C0,%C1", op, plen, -1);
5379 if (AVR_HAVE_MOVW)
5380 return avr_asm_len ("movw %A0,%A1", op, plen, 1);
5381 else
5382 return avr_asm_len ("mov %B0,%B1" CR_TAB
5383 "mov %A0,%A1", op, plen, 2);
5385 else
5387 if (AVR_HAVE_MOVW)
5388 avr_asm_len ("movw %A0,%A1", op, plen, -1);
5389 else
5390 avr_asm_len ("mov %A0,%A1" CR_TAB
5391 "mov %B0,%B1", op, plen, -2);
5393 return avr_asm_len ("mov %C0,%C1", op, plen, 1);
5396 else if (CONSTANT_P (src))
5398 return avr_out_reload_inpsi (op, NULL_RTX, plen);
5400 else if (MEM_P (src))
5401 return avr_out_load_psi (insn, op, plen); /* mov r,m */
5403 else if (MEM_P (dest))
5405 rtx xop[2];
5407 xop[0] = dest;
5408 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
5410 return avr_out_store_psi (insn, xop, plen);
5413 fatal_insn ("invalid insn:", insn);
5414 return "";
5417 static const char*
5418 avr_out_movqi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5420 rtx dest = op[0];
5421 rtx src = op[1];
5422 rtx x = XEXP (dest, 0);
5424 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
5426 avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
5427 TINY_ADIW (%I0, %J0, %o0) CR_TAB
5428 "st %b0,__tmp_reg__", op, plen, -4);
5430 else
5432 avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
5433 "st %b0,%1", op, plen, -3);
5436 if (!reg_unused_after (insn, XEXP (x, 0)))
5437 avr_asm_len (TINY_SBIW (%I0, %J0, %o0), op, plen, 2);
5439 return "";
5442 static const char*
5443 out_movqi_mr_r (rtx_insn *insn, rtx op[], int *plen)
5445 rtx dest = op[0];
5446 rtx src = op[1];
5447 rtx x = XEXP (dest, 0);
5449 if (CONSTANT_ADDRESS_P (x))
5451 int n_words = AVR_TINY ? 1 : 2;
5452 return io_address_operand (x, QImode)
5453 ? avr_asm_len ("out %i0,%1", op, plen, -1)
5454 : avr_asm_len ("sts %m0,%1", op, plen, -n_words);
5456 else if (GET_CODE (x) == PLUS
5457 && REG_P (XEXP (x, 0))
5458 && CONST_INT_P (XEXP (x, 1)))
5460 /* memory access by reg+disp */
5462 int disp = INTVAL (XEXP (x, 1));
5464 if (AVR_TINY)
5465 return avr_out_movqi_mr_r_reg_disp_tiny (insn, op, plen);
5467 if (disp - GET_MODE_SIZE (GET_MODE (dest)) >= 63)
5469 if (REGNO (XEXP (x, 0)) != REG_Y)
5470 fatal_insn ("incorrect insn:",insn);
5472 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
5473 return avr_asm_len ("adiw r28,%o0-63" CR_TAB
5474 "std Y+63,%1" CR_TAB
5475 "sbiw r28,%o0-63", op, plen, -3);
5477 return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5478 "sbci r29,hi8(-%o0)" CR_TAB
5479 "st Y,%1" CR_TAB
5480 "subi r28,lo8(%o0)" CR_TAB
5481 "sbci r29,hi8(%o0)", op, plen, -5);
5483 else if (REGNO (XEXP (x, 0)) == REG_X)
5485 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
5487 avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
5488 "adiw r26,%o0" CR_TAB
5489 "st X,__tmp_reg__", op, plen, -3);
5491 else
5493 avr_asm_len ("adiw r26,%o0" CR_TAB
5494 "st X,%1", op, plen, -2);
5497 if (!reg_unused_after (insn, XEXP (x, 0)))
5498 avr_asm_len ("sbiw r26,%o0", op, plen, 1);
5500 return "";
5503 return avr_asm_len ("std %0,%1", op, plen, -1);
5506 return avr_asm_len ("st %0,%1", op, plen, -1);
5510 /* Helper for the next function for XMEGA. It does the same
5511 but with low byte first. */
5513 static const char*
5514 avr_out_movhi_mr_r_xmega (rtx_insn *insn, rtx op[], int *plen)
5516 rtx dest = op[0];
5517 rtx src = op[1];
5518 rtx base = XEXP (dest, 0);
5519 int reg_base = true_regnum (base);
5520 int reg_src = true_regnum (src);
5522 /* "volatile" forces writing low byte first, even if less efficient,
5523 for correct operation with 16-bit I/O registers like SP. */
5524 int mem_volatile_p = MEM_VOLATILE_P (dest);
5526 if (CONSTANT_ADDRESS_P (base))
5528 return io_address_operand (base, HImode)
5529 ? avr_asm_len ("out %i0,%A1" CR_TAB
5530 "out %i0+1,%B1", op, plen, -2)
5532 : avr_asm_len ("sts %m0,%A1" CR_TAB
5533 "sts %m0+1,%B1", op, plen, -4);
5536 if (reg_base > 0)
5538 if (reg_base != REG_X)
5539 return avr_asm_len ("st %0,%A1" CR_TAB
5540 "std %0+1,%B1", op, plen, -2);
5542 if (reg_src == REG_X)
5543 /* "st X+,r26" and "st -X,r26" are undefined. */
5544 avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5545 "st X,r26" CR_TAB
5546 "adiw r26,1" CR_TAB
5547 "st X,__tmp_reg__", op, plen, -4);
5548 else
5549 avr_asm_len ("st X+,%A1" CR_TAB
5550 "st X,%B1", op, plen, -2);
5552 return reg_unused_after (insn, base)
5553 ? ""
5554 : avr_asm_len ("sbiw r26,1", op, plen, 1);
5556 else if (GET_CODE (base) == PLUS)
5558 int disp = INTVAL (XEXP (base, 1));
5559 reg_base = REGNO (XEXP (base, 0));
5560 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5562 if (reg_base != REG_Y)
5563 fatal_insn ("incorrect insn:",insn);
5565 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
5566 ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
5567 "std Y+62,%A1" CR_TAB
5568 "std Y+63,%B1" CR_TAB
5569 "sbiw r28,%o0-62", op, plen, -4)
5571 : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5572 "sbci r29,hi8(-%o0)" CR_TAB
5573 "st Y,%A1" CR_TAB
5574 "std Y+1,%B1" CR_TAB
5575 "subi r28,lo8(%o0)" CR_TAB
5576 "sbci r29,hi8(%o0)", op, plen, -6);
5579 if (reg_base != REG_X)
5580 return avr_asm_len ("std %A0,%A1" CR_TAB
5581 "std %B0,%B1", op, plen, -2);
5582 /* (X + d) = R */
5583 return reg_src == REG_X
5584 ? avr_asm_len ("mov __tmp_reg__,r26" CR_TAB
5585 "mov __zero_reg__,r27" CR_TAB
5586 "adiw r26,%o0" CR_TAB
5587 "st X+,__tmp_reg__" CR_TAB
5588 "st X,__zero_reg__" CR_TAB
5589 "clr __zero_reg__" CR_TAB
5590 "sbiw r26,%o0+1", op, plen, -7)
5592 : avr_asm_len ("adiw r26,%o0" CR_TAB
5593 "st X+,%A1" CR_TAB
5594 "st X,%B1" CR_TAB
5595 "sbiw r26,%o0+1", op, plen, -4);
5597 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5599 if (!mem_volatile_p)
5600 return avr_asm_len ("st %0,%B1" CR_TAB
5601 "st %0,%A1", op, plen, -2);
5603 return REGNO (XEXP (base, 0)) == REG_X
5604 ? avr_asm_len ("sbiw r26,2" CR_TAB
5605 "st X+,%A1" CR_TAB
5606 "st X,%B1" CR_TAB
5607 "sbiw r26,1", op, plen, -4)
5609 : avr_asm_len ("sbiw %r0,2" CR_TAB
5610 "st %p0,%A1" CR_TAB
5611 "std %p0+1,%B1", op, plen, -3);
5613 else if (GET_CODE (base) == POST_INC) /* (R++) */
5615 return avr_asm_len ("st %0,%A1" CR_TAB
5616 "st %0,%B1", op, plen, -2);
5619 fatal_insn ("unknown move insn:",insn);
5620 return "";
5623 static const char*
5624 avr_out_movhi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5626 rtx dest = op[0];
5627 rtx src = op[1];
5628 rtx base = XEXP (dest, 0);
5629 int reg_base = true_regnum (base);
5630 int reg_src = true_regnum (src);
5631 int mem_volatile_p = MEM_VOLATILE_P (dest);
5633 if (reg_base == reg_src)
5635 return !mem_volatile_p && reg_unused_after (insn, src)
5636 ? avr_asm_len ("mov __tmp_reg__,%B1" CR_TAB
5637 "st %0,%A1" CR_TAB
5638 TINY_ADIW (%E0, %F0, 1) CR_TAB
5639 "st %0,__tmp_reg__", op, plen, -5)
5640 : avr_asm_len ("mov __tmp_reg__,%B1" CR_TAB
5641 TINY_ADIW (%E0, %F0, 1) CR_TAB
5642 "st %0,__tmp_reg__" CR_TAB
5643 TINY_SBIW (%E0, %F0, 1) CR_TAB
5644 "st %0, %A1", op, plen, -7);
5647 return !mem_volatile_p && reg_unused_after (insn, base)
5648 ? avr_asm_len ("st %0+,%A1" CR_TAB
5649 "st %0,%B1", op, plen, -2)
5650 : avr_asm_len (TINY_ADIW (%E0, %F0, 1) CR_TAB
5651 "st %0,%B1" CR_TAB
5652 "st -%0,%A1", op, plen, -4);
5655 static const char*
5656 avr_out_movhi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5658 rtx dest = op[0];
5659 rtx src = op[1];
5660 rtx base = XEXP (dest, 0);
5661 int reg_base = REGNO (XEXP (base, 0));
5662 int reg_src = true_regnum (src);
5664 if (reg_src == reg_base)
5665 avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
5666 "mov __zero_reg__,%B1" CR_TAB
5667 TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
5668 "st %b0,__zero_reg__" CR_TAB
5669 "st -%b0,__tmp_reg__" CR_TAB
5670 "clr __zero_reg__", op, plen, -7);
5671 else
5672 avr_asm_len (TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
5673 "st %b0,%B1" CR_TAB
5674 "st -%b0,%A1", op, plen, -4);
5676 if (!reg_unused_after (insn, XEXP (base, 0)))
5677 avr_asm_len (TINY_SBIW (%I0, %J0, %o0), op, plen, 2);
5679 return "";
5682 static const char*
5683 avr_out_movhi_mr_r_post_inc_tiny (rtx op[], int *plen)
5685 return avr_asm_len (TINY_ADIW (%I0, %J0, 1) CR_TAB
5686 "st %p0,%B1" CR_TAB
5687 "st -%p0,%A1" CR_TAB
5688 TINY_ADIW (%I0, %J0, 2), op, plen, -6);
5691 static const char*
5692 out_movhi_mr_r (rtx_insn *insn, rtx op[], int *plen)
5694 rtx dest = op[0];
5695 rtx src = op[1];
5696 rtx base = XEXP (dest, 0);
5697 int reg_base = true_regnum (base);
5698 int reg_src = true_regnum (src);
5699 int mem_volatile_p;
5701 /* "volatile" forces writing high-byte first (no-xmega) resp.
5702 low-byte first (xmega) even if less efficient, for correct
5703 operation with 16-bit I/O registers like. */
5705 if (AVR_XMEGA)
5706 return avr_out_movhi_mr_r_xmega (insn, op, plen);
5708 mem_volatile_p = MEM_VOLATILE_P (dest);
5710 if (CONSTANT_ADDRESS_P (base))
5712 int n_words = AVR_TINY ? 2 : 4;
5713 return io_address_operand (base, HImode)
5714 ? avr_asm_len ("out %i0+1,%B1" CR_TAB
5715 "out %i0,%A1", op, plen, -2)
5717 : avr_asm_len ("sts %m0+1,%B1" CR_TAB
5718 "sts %m0,%A1", op, plen, -n_words);
5721 if (reg_base > 0)
5723 if (AVR_TINY)
5724 return avr_out_movhi_mr_r_reg_no_disp_tiny (insn, op, plen);
5726 if (reg_base != REG_X)
5727 return avr_asm_len ("std %0+1,%B1" CR_TAB
5728 "st %0,%A1", op, plen, -2);
5730 if (reg_src == REG_X)
5731 /* "st X+,r26" and "st -X,r26" are undefined. */
5732 return !mem_volatile_p && reg_unused_after (insn, src)
5733 ? avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5734 "st X,r26" CR_TAB
5735 "adiw r26,1" CR_TAB
5736 "st X,__tmp_reg__", op, plen, -4)
5738 : avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5739 "adiw r26,1" CR_TAB
5740 "st X,__tmp_reg__" CR_TAB
5741 "sbiw r26,1" CR_TAB
5742 "st X,r26", op, plen, -5);
5744 return !mem_volatile_p && reg_unused_after (insn, base)
5745 ? avr_asm_len ("st X+,%A1" CR_TAB
5746 "st X,%B1", op, plen, -2)
5747 : avr_asm_len ("adiw r26,1" CR_TAB
5748 "st X,%B1" CR_TAB
5749 "st -X,%A1", op, plen, -3);
5751 else if (GET_CODE (base) == PLUS)
5753 int disp = INTVAL (XEXP (base, 1));
5755 if (AVR_TINY)
5756 return avr_out_movhi_mr_r_reg_disp_tiny (insn, op, plen);
5758 reg_base = REGNO (XEXP (base, 0));
5759 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5761 if (reg_base != REG_Y)
5762 fatal_insn ("incorrect insn:",insn);
5764 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
5765 ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
5766 "std Y+63,%B1" CR_TAB
5767 "std Y+62,%A1" CR_TAB
5768 "sbiw r28,%o0-62", op, plen, -4)
5770 : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5771 "sbci r29,hi8(-%o0)" CR_TAB
5772 "std Y+1,%B1" CR_TAB
5773 "st Y,%A1" CR_TAB
5774 "subi r28,lo8(%o0)" CR_TAB
5775 "sbci r29,hi8(%o0)", op, plen, -6);
5778 if (reg_base != REG_X)
5779 return avr_asm_len ("std %B0,%B1" CR_TAB
5780 "std %A0,%A1", op, plen, -2);
5781 /* (X + d) = R */
5782 return reg_src == REG_X
5783 ? avr_asm_len ("mov __tmp_reg__,r26" CR_TAB
5784 "mov __zero_reg__,r27" CR_TAB
5785 "adiw r26,%o0+1" CR_TAB
5786 "st X,__zero_reg__" CR_TAB
5787 "st -X,__tmp_reg__" CR_TAB
5788 "clr __zero_reg__" CR_TAB
5789 "sbiw r26,%o0", op, plen, -7)
5791 : avr_asm_len ("adiw r26,%o0+1" CR_TAB
5792 "st X,%B1" CR_TAB
5793 "st -X,%A1" CR_TAB
5794 "sbiw r26,%o0", op, plen, -4);
5796 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5798 return avr_asm_len ("st %0,%B1" CR_TAB
5799 "st %0,%A1", op, plen, -2);
5801 else if (GET_CODE (base) == POST_INC) /* (R++) */
5803 if (!mem_volatile_p)
5804 return avr_asm_len ("st %0,%A1" CR_TAB
5805 "st %0,%B1", op, plen, -2);
5807 if (AVR_TINY)
5808 return avr_out_movhi_mr_r_post_inc_tiny (op, plen);
5810 return REGNO (XEXP (base, 0)) == REG_X
5811 ? avr_asm_len ("adiw r26,1" CR_TAB
5812 "st X,%B1" CR_TAB
5813 "st -X,%A1" CR_TAB
5814 "adiw r26,2", op, plen, -4)
5816 : avr_asm_len ("std %p0+1,%B1" CR_TAB
5817 "st %p0,%A1" CR_TAB
5818 "adiw %r0,2", op, plen, -3);
5820 fatal_insn ("unknown move insn:",insn);
5821 return "";
5824 /* Return 1 if frame pointer for current function required. */
5826 static bool
5827 avr_frame_pointer_required_p (void)
5829 return (cfun->calls_alloca
5830 || cfun->calls_setjmp
5831 || cfun->has_nonlocal_label
5832 || crtl->args.info.nregs == 0
5833 || get_frame_size () > 0);
5836 /* Returns the condition of compare insn INSN, or UNKNOWN. */
5838 static RTX_CODE
5839 compare_condition (rtx_insn *insn)
5841 rtx_insn *next = next_real_insn (insn);
5843 if (next && JUMP_P (next))
5845 rtx pat = PATTERN (next);
5846 rtx src = SET_SRC (pat);
5848 if (IF_THEN_ELSE == GET_CODE (src))
5849 return GET_CODE (XEXP (src, 0));
5852 return UNKNOWN;
5856 /* Returns true iff INSN is a tst insn that only tests the sign. */
5858 static bool
5859 compare_sign_p (rtx_insn *insn)
5861 RTX_CODE cond = compare_condition (insn);
5862 return (cond == GE || cond == LT);
5866 /* Returns true iff the next insn is a JUMP_INSN with a condition
5867 that needs to be swapped (GT, GTU, LE, LEU). */
5869 static bool
5870 compare_diff_p (rtx_insn *insn)
5872 RTX_CODE cond = compare_condition (insn);
5873 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
5876 /* Returns true iff INSN is a compare insn with the EQ or NE condition. */
5878 static bool
5879 compare_eq_p (rtx_insn *insn)
5881 RTX_CODE cond = compare_condition (insn);
5882 return (cond == EQ || cond == NE);
5886 /* Output compare instruction
5888 compare (XOP[0], XOP[1])
5890 for a register XOP[0] and a compile-time constant XOP[1]. Return "".
5891 XOP[2] is an 8-bit scratch register as needed.
5893 PLEN == NULL: Output instructions.
5894 PLEN != NULL: Set *PLEN to the length (in words) of the sequence.
5895 Don't output anything. */
5897 const char*
5898 avr_out_compare (rtx_insn *insn, rtx *xop, int *plen)
5900 /* Register to compare and value to compare against. */
5901 rtx xreg = xop[0];
5902 rtx xval = xop[1];
5904 /* MODE of the comparison. */
5905 machine_mode mode;
5907 /* Number of bytes to operate on. */
5908 int n_bytes = GET_MODE_SIZE (GET_MODE (xreg));
5910 /* Value (0..0xff) held in clobber register xop[2] or -1 if unknown. */
5911 int clobber_val = -1;
5913 /* Map fixed mode operands to integer operands with the same binary
5914 representation. They are easier to handle in the remainder. */
5916 if (CONST_FIXED_P (xval))
5918 xreg = avr_to_int_mode (xop[0]);
5919 xval = avr_to_int_mode (xop[1]);
5922 mode = GET_MODE (xreg);
5924 gcc_assert (REG_P (xreg));
5925 gcc_assert ((CONST_INT_P (xval) && n_bytes <= 4)
5926 || (const_double_operand (xval, VOIDmode) && n_bytes == 8));
5928 if (plen)
5929 *plen = 0;
5931 /* Comparisons == +/-1 and != +/-1 can be done similar to camparing
5932 against 0 by ORing the bytes. This is one instruction shorter.
5933 Notice that 64-bit comparisons are always against reg:ALL8 18 (ACC_A)
5934 and therefore don't use this. */
5936 if (!test_hard_reg_class (LD_REGS, xreg)
5937 && compare_eq_p (insn)
5938 && reg_unused_after (insn, xreg))
5940 if (xval == const1_rtx)
5942 avr_asm_len ("dec %A0" CR_TAB
5943 "or %A0,%B0", xop, plen, 2);
5945 if (n_bytes >= 3)
5946 avr_asm_len ("or %A0,%C0", xop, plen, 1);
5948 if (n_bytes >= 4)
5949 avr_asm_len ("or %A0,%D0", xop, plen, 1);
5951 return "";
5953 else if (xval == constm1_rtx)
5955 if (n_bytes >= 4)
5956 avr_asm_len ("and %A0,%D0", xop, plen, 1);
5958 if (n_bytes >= 3)
5959 avr_asm_len ("and %A0,%C0", xop, plen, 1);
5961 return avr_asm_len ("and %A0,%B0" CR_TAB
5962 "com %A0", xop, plen, 2);
5966 /* Comparisons == -1 and != -1 of a d-register that's used after the
5967 comparison. (If it's unused after we use CPI / SBCI or ADIW sequence
5968 from below.) Instead of CPI Rlo,-1 / LDI Rx,-1 / CPC Rhi,Rx we can
5969 use CPI Rlo,-1 / CPC Rhi,Rlo which is 1 instruction shorter:
5970 If CPI is true then Rlo contains -1 and we can use Rlo instead of Rx
5971 when CPC'ing the high part. If CPI is false then CPC cannot render
5972 the result to true. This also works for the more generic case where
5973 the constant is of the form 0xabab. */
5975 if (n_bytes == 2
5976 && xval != const0_rtx
5977 && test_hard_reg_class (LD_REGS, xreg)
5978 && compare_eq_p (insn)
5979 && !reg_unused_after (insn, xreg))
5981 rtx xlo8 = simplify_gen_subreg (QImode, xval, mode, 0);
5982 rtx xhi8 = simplify_gen_subreg (QImode, xval, mode, 1);
5984 if (INTVAL (xlo8) == INTVAL (xhi8))
5986 xop[0] = xreg;
5987 xop[1] = xlo8;
5989 return avr_asm_len ("cpi %A0,%1" CR_TAB
5990 "cpc %B0,%A0", xop, plen, 2);
5994 for (int i = 0; i < n_bytes; i++)
5996 /* We compare byte-wise. */
5997 rtx reg8 = simplify_gen_subreg (QImode, xreg, mode, i);
5998 rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
6000 /* 8-bit value to compare with this byte. */
6001 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
6003 /* Registers R16..R31 can operate with immediate. */
6004 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
6006 xop[0] = reg8;
6007 xop[1] = gen_int_mode (val8, QImode);
6009 /* Word registers >= R24 can use SBIW/ADIW with 0..63. */
6011 if (i == 0
6012 && test_hard_reg_class (ADDW_REGS, reg8))
6014 int val16 = trunc_int_for_mode (INTVAL (xval), HImode);
6016 if (IN_RANGE (val16, 0, 63)
6017 && (val8 == 0
6018 || reg_unused_after (insn, xreg)))
6020 if (AVR_TINY)
6021 avr_asm_len (TINY_SBIW (%A0, %B0, %1), xop, plen, 2);
6022 else
6023 avr_asm_len ("sbiw %0,%1", xop, plen, 1);
6025 i++;
6026 continue;
6029 if (n_bytes == 2
6030 && IN_RANGE (val16, -63, -1)
6031 && compare_eq_p (insn)
6032 && reg_unused_after (insn, xreg))
6034 return AVR_TINY
6035 ? avr_asm_len (TINY_ADIW (%A0, %B0, %n1), xop, plen, 2)
6036 : avr_asm_len ("adiw %0,%n1", xop, plen, 1);
6040 /* Comparing against 0 is easy. */
6042 if (val8 == 0)
6044 avr_asm_len (i == 0
6045 ? "cp %0,__zero_reg__"
6046 : "cpc %0,__zero_reg__", xop, plen, 1);
6047 continue;
6050 /* Upper registers can compare and subtract-with-carry immediates.
6051 Notice that compare instructions do the same as respective subtract
6052 instruction; the only difference is that comparisons don't write
6053 the result back to the target register. */
6055 if (ld_reg_p)
6057 if (i == 0)
6059 avr_asm_len ("cpi %0,%1", xop, plen, 1);
6060 continue;
6062 else if (reg_unused_after (insn, xreg))
6064 avr_asm_len ("sbci %0,%1", xop, plen, 1);
6065 continue;
6069 /* Must load the value into the scratch register. */
6071 gcc_assert (REG_P (xop[2]));
6073 if (clobber_val != (int) val8)
6074 avr_asm_len ("ldi %2,%1", xop, plen, 1);
6075 clobber_val = (int) val8;
6077 avr_asm_len (i == 0
6078 ? "cp %0,%2"
6079 : "cpc %0,%2", xop, plen, 1);
6082 return "";
6086 /* Prepare operands of compare_const_di2 to be used with avr_out_compare. */
6088 const char*
6089 avr_out_compare64 (rtx_insn *insn, rtx *op, int *plen)
6091 rtx xop[3];
6093 xop[0] = gen_rtx_REG (DImode, 18);
6094 xop[1] = op[0];
6095 xop[2] = op[1];
6097 return avr_out_compare (insn, xop, plen);
6100 /* Output test instruction for HImode. */
6102 const char*
6103 avr_out_tsthi (rtx_insn *insn, rtx *op, int *plen)
6105 if (compare_sign_p (insn))
6107 avr_asm_len ("tst %B0", op, plen, -1);
6109 else if (reg_unused_after (insn, op[0])
6110 && compare_eq_p (insn))
6112 /* Faster than sbiw if we can clobber the operand. */
6113 avr_asm_len ("or %A0,%B0", op, plen, -1);
6115 else
6117 avr_out_compare (insn, op, plen);
6120 return "";
6124 /* Output test instruction for PSImode. */
6126 const char*
6127 avr_out_tstpsi (rtx_insn *insn, rtx *op, int *plen)
6129 if (compare_sign_p (insn))
6131 avr_asm_len ("tst %C0", op, plen, -1);
6133 else if (reg_unused_after (insn, op[0])
6134 && compare_eq_p (insn))
6136 /* Faster than sbiw if we can clobber the operand. */
6137 avr_asm_len ("or %A0,%B0" CR_TAB
6138 "or %A0,%C0", op, plen, -2);
6140 else
6142 avr_out_compare (insn, op, plen);
6145 return "";
6149 /* Output test instruction for SImode. */
6151 const char*
6152 avr_out_tstsi (rtx_insn *insn, rtx *op, int *plen)
6154 if (compare_sign_p (insn))
6156 avr_asm_len ("tst %D0", op, plen, -1);
6158 else if (reg_unused_after (insn, op[0])
6159 && compare_eq_p (insn))
6161 /* Faster than sbiw if we can clobber the operand. */
6162 avr_asm_len ("or %A0,%B0" CR_TAB
6163 "or %A0,%C0" CR_TAB
6164 "or %A0,%D0", op, plen, -3);
6166 else
6168 avr_out_compare (insn, op, plen);
6171 return "";
6175 /* Generate asm equivalent for various shifts. This only handles cases
6176 that are not already carefully hand-optimized in ?sh??i3_out.
6178 OPERANDS[0] resp. %0 in TEMPL is the operand to be shifted.
6179 OPERANDS[2] is the shift count as CONST_INT, MEM or REG.
6180 OPERANDS[3] is a QImode scratch register from LD regs if
6181 available and SCRATCH, otherwise (no scratch available)
6183 TEMPL is an assembler template that shifts by one position.
6184 T_LEN is the length of this template. */
6186 void
6187 out_shift_with_cnt (const char *templ, rtx_insn *insn, rtx operands[],
6188 int *plen, int t_len)
6190 bool second_label = true;
6191 bool saved_in_tmp = false;
6192 bool use_zero_reg = false;
6193 rtx op[5];
6195 op[0] = operands[0];
6196 op[1] = operands[1];
6197 op[2] = operands[2];
6198 op[3] = operands[3];
6200 if (plen)
6201 *plen = 0;
6203 if (CONST_INT_P (operands[2]))
6205 bool scratch = (GET_CODE (PATTERN (insn)) == PARALLEL
6206 && REG_P (operands[3]));
6207 int count = INTVAL (operands[2]);
6208 int max_len = 10; /* If larger than this, always use a loop. */
6210 if (count <= 0)
6211 return;
6213 if (count < 8 && !scratch)
6214 use_zero_reg = true;
6216 if (optimize_size)
6217 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
6219 if (t_len * count <= max_len)
6221 /* Output shifts inline with no loop - faster. */
6223 while (count-- > 0)
6224 avr_asm_len (templ, op, plen, t_len);
6226 return;
6229 if (scratch)
6231 avr_asm_len ("ldi %3,%2", op, plen, 1);
6233 else if (use_zero_reg)
6235 /* Hack to save one word: use __zero_reg__ as loop counter.
6236 Set one bit, then shift in a loop until it is 0 again. */
6238 op[3] = zero_reg_rtx;
6240 avr_asm_len ("set" CR_TAB
6241 "bld %3,%2-1", op, plen, 2);
6243 else
6245 /* No scratch register available, use one from LD_REGS (saved in
6246 __tmp_reg__) that doesn't overlap with registers to shift. */
6248 op[3] = all_regs_rtx[((REGNO (op[0]) - 1) & 15) + 16];
6249 op[4] = tmp_reg_rtx;
6250 saved_in_tmp = true;
6252 avr_asm_len ("mov %4,%3" CR_TAB
6253 "ldi %3,%2", op, plen, 2);
6256 second_label = false;
6258 else if (MEM_P (op[2]))
6260 rtx op_mov[2];
6262 op_mov[0] = op[3] = tmp_reg_rtx;
6263 op_mov[1] = op[2];
6265 out_movqi_r_mr (insn, op_mov, plen);
6267 else if (register_operand (op[2], QImode))
6269 op[3] = op[2];
6271 if (!reg_unused_after (insn, op[2])
6272 || reg_overlap_mentioned_p (op[0], op[2]))
6274 op[3] = tmp_reg_rtx;
6275 avr_asm_len ("mov %3,%2", op, plen, 1);
6278 else
6279 fatal_insn ("bad shift insn:", insn);
6281 if (second_label)
6282 avr_asm_len ("rjmp 2f", op, plen, 1);
6284 avr_asm_len ("1:", op, plen, 0);
6285 avr_asm_len (templ, op, plen, t_len);
6287 if (second_label)
6288 avr_asm_len ("2:", op, plen, 0);
6290 avr_asm_len (use_zero_reg ? "lsr %3" : "dec %3", op, plen, 1);
6291 avr_asm_len (second_label ? "brpl 1b" : "brne 1b", op, plen, 1);
6293 if (saved_in_tmp)
6294 avr_asm_len ("mov %3,%4", op, plen, 1);
6298 /* 8bit shift left ((char)x << i) */
6300 const char *
6301 ashlqi3_out (rtx_insn *insn, rtx operands[], int *len)
6303 if (CONST_INT_P (operands[2]))
6305 int k;
6307 if (!len)
6308 len = &k;
6310 switch (INTVAL (operands[2]))
6312 default:
6313 if (INTVAL (operands[2]) < 8)
6314 break;
6316 *len = 1;
6317 return "clr %0";
6319 case 1:
6320 *len = 1;
6321 return "lsl %0";
6323 case 2:
6324 *len = 2;
6325 return ("lsl %0" CR_TAB
6326 "lsl %0");
6328 case 3:
6329 *len = 3;
6330 return ("lsl %0" CR_TAB
6331 "lsl %0" CR_TAB
6332 "lsl %0");
6334 case 4:
6335 if (test_hard_reg_class (LD_REGS, operands[0]))
6337 *len = 2;
6338 return ("swap %0" CR_TAB
6339 "andi %0,0xf0");
6341 *len = 4;
6342 return ("lsl %0" CR_TAB
6343 "lsl %0" CR_TAB
6344 "lsl %0" CR_TAB
6345 "lsl %0");
6347 case 5:
6348 if (test_hard_reg_class (LD_REGS, operands[0]))
6350 *len = 3;
6351 return ("swap %0" CR_TAB
6352 "lsl %0" CR_TAB
6353 "andi %0,0xe0");
6355 *len = 5;
6356 return ("lsl %0" CR_TAB
6357 "lsl %0" CR_TAB
6358 "lsl %0" CR_TAB
6359 "lsl %0" CR_TAB
6360 "lsl %0");
6362 case 6:
6363 if (test_hard_reg_class (LD_REGS, operands[0]))
6365 *len = 4;
6366 return ("swap %0" CR_TAB
6367 "lsl %0" CR_TAB
6368 "lsl %0" CR_TAB
6369 "andi %0,0xc0");
6371 *len = 6;
6372 return ("lsl %0" CR_TAB
6373 "lsl %0" CR_TAB
6374 "lsl %0" CR_TAB
6375 "lsl %0" CR_TAB
6376 "lsl %0" CR_TAB
6377 "lsl %0");
6379 case 7:
6380 *len = 3;
6381 return ("ror %0" CR_TAB
6382 "clr %0" CR_TAB
6383 "ror %0");
6386 else if (CONSTANT_P (operands[2]))
6387 fatal_insn ("internal compiler error. Incorrect shift:", insn);
6389 out_shift_with_cnt ("lsl %0",
6390 insn, operands, len, 1);
6391 return "";
6395 /* 16bit shift left ((short)x << i) */
6397 const char *
6398 ashlhi3_out (rtx_insn *insn, rtx operands[], int *len)
6400 if (CONST_INT_P (operands[2]))
6402 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
6403 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
6404 int k;
6405 int *t = len;
6407 if (!len)
6408 len = &k;
6410 switch (INTVAL (operands[2]))
6412 default:
6413 if (INTVAL (operands[2]) < 16)
6414 break;
6416 *len = 2;
6417 return ("clr %B0" CR_TAB
6418 "clr %A0");
6420 case 4:
6421 if (optimize_size && scratch)
6422 break; /* 5 */
6423 if (ldi_ok)
6425 *len = 6;
6426 return ("swap %A0" CR_TAB
6427 "swap %B0" CR_TAB
6428 "andi %B0,0xf0" CR_TAB
6429 "eor %B0,%A0" CR_TAB
6430 "andi %A0,0xf0" CR_TAB
6431 "eor %B0,%A0");
6433 if (scratch)
6435 *len = 7;
6436 return ("swap %A0" CR_TAB
6437 "swap %B0" CR_TAB
6438 "ldi %3,0xf0" CR_TAB
6439 "and %B0,%3" CR_TAB
6440 "eor %B0,%A0" CR_TAB
6441 "and %A0,%3" CR_TAB
6442 "eor %B0,%A0");
6444 break; /* optimize_size ? 6 : 8 */
6446 case 5:
6447 if (optimize_size)
6448 break; /* scratch ? 5 : 6 */
6449 if (ldi_ok)
6451 *len = 8;
6452 return ("lsl %A0" CR_TAB
6453 "rol %B0" CR_TAB
6454 "swap %A0" CR_TAB
6455 "swap %B0" CR_TAB
6456 "andi %B0,0xf0" CR_TAB
6457 "eor %B0,%A0" CR_TAB
6458 "andi %A0,0xf0" CR_TAB
6459 "eor %B0,%A0");
6461 if (scratch)
6463 *len = 9;
6464 return ("lsl %A0" CR_TAB
6465 "rol %B0" CR_TAB
6466 "swap %A0" CR_TAB
6467 "swap %B0" CR_TAB
6468 "ldi %3,0xf0" CR_TAB
6469 "and %B0,%3" CR_TAB
6470 "eor %B0,%A0" CR_TAB
6471 "and %A0,%3" CR_TAB
6472 "eor %B0,%A0");
6474 break; /* 10 */
6476 case 6:
6477 if (optimize_size)
6478 break; /* scratch ? 5 : 6 */
6479 *len = 9;
6480 return ("clr __tmp_reg__" CR_TAB
6481 "lsr %B0" CR_TAB
6482 "ror %A0" CR_TAB
6483 "ror __tmp_reg__" CR_TAB
6484 "lsr %B0" CR_TAB
6485 "ror %A0" CR_TAB
6486 "ror __tmp_reg__" CR_TAB
6487 "mov %B0,%A0" CR_TAB
6488 "mov %A0,__tmp_reg__");
6490 case 7:
6491 *len = 5;
6492 return ("lsr %B0" CR_TAB
6493 "mov %B0,%A0" CR_TAB
6494 "clr %A0" CR_TAB
6495 "ror %B0" CR_TAB
6496 "ror %A0");
6498 case 8:
6499 return *len = 2, ("mov %B0,%A1" CR_TAB
6500 "clr %A0");
6502 case 9:
6503 *len = 3;
6504 return ("mov %B0,%A0" CR_TAB
6505 "clr %A0" CR_TAB
6506 "lsl %B0");
6508 case 10:
6509 *len = 4;
6510 return ("mov %B0,%A0" CR_TAB
6511 "clr %A0" CR_TAB
6512 "lsl %B0" CR_TAB
6513 "lsl %B0");
6515 case 11:
6516 *len = 5;
6517 return ("mov %B0,%A0" CR_TAB
6518 "clr %A0" CR_TAB
6519 "lsl %B0" CR_TAB
6520 "lsl %B0" CR_TAB
6521 "lsl %B0");
6523 case 12:
6524 if (ldi_ok)
6526 *len = 4;
6527 return ("mov %B0,%A0" CR_TAB
6528 "clr %A0" CR_TAB
6529 "swap %B0" CR_TAB
6530 "andi %B0,0xf0");
6532 if (scratch)
6534 *len = 5;
6535 return ("mov %B0,%A0" CR_TAB
6536 "clr %A0" CR_TAB
6537 "swap %B0" CR_TAB
6538 "ldi %3,0xf0" CR_TAB
6539 "and %B0,%3");
6541 *len = 6;
6542 return ("mov %B0,%A0" CR_TAB
6543 "clr %A0" CR_TAB
6544 "lsl %B0" CR_TAB
6545 "lsl %B0" CR_TAB
6546 "lsl %B0" CR_TAB
6547 "lsl %B0");
6549 case 13:
6550 if (ldi_ok)
6552 *len = 5;
6553 return ("mov %B0,%A0" CR_TAB
6554 "clr %A0" CR_TAB
6555 "swap %B0" CR_TAB
6556 "lsl %B0" CR_TAB
6557 "andi %B0,0xe0");
6559 if (AVR_HAVE_MUL && scratch)
6561 *len = 5;
6562 return ("ldi %3,0x20" CR_TAB
6563 "mul %A0,%3" CR_TAB
6564 "mov %B0,r0" CR_TAB
6565 "clr %A0" CR_TAB
6566 "clr __zero_reg__");
6568 if (optimize_size && scratch)
6569 break; /* 5 */
6570 if (scratch)
6572 *len = 6;
6573 return ("mov %B0,%A0" CR_TAB
6574 "clr %A0" CR_TAB
6575 "swap %B0" CR_TAB
6576 "lsl %B0" CR_TAB
6577 "ldi %3,0xe0" CR_TAB
6578 "and %B0,%3");
6580 if (AVR_HAVE_MUL)
6582 *len = 6;
6583 return ("set" CR_TAB
6584 "bld r1,5" CR_TAB
6585 "mul %A0,r1" CR_TAB
6586 "mov %B0,r0" CR_TAB
6587 "clr %A0" CR_TAB
6588 "clr __zero_reg__");
6590 *len = 7;
6591 return ("mov %B0,%A0" CR_TAB
6592 "clr %A0" CR_TAB
6593 "lsl %B0" CR_TAB
6594 "lsl %B0" CR_TAB
6595 "lsl %B0" CR_TAB
6596 "lsl %B0" CR_TAB
6597 "lsl %B0");
6599 case 14:
6600 if (AVR_HAVE_MUL && ldi_ok)
6602 *len = 5;
6603 return ("ldi %B0,0x40" CR_TAB
6604 "mul %A0,%B0" CR_TAB
6605 "mov %B0,r0" CR_TAB
6606 "clr %A0" CR_TAB
6607 "clr __zero_reg__");
6609 if (AVR_HAVE_MUL && scratch)
6611 *len = 5;
6612 return ("ldi %3,0x40" CR_TAB
6613 "mul %A0,%3" CR_TAB
6614 "mov %B0,r0" CR_TAB
6615 "clr %A0" CR_TAB
6616 "clr __zero_reg__");
6618 if (optimize_size && ldi_ok)
6620 *len = 5;
6621 return ("mov %B0,%A0" CR_TAB
6622 "ldi %A0,6" "\n1:\t"
6623 "lsl %B0" CR_TAB
6624 "dec %A0" CR_TAB
6625 "brne 1b");
6627 if (optimize_size && scratch)
6628 break; /* 5 */
6629 *len = 6;
6630 return ("clr %B0" CR_TAB
6631 "lsr %A0" CR_TAB
6632 "ror %B0" CR_TAB
6633 "lsr %A0" CR_TAB
6634 "ror %B0" CR_TAB
6635 "clr %A0");
6637 case 15:
6638 *len = 4;
6639 return ("clr %B0" CR_TAB
6640 "lsr %A0" CR_TAB
6641 "ror %B0" CR_TAB
6642 "clr %A0");
6644 len = t;
6646 out_shift_with_cnt ("lsl %A0" CR_TAB
6647 "rol %B0", insn, operands, len, 2);
6648 return "";
6652 /* 24-bit shift left */
6654 const char*
6655 avr_out_ashlpsi3 (rtx_insn *insn, rtx *op, int *plen)
6657 if (plen)
6658 *plen = 0;
6660 if (CONST_INT_P (op[2]))
6662 switch (INTVAL (op[2]))
6664 default:
6665 if (INTVAL (op[2]) < 24)
6666 break;
6668 return avr_asm_len ("clr %A0" CR_TAB
6669 "clr %B0" CR_TAB
6670 "clr %C0", op, plen, 3);
6672 case 8:
6674 int reg0 = REGNO (op[0]);
6675 int reg1 = REGNO (op[1]);
6677 if (reg0 >= reg1)
6678 return avr_asm_len ("mov %C0,%B1" CR_TAB
6679 "mov %B0,%A1" CR_TAB
6680 "clr %A0", op, plen, 3);
6681 else
6682 return avr_asm_len ("clr %A0" CR_TAB
6683 "mov %B0,%A1" CR_TAB
6684 "mov %C0,%B1", op, plen, 3);
6687 case 16:
6689 int reg0 = REGNO (op[0]);
6690 int reg1 = REGNO (op[1]);
6692 if (reg0 + 2 != reg1)
6693 avr_asm_len ("mov %C0,%A0", op, plen, 1);
6695 return avr_asm_len ("clr %B0" CR_TAB
6696 "clr %A0", op, plen, 2);
6699 case 23:
6700 return avr_asm_len ("clr %C0" CR_TAB
6701 "lsr %A0" CR_TAB
6702 "ror %C0" CR_TAB
6703 "clr %B0" CR_TAB
6704 "clr %A0", op, plen, 5);
6708 out_shift_with_cnt ("lsl %A0" CR_TAB
6709 "rol %B0" CR_TAB
6710 "rol %C0", insn, op, plen, 3);
6711 return "";
6715 /* 32bit shift left ((long)x << i) */
6717 const char *
6718 ashlsi3_out (rtx_insn *insn, rtx operands[], int *len)
6720 if (CONST_INT_P (operands[2]))
6722 int k;
6723 int *t = len;
6725 if (!len)
6726 len = &k;
6728 switch (INTVAL (operands[2]))
6730 default:
6731 if (INTVAL (operands[2]) < 32)
6732 break;
6734 if (AVR_HAVE_MOVW)
6735 return *len = 3, ("clr %D0" CR_TAB
6736 "clr %C0" CR_TAB
6737 "movw %A0,%C0");
6738 *len = 4;
6739 return ("clr %D0" CR_TAB
6740 "clr %C0" CR_TAB
6741 "clr %B0" CR_TAB
6742 "clr %A0");
6744 case 8:
6746 int reg0 = true_regnum (operands[0]);
6747 int reg1 = true_regnum (operands[1]);
6748 *len = 4;
6749 if (reg0 >= reg1)
6750 return ("mov %D0,%C1" CR_TAB
6751 "mov %C0,%B1" CR_TAB
6752 "mov %B0,%A1" CR_TAB
6753 "clr %A0");
6754 else
6755 return ("clr %A0" CR_TAB
6756 "mov %B0,%A1" CR_TAB
6757 "mov %C0,%B1" CR_TAB
6758 "mov %D0,%C1");
6761 case 16:
6763 int reg0 = true_regnum (operands[0]);
6764 int reg1 = true_regnum (operands[1]);
6765 if (reg0 + 2 == reg1)
6766 return *len = 2, ("clr %B0" CR_TAB
6767 "clr %A0");
6768 if (AVR_HAVE_MOVW)
6769 return *len = 3, ("movw %C0,%A1" CR_TAB
6770 "clr %B0" CR_TAB
6771 "clr %A0");
6772 else
6773 return *len = 4, ("mov %C0,%A1" CR_TAB
6774 "mov %D0,%B1" CR_TAB
6775 "clr %B0" CR_TAB
6776 "clr %A0");
6779 case 24:
6780 *len = 4;
6781 return ("mov %D0,%A1" CR_TAB
6782 "clr %C0" CR_TAB
6783 "clr %B0" CR_TAB
6784 "clr %A0");
6786 case 31:
6787 *len = 6;
6788 return ("clr %D0" CR_TAB
6789 "lsr %A0" CR_TAB
6790 "ror %D0" CR_TAB
6791 "clr %C0" CR_TAB
6792 "clr %B0" CR_TAB
6793 "clr %A0");
6795 len = t;
6797 out_shift_with_cnt ("lsl %A0" CR_TAB
6798 "rol %B0" CR_TAB
6799 "rol %C0" CR_TAB
6800 "rol %D0", insn, operands, len, 4);
6801 return "";
6804 /* 8bit arithmetic shift right ((signed char)x >> i) */
6806 const char *
6807 ashrqi3_out (rtx_insn *insn, rtx operands[], int *len)
6809 if (CONST_INT_P (operands[2]))
6811 int k;
6813 if (!len)
6814 len = &k;
6816 switch (INTVAL (operands[2]))
6818 case 1:
6819 *len = 1;
6820 return "asr %0";
6822 case 2:
6823 *len = 2;
6824 return ("asr %0" CR_TAB
6825 "asr %0");
6827 case 3:
6828 *len = 3;
6829 return ("asr %0" CR_TAB
6830 "asr %0" CR_TAB
6831 "asr %0");
6833 case 4:
6834 *len = 4;
6835 return ("asr %0" CR_TAB
6836 "asr %0" CR_TAB
6837 "asr %0" CR_TAB
6838 "asr %0");
6840 case 5:
6841 *len = 5;
6842 return ("asr %0" CR_TAB
6843 "asr %0" CR_TAB
6844 "asr %0" CR_TAB
6845 "asr %0" CR_TAB
6846 "asr %0");
6848 case 6:
6849 *len = 4;
6850 return ("bst %0,6" CR_TAB
6851 "lsl %0" CR_TAB
6852 "sbc %0,%0" CR_TAB
6853 "bld %0,0");
6855 default:
6856 if (INTVAL (operands[2]) < 8)
6857 break;
6859 /* fall through */
6861 case 7:
6862 *len = 2;
6863 return ("lsl %0" CR_TAB
6864 "sbc %0,%0");
6867 else if (CONSTANT_P (operands[2]))
6868 fatal_insn ("internal compiler error. Incorrect shift:", insn);
6870 out_shift_with_cnt ("asr %0",
6871 insn, operands, len, 1);
6872 return "";
6876 /* 16bit arithmetic shift right ((signed short)x >> i) */
6878 const char *
6879 ashrhi3_out (rtx_insn *insn, rtx operands[], int *len)
6881 if (CONST_INT_P (operands[2]))
6883 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
6884 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
6885 int k;
6886 int *t = len;
6888 if (!len)
6889 len = &k;
6891 switch (INTVAL (operands[2]))
6893 case 4:
6894 case 5:
6895 /* XXX try to optimize this too? */
6896 break;
6898 case 6:
6899 if (optimize_size)
6900 break; /* scratch ? 5 : 6 */
6901 *len = 8;
6902 return ("mov __tmp_reg__,%A0" CR_TAB
6903 "mov %A0,%B0" CR_TAB
6904 "lsl __tmp_reg__" CR_TAB
6905 "rol %A0" CR_TAB
6906 "sbc %B0,%B0" CR_TAB
6907 "lsl __tmp_reg__" CR_TAB
6908 "rol %A0" CR_TAB
6909 "rol %B0");
6911 case 7:
6912 *len = 4;
6913 return ("lsl %A0" CR_TAB
6914 "mov %A0,%B0" CR_TAB
6915 "rol %A0" CR_TAB
6916 "sbc %B0,%B0");
6918 case 8:
6920 int reg0 = true_regnum (operands[0]);
6921 int reg1 = true_regnum (operands[1]);
6923 if (reg0 == reg1)
6924 return *len = 3, ("mov %A0,%B0" CR_TAB
6925 "lsl %B0" CR_TAB
6926 "sbc %B0,%B0");
6927 else
6928 return *len = 4, ("mov %A0,%B1" CR_TAB
6929 "clr %B0" CR_TAB
6930 "sbrc %A0,7" CR_TAB
6931 "dec %B0");
6934 case 9:
6935 *len = 4;
6936 return ("mov %A0,%B0" CR_TAB
6937 "lsl %B0" CR_TAB
6938 "sbc %B0,%B0" CR_TAB
6939 "asr %A0");
6941 case 10:
6942 *len = 5;
6943 return ("mov %A0,%B0" CR_TAB
6944 "lsl %B0" CR_TAB
6945 "sbc %B0,%B0" CR_TAB
6946 "asr %A0" CR_TAB
6947 "asr %A0");
6949 case 11:
6950 if (AVR_HAVE_MUL && ldi_ok)
6952 *len = 5;
6953 return ("ldi %A0,0x20" CR_TAB
6954 "muls %B0,%A0" CR_TAB
6955 "mov %A0,r1" CR_TAB
6956 "sbc %B0,%B0" CR_TAB
6957 "clr __zero_reg__");
6959 if (optimize_size && scratch)
6960 break; /* 5 */
6961 *len = 6;
6962 return ("mov %A0,%B0" CR_TAB
6963 "lsl %B0" CR_TAB
6964 "sbc %B0,%B0" CR_TAB
6965 "asr %A0" CR_TAB
6966 "asr %A0" CR_TAB
6967 "asr %A0");
6969 case 12:
6970 if (AVR_HAVE_MUL && ldi_ok)
6972 *len = 5;
6973 return ("ldi %A0,0x10" CR_TAB
6974 "muls %B0,%A0" CR_TAB
6975 "mov %A0,r1" CR_TAB
6976 "sbc %B0,%B0" CR_TAB
6977 "clr __zero_reg__");
6979 if (optimize_size && scratch)
6980 break; /* 5 */
6981 *len = 7;
6982 return ("mov %A0,%B0" CR_TAB
6983 "lsl %B0" CR_TAB
6984 "sbc %B0,%B0" CR_TAB
6985 "asr %A0" CR_TAB
6986 "asr %A0" CR_TAB
6987 "asr %A0" CR_TAB
6988 "asr %A0");
6990 case 13:
6991 if (AVR_HAVE_MUL && ldi_ok)
6993 *len = 5;
6994 return ("ldi %A0,0x08" CR_TAB
6995 "muls %B0,%A0" CR_TAB
6996 "mov %A0,r1" CR_TAB
6997 "sbc %B0,%B0" CR_TAB
6998 "clr __zero_reg__");
7000 if (optimize_size)
7001 break; /* scratch ? 5 : 7 */
7002 *len = 8;
7003 return ("mov %A0,%B0" CR_TAB
7004 "lsl %B0" CR_TAB
7005 "sbc %B0,%B0" CR_TAB
7006 "asr %A0" CR_TAB
7007 "asr %A0" CR_TAB
7008 "asr %A0" CR_TAB
7009 "asr %A0" CR_TAB
7010 "asr %A0");
7012 case 14:
7013 *len = 5;
7014 return ("lsl %B0" CR_TAB
7015 "sbc %A0,%A0" CR_TAB
7016 "lsl %B0" CR_TAB
7017 "mov %B0,%A0" CR_TAB
7018 "rol %A0");
7020 default:
7021 if (INTVAL (operands[2]) < 16)
7022 break;
7024 /* fall through */
7026 case 15:
7027 return *len = 3, ("lsl %B0" CR_TAB
7028 "sbc %A0,%A0" CR_TAB
7029 "mov %B0,%A0");
7031 len = t;
7033 out_shift_with_cnt ("asr %B0" CR_TAB
7034 "ror %A0", insn, operands, len, 2);
7035 return "";
7039 /* 24-bit arithmetic shift right */
7041 const char*
7042 avr_out_ashrpsi3 (rtx_insn *insn, rtx *op, int *plen)
7044 int dest = REGNO (op[0]);
7045 int src = REGNO (op[1]);
7047 if (CONST_INT_P (op[2]))
7049 if (plen)
7050 *plen = 0;
7052 switch (INTVAL (op[2]))
7054 case 8:
7055 if (dest <= src)
7056 return avr_asm_len ("mov %A0,%B1" CR_TAB
7057 "mov %B0,%C1" CR_TAB
7058 "clr %C0" CR_TAB
7059 "sbrc %B0,7" CR_TAB
7060 "dec %C0", op, plen, 5);
7061 else
7062 return avr_asm_len ("clr %C0" CR_TAB
7063 "sbrc %C1,7" CR_TAB
7064 "dec %C0" CR_TAB
7065 "mov %B0,%C1" CR_TAB
7066 "mov %A0,%B1", op, plen, 5);
7068 case 16:
7069 if (dest != src + 2)
7070 avr_asm_len ("mov %A0,%C1", op, plen, 1);
7072 return avr_asm_len ("clr %B0" CR_TAB
7073 "sbrc %A0,7" CR_TAB
7074 "com %B0" CR_TAB
7075 "mov %C0,%B0", op, plen, 4);
7077 default:
7078 if (INTVAL (op[2]) < 24)
7079 break;
7081 /* fall through */
7083 case 23:
7084 return avr_asm_len ("lsl %C0" CR_TAB
7085 "sbc %A0,%A0" CR_TAB
7086 "mov %B0,%A0" CR_TAB
7087 "mov %C0,%A0", op, plen, 4);
7088 } /* switch */
7091 out_shift_with_cnt ("asr %C0" CR_TAB
7092 "ror %B0" CR_TAB
7093 "ror %A0", insn, op, plen, 3);
7094 return "";
7098 /* 32-bit arithmetic shift right ((signed long)x >> i) */
7100 const char *
7101 ashrsi3_out (rtx_insn *insn, rtx operands[], int *len)
7103 if (CONST_INT_P (operands[2]))
7105 int k;
7106 int *t = len;
7108 if (!len)
7109 len = &k;
7111 switch (INTVAL (operands[2]))
7113 case 8:
7115 int reg0 = true_regnum (operands[0]);
7116 int reg1 = true_regnum (operands[1]);
7117 *len=6;
7118 if (reg0 <= reg1)
7119 return ("mov %A0,%B1" CR_TAB
7120 "mov %B0,%C1" CR_TAB
7121 "mov %C0,%D1" CR_TAB
7122 "clr %D0" CR_TAB
7123 "sbrc %C0,7" CR_TAB
7124 "dec %D0");
7125 else
7126 return ("clr %D0" CR_TAB
7127 "sbrc %D1,7" CR_TAB
7128 "dec %D0" CR_TAB
7129 "mov %C0,%D1" CR_TAB
7130 "mov %B0,%C1" CR_TAB
7131 "mov %A0,%B1");
7134 case 16:
7136 int reg0 = true_regnum (operands[0]);
7137 int reg1 = true_regnum (operands[1]);
7139 if (reg0 == reg1 + 2)
7140 return *len = 4, ("clr %D0" CR_TAB
7141 "sbrc %B0,7" CR_TAB
7142 "com %D0" CR_TAB
7143 "mov %C0,%D0");
7144 if (AVR_HAVE_MOVW)
7145 return *len = 5, ("movw %A0,%C1" CR_TAB
7146 "clr %D0" CR_TAB
7147 "sbrc %B0,7" CR_TAB
7148 "com %D0" CR_TAB
7149 "mov %C0,%D0");
7150 else
7151 return *len = 6, ("mov %B0,%D1" CR_TAB
7152 "mov %A0,%C1" CR_TAB
7153 "clr %D0" CR_TAB
7154 "sbrc %B0,7" CR_TAB
7155 "com %D0" CR_TAB
7156 "mov %C0,%D0");
7159 case 24:
7160 return *len = 6, ("mov %A0,%D1" CR_TAB
7161 "clr %D0" CR_TAB
7162 "sbrc %A0,7" CR_TAB
7163 "com %D0" CR_TAB
7164 "mov %B0,%D0" CR_TAB
7165 "mov %C0,%D0");
7167 default:
7168 if (INTVAL (operands[2]) < 32)
7169 break;
7171 /* fall through */
7173 case 31:
7174 if (AVR_HAVE_MOVW)
7175 return *len = 4, ("lsl %D0" CR_TAB
7176 "sbc %A0,%A0" CR_TAB
7177 "mov %B0,%A0" CR_TAB
7178 "movw %C0,%A0");
7179 else
7180 return *len = 5, ("lsl %D0" CR_TAB
7181 "sbc %A0,%A0" CR_TAB
7182 "mov %B0,%A0" CR_TAB
7183 "mov %C0,%A0" CR_TAB
7184 "mov %D0,%A0");
7186 len = t;
7188 out_shift_with_cnt ("asr %D0" CR_TAB
7189 "ror %C0" CR_TAB
7190 "ror %B0" CR_TAB
7191 "ror %A0", insn, operands, len, 4);
7192 return "";
7195 /* 8-bit logic shift right ((unsigned char)x >> i) */
7197 const char *
7198 lshrqi3_out (rtx_insn *insn, rtx operands[], int *len)
7200 if (CONST_INT_P (operands[2]))
7202 int k;
7204 if (!len)
7205 len = &k;
7207 switch (INTVAL (operands[2]))
7209 default:
7210 if (INTVAL (operands[2]) < 8)
7211 break;
7213 *len = 1;
7214 return "clr %0";
7216 case 1:
7217 *len = 1;
7218 return "lsr %0";
7220 case 2:
7221 *len = 2;
7222 return ("lsr %0" CR_TAB
7223 "lsr %0");
7224 case 3:
7225 *len = 3;
7226 return ("lsr %0" CR_TAB
7227 "lsr %0" CR_TAB
7228 "lsr %0");
7230 case 4:
7231 if (test_hard_reg_class (LD_REGS, operands[0]))
7233 *len=2;
7234 return ("swap %0" CR_TAB
7235 "andi %0,0x0f");
7237 *len = 4;
7238 return ("lsr %0" CR_TAB
7239 "lsr %0" CR_TAB
7240 "lsr %0" CR_TAB
7241 "lsr %0");
7243 case 5:
7244 if (test_hard_reg_class (LD_REGS, operands[0]))
7246 *len = 3;
7247 return ("swap %0" CR_TAB
7248 "lsr %0" CR_TAB
7249 "andi %0,0x7");
7251 *len = 5;
7252 return ("lsr %0" CR_TAB
7253 "lsr %0" CR_TAB
7254 "lsr %0" CR_TAB
7255 "lsr %0" CR_TAB
7256 "lsr %0");
7258 case 6:
7259 if (test_hard_reg_class (LD_REGS, operands[0]))
7261 *len = 4;
7262 return ("swap %0" CR_TAB
7263 "lsr %0" CR_TAB
7264 "lsr %0" CR_TAB
7265 "andi %0,0x3");
7267 *len = 6;
7268 return ("lsr %0" CR_TAB
7269 "lsr %0" CR_TAB
7270 "lsr %0" CR_TAB
7271 "lsr %0" CR_TAB
7272 "lsr %0" CR_TAB
7273 "lsr %0");
7275 case 7:
7276 *len = 3;
7277 return ("rol %0" CR_TAB
7278 "clr %0" CR_TAB
7279 "rol %0");
7282 else if (CONSTANT_P (operands[2]))
7283 fatal_insn ("internal compiler error. Incorrect shift:", insn);
7285 out_shift_with_cnt ("lsr %0",
7286 insn, operands, len, 1);
7287 return "";
7290 /* 16-bit logic shift right ((unsigned short)x >> i) */
7292 const char *
7293 lshrhi3_out (rtx_insn *insn, rtx operands[], int *len)
7295 if (CONST_INT_P (operands[2]))
7297 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
7298 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
7299 int k;
7300 int *t = len;
7302 if (!len)
7303 len = &k;
7305 switch (INTVAL (operands[2]))
7307 default:
7308 if (INTVAL (operands[2]) < 16)
7309 break;
7311 *len = 2;
7312 return ("clr %B0" CR_TAB
7313 "clr %A0");
7315 case 4:
7316 if (optimize_size && scratch)
7317 break; /* 5 */
7318 if (ldi_ok)
7320 *len = 6;
7321 return ("swap %B0" CR_TAB
7322 "swap %A0" CR_TAB
7323 "andi %A0,0x0f" CR_TAB
7324 "eor %A0,%B0" CR_TAB
7325 "andi %B0,0x0f" CR_TAB
7326 "eor %A0,%B0");
7328 if (scratch)
7330 *len = 7;
7331 return ("swap %B0" CR_TAB
7332 "swap %A0" CR_TAB
7333 "ldi %3,0x0f" CR_TAB
7334 "and %A0,%3" CR_TAB
7335 "eor %A0,%B0" CR_TAB
7336 "and %B0,%3" CR_TAB
7337 "eor %A0,%B0");
7339 break; /* optimize_size ? 6 : 8 */
7341 case 5:
7342 if (optimize_size)
7343 break; /* scratch ? 5 : 6 */
7344 if (ldi_ok)
7346 *len = 8;
7347 return ("lsr %B0" CR_TAB
7348 "ror %A0" CR_TAB
7349 "swap %B0" CR_TAB
7350 "swap %A0" CR_TAB
7351 "andi %A0,0x0f" CR_TAB
7352 "eor %A0,%B0" CR_TAB
7353 "andi %B0,0x0f" CR_TAB
7354 "eor %A0,%B0");
7356 if (scratch)
7358 *len = 9;
7359 return ("lsr %B0" CR_TAB
7360 "ror %A0" CR_TAB
7361 "swap %B0" CR_TAB
7362 "swap %A0" CR_TAB
7363 "ldi %3,0x0f" CR_TAB
7364 "and %A0,%3" CR_TAB
7365 "eor %A0,%B0" CR_TAB
7366 "and %B0,%3" CR_TAB
7367 "eor %A0,%B0");
7369 break; /* 10 */
7371 case 6:
7372 if (optimize_size)
7373 break; /* scratch ? 5 : 6 */
7374 *len = 9;
7375 return ("clr __tmp_reg__" CR_TAB
7376 "lsl %A0" CR_TAB
7377 "rol %B0" CR_TAB
7378 "rol __tmp_reg__" CR_TAB
7379 "lsl %A0" CR_TAB
7380 "rol %B0" CR_TAB
7381 "rol __tmp_reg__" CR_TAB
7382 "mov %A0,%B0" CR_TAB
7383 "mov %B0,__tmp_reg__");
7385 case 7:
7386 *len = 5;
7387 return ("lsl %A0" CR_TAB
7388 "mov %A0,%B0" CR_TAB
7389 "rol %A0" CR_TAB
7390 "sbc %B0,%B0" CR_TAB
7391 "neg %B0");
7393 case 8:
7394 return *len = 2, ("mov %A0,%B1" CR_TAB
7395 "clr %B0");
7397 case 9:
7398 *len = 3;
7399 return ("mov %A0,%B0" CR_TAB
7400 "clr %B0" CR_TAB
7401 "lsr %A0");
7403 case 10:
7404 *len = 4;
7405 return ("mov %A0,%B0" CR_TAB
7406 "clr %B0" CR_TAB
7407 "lsr %A0" CR_TAB
7408 "lsr %A0");
7410 case 11:
7411 *len = 5;
7412 return ("mov %A0,%B0" CR_TAB
7413 "clr %B0" CR_TAB
7414 "lsr %A0" CR_TAB
7415 "lsr %A0" CR_TAB
7416 "lsr %A0");
7418 case 12:
7419 if (ldi_ok)
7421 *len = 4;
7422 return ("mov %A0,%B0" CR_TAB
7423 "clr %B0" CR_TAB
7424 "swap %A0" CR_TAB
7425 "andi %A0,0x0f");
7427 if (scratch)
7429 *len = 5;
7430 return ("mov %A0,%B0" CR_TAB
7431 "clr %B0" CR_TAB
7432 "swap %A0" CR_TAB
7433 "ldi %3,0x0f" CR_TAB
7434 "and %A0,%3");
7436 *len = 6;
7437 return ("mov %A0,%B0" CR_TAB
7438 "clr %B0" CR_TAB
7439 "lsr %A0" CR_TAB
7440 "lsr %A0" CR_TAB
7441 "lsr %A0" CR_TAB
7442 "lsr %A0");
7444 case 13:
7445 if (ldi_ok)
7447 *len = 5;
7448 return ("mov %A0,%B0" CR_TAB
7449 "clr %B0" CR_TAB
7450 "swap %A0" CR_TAB
7451 "lsr %A0" CR_TAB
7452 "andi %A0,0x07");
7454 if (AVR_HAVE_MUL && scratch)
7456 *len = 5;
7457 return ("ldi %3,0x08" CR_TAB
7458 "mul %B0,%3" CR_TAB
7459 "mov %A0,r1" CR_TAB
7460 "clr %B0" CR_TAB
7461 "clr __zero_reg__");
7463 if (optimize_size && scratch)
7464 break; /* 5 */
7465 if (scratch)
7467 *len = 6;
7468 return ("mov %A0,%B0" CR_TAB
7469 "clr %B0" CR_TAB
7470 "swap %A0" CR_TAB
7471 "lsr %A0" CR_TAB
7472 "ldi %3,0x07" CR_TAB
7473 "and %A0,%3");
7475 if (AVR_HAVE_MUL)
7477 *len = 6;
7478 return ("set" CR_TAB
7479 "bld r1,3" CR_TAB
7480 "mul %B0,r1" CR_TAB
7481 "mov %A0,r1" CR_TAB
7482 "clr %B0" CR_TAB
7483 "clr __zero_reg__");
7485 *len = 7;
7486 return ("mov %A0,%B0" CR_TAB
7487 "clr %B0" CR_TAB
7488 "lsr %A0" CR_TAB
7489 "lsr %A0" CR_TAB
7490 "lsr %A0" CR_TAB
7491 "lsr %A0" CR_TAB
7492 "lsr %A0");
7494 case 14:
7495 if (AVR_HAVE_MUL && ldi_ok)
7497 *len = 5;
7498 return ("ldi %A0,0x04" CR_TAB
7499 "mul %B0,%A0" CR_TAB
7500 "mov %A0,r1" CR_TAB
7501 "clr %B0" CR_TAB
7502 "clr __zero_reg__");
7504 if (AVR_HAVE_MUL && scratch)
7506 *len = 5;
7507 return ("ldi %3,0x04" CR_TAB
7508 "mul %B0,%3" CR_TAB
7509 "mov %A0,r1" CR_TAB
7510 "clr %B0" CR_TAB
7511 "clr __zero_reg__");
7513 if (optimize_size && ldi_ok)
7515 *len = 5;
7516 return ("mov %A0,%B0" CR_TAB
7517 "ldi %B0,6" "\n1:\t"
7518 "lsr %A0" CR_TAB
7519 "dec %B0" CR_TAB
7520 "brne 1b");
7522 if (optimize_size && scratch)
7523 break; /* 5 */
7524 *len = 6;
7525 return ("clr %A0" CR_TAB
7526 "lsl %B0" CR_TAB
7527 "rol %A0" CR_TAB
7528 "lsl %B0" CR_TAB
7529 "rol %A0" CR_TAB
7530 "clr %B0");
7532 case 15:
7533 *len = 4;
7534 return ("clr %A0" CR_TAB
7535 "lsl %B0" CR_TAB
7536 "rol %A0" CR_TAB
7537 "clr %B0");
7539 len = t;
7541 out_shift_with_cnt ("lsr %B0" CR_TAB
7542 "ror %A0", insn, operands, len, 2);
7543 return "";
7547 /* 24-bit logic shift right */
7549 const char*
7550 avr_out_lshrpsi3 (rtx_insn *insn, rtx *op, int *plen)
7552 int dest = REGNO (op[0]);
7553 int src = REGNO (op[1]);
7555 if (CONST_INT_P (op[2]))
7557 if (plen)
7558 *plen = 0;
7560 switch (INTVAL (op[2]))
7562 case 8:
7563 if (dest <= src)
7564 return avr_asm_len ("mov %A0,%B1" CR_TAB
7565 "mov %B0,%C1" CR_TAB
7566 "clr %C0", op, plen, 3);
7567 else
7568 return avr_asm_len ("clr %C0" CR_TAB
7569 "mov %B0,%C1" CR_TAB
7570 "mov %A0,%B1", op, plen, 3);
7572 case 16:
7573 if (dest != src + 2)
7574 avr_asm_len ("mov %A0,%C1", op, plen, 1);
7576 return avr_asm_len ("clr %B0" CR_TAB
7577 "clr %C0", op, plen, 2);
7579 default:
7580 if (INTVAL (op[2]) < 24)
7581 break;
7583 /* fall through */
7585 case 23:
7586 return avr_asm_len ("clr %A0" CR_TAB
7587 "sbrc %C0,7" CR_TAB
7588 "inc %A0" CR_TAB
7589 "clr %B0" CR_TAB
7590 "clr %C0", op, plen, 5);
7591 } /* switch */
7594 out_shift_with_cnt ("lsr %C0" CR_TAB
7595 "ror %B0" CR_TAB
7596 "ror %A0", insn, op, plen, 3);
7597 return "";
7601 /* 32-bit logic shift right ((unsigned int)x >> i) */
7603 const char *
7604 lshrsi3_out (rtx_insn *insn, rtx operands[], int *len)
7606 if (CONST_INT_P (operands[2]))
7608 int k;
7609 int *t = len;
7611 if (!len)
7612 len = &k;
7614 switch (INTVAL (operands[2]))
7616 default:
7617 if (INTVAL (operands[2]) < 32)
7618 break;
7620 if (AVR_HAVE_MOVW)
7621 return *len = 3, ("clr %D0" CR_TAB
7622 "clr %C0" CR_TAB
7623 "movw %A0,%C0");
7624 *len = 4;
7625 return ("clr %D0" CR_TAB
7626 "clr %C0" CR_TAB
7627 "clr %B0" CR_TAB
7628 "clr %A0");
7630 case 8:
7632 int reg0 = true_regnum (operands[0]);
7633 int reg1 = true_regnum (operands[1]);
7634 *len = 4;
7635 if (reg0 <= reg1)
7636 return ("mov %A0,%B1" CR_TAB
7637 "mov %B0,%C1" CR_TAB
7638 "mov %C0,%D1" CR_TAB
7639 "clr %D0");
7640 else
7641 return ("clr %D0" CR_TAB
7642 "mov %C0,%D1" CR_TAB
7643 "mov %B0,%C1" CR_TAB
7644 "mov %A0,%B1");
7647 case 16:
7649 int reg0 = true_regnum (operands[0]);
7650 int reg1 = true_regnum (operands[1]);
7652 if (reg0 == reg1 + 2)
7653 return *len = 2, ("clr %C0" CR_TAB
7654 "clr %D0");
7655 if (AVR_HAVE_MOVW)
7656 return *len = 3, ("movw %A0,%C1" CR_TAB
7657 "clr %C0" CR_TAB
7658 "clr %D0");
7659 else
7660 return *len = 4, ("mov %B0,%D1" CR_TAB
7661 "mov %A0,%C1" CR_TAB
7662 "clr %C0" CR_TAB
7663 "clr %D0");
7666 case 24:
7667 return *len = 4, ("mov %A0,%D1" CR_TAB
7668 "clr %B0" CR_TAB
7669 "clr %C0" CR_TAB
7670 "clr %D0");
7672 case 31:
7673 *len = 6;
7674 return ("clr %A0" CR_TAB
7675 "sbrc %D0,7" CR_TAB
7676 "inc %A0" CR_TAB
7677 "clr %B0" CR_TAB
7678 "clr %C0" CR_TAB
7679 "clr %D0");
7681 len = t;
7683 out_shift_with_cnt ("lsr %D0" CR_TAB
7684 "ror %C0" CR_TAB
7685 "ror %B0" CR_TAB
7686 "ror %A0", insn, operands, len, 4);
7687 return "";
7691 /* Output addition of register XOP[0] and compile time constant XOP[2].
7692 CODE == PLUS: perform addition by using ADD instructions or
7693 CODE == MINUS: perform addition by using SUB instructions:
7695 XOP[0] = XOP[0] + XOP[2]
7697 Or perform addition/subtraction with register XOP[2] depending on CODE:
7699 XOP[0] = XOP[0] +/- XOP[2]
7701 If PLEN == NULL, print assembler instructions to perform the operation;
7702 otherwise, set *PLEN to the length of the instruction sequence (in words)
7703 printed with PLEN == NULL. XOP[3] is an 8-bit scratch register or NULL_RTX.
7704 Set *PCC to effect on cc0 according to respective CC_* insn attribute.
7706 CODE_SAT == UNKNOWN: Perform ordinary, non-saturating operation.
7707 CODE_SAT != UNKNOWN: Perform operation and saturate according to CODE_SAT.
7708 If CODE_SAT != UNKNOWN then SIGN contains the sign of the summand resp.
7709 the subtrahend in the original insn, provided it is a compile time constant.
7710 In all other cases, SIGN is 0.
7712 If OUT_LABEL is true, print the final 0: label which is needed for
7713 saturated addition / subtraction. The only case where OUT_LABEL = false
7714 is useful is for saturated addition / subtraction performed during
7715 fixed-point rounding, cf. `avr_out_round'. */
7717 static void
7718 avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc,
7719 enum rtx_code code_sat, int sign, bool out_label)
7721 /* MODE of the operation. */
7722 machine_mode mode = GET_MODE (xop[0]);
7724 /* INT_MODE of the same size. */
7725 scalar_int_mode imode = int_mode_for_mode (mode).require ();
7727 /* Number of bytes to operate on. */
7728 int n_bytes = GET_MODE_SIZE (mode);
7730 /* Value (0..0xff) held in clobber register op[3] or -1 if unknown. */
7731 int clobber_val = -1;
7733 /* op[0]: 8-bit destination register
7734 op[1]: 8-bit const int
7735 op[2]: 8-bit scratch register */
7736 rtx op[3];
7738 /* Started the operation? Before starting the operation we may skip
7739 adding 0. This is no more true after the operation started because
7740 carry must be taken into account. */
7741 bool started = false;
7743 /* Value to add. There are two ways to add VAL: R += VAL and R -= -VAL. */
7744 rtx xval = xop[2];
7746 /* Output a BRVC instruction. Only needed with saturation. */
7747 bool out_brvc = true;
7749 if (plen)
7750 *plen = 0;
7752 if (REG_P (xop[2]))
7754 *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_CLOBBER;
7756 for (int i = 0; i < n_bytes; i++)
7758 /* We operate byte-wise on the destination. */
7759 op[0] = simplify_gen_subreg (QImode, xop[0], mode, i);
7760 op[1] = simplify_gen_subreg (QImode, xop[2], mode, i);
7762 if (i == 0)
7763 avr_asm_len (code == PLUS ? "add %0,%1" : "sub %0,%1",
7764 op, plen, 1);
7765 else
7766 avr_asm_len (code == PLUS ? "adc %0,%1" : "sbc %0,%1",
7767 op, plen, 1);
7770 if (reg_overlap_mentioned_p (xop[0], xop[2]))
7772 gcc_assert (REGNO (xop[0]) == REGNO (xop[2]));
7774 if (MINUS == code)
7775 return;
7778 goto saturate;
7781 /* Except in the case of ADIW with 16-bit register (see below)
7782 addition does not set cc0 in a usable way. */
7784 *pcc = (MINUS == code) ? CC_SET_CZN : CC_CLOBBER;
7786 if (CONST_FIXED_P (xval))
7787 xval = avr_to_int_mode (xval);
7789 /* Adding/Subtracting zero is a no-op. */
7791 if (xval == const0_rtx)
7793 *pcc = CC_NONE;
7794 return;
7797 if (MINUS == code)
7798 xval = simplify_unary_operation (NEG, imode, xval, imode);
7800 op[2] = xop[3];
7802 if (SS_PLUS == code_sat && MINUS == code
7803 && sign < 0
7804 && 0x80 == (INTVAL (simplify_gen_subreg (QImode, xval, imode, n_bytes-1))
7805 & GET_MODE_MASK (QImode)))
7807 /* We compute x + 0x80 by means of SUB instructions. We negated the
7808 constant subtrahend above and are left with x - (-128) so that we
7809 need something like SUBI r,128 which does not exist because SUBI sets
7810 V according to the sign of the subtrahend. Notice the only case
7811 where this must be done is when NEG overflowed in case [2s] because
7812 the V computation needs the right sign of the subtrahend. */
7814 rtx msb = simplify_gen_subreg (QImode, xop[0], mode, n_bytes - 1);
7816 avr_asm_len ("subi %0,128" CR_TAB
7817 "brmi 0f", &msb, plen, 2);
7818 out_brvc = false;
7820 goto saturate;
7823 for (int i = 0; i < n_bytes; i++)
7825 /* We operate byte-wise on the destination. */
7826 rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
7827 rtx xval8 = simplify_gen_subreg (QImode, xval, imode, i);
7829 /* 8-bit value to operate with this byte. */
7830 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
7832 /* Registers R16..R31 can operate with immediate. */
7833 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
7835 op[0] = reg8;
7836 op[1] = gen_int_mode (val8, QImode);
7838 /* To get usable cc0 no low-bytes must have been skipped. */
7840 if (i && !started)
7841 *pcc = CC_CLOBBER;
7843 if (!started
7844 && i % 2 == 0
7845 && i + 2 <= n_bytes
7846 && test_hard_reg_class (ADDW_REGS, reg8))
7848 rtx xval16 = simplify_gen_subreg (HImode, xval, imode, i);
7849 unsigned int val16 = UINTVAL (xval16) & GET_MODE_MASK (HImode);
7851 /* Registers R24, X, Y, Z can use ADIW/SBIW with constants < 64
7852 i.e. operate word-wise. */
7854 if (val16 < 64)
7856 if (val16 != 0)
7858 started = true;
7859 avr_asm_len (code == PLUS ? "adiw %0,%1" : "sbiw %0,%1",
7860 op, plen, 1);
7862 if (n_bytes == 2 && PLUS == code)
7863 *pcc = CC_SET_CZN;
7866 i++;
7867 continue;
7871 if (val8 == 0)
7873 if (started)
7874 avr_asm_len (code == PLUS
7875 ? "adc %0,__zero_reg__" : "sbc %0,__zero_reg__",
7876 op, plen, 1);
7877 continue;
7879 else if ((val8 == 1 || val8 == 0xff)
7880 && UNKNOWN == code_sat
7881 && !started
7882 && i == n_bytes - 1)
7884 avr_asm_len ((code == PLUS) ^ (val8 == 1) ? "dec %0" : "inc %0",
7885 op, plen, 1);
7886 *pcc = CC_CLOBBER;
7887 break;
7890 switch (code)
7892 case PLUS:
7894 gcc_assert (plen != NULL || (op[2] && REG_P (op[2])));
7896 if (plen != NULL && UNKNOWN != code_sat)
7898 /* This belongs to the x + 0x80 corner case. The code with
7899 ADD instruction is not smaller, thus make this case
7900 expensive so that the caller won't pick it. */
7902 *plen += 10;
7903 break;
7906 if (clobber_val != (int) val8)
7907 avr_asm_len ("ldi %2,%1", op, plen, 1);
7908 clobber_val = (int) val8;
7910 avr_asm_len (started ? "adc %0,%2" : "add %0,%2", op, plen, 1);
7912 break; /* PLUS */
7914 case MINUS:
7916 if (ld_reg_p)
7917 avr_asm_len (started ? "sbci %0,%1" : "subi %0,%1", op, plen, 1);
7918 else
7920 gcc_assert (plen != NULL || REG_P (op[2]));
7922 if (clobber_val != (int) val8)
7923 avr_asm_len ("ldi %2,%1", op, plen, 1);
7924 clobber_val = (int) val8;
7926 avr_asm_len (started ? "sbc %0,%2" : "sub %0,%2", op, plen, 1);
7929 break; /* MINUS */
7931 default:
7932 /* Unknown code */
7933 gcc_unreachable();
7936 started = true;
7938 } /* for all sub-bytes */
7940 saturate:
7942 if (UNKNOWN == code_sat)
7943 return;
7945 *pcc = (int) CC_CLOBBER;
7947 /* Vanilla addition/subtraction is done. We are left with saturation.
7949 We have to compute A = A <op> B where A is a register and
7950 B is a register or a non-zero compile time constant CONST.
7951 A is register class "r" if unsigned && B is REG. Otherwise, A is in "d".
7952 B stands for the original operand $2 in INSN. In the case of B = CONST,
7953 SIGN in { -1, 1 } is the sign of B. Otherwise, SIGN is 0.
7955 CODE is the instruction flavor we use in the asm sequence to perform <op>.
7958 unsigned
7959 operation | code | sat if | b is | sat value | case
7960 -----------------+-------+----------+--------------+-----------+-------
7961 + as a + b | add | C == 1 | const, reg | u+ = 0xff | [1u]
7962 + as a - (-b) | sub | C == 0 | const | u+ = 0xff | [2u]
7963 - as a - b | sub | C == 1 | const, reg | u- = 0 | [3u]
7964 - as a + (-b) | add | C == 0 | const | u- = 0 | [4u]
7967 signed
7968 operation | code | sat if | b is | sat value | case
7969 -----------------+-------+----------+--------------+-----------+-------
7970 + as a + b | add | V == 1 | const, reg | s+ | [1s]
7971 + as a - (-b) | sub | V == 1 | const | s+ | [2s]
7972 - as a - b | sub | V == 1 | const, reg | s- | [3s]
7973 - as a + (-b) | add | V == 1 | const | s- | [4s]
7975 s+ = b < 0 ? -0x80 : 0x7f
7976 s- = b < 0 ? 0x7f : -0x80
7978 The cases a - b actually perform a - (-(-b)) if B is CONST.
7981 op[0] = simplify_gen_subreg (QImode, xop[0], mode, n_bytes-1);
7982 op[1] = n_bytes > 1
7983 ? simplify_gen_subreg (QImode, xop[0], mode, n_bytes-2)
7984 : NULL_RTX;
7986 bool need_copy = true;
7987 int len_call = 1 + AVR_HAVE_JMP_CALL;
7989 switch (code_sat)
7991 default:
7992 gcc_unreachable();
7994 case SS_PLUS:
7995 case SS_MINUS:
7997 if (out_brvc)
7998 avr_asm_len ("brvc 0f", op, plen, 1);
8000 if (reg_overlap_mentioned_p (xop[0], xop[2]))
8002 /* [1s,reg] */
8004 if (n_bytes == 1)
8005 avr_asm_len ("ldi %0,0x7f" CR_TAB
8006 "adc %0,__zero_reg__", op, plen, 2);
8007 else
8008 avr_asm_len ("ldi %0,0x7f" CR_TAB
8009 "ldi %1,0xff" CR_TAB
8010 "adc %1,__zero_reg__" CR_TAB
8011 "adc %0,__zero_reg__", op, plen, 4);
8013 else if (sign == 0 && PLUS == code)
8015 /* [1s,reg] */
8017 op[2] = simplify_gen_subreg (QImode, xop[2], mode, n_bytes-1);
8019 if (n_bytes == 1)
8020 avr_asm_len ("ldi %0,0x80" CR_TAB
8021 "sbrs %2,7" CR_TAB
8022 "dec %0", op, plen, 3);
8023 else
8024 avr_asm_len ("ldi %0,0x80" CR_TAB
8025 "cp %2,%0" CR_TAB
8026 "sbc %1,%1" CR_TAB
8027 "sbci %0,0", op, plen, 4);
8029 else if (sign == 0 && MINUS == code)
8031 /* [3s,reg] */
8033 op[2] = simplify_gen_subreg (QImode, xop[2], mode, n_bytes-1);
8035 if (n_bytes == 1)
8036 avr_asm_len ("ldi %0,0x7f" CR_TAB
8037 "sbrs %2,7" CR_TAB
8038 "inc %0", op, plen, 3);
8039 else
8040 avr_asm_len ("ldi %0,0x7f" CR_TAB
8041 "cp %0,%2" CR_TAB
8042 "sbc %1,%1" CR_TAB
8043 "sbci %0,-1", op, plen, 4);
8045 else if ((sign < 0) ^ (SS_MINUS == code_sat))
8047 /* [1s,const,B < 0] [2s,B < 0] */
8048 /* [3s,const,B > 0] [4s,B > 0] */
8050 if (n_bytes == 8)
8052 avr_asm_len ("%~call __clr_8", op, plen, len_call);
8053 need_copy = false;
8056 avr_asm_len ("ldi %0,0x80", op, plen, 1);
8057 if (n_bytes > 1 && need_copy)
8058 avr_asm_len ("clr %1", op, plen, 1);
8060 else if ((sign > 0) ^ (SS_MINUS == code_sat))
8062 /* [1s,const,B > 0] [2s,B > 0] */
8063 /* [3s,const,B < 0] [4s,B < 0] */
8065 if (n_bytes == 8)
8067 avr_asm_len ("sec" CR_TAB
8068 "%~call __sbc_8", op, plen, 1 + len_call);
8069 need_copy = false;
8072 avr_asm_len ("ldi %0,0x7f", op, plen, 1);
8073 if (n_bytes > 1 && need_copy)
8074 avr_asm_len ("ldi %1,0xff", op, plen, 1);
8076 else
8077 gcc_unreachable();
8079 break;
8081 case US_PLUS:
8082 /* [1u] : [2u] */
8084 avr_asm_len (PLUS == code ? "brcc 0f" : "brcs 0f", op, plen, 1);
8086 if (n_bytes == 8)
8088 if (MINUS == code)
8089 avr_asm_len ("sec", op, plen, 1);
8090 avr_asm_len ("%~call __sbc_8", op, plen, len_call);
8092 need_copy = false;
8094 else
8096 if (MINUS == code && !test_hard_reg_class (LD_REGS, op[0]))
8097 avr_asm_len ("sec" CR_TAB
8098 "sbc %0,%0", op, plen, 2);
8099 else
8100 avr_asm_len (PLUS == code ? "sbc %0,%0" : "ldi %0,0xff",
8101 op, plen, 1);
8103 break; /* US_PLUS */
8105 case US_MINUS:
8106 /* [4u] : [3u] */
8108 avr_asm_len (PLUS == code ? "brcs 0f" : "brcc 0f", op, plen, 1);
8110 if (n_bytes == 8)
8112 avr_asm_len ("%~call __clr_8", op, plen, len_call);
8113 need_copy = false;
8115 else
8116 avr_asm_len ("clr %0", op, plen, 1);
8118 break;
8121 /* We set the MSB in the unsigned case and the 2 MSBs in the signed case.
8122 Now copy the right value to the LSBs. */
8124 if (need_copy && n_bytes > 1)
8126 if (US_MINUS == code_sat || US_PLUS == code_sat)
8128 avr_asm_len ("mov %1,%0", op, plen, 1);
8130 if (n_bytes > 2)
8132 op[0] = xop[0];
8133 if (AVR_HAVE_MOVW)
8134 avr_asm_len ("movw %0,%1", op, plen, 1);
8135 else
8136 avr_asm_len ("mov %A0,%1" CR_TAB
8137 "mov %B0,%1", op, plen, 2);
8140 else if (n_bytes > 2)
8142 op[0] = xop[0];
8143 avr_asm_len ("mov %A0,%1" CR_TAB
8144 "mov %B0,%1", op, plen, 2);
8148 if (need_copy && n_bytes == 8)
8150 if (AVR_HAVE_MOVW)
8151 avr_asm_len ("movw %r0+2,%0" CR_TAB
8152 "movw %r0+4,%0", xop, plen, 2);
8153 else
8154 avr_asm_len ("mov %r0+2,%0" CR_TAB
8155 "mov %r0+3,%0" CR_TAB
8156 "mov %r0+4,%0" CR_TAB
8157 "mov %r0+5,%0", xop, plen, 4);
8160 if (out_label)
8161 avr_asm_len ("0:", op, plen, 0);
8165 /* Output addition/subtraction of register XOP[0] and a constant XOP[2] that
8166 is ont a compile-time constant:
8168 XOP[0] = XOP[0] +/- XOP[2]
8170 This is a helper for the function below. The only insns that need this
8171 are additions/subtraction for pointer modes, i.e. HImode and PSImode. */
8173 static const char*
8174 avr_out_plus_symbol (rtx *xop, enum rtx_code code, int *plen, int *pcc)
8176 machine_mode mode = GET_MODE (xop[0]);
8178 /* Only pointer modes want to add symbols. */
8180 gcc_assert (mode == HImode || mode == PSImode);
8182 *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_SET_N;
8184 avr_asm_len (PLUS == code
8185 ? "subi %A0,lo8(-(%2))" CR_TAB "sbci %B0,hi8(-(%2))"
8186 : "subi %A0,lo8(%2)" CR_TAB "sbci %B0,hi8(%2)",
8187 xop, plen, -2);
8189 if (PSImode == mode)
8190 avr_asm_len (PLUS == code
8191 ? "sbci %C0,hlo8(-(%2))"
8192 : "sbci %C0,hlo8(%2)", xop, plen, 1);
8193 return "";
8197 /* Prepare operands of addition/subtraction to be used with avr_out_plus_1.
8199 INSN is a single_set insn or an insn pattern with a binary operation as
8200 SET_SRC that is one of: PLUS, SS_PLUS, US_PLUS, MINUS, SS_MINUS, US_MINUS.
8202 XOP are the operands of INSN. In the case of 64-bit operations with
8203 constant XOP[] has just one element: The summand/subtrahend in XOP[0].
8204 The non-saturating insns up to 32 bits may or may not supply a "d" class
8205 scratch as XOP[3].
8207 If PLEN == NULL output the instructions.
8208 If PLEN != NULL set *PLEN to the length of the sequence in words.
8210 PCC is a pointer to store the instructions' effect on cc0.
8211 PCC may be NULL.
8213 PLEN and PCC default to NULL.
8215 OUT_LABEL defaults to TRUE. For a description, see AVR_OUT_PLUS_1.
8217 Return "" */
8219 const char*
8220 avr_out_plus (rtx insn, rtx *xop, int *plen, int *pcc, bool out_label)
8222 int cc_plus, cc_minus, cc_dummy;
8223 int len_plus, len_minus;
8224 rtx op[4];
8225 rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
8226 rtx xdest = SET_DEST (xpattern);
8227 machine_mode mode = GET_MODE (xdest);
8228 scalar_int_mode imode = int_mode_for_mode (mode).require ();
8229 int n_bytes = GET_MODE_SIZE (mode);
8230 enum rtx_code code_sat = GET_CODE (SET_SRC (xpattern));
8231 enum rtx_code code
8232 = (PLUS == code_sat || SS_PLUS == code_sat || US_PLUS == code_sat
8233 ? PLUS : MINUS);
8235 if (!pcc)
8236 pcc = &cc_dummy;
8238 /* PLUS and MINUS don't saturate: Use modular wrap-around. */
8240 if (PLUS == code_sat || MINUS == code_sat)
8241 code_sat = UNKNOWN;
8243 if (n_bytes <= 4 && REG_P (xop[2]))
8245 avr_out_plus_1 (xop, plen, code, pcc, code_sat, 0, out_label);
8246 return "";
8249 if (n_bytes == 8)
8251 op[0] = gen_rtx_REG (DImode, ACC_A);
8252 op[1] = gen_rtx_REG (DImode, ACC_A);
8253 op[2] = avr_to_int_mode (xop[0]);
8255 else
8257 if (!REG_P (xop[2])
8258 && !CONST_INT_P (xop[2])
8259 && !CONST_FIXED_P (xop[2]))
8261 return avr_out_plus_symbol (xop, code, plen, pcc);
8264 op[0] = avr_to_int_mode (xop[0]);
8265 op[1] = avr_to_int_mode (xop[1]);
8266 op[2] = avr_to_int_mode (xop[2]);
8269 /* Saturations and 64-bit operations don't have a clobber operand.
8270 For the other cases, the caller will provide a proper XOP[3]. */
8272 xpattern = INSN_P (insn) ? PATTERN (insn) : insn;
8273 op[3] = PARALLEL == GET_CODE (xpattern) ? xop[3] : NULL_RTX;
8275 /* Saturation will need the sign of the original operand. */
8277 rtx xmsb = simplify_gen_subreg (QImode, op[2], imode, n_bytes-1);
8278 int sign = INTVAL (xmsb) < 0 ? -1 : 1;
8280 /* If we subtract and the subtrahend is a constant, then negate it
8281 so that avr_out_plus_1 can be used. */
8283 if (MINUS == code)
8284 op[2] = simplify_unary_operation (NEG, imode, op[2], imode);
8286 /* Work out the shortest sequence. */
8288 avr_out_plus_1 (op, &len_minus, MINUS, &cc_minus, code_sat, sign, out_label);
8289 avr_out_plus_1 (op, &len_plus, PLUS, &cc_plus, code_sat, sign, out_label);
8291 if (plen)
8293 *plen = (len_minus <= len_plus) ? len_minus : len_plus;
8294 *pcc = (len_minus <= len_plus) ? cc_minus : cc_plus;
8296 else if (len_minus <= len_plus)
8297 avr_out_plus_1 (op, NULL, MINUS, pcc, code_sat, sign, out_label);
8298 else
8299 avr_out_plus_1 (op, NULL, PLUS, pcc, code_sat, sign, out_label);
8301 return "";
8305 /* Output bit operation (IOR, AND, XOR) with register XOP[0] and compile
8306 time constant XOP[2]:
8308 XOP[0] = XOP[0] <op> XOP[2]
8310 and return "". If PLEN == NULL, print assembler instructions to perform the
8311 operation; otherwise, set *PLEN to the length of the instruction sequence
8312 (in words) printed with PLEN == NULL. XOP[3] is either an 8-bit clobber
8313 register or SCRATCH if no clobber register is needed for the operation.
8314 INSN is an INSN_P or a pattern of an insn. */
8316 const char*
8317 avr_out_bitop (rtx insn, rtx *xop, int *plen)
8319 /* CODE and MODE of the operation. */
8320 rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
8321 enum rtx_code code = GET_CODE (SET_SRC (xpattern));
8322 machine_mode mode = GET_MODE (xop[0]);
8324 /* Number of bytes to operate on. */
8325 int n_bytes = GET_MODE_SIZE (mode);
8327 /* Value of T-flag (0 or 1) or -1 if unknow. */
8328 int set_t = -1;
8330 /* Value (0..0xff) held in clobber register op[3] or -1 if unknown. */
8331 int clobber_val = -1;
8333 /* op[0]: 8-bit destination register
8334 op[1]: 8-bit const int
8335 op[2]: 8-bit clobber register, SCRATCH or NULL_RTX.
8336 op[3]: 8-bit register containing 0xff or NULL_RTX */
8337 rtx op[4];
8339 op[2] = QImode == mode ? NULL_RTX : xop[3];
8340 op[3] = NULL_RTX;
8342 if (plen)
8343 *plen = 0;
8345 for (int i = 0; i < n_bytes; i++)
8347 /* We operate byte-wise on the destination. */
8348 rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
8349 rtx xval8 = simplify_gen_subreg (QImode, xop[2], mode, i);
8351 /* 8-bit value to operate with this byte. */
8352 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
8354 /* Number of bits set in the current byte of the constant. */
8355 int pop8 = popcount_hwi (val8);
8357 /* Registers R16..R31 can operate with immediate. */
8358 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
8360 op[0] = reg8;
8361 op[1] = GEN_INT (val8);
8363 switch (code)
8365 case IOR:
8367 if (pop8 == 0)
8368 continue;
8369 else if (ld_reg_p)
8370 avr_asm_len ("ori %0,%1", op, plen, 1);
8371 else if (pop8 == 1)
8373 if (set_t != 1)
8374 avr_asm_len ("set", op, plen, 1);
8375 set_t = 1;
8377 op[1] = GEN_INT (exact_log2 (val8));
8378 avr_asm_len ("bld %0,%1", op, plen, 1);
8380 else if (pop8 == 8)
8382 if (op[3] != NULL_RTX)
8383 avr_asm_len ("mov %0,%3", op, plen, 1);
8384 else
8385 avr_asm_len ("clr %0" CR_TAB
8386 "dec %0", op, plen, 2);
8388 op[3] = op[0];
8390 else
8392 if (clobber_val != (int) val8)
8393 avr_asm_len ("ldi %2,%1", op, plen, 1);
8394 clobber_val = (int) val8;
8396 avr_asm_len ("or %0,%2", op, plen, 1);
8399 continue; /* IOR */
8401 case AND:
8403 if (pop8 == 8)
8404 continue;
8405 else if (pop8 == 0)
8406 avr_asm_len ("clr %0", op, plen, 1);
8407 else if (ld_reg_p)
8408 avr_asm_len ("andi %0,%1", op, plen, 1);
8409 else if (pop8 == 7)
8411 if (set_t != 0)
8412 avr_asm_len ("clt", op, plen, 1);
8413 set_t = 0;
8415 op[1] = GEN_INT (exact_log2 (GET_MODE_MASK (QImode) & ~val8));
8416 avr_asm_len ("bld %0,%1", op, plen, 1);
8418 else
8420 if (clobber_val != (int) val8)
8421 avr_asm_len ("ldi %2,%1", op, plen, 1);
8422 clobber_val = (int) val8;
8424 avr_asm_len ("and %0,%2", op, plen, 1);
8427 continue; /* AND */
8429 case XOR:
8431 if (pop8 == 0)
8432 continue;
8433 else if (pop8 == 8)
8434 avr_asm_len ("com %0", op, plen, 1);
8435 else if (ld_reg_p && val8 == (1 << 7))
8436 avr_asm_len ("subi %0,%1", op, plen, 1);
8437 else
8439 if (clobber_val != (int) val8)
8440 avr_asm_len ("ldi %2,%1", op, plen, 1);
8441 clobber_val = (int) val8;
8443 avr_asm_len ("eor %0,%2", op, plen, 1);
8446 continue; /* XOR */
8448 default:
8449 /* Unknown rtx_code */
8450 gcc_unreachable();
8452 } /* for all sub-bytes */
8454 return "";
8458 /* Output sign extension from XOP[1] to XOP[0] and return "".
8459 If PLEN == NULL, print assembler instructions to perform the operation;
8460 otherwise, set *PLEN to the length of the instruction sequence (in words)
8461 as printed with PLEN == NULL. */
8463 const char*
8464 avr_out_sign_extend (rtx_insn *insn, rtx *xop, int *plen)
8466 // Size in bytes of source resp. destination operand.
8467 unsigned n_src = GET_MODE_SIZE (GET_MODE (xop[1]));
8468 unsigned n_dest = GET_MODE_SIZE (GET_MODE (xop[0]));
8469 rtx r_msb = all_regs_rtx[REGNO (xop[1]) + n_src - 1];
8471 if (plen)
8472 *plen = 0;
8474 // Copy destination to source
8476 if (REGNO (xop[0]) != REGNO (xop[1]))
8478 gcc_assert (n_src <= 2);
8480 if (n_src == 2)
8481 avr_asm_len (AVR_HAVE_MOVW
8482 ? "movw %0,%1"
8483 : "mov %B0,%B1", xop, plen, 1);
8484 if (n_src == 1 || !AVR_HAVE_MOVW)
8485 avr_asm_len ("mov %A0,%A1", xop, plen, 1);
8488 // Set Carry to the sign bit MSB.7...
8490 if (REGNO (xop[0]) == REGNO (xop[1])
8491 || !reg_unused_after (insn, r_msb))
8493 avr_asm_len ("mov __tmp_reg__,%0", &r_msb, plen, 1);
8494 r_msb = tmp_reg_rtx;
8497 avr_asm_len ("lsl %0", &r_msb, plen, 1);
8499 // ...and propagate it to all the new sign bits
8501 for (unsigned n = n_src; n < n_dest; n++)
8502 avr_asm_len ("sbc %0,%0", &all_regs_rtx[REGNO (xop[0]) + n], plen, 1);
8504 return "";
8508 /* PLEN == NULL: Output code to add CONST_INT OP[0] to SP.
8509 PLEN != NULL: Set *PLEN to the length of that sequence.
8510 Return "". */
8512 const char*
8513 avr_out_addto_sp (rtx *op, int *plen)
8515 int pc_len = AVR_2_BYTE_PC ? 2 : 3;
8516 int addend = INTVAL (op[0]);
8518 if (plen)
8519 *plen = 0;
8521 if (addend < 0)
8523 if (flag_verbose_asm || flag_print_asm_name)
8524 avr_asm_len (ASM_COMMENT_START "SP -= %n0", op, plen, 0);
8526 while (addend <= -pc_len)
8528 addend += pc_len;
8529 avr_asm_len ("rcall .", op, plen, 1);
8532 while (addend++ < 0)
8533 avr_asm_len ("push __tmp_reg__", op, plen, 1);
8535 else if (addend > 0)
8537 if (flag_verbose_asm || flag_print_asm_name)
8538 avr_asm_len (ASM_COMMENT_START "SP += %0", op, plen, 0);
8540 while (addend-- > 0)
8541 avr_asm_len ("pop __tmp_reg__", op, plen, 1);
8544 return "";
8548 /* Output instructions to insert an inverted bit into OPERANDS[0]:
8549 $0.$1 = ~$2.$3 if XBITNO = NULL
8550 $0.$1 = ~$2.XBITNO if XBITNO != NULL.
8551 If PLEN = NULL then output the respective instruction sequence which
8552 is a combination of BST / BLD and some instruction(s) to invert the bit.
8553 If PLEN != NULL then store the length of the sequence (in words) in *PLEN.
8554 Return "". */
8556 const char*
8557 avr_out_insert_notbit (rtx_insn *insn, rtx operands[], rtx xbitno, int *plen)
8559 rtx op[4] = { operands[0], operands[1], operands[2],
8560 xbitno == NULL_RTX ? operands [3] : xbitno };
8562 if (INTVAL (op[1]) == 7
8563 && test_hard_reg_class (LD_REGS, op[0]))
8565 /* If the inserted bit number is 7 and we have a d-reg, then invert
8566 the bit after the insertion by means of SUBI *,0x80. */
8568 if (INTVAL (op[3]) == 7
8569 && REGNO (op[0]) == REGNO (op[2]))
8571 avr_asm_len ("subi %0,0x80", op, plen, -1);
8573 else
8575 avr_asm_len ("bst %2,%3" CR_TAB
8576 "bld %0,%1" CR_TAB
8577 "subi %0,0x80", op, plen, -3);
8580 else if (test_hard_reg_class (LD_REGS, op[0])
8581 && (INTVAL (op[1]) != INTVAL (op[3])
8582 || !reg_overlap_mentioned_p (op[0], op[2])))
8584 /* If the destination bit is in a d-reg we can jump depending
8585 on the source bit and use ANDI / ORI. This just applies if we
8586 have not an early-clobber situation with the bit. */
8588 avr_asm_len ("andi %0,~(1<<%1)" CR_TAB
8589 "sbrs %2,%3" CR_TAB
8590 "ori %0,1<<%1", op, plen, -3);
8592 else
8594 /* Otherwise, invert the bit by means of COM before we store it with
8595 BST and then undo the COM if needed. */
8597 avr_asm_len ("com %2" CR_TAB
8598 "bst %2,%3", op, plen, -2);
8600 if (!reg_unused_after (insn, op[2])
8601 // A simple 'reg_unused_after' is not enough because that function
8602 // assumes that the destination register is overwritten completely
8603 // and hence is in order for our purpose. This is not the case
8604 // with BLD which just changes one bit of the destination.
8605 || reg_overlap_mentioned_p (op[0], op[2]))
8607 /* Undo the COM from above. */
8608 avr_asm_len ("com %2", op, plen, 1);
8611 avr_asm_len ("bld %0,%1", op, plen, 1);
8614 return "";
8618 /* Outputs instructions needed for fixed point type conversion.
8619 This includes converting between any fixed point type, as well
8620 as converting to any integer type. Conversion between integer
8621 types is not supported.
8623 Converting signed fractional types requires a bit shift if converting
8624 to or from any unsigned fractional type because the decimal place is
8625 shifted by 1 bit. When the destination is a signed fractional, the sign
8626 is stored in either the carry or T bit. */
8628 const char*
8629 avr_out_fract (rtx_insn *insn, rtx operands[], bool intsigned, int *plen)
8631 rtx xop[6];
8632 RTX_CODE shift = UNKNOWN;
8633 bool sign_in_carry = false;
8634 bool msb_in_carry = false;
8635 bool lsb_in_tmp_reg = false;
8636 bool lsb_in_carry = false;
8637 bool frac_rounded = false;
8638 const char *code_ashift = "lsl %0";
8641 #define MAY_CLOBBER(RR) \
8642 /* Shorthand used below. */ \
8643 ((sign_bytes \
8644 && IN_RANGE (RR, dest.regno_msb - sign_bytes + 1, dest.regno_msb)) \
8645 || (offset && IN_RANGE (RR, dest.regno, dest.regno_msb)) \
8646 || (reg_unused_after (insn, all_regs_rtx[RR]) \
8647 && !IN_RANGE (RR, dest.regno, dest.regno_msb)))
8649 struct
8651 /* bytes : Length of operand in bytes.
8652 ibyte : Length of integral part in bytes.
8653 fbyte, fbit : Length of fractional part in bytes, bits. */
8655 bool sbit;
8656 unsigned fbit, bytes, ibyte, fbyte;
8657 unsigned regno, regno_msb;
8658 } dest, src, *val[2] = { &dest, &src };
8660 if (plen)
8661 *plen = 0;
8663 /* Step 0: Determine information on source and destination operand we
8664 ====== will need in the remainder. */
8666 for (size_t i = 0; i < ARRAY_SIZE (val); i++)
8668 machine_mode mode;
8670 xop[i] = operands[i];
8672 mode = GET_MODE (xop[i]);
8674 val[i]->bytes = GET_MODE_SIZE (mode);
8675 val[i]->regno = REGNO (xop[i]);
8676 val[i]->regno_msb = REGNO (xop[i]) + val[i]->bytes - 1;
8678 if (SCALAR_INT_MODE_P (mode))
8680 val[i]->sbit = intsigned;
8681 val[i]->fbit = 0;
8683 else if (ALL_SCALAR_FIXED_POINT_MODE_P (mode))
8685 val[i]->sbit = SIGNED_SCALAR_FIXED_POINT_MODE_P (mode);
8686 val[i]->fbit = GET_MODE_FBIT (mode);
8688 else
8689 fatal_insn ("unsupported fixed-point conversion", insn);
8691 val[i]->fbyte = (1 + val[i]->fbit) / BITS_PER_UNIT;
8692 val[i]->ibyte = val[i]->bytes - val[i]->fbyte;
8695 // Byte offset of the decimal point taking into account different place
8696 // of the decimal point in input and output and different register numbers
8697 // of input and output.
8698 int offset = dest.regno - src.regno + dest.fbyte - src.fbyte;
8700 // Number of destination bytes that will come from sign / zero extension.
8701 int sign_bytes = (dest.ibyte - src.ibyte) * (dest.ibyte > src.ibyte);
8703 // Number of bytes at the low end to be filled with zeros.
8704 int zero_bytes = (dest.fbyte - src.fbyte) * (dest.fbyte > src.fbyte);
8706 // Do we have a 16-Bit register that is cleared?
8707 rtx clrw = NULL_RTX;
8709 bool sign_extend = src.sbit && sign_bytes;
8711 if (dest.fbit % 8 == 0 && src.fbit % 8 == 7)
8712 shift = ASHIFT;
8713 else if (dest.fbit % 8 == 7 && src.fbit % 8 == 0)
8714 shift = ASHIFTRT;
8715 else if (dest.fbit % 8 == src.fbit % 8)
8716 shift = UNKNOWN;
8717 else
8718 gcc_unreachable();
8720 /* If we need to round the fraction part, we might need to save/round it
8721 before clobbering any of it in Step 1. Also, we might want to do
8722 the rounding now to make use of LD_REGS. */
8723 if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8724 && SCALAR_ACCUM_MODE_P (GET_MODE (xop[1]))
8725 && !TARGET_FRACT_CONV_TRUNC)
8727 bool overlap
8728 = (src.regno <=
8729 (offset ? dest.regno_msb - sign_bytes : dest.regno + zero_bytes - 1)
8730 && dest.regno - offset -1 >= dest.regno);
8731 unsigned s0 = dest.regno - offset -1;
8732 bool use_src = true;
8733 unsigned sn;
8734 unsigned copied_msb = src.regno_msb;
8735 bool have_carry = false;
8737 if (src.ibyte > dest.ibyte)
8738 copied_msb -= src.ibyte - dest.ibyte;
8740 for (sn = s0; sn <= copied_msb; sn++)
8741 if (!IN_RANGE (sn, dest.regno, dest.regno_msb)
8742 && !reg_unused_after (insn, all_regs_rtx[sn]))
8743 use_src = false;
8744 if (use_src && TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], s0))
8746 avr_asm_len ("tst %0" CR_TAB "brpl 0f",
8747 &all_regs_rtx[src.regno_msb], plen, 2);
8748 sn = src.regno;
8749 if (sn < s0)
8751 if (TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], sn))
8752 avr_asm_len ("cpi %0,1", &all_regs_rtx[sn], plen, 1);
8753 else
8754 avr_asm_len ("sec" CR_TAB
8755 "cpc %0,__zero_reg__",
8756 &all_regs_rtx[sn], plen, 2);
8757 have_carry = true;
8759 while (++sn < s0)
8760 avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8762 avr_asm_len (have_carry ? "sbci %0,128" : "subi %0,129",
8763 &all_regs_rtx[s0], plen, 1);
8764 for (sn = src.regno + src.fbyte; sn <= copied_msb; sn++)
8765 avr_asm_len ("sbci %0,255", &all_regs_rtx[sn], plen, 1);
8766 avr_asm_len ("\n0:", NULL, plen, 0);
8767 frac_rounded = true;
8769 else if (use_src && overlap)
8771 avr_asm_len ("clr __tmp_reg__" CR_TAB
8772 "sbrc %1,0" CR_TAB
8773 "dec __tmp_reg__", xop, plen, 1);
8774 sn = src.regno;
8775 if (sn < s0)
8777 avr_asm_len ("add %0,__tmp_reg__", &all_regs_rtx[sn], plen, 1);
8778 have_carry = true;
8781 while (++sn < s0)
8782 avr_asm_len ("adc %0,__tmp_reg__", &all_regs_rtx[sn], plen, 1);
8784 if (have_carry)
8785 avr_asm_len ("clt" CR_TAB
8786 "bld __tmp_reg__,7" CR_TAB
8787 "adc %0,__tmp_reg__",
8788 &all_regs_rtx[s0], plen, 1);
8789 else
8790 avr_asm_len ("lsr __tmp_reg" CR_TAB
8791 "add %0,__tmp_reg__",
8792 &all_regs_rtx[s0], plen, 2);
8793 for (sn = src.regno + src.fbyte; sn <= copied_msb; sn++)
8794 avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8795 frac_rounded = true;
8797 else if (overlap)
8799 bool use_src
8800 = (TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], s0)
8801 && (IN_RANGE (s0, dest.regno, dest.regno_msb)
8802 || reg_unused_after (insn, all_regs_rtx[s0])));
8803 xop[2] = all_regs_rtx[s0];
8804 unsigned sn = src.regno;
8805 if (!use_src || sn == s0)
8806 avr_asm_len ("mov __tmp_reg__,%2", xop, plen, 1);
8807 /* We need to consider to-be-discarded bits
8808 if the value is negative. */
8809 if (sn < s0)
8811 avr_asm_len ("tst %0" CR_TAB
8812 "brpl 0f",
8813 &all_regs_rtx[src.regno_msb], plen, 2);
8814 /* Test to-be-discarded bytes for any nozero bits.
8815 ??? Could use OR or SBIW to test two registers at once. */
8816 if (sn < s0)
8817 avr_asm_len ("cp %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8819 while (++sn < s0)
8820 avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8821 /* Set bit 0 in __tmp_reg__ if any of the lower bits was set. */
8822 if (use_src)
8823 avr_asm_len ("breq 0f" CR_TAB
8824 "ori %2,1"
8825 "\n0:\t" "mov __tmp_reg__,%2",
8826 xop, plen, 3);
8827 else
8828 avr_asm_len ("breq 0f" CR_TAB
8829 "set" CR_TAB
8830 "bld __tmp_reg__,0\n0:",
8831 xop, plen, 3);
8833 lsb_in_tmp_reg = true;
8837 /* Step 1: Clear bytes at the low end and copy payload bits from source
8838 ====== to destination. */
8840 int step = offset < 0 ? 1 : -1;
8841 unsigned d0 = offset < 0 ? dest.regno : dest.regno_msb;
8843 // We cleared at least that number of registers.
8844 int clr_n = 0;
8846 for (; d0 >= dest.regno && d0 <= dest.regno_msb; d0 += step)
8848 // Next regno of destination is needed for MOVW
8849 unsigned d1 = d0 + step;
8851 // Current and next regno of source
8852 signed s0 = d0 - offset;
8853 signed s1 = s0 + step;
8855 // Must current resp. next regno be CLRed? This applies to the low
8856 // bytes of the destination that have no associated source bytes.
8857 bool clr0 = s0 < (signed) src.regno;
8858 bool clr1 = s1 < (signed) src.regno && d1 >= dest.regno;
8860 // First gather what code to emit (if any) and additional step to
8861 // apply if a MOVW is in use. xop[2] is destination rtx and xop[3]
8862 // is the source rtx for the current loop iteration.
8863 const char *code = NULL;
8864 int stepw = 0;
8866 if (clr0)
8868 if (AVR_HAVE_MOVW && clr1 && clrw)
8870 xop[2] = all_regs_rtx[d0 & ~1];
8871 xop[3] = clrw;
8872 code = "movw %2,%3";
8873 stepw = step;
8875 else
8877 xop[2] = all_regs_rtx[d0];
8878 code = "clr %2";
8880 if (++clr_n >= 2
8881 && !clrw
8882 && d0 % 2 == (step > 0))
8884 clrw = all_regs_rtx[d0 & ~1];
8888 else if (offset && s0 <= (signed) src.regno_msb)
8890 int movw = AVR_HAVE_MOVW && offset % 2 == 0
8891 && d0 % 2 == (offset > 0)
8892 && d1 <= dest.regno_msb && d1 >= dest.regno
8893 && s1 <= (signed) src.regno_msb && s1 >= (signed) src.regno;
8895 xop[2] = all_regs_rtx[d0 & ~movw];
8896 xop[3] = all_regs_rtx[s0 & ~movw];
8897 code = movw ? "movw %2,%3" : "mov %2,%3";
8898 stepw = step * movw;
8901 if (code)
8903 if (sign_extend && shift != ASHIFT && !sign_in_carry
8904 && (d0 == src.regno_msb || d0 + stepw == src.regno_msb))
8906 /* We are going to override the sign bit. If we sign-extend,
8907 store the sign in the Carry flag. This is not needed if
8908 the destination will be ASHIFT in the remainder because
8909 the ASHIFT will set Carry without extra instruction. */
8911 avr_asm_len ("lsl %0", &all_regs_rtx[src.regno_msb], plen, 1);
8912 sign_in_carry = true;
8915 unsigned src_msb = dest.regno_msb - sign_bytes - offset + 1;
8917 if (!sign_extend && shift == ASHIFTRT && !msb_in_carry
8918 && src.ibyte > dest.ibyte
8919 && (d0 == src_msb || d0 + stepw == src_msb))
8921 /* We are going to override the MSB. If we shift right,
8922 store the MSB in the Carry flag. This is only needed if
8923 we don't sign-extend becaue with sign-extension the MSB
8924 (the sign) will be produced by the sign extension. */
8926 avr_asm_len ("lsr %0", &all_regs_rtx[src_msb], plen, 1);
8927 msb_in_carry = true;
8930 unsigned src_lsb = dest.regno - offset -1;
8932 if (shift == ASHIFT && src.fbyte > dest.fbyte && !lsb_in_carry
8933 && !lsb_in_tmp_reg
8934 && (d0 == src_lsb || d0 + stepw == src_lsb))
8936 /* We are going to override the new LSB; store it into carry. */
8938 avr_asm_len ("lsl %0", &all_regs_rtx[src_lsb], plen, 1);
8939 code_ashift = "rol %0";
8940 lsb_in_carry = true;
8943 avr_asm_len (code, xop, plen, 1);
8944 d0 += stepw;
8948 /* Step 2: Shift destination left by 1 bit position. This might be needed
8949 ====== for signed input and unsigned output. */
8951 if (shift == ASHIFT && src.fbyte > dest.fbyte && !lsb_in_carry)
8953 unsigned s0 = dest.regno - offset -1;
8955 /* n1169 4.1.4 says:
8956 "Conversions from a fixed-point to an integer type round toward zero."
8957 Hence, converting a fract type to integer only gives a non-zero result
8958 for -1. */
8959 if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8960 && SCALAR_FRACT_MODE_P (GET_MODE (xop[1]))
8961 && !TARGET_FRACT_CONV_TRUNC)
8963 gcc_assert (s0 == src.regno_msb);
8964 /* Check if the input is -1. We do that by checking if negating
8965 the input causes an integer overflow. */
8966 unsigned sn = src.regno;
8967 avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx[sn++], plen, 1);
8968 while (sn <= s0)
8969 avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx[sn++], plen, 1);
8971 /* Overflow goes with set carry. Clear carry otherwise. */
8972 avr_asm_len ("brvs 0f" CR_TAB
8973 "clc\n0:", NULL, plen, 2);
8975 /* Likewise, when converting from accumulator types to integer, we
8976 need to round up negative values. */
8977 else if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8978 && SCALAR_ACCUM_MODE_P (GET_MODE (xop[1]))
8979 && !TARGET_FRACT_CONV_TRUNC
8980 && !frac_rounded)
8982 bool have_carry = false;
8984 xop[2] = all_regs_rtx[s0];
8985 if (!lsb_in_tmp_reg && !MAY_CLOBBER (s0))
8986 avr_asm_len ("mov __tmp_reg__,%2", xop, plen, 1);
8987 avr_asm_len ("tst %0" CR_TAB "brpl 0f",
8988 &all_regs_rtx[src.regno_msb], plen, 2);
8989 if (!lsb_in_tmp_reg)
8991 unsigned sn = src.regno;
8992 if (sn < s0)
8994 avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx[sn],
8995 plen, 1);
8996 have_carry = true;
8998 while (++sn < s0)
8999 avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx[sn], plen, 1);
9000 lsb_in_tmp_reg = !MAY_CLOBBER (s0);
9002 /* Add in C and the rounding value 127. */
9003 /* If the destination msb is a sign byte, and in LD_REGS,
9004 grab it as a temporary. */
9005 if (sign_bytes
9006 && TEST_HARD_REG_BIT (reg_class_contents[LD_REGS],
9007 dest.regno_msb))
9009 xop[3] = all_regs_rtx[dest.regno_msb];
9010 avr_asm_len ("ldi %3,127", xop, plen, 1);
9011 avr_asm_len ((have_carry && lsb_in_tmp_reg ? "adc __tmp_reg__,%3"
9012 : have_carry ? "adc %2,%3"
9013 : lsb_in_tmp_reg ? "add __tmp_reg__,%3"
9014 : "add %2,%3"),
9015 xop, plen, 1);
9017 else
9019 /* Fall back to use __zero_reg__ as a temporary. */
9020 avr_asm_len ("dec __zero_reg__", NULL, plen, 1);
9021 if (have_carry)
9022 avr_asm_len ("clt" CR_TAB
9023 "bld __zero_reg__,7", NULL, plen, 2);
9024 else
9025 avr_asm_len ("lsr __zero_reg__", NULL, plen, 1);
9026 avr_asm_len (have_carry && lsb_in_tmp_reg
9027 ? "adc __tmp_reg__,__zero_reg__"
9028 : have_carry ? "adc %2,__zero_reg__"
9029 : lsb_in_tmp_reg ? "add __tmp_reg__,__zero_reg__"
9030 : "add %2,__zero_reg__",
9031 xop, plen, 1);
9032 avr_asm_len ("eor __zero_reg__,__zero_reg__", NULL, plen, 1);
9035 for (d0 = dest.regno + zero_bytes;
9036 d0 <= dest.regno_msb - sign_bytes; d0++)
9037 avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx[d0], plen, 1);
9039 avr_asm_len (lsb_in_tmp_reg
9040 ? "\n0:\t" "lsl __tmp_reg__"
9041 : "\n0:\t" "lsl %2",
9042 xop, plen, 1);
9044 else if (MAY_CLOBBER (s0))
9045 avr_asm_len ("lsl %0", &all_regs_rtx[s0], plen, 1);
9046 else
9047 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
9048 "lsl __tmp_reg__", &all_regs_rtx[s0], plen, 2);
9050 code_ashift = "rol %0";
9051 lsb_in_carry = true;
9054 if (shift == ASHIFT)
9056 for (d0 = dest.regno + zero_bytes;
9057 d0 <= dest.regno_msb - sign_bytes; d0++)
9059 avr_asm_len (code_ashift, &all_regs_rtx[d0], plen, 1);
9060 code_ashift = "rol %0";
9063 lsb_in_carry = false;
9064 sign_in_carry = true;
9067 /* Step 4a: Store MSB in carry if we don't already have it or will produce
9068 ======= it in sign-extension below. */
9070 if (!sign_extend && shift == ASHIFTRT && !msb_in_carry
9071 && src.ibyte > dest.ibyte)
9073 unsigned s0 = dest.regno_msb - sign_bytes - offset + 1;
9075 if (MAY_CLOBBER (s0))
9076 avr_asm_len ("lsr %0", &all_regs_rtx[s0], plen, 1);
9077 else
9078 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
9079 "lsr __tmp_reg__", &all_regs_rtx[s0], plen, 2);
9081 msb_in_carry = true;
9084 /* Step 3: Sign-extend or zero-extend the destination as needed.
9085 ====== */
9087 if (sign_extend && !sign_in_carry)
9089 unsigned s0 = src.regno_msb;
9091 if (MAY_CLOBBER (s0))
9092 avr_asm_len ("lsl %0", &all_regs_rtx[s0], plen, 1);
9093 else
9094 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
9095 "lsl __tmp_reg__", &all_regs_rtx[s0], plen, 2);
9097 sign_in_carry = true;
9100 gcc_assert (sign_in_carry + msb_in_carry + lsb_in_carry <= 1);
9102 unsigned copies = 0;
9103 rtx movw = sign_extend ? NULL_RTX : clrw;
9105 for (d0 = dest.regno_msb - sign_bytes + 1; d0 <= dest.regno_msb; d0++)
9107 if (AVR_HAVE_MOVW && movw
9108 && d0 % 2 == 0 && d0 + 1 <= dest.regno_msb)
9110 xop[2] = all_regs_rtx[d0];
9111 xop[3] = movw;
9112 avr_asm_len ("movw %2,%3", xop, plen, 1);
9113 d0++;
9115 else
9117 avr_asm_len (sign_extend ? "sbc %0,%0" : "clr %0",
9118 &all_regs_rtx[d0], plen, 1);
9120 if (++copies >= 2 && !movw && d0 % 2 == 1)
9121 movw = all_regs_rtx[d0-1];
9123 } /* for */
9126 /* Step 4: Right shift the destination. This might be needed for
9127 ====== conversions from unsigned to signed. */
9129 if (shift == ASHIFTRT)
9131 const char *code_ashiftrt = "lsr %0";
9133 if (sign_extend || msb_in_carry)
9134 code_ashiftrt = "ror %0";
9136 if (src.sbit && src.ibyte == dest.ibyte)
9137 code_ashiftrt = "asr %0";
9139 for (d0 = dest.regno_msb - sign_bytes;
9140 d0 >= dest.regno + zero_bytes - 1 && d0 >= dest.regno; d0--)
9142 avr_asm_len (code_ashiftrt, &all_regs_rtx[d0], plen, 1);
9143 code_ashiftrt = "ror %0";
9147 #undef MAY_CLOBBER
9149 return "";
9153 /* Output fixed-point rounding. XOP[0] = XOP[1] is the operand to round.
9154 XOP[2] is the rounding point, a CONST_INT. The function prints the
9155 instruction sequence if PLEN = NULL and computes the length in words
9156 of the sequence if PLEN != NULL. Most of this function deals with
9157 preparing operands for calls to `avr_out_plus' and `avr_out_bitop'. */
9159 const char*
9160 avr_out_round (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *xop, int *plen)
9162 scalar_mode mode = as_a <scalar_mode> (GET_MODE (xop[0]));
9163 scalar_int_mode imode = int_mode_for_mode (mode).require ();
9164 // The smallest fractional bit not cleared by the rounding is 2^(-RP).
9165 int fbit = (int) GET_MODE_FBIT (mode);
9166 double_int i_add = double_int_zero.set_bit (fbit-1 - INTVAL (xop[2]));
9167 wide_int wi_add = wi::set_bit_in_zero (fbit-1 - INTVAL (xop[2]),
9168 GET_MODE_PRECISION (imode));
9169 // Lengths of PLUS and AND parts.
9170 int len_add = 0, *plen_add = plen ? &len_add : NULL;
9171 int len_and = 0, *plen_and = plen ? &len_and : NULL;
9173 // Add-Saturate 1/2 * 2^(-RP). Don't print the label "0:" when printing
9174 // the saturated addition so that we can emit the "rjmp 1f" before the
9175 // "0:" below.
9177 rtx xadd = const_fixed_from_double_int (i_add, mode);
9178 rtx xpattern, xsrc, op[4];
9180 xsrc = SIGNED_FIXED_POINT_MODE_P (mode)
9181 ? gen_rtx_SS_PLUS (mode, xop[1], xadd)
9182 : gen_rtx_US_PLUS (mode, xop[1], xadd);
9183 xpattern = gen_rtx_SET (xop[0], xsrc);
9185 op[0] = xop[0];
9186 op[1] = xop[1];
9187 op[2] = xadd;
9188 avr_out_plus (xpattern, op, plen_add, NULL, false /* Don't print "0:" */);
9190 avr_asm_len ("rjmp 1f" CR_TAB
9191 "0:", NULL, plen_add, 1);
9193 // Keep all bits from RP and higher: ... 2^(-RP)
9194 // Clear all bits from RP+1 and lower: 2^(-RP-1) ...
9195 // Rounding point ^^^^^^^
9196 // Added above ^^^^^^^^^
9197 rtx xreg = simplify_gen_subreg (imode, xop[0], mode, 0);
9198 rtx xmask = immed_wide_int_const (-wi_add - wi_add, imode);
9200 xpattern = gen_rtx_SET (xreg, gen_rtx_AND (imode, xreg, xmask));
9202 op[0] = xreg;
9203 op[1] = xreg;
9204 op[2] = xmask;
9205 op[3] = gen_rtx_SCRATCH (QImode);
9206 avr_out_bitop (xpattern, op, plen_and);
9207 avr_asm_len ("1:", NULL, plen, 0);
9209 if (plen)
9210 *plen = len_add + len_and;
9212 return "";
9216 /* Create RTL split patterns for byte sized rotate expressions. This
9217 produces a series of move instructions and considers overlap situations.
9218 Overlapping non-HImode operands need a scratch register. */
9220 bool
9221 avr_rotate_bytes (rtx operands[])
9223 machine_mode mode = GET_MODE (operands[0]);
9224 bool overlapped = reg_overlap_mentioned_p (operands[0], operands[1]);
9225 bool same_reg = rtx_equal_p (operands[0], operands[1]);
9226 int num = INTVAL (operands[2]);
9227 rtx scratch = operands[3];
9228 /* Work out if byte or word move is needed. Odd byte rotates need QImode.
9229 Word move if no scratch is needed, otherwise use size of scratch. */
9230 machine_mode move_mode = QImode;
9231 int move_size, offset, size;
9233 if (num & 0xf)
9234 move_mode = QImode;
9235 else if ((mode == SImode && !same_reg) || !overlapped)
9236 move_mode = HImode;
9237 else
9238 move_mode = GET_MODE (scratch);
9240 /* Force DI rotate to use QI moves since other DI moves are currently split
9241 into QI moves so forward propagation works better. */
9242 if (mode == DImode)
9243 move_mode = QImode;
9244 /* Make scratch smaller if needed. */
9245 if (SCRATCH != GET_CODE (scratch)
9246 && HImode == GET_MODE (scratch)
9247 && QImode == move_mode)
9248 scratch = simplify_gen_subreg (move_mode, scratch, HImode, 0);
9250 move_size = GET_MODE_SIZE (move_mode);
9251 /* Number of bytes/words to rotate. */
9252 offset = (num >> 3) / move_size;
9253 /* Number of moves needed. */
9254 size = GET_MODE_SIZE (mode) / move_size;
9255 /* Himode byte swap is special case to avoid a scratch register. */
9256 if (mode == HImode && same_reg)
9258 /* HImode byte swap, using xor. This is as quick as using scratch. */
9259 rtx src, dst;
9260 src = simplify_gen_subreg (move_mode, operands[1], mode, 0);
9261 dst = simplify_gen_subreg (move_mode, operands[0], mode, 1);
9262 if (!rtx_equal_p (dst, src))
9264 emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
9265 emit_move_insn (src, gen_rtx_XOR (QImode, src, dst));
9266 emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
9269 else
9271 #define MAX_SIZE 8 /* GET_MODE_SIZE (DImode) / GET_MODE_SIZE (QImode) */
9272 /* Create linked list of moves to determine move order. */
9273 struct {
9274 rtx src, dst;
9275 int links;
9276 } move[MAX_SIZE + 8];
9277 int blocked, moves;
9279 gcc_assert (size <= MAX_SIZE);
9280 /* Generate list of subreg moves. */
9281 for (int i = 0; i < size; i++)
9283 int from = i;
9284 int to = (from + offset) % size;
9285 move[i].src = simplify_gen_subreg (move_mode, operands[1],
9286 mode, from * move_size);
9287 move[i].dst = simplify_gen_subreg (move_mode, operands[0],
9288 mode, to * move_size);
9289 move[i].links = -1;
9291 /* Mark dependence where a dst of one move is the src of another move.
9292 The first move is a conflict as it must wait until second is
9293 performed. We ignore moves to self - we catch this later. */
9294 if (overlapped)
9295 for (int i = 0; i < size; i++)
9296 if (reg_overlap_mentioned_p (move[i].dst, operands[1]))
9297 for (int j = 0; j < size; j++)
9298 if (j != i && rtx_equal_p (move[j].src, move[i].dst))
9300 /* The dst of move i is the src of move j. */
9301 move[i].links = j;
9302 break;
9305 blocked = -1;
9306 moves = 0;
9307 /* Go through move list and perform non-conflicting moves. As each
9308 non-overlapping move is made, it may remove other conflicts
9309 so the process is repeated until no conflicts remain. */
9312 blocked = -1;
9313 moves = 0;
9314 /* Emit move where dst is not also a src or we have used that
9315 src already. */
9316 for (int i = 0; i < size; i++)
9317 if (move[i].src != NULL_RTX)
9319 if (move[i].links == -1
9320 || move[move[i].links].src == NULL_RTX)
9322 moves++;
9323 /* Ignore NOP moves to self. */
9324 if (!rtx_equal_p (move[i].dst, move[i].src))
9325 emit_move_insn (move[i].dst, move[i].src);
9327 /* Remove conflict from list. */
9328 move[i].src = NULL_RTX;
9330 else
9331 blocked = i;
9334 /* Check for deadlock. This is when no moves occurred and we have
9335 at least one blocked move. */
9336 if (moves == 0 && blocked != -1)
9338 /* Need to use scratch register to break deadlock.
9339 Add move to put dst of blocked move into scratch.
9340 When this move occurs, it will break chain deadlock.
9341 The scratch register is substituted for real move. */
9343 gcc_assert (SCRATCH != GET_CODE (scratch));
9345 move[size].src = move[blocked].dst;
9346 move[size].dst = scratch;
9347 /* Scratch move is never blocked. */
9348 move[size].links = -1;
9349 /* Make sure we have valid link. */
9350 gcc_assert (move[blocked].links != -1);
9351 /* Replace src of blocking move with scratch reg. */
9352 move[move[blocked].links].src = scratch;
9353 /* Make dependent on scratch move occurring. */
9354 move[blocked].links = size;
9355 size=size+1;
9358 while (blocked != -1);
9360 return true;
9364 /* Worker function for `ADJUST_INSN_LENGTH'. */
9365 /* Modifies the length assigned to instruction INSN
9366 LEN is the initially computed length of the insn. */
9369 avr_adjust_insn_length (rtx_insn *insn, int len)
9371 rtx *op = recog_data.operand;
9372 enum attr_adjust_len adjust_len;
9374 /* As we pretend jump tables in .text, fix branch offsets crossing jump
9375 tables now. */
9377 if (JUMP_TABLE_DATA_P (insn))
9378 return 0;
9380 /* Some complex insns don't need length adjustment and therefore
9381 the length need not/must not be adjusted for these insns.
9382 It is easier to state this in an insn attribute "adjust_len" than
9383 to clutter up code here... */
9385 if (!NONDEBUG_INSN_P (insn) || recog_memoized (insn) == -1)
9387 return len;
9390 /* Read from insn attribute "adjust_len" if/how length is to be adjusted. */
9392 adjust_len = get_attr_adjust_len (insn);
9394 if (adjust_len == ADJUST_LEN_NO)
9396 /* Nothing to adjust: The length from attribute "length" is fine.
9397 This is the default. */
9399 return len;
9402 /* Extract insn's operands. */
9404 extract_constrain_insn_cached (insn);
9406 /* Dispatch to right function. */
9408 switch (adjust_len)
9410 case ADJUST_LEN_RELOAD_IN16: output_reload_inhi (op, op[2], &len); break;
9411 case ADJUST_LEN_RELOAD_IN24: avr_out_reload_inpsi (op, op[2], &len); break;
9412 case ADJUST_LEN_RELOAD_IN32: output_reload_insisf (op, op[2], &len); break;
9414 case ADJUST_LEN_OUT_BITOP: avr_out_bitop (insn, op, &len); break;
9416 case ADJUST_LEN_PLUS: avr_out_plus (insn, op, &len); break;
9417 case ADJUST_LEN_ADDTO_SP: avr_out_addto_sp (op, &len); break;
9419 case ADJUST_LEN_MOV8: output_movqi (insn, op, &len); break;
9420 case ADJUST_LEN_MOV16: output_movhi (insn, op, &len); break;
9421 case ADJUST_LEN_MOV24: avr_out_movpsi (insn, op, &len); break;
9422 case ADJUST_LEN_MOV32: output_movsisf (insn, op, &len); break;
9423 case ADJUST_LEN_MOVMEM: avr_out_movmem (insn, op, &len); break;
9424 case ADJUST_LEN_XLOAD: avr_out_xload (insn, op, &len); break;
9425 case ADJUST_LEN_SEXT: avr_out_sign_extend (insn, op, &len); break;
9427 case ADJUST_LEN_SFRACT: avr_out_fract (insn, op, true, &len); break;
9428 case ADJUST_LEN_UFRACT: avr_out_fract (insn, op, false, &len); break;
9429 case ADJUST_LEN_ROUND: avr_out_round (insn, op, &len); break;
9431 case ADJUST_LEN_TSTHI: avr_out_tsthi (insn, op, &len); break;
9432 case ADJUST_LEN_TSTPSI: avr_out_tstpsi (insn, op, &len); break;
9433 case ADJUST_LEN_TSTSI: avr_out_tstsi (insn, op, &len); break;
9434 case ADJUST_LEN_COMPARE: avr_out_compare (insn, op, &len); break;
9435 case ADJUST_LEN_COMPARE64: avr_out_compare64 (insn, op, &len); break;
9437 case ADJUST_LEN_LSHRQI: lshrqi3_out (insn, op, &len); break;
9438 case ADJUST_LEN_LSHRHI: lshrhi3_out (insn, op, &len); break;
9439 case ADJUST_LEN_LSHRSI: lshrsi3_out (insn, op, &len); break;
9441 case ADJUST_LEN_ASHRQI: ashrqi3_out (insn, op, &len); break;
9442 case ADJUST_LEN_ASHRHI: ashrhi3_out (insn, op, &len); break;
9443 case ADJUST_LEN_ASHRSI: ashrsi3_out (insn, op, &len); break;
9445 case ADJUST_LEN_ASHLQI: ashlqi3_out (insn, op, &len); break;
9446 case ADJUST_LEN_ASHLHI: ashlhi3_out (insn, op, &len); break;
9447 case ADJUST_LEN_ASHLSI: ashlsi3_out (insn, op, &len); break;
9449 case ADJUST_LEN_ASHLPSI: avr_out_ashlpsi3 (insn, op, &len); break;
9450 case ADJUST_LEN_ASHRPSI: avr_out_ashrpsi3 (insn, op, &len); break;
9451 case ADJUST_LEN_LSHRPSI: avr_out_lshrpsi3 (insn, op, &len); break;
9453 case ADJUST_LEN_CALL: len = AVR_HAVE_JMP_CALL ? 2 : 1; break;
9455 case ADJUST_LEN_INSERT_BITS: avr_out_insert_bits (op, &len); break;
9457 case ADJUST_LEN_INSV_NOTBIT:
9458 avr_out_insert_notbit (insn, op, NULL_RTX, &len);
9459 break;
9460 case ADJUST_LEN_INSV_NOTBIT_0:
9461 avr_out_insert_notbit (insn, op, const0_rtx, &len);
9462 break;
9463 case ADJUST_LEN_INSV_NOTBIT_7:
9464 avr_out_insert_notbit (insn, op, GEN_INT (7), &len);
9465 break;
9467 default:
9468 gcc_unreachable();
9471 return len;
9474 /* Return nonzero if register REG dead after INSN. */
9477 reg_unused_after (rtx_insn *insn, rtx reg)
9479 return (dead_or_set_p (insn, reg)
9480 || (REG_P (reg) && _reg_unused_after (insn, reg)));
9483 /* Return nonzero if REG is not used after INSN.
9484 We assume REG is a reload reg, and therefore does
9485 not live past labels. It may live past calls or jumps though. */
9488 _reg_unused_after (rtx_insn *insn, rtx reg)
9490 enum rtx_code code;
9491 rtx set;
9493 /* If the reg is set by this instruction, then it is safe for our
9494 case. Disregard the case where this is a store to memory, since
9495 we are checking a register used in the store address. */
9496 set = single_set (insn);
9497 if (set && !MEM_P (SET_DEST (set))
9498 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
9499 return 1;
9501 while ((insn = NEXT_INSN (insn)))
9503 rtx set;
9504 code = GET_CODE (insn);
9506 #if 0
9507 /* If this is a label that existed before reload, then the register
9508 if dead here. However, if this is a label added by reorg, then
9509 the register may still be live here. We can't tell the difference,
9510 so we just ignore labels completely. */
9511 if (code == CODE_LABEL)
9512 return 1;
9513 /* else */
9514 #endif
9516 if (!INSN_P (insn))
9517 continue;
9519 if (code == JUMP_INSN)
9520 return 0;
9522 /* If this is a sequence, we must handle them all at once.
9523 We could have for instance a call that sets the target register,
9524 and an insn in a delay slot that uses the register. In this case,
9525 we must return 0. */
9526 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
9528 rtx_sequence *seq = as_a <rtx_sequence *> (PATTERN (insn));
9529 int retval = 0;
9531 for (int i = 0; i < seq->len (); i++)
9533 rtx_insn *this_insn = seq->insn (i);
9534 rtx set = single_set (this_insn);
9536 if (CALL_P (this_insn))
9537 code = CALL_INSN;
9538 else if (JUMP_P (this_insn))
9540 if (INSN_ANNULLED_BRANCH_P (this_insn))
9541 return 0;
9542 code = JUMP_INSN;
9545 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
9546 return 0;
9547 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
9549 if (!MEM_P (SET_DEST (set)))
9550 retval = 1;
9551 else
9552 return 0;
9554 if (set == 0
9555 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
9556 return 0;
9558 if (retval == 1)
9559 return 1;
9560 else if (code == JUMP_INSN)
9561 return 0;
9564 if (code == CALL_INSN)
9566 rtx tem;
9567 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
9568 if (GET_CODE (XEXP (tem, 0)) == USE
9569 && REG_P (XEXP (XEXP (tem, 0), 0))
9570 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
9571 return 0;
9572 if (call_used_regs[REGNO (reg)])
9573 return 1;
9576 set = single_set (insn);
9578 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
9579 return 0;
9580 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
9581 return !MEM_P (SET_DEST (set));
9582 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
9583 return 0;
9585 return 1;
9589 /* Implement `TARGET_ASM_INTEGER'. */
9590 /* Target hook for assembling integer objects. The AVR version needs
9591 special handling for references to certain labels. */
9593 static bool
9594 avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
9596 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
9597 && text_segment_operand (x, VOIDmode))
9599 fputs ("\t.word\tgs(", asm_out_file);
9600 output_addr_const (asm_out_file, x);
9601 fputs (")\n", asm_out_file);
9603 return true;
9605 else if (GET_MODE (x) == PSImode)
9607 /* This needs binutils 2.23+, see PR binutils/13503 */
9609 fputs ("\t.byte\tlo8(", asm_out_file);
9610 output_addr_const (asm_out_file, x);
9611 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
9613 fputs ("\t.byte\thi8(", asm_out_file);
9614 output_addr_const (asm_out_file, x);
9615 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
9617 fputs ("\t.byte\thh8(", asm_out_file);
9618 output_addr_const (asm_out_file, x);
9619 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
9621 return true;
9623 else if (CONST_FIXED_P (x))
9625 /* varasm fails to handle big fixed modes that don't fit in hwi. */
9627 for (unsigned n = 0; n < size; n++)
9629 rtx xn = simplify_gen_subreg (QImode, x, GET_MODE (x), n);
9630 default_assemble_integer (xn, 1, aligned_p);
9633 return true;
9636 if (AVR_TINY
9637 && avr_address_tiny_pm_p (x))
9639 x = plus_constant (Pmode, x, avr_arch->flash_pm_offset);
9642 return default_assemble_integer (x, size, aligned_p);
9646 /* Implement `TARGET_CLASS_LIKELY_SPILLED_P'. */
9647 /* Return value is nonzero if pseudos that have been
9648 assigned to registers of class CLASS would likely be spilled
9649 because registers of CLASS are needed for spill registers. */
9651 static bool
9652 avr_class_likely_spilled_p (reg_class_t c)
9654 return (c != ALL_REGS &&
9655 (AVR_TINY ? 1 : c != ADDW_REGS));
9659 /* Valid attributes:
9660 progmem - Put data to program memory.
9661 signal - Make a function to be hardware interrupt.
9662 After function prologue interrupts remain disabled.
9663 interrupt - Make a function to be hardware interrupt. Before function
9664 prologue interrupts are enabled by means of SEI.
9665 naked - Don't generate function prologue/epilogue and RET
9666 instruction. */
9668 /* Handle a "progmem" attribute; arguments as in
9669 struct attribute_spec.handler. */
9671 static tree
9672 avr_handle_progmem_attribute (tree *node, tree name,
9673 tree args ATTRIBUTE_UNUSED,
9674 int flags ATTRIBUTE_UNUSED,
9675 bool *no_add_attrs)
9677 if (DECL_P (*node))
9679 if (TREE_CODE (*node) == TYPE_DECL)
9681 /* This is really a decl attribute, not a type attribute,
9682 but try to handle it for GCC 3.0 backwards compatibility. */
9684 tree type = TREE_TYPE (*node);
9685 tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
9686 tree newtype = build_type_attribute_variant (type, attr);
9688 TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
9689 TREE_TYPE (*node) = newtype;
9690 *no_add_attrs = true;
9692 else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
9694 *no_add_attrs = false;
9696 else
9698 warning (OPT_Wattributes, "%qE attribute ignored",
9699 name);
9700 *no_add_attrs = true;
9704 return NULL_TREE;
9707 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
9708 struct attribute_spec.handler. */
9710 static tree
9711 avr_handle_fndecl_attribute (tree *node, tree name,
9712 tree args ATTRIBUTE_UNUSED,
9713 int flags ATTRIBUTE_UNUSED,
9714 bool *no_add_attrs)
9716 if (TREE_CODE (*node) != FUNCTION_DECL)
9718 warning (OPT_Wattributes, "%qE attribute only applies to functions",
9719 name);
9720 *no_add_attrs = true;
9723 return NULL_TREE;
9726 static tree
9727 avr_handle_fntype_attribute (tree *node, tree name,
9728 tree args ATTRIBUTE_UNUSED,
9729 int flags ATTRIBUTE_UNUSED,
9730 bool *no_add_attrs)
9732 if (TREE_CODE (*node) != FUNCTION_TYPE)
9734 warning (OPT_Wattributes, "%qE attribute only applies to functions",
9735 name);
9736 *no_add_attrs = true;
9739 return NULL_TREE;
9742 static tree
9743 avr_handle_absdata_attribute (tree *node, tree name, tree /* args */,
9744 int /* flags */, bool *no_add)
9746 location_t loc = DECL_SOURCE_LOCATION (*node);
9748 if (AVR_TINY)
9750 if (TREE_CODE (*node) != VAR_DECL
9751 || (!TREE_STATIC (*node) && !DECL_EXTERNAL (*node)))
9753 warning_at (loc, OPT_Wattributes, "%qE attribute only applies to"
9754 " variables in static storage", name);
9755 *no_add = true;
9758 else
9760 warning_at (loc, OPT_Wattributes, "%qE attribute only supported"
9761 " for reduced Tiny cores", name);
9762 *no_add = true;
9765 return NULL_TREE;
9768 static tree
9769 avr_handle_addr_attribute (tree *node, tree name, tree args,
9770 int flags ATTRIBUTE_UNUSED, bool *no_add)
9772 bool io_p = (strncmp (IDENTIFIER_POINTER (name), "io", 2) == 0);
9773 location_t loc = DECL_SOURCE_LOCATION (*node);
9775 if (!VAR_P (*node))
9777 warning_at (loc, OPT_Wattributes, "%qE attribute only applies to "
9778 "variables", name);
9779 *no_add = true;
9780 return NULL_TREE;
9783 if (args != NULL_TREE)
9785 if (TREE_CODE (TREE_VALUE (args)) == NON_LVALUE_EXPR)
9786 TREE_VALUE (args) = TREE_OPERAND (TREE_VALUE (args), 0);
9787 tree arg = TREE_VALUE (args);
9788 if (TREE_CODE (arg) != INTEGER_CST)
9790 warning_at (loc, OPT_Wattributes, "%qE attribute allows only an "
9791 "integer constant argument", name);
9792 *no_add = true;
9794 else if (io_p
9795 && (!tree_fits_shwi_p (arg)
9796 || !(strcmp (IDENTIFIER_POINTER (name), "io_low") == 0
9797 ? low_io_address_operand : io_address_operand)
9798 (GEN_INT (TREE_INT_CST_LOW (arg)), QImode)))
9800 warning_at (loc, OPT_Wattributes, "%qE attribute address "
9801 "out of range", name);
9802 *no_add = true;
9804 else
9806 tree attribs = DECL_ATTRIBUTES (*node);
9807 const char *names[] = { "io", "io_low", "address", NULL };
9808 for (const char **p = names; *p; p++)
9810 tree other = lookup_attribute (*p, attribs);
9811 if (other && TREE_VALUE (other))
9813 warning_at (loc, OPT_Wattributes,
9814 "both %s and %qE attribute provide address",
9815 *p, name);
9816 *no_add = true;
9817 break;
9823 if (*no_add == false && io_p && !TREE_THIS_VOLATILE (*node))
9824 warning_at (loc, OPT_Wattributes, "%qE attribute on non-volatile variable",
9825 name);
9827 return NULL_TREE;
9831 avr_eval_addr_attrib (rtx x)
9833 if (SYMBOL_REF_P (x)
9834 && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_ADDRESS))
9836 tree decl = SYMBOL_REF_DECL (x);
9837 tree attr = NULL_TREE;
9839 if (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO)
9841 attr = lookup_attribute ("io", DECL_ATTRIBUTES (decl));
9842 if (!attr || !TREE_VALUE (attr))
9843 attr = lookup_attribute ("io_low", DECL_ATTRIBUTES (decl));
9844 gcc_assert (attr);
9846 if (!attr || !TREE_VALUE (attr))
9847 attr = lookup_attribute ("address", DECL_ATTRIBUTES (decl));
9848 gcc_assert (attr && TREE_VALUE (attr) && TREE_VALUE (TREE_VALUE (attr)));
9849 return GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))));
9851 return x;
9855 /* AVR attributes. */
9856 static const struct attribute_spec avr_attribute_table[] =
9858 /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
9859 affects_type_identity, handler, exclude } */
9860 { "progmem", 0, 0, false, false, false, false,
9861 avr_handle_progmem_attribute, NULL },
9862 { "signal", 0, 0, true, false, false, false,
9863 avr_handle_fndecl_attribute, NULL },
9864 { "interrupt", 0, 0, true, false, false, false,
9865 avr_handle_fndecl_attribute, NULL },
9866 { "no_gccisr", 0, 0, true, false, false, false,
9867 avr_handle_fndecl_attribute, NULL },
9868 { "naked", 0, 0, false, true, true, false,
9869 avr_handle_fntype_attribute, NULL },
9870 { "OS_task", 0, 0, false, true, true, false,
9871 avr_handle_fntype_attribute, NULL },
9872 { "OS_main", 0, 0, false, true, true, false,
9873 avr_handle_fntype_attribute, NULL },
9874 { "io", 0, 1, true, false, false, false,
9875 avr_handle_addr_attribute, NULL },
9876 { "io_low", 0, 1, true, false, false, false,
9877 avr_handle_addr_attribute, NULL },
9878 { "address", 1, 1, true, false, false, false,
9879 avr_handle_addr_attribute, NULL },
9880 { "absdata", 0, 0, true, false, false, false,
9881 avr_handle_absdata_attribute, NULL },
9882 { NULL, 0, 0, false, false, false, false, NULL, NULL }
9886 /* Return true if we support address space AS for the architecture in effect
9887 and false, otherwise. If LOC is not UNKNOWN_LOCATION then also issue
9888 a respective error. */
9890 bool
9891 avr_addr_space_supported_p (addr_space_t as, location_t loc)
9893 if (AVR_TINY)
9895 if (loc != UNKNOWN_LOCATION)
9896 error_at (loc, "address spaces are not supported for reduced "
9897 "Tiny devices");
9898 return false;
9900 else if (avr_addrspace[as].segment >= avr_n_flash)
9902 if (loc != UNKNOWN_LOCATION)
9903 error_at (loc, "address space %qs not supported for devices with "
9904 "flash size up to %d KiB", avr_addrspace[as].name,
9905 64 * avr_n_flash);
9906 return false;
9909 return true;
9913 /* Implement `TARGET_ADDR_SPACE_DIAGNOSE_USAGE'. */
9915 static void
9916 avr_addr_space_diagnose_usage (addr_space_t as, location_t loc)
9918 (void) avr_addr_space_supported_p (as, loc);
9922 /* Look if DECL shall be placed in program memory space by
9923 means of attribute `progmem' or some address-space qualifier.
9924 Return non-zero if DECL is data that must end up in Flash and
9925 zero if the data lives in RAM (.bss, .data, .rodata, ...).
9927 Return 2 if DECL is located in 24-bit flash address-space
9928 Return 1 if DECL is located in 16-bit flash address-space
9929 Return -1 if attribute `progmem' occurs in DECL or ATTRIBUTES
9930 Return 0 otherwise */
9933 avr_progmem_p (tree decl, tree attributes)
9935 tree a;
9937 if (TREE_CODE (decl) != VAR_DECL)
9938 return 0;
9940 if (avr_decl_memx_p (decl))
9941 return 2;
9943 if (avr_decl_flash_p (decl))
9944 return 1;
9946 if (NULL_TREE
9947 != lookup_attribute ("progmem", attributes))
9948 return -1;
9950 a = decl;
9953 a = TREE_TYPE(a);
9954 while (TREE_CODE (a) == ARRAY_TYPE);
9956 if (a == error_mark_node)
9957 return 0;
9959 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
9960 return -1;
9962 return 0;
9966 /* Return true if DECL has attribute `absdata' set. This function should
9967 only be used for AVR_TINY. */
9969 static bool
9970 avr_decl_absdata_p (tree decl, tree attributes)
9972 return (TREE_CODE (decl) == VAR_DECL
9973 && NULL_TREE != lookup_attribute ("absdata", attributes));
9977 /* Scan type TYP for pointer references to address space ASn.
9978 Return ADDR_SPACE_GENERIC (i.e. 0) if all pointers targeting
9979 the AS are also declared to be CONST.
9980 Otherwise, return the respective address space, i.e. a value != 0. */
9982 static addr_space_t
9983 avr_nonconst_pointer_addrspace (tree typ)
9985 while (ARRAY_TYPE == TREE_CODE (typ))
9986 typ = TREE_TYPE (typ);
9988 if (POINTER_TYPE_P (typ))
9990 addr_space_t as;
9991 tree target = TREE_TYPE (typ);
9993 /* Pointer to function: Test the function's return type. */
9995 if (FUNCTION_TYPE == TREE_CODE (target))
9996 return avr_nonconst_pointer_addrspace (TREE_TYPE (target));
9998 /* "Ordinary" pointers... */
10000 while (TREE_CODE (target) == ARRAY_TYPE)
10001 target = TREE_TYPE (target);
10003 /* Pointers to non-generic address space must be const. */
10005 as = TYPE_ADDR_SPACE (target);
10007 if (!ADDR_SPACE_GENERIC_P (as)
10008 && !TYPE_READONLY (target)
10009 && avr_addr_space_supported_p (as))
10011 return as;
10014 /* Scan pointer's target type. */
10016 return avr_nonconst_pointer_addrspace (target);
10019 return ADDR_SPACE_GENERIC;
10023 /* Sanity check NODE so that all pointers targeting non-generic address spaces
10024 go along with CONST qualifier. Writing to these address spaces should
10025 be detected and complained about as early as possible. */
10027 static bool
10028 avr_pgm_check_var_decl (tree node)
10030 const char *reason = NULL;
10032 addr_space_t as = ADDR_SPACE_GENERIC;
10034 gcc_assert (as == 0);
10036 if (avr_log.progmem)
10037 avr_edump ("%?: %t\n", node);
10039 switch (TREE_CODE (node))
10041 default:
10042 break;
10044 case VAR_DECL:
10045 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
10046 reason = _("variable");
10047 break;
10049 case PARM_DECL:
10050 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
10051 reason = _("function parameter");
10052 break;
10054 case FIELD_DECL:
10055 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
10056 reason = _("structure field");
10057 break;
10059 case FUNCTION_DECL:
10060 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (TREE_TYPE (node))),
10062 reason = _("return type of function");
10063 break;
10065 case POINTER_TYPE:
10066 if (as = avr_nonconst_pointer_addrspace (node), as)
10067 reason = _("pointer");
10068 break;
10071 if (reason)
10073 if (TYPE_P (node))
10074 error ("pointer targeting address space %qs must be const in %qT",
10075 avr_addrspace[as].name, node);
10076 else
10077 error ("pointer targeting address space %qs must be const"
10078 " in %s %q+D",
10079 avr_addrspace[as].name, reason, node);
10082 return reason == NULL;
10086 /* Implement `TARGET_INSERT_ATTRIBUTES'. */
10088 static void
10089 avr_insert_attributes (tree node, tree *attributes)
10091 avr_pgm_check_var_decl (node);
10093 if (TARGET_MAIN_IS_OS_TASK
10094 && TREE_CODE (node) == FUNCTION_DECL
10095 && MAIN_NAME_P (DECL_NAME (node))
10096 // FIXME: We'd like to also test `flag_hosted' which is only
10097 // available in the C-ish fronts, hence no such test for now.
10098 // Instead, we test the return type of "main" which is not exactly
10099 // the same but good enough.
10100 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (node)))
10101 && NULL == lookup_attribute ("OS_task", *attributes))
10103 *attributes = tree_cons (get_identifier ("OS_task"),
10104 NULL, *attributes);
10107 /* Add the section attribute if the variable is in progmem. */
10109 if (TREE_CODE (node) == VAR_DECL
10110 && (TREE_STATIC (node) || DECL_EXTERNAL (node))
10111 && avr_progmem_p (node, *attributes))
10113 addr_space_t as;
10114 tree node0 = node;
10116 /* For C++, we have to peel arrays in order to get correct
10117 determination of readonlyness. */
10120 node0 = TREE_TYPE (node0);
10121 while (TREE_CODE (node0) == ARRAY_TYPE);
10123 if (error_mark_node == node0)
10124 return;
10126 as = TYPE_ADDR_SPACE (TREE_TYPE (node));
10128 if (!TYPE_READONLY (node0)
10129 && !TREE_READONLY (node))
10131 const char *reason = "__attribute__((progmem))";
10133 if (!ADDR_SPACE_GENERIC_P (as))
10134 reason = avr_addrspace[as].name;
10136 if (avr_log.progmem)
10137 avr_edump ("\n%?: %t\n%t\n", node, node0);
10139 error ("variable %q+D must be const in order to be put into"
10140 " read-only section by means of %qs", node, reason);
10146 /* Implement `ASM_OUTPUT_ALIGNED_DECL_LOCAL'. */
10147 /* Implement `ASM_OUTPUT_ALIGNED_DECL_COMMON'. */
10148 /* Track need of __do_clear_bss. */
10150 void
10151 avr_asm_output_aligned_decl_common (FILE * stream,
10152 tree decl,
10153 const char *name,
10154 unsigned HOST_WIDE_INT size,
10155 unsigned int align, bool local_p)
10157 rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
10158 rtx symbol;
10160 if (mem != NULL_RTX && MEM_P (mem)
10161 && SYMBOL_REF_P ((symbol = XEXP (mem, 0)))
10162 && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
10164 if (!local_p)
10166 fprintf (stream, "\t.globl\t");
10167 assemble_name (stream, name);
10168 fprintf (stream, "\n");
10170 if (SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS)
10172 assemble_name (stream, name);
10173 fprintf (stream, " = %ld\n",
10174 (long) INTVAL (avr_eval_addr_attrib (symbol)));
10176 else if (local_p)
10177 error_at (DECL_SOURCE_LOCATION (decl),
10178 "static IO declaration for %q+D needs an address", decl);
10179 return;
10182 /* __gnu_lto_v1 etc. are just markers for the linker injected by toplev.c.
10183 There is no need to trigger __do_clear_bss code for them. */
10185 if (!STR_PREFIX_P (name, "__gnu_lto"))
10186 avr_need_clear_bss_p = true;
10188 if (local_p)
10189 ASM_OUTPUT_ALIGNED_LOCAL (stream, name, size, align);
10190 else
10191 ASM_OUTPUT_ALIGNED_COMMON (stream, name, size, align);
10194 void
10195 avr_asm_asm_output_aligned_bss (FILE *file, tree decl, const char *name,
10196 unsigned HOST_WIDE_INT size, int align,
10197 void (*default_func)
10198 (FILE *, tree, const char *,
10199 unsigned HOST_WIDE_INT, int))
10201 rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
10202 rtx symbol;
10204 if (mem != NULL_RTX && MEM_P (mem)
10205 && SYMBOL_REF_P ((symbol = XEXP (mem, 0)))
10206 && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
10208 if (!(SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS))
10209 error_at (DECL_SOURCE_LOCATION (decl),
10210 "IO definition for %q+D needs an address", decl);
10211 avr_asm_output_aligned_decl_common (file, decl, name, size, align, false);
10213 else
10214 default_func (file, decl, name, size, align);
10218 /* Unnamed section callback for data_section
10219 to track need of __do_copy_data. */
10221 static void
10222 avr_output_data_section_asm_op (const void *data)
10224 avr_need_copy_data_p = true;
10226 /* Dispatch to default. */
10227 output_section_asm_op (data);
10231 /* Unnamed section callback for bss_section
10232 to track need of __do_clear_bss. */
10234 static void
10235 avr_output_bss_section_asm_op (const void *data)
10237 avr_need_clear_bss_p = true;
10239 /* Dispatch to default. */
10240 output_section_asm_op (data);
10244 /* Unnamed section callback for progmem*.data sections. */
10246 static void
10247 avr_output_progmem_section_asm_op (const void *data)
10249 fprintf (asm_out_file, "\t.section\t%s,\"a\",@progbits\n",
10250 (const char*) data);
10254 /* Implement `TARGET_ASM_INIT_SECTIONS'. */
10256 static void
10257 avr_asm_init_sections (void)
10259 /* Override section callbacks to keep track of `avr_need_clear_bss_p'
10260 resp. `avr_need_copy_data_p'. If flash is not mapped to RAM then
10261 we have also to track .rodata because it is located in RAM then. */
10263 #if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
10264 if (avr_arch->flash_pm_offset == 0)
10265 #endif
10266 readonly_data_section->unnamed.callback = avr_output_data_section_asm_op;
10267 data_section->unnamed.callback = avr_output_data_section_asm_op;
10268 bss_section->unnamed.callback = avr_output_bss_section_asm_op;
10272 /* Implement `TARGET_ASM_NAMED_SECTION'. */
10273 /* Track need of __do_clear_bss, __do_copy_data for named sections. */
10275 static void
10276 avr_asm_named_section (const char *name, unsigned int flags, tree decl)
10278 if (flags & AVR_SECTION_PROGMEM)
10280 addr_space_t as = (flags & AVR_SECTION_PROGMEM) / SECTION_MACH_DEP;
10281 const char *old_prefix = ".rodata";
10282 const char *new_prefix = avr_addrspace[as].section_name;
10284 if (STR_PREFIX_P (name, old_prefix))
10286 const char *sname = ACONCAT ((new_prefix,
10287 name + strlen (old_prefix), NULL));
10288 default_elf_asm_named_section (sname, flags, decl);
10289 return;
10292 default_elf_asm_named_section (new_prefix, flags, decl);
10293 return;
10296 if (!avr_need_copy_data_p)
10297 avr_need_copy_data_p = (STR_PREFIX_P (name, ".data")
10298 || STR_PREFIX_P (name, ".gnu.linkonce.d"));
10300 if (!avr_need_copy_data_p
10301 #if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
10302 && avr_arch->flash_pm_offset == 0
10303 #endif
10305 avr_need_copy_data_p = (STR_PREFIX_P (name, ".rodata")
10306 || STR_PREFIX_P (name, ".gnu.linkonce.r"));
10308 if (!avr_need_clear_bss_p)
10309 avr_need_clear_bss_p = STR_PREFIX_P (name, ".bss");
10311 default_elf_asm_named_section (name, flags, decl);
10315 /* Implement `TARGET_SECTION_TYPE_FLAGS'. */
10317 static unsigned int
10318 avr_section_type_flags (tree decl, const char *name, int reloc)
10320 unsigned int flags = default_section_type_flags (decl, name, reloc);
10322 if (STR_PREFIX_P (name, ".noinit"))
10324 if (decl && TREE_CODE (decl) == VAR_DECL
10325 && DECL_INITIAL (decl) == NULL_TREE)
10326 flags |= SECTION_BSS; /* @nobits */
10327 else
10328 warning (0, "only uninitialized variables can be placed in the "
10329 ".noinit section");
10332 if (decl && DECL_P (decl)
10333 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
10335 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
10337 /* Attribute progmem puts data in generic address space.
10338 Set section flags as if it was in __flash to get the right
10339 section prefix in the remainder. */
10341 if (ADDR_SPACE_GENERIC_P (as))
10342 as = ADDR_SPACE_FLASH;
10344 flags |= as * SECTION_MACH_DEP;
10345 flags &= ~SECTION_WRITE;
10346 flags &= ~SECTION_BSS;
10349 return flags;
10353 /* A helper for the next function. NODE is a decl that is associated with
10354 a symbol. Return TRUE if the respective object may be accessed by LDS.
10355 There might still be other reasons for why LDS is not appropriate.
10356 This function is only appropriate for AVR_TINY. */
10358 static bool
10359 avr_decl_maybe_lds_p (tree node)
10361 if (!node
10362 || TREE_CODE (node) != VAR_DECL
10363 || DECL_SECTION_NAME (node) != NULL)
10364 return false;
10366 /* Don't use LDS for objects that go to .rodata. The current default
10367 linker description file still locates .rodata in RAM, but this is not
10368 a must. A better linker script would just keep .rodata in flash and
10369 add an offset of 0x4000 to the VMA. Hence avoid LDS for such data. */
10371 if (TREE_READONLY (node))
10372 return false;
10374 // C++ requires peeling arrays.
10377 node = TREE_TYPE (node);
10378 while (ARRAY_TYPE == TREE_CODE (node));
10380 return (node != error_mark_node
10381 && !TYPE_READONLY (node));
10385 /* Implement `TARGET_ENCODE_SECTION_INFO'. */
10387 static void
10388 avr_encode_section_info (tree decl, rtx rtl, int new_decl_p)
10390 tree addr_attr = NULL_TREE;
10392 /* In avr_handle_progmem_attribute, DECL_INITIAL is not yet
10393 readily available, see PR34734. So we postpone the warning
10394 about uninitialized data in program memory section until here. */
10396 if (new_decl_p
10397 && decl && DECL_P (decl)
10398 && !DECL_EXTERNAL (decl)
10399 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
10401 if (!TREE_READONLY (decl))
10403 // This might happen with C++ if stuff needs constructing.
10404 error ("variable %q+D with dynamic initialization put "
10405 "into program memory area", decl);
10407 else if (NULL_TREE == DECL_INITIAL (decl))
10409 // Don't warn for (implicit) aliases like in PR80462.
10410 tree asmname = DECL_ASSEMBLER_NAME (decl);
10411 varpool_node *node = varpool_node::get_for_asmname (asmname);
10412 bool alias_p = node && node->alias;
10414 if (!alias_p)
10415 warning (OPT_Wuninitialized, "uninitialized variable %q+D put "
10416 "into program memory area", decl);
10420 default_encode_section_info (decl, rtl, new_decl_p);
10422 if (decl && DECL_P (decl)
10423 && TREE_CODE (decl) != FUNCTION_DECL
10424 && MEM_P (rtl)
10425 && SYMBOL_REF_P (XEXP (rtl, 0)))
10427 rtx sym = XEXP (rtl, 0);
10428 tree type = TREE_TYPE (decl);
10429 tree attr = DECL_ATTRIBUTES (decl);
10430 if (type == error_mark_node)
10431 return;
10433 addr_space_t as = TYPE_ADDR_SPACE (type);
10435 /* PSTR strings are in generic space but located in flash:
10436 patch address space. */
10438 if (!AVR_TINY && avr_progmem_p (decl, attr) == -1)
10439 as = ADDR_SPACE_FLASH;
10441 AVR_SYMBOL_SET_ADDR_SPACE (sym, as);
10443 tree io_low_attr = lookup_attribute ("io_low", attr);
10444 tree io_attr = lookup_attribute ("io", attr);
10446 if (io_low_attr
10447 && TREE_VALUE (io_low_attr) && TREE_VALUE (TREE_VALUE (io_low_attr)))
10448 addr_attr = io_attr;
10449 else if (io_attr
10450 && TREE_VALUE (io_attr) && TREE_VALUE (TREE_VALUE (io_attr)))
10451 addr_attr = io_attr;
10452 else
10453 addr_attr = lookup_attribute ("address", attr);
10454 if (io_low_attr
10455 || (io_attr && addr_attr
10456 && low_io_address_operand
10457 (GEN_INT (TREE_INT_CST_LOW
10458 (TREE_VALUE (TREE_VALUE (addr_attr)))), QImode)))
10459 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO_LOW;
10460 if (io_attr || io_low_attr)
10461 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO;
10462 /* If we have an (io) address attribute specification, but the variable
10463 is external, treat the address as only a tentative definition
10464 to be used to determine if an io port is in the lower range, but
10465 don't use the exact value for constant propagation. */
10466 if (addr_attr && !DECL_EXTERNAL (decl))
10467 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_ADDRESS;
10470 if (AVR_TINY
10471 && decl
10472 && VAR_DECL == TREE_CODE (decl)
10473 && MEM_P (rtl)
10474 && SYMBOL_REF_P (XEXP (rtl, 0)))
10476 rtx sym = XEXP (rtl, 0);
10477 bool progmem_p = avr_progmem_p (decl, DECL_ATTRIBUTES (decl)) == -1;
10479 if (progmem_p)
10481 // Tag symbols for addition of 0x4000 (avr_arch->flash_pm_offset).
10482 SYMBOL_REF_FLAGS (sym) |= AVR_SYMBOL_FLAG_TINY_PM;
10485 if (avr_decl_absdata_p (decl, DECL_ATTRIBUTES (decl))
10486 || (TARGET_ABSDATA
10487 && !progmem_p
10488 && !addr_attr
10489 && avr_decl_maybe_lds_p (decl))
10490 || (addr_attr
10491 // If addr_attr is non-null, it has an argument. Peek into it.
10492 && TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (addr_attr))) < 0xc0))
10494 // May be accessed by LDS / STS.
10495 SYMBOL_REF_FLAGS (sym) |= AVR_SYMBOL_FLAG_TINY_ABSDATA;
10498 if (progmem_p
10499 && avr_decl_absdata_p (decl, DECL_ATTRIBUTES (decl)))
10501 error ("%q+D has incompatible attributes %qs and %qs",
10502 decl, "progmem", "absdata");
10508 /* Implement `TARGET_ASM_SELECT_SECTION' */
10510 static section *
10511 avr_asm_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
10513 section * sect = default_elf_select_section (decl, reloc, align);
10515 if (decl && DECL_P (decl)
10516 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
10518 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
10520 /* __progmem__ goes in generic space but shall be allocated to
10521 .progmem.data */
10523 if (ADDR_SPACE_GENERIC_P (as))
10524 as = ADDR_SPACE_FLASH;
10526 if (sect->common.flags & SECTION_NAMED)
10528 const char * name = sect->named.name;
10529 const char * old_prefix = ".rodata";
10530 const char * new_prefix = avr_addrspace[as].section_name;
10532 if (STR_PREFIX_P (name, old_prefix))
10534 const char *sname = ACONCAT ((new_prefix,
10535 name + strlen (old_prefix), NULL));
10536 return get_section (sname,
10537 sect->common.flags & ~SECTION_DECLARED,
10538 sect->named.decl);
10542 if (!progmem_section[as])
10544 progmem_section[as]
10545 = get_unnamed_section (0, avr_output_progmem_section_asm_op,
10546 avr_addrspace[as].section_name);
10549 return progmem_section[as];
10552 return sect;
10555 /* Implement `TARGET_ASM_FILE_START'. */
10556 /* Outputs some text at the start of each assembler file. */
10558 static void
10559 avr_file_start (void)
10561 int sfr_offset = avr_arch->sfr_offset;
10563 if (avr_arch->asm_only)
10564 error ("architecture %qs supported for assembler only", avr_mmcu);
10566 default_file_start ();
10568 /* Print I/O addresses of some SFRs used with IN and OUT. */
10570 if (AVR_HAVE_SPH)
10571 fprintf (asm_out_file, "__SP_H__ = 0x%02x\n", avr_addr.sp_h - sfr_offset);
10573 fprintf (asm_out_file, "__SP_L__ = 0x%02x\n", avr_addr.sp_l - sfr_offset);
10574 fprintf (asm_out_file, "__SREG__ = 0x%02x\n", avr_addr.sreg - sfr_offset);
10575 if (AVR_HAVE_RAMPZ)
10576 fprintf (asm_out_file, "__RAMPZ__ = 0x%02x\n", avr_addr.rampz - sfr_offset);
10577 if (AVR_HAVE_RAMPY)
10578 fprintf (asm_out_file, "__RAMPY__ = 0x%02x\n", avr_addr.rampy - sfr_offset);
10579 if (AVR_HAVE_RAMPX)
10580 fprintf (asm_out_file, "__RAMPX__ = 0x%02x\n", avr_addr.rampx - sfr_offset);
10581 if (AVR_HAVE_RAMPD)
10582 fprintf (asm_out_file, "__RAMPD__ = 0x%02x\n", avr_addr.rampd - sfr_offset);
10583 if (AVR_XMEGA || AVR_TINY)
10584 fprintf (asm_out_file, "__CCP__ = 0x%02x\n", avr_addr.ccp - sfr_offset);
10585 fprintf (asm_out_file, "__tmp_reg__ = %d\n", AVR_TMP_REGNO);
10586 fprintf (asm_out_file, "__zero_reg__ = %d\n", AVR_ZERO_REGNO);
10590 /* Implement `TARGET_ASM_FILE_END'. */
10591 /* Outputs to the stdio stream FILE some
10592 appropriate text to go at the end of an assembler file. */
10594 static void
10595 avr_file_end (void)
10597 /* Output these only if there is anything in the
10598 .data* / .rodata* / .gnu.linkonce.* resp. .bss* or COMMON
10599 input section(s) - some code size can be saved by not
10600 linking in the initialization code from libgcc if resp.
10601 sections are empty, see PR18145. */
10603 if (avr_need_copy_data_p)
10604 fputs (".global __do_copy_data\n", asm_out_file);
10606 if (avr_need_clear_bss_p)
10607 fputs (".global __do_clear_bss\n", asm_out_file);
10611 /* Worker function for `ADJUST_REG_ALLOC_ORDER'. */
10612 /* Choose the order in which to allocate hard registers for
10613 pseudo-registers local to a basic block.
10615 Store the desired register order in the array `reg_alloc_order'.
10616 Element 0 should be the register to allocate first; element 1, the
10617 next register; and so on. */
10619 void
10620 avr_adjust_reg_alloc_order (void)
10622 static const int order_0[] =
10624 24, 25,
10625 18, 19, 20, 21, 22, 23,
10626 30, 31,
10627 26, 27, 28, 29,
10628 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
10629 0, 1,
10630 32, 33, 34, 35
10632 static const int tiny_order_0[] = {
10633 20, 21,
10634 22, 23,
10635 24, 25,
10636 30, 31,
10637 26, 27,
10638 28, 29,
10639 19, 18,
10640 16, 17,
10641 32, 33, 34, 35,
10642 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
10644 static const int order_1[] =
10646 18, 19, 20, 21, 22, 23, 24, 25,
10647 30, 31,
10648 26, 27, 28, 29,
10649 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
10650 0, 1,
10651 32, 33, 34, 35
10653 static const int tiny_order_1[] = {
10654 22, 23,
10655 24, 25,
10656 30, 31,
10657 26, 27,
10658 28, 29,
10659 21, 20, 19, 18,
10660 16, 17,
10661 32, 33, 34, 35,
10662 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
10664 static const int order_2[] =
10666 25, 24, 23, 22, 21, 20, 19, 18,
10667 30, 31,
10668 26, 27, 28, 29,
10669 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
10670 1, 0,
10671 32, 33, 34, 35
10674 /* Select specific register allocation order.
10675 Tiny Core (ATtiny4/5/9/10/20/40) devices have only 16 registers,
10676 so different allocation order should be used. */
10678 const int *order = (TARGET_ORDER_1 ? (AVR_TINY ? tiny_order_1 : order_1)
10679 : TARGET_ORDER_2 ? (AVR_TINY ? tiny_order_0 : order_2)
10680 : (AVR_TINY ? tiny_order_0 : order_0));
10682 for (size_t i = 0; i < ARRAY_SIZE (order_0); ++i)
10683 reg_alloc_order[i] = order[i];
10687 /* Implement `TARGET_REGISTER_MOVE_COST' */
10689 static int
10690 avr_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
10691 reg_class_t from, reg_class_t to)
10693 return (from == STACK_REG ? 6
10694 : to == STACK_REG ? 12
10695 : 2);
10699 /* Implement `TARGET_MEMORY_MOVE_COST' */
10701 static int
10702 avr_memory_move_cost (machine_mode mode,
10703 reg_class_t rclass ATTRIBUTE_UNUSED,
10704 bool in ATTRIBUTE_UNUSED)
10706 return (mode == QImode ? 2
10707 : mode == HImode ? 4
10708 : mode == SImode ? 8
10709 : mode == SFmode ? 8
10710 : 16);
10714 /* Cost for mul highpart. X is a LSHIFTRT, i.e. the outer TRUNCATE is
10715 already stripped off. */
10717 static int
10718 avr_mul_highpart_cost (rtx x, int)
10720 if (AVR_HAVE_MUL
10721 && LSHIFTRT == GET_CODE (x)
10722 && MULT == GET_CODE (XEXP (x, 0))
10723 && CONST_INT_P (XEXP (x, 1)))
10725 // This is the wider mode.
10726 machine_mode mode = GET_MODE (x);
10728 // The middle-end might still have PR81444, i.e. it is calling the cost
10729 // functions with strange modes. Fix this now by also considering
10730 // PSImode (should actually be SImode instead).
10731 if (HImode == mode || PSImode == mode || SImode == mode)
10733 return COSTS_N_INSNS (2);
10737 return 10000;
10741 /* Mutually recursive subroutine of avr_rtx_cost for calculating the
10742 cost of an RTX operand given its context. X is the rtx of the
10743 operand, MODE is its mode, and OUTER is the rtx_code of this
10744 operand's parent operator. */
10746 static int
10747 avr_operand_rtx_cost (rtx x, machine_mode mode, enum rtx_code outer,
10748 int opno, bool speed)
10750 enum rtx_code code = GET_CODE (x);
10751 int total;
10753 switch (code)
10755 case REG:
10756 case SUBREG:
10757 return 0;
10759 case CONST_INT:
10760 case CONST_FIXED:
10761 case CONST_DOUBLE:
10762 return COSTS_N_INSNS (GET_MODE_SIZE (mode));
10764 default:
10765 break;
10768 total = 0;
10769 avr_rtx_costs (x, mode, outer, opno, &total, speed);
10770 return total;
10773 /* Worker function for AVR backend's rtx_cost function.
10774 X is rtx expression whose cost is to be calculated.
10775 Return true if the complete cost has been computed.
10776 Return false if subexpressions should be scanned.
10777 In either case, *TOTAL contains the cost result. */
10779 static bool
10780 avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
10781 int opno ATTRIBUTE_UNUSED, int *total, bool speed)
10783 enum rtx_code code = GET_CODE (x);
10784 HOST_WIDE_INT val;
10786 switch (code)
10788 case CONST_INT:
10789 case CONST_FIXED:
10790 case CONST_DOUBLE:
10791 case SYMBOL_REF:
10792 case CONST:
10793 case LABEL_REF:
10794 /* Immediate constants are as cheap as registers. */
10795 *total = 0;
10796 return true;
10798 case MEM:
10799 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10800 return true;
10802 case NEG:
10803 switch (mode)
10805 case E_QImode:
10806 case E_SFmode:
10807 *total = COSTS_N_INSNS (1);
10808 break;
10810 case E_HImode:
10811 case E_PSImode:
10812 case E_SImode:
10813 *total = COSTS_N_INSNS (2 * GET_MODE_SIZE (mode) - 1);
10814 break;
10816 default:
10817 return false;
10819 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10820 return true;
10822 case ABS:
10823 switch (mode)
10825 case E_QImode:
10826 case E_SFmode:
10827 *total = COSTS_N_INSNS (1);
10828 break;
10830 default:
10831 return false;
10833 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10834 return true;
10836 case NOT:
10837 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10838 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10839 return true;
10841 case ZERO_EXTEND:
10842 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
10843 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
10844 *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
10845 code, 0, speed);
10846 return true;
10848 case SIGN_EXTEND:
10849 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
10850 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
10851 *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
10852 code, 0, speed);
10853 return true;
10855 case PLUS:
10856 switch (mode)
10858 case E_QImode:
10859 if (AVR_HAVE_MUL
10860 && MULT == GET_CODE (XEXP (x, 0))
10861 && register_operand (XEXP (x, 1), QImode))
10863 /* multiply-add */
10864 *total = COSTS_N_INSNS (speed ? 4 : 3);
10865 /* multiply-add with constant: will be split and load constant. */
10866 if (CONST_INT_P (XEXP (XEXP (x, 0), 1)))
10867 *total = COSTS_N_INSNS (1) + *total;
10868 return true;
10870 *total = COSTS_N_INSNS (1);
10871 if (!CONST_INT_P (XEXP (x, 1)))
10872 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10873 break;
10875 case E_HImode:
10876 if (AVR_HAVE_MUL
10877 && (MULT == GET_CODE (XEXP (x, 0))
10878 || ASHIFT == GET_CODE (XEXP (x, 0)))
10879 && register_operand (XEXP (x, 1), HImode)
10880 && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))
10881 || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))))
10883 /* multiply-add */
10884 *total = COSTS_N_INSNS (speed ? 5 : 4);
10885 /* multiply-add with constant: will be split and load constant. */
10886 if (CONST_INT_P (XEXP (XEXP (x, 0), 1)))
10887 *total = COSTS_N_INSNS (1) + *total;
10888 return true;
10890 if (!CONST_INT_P (XEXP (x, 1)))
10892 *total = COSTS_N_INSNS (2);
10893 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10894 speed);
10896 else if (IN_RANGE (INTVAL (XEXP (x, 1)), -63, 63))
10897 *total = COSTS_N_INSNS (1);
10898 else
10899 *total = COSTS_N_INSNS (2);
10900 break;
10902 case E_PSImode:
10903 if (!CONST_INT_P (XEXP (x, 1)))
10905 *total = COSTS_N_INSNS (3);
10906 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10907 speed);
10909 else if (IN_RANGE (INTVAL (XEXP (x, 1)), -63, 63))
10910 *total = COSTS_N_INSNS (2);
10911 else
10912 *total = COSTS_N_INSNS (3);
10913 break;
10915 case E_SImode:
10916 if (!CONST_INT_P (XEXP (x, 1)))
10918 *total = COSTS_N_INSNS (4);
10919 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10920 speed);
10922 else if (IN_RANGE (INTVAL (XEXP (x, 1)), -63, 63))
10923 *total = COSTS_N_INSNS (1);
10924 else
10925 *total = COSTS_N_INSNS (4);
10926 break;
10928 default:
10929 return false;
10931 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10932 return true;
10934 case MINUS:
10935 if (AVR_HAVE_MUL
10936 && QImode == mode
10937 && register_operand (XEXP (x, 0), QImode)
10938 && MULT == GET_CODE (XEXP (x, 1)))
10940 /* multiply-sub */
10941 *total = COSTS_N_INSNS (speed ? 4 : 3);
10942 /* multiply-sub with constant: will be split and load constant. */
10943 if (CONST_INT_P (XEXP (XEXP (x, 1), 1)))
10944 *total = COSTS_N_INSNS (1) + *total;
10945 return true;
10947 if (AVR_HAVE_MUL
10948 && HImode == mode
10949 && register_operand (XEXP (x, 0), HImode)
10950 && (MULT == GET_CODE (XEXP (x, 1))
10951 || ASHIFT == GET_CODE (XEXP (x, 1)))
10952 && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))
10953 || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))))
10955 /* multiply-sub */
10956 *total = COSTS_N_INSNS (speed ? 5 : 4);
10957 /* multiply-sub with constant: will be split and load constant. */
10958 if (CONST_INT_P (XEXP (XEXP (x, 1), 1)))
10959 *total = COSTS_N_INSNS (1) + *total;
10960 return true;
10962 /* FALLTHRU */
10963 case AND:
10964 case IOR:
10965 if (IOR == code
10966 && HImode == mode
10967 && ASHIFT == GET_CODE (XEXP (x, 0)))
10969 *total = COSTS_N_INSNS (2);
10970 // Just a rough estimate. If we see no sign- or zero-extend,
10971 // then increase the cost a little bit.
10972 if (REG_P (XEXP (XEXP (x, 0), 0)))
10973 *total += COSTS_N_INSNS (1);
10974 if (REG_P (XEXP (x, 1)))
10975 *total += COSTS_N_INSNS (1);
10976 return true;
10978 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10979 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10980 if (!CONST_INT_P (XEXP (x, 1)))
10981 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10982 return true;
10984 case XOR:
10985 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10986 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10987 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10988 return true;
10990 case MULT:
10991 switch (mode)
10993 case E_QImode:
10994 if (AVR_HAVE_MUL)
10995 *total = COSTS_N_INSNS (!speed ? 3 : 4);
10996 else if (!speed)
10997 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
10998 else
10999 return false;
11000 break;
11002 case E_HImode:
11003 if (AVR_HAVE_MUL)
11005 rtx op0 = XEXP (x, 0);
11006 rtx op1 = XEXP (x, 1);
11007 enum rtx_code code0 = GET_CODE (op0);
11008 enum rtx_code code1 = GET_CODE (op1);
11009 bool ex0 = SIGN_EXTEND == code0 || ZERO_EXTEND == code0;
11010 bool ex1 = SIGN_EXTEND == code1 || ZERO_EXTEND == code1;
11012 if (ex0
11013 && (u8_operand (op1, HImode)
11014 || s8_operand (op1, HImode)))
11016 *total = COSTS_N_INSNS (!speed ? 4 : 6);
11017 return true;
11019 if (ex0
11020 && register_operand (op1, HImode))
11022 *total = COSTS_N_INSNS (!speed ? 5 : 8);
11023 return true;
11025 else if (ex0 || ex1)
11027 *total = COSTS_N_INSNS (!speed ? 3 : 5);
11028 return true;
11030 else if (register_operand (op0, HImode)
11031 && (u8_operand (op1, HImode)
11032 || s8_operand (op1, HImode)))
11034 *total = COSTS_N_INSNS (!speed ? 6 : 9);
11035 return true;
11037 else
11038 *total = COSTS_N_INSNS (!speed ? 7 : 10);
11040 else if (!speed)
11041 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
11042 else
11043 return false;
11044 break;
11046 case E_PSImode:
11047 if (!speed)
11048 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
11049 else
11050 *total = 10;
11051 break;
11053 case E_SImode:
11054 case E_DImode:
11055 if (AVR_HAVE_MUL)
11057 if (!speed)
11059 /* Add some additional costs besides CALL like moves etc. */
11061 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
11063 else
11065 /* Just a rough estimate. Even with -O2 we don't want bulky
11066 code expanded inline. */
11068 *total = COSTS_N_INSNS (25);
11071 else
11073 if (speed)
11074 *total = COSTS_N_INSNS (300);
11075 else
11076 /* Add some additional costs besides CALL like moves etc. */
11077 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
11080 if (mode == DImode)
11081 *total *= 2;
11083 return true;
11085 default:
11086 return false;
11088 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11089 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
11090 return true;
11092 case DIV:
11093 case MOD:
11094 case UDIV:
11095 case UMOD:
11096 if (!speed)
11097 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
11098 else
11099 *total = COSTS_N_INSNS (15 * GET_MODE_SIZE (mode));
11100 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11101 /* For div/mod with const-int divisor we have at least the cost of
11102 loading the divisor. */
11103 if (CONST_INT_P (XEXP (x, 1)))
11104 *total += COSTS_N_INSNS (GET_MODE_SIZE (mode));
11105 /* Add some overall penaly for clobbering and moving around registers */
11106 *total += COSTS_N_INSNS (2);
11107 return true;
11109 case ROTATE:
11110 switch (mode)
11112 case E_QImode:
11113 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 4)
11114 *total = COSTS_N_INSNS (1);
11116 break;
11118 case E_HImode:
11119 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 8)
11120 *total = COSTS_N_INSNS (3);
11122 break;
11124 case E_SImode:
11125 if (CONST_INT_P (XEXP (x, 1)))
11126 switch (INTVAL (XEXP (x, 1)))
11128 case 8:
11129 case 24:
11130 *total = COSTS_N_INSNS (5);
11131 break;
11132 case 16:
11133 *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 6);
11134 break;
11136 break;
11138 default:
11139 return false;
11141 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11142 return true;
11144 case ASHIFT:
11145 switch (mode)
11147 case E_QImode:
11148 if (!CONST_INT_P (XEXP (x, 1)))
11150 *total = COSTS_N_INSNS (!speed ? 4 : 17);
11151 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11152 speed);
11154 else
11156 val = INTVAL (XEXP (x, 1));
11157 if (val == 7)
11158 *total = COSTS_N_INSNS (3);
11159 else if (val >= 0 && val <= 7)
11160 *total = COSTS_N_INSNS (val);
11161 else
11162 *total = COSTS_N_INSNS (1);
11164 break;
11166 case E_HImode:
11167 if (AVR_HAVE_MUL)
11169 if (const_2_to_7_operand (XEXP (x, 1), HImode)
11170 && (SIGN_EXTEND == GET_CODE (XEXP (x, 0))
11171 || ZERO_EXTEND == GET_CODE (XEXP (x, 0))))
11173 *total = COSTS_N_INSNS (!speed ? 4 : 6);
11174 return true;
11178 if (const1_rtx == (XEXP (x, 1))
11179 && SIGN_EXTEND == GET_CODE (XEXP (x, 0)))
11181 *total = COSTS_N_INSNS (2);
11182 return true;
11185 if (!CONST_INT_P (XEXP (x, 1)))
11187 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11188 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11189 speed);
11191 else
11192 switch (INTVAL (XEXP (x, 1)))
11194 case 0:
11195 *total = 0;
11196 break;
11197 case 1:
11198 case 8:
11199 *total = COSTS_N_INSNS (2);
11200 break;
11201 case 9:
11202 *total = COSTS_N_INSNS (3);
11203 break;
11204 case 2:
11205 case 3:
11206 case 10:
11207 case 15:
11208 *total = COSTS_N_INSNS (4);
11209 break;
11210 case 7:
11211 case 11:
11212 case 12:
11213 *total = COSTS_N_INSNS (5);
11214 break;
11215 case 4:
11216 *total = COSTS_N_INSNS (!speed ? 5 : 8);
11217 break;
11218 case 6:
11219 *total = COSTS_N_INSNS (!speed ? 5 : 9);
11220 break;
11221 case 5:
11222 *total = COSTS_N_INSNS (!speed ? 5 : 10);
11223 break;
11224 default:
11225 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11226 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11227 speed);
11229 break;
11231 case E_PSImode:
11232 if (!CONST_INT_P (XEXP (x, 1)))
11234 *total = COSTS_N_INSNS (!speed ? 6 : 73);
11236 else
11237 switch (INTVAL (XEXP (x, 1)))
11239 case 0:
11240 *total = 0;
11241 break;
11242 case 1:
11243 case 8:
11244 case 16:
11245 *total = COSTS_N_INSNS (3);
11246 break;
11247 case 23:
11248 *total = COSTS_N_INSNS (5);
11249 break;
11250 default:
11251 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
11252 break;
11254 break;
11256 case E_SImode:
11257 if (!CONST_INT_P (XEXP (x, 1)))
11259 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11260 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11261 speed);
11263 else
11264 switch (INTVAL (XEXP (x, 1)))
11266 case 0:
11267 *total = 0;
11268 break;
11269 case 24:
11270 *total = COSTS_N_INSNS (3);
11271 break;
11272 case 1:
11273 case 8:
11274 case 16:
11275 *total = COSTS_N_INSNS (4);
11276 break;
11277 case 31:
11278 *total = COSTS_N_INSNS (6);
11279 break;
11280 case 2:
11281 *total = COSTS_N_INSNS (!speed ? 7 : 8);
11282 break;
11283 default:
11284 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11285 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11286 speed);
11288 break;
11290 default:
11291 return false;
11293 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11294 return true;
11296 case ASHIFTRT:
11297 switch (mode)
11299 case E_QImode:
11300 if (!CONST_INT_P (XEXP (x, 1)))
11302 *total = COSTS_N_INSNS (!speed ? 4 : 17);
11303 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11304 speed);
11306 else
11308 val = INTVAL (XEXP (x, 1));
11309 if (val == 6)
11310 *total = COSTS_N_INSNS (4);
11311 else if (val == 7)
11312 *total = COSTS_N_INSNS (2);
11313 else if (val >= 0 && val <= 7)
11314 *total = COSTS_N_INSNS (val);
11315 else
11316 *total = COSTS_N_INSNS (1);
11318 break;
11320 case E_HImode:
11321 if (!CONST_INT_P (XEXP (x, 1)))
11323 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11324 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11325 speed);
11327 else
11328 switch (INTVAL (XEXP (x, 1)))
11330 case 0:
11331 *total = 0;
11332 break;
11333 case 1:
11334 *total = COSTS_N_INSNS (2);
11335 break;
11336 case 15:
11337 *total = COSTS_N_INSNS (3);
11338 break;
11339 case 2:
11340 case 7:
11341 case 8:
11342 case 9:
11343 *total = COSTS_N_INSNS (4);
11344 break;
11345 case 10:
11346 case 14:
11347 *total = COSTS_N_INSNS (5);
11348 break;
11349 case 11:
11350 *total = COSTS_N_INSNS (!speed ? 5 : 6);
11351 break;
11352 case 12:
11353 *total = COSTS_N_INSNS (!speed ? 5 : 7);
11354 break;
11355 case 6:
11356 case 13:
11357 *total = COSTS_N_INSNS (!speed ? 5 : 8);
11358 break;
11359 default:
11360 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11361 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11362 speed);
11364 break;
11366 case E_PSImode:
11367 if (!CONST_INT_P (XEXP (x, 1)))
11369 *total = COSTS_N_INSNS (!speed ? 6 : 73);
11371 else
11372 switch (INTVAL (XEXP (x, 1)))
11374 case 0:
11375 *total = 0;
11376 break;
11377 case 1:
11378 *total = COSTS_N_INSNS (3);
11379 break;
11380 case 16:
11381 case 8:
11382 *total = COSTS_N_INSNS (5);
11383 break;
11384 case 23:
11385 *total = COSTS_N_INSNS (4);
11386 break;
11387 default:
11388 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
11389 break;
11391 break;
11393 case E_SImode:
11394 if (!CONST_INT_P (XEXP (x, 1)))
11396 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11397 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11398 speed);
11400 else
11401 switch (INTVAL (XEXP (x, 1)))
11403 case 0:
11404 *total = 0;
11405 break;
11406 case 1:
11407 *total = COSTS_N_INSNS (4);
11408 break;
11409 case 8:
11410 case 16:
11411 case 24:
11412 *total = COSTS_N_INSNS (6);
11413 break;
11414 case 2:
11415 *total = COSTS_N_INSNS (!speed ? 7 : 8);
11416 break;
11417 case 31:
11418 *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 5);
11419 break;
11420 default:
11421 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11422 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11423 speed);
11425 break;
11427 default:
11428 return false;
11430 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11431 return true;
11433 case LSHIFTRT:
11434 if (outer_code == TRUNCATE)
11436 *total = avr_mul_highpart_cost (x, speed);
11437 return true;
11440 switch (mode)
11442 case E_QImode:
11443 if (!CONST_INT_P (XEXP (x, 1)))
11445 *total = COSTS_N_INSNS (!speed ? 4 : 17);
11446 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11447 speed);
11449 else
11451 val = INTVAL (XEXP (x, 1));
11452 if (val == 7)
11453 *total = COSTS_N_INSNS (3);
11454 else if (val >= 0 && val <= 7)
11455 *total = COSTS_N_INSNS (val);
11456 else
11457 *total = COSTS_N_INSNS (1);
11459 break;
11461 case E_HImode:
11462 if (!CONST_INT_P (XEXP (x, 1)))
11464 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11465 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11466 speed);
11468 else
11469 switch (INTVAL (XEXP (x, 1)))
11471 case 0:
11472 *total = 0;
11473 break;
11474 case 1:
11475 case 8:
11476 *total = COSTS_N_INSNS (2);
11477 break;
11478 case 9:
11479 *total = COSTS_N_INSNS (3);
11480 break;
11481 case 2:
11482 case 10:
11483 case 15:
11484 *total = COSTS_N_INSNS (4);
11485 break;
11486 case 7:
11487 case 11:
11488 *total = COSTS_N_INSNS (5);
11489 break;
11490 case 3:
11491 case 12:
11492 case 13:
11493 case 14:
11494 *total = COSTS_N_INSNS (!speed ? 5 : 6);
11495 break;
11496 case 4:
11497 *total = COSTS_N_INSNS (!speed ? 5 : 7);
11498 break;
11499 case 5:
11500 case 6:
11501 *total = COSTS_N_INSNS (!speed ? 5 : 9);
11502 break;
11503 default:
11504 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11505 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11506 speed);
11508 break;
11510 case E_PSImode:
11511 if (!CONST_INT_P (XEXP (x, 1)))
11513 *total = COSTS_N_INSNS (!speed ? 6 : 73);
11515 else
11516 switch (INTVAL (XEXP (x, 1)))
11518 case 0:
11519 *total = 0;
11520 break;
11521 case 1:
11522 case 8:
11523 case 16:
11524 *total = COSTS_N_INSNS (3);
11525 break;
11526 case 23:
11527 *total = COSTS_N_INSNS (5);
11528 break;
11529 default:
11530 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
11531 break;
11533 break;
11535 case E_SImode:
11536 if (!CONST_INT_P (XEXP (x, 1)))
11538 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11539 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11540 speed);
11542 else
11543 switch (INTVAL (XEXP (x, 1)))
11545 case 0:
11546 *total = 0;
11547 break;
11548 case 1:
11549 *total = COSTS_N_INSNS (4);
11550 break;
11551 case 2:
11552 *total = COSTS_N_INSNS (!speed ? 7 : 8);
11553 break;
11554 case 8:
11555 case 16:
11556 case 24:
11557 *total = COSTS_N_INSNS (4);
11558 break;
11559 case 31:
11560 *total = COSTS_N_INSNS (6);
11561 break;
11562 default:
11563 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11564 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11565 speed);
11567 break;
11569 default:
11570 return false;
11572 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11573 return true;
11575 case COMPARE:
11576 switch (GET_MODE (XEXP (x, 0)))
11578 case E_QImode:
11579 *total = COSTS_N_INSNS (1);
11580 if (!CONST_INT_P (XEXP (x, 1)))
11581 *total += avr_operand_rtx_cost (XEXP (x, 1), QImode, code,
11582 1, speed);
11583 break;
11585 case E_HImode:
11586 *total = COSTS_N_INSNS (2);
11587 if (!CONST_INT_P (XEXP (x, 1)))
11588 *total += avr_operand_rtx_cost (XEXP (x, 1), HImode, code,
11589 1, speed);
11590 else if (INTVAL (XEXP (x, 1)) != 0)
11591 *total += COSTS_N_INSNS (1);
11592 break;
11594 case E_PSImode:
11595 *total = COSTS_N_INSNS (3);
11596 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) != 0)
11597 *total += COSTS_N_INSNS (2);
11598 break;
11600 case E_SImode:
11601 *total = COSTS_N_INSNS (4);
11602 if (!CONST_INT_P (XEXP (x, 1)))
11603 *total += avr_operand_rtx_cost (XEXP (x, 1), SImode, code,
11604 1, speed);
11605 else if (INTVAL (XEXP (x, 1)) != 0)
11606 *total += COSTS_N_INSNS (3);
11607 break;
11609 default:
11610 return false;
11612 *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
11613 code, 0, speed);
11614 return true;
11616 case TRUNCATE:
11617 if (LSHIFTRT == GET_CODE (XEXP (x, 0)))
11619 *total = avr_mul_highpart_cost (XEXP (x, 0), speed);
11620 return true;
11622 break;
11624 default:
11625 break;
11627 return false;
11631 /* Implement `TARGET_RTX_COSTS'. */
11633 static bool
11634 avr_rtx_costs (rtx x, machine_mode mode, int outer_code,
11635 int opno, int *total, bool speed)
11637 bool done = avr_rtx_costs_1 (x, mode, outer_code, opno, total, speed);
11639 if (avr_log.rtx_costs)
11641 avr_edump ("\n%?=%b (%s) total=%d, outer=%C:\n%r\n",
11642 done, speed ? "speed" : "size", *total, outer_code, x);
11645 return done;
11649 /* Implement `TARGET_ADDRESS_COST'. */
11651 static int
11652 avr_address_cost (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
11653 addr_space_t as ATTRIBUTE_UNUSED,
11654 bool speed ATTRIBUTE_UNUSED)
11656 int cost = 4;
11658 if (GET_CODE (x) == PLUS
11659 && CONST_INT_P (XEXP (x, 1))
11660 && (REG_P (XEXP (x, 0))
11661 || SUBREG_P (XEXP (x, 0))))
11663 if (INTVAL (XEXP (x, 1)) > MAX_LD_OFFSET(mode))
11664 cost = 18;
11666 else if (CONSTANT_ADDRESS_P (x))
11668 if (io_address_operand (x, QImode))
11669 cost = 2;
11671 if (AVR_TINY
11672 && avr_address_tiny_absdata_p (x, QImode))
11673 cost = 2;
11676 if (avr_log.address_cost)
11677 avr_edump ("\n%?: %d = %r\n", cost, x);
11679 return cost;
11682 /* Test for extra memory constraint 'Q'.
11683 It's a memory address based on Y or Z pointer with valid displacement. */
11686 extra_constraint_Q (rtx x)
11688 int ok = 0;
11689 rtx plus = XEXP (x, 0);
11691 if (GET_CODE (plus) == PLUS
11692 && REG_P (XEXP (plus, 0))
11693 && CONST_INT_P (XEXP (plus, 1))
11694 && (INTVAL (XEXP (plus, 1))
11695 <= MAX_LD_OFFSET (GET_MODE (x))))
11697 rtx xx = XEXP (plus, 0);
11698 int regno = REGNO (xx);
11700 ok = (/* allocate pseudos */
11701 regno >= FIRST_PSEUDO_REGISTER
11702 /* strictly check */
11703 || regno == REG_Z || regno == REG_Y
11704 /* XXX frame & arg pointer checks */
11705 || xx == frame_pointer_rtx
11706 || xx == arg_pointer_rtx);
11708 if (avr_log.constraints)
11709 avr_edump ("\n%?=%d reload_completed=%d reload_in_progress=%d\n %r\n",
11710 ok, reload_completed, reload_in_progress, x);
11713 return ok;
11716 /* Convert condition code CONDITION to the valid AVR condition code. */
11718 RTX_CODE
11719 avr_normalize_condition (RTX_CODE condition)
11721 switch (condition)
11723 case GT:
11724 return GE;
11725 case GTU:
11726 return GEU;
11727 case LE:
11728 return LT;
11729 case LEU:
11730 return LTU;
11731 default:
11732 gcc_unreachable ();
11736 /* Helper function for `avr_reorg'. */
11738 static rtx
11739 avr_compare_pattern (rtx_insn *insn)
11741 rtx pattern = single_set (insn);
11743 if (pattern
11744 && NONJUMP_INSN_P (insn)
11745 && SET_DEST (pattern) == cc0_rtx
11746 && GET_CODE (SET_SRC (pattern)) == COMPARE)
11748 machine_mode mode0 = GET_MODE (XEXP (SET_SRC (pattern), 0));
11749 machine_mode mode1 = GET_MODE (XEXP (SET_SRC (pattern), 1));
11751 /* The 64-bit comparisons have fixed operands ACC_A and ACC_B.
11752 They must not be swapped, thus skip them. */
11754 if ((mode0 == VOIDmode || GET_MODE_SIZE (mode0) <= 4)
11755 && (mode1 == VOIDmode || GET_MODE_SIZE (mode1) <= 4))
11756 return pattern;
11759 return NULL_RTX;
11762 /* Helper function for `avr_reorg'. */
11764 /* Expansion of switch/case decision trees leads to code like
11766 cc0 = compare (Reg, Num)
11767 if (cc0 == 0)
11768 goto L1
11770 cc0 = compare (Reg, Num)
11771 if (cc0 > 0)
11772 goto L2
11774 The second comparison is superfluous and can be deleted.
11775 The second jump condition can be transformed from a
11776 "difficult" one to a "simple" one because "cc0 > 0" and
11777 "cc0 >= 0" will have the same effect here.
11779 This function relies on the way switch/case is being expaned
11780 as binary decision tree. For example code see PR 49903.
11782 Return TRUE if optimization performed.
11783 Return FALSE if nothing changed.
11785 INSN1 is a comparison, i.e. avr_compare_pattern != 0.
11787 We don't want to do this in text peephole because it is
11788 tedious to work out jump offsets there and the second comparison
11789 might have been transormed by `avr_reorg'.
11791 RTL peephole won't do because peephole2 does not scan across
11792 basic blocks. */
11794 static bool
11795 avr_reorg_remove_redundant_compare (rtx_insn *insn1)
11797 rtx comp1, ifelse1, xcond1;
11798 rtx_insn *branch1;
11799 rtx comp2, ifelse2, xcond2;
11800 rtx_insn *branch2, *insn2;
11801 enum rtx_code code;
11802 rtx_insn *jump;
11803 rtx target, cond;
11805 /* Look out for: compare1 - branch1 - compare2 - branch2 */
11807 branch1 = next_nonnote_nondebug_insn (insn1);
11808 if (!branch1 || !JUMP_P (branch1))
11809 return false;
11811 insn2 = next_nonnote_nondebug_insn (branch1);
11812 if (!insn2 || !avr_compare_pattern (insn2))
11813 return false;
11815 branch2 = next_nonnote_nondebug_insn (insn2);
11816 if (!branch2 || !JUMP_P (branch2))
11817 return false;
11819 comp1 = avr_compare_pattern (insn1);
11820 comp2 = avr_compare_pattern (insn2);
11821 xcond1 = single_set (branch1);
11822 xcond2 = single_set (branch2);
11824 if (!comp1 || !comp2
11825 || !rtx_equal_p (comp1, comp2)
11826 || !xcond1 || SET_DEST (xcond1) != pc_rtx
11827 || !xcond2 || SET_DEST (xcond2) != pc_rtx
11828 || IF_THEN_ELSE != GET_CODE (SET_SRC (xcond1))
11829 || IF_THEN_ELSE != GET_CODE (SET_SRC (xcond2)))
11831 return false;
11834 comp1 = SET_SRC (comp1);
11835 ifelse1 = SET_SRC (xcond1);
11836 ifelse2 = SET_SRC (xcond2);
11838 /* comp<n> is COMPARE now and ifelse<n> is IF_THEN_ELSE. */
11840 if (EQ != GET_CODE (XEXP (ifelse1, 0))
11841 || !REG_P (XEXP (comp1, 0))
11842 || !CONST_INT_P (XEXP (comp1, 1))
11843 || XEXP (ifelse1, 2) != pc_rtx
11844 || XEXP (ifelse2, 2) != pc_rtx
11845 || LABEL_REF != GET_CODE (XEXP (ifelse1, 1))
11846 || LABEL_REF != GET_CODE (XEXP (ifelse2, 1))
11847 || !COMPARISON_P (XEXP (ifelse2, 0))
11848 || cc0_rtx != XEXP (XEXP (ifelse1, 0), 0)
11849 || cc0_rtx != XEXP (XEXP (ifelse2, 0), 0)
11850 || const0_rtx != XEXP (XEXP (ifelse1, 0), 1)
11851 || const0_rtx != XEXP (XEXP (ifelse2, 0), 1))
11853 return false;
11856 /* We filtered the insn sequence to look like
11858 (set (cc0)
11859 (compare (reg:M N)
11860 (const_int VAL)))
11861 (set (pc)
11862 (if_then_else (eq (cc0)
11863 (const_int 0))
11864 (label_ref L1)
11865 (pc)))
11867 (set (cc0)
11868 (compare (reg:M N)
11869 (const_int VAL)))
11870 (set (pc)
11871 (if_then_else (CODE (cc0)
11872 (const_int 0))
11873 (label_ref L2)
11874 (pc)))
11877 code = GET_CODE (XEXP (ifelse2, 0));
11879 /* Map GT/GTU to GE/GEU which is easier for AVR.
11880 The first two instructions compare/branch on EQ
11881 so we may replace the difficult
11883 if (x == VAL) goto L1;
11884 if (x > VAL) goto L2;
11886 with easy
11888 if (x == VAL) goto L1;
11889 if (x >= VAL) goto L2;
11891 Similarly, replace LE/LEU by LT/LTU. */
11893 switch (code)
11895 case EQ:
11896 case LT: case LTU:
11897 case GE: case GEU:
11898 break;
11900 case LE: case LEU:
11901 case GT: case GTU:
11902 code = avr_normalize_condition (code);
11903 break;
11905 default:
11906 return false;
11909 /* Wrap the branches into UNSPECs so they won't be changed or
11910 optimized in the remainder. */
11912 target = XEXP (XEXP (ifelse1, 1), 0);
11913 cond = XEXP (ifelse1, 0);
11914 jump = emit_jump_insn_after (gen_branch_unspec (target, cond), insn1);
11916 JUMP_LABEL (jump) = JUMP_LABEL (branch1);
11918 target = XEXP (XEXP (ifelse2, 1), 0);
11919 cond = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
11920 jump = emit_jump_insn_after (gen_branch_unspec (target, cond), insn2);
11922 JUMP_LABEL (jump) = JUMP_LABEL (branch2);
11924 /* The comparisons in insn1 and insn2 are exactly the same;
11925 insn2 is superfluous so delete it. */
11927 delete_insn (insn2);
11928 delete_insn (branch1);
11929 delete_insn (branch2);
11931 return true;
11935 /* Implement `TARGET_MACHINE_DEPENDENT_REORG'. */
11936 /* Optimize conditional jumps. */
11938 static void
11939 avr_reorg (void)
11941 rtx_insn *insn = get_insns();
11943 for (insn = next_real_insn (insn); insn; insn = next_real_insn (insn))
11945 rtx pattern = avr_compare_pattern (insn);
11947 if (!pattern)
11948 continue;
11950 if (optimize
11951 && avr_reorg_remove_redundant_compare (insn))
11953 continue;
11956 if (compare_diff_p (insn))
11958 /* Now we work under compare insn with difficult branch. */
11960 rtx_insn *next = next_real_insn (insn);
11961 rtx pat = PATTERN (next);
11963 pattern = SET_SRC (pattern);
11965 if (true_regnum (XEXP (pattern, 0)) >= 0
11966 && true_regnum (XEXP (pattern, 1)) >= 0)
11968 rtx x = XEXP (pattern, 0);
11969 rtx src = SET_SRC (pat);
11970 rtx t = XEXP (src, 0);
11971 PUT_CODE (t, swap_condition (GET_CODE (t)));
11972 XEXP (pattern, 0) = XEXP (pattern, 1);
11973 XEXP (pattern, 1) = x;
11974 INSN_CODE (next) = -1;
11976 else if (true_regnum (XEXP (pattern, 0)) >= 0
11977 && XEXP (pattern, 1) == const0_rtx)
11979 /* This is a tst insn, we can reverse it. */
11980 rtx src = SET_SRC (pat);
11981 rtx t = XEXP (src, 0);
11983 PUT_CODE (t, swap_condition (GET_CODE (t)));
11984 XEXP (pattern, 1) = XEXP (pattern, 0);
11985 XEXP (pattern, 0) = const0_rtx;
11986 INSN_CODE (next) = -1;
11987 INSN_CODE (insn) = -1;
11989 else if (true_regnum (XEXP (pattern, 0)) >= 0
11990 && CONST_INT_P (XEXP (pattern, 1)))
11992 rtx x = XEXP (pattern, 1);
11993 rtx src = SET_SRC (pat);
11994 rtx t = XEXP (src, 0);
11995 machine_mode mode = GET_MODE (XEXP (pattern, 0));
11997 if (avr_simplify_comparison_p (mode, GET_CODE (t), x))
11999 XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
12000 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
12001 INSN_CODE (next) = -1;
12002 INSN_CODE (insn) = -1;
12009 /* Returns register number for function return value.*/
12011 static inline unsigned int
12012 avr_ret_register (void)
12014 return 24;
12018 /* Implement `TARGET_FUNCTION_VALUE_REGNO_P'. */
12020 static bool
12021 avr_function_value_regno_p (const unsigned int regno)
12023 return (regno == avr_ret_register ());
12027 /* Implement `TARGET_LIBCALL_VALUE'. */
12028 /* Create an RTX representing the place where a
12029 library function returns a value of mode MODE. */
12031 static rtx
12032 avr_libcall_value (machine_mode mode,
12033 const_rtx func ATTRIBUTE_UNUSED)
12035 int offs = GET_MODE_SIZE (mode);
12037 if (offs <= 4)
12038 offs = (offs + 1) & ~1;
12040 return gen_rtx_REG (mode, avr_ret_register () + 2 - offs);
12044 /* Implement `TARGET_FUNCTION_VALUE'. */
12045 /* Create an RTX representing the place where a
12046 function returns a value of data type VALTYPE. */
12048 static rtx
12049 avr_function_value (const_tree type,
12050 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
12051 bool outgoing ATTRIBUTE_UNUSED)
12053 unsigned int offs;
12055 if (TYPE_MODE (type) != BLKmode)
12056 return avr_libcall_value (TYPE_MODE (type), NULL_RTX);
12058 offs = int_size_in_bytes (type);
12059 if (offs < 2)
12060 offs = 2;
12061 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
12062 offs = GET_MODE_SIZE (SImode);
12063 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
12064 offs = GET_MODE_SIZE (DImode);
12066 return gen_rtx_REG (BLKmode, avr_ret_register () + 2 - offs);
12070 test_hard_reg_class (enum reg_class rclass, rtx x)
12072 int regno = true_regnum (x);
12073 if (regno < 0)
12074 return 0;
12076 if (TEST_HARD_REG_CLASS (rclass, regno))
12077 return 1;
12079 return 0;
12083 /* Helper for jump_over_one_insn_p: Test if INSN is a 2-word instruction
12084 and thus is suitable to be skipped by CPSE, SBRC, etc. */
12086 static bool
12087 avr_2word_insn_p (rtx_insn *insn)
12089 if (TARGET_SKIP_BUG || !insn || get_attr_length (insn) != 2)
12091 return false;
12094 switch (INSN_CODE (insn))
12096 default:
12097 return false;
12099 case CODE_FOR_movqi_insn:
12100 case CODE_FOR_movuqq_insn:
12101 case CODE_FOR_movqq_insn:
12103 rtx set = single_set (insn);
12104 rtx src = SET_SRC (set);
12105 rtx dest = SET_DEST (set);
12107 /* Factor out LDS and STS from movqi_insn. */
12109 if (MEM_P (dest)
12110 && (REG_P (src) || src == CONST0_RTX (GET_MODE (dest))))
12112 return CONSTANT_ADDRESS_P (XEXP (dest, 0));
12114 else if (REG_P (dest)
12115 && MEM_P (src))
12117 return CONSTANT_ADDRESS_P (XEXP (src, 0));
12120 return false;
12123 case CODE_FOR_call_insn:
12124 case CODE_FOR_call_value_insn:
12125 return true;
12131 jump_over_one_insn_p (rtx_insn *insn, rtx dest)
12133 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
12134 ? XEXP (dest, 0)
12135 : dest);
12136 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
12137 int dest_addr = INSN_ADDRESSES (uid);
12138 int jump_offset = dest_addr - jump_addr - get_attr_length (insn);
12140 return (jump_offset == 1
12141 || (jump_offset == 2
12142 && avr_2word_insn_p (next_active_insn (insn))));
12146 /* Implement TARGET_HARD_REGNO_MODE_OK. On the enhanced core, anything
12147 larger than 1 byte must start in even numbered register for "movw" to
12148 work (this way we don't have to check for odd registers everywhere). */
12150 static bool
12151 avr_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
12153 /* NOTE: 8-bit values must not be disallowed for R28 or R29.
12154 Disallowing QI et al. in these regs might lead to code like
12155 (set (subreg:QI (reg:HI 28) n) ...)
12156 which will result in wrong code because reload does not
12157 handle SUBREGs of hard regsisters like this.
12158 This could be fixed in reload. However, it appears
12159 that fixing reload is not wanted by reload people. */
12161 /* Any GENERAL_REGS register can hold 8-bit values. */
12163 if (GET_MODE_SIZE (mode) == 1)
12164 return true;
12166 /* FIXME: Ideally, the following test is not needed.
12167 However, it turned out that it can reduce the number
12168 of spill fails. AVR and it's poor endowment with
12169 address registers is extreme stress test for reload. */
12171 if (GET_MODE_SIZE (mode) >= 4
12172 && regno >= REG_X)
12173 return false;
12175 /* All modes larger than 8 bits should start in an even register. */
12177 return !(regno & 1);
12181 /* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED. */
12183 static bool
12184 avr_hard_regno_call_part_clobbered (unsigned regno, machine_mode mode)
12186 /* FIXME: This hook gets called with MODE:REGNO combinations that don't
12187 represent valid hard registers like, e.g. HI:29. Returning TRUE
12188 for such registers can lead to performance degradation as mentioned
12189 in PR53595. Thus, report invalid hard registers as FALSE. */
12191 if (!avr_hard_regno_mode_ok (regno, mode))
12192 return 0;
12194 /* Return true if any of the following boundaries is crossed:
12195 17/18 or 19/20 (if AVR_TINY), 27/28 and 29/30. */
12197 return ((regno <= LAST_CALLEE_SAVED_REG
12198 && regno + GET_MODE_SIZE (mode) > 1 + LAST_CALLEE_SAVED_REG)
12199 || (regno < REG_Y && regno + GET_MODE_SIZE (mode) > REG_Y)
12200 || (regno < REG_Z && regno + GET_MODE_SIZE (mode) > REG_Z));
12204 /* Implement `MODE_CODE_BASE_REG_CLASS'. */
12206 enum reg_class
12207 avr_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED,
12208 addr_space_t as, RTX_CODE outer_code,
12209 RTX_CODE index_code ATTRIBUTE_UNUSED)
12211 if (!ADDR_SPACE_GENERIC_P (as))
12213 return POINTER_Z_REGS;
12216 if (!avr_strict_X)
12217 return reload_completed ? BASE_POINTER_REGS : POINTER_REGS;
12219 return PLUS == outer_code ? BASE_POINTER_REGS : POINTER_REGS;
12223 /* Implement `REGNO_MODE_CODE_OK_FOR_BASE_P'. */
12225 bool
12226 avr_regno_mode_code_ok_for_base_p (int regno,
12227 machine_mode mode ATTRIBUTE_UNUSED,
12228 addr_space_t as ATTRIBUTE_UNUSED,
12229 RTX_CODE outer_code,
12230 RTX_CODE index_code ATTRIBUTE_UNUSED)
12232 bool ok = false;
12234 if (!ADDR_SPACE_GENERIC_P (as))
12236 if (regno < FIRST_PSEUDO_REGISTER
12237 && regno == REG_Z)
12239 return true;
12242 if (reg_renumber)
12244 regno = reg_renumber[regno];
12246 if (regno == REG_Z)
12248 return true;
12252 return false;
12255 if (regno < FIRST_PSEUDO_REGISTER
12256 && (regno == REG_X
12257 || regno == REG_Y
12258 || regno == REG_Z
12259 || regno == ARG_POINTER_REGNUM))
12261 ok = true;
12263 else if (reg_renumber)
12265 regno = reg_renumber[regno];
12267 if (regno == REG_X
12268 || regno == REG_Y
12269 || regno == REG_Z
12270 || regno == ARG_POINTER_REGNUM)
12272 ok = true;
12276 if (avr_strict_X
12277 && PLUS == outer_code
12278 && regno == REG_X)
12280 ok = false;
12283 return ok;
12287 /* A helper for `output_reload_insisf' and `output_reload_inhi'. */
12288 /* Set 32-bit register OP[0] to compile-time constant OP[1].
12289 CLOBBER_REG is a QI clobber register or NULL_RTX.
12290 LEN == NULL: output instructions.
12291 LEN != NULL: set *LEN to the length of the instruction sequence
12292 (in words) printed with LEN = NULL.
12293 If CLEAR_P is true, OP[0] had been cleard to Zero already.
12294 If CLEAR_P is false, nothing is known about OP[0].
12296 The effect on cc0 is as follows:
12298 Load 0 to any register except ZERO_REG : NONE
12299 Load ld register with any value : NONE
12300 Anything else: : CLOBBER */
12302 static void
12303 output_reload_in_const (rtx *op, rtx clobber_reg, int *len, bool clear_p)
12305 rtx src = op[1];
12306 rtx dest = op[0];
12307 rtx xval, xdest[4];
12308 int ival[4];
12309 int clobber_val = 1234;
12310 bool cooked_clobber_p = false;
12311 bool set_p = false;
12312 machine_mode mode = GET_MODE (dest);
12313 int n_bytes = GET_MODE_SIZE (mode);
12315 gcc_assert (REG_P (dest)
12316 && CONSTANT_P (src));
12318 if (len)
12319 *len = 0;
12321 /* (REG:SI 14) is special: It's neither in LD_REGS nor in NO_LD_REGS
12322 but has some subregs that are in LD_REGS. Use the MSB (REG:QI 17). */
12324 if (REGNO (dest) < 16
12325 && REGNO (dest) + GET_MODE_SIZE (mode) > 16)
12327 clobber_reg = all_regs_rtx[REGNO (dest) + n_bytes - 1];
12330 /* We might need a clobber reg but don't have one. Look at the value to
12331 be loaded more closely. A clobber is only needed if it is a symbol
12332 or contains a byte that is neither 0, -1 or a power of 2. */
12334 if (NULL_RTX == clobber_reg
12335 && !test_hard_reg_class (LD_REGS, dest)
12336 && (! (CONST_INT_P (src) || CONST_FIXED_P (src) || CONST_DOUBLE_P (src))
12337 || !avr_popcount_each_byte (src, n_bytes,
12338 (1 << 0) | (1 << 1) | (1 << 8))))
12340 /* We have no clobber register but need one. Cook one up.
12341 That's cheaper than loading from constant pool. */
12343 cooked_clobber_p = true;
12344 clobber_reg = all_regs_rtx[REG_Z + 1];
12345 avr_asm_len ("mov __tmp_reg__,%0", &clobber_reg, len, 1);
12348 /* Now start filling DEST from LSB to MSB. */
12350 for (int n = 0; n < n_bytes; n++)
12352 int ldreg_p;
12353 bool done_byte = false;
12354 rtx xop[3];
12356 /* Crop the n-th destination byte. */
12358 xdest[n] = simplify_gen_subreg (QImode, dest, mode, n);
12359 ldreg_p = test_hard_reg_class (LD_REGS, xdest[n]);
12361 if (!CONST_INT_P (src)
12362 && !CONST_FIXED_P (src)
12363 && !CONST_DOUBLE_P (src))
12365 static const char* const asm_code[][2] =
12367 { "ldi %2,lo8(%1)" CR_TAB "mov %0,%2", "ldi %0,lo8(%1)" },
12368 { "ldi %2,hi8(%1)" CR_TAB "mov %0,%2", "ldi %0,hi8(%1)" },
12369 { "ldi %2,hlo8(%1)" CR_TAB "mov %0,%2", "ldi %0,hlo8(%1)" },
12370 { "ldi %2,hhi8(%1)" CR_TAB "mov %0,%2", "ldi %0,hhi8(%1)" }
12373 xop[0] = xdest[n];
12374 xop[1] = src;
12375 xop[2] = clobber_reg;
12377 avr_asm_len (asm_code[n][ldreg_p], xop, len, ldreg_p ? 1 : 2);
12379 continue;
12382 /* Crop the n-th source byte. */
12384 xval = simplify_gen_subreg (QImode, src, mode, n);
12385 ival[n] = INTVAL (xval);
12387 /* Look if we can reuse the low word by means of MOVW. */
12389 if (n == 2
12390 && n_bytes >= 4
12391 && AVR_HAVE_MOVW)
12393 rtx lo16 = simplify_gen_subreg (HImode, src, mode, 0);
12394 rtx hi16 = simplify_gen_subreg (HImode, src, mode, 2);
12396 if (INTVAL (lo16) == INTVAL (hi16))
12398 if (INTVAL (lo16) != 0 || !clear_p)
12399 avr_asm_len ("movw %C0,%A0", &op[0], len, 1);
12401 break;
12405 /* Don't use CLR so that cc0 is set as expected. */
12407 if (ival[n] == 0)
12409 if (!clear_p)
12410 avr_asm_len (ldreg_p ? "ldi %0,0"
12411 : AVR_ZERO_REGNO == REGNO (xdest[n]) ? "clr %0"
12412 : "mov %0,__zero_reg__",
12413 &xdest[n], len, 1);
12414 continue;
12417 if (clobber_val == ival[n]
12418 && REGNO (clobber_reg) == REGNO (xdest[n]))
12420 continue;
12423 /* LD_REGS can use LDI to move a constant value */
12425 if (ldreg_p)
12427 xop[0] = xdest[n];
12428 xop[1] = xval;
12429 avr_asm_len ("ldi %0,lo8(%1)", xop, len, 1);
12430 continue;
12433 /* Try to reuse value already loaded in some lower byte. */
12435 for (int j = 0; j < n; j++)
12436 if (ival[j] == ival[n])
12438 xop[0] = xdest[n];
12439 xop[1] = xdest[j];
12441 avr_asm_len ("mov %0,%1", xop, len, 1);
12442 done_byte = true;
12443 break;
12446 if (done_byte)
12447 continue;
12449 /* Need no clobber reg for -1: Use CLR/DEC */
12451 if (ival[n] == -1)
12453 if (!clear_p)
12454 avr_asm_len ("clr %0", &xdest[n], len, 1);
12456 avr_asm_len ("dec %0", &xdest[n], len, 1);
12457 continue;
12459 else if (ival[n] == 1)
12461 if (!clear_p)
12462 avr_asm_len ("clr %0", &xdest[n], len, 1);
12464 avr_asm_len ("inc %0", &xdest[n], len, 1);
12465 continue;
12468 /* Use T flag or INC to manage powers of 2 if we have
12469 no clobber reg. */
12471 if (NULL_RTX == clobber_reg
12472 && single_one_operand (xval, QImode))
12474 xop[0] = xdest[n];
12475 xop[1] = GEN_INT (exact_log2 (ival[n] & GET_MODE_MASK (QImode)));
12477 gcc_assert (constm1_rtx != xop[1]);
12479 if (!set_p)
12481 set_p = true;
12482 avr_asm_len ("set", xop, len, 1);
12485 if (!clear_p)
12486 avr_asm_len ("clr %0", xop, len, 1);
12488 avr_asm_len ("bld %0,%1", xop, len, 1);
12489 continue;
12492 /* We actually need the LD_REGS clobber reg. */
12494 gcc_assert (NULL_RTX != clobber_reg);
12496 xop[0] = xdest[n];
12497 xop[1] = xval;
12498 xop[2] = clobber_reg;
12499 clobber_val = ival[n];
12501 avr_asm_len ("ldi %2,lo8(%1)" CR_TAB
12502 "mov %0,%2", xop, len, 2);
12505 /* If we cooked up a clobber reg above, restore it. */
12507 if (cooked_clobber_p)
12509 avr_asm_len ("mov %0,__tmp_reg__", &clobber_reg, len, 1);
12514 /* Reload the constant OP[1] into the HI register OP[0].
12515 CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
12516 into a NO_LD_REGS register. If CLOBBER_REG is NULL_RTX we either don't
12517 need a clobber reg or have to cook one up.
12519 PLEN == NULL: Output instructions.
12520 PLEN != NULL: Output nothing. Set *PLEN to number of words occupied
12521 by the insns printed.
12523 Return "". */
12525 const char*
12526 output_reload_inhi (rtx *op, rtx clobber_reg, int *plen)
12528 output_reload_in_const (op, clobber_reg, plen, false);
12529 return "";
12533 /* Reload a SI or SF compile time constant OP[1] into the register OP[0].
12534 CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
12535 into a NO_LD_REGS register. If CLOBBER_REG is NULL_RTX we either don't
12536 need a clobber reg or have to cook one up.
12538 LEN == NULL: Output instructions.
12540 LEN != NULL: Output nothing. Set *LEN to number of words occupied
12541 by the insns printed.
12543 Return "". */
12545 const char *
12546 output_reload_insisf (rtx *op, rtx clobber_reg, int *len)
12548 if (AVR_HAVE_MOVW
12549 && !test_hard_reg_class (LD_REGS, op[0])
12550 && (CONST_INT_P (op[1])
12551 || CONST_FIXED_P (op[1])
12552 || CONST_DOUBLE_P (op[1])))
12554 int len_clr, len_noclr;
12556 /* In some cases it is better to clear the destination beforehand, e.g.
12558 CLR R2 CLR R3 MOVW R4,R2 INC R2
12560 is shorther than
12562 CLR R2 INC R2 CLR R3 CLR R4 CLR R5
12564 We find it too tedious to work that out in the print function.
12565 Instead, we call the print function twice to get the lengths of
12566 both methods and use the shortest one. */
12568 output_reload_in_const (op, clobber_reg, &len_clr, true);
12569 output_reload_in_const (op, clobber_reg, &len_noclr, false);
12571 if (len_noclr - len_clr == 4)
12573 /* Default needs 4 CLR instructions: clear register beforehand. */
12575 avr_asm_len ("mov %A0,__zero_reg__" CR_TAB
12576 "mov %B0,__zero_reg__" CR_TAB
12577 "movw %C0,%A0", &op[0], len, 3);
12579 output_reload_in_const (op, clobber_reg, len, true);
12581 if (len)
12582 *len += 3;
12584 return "";
12588 /* Default: destination not pre-cleared. */
12590 output_reload_in_const (op, clobber_reg, len, false);
12591 return "";
12594 const char*
12595 avr_out_reload_inpsi (rtx *op, rtx clobber_reg, int *len)
12597 output_reload_in_const (op, clobber_reg, len, false);
12598 return "";
12602 /* Worker function for `ASM_OUTPUT_ADDR_VEC'. */
12603 /* Emit jump tables out-of-line so that branches crossing the table
12604 get shorter offsets. If we have JUMP + CALL, then put the tables
12605 in a dedicated non-.text section so that CALLs get better chance to
12606 be relaxed to RCALLs.
12608 We emit the tables by hand because `function_rodata_section' does not
12609 work as expected, cf. PR71151, and we do *NOT* want the table to be
12610 in .rodata, hence setting JUMP_TABLES_IN_TEXT_SECTION = 0 is of limited
12611 use; and setting it to 1 attributes table lengths to branch offsets...
12612 Moreover, fincal.c keeps switching section before each table entry
12613 which we find too fragile as to rely on section caching. */
12615 void
12616 avr_output_addr_vec (rtx_insn *labl, rtx table)
12618 FILE *stream = asm_out_file;
12620 app_disable();
12622 // Switch to appropriate (sub)section.
12624 if (DECL_SECTION_NAME (current_function_decl)
12625 && symtab_node::get (current_function_decl)
12626 && ! symtab_node::get (current_function_decl)->implicit_section)
12628 // .subsection will emit the code after the function and in the
12629 // section as chosen by the user.
12631 switch_to_section (current_function_section ());
12632 fprintf (stream, "\t.subsection\t1\n");
12634 else
12636 // Since PR63223 there is no restriction where to put the table; it
12637 // may even reside above 128 KiB. We put it in a section as high as
12638 // possible and avoid progmem in order not to waste flash <= 64 KiB.
12640 const char *sec_name = ".jumptables.gcc";
12642 // The table belongs to its host function, therefore use fine
12643 // grained sections so that, if that function is removed by
12644 // --gc-sections, the child table(s) may also be removed. */
12646 tree asm_name = DECL_ASSEMBLER_NAME (current_function_decl);
12647 const char *fname = IDENTIFIER_POINTER (asm_name);
12648 fname = targetm.strip_name_encoding (fname);
12649 sec_name = ACONCAT ((sec_name, ".", fname, NULL));
12651 fprintf (stream, "\t.section\t%s,\"%s\",@progbits\n", sec_name,
12652 AVR_HAVE_JMP_CALL ? "a" : "ax");
12655 // Output the label that preceeds the table.
12657 ASM_OUTPUT_ALIGN (stream, 1);
12658 targetm.asm_out.internal_label (stream, "L", CODE_LABEL_NUMBER (labl));
12660 // Output the table's content.
12662 int vlen = XVECLEN (table, 0);
12664 for (int idx = 0; idx < vlen; idx++)
12666 int value = CODE_LABEL_NUMBER (XEXP (XVECEXP (table, 0, idx), 0));
12668 if (AVR_HAVE_JMP_CALL)
12669 fprintf (stream, "\t.word gs(.L%d)\n", value);
12670 else
12671 fprintf (stream, "\trjmp .L%d\n", value);
12674 // Switch back to original section. As we clobbered the section above,
12675 // forget the current section before switching back.
12677 in_section = NULL;
12678 switch_to_section (current_function_section ());
12682 /* Implement `TARGET_CONDITIONAL_REGISTER_USAGE'. */
12684 static void
12685 avr_conditional_register_usage (void)
12687 if (AVR_TINY)
12689 const int tiny_reg_alloc_order[] = {
12690 24, 25,
12691 22, 23,
12692 30, 31,
12693 26, 27,
12694 28, 29,
12695 21, 20, 19, 18,
12696 16, 17,
12697 32, 33, 34, 35,
12698 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
12701 /* Set R0-R17 as fixed registers. Reset R0-R17 in call used register list
12702 - R0-R15 are not available in Tiny Core devices
12703 - R16 and R17 are fixed registers. */
12705 for (size_t i = 0; i <= 17; i++)
12707 fixed_regs[i] = 1;
12708 call_used_regs[i] = 1;
12711 /* Set R18 to R21 as callee saved registers
12712 - R18, R19, R20 and R21 are the callee saved registers in
12713 Tiny Core devices */
12715 for (size_t i = 18; i <= LAST_CALLEE_SAVED_REG; i++)
12717 call_used_regs[i] = 0;
12720 /* Update register allocation order for Tiny Core devices */
12722 for (size_t i = 0; i < ARRAY_SIZE (tiny_reg_alloc_order); i++)
12724 reg_alloc_order[i] = tiny_reg_alloc_order[i];
12727 CLEAR_HARD_REG_SET (reg_class_contents[(int) ADDW_REGS]);
12728 CLEAR_HARD_REG_SET (reg_class_contents[(int) NO_LD_REGS]);
12732 /* Implement `TARGET_HARD_REGNO_SCRATCH_OK'. */
12733 /* Returns true if SCRATCH are safe to be allocated as a scratch
12734 registers (for a define_peephole2) in the current function. */
12736 static bool
12737 avr_hard_regno_scratch_ok (unsigned int regno)
12739 /* Interrupt functions can only use registers that have already been saved
12740 by the prologue, even if they would normally be call-clobbered. */
12742 if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
12743 && !df_regs_ever_live_p (regno))
12744 return false;
12746 /* Don't allow hard registers that might be part of the frame pointer.
12747 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
12748 and don't care for a frame pointer that spans more than one register. */
12750 if ((!reload_completed || frame_pointer_needed)
12751 && (regno == REG_Y || regno == REG_Y + 1))
12753 return false;
12756 return true;
12760 /* Worker function for `HARD_REGNO_RENAME_OK'. */
12761 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
12764 avr_hard_regno_rename_ok (unsigned int old_reg,
12765 unsigned int new_reg)
12767 /* Interrupt functions can only use registers that have already been
12768 saved by the prologue, even if they would normally be
12769 call-clobbered. */
12771 if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
12772 && !df_regs_ever_live_p (new_reg))
12773 return 0;
12775 /* Don't allow hard registers that might be part of the frame pointer.
12776 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
12777 and don't care for a frame pointer that spans more than one register. */
12779 if ((!reload_completed || frame_pointer_needed)
12780 && (old_reg == REG_Y || old_reg == REG_Y + 1
12781 || new_reg == REG_Y || new_reg == REG_Y + 1))
12783 return 0;
12786 return 1;
12789 /* Output a branch that tests a single bit of a register (QI, HI, SI or DImode)
12790 or memory location in the I/O space (QImode only).
12792 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
12793 Operand 1: register operand to test, or CONST_INT memory address.
12794 Operand 2: bit number.
12795 Operand 3: label to jump to if the test is true. */
12797 const char*
12798 avr_out_sbxx_branch (rtx_insn *insn, rtx operands[])
12800 enum rtx_code comp = GET_CODE (operands[0]);
12801 bool long_jump = get_attr_length (insn) >= 4;
12802 bool reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
12804 if (comp == GE)
12805 comp = EQ;
12806 else if (comp == LT)
12807 comp = NE;
12809 if (reverse)
12810 comp = reverse_condition (comp);
12812 switch (GET_CODE (operands[1]))
12814 default:
12815 gcc_unreachable();
12817 case CONST_INT:
12818 case CONST:
12819 case SYMBOL_REF:
12821 if (low_io_address_operand (operands[1], QImode))
12823 if (comp == EQ)
12824 output_asm_insn ("sbis %i1,%2", operands);
12825 else
12826 output_asm_insn ("sbic %i1,%2", operands);
12828 else
12830 gcc_assert (io_address_operand (operands[1], QImode));
12831 output_asm_insn ("in __tmp_reg__,%i1", operands);
12832 if (comp == EQ)
12833 output_asm_insn ("sbrs __tmp_reg__,%2", operands);
12834 else
12835 output_asm_insn ("sbrc __tmp_reg__,%2", operands);
12838 break; /* CONST_INT */
12840 case REG:
12842 if (comp == EQ)
12843 output_asm_insn ("sbrs %T1%T2", operands);
12844 else
12845 output_asm_insn ("sbrc %T1%T2", operands);
12847 break; /* REG */
12848 } /* switch */
12850 if (long_jump)
12851 return ("rjmp .+4" CR_TAB
12852 "jmp %x3");
12854 if (!reverse)
12855 return "rjmp %x3";
12857 return "";
12860 /* Worker function for `TARGET_ASM_CONSTRUCTOR'. */
12862 static void
12863 avr_asm_out_ctor (rtx symbol, int priority)
12865 fputs ("\t.global __do_global_ctors\n", asm_out_file);
12866 default_ctor_section_asm_out_constructor (symbol, priority);
12870 /* Worker function for `TARGET_ASM_DESTRUCTOR'. */
12872 static void
12873 avr_asm_out_dtor (rtx symbol, int priority)
12875 fputs ("\t.global __do_global_dtors\n", asm_out_file);
12876 default_dtor_section_asm_out_destructor (symbol, priority);
12880 /* Worker function for `TARGET_RETURN_IN_MEMORY'. */
12882 static bool
12883 avr_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
12885 HOST_WIDE_INT size = int_size_in_bytes (type);
12886 HOST_WIDE_INT ret_size_limit = AVR_TINY ? 4 : 8;
12888 /* In avr, there are 8 return registers. But, for Tiny Core
12889 (ATtiny4/5/9/10/20/40) devices, only 4 registers are available.
12890 Return true if size is unknown or greater than the limit. */
12892 if (size == -1 || size > ret_size_limit)
12894 return true;
12896 else
12898 return false;
12903 /* Implement `CASE_VALUES_THRESHOLD'. */
12904 /* Supply the default for --param case-values-threshold=0 */
12906 static unsigned int
12907 avr_case_values_threshold (void)
12909 /* The exact break-even point between a jump table and an if-else tree
12910 depends on several factors not available here like, e.g. if 8-bit
12911 comparisons can be used in the if-else tree or not, on the
12912 range of the case values, if the case value can be reused, on the
12913 register allocation, etc. '7' appears to be a good choice. */
12915 return 7;
12919 /* Implement `TARGET_ADDR_SPACE_ADDRESS_MODE'. */
12921 static scalar_int_mode
12922 avr_addr_space_address_mode (addr_space_t as)
12924 return avr_addrspace[as].pointer_size == 3 ? PSImode : HImode;
12928 /* Implement `TARGET_ADDR_SPACE_POINTER_MODE'. */
12930 static scalar_int_mode
12931 avr_addr_space_pointer_mode (addr_space_t as)
12933 return avr_addr_space_address_mode (as);
12937 /* Helper for following function. */
12939 static bool
12940 avr_reg_ok_for_pgm_addr (rtx reg, bool strict)
12942 gcc_assert (REG_P (reg));
12944 if (strict)
12946 return REGNO (reg) == REG_Z;
12949 /* Avoid combine to propagate hard regs. */
12951 if (can_create_pseudo_p()
12952 && REGNO (reg) < REG_Z)
12954 return false;
12957 return true;
12961 /* Implement `TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P'. */
12963 static bool
12964 avr_addr_space_legitimate_address_p (machine_mode mode, rtx x,
12965 bool strict, addr_space_t as)
12967 bool ok = false;
12969 switch (as)
12971 default:
12972 gcc_unreachable();
12974 case ADDR_SPACE_GENERIC:
12975 return avr_legitimate_address_p (mode, x, strict);
12977 case ADDR_SPACE_FLASH:
12978 case ADDR_SPACE_FLASH1:
12979 case ADDR_SPACE_FLASH2:
12980 case ADDR_SPACE_FLASH3:
12981 case ADDR_SPACE_FLASH4:
12982 case ADDR_SPACE_FLASH5:
12984 switch (GET_CODE (x))
12986 case REG:
12987 ok = avr_reg_ok_for_pgm_addr (x, strict);
12988 break;
12990 case POST_INC:
12991 ok = avr_reg_ok_for_pgm_addr (XEXP (x, 0), strict);
12992 break;
12994 default:
12995 break;
12998 break; /* FLASH */
13000 case ADDR_SPACE_MEMX:
13001 if (REG_P (x))
13002 ok = (!strict
13003 && can_create_pseudo_p());
13005 if (LO_SUM == GET_CODE (x))
13007 rtx hi = XEXP (x, 0);
13008 rtx lo = XEXP (x, 1);
13010 ok = (REG_P (hi)
13011 && (!strict || REGNO (hi) < FIRST_PSEUDO_REGISTER)
13012 && REG_P (lo)
13013 && REGNO (lo) == REG_Z);
13016 break; /* MEMX */
13019 if (avr_log.legitimate_address_p)
13021 avr_edump ("\n%?: ret=%b, mode=%m strict=%d "
13022 "reload_completed=%d reload_in_progress=%d %s:",
13023 ok, mode, strict, reload_completed, reload_in_progress,
13024 reg_renumber ? "(reg_renumber)" : "");
13026 if (GET_CODE (x) == PLUS
13027 && REG_P (XEXP (x, 0))
13028 && CONST_INT_P (XEXP (x, 1))
13029 && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
13030 && reg_renumber)
13032 avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
13033 true_regnum (XEXP (x, 0)));
13036 avr_edump ("\n%r\n", x);
13039 return ok;
13043 /* Implement `TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS'. */
13045 static rtx
13046 avr_addr_space_legitimize_address (rtx x, rtx old_x,
13047 machine_mode mode, addr_space_t as)
13049 if (ADDR_SPACE_GENERIC_P (as))
13050 return avr_legitimize_address (x, old_x, mode);
13052 if (avr_log.legitimize_address)
13054 avr_edump ("\n%?: mode=%m\n %r\n", mode, old_x);
13057 return old_x;
13061 /* Implement `TARGET_ADDR_SPACE_CONVERT'. */
13063 static rtx
13064 avr_addr_space_convert (rtx src, tree type_from, tree type_to)
13066 addr_space_t as_from = TYPE_ADDR_SPACE (TREE_TYPE (type_from));
13067 addr_space_t as_to = TYPE_ADDR_SPACE (TREE_TYPE (type_to));
13069 if (avr_log.progmem)
13070 avr_edump ("\n%!: op = %r\nfrom = %t\nto = %t\n",
13071 src, type_from, type_to);
13073 /* Up-casting from 16-bit to 24-bit pointer. */
13075 if (as_from != ADDR_SPACE_MEMX
13076 && as_to == ADDR_SPACE_MEMX)
13078 int msb;
13079 rtx sym = src;
13080 rtx reg = gen_reg_rtx (PSImode);
13082 while (CONST == GET_CODE (sym) || PLUS == GET_CODE (sym))
13083 sym = XEXP (sym, 0);
13085 /* Look at symbol flags: avr_encode_section_info set the flags
13086 also if attribute progmem was seen so that we get the right
13087 promotion for, e.g. PSTR-like strings that reside in generic space
13088 but are located in flash. In that case we patch the incoming
13089 address space. */
13091 if (SYMBOL_REF_P (sym)
13092 && ADDR_SPACE_FLASH == AVR_SYMBOL_GET_ADDR_SPACE (sym))
13094 as_from = ADDR_SPACE_FLASH;
13097 /* Linearize memory: RAM has bit 23 set. */
13099 msb = ADDR_SPACE_GENERIC_P (as_from)
13100 ? 0x80
13101 : avr_addrspace[as_from].segment;
13103 src = force_reg (Pmode, src);
13105 emit_insn (msb == 0
13106 ? gen_zero_extendhipsi2 (reg, src)
13107 : gen_n_extendhipsi2 (reg, gen_int_mode (msb, QImode), src));
13109 return reg;
13112 /* Down-casting from 24-bit to 16-bit throws away the high byte. */
13114 if (as_from == ADDR_SPACE_MEMX
13115 && as_to != ADDR_SPACE_MEMX)
13117 rtx new_src = gen_reg_rtx (Pmode);
13119 src = force_reg (PSImode, src);
13121 emit_move_insn (new_src,
13122 simplify_gen_subreg (Pmode, src, PSImode, 0));
13123 return new_src;
13126 return src;
13130 /* Implement `TARGET_ADDR_SPACE_SUBSET_P'. */
13132 static bool
13133 avr_addr_space_subset_p (addr_space_t subset ATTRIBUTE_UNUSED,
13134 addr_space_t superset ATTRIBUTE_UNUSED)
13136 /* Allow any kind of pointer mess. */
13138 return true;
13142 /* Implement `TARGET_CONVERT_TO_TYPE'. */
13144 static tree
13145 avr_convert_to_type (tree type, tree expr)
13147 /* Print a diagnose for pointer conversion that changes the address
13148 space of the pointer target to a non-enclosing address space,
13149 provided -Waddr-space-convert is on.
13151 FIXME: Filter out cases where the target object is known to
13152 be located in the right memory, like in
13154 (const __flash*) PSTR ("text")
13156 Also try to distinguish between explicit casts requested by
13157 the user and implicit casts like
13159 void f (const __flash char*);
13161 void g (const char *p)
13163 f ((const __flash*) p);
13166 under the assumption that an explicit casts means that the user
13167 knows what he is doing, e.g. interface with PSTR or old style
13168 code with progmem and pgm_read_xxx.
13171 if (avr_warn_addr_space_convert
13172 && expr != error_mark_node
13173 && POINTER_TYPE_P (type)
13174 && POINTER_TYPE_P (TREE_TYPE (expr)))
13176 addr_space_t as_old = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (expr)));
13177 addr_space_t as_new = TYPE_ADDR_SPACE (TREE_TYPE (type));
13179 if (avr_log.progmem)
13180 avr_edump ("%?: type = %t\nexpr = %t\n\n", type, expr);
13182 if (as_new != ADDR_SPACE_MEMX
13183 && as_new != as_old)
13185 location_t loc = EXPR_LOCATION (expr);
13186 const char *name_old = avr_addrspace[as_old].name;
13187 const char *name_new = avr_addrspace[as_new].name;
13189 warning (OPT_Waddr_space_convert,
13190 "conversion from address space %qs to address space %qs",
13191 ADDR_SPACE_GENERIC_P (as_old) ? "generic" : name_old,
13192 ADDR_SPACE_GENERIC_P (as_new) ? "generic" : name_new);
13194 return fold_build1_loc (loc, ADDR_SPACE_CONVERT_EXPR, type, expr);
13198 return NULL_TREE;
13202 /* Implement `TARGET_LEGITIMATE_COMBINED_INSN'. */
13204 /* PR78883: Filter out paradoxical SUBREGs of MEM which are not handled
13205 properly by following passes. As INSN_SCHEDULING is off and hence
13206 general_operand accepts such expressions, ditch them now. */
13208 static bool
13209 avr_legitimate_combined_insn (rtx_insn *insn)
13211 subrtx_iterator::array_type array;
13213 FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
13215 const_rtx op = *iter;
13217 if (SUBREG_P (op)
13218 && MEM_P (SUBREG_REG (op))
13219 && (GET_MODE_SIZE (GET_MODE (op))
13220 > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))))
13222 return false;
13226 return true;
13230 /* PR63633: The middle-end might come up with hard regs as input operands.
13232 RMASK is a bit mask representing a subset of hard registers R0...R31:
13233 Rn is an element of that set iff bit n of RMASK is set.
13234 OPMASK describes a subset of OP[]: If bit n of OPMASK is 1 then
13235 OP[n] has to be fixed; otherwise OP[n] is left alone.
13237 For each element of OPMASK which is a hard register overlapping RMASK,
13238 replace OP[n] with a newly created pseudo register
13240 HREG == 0: Also emit a move insn that copies the contents of that
13241 hard register into the new pseudo.
13243 HREG != 0: Also set HREG[n] to the hard register. */
13245 static void
13246 avr_fix_operands (rtx *op, rtx *hreg, unsigned opmask, unsigned rmask)
13248 for (; opmask; opmask >>= 1, op++)
13250 rtx reg = *op;
13252 if (hreg)
13253 *hreg = NULL_RTX;
13255 if ((opmask & 1)
13256 && REG_P (reg)
13257 && REGNO (reg) < FIRST_PSEUDO_REGISTER
13258 // This hard-reg overlaps other prohibited hard regs?
13259 && (rmask & regmask (GET_MODE (reg), REGNO (reg))))
13261 *op = gen_reg_rtx (GET_MODE (reg));
13262 if (hreg == NULL)
13263 emit_move_insn (*op, reg);
13264 else
13265 *hreg = reg;
13268 if (hreg)
13269 hreg++;
13274 void
13275 avr_fix_inputs (rtx *op, unsigned opmask, unsigned rmask)
13277 avr_fix_operands (op, NULL, opmask, rmask);
13281 /* Helper for the function below: If bit n of MASK is set and
13282 HREG[n] != NULL, then emit a move insn to copy OP[n] to HREG[n].
13283 Otherwise do nothing for that n. Return TRUE. */
13285 static bool
13286 avr_move_fixed_operands (rtx *op, rtx *hreg, unsigned mask)
13288 for (; mask; mask >>= 1, op++, hreg++)
13289 if ((mask & 1)
13290 && *hreg)
13291 emit_move_insn (*hreg, *op);
13293 return true;
13297 /* PR63633: The middle-end might come up with hard regs as output operands.
13299 GEN is a sequence generating function like gen_mulsi3 with 3 operands OP[].
13300 RMASK is a bit mask representing a subset of hard registers R0...R31:
13301 Rn is an element of that set iff bit n of RMASK is set.
13302 OPMASK describes a subset of OP[]: If bit n of OPMASK is 1 then
13303 OP[n] has to be fixed; otherwise OP[n] is left alone.
13305 Emit the insn sequence as generated by GEN() with all elements of OPMASK
13306 which are hard registers overlapping RMASK replaced by newly created
13307 pseudo registers. After the sequence has been emitted, emit insns that
13308 move the contents of respective pseudos to their hard regs. */
13310 bool
13311 avr_emit3_fix_outputs (rtx (*gen)(rtx,rtx,rtx), rtx *op,
13312 unsigned opmask, unsigned rmask)
13314 const int n = 3;
13315 rtx hreg[n];
13317 /* It is letigimate for GEN to call this function, and in order not to
13318 get self-recursive we use the following static kludge. This is the
13319 only way not to duplicate all expanders and to avoid ugly and
13320 hard-to-maintain C-code instead of the much more appreciated RTL
13321 representation as supplied by define_expand. */
13322 static bool lock = false;
13324 gcc_assert (opmask < (1u << n));
13326 if (lock)
13327 return false;
13329 avr_fix_operands (op, hreg, opmask, rmask);
13331 lock = true;
13332 emit_insn (gen (op[0], op[1], op[2]));
13333 lock = false;
13335 return avr_move_fixed_operands (op, hreg, opmask);
13339 /* Worker function for movmemhi expander.
13340 XOP[0] Destination as MEM:BLK
13341 XOP[1] Source " "
13342 XOP[2] # Bytes to copy
13344 Return TRUE if the expansion is accomplished.
13345 Return FALSE if the operand compination is not supported. */
13347 bool
13348 avr_emit_movmemhi (rtx *xop)
13350 HOST_WIDE_INT count;
13351 machine_mode loop_mode;
13352 addr_space_t as = MEM_ADDR_SPACE (xop[1]);
13353 rtx loop_reg, addr1, a_src, a_dest, insn, xas;
13354 rtx a_hi8 = NULL_RTX;
13356 if (avr_mem_flash_p (xop[0]))
13357 return false;
13359 if (!CONST_INT_P (xop[2]))
13360 return false;
13362 count = INTVAL (xop[2]);
13363 if (count <= 0)
13364 return false;
13366 a_src = XEXP (xop[1], 0);
13367 a_dest = XEXP (xop[0], 0);
13369 if (PSImode == GET_MODE (a_src))
13371 gcc_assert (as == ADDR_SPACE_MEMX);
13373 loop_mode = (count < 0x100) ? QImode : HImode;
13374 loop_reg = gen_rtx_REG (loop_mode, 24);
13375 emit_move_insn (loop_reg, gen_int_mode (count, loop_mode));
13377 addr1 = simplify_gen_subreg (HImode, a_src, PSImode, 0);
13378 a_hi8 = simplify_gen_subreg (QImode, a_src, PSImode, 2);
13380 else
13382 int segment = avr_addrspace[as].segment;
13384 if (segment
13385 && avr_n_flash > 1)
13387 a_hi8 = GEN_INT (segment);
13388 emit_move_insn (rampz_rtx, a_hi8 = copy_to_mode_reg (QImode, a_hi8));
13390 else if (!ADDR_SPACE_GENERIC_P (as))
13392 as = ADDR_SPACE_FLASH;
13395 addr1 = a_src;
13397 loop_mode = (count <= 0x100) ? QImode : HImode;
13398 loop_reg = copy_to_mode_reg (loop_mode, gen_int_mode (count, loop_mode));
13401 xas = GEN_INT (as);
13403 /* FIXME: Register allocator might come up with spill fails if it is left
13404 on its own. Thus, we allocate the pointer registers by hand:
13405 Z = source address
13406 X = destination address */
13408 emit_move_insn (lpm_addr_reg_rtx, addr1);
13409 emit_move_insn (gen_rtx_REG (HImode, REG_X), a_dest);
13411 /* FIXME: Register allocator does a bad job and might spill address
13412 register(s) inside the loop leading to additional move instruction
13413 to/from stack which could clobber tmp_reg. Thus, do *not* emit
13414 load and store as separate insns. Instead, we perform the copy
13415 by means of one monolithic insn. */
13417 gcc_assert (TMP_REGNO == LPM_REGNO);
13419 if (as != ADDR_SPACE_MEMX)
13421 /* Load instruction ([E]LPM or LD) is known at compile time:
13422 Do the copy-loop inline. */
13424 rtx (*fun) (rtx, rtx, rtx)
13425 = QImode == loop_mode ? gen_movmem_qi : gen_movmem_hi;
13427 insn = fun (xas, loop_reg, loop_reg);
13429 else
13431 rtx (*fun) (rtx, rtx)
13432 = QImode == loop_mode ? gen_movmemx_qi : gen_movmemx_hi;
13434 emit_move_insn (gen_rtx_REG (QImode, 23), a_hi8);
13436 insn = fun (xas, GEN_INT (avr_addr.rampz));
13439 set_mem_addr_space (SET_SRC (XVECEXP (insn, 0, 0)), as);
13440 emit_insn (insn);
13442 return true;
13446 /* Print assembler for movmem_qi, movmem_hi insns...
13447 $0 : Address Space
13448 $1, $2 : Loop register
13449 Z : Source address
13450 X : Destination address
13453 const char*
13454 avr_out_movmem (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
13456 addr_space_t as = (addr_space_t) INTVAL (op[0]);
13457 machine_mode loop_mode = GET_MODE (op[1]);
13458 bool sbiw_p = test_hard_reg_class (ADDW_REGS, op[1]);
13459 rtx xop[3];
13461 if (plen)
13462 *plen = 0;
13464 xop[0] = op[0];
13465 xop[1] = op[1];
13466 xop[2] = tmp_reg_rtx;
13468 /* Loop label */
13470 avr_asm_len ("0:", xop, plen, 0);
13472 /* Load with post-increment */
13474 switch (as)
13476 default:
13477 gcc_unreachable();
13479 case ADDR_SPACE_GENERIC:
13481 avr_asm_len ("ld %2,Z+", xop, plen, 1);
13482 break;
13484 case ADDR_SPACE_FLASH:
13486 if (AVR_HAVE_LPMX)
13487 avr_asm_len ("lpm %2,Z+", xop, plen, 1);
13488 else
13489 avr_asm_len ("lpm" CR_TAB
13490 "adiw r30,1", xop, plen, 2);
13491 break;
13493 case ADDR_SPACE_FLASH1:
13494 case ADDR_SPACE_FLASH2:
13495 case ADDR_SPACE_FLASH3:
13496 case ADDR_SPACE_FLASH4:
13497 case ADDR_SPACE_FLASH5:
13499 if (AVR_HAVE_ELPMX)
13500 avr_asm_len ("elpm %2,Z+", xop, plen, 1);
13501 else
13502 avr_asm_len ("elpm" CR_TAB
13503 "adiw r30,1", xop, plen, 2);
13504 break;
13507 /* Store with post-increment */
13509 avr_asm_len ("st X+,%2", xop, plen, 1);
13511 /* Decrement loop-counter and set Z-flag */
13513 if (QImode == loop_mode)
13515 avr_asm_len ("dec %1", xop, plen, 1);
13517 else if (sbiw_p)
13519 avr_asm_len ("sbiw %1,1", xop, plen, 1);
13521 else
13523 avr_asm_len ("subi %A1,1" CR_TAB
13524 "sbci %B1,0", xop, plen, 2);
13527 /* Loop until zero */
13529 return avr_asm_len ("brne 0b", xop, plen, 1);
13534 /* Helper for __builtin_avr_delay_cycles */
13536 static rtx
13537 avr_mem_clobber (void)
13539 rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
13540 MEM_VOLATILE_P (mem) = 1;
13541 return mem;
13544 static void
13545 avr_expand_delay_cycles (rtx operands0)
13547 unsigned HOST_WIDE_INT cycles = UINTVAL (operands0) & GET_MODE_MASK (SImode);
13548 unsigned HOST_WIDE_INT cycles_used;
13549 unsigned HOST_WIDE_INT loop_count;
13551 if (IN_RANGE (cycles, 83886082, 0xFFFFFFFF))
13553 loop_count = ((cycles - 9) / 6) + 1;
13554 cycles_used = ((loop_count - 1) * 6) + 9;
13555 emit_insn (gen_delay_cycles_4 (gen_int_mode (loop_count, SImode),
13556 avr_mem_clobber()));
13557 cycles -= cycles_used;
13560 if (IN_RANGE (cycles, 262145, 83886081))
13562 loop_count = ((cycles - 7) / 5) + 1;
13563 if (loop_count > 0xFFFFFF)
13564 loop_count = 0xFFFFFF;
13565 cycles_used = ((loop_count - 1) * 5) + 7;
13566 emit_insn (gen_delay_cycles_3 (gen_int_mode (loop_count, SImode),
13567 avr_mem_clobber()));
13568 cycles -= cycles_used;
13571 if (IN_RANGE (cycles, 768, 262144))
13573 loop_count = ((cycles - 5) / 4) + 1;
13574 if (loop_count > 0xFFFF)
13575 loop_count = 0xFFFF;
13576 cycles_used = ((loop_count - 1) * 4) + 5;
13577 emit_insn (gen_delay_cycles_2 (gen_int_mode (loop_count, HImode),
13578 avr_mem_clobber()));
13579 cycles -= cycles_used;
13582 if (IN_RANGE (cycles, 6, 767))
13584 loop_count = cycles / 3;
13585 if (loop_count > 255)
13586 loop_count = 255;
13587 cycles_used = loop_count * 3;
13588 emit_insn (gen_delay_cycles_1 (gen_int_mode (loop_count, QImode),
13589 avr_mem_clobber()));
13590 cycles -= cycles_used;
13593 while (cycles >= 2)
13595 emit_insn (gen_nopv (GEN_INT (2)));
13596 cycles -= 2;
13599 if (cycles == 1)
13601 emit_insn (gen_nopv (GEN_INT (1)));
13602 cycles--;
13607 static void
13608 avr_expand_nops (rtx operands0)
13610 unsigned HOST_WIDE_INT n_nops = UINTVAL (operands0) & GET_MODE_MASK (HImode);
13612 while (n_nops--)
13614 emit_insn (gen_nopv (const1_rtx));
13619 /* Compute the image of x under f, i.e. perform x --> f(x) */
13621 static int
13622 avr_map (unsigned int f, int x)
13624 return x < 8 ? (f >> (4 * x)) & 0xf : 0;
13628 /* Return some metrics of map A. */
13630 enum
13632 /* Number of fixed points in { 0 ... 7 } */
13633 MAP_FIXED_0_7,
13635 /* Size of preimage of non-fixed points in { 0 ... 7 } */
13636 MAP_NONFIXED_0_7,
13638 /* Mask representing the fixed points in { 0 ... 7 } */
13639 MAP_MASK_FIXED_0_7,
13641 /* Size of the preimage of { 0 ... 7 } */
13642 MAP_PREIMAGE_0_7,
13644 /* Mask that represents the preimage of { f } */
13645 MAP_MASK_PREIMAGE_F
13648 static unsigned
13649 avr_map_metric (unsigned int a, int mode)
13651 unsigned metric = 0;
13653 for (unsigned i = 0; i < 8; i++)
13655 unsigned ai = avr_map (a, i);
13657 if (mode == MAP_FIXED_0_7)
13658 metric += ai == i;
13659 else if (mode == MAP_NONFIXED_0_7)
13660 metric += ai < 8 && ai != i;
13661 else if (mode == MAP_MASK_FIXED_0_7)
13662 metric |= ((unsigned) (ai == i)) << i;
13663 else if (mode == MAP_PREIMAGE_0_7)
13664 metric += ai < 8;
13665 else if (mode == MAP_MASK_PREIMAGE_F)
13666 metric |= ((unsigned) (ai == 0xf)) << i;
13667 else
13668 gcc_unreachable();
13671 return metric;
13675 /* Return true if IVAL has a 0xf in its hexadecimal representation
13676 and false, otherwise. Only nibbles 0..7 are taken into account.
13677 Used as constraint helper for C0f and Cxf. */
13679 bool
13680 avr_has_nibble_0xf (rtx ival)
13682 unsigned int map = UINTVAL (ival) & GET_MODE_MASK (SImode);
13683 return avr_map_metric (map, MAP_MASK_PREIMAGE_F) != 0;
13687 /* We have a set of bits that are mapped by a function F.
13688 Try to decompose F by means of a second function G so that
13690 F = F o G^-1 o G
13694 cost (F o G^-1) + cost (G) < cost (F)
13696 Example: Suppose builtin insert_bits supplies us with the map
13697 F = 0x3210ffff. Instead of doing 4 bit insertions to get the high
13698 nibble of the result, we can just as well rotate the bits before inserting
13699 them and use the map 0x7654ffff which is cheaper than the original map.
13700 For this example G = G^-1 = 0x32107654 and F o G^-1 = 0x7654ffff. */
13702 typedef struct
13704 /* tree code of binary function G */
13705 enum tree_code code;
13707 /* The constant second argument of G */
13708 int arg;
13710 /* G^-1, the inverse of G (*, arg) */
13711 unsigned ginv;
13713 /* The cost of applying G (*, arg) */
13714 int cost;
13716 /* The composition F o G^-1 (*, arg) for some function F */
13717 unsigned int map;
13719 /* For debug purpose only */
13720 const char *str;
13721 } avr_map_op_t;
13723 static const avr_map_op_t avr_map_op[] =
13725 { LROTATE_EXPR, 0, 0x76543210, 0, 0, "id" },
13726 { LROTATE_EXPR, 1, 0x07654321, 2, 0, "<<<" },
13727 { LROTATE_EXPR, 2, 0x10765432, 4, 0, "<<<" },
13728 { LROTATE_EXPR, 3, 0x21076543, 4, 0, "<<<" },
13729 { LROTATE_EXPR, 4, 0x32107654, 1, 0, "<<<" },
13730 { LROTATE_EXPR, 5, 0x43210765, 3, 0, "<<<" },
13731 { LROTATE_EXPR, 6, 0x54321076, 5, 0, "<<<" },
13732 { LROTATE_EXPR, 7, 0x65432107, 3, 0, "<<<" },
13733 { RSHIFT_EXPR, 1, 0x6543210c, 1, 0, ">>" },
13734 { RSHIFT_EXPR, 1, 0x7543210c, 1, 0, ">>" },
13735 { RSHIFT_EXPR, 2, 0x543210cc, 2, 0, ">>" },
13736 { RSHIFT_EXPR, 2, 0x643210cc, 2, 0, ">>" },
13737 { RSHIFT_EXPR, 2, 0x743210cc, 2, 0, ">>" },
13738 { LSHIFT_EXPR, 1, 0xc7654321, 1, 0, "<<" },
13739 { LSHIFT_EXPR, 2, 0xcc765432, 2, 0, "<<" }
13743 /* Try to decompose F as F = (F o G^-1) o G as described above.
13744 The result is a struct representing F o G^-1 and G.
13745 If result.cost < 0 then such a decomposition does not exist. */
13747 static avr_map_op_t
13748 avr_map_decompose (unsigned int f, const avr_map_op_t *g, bool val_const_p)
13750 bool val_used_p = avr_map_metric (f, MAP_MASK_PREIMAGE_F) != 0;
13751 avr_map_op_t f_ginv = *g;
13752 unsigned int ginv = g->ginv;
13754 f_ginv.cost = -1;
13756 /* Step 1: Computing F o G^-1 */
13758 for (int i = 7; i >= 0; i--)
13760 int x = avr_map (f, i);
13762 if (x <= 7)
13764 x = avr_map (ginv, x);
13766 /* The bit is no element of the image of G: no avail (cost = -1) */
13768 if (x > 7)
13769 return f_ginv;
13772 f_ginv.map = (f_ginv.map << 4) + x;
13775 /* Step 2: Compute the cost of the operations.
13776 The overall cost of doing an operation prior to the insertion is
13777 the cost of the insertion plus the cost of the operation. */
13779 /* Step 2a: Compute cost of F o G^-1 */
13781 if (avr_map_metric (f_ginv.map, MAP_NONFIXED_0_7) == 0)
13782 /* The mapping consists only of fixed points and can be folded
13783 to AND/OR logic in the remainder. Reasonable cost is 3. */
13784 f_ginv.cost = 2 + (val_used_p && !val_const_p);
13785 else
13787 rtx xop[4];
13789 /* Get the cost of the insn by calling the output worker with some
13790 fake values. Mimic effect of reloading xop[3]: Unused operands
13791 are mapped to 0 and used operands are reloaded to xop[0]. */
13793 xop[0] = all_regs_rtx[24];
13794 xop[1] = gen_int_mode (f_ginv.map, SImode);
13795 xop[2] = all_regs_rtx[25];
13796 xop[3] = val_used_p ? xop[0] : const0_rtx;
13798 avr_out_insert_bits (xop, &f_ginv.cost);
13800 f_ginv.cost += val_const_p && val_used_p ? 1 : 0;
13803 /* Step 2b: Add cost of G */
13805 f_ginv.cost += g->cost;
13807 if (avr_log.builtin)
13808 avr_edump (" %s%d=%d", g->str, g->arg, f_ginv.cost);
13810 return f_ginv;
13814 /* Insert bits from XOP[1] into XOP[0] according to MAP.
13815 XOP[0] and XOP[1] don't overlap.
13816 If FIXP_P = true: Move all bits according to MAP using BLD/BST sequences.
13817 If FIXP_P = false: Just move the bit if its position in the destination
13818 is different to its source position. */
13820 static void
13821 avr_move_bits (rtx *xop, unsigned int map, bool fixp_p, int *plen)
13823 /* T-flag contains this bit of the source, i.e. of XOP[1] */
13824 int t_bit_src = -1;
13826 /* We order the operations according to the requested source bit b. */
13828 for (int b = 0; b < 8; b++)
13829 for (int bit_dest = 0; bit_dest < 8; bit_dest++)
13831 int bit_src = avr_map (map, bit_dest);
13833 if (b != bit_src
13834 || bit_src >= 8
13835 /* Same position: No need to copy as requested by FIXP_P. */
13836 || (bit_dest == bit_src && !fixp_p))
13837 continue;
13839 if (t_bit_src != bit_src)
13841 /* Source bit is not yet in T: Store it to T. */
13843 t_bit_src = bit_src;
13845 xop[3] = GEN_INT (bit_src);
13846 avr_asm_len ("bst %T1%T3", xop, plen, 1);
13849 /* Load destination bit with T. */
13851 xop[3] = GEN_INT (bit_dest);
13852 avr_asm_len ("bld %T0%T3", xop, plen, 1);
13857 /* PLEN == 0: Print assembler code for `insert_bits'.
13858 PLEN != 0: Compute code length in bytes.
13860 OP[0]: Result
13861 OP[1]: The mapping composed of nibbles. If nibble no. N is
13862 0: Bit N of result is copied from bit OP[2].0
13863 ... ...
13864 7: Bit N of result is copied from bit OP[2].7
13865 0xf: Bit N of result is copied from bit OP[3].N
13866 OP[2]: Bits to be inserted
13867 OP[3]: Target value */
13869 const char*
13870 avr_out_insert_bits (rtx *op, int *plen)
13872 unsigned int map = UINTVAL (op[1]) & GET_MODE_MASK (SImode);
13873 unsigned mask_fixed;
13874 bool fixp_p = true;
13875 rtx xop[4];
13877 xop[0] = op[0];
13878 xop[1] = op[2];
13879 xop[2] = op[3];
13881 gcc_assert (REG_P (xop[2]) || CONST_INT_P (xop[2]));
13883 if (plen)
13884 *plen = 0;
13885 else if (flag_print_asm_name)
13886 fprintf (asm_out_file, ASM_COMMENT_START "map = 0x%08x\n", map);
13888 /* If MAP has fixed points it might be better to initialize the result
13889 with the bits to be inserted instead of moving all bits by hand. */
13891 mask_fixed = avr_map_metric (map, MAP_MASK_FIXED_0_7);
13893 if (REGNO (xop[0]) == REGNO (xop[1]))
13895 /* Avoid early-clobber conflicts */
13897 avr_asm_len ("mov __tmp_reg__,%1", xop, plen, 1);
13898 xop[1] = tmp_reg_rtx;
13899 fixp_p = false;
13902 if (avr_map_metric (map, MAP_MASK_PREIMAGE_F))
13904 /* XOP[2] is used and reloaded to XOP[0] already */
13906 int n_fix = 0, n_nofix = 0;
13908 gcc_assert (REG_P (xop[2]));
13910 /* Get the code size of the bit insertions; once with all bits
13911 moved and once with fixed points omitted. */
13913 avr_move_bits (xop, map, true, &n_fix);
13914 avr_move_bits (xop, map, false, &n_nofix);
13916 if (fixp_p && n_fix - n_nofix > 3)
13918 xop[3] = gen_int_mode (~mask_fixed, QImode);
13920 avr_asm_len ("eor %0,%1" CR_TAB
13921 "andi %0,%3" CR_TAB
13922 "eor %0,%1", xop, plen, 3);
13923 fixp_p = false;
13926 else
13928 /* XOP[2] is unused */
13930 if (fixp_p && mask_fixed)
13932 avr_asm_len ("mov %0,%1", xop, plen, 1);
13933 fixp_p = false;
13937 /* Move/insert remaining bits. */
13939 avr_move_bits (xop, map, fixp_p, plen);
13941 return "";
13945 /* IDs for all the AVR builtins. */
13947 enum avr_builtin_id
13949 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
13950 AVR_BUILTIN_ ## NAME,
13951 #include "builtins.def"
13952 #undef DEF_BUILTIN
13954 AVR_BUILTIN_COUNT
13957 struct GTY(()) avr_builtin_description
13959 enum insn_code icode;
13960 int n_args;
13961 tree fndecl;
13965 /* Notice that avr_bdesc[] and avr_builtin_id are initialized in such a way
13966 that a built-in's ID can be used to access the built-in by means of
13967 avr_bdesc[ID] */
13969 static GTY(()) struct avr_builtin_description
13970 avr_bdesc[AVR_BUILTIN_COUNT] =
13972 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE, LIBNAME) \
13973 { (enum insn_code) CODE_FOR_ ## ICODE, N_ARGS, NULL_TREE },
13974 #include "builtins.def"
13975 #undef DEF_BUILTIN
13979 /* Implement `TARGET_BUILTIN_DECL'. */
13981 static tree
13982 avr_builtin_decl (unsigned id, bool initialize_p ATTRIBUTE_UNUSED)
13984 if (id < AVR_BUILTIN_COUNT)
13985 return avr_bdesc[id].fndecl;
13987 return error_mark_node;
13991 static void
13992 avr_init_builtin_int24 (void)
13994 tree int24_type = make_signed_type (GET_MODE_BITSIZE (PSImode));
13995 tree uint24_type = make_unsigned_type (GET_MODE_BITSIZE (PSImode));
13997 lang_hooks.types.register_builtin_type (int24_type, "__int24");
13998 lang_hooks.types.register_builtin_type (uint24_type, "__uint24");
14002 /* Implement `TARGET_INIT_BUILTINS' */
14003 /* Set up all builtin functions for this target. */
14005 static void
14006 avr_init_builtins (void)
14008 tree void_ftype_void
14009 = build_function_type_list (void_type_node, NULL_TREE);
14010 tree uchar_ftype_uchar
14011 = build_function_type_list (unsigned_char_type_node,
14012 unsigned_char_type_node,
14013 NULL_TREE);
14014 tree uint_ftype_uchar_uchar
14015 = build_function_type_list (unsigned_type_node,
14016 unsigned_char_type_node,
14017 unsigned_char_type_node,
14018 NULL_TREE);
14019 tree int_ftype_char_char
14020 = build_function_type_list (integer_type_node,
14021 char_type_node,
14022 char_type_node,
14023 NULL_TREE);
14024 tree int_ftype_char_uchar
14025 = build_function_type_list (integer_type_node,
14026 char_type_node,
14027 unsigned_char_type_node,
14028 NULL_TREE);
14029 tree void_ftype_ulong
14030 = build_function_type_list (void_type_node,
14031 long_unsigned_type_node,
14032 NULL_TREE);
14034 tree uchar_ftype_ulong_uchar_uchar
14035 = build_function_type_list (unsigned_char_type_node,
14036 long_unsigned_type_node,
14037 unsigned_char_type_node,
14038 unsigned_char_type_node,
14039 NULL_TREE);
14041 tree const_memx_void_node
14042 = build_qualified_type (void_type_node,
14043 TYPE_QUAL_CONST
14044 | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_MEMX));
14046 tree const_memx_ptr_type_node
14047 = build_pointer_type_for_mode (const_memx_void_node, PSImode, false);
14049 tree char_ftype_const_memx_ptr
14050 = build_function_type_list (char_type_node,
14051 const_memx_ptr_type_node,
14052 NULL);
14054 #define ITYP(T) \
14055 lang_hooks.types.type_for_size (TYPE_PRECISION (T), TYPE_UNSIGNED (T))
14057 #define FX_FTYPE_FX(fx) \
14058 tree fx##r_ftype_##fx##r \
14059 = build_function_type_list (node_##fx##r, node_##fx##r, NULL); \
14060 tree fx##k_ftype_##fx##k \
14061 = build_function_type_list (node_##fx##k, node_##fx##k, NULL)
14063 #define FX_FTYPE_FX_INT(fx) \
14064 tree fx##r_ftype_##fx##r_int \
14065 = build_function_type_list (node_##fx##r, node_##fx##r, \
14066 integer_type_node, NULL); \
14067 tree fx##k_ftype_##fx##k_int \
14068 = build_function_type_list (node_##fx##k, node_##fx##k, \
14069 integer_type_node, NULL)
14071 #define INT_FTYPE_FX(fx) \
14072 tree int_ftype_##fx##r \
14073 = build_function_type_list (integer_type_node, node_##fx##r, NULL); \
14074 tree int_ftype_##fx##k \
14075 = build_function_type_list (integer_type_node, node_##fx##k, NULL)
14077 #define INTX_FTYPE_FX(fx) \
14078 tree int##fx##r_ftype_##fx##r \
14079 = build_function_type_list (ITYP (node_##fx##r), node_##fx##r, NULL); \
14080 tree int##fx##k_ftype_##fx##k \
14081 = build_function_type_list (ITYP (node_##fx##k), node_##fx##k, NULL)
14083 #define FX_FTYPE_INTX(fx) \
14084 tree fx##r_ftype_int##fx##r \
14085 = build_function_type_list (node_##fx##r, ITYP (node_##fx##r), NULL); \
14086 tree fx##k_ftype_int##fx##k \
14087 = build_function_type_list (node_##fx##k, ITYP (node_##fx##k), NULL)
14089 tree node_hr = short_fract_type_node;
14090 tree node_nr = fract_type_node;
14091 tree node_lr = long_fract_type_node;
14092 tree node_llr = long_long_fract_type_node;
14094 tree node_uhr = unsigned_short_fract_type_node;
14095 tree node_unr = unsigned_fract_type_node;
14096 tree node_ulr = unsigned_long_fract_type_node;
14097 tree node_ullr = unsigned_long_long_fract_type_node;
14099 tree node_hk = short_accum_type_node;
14100 tree node_nk = accum_type_node;
14101 tree node_lk = long_accum_type_node;
14102 tree node_llk = long_long_accum_type_node;
14104 tree node_uhk = unsigned_short_accum_type_node;
14105 tree node_unk = unsigned_accum_type_node;
14106 tree node_ulk = unsigned_long_accum_type_node;
14107 tree node_ullk = unsigned_long_long_accum_type_node;
14110 /* For absfx builtins. */
14112 FX_FTYPE_FX (h);
14113 FX_FTYPE_FX (n);
14114 FX_FTYPE_FX (l);
14115 FX_FTYPE_FX (ll);
14117 /* For roundfx builtins. */
14119 FX_FTYPE_FX_INT (h);
14120 FX_FTYPE_FX_INT (n);
14121 FX_FTYPE_FX_INT (l);
14122 FX_FTYPE_FX_INT (ll);
14124 FX_FTYPE_FX_INT (uh);
14125 FX_FTYPE_FX_INT (un);
14126 FX_FTYPE_FX_INT (ul);
14127 FX_FTYPE_FX_INT (ull);
14129 /* For countlsfx builtins. */
14131 INT_FTYPE_FX (h);
14132 INT_FTYPE_FX (n);
14133 INT_FTYPE_FX (l);
14134 INT_FTYPE_FX (ll);
14136 INT_FTYPE_FX (uh);
14137 INT_FTYPE_FX (un);
14138 INT_FTYPE_FX (ul);
14139 INT_FTYPE_FX (ull);
14141 /* For bitsfx builtins. */
14143 INTX_FTYPE_FX (h);
14144 INTX_FTYPE_FX (n);
14145 INTX_FTYPE_FX (l);
14146 INTX_FTYPE_FX (ll);
14148 INTX_FTYPE_FX (uh);
14149 INTX_FTYPE_FX (un);
14150 INTX_FTYPE_FX (ul);
14151 INTX_FTYPE_FX (ull);
14153 /* For fxbits builtins. */
14155 FX_FTYPE_INTX (h);
14156 FX_FTYPE_INTX (n);
14157 FX_FTYPE_INTX (l);
14158 FX_FTYPE_INTX (ll);
14160 FX_FTYPE_INTX (uh);
14161 FX_FTYPE_INTX (un);
14162 FX_FTYPE_INTX (ul);
14163 FX_FTYPE_INTX (ull);
14166 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
14168 int id = AVR_BUILTIN_ ## NAME; \
14169 const char *Name = "__builtin_avr_" #NAME; \
14170 char *name = (char*) alloca (1 + strlen (Name)); \
14172 gcc_assert (id < AVR_BUILTIN_COUNT); \
14173 avr_bdesc[id].fndecl \
14174 = add_builtin_function (avr_tolower (name, Name), TYPE, id, \
14175 BUILT_IN_MD, LIBNAME, NULL_TREE); \
14177 #include "builtins.def"
14178 #undef DEF_BUILTIN
14180 avr_init_builtin_int24 ();
14184 /* Subroutine of avr_expand_builtin to expand vanilla builtins
14185 with non-void result and 1 ... 3 arguments. */
14187 static rtx
14188 avr_default_expand_builtin (enum insn_code icode, tree exp, rtx target)
14190 rtx pat, xop[3];
14191 int n_args = call_expr_nargs (exp);
14192 machine_mode tmode = insn_data[icode].operand[0].mode;
14194 gcc_assert (n_args >= 1 && n_args <= 3);
14196 if (target == NULL_RTX
14197 || GET_MODE (target) != tmode
14198 || !insn_data[icode].operand[0].predicate (target, tmode))
14200 target = gen_reg_rtx (tmode);
14203 for (int n = 0; n < n_args; n++)
14205 tree arg = CALL_EXPR_ARG (exp, n);
14206 rtx op = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14207 machine_mode opmode = GET_MODE (op);
14208 machine_mode mode = insn_data[icode].operand[n + 1].mode;
14210 if ((opmode == SImode || opmode == VOIDmode) && mode == HImode)
14212 opmode = HImode;
14213 op = gen_lowpart (HImode, op);
14216 /* In case the insn wants input operands in modes different from
14217 the result, abort. */
14219 gcc_assert (opmode == mode || opmode == VOIDmode);
14221 if (!insn_data[icode].operand[n + 1].predicate (op, mode))
14222 op = copy_to_mode_reg (mode, op);
14224 xop[n] = op;
14227 switch (n_args)
14229 case 1: pat = GEN_FCN (icode) (target, xop[0]); break;
14230 case 2: pat = GEN_FCN (icode) (target, xop[0], xop[1]); break;
14231 case 3: pat = GEN_FCN (icode) (target, xop[0], xop[1], xop[2]); break;
14233 default:
14234 gcc_unreachable();
14237 if (pat == NULL_RTX)
14238 return NULL_RTX;
14240 emit_insn (pat);
14242 return target;
14246 /* Implement `TARGET_EXPAND_BUILTIN'. */
14247 /* Expand an expression EXP that calls a built-in function,
14248 with result going to TARGET if that's convenient
14249 (and in mode MODE if that's convenient).
14250 SUBTARGET may be used as the target for computing one of EXP's operands.
14251 IGNORE is nonzero if the value is to be ignored. */
14253 static rtx
14254 avr_expand_builtin (tree exp, rtx target,
14255 rtx subtarget ATTRIBUTE_UNUSED,
14256 machine_mode mode ATTRIBUTE_UNUSED,
14257 int ignore)
14259 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
14260 const char *bname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
14261 unsigned int id = DECL_FUNCTION_CODE (fndecl);
14262 const struct avr_builtin_description *d = &avr_bdesc[id];
14263 tree arg0;
14264 rtx op0;
14266 gcc_assert (id < AVR_BUILTIN_COUNT);
14268 switch (id)
14270 case AVR_BUILTIN_NOP:
14271 emit_insn (gen_nopv (GEN_INT (1)));
14272 return 0;
14274 case AVR_BUILTIN_DELAY_CYCLES:
14276 arg0 = CALL_EXPR_ARG (exp, 0);
14277 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14279 if (!CONST_INT_P (op0))
14280 error ("%s expects a compile time integer constant", bname);
14281 else
14282 avr_expand_delay_cycles (op0);
14284 return NULL_RTX;
14287 case AVR_BUILTIN_NOPS:
14289 arg0 = CALL_EXPR_ARG (exp, 0);
14290 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14292 if (!CONST_INT_P (op0))
14293 error ("%s expects a compile time integer constant", bname);
14294 else
14295 avr_expand_nops (op0);
14297 return NULL_RTX;
14300 case AVR_BUILTIN_INSERT_BITS:
14302 arg0 = CALL_EXPR_ARG (exp, 0);
14303 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14305 if (!CONST_INT_P (op0))
14307 error ("%s expects a compile time long integer constant"
14308 " as first argument", bname);
14309 return target;
14312 break;
14315 case AVR_BUILTIN_ROUNDHR: case AVR_BUILTIN_ROUNDUHR:
14316 case AVR_BUILTIN_ROUNDR: case AVR_BUILTIN_ROUNDUR:
14317 case AVR_BUILTIN_ROUNDLR: case AVR_BUILTIN_ROUNDULR:
14318 case AVR_BUILTIN_ROUNDLLR: case AVR_BUILTIN_ROUNDULLR:
14320 case AVR_BUILTIN_ROUNDHK: case AVR_BUILTIN_ROUNDUHK:
14321 case AVR_BUILTIN_ROUNDK: case AVR_BUILTIN_ROUNDUK:
14322 case AVR_BUILTIN_ROUNDLK: case AVR_BUILTIN_ROUNDULK:
14323 case AVR_BUILTIN_ROUNDLLK: case AVR_BUILTIN_ROUNDULLK:
14325 /* Warn about odd rounding. Rounding points >= FBIT will have
14326 no effect. */
14328 if (TREE_CODE (CALL_EXPR_ARG (exp, 1)) != INTEGER_CST)
14329 break;
14331 int rbit = (int) TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1));
14333 if (rbit >= (int) GET_MODE_FBIT (mode))
14335 warning (OPT_Wextra, "rounding to %d bits has no effect for "
14336 "fixed-point value with %d fractional bits",
14337 rbit, GET_MODE_FBIT (mode));
14339 return expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX, mode,
14340 EXPAND_NORMAL);
14342 else if (rbit <= - (int) GET_MODE_IBIT (mode))
14344 warning (0, "rounding result will always be 0");
14345 return CONST0_RTX (mode);
14348 /* The rounding points RP satisfies now: -IBIT < RP < FBIT.
14350 TR 18037 only specifies results for RP > 0. However, the
14351 remaining cases of -IBIT < RP <= 0 can easily be supported
14352 without any additional overhead. */
14354 break; /* round */
14357 /* No fold found and no insn: Call support function from libgcc. */
14359 if (d->icode == CODE_FOR_nothing
14360 && DECL_ASSEMBLER_NAME (get_callee_fndecl (exp)) != NULL_TREE)
14362 return expand_call (exp, target, ignore);
14365 /* No special treatment needed: vanilla expand. */
14367 gcc_assert (d->icode != CODE_FOR_nothing);
14368 gcc_assert (d->n_args == call_expr_nargs (exp));
14370 if (d->n_args == 0)
14372 emit_insn ((GEN_FCN (d->icode)) (target));
14373 return NULL_RTX;
14376 return avr_default_expand_builtin (d->icode, exp, target);
14380 /* Helper for `avr_fold_builtin' that folds absfx (FIXED_CST). */
14382 static tree
14383 avr_fold_absfx (tree tval)
14385 if (FIXED_CST != TREE_CODE (tval))
14386 return NULL_TREE;
14388 /* Our fixed-points have no padding: Use double_int payload directly. */
14390 FIXED_VALUE_TYPE fval = TREE_FIXED_CST (tval);
14391 unsigned int bits = GET_MODE_BITSIZE (fval.mode);
14392 double_int ival = fval.data.sext (bits);
14394 if (!ival.is_negative())
14395 return tval;
14397 /* ISO/IEC TR 18037, 7.18a.6.2: The absfx functions are saturating. */
14399 fval.data = (ival == double_int::min_value (bits, false).sext (bits))
14400 ? double_int::max_value (bits, false)
14401 : -ival;
14403 return build_fixed (TREE_TYPE (tval), fval);
14407 /* Implement `TARGET_FOLD_BUILTIN'. */
14409 static tree
14410 avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg,
14411 bool ignore ATTRIBUTE_UNUSED)
14413 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
14414 tree val_type = TREE_TYPE (TREE_TYPE (fndecl));
14416 if (!optimize)
14417 return NULL_TREE;
14419 switch (fcode)
14421 default:
14422 break;
14424 case AVR_BUILTIN_SWAP:
14426 return fold_build2 (LROTATE_EXPR, val_type, arg[0],
14427 build_int_cst (val_type, 4));
14430 case AVR_BUILTIN_ABSHR:
14431 case AVR_BUILTIN_ABSR:
14432 case AVR_BUILTIN_ABSLR:
14433 case AVR_BUILTIN_ABSLLR:
14435 case AVR_BUILTIN_ABSHK:
14436 case AVR_BUILTIN_ABSK:
14437 case AVR_BUILTIN_ABSLK:
14438 case AVR_BUILTIN_ABSLLK:
14439 /* GCC is not good with folding ABS for fixed-point. Do it by hand. */
14441 return avr_fold_absfx (arg[0]);
14443 case AVR_BUILTIN_BITSHR: case AVR_BUILTIN_HRBITS:
14444 case AVR_BUILTIN_BITSHK: case AVR_BUILTIN_HKBITS:
14445 case AVR_BUILTIN_BITSUHR: case AVR_BUILTIN_UHRBITS:
14446 case AVR_BUILTIN_BITSUHK: case AVR_BUILTIN_UHKBITS:
14448 case AVR_BUILTIN_BITSR: case AVR_BUILTIN_RBITS:
14449 case AVR_BUILTIN_BITSK: case AVR_BUILTIN_KBITS:
14450 case AVR_BUILTIN_BITSUR: case AVR_BUILTIN_URBITS:
14451 case AVR_BUILTIN_BITSUK: case AVR_BUILTIN_UKBITS:
14453 case AVR_BUILTIN_BITSLR: case AVR_BUILTIN_LRBITS:
14454 case AVR_BUILTIN_BITSLK: case AVR_BUILTIN_LKBITS:
14455 case AVR_BUILTIN_BITSULR: case AVR_BUILTIN_ULRBITS:
14456 case AVR_BUILTIN_BITSULK: case AVR_BUILTIN_ULKBITS:
14458 case AVR_BUILTIN_BITSLLR: case AVR_BUILTIN_LLRBITS:
14459 case AVR_BUILTIN_BITSLLK: case AVR_BUILTIN_LLKBITS:
14460 case AVR_BUILTIN_BITSULLR: case AVR_BUILTIN_ULLRBITS:
14461 case AVR_BUILTIN_BITSULLK: case AVR_BUILTIN_ULLKBITS:
14463 gcc_assert (TYPE_PRECISION (val_type)
14464 == TYPE_PRECISION (TREE_TYPE (arg[0])));
14466 return build1 (VIEW_CONVERT_EXPR, val_type, arg[0]);
14468 case AVR_BUILTIN_INSERT_BITS:
14470 tree tbits = arg[1];
14471 tree tval = arg[2];
14472 tree tmap;
14473 tree map_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
14474 unsigned int map;
14475 bool changed = false;
14476 avr_map_op_t best_g;
14478 if (TREE_CODE (arg[0]) != INTEGER_CST)
14480 /* No constant as first argument: Don't fold this and run into
14481 error in avr_expand_builtin. */
14483 break;
14486 tmap = wide_int_to_tree (map_type, wi::to_wide (arg[0]));
14487 map = TREE_INT_CST_LOW (tmap);
14489 if (TREE_CODE (tval) != INTEGER_CST
14490 && avr_map_metric (map, MAP_MASK_PREIMAGE_F) == 0)
14492 /* There are no F in the map, i.e. 3rd operand is unused.
14493 Replace that argument with some constant to render
14494 respective input unused. */
14496 tval = build_int_cst (val_type, 0);
14497 changed = true;
14500 if (TREE_CODE (tbits) != INTEGER_CST
14501 && avr_map_metric (map, MAP_PREIMAGE_0_7) == 0)
14503 /* Similar for the bits to be inserted. If they are unused,
14504 we can just as well pass 0. */
14506 tbits = build_int_cst (val_type, 0);
14509 if (TREE_CODE (tbits) == INTEGER_CST)
14511 /* Inserting bits known at compile time is easy and can be
14512 performed by AND and OR with appropriate masks. */
14514 int bits = TREE_INT_CST_LOW (tbits);
14515 int mask_ior = 0, mask_and = 0xff;
14517 for (size_t i = 0; i < 8; i++)
14519 int mi = avr_map (map, i);
14521 if (mi < 8)
14523 if (bits & (1 << mi)) mask_ior |= (1 << i);
14524 else mask_and &= ~(1 << i);
14528 tval = fold_build2 (BIT_IOR_EXPR, val_type, tval,
14529 build_int_cst (val_type, mask_ior));
14530 return fold_build2 (BIT_AND_EXPR, val_type, tval,
14531 build_int_cst (val_type, mask_and));
14534 if (changed)
14535 return build_call_expr (fndecl, 3, tmap, tbits, tval);
14537 /* If bits don't change their position we can use vanilla logic
14538 to merge the two arguments. */
14540 if (avr_map_metric (map, MAP_NONFIXED_0_7) == 0)
14542 int mask_f = avr_map_metric (map, MAP_MASK_PREIMAGE_F);
14543 tree tres, tmask = build_int_cst (val_type, mask_f ^ 0xff);
14545 tres = fold_build2 (BIT_XOR_EXPR, val_type, tbits, tval);
14546 tres = fold_build2 (BIT_AND_EXPR, val_type, tres, tmask);
14547 return fold_build2 (BIT_XOR_EXPR, val_type, tres, tval);
14550 /* Try to decomposing map to reduce overall cost. */
14552 if (avr_log.builtin)
14553 avr_edump ("\n%?: %x\n%?: ROL cost: ", map);
14555 best_g = avr_map_op[0];
14556 best_g.cost = 1000;
14558 for (size_t i = 0; i < ARRAY_SIZE (avr_map_op); i++)
14560 avr_map_op_t g
14561 = avr_map_decompose (map, avr_map_op + i,
14562 TREE_CODE (tval) == INTEGER_CST);
14564 if (g.cost >= 0 && g.cost < best_g.cost)
14565 best_g = g;
14568 if (avr_log.builtin)
14569 avr_edump ("\n");
14571 if (best_g.arg == 0)
14572 /* No optimization found */
14573 break;
14575 /* Apply operation G to the 2nd argument. */
14577 if (avr_log.builtin)
14578 avr_edump ("%?: using OP(%s%d, %x) cost %d\n",
14579 best_g.str, best_g.arg, best_g.map, best_g.cost);
14581 /* Do right-shifts arithmetically: They copy the MSB instead of
14582 shifting in a non-usable value (0) as with logic right-shift. */
14584 tbits = fold_convert (signed_char_type_node, tbits);
14585 tbits = fold_build2 (best_g.code, signed_char_type_node, tbits,
14586 build_int_cst (val_type, best_g.arg));
14587 tbits = fold_convert (val_type, tbits);
14589 /* Use map o G^-1 instead of original map to undo the effect of G. */
14591 tmap = wide_int_to_tree (map_type, best_g.map);
14593 return build_call_expr (fndecl, 3, tmap, tbits, tval);
14594 } /* AVR_BUILTIN_INSERT_BITS */
14597 return NULL_TREE;
14602 /* Initialize the GCC target structure. */
14604 #undef TARGET_ASM_ALIGNED_HI_OP
14605 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
14606 #undef TARGET_ASM_ALIGNED_SI_OP
14607 #define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
14608 #undef TARGET_ASM_UNALIGNED_HI_OP
14609 #define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
14610 #undef TARGET_ASM_UNALIGNED_SI_OP
14611 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
14612 #undef TARGET_ASM_INTEGER
14613 #define TARGET_ASM_INTEGER avr_assemble_integer
14614 #undef TARGET_ASM_FILE_START
14615 #define TARGET_ASM_FILE_START avr_file_start
14616 #undef TARGET_ASM_FILE_END
14617 #define TARGET_ASM_FILE_END avr_file_end
14619 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
14620 #define TARGET_ASM_FUNCTION_END_PROLOGUE avr_asm_function_end_prologue
14621 #undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
14622 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE avr_asm_function_begin_epilogue
14624 #undef TARGET_FUNCTION_VALUE
14625 #define TARGET_FUNCTION_VALUE avr_function_value
14626 #undef TARGET_LIBCALL_VALUE
14627 #define TARGET_LIBCALL_VALUE avr_libcall_value
14628 #undef TARGET_FUNCTION_VALUE_REGNO_P
14629 #define TARGET_FUNCTION_VALUE_REGNO_P avr_function_value_regno_p
14631 #undef TARGET_ATTRIBUTE_TABLE
14632 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
14633 #undef TARGET_INSERT_ATTRIBUTES
14634 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
14635 #undef TARGET_SECTION_TYPE_FLAGS
14636 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
14638 #undef TARGET_ASM_NAMED_SECTION
14639 #define TARGET_ASM_NAMED_SECTION avr_asm_named_section
14640 #undef TARGET_ASM_INIT_SECTIONS
14641 #define TARGET_ASM_INIT_SECTIONS avr_asm_init_sections
14642 #undef TARGET_ENCODE_SECTION_INFO
14643 #define TARGET_ENCODE_SECTION_INFO avr_encode_section_info
14644 #undef TARGET_ASM_SELECT_SECTION
14645 #define TARGET_ASM_SELECT_SECTION avr_asm_select_section
14647 #undef TARGET_ASM_FINAL_POSTSCAN_INSN
14648 #define TARGET_ASM_FINAL_POSTSCAN_INSN avr_asm_final_postscan_insn
14650 #undef TARGET_REGISTER_MOVE_COST
14651 #define TARGET_REGISTER_MOVE_COST avr_register_move_cost
14652 #undef TARGET_MEMORY_MOVE_COST
14653 #define TARGET_MEMORY_MOVE_COST avr_memory_move_cost
14654 #undef TARGET_RTX_COSTS
14655 #define TARGET_RTX_COSTS avr_rtx_costs
14656 #undef TARGET_ADDRESS_COST
14657 #define TARGET_ADDRESS_COST avr_address_cost
14658 #undef TARGET_MACHINE_DEPENDENT_REORG
14659 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
14660 #undef TARGET_FUNCTION_ARG
14661 #define TARGET_FUNCTION_ARG avr_function_arg
14662 #undef TARGET_FUNCTION_ARG_ADVANCE
14663 #define TARGET_FUNCTION_ARG_ADVANCE avr_function_arg_advance
14665 #undef TARGET_SET_CURRENT_FUNCTION
14666 #define TARGET_SET_CURRENT_FUNCTION avr_set_current_function
14668 #undef TARGET_RETURN_IN_MEMORY
14669 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
14671 #undef TARGET_STRICT_ARGUMENT_NAMING
14672 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
14674 #undef TARGET_BUILTIN_SETJMP_FRAME_VALUE
14675 #define TARGET_BUILTIN_SETJMP_FRAME_VALUE avr_builtin_setjmp_frame_value
14677 #undef TARGET_CONDITIONAL_REGISTER_USAGE
14678 #define TARGET_CONDITIONAL_REGISTER_USAGE avr_conditional_register_usage
14680 #undef TARGET_HARD_REGNO_MODE_OK
14681 #define TARGET_HARD_REGNO_MODE_OK avr_hard_regno_mode_ok
14682 #undef TARGET_HARD_REGNO_SCRATCH_OK
14683 #define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok
14684 #undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED
14685 #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
14686 avr_hard_regno_call_part_clobbered
14688 #undef TARGET_CASE_VALUES_THRESHOLD
14689 #define TARGET_CASE_VALUES_THRESHOLD avr_case_values_threshold
14691 #undef TARGET_FRAME_POINTER_REQUIRED
14692 #define TARGET_FRAME_POINTER_REQUIRED avr_frame_pointer_required_p
14693 #undef TARGET_CAN_ELIMINATE
14694 #define TARGET_CAN_ELIMINATE avr_can_eliminate
14696 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
14697 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS avr_allocate_stack_slots_for_args
14699 #undef TARGET_WARN_FUNC_RETURN
14700 #define TARGET_WARN_FUNC_RETURN avr_warn_func_return
14702 #undef TARGET_CLASS_LIKELY_SPILLED_P
14703 #define TARGET_CLASS_LIKELY_SPILLED_P avr_class_likely_spilled_p
14705 #undef TARGET_OPTION_OVERRIDE
14706 #define TARGET_OPTION_OVERRIDE avr_option_override
14708 #undef TARGET_CANNOT_MODIFY_JUMPS_P
14709 #define TARGET_CANNOT_MODIFY_JUMPS_P avr_cannot_modify_jumps_p
14711 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
14712 #define TARGET_FUNCTION_OK_FOR_SIBCALL avr_function_ok_for_sibcall
14714 #undef TARGET_INIT_BUILTINS
14715 #define TARGET_INIT_BUILTINS avr_init_builtins
14717 #undef TARGET_BUILTIN_DECL
14718 #define TARGET_BUILTIN_DECL avr_builtin_decl
14720 #undef TARGET_EXPAND_BUILTIN
14721 #define TARGET_EXPAND_BUILTIN avr_expand_builtin
14723 #undef TARGET_FOLD_BUILTIN
14724 #define TARGET_FOLD_BUILTIN avr_fold_builtin
14726 #undef TARGET_SCALAR_MODE_SUPPORTED_P
14727 #define TARGET_SCALAR_MODE_SUPPORTED_P avr_scalar_mode_supported_p
14729 #undef TARGET_BUILD_BUILTIN_VA_LIST
14730 #define TARGET_BUILD_BUILTIN_VA_LIST avr_build_builtin_va_list
14732 #undef TARGET_FIXED_POINT_SUPPORTED_P
14733 #define TARGET_FIXED_POINT_SUPPORTED_P hook_bool_void_true
14735 #undef TARGET_CONVERT_TO_TYPE
14736 #define TARGET_CONVERT_TO_TYPE avr_convert_to_type
14738 #undef TARGET_LRA_P
14739 #define TARGET_LRA_P hook_bool_void_false
14741 #undef TARGET_ADDR_SPACE_SUBSET_P
14742 #define TARGET_ADDR_SPACE_SUBSET_P avr_addr_space_subset_p
14744 #undef TARGET_ADDR_SPACE_CONVERT
14745 #define TARGET_ADDR_SPACE_CONVERT avr_addr_space_convert
14747 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
14748 #define TARGET_ADDR_SPACE_ADDRESS_MODE avr_addr_space_address_mode
14750 #undef TARGET_ADDR_SPACE_POINTER_MODE
14751 #define TARGET_ADDR_SPACE_POINTER_MODE avr_addr_space_pointer_mode
14753 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
14754 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
14755 avr_addr_space_legitimate_address_p
14757 #undef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
14758 #define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS avr_addr_space_legitimize_address
14760 #undef TARGET_ADDR_SPACE_DIAGNOSE_USAGE
14761 #define TARGET_ADDR_SPACE_DIAGNOSE_USAGE avr_addr_space_diagnose_usage
14763 #undef TARGET_MODE_DEPENDENT_ADDRESS_P
14764 #define TARGET_MODE_DEPENDENT_ADDRESS_P avr_mode_dependent_address_p
14766 #undef TARGET_PRINT_OPERAND
14767 #define TARGET_PRINT_OPERAND avr_print_operand
14768 #undef TARGET_PRINT_OPERAND_ADDRESS
14769 #define TARGET_PRINT_OPERAND_ADDRESS avr_print_operand_address
14770 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
14771 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P avr_print_operand_punct_valid_p
14773 #undef TARGET_USE_BY_PIECES_INFRASTRUCTURE_P
14774 #define TARGET_USE_BY_PIECES_INFRASTRUCTURE_P \
14775 avr_use_by_pieces_infrastructure_p
14777 #undef TARGET_LEGITIMATE_COMBINED_INSN
14778 #define TARGET_LEGITIMATE_COMBINED_INSN avr_legitimate_combined_insn
14780 #undef TARGET_STARTING_FRAME_OFFSET
14781 #define TARGET_STARTING_FRAME_OFFSET avr_starting_frame_offset
14783 struct gcc_target targetm = TARGET_INITIALIZER;
14786 #include "gt-avr.h"