qimode_for_vec_perm
[official-gcc.git] / gcc / config / avr / avr.c
blobb69d42e34a6bd0fbc1305932ddd5dc7241691314
1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2 Copyright (C) 1998-2017 Free Software Foundation, Inc.
3 Contributed by Denis Chertykov (chertykov@gmail.com)
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
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 /* Disable -fdelete-null-pointer-checks option for AVR target.
734 This option compiler assumes that dereferencing of a null pointer
735 would halt the program. For AVR this assumption is not true and
736 programs can safely dereference null pointers. Changes made by this
737 option may not work properly for AVR. So disable this option. */
739 flag_delete_null_pointer_checks = 0;
741 /* caller-save.c looks for call-clobbered hard registers that are assigned
742 to pseudos that cross calls and tries so save-restore them around calls
743 in order to reduce the number of stack slots needed.
745 This might lead to situations where reload is no more able to cope
746 with the challenge of AVR's very few address registers and fails to
747 perform the requested spills. */
749 if (avr_strict_X)
750 flag_caller_saves = 0;
752 /* Allow optimizer to introduce store data races. This used to be the
753 default - it was changed because bigger targets did not see any
754 performance decrease. For the AVR though, disallowing data races
755 introduces additional code in LIM and increases reg pressure. */
757 maybe_set_param_value (PARAM_ALLOW_STORE_DATA_RACES, 1,
758 global_options.x_param_values,
759 global_options_set.x_param_values);
761 /* Unwind tables currently require a frame pointer for correctness,
762 see toplev.c:process_options(). */
764 if ((flag_unwind_tables
765 || flag_non_call_exceptions
766 || flag_asynchronous_unwind_tables)
767 && !ACCUMULATE_OUTGOING_ARGS)
769 flag_omit_frame_pointer = 0;
772 if (flag_pic == 1)
773 warning (OPT_fpic, "-fpic is not supported");
774 if (flag_pic == 2)
775 warning (OPT_fPIC, "-fPIC is not supported");
776 if (flag_pie == 1)
777 warning (OPT_fpie, "-fpie is not supported");
778 if (flag_pie == 2)
779 warning (OPT_fPIE, "-fPIE is not supported");
781 #if !defined (HAVE_AS_AVR_MGCCISR_OPTION)
782 avr_gasisr_prologues = 0;
783 #endif
785 if (!avr_set_core_architecture())
786 return;
788 /* RAM addresses of some SFRs common to all devices in respective arch. */
790 /* SREG: Status Register containing flags like I (global IRQ) */
791 avr_addr.sreg = 0x3F + avr_arch->sfr_offset;
793 /* RAMPZ: Address' high part when loading via ELPM */
794 avr_addr.rampz = 0x3B + avr_arch->sfr_offset;
796 avr_addr.rampy = 0x3A + avr_arch->sfr_offset;
797 avr_addr.rampx = 0x39 + avr_arch->sfr_offset;
798 avr_addr.rampd = 0x38 + avr_arch->sfr_offset;
799 avr_addr.ccp = (AVR_TINY ? 0x3C : 0x34) + avr_arch->sfr_offset;
801 /* SP: Stack Pointer (SP_H:SP_L) */
802 avr_addr.sp_l = 0x3D + avr_arch->sfr_offset;
803 avr_addr.sp_h = avr_addr.sp_l + 1;
805 init_machine_status = avr_init_machine_status;
807 avr_log_set_avr_log();
810 /* Function to set up the backend function structure. */
812 static struct machine_function *
813 avr_init_machine_status (void)
815 return ggc_cleared_alloc<machine_function> ();
819 /* Implement `INIT_EXPANDERS'. */
820 /* The function works like a singleton. */
822 void
823 avr_init_expanders (void)
825 for (int regno = 0; regno < 32; regno ++)
826 all_regs_rtx[regno] = gen_rtx_REG (QImode, regno);
828 lpm_reg_rtx = all_regs_rtx[LPM_REGNO];
829 tmp_reg_rtx = all_regs_rtx[AVR_TMP_REGNO];
830 zero_reg_rtx = all_regs_rtx[AVR_ZERO_REGNO];
832 lpm_addr_reg_rtx = gen_rtx_REG (HImode, REG_Z);
834 sreg_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.sreg));
835 rampd_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampd));
836 rampx_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampx));
837 rampy_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampy));
838 rampz_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampz));
840 xstring_empty = gen_rtx_CONST_STRING (VOIDmode, "");
841 xstring_e = gen_rtx_CONST_STRING (VOIDmode, "e");
843 /* TINY core does not have regs r10-r16, but avr-dimode.md expects them
844 to be present */
845 if (AVR_TINY)
846 avr_have_dimode = false;
850 /* Implement `REGNO_REG_CLASS'. */
851 /* Return register class for register R. */
853 enum reg_class
854 avr_regno_reg_class (int r)
856 static const enum reg_class reg_class_tab[] =
858 R0_REG,
859 /* r1 - r15 */
860 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
861 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
862 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
863 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
864 /* r16 - r23 */
865 SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
866 SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
867 /* r24, r25 */
868 ADDW_REGS, ADDW_REGS,
869 /* X: r26, 27 */
870 POINTER_X_REGS, POINTER_X_REGS,
871 /* Y: r28, r29 */
872 POINTER_Y_REGS, POINTER_Y_REGS,
873 /* Z: r30, r31 */
874 POINTER_Z_REGS, POINTER_Z_REGS,
875 /* SP: SPL, SPH */
876 STACK_REG, STACK_REG
879 if (r <= 33)
880 return reg_class_tab[r];
882 return ALL_REGS;
886 /* Implement `TARGET_SCALAR_MODE_SUPPORTED_P'. */
888 static bool
889 avr_scalar_mode_supported_p (scalar_mode mode)
891 if (ALL_FIXED_POINT_MODE_P (mode))
892 return true;
894 if (PSImode == mode)
895 return true;
897 return default_scalar_mode_supported_p (mode);
901 /* Return TRUE if DECL is a VAR_DECL located in flash and FALSE, otherwise. */
903 static bool
904 avr_decl_flash_p (tree decl)
906 if (TREE_CODE (decl) != VAR_DECL
907 || TREE_TYPE (decl) == error_mark_node)
909 return false;
912 return !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (decl)));
916 /* Return TRUE if DECL is a VAR_DECL located in the 24-bit flash
917 address space and FALSE, otherwise. */
919 static bool
920 avr_decl_memx_p (tree decl)
922 if (TREE_CODE (decl) != VAR_DECL
923 || TREE_TYPE (decl) == error_mark_node)
925 return false;
928 return (ADDR_SPACE_MEMX == TYPE_ADDR_SPACE (TREE_TYPE (decl)));
932 /* Return TRUE if X is a MEM rtx located in flash and FALSE, otherwise. */
934 bool
935 avr_mem_flash_p (rtx x)
937 return (MEM_P (x)
938 && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x)));
942 /* Return TRUE if X is a MEM rtx located in the 24-bit flash
943 address space and FALSE, otherwise. */
945 bool
946 avr_mem_memx_p (rtx x)
948 return (MEM_P (x)
949 && ADDR_SPACE_MEMX == MEM_ADDR_SPACE (x));
953 /* A helper for the subsequent function attribute used to dig for
954 attribute 'name' in a FUNCTION_DECL or FUNCTION_TYPE */
956 static inline int
957 avr_lookup_function_attribute1 (const_tree func, const char *name)
959 if (FUNCTION_DECL == TREE_CODE (func))
961 if (NULL_TREE != lookup_attribute (name, DECL_ATTRIBUTES (func)))
963 return true;
966 func = TREE_TYPE (func);
969 gcc_assert (TREE_CODE (func) == FUNCTION_TYPE
970 || TREE_CODE (func) == METHOD_TYPE);
972 return NULL_TREE != lookup_attribute (name, TYPE_ATTRIBUTES (func));
975 /* Return nonzero if FUNC is a naked function. */
977 static int
978 avr_naked_function_p (tree func)
980 return avr_lookup_function_attribute1 (func, "naked");
983 /* Return nonzero if FUNC is an interrupt function as specified
984 by the "interrupt" attribute. */
986 static int
987 avr_interrupt_function_p (tree func)
989 return avr_lookup_function_attribute1 (func, "interrupt");
992 /* Return nonzero if FUNC is a signal function as specified
993 by the "signal" attribute. */
995 static int
996 avr_signal_function_p (tree func)
998 return avr_lookup_function_attribute1 (func, "signal");
1001 /* Return nonzero if FUNC is an OS_task function. */
1003 static int
1004 avr_OS_task_function_p (tree func)
1006 return avr_lookup_function_attribute1 (func, "OS_task");
1009 /* Return nonzero if FUNC is an OS_main function. */
1011 static int
1012 avr_OS_main_function_p (tree func)
1014 return avr_lookup_function_attribute1 (func, "OS_main");
1018 /* Return nonzero if FUNC is a no_gccisr function as specified
1019 by the "no_gccisr" attribute. */
1021 static int
1022 avr_no_gccisr_function_p (tree func)
1024 return avr_lookup_function_attribute1 (func, "no_gccisr");
1027 /* Implement `TARGET_SET_CURRENT_FUNCTION'. */
1028 /* Sanity cheching for above function attributes. */
1030 static void
1031 avr_set_current_function (tree decl)
1033 location_t loc;
1034 const char *isr;
1036 if (decl == NULL_TREE
1037 || current_function_decl == NULL_TREE
1038 || current_function_decl == error_mark_node
1039 || ! cfun->machine
1040 || cfun->machine->attributes_checked_p)
1041 return;
1043 loc = DECL_SOURCE_LOCATION (decl);
1045 cfun->machine->is_naked = avr_naked_function_p (decl);
1046 cfun->machine->is_signal = avr_signal_function_p (decl);
1047 cfun->machine->is_interrupt = avr_interrupt_function_p (decl);
1048 cfun->machine->is_OS_task = avr_OS_task_function_p (decl);
1049 cfun->machine->is_OS_main = avr_OS_main_function_p (decl);
1050 cfun->machine->is_no_gccisr = avr_no_gccisr_function_p (decl);
1052 isr = cfun->machine->is_interrupt ? "interrupt" : "signal";
1054 /* Too much attributes make no sense as they request conflicting features. */
1056 if (cfun->machine->is_OS_task + cfun->machine->is_OS_main
1057 + (cfun->machine->is_signal || cfun->machine->is_interrupt) > 1)
1058 error_at (loc, "function attributes %qs, %qs and %qs are mutually"
1059 " exclusive", "OS_task", "OS_main", isr);
1061 /* 'naked' will hide effects of 'OS_task' and 'OS_main'. */
1063 if (cfun->machine->is_naked
1064 && (cfun->machine->is_OS_task || cfun->machine->is_OS_main))
1065 warning_at (loc, OPT_Wattributes, "function attributes %qs and %qs have"
1066 " no effect on %qs function", "OS_task", "OS_main", "naked");
1068 if (cfun->machine->is_interrupt || cfun->machine->is_signal)
1070 tree args = TYPE_ARG_TYPES (TREE_TYPE (decl));
1071 tree ret = TREE_TYPE (TREE_TYPE (decl));
1072 const char *name;
1074 name = DECL_ASSEMBLER_NAME_SET_P (decl)
1075 ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))
1076 : IDENTIFIER_POINTER (DECL_NAME (decl));
1078 /* Skip a leading '*' that might still prefix the assembler name,
1079 e.g. in non-LTO runs. */
1081 name = default_strip_name_encoding (name);
1083 /* Interrupt handlers must be void __vector (void) functions. */
1085 if (args && TREE_CODE (TREE_VALUE (args)) != VOID_TYPE)
1086 error_at (loc, "%qs function cannot have arguments", isr);
1088 if (TREE_CODE (ret) != VOID_TYPE)
1089 error_at (loc, "%qs function cannot return a value", isr);
1091 #if defined WITH_AVRLIBC
1092 /* Silently ignore 'signal' if 'interrupt' is present. AVR-LibC startet
1093 using this when it switched from SIGNAL and INTERRUPT to ISR. */
1095 if (cfun->machine->is_interrupt)
1096 cfun->machine->is_signal = 0;
1098 /* If the function has the 'signal' or 'interrupt' attribute, ensure
1099 that the name of the function is "__vector_NN" so as to catch
1100 when the user misspells the vector name. */
1102 if (!STR_PREFIX_P (name, "__vector"))
1103 warning_at (loc, OPT_Wmisspelled_isr, "%qs appears to be a misspelled "
1104 "%qs handler, missing %<__vector%> prefix", name, isr);
1105 #endif // AVR-LibC naming conventions
1108 #if defined WITH_AVRLIBC
1109 // Common problem is using "ISR" without first including avr/interrupt.h.
1110 const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
1111 name = default_strip_name_encoding (name);
1112 if (strcmp ("ISR", name) == 0
1113 || strcmp ("INTERRUPT", name) == 0
1114 || strcmp ("SIGNAL", name) == 0)
1116 warning_at (loc, OPT_Wmisspelled_isr, "%qs is a reserved identifier"
1117 " in AVR-LibC. Consider %<#include <avr/interrupt.h>%>"
1118 " before using the %qs macro", name, name);
1120 #endif // AVR-LibC naming conventions
1122 /* Don't print the above diagnostics more than once. */
1124 cfun->machine->attributes_checked_p = 1;
1128 /* Implement `ACCUMULATE_OUTGOING_ARGS'. */
1131 avr_accumulate_outgoing_args (void)
1133 if (!cfun)
1134 return TARGET_ACCUMULATE_OUTGOING_ARGS;
1136 /* FIXME: For setjmp and in avr_builtin_setjmp_frame_value we don't know
1137 what offset is correct. In some cases it is relative to
1138 virtual_outgoing_args_rtx and in others it is relative to
1139 virtual_stack_vars_rtx. For example code see
1140 gcc.c-torture/execute/built-in-setjmp.c
1141 gcc.c-torture/execute/builtins/sprintf-chk.c */
1143 return (TARGET_ACCUMULATE_OUTGOING_ARGS
1144 && !(cfun->calls_setjmp
1145 || cfun->has_nonlocal_label));
1149 /* Report contribution of accumulated outgoing arguments to stack size. */
1151 static inline int
1152 avr_outgoing_args_size (void)
1154 return (ACCUMULATE_OUTGOING_ARGS
1155 ? (HOST_WIDE_INT) crtl->outgoing_args_size : 0);
1159 /* Implement TARGET_STARTING_FRAME_OFFSET. */
1160 /* This is the offset from the frame pointer register to the first stack slot
1161 that contains a variable living in the frame. */
1163 static HOST_WIDE_INT
1164 avr_starting_frame_offset (void)
1166 return 1 + avr_outgoing_args_size ();
1170 /* Return the number of hard registers to push/pop in the prologue/epilogue
1171 of the current function, and optionally store these registers in SET. */
1173 static int
1174 avr_regs_to_save (HARD_REG_SET *set)
1176 int count;
1177 int int_or_sig_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1179 if (set)
1180 CLEAR_HARD_REG_SET (*set);
1181 count = 0;
1183 /* No need to save any registers if the function never returns or
1184 has the "OS_task" or "OS_main" attribute. */
1186 if (TREE_THIS_VOLATILE (current_function_decl)
1187 || cfun->machine->is_OS_task
1188 || cfun->machine->is_OS_main)
1189 return 0;
1191 for (int reg = 0; reg < 32; reg++)
1193 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
1194 any global register variables. */
1196 if (fixed_regs[reg])
1197 continue;
1199 if ((int_or_sig_p && !crtl->is_leaf && call_used_regs[reg])
1200 || (df_regs_ever_live_p (reg)
1201 && (int_or_sig_p || !call_used_regs[reg])
1202 /* Don't record frame pointer registers here. They are treated
1203 indivitually in prologue. */
1204 && !(frame_pointer_needed
1205 && (reg == REG_Y || reg == REG_Y + 1))))
1207 if (set)
1208 SET_HARD_REG_BIT (*set, reg);
1209 count++;
1212 return count;
1216 /* Implement `TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS' */
1218 static bool
1219 avr_allocate_stack_slots_for_args (void)
1221 return !cfun->machine->is_naked;
1225 /* Return true if register FROM can be eliminated via register TO. */
1227 static bool
1228 avr_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
1230 return ((frame_pointer_needed && to == FRAME_POINTER_REGNUM)
1231 || !frame_pointer_needed);
1235 /* Implement `TARGET_WARN_FUNC_RETURN'. */
1237 static bool
1238 avr_warn_func_return (tree decl)
1240 /* Naked functions are implemented entirely in assembly, including the
1241 return sequence, so suppress warnings about this. */
1243 return !avr_naked_function_p (decl);
1246 /* Compute offset between arg_pointer and frame_pointer. */
1249 avr_initial_elimination_offset (int from, int to)
1251 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
1252 return 0;
1253 else
1255 int offset = frame_pointer_needed ? 2 : 0;
1256 int avr_pc_size = AVR_HAVE_EIJMP_EICALL ? 3 : 2;
1258 // If FROM is ARG_POINTER_REGNUM, we are not in an ISR as ISRs
1259 // might not have arguments. Hence the following is not affected
1260 // by gasisr prologues.
1261 offset += avr_regs_to_save (NULL);
1262 return (get_frame_size () + avr_outgoing_args_size()
1263 + avr_pc_size + 1 + offset);
1268 /* Helper for the function below. */
1270 static void
1271 avr_adjust_type_node (tree *node, machine_mode mode, int sat_p)
1273 *node = make_node (FIXED_POINT_TYPE);
1274 TYPE_SATURATING (*node) = sat_p;
1275 TYPE_UNSIGNED (*node) = UNSIGNED_FIXED_POINT_MODE_P (mode);
1276 TYPE_IBIT (*node) = GET_MODE_IBIT (mode);
1277 TYPE_FBIT (*node) = GET_MODE_FBIT (mode);
1278 TYPE_PRECISION (*node) = GET_MODE_BITSIZE (mode);
1279 SET_TYPE_ALIGN (*node, 8);
1280 SET_TYPE_MODE (*node, mode);
1282 layout_type (*node);
1286 /* Implement `TARGET_BUILD_BUILTIN_VA_LIST'. */
1288 static tree
1289 avr_build_builtin_va_list (void)
1291 /* avr-modes.def adjusts [U]TA to be 64-bit modes with 48 fractional bits.
1292 This is more appropriate for the 8-bit machine AVR than 128-bit modes.
1293 The ADJUST_IBIT/FBIT are handled in toplev:init_adjust_machine_modes()
1294 which is auto-generated by genmodes, but the compiler assigns [U]DAmode
1295 to the long long accum modes instead of the desired [U]TAmode.
1297 Fix this now, right after node setup in tree.c:build_common_tree_nodes().
1298 This must run before c-cppbuiltin.c:builtin_define_fixed_point_constants()
1299 which built-in defines macros like __ULLACCUM_FBIT__ that are used by
1300 libgcc to detect IBIT and FBIT. */
1302 avr_adjust_type_node (&ta_type_node, TAmode, 0);
1303 avr_adjust_type_node (&uta_type_node, UTAmode, 0);
1304 avr_adjust_type_node (&sat_ta_type_node, TAmode, 1);
1305 avr_adjust_type_node (&sat_uta_type_node, UTAmode, 1);
1307 unsigned_long_long_accum_type_node = uta_type_node;
1308 long_long_accum_type_node = ta_type_node;
1309 sat_unsigned_long_long_accum_type_node = sat_uta_type_node;
1310 sat_long_long_accum_type_node = sat_ta_type_node;
1312 /* Dispatch to the default handler. */
1314 return std_build_builtin_va_list ();
1318 /* Implement `TARGET_BUILTIN_SETJMP_FRAME_VALUE'. */
1319 /* Actual start of frame is virtual_stack_vars_rtx this is offset from
1320 frame pointer by +TARGET_STARTING_FRAME_OFFSET.
1321 Using saved frame = virtual_stack_vars_rtx - TARGET_STARTING_FRAME_OFFSET
1322 avoids creating add/sub of offset in nonlocal goto and setjmp. */
1324 static rtx
1325 avr_builtin_setjmp_frame_value (void)
1327 rtx xval = gen_reg_rtx (Pmode);
1328 emit_insn (gen_subhi3 (xval, virtual_stack_vars_rtx,
1329 gen_int_mode (avr_starting_frame_offset (), Pmode)));
1330 return xval;
1334 /* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3-byte PC).
1335 This is return address of function. */
1338 avr_return_addr_rtx (int count, rtx tem)
1340 rtx r;
1342 /* Can only return this function's return address. Others not supported. */
1343 if (count)
1344 return NULL;
1346 if (AVR_3_BYTE_PC)
1348 r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+2");
1349 warning (0, "%<builtin_return_address%> contains only 2 bytes"
1350 " of address");
1352 else
1353 r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+1");
1355 cfun->machine->use_L__stack_usage = 1;
1357 r = gen_rtx_PLUS (Pmode, tem, r);
1358 r = gen_frame_mem (Pmode, memory_address (Pmode, r));
1359 r = gen_rtx_ROTATE (HImode, r, GEN_INT (8));
1360 return r;
1363 /* Return 1 if the function epilogue is just a single "ret". */
1366 avr_simple_epilogue (void)
1368 return (! frame_pointer_needed
1369 && get_frame_size () == 0
1370 && avr_outgoing_args_size() == 0
1371 && avr_regs_to_save (NULL) == 0
1372 && ! cfun->machine->is_interrupt
1373 && ! cfun->machine->is_signal
1374 && ! cfun->machine->is_naked
1375 && ! TREE_THIS_VOLATILE (current_function_decl));
1378 /* This function checks sequence of live registers. */
1380 static int
1381 sequent_regs_live (void)
1383 int live_seq = 0;
1384 int cur_seq = 0;
1386 for (int reg = 0; reg <= LAST_CALLEE_SAVED_REG; ++reg)
1388 if (fixed_regs[reg])
1390 /* Don't recognize sequences that contain global register
1391 variables. */
1393 if (live_seq != 0)
1394 return 0;
1395 else
1396 continue;
1399 if (!call_used_regs[reg])
1401 if (df_regs_ever_live_p (reg))
1403 ++live_seq;
1404 ++cur_seq;
1406 else
1407 cur_seq = 0;
1411 if (!frame_pointer_needed)
1413 if (df_regs_ever_live_p (REG_Y))
1415 ++live_seq;
1416 ++cur_seq;
1418 else
1419 cur_seq = 0;
1421 if (df_regs_ever_live_p (REG_Y + 1))
1423 ++live_seq;
1424 ++cur_seq;
1426 else
1427 cur_seq = 0;
1429 else
1431 cur_seq += 2;
1432 live_seq += 2;
1434 return (cur_seq == live_seq) ? live_seq : 0;
1437 namespace {
1438 static const pass_data avr_pass_data_pre_proep =
1440 RTL_PASS, // type
1441 "", // name (will be patched)
1442 OPTGROUP_NONE, // optinfo_flags
1443 TV_DF_SCAN, // tv_id
1444 0, // properties_required
1445 0, // properties_provided
1446 0, // properties_destroyed
1447 0, // todo_flags_start
1448 0 // todo_flags_finish
1452 class avr_pass_pre_proep : public rtl_opt_pass
1454 public:
1455 avr_pass_pre_proep (gcc::context *ctxt, const char *name)
1456 : rtl_opt_pass (avr_pass_data_pre_proep, ctxt)
1458 this->name = name;
1461 void compute_maybe_gasisr (function*);
1463 virtual unsigned int execute (function *fun)
1465 if (avr_gasisr_prologues
1466 // Whether this function is an ISR worth scanning at all.
1467 && !fun->machine->is_no_gccisr
1468 && (fun->machine->is_interrupt
1469 || fun->machine->is_signal)
1470 && !cfun->machine->is_naked
1471 // Paranoia: Non-local gotos and labels that might escape.
1472 && !cfun->calls_setjmp
1473 && !cfun->has_nonlocal_label
1474 && !cfun->has_forced_label_in_static)
1476 compute_maybe_gasisr (fun);
1479 return 0;
1482 }; // avr_pass_pre_proep
1484 } // anon namespace
1486 rtl_opt_pass*
1487 make_avr_pass_pre_proep (gcc::context *ctxt)
1489 return new avr_pass_pre_proep (ctxt, "avr-pre-proep");
1493 /* Set fun->machine->gasisr.maybe provided we don't find anything that
1494 prohibits GAS generating parts of ISR prologues / epilogues for us. */
1496 void
1497 avr_pass_pre_proep::compute_maybe_gasisr (function *fun)
1499 // Don't use BB iterators so that we see JUMP_TABLE_DATA.
1501 for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
1503 // Transparent calls always use [R]CALL and are filtered out by GAS.
1504 // ISRs don't use -mcall-prologues, hence what remains to be filtered
1505 // out are open coded (tail) calls.
1507 if (CALL_P (insn))
1508 return;
1510 // __tablejump2__ clobbers something and is targeted by JMP so
1511 // that GAS won't see its usage.
1513 if (AVR_HAVE_JMP_CALL
1514 && JUMP_TABLE_DATA_P (insn))
1515 return;
1517 // Non-local gotos not seen in *FUN.
1519 if (JUMP_P (insn)
1520 && find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
1521 return;
1524 fun->machine->gasisr.maybe = 1;
1528 /* Obtain the length sequence of insns. */
1531 get_sequence_length (rtx_insn *insns)
1533 int length = 0;
1535 for (rtx_insn *insn = insns; insn; insn = NEXT_INSN (insn))
1536 length += get_attr_length (insn);
1538 return length;
1542 /* Implement `INCOMING_RETURN_ADDR_RTX'. */
1545 avr_incoming_return_addr_rtx (void)
1547 /* The return address is at the top of the stack. Note that the push
1548 was via post-decrement, which means the actual address is off by one. */
1549 return gen_frame_mem (HImode, plus_constant (Pmode, stack_pointer_rtx, 1));
1553 /* Unset a bit in *SET. If successful, return the respective bit number.
1554 Otherwise, return -1 and *SET is unaltered. */
1556 static int
1557 avr_hregs_split_reg (HARD_REG_SET *set)
1559 for (int regno = 0; regno < 32; regno++)
1560 if (TEST_HARD_REG_BIT (*set, regno))
1562 // Don't remove a register from *SET which might indicate that
1563 // some RAMP* register might need ISR prologue / epilogue treatment.
1565 if (AVR_HAVE_RAMPX
1566 && (REG_X == regno || REG_X + 1 == regno)
1567 && TEST_HARD_REG_BIT (*set, REG_X)
1568 && TEST_HARD_REG_BIT (*set, REG_X + 1))
1569 continue;
1571 if (AVR_HAVE_RAMPY
1572 && !frame_pointer_needed
1573 && (REG_Y == regno || REG_Y + 1 == regno)
1574 && TEST_HARD_REG_BIT (*set, REG_Y)
1575 && TEST_HARD_REG_BIT (*set, REG_Y + 1))
1576 continue;
1578 if (AVR_HAVE_RAMPZ
1579 && (REG_Z == regno || REG_Z + 1 == regno)
1580 && TEST_HARD_REG_BIT (*set, REG_Z)
1581 && TEST_HARD_REG_BIT (*set, REG_Z + 1))
1582 continue;
1584 CLEAR_HARD_REG_BIT (*set, regno);
1585 return regno;
1588 return -1;
1592 /* Helper for expand_prologue. Emit a push of a byte register. */
1594 static void
1595 emit_push_byte (unsigned regno, bool frame_related_p)
1597 rtx mem, reg;
1598 rtx_insn *insn;
1600 mem = gen_rtx_POST_DEC (HImode, stack_pointer_rtx);
1601 mem = gen_frame_mem (QImode, mem);
1602 reg = gen_rtx_REG (QImode, regno);
1604 insn = emit_insn (gen_rtx_SET (mem, reg));
1605 if (frame_related_p)
1606 RTX_FRAME_RELATED_P (insn) = 1;
1608 cfun->machine->stack_usage++;
1612 /* Helper for expand_prologue. Emit a push of a SFR via register TREG.
1613 SFR is a MEM representing the memory location of the SFR.
1614 If CLR_P then clear the SFR after the push using zero_reg. */
1616 static void
1617 emit_push_sfr (rtx sfr, bool frame_related_p, bool clr_p, int treg)
1619 rtx_insn *insn;
1621 gcc_assert (MEM_P (sfr));
1623 /* IN treg, IO(SFR) */
1624 insn = emit_move_insn (all_regs_rtx[treg], sfr);
1625 if (frame_related_p)
1626 RTX_FRAME_RELATED_P (insn) = 1;
1628 /* PUSH treg */
1629 emit_push_byte (treg, frame_related_p);
1631 if (clr_p)
1633 /* OUT IO(SFR), __zero_reg__ */
1634 insn = emit_move_insn (sfr, const0_rtx);
1635 if (frame_related_p)
1636 RTX_FRAME_RELATED_P (insn) = 1;
1640 static void
1641 avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
1643 rtx_insn *insn;
1644 bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1645 int live_seq = sequent_regs_live ();
1647 HOST_WIDE_INT size_max
1648 = (HOST_WIDE_INT) GET_MODE_MASK (AVR_HAVE_8BIT_SP ? QImode : Pmode);
1650 bool minimize = (TARGET_CALL_PROLOGUES
1651 && size < size_max
1652 && live_seq
1653 && !isr_p
1654 && !cfun->machine->is_OS_task
1655 && !cfun->machine->is_OS_main
1656 && !AVR_TINY);
1658 if (minimize
1659 && (frame_pointer_needed
1660 || avr_outgoing_args_size() > 8
1661 || (AVR_2_BYTE_PC && live_seq > 6)
1662 || live_seq > 7))
1664 rtx pattern;
1665 int first_reg, reg, offset;
1667 emit_move_insn (gen_rtx_REG (HImode, REG_X),
1668 gen_int_mode (size, HImode));
1670 pattern = gen_call_prologue_saves (gen_int_mode (live_seq, HImode),
1671 gen_int_mode (live_seq+size, HImode));
1672 insn = emit_insn (pattern);
1673 RTX_FRAME_RELATED_P (insn) = 1;
1675 /* Describe the effect of the unspec_volatile call to prologue_saves.
1676 Note that this formulation assumes that add_reg_note pushes the
1677 notes to the front. Thus we build them in the reverse order of
1678 how we want dwarf2out to process them. */
1680 /* The function does always set frame_pointer_rtx, but whether that
1681 is going to be permanent in the function is frame_pointer_needed. */
1683 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1684 gen_rtx_SET ((frame_pointer_needed
1685 ? frame_pointer_rtx
1686 : stack_pointer_rtx),
1687 plus_constant (Pmode, stack_pointer_rtx,
1688 -(size + live_seq))));
1690 /* Note that live_seq always contains r28+r29, but the other
1691 registers to be saved are all below 18. */
1693 first_reg = (LAST_CALLEE_SAVED_REG + 1) - (live_seq - 2);
1695 for (reg = 29, offset = -live_seq + 1;
1696 reg >= first_reg;
1697 reg = (reg == 28 ? LAST_CALLEE_SAVED_REG : reg - 1), ++offset)
1699 rtx m, r;
1701 m = gen_rtx_MEM (QImode, plus_constant (Pmode, stack_pointer_rtx,
1702 offset));
1703 r = gen_rtx_REG (QImode, reg);
1704 add_reg_note (insn, REG_CFA_OFFSET, gen_rtx_SET (m, r));
1707 cfun->machine->stack_usage += size + live_seq;
1709 else /* !minimize */
1711 for (int reg = 0; reg < 32; ++reg)
1712 if (TEST_HARD_REG_BIT (set, reg))
1713 emit_push_byte (reg, true);
1715 if (frame_pointer_needed
1716 && (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main)))
1718 /* Push frame pointer. Always be consistent about the
1719 ordering of pushes -- epilogue_restores expects the
1720 register pair to be pushed low byte first. */
1722 emit_push_byte (REG_Y, true);
1723 emit_push_byte (REG_Y + 1, true);
1726 if (frame_pointer_needed
1727 && size == 0)
1729 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
1730 RTX_FRAME_RELATED_P (insn) = 1;
1733 if (size != 0)
1735 /* Creating a frame can be done by direct manipulation of the
1736 stack or via the frame pointer. These two methods are:
1737 fp = sp
1738 fp -= size
1739 sp = fp
1741 sp -= size
1742 fp = sp (*)
1743 the optimum method depends on function type, stack and
1744 frame size. To avoid a complex logic, both methods are
1745 tested and shortest is selected.
1747 There is also the case where SIZE != 0 and no frame pointer is
1748 needed; this can occur if ACCUMULATE_OUTGOING_ARGS is on.
1749 In that case, insn (*) is not needed in that case.
1750 We use the X register as scratch. This is save because in X
1751 is call-clobbered.
1752 In an interrupt routine, the case of SIZE != 0 together with
1753 !frame_pointer_needed can only occur if the function is not a
1754 leaf function and thus X has already been saved. */
1756 int irq_state = -1;
1757 HOST_WIDE_INT size_cfa = size, neg_size;
1758 rtx_insn *fp_plus_insns;
1759 rtx fp, my_fp;
1761 gcc_assert (frame_pointer_needed
1762 || !isr_p
1763 || !crtl->is_leaf);
1765 fp = my_fp = (frame_pointer_needed
1766 ? frame_pointer_rtx
1767 : gen_rtx_REG (Pmode, REG_X));
1769 if (AVR_HAVE_8BIT_SP)
1771 /* The high byte (r29) does not change:
1772 Prefer SUBI (1 cycle) over SBIW (2 cycles, same size). */
1774 my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
1777 /* Cut down size and avoid size = 0 so that we don't run
1778 into ICE like PR52488 in the remainder. */
1780 if (size > size_max)
1782 /* Don't error so that insane code from newlib still compiles
1783 and does not break building newlib. As PR51345 is implemented
1784 now, there are multilib variants with -msp8.
1786 If user wants sanity checks he can use -Wstack-usage=
1787 or similar options.
1789 For CFA we emit the original, non-saturated size so that
1790 the generic machinery is aware of the real stack usage and
1791 will print the above diagnostic as expected. */
1793 size = size_max;
1796 size = trunc_int_for_mode (size, GET_MODE (my_fp));
1797 neg_size = trunc_int_for_mode (-size, GET_MODE (my_fp));
1799 /************ Method 1: Adjust frame pointer ************/
1801 start_sequence ();
1803 /* Normally, the dwarf2out frame-related-expr interpreter does
1804 not expect to have the CFA change once the frame pointer is
1805 set up. Thus, we avoid marking the move insn below and
1806 instead indicate that the entire operation is complete after
1807 the frame pointer subtraction is done. */
1809 insn = emit_move_insn (fp, stack_pointer_rtx);
1810 if (frame_pointer_needed)
1812 RTX_FRAME_RELATED_P (insn) = 1;
1813 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1814 gen_rtx_SET (fp, stack_pointer_rtx));
1817 insn = emit_move_insn (my_fp, plus_constant (GET_MODE (my_fp),
1818 my_fp, neg_size));
1820 if (frame_pointer_needed)
1822 RTX_FRAME_RELATED_P (insn) = 1;
1823 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1824 gen_rtx_SET (fp, plus_constant (Pmode, fp,
1825 -size_cfa)));
1828 /* Copy to stack pointer. Note that since we've already
1829 changed the CFA to the frame pointer this operation
1830 need not be annotated if frame pointer is needed.
1831 Always move through unspec, see PR50063.
1832 For meaning of irq_state see movhi_sp_r insn. */
1834 if (cfun->machine->is_interrupt)
1835 irq_state = 1;
1837 if (TARGET_NO_INTERRUPTS
1838 || cfun->machine->is_signal
1839 || cfun->machine->is_OS_main)
1840 irq_state = 0;
1842 if (AVR_HAVE_8BIT_SP)
1843 irq_state = 2;
1845 insn = emit_insn (gen_movhi_sp_r (stack_pointer_rtx,
1846 fp, GEN_INT (irq_state)));
1847 if (!frame_pointer_needed)
1849 RTX_FRAME_RELATED_P (insn) = 1;
1850 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1851 gen_rtx_SET (stack_pointer_rtx,
1852 plus_constant (Pmode,
1853 stack_pointer_rtx,
1854 -size_cfa)));
1857 fp_plus_insns = get_insns ();
1858 end_sequence ();
1860 /************ Method 2: Adjust Stack pointer ************/
1862 /* Stack adjustment by means of RCALL . and/or PUSH __TMP_REG__
1863 can only handle specific offsets. */
1865 int n_rcall = size / (AVR_3_BYTE_PC ? 3 : 2);
1867 if (avr_sp_immediate_operand (gen_int_mode (-size, HImode), HImode)
1868 // Don't use more than 3 RCALLs.
1869 && n_rcall <= 3)
1871 rtx_insn *sp_plus_insns;
1873 start_sequence ();
1875 insn = emit_move_insn (stack_pointer_rtx,
1876 plus_constant (Pmode, stack_pointer_rtx,
1877 -size));
1878 RTX_FRAME_RELATED_P (insn) = 1;
1879 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1880 gen_rtx_SET (stack_pointer_rtx,
1881 plus_constant (Pmode,
1882 stack_pointer_rtx,
1883 -size_cfa)));
1884 if (frame_pointer_needed)
1886 insn = emit_move_insn (fp, stack_pointer_rtx);
1887 RTX_FRAME_RELATED_P (insn) = 1;
1890 sp_plus_insns = get_insns ();
1891 end_sequence ();
1893 /************ Use shortest method ************/
1895 emit_insn (get_sequence_length (sp_plus_insns)
1896 < get_sequence_length (fp_plus_insns)
1897 ? sp_plus_insns
1898 : fp_plus_insns);
1900 else
1902 emit_insn (fp_plus_insns);
1905 cfun->machine->stack_usage += size_cfa;
1906 } /* !minimize && size != 0 */
1907 } /* !minimize */
1911 /* Output function prologue. */
1913 void
1914 avr_expand_prologue (void)
1916 HARD_REG_SET set;
1917 HOST_WIDE_INT size;
1919 size = get_frame_size() + avr_outgoing_args_size();
1921 cfun->machine->stack_usage = 0;
1923 /* Prologue: naked. */
1924 if (cfun->machine->is_naked)
1926 return;
1929 avr_regs_to_save (&set);
1931 if (cfun->machine->is_interrupt || cfun->machine->is_signal)
1933 int treg = AVR_TMP_REGNO;
1934 /* Enable interrupts. */
1935 if (cfun->machine->is_interrupt)
1936 emit_insn (gen_enable_interrupt ());
1938 if (cfun->machine->gasisr.maybe)
1940 /* Let GAS PR21472 emit prologue preamble for us which handles SREG,
1941 ZERO_REG and TMP_REG and one additional, optional register for
1942 us in an optimal way. This even scans through inline asm. */
1944 cfun->machine->gasisr.yes = 1;
1946 // The optional reg or TMP_REG if we don't need one. If we need one,
1947 // remove that reg from SET so that it's not puhed / popped twice.
1948 // We also use it below instead of TMP_REG in some places.
1950 treg = avr_hregs_split_reg (&set);
1951 if (treg < 0)
1952 treg = AVR_TMP_REGNO;
1953 cfun->machine->gasisr.regno = treg;
1955 // The worst case of pushes. The exact number can be inferred
1956 // at assembly time by magic expression __gcc_isr.n_pushed.
1957 cfun->machine->stack_usage += 3 + (treg != AVR_TMP_REGNO);
1959 // Emit a Prologue chunk. Epilogue chunk(s) might follow.
1960 // The final Done chunk is emit by final postscan.
1961 emit_insn (gen_gasisr (GEN_INT (GASISR_Prologue), GEN_INT (treg)));
1963 else // !TARGET_GASISR_PROLOGUES: Classic, dumb prologue preamble.
1965 /* Push zero reg. */
1966 emit_push_byte (AVR_ZERO_REGNO, true);
1968 /* Push tmp reg. */
1969 emit_push_byte (AVR_TMP_REGNO, true);
1971 /* Push SREG. */
1972 /* ??? There's no dwarf2 column reserved for SREG. */
1973 emit_push_sfr (sreg_rtx, false, false /* clr */, AVR_TMP_REGNO);
1975 /* Clear zero reg. */
1976 emit_move_insn (zero_reg_rtx, const0_rtx);
1978 /* Prevent any attempt to delete the setting of ZERO_REG! */
1979 emit_use (zero_reg_rtx);
1982 /* Push and clear RAMPD/X/Y/Z if present and low-part register is used.
1983 ??? There are no dwarf2 columns reserved for RAMPD/X/Y/Z. */
1985 if (AVR_HAVE_RAMPD)
1986 emit_push_sfr (rampd_rtx, false /* frame */, true /* clr */, treg);
1988 if (AVR_HAVE_RAMPX
1989 && TEST_HARD_REG_BIT (set, REG_X)
1990 && TEST_HARD_REG_BIT (set, REG_X + 1))
1992 emit_push_sfr (rampx_rtx, false /* frame */, true /* clr */, treg);
1995 if (AVR_HAVE_RAMPY
1996 && (frame_pointer_needed
1997 || (TEST_HARD_REG_BIT (set, REG_Y)
1998 && TEST_HARD_REG_BIT (set, REG_Y + 1))))
2000 emit_push_sfr (rampy_rtx, false /* frame */, true /* clr */, treg);
2003 if (AVR_HAVE_RAMPZ
2004 && TEST_HARD_REG_BIT (set, REG_Z)
2005 && TEST_HARD_REG_BIT (set, REG_Z + 1))
2007 emit_push_sfr (rampz_rtx, false /* frame */, AVR_HAVE_RAMPD, treg);
2009 } /* is_interrupt is_signal */
2011 avr_prologue_setup_frame (size, set);
2013 if (flag_stack_usage_info)
2014 current_function_static_stack_size
2015 = cfun->machine->stack_usage + INCOMING_FRAME_SP_OFFSET;
2019 /* Implement `TARGET_ASM_FUNCTION_END_PROLOGUE'. */
2020 /* Output summary at end of function prologue. */
2022 static void
2023 avr_asm_function_end_prologue (FILE *file)
2025 if (cfun->machine->is_naked)
2027 fputs ("/* prologue: naked */\n", file);
2029 else
2031 if (cfun->machine->is_interrupt)
2033 fputs ("/* prologue: Interrupt */\n", file);
2035 else if (cfun->machine->is_signal)
2037 fputs ("/* prologue: Signal */\n", file);
2039 else
2040 fputs ("/* prologue: function */\n", file);
2043 if (ACCUMULATE_OUTGOING_ARGS)
2044 fprintf (file, "/* outgoing args size = %d */\n",
2045 avr_outgoing_args_size());
2047 fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n",
2048 (HOST_WIDE_INT) get_frame_size());
2050 if (!cfun->machine->gasisr.yes)
2052 fprintf (file, "/* stack size = %d */\n", cfun->machine->stack_usage);
2053 // Create symbol stack offset so all functions have it. Add 1 to stack
2054 // usage for offset so that SP + .L__stack_offset = return address.
2055 fprintf (file, ".L__stack_usage = %d\n", cfun->machine->stack_usage);
2057 else
2059 int used_by_gasisr = 3 + (cfun->machine->gasisr.regno != AVR_TMP_REGNO);
2060 int to = cfun->machine->stack_usage;
2061 int from = to - used_by_gasisr;
2062 // Number of pushed regs is only known at assembly-time.
2063 fprintf (file, "/* stack size = %d...%d */\n", from , to);
2064 fprintf (file, ".L__stack_usage = %d + __gcc_isr.n_pushed\n", from);
2069 /* Implement `EPILOGUE_USES'. */
2072 avr_epilogue_uses (int regno ATTRIBUTE_UNUSED)
2074 if (reload_completed
2075 && cfun->machine
2076 && (cfun->machine->is_interrupt || cfun->machine->is_signal))
2077 return 1;
2078 return 0;
2081 /* Helper for avr_expand_epilogue. Emit a pop of a byte register. */
2083 static void
2084 emit_pop_byte (unsigned regno)
2086 rtx mem, reg;
2088 mem = gen_rtx_PRE_INC (HImode, stack_pointer_rtx);
2089 mem = gen_frame_mem (QImode, mem);
2090 reg = gen_rtx_REG (QImode, regno);
2092 emit_insn (gen_rtx_SET (reg, mem));
2095 /* Output RTL epilogue. */
2097 void
2098 avr_expand_epilogue (bool sibcall_p)
2100 int live_seq;
2101 HARD_REG_SET set;
2102 int minimize;
2103 HOST_WIDE_INT size;
2104 bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
2106 size = get_frame_size() + avr_outgoing_args_size();
2108 /* epilogue: naked */
2109 if (cfun->machine->is_naked)
2111 gcc_assert (!sibcall_p);
2113 emit_jump_insn (gen_return ());
2114 return;
2117 avr_regs_to_save (&set);
2118 live_seq = sequent_regs_live ();
2120 minimize = (TARGET_CALL_PROLOGUES
2121 && live_seq
2122 && !isr_p
2123 && !cfun->machine->is_OS_task
2124 && !cfun->machine->is_OS_main
2125 && !AVR_TINY);
2127 if (minimize
2128 && (live_seq > 4
2129 || frame_pointer_needed
2130 || size))
2132 /* Get rid of frame. */
2134 if (!frame_pointer_needed)
2136 emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
2139 if (size)
2141 emit_move_insn (frame_pointer_rtx,
2142 plus_constant (Pmode, frame_pointer_rtx, size));
2145 emit_insn (gen_epilogue_restores (gen_int_mode (live_seq, HImode)));
2146 return;
2149 if (size)
2151 /* Try two methods to adjust stack and select shortest. */
2153 int irq_state = -1;
2154 rtx fp, my_fp;
2155 rtx_insn *fp_plus_insns;
2156 HOST_WIDE_INT size_max;
2158 gcc_assert (frame_pointer_needed
2159 || !isr_p
2160 || !crtl->is_leaf);
2162 fp = my_fp = (frame_pointer_needed
2163 ? frame_pointer_rtx
2164 : gen_rtx_REG (Pmode, REG_X));
2166 if (AVR_HAVE_8BIT_SP)
2168 /* The high byte (r29) does not change:
2169 Prefer SUBI (1 cycle) over SBIW (2 cycles). */
2171 my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
2174 /* For rationale see comment in prologue generation. */
2176 size_max = (HOST_WIDE_INT) GET_MODE_MASK (GET_MODE (my_fp));
2177 if (size > size_max)
2178 size = size_max;
2179 size = trunc_int_for_mode (size, GET_MODE (my_fp));
2181 /********** Method 1: Adjust fp register **********/
2183 start_sequence ();
2185 if (!frame_pointer_needed)
2186 emit_move_insn (fp, stack_pointer_rtx);
2188 emit_move_insn (my_fp, plus_constant (GET_MODE (my_fp), my_fp, size));
2190 /* Copy to stack pointer. */
2192 if (TARGET_NO_INTERRUPTS)
2193 irq_state = 0;
2195 if (AVR_HAVE_8BIT_SP)
2196 irq_state = 2;
2198 emit_insn (gen_movhi_sp_r (stack_pointer_rtx, fp,
2199 GEN_INT (irq_state)));
2201 fp_plus_insns = get_insns ();
2202 end_sequence ();
2204 /********** Method 2: Adjust Stack pointer **********/
2206 if (avr_sp_immediate_operand (gen_int_mode (size, HImode), HImode))
2208 rtx_insn *sp_plus_insns;
2210 start_sequence ();
2212 emit_move_insn (stack_pointer_rtx,
2213 plus_constant (Pmode, stack_pointer_rtx, size));
2215 sp_plus_insns = get_insns ();
2216 end_sequence ();
2218 /************ Use shortest method ************/
2220 emit_insn (get_sequence_length (sp_plus_insns)
2221 < get_sequence_length (fp_plus_insns)
2222 ? sp_plus_insns
2223 : fp_plus_insns);
2225 else
2226 emit_insn (fp_plus_insns);
2227 } /* size != 0 */
2229 if (frame_pointer_needed
2230 && !(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
2232 /* Restore previous frame_pointer. See avr_expand_prologue for
2233 rationale for not using pophi. */
2235 emit_pop_byte (REG_Y + 1);
2236 emit_pop_byte (REG_Y);
2239 /* Restore used registers. */
2241 int treg = AVR_TMP_REGNO;
2243 if (isr_p
2244 && cfun->machine->gasisr.yes)
2246 treg = cfun->machine->gasisr.regno;
2247 CLEAR_HARD_REG_BIT (set, treg);
2250 for (int reg = 31; reg >= 0; --reg)
2251 if (TEST_HARD_REG_BIT (set, reg))
2252 emit_pop_byte (reg);
2254 if (isr_p)
2256 /* Restore RAMPZ/Y/X/D using tmp_reg as scratch.
2257 The conditions to restore them must be tha same as in prologue. */
2259 if (AVR_HAVE_RAMPZ
2260 && TEST_HARD_REG_BIT (set, REG_Z)
2261 && TEST_HARD_REG_BIT (set, REG_Z + 1))
2263 emit_pop_byte (treg);
2264 emit_move_insn (rampz_rtx, all_regs_rtx[treg]);
2267 if (AVR_HAVE_RAMPY
2268 && (frame_pointer_needed
2269 || (TEST_HARD_REG_BIT (set, REG_Y)
2270 && TEST_HARD_REG_BIT (set, REG_Y + 1))))
2272 emit_pop_byte (treg);
2273 emit_move_insn (rampy_rtx, all_regs_rtx[treg]);
2276 if (AVR_HAVE_RAMPX
2277 && TEST_HARD_REG_BIT (set, REG_X)
2278 && TEST_HARD_REG_BIT (set, REG_X + 1))
2280 emit_pop_byte (treg);
2281 emit_move_insn (rampx_rtx, all_regs_rtx[treg]);
2284 if (AVR_HAVE_RAMPD)
2286 emit_pop_byte (treg);
2287 emit_move_insn (rampd_rtx, all_regs_rtx[treg]);
2290 if (cfun->machine->gasisr.yes)
2292 // Emit an Epilogue chunk.
2293 emit_insn (gen_gasisr (GEN_INT (GASISR_Epilogue),
2294 GEN_INT (cfun->machine->gasisr.regno)));
2296 else // !TARGET_GASISR_PROLOGUES
2298 /* Restore SREG using tmp_reg as scratch. */
2300 emit_pop_byte (AVR_TMP_REGNO);
2301 emit_move_insn (sreg_rtx, tmp_reg_rtx);
2303 /* Restore tmp REG. */
2304 emit_pop_byte (AVR_TMP_REGNO);
2306 /* Restore zero REG. */
2307 emit_pop_byte (AVR_ZERO_REGNO);
2311 if (!sibcall_p)
2312 emit_jump_insn (gen_return ());
2316 /* Implement `TARGET_ASM_FUNCTION_BEGIN_EPILOGUE'. */
2318 static void
2319 avr_asm_function_begin_epilogue (FILE *file)
2321 app_disable();
2322 fprintf (file, "/* epilogue start */\n");
2326 /* Implement `TARGET_CANNOT_MODITY_JUMPS_P'. */
2328 static bool
2329 avr_cannot_modify_jumps_p (void)
2331 /* Naked Functions must not have any instructions after
2332 their epilogue, see PR42240 */
2334 if (reload_completed
2335 && cfun->machine
2336 && cfun->machine->is_naked)
2338 return true;
2341 return false;
2345 /* Implement `TARGET_MODE_DEPENDENT_ADDRESS_P'. */
2347 static bool
2348 avr_mode_dependent_address_p (const_rtx addr ATTRIBUTE_UNUSED, addr_space_t as)
2350 /* FIXME: Non-generic addresses are not mode-dependent in themselves.
2351 This hook just serves to hack around PR rtl-optimization/52543 by
2352 claiming that non-generic addresses were mode-dependent so that
2353 lower-subreg.c will skip these addresses. lower-subreg.c sets up fake
2354 RTXes to probe SET and MEM costs and assumes that MEM is always in the
2355 generic address space which is not true. */
2357 return !ADDR_SPACE_GENERIC_P (as);
2361 /* Return true if rtx X is a CONST_INT, CONST or SYMBOL_REF
2362 address with the `absdata' variable attribute, i.e. respective
2363 data can be read / written by LDS / STS instruction.
2364 This is used only for AVR_TINY. */
2366 static bool
2367 avr_address_tiny_absdata_p (rtx x, machine_mode mode)
2369 if (CONST == GET_CODE (x))
2370 x = XEXP (XEXP (x, 0), 0);
2372 if (SYMBOL_REF_P (x))
2373 return SYMBOL_REF_FLAGS (x) & AVR_SYMBOL_FLAG_TINY_ABSDATA;
2375 if (CONST_INT_P (x)
2376 && IN_RANGE (INTVAL (x), 0, 0xc0 - GET_MODE_SIZE (mode)))
2377 return true;
2379 return false;
2383 /* Helper function for `avr_legitimate_address_p'. */
2385 static inline bool
2386 avr_reg_ok_for_addr_p (rtx reg, addr_space_t as,
2387 RTX_CODE outer_code, bool strict)
2389 return (REG_P (reg)
2390 && (avr_regno_mode_code_ok_for_base_p (REGNO (reg), QImode,
2391 as, outer_code, UNKNOWN)
2392 || (!strict
2393 && REGNO (reg) >= FIRST_PSEUDO_REGISTER)));
2397 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
2398 machine for a memory operand of mode MODE. */
2400 static bool
2401 avr_legitimate_address_p (machine_mode mode, rtx x, bool strict)
2403 bool ok = CONSTANT_ADDRESS_P (x);
2405 switch (GET_CODE (x))
2407 case REG:
2408 ok = avr_reg_ok_for_addr_p (x, ADDR_SPACE_GENERIC,
2409 MEM, strict);
2411 if (strict
2412 && GET_MODE_SIZE (mode) > 4
2413 && REG_X == REGNO (x))
2415 ok = false;
2417 break;
2419 case POST_INC:
2420 case PRE_DEC:
2421 ok = avr_reg_ok_for_addr_p (XEXP (x, 0), ADDR_SPACE_GENERIC,
2422 GET_CODE (x), strict);
2423 break;
2425 case PLUS:
2427 rtx reg = XEXP (x, 0);
2428 rtx op1 = XEXP (x, 1);
2430 if (REG_P (reg)
2431 && CONST_INT_P (op1)
2432 && INTVAL (op1) >= 0)
2434 bool fit = IN_RANGE (INTVAL (op1), 0, MAX_LD_OFFSET (mode));
2436 if (fit)
2438 ok = (! strict
2439 || avr_reg_ok_for_addr_p (reg, ADDR_SPACE_GENERIC,
2440 PLUS, strict));
2442 if (reg == frame_pointer_rtx
2443 || reg == arg_pointer_rtx)
2445 ok = true;
2448 else if (frame_pointer_needed
2449 && reg == frame_pointer_rtx)
2451 ok = true;
2455 break;
2457 default:
2458 break;
2461 if (AVR_TINY
2462 && CONSTANT_ADDRESS_P (x))
2464 /* avrtiny's load / store instructions only cover addresses 0..0xbf:
2465 IN / OUT range is 0..0x3f and LDS / STS can access 0x40..0xbf. */
2467 ok = avr_address_tiny_absdata_p (x, mode);
2470 if (avr_log.legitimate_address_p)
2472 avr_edump ("\n%?: ret=%d, mode=%m strict=%d "
2473 "reload_completed=%d reload_in_progress=%d %s:",
2474 ok, mode, strict, reload_completed, reload_in_progress,
2475 reg_renumber ? "(reg_renumber)" : "");
2477 if (GET_CODE (x) == PLUS
2478 && REG_P (XEXP (x, 0))
2479 && CONST_INT_P (XEXP (x, 1))
2480 && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
2481 && reg_renumber)
2483 avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
2484 true_regnum (XEXP (x, 0)));
2487 avr_edump ("\n%r\n", x);
2490 return ok;
2494 /* Former implementation of TARGET_LEGITIMIZE_ADDRESS,
2495 now only a helper for avr_addr_space_legitimize_address. */
2496 /* Attempts to replace X with a valid
2497 memory address for an operand of mode MODE */
2499 static rtx
2500 avr_legitimize_address (rtx x, rtx oldx, machine_mode mode)
2502 bool big_offset_p = false;
2504 x = oldx;
2506 if (AVR_TINY)
2508 if (CONSTANT_ADDRESS_P (x)
2509 && ! avr_address_tiny_absdata_p (x, mode))
2511 x = force_reg (Pmode, x);
2515 if (GET_CODE (oldx) == PLUS
2516 && REG_P (XEXP (oldx, 0)))
2518 if (REG_P (XEXP (oldx, 1)))
2519 x = force_reg (GET_MODE (oldx), oldx);
2520 else if (CONST_INT_P (XEXP (oldx, 1)))
2522 int offs = INTVAL (XEXP (oldx, 1));
2523 if (frame_pointer_rtx != XEXP (oldx, 0)
2524 && offs > MAX_LD_OFFSET (mode))
2526 big_offset_p = true;
2527 x = force_reg (GET_MODE (oldx), oldx);
2532 if (avr_log.legitimize_address)
2534 avr_edump ("\n%?: mode=%m\n %r\n", mode, oldx);
2536 if (x != oldx)
2537 avr_edump (" %s --> %r\n", big_offset_p ? "(big offset)" : "", x);
2540 return x;
2544 /* Implement `LEGITIMIZE_RELOAD_ADDRESS'. */
2545 /* This will allow register R26/27 to be used where it is no worse than normal
2546 base pointers R28/29 or R30/31. For example, if base offset is greater
2547 than 63 bytes or for R++ or --R addressing. */
2550 avr_legitimize_reload_address (rtx *px, machine_mode mode,
2551 int opnum, int type, int addr_type,
2552 int ind_levels ATTRIBUTE_UNUSED,
2553 rtx (*mk_memloc)(rtx,int))
2555 rtx x = *px;
2557 if (avr_log.legitimize_reload_address)
2558 avr_edump ("\n%?:%m %r\n", mode, x);
2560 if (1 && (GET_CODE (x) == POST_INC
2561 || GET_CODE (x) == PRE_DEC))
2563 push_reload (XEXP (x, 0), XEXP (x, 0), &XEXP (x, 0), &XEXP (x, 0),
2564 POINTER_REGS, GET_MODE (x), GET_MODE (x), 0, 0,
2565 opnum, RELOAD_OTHER);
2567 if (avr_log.legitimize_reload_address)
2568 avr_edump (" RCLASS.1 = %R\n IN = %r\n OUT = %r\n",
2569 POINTER_REGS, XEXP (x, 0), XEXP (x, 0));
2571 return x;
2574 if (GET_CODE (x) == PLUS
2575 && REG_P (XEXP (x, 0))
2576 && reg_equiv_constant (REGNO (XEXP (x, 0))) == 0
2577 && CONST_INT_P (XEXP (x, 1))
2578 && INTVAL (XEXP (x, 1)) >= 1)
2580 bool fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
2582 if (fit)
2584 if (reg_equiv_address (REGNO (XEXP (x, 0))) != 0)
2586 int regno = REGNO (XEXP (x, 0));
2587 rtx mem = mk_memloc (x, regno);
2589 push_reload (XEXP (mem, 0), NULL_RTX, &XEXP (mem, 0), NULL,
2590 POINTER_REGS, Pmode, VOIDmode, 0, 0,
2591 1, (enum reload_type) addr_type);
2593 if (avr_log.legitimize_reload_address)
2594 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
2595 POINTER_REGS, XEXP (mem, 0), NULL_RTX);
2597 push_reload (mem, NULL_RTX, &XEXP (x, 0), NULL,
2598 BASE_POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
2599 opnum, (enum reload_type) type);
2601 if (avr_log.legitimize_reload_address)
2602 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
2603 BASE_POINTER_REGS, mem, NULL_RTX);
2605 return x;
2608 else if (! (frame_pointer_needed
2609 && XEXP (x, 0) == frame_pointer_rtx))
2611 push_reload (x, NULL_RTX, px, NULL,
2612 POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
2613 opnum, (enum reload_type) type);
2615 if (avr_log.legitimize_reload_address)
2616 avr_edump (" RCLASS.3 = %R\n IN = %r\n OUT = %r\n",
2617 POINTER_REGS, x, NULL_RTX);
2619 return x;
2623 return NULL_RTX;
2627 /* Helper function to print assembler resp. track instruction
2628 sequence lengths. Always return "".
2630 If PLEN == NULL:
2631 Output assembler code from template TPL with operands supplied
2632 by OPERANDS. This is just forwarding to output_asm_insn.
2634 If PLEN != NULL:
2635 If N_WORDS >= 0 Add N_WORDS to *PLEN.
2636 If N_WORDS < 0 Set *PLEN to -N_WORDS.
2637 Don't output anything.
2640 static const char*
2641 avr_asm_len (const char* tpl, rtx* operands, int* plen, int n_words)
2643 if (plen == NULL)
2644 output_asm_insn (tpl, operands);
2645 else
2647 if (n_words < 0)
2648 *plen = -n_words;
2649 else
2650 *plen += n_words;
2653 return "";
2657 /* Return a pointer register name as a string. */
2659 static const char*
2660 ptrreg_to_str (int regno)
2662 switch (regno)
2664 case REG_X: return "X";
2665 case REG_Y: return "Y";
2666 case REG_Z: return "Z";
2667 default:
2668 output_operand_lossage ("address operand requires constraint for"
2669 " X, Y, or Z register");
2671 return NULL;
2674 /* Return the condition name as a string.
2675 Used in conditional jump constructing */
2677 static const char*
2678 cond_string (enum rtx_code code)
2680 switch (code)
2682 case NE:
2683 return "ne";
2684 case EQ:
2685 return "eq";
2686 case GE:
2687 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
2688 return "pl";
2689 else
2690 return "ge";
2691 case LT:
2692 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
2693 return "mi";
2694 else
2695 return "lt";
2696 case GEU:
2697 return "sh";
2698 case LTU:
2699 return "lo";
2700 default:
2701 gcc_unreachable ();
2704 return "";
2708 /* Return true if rtx X is a CONST or SYMBOL_REF with progmem.
2709 This must be used for AVR_TINY only because on other cores
2710 the flash memory is not visible in the RAM address range and
2711 cannot be read by, say, LD instruction. */
2713 static bool
2714 avr_address_tiny_pm_p (rtx x)
2716 if (CONST == GET_CODE (x))
2717 x = XEXP (XEXP (x, 0), 0);
2719 if (SYMBOL_REF_P (x))
2720 return SYMBOL_REF_FLAGS (x) & AVR_SYMBOL_FLAG_TINY_PM;
2722 return false;
2725 /* Implement `TARGET_PRINT_OPERAND_ADDRESS'. */
2726 /* Output ADDR to FILE as address. */
2728 static void
2729 avr_print_operand_address (FILE *file, machine_mode /*mode*/, rtx addr)
2731 if (AVR_TINY
2732 && avr_address_tiny_pm_p (addr))
2734 addr = plus_constant (Pmode, addr, avr_arch->flash_pm_offset);
2737 switch (GET_CODE (addr))
2739 case REG:
2740 fprintf (file, "%s", ptrreg_to_str (REGNO (addr)));
2741 break;
2743 case PRE_DEC:
2744 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
2745 break;
2747 case POST_INC:
2748 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
2749 break;
2751 default:
2752 if (CONSTANT_ADDRESS_P (addr)
2753 && text_segment_operand (addr, VOIDmode))
2755 rtx x = addr;
2756 if (GET_CODE (x) == CONST)
2757 x = XEXP (x, 0);
2758 if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1)))
2760 /* Assembler gs() will implant word address. Make offset
2761 a byte offset inside gs() for assembler. This is
2762 needed because the more logical (constant+gs(sym)) is not
2763 accepted by gas. For 128K and smaller devices this is ok.
2764 For large devices it will create a trampoline to offset
2765 from symbol which may not be what the user really wanted. */
2767 fprintf (file, "gs(");
2768 output_addr_const (file, XEXP (x, 0));
2769 fprintf (file, "+" HOST_WIDE_INT_PRINT_DEC ")",
2770 2 * INTVAL (XEXP (x, 1)));
2771 if (AVR_3_BYTE_PC)
2772 if (warning (0, "pointer offset from symbol maybe incorrect"))
2774 output_addr_const (stderr, addr);
2775 fprintf (stderr, "\n");
2778 else
2780 fprintf (file, "gs(");
2781 output_addr_const (file, addr);
2782 fprintf (file, ")");
2785 else
2786 output_addr_const (file, addr);
2791 /* Implement `TARGET_PRINT_OPERAND_PUNCT_VALID_P'. */
2793 static bool
2794 avr_print_operand_punct_valid_p (unsigned char code)
2796 return code == '~' || code == '!';
2800 /* Implement `TARGET_PRINT_OPERAND'. */
2801 /* Output X as assembler operand to file FILE.
2802 For a description of supported %-codes, see top of avr.md. */
2804 static void
2805 avr_print_operand (FILE *file, rtx x, int code)
2807 int abcd = 0, ef = 0, ij = 0;
2809 if (code >= 'A' && code <= 'D')
2810 abcd = code - 'A';
2811 else if (code == 'E' || code == 'F')
2812 ef = code - 'E';
2813 else if (code == 'I' || code == 'J')
2814 ij = code - 'I';
2816 if (code == '~')
2818 if (!AVR_HAVE_JMP_CALL)
2819 fputc ('r', file);
2821 else if (code == '!')
2823 if (AVR_HAVE_EIJMP_EICALL)
2824 fputc ('e', file);
2826 else if (code == 't'
2827 || code == 'T')
2829 static int t_regno = -1;
2830 static int t_nbits = -1;
2832 if (REG_P (x) && t_regno < 0 && code == 'T')
2834 t_regno = REGNO (x);
2835 t_nbits = GET_MODE_BITSIZE (GET_MODE (x));
2837 else if (CONST_INT_P (x) && t_regno >= 0
2838 && IN_RANGE (INTVAL (x), 0, t_nbits - 1))
2840 int bpos = INTVAL (x);
2842 fprintf (file, "%s", reg_names[t_regno + bpos / 8]);
2843 if (code == 'T')
2844 fprintf (file, ",%d", bpos % 8);
2846 t_regno = -1;
2848 else
2849 fatal_insn ("operands to %T/%t must be reg + const_int:", x);
2851 else if (code == 'E' || code == 'F')
2853 rtx op = XEXP (x, 0);
2854 fprintf (file, "%s", reg_names[REGNO (op) + ef]);
2856 else if (code == 'I' || code == 'J')
2858 rtx op = XEXP (XEXP (x, 0), 0);
2859 fprintf (file, "%s", reg_names[REGNO (op) + ij]);
2861 else if (REG_P (x))
2863 if (x == zero_reg_rtx)
2864 fprintf (file, "__zero_reg__");
2865 else if (code == 'r' && REGNO (x) < 32)
2866 fprintf (file, "%d", (int) REGNO (x));
2867 else
2868 fprintf (file, "%s", reg_names[REGNO (x) + abcd]);
2870 else if (CONST_INT_P (x))
2872 HOST_WIDE_INT ival = INTVAL (x);
2874 if ('i' != code)
2875 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival + abcd);
2876 else if (low_io_address_operand (x, VOIDmode)
2877 || high_io_address_operand (x, VOIDmode))
2879 if (AVR_HAVE_RAMPZ && ival == avr_addr.rampz)
2880 fprintf (file, "__RAMPZ__");
2881 else if (AVR_HAVE_RAMPY && ival == avr_addr.rampy)
2882 fprintf (file, "__RAMPY__");
2883 else if (AVR_HAVE_RAMPX && ival == avr_addr.rampx)
2884 fprintf (file, "__RAMPX__");
2885 else if (AVR_HAVE_RAMPD && ival == avr_addr.rampd)
2886 fprintf (file, "__RAMPD__");
2887 else if ((AVR_XMEGA || AVR_TINY) && ival == avr_addr.ccp)
2888 fprintf (file, "__CCP__");
2889 else if (ival == avr_addr.sreg) fprintf (file, "__SREG__");
2890 else if (ival == avr_addr.sp_l) fprintf (file, "__SP_L__");
2891 else if (ival == avr_addr.sp_h) fprintf (file, "__SP_H__");
2892 else
2894 fprintf (file, HOST_WIDE_INT_PRINT_HEX,
2895 ival - avr_arch->sfr_offset);
2898 else
2899 fatal_insn ("bad address, not an I/O address:", x);
2901 else if (MEM_P (x))
2903 rtx addr = XEXP (x, 0);
2905 if (code == 'm')
2907 if (!CONSTANT_P (addr))
2908 fatal_insn ("bad address, not a constant:", addr);
2909 /* Assembler template with m-code is data - not progmem section */
2910 if (text_segment_operand (addr, VOIDmode))
2911 if (warning (0, "accessing data memory with"
2912 " program memory address"))
2914 output_addr_const (stderr, addr);
2915 fprintf(stderr,"\n");
2917 output_addr_const (file, addr);
2919 else if (code == 'i')
2921 avr_print_operand (file, addr, 'i');
2923 else if (code == 'o')
2925 if (GET_CODE (addr) != PLUS)
2926 fatal_insn ("bad address, not (reg+disp):", addr);
2928 avr_print_operand (file, XEXP (addr, 1), 0);
2930 else if (code == 'b')
2932 if (GET_CODE (addr) != PLUS)
2933 fatal_insn ("bad address, not (reg+disp):", addr);
2935 avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
2937 else if (code == 'p' || code == 'r')
2939 if (GET_CODE (addr) != POST_INC && GET_CODE (addr) != PRE_DEC)
2940 fatal_insn ("bad address, not post_inc or pre_dec:", addr);
2942 if (code == 'p')
2943 /* X, Y, Z */
2944 avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
2945 else
2946 avr_print_operand (file, XEXP (addr, 0), 0); /* r26, r28, r30 */
2948 else if (GET_CODE (addr) == PLUS)
2950 avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
2951 if (REGNO (XEXP (addr, 0)) == REG_X)
2952 fatal_insn ("internal compiler error. Bad address:"
2953 ,addr);
2954 fputc ('+', file);
2955 avr_print_operand (file, XEXP (addr, 1), code);
2957 else
2958 avr_print_operand_address (file, VOIDmode, addr);
2960 else if (code == 'i')
2962 if (SYMBOL_REF_P (x) && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO))
2963 avr_print_operand_address
2964 (file, VOIDmode, plus_constant (HImode, x, -avr_arch->sfr_offset));
2965 else
2966 fatal_insn ("bad address, not an I/O address:", x);
2968 else if (code == 'x')
2970 /* Constant progmem address - like used in jmp or call */
2971 if (text_segment_operand (x, VOIDmode) == 0)
2972 if (warning (0, "accessing program memory"
2973 " with data memory address"))
2975 output_addr_const (stderr, x);
2976 fprintf(stderr,"\n");
2978 /* Use normal symbol for direct address no linker trampoline needed */
2979 output_addr_const (file, x);
2981 else if (CONST_FIXED_P (x))
2983 HOST_WIDE_INT ival = INTVAL (avr_to_int_mode (x));
2984 if (code != 0)
2985 output_operand_lossage ("Unsupported code '%c' for fixed-point:",
2986 code);
2987 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);
2989 else if (CONST_DOUBLE_P (x))
2991 long val;
2992 if (GET_MODE (x) != SFmode)
2993 fatal_insn ("internal compiler error. Unknown mode:", x);
2994 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), val);
2995 fprintf (file, "0x%lx", val);
2997 else if (GET_CODE (x) == CONST_STRING)
2998 fputs (XSTR (x, 0), file);
2999 else if (code == 'j')
3000 fputs (cond_string (GET_CODE (x)), file);
3001 else if (code == 'k')
3002 fputs (cond_string (reverse_condition (GET_CODE (x))), file);
3003 else
3004 avr_print_operand_address (file, VOIDmode, x);
3008 /* Implement TARGET_USE_BY_PIECES_INFRASTRUCTURE_P. */
3010 /* Prefer sequence of loads/stores for moves of size upto
3011 two - two pairs of load/store instructions are always better
3012 than the 5 instruction sequence for a loop (1 instruction
3013 for loop counter setup, and 4 for the body of the loop). */
3015 static bool
3016 avr_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size,
3017 unsigned int align ATTRIBUTE_UNUSED,
3018 enum by_pieces_operation op,
3019 bool speed_p)
3021 if (op != MOVE_BY_PIECES
3022 || (speed_p && size > MOVE_MAX_PIECES))
3023 return default_use_by_pieces_infrastructure_p (size, align, op, speed_p);
3025 return size <= MOVE_MAX_PIECES;
3029 /* Worker function for `NOTICE_UPDATE_CC'. */
3030 /* Update the condition code in the INSN. */
3032 void
3033 avr_notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx_insn *insn)
3035 rtx set;
3036 enum attr_cc cc = get_attr_cc (insn);
3038 switch (cc)
3040 default:
3041 break;
3043 case CC_PLUS:
3044 case CC_LDI:
3046 rtx *op = recog_data.operand;
3047 int len_dummy, icc;
3049 /* Extract insn's operands. */
3050 extract_constrain_insn_cached (insn);
3052 switch (cc)
3054 default:
3055 gcc_unreachable();
3057 case CC_PLUS:
3058 avr_out_plus (insn, op, &len_dummy, &icc);
3059 cc = (enum attr_cc) icc;
3060 break;
3062 case CC_LDI:
3064 cc = (op[1] == CONST0_RTX (GET_MODE (op[0]))
3065 && reg_overlap_mentioned_p (op[0], zero_reg_rtx))
3066 /* Loading zero-reg with 0 uses CLR and thus clobbers cc0. */
3067 ? CC_CLOBBER
3068 /* Any other "r,rL" combination does not alter cc0. */
3069 : CC_NONE;
3071 break;
3072 } /* inner switch */
3074 break;
3076 } /* outer swicth */
3078 switch (cc)
3080 default:
3081 /* Special values like CC_OUT_PLUS from above have been
3082 mapped to "standard" CC_* values so we never come here. */
3084 gcc_unreachable();
3085 break;
3087 case CC_NONE:
3088 /* Insn does not affect CC at all, but it might set some registers
3089 that are stored in cc_status. If such a register is affected by
3090 the current insn, for example by means of a SET or a CLOBBER,
3091 then we must reset cc_status; cf. PR77326.
3093 Unfortunately, set_of cannot be used as reg_overlap_mentioned_p
3094 will abort on COMPARE (which might be found in cc_status.value1/2).
3095 Thus work out the registers set by the insn and regs mentioned
3096 in cc_status.value1/2. */
3098 if (cc_status.value1
3099 || cc_status.value2)
3101 HARD_REG_SET regs_used;
3102 HARD_REG_SET regs_set;
3103 CLEAR_HARD_REG_SET (regs_used);
3105 if (cc_status.value1
3106 && !CONSTANT_P (cc_status.value1))
3108 find_all_hard_regs (cc_status.value1, &regs_used);
3111 if (cc_status.value2
3112 && !CONSTANT_P (cc_status.value2))
3114 find_all_hard_regs (cc_status.value2, &regs_used);
3117 find_all_hard_reg_sets (insn, &regs_set, false);
3119 if (hard_reg_set_intersect_p (regs_used, regs_set))
3121 CC_STATUS_INIT;
3125 break; // CC_NONE
3127 case CC_SET_N:
3128 CC_STATUS_INIT;
3129 break;
3131 case CC_SET_ZN:
3132 set = single_set (insn);
3133 CC_STATUS_INIT;
3134 if (set)
3136 cc_status.flags |= CC_NO_OVERFLOW;
3137 cc_status.value1 = SET_DEST (set);
3139 break;
3141 case CC_SET_VZN:
3142 /* Insn like INC, DEC, NEG that set Z,N,V. We currently don't make use
3143 of this combination, cf. also PR61055. */
3144 CC_STATUS_INIT;
3145 break;
3147 case CC_SET_CZN:
3148 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
3149 The V flag may or may not be known but that's ok because
3150 alter_cond will change tests to use EQ/NE. */
3151 set = single_set (insn);
3152 CC_STATUS_INIT;
3153 if (set)
3155 cc_status.value1 = SET_DEST (set);
3156 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
3158 break;
3160 case CC_COMPARE:
3161 set = single_set (insn);
3162 CC_STATUS_INIT;
3163 if (set)
3164 cc_status.value1 = SET_SRC (set);
3165 break;
3167 case CC_CLOBBER:
3168 /* Insn doesn't leave CC in a usable state. */
3169 CC_STATUS_INIT;
3170 break;
3174 /* Choose mode for jump insn:
3175 1 - relative jump in range -63 <= x <= 62 ;
3176 2 - relative jump in range -2046 <= x <= 2045 ;
3177 3 - absolute jump (only for ATmega[16]03). */
3180 avr_jump_mode (rtx x, rtx_insn *insn)
3182 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_CODE (x) == LABEL_REF
3183 ? XEXP (x, 0) : x));
3184 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
3185 int jump_distance = cur_addr - dest_addr;
3187 if (IN_RANGE (jump_distance, -63, 62))
3188 return 1;
3189 else if (IN_RANGE (jump_distance, -2046, 2045))
3190 return 2;
3191 else if (AVR_HAVE_JMP_CALL)
3192 return 3;
3194 return 2;
3197 /* Return an AVR condition jump commands.
3198 X is a comparison RTX.
3199 LEN is a number returned by avr_jump_mode function.
3200 If REVERSE nonzero then condition code in X must be reversed. */
3202 const char*
3203 ret_cond_branch (rtx x, int len, int reverse)
3205 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
3207 switch (cond)
3209 case GT:
3210 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
3211 return (len == 1 ? ("breq .+2" CR_TAB
3212 "brpl %0") :
3213 len == 2 ? ("breq .+4" CR_TAB
3214 "brmi .+2" CR_TAB
3215 "rjmp %0") :
3216 ("breq .+6" CR_TAB
3217 "brmi .+4" CR_TAB
3218 "jmp %0"));
3220 else
3221 return (len == 1 ? ("breq .+2" CR_TAB
3222 "brge %0") :
3223 len == 2 ? ("breq .+4" CR_TAB
3224 "brlt .+2" CR_TAB
3225 "rjmp %0") :
3226 ("breq .+6" CR_TAB
3227 "brlt .+4" CR_TAB
3228 "jmp %0"));
3229 case GTU:
3230 return (len == 1 ? ("breq .+2" CR_TAB
3231 "brsh %0") :
3232 len == 2 ? ("breq .+4" CR_TAB
3233 "brlo .+2" CR_TAB
3234 "rjmp %0") :
3235 ("breq .+6" CR_TAB
3236 "brlo .+4" CR_TAB
3237 "jmp %0"));
3238 case LE:
3239 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
3240 return (len == 1 ? ("breq %0" CR_TAB
3241 "brmi %0") :
3242 len == 2 ? ("breq .+2" CR_TAB
3243 "brpl .+2" CR_TAB
3244 "rjmp %0") :
3245 ("breq .+2" CR_TAB
3246 "brpl .+4" CR_TAB
3247 "jmp %0"));
3248 else
3249 return (len == 1 ? ("breq %0" CR_TAB
3250 "brlt %0") :
3251 len == 2 ? ("breq .+2" CR_TAB
3252 "brge .+2" CR_TAB
3253 "rjmp %0") :
3254 ("breq .+2" CR_TAB
3255 "brge .+4" CR_TAB
3256 "jmp %0"));
3257 case LEU:
3258 return (len == 1 ? ("breq %0" CR_TAB
3259 "brlo %0") :
3260 len == 2 ? ("breq .+2" CR_TAB
3261 "brsh .+2" CR_TAB
3262 "rjmp %0") :
3263 ("breq .+2" CR_TAB
3264 "brsh .+4" CR_TAB
3265 "jmp %0"));
3266 default:
3267 if (reverse)
3269 switch (len)
3271 case 1:
3272 return "br%k1 %0";
3273 case 2:
3274 return ("br%j1 .+2" CR_TAB
3275 "rjmp %0");
3276 default:
3277 return ("br%j1 .+4" CR_TAB
3278 "jmp %0");
3281 else
3283 switch (len)
3285 case 1:
3286 return "br%j1 %0";
3287 case 2:
3288 return ("br%k1 .+2" CR_TAB
3289 "rjmp %0");
3290 default:
3291 return ("br%k1 .+4" CR_TAB
3292 "jmp %0");
3296 return "";
3300 /* Worker function for `FINAL_PRESCAN_INSN'. */
3301 /* Output insn cost for next insn. */
3303 void
3304 avr_final_prescan_insn (rtx_insn *insn, rtx *operand ATTRIBUTE_UNUSED,
3305 int num_operands ATTRIBUTE_UNUSED)
3307 if (avr_log.rtx_costs)
3309 rtx set = single_set (insn);
3311 if (set)
3312 fprintf (asm_out_file, "/* DEBUG: cost = %d. */\n",
3313 set_src_cost (SET_SRC (set), GET_MODE (SET_DEST (set)),
3314 optimize_insn_for_speed_p ()));
3315 else
3316 fprintf (asm_out_file, "/* DEBUG: pattern-cost = %d. */\n",
3317 rtx_cost (PATTERN (insn), VOIDmode, INSN, 0,
3318 optimize_insn_for_speed_p()));
3321 if (avr_log.insn_addresses)
3322 fprintf (asm_out_file, ";; ADDR = %d\n",
3323 (int) INSN_ADDRESSES (INSN_UID (insn)));
3327 /* Implement `TARGET_ASM_FINAL_POSTSCAN_INSN'. */
3328 /* When GAS generates (parts of) ISR prologue / epilogue for us, we must
3329 hint GAS about the end of the code to scan. There migh be code located
3330 after the last epilogue. */
3332 static void
3333 avr_asm_final_postscan_insn (FILE *stream, rtx_insn *insn, rtx*, int)
3335 if (cfun->machine->gasisr.yes
3336 && !next_real_insn (insn))
3338 app_disable();
3339 fprintf (stream, "\t__gcc_isr %d,r%d\n", GASISR_Done,
3340 cfun->machine->gasisr.regno);
3345 /* Return 0 if undefined, 1 if always true or always false. */
3348 avr_simplify_comparison_p (machine_mode mode, RTX_CODE op, rtx x)
3350 unsigned int max = (mode == QImode ? 0xff :
3351 mode == HImode ? 0xffff :
3352 mode == PSImode ? 0xffffff :
3353 mode == SImode ? 0xffffffff : 0);
3354 if (max && op && CONST_INT_P (x))
3356 if (unsigned_condition (op) != op)
3357 max >>= 1;
3359 if (max != (INTVAL (x) & max)
3360 && INTVAL (x) != 0xff)
3361 return 1;
3363 return 0;
3367 /* Worker function for `FUNCTION_ARG_REGNO_P'. */
3368 /* Returns nonzero if REGNO is the number of a hard
3369 register in which function arguments are sometimes passed. */
3372 avr_function_arg_regno_p (int r)
3374 return AVR_TINY ? IN_RANGE (r, 20, 25) : IN_RANGE (r, 8, 25);
3378 /* Worker function for `INIT_CUMULATIVE_ARGS'. */
3379 /* Initializing the variable cum for the state at the beginning
3380 of the argument list. */
3382 void
3383 avr_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
3384 tree fndecl ATTRIBUTE_UNUSED)
3386 cum->nregs = AVR_TINY ? 6 : 18;
3387 cum->regno = FIRST_CUM_REG;
3388 if (!libname && stdarg_p (fntype))
3389 cum->nregs = 0;
3391 /* Assume the calle may be tail called */
3393 cfun->machine->sibcall_fails = 0;
3396 /* Returns the number of registers to allocate for a function argument. */
3398 static int
3399 avr_num_arg_regs (machine_mode mode, const_tree type)
3401 int size;
3403 if (mode == BLKmode)
3404 size = int_size_in_bytes (type);
3405 else
3406 size = GET_MODE_SIZE (mode);
3408 /* Align all function arguments to start in even-numbered registers.
3409 Odd-sized arguments leave holes above them. */
3411 return (size + 1) & ~1;
3415 /* Implement `TARGET_FUNCTION_ARG'. */
3416 /* Controls whether a function argument is passed
3417 in a register, and which register. */
3419 static rtx
3420 avr_function_arg (cumulative_args_t cum_v, machine_mode mode,
3421 const_tree type, bool named ATTRIBUTE_UNUSED)
3423 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
3424 int bytes = avr_num_arg_regs (mode, type);
3426 if (cum->nregs && bytes <= cum->nregs)
3427 return gen_rtx_REG (mode, cum->regno - bytes);
3429 return NULL_RTX;
3433 /* Implement `TARGET_FUNCTION_ARG_ADVANCE'. */
3434 /* Update the summarizer variable CUM to advance past an argument
3435 in the argument list. */
3437 static void
3438 avr_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
3439 const_tree type, bool named ATTRIBUTE_UNUSED)
3441 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
3442 int bytes = avr_num_arg_regs (mode, type);
3444 cum->nregs -= bytes;
3445 cum->regno -= bytes;
3447 /* A parameter is being passed in a call-saved register. As the original
3448 contents of these regs has to be restored before leaving the function,
3449 a function must not pass arguments in call-saved regs in order to get
3450 tail-called. */
3452 if (cum->regno >= 8
3453 && cum->nregs >= 0
3454 && !call_used_regs[cum->regno])
3456 /* FIXME: We ship info on failing tail-call in struct machine_function.
3457 This uses internals of calls.c:expand_call() and the way args_so_far
3458 is used. targetm.function_ok_for_sibcall() needs to be extended to
3459 pass &args_so_far, too. At present, CUMULATIVE_ARGS is target
3460 dependent so that such an extension is not wanted. */
3462 cfun->machine->sibcall_fails = 1;
3465 /* Test if all registers needed by the ABI are actually available. If the
3466 user has fixed a GPR needed to pass an argument, an (implicit) function
3467 call will clobber that fixed register. See PR45099 for an example. */
3469 if (cum->regno >= 8
3470 && cum->nregs >= 0)
3472 for (int regno = cum->regno; regno < cum->regno + bytes; regno++)
3473 if (fixed_regs[regno])
3474 warning (0, "fixed register %s used to pass parameter to function",
3475 reg_names[regno]);
3478 if (cum->nregs <= 0)
3480 cum->nregs = 0;
3481 cum->regno = FIRST_CUM_REG;
3485 /* Implement `TARGET_FUNCTION_OK_FOR_SIBCALL' */
3486 /* Decide whether we can make a sibling call to a function. DECL is the
3487 declaration of the function being targeted by the call and EXP is the
3488 CALL_EXPR representing the call. */
3490 static bool
3491 avr_function_ok_for_sibcall (tree decl_callee, tree exp_callee)
3493 tree fntype_callee;
3495 /* Tail-calling must fail if callee-saved regs are used to pass
3496 function args. We must not tail-call when `epilogue_restores'
3497 is used. Unfortunately, we cannot tell at this point if that
3498 actually will happen or not, and we cannot step back from
3499 tail-calling. Thus, we inhibit tail-calling with -mcall-prologues. */
3501 if (cfun->machine->sibcall_fails
3502 || TARGET_CALL_PROLOGUES)
3504 return false;
3507 fntype_callee = TREE_TYPE (CALL_EXPR_FN (exp_callee));
3509 if (decl_callee)
3511 decl_callee = TREE_TYPE (decl_callee);
3513 else
3515 decl_callee = fntype_callee;
3517 while (FUNCTION_TYPE != TREE_CODE (decl_callee)
3518 && METHOD_TYPE != TREE_CODE (decl_callee))
3520 decl_callee = TREE_TYPE (decl_callee);
3524 /* Ensure that caller and callee have compatible epilogues */
3526 if (cfun->machine->is_interrupt
3527 || cfun->machine->is_signal
3528 || cfun->machine->is_naked
3529 || avr_naked_function_p (decl_callee)
3530 /* FIXME: For OS_task and OS_main, this might be over-conservative. */
3531 || (avr_OS_task_function_p (decl_callee)
3532 != cfun->machine->is_OS_task)
3533 || (avr_OS_main_function_p (decl_callee)
3534 != cfun->machine->is_OS_main))
3536 return false;
3539 return true;
3542 /***********************************************************************
3543 Functions for outputting various mov's for a various modes
3544 ************************************************************************/
3546 /* Return true if a value of mode MODE is read from flash by
3547 __load_* function from libgcc. */
3549 bool
3550 avr_load_libgcc_p (rtx op)
3552 machine_mode mode = GET_MODE (op);
3553 int n_bytes = GET_MODE_SIZE (mode);
3555 return (n_bytes > 2
3556 && !AVR_HAVE_LPMX
3557 && avr_mem_flash_p (op));
3560 /* Return true if a value of mode MODE is read by __xload_* function. */
3562 bool
3563 avr_xload_libgcc_p (machine_mode mode)
3565 int n_bytes = GET_MODE_SIZE (mode);
3567 return (n_bytes > 1
3568 || avr_n_flash > 1);
3572 /* Fixme: This is a hack because secondary reloads don't works as expected.
3574 Find an unused d-register to be used as scratch in INSN.
3575 EXCLUDE is either NULL_RTX or some register. In the case where EXCLUDE
3576 is a register, skip all possible return values that overlap EXCLUDE.
3577 The policy for the returned register is similar to that of
3578 `reg_unused_after', i.e. the returned register may overlap the SET_DEST
3579 of INSN.
3581 Return a QImode d-register or NULL_RTX if nothing found. */
3583 static rtx
3584 avr_find_unused_d_reg (rtx_insn *insn, rtx exclude)
3586 bool isr_p = (avr_interrupt_function_p (current_function_decl)
3587 || avr_signal_function_p (current_function_decl));
3589 for (int regno = 16; regno < 32; regno++)
3591 rtx reg = all_regs_rtx[regno];
3593 if ((exclude
3594 && reg_overlap_mentioned_p (exclude, reg))
3595 || fixed_regs[regno])
3597 continue;
3600 /* Try non-live register */
3602 if (!df_regs_ever_live_p (regno)
3603 && (TREE_THIS_VOLATILE (current_function_decl)
3604 || cfun->machine->is_OS_task
3605 || cfun->machine->is_OS_main
3606 || (!isr_p && call_used_regs[regno])))
3608 return reg;
3611 /* Any live register can be used if it is unused after.
3612 Prologue/epilogue will care for it as needed. */
3614 if (df_regs_ever_live_p (regno)
3615 && reg_unused_after (insn, reg))
3617 return reg;
3621 return NULL_RTX;
3625 /* Helper function for the next function in the case where only restricted
3626 version of LPM instruction is available. */
3628 static const char*
3629 avr_out_lpm_no_lpmx (rtx_insn *insn, rtx *xop, int *plen)
3631 rtx dest = xop[0];
3632 rtx addr = xop[1];
3633 int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
3634 int regno_dest;
3636 regno_dest = REGNO (dest);
3638 /* The implicit target register of LPM. */
3639 xop[3] = lpm_reg_rtx;
3641 switch (GET_CODE (addr))
3643 default:
3644 gcc_unreachable();
3646 case REG:
3648 gcc_assert (REG_Z == REGNO (addr));
3650 switch (n_bytes)
3652 default:
3653 gcc_unreachable();
3655 case 1:
3656 avr_asm_len ("%4lpm", xop, plen, 1);
3658 if (regno_dest != LPM_REGNO)
3659 avr_asm_len ("mov %0,%3", xop, plen, 1);
3661 return "";
3663 case 2:
3664 if (REGNO (dest) == REG_Z)
3665 return avr_asm_len ("%4lpm" CR_TAB
3666 "push %3" CR_TAB
3667 "adiw %2,1" CR_TAB
3668 "%4lpm" CR_TAB
3669 "mov %B0,%3" CR_TAB
3670 "pop %A0", xop, plen, 6);
3672 avr_asm_len ("%4lpm" CR_TAB
3673 "mov %A0,%3" CR_TAB
3674 "adiw %2,1" CR_TAB
3675 "%4lpm" CR_TAB
3676 "mov %B0,%3", xop, plen, 5);
3678 if (!reg_unused_after (insn, addr))
3679 avr_asm_len ("sbiw %2,1", xop, plen, 1);
3681 break; /* 2 */
3684 break; /* REG */
3686 case POST_INC:
3688 gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
3689 && n_bytes <= 4);
3691 if (regno_dest == LPM_REGNO)
3692 avr_asm_len ("%4lpm" CR_TAB
3693 "adiw %2,1", xop, plen, 2);
3694 else
3695 avr_asm_len ("%4lpm" CR_TAB
3696 "mov %A0,%3" CR_TAB
3697 "adiw %2,1", xop, plen, 3);
3699 if (n_bytes >= 2)
3700 avr_asm_len ("%4lpm" CR_TAB
3701 "mov %B0,%3" CR_TAB
3702 "adiw %2,1", xop, plen, 3);
3704 if (n_bytes >= 3)
3705 avr_asm_len ("%4lpm" CR_TAB
3706 "mov %C0,%3" CR_TAB
3707 "adiw %2,1", xop, plen, 3);
3709 if (n_bytes >= 4)
3710 avr_asm_len ("%4lpm" CR_TAB
3711 "mov %D0,%3" CR_TAB
3712 "adiw %2,1", xop, plen, 3);
3714 break; /* POST_INC */
3716 } /* switch CODE (addr) */
3718 return "";
3722 /* If PLEN == NULL: Ouput instructions to load a value from a memory location
3723 OP[1] in AS1 to register OP[0].
3724 If PLEN != 0 set *PLEN to the length in words of the instruction sequence.
3725 Return "". */
3727 const char*
3728 avr_out_lpm (rtx_insn *insn, rtx *op, int *plen)
3730 rtx xop[7];
3731 rtx dest = op[0];
3732 rtx src = SET_SRC (single_set (insn));
3733 rtx addr;
3734 int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
3735 int segment;
3736 RTX_CODE code;
3737 addr_space_t as = MEM_ADDR_SPACE (src);
3739 if (plen)
3740 *plen = 0;
3742 if (MEM_P (dest))
3744 warning (0, "writing to address space %qs not supported",
3745 avr_addrspace[MEM_ADDR_SPACE (dest)].name);
3747 return "";
3750 addr = XEXP (src, 0);
3751 code = GET_CODE (addr);
3753 gcc_assert (REG_P (dest));
3754 gcc_assert (REG == code || POST_INC == code);
3756 xop[0] = dest;
3757 xop[1] = addr;
3758 xop[2] = lpm_addr_reg_rtx;
3759 xop[4] = xstring_empty;
3760 xop[5] = tmp_reg_rtx;
3761 xop[6] = XEXP (rampz_rtx, 0);
3763 segment = avr_addrspace[as].segment;
3765 /* Set RAMPZ as needed. */
3767 if (segment)
3769 xop[4] = GEN_INT (segment);
3770 xop[3] = avr_find_unused_d_reg (insn, lpm_addr_reg_rtx);
3772 if (xop[3] != NULL_RTX)
3774 avr_asm_len ("ldi %3,%4" CR_TAB
3775 "out %i6,%3", xop, plen, 2);
3777 else if (segment == 1)
3779 avr_asm_len ("clr %5" CR_TAB
3780 "inc %5" CR_TAB
3781 "out %i6,%5", xop, plen, 3);
3783 else
3785 avr_asm_len ("mov %5,%2" CR_TAB
3786 "ldi %2,%4" CR_TAB
3787 "out %i6,%2" CR_TAB
3788 "mov %2,%5", xop, plen, 4);
3791 xop[4] = xstring_e;
3793 if (!AVR_HAVE_ELPMX)
3794 return avr_out_lpm_no_lpmx (insn, xop, plen);
3796 else if (!AVR_HAVE_LPMX)
3798 return avr_out_lpm_no_lpmx (insn, xop, plen);
3801 /* We have [E]LPMX: Output reading from Flash the comfortable way. */
3803 switch (GET_CODE (addr))
3805 default:
3806 gcc_unreachable();
3808 case REG:
3810 gcc_assert (REG_Z == REGNO (addr));
3812 switch (n_bytes)
3814 default:
3815 gcc_unreachable();
3817 case 1:
3818 return avr_asm_len ("%4lpm %0,%a2", xop, plen, 1);
3820 case 2:
3821 if (REGNO (dest) == REG_Z)
3822 return avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3823 "%4lpm %B0,%a2" CR_TAB
3824 "mov %A0,%5", xop, plen, 3);
3825 else
3827 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3828 "%4lpm %B0,%a2", xop, plen, 2);
3830 if (!reg_unused_after (insn, addr))
3831 avr_asm_len ("sbiw %2,1", xop, plen, 1);
3834 break; /* 2 */
3836 case 3:
3838 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3839 "%4lpm %B0,%a2+" CR_TAB
3840 "%4lpm %C0,%a2", xop, plen, 3);
3842 if (!reg_unused_after (insn, addr))
3843 avr_asm_len ("sbiw %2,2", xop, plen, 1);
3845 break; /* 3 */
3847 case 4:
3849 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3850 "%4lpm %B0,%a2+", xop, plen, 2);
3852 if (REGNO (dest) == REG_Z - 2)
3853 return avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3854 "%4lpm %C0,%a2" CR_TAB
3855 "mov %D0,%5", xop, plen, 3);
3856 else
3858 avr_asm_len ("%4lpm %C0,%a2+" CR_TAB
3859 "%4lpm %D0,%a2", xop, plen, 2);
3861 if (!reg_unused_after (insn, addr))
3862 avr_asm_len ("sbiw %2,3", xop, plen, 1);
3865 break; /* 4 */
3866 } /* n_bytes */
3868 break; /* REG */
3870 case POST_INC:
3872 gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
3873 && n_bytes <= 4);
3875 avr_asm_len ("%4lpm %A0,%a2+", xop, plen, 1);
3876 if (n_bytes >= 2) avr_asm_len ("%4lpm %B0,%a2+", xop, plen, 1);
3877 if (n_bytes >= 3) avr_asm_len ("%4lpm %C0,%a2+", xop, plen, 1);
3878 if (n_bytes >= 4) avr_asm_len ("%4lpm %D0,%a2+", xop, plen, 1);
3880 break; /* POST_INC */
3882 } /* switch CODE (addr) */
3884 if (xop[4] == xstring_e && AVR_HAVE_RAMPD)
3886 /* Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM. */
3888 xop[0] = zero_reg_rtx;
3889 avr_asm_len ("out %i6,%0", xop, plen, 1);
3892 return "";
3896 /* Worker function for xload_8 insn. */
3898 const char*
3899 avr_out_xload (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
3901 rtx xop[4];
3903 xop[0] = op[0];
3904 xop[1] = op[1];
3905 xop[2] = lpm_addr_reg_rtx;
3906 xop[3] = AVR_HAVE_LPMX ? op[0] : lpm_reg_rtx;
3908 avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, -1);
3910 avr_asm_len ("sbrc %1,7" CR_TAB
3911 "ld %3,%a2", xop, plen, 2);
3913 if (REGNO (xop[0]) != REGNO (xop[3]))
3914 avr_asm_len ("mov %0,%3", xop, plen, 1);
3916 return "";
3920 const char*
3921 output_movqi (rtx_insn *insn, rtx operands[], int *plen)
3923 rtx dest = operands[0];
3924 rtx src = operands[1];
3926 if (avr_mem_flash_p (src)
3927 || avr_mem_flash_p (dest))
3929 return avr_out_lpm (insn, operands, plen);
3932 gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 1);
3934 if (REG_P (dest))
3936 if (REG_P (src)) /* mov r,r */
3938 if (test_hard_reg_class (STACK_REG, dest))
3939 return avr_asm_len ("out %0,%1", operands, plen, -1);
3940 else if (test_hard_reg_class (STACK_REG, src))
3941 return avr_asm_len ("in %0,%1", operands, plen, -1);
3943 return avr_asm_len ("mov %0,%1", operands, plen, -1);
3945 else if (CONSTANT_P (src))
3947 output_reload_in_const (operands, NULL_RTX, plen, false);
3948 return "";
3950 else if (MEM_P (src))
3951 return out_movqi_r_mr (insn, operands, plen); /* mov r,m */
3953 else if (MEM_P (dest))
3955 rtx xop[2];
3957 xop[0] = dest;
3958 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
3960 return out_movqi_mr_r (insn, xop, plen);
3963 return "";
3967 const char *
3968 output_movhi (rtx_insn *insn, rtx xop[], int *plen)
3970 rtx dest = xop[0];
3971 rtx src = xop[1];
3973 gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 2);
3975 if (avr_mem_flash_p (src)
3976 || avr_mem_flash_p (dest))
3978 return avr_out_lpm (insn, xop, plen);
3981 if (REG_P (dest))
3983 if (REG_P (src)) /* mov r,r */
3985 if (test_hard_reg_class (STACK_REG, dest))
3987 if (AVR_HAVE_8BIT_SP)
3988 return avr_asm_len ("out __SP_L__,%A1", xop, plen, -1);
3990 if (AVR_XMEGA)
3991 return avr_asm_len ("out __SP_L__,%A1" CR_TAB
3992 "out __SP_H__,%B1", xop, plen, -2);
3994 /* Use simple load of SP if no interrupts are used. */
3996 return TARGET_NO_INTERRUPTS
3997 ? avr_asm_len ("out __SP_H__,%B1" CR_TAB
3998 "out __SP_L__,%A1", xop, plen, -2)
3999 : avr_asm_len ("in __tmp_reg__,__SREG__" CR_TAB
4000 "cli" CR_TAB
4001 "out __SP_H__,%B1" CR_TAB
4002 "out __SREG__,__tmp_reg__" CR_TAB
4003 "out __SP_L__,%A1", xop, plen, -5);
4005 else if (test_hard_reg_class (STACK_REG, src))
4007 return !AVR_HAVE_SPH
4008 ? avr_asm_len ("in %A0,__SP_L__" CR_TAB
4009 "clr %B0", xop, plen, -2)
4011 : avr_asm_len ("in %A0,__SP_L__" CR_TAB
4012 "in %B0,__SP_H__", xop, plen, -2);
4015 return AVR_HAVE_MOVW
4016 ? avr_asm_len ("movw %0,%1", xop, plen, -1)
4018 : avr_asm_len ("mov %A0,%A1" CR_TAB
4019 "mov %B0,%B1", xop, plen, -2);
4020 } /* REG_P (src) */
4021 else if (CONSTANT_P (src))
4023 return output_reload_inhi (xop, NULL, plen);
4025 else if (MEM_P (src))
4027 return out_movhi_r_mr (insn, xop, plen); /* mov r,m */
4030 else if (MEM_P (dest))
4032 rtx xop[2];
4034 xop[0] = dest;
4035 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
4037 return out_movhi_mr_r (insn, xop, plen);
4040 fatal_insn ("invalid insn:", insn);
4042 return "";
4046 /* Same as out_movqi_r_mr, but TINY does not have ADIW or SBIW */
4048 static const char*
4049 avr_out_movqi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
4051 rtx dest = op[0];
4052 rtx src = op[1];
4053 rtx x = XEXP (src, 0);
4055 avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4056 "ld %0,%b1" , op, plen, -3);
4058 if (!reg_overlap_mentioned_p (dest, XEXP (x, 0))
4059 && !reg_unused_after (insn, XEXP (x, 0)))
4060 avr_asm_len (TINY_SBIW (%I1, %J1, %o1), op, plen, 2);
4062 return "";
4065 static const char*
4066 out_movqi_r_mr (rtx_insn *insn, rtx op[], int *plen)
4068 rtx dest = op[0];
4069 rtx src = op[1];
4070 rtx x = XEXP (src, 0);
4072 if (CONSTANT_ADDRESS_P (x))
4074 int n_words = AVR_TINY ? 1 : 2;
4075 return io_address_operand (x, QImode)
4076 ? avr_asm_len ("in %0,%i1", op, plen, -1)
4077 : avr_asm_len ("lds %0,%m1", op, plen, -n_words);
4080 if (GET_CODE (x) == PLUS
4081 && REG_P (XEXP (x, 0))
4082 && CONST_INT_P (XEXP (x, 1)))
4084 /* memory access by reg+disp */
4086 int disp = INTVAL (XEXP (x, 1));
4088 if (AVR_TINY)
4089 return avr_out_movqi_r_mr_reg_disp_tiny (insn, op, plen);
4091 if (disp - GET_MODE_SIZE (GET_MODE (src)) >= 63)
4093 if (REGNO (XEXP (x, 0)) != REG_Y)
4094 fatal_insn ("incorrect insn:",insn);
4096 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
4097 return avr_asm_len ("adiw r28,%o1-63" CR_TAB
4098 "ldd %0,Y+63" CR_TAB
4099 "sbiw r28,%o1-63", op, plen, -3);
4101 return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
4102 "sbci r29,hi8(-%o1)" CR_TAB
4103 "ld %0,Y" CR_TAB
4104 "subi r28,lo8(%o1)" CR_TAB
4105 "sbci r29,hi8(%o1)", op, plen, -5);
4107 else if (REGNO (XEXP (x, 0)) == REG_X)
4109 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
4110 it but I have this situation with extremal optimizing options. */
4112 avr_asm_len ("adiw r26,%o1" CR_TAB
4113 "ld %0,X", op, plen, -2);
4115 if (!reg_overlap_mentioned_p (dest, XEXP (x, 0))
4116 && !reg_unused_after (insn, XEXP (x, 0)))
4118 avr_asm_len ("sbiw r26,%o1", op, plen, 1);
4121 return "";
4124 return avr_asm_len ("ldd %0,%1", op, plen, -1);
4127 return avr_asm_len ("ld %0,%1", op, plen, -1);
4131 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
4133 static const char*
4134 avr_out_movhi_r_mr_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
4136 rtx dest = op[0];
4137 rtx src = op[1];
4138 rtx base = XEXP (src, 0);
4140 int reg_dest = true_regnum (dest);
4141 int reg_base = true_regnum (base);
4143 if (reg_dest == reg_base) /* R = (R) */
4144 return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
4145 "ld %B0,%1" CR_TAB
4146 "mov %A0,__tmp_reg__", op, plen, -3);
4148 avr_asm_len ("ld %A0,%1+" CR_TAB
4149 "ld %B0,%1", op, plen, -2);
4151 if (!reg_unused_after (insn, base))
4152 avr_asm_len (TINY_SBIW (%E1, %F1, 1), op, plen, 2);
4154 return "";
4158 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
4160 static const char*
4161 avr_out_movhi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
4163 rtx dest = op[0];
4164 rtx src = op[1];
4165 rtx base = XEXP (src, 0);
4167 int reg_dest = true_regnum (dest);
4168 int reg_base = true_regnum (XEXP (base, 0));
4170 if (reg_base == reg_dest)
4172 return avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4173 "ld __tmp_reg__,%b1+" CR_TAB
4174 "ld %B0,%b1" CR_TAB
4175 "mov %A0,__tmp_reg__", op, plen, -5);
4177 else
4179 avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4180 "ld %A0,%b1+" CR_TAB
4181 "ld %B0,%b1", op, plen, -4);
4183 if (!reg_unused_after (insn, XEXP (base, 0)))
4184 avr_asm_len (TINY_SBIW (%I1, %J1, %o1+1), op, plen, 2);
4186 return "";
4191 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
4193 static const char*
4194 avr_out_movhi_r_mr_pre_dec_tiny (rtx_insn *insn, rtx op[], int *plen)
4196 int mem_volatile_p = 0;
4197 rtx dest = op[0];
4198 rtx src = op[1];
4199 rtx base = XEXP (src, 0);
4201 /* "volatile" forces reading low byte first, even if less efficient,
4202 for correct operation with 16-bit I/O registers. */
4203 mem_volatile_p = MEM_VOLATILE_P (src);
4205 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
4206 fatal_insn ("incorrect insn:", insn);
4208 if (!mem_volatile_p)
4209 return avr_asm_len ("ld %B0,%1" CR_TAB
4210 "ld %A0,%1", op, plen, -2);
4212 return avr_asm_len (TINY_SBIW (%I1, %J1, 2) CR_TAB
4213 "ld %A0,%p1+" CR_TAB
4214 "ld %B0,%p1" CR_TAB
4215 TINY_SBIW (%I1, %J1, 1), op, plen, -6);
4219 static const char*
4220 out_movhi_r_mr (rtx_insn *insn, rtx op[], int *plen)
4222 rtx dest = op[0];
4223 rtx src = op[1];
4224 rtx base = XEXP (src, 0);
4225 int reg_dest = true_regnum (dest);
4226 int reg_base = true_regnum (base);
4227 /* "volatile" forces reading low byte first, even if less efficient,
4228 for correct operation with 16-bit I/O registers. */
4229 int mem_volatile_p = MEM_VOLATILE_P (src);
4231 if (reg_base > 0)
4233 if (AVR_TINY)
4234 return avr_out_movhi_r_mr_reg_no_disp_tiny (insn, op, plen);
4236 if (reg_dest == reg_base) /* R = (R) */
4237 return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
4238 "ld %B0,%1" CR_TAB
4239 "mov %A0,__tmp_reg__", op, plen, -3);
4241 if (reg_base != REG_X)
4242 return avr_asm_len ("ld %A0,%1" CR_TAB
4243 "ldd %B0,%1+1", op, plen, -2);
4245 avr_asm_len ("ld %A0,X+" CR_TAB
4246 "ld %B0,X", op, plen, -2);
4248 if (!reg_unused_after (insn, base))
4249 avr_asm_len ("sbiw r26,1", op, plen, 1);
4251 return "";
4253 else if (GET_CODE (base) == PLUS) /* (R + i) */
4255 int disp = INTVAL (XEXP (base, 1));
4256 int reg_base = true_regnum (XEXP (base, 0));
4258 if (AVR_TINY)
4259 return avr_out_movhi_r_mr_reg_disp_tiny (insn, op, plen);
4261 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
4263 if (REGNO (XEXP (base, 0)) != REG_Y)
4264 fatal_insn ("incorrect insn:",insn);
4266 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (src))
4267 ? avr_asm_len ("adiw r28,%o1-62" CR_TAB
4268 "ldd %A0,Y+62" CR_TAB
4269 "ldd %B0,Y+63" CR_TAB
4270 "sbiw r28,%o1-62", op, plen, -4)
4272 : avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
4273 "sbci r29,hi8(-%o1)" CR_TAB
4274 "ld %A0,Y" CR_TAB
4275 "ldd %B0,Y+1" CR_TAB
4276 "subi r28,lo8(%o1)" CR_TAB
4277 "sbci r29,hi8(%o1)", op, plen, -6);
4280 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
4281 it but I have this situation with extremal
4282 optimization options. */
4284 if (reg_base == REG_X)
4286 if (reg_base == reg_dest)
4287 return avr_asm_len ("adiw r26,%o1" CR_TAB
4288 "ld __tmp_reg__,X+" CR_TAB
4289 "ld %B0,X" CR_TAB
4290 "mov %A0,__tmp_reg__", op, plen, -4);
4292 avr_asm_len ("adiw r26,%o1" CR_TAB
4293 "ld %A0,X+" CR_TAB
4294 "ld %B0,X", op, plen, -3);
4296 if (!reg_unused_after (insn, XEXP (base, 0)))
4297 avr_asm_len ("sbiw r26,%o1+1", op, plen, 1);
4299 return "";
4302 return reg_base == reg_dest
4303 ? avr_asm_len ("ldd __tmp_reg__,%A1" CR_TAB
4304 "ldd %B0,%B1" CR_TAB
4305 "mov %A0,__tmp_reg__", op, plen, -3)
4307 : avr_asm_len ("ldd %A0,%A1" CR_TAB
4308 "ldd %B0,%B1", op, plen, -2);
4310 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4312 if (AVR_TINY)
4313 return avr_out_movhi_r_mr_pre_dec_tiny (insn, op, plen);
4315 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
4316 fatal_insn ("incorrect insn:", insn);
4318 if (!mem_volatile_p)
4319 return avr_asm_len ("ld %B0,%1" CR_TAB
4320 "ld %A0,%1", op, plen, -2);
4322 return REGNO (XEXP (base, 0)) == REG_X
4323 ? avr_asm_len ("sbiw r26,2" CR_TAB
4324 "ld %A0,X+" CR_TAB
4325 "ld %B0,X" CR_TAB
4326 "sbiw r26,1", op, plen, -4)
4328 : avr_asm_len ("sbiw %r1,2" CR_TAB
4329 "ld %A0,%p1" CR_TAB
4330 "ldd %B0,%p1+1", op, plen, -3);
4332 else if (GET_CODE (base) == POST_INC) /* (R++) */
4334 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
4335 fatal_insn ("incorrect insn:", insn);
4337 return avr_asm_len ("ld %A0,%1" CR_TAB
4338 "ld %B0,%1", op, plen, -2);
4340 else if (CONSTANT_ADDRESS_P (base))
4342 int n_words = AVR_TINY ? 2 : 4;
4343 return io_address_operand (base, HImode)
4344 ? avr_asm_len ("in %A0,%i1" CR_TAB
4345 "in %B0,%i1+1", op, plen, -2)
4347 : avr_asm_len ("lds %A0,%m1" CR_TAB
4348 "lds %B0,%m1+1", op, plen, -n_words);
4351 fatal_insn ("unknown move insn:",insn);
4352 return "";
4355 static const char*
4356 avr_out_movsi_r_mr_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *l)
4358 rtx dest = op[0];
4359 rtx src = op[1];
4360 rtx base = XEXP (src, 0);
4361 int reg_dest = true_regnum (dest);
4362 int reg_base = true_regnum (base);
4364 if (reg_dest == reg_base)
4366 /* "ld r26,-X" is undefined */
4367 return *l = 9, (TINY_ADIW (%E1, %F1, 3) CR_TAB
4368 "ld %D0,%1" CR_TAB
4369 "ld %C0,-%1" CR_TAB
4370 "ld __tmp_reg__,-%1" CR_TAB
4371 TINY_SBIW (%E1, %F1, 1) CR_TAB
4372 "ld %A0,%1" CR_TAB
4373 "mov %B0,__tmp_reg__");
4375 else if (reg_dest == reg_base - 2)
4377 return *l = 5, ("ld %A0,%1+" CR_TAB
4378 "ld %B0,%1+" CR_TAB
4379 "ld __tmp_reg__,%1+" CR_TAB
4380 "ld %D0,%1" CR_TAB
4381 "mov %C0,__tmp_reg__");
4383 else if (reg_unused_after (insn, base))
4385 return *l = 4, ("ld %A0,%1+" CR_TAB
4386 "ld %B0,%1+" CR_TAB
4387 "ld %C0,%1+" CR_TAB
4388 "ld %D0,%1");
4390 else
4392 return *l = 6, ("ld %A0,%1+" CR_TAB
4393 "ld %B0,%1+" CR_TAB
4394 "ld %C0,%1+" CR_TAB
4395 "ld %D0,%1" CR_TAB
4396 TINY_SBIW (%E1, %F1, 3));
4401 static const char*
4402 avr_out_movsi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *l)
4404 rtx dest = op[0];
4405 rtx src = op[1];
4406 rtx base = XEXP (src, 0);
4407 int reg_dest = true_regnum (dest);
4408 int reg_base = true_regnum (XEXP (base, 0));
4410 if (reg_dest == reg_base)
4412 /* "ld r26,-X" is undefined */
4413 return *l = 9, (TINY_ADIW (%I1, %J1, %o1+3) CR_TAB
4414 "ld %D0,%b1" CR_TAB
4415 "ld %C0,-%b1" CR_TAB
4416 "ld __tmp_reg__,-%b1" CR_TAB
4417 TINY_SBIW (%I1, %J1, 1) CR_TAB
4418 "ld %A0,%b1" CR_TAB
4419 "mov %B0,__tmp_reg__");
4421 else if (reg_dest == reg_base - 2)
4423 return *l = 7, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4424 "ld %A0,%b1+" CR_TAB
4425 "ld %B0,%b1+" CR_TAB
4426 "ld __tmp_reg__,%b1+" CR_TAB
4427 "ld %D0,%b1" CR_TAB
4428 "mov %C0,__tmp_reg__");
4430 else if (reg_unused_after (insn, XEXP (base, 0)))
4432 return *l = 6, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4433 "ld %A0,%b1+" CR_TAB
4434 "ld %B0,%b1+" CR_TAB
4435 "ld %C0,%b1+" CR_TAB
4436 "ld %D0,%b1");
4438 else
4440 return *l = 8, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4441 "ld %A0,%b1+" CR_TAB
4442 "ld %B0,%b1+" CR_TAB
4443 "ld %C0,%b1+" CR_TAB
4444 "ld %D0,%b1" CR_TAB
4445 TINY_SBIW (%I1, %J1, %o1+3));
4449 static const char*
4450 out_movsi_r_mr (rtx_insn *insn, rtx op[], int *l)
4452 rtx dest = op[0];
4453 rtx src = op[1];
4454 rtx base = XEXP (src, 0);
4455 int reg_dest = true_regnum (dest);
4456 int reg_base = true_regnum (base);
4457 int tmp;
4459 if (!l)
4460 l = &tmp;
4462 if (reg_base > 0)
4464 if (AVR_TINY)
4465 return avr_out_movsi_r_mr_reg_no_disp_tiny (insn, op, l);
4467 if (reg_base == REG_X) /* (R26) */
4469 if (reg_dest == REG_X)
4470 /* "ld r26,-X" is undefined */
4471 return *l=7, ("adiw r26,3" CR_TAB
4472 "ld r29,X" CR_TAB
4473 "ld r28,-X" CR_TAB
4474 "ld __tmp_reg__,-X" CR_TAB
4475 "sbiw r26,1" CR_TAB
4476 "ld r26,X" CR_TAB
4477 "mov r27,__tmp_reg__");
4478 else if (reg_dest == REG_X - 2)
4479 return *l=5, ("ld %A0,X+" CR_TAB
4480 "ld %B0,X+" CR_TAB
4481 "ld __tmp_reg__,X+" CR_TAB
4482 "ld %D0,X" CR_TAB
4483 "mov %C0,__tmp_reg__");
4484 else if (reg_unused_after (insn, base))
4485 return *l=4, ("ld %A0,X+" CR_TAB
4486 "ld %B0,X+" CR_TAB
4487 "ld %C0,X+" CR_TAB
4488 "ld %D0,X");
4489 else
4490 return *l=5, ("ld %A0,X+" CR_TAB
4491 "ld %B0,X+" CR_TAB
4492 "ld %C0,X+" CR_TAB
4493 "ld %D0,X" CR_TAB
4494 "sbiw r26,3");
4496 else
4498 if (reg_dest == reg_base)
4499 return *l=5, ("ldd %D0,%1+3" CR_TAB
4500 "ldd %C0,%1+2" CR_TAB
4501 "ldd __tmp_reg__,%1+1" CR_TAB
4502 "ld %A0,%1" CR_TAB
4503 "mov %B0,__tmp_reg__");
4504 else if (reg_base == reg_dest + 2)
4505 return *l=5, ("ld %A0,%1" CR_TAB
4506 "ldd %B0,%1+1" CR_TAB
4507 "ldd __tmp_reg__,%1+2" CR_TAB
4508 "ldd %D0,%1+3" CR_TAB
4509 "mov %C0,__tmp_reg__");
4510 else
4511 return *l=4, ("ld %A0,%1" CR_TAB
4512 "ldd %B0,%1+1" CR_TAB
4513 "ldd %C0,%1+2" CR_TAB
4514 "ldd %D0,%1+3");
4517 else if (GET_CODE (base) == PLUS) /* (R + i) */
4519 int disp = INTVAL (XEXP (base, 1));
4521 if (AVR_TINY)
4522 return avr_out_movsi_r_mr_reg_disp_tiny (insn, op, l);
4524 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
4526 if (REGNO (XEXP (base, 0)) != REG_Y)
4527 fatal_insn ("incorrect insn:",insn);
4529 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
4530 return *l = 6, ("adiw r28,%o1-60" CR_TAB
4531 "ldd %A0,Y+60" CR_TAB
4532 "ldd %B0,Y+61" CR_TAB
4533 "ldd %C0,Y+62" CR_TAB
4534 "ldd %D0,Y+63" CR_TAB
4535 "sbiw r28,%o1-60");
4537 return *l = 8, ("subi r28,lo8(-%o1)" CR_TAB
4538 "sbci r29,hi8(-%o1)" CR_TAB
4539 "ld %A0,Y" CR_TAB
4540 "ldd %B0,Y+1" CR_TAB
4541 "ldd %C0,Y+2" CR_TAB
4542 "ldd %D0,Y+3" CR_TAB
4543 "subi r28,lo8(%o1)" CR_TAB
4544 "sbci r29,hi8(%o1)");
4547 reg_base = true_regnum (XEXP (base, 0));
4548 if (reg_base == REG_X)
4550 /* R = (X + d) */
4551 if (reg_dest == REG_X)
4553 *l = 7;
4554 /* "ld r26,-X" is undefined */
4555 return ("adiw r26,%o1+3" CR_TAB
4556 "ld r29,X" CR_TAB
4557 "ld r28,-X" CR_TAB
4558 "ld __tmp_reg__,-X" CR_TAB
4559 "sbiw r26,1" CR_TAB
4560 "ld r26,X" CR_TAB
4561 "mov r27,__tmp_reg__");
4563 *l = 6;
4564 if (reg_dest == REG_X - 2)
4565 return ("adiw r26,%o1" CR_TAB
4566 "ld r24,X+" CR_TAB
4567 "ld r25,X+" CR_TAB
4568 "ld __tmp_reg__,X+" CR_TAB
4569 "ld r27,X" CR_TAB
4570 "mov r26,__tmp_reg__");
4572 return ("adiw r26,%o1" CR_TAB
4573 "ld %A0,X+" CR_TAB
4574 "ld %B0,X+" CR_TAB
4575 "ld %C0,X+" CR_TAB
4576 "ld %D0,X" CR_TAB
4577 "sbiw r26,%o1+3");
4579 if (reg_dest == reg_base)
4580 return *l=5, ("ldd %D0,%D1" CR_TAB
4581 "ldd %C0,%C1" CR_TAB
4582 "ldd __tmp_reg__,%B1" CR_TAB
4583 "ldd %A0,%A1" CR_TAB
4584 "mov %B0,__tmp_reg__");
4585 else if (reg_dest == reg_base - 2)
4586 return *l=5, ("ldd %A0,%A1" CR_TAB
4587 "ldd %B0,%B1" CR_TAB
4588 "ldd __tmp_reg__,%C1" CR_TAB
4589 "ldd %D0,%D1" CR_TAB
4590 "mov %C0,__tmp_reg__");
4591 return *l=4, ("ldd %A0,%A1" CR_TAB
4592 "ldd %B0,%B1" CR_TAB
4593 "ldd %C0,%C1" CR_TAB
4594 "ldd %D0,%D1");
4596 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4597 return *l=4, ("ld %D0,%1" CR_TAB
4598 "ld %C0,%1" CR_TAB
4599 "ld %B0,%1" CR_TAB
4600 "ld %A0,%1");
4601 else if (GET_CODE (base) == POST_INC) /* (R++) */
4602 return *l=4, ("ld %A0,%1" CR_TAB
4603 "ld %B0,%1" CR_TAB
4604 "ld %C0,%1" CR_TAB
4605 "ld %D0,%1");
4606 else if (CONSTANT_ADDRESS_P (base))
4608 if (io_address_operand (base, SImode))
4610 *l = 4;
4611 return ("in %A0,%i1" CR_TAB
4612 "in %B0,%i1+1" CR_TAB
4613 "in %C0,%i1+2" CR_TAB
4614 "in %D0,%i1+3");
4616 else
4618 *l = AVR_TINY ? 4 : 8;
4619 return ("lds %A0,%m1" CR_TAB
4620 "lds %B0,%m1+1" CR_TAB
4621 "lds %C0,%m1+2" CR_TAB
4622 "lds %D0,%m1+3");
4626 fatal_insn ("unknown move insn:",insn);
4627 return "";
4630 static const char*
4631 avr_out_movsi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *l)
4633 rtx dest = op[0];
4634 rtx src = op[1];
4635 rtx base = XEXP (dest, 0);
4636 int reg_base = true_regnum (base);
4637 int reg_src = true_regnum (src);
4639 if (reg_base == reg_src)
4641 /* "ld r26,-X" is undefined */
4642 if (reg_unused_after (insn, base))
4644 return *l = 7, ("mov __tmp_reg__, %B1" CR_TAB
4645 "st %0,%A1" CR_TAB
4646 TINY_ADIW (%E0, %F0, 1) CR_TAB
4647 "st %0+,__tmp_reg__" CR_TAB
4648 "st %0+,%C1" CR_TAB
4649 "st %0+,%D1");
4651 else
4653 return *l = 9, ("mov __tmp_reg__, %B1" CR_TAB
4654 "st %0,%A1" CR_TAB
4655 TINY_ADIW (%E0, %F0, 1) CR_TAB
4656 "st %0+,__tmp_reg__" CR_TAB
4657 "st %0+,%C1" CR_TAB
4658 "st %0+,%D1" CR_TAB
4659 TINY_SBIW (%E0, %F0, 3));
4662 else if (reg_base == reg_src + 2)
4664 if (reg_unused_after (insn, base))
4665 return *l = 7, ("mov __zero_reg__,%C1" CR_TAB
4666 "mov __tmp_reg__,%D1" CR_TAB
4667 "st %0+,%A1" CR_TAB
4668 "st %0+,%B1" CR_TAB
4669 "st %0+,__zero_reg__" CR_TAB
4670 "st %0,__tmp_reg__" CR_TAB
4671 "clr __zero_reg__");
4672 else
4673 return *l = 9, ("mov __zero_reg__,%C1" CR_TAB
4674 "mov __tmp_reg__,%D1" CR_TAB
4675 "st %0+,%A1" CR_TAB
4676 "st %0+,%B1" CR_TAB
4677 "st %0+,__zero_reg__" CR_TAB
4678 "st %0,__tmp_reg__" CR_TAB
4679 "clr __zero_reg__" CR_TAB
4680 TINY_SBIW (%E0, %F0, 3));
4683 return *l = 6, ("st %0+,%A1" CR_TAB
4684 "st %0+,%B1" CR_TAB
4685 "st %0+,%C1" CR_TAB
4686 "st %0,%D1" CR_TAB
4687 TINY_SBIW (%E0, %F0, 3));
4690 static const char*
4691 avr_out_movsi_mr_r_reg_disp_tiny (rtx op[], int *l)
4693 rtx dest = op[0];
4694 rtx src = op[1];
4695 rtx base = XEXP (dest, 0);
4696 int reg_base = REGNO (XEXP (base, 0));
4697 int reg_src =true_regnum (src);
4699 if (reg_base == reg_src)
4701 *l = 11;
4702 return ("mov __tmp_reg__,%A2" CR_TAB
4703 "mov __zero_reg__,%B2" CR_TAB
4704 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4705 "st %b0+,__tmp_reg__" CR_TAB
4706 "st %b0+,__zero_reg__" CR_TAB
4707 "st %b0+,%C2" CR_TAB
4708 "st %b0,%D2" CR_TAB
4709 "clr __zero_reg__" CR_TAB
4710 TINY_SBIW (%I0, %J0, %o0+3));
4712 else if (reg_src == reg_base - 2)
4714 *l = 11;
4715 return ("mov __tmp_reg__,%C2" CR_TAB
4716 "mov __zero_reg__,%D2" CR_TAB
4717 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4718 "st %b0+,%A0" CR_TAB
4719 "st %b0+,%B0" CR_TAB
4720 "st %b0+,__tmp_reg__" CR_TAB
4721 "st %b0,__zero_reg__" CR_TAB
4722 "clr __zero_reg__" CR_TAB
4723 TINY_SBIW (%I0, %J0, %o0+3));
4725 *l = 8;
4726 return (TINY_ADIW (%I0, %J0, %o0) CR_TAB
4727 "st %b0+,%A1" CR_TAB
4728 "st %b0+,%B1" CR_TAB
4729 "st %b0+,%C1" CR_TAB
4730 "st %b0,%D1" CR_TAB
4731 TINY_SBIW (%I0, %J0, %o0+3));
4734 static const char*
4735 out_movsi_mr_r (rtx_insn *insn, rtx op[], int *l)
4737 rtx dest = op[0];
4738 rtx src = op[1];
4739 rtx base = XEXP (dest, 0);
4740 int reg_base = true_regnum (base);
4741 int reg_src = true_regnum (src);
4742 int tmp;
4744 if (!l)
4745 l = &tmp;
4747 if (CONSTANT_ADDRESS_P (base))
4749 if (io_address_operand (base, SImode))
4751 return *l=4,("out %i0, %A1" CR_TAB
4752 "out %i0+1,%B1" CR_TAB
4753 "out %i0+2,%C1" CR_TAB
4754 "out %i0+3,%D1");
4756 else
4758 *l = AVR_TINY ? 4 : 8;
4759 return ("sts %m0,%A1" CR_TAB
4760 "sts %m0+1,%B1" CR_TAB
4761 "sts %m0+2,%C1" CR_TAB
4762 "sts %m0+3,%D1");
4766 if (reg_base > 0) /* (r) */
4768 if (AVR_TINY)
4769 return avr_out_movsi_mr_r_reg_no_disp_tiny (insn, op, l);
4771 if (reg_base == REG_X) /* (R26) */
4773 if (reg_src == REG_X)
4775 /* "st X+,r26" is undefined */
4776 if (reg_unused_after (insn, base))
4777 return *l=6, ("mov __tmp_reg__,r27" CR_TAB
4778 "st X,r26" CR_TAB
4779 "adiw r26,1" CR_TAB
4780 "st X+,__tmp_reg__" CR_TAB
4781 "st X+,r28" CR_TAB
4782 "st X,r29");
4783 else
4784 return *l=7, ("mov __tmp_reg__,r27" CR_TAB
4785 "st X,r26" CR_TAB
4786 "adiw r26,1" CR_TAB
4787 "st X+,__tmp_reg__" CR_TAB
4788 "st X+,r28" CR_TAB
4789 "st X,r29" CR_TAB
4790 "sbiw r26,3");
4792 else if (reg_base == reg_src + 2)
4794 if (reg_unused_after (insn, base))
4795 return *l=7, ("mov __zero_reg__,%C1" CR_TAB
4796 "mov __tmp_reg__,%D1" CR_TAB
4797 "st %0+,%A1" CR_TAB
4798 "st %0+,%B1" CR_TAB
4799 "st %0+,__zero_reg__" CR_TAB
4800 "st %0,__tmp_reg__" CR_TAB
4801 "clr __zero_reg__");
4802 else
4803 return *l=8, ("mov __zero_reg__,%C1" CR_TAB
4804 "mov __tmp_reg__,%D1" CR_TAB
4805 "st %0+,%A1" CR_TAB
4806 "st %0+,%B1" CR_TAB
4807 "st %0+,__zero_reg__" CR_TAB
4808 "st %0,__tmp_reg__" CR_TAB
4809 "clr __zero_reg__" CR_TAB
4810 "sbiw r26,3");
4812 return *l=5, ("st %0+,%A1" CR_TAB
4813 "st %0+,%B1" CR_TAB
4814 "st %0+,%C1" CR_TAB
4815 "st %0,%D1" CR_TAB
4816 "sbiw r26,3");
4818 else
4819 return *l=4, ("st %0,%A1" CR_TAB
4820 "std %0+1,%B1" CR_TAB
4821 "std %0+2,%C1" CR_TAB
4822 "std %0+3,%D1");
4824 else if (GET_CODE (base) == PLUS) /* (R + i) */
4826 int disp = INTVAL (XEXP (base, 1));
4828 if (AVR_TINY)
4829 return avr_out_movsi_mr_r_reg_disp_tiny (op, l);
4831 reg_base = REGNO (XEXP (base, 0));
4832 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
4834 if (reg_base != REG_Y)
4835 fatal_insn ("incorrect insn:",insn);
4837 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
4838 return *l = 6, ("adiw r28,%o0-60" CR_TAB
4839 "std Y+60,%A1" CR_TAB
4840 "std Y+61,%B1" CR_TAB
4841 "std Y+62,%C1" CR_TAB
4842 "std Y+63,%D1" CR_TAB
4843 "sbiw r28,%o0-60");
4845 return *l = 8, ("subi r28,lo8(-%o0)" CR_TAB
4846 "sbci r29,hi8(-%o0)" CR_TAB
4847 "st Y,%A1" CR_TAB
4848 "std Y+1,%B1" CR_TAB
4849 "std Y+2,%C1" CR_TAB
4850 "std Y+3,%D1" CR_TAB
4851 "subi r28,lo8(%o0)" CR_TAB
4852 "sbci r29,hi8(%o0)");
4854 if (reg_base == REG_X)
4856 /* (X + d) = R */
4857 if (reg_src == REG_X)
4859 *l = 9;
4860 return ("mov __tmp_reg__,r26" CR_TAB
4861 "mov __zero_reg__,r27" CR_TAB
4862 "adiw r26,%o0" CR_TAB
4863 "st X+,__tmp_reg__" CR_TAB
4864 "st X+,__zero_reg__" CR_TAB
4865 "st X+,r28" CR_TAB
4866 "st X,r29" CR_TAB
4867 "clr __zero_reg__" CR_TAB
4868 "sbiw r26,%o0+3");
4870 else if (reg_src == REG_X - 2)
4872 *l = 9;
4873 return ("mov __tmp_reg__,r26" CR_TAB
4874 "mov __zero_reg__,r27" CR_TAB
4875 "adiw r26,%o0" CR_TAB
4876 "st X+,r24" CR_TAB
4877 "st X+,r25" CR_TAB
4878 "st X+,__tmp_reg__" CR_TAB
4879 "st X,__zero_reg__" CR_TAB
4880 "clr __zero_reg__" CR_TAB
4881 "sbiw r26,%o0+3");
4883 *l = 6;
4884 return ("adiw r26,%o0" CR_TAB
4885 "st X+,%A1" CR_TAB
4886 "st X+,%B1" CR_TAB
4887 "st X+,%C1" CR_TAB
4888 "st X,%D1" CR_TAB
4889 "sbiw r26,%o0+3");
4891 return *l=4, ("std %A0,%A1" CR_TAB
4892 "std %B0,%B1" CR_TAB
4893 "std %C0,%C1" CR_TAB
4894 "std %D0,%D1");
4896 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4897 return *l=4, ("st %0,%D1" CR_TAB
4898 "st %0,%C1" CR_TAB
4899 "st %0,%B1" CR_TAB
4900 "st %0,%A1");
4901 else if (GET_CODE (base) == POST_INC) /* (R++) */
4902 return *l=4, ("st %0,%A1" CR_TAB
4903 "st %0,%B1" CR_TAB
4904 "st %0,%C1" CR_TAB
4905 "st %0,%D1");
4906 fatal_insn ("unknown move insn:",insn);
4907 return "";
4910 const char *
4911 output_movsisf (rtx_insn *insn, rtx operands[], int *l)
4913 int dummy;
4914 rtx dest = operands[0];
4915 rtx src = operands[1];
4916 int *real_l = l;
4918 if (avr_mem_flash_p (src)
4919 || avr_mem_flash_p (dest))
4921 return avr_out_lpm (insn, operands, real_l);
4924 if (!l)
4925 l = &dummy;
4927 gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 4);
4929 if (REG_P (dest))
4931 if (REG_P (src)) /* mov r,r */
4933 if (true_regnum (dest) > true_regnum (src))
4935 if (AVR_HAVE_MOVW)
4937 *l = 2;
4938 return ("movw %C0,%C1" CR_TAB
4939 "movw %A0,%A1");
4941 *l = 4;
4942 return ("mov %D0,%D1" CR_TAB
4943 "mov %C0,%C1" CR_TAB
4944 "mov %B0,%B1" CR_TAB
4945 "mov %A0,%A1");
4947 else
4949 if (AVR_HAVE_MOVW)
4951 *l = 2;
4952 return ("movw %A0,%A1" CR_TAB
4953 "movw %C0,%C1");
4955 *l = 4;
4956 return ("mov %A0,%A1" CR_TAB
4957 "mov %B0,%B1" CR_TAB
4958 "mov %C0,%C1" CR_TAB
4959 "mov %D0,%D1");
4962 else if (CONSTANT_P (src))
4964 return output_reload_insisf (operands, NULL_RTX, real_l);
4966 else if (MEM_P (src))
4967 return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
4969 else if (MEM_P (dest))
4971 const char *templ;
4973 if (src == CONST0_RTX (GET_MODE (dest)))
4974 operands[1] = zero_reg_rtx;
4976 templ = out_movsi_mr_r (insn, operands, real_l);
4978 if (!real_l)
4979 output_asm_insn (templ, operands);
4981 operands[1] = src;
4982 return "";
4984 fatal_insn ("invalid insn:", insn);
4985 return "";
4989 /* Handle loads of 24-bit types from memory to register. */
4991 static const char*
4992 avr_out_load_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
4994 rtx dest = op[0];
4995 rtx src = op[1];
4996 rtx base = XEXP (src, 0);
4997 int reg_dest = true_regnum (dest);
4998 int reg_base = true_regnum (base);
5000 if (reg_base == reg_dest)
5002 return avr_asm_len (TINY_ADIW (%E1, %F1, 2) CR_TAB
5003 "ld %C0,%1" CR_TAB
5004 "ld __tmp_reg__,-%1" CR_TAB
5005 TINY_SBIW (%E1, %F1, 1) CR_TAB
5006 "ld %A0,%1" CR_TAB
5007 "mov %B0,__tmp_reg__", op, plen, -8);
5009 else
5011 avr_asm_len ("ld %A0,%1+" CR_TAB
5012 "ld %B0,%1+" CR_TAB
5013 "ld %C0,%1", op, plen, -3);
5015 if (reg_dest != reg_base - 2
5016 && !reg_unused_after (insn, base))
5018 avr_asm_len (TINY_SBIW (%E1, %F1, 2), op, plen, 2);
5020 return "";
5024 static const char*
5025 avr_out_load_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
5027 rtx dest = op[0];
5028 rtx src = op[1];
5029 rtx base = XEXP (src, 0);
5030 int reg_dest = true_regnum (dest);
5031 int reg_base = true_regnum (base);
5033 reg_base = true_regnum (XEXP (base, 0));
5034 if (reg_base == reg_dest)
5036 return avr_asm_len (TINY_ADIW (%I1, %J1, %o1+2) CR_TAB
5037 "ld %C0,%b1" CR_TAB
5038 "ld __tmp_reg__,-%b1" CR_TAB
5039 TINY_SBIW (%I1, %J1, 1) CR_TAB
5040 "ld %A0,%b1" CR_TAB
5041 "mov %B0,__tmp_reg__", op, plen, -8);
5043 else
5045 avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
5046 "ld %A0,%b1+" CR_TAB
5047 "ld %B0,%b1+" CR_TAB
5048 "ld %C0,%b1", op, plen, -5);
5050 if (reg_dest != reg_base - 2
5051 && !reg_unused_after (insn, XEXP (base, 0)))
5052 avr_asm_len (TINY_SBIW (%I1, %J1, %o1+2), op, plen, 2);
5054 return "";
5058 static const char*
5059 avr_out_load_psi (rtx_insn *insn, rtx *op, int *plen)
5061 rtx dest = op[0];
5062 rtx src = op[1];
5063 rtx base = XEXP (src, 0);
5064 int reg_dest = true_regnum (dest);
5065 int reg_base = true_regnum (base);
5067 if (reg_base > 0)
5069 if (AVR_TINY)
5070 return avr_out_load_psi_reg_no_disp_tiny (insn, op, plen);
5072 if (reg_base == REG_X) /* (R26) */
5074 if (reg_dest == REG_X)
5075 /* "ld r26,-X" is undefined */
5076 return avr_asm_len ("adiw r26,2" CR_TAB
5077 "ld r28,X" CR_TAB
5078 "ld __tmp_reg__,-X" CR_TAB
5079 "sbiw r26,1" CR_TAB
5080 "ld r26,X" CR_TAB
5081 "mov r27,__tmp_reg__", op, plen, -6);
5082 else
5084 avr_asm_len ("ld %A0,X+" CR_TAB
5085 "ld %B0,X+" CR_TAB
5086 "ld %C0,X", op, plen, -3);
5088 if (reg_dest != REG_X - 2
5089 && !reg_unused_after (insn, base))
5091 avr_asm_len ("sbiw r26,2", op, plen, 1);
5094 return "";
5097 else /* reg_base != REG_X */
5099 if (reg_dest == reg_base)
5100 return avr_asm_len ("ldd %C0,%1+2" CR_TAB
5101 "ldd __tmp_reg__,%1+1" CR_TAB
5102 "ld %A0,%1" CR_TAB
5103 "mov %B0,__tmp_reg__", op, plen, -4);
5104 else
5105 return avr_asm_len ("ld %A0,%1" CR_TAB
5106 "ldd %B0,%1+1" CR_TAB
5107 "ldd %C0,%1+2", op, plen, -3);
5110 else if (GET_CODE (base) == PLUS) /* (R + i) */
5112 int disp = INTVAL (XEXP (base, 1));
5114 if (AVR_TINY)
5115 return avr_out_load_psi_reg_disp_tiny (insn, op, plen);
5117 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
5119 if (REGNO (XEXP (base, 0)) != REG_Y)
5120 fatal_insn ("incorrect insn:",insn);
5122 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
5123 return avr_asm_len ("adiw r28,%o1-61" CR_TAB
5124 "ldd %A0,Y+61" CR_TAB
5125 "ldd %B0,Y+62" CR_TAB
5126 "ldd %C0,Y+63" CR_TAB
5127 "sbiw r28,%o1-61", op, plen, -5);
5129 return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
5130 "sbci r29,hi8(-%o1)" CR_TAB
5131 "ld %A0,Y" CR_TAB
5132 "ldd %B0,Y+1" CR_TAB
5133 "ldd %C0,Y+2" CR_TAB
5134 "subi r28,lo8(%o1)" CR_TAB
5135 "sbci r29,hi8(%o1)", op, plen, -7);
5138 reg_base = true_regnum (XEXP (base, 0));
5139 if (reg_base == REG_X)
5141 /* R = (X + d) */
5142 if (reg_dest == REG_X)
5144 /* "ld r26,-X" is undefined */
5145 return avr_asm_len ("adiw r26,%o1+2" CR_TAB
5146 "ld r28,X" CR_TAB
5147 "ld __tmp_reg__,-X" CR_TAB
5148 "sbiw r26,1" CR_TAB
5149 "ld r26,X" CR_TAB
5150 "mov r27,__tmp_reg__", op, plen, -6);
5153 avr_asm_len ("adiw r26,%o1" CR_TAB
5154 "ld %A0,X+" CR_TAB
5155 "ld %B0,X+" CR_TAB
5156 "ld %C0,X", op, plen, -4);
5158 if (reg_dest != REG_W
5159 && !reg_unused_after (insn, XEXP (base, 0)))
5160 avr_asm_len ("sbiw r26,%o1+2", op, plen, 1);
5162 return "";
5165 if (reg_dest == reg_base)
5166 return avr_asm_len ("ldd %C0,%C1" CR_TAB
5167 "ldd __tmp_reg__,%B1" CR_TAB
5168 "ldd %A0,%A1" CR_TAB
5169 "mov %B0,__tmp_reg__", op, plen, -4);
5171 return avr_asm_len ("ldd %A0,%A1" CR_TAB
5172 "ldd %B0,%B1" CR_TAB
5173 "ldd %C0,%C1", op, plen, -3);
5175 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5176 return avr_asm_len ("ld %C0,%1" CR_TAB
5177 "ld %B0,%1" CR_TAB
5178 "ld %A0,%1", op, plen, -3);
5179 else if (GET_CODE (base) == POST_INC) /* (R++) */
5180 return avr_asm_len ("ld %A0,%1" CR_TAB
5181 "ld %B0,%1" CR_TAB
5182 "ld %C0,%1", op, plen, -3);
5184 else if (CONSTANT_ADDRESS_P (base))
5186 int n_words = AVR_TINY ? 3 : 6;
5187 return avr_asm_len ("lds %A0,%m1" CR_TAB
5188 "lds %B0,%m1+1" CR_TAB
5189 "lds %C0,%m1+2", op, plen , -n_words);
5192 fatal_insn ("unknown move insn:",insn);
5193 return "";
5197 static const char*
5198 avr_out_store_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
5200 rtx dest = op[0];
5201 rtx src = op[1];
5202 rtx base = XEXP (dest, 0);
5203 int reg_base = true_regnum (base);
5204 int reg_src = true_regnum (src);
5206 if (reg_base == reg_src)
5208 avr_asm_len ("st %0,%A1" CR_TAB
5209 "mov __tmp_reg__,%B1" CR_TAB
5210 TINY_ADIW (%E0, %F0, 1) CR_TAB /* st X+, r27 is undefined */
5211 "st %0+,__tmp_reg__" CR_TAB
5212 "st %0,%C1", op, plen, -6);
5215 else if (reg_src == reg_base - 2)
5217 avr_asm_len ("st %0,%A1" CR_TAB
5218 "mov __tmp_reg__,%C1" CR_TAB
5219 TINY_ADIW (%E0, %F0, 1) CR_TAB
5220 "st %0+,%B1" CR_TAB
5221 "st %0,__tmp_reg__", op, plen, 6);
5223 else
5225 avr_asm_len ("st %0+,%A1" CR_TAB
5226 "st %0+,%B1" CR_TAB
5227 "st %0,%C1", op, plen, -3);
5230 if (!reg_unused_after (insn, base))
5231 avr_asm_len (TINY_SBIW (%E0, %F0, 2), op, plen, 2);
5233 return "";
5236 static const char*
5237 avr_out_store_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
5239 rtx dest = op[0];
5240 rtx src = op[1];
5241 rtx base = XEXP (dest, 0);
5242 int reg_base = REGNO (XEXP (base, 0));
5243 int reg_src = true_regnum (src);
5245 if (reg_src == reg_base)
5246 avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
5247 "mov __zero_reg__,%B1" CR_TAB
5248 TINY_ADIW (%I0, %J0, %o0) CR_TAB
5249 "st %b0+,__tmp_reg__" CR_TAB
5250 "st %b0+,__zero_reg__" CR_TAB
5251 "st %b0,%C1" CR_TAB
5252 "clr __zero_reg__", op, plen, -8);
5253 else if (reg_src == reg_base - 2)
5254 avr_asm_len ("mov __tmp_reg__,%C1" CR_TAB
5255 TINY_ADIW (%I0, %J0, %o0) CR_TAB
5256 "st %b0+,%A1" CR_TAB
5257 "st %b0+,%B1" CR_TAB
5258 "st %b0,__tmp_reg__", op, plen, -6);
5259 else
5260 avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
5261 "st %b0+,%A1" CR_TAB
5262 "st %b0+,%B1" CR_TAB
5263 "st %b0,%C1", op, plen, -5);
5265 if (!reg_unused_after (insn, XEXP (base, 0)))
5266 avr_asm_len (TINY_SBIW (%I0, %J0, %o0+2), op, plen, 2);
5268 return "";
5271 /* Handle store of 24-bit type from register or zero to memory. */
5273 static const char*
5274 avr_out_store_psi (rtx_insn *insn, rtx *op, int *plen)
5276 rtx dest = op[0];
5277 rtx src = op[1];
5278 rtx base = XEXP (dest, 0);
5279 int reg_base = true_regnum (base);
5281 if (CONSTANT_ADDRESS_P (base))
5283 int n_words = AVR_TINY ? 3 : 6;
5284 return avr_asm_len ("sts %m0,%A1" CR_TAB
5285 "sts %m0+1,%B1" CR_TAB
5286 "sts %m0+2,%C1", op, plen, -n_words);
5289 if (reg_base > 0) /* (r) */
5291 if (AVR_TINY)
5292 return avr_out_store_psi_reg_no_disp_tiny (insn, op, plen);
5294 if (reg_base == REG_X) /* (R26) */
5296 gcc_assert (!reg_overlap_mentioned_p (base, src));
5298 avr_asm_len ("st %0+,%A1" CR_TAB
5299 "st %0+,%B1" CR_TAB
5300 "st %0,%C1", op, plen, -3);
5302 if (!reg_unused_after (insn, base))
5303 avr_asm_len ("sbiw r26,2", op, plen, 1);
5305 return "";
5307 else
5308 return avr_asm_len ("st %0,%A1" CR_TAB
5309 "std %0+1,%B1" CR_TAB
5310 "std %0+2,%C1", op, plen, -3);
5312 else if (GET_CODE (base) == PLUS) /* (R + i) */
5314 int disp = INTVAL (XEXP (base, 1));
5316 if (AVR_TINY)
5317 return avr_out_store_psi_reg_disp_tiny (insn, op, plen);
5319 reg_base = REGNO (XEXP (base, 0));
5321 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5323 if (reg_base != REG_Y)
5324 fatal_insn ("incorrect insn:",insn);
5326 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
5327 return avr_asm_len ("adiw r28,%o0-61" CR_TAB
5328 "std Y+61,%A1" CR_TAB
5329 "std Y+62,%B1" CR_TAB
5330 "std Y+63,%C1" CR_TAB
5331 "sbiw r28,%o0-61", op, plen, -5);
5333 return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5334 "sbci r29,hi8(-%o0)" CR_TAB
5335 "st Y,%A1" CR_TAB
5336 "std Y+1,%B1" CR_TAB
5337 "std Y+2,%C1" CR_TAB
5338 "subi r28,lo8(%o0)" CR_TAB
5339 "sbci r29,hi8(%o0)", op, plen, -7);
5341 if (reg_base == REG_X)
5343 /* (X + d) = R */
5344 gcc_assert (!reg_overlap_mentioned_p (XEXP (base, 0), src));
5346 avr_asm_len ("adiw r26,%o0" CR_TAB
5347 "st X+,%A1" CR_TAB
5348 "st X+,%B1" CR_TAB
5349 "st X,%C1", op, plen, -4);
5351 if (!reg_unused_after (insn, XEXP (base, 0)))
5352 avr_asm_len ("sbiw r26,%o0+2", op, plen, 1);
5354 return "";
5357 return avr_asm_len ("std %A0,%A1" CR_TAB
5358 "std %B0,%B1" CR_TAB
5359 "std %C0,%C1", op, plen, -3);
5361 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5362 return avr_asm_len ("st %0,%C1" CR_TAB
5363 "st %0,%B1" CR_TAB
5364 "st %0,%A1", op, plen, -3);
5365 else if (GET_CODE (base) == POST_INC) /* (R++) */
5366 return avr_asm_len ("st %0,%A1" CR_TAB
5367 "st %0,%B1" CR_TAB
5368 "st %0,%C1", op, plen, -3);
5370 fatal_insn ("unknown move insn:",insn);
5371 return "";
5375 /* Move around 24-bit stuff. */
5377 const char *
5378 avr_out_movpsi (rtx_insn *insn, rtx *op, int *plen)
5380 rtx dest = op[0];
5381 rtx src = op[1];
5383 if (avr_mem_flash_p (src)
5384 || avr_mem_flash_p (dest))
5386 return avr_out_lpm (insn, op, plen);
5389 if (register_operand (dest, VOIDmode))
5391 if (register_operand (src, VOIDmode)) /* mov r,r */
5393 if (true_regnum (dest) > true_regnum (src))
5395 avr_asm_len ("mov %C0,%C1", op, plen, -1);
5397 if (AVR_HAVE_MOVW)
5398 return avr_asm_len ("movw %A0,%A1", op, plen, 1);
5399 else
5400 return avr_asm_len ("mov %B0,%B1" CR_TAB
5401 "mov %A0,%A1", op, plen, 2);
5403 else
5405 if (AVR_HAVE_MOVW)
5406 avr_asm_len ("movw %A0,%A1", op, plen, -1);
5407 else
5408 avr_asm_len ("mov %A0,%A1" CR_TAB
5409 "mov %B0,%B1", op, plen, -2);
5411 return avr_asm_len ("mov %C0,%C1", op, plen, 1);
5414 else if (CONSTANT_P (src))
5416 return avr_out_reload_inpsi (op, NULL_RTX, plen);
5418 else if (MEM_P (src))
5419 return avr_out_load_psi (insn, op, plen); /* mov r,m */
5421 else if (MEM_P (dest))
5423 rtx xop[2];
5425 xop[0] = dest;
5426 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
5428 return avr_out_store_psi (insn, xop, plen);
5431 fatal_insn ("invalid insn:", insn);
5432 return "";
5435 static const char*
5436 avr_out_movqi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5438 rtx dest = op[0];
5439 rtx src = op[1];
5440 rtx x = XEXP (dest, 0);
5442 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
5444 avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
5445 TINY_ADIW (%I0, %J0, %o0) CR_TAB
5446 "st %b0,__tmp_reg__", op, plen, -4);
5448 else
5450 avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
5451 "st %b0,%1", op, plen, -3);
5454 if (!reg_unused_after (insn, XEXP (x, 0)))
5455 avr_asm_len (TINY_SBIW (%I0, %J0, %o0), op, plen, 2);
5457 return "";
5460 static const char*
5461 out_movqi_mr_r (rtx_insn *insn, rtx op[], int *plen)
5463 rtx dest = op[0];
5464 rtx src = op[1];
5465 rtx x = XEXP (dest, 0);
5467 if (CONSTANT_ADDRESS_P (x))
5469 int n_words = AVR_TINY ? 1 : 2;
5470 return io_address_operand (x, QImode)
5471 ? avr_asm_len ("out %i0,%1", op, plen, -1)
5472 : avr_asm_len ("sts %m0,%1", op, plen, -n_words);
5474 else if (GET_CODE (x) == PLUS
5475 && REG_P (XEXP (x, 0))
5476 && CONST_INT_P (XEXP (x, 1)))
5478 /* memory access by reg+disp */
5480 int disp = INTVAL (XEXP (x, 1));
5482 if (AVR_TINY)
5483 return avr_out_movqi_mr_r_reg_disp_tiny (insn, op, plen);
5485 if (disp - GET_MODE_SIZE (GET_MODE (dest)) >= 63)
5487 if (REGNO (XEXP (x, 0)) != REG_Y)
5488 fatal_insn ("incorrect insn:",insn);
5490 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
5491 return avr_asm_len ("adiw r28,%o0-63" CR_TAB
5492 "std Y+63,%1" CR_TAB
5493 "sbiw r28,%o0-63", op, plen, -3);
5495 return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5496 "sbci r29,hi8(-%o0)" CR_TAB
5497 "st Y,%1" CR_TAB
5498 "subi r28,lo8(%o0)" CR_TAB
5499 "sbci r29,hi8(%o0)", op, plen, -5);
5501 else if (REGNO (XEXP (x, 0)) == REG_X)
5503 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
5505 avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
5506 "adiw r26,%o0" CR_TAB
5507 "st X,__tmp_reg__", op, plen, -3);
5509 else
5511 avr_asm_len ("adiw r26,%o0" CR_TAB
5512 "st X,%1", op, plen, -2);
5515 if (!reg_unused_after (insn, XEXP (x, 0)))
5516 avr_asm_len ("sbiw r26,%o0", op, plen, 1);
5518 return "";
5521 return avr_asm_len ("std %0,%1", op, plen, -1);
5524 return avr_asm_len ("st %0,%1", op, plen, -1);
5528 /* Helper for the next function for XMEGA. It does the same
5529 but with low byte first. */
5531 static const char*
5532 avr_out_movhi_mr_r_xmega (rtx_insn *insn, rtx op[], int *plen)
5534 rtx dest = op[0];
5535 rtx src = op[1];
5536 rtx base = XEXP (dest, 0);
5537 int reg_base = true_regnum (base);
5538 int reg_src = true_regnum (src);
5540 /* "volatile" forces writing low byte first, even if less efficient,
5541 for correct operation with 16-bit I/O registers like SP. */
5542 int mem_volatile_p = MEM_VOLATILE_P (dest);
5544 if (CONSTANT_ADDRESS_P (base))
5546 return io_address_operand (base, HImode)
5547 ? avr_asm_len ("out %i0,%A1" CR_TAB
5548 "out %i0+1,%B1", op, plen, -2)
5550 : avr_asm_len ("sts %m0,%A1" CR_TAB
5551 "sts %m0+1,%B1", op, plen, -4);
5554 if (reg_base > 0)
5556 if (reg_base != REG_X)
5557 return avr_asm_len ("st %0,%A1" CR_TAB
5558 "std %0+1,%B1", op, plen, -2);
5560 if (reg_src == REG_X)
5561 /* "st X+,r26" and "st -X,r26" are undefined. */
5562 avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5563 "st X,r26" CR_TAB
5564 "adiw r26,1" CR_TAB
5565 "st X,__tmp_reg__", op, plen, -4);
5566 else
5567 avr_asm_len ("st X+,%A1" CR_TAB
5568 "st X,%B1", op, plen, -2);
5570 return reg_unused_after (insn, base)
5571 ? ""
5572 : avr_asm_len ("sbiw r26,1", op, plen, 1);
5574 else if (GET_CODE (base) == PLUS)
5576 int disp = INTVAL (XEXP (base, 1));
5577 reg_base = REGNO (XEXP (base, 0));
5578 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5580 if (reg_base != REG_Y)
5581 fatal_insn ("incorrect insn:",insn);
5583 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
5584 ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
5585 "std Y+62,%A1" CR_TAB
5586 "std Y+63,%B1" CR_TAB
5587 "sbiw r28,%o0-62", op, plen, -4)
5589 : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5590 "sbci r29,hi8(-%o0)" CR_TAB
5591 "st Y,%A1" CR_TAB
5592 "std Y+1,%B1" CR_TAB
5593 "subi r28,lo8(%o0)" CR_TAB
5594 "sbci r29,hi8(%o0)", op, plen, -6);
5597 if (reg_base != REG_X)
5598 return avr_asm_len ("std %A0,%A1" CR_TAB
5599 "std %B0,%B1", op, plen, -2);
5600 /* (X + d) = R */
5601 return reg_src == REG_X
5602 ? avr_asm_len ("mov __tmp_reg__,r26" CR_TAB
5603 "mov __zero_reg__,r27" CR_TAB
5604 "adiw r26,%o0" CR_TAB
5605 "st X+,__tmp_reg__" CR_TAB
5606 "st X,__zero_reg__" CR_TAB
5607 "clr __zero_reg__" CR_TAB
5608 "sbiw r26,%o0+1", op, plen, -7)
5610 : avr_asm_len ("adiw r26,%o0" CR_TAB
5611 "st X+,%A1" CR_TAB
5612 "st X,%B1" CR_TAB
5613 "sbiw r26,%o0+1", op, plen, -4);
5615 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5617 if (!mem_volatile_p)
5618 return avr_asm_len ("st %0,%B1" CR_TAB
5619 "st %0,%A1", op, plen, -2);
5621 return REGNO (XEXP (base, 0)) == REG_X
5622 ? avr_asm_len ("sbiw r26,2" CR_TAB
5623 "st X+,%A1" CR_TAB
5624 "st X,%B1" CR_TAB
5625 "sbiw r26,1", op, plen, -4)
5627 : avr_asm_len ("sbiw %r0,2" CR_TAB
5628 "st %p0,%A1" CR_TAB
5629 "std %p0+1,%B1", op, plen, -3);
5631 else if (GET_CODE (base) == POST_INC) /* (R++) */
5633 return avr_asm_len ("st %0,%A1" CR_TAB
5634 "st %0,%B1", op, plen, -2);
5637 fatal_insn ("unknown move insn:",insn);
5638 return "";
5641 static const char*
5642 avr_out_movhi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5644 rtx dest = op[0];
5645 rtx src = op[1];
5646 rtx base = XEXP (dest, 0);
5647 int reg_base = true_regnum (base);
5648 int reg_src = true_regnum (src);
5649 int mem_volatile_p = MEM_VOLATILE_P (dest);
5651 if (reg_base == reg_src)
5653 return !mem_volatile_p && reg_unused_after (insn, src)
5654 ? avr_asm_len ("mov __tmp_reg__,%B1" CR_TAB
5655 "st %0,%A1" CR_TAB
5656 TINY_ADIW (%E0, %F0, 1) CR_TAB
5657 "st %0,__tmp_reg__", op, plen, -5)
5658 : avr_asm_len ("mov __tmp_reg__,%B1" CR_TAB
5659 TINY_ADIW (%E0, %F0, 1) CR_TAB
5660 "st %0,__tmp_reg__" CR_TAB
5661 TINY_SBIW (%E0, %F0, 1) CR_TAB
5662 "st %0, %A1", op, plen, -7);
5665 return !mem_volatile_p && reg_unused_after (insn, base)
5666 ? avr_asm_len ("st %0+,%A1" CR_TAB
5667 "st %0,%B1", op, plen, -2)
5668 : avr_asm_len (TINY_ADIW (%E0, %F0, 1) CR_TAB
5669 "st %0,%B1" CR_TAB
5670 "st -%0,%A1", op, plen, -4);
5673 static const char*
5674 avr_out_movhi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5676 rtx dest = op[0];
5677 rtx src = op[1];
5678 rtx base = XEXP (dest, 0);
5679 int reg_base = REGNO (XEXP (base, 0));
5680 int reg_src = true_regnum (src);
5682 if (reg_src == reg_base)
5683 avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
5684 "mov __zero_reg__,%B1" CR_TAB
5685 TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
5686 "st %b0,__zero_reg__" CR_TAB
5687 "st -%b0,__tmp_reg__" CR_TAB
5688 "clr __zero_reg__", op, plen, -7);
5689 else
5690 avr_asm_len (TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
5691 "st %b0,%B1" CR_TAB
5692 "st -%b0,%A1", op, plen, -4);
5694 if (!reg_unused_after (insn, XEXP (base, 0)))
5695 avr_asm_len (TINY_SBIW (%I0, %J0, %o0), op, plen, 2);
5697 return "";
5700 static const char*
5701 avr_out_movhi_mr_r_post_inc_tiny (rtx op[], int *plen)
5703 return avr_asm_len (TINY_ADIW (%I0, %J0, 1) CR_TAB
5704 "st %p0,%B1" CR_TAB
5705 "st -%p0,%A1" CR_TAB
5706 TINY_ADIW (%I0, %J0, 2), op, plen, -6);
5709 static const char*
5710 out_movhi_mr_r (rtx_insn *insn, rtx op[], int *plen)
5712 rtx dest = op[0];
5713 rtx src = op[1];
5714 rtx base = XEXP (dest, 0);
5715 int reg_base = true_regnum (base);
5716 int reg_src = true_regnum (src);
5717 int mem_volatile_p;
5719 /* "volatile" forces writing high-byte first (no-xmega) resp.
5720 low-byte first (xmega) even if less efficient, for correct
5721 operation with 16-bit I/O registers like. */
5723 if (AVR_XMEGA)
5724 return avr_out_movhi_mr_r_xmega (insn, op, plen);
5726 mem_volatile_p = MEM_VOLATILE_P (dest);
5728 if (CONSTANT_ADDRESS_P (base))
5730 int n_words = AVR_TINY ? 2 : 4;
5731 return io_address_operand (base, HImode)
5732 ? avr_asm_len ("out %i0+1,%B1" CR_TAB
5733 "out %i0,%A1", op, plen, -2)
5735 : avr_asm_len ("sts %m0+1,%B1" CR_TAB
5736 "sts %m0,%A1", op, plen, -n_words);
5739 if (reg_base > 0)
5741 if (AVR_TINY)
5742 return avr_out_movhi_mr_r_reg_no_disp_tiny (insn, op, plen);
5744 if (reg_base != REG_X)
5745 return avr_asm_len ("std %0+1,%B1" CR_TAB
5746 "st %0,%A1", op, plen, -2);
5748 if (reg_src == REG_X)
5749 /* "st X+,r26" and "st -X,r26" are undefined. */
5750 return !mem_volatile_p && reg_unused_after (insn, src)
5751 ? avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5752 "st X,r26" CR_TAB
5753 "adiw r26,1" CR_TAB
5754 "st X,__tmp_reg__", op, plen, -4)
5756 : avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5757 "adiw r26,1" CR_TAB
5758 "st X,__tmp_reg__" CR_TAB
5759 "sbiw r26,1" CR_TAB
5760 "st X,r26", op, plen, -5);
5762 return !mem_volatile_p && reg_unused_after (insn, base)
5763 ? avr_asm_len ("st X+,%A1" CR_TAB
5764 "st X,%B1", op, plen, -2)
5765 : avr_asm_len ("adiw r26,1" CR_TAB
5766 "st X,%B1" CR_TAB
5767 "st -X,%A1", op, plen, -3);
5769 else if (GET_CODE (base) == PLUS)
5771 int disp = INTVAL (XEXP (base, 1));
5773 if (AVR_TINY)
5774 return avr_out_movhi_mr_r_reg_disp_tiny (insn, op, plen);
5776 reg_base = REGNO (XEXP (base, 0));
5777 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5779 if (reg_base != REG_Y)
5780 fatal_insn ("incorrect insn:",insn);
5782 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
5783 ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
5784 "std Y+63,%B1" CR_TAB
5785 "std Y+62,%A1" CR_TAB
5786 "sbiw r28,%o0-62", op, plen, -4)
5788 : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5789 "sbci r29,hi8(-%o0)" CR_TAB
5790 "std Y+1,%B1" CR_TAB
5791 "st Y,%A1" CR_TAB
5792 "subi r28,lo8(%o0)" CR_TAB
5793 "sbci r29,hi8(%o0)", op, plen, -6);
5796 if (reg_base != REG_X)
5797 return avr_asm_len ("std %B0,%B1" CR_TAB
5798 "std %A0,%A1", op, plen, -2);
5799 /* (X + d) = R */
5800 return reg_src == REG_X
5801 ? avr_asm_len ("mov __tmp_reg__,r26" CR_TAB
5802 "mov __zero_reg__,r27" CR_TAB
5803 "adiw r26,%o0+1" CR_TAB
5804 "st X,__zero_reg__" CR_TAB
5805 "st -X,__tmp_reg__" CR_TAB
5806 "clr __zero_reg__" CR_TAB
5807 "sbiw r26,%o0", op, plen, -7)
5809 : avr_asm_len ("adiw r26,%o0+1" CR_TAB
5810 "st X,%B1" CR_TAB
5811 "st -X,%A1" CR_TAB
5812 "sbiw r26,%o0", op, plen, -4);
5814 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5816 return avr_asm_len ("st %0,%B1" CR_TAB
5817 "st %0,%A1", op, plen, -2);
5819 else if (GET_CODE (base) == POST_INC) /* (R++) */
5821 if (!mem_volatile_p)
5822 return avr_asm_len ("st %0,%A1" CR_TAB
5823 "st %0,%B1", op, plen, -2);
5825 if (AVR_TINY)
5826 return avr_out_movhi_mr_r_post_inc_tiny (op, plen);
5828 return REGNO (XEXP (base, 0)) == REG_X
5829 ? avr_asm_len ("adiw r26,1" CR_TAB
5830 "st X,%B1" CR_TAB
5831 "st -X,%A1" CR_TAB
5832 "adiw r26,2", op, plen, -4)
5834 : avr_asm_len ("std %p0+1,%B1" CR_TAB
5835 "st %p0,%A1" CR_TAB
5836 "adiw %r0,2", op, plen, -3);
5838 fatal_insn ("unknown move insn:",insn);
5839 return "";
5842 /* Return 1 if frame pointer for current function required. */
5844 static bool
5845 avr_frame_pointer_required_p (void)
5847 return (cfun->calls_alloca
5848 || cfun->calls_setjmp
5849 || cfun->has_nonlocal_label
5850 || crtl->args.info.nregs == 0
5851 || get_frame_size () > 0);
5854 /* Returns the condition of compare insn INSN, or UNKNOWN. */
5856 static RTX_CODE
5857 compare_condition (rtx_insn *insn)
5859 rtx_insn *next = next_real_insn (insn);
5861 if (next && JUMP_P (next))
5863 rtx pat = PATTERN (next);
5864 rtx src = SET_SRC (pat);
5866 if (IF_THEN_ELSE == GET_CODE (src))
5867 return GET_CODE (XEXP (src, 0));
5870 return UNKNOWN;
5874 /* Returns true iff INSN is a tst insn that only tests the sign. */
5876 static bool
5877 compare_sign_p (rtx_insn *insn)
5879 RTX_CODE cond = compare_condition (insn);
5880 return (cond == GE || cond == LT);
5884 /* Returns true iff the next insn is a JUMP_INSN with a condition
5885 that needs to be swapped (GT, GTU, LE, LEU). */
5887 static bool
5888 compare_diff_p (rtx_insn *insn)
5890 RTX_CODE cond = compare_condition (insn);
5891 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
5894 /* Returns true iff INSN is a compare insn with the EQ or NE condition. */
5896 static bool
5897 compare_eq_p (rtx_insn *insn)
5899 RTX_CODE cond = compare_condition (insn);
5900 return (cond == EQ || cond == NE);
5904 /* Output compare instruction
5906 compare (XOP[0], XOP[1])
5908 for a register XOP[0] and a compile-time constant XOP[1]. Return "".
5909 XOP[2] is an 8-bit scratch register as needed.
5911 PLEN == NULL: Output instructions.
5912 PLEN != NULL: Set *PLEN to the length (in words) of the sequence.
5913 Don't output anything. */
5915 const char*
5916 avr_out_compare (rtx_insn *insn, rtx *xop, int *plen)
5918 /* Register to compare and value to compare against. */
5919 rtx xreg = xop[0];
5920 rtx xval = xop[1];
5922 /* MODE of the comparison. */
5923 machine_mode mode;
5925 /* Number of bytes to operate on. */
5926 int n_bytes = GET_MODE_SIZE (GET_MODE (xreg));
5928 /* Value (0..0xff) held in clobber register xop[2] or -1 if unknown. */
5929 int clobber_val = -1;
5931 /* Map fixed mode operands to integer operands with the same binary
5932 representation. They are easier to handle in the remainder. */
5934 if (CONST_FIXED_P (xval))
5936 xreg = avr_to_int_mode (xop[0]);
5937 xval = avr_to_int_mode (xop[1]);
5940 mode = GET_MODE (xreg);
5942 gcc_assert (REG_P (xreg));
5943 gcc_assert ((CONST_INT_P (xval) && n_bytes <= 4)
5944 || (const_double_operand (xval, VOIDmode) && n_bytes == 8));
5946 if (plen)
5947 *plen = 0;
5949 /* Comparisons == +/-1 and != +/-1 can be done similar to camparing
5950 against 0 by ORing the bytes. This is one instruction shorter.
5951 Notice that 64-bit comparisons are always against reg:ALL8 18 (ACC_A)
5952 and therefore don't use this. */
5954 if (!test_hard_reg_class (LD_REGS, xreg)
5955 && compare_eq_p (insn)
5956 && reg_unused_after (insn, xreg))
5958 if (xval == const1_rtx)
5960 avr_asm_len ("dec %A0" CR_TAB
5961 "or %A0,%B0", xop, plen, 2);
5963 if (n_bytes >= 3)
5964 avr_asm_len ("or %A0,%C0", xop, plen, 1);
5966 if (n_bytes >= 4)
5967 avr_asm_len ("or %A0,%D0", xop, plen, 1);
5969 return "";
5971 else if (xval == constm1_rtx)
5973 if (n_bytes >= 4)
5974 avr_asm_len ("and %A0,%D0", xop, plen, 1);
5976 if (n_bytes >= 3)
5977 avr_asm_len ("and %A0,%C0", xop, plen, 1);
5979 return avr_asm_len ("and %A0,%B0" CR_TAB
5980 "com %A0", xop, plen, 2);
5984 /* Comparisons == -1 and != -1 of a d-register that's used after the
5985 comparison. (If it's unused after we use CPI / SBCI or ADIW sequence
5986 from below.) Instead of CPI Rlo,-1 / LDI Rx,-1 / CPC Rhi,Rx we can
5987 use CPI Rlo,-1 / CPC Rhi,Rlo which is 1 instruction shorter:
5988 If CPI is true then Rlo contains -1 and we can use Rlo instead of Rx
5989 when CPC'ing the high part. If CPI is false then CPC cannot render
5990 the result to true. This also works for the more generic case where
5991 the constant is of the form 0xabab. */
5993 if (n_bytes == 2
5994 && xval != const0_rtx
5995 && test_hard_reg_class (LD_REGS, xreg)
5996 && compare_eq_p (insn)
5997 && !reg_unused_after (insn, xreg))
5999 rtx xlo8 = simplify_gen_subreg (QImode, xval, mode, 0);
6000 rtx xhi8 = simplify_gen_subreg (QImode, xval, mode, 1);
6002 if (INTVAL (xlo8) == INTVAL (xhi8))
6004 xop[0] = xreg;
6005 xop[1] = xlo8;
6007 return avr_asm_len ("cpi %A0,%1" CR_TAB
6008 "cpc %B0,%A0", xop, plen, 2);
6012 for (int i = 0; i < n_bytes; i++)
6014 /* We compare byte-wise. */
6015 rtx reg8 = simplify_gen_subreg (QImode, xreg, mode, i);
6016 rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
6018 /* 8-bit value to compare with this byte. */
6019 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
6021 /* Registers R16..R31 can operate with immediate. */
6022 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
6024 xop[0] = reg8;
6025 xop[1] = gen_int_mode (val8, QImode);
6027 /* Word registers >= R24 can use SBIW/ADIW with 0..63. */
6029 if (i == 0
6030 && test_hard_reg_class (ADDW_REGS, reg8))
6032 int val16 = trunc_int_for_mode (INTVAL (xval), HImode);
6034 if (IN_RANGE (val16, 0, 63)
6035 && (val8 == 0
6036 || reg_unused_after (insn, xreg)))
6038 if (AVR_TINY)
6039 avr_asm_len (TINY_SBIW (%A0, %B0, %1), xop, plen, 2);
6040 else
6041 avr_asm_len ("sbiw %0,%1", xop, plen, 1);
6043 i++;
6044 continue;
6047 if (n_bytes == 2
6048 && IN_RANGE (val16, -63, -1)
6049 && compare_eq_p (insn)
6050 && reg_unused_after (insn, xreg))
6052 return AVR_TINY
6053 ? avr_asm_len (TINY_ADIW (%A0, %B0, %n1), xop, plen, 2)
6054 : avr_asm_len ("adiw %0,%n1", xop, plen, 1);
6058 /* Comparing against 0 is easy. */
6060 if (val8 == 0)
6062 avr_asm_len (i == 0
6063 ? "cp %0,__zero_reg__"
6064 : "cpc %0,__zero_reg__", xop, plen, 1);
6065 continue;
6068 /* Upper registers can compare and subtract-with-carry immediates.
6069 Notice that compare instructions do the same as respective subtract
6070 instruction; the only difference is that comparisons don't write
6071 the result back to the target register. */
6073 if (ld_reg_p)
6075 if (i == 0)
6077 avr_asm_len ("cpi %0,%1", xop, plen, 1);
6078 continue;
6080 else if (reg_unused_after (insn, xreg))
6082 avr_asm_len ("sbci %0,%1", xop, plen, 1);
6083 continue;
6087 /* Must load the value into the scratch register. */
6089 gcc_assert (REG_P (xop[2]));
6091 if (clobber_val != (int) val8)
6092 avr_asm_len ("ldi %2,%1", xop, plen, 1);
6093 clobber_val = (int) val8;
6095 avr_asm_len (i == 0
6096 ? "cp %0,%2"
6097 : "cpc %0,%2", xop, plen, 1);
6100 return "";
6104 /* Prepare operands of compare_const_di2 to be used with avr_out_compare. */
6106 const char*
6107 avr_out_compare64 (rtx_insn *insn, rtx *op, int *plen)
6109 rtx xop[3];
6111 xop[0] = gen_rtx_REG (DImode, 18);
6112 xop[1] = op[0];
6113 xop[2] = op[1];
6115 return avr_out_compare (insn, xop, plen);
6118 /* Output test instruction for HImode. */
6120 const char*
6121 avr_out_tsthi (rtx_insn *insn, rtx *op, int *plen)
6123 if (compare_sign_p (insn))
6125 avr_asm_len ("tst %B0", op, plen, -1);
6127 else if (reg_unused_after (insn, op[0])
6128 && compare_eq_p (insn))
6130 /* Faster than sbiw if we can clobber the operand. */
6131 avr_asm_len ("or %A0,%B0", op, plen, -1);
6133 else
6135 avr_out_compare (insn, op, plen);
6138 return "";
6142 /* Output test instruction for PSImode. */
6144 const char*
6145 avr_out_tstpsi (rtx_insn *insn, rtx *op, int *plen)
6147 if (compare_sign_p (insn))
6149 avr_asm_len ("tst %C0", op, plen, -1);
6151 else if (reg_unused_after (insn, op[0])
6152 && compare_eq_p (insn))
6154 /* Faster than sbiw if we can clobber the operand. */
6155 avr_asm_len ("or %A0,%B0" CR_TAB
6156 "or %A0,%C0", op, plen, -2);
6158 else
6160 avr_out_compare (insn, op, plen);
6163 return "";
6167 /* Output test instruction for SImode. */
6169 const char*
6170 avr_out_tstsi (rtx_insn *insn, rtx *op, int *plen)
6172 if (compare_sign_p (insn))
6174 avr_asm_len ("tst %D0", op, plen, -1);
6176 else if (reg_unused_after (insn, op[0])
6177 && compare_eq_p (insn))
6179 /* Faster than sbiw if we can clobber the operand. */
6180 avr_asm_len ("or %A0,%B0" CR_TAB
6181 "or %A0,%C0" CR_TAB
6182 "or %A0,%D0", op, plen, -3);
6184 else
6186 avr_out_compare (insn, op, plen);
6189 return "";
6193 /* Generate asm equivalent for various shifts. This only handles cases
6194 that are not already carefully hand-optimized in ?sh??i3_out.
6196 OPERANDS[0] resp. %0 in TEMPL is the operand to be shifted.
6197 OPERANDS[2] is the shift count as CONST_INT, MEM or REG.
6198 OPERANDS[3] is a QImode scratch register from LD regs if
6199 available and SCRATCH, otherwise (no scratch available)
6201 TEMPL is an assembler template that shifts by one position.
6202 T_LEN is the length of this template. */
6204 void
6205 out_shift_with_cnt (const char *templ, rtx_insn *insn, rtx operands[],
6206 int *plen, int t_len)
6208 bool second_label = true;
6209 bool saved_in_tmp = false;
6210 bool use_zero_reg = false;
6211 rtx op[5];
6213 op[0] = operands[0];
6214 op[1] = operands[1];
6215 op[2] = operands[2];
6216 op[3] = operands[3];
6218 if (plen)
6219 *plen = 0;
6221 if (CONST_INT_P (operands[2]))
6223 bool scratch = (GET_CODE (PATTERN (insn)) == PARALLEL
6224 && REG_P (operands[3]));
6225 int count = INTVAL (operands[2]);
6226 int max_len = 10; /* If larger than this, always use a loop. */
6228 if (count <= 0)
6229 return;
6231 if (count < 8 && !scratch)
6232 use_zero_reg = true;
6234 if (optimize_size)
6235 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
6237 if (t_len * count <= max_len)
6239 /* Output shifts inline with no loop - faster. */
6241 while (count-- > 0)
6242 avr_asm_len (templ, op, plen, t_len);
6244 return;
6247 if (scratch)
6249 avr_asm_len ("ldi %3,%2", op, plen, 1);
6251 else if (use_zero_reg)
6253 /* Hack to save one word: use __zero_reg__ as loop counter.
6254 Set one bit, then shift in a loop until it is 0 again. */
6256 op[3] = zero_reg_rtx;
6258 avr_asm_len ("set" CR_TAB
6259 "bld %3,%2-1", op, plen, 2);
6261 else
6263 /* No scratch register available, use one from LD_REGS (saved in
6264 __tmp_reg__) that doesn't overlap with registers to shift. */
6266 op[3] = all_regs_rtx[((REGNO (op[0]) - 1) & 15) + 16];
6267 op[4] = tmp_reg_rtx;
6268 saved_in_tmp = true;
6270 avr_asm_len ("mov %4,%3" CR_TAB
6271 "ldi %3,%2", op, plen, 2);
6274 second_label = false;
6276 else if (MEM_P (op[2]))
6278 rtx op_mov[2];
6280 op_mov[0] = op[3] = tmp_reg_rtx;
6281 op_mov[1] = op[2];
6283 out_movqi_r_mr (insn, op_mov, plen);
6285 else if (register_operand (op[2], QImode))
6287 op[3] = op[2];
6289 if (!reg_unused_after (insn, op[2])
6290 || reg_overlap_mentioned_p (op[0], op[2]))
6292 op[3] = tmp_reg_rtx;
6293 avr_asm_len ("mov %3,%2", op, plen, 1);
6296 else
6297 fatal_insn ("bad shift insn:", insn);
6299 if (second_label)
6300 avr_asm_len ("rjmp 2f", op, plen, 1);
6302 avr_asm_len ("1:", op, plen, 0);
6303 avr_asm_len (templ, op, plen, t_len);
6305 if (second_label)
6306 avr_asm_len ("2:", op, plen, 0);
6308 avr_asm_len (use_zero_reg ? "lsr %3" : "dec %3", op, plen, 1);
6309 avr_asm_len (second_label ? "brpl 1b" : "brne 1b", op, plen, 1);
6311 if (saved_in_tmp)
6312 avr_asm_len ("mov %3,%4", op, plen, 1);
6316 /* 8bit shift left ((char)x << i) */
6318 const char *
6319 ashlqi3_out (rtx_insn *insn, rtx operands[], int *len)
6321 if (CONST_INT_P (operands[2]))
6323 int k;
6325 if (!len)
6326 len = &k;
6328 switch (INTVAL (operands[2]))
6330 default:
6331 if (INTVAL (operands[2]) < 8)
6332 break;
6334 *len = 1;
6335 return "clr %0";
6337 case 1:
6338 *len = 1;
6339 return "lsl %0";
6341 case 2:
6342 *len = 2;
6343 return ("lsl %0" CR_TAB
6344 "lsl %0");
6346 case 3:
6347 *len = 3;
6348 return ("lsl %0" CR_TAB
6349 "lsl %0" CR_TAB
6350 "lsl %0");
6352 case 4:
6353 if (test_hard_reg_class (LD_REGS, operands[0]))
6355 *len = 2;
6356 return ("swap %0" CR_TAB
6357 "andi %0,0xf0");
6359 *len = 4;
6360 return ("lsl %0" CR_TAB
6361 "lsl %0" CR_TAB
6362 "lsl %0" CR_TAB
6363 "lsl %0");
6365 case 5:
6366 if (test_hard_reg_class (LD_REGS, operands[0]))
6368 *len = 3;
6369 return ("swap %0" CR_TAB
6370 "lsl %0" CR_TAB
6371 "andi %0,0xe0");
6373 *len = 5;
6374 return ("lsl %0" CR_TAB
6375 "lsl %0" CR_TAB
6376 "lsl %0" CR_TAB
6377 "lsl %0" CR_TAB
6378 "lsl %0");
6380 case 6:
6381 if (test_hard_reg_class (LD_REGS, operands[0]))
6383 *len = 4;
6384 return ("swap %0" CR_TAB
6385 "lsl %0" CR_TAB
6386 "lsl %0" CR_TAB
6387 "andi %0,0xc0");
6389 *len = 6;
6390 return ("lsl %0" CR_TAB
6391 "lsl %0" CR_TAB
6392 "lsl %0" CR_TAB
6393 "lsl %0" CR_TAB
6394 "lsl %0" CR_TAB
6395 "lsl %0");
6397 case 7:
6398 *len = 3;
6399 return ("ror %0" CR_TAB
6400 "clr %0" CR_TAB
6401 "ror %0");
6404 else if (CONSTANT_P (operands[2]))
6405 fatal_insn ("internal compiler error. Incorrect shift:", insn);
6407 out_shift_with_cnt ("lsl %0",
6408 insn, operands, len, 1);
6409 return "";
6413 /* 16bit shift left ((short)x << i) */
6415 const char *
6416 ashlhi3_out (rtx_insn *insn, rtx operands[], int *len)
6418 if (CONST_INT_P (operands[2]))
6420 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
6421 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
6422 int k;
6423 int *t = len;
6425 if (!len)
6426 len = &k;
6428 switch (INTVAL (operands[2]))
6430 default:
6431 if (INTVAL (operands[2]) < 16)
6432 break;
6434 *len = 2;
6435 return ("clr %B0" CR_TAB
6436 "clr %A0");
6438 case 4:
6439 if (optimize_size && scratch)
6440 break; /* 5 */
6441 if (ldi_ok)
6443 *len = 6;
6444 return ("swap %A0" CR_TAB
6445 "swap %B0" CR_TAB
6446 "andi %B0,0xf0" CR_TAB
6447 "eor %B0,%A0" CR_TAB
6448 "andi %A0,0xf0" CR_TAB
6449 "eor %B0,%A0");
6451 if (scratch)
6453 *len = 7;
6454 return ("swap %A0" CR_TAB
6455 "swap %B0" CR_TAB
6456 "ldi %3,0xf0" CR_TAB
6457 "and %B0,%3" CR_TAB
6458 "eor %B0,%A0" CR_TAB
6459 "and %A0,%3" CR_TAB
6460 "eor %B0,%A0");
6462 break; /* optimize_size ? 6 : 8 */
6464 case 5:
6465 if (optimize_size)
6466 break; /* scratch ? 5 : 6 */
6467 if (ldi_ok)
6469 *len = 8;
6470 return ("lsl %A0" CR_TAB
6471 "rol %B0" CR_TAB
6472 "swap %A0" CR_TAB
6473 "swap %B0" CR_TAB
6474 "andi %B0,0xf0" CR_TAB
6475 "eor %B0,%A0" CR_TAB
6476 "andi %A0,0xf0" CR_TAB
6477 "eor %B0,%A0");
6479 if (scratch)
6481 *len = 9;
6482 return ("lsl %A0" CR_TAB
6483 "rol %B0" CR_TAB
6484 "swap %A0" CR_TAB
6485 "swap %B0" CR_TAB
6486 "ldi %3,0xf0" CR_TAB
6487 "and %B0,%3" CR_TAB
6488 "eor %B0,%A0" CR_TAB
6489 "and %A0,%3" CR_TAB
6490 "eor %B0,%A0");
6492 break; /* 10 */
6494 case 6:
6495 if (optimize_size)
6496 break; /* scratch ? 5 : 6 */
6497 *len = 9;
6498 return ("clr __tmp_reg__" CR_TAB
6499 "lsr %B0" CR_TAB
6500 "ror %A0" CR_TAB
6501 "ror __tmp_reg__" CR_TAB
6502 "lsr %B0" CR_TAB
6503 "ror %A0" CR_TAB
6504 "ror __tmp_reg__" CR_TAB
6505 "mov %B0,%A0" CR_TAB
6506 "mov %A0,__tmp_reg__");
6508 case 7:
6509 *len = 5;
6510 return ("lsr %B0" CR_TAB
6511 "mov %B0,%A0" CR_TAB
6512 "clr %A0" CR_TAB
6513 "ror %B0" CR_TAB
6514 "ror %A0");
6516 case 8:
6517 return *len = 2, ("mov %B0,%A1" CR_TAB
6518 "clr %A0");
6520 case 9:
6521 *len = 3;
6522 return ("mov %B0,%A0" CR_TAB
6523 "clr %A0" CR_TAB
6524 "lsl %B0");
6526 case 10:
6527 *len = 4;
6528 return ("mov %B0,%A0" CR_TAB
6529 "clr %A0" CR_TAB
6530 "lsl %B0" CR_TAB
6531 "lsl %B0");
6533 case 11:
6534 *len = 5;
6535 return ("mov %B0,%A0" CR_TAB
6536 "clr %A0" CR_TAB
6537 "lsl %B0" CR_TAB
6538 "lsl %B0" CR_TAB
6539 "lsl %B0");
6541 case 12:
6542 if (ldi_ok)
6544 *len = 4;
6545 return ("mov %B0,%A0" CR_TAB
6546 "clr %A0" CR_TAB
6547 "swap %B0" CR_TAB
6548 "andi %B0,0xf0");
6550 if (scratch)
6552 *len = 5;
6553 return ("mov %B0,%A0" CR_TAB
6554 "clr %A0" CR_TAB
6555 "swap %B0" CR_TAB
6556 "ldi %3,0xf0" CR_TAB
6557 "and %B0,%3");
6559 *len = 6;
6560 return ("mov %B0,%A0" CR_TAB
6561 "clr %A0" CR_TAB
6562 "lsl %B0" CR_TAB
6563 "lsl %B0" CR_TAB
6564 "lsl %B0" CR_TAB
6565 "lsl %B0");
6567 case 13:
6568 if (ldi_ok)
6570 *len = 5;
6571 return ("mov %B0,%A0" CR_TAB
6572 "clr %A0" CR_TAB
6573 "swap %B0" CR_TAB
6574 "lsl %B0" CR_TAB
6575 "andi %B0,0xe0");
6577 if (AVR_HAVE_MUL && scratch)
6579 *len = 5;
6580 return ("ldi %3,0x20" CR_TAB
6581 "mul %A0,%3" CR_TAB
6582 "mov %B0,r0" CR_TAB
6583 "clr %A0" CR_TAB
6584 "clr __zero_reg__");
6586 if (optimize_size && scratch)
6587 break; /* 5 */
6588 if (scratch)
6590 *len = 6;
6591 return ("mov %B0,%A0" CR_TAB
6592 "clr %A0" CR_TAB
6593 "swap %B0" CR_TAB
6594 "lsl %B0" CR_TAB
6595 "ldi %3,0xe0" CR_TAB
6596 "and %B0,%3");
6598 if (AVR_HAVE_MUL)
6600 *len = 6;
6601 return ("set" CR_TAB
6602 "bld r1,5" CR_TAB
6603 "mul %A0,r1" CR_TAB
6604 "mov %B0,r0" CR_TAB
6605 "clr %A0" CR_TAB
6606 "clr __zero_reg__");
6608 *len = 7;
6609 return ("mov %B0,%A0" CR_TAB
6610 "clr %A0" CR_TAB
6611 "lsl %B0" CR_TAB
6612 "lsl %B0" CR_TAB
6613 "lsl %B0" CR_TAB
6614 "lsl %B0" CR_TAB
6615 "lsl %B0");
6617 case 14:
6618 if (AVR_HAVE_MUL && ldi_ok)
6620 *len = 5;
6621 return ("ldi %B0,0x40" CR_TAB
6622 "mul %A0,%B0" CR_TAB
6623 "mov %B0,r0" CR_TAB
6624 "clr %A0" CR_TAB
6625 "clr __zero_reg__");
6627 if (AVR_HAVE_MUL && scratch)
6629 *len = 5;
6630 return ("ldi %3,0x40" CR_TAB
6631 "mul %A0,%3" CR_TAB
6632 "mov %B0,r0" CR_TAB
6633 "clr %A0" CR_TAB
6634 "clr __zero_reg__");
6636 if (optimize_size && ldi_ok)
6638 *len = 5;
6639 return ("mov %B0,%A0" CR_TAB
6640 "ldi %A0,6" "\n1:\t"
6641 "lsl %B0" CR_TAB
6642 "dec %A0" CR_TAB
6643 "brne 1b");
6645 if (optimize_size && scratch)
6646 break; /* 5 */
6647 *len = 6;
6648 return ("clr %B0" CR_TAB
6649 "lsr %A0" CR_TAB
6650 "ror %B0" CR_TAB
6651 "lsr %A0" CR_TAB
6652 "ror %B0" CR_TAB
6653 "clr %A0");
6655 case 15:
6656 *len = 4;
6657 return ("clr %B0" CR_TAB
6658 "lsr %A0" CR_TAB
6659 "ror %B0" CR_TAB
6660 "clr %A0");
6662 len = t;
6664 out_shift_with_cnt ("lsl %A0" CR_TAB
6665 "rol %B0", insn, operands, len, 2);
6666 return "";
6670 /* 24-bit shift left */
6672 const char*
6673 avr_out_ashlpsi3 (rtx_insn *insn, rtx *op, int *plen)
6675 if (plen)
6676 *plen = 0;
6678 if (CONST_INT_P (op[2]))
6680 switch (INTVAL (op[2]))
6682 default:
6683 if (INTVAL (op[2]) < 24)
6684 break;
6686 return avr_asm_len ("clr %A0" CR_TAB
6687 "clr %B0" CR_TAB
6688 "clr %C0", op, plen, 3);
6690 case 8:
6692 int reg0 = REGNO (op[0]);
6693 int reg1 = REGNO (op[1]);
6695 if (reg0 >= reg1)
6696 return avr_asm_len ("mov %C0,%B1" CR_TAB
6697 "mov %B0,%A1" CR_TAB
6698 "clr %A0", op, plen, 3);
6699 else
6700 return avr_asm_len ("clr %A0" CR_TAB
6701 "mov %B0,%A1" CR_TAB
6702 "mov %C0,%B1", op, plen, 3);
6705 case 16:
6707 int reg0 = REGNO (op[0]);
6708 int reg1 = REGNO (op[1]);
6710 if (reg0 + 2 != reg1)
6711 avr_asm_len ("mov %C0,%A0", op, plen, 1);
6713 return avr_asm_len ("clr %B0" CR_TAB
6714 "clr %A0", op, plen, 2);
6717 case 23:
6718 return avr_asm_len ("clr %C0" CR_TAB
6719 "lsr %A0" CR_TAB
6720 "ror %C0" CR_TAB
6721 "clr %B0" CR_TAB
6722 "clr %A0", op, plen, 5);
6726 out_shift_with_cnt ("lsl %A0" CR_TAB
6727 "rol %B0" CR_TAB
6728 "rol %C0", insn, op, plen, 3);
6729 return "";
6733 /* 32bit shift left ((long)x << i) */
6735 const char *
6736 ashlsi3_out (rtx_insn *insn, rtx operands[], int *len)
6738 if (CONST_INT_P (operands[2]))
6740 int k;
6741 int *t = len;
6743 if (!len)
6744 len = &k;
6746 switch (INTVAL (operands[2]))
6748 default:
6749 if (INTVAL (operands[2]) < 32)
6750 break;
6752 if (AVR_HAVE_MOVW)
6753 return *len = 3, ("clr %D0" CR_TAB
6754 "clr %C0" CR_TAB
6755 "movw %A0,%C0");
6756 *len = 4;
6757 return ("clr %D0" CR_TAB
6758 "clr %C0" CR_TAB
6759 "clr %B0" CR_TAB
6760 "clr %A0");
6762 case 8:
6764 int reg0 = true_regnum (operands[0]);
6765 int reg1 = true_regnum (operands[1]);
6766 *len = 4;
6767 if (reg0 >= reg1)
6768 return ("mov %D0,%C1" CR_TAB
6769 "mov %C0,%B1" CR_TAB
6770 "mov %B0,%A1" CR_TAB
6771 "clr %A0");
6772 else
6773 return ("clr %A0" CR_TAB
6774 "mov %B0,%A1" CR_TAB
6775 "mov %C0,%B1" CR_TAB
6776 "mov %D0,%C1");
6779 case 16:
6781 int reg0 = true_regnum (operands[0]);
6782 int reg1 = true_regnum (operands[1]);
6783 if (reg0 + 2 == reg1)
6784 return *len = 2, ("clr %B0" CR_TAB
6785 "clr %A0");
6786 if (AVR_HAVE_MOVW)
6787 return *len = 3, ("movw %C0,%A1" CR_TAB
6788 "clr %B0" CR_TAB
6789 "clr %A0");
6790 else
6791 return *len = 4, ("mov %C0,%A1" CR_TAB
6792 "mov %D0,%B1" CR_TAB
6793 "clr %B0" CR_TAB
6794 "clr %A0");
6797 case 24:
6798 *len = 4;
6799 return ("mov %D0,%A1" CR_TAB
6800 "clr %C0" CR_TAB
6801 "clr %B0" CR_TAB
6802 "clr %A0");
6804 case 31:
6805 *len = 6;
6806 return ("clr %D0" CR_TAB
6807 "lsr %A0" CR_TAB
6808 "ror %D0" CR_TAB
6809 "clr %C0" CR_TAB
6810 "clr %B0" CR_TAB
6811 "clr %A0");
6813 len = t;
6815 out_shift_with_cnt ("lsl %A0" CR_TAB
6816 "rol %B0" CR_TAB
6817 "rol %C0" CR_TAB
6818 "rol %D0", insn, operands, len, 4);
6819 return "";
6822 /* 8bit arithmetic shift right ((signed char)x >> i) */
6824 const char *
6825 ashrqi3_out (rtx_insn *insn, rtx operands[], int *len)
6827 if (CONST_INT_P (operands[2]))
6829 int k;
6831 if (!len)
6832 len = &k;
6834 switch (INTVAL (operands[2]))
6836 case 1:
6837 *len = 1;
6838 return "asr %0";
6840 case 2:
6841 *len = 2;
6842 return ("asr %0" CR_TAB
6843 "asr %0");
6845 case 3:
6846 *len = 3;
6847 return ("asr %0" CR_TAB
6848 "asr %0" CR_TAB
6849 "asr %0");
6851 case 4:
6852 *len = 4;
6853 return ("asr %0" CR_TAB
6854 "asr %0" CR_TAB
6855 "asr %0" CR_TAB
6856 "asr %0");
6858 case 5:
6859 *len = 5;
6860 return ("asr %0" CR_TAB
6861 "asr %0" CR_TAB
6862 "asr %0" CR_TAB
6863 "asr %0" CR_TAB
6864 "asr %0");
6866 case 6:
6867 *len = 4;
6868 return ("bst %0,6" CR_TAB
6869 "lsl %0" CR_TAB
6870 "sbc %0,%0" CR_TAB
6871 "bld %0,0");
6873 default:
6874 if (INTVAL (operands[2]) < 8)
6875 break;
6877 /* fall through */
6879 case 7:
6880 *len = 2;
6881 return ("lsl %0" CR_TAB
6882 "sbc %0,%0");
6885 else if (CONSTANT_P (operands[2]))
6886 fatal_insn ("internal compiler error. Incorrect shift:", insn);
6888 out_shift_with_cnt ("asr %0",
6889 insn, operands, len, 1);
6890 return "";
6894 /* 16bit arithmetic shift right ((signed short)x >> i) */
6896 const char *
6897 ashrhi3_out (rtx_insn *insn, rtx operands[], int *len)
6899 if (CONST_INT_P (operands[2]))
6901 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
6902 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
6903 int k;
6904 int *t = len;
6906 if (!len)
6907 len = &k;
6909 switch (INTVAL (operands[2]))
6911 case 4:
6912 case 5:
6913 /* XXX try to optimize this too? */
6914 break;
6916 case 6:
6917 if (optimize_size)
6918 break; /* scratch ? 5 : 6 */
6919 *len = 8;
6920 return ("mov __tmp_reg__,%A0" CR_TAB
6921 "mov %A0,%B0" CR_TAB
6922 "lsl __tmp_reg__" CR_TAB
6923 "rol %A0" CR_TAB
6924 "sbc %B0,%B0" CR_TAB
6925 "lsl __tmp_reg__" CR_TAB
6926 "rol %A0" CR_TAB
6927 "rol %B0");
6929 case 7:
6930 *len = 4;
6931 return ("lsl %A0" CR_TAB
6932 "mov %A0,%B0" CR_TAB
6933 "rol %A0" CR_TAB
6934 "sbc %B0,%B0");
6936 case 8:
6938 int reg0 = true_regnum (operands[0]);
6939 int reg1 = true_regnum (operands[1]);
6941 if (reg0 == reg1)
6942 return *len = 3, ("mov %A0,%B0" CR_TAB
6943 "lsl %B0" CR_TAB
6944 "sbc %B0,%B0");
6945 else
6946 return *len = 4, ("mov %A0,%B1" CR_TAB
6947 "clr %B0" CR_TAB
6948 "sbrc %A0,7" CR_TAB
6949 "dec %B0");
6952 case 9:
6953 *len = 4;
6954 return ("mov %A0,%B0" CR_TAB
6955 "lsl %B0" CR_TAB
6956 "sbc %B0,%B0" CR_TAB
6957 "asr %A0");
6959 case 10:
6960 *len = 5;
6961 return ("mov %A0,%B0" CR_TAB
6962 "lsl %B0" CR_TAB
6963 "sbc %B0,%B0" CR_TAB
6964 "asr %A0" CR_TAB
6965 "asr %A0");
6967 case 11:
6968 if (AVR_HAVE_MUL && ldi_ok)
6970 *len = 5;
6971 return ("ldi %A0,0x20" CR_TAB
6972 "muls %B0,%A0" CR_TAB
6973 "mov %A0,r1" CR_TAB
6974 "sbc %B0,%B0" CR_TAB
6975 "clr __zero_reg__");
6977 if (optimize_size && scratch)
6978 break; /* 5 */
6979 *len = 6;
6980 return ("mov %A0,%B0" CR_TAB
6981 "lsl %B0" CR_TAB
6982 "sbc %B0,%B0" CR_TAB
6983 "asr %A0" CR_TAB
6984 "asr %A0" CR_TAB
6985 "asr %A0");
6987 case 12:
6988 if (AVR_HAVE_MUL && ldi_ok)
6990 *len = 5;
6991 return ("ldi %A0,0x10" CR_TAB
6992 "muls %B0,%A0" CR_TAB
6993 "mov %A0,r1" CR_TAB
6994 "sbc %B0,%B0" CR_TAB
6995 "clr __zero_reg__");
6997 if (optimize_size && scratch)
6998 break; /* 5 */
6999 *len = 7;
7000 return ("mov %A0,%B0" CR_TAB
7001 "lsl %B0" CR_TAB
7002 "sbc %B0,%B0" CR_TAB
7003 "asr %A0" CR_TAB
7004 "asr %A0" CR_TAB
7005 "asr %A0" CR_TAB
7006 "asr %A0");
7008 case 13:
7009 if (AVR_HAVE_MUL && ldi_ok)
7011 *len = 5;
7012 return ("ldi %A0,0x08" CR_TAB
7013 "muls %B0,%A0" CR_TAB
7014 "mov %A0,r1" CR_TAB
7015 "sbc %B0,%B0" CR_TAB
7016 "clr __zero_reg__");
7018 if (optimize_size)
7019 break; /* scratch ? 5 : 7 */
7020 *len = 8;
7021 return ("mov %A0,%B0" CR_TAB
7022 "lsl %B0" CR_TAB
7023 "sbc %B0,%B0" CR_TAB
7024 "asr %A0" CR_TAB
7025 "asr %A0" CR_TAB
7026 "asr %A0" CR_TAB
7027 "asr %A0" CR_TAB
7028 "asr %A0");
7030 case 14:
7031 *len = 5;
7032 return ("lsl %B0" CR_TAB
7033 "sbc %A0,%A0" CR_TAB
7034 "lsl %B0" CR_TAB
7035 "mov %B0,%A0" CR_TAB
7036 "rol %A0");
7038 default:
7039 if (INTVAL (operands[2]) < 16)
7040 break;
7042 /* fall through */
7044 case 15:
7045 return *len = 3, ("lsl %B0" CR_TAB
7046 "sbc %A0,%A0" CR_TAB
7047 "mov %B0,%A0");
7049 len = t;
7051 out_shift_with_cnt ("asr %B0" CR_TAB
7052 "ror %A0", insn, operands, len, 2);
7053 return "";
7057 /* 24-bit arithmetic shift right */
7059 const char*
7060 avr_out_ashrpsi3 (rtx_insn *insn, rtx *op, int *plen)
7062 int dest = REGNO (op[0]);
7063 int src = REGNO (op[1]);
7065 if (CONST_INT_P (op[2]))
7067 if (plen)
7068 *plen = 0;
7070 switch (INTVAL (op[2]))
7072 case 8:
7073 if (dest <= src)
7074 return avr_asm_len ("mov %A0,%B1" CR_TAB
7075 "mov %B0,%C1" CR_TAB
7076 "clr %C0" CR_TAB
7077 "sbrc %B0,7" CR_TAB
7078 "dec %C0", op, plen, 5);
7079 else
7080 return avr_asm_len ("clr %C0" CR_TAB
7081 "sbrc %C1,7" CR_TAB
7082 "dec %C0" CR_TAB
7083 "mov %B0,%C1" CR_TAB
7084 "mov %A0,%B1", op, plen, 5);
7086 case 16:
7087 if (dest != src + 2)
7088 avr_asm_len ("mov %A0,%C1", op, plen, 1);
7090 return avr_asm_len ("clr %B0" CR_TAB
7091 "sbrc %A0,7" CR_TAB
7092 "com %B0" CR_TAB
7093 "mov %C0,%B0", op, plen, 4);
7095 default:
7096 if (INTVAL (op[2]) < 24)
7097 break;
7099 /* fall through */
7101 case 23:
7102 return avr_asm_len ("lsl %C0" CR_TAB
7103 "sbc %A0,%A0" CR_TAB
7104 "mov %B0,%A0" CR_TAB
7105 "mov %C0,%A0", op, plen, 4);
7106 } /* switch */
7109 out_shift_with_cnt ("asr %C0" CR_TAB
7110 "ror %B0" CR_TAB
7111 "ror %A0", insn, op, plen, 3);
7112 return "";
7116 /* 32-bit arithmetic shift right ((signed long)x >> i) */
7118 const char *
7119 ashrsi3_out (rtx_insn *insn, rtx operands[], int *len)
7121 if (CONST_INT_P (operands[2]))
7123 int k;
7124 int *t = len;
7126 if (!len)
7127 len = &k;
7129 switch (INTVAL (operands[2]))
7131 case 8:
7133 int reg0 = true_regnum (operands[0]);
7134 int reg1 = true_regnum (operands[1]);
7135 *len=6;
7136 if (reg0 <= reg1)
7137 return ("mov %A0,%B1" CR_TAB
7138 "mov %B0,%C1" CR_TAB
7139 "mov %C0,%D1" CR_TAB
7140 "clr %D0" CR_TAB
7141 "sbrc %C0,7" CR_TAB
7142 "dec %D0");
7143 else
7144 return ("clr %D0" CR_TAB
7145 "sbrc %D1,7" CR_TAB
7146 "dec %D0" CR_TAB
7147 "mov %C0,%D1" CR_TAB
7148 "mov %B0,%C1" CR_TAB
7149 "mov %A0,%B1");
7152 case 16:
7154 int reg0 = true_regnum (operands[0]);
7155 int reg1 = true_regnum (operands[1]);
7157 if (reg0 == reg1 + 2)
7158 return *len = 4, ("clr %D0" CR_TAB
7159 "sbrc %B0,7" CR_TAB
7160 "com %D0" CR_TAB
7161 "mov %C0,%D0");
7162 if (AVR_HAVE_MOVW)
7163 return *len = 5, ("movw %A0,%C1" CR_TAB
7164 "clr %D0" CR_TAB
7165 "sbrc %B0,7" CR_TAB
7166 "com %D0" CR_TAB
7167 "mov %C0,%D0");
7168 else
7169 return *len = 6, ("mov %B0,%D1" CR_TAB
7170 "mov %A0,%C1" CR_TAB
7171 "clr %D0" CR_TAB
7172 "sbrc %B0,7" CR_TAB
7173 "com %D0" CR_TAB
7174 "mov %C0,%D0");
7177 case 24:
7178 return *len = 6, ("mov %A0,%D1" CR_TAB
7179 "clr %D0" CR_TAB
7180 "sbrc %A0,7" CR_TAB
7181 "com %D0" CR_TAB
7182 "mov %B0,%D0" CR_TAB
7183 "mov %C0,%D0");
7185 default:
7186 if (INTVAL (operands[2]) < 32)
7187 break;
7189 /* fall through */
7191 case 31:
7192 if (AVR_HAVE_MOVW)
7193 return *len = 4, ("lsl %D0" CR_TAB
7194 "sbc %A0,%A0" CR_TAB
7195 "mov %B0,%A0" CR_TAB
7196 "movw %C0,%A0");
7197 else
7198 return *len = 5, ("lsl %D0" CR_TAB
7199 "sbc %A0,%A0" CR_TAB
7200 "mov %B0,%A0" CR_TAB
7201 "mov %C0,%A0" CR_TAB
7202 "mov %D0,%A0");
7204 len = t;
7206 out_shift_with_cnt ("asr %D0" CR_TAB
7207 "ror %C0" CR_TAB
7208 "ror %B0" CR_TAB
7209 "ror %A0", insn, operands, len, 4);
7210 return "";
7213 /* 8-bit logic shift right ((unsigned char)x >> i) */
7215 const char *
7216 lshrqi3_out (rtx_insn *insn, rtx operands[], int *len)
7218 if (CONST_INT_P (operands[2]))
7220 int k;
7222 if (!len)
7223 len = &k;
7225 switch (INTVAL (operands[2]))
7227 default:
7228 if (INTVAL (operands[2]) < 8)
7229 break;
7231 *len = 1;
7232 return "clr %0";
7234 case 1:
7235 *len = 1;
7236 return "lsr %0";
7238 case 2:
7239 *len = 2;
7240 return ("lsr %0" CR_TAB
7241 "lsr %0");
7242 case 3:
7243 *len = 3;
7244 return ("lsr %0" CR_TAB
7245 "lsr %0" CR_TAB
7246 "lsr %0");
7248 case 4:
7249 if (test_hard_reg_class (LD_REGS, operands[0]))
7251 *len=2;
7252 return ("swap %0" CR_TAB
7253 "andi %0,0x0f");
7255 *len = 4;
7256 return ("lsr %0" CR_TAB
7257 "lsr %0" CR_TAB
7258 "lsr %0" CR_TAB
7259 "lsr %0");
7261 case 5:
7262 if (test_hard_reg_class (LD_REGS, operands[0]))
7264 *len = 3;
7265 return ("swap %0" CR_TAB
7266 "lsr %0" CR_TAB
7267 "andi %0,0x7");
7269 *len = 5;
7270 return ("lsr %0" CR_TAB
7271 "lsr %0" CR_TAB
7272 "lsr %0" CR_TAB
7273 "lsr %0" CR_TAB
7274 "lsr %0");
7276 case 6:
7277 if (test_hard_reg_class (LD_REGS, operands[0]))
7279 *len = 4;
7280 return ("swap %0" CR_TAB
7281 "lsr %0" CR_TAB
7282 "lsr %0" CR_TAB
7283 "andi %0,0x3");
7285 *len = 6;
7286 return ("lsr %0" CR_TAB
7287 "lsr %0" CR_TAB
7288 "lsr %0" CR_TAB
7289 "lsr %0" CR_TAB
7290 "lsr %0" CR_TAB
7291 "lsr %0");
7293 case 7:
7294 *len = 3;
7295 return ("rol %0" CR_TAB
7296 "clr %0" CR_TAB
7297 "rol %0");
7300 else if (CONSTANT_P (operands[2]))
7301 fatal_insn ("internal compiler error. Incorrect shift:", insn);
7303 out_shift_with_cnt ("lsr %0",
7304 insn, operands, len, 1);
7305 return "";
7308 /* 16-bit logic shift right ((unsigned short)x >> i) */
7310 const char *
7311 lshrhi3_out (rtx_insn *insn, rtx operands[], int *len)
7313 if (CONST_INT_P (operands[2]))
7315 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
7316 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
7317 int k;
7318 int *t = len;
7320 if (!len)
7321 len = &k;
7323 switch (INTVAL (operands[2]))
7325 default:
7326 if (INTVAL (operands[2]) < 16)
7327 break;
7329 *len = 2;
7330 return ("clr %B0" CR_TAB
7331 "clr %A0");
7333 case 4:
7334 if (optimize_size && scratch)
7335 break; /* 5 */
7336 if (ldi_ok)
7338 *len = 6;
7339 return ("swap %B0" CR_TAB
7340 "swap %A0" CR_TAB
7341 "andi %A0,0x0f" CR_TAB
7342 "eor %A0,%B0" CR_TAB
7343 "andi %B0,0x0f" CR_TAB
7344 "eor %A0,%B0");
7346 if (scratch)
7348 *len = 7;
7349 return ("swap %B0" CR_TAB
7350 "swap %A0" CR_TAB
7351 "ldi %3,0x0f" CR_TAB
7352 "and %A0,%3" CR_TAB
7353 "eor %A0,%B0" CR_TAB
7354 "and %B0,%3" CR_TAB
7355 "eor %A0,%B0");
7357 break; /* optimize_size ? 6 : 8 */
7359 case 5:
7360 if (optimize_size)
7361 break; /* scratch ? 5 : 6 */
7362 if (ldi_ok)
7364 *len = 8;
7365 return ("lsr %B0" CR_TAB
7366 "ror %A0" CR_TAB
7367 "swap %B0" CR_TAB
7368 "swap %A0" CR_TAB
7369 "andi %A0,0x0f" CR_TAB
7370 "eor %A0,%B0" CR_TAB
7371 "andi %B0,0x0f" CR_TAB
7372 "eor %A0,%B0");
7374 if (scratch)
7376 *len = 9;
7377 return ("lsr %B0" CR_TAB
7378 "ror %A0" CR_TAB
7379 "swap %B0" CR_TAB
7380 "swap %A0" CR_TAB
7381 "ldi %3,0x0f" CR_TAB
7382 "and %A0,%3" CR_TAB
7383 "eor %A0,%B0" CR_TAB
7384 "and %B0,%3" CR_TAB
7385 "eor %A0,%B0");
7387 break; /* 10 */
7389 case 6:
7390 if (optimize_size)
7391 break; /* scratch ? 5 : 6 */
7392 *len = 9;
7393 return ("clr __tmp_reg__" CR_TAB
7394 "lsl %A0" CR_TAB
7395 "rol %B0" CR_TAB
7396 "rol __tmp_reg__" CR_TAB
7397 "lsl %A0" CR_TAB
7398 "rol %B0" CR_TAB
7399 "rol __tmp_reg__" CR_TAB
7400 "mov %A0,%B0" CR_TAB
7401 "mov %B0,__tmp_reg__");
7403 case 7:
7404 *len = 5;
7405 return ("lsl %A0" CR_TAB
7406 "mov %A0,%B0" CR_TAB
7407 "rol %A0" CR_TAB
7408 "sbc %B0,%B0" CR_TAB
7409 "neg %B0");
7411 case 8:
7412 return *len = 2, ("mov %A0,%B1" CR_TAB
7413 "clr %B0");
7415 case 9:
7416 *len = 3;
7417 return ("mov %A0,%B0" CR_TAB
7418 "clr %B0" CR_TAB
7419 "lsr %A0");
7421 case 10:
7422 *len = 4;
7423 return ("mov %A0,%B0" CR_TAB
7424 "clr %B0" CR_TAB
7425 "lsr %A0" CR_TAB
7426 "lsr %A0");
7428 case 11:
7429 *len = 5;
7430 return ("mov %A0,%B0" CR_TAB
7431 "clr %B0" CR_TAB
7432 "lsr %A0" CR_TAB
7433 "lsr %A0" CR_TAB
7434 "lsr %A0");
7436 case 12:
7437 if (ldi_ok)
7439 *len = 4;
7440 return ("mov %A0,%B0" CR_TAB
7441 "clr %B0" CR_TAB
7442 "swap %A0" CR_TAB
7443 "andi %A0,0x0f");
7445 if (scratch)
7447 *len = 5;
7448 return ("mov %A0,%B0" CR_TAB
7449 "clr %B0" CR_TAB
7450 "swap %A0" CR_TAB
7451 "ldi %3,0x0f" CR_TAB
7452 "and %A0,%3");
7454 *len = 6;
7455 return ("mov %A0,%B0" CR_TAB
7456 "clr %B0" CR_TAB
7457 "lsr %A0" CR_TAB
7458 "lsr %A0" CR_TAB
7459 "lsr %A0" CR_TAB
7460 "lsr %A0");
7462 case 13:
7463 if (ldi_ok)
7465 *len = 5;
7466 return ("mov %A0,%B0" CR_TAB
7467 "clr %B0" CR_TAB
7468 "swap %A0" CR_TAB
7469 "lsr %A0" CR_TAB
7470 "andi %A0,0x07");
7472 if (AVR_HAVE_MUL && scratch)
7474 *len = 5;
7475 return ("ldi %3,0x08" CR_TAB
7476 "mul %B0,%3" CR_TAB
7477 "mov %A0,r1" CR_TAB
7478 "clr %B0" CR_TAB
7479 "clr __zero_reg__");
7481 if (optimize_size && scratch)
7482 break; /* 5 */
7483 if (scratch)
7485 *len = 6;
7486 return ("mov %A0,%B0" CR_TAB
7487 "clr %B0" CR_TAB
7488 "swap %A0" CR_TAB
7489 "lsr %A0" CR_TAB
7490 "ldi %3,0x07" CR_TAB
7491 "and %A0,%3");
7493 if (AVR_HAVE_MUL)
7495 *len = 6;
7496 return ("set" CR_TAB
7497 "bld r1,3" CR_TAB
7498 "mul %B0,r1" CR_TAB
7499 "mov %A0,r1" CR_TAB
7500 "clr %B0" CR_TAB
7501 "clr __zero_reg__");
7503 *len = 7;
7504 return ("mov %A0,%B0" CR_TAB
7505 "clr %B0" CR_TAB
7506 "lsr %A0" CR_TAB
7507 "lsr %A0" CR_TAB
7508 "lsr %A0" CR_TAB
7509 "lsr %A0" CR_TAB
7510 "lsr %A0");
7512 case 14:
7513 if (AVR_HAVE_MUL && ldi_ok)
7515 *len = 5;
7516 return ("ldi %A0,0x04" CR_TAB
7517 "mul %B0,%A0" CR_TAB
7518 "mov %A0,r1" CR_TAB
7519 "clr %B0" CR_TAB
7520 "clr __zero_reg__");
7522 if (AVR_HAVE_MUL && scratch)
7524 *len = 5;
7525 return ("ldi %3,0x04" CR_TAB
7526 "mul %B0,%3" CR_TAB
7527 "mov %A0,r1" CR_TAB
7528 "clr %B0" CR_TAB
7529 "clr __zero_reg__");
7531 if (optimize_size && ldi_ok)
7533 *len = 5;
7534 return ("mov %A0,%B0" CR_TAB
7535 "ldi %B0,6" "\n1:\t"
7536 "lsr %A0" CR_TAB
7537 "dec %B0" CR_TAB
7538 "brne 1b");
7540 if (optimize_size && scratch)
7541 break; /* 5 */
7542 *len = 6;
7543 return ("clr %A0" CR_TAB
7544 "lsl %B0" CR_TAB
7545 "rol %A0" CR_TAB
7546 "lsl %B0" CR_TAB
7547 "rol %A0" CR_TAB
7548 "clr %B0");
7550 case 15:
7551 *len = 4;
7552 return ("clr %A0" CR_TAB
7553 "lsl %B0" CR_TAB
7554 "rol %A0" CR_TAB
7555 "clr %B0");
7557 len = t;
7559 out_shift_with_cnt ("lsr %B0" CR_TAB
7560 "ror %A0", insn, operands, len, 2);
7561 return "";
7565 /* 24-bit logic shift right */
7567 const char*
7568 avr_out_lshrpsi3 (rtx_insn *insn, rtx *op, int *plen)
7570 int dest = REGNO (op[0]);
7571 int src = REGNO (op[1]);
7573 if (CONST_INT_P (op[2]))
7575 if (plen)
7576 *plen = 0;
7578 switch (INTVAL (op[2]))
7580 case 8:
7581 if (dest <= src)
7582 return avr_asm_len ("mov %A0,%B1" CR_TAB
7583 "mov %B0,%C1" CR_TAB
7584 "clr %C0", op, plen, 3);
7585 else
7586 return avr_asm_len ("clr %C0" CR_TAB
7587 "mov %B0,%C1" CR_TAB
7588 "mov %A0,%B1", op, plen, 3);
7590 case 16:
7591 if (dest != src + 2)
7592 avr_asm_len ("mov %A0,%C1", op, plen, 1);
7594 return avr_asm_len ("clr %B0" CR_TAB
7595 "clr %C0", op, plen, 2);
7597 default:
7598 if (INTVAL (op[2]) < 24)
7599 break;
7601 /* fall through */
7603 case 23:
7604 return avr_asm_len ("clr %A0" CR_TAB
7605 "sbrc %C0,7" CR_TAB
7606 "inc %A0" CR_TAB
7607 "clr %B0" CR_TAB
7608 "clr %C0", op, plen, 5);
7609 } /* switch */
7612 out_shift_with_cnt ("lsr %C0" CR_TAB
7613 "ror %B0" CR_TAB
7614 "ror %A0", insn, op, plen, 3);
7615 return "";
7619 /* 32-bit logic shift right ((unsigned int)x >> i) */
7621 const char *
7622 lshrsi3_out (rtx_insn *insn, rtx operands[], int *len)
7624 if (CONST_INT_P (operands[2]))
7626 int k;
7627 int *t = len;
7629 if (!len)
7630 len = &k;
7632 switch (INTVAL (operands[2]))
7634 default:
7635 if (INTVAL (operands[2]) < 32)
7636 break;
7638 if (AVR_HAVE_MOVW)
7639 return *len = 3, ("clr %D0" CR_TAB
7640 "clr %C0" CR_TAB
7641 "movw %A0,%C0");
7642 *len = 4;
7643 return ("clr %D0" CR_TAB
7644 "clr %C0" CR_TAB
7645 "clr %B0" CR_TAB
7646 "clr %A0");
7648 case 8:
7650 int reg0 = true_regnum (operands[0]);
7651 int reg1 = true_regnum (operands[1]);
7652 *len = 4;
7653 if (reg0 <= reg1)
7654 return ("mov %A0,%B1" CR_TAB
7655 "mov %B0,%C1" CR_TAB
7656 "mov %C0,%D1" CR_TAB
7657 "clr %D0");
7658 else
7659 return ("clr %D0" CR_TAB
7660 "mov %C0,%D1" CR_TAB
7661 "mov %B0,%C1" CR_TAB
7662 "mov %A0,%B1");
7665 case 16:
7667 int reg0 = true_regnum (operands[0]);
7668 int reg1 = true_regnum (operands[1]);
7670 if (reg0 == reg1 + 2)
7671 return *len = 2, ("clr %C0" CR_TAB
7672 "clr %D0");
7673 if (AVR_HAVE_MOVW)
7674 return *len = 3, ("movw %A0,%C1" CR_TAB
7675 "clr %C0" CR_TAB
7676 "clr %D0");
7677 else
7678 return *len = 4, ("mov %B0,%D1" CR_TAB
7679 "mov %A0,%C1" CR_TAB
7680 "clr %C0" CR_TAB
7681 "clr %D0");
7684 case 24:
7685 return *len = 4, ("mov %A0,%D1" CR_TAB
7686 "clr %B0" CR_TAB
7687 "clr %C0" CR_TAB
7688 "clr %D0");
7690 case 31:
7691 *len = 6;
7692 return ("clr %A0" CR_TAB
7693 "sbrc %D0,7" CR_TAB
7694 "inc %A0" CR_TAB
7695 "clr %B0" CR_TAB
7696 "clr %C0" CR_TAB
7697 "clr %D0");
7699 len = t;
7701 out_shift_with_cnt ("lsr %D0" CR_TAB
7702 "ror %C0" CR_TAB
7703 "ror %B0" CR_TAB
7704 "ror %A0", insn, operands, len, 4);
7705 return "";
7709 /* Output addition of register XOP[0] and compile time constant XOP[2].
7710 CODE == PLUS: perform addition by using ADD instructions or
7711 CODE == MINUS: perform addition by using SUB instructions:
7713 XOP[0] = XOP[0] + XOP[2]
7715 Or perform addition/subtraction with register XOP[2] depending on CODE:
7717 XOP[0] = XOP[0] +/- XOP[2]
7719 If PLEN == NULL, print assembler instructions to perform the operation;
7720 otherwise, set *PLEN to the length of the instruction sequence (in words)
7721 printed with PLEN == NULL. XOP[3] is an 8-bit scratch register or NULL_RTX.
7722 Set *PCC to effect on cc0 according to respective CC_* insn attribute.
7724 CODE_SAT == UNKNOWN: Perform ordinary, non-saturating operation.
7725 CODE_SAT != UNKNOWN: Perform operation and saturate according to CODE_SAT.
7726 If CODE_SAT != UNKNOWN then SIGN contains the sign of the summand resp.
7727 the subtrahend in the original insn, provided it is a compile time constant.
7728 In all other cases, SIGN is 0.
7730 If OUT_LABEL is true, print the final 0: label which is needed for
7731 saturated addition / subtraction. The only case where OUT_LABEL = false
7732 is useful is for saturated addition / subtraction performed during
7733 fixed-point rounding, cf. `avr_out_round'. */
7735 static void
7736 avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc,
7737 enum rtx_code code_sat, int sign, bool out_label)
7739 /* MODE of the operation. */
7740 machine_mode mode = GET_MODE (xop[0]);
7742 /* INT_MODE of the same size. */
7743 scalar_int_mode imode = int_mode_for_mode (mode).require ();
7745 /* Number of bytes to operate on. */
7746 int n_bytes = GET_MODE_SIZE (mode);
7748 /* Value (0..0xff) held in clobber register op[3] or -1 if unknown. */
7749 int clobber_val = -1;
7751 /* op[0]: 8-bit destination register
7752 op[1]: 8-bit const int
7753 op[2]: 8-bit scratch register */
7754 rtx op[3];
7756 /* Started the operation? Before starting the operation we may skip
7757 adding 0. This is no more true after the operation started because
7758 carry must be taken into account. */
7759 bool started = false;
7761 /* Value to add. There are two ways to add VAL: R += VAL and R -= -VAL. */
7762 rtx xval = xop[2];
7764 /* Output a BRVC instruction. Only needed with saturation. */
7765 bool out_brvc = true;
7767 if (plen)
7768 *plen = 0;
7770 if (REG_P (xop[2]))
7772 *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_CLOBBER;
7774 for (int i = 0; i < n_bytes; i++)
7776 /* We operate byte-wise on the destination. */
7777 op[0] = simplify_gen_subreg (QImode, xop[0], mode, i);
7778 op[1] = simplify_gen_subreg (QImode, xop[2], mode, i);
7780 if (i == 0)
7781 avr_asm_len (code == PLUS ? "add %0,%1" : "sub %0,%1",
7782 op, plen, 1);
7783 else
7784 avr_asm_len (code == PLUS ? "adc %0,%1" : "sbc %0,%1",
7785 op, plen, 1);
7788 if (reg_overlap_mentioned_p (xop[0], xop[2]))
7790 gcc_assert (REGNO (xop[0]) == REGNO (xop[2]));
7792 if (MINUS == code)
7793 return;
7796 goto saturate;
7799 /* Except in the case of ADIW with 16-bit register (see below)
7800 addition does not set cc0 in a usable way. */
7802 *pcc = (MINUS == code) ? CC_SET_CZN : CC_CLOBBER;
7804 if (CONST_FIXED_P (xval))
7805 xval = avr_to_int_mode (xval);
7807 /* Adding/Subtracting zero is a no-op. */
7809 if (xval == const0_rtx)
7811 *pcc = CC_NONE;
7812 return;
7815 if (MINUS == code)
7816 xval = simplify_unary_operation (NEG, imode, xval, imode);
7818 op[2] = xop[3];
7820 if (SS_PLUS == code_sat && MINUS == code
7821 && sign < 0
7822 && 0x80 == (INTVAL (simplify_gen_subreg (QImode, xval, imode, n_bytes-1))
7823 & GET_MODE_MASK (QImode)))
7825 /* We compute x + 0x80 by means of SUB instructions. We negated the
7826 constant subtrahend above and are left with x - (-128) so that we
7827 need something like SUBI r,128 which does not exist because SUBI sets
7828 V according to the sign of the subtrahend. Notice the only case
7829 where this must be done is when NEG overflowed in case [2s] because
7830 the V computation needs the right sign of the subtrahend. */
7832 rtx msb = simplify_gen_subreg (QImode, xop[0], mode, n_bytes - 1);
7834 avr_asm_len ("subi %0,128" CR_TAB
7835 "brmi 0f", &msb, plen, 2);
7836 out_brvc = false;
7838 goto saturate;
7841 for (int i = 0; i < n_bytes; i++)
7843 /* We operate byte-wise on the destination. */
7844 rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
7845 rtx xval8 = simplify_gen_subreg (QImode, xval, imode, i);
7847 /* 8-bit value to operate with this byte. */
7848 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
7850 /* Registers R16..R31 can operate with immediate. */
7851 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
7853 op[0] = reg8;
7854 op[1] = gen_int_mode (val8, QImode);
7856 /* To get usable cc0 no low-bytes must have been skipped. */
7858 if (i && !started)
7859 *pcc = CC_CLOBBER;
7861 if (!started
7862 && i % 2 == 0
7863 && i + 2 <= n_bytes
7864 && test_hard_reg_class (ADDW_REGS, reg8))
7866 rtx xval16 = simplify_gen_subreg (HImode, xval, imode, i);
7867 unsigned int val16 = UINTVAL (xval16) & GET_MODE_MASK (HImode);
7869 /* Registers R24, X, Y, Z can use ADIW/SBIW with constants < 64
7870 i.e. operate word-wise. */
7872 if (val16 < 64)
7874 if (val16 != 0)
7876 started = true;
7877 avr_asm_len (code == PLUS ? "adiw %0,%1" : "sbiw %0,%1",
7878 op, plen, 1);
7880 if (n_bytes == 2 && PLUS == code)
7881 *pcc = CC_SET_CZN;
7884 i++;
7885 continue;
7889 if (val8 == 0)
7891 if (started)
7892 avr_asm_len (code == PLUS
7893 ? "adc %0,__zero_reg__" : "sbc %0,__zero_reg__",
7894 op, plen, 1);
7895 continue;
7897 else if ((val8 == 1 || val8 == 0xff)
7898 && UNKNOWN == code_sat
7899 && !started
7900 && i == n_bytes - 1)
7902 avr_asm_len ((code == PLUS) ^ (val8 == 1) ? "dec %0" : "inc %0",
7903 op, plen, 1);
7904 *pcc = CC_CLOBBER;
7905 break;
7908 switch (code)
7910 case PLUS:
7912 gcc_assert (plen != NULL || (op[2] && REG_P (op[2])));
7914 if (plen != NULL && UNKNOWN != code_sat)
7916 /* This belongs to the x + 0x80 corner case. The code with
7917 ADD instruction is not smaller, thus make this case
7918 expensive so that the caller won't pick it. */
7920 *plen += 10;
7921 break;
7924 if (clobber_val != (int) val8)
7925 avr_asm_len ("ldi %2,%1", op, plen, 1);
7926 clobber_val = (int) val8;
7928 avr_asm_len (started ? "adc %0,%2" : "add %0,%2", op, plen, 1);
7930 break; /* PLUS */
7932 case MINUS:
7934 if (ld_reg_p)
7935 avr_asm_len (started ? "sbci %0,%1" : "subi %0,%1", op, plen, 1);
7936 else
7938 gcc_assert (plen != NULL || REG_P (op[2]));
7940 if (clobber_val != (int) val8)
7941 avr_asm_len ("ldi %2,%1", op, plen, 1);
7942 clobber_val = (int) val8;
7944 avr_asm_len (started ? "sbc %0,%2" : "sub %0,%2", op, plen, 1);
7947 break; /* MINUS */
7949 default:
7950 /* Unknown code */
7951 gcc_unreachable();
7954 started = true;
7956 } /* for all sub-bytes */
7958 saturate:
7960 if (UNKNOWN == code_sat)
7961 return;
7963 *pcc = (int) CC_CLOBBER;
7965 /* Vanilla addition/subtraction is done. We are left with saturation.
7967 We have to compute A = A <op> B where A is a register and
7968 B is a register or a non-zero compile time constant CONST.
7969 A is register class "r" if unsigned && B is REG. Otherwise, A is in "d".
7970 B stands for the original operand $2 in INSN. In the case of B = CONST,
7971 SIGN in { -1, 1 } is the sign of B. Otherwise, SIGN is 0.
7973 CODE is the instruction flavor we use in the asm sequence to perform <op>.
7976 unsigned
7977 operation | code | sat if | b is | sat value | case
7978 -----------------+-------+----------+--------------+-----------+-------
7979 + as a + b | add | C == 1 | const, reg | u+ = 0xff | [1u]
7980 + as a - (-b) | sub | C == 0 | const | u+ = 0xff | [2u]
7981 - as a - b | sub | C == 1 | const, reg | u- = 0 | [3u]
7982 - as a + (-b) | add | C == 0 | const | u- = 0 | [4u]
7985 signed
7986 operation | code | sat if | b is | sat value | case
7987 -----------------+-------+----------+--------------+-----------+-------
7988 + as a + b | add | V == 1 | const, reg | s+ | [1s]
7989 + as a - (-b) | sub | V == 1 | const | s+ | [2s]
7990 - as a - b | sub | V == 1 | const, reg | s- | [3s]
7991 - as a + (-b) | add | V == 1 | const | s- | [4s]
7993 s+ = b < 0 ? -0x80 : 0x7f
7994 s- = b < 0 ? 0x7f : -0x80
7996 The cases a - b actually perform a - (-(-b)) if B is CONST.
7999 op[0] = simplify_gen_subreg (QImode, xop[0], mode, n_bytes-1);
8000 op[1] = n_bytes > 1
8001 ? simplify_gen_subreg (QImode, xop[0], mode, n_bytes-2)
8002 : NULL_RTX;
8004 bool need_copy = true;
8005 int len_call = 1 + AVR_HAVE_JMP_CALL;
8007 switch (code_sat)
8009 default:
8010 gcc_unreachable();
8012 case SS_PLUS:
8013 case SS_MINUS:
8015 if (out_brvc)
8016 avr_asm_len ("brvc 0f", op, plen, 1);
8018 if (reg_overlap_mentioned_p (xop[0], xop[2]))
8020 /* [1s,reg] */
8022 if (n_bytes == 1)
8023 avr_asm_len ("ldi %0,0x7f" CR_TAB
8024 "adc %0,__zero_reg__", op, plen, 2);
8025 else
8026 avr_asm_len ("ldi %0,0x7f" CR_TAB
8027 "ldi %1,0xff" CR_TAB
8028 "adc %1,__zero_reg__" CR_TAB
8029 "adc %0,__zero_reg__", op, plen, 4);
8031 else if (sign == 0 && PLUS == code)
8033 /* [1s,reg] */
8035 op[2] = simplify_gen_subreg (QImode, xop[2], mode, n_bytes-1);
8037 if (n_bytes == 1)
8038 avr_asm_len ("ldi %0,0x80" CR_TAB
8039 "sbrs %2,7" CR_TAB
8040 "dec %0", op, plen, 3);
8041 else
8042 avr_asm_len ("ldi %0,0x80" CR_TAB
8043 "cp %2,%0" CR_TAB
8044 "sbc %1,%1" CR_TAB
8045 "sbci %0,0", op, plen, 4);
8047 else if (sign == 0 && MINUS == code)
8049 /* [3s,reg] */
8051 op[2] = simplify_gen_subreg (QImode, xop[2], mode, n_bytes-1);
8053 if (n_bytes == 1)
8054 avr_asm_len ("ldi %0,0x7f" CR_TAB
8055 "sbrs %2,7" CR_TAB
8056 "inc %0", op, plen, 3);
8057 else
8058 avr_asm_len ("ldi %0,0x7f" CR_TAB
8059 "cp %0,%2" CR_TAB
8060 "sbc %1,%1" CR_TAB
8061 "sbci %0,-1", op, plen, 4);
8063 else if ((sign < 0) ^ (SS_MINUS == code_sat))
8065 /* [1s,const,B < 0] [2s,B < 0] */
8066 /* [3s,const,B > 0] [4s,B > 0] */
8068 if (n_bytes == 8)
8070 avr_asm_len ("%~call __clr_8", op, plen, len_call);
8071 need_copy = false;
8074 avr_asm_len ("ldi %0,0x80", op, plen, 1);
8075 if (n_bytes > 1 && need_copy)
8076 avr_asm_len ("clr %1", op, plen, 1);
8078 else if ((sign > 0) ^ (SS_MINUS == code_sat))
8080 /* [1s,const,B > 0] [2s,B > 0] */
8081 /* [3s,const,B < 0] [4s,B < 0] */
8083 if (n_bytes == 8)
8085 avr_asm_len ("sec" CR_TAB
8086 "%~call __sbc_8", op, plen, 1 + len_call);
8087 need_copy = false;
8090 avr_asm_len ("ldi %0,0x7f", op, plen, 1);
8091 if (n_bytes > 1 && need_copy)
8092 avr_asm_len ("ldi %1,0xff", op, plen, 1);
8094 else
8095 gcc_unreachable();
8097 break;
8099 case US_PLUS:
8100 /* [1u] : [2u] */
8102 avr_asm_len (PLUS == code ? "brcc 0f" : "brcs 0f", op, plen, 1);
8104 if (n_bytes == 8)
8106 if (MINUS == code)
8107 avr_asm_len ("sec", op, plen, 1);
8108 avr_asm_len ("%~call __sbc_8", op, plen, len_call);
8110 need_copy = false;
8112 else
8114 if (MINUS == code && !test_hard_reg_class (LD_REGS, op[0]))
8115 avr_asm_len ("sec" CR_TAB
8116 "sbc %0,%0", op, plen, 2);
8117 else
8118 avr_asm_len (PLUS == code ? "sbc %0,%0" : "ldi %0,0xff",
8119 op, plen, 1);
8121 break; /* US_PLUS */
8123 case US_MINUS:
8124 /* [4u] : [3u] */
8126 avr_asm_len (PLUS == code ? "brcs 0f" : "brcc 0f", op, plen, 1);
8128 if (n_bytes == 8)
8130 avr_asm_len ("%~call __clr_8", op, plen, len_call);
8131 need_copy = false;
8133 else
8134 avr_asm_len ("clr %0", op, plen, 1);
8136 break;
8139 /* We set the MSB in the unsigned case and the 2 MSBs in the signed case.
8140 Now copy the right value to the LSBs. */
8142 if (need_copy && n_bytes > 1)
8144 if (US_MINUS == code_sat || US_PLUS == code_sat)
8146 avr_asm_len ("mov %1,%0", op, plen, 1);
8148 if (n_bytes > 2)
8150 op[0] = xop[0];
8151 if (AVR_HAVE_MOVW)
8152 avr_asm_len ("movw %0,%1", op, plen, 1);
8153 else
8154 avr_asm_len ("mov %A0,%1" CR_TAB
8155 "mov %B0,%1", op, plen, 2);
8158 else if (n_bytes > 2)
8160 op[0] = xop[0];
8161 avr_asm_len ("mov %A0,%1" CR_TAB
8162 "mov %B0,%1", op, plen, 2);
8166 if (need_copy && n_bytes == 8)
8168 if (AVR_HAVE_MOVW)
8169 avr_asm_len ("movw %r0+2,%0" CR_TAB
8170 "movw %r0+4,%0", xop, plen, 2);
8171 else
8172 avr_asm_len ("mov %r0+2,%0" CR_TAB
8173 "mov %r0+3,%0" CR_TAB
8174 "mov %r0+4,%0" CR_TAB
8175 "mov %r0+5,%0", xop, plen, 4);
8178 if (out_label)
8179 avr_asm_len ("0:", op, plen, 0);
8183 /* Output addition/subtraction of register XOP[0] and a constant XOP[2] that
8184 is ont a compile-time constant:
8186 XOP[0] = XOP[0] +/- XOP[2]
8188 This is a helper for the function below. The only insns that need this
8189 are additions/subtraction for pointer modes, i.e. HImode and PSImode. */
8191 static const char*
8192 avr_out_plus_symbol (rtx *xop, enum rtx_code code, int *plen, int *pcc)
8194 machine_mode mode = GET_MODE (xop[0]);
8196 /* Only pointer modes want to add symbols. */
8198 gcc_assert (mode == HImode || mode == PSImode);
8200 *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_SET_N;
8202 avr_asm_len (PLUS == code
8203 ? "subi %A0,lo8(-(%2))" CR_TAB "sbci %B0,hi8(-(%2))"
8204 : "subi %A0,lo8(%2)" CR_TAB "sbci %B0,hi8(%2)",
8205 xop, plen, -2);
8207 if (PSImode == mode)
8208 avr_asm_len (PLUS == code
8209 ? "sbci %C0,hlo8(-(%2))"
8210 : "sbci %C0,hlo8(%2)", xop, plen, 1);
8211 return "";
8215 /* Prepare operands of addition/subtraction to be used with avr_out_plus_1.
8217 INSN is a single_set insn or an insn pattern with a binary operation as
8218 SET_SRC that is one of: PLUS, SS_PLUS, US_PLUS, MINUS, SS_MINUS, US_MINUS.
8220 XOP are the operands of INSN. In the case of 64-bit operations with
8221 constant XOP[] has just one element: The summand/subtrahend in XOP[0].
8222 The non-saturating insns up to 32 bits may or may not supply a "d" class
8223 scratch as XOP[3].
8225 If PLEN == NULL output the instructions.
8226 If PLEN != NULL set *PLEN to the length of the sequence in words.
8228 PCC is a pointer to store the instructions' effect on cc0.
8229 PCC may be NULL.
8231 PLEN and PCC default to NULL.
8233 OUT_LABEL defaults to TRUE. For a description, see AVR_OUT_PLUS_1.
8235 Return "" */
8237 const char*
8238 avr_out_plus (rtx insn, rtx *xop, int *plen, int *pcc, bool out_label)
8240 int cc_plus, cc_minus, cc_dummy;
8241 int len_plus, len_minus;
8242 rtx op[4];
8243 rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
8244 rtx xdest = SET_DEST (xpattern);
8245 machine_mode mode = GET_MODE (xdest);
8246 scalar_int_mode imode = int_mode_for_mode (mode).require ();
8247 int n_bytes = GET_MODE_SIZE (mode);
8248 enum rtx_code code_sat = GET_CODE (SET_SRC (xpattern));
8249 enum rtx_code code
8250 = (PLUS == code_sat || SS_PLUS == code_sat || US_PLUS == code_sat
8251 ? PLUS : MINUS);
8253 if (!pcc)
8254 pcc = &cc_dummy;
8256 /* PLUS and MINUS don't saturate: Use modular wrap-around. */
8258 if (PLUS == code_sat || MINUS == code_sat)
8259 code_sat = UNKNOWN;
8261 if (n_bytes <= 4 && REG_P (xop[2]))
8263 avr_out_plus_1 (xop, plen, code, pcc, code_sat, 0, out_label);
8264 return "";
8267 if (n_bytes == 8)
8269 op[0] = gen_rtx_REG (DImode, ACC_A);
8270 op[1] = gen_rtx_REG (DImode, ACC_A);
8271 op[2] = avr_to_int_mode (xop[0]);
8273 else
8275 if (!REG_P (xop[2])
8276 && !CONST_INT_P (xop[2])
8277 && !CONST_FIXED_P (xop[2]))
8279 return avr_out_plus_symbol (xop, code, plen, pcc);
8282 op[0] = avr_to_int_mode (xop[0]);
8283 op[1] = avr_to_int_mode (xop[1]);
8284 op[2] = avr_to_int_mode (xop[2]);
8287 /* Saturations and 64-bit operations don't have a clobber operand.
8288 For the other cases, the caller will provide a proper XOP[3]. */
8290 xpattern = INSN_P (insn) ? PATTERN (insn) : insn;
8291 op[3] = PARALLEL == GET_CODE (xpattern) ? xop[3] : NULL_RTX;
8293 /* Saturation will need the sign of the original operand. */
8295 rtx xmsb = simplify_gen_subreg (QImode, op[2], imode, n_bytes-1);
8296 int sign = INTVAL (xmsb) < 0 ? -1 : 1;
8298 /* If we subtract and the subtrahend is a constant, then negate it
8299 so that avr_out_plus_1 can be used. */
8301 if (MINUS == code)
8302 op[2] = simplify_unary_operation (NEG, imode, op[2], imode);
8304 /* Work out the shortest sequence. */
8306 avr_out_plus_1 (op, &len_minus, MINUS, &cc_minus, code_sat, sign, out_label);
8307 avr_out_plus_1 (op, &len_plus, PLUS, &cc_plus, code_sat, sign, out_label);
8309 if (plen)
8311 *plen = (len_minus <= len_plus) ? len_minus : len_plus;
8312 *pcc = (len_minus <= len_plus) ? cc_minus : cc_plus;
8314 else if (len_minus <= len_plus)
8315 avr_out_plus_1 (op, NULL, MINUS, pcc, code_sat, sign, out_label);
8316 else
8317 avr_out_plus_1 (op, NULL, PLUS, pcc, code_sat, sign, out_label);
8319 return "";
8323 /* Output bit operation (IOR, AND, XOR) with register XOP[0] and compile
8324 time constant XOP[2]:
8326 XOP[0] = XOP[0] <op> XOP[2]
8328 and return "". If PLEN == NULL, print assembler instructions to perform the
8329 operation; otherwise, set *PLEN to the length of the instruction sequence
8330 (in words) printed with PLEN == NULL. XOP[3] is either an 8-bit clobber
8331 register or SCRATCH if no clobber register is needed for the operation.
8332 INSN is an INSN_P or a pattern of an insn. */
8334 const char*
8335 avr_out_bitop (rtx insn, rtx *xop, int *plen)
8337 /* CODE and MODE of the operation. */
8338 rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
8339 enum rtx_code code = GET_CODE (SET_SRC (xpattern));
8340 machine_mode mode = GET_MODE (xop[0]);
8342 /* Number of bytes to operate on. */
8343 int n_bytes = GET_MODE_SIZE (mode);
8345 /* Value of T-flag (0 or 1) or -1 if unknow. */
8346 int set_t = -1;
8348 /* Value (0..0xff) held in clobber register op[3] or -1 if unknown. */
8349 int clobber_val = -1;
8351 /* op[0]: 8-bit destination register
8352 op[1]: 8-bit const int
8353 op[2]: 8-bit clobber register, SCRATCH or NULL_RTX.
8354 op[3]: 8-bit register containing 0xff or NULL_RTX */
8355 rtx op[4];
8357 op[2] = QImode == mode ? NULL_RTX : xop[3];
8358 op[3] = NULL_RTX;
8360 if (plen)
8361 *plen = 0;
8363 for (int i = 0; i < n_bytes; i++)
8365 /* We operate byte-wise on the destination. */
8366 rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
8367 rtx xval8 = simplify_gen_subreg (QImode, xop[2], mode, i);
8369 /* 8-bit value to operate with this byte. */
8370 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
8372 /* Number of bits set in the current byte of the constant. */
8373 int pop8 = popcount_hwi (val8);
8375 /* Registers R16..R31 can operate with immediate. */
8376 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
8378 op[0] = reg8;
8379 op[1] = GEN_INT (val8);
8381 switch (code)
8383 case IOR:
8385 if (pop8 == 0)
8386 continue;
8387 else if (ld_reg_p)
8388 avr_asm_len ("ori %0,%1", op, plen, 1);
8389 else if (pop8 == 1)
8391 if (set_t != 1)
8392 avr_asm_len ("set", op, plen, 1);
8393 set_t = 1;
8395 op[1] = GEN_INT (exact_log2 (val8));
8396 avr_asm_len ("bld %0,%1", op, plen, 1);
8398 else if (pop8 == 8)
8400 if (op[3] != NULL_RTX)
8401 avr_asm_len ("mov %0,%3", op, plen, 1);
8402 else
8403 avr_asm_len ("clr %0" CR_TAB
8404 "dec %0", op, plen, 2);
8406 op[3] = op[0];
8408 else
8410 if (clobber_val != (int) val8)
8411 avr_asm_len ("ldi %2,%1", op, plen, 1);
8412 clobber_val = (int) val8;
8414 avr_asm_len ("or %0,%2", op, plen, 1);
8417 continue; /* IOR */
8419 case AND:
8421 if (pop8 == 8)
8422 continue;
8423 else if (pop8 == 0)
8424 avr_asm_len ("clr %0", op, plen, 1);
8425 else if (ld_reg_p)
8426 avr_asm_len ("andi %0,%1", op, plen, 1);
8427 else if (pop8 == 7)
8429 if (set_t != 0)
8430 avr_asm_len ("clt", op, plen, 1);
8431 set_t = 0;
8433 op[1] = GEN_INT (exact_log2 (GET_MODE_MASK (QImode) & ~val8));
8434 avr_asm_len ("bld %0,%1", op, plen, 1);
8436 else
8438 if (clobber_val != (int) val8)
8439 avr_asm_len ("ldi %2,%1", op, plen, 1);
8440 clobber_val = (int) val8;
8442 avr_asm_len ("and %0,%2", op, plen, 1);
8445 continue; /* AND */
8447 case XOR:
8449 if (pop8 == 0)
8450 continue;
8451 else if (pop8 == 8)
8452 avr_asm_len ("com %0", op, plen, 1);
8453 else if (ld_reg_p && val8 == (1 << 7))
8454 avr_asm_len ("subi %0,%1", op, plen, 1);
8455 else
8457 if (clobber_val != (int) val8)
8458 avr_asm_len ("ldi %2,%1", op, plen, 1);
8459 clobber_val = (int) val8;
8461 avr_asm_len ("eor %0,%2", op, plen, 1);
8464 continue; /* XOR */
8466 default:
8467 /* Unknown rtx_code */
8468 gcc_unreachable();
8470 } /* for all sub-bytes */
8472 return "";
8476 /* Output sign extension from XOP[1] to XOP[0] and return "".
8477 If PLEN == NULL, print assembler instructions to perform the operation;
8478 otherwise, set *PLEN to the length of the instruction sequence (in words)
8479 as printed with PLEN == NULL. */
8481 const char*
8482 avr_out_sign_extend (rtx_insn *insn, rtx *xop, int *plen)
8484 // Size in bytes of source resp. destination operand.
8485 unsigned n_src = GET_MODE_SIZE (GET_MODE (xop[1]));
8486 unsigned n_dest = GET_MODE_SIZE (GET_MODE (xop[0]));
8487 rtx r_msb = all_regs_rtx[REGNO (xop[1]) + n_src - 1];
8489 if (plen)
8490 *plen = 0;
8492 // Copy destination to source
8494 if (REGNO (xop[0]) != REGNO (xop[1]))
8496 gcc_assert (n_src <= 2);
8498 if (n_src == 2)
8499 avr_asm_len (AVR_HAVE_MOVW
8500 ? "movw %0,%1"
8501 : "mov %B0,%B1", xop, plen, 1);
8502 if (n_src == 1 || !AVR_HAVE_MOVW)
8503 avr_asm_len ("mov %A0,%A1", xop, plen, 1);
8506 // Set Carry to the sign bit MSB.7...
8508 if (REGNO (xop[0]) == REGNO (xop[1])
8509 || !reg_unused_after (insn, r_msb))
8511 avr_asm_len ("mov __tmp_reg__,%0", &r_msb, plen, 1);
8512 r_msb = tmp_reg_rtx;
8515 avr_asm_len ("lsl %0", &r_msb, plen, 1);
8517 // ...and propagate it to all the new sign bits
8519 for (unsigned n = n_src; n < n_dest; n++)
8520 avr_asm_len ("sbc %0,%0", &all_regs_rtx[REGNO (xop[0]) + n], plen, 1);
8522 return "";
8526 /* PLEN == NULL: Output code to add CONST_INT OP[0] to SP.
8527 PLEN != NULL: Set *PLEN to the length of that sequence.
8528 Return "". */
8530 const char*
8531 avr_out_addto_sp (rtx *op, int *plen)
8533 int pc_len = AVR_2_BYTE_PC ? 2 : 3;
8534 int addend = INTVAL (op[0]);
8536 if (plen)
8537 *plen = 0;
8539 if (addend < 0)
8541 if (flag_verbose_asm || flag_print_asm_name)
8542 avr_asm_len (ASM_COMMENT_START "SP -= %n0", op, plen, 0);
8544 while (addend <= -pc_len)
8546 addend += pc_len;
8547 avr_asm_len ("rcall .", op, plen, 1);
8550 while (addend++ < 0)
8551 avr_asm_len ("push __tmp_reg__", op, plen, 1);
8553 else if (addend > 0)
8555 if (flag_verbose_asm || flag_print_asm_name)
8556 avr_asm_len (ASM_COMMENT_START "SP += %0", op, plen, 0);
8558 while (addend-- > 0)
8559 avr_asm_len ("pop __tmp_reg__", op, plen, 1);
8562 return "";
8566 /* Output instructions to insert an inverted bit into OPERANDS[0]:
8567 $0.$1 = ~$2.$3 if XBITNO = NULL
8568 $0.$1 = ~$2.XBITNO if XBITNO != NULL.
8569 If PLEN = NULL then output the respective instruction sequence which
8570 is a combination of BST / BLD and some instruction(s) to invert the bit.
8571 If PLEN != NULL then store the length of the sequence (in words) in *PLEN.
8572 Return "". */
8574 const char*
8575 avr_out_insert_notbit (rtx_insn *insn, rtx operands[], rtx xbitno, int *plen)
8577 rtx op[4] = { operands[0], operands[1], operands[2],
8578 xbitno == NULL_RTX ? operands [3] : xbitno };
8580 if (INTVAL (op[1]) == 7
8581 && test_hard_reg_class (LD_REGS, op[0]))
8583 /* If the inserted bit number is 7 and we have a d-reg, then invert
8584 the bit after the insertion by means of SUBI *,0x80. */
8586 if (INTVAL (op[3]) == 7
8587 && REGNO (op[0]) == REGNO (op[2]))
8589 avr_asm_len ("subi %0,0x80", op, plen, -1);
8591 else
8593 avr_asm_len ("bst %2,%3" CR_TAB
8594 "bld %0,%1" CR_TAB
8595 "subi %0,0x80", op, plen, -3);
8598 else if (test_hard_reg_class (LD_REGS, op[0])
8599 && (INTVAL (op[1]) != INTVAL (op[3])
8600 || !reg_overlap_mentioned_p (op[0], op[2])))
8602 /* If the destination bit is in a d-reg we can jump depending
8603 on the source bit and use ANDI / ORI. This just applies if we
8604 have not an early-clobber situation with the bit. */
8606 avr_asm_len ("andi %0,~(1<<%1)" CR_TAB
8607 "sbrs %2,%3" CR_TAB
8608 "ori %0,1<<%1", op, plen, -3);
8610 else
8612 /* Otherwise, invert the bit by means of COM before we store it with
8613 BST and then undo the COM if needed. */
8615 avr_asm_len ("com %2" CR_TAB
8616 "bst %2,%3", op, plen, -2);
8618 if (!reg_unused_after (insn, op[2])
8619 // A simple 'reg_unused_after' is not enough because that function
8620 // assumes that the destination register is overwritten completely
8621 // and hence is in order for our purpose. This is not the case
8622 // with BLD which just changes one bit of the destination.
8623 || reg_overlap_mentioned_p (op[0], op[2]))
8625 /* Undo the COM from above. */
8626 avr_asm_len ("com %2", op, plen, 1);
8629 avr_asm_len ("bld %0,%1", op, plen, 1);
8632 return "";
8636 /* Outputs instructions needed for fixed point type conversion.
8637 This includes converting between any fixed point type, as well
8638 as converting to any integer type. Conversion between integer
8639 types is not supported.
8641 Converting signed fractional types requires a bit shift if converting
8642 to or from any unsigned fractional type because the decimal place is
8643 shifted by 1 bit. When the destination is a signed fractional, the sign
8644 is stored in either the carry or T bit. */
8646 const char*
8647 avr_out_fract (rtx_insn *insn, rtx operands[], bool intsigned, int *plen)
8649 rtx xop[6];
8650 RTX_CODE shift = UNKNOWN;
8651 bool sign_in_carry = false;
8652 bool msb_in_carry = false;
8653 bool lsb_in_tmp_reg = false;
8654 bool lsb_in_carry = false;
8655 bool frac_rounded = false;
8656 const char *code_ashift = "lsl %0";
8659 #define MAY_CLOBBER(RR) \
8660 /* Shorthand used below. */ \
8661 ((sign_bytes \
8662 && IN_RANGE (RR, dest.regno_msb - sign_bytes + 1, dest.regno_msb)) \
8663 || (offset && IN_RANGE (RR, dest.regno, dest.regno_msb)) \
8664 || (reg_unused_after (insn, all_regs_rtx[RR]) \
8665 && !IN_RANGE (RR, dest.regno, dest.regno_msb)))
8667 struct
8669 /* bytes : Length of operand in bytes.
8670 ibyte : Length of integral part in bytes.
8671 fbyte, fbit : Length of fractional part in bytes, bits. */
8673 bool sbit;
8674 unsigned fbit, bytes, ibyte, fbyte;
8675 unsigned regno, regno_msb;
8676 } dest, src, *val[2] = { &dest, &src };
8678 if (plen)
8679 *plen = 0;
8681 /* Step 0: Determine information on source and destination operand we
8682 ====== will need in the remainder. */
8684 for (size_t i = 0; i < ARRAY_SIZE (val); i++)
8686 machine_mode mode;
8688 xop[i] = operands[i];
8690 mode = GET_MODE (xop[i]);
8692 val[i]->bytes = GET_MODE_SIZE (mode);
8693 val[i]->regno = REGNO (xop[i]);
8694 val[i]->regno_msb = REGNO (xop[i]) + val[i]->bytes - 1;
8696 if (SCALAR_INT_MODE_P (mode))
8698 val[i]->sbit = intsigned;
8699 val[i]->fbit = 0;
8701 else if (ALL_SCALAR_FIXED_POINT_MODE_P (mode))
8703 val[i]->sbit = SIGNED_SCALAR_FIXED_POINT_MODE_P (mode);
8704 val[i]->fbit = GET_MODE_FBIT (mode);
8706 else
8707 fatal_insn ("unsupported fixed-point conversion", insn);
8709 val[i]->fbyte = (1 + val[i]->fbit) / BITS_PER_UNIT;
8710 val[i]->ibyte = val[i]->bytes - val[i]->fbyte;
8713 // Byte offset of the decimal point taking into account different place
8714 // of the decimal point in input and output and different register numbers
8715 // of input and output.
8716 int offset = dest.regno - src.regno + dest.fbyte - src.fbyte;
8718 // Number of destination bytes that will come from sign / zero extension.
8719 int sign_bytes = (dest.ibyte - src.ibyte) * (dest.ibyte > src.ibyte);
8721 // Number of bytes at the low end to be filled with zeros.
8722 int zero_bytes = (dest.fbyte - src.fbyte) * (dest.fbyte > src.fbyte);
8724 // Do we have a 16-Bit register that is cleared?
8725 rtx clrw = NULL_RTX;
8727 bool sign_extend = src.sbit && sign_bytes;
8729 if (dest.fbit % 8 == 0 && src.fbit % 8 == 7)
8730 shift = ASHIFT;
8731 else if (dest.fbit % 8 == 7 && src.fbit % 8 == 0)
8732 shift = ASHIFTRT;
8733 else if (dest.fbit % 8 == src.fbit % 8)
8734 shift = UNKNOWN;
8735 else
8736 gcc_unreachable();
8738 /* If we need to round the fraction part, we might need to save/round it
8739 before clobbering any of it in Step 1. Also, we might want to do
8740 the rounding now to make use of LD_REGS. */
8741 if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8742 && SCALAR_ACCUM_MODE_P (GET_MODE (xop[1]))
8743 && !TARGET_FRACT_CONV_TRUNC)
8745 bool overlap
8746 = (src.regno <=
8747 (offset ? dest.regno_msb - sign_bytes : dest.regno + zero_bytes - 1)
8748 && dest.regno - offset -1 >= dest.regno);
8749 unsigned s0 = dest.regno - offset -1;
8750 bool use_src = true;
8751 unsigned sn;
8752 unsigned copied_msb = src.regno_msb;
8753 bool have_carry = false;
8755 if (src.ibyte > dest.ibyte)
8756 copied_msb -= src.ibyte - dest.ibyte;
8758 for (sn = s0; sn <= copied_msb; sn++)
8759 if (!IN_RANGE (sn, dest.regno, dest.regno_msb)
8760 && !reg_unused_after (insn, all_regs_rtx[sn]))
8761 use_src = false;
8762 if (use_src && TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], s0))
8764 avr_asm_len ("tst %0" CR_TAB "brpl 0f",
8765 &all_regs_rtx[src.regno_msb], plen, 2);
8766 sn = src.regno;
8767 if (sn < s0)
8769 if (TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], sn))
8770 avr_asm_len ("cpi %0,1", &all_regs_rtx[sn], plen, 1);
8771 else
8772 avr_asm_len ("sec" CR_TAB
8773 "cpc %0,__zero_reg__",
8774 &all_regs_rtx[sn], plen, 2);
8775 have_carry = true;
8777 while (++sn < s0)
8778 avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8780 avr_asm_len (have_carry ? "sbci %0,128" : "subi %0,129",
8781 &all_regs_rtx[s0], plen, 1);
8782 for (sn = src.regno + src.fbyte; sn <= copied_msb; sn++)
8783 avr_asm_len ("sbci %0,255", &all_regs_rtx[sn], plen, 1);
8784 avr_asm_len ("\n0:", NULL, plen, 0);
8785 frac_rounded = true;
8787 else if (use_src && overlap)
8789 avr_asm_len ("clr __tmp_reg__" CR_TAB
8790 "sbrc %1,0" CR_TAB
8791 "dec __tmp_reg__", xop, plen, 1);
8792 sn = src.regno;
8793 if (sn < s0)
8795 avr_asm_len ("add %0,__tmp_reg__", &all_regs_rtx[sn], plen, 1);
8796 have_carry = true;
8799 while (++sn < s0)
8800 avr_asm_len ("adc %0,__tmp_reg__", &all_regs_rtx[sn], plen, 1);
8802 if (have_carry)
8803 avr_asm_len ("clt" CR_TAB
8804 "bld __tmp_reg__,7" CR_TAB
8805 "adc %0,__tmp_reg__",
8806 &all_regs_rtx[s0], plen, 1);
8807 else
8808 avr_asm_len ("lsr __tmp_reg" CR_TAB
8809 "add %0,__tmp_reg__",
8810 &all_regs_rtx[s0], plen, 2);
8811 for (sn = src.regno + src.fbyte; sn <= copied_msb; sn++)
8812 avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8813 frac_rounded = true;
8815 else if (overlap)
8817 bool use_src
8818 = (TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], s0)
8819 && (IN_RANGE (s0, dest.regno, dest.regno_msb)
8820 || reg_unused_after (insn, all_regs_rtx[s0])));
8821 xop[2] = all_regs_rtx[s0];
8822 unsigned sn = src.regno;
8823 if (!use_src || sn == s0)
8824 avr_asm_len ("mov __tmp_reg__,%2", xop, plen, 1);
8825 /* We need to consider to-be-discarded bits
8826 if the value is negative. */
8827 if (sn < s0)
8829 avr_asm_len ("tst %0" CR_TAB
8830 "brpl 0f",
8831 &all_regs_rtx[src.regno_msb], plen, 2);
8832 /* Test to-be-discarded bytes for any nozero bits.
8833 ??? Could use OR or SBIW to test two registers at once. */
8834 if (sn < s0)
8835 avr_asm_len ("cp %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8837 while (++sn < s0)
8838 avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8839 /* Set bit 0 in __tmp_reg__ if any of the lower bits was set. */
8840 if (use_src)
8841 avr_asm_len ("breq 0f" CR_TAB
8842 "ori %2,1"
8843 "\n0:\t" "mov __tmp_reg__,%2",
8844 xop, plen, 3);
8845 else
8846 avr_asm_len ("breq 0f" CR_TAB
8847 "set" CR_TAB
8848 "bld __tmp_reg__,0\n0:",
8849 xop, plen, 3);
8851 lsb_in_tmp_reg = true;
8855 /* Step 1: Clear bytes at the low end and copy payload bits from source
8856 ====== to destination. */
8858 int step = offset < 0 ? 1 : -1;
8859 unsigned d0 = offset < 0 ? dest.regno : dest.regno_msb;
8861 // We cleared at least that number of registers.
8862 int clr_n = 0;
8864 for (; d0 >= dest.regno && d0 <= dest.regno_msb; d0 += step)
8866 // Next regno of destination is needed for MOVW
8867 unsigned d1 = d0 + step;
8869 // Current and next regno of source
8870 signed s0 = d0 - offset;
8871 signed s1 = s0 + step;
8873 // Must current resp. next regno be CLRed? This applies to the low
8874 // bytes of the destination that have no associated source bytes.
8875 bool clr0 = s0 < (signed) src.regno;
8876 bool clr1 = s1 < (signed) src.regno && d1 >= dest.regno;
8878 // First gather what code to emit (if any) and additional step to
8879 // apply if a MOVW is in use. xop[2] is destination rtx and xop[3]
8880 // is the source rtx for the current loop iteration.
8881 const char *code = NULL;
8882 int stepw = 0;
8884 if (clr0)
8886 if (AVR_HAVE_MOVW && clr1 && clrw)
8888 xop[2] = all_regs_rtx[d0 & ~1];
8889 xop[3] = clrw;
8890 code = "movw %2,%3";
8891 stepw = step;
8893 else
8895 xop[2] = all_regs_rtx[d0];
8896 code = "clr %2";
8898 if (++clr_n >= 2
8899 && !clrw
8900 && d0 % 2 == (step > 0))
8902 clrw = all_regs_rtx[d0 & ~1];
8906 else if (offset && s0 <= (signed) src.regno_msb)
8908 int movw = AVR_HAVE_MOVW && offset % 2 == 0
8909 && d0 % 2 == (offset > 0)
8910 && d1 <= dest.regno_msb && d1 >= dest.regno
8911 && s1 <= (signed) src.regno_msb && s1 >= (signed) src.regno;
8913 xop[2] = all_regs_rtx[d0 & ~movw];
8914 xop[3] = all_regs_rtx[s0 & ~movw];
8915 code = movw ? "movw %2,%3" : "mov %2,%3";
8916 stepw = step * movw;
8919 if (code)
8921 if (sign_extend && shift != ASHIFT && !sign_in_carry
8922 && (d0 == src.regno_msb || d0 + stepw == src.regno_msb))
8924 /* We are going to override the sign bit. If we sign-extend,
8925 store the sign in the Carry flag. This is not needed if
8926 the destination will be ASHIFT in the remainder because
8927 the ASHIFT will set Carry without extra instruction. */
8929 avr_asm_len ("lsl %0", &all_regs_rtx[src.regno_msb], plen, 1);
8930 sign_in_carry = true;
8933 unsigned src_msb = dest.regno_msb - sign_bytes - offset + 1;
8935 if (!sign_extend && shift == ASHIFTRT && !msb_in_carry
8936 && src.ibyte > dest.ibyte
8937 && (d0 == src_msb || d0 + stepw == src_msb))
8939 /* We are going to override the MSB. If we shift right,
8940 store the MSB in the Carry flag. This is only needed if
8941 we don't sign-extend becaue with sign-extension the MSB
8942 (the sign) will be produced by the sign extension. */
8944 avr_asm_len ("lsr %0", &all_regs_rtx[src_msb], plen, 1);
8945 msb_in_carry = true;
8948 unsigned src_lsb = dest.regno - offset -1;
8950 if (shift == ASHIFT && src.fbyte > dest.fbyte && !lsb_in_carry
8951 && !lsb_in_tmp_reg
8952 && (d0 == src_lsb || d0 + stepw == src_lsb))
8954 /* We are going to override the new LSB; store it into carry. */
8956 avr_asm_len ("lsl %0", &all_regs_rtx[src_lsb], plen, 1);
8957 code_ashift = "rol %0";
8958 lsb_in_carry = true;
8961 avr_asm_len (code, xop, plen, 1);
8962 d0 += stepw;
8966 /* Step 2: Shift destination left by 1 bit position. This might be needed
8967 ====== for signed input and unsigned output. */
8969 if (shift == ASHIFT && src.fbyte > dest.fbyte && !lsb_in_carry)
8971 unsigned s0 = dest.regno - offset -1;
8973 /* n1169 4.1.4 says:
8974 "Conversions from a fixed-point to an integer type round toward zero."
8975 Hence, converting a fract type to integer only gives a non-zero result
8976 for -1. */
8977 if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8978 && SCALAR_FRACT_MODE_P (GET_MODE (xop[1]))
8979 && !TARGET_FRACT_CONV_TRUNC)
8981 gcc_assert (s0 == src.regno_msb);
8982 /* Check if the input is -1. We do that by checking if negating
8983 the input causes an integer overflow. */
8984 unsigned sn = src.regno;
8985 avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx[sn++], plen, 1);
8986 while (sn <= s0)
8987 avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx[sn++], plen, 1);
8989 /* Overflow goes with set carry. Clear carry otherwise. */
8990 avr_asm_len ("brvs 0f" CR_TAB
8991 "clc\n0:", NULL, plen, 2);
8993 /* Likewise, when converting from accumulator types to integer, we
8994 need to round up negative values. */
8995 else if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8996 && SCALAR_ACCUM_MODE_P (GET_MODE (xop[1]))
8997 && !TARGET_FRACT_CONV_TRUNC
8998 && !frac_rounded)
9000 bool have_carry = false;
9002 xop[2] = all_regs_rtx[s0];
9003 if (!lsb_in_tmp_reg && !MAY_CLOBBER (s0))
9004 avr_asm_len ("mov __tmp_reg__,%2", xop, plen, 1);
9005 avr_asm_len ("tst %0" CR_TAB "brpl 0f",
9006 &all_regs_rtx[src.regno_msb], plen, 2);
9007 if (!lsb_in_tmp_reg)
9009 unsigned sn = src.regno;
9010 if (sn < s0)
9012 avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx[sn],
9013 plen, 1);
9014 have_carry = true;
9016 while (++sn < s0)
9017 avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx[sn], plen, 1);
9018 lsb_in_tmp_reg = !MAY_CLOBBER (s0);
9020 /* Add in C and the rounding value 127. */
9021 /* If the destination msb is a sign byte, and in LD_REGS,
9022 grab it as a temporary. */
9023 if (sign_bytes
9024 && TEST_HARD_REG_BIT (reg_class_contents[LD_REGS],
9025 dest.regno_msb))
9027 xop[3] = all_regs_rtx[dest.regno_msb];
9028 avr_asm_len ("ldi %3,127", xop, plen, 1);
9029 avr_asm_len ((have_carry && lsb_in_tmp_reg ? "adc __tmp_reg__,%3"
9030 : have_carry ? "adc %2,%3"
9031 : lsb_in_tmp_reg ? "add __tmp_reg__,%3"
9032 : "add %2,%3"),
9033 xop, plen, 1);
9035 else
9037 /* Fall back to use __zero_reg__ as a temporary. */
9038 avr_asm_len ("dec __zero_reg__", NULL, plen, 1);
9039 if (have_carry)
9040 avr_asm_len ("clt" CR_TAB
9041 "bld __zero_reg__,7", NULL, plen, 2);
9042 else
9043 avr_asm_len ("lsr __zero_reg__", NULL, plen, 1);
9044 avr_asm_len (have_carry && lsb_in_tmp_reg
9045 ? "adc __tmp_reg__,__zero_reg__"
9046 : have_carry ? "adc %2,__zero_reg__"
9047 : lsb_in_tmp_reg ? "add __tmp_reg__,__zero_reg__"
9048 : "add %2,__zero_reg__",
9049 xop, plen, 1);
9050 avr_asm_len ("eor __zero_reg__,__zero_reg__", NULL, plen, 1);
9053 for (d0 = dest.regno + zero_bytes;
9054 d0 <= dest.regno_msb - sign_bytes; d0++)
9055 avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx[d0], plen, 1);
9057 avr_asm_len (lsb_in_tmp_reg
9058 ? "\n0:\t" "lsl __tmp_reg__"
9059 : "\n0:\t" "lsl %2",
9060 xop, plen, 1);
9062 else if (MAY_CLOBBER (s0))
9063 avr_asm_len ("lsl %0", &all_regs_rtx[s0], plen, 1);
9064 else
9065 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
9066 "lsl __tmp_reg__", &all_regs_rtx[s0], plen, 2);
9068 code_ashift = "rol %0";
9069 lsb_in_carry = true;
9072 if (shift == ASHIFT)
9074 for (d0 = dest.regno + zero_bytes;
9075 d0 <= dest.regno_msb - sign_bytes; d0++)
9077 avr_asm_len (code_ashift, &all_regs_rtx[d0], plen, 1);
9078 code_ashift = "rol %0";
9081 lsb_in_carry = false;
9082 sign_in_carry = true;
9085 /* Step 4a: Store MSB in carry if we don't already have it or will produce
9086 ======= it in sign-extension below. */
9088 if (!sign_extend && shift == ASHIFTRT && !msb_in_carry
9089 && src.ibyte > dest.ibyte)
9091 unsigned s0 = dest.regno_msb - sign_bytes - offset + 1;
9093 if (MAY_CLOBBER (s0))
9094 avr_asm_len ("lsr %0", &all_regs_rtx[s0], plen, 1);
9095 else
9096 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
9097 "lsr __tmp_reg__", &all_regs_rtx[s0], plen, 2);
9099 msb_in_carry = true;
9102 /* Step 3: Sign-extend or zero-extend the destination as needed.
9103 ====== */
9105 if (sign_extend && !sign_in_carry)
9107 unsigned s0 = src.regno_msb;
9109 if (MAY_CLOBBER (s0))
9110 avr_asm_len ("lsl %0", &all_regs_rtx[s0], plen, 1);
9111 else
9112 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
9113 "lsl __tmp_reg__", &all_regs_rtx[s0], plen, 2);
9115 sign_in_carry = true;
9118 gcc_assert (sign_in_carry + msb_in_carry + lsb_in_carry <= 1);
9120 unsigned copies = 0;
9121 rtx movw = sign_extend ? NULL_RTX : clrw;
9123 for (d0 = dest.regno_msb - sign_bytes + 1; d0 <= dest.regno_msb; d0++)
9125 if (AVR_HAVE_MOVW && movw
9126 && d0 % 2 == 0 && d0 + 1 <= dest.regno_msb)
9128 xop[2] = all_regs_rtx[d0];
9129 xop[3] = movw;
9130 avr_asm_len ("movw %2,%3", xop, plen, 1);
9131 d0++;
9133 else
9135 avr_asm_len (sign_extend ? "sbc %0,%0" : "clr %0",
9136 &all_regs_rtx[d0], plen, 1);
9138 if (++copies >= 2 && !movw && d0 % 2 == 1)
9139 movw = all_regs_rtx[d0-1];
9141 } /* for */
9144 /* Step 4: Right shift the destination. This might be needed for
9145 ====== conversions from unsigned to signed. */
9147 if (shift == ASHIFTRT)
9149 const char *code_ashiftrt = "lsr %0";
9151 if (sign_extend || msb_in_carry)
9152 code_ashiftrt = "ror %0";
9154 if (src.sbit && src.ibyte == dest.ibyte)
9155 code_ashiftrt = "asr %0";
9157 for (d0 = dest.regno_msb - sign_bytes;
9158 d0 >= dest.regno + zero_bytes - 1 && d0 >= dest.regno; d0--)
9160 avr_asm_len (code_ashiftrt, &all_regs_rtx[d0], plen, 1);
9161 code_ashiftrt = "ror %0";
9165 #undef MAY_CLOBBER
9167 return "";
9171 /* Output fixed-point rounding. XOP[0] = XOP[1] is the operand to round.
9172 XOP[2] is the rounding point, a CONST_INT. The function prints the
9173 instruction sequence if PLEN = NULL and computes the length in words
9174 of the sequence if PLEN != NULL. Most of this function deals with
9175 preparing operands for calls to `avr_out_plus' and `avr_out_bitop'. */
9177 const char*
9178 avr_out_round (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *xop, int *plen)
9180 scalar_mode mode = as_a <scalar_mode> (GET_MODE (xop[0]));
9181 scalar_int_mode imode = int_mode_for_mode (mode).require ();
9182 // The smallest fractional bit not cleared by the rounding is 2^(-RP).
9183 int fbit = (int) GET_MODE_FBIT (mode);
9184 double_int i_add = double_int_zero.set_bit (fbit-1 - INTVAL (xop[2]));
9185 wide_int wi_add = wi::set_bit_in_zero (fbit-1 - INTVAL (xop[2]),
9186 GET_MODE_PRECISION (imode));
9187 // Lengths of PLUS and AND parts.
9188 int len_add = 0, *plen_add = plen ? &len_add : NULL;
9189 int len_and = 0, *plen_and = plen ? &len_and : NULL;
9191 // Add-Saturate 1/2 * 2^(-RP). Don't print the label "0:" when printing
9192 // the saturated addition so that we can emit the "rjmp 1f" before the
9193 // "0:" below.
9195 rtx xadd = const_fixed_from_double_int (i_add, mode);
9196 rtx xpattern, xsrc, op[4];
9198 xsrc = SIGNED_FIXED_POINT_MODE_P (mode)
9199 ? gen_rtx_SS_PLUS (mode, xop[1], xadd)
9200 : gen_rtx_US_PLUS (mode, xop[1], xadd);
9201 xpattern = gen_rtx_SET (xop[0], xsrc);
9203 op[0] = xop[0];
9204 op[1] = xop[1];
9205 op[2] = xadd;
9206 avr_out_plus (xpattern, op, plen_add, NULL, false /* Don't print "0:" */);
9208 avr_asm_len ("rjmp 1f" CR_TAB
9209 "0:", NULL, plen_add, 1);
9211 // Keep all bits from RP and higher: ... 2^(-RP)
9212 // Clear all bits from RP+1 and lower: 2^(-RP-1) ...
9213 // Rounding point ^^^^^^^
9214 // Added above ^^^^^^^^^
9215 rtx xreg = simplify_gen_subreg (imode, xop[0], mode, 0);
9216 rtx xmask = immed_wide_int_const (-wi_add - wi_add, imode);
9218 xpattern = gen_rtx_SET (xreg, gen_rtx_AND (imode, xreg, xmask));
9220 op[0] = xreg;
9221 op[1] = xreg;
9222 op[2] = xmask;
9223 op[3] = gen_rtx_SCRATCH (QImode);
9224 avr_out_bitop (xpattern, op, plen_and);
9225 avr_asm_len ("1:", NULL, plen, 0);
9227 if (plen)
9228 *plen = len_add + len_and;
9230 return "";
9234 /* Create RTL split patterns for byte sized rotate expressions. This
9235 produces a series of move instructions and considers overlap situations.
9236 Overlapping non-HImode operands need a scratch register. */
9238 bool
9239 avr_rotate_bytes (rtx operands[])
9241 machine_mode mode = GET_MODE (operands[0]);
9242 bool overlapped = reg_overlap_mentioned_p (operands[0], operands[1]);
9243 bool same_reg = rtx_equal_p (operands[0], operands[1]);
9244 int num = INTVAL (operands[2]);
9245 rtx scratch = operands[3];
9246 /* Work out if byte or word move is needed. Odd byte rotates need QImode.
9247 Word move if no scratch is needed, otherwise use size of scratch. */
9248 machine_mode move_mode = QImode;
9249 int move_size, offset, size;
9251 if (num & 0xf)
9252 move_mode = QImode;
9253 else if ((mode == SImode && !same_reg) || !overlapped)
9254 move_mode = HImode;
9255 else
9256 move_mode = GET_MODE (scratch);
9258 /* Force DI rotate to use QI moves since other DI moves are currently split
9259 into QI moves so forward propagation works better. */
9260 if (mode == DImode)
9261 move_mode = QImode;
9262 /* Make scratch smaller if needed. */
9263 if (SCRATCH != GET_CODE (scratch)
9264 && HImode == GET_MODE (scratch)
9265 && QImode == move_mode)
9266 scratch = simplify_gen_subreg (move_mode, scratch, HImode, 0);
9268 move_size = GET_MODE_SIZE (move_mode);
9269 /* Number of bytes/words to rotate. */
9270 offset = (num >> 3) / move_size;
9271 /* Number of moves needed. */
9272 size = GET_MODE_SIZE (mode) / move_size;
9273 /* Himode byte swap is special case to avoid a scratch register. */
9274 if (mode == HImode && same_reg)
9276 /* HImode byte swap, using xor. This is as quick as using scratch. */
9277 rtx src, dst;
9278 src = simplify_gen_subreg (move_mode, operands[1], mode, 0);
9279 dst = simplify_gen_subreg (move_mode, operands[0], mode, 1);
9280 if (!rtx_equal_p (dst, src))
9282 emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
9283 emit_move_insn (src, gen_rtx_XOR (QImode, src, dst));
9284 emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
9287 else
9289 #define MAX_SIZE 8 /* GET_MODE_SIZE (DImode) / GET_MODE_SIZE (QImode) */
9290 /* Create linked list of moves to determine move order. */
9291 struct {
9292 rtx src, dst;
9293 int links;
9294 } move[MAX_SIZE + 8];
9295 int blocked, moves;
9297 gcc_assert (size <= MAX_SIZE);
9298 /* Generate list of subreg moves. */
9299 for (int i = 0; i < size; i++)
9301 int from = i;
9302 int to = (from + offset) % size;
9303 move[i].src = simplify_gen_subreg (move_mode, operands[1],
9304 mode, from * move_size);
9305 move[i].dst = simplify_gen_subreg (move_mode, operands[0],
9306 mode, to * move_size);
9307 move[i].links = -1;
9309 /* Mark dependence where a dst of one move is the src of another move.
9310 The first move is a conflict as it must wait until second is
9311 performed. We ignore moves to self - we catch this later. */
9312 if (overlapped)
9313 for (int i = 0; i < size; i++)
9314 if (reg_overlap_mentioned_p (move[i].dst, operands[1]))
9315 for (int j = 0; j < size; j++)
9316 if (j != i && rtx_equal_p (move[j].src, move[i].dst))
9318 /* The dst of move i is the src of move j. */
9319 move[i].links = j;
9320 break;
9323 blocked = -1;
9324 moves = 0;
9325 /* Go through move list and perform non-conflicting moves. As each
9326 non-overlapping move is made, it may remove other conflicts
9327 so the process is repeated until no conflicts remain. */
9330 blocked = -1;
9331 moves = 0;
9332 /* Emit move where dst is not also a src or we have used that
9333 src already. */
9334 for (int i = 0; i < size; i++)
9335 if (move[i].src != NULL_RTX)
9337 if (move[i].links == -1
9338 || move[move[i].links].src == NULL_RTX)
9340 moves++;
9341 /* Ignore NOP moves to self. */
9342 if (!rtx_equal_p (move[i].dst, move[i].src))
9343 emit_move_insn (move[i].dst, move[i].src);
9345 /* Remove conflict from list. */
9346 move[i].src = NULL_RTX;
9348 else
9349 blocked = i;
9352 /* Check for deadlock. This is when no moves occurred and we have
9353 at least one blocked move. */
9354 if (moves == 0 && blocked != -1)
9356 /* Need to use scratch register to break deadlock.
9357 Add move to put dst of blocked move into scratch.
9358 When this move occurs, it will break chain deadlock.
9359 The scratch register is substituted for real move. */
9361 gcc_assert (SCRATCH != GET_CODE (scratch));
9363 move[size].src = move[blocked].dst;
9364 move[size].dst = scratch;
9365 /* Scratch move is never blocked. */
9366 move[size].links = -1;
9367 /* Make sure we have valid link. */
9368 gcc_assert (move[blocked].links != -1);
9369 /* Replace src of blocking move with scratch reg. */
9370 move[move[blocked].links].src = scratch;
9371 /* Make dependent on scratch move occurring. */
9372 move[blocked].links = size;
9373 size=size+1;
9376 while (blocked != -1);
9378 return true;
9382 /* Worker function for `ADJUST_INSN_LENGTH'. */
9383 /* Modifies the length assigned to instruction INSN
9384 LEN is the initially computed length of the insn. */
9387 avr_adjust_insn_length (rtx_insn *insn, int len)
9389 rtx *op = recog_data.operand;
9390 enum attr_adjust_len adjust_len;
9392 /* As we pretend jump tables in .text, fix branch offsets crossing jump
9393 tables now. */
9395 if (JUMP_TABLE_DATA_P (insn))
9396 return 0;
9398 /* Some complex insns don't need length adjustment and therefore
9399 the length need not/must not be adjusted for these insns.
9400 It is easier to state this in an insn attribute "adjust_len" than
9401 to clutter up code here... */
9403 if (!NONDEBUG_INSN_P (insn) || recog_memoized (insn) == -1)
9405 return len;
9408 /* Read from insn attribute "adjust_len" if/how length is to be adjusted. */
9410 adjust_len = get_attr_adjust_len (insn);
9412 if (adjust_len == ADJUST_LEN_NO)
9414 /* Nothing to adjust: The length from attribute "length" is fine.
9415 This is the default. */
9417 return len;
9420 /* Extract insn's operands. */
9422 extract_constrain_insn_cached (insn);
9424 /* Dispatch to right function. */
9426 switch (adjust_len)
9428 case ADJUST_LEN_RELOAD_IN16: output_reload_inhi (op, op[2], &len); break;
9429 case ADJUST_LEN_RELOAD_IN24: avr_out_reload_inpsi (op, op[2], &len); break;
9430 case ADJUST_LEN_RELOAD_IN32: output_reload_insisf (op, op[2], &len); break;
9432 case ADJUST_LEN_OUT_BITOP: avr_out_bitop (insn, op, &len); break;
9434 case ADJUST_LEN_PLUS: avr_out_plus (insn, op, &len); break;
9435 case ADJUST_LEN_ADDTO_SP: avr_out_addto_sp (op, &len); break;
9437 case ADJUST_LEN_MOV8: output_movqi (insn, op, &len); break;
9438 case ADJUST_LEN_MOV16: output_movhi (insn, op, &len); break;
9439 case ADJUST_LEN_MOV24: avr_out_movpsi (insn, op, &len); break;
9440 case ADJUST_LEN_MOV32: output_movsisf (insn, op, &len); break;
9441 case ADJUST_LEN_MOVMEM: avr_out_movmem (insn, op, &len); break;
9442 case ADJUST_LEN_XLOAD: avr_out_xload (insn, op, &len); break;
9443 case ADJUST_LEN_SEXT: avr_out_sign_extend (insn, op, &len); break;
9445 case ADJUST_LEN_SFRACT: avr_out_fract (insn, op, true, &len); break;
9446 case ADJUST_LEN_UFRACT: avr_out_fract (insn, op, false, &len); break;
9447 case ADJUST_LEN_ROUND: avr_out_round (insn, op, &len); break;
9449 case ADJUST_LEN_TSTHI: avr_out_tsthi (insn, op, &len); break;
9450 case ADJUST_LEN_TSTPSI: avr_out_tstpsi (insn, op, &len); break;
9451 case ADJUST_LEN_TSTSI: avr_out_tstsi (insn, op, &len); break;
9452 case ADJUST_LEN_COMPARE: avr_out_compare (insn, op, &len); break;
9453 case ADJUST_LEN_COMPARE64: avr_out_compare64 (insn, op, &len); break;
9455 case ADJUST_LEN_LSHRQI: lshrqi3_out (insn, op, &len); break;
9456 case ADJUST_LEN_LSHRHI: lshrhi3_out (insn, op, &len); break;
9457 case ADJUST_LEN_LSHRSI: lshrsi3_out (insn, op, &len); break;
9459 case ADJUST_LEN_ASHRQI: ashrqi3_out (insn, op, &len); break;
9460 case ADJUST_LEN_ASHRHI: ashrhi3_out (insn, op, &len); break;
9461 case ADJUST_LEN_ASHRSI: ashrsi3_out (insn, op, &len); break;
9463 case ADJUST_LEN_ASHLQI: ashlqi3_out (insn, op, &len); break;
9464 case ADJUST_LEN_ASHLHI: ashlhi3_out (insn, op, &len); break;
9465 case ADJUST_LEN_ASHLSI: ashlsi3_out (insn, op, &len); break;
9467 case ADJUST_LEN_ASHLPSI: avr_out_ashlpsi3 (insn, op, &len); break;
9468 case ADJUST_LEN_ASHRPSI: avr_out_ashrpsi3 (insn, op, &len); break;
9469 case ADJUST_LEN_LSHRPSI: avr_out_lshrpsi3 (insn, op, &len); break;
9471 case ADJUST_LEN_CALL: len = AVR_HAVE_JMP_CALL ? 2 : 1; break;
9473 case ADJUST_LEN_INSERT_BITS: avr_out_insert_bits (op, &len); break;
9475 case ADJUST_LEN_INSV_NOTBIT:
9476 avr_out_insert_notbit (insn, op, NULL_RTX, &len);
9477 break;
9478 case ADJUST_LEN_INSV_NOTBIT_0:
9479 avr_out_insert_notbit (insn, op, const0_rtx, &len);
9480 break;
9481 case ADJUST_LEN_INSV_NOTBIT_7:
9482 avr_out_insert_notbit (insn, op, GEN_INT (7), &len);
9483 break;
9485 default:
9486 gcc_unreachable();
9489 return len;
9492 /* Return nonzero if register REG dead after INSN. */
9495 reg_unused_after (rtx_insn *insn, rtx reg)
9497 return (dead_or_set_p (insn, reg)
9498 || (REG_P (reg) && _reg_unused_after (insn, reg)));
9501 /* Return nonzero if REG is not used after INSN.
9502 We assume REG is a reload reg, and therefore does
9503 not live past labels. It may live past calls or jumps though. */
9506 _reg_unused_after (rtx_insn *insn, rtx reg)
9508 enum rtx_code code;
9509 rtx set;
9511 /* If the reg is set by this instruction, then it is safe for our
9512 case. Disregard the case where this is a store to memory, since
9513 we are checking a register used in the store address. */
9514 set = single_set (insn);
9515 if (set && !MEM_P (SET_DEST (set))
9516 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
9517 return 1;
9519 while ((insn = NEXT_INSN (insn)))
9521 rtx set;
9522 code = GET_CODE (insn);
9524 #if 0
9525 /* If this is a label that existed before reload, then the register
9526 if dead here. However, if this is a label added by reorg, then
9527 the register may still be live here. We can't tell the difference,
9528 so we just ignore labels completely. */
9529 if (code == CODE_LABEL)
9530 return 1;
9531 /* else */
9532 #endif
9534 if (!INSN_P (insn))
9535 continue;
9537 if (code == JUMP_INSN)
9538 return 0;
9540 /* If this is a sequence, we must handle them all at once.
9541 We could have for instance a call that sets the target register,
9542 and an insn in a delay slot that uses the register. In this case,
9543 we must return 0. */
9544 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
9546 rtx_sequence *seq = as_a <rtx_sequence *> (PATTERN (insn));
9547 int retval = 0;
9549 for (int i = 0; i < seq->len (); i++)
9551 rtx_insn *this_insn = seq->insn (i);
9552 rtx set = single_set (this_insn);
9554 if (CALL_P (this_insn))
9555 code = CALL_INSN;
9556 else if (JUMP_P (this_insn))
9558 if (INSN_ANNULLED_BRANCH_P (this_insn))
9559 return 0;
9560 code = JUMP_INSN;
9563 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
9564 return 0;
9565 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
9567 if (!MEM_P (SET_DEST (set)))
9568 retval = 1;
9569 else
9570 return 0;
9572 if (set == 0
9573 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
9574 return 0;
9576 if (retval == 1)
9577 return 1;
9578 else if (code == JUMP_INSN)
9579 return 0;
9582 if (code == CALL_INSN)
9584 rtx tem;
9585 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
9586 if (GET_CODE (XEXP (tem, 0)) == USE
9587 && REG_P (XEXP (XEXP (tem, 0), 0))
9588 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
9589 return 0;
9590 if (call_used_regs[REGNO (reg)])
9591 return 1;
9594 set = single_set (insn);
9596 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
9597 return 0;
9598 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
9599 return !MEM_P (SET_DEST (set));
9600 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
9601 return 0;
9603 return 1;
9607 /* Implement `TARGET_ASM_INTEGER'. */
9608 /* Target hook for assembling integer objects. The AVR version needs
9609 special handling for references to certain labels. */
9611 static bool
9612 avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
9614 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
9615 && text_segment_operand (x, VOIDmode))
9617 fputs ("\t.word\tgs(", asm_out_file);
9618 output_addr_const (asm_out_file, x);
9619 fputs (")\n", asm_out_file);
9621 return true;
9623 else if (GET_MODE (x) == PSImode)
9625 /* This needs binutils 2.23+, see PR binutils/13503 */
9627 fputs ("\t.byte\tlo8(", asm_out_file);
9628 output_addr_const (asm_out_file, x);
9629 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
9631 fputs ("\t.byte\thi8(", asm_out_file);
9632 output_addr_const (asm_out_file, x);
9633 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
9635 fputs ("\t.byte\thh8(", asm_out_file);
9636 output_addr_const (asm_out_file, x);
9637 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
9639 return true;
9641 else if (CONST_FIXED_P (x))
9643 /* varasm fails to handle big fixed modes that don't fit in hwi. */
9645 for (unsigned n = 0; n < size; n++)
9647 rtx xn = simplify_gen_subreg (QImode, x, GET_MODE (x), n);
9648 default_assemble_integer (xn, 1, aligned_p);
9651 return true;
9654 if (AVR_TINY
9655 && avr_address_tiny_pm_p (x))
9657 x = plus_constant (Pmode, x, avr_arch->flash_pm_offset);
9660 return default_assemble_integer (x, size, aligned_p);
9664 /* Implement `TARGET_CLASS_LIKELY_SPILLED_P'. */
9665 /* Return value is nonzero if pseudos that have been
9666 assigned to registers of class CLASS would likely be spilled
9667 because registers of CLASS are needed for spill registers. */
9669 static bool
9670 avr_class_likely_spilled_p (reg_class_t c)
9672 return (c != ALL_REGS &&
9673 (AVR_TINY ? 1 : c != ADDW_REGS));
9677 /* Valid attributes:
9678 progmem - Put data to program memory.
9679 signal - Make a function to be hardware interrupt.
9680 After function prologue interrupts remain disabled.
9681 interrupt - Make a function to be hardware interrupt. Before function
9682 prologue interrupts are enabled by means of SEI.
9683 naked - Don't generate function prologue/epilogue and RET
9684 instruction. */
9686 /* Handle a "progmem" attribute; arguments as in
9687 struct attribute_spec.handler. */
9689 static tree
9690 avr_handle_progmem_attribute (tree *node, tree name,
9691 tree args ATTRIBUTE_UNUSED,
9692 int flags ATTRIBUTE_UNUSED,
9693 bool *no_add_attrs)
9695 if (DECL_P (*node))
9697 if (TREE_CODE (*node) == TYPE_DECL)
9699 /* This is really a decl attribute, not a type attribute,
9700 but try to handle it for GCC 3.0 backwards compatibility. */
9702 tree type = TREE_TYPE (*node);
9703 tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
9704 tree newtype = build_type_attribute_variant (type, attr);
9706 TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
9707 TREE_TYPE (*node) = newtype;
9708 *no_add_attrs = true;
9710 else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
9712 *no_add_attrs = false;
9714 else
9716 warning (OPT_Wattributes, "%qE attribute ignored",
9717 name);
9718 *no_add_attrs = true;
9722 return NULL_TREE;
9725 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
9726 struct attribute_spec.handler. */
9728 static tree
9729 avr_handle_fndecl_attribute (tree *node, tree name,
9730 tree args ATTRIBUTE_UNUSED,
9731 int flags ATTRIBUTE_UNUSED,
9732 bool *no_add_attrs)
9734 if (TREE_CODE (*node) != FUNCTION_DECL)
9736 warning (OPT_Wattributes, "%qE attribute only applies to functions",
9737 name);
9738 *no_add_attrs = true;
9741 return NULL_TREE;
9744 static tree
9745 avr_handle_fntype_attribute (tree *node, tree name,
9746 tree args ATTRIBUTE_UNUSED,
9747 int flags ATTRIBUTE_UNUSED,
9748 bool *no_add_attrs)
9750 if (TREE_CODE (*node) != FUNCTION_TYPE)
9752 warning (OPT_Wattributes, "%qE attribute only applies to functions",
9753 name);
9754 *no_add_attrs = true;
9757 return NULL_TREE;
9760 static tree
9761 avr_handle_absdata_attribute (tree *node, tree name, tree /* args */,
9762 int /* flags */, bool *no_add)
9764 location_t loc = DECL_SOURCE_LOCATION (*node);
9766 if (AVR_TINY)
9768 if (TREE_CODE (*node) != VAR_DECL
9769 || (!TREE_STATIC (*node) && !DECL_EXTERNAL (*node)))
9771 warning_at (loc, OPT_Wattributes, "%qE attribute only applies to"
9772 " variables in static storage", name);
9773 *no_add = true;
9776 else
9778 warning_at (loc, OPT_Wattributes, "%qE attribute only supported"
9779 " for reduced Tiny cores", name);
9780 *no_add = true;
9783 return NULL_TREE;
9786 static tree
9787 avr_handle_addr_attribute (tree *node, tree name, tree args,
9788 int flags ATTRIBUTE_UNUSED, bool *no_add)
9790 bool io_p = (strncmp (IDENTIFIER_POINTER (name), "io", 2) == 0);
9791 location_t loc = DECL_SOURCE_LOCATION (*node);
9793 if (!VAR_P (*node))
9795 warning_at (loc, OPT_Wattributes, "%qE attribute only applies to "
9796 "variables", name);
9797 *no_add = true;
9798 return NULL_TREE;
9801 if (args != NULL_TREE)
9803 if (TREE_CODE (TREE_VALUE (args)) == NON_LVALUE_EXPR)
9804 TREE_VALUE (args) = TREE_OPERAND (TREE_VALUE (args), 0);
9805 tree arg = TREE_VALUE (args);
9806 if (TREE_CODE (arg) != INTEGER_CST)
9808 warning_at (loc, OPT_Wattributes, "%qE attribute allows only an "
9809 "integer constant argument", name);
9810 *no_add = true;
9812 else if (io_p
9813 && (!tree_fits_shwi_p (arg)
9814 || !(strcmp (IDENTIFIER_POINTER (name), "io_low") == 0
9815 ? low_io_address_operand : io_address_operand)
9816 (GEN_INT (TREE_INT_CST_LOW (arg)), QImode)))
9818 warning_at (loc, OPT_Wattributes, "%qE attribute address "
9819 "out of range", name);
9820 *no_add = true;
9822 else
9824 tree attribs = DECL_ATTRIBUTES (*node);
9825 const char *names[] = { "io", "io_low", "address", NULL };
9826 for (const char **p = names; *p; p++)
9828 tree other = lookup_attribute (*p, attribs);
9829 if (other && TREE_VALUE (other))
9831 warning_at (loc, OPT_Wattributes,
9832 "both %s and %qE attribute provide address",
9833 *p, name);
9834 *no_add = true;
9835 break;
9841 if (*no_add == false && io_p && !TREE_THIS_VOLATILE (*node))
9842 warning_at (loc, OPT_Wattributes, "%qE attribute on non-volatile variable",
9843 name);
9845 return NULL_TREE;
9849 avr_eval_addr_attrib (rtx x)
9851 if (SYMBOL_REF_P (x)
9852 && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_ADDRESS))
9854 tree decl = SYMBOL_REF_DECL (x);
9855 tree attr = NULL_TREE;
9857 if (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO)
9859 attr = lookup_attribute ("io", DECL_ATTRIBUTES (decl));
9860 if (!attr || !TREE_VALUE (attr))
9861 attr = lookup_attribute ("io_low", DECL_ATTRIBUTES (decl));
9862 gcc_assert (attr);
9864 if (!attr || !TREE_VALUE (attr))
9865 attr = lookup_attribute ("address", DECL_ATTRIBUTES (decl));
9866 gcc_assert (attr && TREE_VALUE (attr) && TREE_VALUE (TREE_VALUE (attr)));
9867 return GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))));
9869 return x;
9873 /* AVR attributes. */
9874 static const struct attribute_spec avr_attribute_table[] =
9876 /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
9877 affects_type_identity, handler, exclude } */
9878 { "progmem", 0, 0, false, false, false, false,
9879 avr_handle_progmem_attribute, NULL },
9880 { "signal", 0, 0, true, false, false, false,
9881 avr_handle_fndecl_attribute, NULL },
9882 { "interrupt", 0, 0, true, false, false, false,
9883 avr_handle_fndecl_attribute, NULL },
9884 { "no_gccisr", 0, 0, true, false, false, false,
9885 avr_handle_fndecl_attribute, NULL },
9886 { "naked", 0, 0, false, true, true, false,
9887 avr_handle_fntype_attribute, NULL },
9888 { "OS_task", 0, 0, false, true, true, false,
9889 avr_handle_fntype_attribute, NULL },
9890 { "OS_main", 0, 0, false, true, true, false,
9891 avr_handle_fntype_attribute, NULL },
9892 { "io", 0, 1, true, false, false, false,
9893 avr_handle_addr_attribute, NULL },
9894 { "io_low", 0, 1, true, false, false, false,
9895 avr_handle_addr_attribute, NULL },
9896 { "address", 1, 1, true, false, false, false,
9897 avr_handle_addr_attribute, NULL },
9898 { "absdata", 0, 0, true, false, false, false,
9899 avr_handle_absdata_attribute, NULL },
9900 { NULL, 0, 0, false, false, false, false, NULL, NULL }
9904 /* Return true if we support address space AS for the architecture in effect
9905 and false, otherwise. If LOC is not UNKNOWN_LOCATION then also issue
9906 a respective error. */
9908 bool
9909 avr_addr_space_supported_p (addr_space_t as, location_t loc)
9911 if (AVR_TINY)
9913 if (loc != UNKNOWN_LOCATION)
9914 error_at (loc, "address spaces are not supported for reduced "
9915 "Tiny devices");
9916 return false;
9918 else if (avr_addrspace[as].segment >= avr_n_flash)
9920 if (loc != UNKNOWN_LOCATION)
9921 error_at (loc, "address space %qs not supported for devices with "
9922 "flash size up to %d KiB", avr_addrspace[as].name,
9923 64 * avr_n_flash);
9924 return false;
9927 return true;
9931 /* Implement `TARGET_ADDR_SPACE_DIAGNOSE_USAGE'. */
9933 static void
9934 avr_addr_space_diagnose_usage (addr_space_t as, location_t loc)
9936 (void) avr_addr_space_supported_p (as, loc);
9940 /* Look if DECL shall be placed in program memory space by
9941 means of attribute `progmem' or some address-space qualifier.
9942 Return non-zero if DECL is data that must end up in Flash and
9943 zero if the data lives in RAM (.bss, .data, .rodata, ...).
9945 Return 2 if DECL is located in 24-bit flash address-space
9946 Return 1 if DECL is located in 16-bit flash address-space
9947 Return -1 if attribute `progmem' occurs in DECL or ATTRIBUTES
9948 Return 0 otherwise */
9951 avr_progmem_p (tree decl, tree attributes)
9953 tree a;
9955 if (TREE_CODE (decl) != VAR_DECL)
9956 return 0;
9958 if (avr_decl_memx_p (decl))
9959 return 2;
9961 if (avr_decl_flash_p (decl))
9962 return 1;
9964 if (NULL_TREE
9965 != lookup_attribute ("progmem", attributes))
9966 return -1;
9968 a = decl;
9971 a = TREE_TYPE(a);
9972 while (TREE_CODE (a) == ARRAY_TYPE);
9974 if (a == error_mark_node)
9975 return 0;
9977 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
9978 return -1;
9980 return 0;
9984 /* Return true if DECL has attribute `absdata' set. This function should
9985 only be used for AVR_TINY. */
9987 static bool
9988 avr_decl_absdata_p (tree decl, tree attributes)
9990 return (TREE_CODE (decl) == VAR_DECL
9991 && NULL_TREE != lookup_attribute ("absdata", attributes));
9995 /* Scan type TYP for pointer references to address space ASn.
9996 Return ADDR_SPACE_GENERIC (i.e. 0) if all pointers targeting
9997 the AS are also declared to be CONST.
9998 Otherwise, return the respective address space, i.e. a value != 0. */
10000 static addr_space_t
10001 avr_nonconst_pointer_addrspace (tree typ)
10003 while (ARRAY_TYPE == TREE_CODE (typ))
10004 typ = TREE_TYPE (typ);
10006 if (POINTER_TYPE_P (typ))
10008 addr_space_t as;
10009 tree target = TREE_TYPE (typ);
10011 /* Pointer to function: Test the function's return type. */
10013 if (FUNCTION_TYPE == TREE_CODE (target))
10014 return avr_nonconst_pointer_addrspace (TREE_TYPE (target));
10016 /* "Ordinary" pointers... */
10018 while (TREE_CODE (target) == ARRAY_TYPE)
10019 target = TREE_TYPE (target);
10021 /* Pointers to non-generic address space must be const. */
10023 as = TYPE_ADDR_SPACE (target);
10025 if (!ADDR_SPACE_GENERIC_P (as)
10026 && !TYPE_READONLY (target)
10027 && avr_addr_space_supported_p (as))
10029 return as;
10032 /* Scan pointer's target type. */
10034 return avr_nonconst_pointer_addrspace (target);
10037 return ADDR_SPACE_GENERIC;
10041 /* Sanity check NODE so that all pointers targeting non-generic address spaces
10042 go along with CONST qualifier. Writing to these address spaces should
10043 be detected and complained about as early as possible. */
10045 static bool
10046 avr_pgm_check_var_decl (tree node)
10048 const char *reason = NULL;
10050 addr_space_t as = ADDR_SPACE_GENERIC;
10052 gcc_assert (as == 0);
10054 if (avr_log.progmem)
10055 avr_edump ("%?: %t\n", node);
10057 switch (TREE_CODE (node))
10059 default:
10060 break;
10062 case VAR_DECL:
10063 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
10064 reason = _("variable");
10065 break;
10067 case PARM_DECL:
10068 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
10069 reason = _("function parameter");
10070 break;
10072 case FIELD_DECL:
10073 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
10074 reason = _("structure field");
10075 break;
10077 case FUNCTION_DECL:
10078 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (TREE_TYPE (node))),
10080 reason = _("return type of function");
10081 break;
10083 case POINTER_TYPE:
10084 if (as = avr_nonconst_pointer_addrspace (node), as)
10085 reason = _("pointer");
10086 break;
10089 if (reason)
10091 if (TYPE_P (node))
10092 error ("pointer targeting address space %qs must be const in %qT",
10093 avr_addrspace[as].name, node);
10094 else
10095 error ("pointer targeting address space %qs must be const"
10096 " in %s %q+D",
10097 avr_addrspace[as].name, reason, node);
10100 return reason == NULL;
10104 /* Add the section attribute if the variable is in progmem. */
10106 static void
10107 avr_insert_attributes (tree node, tree *attributes)
10109 avr_pgm_check_var_decl (node);
10111 if (TREE_CODE (node) == VAR_DECL
10112 && (TREE_STATIC (node) || DECL_EXTERNAL (node))
10113 && avr_progmem_p (node, *attributes))
10115 addr_space_t as;
10116 tree node0 = node;
10118 /* For C++, we have to peel arrays in order to get correct
10119 determination of readonlyness. */
10122 node0 = TREE_TYPE (node0);
10123 while (TREE_CODE (node0) == ARRAY_TYPE);
10125 if (error_mark_node == node0)
10126 return;
10128 as = TYPE_ADDR_SPACE (TREE_TYPE (node));
10130 if (!TYPE_READONLY (node0)
10131 && !TREE_READONLY (node))
10133 const char *reason = "__attribute__((progmem))";
10135 if (!ADDR_SPACE_GENERIC_P (as))
10136 reason = avr_addrspace[as].name;
10138 if (avr_log.progmem)
10139 avr_edump ("\n%?: %t\n%t\n", node, node0);
10141 error ("variable %q+D must be const in order to be put into"
10142 " read-only section by means of %qs", node, reason);
10148 /* Implement `ASM_OUTPUT_ALIGNED_DECL_LOCAL'. */
10149 /* Implement `ASM_OUTPUT_ALIGNED_DECL_COMMON'. */
10150 /* Track need of __do_clear_bss. */
10152 void
10153 avr_asm_output_aligned_decl_common (FILE * stream,
10154 tree decl,
10155 const char *name,
10156 unsigned HOST_WIDE_INT size,
10157 unsigned int align, bool local_p)
10159 rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
10160 rtx symbol;
10162 if (mem != NULL_RTX && MEM_P (mem)
10163 && SYMBOL_REF_P ((symbol = XEXP (mem, 0)))
10164 && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
10166 if (!local_p)
10168 fprintf (stream, "\t.globl\t");
10169 assemble_name (stream, name);
10170 fprintf (stream, "\n");
10172 if (SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS)
10174 assemble_name (stream, name);
10175 fprintf (stream, " = %ld\n",
10176 (long) INTVAL (avr_eval_addr_attrib (symbol)));
10178 else if (local_p)
10179 error_at (DECL_SOURCE_LOCATION (decl),
10180 "static IO declaration for %q+D needs an address", decl);
10181 return;
10184 /* __gnu_lto_v1 etc. are just markers for the linker injected by toplev.c.
10185 There is no need to trigger __do_clear_bss code for them. */
10187 if (!STR_PREFIX_P (name, "__gnu_lto"))
10188 avr_need_clear_bss_p = true;
10190 if (local_p)
10191 ASM_OUTPUT_ALIGNED_LOCAL (stream, name, size, align);
10192 else
10193 ASM_OUTPUT_ALIGNED_COMMON (stream, name, size, align);
10196 void
10197 avr_asm_asm_output_aligned_bss (FILE *file, tree decl, const char *name,
10198 unsigned HOST_WIDE_INT size, int align,
10199 void (*default_func)
10200 (FILE *, tree, const char *,
10201 unsigned HOST_WIDE_INT, int))
10203 rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
10204 rtx symbol;
10206 if (mem != NULL_RTX && MEM_P (mem)
10207 && SYMBOL_REF_P ((symbol = XEXP (mem, 0)))
10208 && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
10210 if (!(SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS))
10211 error_at (DECL_SOURCE_LOCATION (decl),
10212 "IO definition for %q+D needs an address", decl);
10213 avr_asm_output_aligned_decl_common (file, decl, name, size, align, false);
10215 else
10216 default_func (file, decl, name, size, align);
10220 /* Unnamed section callback for data_section
10221 to track need of __do_copy_data. */
10223 static void
10224 avr_output_data_section_asm_op (const void *data)
10226 avr_need_copy_data_p = true;
10228 /* Dispatch to default. */
10229 output_section_asm_op (data);
10233 /* Unnamed section callback for bss_section
10234 to track need of __do_clear_bss. */
10236 static void
10237 avr_output_bss_section_asm_op (const void *data)
10239 avr_need_clear_bss_p = true;
10241 /* Dispatch to default. */
10242 output_section_asm_op (data);
10246 /* Unnamed section callback for progmem*.data sections. */
10248 static void
10249 avr_output_progmem_section_asm_op (const void *data)
10251 fprintf (asm_out_file, "\t.section\t%s,\"a\",@progbits\n",
10252 (const char*) data);
10256 /* Implement `TARGET_ASM_INIT_SECTIONS'. */
10258 static void
10259 avr_asm_init_sections (void)
10261 /* Override section callbacks to keep track of `avr_need_clear_bss_p'
10262 resp. `avr_need_copy_data_p'. If flash is not mapped to RAM then
10263 we have also to track .rodata because it is located in RAM then. */
10265 #if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
10266 if (avr_arch->flash_pm_offset == 0)
10267 #endif
10268 readonly_data_section->unnamed.callback = avr_output_data_section_asm_op;
10269 data_section->unnamed.callback = avr_output_data_section_asm_op;
10270 bss_section->unnamed.callback = avr_output_bss_section_asm_op;
10274 /* Implement `TARGET_ASM_NAMED_SECTION'. */
10275 /* Track need of __do_clear_bss, __do_copy_data for named sections. */
10277 static void
10278 avr_asm_named_section (const char *name, unsigned int flags, tree decl)
10280 if (flags & AVR_SECTION_PROGMEM)
10282 addr_space_t as = (flags & AVR_SECTION_PROGMEM) / SECTION_MACH_DEP;
10283 const char *old_prefix = ".rodata";
10284 const char *new_prefix = avr_addrspace[as].section_name;
10286 if (STR_PREFIX_P (name, old_prefix))
10288 const char *sname = ACONCAT ((new_prefix,
10289 name + strlen (old_prefix), NULL));
10290 default_elf_asm_named_section (sname, flags, decl);
10291 return;
10294 default_elf_asm_named_section (new_prefix, flags, decl);
10295 return;
10298 if (!avr_need_copy_data_p)
10299 avr_need_copy_data_p = (STR_PREFIX_P (name, ".data")
10300 || STR_PREFIX_P (name, ".gnu.linkonce.d"));
10302 if (!avr_need_copy_data_p
10303 #if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
10304 && avr_arch->flash_pm_offset == 0
10305 #endif
10307 avr_need_copy_data_p = (STR_PREFIX_P (name, ".rodata")
10308 || STR_PREFIX_P (name, ".gnu.linkonce.r"));
10310 if (!avr_need_clear_bss_p)
10311 avr_need_clear_bss_p = STR_PREFIX_P (name, ".bss");
10313 default_elf_asm_named_section (name, flags, decl);
10317 /* Implement `TARGET_SECTION_TYPE_FLAGS'. */
10319 static unsigned int
10320 avr_section_type_flags (tree decl, const char *name, int reloc)
10322 unsigned int flags = default_section_type_flags (decl, name, reloc);
10324 if (STR_PREFIX_P (name, ".noinit"))
10326 if (decl && TREE_CODE (decl) == VAR_DECL
10327 && DECL_INITIAL (decl) == NULL_TREE)
10328 flags |= SECTION_BSS; /* @nobits */
10329 else
10330 warning (0, "only uninitialized variables can be placed in the "
10331 ".noinit section");
10334 if (decl && DECL_P (decl)
10335 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
10337 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
10339 /* Attribute progmem puts data in generic address space.
10340 Set section flags as if it was in __flash to get the right
10341 section prefix in the remainder. */
10343 if (ADDR_SPACE_GENERIC_P (as))
10344 as = ADDR_SPACE_FLASH;
10346 flags |= as * SECTION_MACH_DEP;
10347 flags &= ~SECTION_WRITE;
10348 flags &= ~SECTION_BSS;
10351 return flags;
10355 /* A helper for the next function. NODE is a decl that is associated with
10356 a symbol. Return TRUE if the respective object may be accessed by LDS.
10357 There might still be other reasons for why LDS is not appropriate.
10358 This function is only appropriate for AVR_TINY. */
10360 static bool
10361 avr_decl_maybe_lds_p (tree node)
10363 if (!node
10364 || TREE_CODE (node) != VAR_DECL
10365 || DECL_SECTION_NAME (node) != NULL)
10366 return false;
10368 /* Don't use LDS for objects that go to .rodata. The current default
10369 linker description file still locates .rodata in RAM, but this is not
10370 a must. A better linker script would just keep .rodata in flash and
10371 add an offset of 0x4000 to the VMA. Hence avoid LDS for such data. */
10373 if (TREE_READONLY (node))
10374 return false;
10376 // C++ requires peeling arrays.
10379 node = TREE_TYPE (node);
10380 while (ARRAY_TYPE == TREE_CODE (node));
10382 return (node != error_mark_node
10383 && !TYPE_READONLY (node));
10387 /* Implement `TARGET_ENCODE_SECTION_INFO'. */
10389 static void
10390 avr_encode_section_info (tree decl, rtx rtl, int new_decl_p)
10392 tree addr_attr = NULL_TREE;
10394 /* In avr_handle_progmem_attribute, DECL_INITIAL is not yet
10395 readily available, see PR34734. So we postpone the warning
10396 about uninitialized data in program memory section until here. */
10398 if (new_decl_p
10399 && decl && DECL_P (decl)
10400 && !DECL_EXTERNAL (decl)
10401 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
10403 if (!TREE_READONLY (decl))
10405 // This might happen with C++ if stuff needs constructing.
10406 error ("variable %q+D with dynamic initialization put "
10407 "into program memory area", decl);
10409 else if (NULL_TREE == DECL_INITIAL (decl))
10411 // Don't warn for (implicit) aliases like in PR80462.
10412 tree asmname = DECL_ASSEMBLER_NAME (decl);
10413 varpool_node *node = varpool_node::get_for_asmname (asmname);
10414 bool alias_p = node && node->alias;
10416 if (!alias_p)
10417 warning (OPT_Wuninitialized, "uninitialized variable %q+D put "
10418 "into program memory area", decl);
10422 default_encode_section_info (decl, rtl, new_decl_p);
10424 if (decl && DECL_P (decl)
10425 && TREE_CODE (decl) != FUNCTION_DECL
10426 && MEM_P (rtl)
10427 && SYMBOL_REF_P (XEXP (rtl, 0)))
10429 rtx sym = XEXP (rtl, 0);
10430 tree type = TREE_TYPE (decl);
10431 tree attr = DECL_ATTRIBUTES (decl);
10432 if (type == error_mark_node)
10433 return;
10435 addr_space_t as = TYPE_ADDR_SPACE (type);
10437 /* PSTR strings are in generic space but located in flash:
10438 patch address space. */
10440 if (!AVR_TINY && avr_progmem_p (decl, attr) == -1)
10441 as = ADDR_SPACE_FLASH;
10443 AVR_SYMBOL_SET_ADDR_SPACE (sym, as);
10445 tree io_low_attr = lookup_attribute ("io_low", attr);
10446 tree io_attr = lookup_attribute ("io", attr);
10448 if (io_low_attr
10449 && TREE_VALUE (io_low_attr) && TREE_VALUE (TREE_VALUE (io_low_attr)))
10450 addr_attr = io_attr;
10451 else if (io_attr
10452 && TREE_VALUE (io_attr) && TREE_VALUE (TREE_VALUE (io_attr)))
10453 addr_attr = io_attr;
10454 else
10455 addr_attr = lookup_attribute ("address", attr);
10456 if (io_low_attr
10457 || (io_attr && addr_attr
10458 && low_io_address_operand
10459 (GEN_INT (TREE_INT_CST_LOW
10460 (TREE_VALUE (TREE_VALUE (addr_attr)))), QImode)))
10461 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO_LOW;
10462 if (io_attr || io_low_attr)
10463 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO;
10464 /* If we have an (io) address attribute specification, but the variable
10465 is external, treat the address as only a tentative definition
10466 to be used to determine if an io port is in the lower range, but
10467 don't use the exact value for constant propagation. */
10468 if (addr_attr && !DECL_EXTERNAL (decl))
10469 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_ADDRESS;
10472 if (AVR_TINY
10473 && decl
10474 && VAR_DECL == TREE_CODE (decl)
10475 && MEM_P (rtl)
10476 && SYMBOL_REF_P (XEXP (rtl, 0)))
10478 rtx sym = XEXP (rtl, 0);
10479 bool progmem_p = avr_progmem_p (decl, DECL_ATTRIBUTES (decl)) == -1;
10481 if (progmem_p)
10483 // Tag symbols for addition of 0x4000 (avr_arch->flash_pm_offset).
10484 SYMBOL_REF_FLAGS (sym) |= AVR_SYMBOL_FLAG_TINY_PM;
10487 if (avr_decl_absdata_p (decl, DECL_ATTRIBUTES (decl))
10488 || (TARGET_ABSDATA
10489 && !progmem_p
10490 && !addr_attr
10491 && avr_decl_maybe_lds_p (decl))
10492 || (addr_attr
10493 // If addr_attr is non-null, it has an argument. Peek into it.
10494 && TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (addr_attr))) < 0xc0))
10496 // May be accessed by LDS / STS.
10497 SYMBOL_REF_FLAGS (sym) |= AVR_SYMBOL_FLAG_TINY_ABSDATA;
10500 if (progmem_p
10501 && avr_decl_absdata_p (decl, DECL_ATTRIBUTES (decl)))
10503 error ("%q+D has incompatible attributes %qs and %qs",
10504 decl, "progmem", "absdata");
10510 /* Implement `TARGET_ASM_SELECT_SECTION' */
10512 static section *
10513 avr_asm_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
10515 section * sect = default_elf_select_section (decl, reloc, align);
10517 if (decl && DECL_P (decl)
10518 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
10520 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
10522 /* __progmem__ goes in generic space but shall be allocated to
10523 .progmem.data */
10525 if (ADDR_SPACE_GENERIC_P (as))
10526 as = ADDR_SPACE_FLASH;
10528 if (sect->common.flags & SECTION_NAMED)
10530 const char * name = sect->named.name;
10531 const char * old_prefix = ".rodata";
10532 const char * new_prefix = avr_addrspace[as].section_name;
10534 if (STR_PREFIX_P (name, old_prefix))
10536 const char *sname = ACONCAT ((new_prefix,
10537 name + strlen (old_prefix), NULL));
10538 return get_section (sname,
10539 sect->common.flags & ~SECTION_DECLARED,
10540 sect->named.decl);
10544 if (!progmem_section[as])
10546 progmem_section[as]
10547 = get_unnamed_section (0, avr_output_progmem_section_asm_op,
10548 avr_addrspace[as].section_name);
10551 return progmem_section[as];
10554 return sect;
10557 /* Implement `TARGET_ASM_FILE_START'. */
10558 /* Outputs some text at the start of each assembler file. */
10560 static void
10561 avr_file_start (void)
10563 int sfr_offset = avr_arch->sfr_offset;
10565 if (avr_arch->asm_only)
10566 error ("architecture %qs supported for assembler only", avr_mmcu);
10568 default_file_start ();
10570 /* Print I/O addresses of some SFRs used with IN and OUT. */
10572 if (AVR_HAVE_SPH)
10573 fprintf (asm_out_file, "__SP_H__ = 0x%02x\n", avr_addr.sp_h - sfr_offset);
10575 fprintf (asm_out_file, "__SP_L__ = 0x%02x\n", avr_addr.sp_l - sfr_offset);
10576 fprintf (asm_out_file, "__SREG__ = 0x%02x\n", avr_addr.sreg - sfr_offset);
10577 if (AVR_HAVE_RAMPZ)
10578 fprintf (asm_out_file, "__RAMPZ__ = 0x%02x\n", avr_addr.rampz - sfr_offset);
10579 if (AVR_HAVE_RAMPY)
10580 fprintf (asm_out_file, "__RAMPY__ = 0x%02x\n", avr_addr.rampy - sfr_offset);
10581 if (AVR_HAVE_RAMPX)
10582 fprintf (asm_out_file, "__RAMPX__ = 0x%02x\n", avr_addr.rampx - sfr_offset);
10583 if (AVR_HAVE_RAMPD)
10584 fprintf (asm_out_file, "__RAMPD__ = 0x%02x\n", avr_addr.rampd - sfr_offset);
10585 if (AVR_XMEGA || AVR_TINY)
10586 fprintf (asm_out_file, "__CCP__ = 0x%02x\n", avr_addr.ccp - sfr_offset);
10587 fprintf (asm_out_file, "__tmp_reg__ = %d\n", AVR_TMP_REGNO);
10588 fprintf (asm_out_file, "__zero_reg__ = %d\n", AVR_ZERO_REGNO);
10592 /* Implement `TARGET_ASM_FILE_END'. */
10593 /* Outputs to the stdio stream FILE some
10594 appropriate text to go at the end of an assembler file. */
10596 static void
10597 avr_file_end (void)
10599 /* Output these only if there is anything in the
10600 .data* / .rodata* / .gnu.linkonce.* resp. .bss* or COMMON
10601 input section(s) - some code size can be saved by not
10602 linking in the initialization code from libgcc if resp.
10603 sections are empty, see PR18145. */
10605 if (avr_need_copy_data_p)
10606 fputs (".global __do_copy_data\n", asm_out_file);
10608 if (avr_need_clear_bss_p)
10609 fputs (".global __do_clear_bss\n", asm_out_file);
10613 /* Worker function for `ADJUST_REG_ALLOC_ORDER'. */
10614 /* Choose the order in which to allocate hard registers for
10615 pseudo-registers local to a basic block.
10617 Store the desired register order in the array `reg_alloc_order'.
10618 Element 0 should be the register to allocate first; element 1, the
10619 next register; and so on. */
10621 void
10622 avr_adjust_reg_alloc_order (void)
10624 static const int order_0[] =
10626 24, 25,
10627 18, 19, 20, 21, 22, 23,
10628 30, 31,
10629 26, 27, 28, 29,
10630 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
10631 0, 1,
10632 32, 33, 34, 35
10634 static const int tiny_order_0[] = {
10635 20, 21,
10636 22, 23,
10637 24, 25,
10638 30, 31,
10639 26, 27,
10640 28, 29,
10641 19, 18,
10642 16, 17,
10643 32, 33, 34, 35,
10644 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
10646 static const int order_1[] =
10648 18, 19, 20, 21, 22, 23, 24, 25,
10649 30, 31,
10650 26, 27, 28, 29,
10651 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
10652 0, 1,
10653 32, 33, 34, 35
10655 static const int tiny_order_1[] = {
10656 22, 23,
10657 24, 25,
10658 30, 31,
10659 26, 27,
10660 28, 29,
10661 21, 20, 19, 18,
10662 16, 17,
10663 32, 33, 34, 35,
10664 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
10666 static const int order_2[] =
10668 25, 24, 23, 22, 21, 20, 19, 18,
10669 30, 31,
10670 26, 27, 28, 29,
10671 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
10672 1, 0,
10673 32, 33, 34, 35
10676 /* Select specific register allocation order.
10677 Tiny Core (ATtiny4/5/9/10/20/40) devices have only 16 registers,
10678 so different allocation order should be used. */
10680 const int *order = (TARGET_ORDER_1 ? (AVR_TINY ? tiny_order_1 : order_1)
10681 : TARGET_ORDER_2 ? (AVR_TINY ? tiny_order_0 : order_2)
10682 : (AVR_TINY ? tiny_order_0 : order_0));
10684 for (size_t i = 0; i < ARRAY_SIZE (order_0); ++i)
10685 reg_alloc_order[i] = order[i];
10689 /* Implement `TARGET_REGISTER_MOVE_COST' */
10691 static int
10692 avr_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
10693 reg_class_t from, reg_class_t to)
10695 return (from == STACK_REG ? 6
10696 : to == STACK_REG ? 12
10697 : 2);
10701 /* Implement `TARGET_MEMORY_MOVE_COST' */
10703 static int
10704 avr_memory_move_cost (machine_mode mode,
10705 reg_class_t rclass ATTRIBUTE_UNUSED,
10706 bool in ATTRIBUTE_UNUSED)
10708 return (mode == QImode ? 2
10709 : mode == HImode ? 4
10710 : mode == SImode ? 8
10711 : mode == SFmode ? 8
10712 : 16);
10716 /* Cost for mul highpart. X is a LSHIFTRT, i.e. the outer TRUNCATE is
10717 already stripped off. */
10719 static int
10720 avr_mul_highpart_cost (rtx x, int)
10722 if (AVR_HAVE_MUL
10723 && LSHIFTRT == GET_CODE (x)
10724 && MULT == GET_CODE (XEXP (x, 0))
10725 && CONST_INT_P (XEXP (x, 1)))
10727 // This is the wider mode.
10728 machine_mode mode = GET_MODE (x);
10730 // The middle-end might still have PR81444, i.e. it is calling the cost
10731 // functions with strange modes. Fix this now by also considering
10732 // PSImode (should actually be SImode instead).
10733 if (HImode == mode || PSImode == mode || SImode == mode)
10735 return COSTS_N_INSNS (2);
10739 return 10000;
10743 /* Mutually recursive subroutine of avr_rtx_cost for calculating the
10744 cost of an RTX operand given its context. X is the rtx of the
10745 operand, MODE is its mode, and OUTER is the rtx_code of this
10746 operand's parent operator. */
10748 static int
10749 avr_operand_rtx_cost (rtx x, machine_mode mode, enum rtx_code outer,
10750 int opno, bool speed)
10752 enum rtx_code code = GET_CODE (x);
10753 int total;
10755 switch (code)
10757 case REG:
10758 case SUBREG:
10759 return 0;
10761 case CONST_INT:
10762 case CONST_FIXED:
10763 case CONST_DOUBLE:
10764 return COSTS_N_INSNS (GET_MODE_SIZE (mode));
10766 default:
10767 break;
10770 total = 0;
10771 avr_rtx_costs (x, mode, outer, opno, &total, speed);
10772 return total;
10775 /* Worker function for AVR backend's rtx_cost function.
10776 X is rtx expression whose cost is to be calculated.
10777 Return true if the complete cost has been computed.
10778 Return false if subexpressions should be scanned.
10779 In either case, *TOTAL contains the cost result. */
10781 static bool
10782 avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
10783 int opno ATTRIBUTE_UNUSED, int *total, bool speed)
10785 enum rtx_code code = GET_CODE (x);
10786 HOST_WIDE_INT val;
10788 switch (code)
10790 case CONST_INT:
10791 case CONST_FIXED:
10792 case CONST_DOUBLE:
10793 case SYMBOL_REF:
10794 case CONST:
10795 case LABEL_REF:
10796 /* Immediate constants are as cheap as registers. */
10797 *total = 0;
10798 return true;
10800 case MEM:
10801 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10802 return true;
10804 case NEG:
10805 switch (mode)
10807 case E_QImode:
10808 case E_SFmode:
10809 *total = COSTS_N_INSNS (1);
10810 break;
10812 case E_HImode:
10813 case E_PSImode:
10814 case E_SImode:
10815 *total = COSTS_N_INSNS (2 * GET_MODE_SIZE (mode) - 1);
10816 break;
10818 default:
10819 return false;
10821 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10822 return true;
10824 case ABS:
10825 switch (mode)
10827 case E_QImode:
10828 case E_SFmode:
10829 *total = COSTS_N_INSNS (1);
10830 break;
10832 default:
10833 return false;
10835 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10836 return true;
10838 case NOT:
10839 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10840 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10841 return true;
10843 case ZERO_EXTEND:
10844 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
10845 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
10846 *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
10847 code, 0, speed);
10848 return true;
10850 case SIGN_EXTEND:
10851 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
10852 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
10853 *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
10854 code, 0, speed);
10855 return true;
10857 case PLUS:
10858 switch (mode)
10860 case E_QImode:
10861 if (AVR_HAVE_MUL
10862 && MULT == GET_CODE (XEXP (x, 0))
10863 && register_operand (XEXP (x, 1), QImode))
10865 /* multiply-add */
10866 *total = COSTS_N_INSNS (speed ? 4 : 3);
10867 /* multiply-add with constant: will be split and load constant. */
10868 if (CONST_INT_P (XEXP (XEXP (x, 0), 1)))
10869 *total = COSTS_N_INSNS (1) + *total;
10870 return true;
10872 *total = COSTS_N_INSNS (1);
10873 if (!CONST_INT_P (XEXP (x, 1)))
10874 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10875 break;
10877 case E_HImode:
10878 if (AVR_HAVE_MUL
10879 && (MULT == GET_CODE (XEXP (x, 0))
10880 || ASHIFT == GET_CODE (XEXP (x, 0)))
10881 && register_operand (XEXP (x, 1), HImode)
10882 && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))
10883 || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))))
10885 /* multiply-add */
10886 *total = COSTS_N_INSNS (speed ? 5 : 4);
10887 /* multiply-add with constant: will be split and load constant. */
10888 if (CONST_INT_P (XEXP (XEXP (x, 0), 1)))
10889 *total = COSTS_N_INSNS (1) + *total;
10890 return true;
10892 if (!CONST_INT_P (XEXP (x, 1)))
10894 *total = COSTS_N_INSNS (2);
10895 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10896 speed);
10898 else if (IN_RANGE (INTVAL (XEXP (x, 1)), -63, 63))
10899 *total = COSTS_N_INSNS (1);
10900 else
10901 *total = COSTS_N_INSNS (2);
10902 break;
10904 case E_PSImode:
10905 if (!CONST_INT_P (XEXP (x, 1)))
10907 *total = COSTS_N_INSNS (3);
10908 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10909 speed);
10911 else if (IN_RANGE (INTVAL (XEXP (x, 1)), -63, 63))
10912 *total = COSTS_N_INSNS (2);
10913 else
10914 *total = COSTS_N_INSNS (3);
10915 break;
10917 case E_SImode:
10918 if (!CONST_INT_P (XEXP (x, 1)))
10920 *total = COSTS_N_INSNS (4);
10921 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10922 speed);
10924 else if (IN_RANGE (INTVAL (XEXP (x, 1)), -63, 63))
10925 *total = COSTS_N_INSNS (1);
10926 else
10927 *total = COSTS_N_INSNS (4);
10928 break;
10930 default:
10931 return false;
10933 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10934 return true;
10936 case MINUS:
10937 if (AVR_HAVE_MUL
10938 && QImode == mode
10939 && register_operand (XEXP (x, 0), QImode)
10940 && MULT == GET_CODE (XEXP (x, 1)))
10942 /* multiply-sub */
10943 *total = COSTS_N_INSNS (speed ? 4 : 3);
10944 /* multiply-sub with constant: will be split and load constant. */
10945 if (CONST_INT_P (XEXP (XEXP (x, 1), 1)))
10946 *total = COSTS_N_INSNS (1) + *total;
10947 return true;
10949 if (AVR_HAVE_MUL
10950 && HImode == mode
10951 && register_operand (XEXP (x, 0), HImode)
10952 && (MULT == GET_CODE (XEXP (x, 1))
10953 || ASHIFT == GET_CODE (XEXP (x, 1)))
10954 && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))
10955 || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))))
10957 /* multiply-sub */
10958 *total = COSTS_N_INSNS (speed ? 5 : 4);
10959 /* multiply-sub with constant: will be split and load constant. */
10960 if (CONST_INT_P (XEXP (XEXP (x, 1), 1)))
10961 *total = COSTS_N_INSNS (1) + *total;
10962 return true;
10964 /* FALLTHRU */
10965 case AND:
10966 case IOR:
10967 if (IOR == code
10968 && HImode == mode
10969 && ASHIFT == GET_CODE (XEXP (x, 0)))
10971 *total = COSTS_N_INSNS (2);
10972 // Just a rough estimate. If we see no sign- or zero-extend,
10973 // then increase the cost a little bit.
10974 if (REG_P (XEXP (XEXP (x, 0), 0)))
10975 *total += COSTS_N_INSNS (1);
10976 if (REG_P (XEXP (x, 1)))
10977 *total += COSTS_N_INSNS (1);
10978 return true;
10980 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10981 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10982 if (!CONST_INT_P (XEXP (x, 1)))
10983 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10984 return true;
10986 case XOR:
10987 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10988 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10989 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10990 return true;
10992 case MULT:
10993 switch (mode)
10995 case E_QImode:
10996 if (AVR_HAVE_MUL)
10997 *total = COSTS_N_INSNS (!speed ? 3 : 4);
10998 else if (!speed)
10999 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
11000 else
11001 return false;
11002 break;
11004 case E_HImode:
11005 if (AVR_HAVE_MUL)
11007 rtx op0 = XEXP (x, 0);
11008 rtx op1 = XEXP (x, 1);
11009 enum rtx_code code0 = GET_CODE (op0);
11010 enum rtx_code code1 = GET_CODE (op1);
11011 bool ex0 = SIGN_EXTEND == code0 || ZERO_EXTEND == code0;
11012 bool ex1 = SIGN_EXTEND == code1 || ZERO_EXTEND == code1;
11014 if (ex0
11015 && (u8_operand (op1, HImode)
11016 || s8_operand (op1, HImode)))
11018 *total = COSTS_N_INSNS (!speed ? 4 : 6);
11019 return true;
11021 if (ex0
11022 && register_operand (op1, HImode))
11024 *total = COSTS_N_INSNS (!speed ? 5 : 8);
11025 return true;
11027 else if (ex0 || ex1)
11029 *total = COSTS_N_INSNS (!speed ? 3 : 5);
11030 return true;
11032 else if (register_operand (op0, HImode)
11033 && (u8_operand (op1, HImode)
11034 || s8_operand (op1, HImode)))
11036 *total = COSTS_N_INSNS (!speed ? 6 : 9);
11037 return true;
11039 else
11040 *total = COSTS_N_INSNS (!speed ? 7 : 10);
11042 else if (!speed)
11043 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
11044 else
11045 return false;
11046 break;
11048 case E_PSImode:
11049 if (!speed)
11050 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
11051 else
11052 *total = 10;
11053 break;
11055 case E_SImode:
11056 case E_DImode:
11057 if (AVR_HAVE_MUL)
11059 if (!speed)
11061 /* Add some additional costs besides CALL like moves etc. */
11063 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
11065 else
11067 /* Just a rough estimate. Even with -O2 we don't want bulky
11068 code expanded inline. */
11070 *total = COSTS_N_INSNS (25);
11073 else
11075 if (speed)
11076 *total = COSTS_N_INSNS (300);
11077 else
11078 /* Add some additional costs besides CALL like moves etc. */
11079 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
11082 if (mode == DImode)
11083 *total *= 2;
11085 return true;
11087 default:
11088 return false;
11090 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11091 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
11092 return true;
11094 case DIV:
11095 case MOD:
11096 case UDIV:
11097 case UMOD:
11098 if (!speed)
11099 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
11100 else
11101 *total = COSTS_N_INSNS (15 * GET_MODE_SIZE (mode));
11102 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11103 /* For div/mod with const-int divisor we have at least the cost of
11104 loading the divisor. */
11105 if (CONST_INT_P (XEXP (x, 1)))
11106 *total += COSTS_N_INSNS (GET_MODE_SIZE (mode));
11107 /* Add some overall penaly for clobbering and moving around registers */
11108 *total += COSTS_N_INSNS (2);
11109 return true;
11111 case ROTATE:
11112 switch (mode)
11114 case E_QImode:
11115 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 4)
11116 *total = COSTS_N_INSNS (1);
11118 break;
11120 case E_HImode:
11121 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 8)
11122 *total = COSTS_N_INSNS (3);
11124 break;
11126 case E_SImode:
11127 if (CONST_INT_P (XEXP (x, 1)))
11128 switch (INTVAL (XEXP (x, 1)))
11130 case 8:
11131 case 24:
11132 *total = COSTS_N_INSNS (5);
11133 break;
11134 case 16:
11135 *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 6);
11136 break;
11138 break;
11140 default:
11141 return false;
11143 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11144 return true;
11146 case ASHIFT:
11147 switch (mode)
11149 case E_QImode:
11150 if (!CONST_INT_P (XEXP (x, 1)))
11152 *total = COSTS_N_INSNS (!speed ? 4 : 17);
11153 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11154 speed);
11156 else
11158 val = INTVAL (XEXP (x, 1));
11159 if (val == 7)
11160 *total = COSTS_N_INSNS (3);
11161 else if (val >= 0 && val <= 7)
11162 *total = COSTS_N_INSNS (val);
11163 else
11164 *total = COSTS_N_INSNS (1);
11166 break;
11168 case E_HImode:
11169 if (AVR_HAVE_MUL)
11171 if (const_2_to_7_operand (XEXP (x, 1), HImode)
11172 && (SIGN_EXTEND == GET_CODE (XEXP (x, 0))
11173 || ZERO_EXTEND == GET_CODE (XEXP (x, 0))))
11175 *total = COSTS_N_INSNS (!speed ? 4 : 6);
11176 return true;
11180 if (const1_rtx == (XEXP (x, 1))
11181 && SIGN_EXTEND == GET_CODE (XEXP (x, 0)))
11183 *total = COSTS_N_INSNS (2);
11184 return true;
11187 if (!CONST_INT_P (XEXP (x, 1)))
11189 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11190 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11191 speed);
11193 else
11194 switch (INTVAL (XEXP (x, 1)))
11196 case 0:
11197 *total = 0;
11198 break;
11199 case 1:
11200 case 8:
11201 *total = COSTS_N_INSNS (2);
11202 break;
11203 case 9:
11204 *total = COSTS_N_INSNS (3);
11205 break;
11206 case 2:
11207 case 3:
11208 case 10:
11209 case 15:
11210 *total = COSTS_N_INSNS (4);
11211 break;
11212 case 7:
11213 case 11:
11214 case 12:
11215 *total = COSTS_N_INSNS (5);
11216 break;
11217 case 4:
11218 *total = COSTS_N_INSNS (!speed ? 5 : 8);
11219 break;
11220 case 6:
11221 *total = COSTS_N_INSNS (!speed ? 5 : 9);
11222 break;
11223 case 5:
11224 *total = COSTS_N_INSNS (!speed ? 5 : 10);
11225 break;
11226 default:
11227 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11228 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11229 speed);
11231 break;
11233 case E_PSImode:
11234 if (!CONST_INT_P (XEXP (x, 1)))
11236 *total = COSTS_N_INSNS (!speed ? 6 : 73);
11238 else
11239 switch (INTVAL (XEXP (x, 1)))
11241 case 0:
11242 *total = 0;
11243 break;
11244 case 1:
11245 case 8:
11246 case 16:
11247 *total = COSTS_N_INSNS (3);
11248 break;
11249 case 23:
11250 *total = COSTS_N_INSNS (5);
11251 break;
11252 default:
11253 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
11254 break;
11256 break;
11258 case E_SImode:
11259 if (!CONST_INT_P (XEXP (x, 1)))
11261 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11262 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11263 speed);
11265 else
11266 switch (INTVAL (XEXP (x, 1)))
11268 case 0:
11269 *total = 0;
11270 break;
11271 case 24:
11272 *total = COSTS_N_INSNS (3);
11273 break;
11274 case 1:
11275 case 8:
11276 case 16:
11277 *total = COSTS_N_INSNS (4);
11278 break;
11279 case 31:
11280 *total = COSTS_N_INSNS (6);
11281 break;
11282 case 2:
11283 *total = COSTS_N_INSNS (!speed ? 7 : 8);
11284 break;
11285 default:
11286 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11287 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11288 speed);
11290 break;
11292 default:
11293 return false;
11295 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11296 return true;
11298 case ASHIFTRT:
11299 switch (mode)
11301 case E_QImode:
11302 if (!CONST_INT_P (XEXP (x, 1)))
11304 *total = COSTS_N_INSNS (!speed ? 4 : 17);
11305 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11306 speed);
11308 else
11310 val = INTVAL (XEXP (x, 1));
11311 if (val == 6)
11312 *total = COSTS_N_INSNS (4);
11313 else if (val == 7)
11314 *total = COSTS_N_INSNS (2);
11315 else if (val >= 0 && val <= 7)
11316 *total = COSTS_N_INSNS (val);
11317 else
11318 *total = COSTS_N_INSNS (1);
11320 break;
11322 case E_HImode:
11323 if (!CONST_INT_P (XEXP (x, 1)))
11325 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11326 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11327 speed);
11329 else
11330 switch (INTVAL (XEXP (x, 1)))
11332 case 0:
11333 *total = 0;
11334 break;
11335 case 1:
11336 *total = COSTS_N_INSNS (2);
11337 break;
11338 case 15:
11339 *total = COSTS_N_INSNS (3);
11340 break;
11341 case 2:
11342 case 7:
11343 case 8:
11344 case 9:
11345 *total = COSTS_N_INSNS (4);
11346 break;
11347 case 10:
11348 case 14:
11349 *total = COSTS_N_INSNS (5);
11350 break;
11351 case 11:
11352 *total = COSTS_N_INSNS (!speed ? 5 : 6);
11353 break;
11354 case 12:
11355 *total = COSTS_N_INSNS (!speed ? 5 : 7);
11356 break;
11357 case 6:
11358 case 13:
11359 *total = COSTS_N_INSNS (!speed ? 5 : 8);
11360 break;
11361 default:
11362 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11363 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11364 speed);
11366 break;
11368 case E_PSImode:
11369 if (!CONST_INT_P (XEXP (x, 1)))
11371 *total = COSTS_N_INSNS (!speed ? 6 : 73);
11373 else
11374 switch (INTVAL (XEXP (x, 1)))
11376 case 0:
11377 *total = 0;
11378 break;
11379 case 1:
11380 *total = COSTS_N_INSNS (3);
11381 break;
11382 case 16:
11383 case 8:
11384 *total = COSTS_N_INSNS (5);
11385 break;
11386 case 23:
11387 *total = COSTS_N_INSNS (4);
11388 break;
11389 default:
11390 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
11391 break;
11393 break;
11395 case E_SImode:
11396 if (!CONST_INT_P (XEXP (x, 1)))
11398 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11399 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11400 speed);
11402 else
11403 switch (INTVAL (XEXP (x, 1)))
11405 case 0:
11406 *total = 0;
11407 break;
11408 case 1:
11409 *total = COSTS_N_INSNS (4);
11410 break;
11411 case 8:
11412 case 16:
11413 case 24:
11414 *total = COSTS_N_INSNS (6);
11415 break;
11416 case 2:
11417 *total = COSTS_N_INSNS (!speed ? 7 : 8);
11418 break;
11419 case 31:
11420 *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 5);
11421 break;
11422 default:
11423 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11424 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11425 speed);
11427 break;
11429 default:
11430 return false;
11432 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11433 return true;
11435 case LSHIFTRT:
11436 if (outer_code == TRUNCATE)
11438 *total = avr_mul_highpart_cost (x, speed);
11439 return true;
11442 switch (mode)
11444 case E_QImode:
11445 if (!CONST_INT_P (XEXP (x, 1)))
11447 *total = COSTS_N_INSNS (!speed ? 4 : 17);
11448 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11449 speed);
11451 else
11453 val = INTVAL (XEXP (x, 1));
11454 if (val == 7)
11455 *total = COSTS_N_INSNS (3);
11456 else if (val >= 0 && val <= 7)
11457 *total = COSTS_N_INSNS (val);
11458 else
11459 *total = COSTS_N_INSNS (1);
11461 break;
11463 case E_HImode:
11464 if (!CONST_INT_P (XEXP (x, 1)))
11466 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11467 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11468 speed);
11470 else
11471 switch (INTVAL (XEXP (x, 1)))
11473 case 0:
11474 *total = 0;
11475 break;
11476 case 1:
11477 case 8:
11478 *total = COSTS_N_INSNS (2);
11479 break;
11480 case 9:
11481 *total = COSTS_N_INSNS (3);
11482 break;
11483 case 2:
11484 case 10:
11485 case 15:
11486 *total = COSTS_N_INSNS (4);
11487 break;
11488 case 7:
11489 case 11:
11490 *total = COSTS_N_INSNS (5);
11491 break;
11492 case 3:
11493 case 12:
11494 case 13:
11495 case 14:
11496 *total = COSTS_N_INSNS (!speed ? 5 : 6);
11497 break;
11498 case 4:
11499 *total = COSTS_N_INSNS (!speed ? 5 : 7);
11500 break;
11501 case 5:
11502 case 6:
11503 *total = COSTS_N_INSNS (!speed ? 5 : 9);
11504 break;
11505 default:
11506 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11507 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11508 speed);
11510 break;
11512 case E_PSImode:
11513 if (!CONST_INT_P (XEXP (x, 1)))
11515 *total = COSTS_N_INSNS (!speed ? 6 : 73);
11517 else
11518 switch (INTVAL (XEXP (x, 1)))
11520 case 0:
11521 *total = 0;
11522 break;
11523 case 1:
11524 case 8:
11525 case 16:
11526 *total = COSTS_N_INSNS (3);
11527 break;
11528 case 23:
11529 *total = COSTS_N_INSNS (5);
11530 break;
11531 default:
11532 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
11533 break;
11535 break;
11537 case E_SImode:
11538 if (!CONST_INT_P (XEXP (x, 1)))
11540 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11541 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11542 speed);
11544 else
11545 switch (INTVAL (XEXP (x, 1)))
11547 case 0:
11548 *total = 0;
11549 break;
11550 case 1:
11551 *total = COSTS_N_INSNS (4);
11552 break;
11553 case 2:
11554 *total = COSTS_N_INSNS (!speed ? 7 : 8);
11555 break;
11556 case 8:
11557 case 16:
11558 case 24:
11559 *total = COSTS_N_INSNS (4);
11560 break;
11561 case 31:
11562 *total = COSTS_N_INSNS (6);
11563 break;
11564 default:
11565 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11566 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11567 speed);
11569 break;
11571 default:
11572 return false;
11574 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11575 return true;
11577 case COMPARE:
11578 switch (GET_MODE (XEXP (x, 0)))
11580 case E_QImode:
11581 *total = COSTS_N_INSNS (1);
11582 if (!CONST_INT_P (XEXP (x, 1)))
11583 *total += avr_operand_rtx_cost (XEXP (x, 1), QImode, code,
11584 1, speed);
11585 break;
11587 case E_HImode:
11588 *total = COSTS_N_INSNS (2);
11589 if (!CONST_INT_P (XEXP (x, 1)))
11590 *total += avr_operand_rtx_cost (XEXP (x, 1), HImode, code,
11591 1, speed);
11592 else if (INTVAL (XEXP (x, 1)) != 0)
11593 *total += COSTS_N_INSNS (1);
11594 break;
11596 case E_PSImode:
11597 *total = COSTS_N_INSNS (3);
11598 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) != 0)
11599 *total += COSTS_N_INSNS (2);
11600 break;
11602 case E_SImode:
11603 *total = COSTS_N_INSNS (4);
11604 if (!CONST_INT_P (XEXP (x, 1)))
11605 *total += avr_operand_rtx_cost (XEXP (x, 1), SImode, code,
11606 1, speed);
11607 else if (INTVAL (XEXP (x, 1)) != 0)
11608 *total += COSTS_N_INSNS (3);
11609 break;
11611 default:
11612 return false;
11614 *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
11615 code, 0, speed);
11616 return true;
11618 case TRUNCATE:
11619 if (LSHIFTRT == GET_CODE (XEXP (x, 0)))
11621 *total = avr_mul_highpart_cost (XEXP (x, 0), speed);
11622 return true;
11624 break;
11626 default:
11627 break;
11629 return false;
11633 /* Implement `TARGET_RTX_COSTS'. */
11635 static bool
11636 avr_rtx_costs (rtx x, machine_mode mode, int outer_code,
11637 int opno, int *total, bool speed)
11639 bool done = avr_rtx_costs_1 (x, mode, outer_code, opno, total, speed);
11641 if (avr_log.rtx_costs)
11643 avr_edump ("\n%?=%b (%s) total=%d, outer=%C:\n%r\n",
11644 done, speed ? "speed" : "size", *total, outer_code, x);
11647 return done;
11651 /* Implement `TARGET_ADDRESS_COST'. */
11653 static int
11654 avr_address_cost (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
11655 addr_space_t as ATTRIBUTE_UNUSED,
11656 bool speed ATTRIBUTE_UNUSED)
11658 int cost = 4;
11660 if (GET_CODE (x) == PLUS
11661 && CONST_INT_P (XEXP (x, 1))
11662 && (REG_P (XEXP (x, 0))
11663 || SUBREG_P (XEXP (x, 0))))
11665 if (INTVAL (XEXP (x, 1)) > MAX_LD_OFFSET(mode))
11666 cost = 18;
11668 else if (CONSTANT_ADDRESS_P (x))
11670 if (io_address_operand (x, QImode))
11671 cost = 2;
11673 if (AVR_TINY
11674 && avr_address_tiny_absdata_p (x, QImode))
11675 cost = 2;
11678 if (avr_log.address_cost)
11679 avr_edump ("\n%?: %d = %r\n", cost, x);
11681 return cost;
11684 /* Test for extra memory constraint 'Q'.
11685 It's a memory address based on Y or Z pointer with valid displacement. */
11688 extra_constraint_Q (rtx x)
11690 int ok = 0;
11691 rtx plus = XEXP (x, 0);
11693 if (GET_CODE (plus) == PLUS
11694 && REG_P (XEXP (plus, 0))
11695 && CONST_INT_P (XEXP (plus, 1))
11696 && (INTVAL (XEXP (plus, 1))
11697 <= MAX_LD_OFFSET (GET_MODE (x))))
11699 rtx xx = XEXP (plus, 0);
11700 int regno = REGNO (xx);
11702 ok = (/* allocate pseudos */
11703 regno >= FIRST_PSEUDO_REGISTER
11704 /* strictly check */
11705 || regno == REG_Z || regno == REG_Y
11706 /* XXX frame & arg pointer checks */
11707 || xx == frame_pointer_rtx
11708 || xx == arg_pointer_rtx);
11710 if (avr_log.constraints)
11711 avr_edump ("\n%?=%d reload_completed=%d reload_in_progress=%d\n %r\n",
11712 ok, reload_completed, reload_in_progress, x);
11715 return ok;
11718 /* Convert condition code CONDITION to the valid AVR condition code. */
11720 RTX_CODE
11721 avr_normalize_condition (RTX_CODE condition)
11723 switch (condition)
11725 case GT:
11726 return GE;
11727 case GTU:
11728 return GEU;
11729 case LE:
11730 return LT;
11731 case LEU:
11732 return LTU;
11733 default:
11734 gcc_unreachable ();
11738 /* Helper function for `avr_reorg'. */
11740 static rtx
11741 avr_compare_pattern (rtx_insn *insn)
11743 rtx pattern = single_set (insn);
11745 if (pattern
11746 && NONJUMP_INSN_P (insn)
11747 && SET_DEST (pattern) == cc0_rtx
11748 && GET_CODE (SET_SRC (pattern)) == COMPARE)
11750 machine_mode mode0 = GET_MODE (XEXP (SET_SRC (pattern), 0));
11751 machine_mode mode1 = GET_MODE (XEXP (SET_SRC (pattern), 1));
11753 /* The 64-bit comparisons have fixed operands ACC_A and ACC_B.
11754 They must not be swapped, thus skip them. */
11756 if ((mode0 == VOIDmode || GET_MODE_SIZE (mode0) <= 4)
11757 && (mode1 == VOIDmode || GET_MODE_SIZE (mode1) <= 4))
11758 return pattern;
11761 return NULL_RTX;
11764 /* Helper function for `avr_reorg'. */
11766 /* Expansion of switch/case decision trees leads to code like
11768 cc0 = compare (Reg, Num)
11769 if (cc0 == 0)
11770 goto L1
11772 cc0 = compare (Reg, Num)
11773 if (cc0 > 0)
11774 goto L2
11776 The second comparison is superfluous and can be deleted.
11777 The second jump condition can be transformed from a
11778 "difficult" one to a "simple" one because "cc0 > 0" and
11779 "cc0 >= 0" will have the same effect here.
11781 This function relies on the way switch/case is being expaned
11782 as binary decision tree. For example code see PR 49903.
11784 Return TRUE if optimization performed.
11785 Return FALSE if nothing changed.
11787 INSN1 is a comparison, i.e. avr_compare_pattern != 0.
11789 We don't want to do this in text peephole because it is
11790 tedious to work out jump offsets there and the second comparison
11791 might have been transormed by `avr_reorg'.
11793 RTL peephole won't do because peephole2 does not scan across
11794 basic blocks. */
11796 static bool
11797 avr_reorg_remove_redundant_compare (rtx_insn *insn1)
11799 rtx comp1, ifelse1, xcond1;
11800 rtx_insn *branch1;
11801 rtx comp2, ifelse2, xcond2;
11802 rtx_insn *branch2, *insn2;
11803 enum rtx_code code;
11804 rtx_insn *jump;
11805 rtx target, cond;
11807 /* Look out for: compare1 - branch1 - compare2 - branch2 */
11809 branch1 = next_nonnote_nondebug_insn (insn1);
11810 if (!branch1 || !JUMP_P (branch1))
11811 return false;
11813 insn2 = next_nonnote_nondebug_insn (branch1);
11814 if (!insn2 || !avr_compare_pattern (insn2))
11815 return false;
11817 branch2 = next_nonnote_nondebug_insn (insn2);
11818 if (!branch2 || !JUMP_P (branch2))
11819 return false;
11821 comp1 = avr_compare_pattern (insn1);
11822 comp2 = avr_compare_pattern (insn2);
11823 xcond1 = single_set (branch1);
11824 xcond2 = single_set (branch2);
11826 if (!comp1 || !comp2
11827 || !rtx_equal_p (comp1, comp2)
11828 || !xcond1 || SET_DEST (xcond1) != pc_rtx
11829 || !xcond2 || SET_DEST (xcond2) != pc_rtx
11830 || IF_THEN_ELSE != GET_CODE (SET_SRC (xcond1))
11831 || IF_THEN_ELSE != GET_CODE (SET_SRC (xcond2)))
11833 return false;
11836 comp1 = SET_SRC (comp1);
11837 ifelse1 = SET_SRC (xcond1);
11838 ifelse2 = SET_SRC (xcond2);
11840 /* comp<n> is COMPARE now and ifelse<n> is IF_THEN_ELSE. */
11842 if (EQ != GET_CODE (XEXP (ifelse1, 0))
11843 || !REG_P (XEXP (comp1, 0))
11844 || !CONST_INT_P (XEXP (comp1, 1))
11845 || XEXP (ifelse1, 2) != pc_rtx
11846 || XEXP (ifelse2, 2) != pc_rtx
11847 || LABEL_REF != GET_CODE (XEXP (ifelse1, 1))
11848 || LABEL_REF != GET_CODE (XEXP (ifelse2, 1))
11849 || !COMPARISON_P (XEXP (ifelse2, 0))
11850 || cc0_rtx != XEXP (XEXP (ifelse1, 0), 0)
11851 || cc0_rtx != XEXP (XEXP (ifelse2, 0), 0)
11852 || const0_rtx != XEXP (XEXP (ifelse1, 0), 1)
11853 || const0_rtx != XEXP (XEXP (ifelse2, 0), 1))
11855 return false;
11858 /* We filtered the insn sequence to look like
11860 (set (cc0)
11861 (compare (reg:M N)
11862 (const_int VAL)))
11863 (set (pc)
11864 (if_then_else (eq (cc0)
11865 (const_int 0))
11866 (label_ref L1)
11867 (pc)))
11869 (set (cc0)
11870 (compare (reg:M N)
11871 (const_int VAL)))
11872 (set (pc)
11873 (if_then_else (CODE (cc0)
11874 (const_int 0))
11875 (label_ref L2)
11876 (pc)))
11879 code = GET_CODE (XEXP (ifelse2, 0));
11881 /* Map GT/GTU to GE/GEU which is easier for AVR.
11882 The first two instructions compare/branch on EQ
11883 so we may replace the difficult
11885 if (x == VAL) goto L1;
11886 if (x > VAL) goto L2;
11888 with easy
11890 if (x == VAL) goto L1;
11891 if (x >= VAL) goto L2;
11893 Similarly, replace LE/LEU by LT/LTU. */
11895 switch (code)
11897 case EQ:
11898 case LT: case LTU:
11899 case GE: case GEU:
11900 break;
11902 case LE: case LEU:
11903 case GT: case GTU:
11904 code = avr_normalize_condition (code);
11905 break;
11907 default:
11908 return false;
11911 /* Wrap the branches into UNSPECs so they won't be changed or
11912 optimized in the remainder. */
11914 target = XEXP (XEXP (ifelse1, 1), 0);
11915 cond = XEXP (ifelse1, 0);
11916 jump = emit_jump_insn_after (gen_branch_unspec (target, cond), insn1);
11918 JUMP_LABEL (jump) = JUMP_LABEL (branch1);
11920 target = XEXP (XEXP (ifelse2, 1), 0);
11921 cond = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
11922 jump = emit_jump_insn_after (gen_branch_unspec (target, cond), insn2);
11924 JUMP_LABEL (jump) = JUMP_LABEL (branch2);
11926 /* The comparisons in insn1 and insn2 are exactly the same;
11927 insn2 is superfluous so delete it. */
11929 delete_insn (insn2);
11930 delete_insn (branch1);
11931 delete_insn (branch2);
11933 return true;
11937 /* Implement `TARGET_MACHINE_DEPENDENT_REORG'. */
11938 /* Optimize conditional jumps. */
11940 static void
11941 avr_reorg (void)
11943 rtx_insn *insn = get_insns();
11945 for (insn = next_real_insn (insn); insn; insn = next_real_insn (insn))
11947 rtx pattern = avr_compare_pattern (insn);
11949 if (!pattern)
11950 continue;
11952 if (optimize
11953 && avr_reorg_remove_redundant_compare (insn))
11955 continue;
11958 if (compare_diff_p (insn))
11960 /* Now we work under compare insn with difficult branch. */
11962 rtx_insn *next = next_real_insn (insn);
11963 rtx pat = PATTERN (next);
11965 pattern = SET_SRC (pattern);
11967 if (true_regnum (XEXP (pattern, 0)) >= 0
11968 && true_regnum (XEXP (pattern, 1)) >= 0)
11970 rtx x = XEXP (pattern, 0);
11971 rtx src = SET_SRC (pat);
11972 rtx t = XEXP (src, 0);
11973 PUT_CODE (t, swap_condition (GET_CODE (t)));
11974 XEXP (pattern, 0) = XEXP (pattern, 1);
11975 XEXP (pattern, 1) = x;
11976 INSN_CODE (next) = -1;
11978 else if (true_regnum (XEXP (pattern, 0)) >= 0
11979 && XEXP (pattern, 1) == const0_rtx)
11981 /* This is a tst insn, we can reverse it. */
11982 rtx src = SET_SRC (pat);
11983 rtx t = XEXP (src, 0);
11985 PUT_CODE (t, swap_condition (GET_CODE (t)));
11986 XEXP (pattern, 1) = XEXP (pattern, 0);
11987 XEXP (pattern, 0) = const0_rtx;
11988 INSN_CODE (next) = -1;
11989 INSN_CODE (insn) = -1;
11991 else if (true_regnum (XEXP (pattern, 0)) >= 0
11992 && CONST_INT_P (XEXP (pattern, 1)))
11994 rtx x = XEXP (pattern, 1);
11995 rtx src = SET_SRC (pat);
11996 rtx t = XEXP (src, 0);
11997 machine_mode mode = GET_MODE (XEXP (pattern, 0));
11999 if (avr_simplify_comparison_p (mode, GET_CODE (t), x))
12001 XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
12002 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
12003 INSN_CODE (next) = -1;
12004 INSN_CODE (insn) = -1;
12011 /* Returns register number for function return value.*/
12013 static inline unsigned int
12014 avr_ret_register (void)
12016 return 24;
12020 /* Implement `TARGET_FUNCTION_VALUE_REGNO_P'. */
12022 static bool
12023 avr_function_value_regno_p (const unsigned int regno)
12025 return (regno == avr_ret_register ());
12029 /* Implement `TARGET_LIBCALL_VALUE'. */
12030 /* Create an RTX representing the place where a
12031 library function returns a value of mode MODE. */
12033 static rtx
12034 avr_libcall_value (machine_mode mode,
12035 const_rtx func ATTRIBUTE_UNUSED)
12037 int offs = GET_MODE_SIZE (mode);
12039 if (offs <= 4)
12040 offs = (offs + 1) & ~1;
12042 return gen_rtx_REG (mode, avr_ret_register () + 2 - offs);
12046 /* Implement `TARGET_FUNCTION_VALUE'. */
12047 /* Create an RTX representing the place where a
12048 function returns a value of data type VALTYPE. */
12050 static rtx
12051 avr_function_value (const_tree type,
12052 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
12053 bool outgoing ATTRIBUTE_UNUSED)
12055 unsigned int offs;
12057 if (TYPE_MODE (type) != BLKmode)
12058 return avr_libcall_value (TYPE_MODE (type), NULL_RTX);
12060 offs = int_size_in_bytes (type);
12061 if (offs < 2)
12062 offs = 2;
12063 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
12064 offs = GET_MODE_SIZE (SImode);
12065 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
12066 offs = GET_MODE_SIZE (DImode);
12068 return gen_rtx_REG (BLKmode, avr_ret_register () + 2 - offs);
12072 test_hard_reg_class (enum reg_class rclass, rtx x)
12074 int regno = true_regnum (x);
12075 if (regno < 0)
12076 return 0;
12078 if (TEST_HARD_REG_CLASS (rclass, regno))
12079 return 1;
12081 return 0;
12085 /* Helper for jump_over_one_insn_p: Test if INSN is a 2-word instruction
12086 and thus is suitable to be skipped by CPSE, SBRC, etc. */
12088 static bool
12089 avr_2word_insn_p (rtx_insn *insn)
12091 if (TARGET_SKIP_BUG || !insn || get_attr_length (insn) != 2)
12093 return false;
12096 switch (INSN_CODE (insn))
12098 default:
12099 return false;
12101 case CODE_FOR_movqi_insn:
12102 case CODE_FOR_movuqq_insn:
12103 case CODE_FOR_movqq_insn:
12105 rtx set = single_set (insn);
12106 rtx src = SET_SRC (set);
12107 rtx dest = SET_DEST (set);
12109 /* Factor out LDS and STS from movqi_insn. */
12111 if (MEM_P (dest)
12112 && (REG_P (src) || src == CONST0_RTX (GET_MODE (dest))))
12114 return CONSTANT_ADDRESS_P (XEXP (dest, 0));
12116 else if (REG_P (dest)
12117 && MEM_P (src))
12119 return CONSTANT_ADDRESS_P (XEXP (src, 0));
12122 return false;
12125 case CODE_FOR_call_insn:
12126 case CODE_FOR_call_value_insn:
12127 return true;
12133 jump_over_one_insn_p (rtx_insn *insn, rtx dest)
12135 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
12136 ? XEXP (dest, 0)
12137 : dest);
12138 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
12139 int dest_addr = INSN_ADDRESSES (uid);
12140 int jump_offset = dest_addr - jump_addr - get_attr_length (insn);
12142 return (jump_offset == 1
12143 || (jump_offset == 2
12144 && avr_2word_insn_p (next_active_insn (insn))));
12148 /* Implement TARGET_HARD_REGNO_MODE_OK. On the enhanced core, anything
12149 larger than 1 byte must start in even numbered register for "movw" to
12150 work (this way we don't have to check for odd registers everywhere). */
12152 static bool
12153 avr_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
12155 /* NOTE: 8-bit values must not be disallowed for R28 or R29.
12156 Disallowing QI et al. in these regs might lead to code like
12157 (set (subreg:QI (reg:HI 28) n) ...)
12158 which will result in wrong code because reload does not
12159 handle SUBREGs of hard regsisters like this.
12160 This could be fixed in reload. However, it appears
12161 that fixing reload is not wanted by reload people. */
12163 /* Any GENERAL_REGS register can hold 8-bit values. */
12165 if (GET_MODE_SIZE (mode) == 1)
12166 return true;
12168 /* FIXME: Ideally, the following test is not needed.
12169 However, it turned out that it can reduce the number
12170 of spill fails. AVR and it's poor endowment with
12171 address registers is extreme stress test for reload. */
12173 if (GET_MODE_SIZE (mode) >= 4
12174 && regno >= REG_X)
12175 return false;
12177 /* All modes larger than 8 bits should start in an even register. */
12179 return !(regno & 1);
12183 /* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED. */
12185 static bool
12186 avr_hard_regno_call_part_clobbered (unsigned regno, machine_mode mode)
12188 /* FIXME: This hook gets called with MODE:REGNO combinations that don't
12189 represent valid hard registers like, e.g. HI:29. Returning TRUE
12190 for such registers can lead to performance degradation as mentioned
12191 in PR53595. Thus, report invalid hard registers as FALSE. */
12193 if (!avr_hard_regno_mode_ok (regno, mode))
12194 return 0;
12196 /* Return true if any of the following boundaries is crossed:
12197 17/18 or 19/20 (if AVR_TINY), 27/28 and 29/30. */
12199 return ((regno <= LAST_CALLEE_SAVED_REG
12200 && regno + GET_MODE_SIZE (mode) > 1 + LAST_CALLEE_SAVED_REG)
12201 || (regno < REG_Y && regno + GET_MODE_SIZE (mode) > REG_Y)
12202 || (regno < REG_Z && regno + GET_MODE_SIZE (mode) > REG_Z));
12206 /* Implement `MODE_CODE_BASE_REG_CLASS'. */
12208 enum reg_class
12209 avr_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED,
12210 addr_space_t as, RTX_CODE outer_code,
12211 RTX_CODE index_code ATTRIBUTE_UNUSED)
12213 if (!ADDR_SPACE_GENERIC_P (as))
12215 return POINTER_Z_REGS;
12218 if (!avr_strict_X)
12219 return reload_completed ? BASE_POINTER_REGS : POINTER_REGS;
12221 return PLUS == outer_code ? BASE_POINTER_REGS : POINTER_REGS;
12225 /* Implement `REGNO_MODE_CODE_OK_FOR_BASE_P'. */
12227 bool
12228 avr_regno_mode_code_ok_for_base_p (int regno,
12229 machine_mode mode ATTRIBUTE_UNUSED,
12230 addr_space_t as ATTRIBUTE_UNUSED,
12231 RTX_CODE outer_code,
12232 RTX_CODE index_code ATTRIBUTE_UNUSED)
12234 bool ok = false;
12236 if (!ADDR_SPACE_GENERIC_P (as))
12238 if (regno < FIRST_PSEUDO_REGISTER
12239 && regno == REG_Z)
12241 return true;
12244 if (reg_renumber)
12246 regno = reg_renumber[regno];
12248 if (regno == REG_Z)
12250 return true;
12254 return false;
12257 if (regno < FIRST_PSEUDO_REGISTER
12258 && (regno == REG_X
12259 || regno == REG_Y
12260 || regno == REG_Z
12261 || regno == ARG_POINTER_REGNUM))
12263 ok = true;
12265 else if (reg_renumber)
12267 regno = reg_renumber[regno];
12269 if (regno == REG_X
12270 || regno == REG_Y
12271 || regno == REG_Z
12272 || regno == ARG_POINTER_REGNUM)
12274 ok = true;
12278 if (avr_strict_X
12279 && PLUS == outer_code
12280 && regno == REG_X)
12282 ok = false;
12285 return ok;
12289 /* A helper for `output_reload_insisf' and `output_reload_inhi'. */
12290 /* Set 32-bit register OP[0] to compile-time constant OP[1].
12291 CLOBBER_REG is a QI clobber register or NULL_RTX.
12292 LEN == NULL: output instructions.
12293 LEN != NULL: set *LEN to the length of the instruction sequence
12294 (in words) printed with LEN = NULL.
12295 If CLEAR_P is true, OP[0] had been cleard to Zero already.
12296 If CLEAR_P is false, nothing is known about OP[0].
12298 The effect on cc0 is as follows:
12300 Load 0 to any register except ZERO_REG : NONE
12301 Load ld register with any value : NONE
12302 Anything else: : CLOBBER */
12304 static void
12305 output_reload_in_const (rtx *op, rtx clobber_reg, int *len, bool clear_p)
12307 rtx src = op[1];
12308 rtx dest = op[0];
12309 rtx xval, xdest[4];
12310 int ival[4];
12311 int clobber_val = 1234;
12312 bool cooked_clobber_p = false;
12313 bool set_p = false;
12314 machine_mode mode = GET_MODE (dest);
12315 int n_bytes = GET_MODE_SIZE (mode);
12317 gcc_assert (REG_P (dest)
12318 && CONSTANT_P (src));
12320 if (len)
12321 *len = 0;
12323 /* (REG:SI 14) is special: It's neither in LD_REGS nor in NO_LD_REGS
12324 but has some subregs that are in LD_REGS. Use the MSB (REG:QI 17). */
12326 if (REGNO (dest) < 16
12327 && REGNO (dest) + GET_MODE_SIZE (mode) > 16)
12329 clobber_reg = all_regs_rtx[REGNO (dest) + n_bytes - 1];
12332 /* We might need a clobber reg but don't have one. Look at the value to
12333 be loaded more closely. A clobber is only needed if it is a symbol
12334 or contains a byte that is neither 0, -1 or a power of 2. */
12336 if (NULL_RTX == clobber_reg
12337 && !test_hard_reg_class (LD_REGS, dest)
12338 && (! (CONST_INT_P (src) || CONST_FIXED_P (src) || CONST_DOUBLE_P (src))
12339 || !avr_popcount_each_byte (src, n_bytes,
12340 (1 << 0) | (1 << 1) | (1 << 8))))
12342 /* We have no clobber register but need one. Cook one up.
12343 That's cheaper than loading from constant pool. */
12345 cooked_clobber_p = true;
12346 clobber_reg = all_regs_rtx[REG_Z + 1];
12347 avr_asm_len ("mov __tmp_reg__,%0", &clobber_reg, len, 1);
12350 /* Now start filling DEST from LSB to MSB. */
12352 for (int n = 0; n < n_bytes; n++)
12354 int ldreg_p;
12355 bool done_byte = false;
12356 rtx xop[3];
12358 /* Crop the n-th destination byte. */
12360 xdest[n] = simplify_gen_subreg (QImode, dest, mode, n);
12361 ldreg_p = test_hard_reg_class (LD_REGS, xdest[n]);
12363 if (!CONST_INT_P (src)
12364 && !CONST_FIXED_P (src)
12365 && !CONST_DOUBLE_P (src))
12367 static const char* const asm_code[][2] =
12369 { "ldi %2,lo8(%1)" CR_TAB "mov %0,%2", "ldi %0,lo8(%1)" },
12370 { "ldi %2,hi8(%1)" CR_TAB "mov %0,%2", "ldi %0,hi8(%1)" },
12371 { "ldi %2,hlo8(%1)" CR_TAB "mov %0,%2", "ldi %0,hlo8(%1)" },
12372 { "ldi %2,hhi8(%1)" CR_TAB "mov %0,%2", "ldi %0,hhi8(%1)" }
12375 xop[0] = xdest[n];
12376 xop[1] = src;
12377 xop[2] = clobber_reg;
12379 avr_asm_len (asm_code[n][ldreg_p], xop, len, ldreg_p ? 1 : 2);
12381 continue;
12384 /* Crop the n-th source byte. */
12386 xval = simplify_gen_subreg (QImode, src, mode, n);
12387 ival[n] = INTVAL (xval);
12389 /* Look if we can reuse the low word by means of MOVW. */
12391 if (n == 2
12392 && n_bytes >= 4
12393 && AVR_HAVE_MOVW)
12395 rtx lo16 = simplify_gen_subreg (HImode, src, mode, 0);
12396 rtx hi16 = simplify_gen_subreg (HImode, src, mode, 2);
12398 if (INTVAL (lo16) == INTVAL (hi16))
12400 if (INTVAL (lo16) != 0 || !clear_p)
12401 avr_asm_len ("movw %C0,%A0", &op[0], len, 1);
12403 break;
12407 /* Don't use CLR so that cc0 is set as expected. */
12409 if (ival[n] == 0)
12411 if (!clear_p)
12412 avr_asm_len (ldreg_p ? "ldi %0,0"
12413 : AVR_ZERO_REGNO == REGNO (xdest[n]) ? "clr %0"
12414 : "mov %0,__zero_reg__",
12415 &xdest[n], len, 1);
12416 continue;
12419 if (clobber_val == ival[n]
12420 && REGNO (clobber_reg) == REGNO (xdest[n]))
12422 continue;
12425 /* LD_REGS can use LDI to move a constant value */
12427 if (ldreg_p)
12429 xop[0] = xdest[n];
12430 xop[1] = xval;
12431 avr_asm_len ("ldi %0,lo8(%1)", xop, len, 1);
12432 continue;
12435 /* Try to reuse value already loaded in some lower byte. */
12437 for (int j = 0; j < n; j++)
12438 if (ival[j] == ival[n])
12440 xop[0] = xdest[n];
12441 xop[1] = xdest[j];
12443 avr_asm_len ("mov %0,%1", xop, len, 1);
12444 done_byte = true;
12445 break;
12448 if (done_byte)
12449 continue;
12451 /* Need no clobber reg for -1: Use CLR/DEC */
12453 if (ival[n] == -1)
12455 if (!clear_p)
12456 avr_asm_len ("clr %0", &xdest[n], len, 1);
12458 avr_asm_len ("dec %0", &xdest[n], len, 1);
12459 continue;
12461 else if (ival[n] == 1)
12463 if (!clear_p)
12464 avr_asm_len ("clr %0", &xdest[n], len, 1);
12466 avr_asm_len ("inc %0", &xdest[n], len, 1);
12467 continue;
12470 /* Use T flag or INC to manage powers of 2 if we have
12471 no clobber reg. */
12473 if (NULL_RTX == clobber_reg
12474 && single_one_operand (xval, QImode))
12476 xop[0] = xdest[n];
12477 xop[1] = GEN_INT (exact_log2 (ival[n] & GET_MODE_MASK (QImode)));
12479 gcc_assert (constm1_rtx != xop[1]);
12481 if (!set_p)
12483 set_p = true;
12484 avr_asm_len ("set", xop, len, 1);
12487 if (!clear_p)
12488 avr_asm_len ("clr %0", xop, len, 1);
12490 avr_asm_len ("bld %0,%1", xop, len, 1);
12491 continue;
12494 /* We actually need the LD_REGS clobber reg. */
12496 gcc_assert (NULL_RTX != clobber_reg);
12498 xop[0] = xdest[n];
12499 xop[1] = xval;
12500 xop[2] = clobber_reg;
12501 clobber_val = ival[n];
12503 avr_asm_len ("ldi %2,lo8(%1)" CR_TAB
12504 "mov %0,%2", xop, len, 2);
12507 /* If we cooked up a clobber reg above, restore it. */
12509 if (cooked_clobber_p)
12511 avr_asm_len ("mov %0,__tmp_reg__", &clobber_reg, len, 1);
12516 /* Reload the constant OP[1] into the HI register OP[0].
12517 CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
12518 into a NO_LD_REGS register. If CLOBBER_REG is NULL_RTX we either don't
12519 need a clobber reg or have to cook one up.
12521 PLEN == NULL: Output instructions.
12522 PLEN != NULL: Output nothing. Set *PLEN to number of words occupied
12523 by the insns printed.
12525 Return "". */
12527 const char*
12528 output_reload_inhi (rtx *op, rtx clobber_reg, int *plen)
12530 output_reload_in_const (op, clobber_reg, plen, false);
12531 return "";
12535 /* Reload a SI or SF compile time constant OP[1] into the register OP[0].
12536 CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
12537 into a NO_LD_REGS register. If CLOBBER_REG is NULL_RTX we either don't
12538 need a clobber reg or have to cook one up.
12540 LEN == NULL: Output instructions.
12542 LEN != NULL: Output nothing. Set *LEN to number of words occupied
12543 by the insns printed.
12545 Return "". */
12547 const char *
12548 output_reload_insisf (rtx *op, rtx clobber_reg, int *len)
12550 if (AVR_HAVE_MOVW
12551 && !test_hard_reg_class (LD_REGS, op[0])
12552 && (CONST_INT_P (op[1])
12553 || CONST_FIXED_P (op[1])
12554 || CONST_DOUBLE_P (op[1])))
12556 int len_clr, len_noclr;
12558 /* In some cases it is better to clear the destination beforehand, e.g.
12560 CLR R2 CLR R3 MOVW R4,R2 INC R2
12562 is shorther than
12564 CLR R2 INC R2 CLR R3 CLR R4 CLR R5
12566 We find it too tedious to work that out in the print function.
12567 Instead, we call the print function twice to get the lengths of
12568 both methods and use the shortest one. */
12570 output_reload_in_const (op, clobber_reg, &len_clr, true);
12571 output_reload_in_const (op, clobber_reg, &len_noclr, false);
12573 if (len_noclr - len_clr == 4)
12575 /* Default needs 4 CLR instructions: clear register beforehand. */
12577 avr_asm_len ("mov %A0,__zero_reg__" CR_TAB
12578 "mov %B0,__zero_reg__" CR_TAB
12579 "movw %C0,%A0", &op[0], len, 3);
12581 output_reload_in_const (op, clobber_reg, len, true);
12583 if (len)
12584 *len += 3;
12586 return "";
12590 /* Default: destination not pre-cleared. */
12592 output_reload_in_const (op, clobber_reg, len, false);
12593 return "";
12596 const char*
12597 avr_out_reload_inpsi (rtx *op, rtx clobber_reg, int *len)
12599 output_reload_in_const (op, clobber_reg, len, false);
12600 return "";
12604 /* Worker function for `ASM_OUTPUT_ADDR_VEC'. */
12605 /* Emit jump tables out-of-line so that branches crossing the table
12606 get shorter offsets. If we have JUMP + CALL, then put the tables
12607 in a dedicated non-.text section so that CALLs get better chance to
12608 be relaxed to RCALLs.
12610 We emit the tables by hand because `function_rodata_section' does not
12611 work as expected, cf. PR71151, and we do *NOT* want the table to be
12612 in .rodata, hence setting JUMP_TABLES_IN_TEXT_SECTION = 0 is of limited
12613 use; and setting it to 1 attributes table lengths to branch offsets...
12614 Moreover, fincal.c keeps switching section before each table entry
12615 which we find too fragile as to rely on section caching. */
12617 void
12618 avr_output_addr_vec (rtx_insn *labl, rtx table)
12620 FILE *stream = asm_out_file;
12622 app_disable();
12624 // Switch to appropriate (sub)section.
12626 if (DECL_SECTION_NAME (current_function_decl)
12627 && symtab_node::get (current_function_decl)
12628 && ! symtab_node::get (current_function_decl)->implicit_section)
12630 // .subsection will emit the code after the function and in the
12631 // section as chosen by the user.
12633 switch_to_section (current_function_section ());
12634 fprintf (stream, "\t.subsection\t1\n");
12636 else
12638 // Since PR63223 there is no restriction where to put the table; it
12639 // may even reside above 128 KiB. We put it in a section as high as
12640 // possible and avoid progmem in order not to waste flash <= 64 KiB.
12642 const char *sec_name = ".jumptables.gcc";
12644 // The table belongs to its host function, therefore use fine
12645 // grained sections so that, if that function is removed by
12646 // --gc-sections, the child table(s) may also be removed. */
12648 tree asm_name = DECL_ASSEMBLER_NAME (current_function_decl);
12649 const char *fname = IDENTIFIER_POINTER (asm_name);
12650 fname = targetm.strip_name_encoding (fname);
12651 sec_name = ACONCAT ((sec_name, ".", fname, NULL));
12653 fprintf (stream, "\t.section\t%s,\"%s\",@progbits\n", sec_name,
12654 AVR_HAVE_JMP_CALL ? "a" : "ax");
12657 // Output the label that preceeds the table.
12659 ASM_OUTPUT_ALIGN (stream, 1);
12660 targetm.asm_out.internal_label (stream, "L", CODE_LABEL_NUMBER (labl));
12662 // Output the table's content.
12664 int vlen = XVECLEN (table, 0);
12666 for (int idx = 0; idx < vlen; idx++)
12668 int value = CODE_LABEL_NUMBER (XEXP (XVECEXP (table, 0, idx), 0));
12670 if (AVR_HAVE_JMP_CALL)
12671 fprintf (stream, "\t.word gs(.L%d)\n", value);
12672 else
12673 fprintf (stream, "\trjmp .L%d\n", value);
12676 // Switch back to original section. As we clobbered the section above,
12677 // forget the current section before switching back.
12679 in_section = NULL;
12680 switch_to_section (current_function_section ());
12684 /* Implement `TARGET_CONDITIONAL_REGISTER_USAGE'. */
12686 static void
12687 avr_conditional_register_usage (void)
12689 if (AVR_TINY)
12691 const int tiny_reg_alloc_order[] = {
12692 24, 25,
12693 22, 23,
12694 30, 31,
12695 26, 27,
12696 28, 29,
12697 21, 20, 19, 18,
12698 16, 17,
12699 32, 33, 34, 35,
12700 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
12703 /* Set R0-R17 as fixed registers. Reset R0-R17 in call used register list
12704 - R0-R15 are not available in Tiny Core devices
12705 - R16 and R17 are fixed registers. */
12707 for (size_t i = 0; i <= 17; i++)
12709 fixed_regs[i] = 1;
12710 call_used_regs[i] = 1;
12713 /* Set R18 to R21 as callee saved registers
12714 - R18, R19, R20 and R21 are the callee saved registers in
12715 Tiny Core devices */
12717 for (size_t i = 18; i <= LAST_CALLEE_SAVED_REG; i++)
12719 call_used_regs[i] = 0;
12722 /* Update register allocation order for Tiny Core devices */
12724 for (size_t i = 0; i < ARRAY_SIZE (tiny_reg_alloc_order); i++)
12726 reg_alloc_order[i] = tiny_reg_alloc_order[i];
12729 CLEAR_HARD_REG_SET (reg_class_contents[(int) ADDW_REGS]);
12730 CLEAR_HARD_REG_SET (reg_class_contents[(int) NO_LD_REGS]);
12734 /* Implement `TARGET_HARD_REGNO_SCRATCH_OK'. */
12735 /* Returns true if SCRATCH are safe to be allocated as a scratch
12736 registers (for a define_peephole2) in the current function. */
12738 static bool
12739 avr_hard_regno_scratch_ok (unsigned int regno)
12741 /* Interrupt functions can only use registers that have already been saved
12742 by the prologue, even if they would normally be call-clobbered. */
12744 if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
12745 && !df_regs_ever_live_p (regno))
12746 return false;
12748 /* Don't allow hard registers that might be part of the frame pointer.
12749 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
12750 and don't care for a frame pointer that spans more than one register. */
12752 if ((!reload_completed || frame_pointer_needed)
12753 && (regno == REG_Y || regno == REG_Y + 1))
12755 return false;
12758 return true;
12762 /* Worker function for `HARD_REGNO_RENAME_OK'. */
12763 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
12766 avr_hard_regno_rename_ok (unsigned int old_reg,
12767 unsigned int new_reg)
12769 /* Interrupt functions can only use registers that have already been
12770 saved by the prologue, even if they would normally be
12771 call-clobbered. */
12773 if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
12774 && !df_regs_ever_live_p (new_reg))
12775 return 0;
12777 /* Don't allow hard registers that might be part of the frame pointer.
12778 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
12779 and don't care for a frame pointer that spans more than one register. */
12781 if ((!reload_completed || frame_pointer_needed)
12782 && (old_reg == REG_Y || old_reg == REG_Y + 1
12783 || new_reg == REG_Y || new_reg == REG_Y + 1))
12785 return 0;
12788 return 1;
12791 /* Output a branch that tests a single bit of a register (QI, HI, SI or DImode)
12792 or memory location in the I/O space (QImode only).
12794 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
12795 Operand 1: register operand to test, or CONST_INT memory address.
12796 Operand 2: bit number.
12797 Operand 3: label to jump to if the test is true. */
12799 const char*
12800 avr_out_sbxx_branch (rtx_insn *insn, rtx operands[])
12802 enum rtx_code comp = GET_CODE (operands[0]);
12803 bool long_jump = get_attr_length (insn) >= 4;
12804 bool reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
12806 if (comp == GE)
12807 comp = EQ;
12808 else if (comp == LT)
12809 comp = NE;
12811 if (reverse)
12812 comp = reverse_condition (comp);
12814 switch (GET_CODE (operands[1]))
12816 default:
12817 gcc_unreachable();
12819 case CONST_INT:
12820 case CONST:
12821 case SYMBOL_REF:
12823 if (low_io_address_operand (operands[1], QImode))
12825 if (comp == EQ)
12826 output_asm_insn ("sbis %i1,%2", operands);
12827 else
12828 output_asm_insn ("sbic %i1,%2", operands);
12830 else
12832 gcc_assert (io_address_operand (operands[1], QImode));
12833 output_asm_insn ("in __tmp_reg__,%i1", operands);
12834 if (comp == EQ)
12835 output_asm_insn ("sbrs __tmp_reg__,%2", operands);
12836 else
12837 output_asm_insn ("sbrc __tmp_reg__,%2", operands);
12840 break; /* CONST_INT */
12842 case REG:
12844 if (comp == EQ)
12845 output_asm_insn ("sbrs %T1%T2", operands);
12846 else
12847 output_asm_insn ("sbrc %T1%T2", operands);
12849 break; /* REG */
12850 } /* switch */
12852 if (long_jump)
12853 return ("rjmp .+4" CR_TAB
12854 "jmp %x3");
12856 if (!reverse)
12857 return "rjmp %x3";
12859 return "";
12862 /* Worker function for `TARGET_ASM_CONSTRUCTOR'. */
12864 static void
12865 avr_asm_out_ctor (rtx symbol, int priority)
12867 fputs ("\t.global __do_global_ctors\n", asm_out_file);
12868 default_ctor_section_asm_out_constructor (symbol, priority);
12872 /* Worker function for `TARGET_ASM_DESTRUCTOR'. */
12874 static void
12875 avr_asm_out_dtor (rtx symbol, int priority)
12877 fputs ("\t.global __do_global_dtors\n", asm_out_file);
12878 default_dtor_section_asm_out_destructor (symbol, priority);
12882 /* Worker function for `TARGET_RETURN_IN_MEMORY'. */
12884 static bool
12885 avr_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
12887 HOST_WIDE_INT size = int_size_in_bytes (type);
12888 HOST_WIDE_INT ret_size_limit = AVR_TINY ? 4 : 8;
12890 /* In avr, there are 8 return registers. But, for Tiny Core
12891 (ATtiny4/5/9/10/20/40) devices, only 4 registers are available.
12892 Return true if size is unknown or greater than the limit. */
12894 if (size == -1 || size > ret_size_limit)
12896 return true;
12898 else
12900 return false;
12905 /* Implement `CASE_VALUES_THRESHOLD'. */
12906 /* Supply the default for --param case-values-threshold=0 */
12908 static unsigned int
12909 avr_case_values_threshold (void)
12911 /* The exact break-even point between a jump table and an if-else tree
12912 depends on several factors not available here like, e.g. if 8-bit
12913 comparisons can be used in the if-else tree or not, on the
12914 range of the case values, if the case value can be reused, on the
12915 register allocation, etc. '7' appears to be a good choice. */
12917 return 7;
12921 /* Implement `TARGET_ADDR_SPACE_ADDRESS_MODE'. */
12923 static scalar_int_mode
12924 avr_addr_space_address_mode (addr_space_t as)
12926 return avr_addrspace[as].pointer_size == 3 ? PSImode : HImode;
12930 /* Implement `TARGET_ADDR_SPACE_POINTER_MODE'. */
12932 static scalar_int_mode
12933 avr_addr_space_pointer_mode (addr_space_t as)
12935 return avr_addr_space_address_mode (as);
12939 /* Helper for following function. */
12941 static bool
12942 avr_reg_ok_for_pgm_addr (rtx reg, bool strict)
12944 gcc_assert (REG_P (reg));
12946 if (strict)
12948 return REGNO (reg) == REG_Z;
12951 /* Avoid combine to propagate hard regs. */
12953 if (can_create_pseudo_p()
12954 && REGNO (reg) < REG_Z)
12956 return false;
12959 return true;
12963 /* Implement `TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P'. */
12965 static bool
12966 avr_addr_space_legitimate_address_p (machine_mode mode, rtx x,
12967 bool strict, addr_space_t as)
12969 bool ok = false;
12971 switch (as)
12973 default:
12974 gcc_unreachable();
12976 case ADDR_SPACE_GENERIC:
12977 return avr_legitimate_address_p (mode, x, strict);
12979 case ADDR_SPACE_FLASH:
12980 case ADDR_SPACE_FLASH1:
12981 case ADDR_SPACE_FLASH2:
12982 case ADDR_SPACE_FLASH3:
12983 case ADDR_SPACE_FLASH4:
12984 case ADDR_SPACE_FLASH5:
12986 switch (GET_CODE (x))
12988 case REG:
12989 ok = avr_reg_ok_for_pgm_addr (x, strict);
12990 break;
12992 case POST_INC:
12993 ok = avr_reg_ok_for_pgm_addr (XEXP (x, 0), strict);
12994 break;
12996 default:
12997 break;
13000 break; /* FLASH */
13002 case ADDR_SPACE_MEMX:
13003 if (REG_P (x))
13004 ok = (!strict
13005 && can_create_pseudo_p());
13007 if (LO_SUM == GET_CODE (x))
13009 rtx hi = XEXP (x, 0);
13010 rtx lo = XEXP (x, 1);
13012 ok = (REG_P (hi)
13013 && (!strict || REGNO (hi) < FIRST_PSEUDO_REGISTER)
13014 && REG_P (lo)
13015 && REGNO (lo) == REG_Z);
13018 break; /* MEMX */
13021 if (avr_log.legitimate_address_p)
13023 avr_edump ("\n%?: ret=%b, mode=%m strict=%d "
13024 "reload_completed=%d reload_in_progress=%d %s:",
13025 ok, mode, strict, reload_completed, reload_in_progress,
13026 reg_renumber ? "(reg_renumber)" : "");
13028 if (GET_CODE (x) == PLUS
13029 && REG_P (XEXP (x, 0))
13030 && CONST_INT_P (XEXP (x, 1))
13031 && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
13032 && reg_renumber)
13034 avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
13035 true_regnum (XEXP (x, 0)));
13038 avr_edump ("\n%r\n", x);
13041 return ok;
13045 /* Implement `TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS'. */
13047 static rtx
13048 avr_addr_space_legitimize_address (rtx x, rtx old_x,
13049 machine_mode mode, addr_space_t as)
13051 if (ADDR_SPACE_GENERIC_P (as))
13052 return avr_legitimize_address (x, old_x, mode);
13054 if (avr_log.legitimize_address)
13056 avr_edump ("\n%?: mode=%m\n %r\n", mode, old_x);
13059 return old_x;
13063 /* Implement `TARGET_ADDR_SPACE_CONVERT'. */
13065 static rtx
13066 avr_addr_space_convert (rtx src, tree type_from, tree type_to)
13068 addr_space_t as_from = TYPE_ADDR_SPACE (TREE_TYPE (type_from));
13069 addr_space_t as_to = TYPE_ADDR_SPACE (TREE_TYPE (type_to));
13071 if (avr_log.progmem)
13072 avr_edump ("\n%!: op = %r\nfrom = %t\nto = %t\n",
13073 src, type_from, type_to);
13075 /* Up-casting from 16-bit to 24-bit pointer. */
13077 if (as_from != ADDR_SPACE_MEMX
13078 && as_to == ADDR_SPACE_MEMX)
13080 int msb;
13081 rtx sym = src;
13082 rtx reg = gen_reg_rtx (PSImode);
13084 while (CONST == GET_CODE (sym) || PLUS == GET_CODE (sym))
13085 sym = XEXP (sym, 0);
13087 /* Look at symbol flags: avr_encode_section_info set the flags
13088 also if attribute progmem was seen so that we get the right
13089 promotion for, e.g. PSTR-like strings that reside in generic space
13090 but are located in flash. In that case we patch the incoming
13091 address space. */
13093 if (SYMBOL_REF_P (sym)
13094 && ADDR_SPACE_FLASH == AVR_SYMBOL_GET_ADDR_SPACE (sym))
13096 as_from = ADDR_SPACE_FLASH;
13099 /* Linearize memory: RAM has bit 23 set. */
13101 msb = ADDR_SPACE_GENERIC_P (as_from)
13102 ? 0x80
13103 : avr_addrspace[as_from].segment;
13105 src = force_reg (Pmode, src);
13107 emit_insn (msb == 0
13108 ? gen_zero_extendhipsi2 (reg, src)
13109 : gen_n_extendhipsi2 (reg, gen_int_mode (msb, QImode), src));
13111 return reg;
13114 /* Down-casting from 24-bit to 16-bit throws away the high byte. */
13116 if (as_from == ADDR_SPACE_MEMX
13117 && as_to != ADDR_SPACE_MEMX)
13119 rtx new_src = gen_reg_rtx (Pmode);
13121 src = force_reg (PSImode, src);
13123 emit_move_insn (new_src,
13124 simplify_gen_subreg (Pmode, src, PSImode, 0));
13125 return new_src;
13128 return src;
13132 /* Implement `TARGET_ADDR_SPACE_SUBSET_P'. */
13134 static bool
13135 avr_addr_space_subset_p (addr_space_t subset ATTRIBUTE_UNUSED,
13136 addr_space_t superset ATTRIBUTE_UNUSED)
13138 /* Allow any kind of pointer mess. */
13140 return true;
13144 /* Implement `TARGET_CONVERT_TO_TYPE'. */
13146 static tree
13147 avr_convert_to_type (tree type, tree expr)
13149 /* Print a diagnose for pointer conversion that changes the address
13150 space of the pointer target to a non-enclosing address space,
13151 provided -Waddr-space-convert is on.
13153 FIXME: Filter out cases where the target object is known to
13154 be located in the right memory, like in
13156 (const __flash*) PSTR ("text")
13158 Also try to distinguish between explicit casts requested by
13159 the user and implicit casts like
13161 void f (const __flash char*);
13163 void g (const char *p)
13165 f ((const __flash*) p);
13168 under the assumption that an explicit casts means that the user
13169 knows what he is doing, e.g. interface with PSTR or old style
13170 code with progmem and pgm_read_xxx.
13173 if (avr_warn_addr_space_convert
13174 && expr != error_mark_node
13175 && POINTER_TYPE_P (type)
13176 && POINTER_TYPE_P (TREE_TYPE (expr)))
13178 addr_space_t as_old = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (expr)));
13179 addr_space_t as_new = TYPE_ADDR_SPACE (TREE_TYPE (type));
13181 if (avr_log.progmem)
13182 avr_edump ("%?: type = %t\nexpr = %t\n\n", type, expr);
13184 if (as_new != ADDR_SPACE_MEMX
13185 && as_new != as_old)
13187 location_t loc = EXPR_LOCATION (expr);
13188 const char *name_old = avr_addrspace[as_old].name;
13189 const char *name_new = avr_addrspace[as_new].name;
13191 warning (OPT_Waddr_space_convert,
13192 "conversion from address space %qs to address space %qs",
13193 ADDR_SPACE_GENERIC_P (as_old) ? "generic" : name_old,
13194 ADDR_SPACE_GENERIC_P (as_new) ? "generic" : name_new);
13196 return fold_build1_loc (loc, ADDR_SPACE_CONVERT_EXPR, type, expr);
13200 return NULL_TREE;
13204 /* Implement `TARGET_LEGITIMATE_COMBINED_INSN'. */
13206 /* PR78883: Filter out paradoxical SUBREGs of MEM which are not handled
13207 properly by following passes. As INSN_SCHEDULING is off and hence
13208 general_operand accepts such expressions, ditch them now. */
13210 static bool
13211 avr_legitimate_combined_insn (rtx_insn *insn)
13213 subrtx_iterator::array_type array;
13215 FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
13217 const_rtx op = *iter;
13219 if (SUBREG_P (op)
13220 && MEM_P (SUBREG_REG (op))
13221 && (GET_MODE_SIZE (GET_MODE (op))
13222 > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))))
13224 return false;
13228 return true;
13232 /* PR63633: The middle-end might come up with hard regs as input operands.
13234 RMASK is a bit mask representing a subset of hard registers R0...R31:
13235 Rn is an element of that set iff bit n of RMASK is set.
13236 OPMASK describes a subset of OP[]: If bit n of OPMASK is 1 then
13237 OP[n] has to be fixed; otherwise OP[n] is left alone.
13239 For each element of OPMASK which is a hard register overlapping RMASK,
13240 replace OP[n] with a newly created pseudo register
13242 HREG == 0: Also emit a move insn that copies the contents of that
13243 hard register into the new pseudo.
13245 HREG != 0: Also set HREG[n] to the hard register. */
13247 static void
13248 avr_fix_operands (rtx *op, rtx *hreg, unsigned opmask, unsigned rmask)
13250 for (; opmask; opmask >>= 1, op++)
13252 rtx reg = *op;
13254 if (hreg)
13255 *hreg = NULL_RTX;
13257 if ((opmask & 1)
13258 && REG_P (reg)
13259 && REGNO (reg) < FIRST_PSEUDO_REGISTER
13260 // This hard-reg overlaps other prohibited hard regs?
13261 && (rmask & regmask (GET_MODE (reg), REGNO (reg))))
13263 *op = gen_reg_rtx (GET_MODE (reg));
13264 if (hreg == NULL)
13265 emit_move_insn (*op, reg);
13266 else
13267 *hreg = reg;
13270 if (hreg)
13271 hreg++;
13276 void
13277 avr_fix_inputs (rtx *op, unsigned opmask, unsigned rmask)
13279 avr_fix_operands (op, NULL, opmask, rmask);
13283 /* Helper for the function below: If bit n of MASK is set and
13284 HREG[n] != NULL, then emit a move insn to copy OP[n] to HREG[n].
13285 Otherwise do nothing for that n. Return TRUE. */
13287 static bool
13288 avr_move_fixed_operands (rtx *op, rtx *hreg, unsigned mask)
13290 for (; mask; mask >>= 1, op++, hreg++)
13291 if ((mask & 1)
13292 && *hreg)
13293 emit_move_insn (*hreg, *op);
13295 return true;
13299 /* PR63633: The middle-end might come up with hard regs as output operands.
13301 GEN is a sequence generating function like gen_mulsi3 with 3 operands OP[].
13302 RMASK is a bit mask representing a subset of hard registers R0...R31:
13303 Rn is an element of that set iff bit n of RMASK is set.
13304 OPMASK describes a subset of OP[]: If bit n of OPMASK is 1 then
13305 OP[n] has to be fixed; otherwise OP[n] is left alone.
13307 Emit the insn sequence as generated by GEN() with all elements of OPMASK
13308 which are hard registers overlapping RMASK replaced by newly created
13309 pseudo registers. After the sequence has been emitted, emit insns that
13310 move the contents of respective pseudos to their hard regs. */
13312 bool
13313 avr_emit3_fix_outputs (rtx (*gen)(rtx,rtx,rtx), rtx *op,
13314 unsigned opmask, unsigned rmask)
13316 const int n = 3;
13317 rtx hreg[n];
13319 /* It is letigimate for GEN to call this function, and in order not to
13320 get self-recursive we use the following static kludge. This is the
13321 only way not to duplicate all expanders and to avoid ugly and
13322 hard-to-maintain C-code instead of the much more appreciated RTL
13323 representation as supplied by define_expand. */
13324 static bool lock = false;
13326 gcc_assert (opmask < (1u << n));
13328 if (lock)
13329 return false;
13331 avr_fix_operands (op, hreg, opmask, rmask);
13333 lock = true;
13334 emit_insn (gen (op[0], op[1], op[2]));
13335 lock = false;
13337 return avr_move_fixed_operands (op, hreg, opmask);
13341 /* Worker function for movmemhi expander.
13342 XOP[0] Destination as MEM:BLK
13343 XOP[1] Source " "
13344 XOP[2] # Bytes to copy
13346 Return TRUE if the expansion is accomplished.
13347 Return FALSE if the operand compination is not supported. */
13349 bool
13350 avr_emit_movmemhi (rtx *xop)
13352 HOST_WIDE_INT count;
13353 machine_mode loop_mode;
13354 addr_space_t as = MEM_ADDR_SPACE (xop[1]);
13355 rtx loop_reg, addr1, a_src, a_dest, insn, xas;
13356 rtx a_hi8 = NULL_RTX;
13358 if (avr_mem_flash_p (xop[0]))
13359 return false;
13361 if (!CONST_INT_P (xop[2]))
13362 return false;
13364 count = INTVAL (xop[2]);
13365 if (count <= 0)
13366 return false;
13368 a_src = XEXP (xop[1], 0);
13369 a_dest = XEXP (xop[0], 0);
13371 if (PSImode == GET_MODE (a_src))
13373 gcc_assert (as == ADDR_SPACE_MEMX);
13375 loop_mode = (count < 0x100) ? QImode : HImode;
13376 loop_reg = gen_rtx_REG (loop_mode, 24);
13377 emit_move_insn (loop_reg, gen_int_mode (count, loop_mode));
13379 addr1 = simplify_gen_subreg (HImode, a_src, PSImode, 0);
13380 a_hi8 = simplify_gen_subreg (QImode, a_src, PSImode, 2);
13382 else
13384 int segment = avr_addrspace[as].segment;
13386 if (segment
13387 && avr_n_flash > 1)
13389 a_hi8 = GEN_INT (segment);
13390 emit_move_insn (rampz_rtx, a_hi8 = copy_to_mode_reg (QImode, a_hi8));
13392 else if (!ADDR_SPACE_GENERIC_P (as))
13394 as = ADDR_SPACE_FLASH;
13397 addr1 = a_src;
13399 loop_mode = (count <= 0x100) ? QImode : HImode;
13400 loop_reg = copy_to_mode_reg (loop_mode, gen_int_mode (count, loop_mode));
13403 xas = GEN_INT (as);
13405 /* FIXME: Register allocator might come up with spill fails if it is left
13406 on its own. Thus, we allocate the pointer registers by hand:
13407 Z = source address
13408 X = destination address */
13410 emit_move_insn (lpm_addr_reg_rtx, addr1);
13411 emit_move_insn (gen_rtx_REG (HImode, REG_X), a_dest);
13413 /* FIXME: Register allocator does a bad job and might spill address
13414 register(s) inside the loop leading to additional move instruction
13415 to/from stack which could clobber tmp_reg. Thus, do *not* emit
13416 load and store as separate insns. Instead, we perform the copy
13417 by means of one monolithic insn. */
13419 gcc_assert (TMP_REGNO == LPM_REGNO);
13421 if (as != ADDR_SPACE_MEMX)
13423 /* Load instruction ([E]LPM or LD) is known at compile time:
13424 Do the copy-loop inline. */
13426 rtx (*fun) (rtx, rtx, rtx)
13427 = QImode == loop_mode ? gen_movmem_qi : gen_movmem_hi;
13429 insn = fun (xas, loop_reg, loop_reg);
13431 else
13433 rtx (*fun) (rtx, rtx)
13434 = QImode == loop_mode ? gen_movmemx_qi : gen_movmemx_hi;
13436 emit_move_insn (gen_rtx_REG (QImode, 23), a_hi8);
13438 insn = fun (xas, GEN_INT (avr_addr.rampz));
13441 set_mem_addr_space (SET_SRC (XVECEXP (insn, 0, 0)), as);
13442 emit_insn (insn);
13444 return true;
13448 /* Print assembler for movmem_qi, movmem_hi insns...
13449 $0 : Address Space
13450 $1, $2 : Loop register
13451 Z : Source address
13452 X : Destination address
13455 const char*
13456 avr_out_movmem (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
13458 addr_space_t as = (addr_space_t) INTVAL (op[0]);
13459 machine_mode loop_mode = GET_MODE (op[1]);
13460 bool sbiw_p = test_hard_reg_class (ADDW_REGS, op[1]);
13461 rtx xop[3];
13463 if (plen)
13464 *plen = 0;
13466 xop[0] = op[0];
13467 xop[1] = op[1];
13468 xop[2] = tmp_reg_rtx;
13470 /* Loop label */
13472 avr_asm_len ("0:", xop, plen, 0);
13474 /* Load with post-increment */
13476 switch (as)
13478 default:
13479 gcc_unreachable();
13481 case ADDR_SPACE_GENERIC:
13483 avr_asm_len ("ld %2,Z+", xop, plen, 1);
13484 break;
13486 case ADDR_SPACE_FLASH:
13488 if (AVR_HAVE_LPMX)
13489 avr_asm_len ("lpm %2,Z+", xop, plen, 1);
13490 else
13491 avr_asm_len ("lpm" CR_TAB
13492 "adiw r30,1", xop, plen, 2);
13493 break;
13495 case ADDR_SPACE_FLASH1:
13496 case ADDR_SPACE_FLASH2:
13497 case ADDR_SPACE_FLASH3:
13498 case ADDR_SPACE_FLASH4:
13499 case ADDR_SPACE_FLASH5:
13501 if (AVR_HAVE_ELPMX)
13502 avr_asm_len ("elpm %2,Z+", xop, plen, 1);
13503 else
13504 avr_asm_len ("elpm" CR_TAB
13505 "adiw r30,1", xop, plen, 2);
13506 break;
13509 /* Store with post-increment */
13511 avr_asm_len ("st X+,%2", xop, plen, 1);
13513 /* Decrement loop-counter and set Z-flag */
13515 if (QImode == loop_mode)
13517 avr_asm_len ("dec %1", xop, plen, 1);
13519 else if (sbiw_p)
13521 avr_asm_len ("sbiw %1,1", xop, plen, 1);
13523 else
13525 avr_asm_len ("subi %A1,1" CR_TAB
13526 "sbci %B1,0", xop, plen, 2);
13529 /* Loop until zero */
13531 return avr_asm_len ("brne 0b", xop, plen, 1);
13536 /* Helper for __builtin_avr_delay_cycles */
13538 static rtx
13539 avr_mem_clobber (void)
13541 rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
13542 MEM_VOLATILE_P (mem) = 1;
13543 return mem;
13546 static void
13547 avr_expand_delay_cycles (rtx operands0)
13549 unsigned HOST_WIDE_INT cycles = UINTVAL (operands0) & GET_MODE_MASK (SImode);
13550 unsigned HOST_WIDE_INT cycles_used;
13551 unsigned HOST_WIDE_INT loop_count;
13553 if (IN_RANGE (cycles, 83886082, 0xFFFFFFFF))
13555 loop_count = ((cycles - 9) / 6) + 1;
13556 cycles_used = ((loop_count - 1) * 6) + 9;
13557 emit_insn (gen_delay_cycles_4 (gen_int_mode (loop_count, SImode),
13558 avr_mem_clobber()));
13559 cycles -= cycles_used;
13562 if (IN_RANGE (cycles, 262145, 83886081))
13564 loop_count = ((cycles - 7) / 5) + 1;
13565 if (loop_count > 0xFFFFFF)
13566 loop_count = 0xFFFFFF;
13567 cycles_used = ((loop_count - 1) * 5) + 7;
13568 emit_insn (gen_delay_cycles_3 (gen_int_mode (loop_count, SImode),
13569 avr_mem_clobber()));
13570 cycles -= cycles_used;
13573 if (IN_RANGE (cycles, 768, 262144))
13575 loop_count = ((cycles - 5) / 4) + 1;
13576 if (loop_count > 0xFFFF)
13577 loop_count = 0xFFFF;
13578 cycles_used = ((loop_count - 1) * 4) + 5;
13579 emit_insn (gen_delay_cycles_2 (gen_int_mode (loop_count, HImode),
13580 avr_mem_clobber()));
13581 cycles -= cycles_used;
13584 if (IN_RANGE (cycles, 6, 767))
13586 loop_count = cycles / 3;
13587 if (loop_count > 255)
13588 loop_count = 255;
13589 cycles_used = loop_count * 3;
13590 emit_insn (gen_delay_cycles_1 (gen_int_mode (loop_count, QImode),
13591 avr_mem_clobber()));
13592 cycles -= cycles_used;
13595 while (cycles >= 2)
13597 emit_insn (gen_nopv (GEN_INT (2)));
13598 cycles -= 2;
13601 if (cycles == 1)
13603 emit_insn (gen_nopv (GEN_INT (1)));
13604 cycles--;
13609 static void
13610 avr_expand_nops (rtx operands0)
13612 unsigned HOST_WIDE_INT n_nops = UINTVAL (operands0) & GET_MODE_MASK (HImode);
13614 while (n_nops--)
13616 emit_insn (gen_nopv (const1_rtx));
13621 /* Compute the image of x under f, i.e. perform x --> f(x) */
13623 static int
13624 avr_map (unsigned int f, int x)
13626 return x < 8 ? (f >> (4 * x)) & 0xf : 0;
13630 /* Return some metrics of map A. */
13632 enum
13634 /* Number of fixed points in { 0 ... 7 } */
13635 MAP_FIXED_0_7,
13637 /* Size of preimage of non-fixed points in { 0 ... 7 } */
13638 MAP_NONFIXED_0_7,
13640 /* Mask representing the fixed points in { 0 ... 7 } */
13641 MAP_MASK_FIXED_0_7,
13643 /* Size of the preimage of { 0 ... 7 } */
13644 MAP_PREIMAGE_0_7,
13646 /* Mask that represents the preimage of { f } */
13647 MAP_MASK_PREIMAGE_F
13650 static unsigned
13651 avr_map_metric (unsigned int a, int mode)
13653 unsigned metric = 0;
13655 for (unsigned i = 0; i < 8; i++)
13657 unsigned ai = avr_map (a, i);
13659 if (mode == MAP_FIXED_0_7)
13660 metric += ai == i;
13661 else if (mode == MAP_NONFIXED_0_7)
13662 metric += ai < 8 && ai != i;
13663 else if (mode == MAP_MASK_FIXED_0_7)
13664 metric |= ((unsigned) (ai == i)) << i;
13665 else if (mode == MAP_PREIMAGE_0_7)
13666 metric += ai < 8;
13667 else if (mode == MAP_MASK_PREIMAGE_F)
13668 metric |= ((unsigned) (ai == 0xf)) << i;
13669 else
13670 gcc_unreachable();
13673 return metric;
13677 /* Return true if IVAL has a 0xf in its hexadecimal representation
13678 and false, otherwise. Only nibbles 0..7 are taken into account.
13679 Used as constraint helper for C0f and Cxf. */
13681 bool
13682 avr_has_nibble_0xf (rtx ival)
13684 unsigned int map = UINTVAL (ival) & GET_MODE_MASK (SImode);
13685 return avr_map_metric (map, MAP_MASK_PREIMAGE_F) != 0;
13689 /* We have a set of bits that are mapped by a function F.
13690 Try to decompose F by means of a second function G so that
13692 F = F o G^-1 o G
13696 cost (F o G^-1) + cost (G) < cost (F)
13698 Example: Suppose builtin insert_bits supplies us with the map
13699 F = 0x3210ffff. Instead of doing 4 bit insertions to get the high
13700 nibble of the result, we can just as well rotate the bits before inserting
13701 them and use the map 0x7654ffff which is cheaper than the original map.
13702 For this example G = G^-1 = 0x32107654 and F o G^-1 = 0x7654ffff. */
13704 typedef struct
13706 /* tree code of binary function G */
13707 enum tree_code code;
13709 /* The constant second argument of G */
13710 int arg;
13712 /* G^-1, the inverse of G (*, arg) */
13713 unsigned ginv;
13715 /* The cost of applying G (*, arg) */
13716 int cost;
13718 /* The composition F o G^-1 (*, arg) for some function F */
13719 unsigned int map;
13721 /* For debug purpose only */
13722 const char *str;
13723 } avr_map_op_t;
13725 static const avr_map_op_t avr_map_op[] =
13727 { LROTATE_EXPR, 0, 0x76543210, 0, 0, "id" },
13728 { LROTATE_EXPR, 1, 0x07654321, 2, 0, "<<<" },
13729 { LROTATE_EXPR, 2, 0x10765432, 4, 0, "<<<" },
13730 { LROTATE_EXPR, 3, 0x21076543, 4, 0, "<<<" },
13731 { LROTATE_EXPR, 4, 0x32107654, 1, 0, "<<<" },
13732 { LROTATE_EXPR, 5, 0x43210765, 3, 0, "<<<" },
13733 { LROTATE_EXPR, 6, 0x54321076, 5, 0, "<<<" },
13734 { LROTATE_EXPR, 7, 0x65432107, 3, 0, "<<<" },
13735 { RSHIFT_EXPR, 1, 0x6543210c, 1, 0, ">>" },
13736 { RSHIFT_EXPR, 1, 0x7543210c, 1, 0, ">>" },
13737 { RSHIFT_EXPR, 2, 0x543210cc, 2, 0, ">>" },
13738 { RSHIFT_EXPR, 2, 0x643210cc, 2, 0, ">>" },
13739 { RSHIFT_EXPR, 2, 0x743210cc, 2, 0, ">>" },
13740 { LSHIFT_EXPR, 1, 0xc7654321, 1, 0, "<<" },
13741 { LSHIFT_EXPR, 2, 0xcc765432, 2, 0, "<<" }
13745 /* Try to decompose F as F = (F o G^-1) o G as described above.
13746 The result is a struct representing F o G^-1 and G.
13747 If result.cost < 0 then such a decomposition does not exist. */
13749 static avr_map_op_t
13750 avr_map_decompose (unsigned int f, const avr_map_op_t *g, bool val_const_p)
13752 bool val_used_p = avr_map_metric (f, MAP_MASK_PREIMAGE_F) != 0;
13753 avr_map_op_t f_ginv = *g;
13754 unsigned int ginv = g->ginv;
13756 f_ginv.cost = -1;
13758 /* Step 1: Computing F o G^-1 */
13760 for (int i = 7; i >= 0; i--)
13762 int x = avr_map (f, i);
13764 if (x <= 7)
13766 x = avr_map (ginv, x);
13768 /* The bit is no element of the image of G: no avail (cost = -1) */
13770 if (x > 7)
13771 return f_ginv;
13774 f_ginv.map = (f_ginv.map << 4) + x;
13777 /* Step 2: Compute the cost of the operations.
13778 The overall cost of doing an operation prior to the insertion is
13779 the cost of the insertion plus the cost of the operation. */
13781 /* Step 2a: Compute cost of F o G^-1 */
13783 if (avr_map_metric (f_ginv.map, MAP_NONFIXED_0_7) == 0)
13784 /* The mapping consists only of fixed points and can be folded
13785 to AND/OR logic in the remainder. Reasonable cost is 3. */
13786 f_ginv.cost = 2 + (val_used_p && !val_const_p);
13787 else
13789 rtx xop[4];
13791 /* Get the cost of the insn by calling the output worker with some
13792 fake values. Mimic effect of reloading xop[3]: Unused operands
13793 are mapped to 0 and used operands are reloaded to xop[0]. */
13795 xop[0] = all_regs_rtx[24];
13796 xop[1] = gen_int_mode (f_ginv.map, SImode);
13797 xop[2] = all_regs_rtx[25];
13798 xop[3] = val_used_p ? xop[0] : const0_rtx;
13800 avr_out_insert_bits (xop, &f_ginv.cost);
13802 f_ginv.cost += val_const_p && val_used_p ? 1 : 0;
13805 /* Step 2b: Add cost of G */
13807 f_ginv.cost += g->cost;
13809 if (avr_log.builtin)
13810 avr_edump (" %s%d=%d", g->str, g->arg, f_ginv.cost);
13812 return f_ginv;
13816 /* Insert bits from XOP[1] into XOP[0] according to MAP.
13817 XOP[0] and XOP[1] don't overlap.
13818 If FIXP_P = true: Move all bits according to MAP using BLD/BST sequences.
13819 If FIXP_P = false: Just move the bit if its position in the destination
13820 is different to its source position. */
13822 static void
13823 avr_move_bits (rtx *xop, unsigned int map, bool fixp_p, int *plen)
13825 /* T-flag contains this bit of the source, i.e. of XOP[1] */
13826 int t_bit_src = -1;
13828 /* We order the operations according to the requested source bit b. */
13830 for (int b = 0; b < 8; b++)
13831 for (int bit_dest = 0; bit_dest < 8; bit_dest++)
13833 int bit_src = avr_map (map, bit_dest);
13835 if (b != bit_src
13836 || bit_src >= 8
13837 /* Same position: No need to copy as requested by FIXP_P. */
13838 || (bit_dest == bit_src && !fixp_p))
13839 continue;
13841 if (t_bit_src != bit_src)
13843 /* Source bit is not yet in T: Store it to T. */
13845 t_bit_src = bit_src;
13847 xop[3] = GEN_INT (bit_src);
13848 avr_asm_len ("bst %T1%T3", xop, plen, 1);
13851 /* Load destination bit with T. */
13853 xop[3] = GEN_INT (bit_dest);
13854 avr_asm_len ("bld %T0%T3", xop, plen, 1);
13859 /* PLEN == 0: Print assembler code for `insert_bits'.
13860 PLEN != 0: Compute code length in bytes.
13862 OP[0]: Result
13863 OP[1]: The mapping composed of nibbles. If nibble no. N is
13864 0: Bit N of result is copied from bit OP[2].0
13865 ... ...
13866 7: Bit N of result is copied from bit OP[2].7
13867 0xf: Bit N of result is copied from bit OP[3].N
13868 OP[2]: Bits to be inserted
13869 OP[3]: Target value */
13871 const char*
13872 avr_out_insert_bits (rtx *op, int *plen)
13874 unsigned int map = UINTVAL (op[1]) & GET_MODE_MASK (SImode);
13875 unsigned mask_fixed;
13876 bool fixp_p = true;
13877 rtx xop[4];
13879 xop[0] = op[0];
13880 xop[1] = op[2];
13881 xop[2] = op[3];
13883 gcc_assert (REG_P (xop[2]) || CONST_INT_P (xop[2]));
13885 if (plen)
13886 *plen = 0;
13887 else if (flag_print_asm_name)
13888 fprintf (asm_out_file, ASM_COMMENT_START "map = 0x%08x\n", map);
13890 /* If MAP has fixed points it might be better to initialize the result
13891 with the bits to be inserted instead of moving all bits by hand. */
13893 mask_fixed = avr_map_metric (map, MAP_MASK_FIXED_0_7);
13895 if (REGNO (xop[0]) == REGNO (xop[1]))
13897 /* Avoid early-clobber conflicts */
13899 avr_asm_len ("mov __tmp_reg__,%1", xop, plen, 1);
13900 xop[1] = tmp_reg_rtx;
13901 fixp_p = false;
13904 if (avr_map_metric (map, MAP_MASK_PREIMAGE_F))
13906 /* XOP[2] is used and reloaded to XOP[0] already */
13908 int n_fix = 0, n_nofix = 0;
13910 gcc_assert (REG_P (xop[2]));
13912 /* Get the code size of the bit insertions; once with all bits
13913 moved and once with fixed points omitted. */
13915 avr_move_bits (xop, map, true, &n_fix);
13916 avr_move_bits (xop, map, false, &n_nofix);
13918 if (fixp_p && n_fix - n_nofix > 3)
13920 xop[3] = gen_int_mode (~mask_fixed, QImode);
13922 avr_asm_len ("eor %0,%1" CR_TAB
13923 "andi %0,%3" CR_TAB
13924 "eor %0,%1", xop, plen, 3);
13925 fixp_p = false;
13928 else
13930 /* XOP[2] is unused */
13932 if (fixp_p && mask_fixed)
13934 avr_asm_len ("mov %0,%1", xop, plen, 1);
13935 fixp_p = false;
13939 /* Move/insert remaining bits. */
13941 avr_move_bits (xop, map, fixp_p, plen);
13943 return "";
13947 /* IDs for all the AVR builtins. */
13949 enum avr_builtin_id
13951 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
13952 AVR_BUILTIN_ ## NAME,
13953 #include "builtins.def"
13954 #undef DEF_BUILTIN
13956 AVR_BUILTIN_COUNT
13959 struct GTY(()) avr_builtin_description
13961 enum insn_code icode;
13962 int n_args;
13963 tree fndecl;
13967 /* Notice that avr_bdesc[] and avr_builtin_id are initialized in such a way
13968 that a built-in's ID can be used to access the built-in by means of
13969 avr_bdesc[ID] */
13971 static GTY(()) struct avr_builtin_description
13972 avr_bdesc[AVR_BUILTIN_COUNT] =
13974 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE, LIBNAME) \
13975 { (enum insn_code) CODE_FOR_ ## ICODE, N_ARGS, NULL_TREE },
13976 #include "builtins.def"
13977 #undef DEF_BUILTIN
13981 /* Implement `TARGET_BUILTIN_DECL'. */
13983 static tree
13984 avr_builtin_decl (unsigned id, bool initialize_p ATTRIBUTE_UNUSED)
13986 if (id < AVR_BUILTIN_COUNT)
13987 return avr_bdesc[id].fndecl;
13989 return error_mark_node;
13993 static void
13994 avr_init_builtin_int24 (void)
13996 tree int24_type = make_signed_type (GET_MODE_BITSIZE (PSImode));
13997 tree uint24_type = make_unsigned_type (GET_MODE_BITSIZE (PSImode));
13999 lang_hooks.types.register_builtin_type (int24_type, "__int24");
14000 lang_hooks.types.register_builtin_type (uint24_type, "__uint24");
14004 /* Implement `TARGET_INIT_BUILTINS' */
14005 /* Set up all builtin functions for this target. */
14007 static void
14008 avr_init_builtins (void)
14010 tree void_ftype_void
14011 = build_function_type_list (void_type_node, NULL_TREE);
14012 tree uchar_ftype_uchar
14013 = build_function_type_list (unsigned_char_type_node,
14014 unsigned_char_type_node,
14015 NULL_TREE);
14016 tree uint_ftype_uchar_uchar
14017 = build_function_type_list (unsigned_type_node,
14018 unsigned_char_type_node,
14019 unsigned_char_type_node,
14020 NULL_TREE);
14021 tree int_ftype_char_char
14022 = build_function_type_list (integer_type_node,
14023 char_type_node,
14024 char_type_node,
14025 NULL_TREE);
14026 tree int_ftype_char_uchar
14027 = build_function_type_list (integer_type_node,
14028 char_type_node,
14029 unsigned_char_type_node,
14030 NULL_TREE);
14031 tree void_ftype_ulong
14032 = build_function_type_list (void_type_node,
14033 long_unsigned_type_node,
14034 NULL_TREE);
14036 tree uchar_ftype_ulong_uchar_uchar
14037 = build_function_type_list (unsigned_char_type_node,
14038 long_unsigned_type_node,
14039 unsigned_char_type_node,
14040 unsigned_char_type_node,
14041 NULL_TREE);
14043 tree const_memx_void_node
14044 = build_qualified_type (void_type_node,
14045 TYPE_QUAL_CONST
14046 | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_MEMX));
14048 tree const_memx_ptr_type_node
14049 = build_pointer_type_for_mode (const_memx_void_node, PSImode, false);
14051 tree char_ftype_const_memx_ptr
14052 = build_function_type_list (char_type_node,
14053 const_memx_ptr_type_node,
14054 NULL);
14056 #define ITYP(T) \
14057 lang_hooks.types.type_for_size (TYPE_PRECISION (T), TYPE_UNSIGNED (T))
14059 #define FX_FTYPE_FX(fx) \
14060 tree fx##r_ftype_##fx##r \
14061 = build_function_type_list (node_##fx##r, node_##fx##r, NULL); \
14062 tree fx##k_ftype_##fx##k \
14063 = build_function_type_list (node_##fx##k, node_##fx##k, NULL)
14065 #define FX_FTYPE_FX_INT(fx) \
14066 tree fx##r_ftype_##fx##r_int \
14067 = build_function_type_list (node_##fx##r, node_##fx##r, \
14068 integer_type_node, NULL); \
14069 tree fx##k_ftype_##fx##k_int \
14070 = build_function_type_list (node_##fx##k, node_##fx##k, \
14071 integer_type_node, NULL)
14073 #define INT_FTYPE_FX(fx) \
14074 tree int_ftype_##fx##r \
14075 = build_function_type_list (integer_type_node, node_##fx##r, NULL); \
14076 tree int_ftype_##fx##k \
14077 = build_function_type_list (integer_type_node, node_##fx##k, NULL)
14079 #define INTX_FTYPE_FX(fx) \
14080 tree int##fx##r_ftype_##fx##r \
14081 = build_function_type_list (ITYP (node_##fx##r), node_##fx##r, NULL); \
14082 tree int##fx##k_ftype_##fx##k \
14083 = build_function_type_list (ITYP (node_##fx##k), node_##fx##k, NULL)
14085 #define FX_FTYPE_INTX(fx) \
14086 tree fx##r_ftype_int##fx##r \
14087 = build_function_type_list (node_##fx##r, ITYP (node_##fx##r), NULL); \
14088 tree fx##k_ftype_int##fx##k \
14089 = build_function_type_list (node_##fx##k, ITYP (node_##fx##k), NULL)
14091 tree node_hr = short_fract_type_node;
14092 tree node_nr = fract_type_node;
14093 tree node_lr = long_fract_type_node;
14094 tree node_llr = long_long_fract_type_node;
14096 tree node_uhr = unsigned_short_fract_type_node;
14097 tree node_unr = unsigned_fract_type_node;
14098 tree node_ulr = unsigned_long_fract_type_node;
14099 tree node_ullr = unsigned_long_long_fract_type_node;
14101 tree node_hk = short_accum_type_node;
14102 tree node_nk = accum_type_node;
14103 tree node_lk = long_accum_type_node;
14104 tree node_llk = long_long_accum_type_node;
14106 tree node_uhk = unsigned_short_accum_type_node;
14107 tree node_unk = unsigned_accum_type_node;
14108 tree node_ulk = unsigned_long_accum_type_node;
14109 tree node_ullk = unsigned_long_long_accum_type_node;
14112 /* For absfx builtins. */
14114 FX_FTYPE_FX (h);
14115 FX_FTYPE_FX (n);
14116 FX_FTYPE_FX (l);
14117 FX_FTYPE_FX (ll);
14119 /* For roundfx builtins. */
14121 FX_FTYPE_FX_INT (h);
14122 FX_FTYPE_FX_INT (n);
14123 FX_FTYPE_FX_INT (l);
14124 FX_FTYPE_FX_INT (ll);
14126 FX_FTYPE_FX_INT (uh);
14127 FX_FTYPE_FX_INT (un);
14128 FX_FTYPE_FX_INT (ul);
14129 FX_FTYPE_FX_INT (ull);
14131 /* For countlsfx builtins. */
14133 INT_FTYPE_FX (h);
14134 INT_FTYPE_FX (n);
14135 INT_FTYPE_FX (l);
14136 INT_FTYPE_FX (ll);
14138 INT_FTYPE_FX (uh);
14139 INT_FTYPE_FX (un);
14140 INT_FTYPE_FX (ul);
14141 INT_FTYPE_FX (ull);
14143 /* For bitsfx builtins. */
14145 INTX_FTYPE_FX (h);
14146 INTX_FTYPE_FX (n);
14147 INTX_FTYPE_FX (l);
14148 INTX_FTYPE_FX (ll);
14150 INTX_FTYPE_FX (uh);
14151 INTX_FTYPE_FX (un);
14152 INTX_FTYPE_FX (ul);
14153 INTX_FTYPE_FX (ull);
14155 /* For fxbits builtins. */
14157 FX_FTYPE_INTX (h);
14158 FX_FTYPE_INTX (n);
14159 FX_FTYPE_INTX (l);
14160 FX_FTYPE_INTX (ll);
14162 FX_FTYPE_INTX (uh);
14163 FX_FTYPE_INTX (un);
14164 FX_FTYPE_INTX (ul);
14165 FX_FTYPE_INTX (ull);
14168 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
14170 int id = AVR_BUILTIN_ ## NAME; \
14171 const char *Name = "__builtin_avr_" #NAME; \
14172 char *name = (char*) alloca (1 + strlen (Name)); \
14174 gcc_assert (id < AVR_BUILTIN_COUNT); \
14175 avr_bdesc[id].fndecl \
14176 = add_builtin_function (avr_tolower (name, Name), TYPE, id, \
14177 BUILT_IN_MD, LIBNAME, NULL_TREE); \
14179 #include "builtins.def"
14180 #undef DEF_BUILTIN
14182 avr_init_builtin_int24 ();
14186 /* Subroutine of avr_expand_builtin to expand vanilla builtins
14187 with non-void result and 1 ... 3 arguments. */
14189 static rtx
14190 avr_default_expand_builtin (enum insn_code icode, tree exp, rtx target)
14192 rtx pat, xop[3];
14193 int n_args = call_expr_nargs (exp);
14194 machine_mode tmode = insn_data[icode].operand[0].mode;
14196 gcc_assert (n_args >= 1 && n_args <= 3);
14198 if (target == NULL_RTX
14199 || GET_MODE (target) != tmode
14200 || !insn_data[icode].operand[0].predicate (target, tmode))
14202 target = gen_reg_rtx (tmode);
14205 for (int n = 0; n < n_args; n++)
14207 tree arg = CALL_EXPR_ARG (exp, n);
14208 rtx op = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14209 machine_mode opmode = GET_MODE (op);
14210 machine_mode mode = insn_data[icode].operand[n + 1].mode;
14212 if ((opmode == SImode || opmode == VOIDmode) && mode == HImode)
14214 opmode = HImode;
14215 op = gen_lowpart (HImode, op);
14218 /* In case the insn wants input operands in modes different from
14219 the result, abort. */
14221 gcc_assert (opmode == mode || opmode == VOIDmode);
14223 if (!insn_data[icode].operand[n + 1].predicate (op, mode))
14224 op = copy_to_mode_reg (mode, op);
14226 xop[n] = op;
14229 switch (n_args)
14231 case 1: pat = GEN_FCN (icode) (target, xop[0]); break;
14232 case 2: pat = GEN_FCN (icode) (target, xop[0], xop[1]); break;
14233 case 3: pat = GEN_FCN (icode) (target, xop[0], xop[1], xop[2]); break;
14235 default:
14236 gcc_unreachable();
14239 if (pat == NULL_RTX)
14240 return NULL_RTX;
14242 emit_insn (pat);
14244 return target;
14248 /* Implement `TARGET_EXPAND_BUILTIN'. */
14249 /* Expand an expression EXP that calls a built-in function,
14250 with result going to TARGET if that's convenient
14251 (and in mode MODE if that's convenient).
14252 SUBTARGET may be used as the target for computing one of EXP's operands.
14253 IGNORE is nonzero if the value is to be ignored. */
14255 static rtx
14256 avr_expand_builtin (tree exp, rtx target,
14257 rtx subtarget ATTRIBUTE_UNUSED,
14258 machine_mode mode ATTRIBUTE_UNUSED,
14259 int ignore)
14261 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
14262 const char *bname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
14263 unsigned int id = DECL_FUNCTION_CODE (fndecl);
14264 const struct avr_builtin_description *d = &avr_bdesc[id];
14265 tree arg0;
14266 rtx op0;
14268 gcc_assert (id < AVR_BUILTIN_COUNT);
14270 switch (id)
14272 case AVR_BUILTIN_NOP:
14273 emit_insn (gen_nopv (GEN_INT (1)));
14274 return 0;
14276 case AVR_BUILTIN_DELAY_CYCLES:
14278 arg0 = CALL_EXPR_ARG (exp, 0);
14279 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14281 if (!CONST_INT_P (op0))
14282 error ("%s expects a compile time integer constant", bname);
14283 else
14284 avr_expand_delay_cycles (op0);
14286 return NULL_RTX;
14289 case AVR_BUILTIN_NOPS:
14291 arg0 = CALL_EXPR_ARG (exp, 0);
14292 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14294 if (!CONST_INT_P (op0))
14295 error ("%s expects a compile time integer constant", bname);
14296 else
14297 avr_expand_nops (op0);
14299 return NULL_RTX;
14302 case AVR_BUILTIN_INSERT_BITS:
14304 arg0 = CALL_EXPR_ARG (exp, 0);
14305 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14307 if (!CONST_INT_P (op0))
14309 error ("%s expects a compile time long integer constant"
14310 " as first argument", bname);
14311 return target;
14314 break;
14317 case AVR_BUILTIN_ROUNDHR: case AVR_BUILTIN_ROUNDUHR:
14318 case AVR_BUILTIN_ROUNDR: case AVR_BUILTIN_ROUNDUR:
14319 case AVR_BUILTIN_ROUNDLR: case AVR_BUILTIN_ROUNDULR:
14320 case AVR_BUILTIN_ROUNDLLR: case AVR_BUILTIN_ROUNDULLR:
14322 case AVR_BUILTIN_ROUNDHK: case AVR_BUILTIN_ROUNDUHK:
14323 case AVR_BUILTIN_ROUNDK: case AVR_BUILTIN_ROUNDUK:
14324 case AVR_BUILTIN_ROUNDLK: case AVR_BUILTIN_ROUNDULK:
14325 case AVR_BUILTIN_ROUNDLLK: case AVR_BUILTIN_ROUNDULLK:
14327 /* Warn about odd rounding. Rounding points >= FBIT will have
14328 no effect. */
14330 if (TREE_CODE (CALL_EXPR_ARG (exp, 1)) != INTEGER_CST)
14331 break;
14333 int rbit = (int) TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1));
14335 if (rbit >= (int) GET_MODE_FBIT (mode))
14337 warning (OPT_Wextra, "rounding to %d bits has no effect for "
14338 "fixed-point value with %d fractional bits",
14339 rbit, GET_MODE_FBIT (mode));
14341 return expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX, mode,
14342 EXPAND_NORMAL);
14344 else if (rbit <= - (int) GET_MODE_IBIT (mode))
14346 warning (0, "rounding result will always be 0");
14347 return CONST0_RTX (mode);
14350 /* The rounding points RP satisfies now: -IBIT < RP < FBIT.
14352 TR 18037 only specifies results for RP > 0. However, the
14353 remaining cases of -IBIT < RP <= 0 can easily be supported
14354 without any additional overhead. */
14356 break; /* round */
14359 /* No fold found and no insn: Call support function from libgcc. */
14361 if (d->icode == CODE_FOR_nothing
14362 && DECL_ASSEMBLER_NAME (get_callee_fndecl (exp)) != NULL_TREE)
14364 return expand_call (exp, target, ignore);
14367 /* No special treatment needed: vanilla expand. */
14369 gcc_assert (d->icode != CODE_FOR_nothing);
14370 gcc_assert (d->n_args == call_expr_nargs (exp));
14372 if (d->n_args == 0)
14374 emit_insn ((GEN_FCN (d->icode)) (target));
14375 return NULL_RTX;
14378 return avr_default_expand_builtin (d->icode, exp, target);
14382 /* Helper for `avr_fold_builtin' that folds absfx (FIXED_CST). */
14384 static tree
14385 avr_fold_absfx (tree tval)
14387 if (FIXED_CST != TREE_CODE (tval))
14388 return NULL_TREE;
14390 /* Our fixed-points have no padding: Use double_int payload directly. */
14392 FIXED_VALUE_TYPE fval = TREE_FIXED_CST (tval);
14393 unsigned int bits = GET_MODE_BITSIZE (fval.mode);
14394 double_int ival = fval.data.sext (bits);
14396 if (!ival.is_negative())
14397 return tval;
14399 /* ISO/IEC TR 18037, 7.18a.6.2: The absfx functions are saturating. */
14401 fval.data = (ival == double_int::min_value (bits, false).sext (bits))
14402 ? double_int::max_value (bits, false)
14403 : -ival;
14405 return build_fixed (TREE_TYPE (tval), fval);
14409 /* Implement `TARGET_FOLD_BUILTIN'. */
14411 static tree
14412 avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg,
14413 bool ignore ATTRIBUTE_UNUSED)
14415 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
14416 tree val_type = TREE_TYPE (TREE_TYPE (fndecl));
14418 if (!optimize)
14419 return NULL_TREE;
14421 switch (fcode)
14423 default:
14424 break;
14426 case AVR_BUILTIN_SWAP:
14428 return fold_build2 (LROTATE_EXPR, val_type, arg[0],
14429 build_int_cst (val_type, 4));
14432 case AVR_BUILTIN_ABSHR:
14433 case AVR_BUILTIN_ABSR:
14434 case AVR_BUILTIN_ABSLR:
14435 case AVR_BUILTIN_ABSLLR:
14437 case AVR_BUILTIN_ABSHK:
14438 case AVR_BUILTIN_ABSK:
14439 case AVR_BUILTIN_ABSLK:
14440 case AVR_BUILTIN_ABSLLK:
14441 /* GCC is not good with folding ABS for fixed-point. Do it by hand. */
14443 return avr_fold_absfx (arg[0]);
14445 case AVR_BUILTIN_BITSHR: case AVR_BUILTIN_HRBITS:
14446 case AVR_BUILTIN_BITSHK: case AVR_BUILTIN_HKBITS:
14447 case AVR_BUILTIN_BITSUHR: case AVR_BUILTIN_UHRBITS:
14448 case AVR_BUILTIN_BITSUHK: case AVR_BUILTIN_UHKBITS:
14450 case AVR_BUILTIN_BITSR: case AVR_BUILTIN_RBITS:
14451 case AVR_BUILTIN_BITSK: case AVR_BUILTIN_KBITS:
14452 case AVR_BUILTIN_BITSUR: case AVR_BUILTIN_URBITS:
14453 case AVR_BUILTIN_BITSUK: case AVR_BUILTIN_UKBITS:
14455 case AVR_BUILTIN_BITSLR: case AVR_BUILTIN_LRBITS:
14456 case AVR_BUILTIN_BITSLK: case AVR_BUILTIN_LKBITS:
14457 case AVR_BUILTIN_BITSULR: case AVR_BUILTIN_ULRBITS:
14458 case AVR_BUILTIN_BITSULK: case AVR_BUILTIN_ULKBITS:
14460 case AVR_BUILTIN_BITSLLR: case AVR_BUILTIN_LLRBITS:
14461 case AVR_BUILTIN_BITSLLK: case AVR_BUILTIN_LLKBITS:
14462 case AVR_BUILTIN_BITSULLR: case AVR_BUILTIN_ULLRBITS:
14463 case AVR_BUILTIN_BITSULLK: case AVR_BUILTIN_ULLKBITS:
14465 gcc_assert (TYPE_PRECISION (val_type)
14466 == TYPE_PRECISION (TREE_TYPE (arg[0])));
14468 return build1 (VIEW_CONVERT_EXPR, val_type, arg[0]);
14470 case AVR_BUILTIN_INSERT_BITS:
14472 tree tbits = arg[1];
14473 tree tval = arg[2];
14474 tree tmap;
14475 tree map_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
14476 unsigned int map;
14477 bool changed = false;
14478 avr_map_op_t best_g;
14480 if (TREE_CODE (arg[0]) != INTEGER_CST)
14482 /* No constant as first argument: Don't fold this and run into
14483 error in avr_expand_builtin. */
14485 break;
14488 tmap = wide_int_to_tree (map_type, wi::to_wide (arg[0]));
14489 map = TREE_INT_CST_LOW (tmap);
14491 if (TREE_CODE (tval) != INTEGER_CST
14492 && avr_map_metric (map, MAP_MASK_PREIMAGE_F) == 0)
14494 /* There are no F in the map, i.e. 3rd operand is unused.
14495 Replace that argument with some constant to render
14496 respective input unused. */
14498 tval = build_int_cst (val_type, 0);
14499 changed = true;
14502 if (TREE_CODE (tbits) != INTEGER_CST
14503 && avr_map_metric (map, MAP_PREIMAGE_0_7) == 0)
14505 /* Similar for the bits to be inserted. If they are unused,
14506 we can just as well pass 0. */
14508 tbits = build_int_cst (val_type, 0);
14511 if (TREE_CODE (tbits) == INTEGER_CST)
14513 /* Inserting bits known at compile time is easy and can be
14514 performed by AND and OR with appropriate masks. */
14516 int bits = TREE_INT_CST_LOW (tbits);
14517 int mask_ior = 0, mask_and = 0xff;
14519 for (size_t i = 0; i < 8; i++)
14521 int mi = avr_map (map, i);
14523 if (mi < 8)
14525 if (bits & (1 << mi)) mask_ior |= (1 << i);
14526 else mask_and &= ~(1 << i);
14530 tval = fold_build2 (BIT_IOR_EXPR, val_type, tval,
14531 build_int_cst (val_type, mask_ior));
14532 return fold_build2 (BIT_AND_EXPR, val_type, tval,
14533 build_int_cst (val_type, mask_and));
14536 if (changed)
14537 return build_call_expr (fndecl, 3, tmap, tbits, tval);
14539 /* If bits don't change their position we can use vanilla logic
14540 to merge the two arguments. */
14542 if (avr_map_metric (map, MAP_NONFIXED_0_7) == 0)
14544 int mask_f = avr_map_metric (map, MAP_MASK_PREIMAGE_F);
14545 tree tres, tmask = build_int_cst (val_type, mask_f ^ 0xff);
14547 tres = fold_build2 (BIT_XOR_EXPR, val_type, tbits, tval);
14548 tres = fold_build2 (BIT_AND_EXPR, val_type, tres, tmask);
14549 return fold_build2 (BIT_XOR_EXPR, val_type, tres, tval);
14552 /* Try to decomposing map to reduce overall cost. */
14554 if (avr_log.builtin)
14555 avr_edump ("\n%?: %x\n%?: ROL cost: ", map);
14557 best_g = avr_map_op[0];
14558 best_g.cost = 1000;
14560 for (size_t i = 0; i < ARRAY_SIZE (avr_map_op); i++)
14562 avr_map_op_t g
14563 = avr_map_decompose (map, avr_map_op + i,
14564 TREE_CODE (tval) == INTEGER_CST);
14566 if (g.cost >= 0 && g.cost < best_g.cost)
14567 best_g = g;
14570 if (avr_log.builtin)
14571 avr_edump ("\n");
14573 if (best_g.arg == 0)
14574 /* No optimization found */
14575 break;
14577 /* Apply operation G to the 2nd argument. */
14579 if (avr_log.builtin)
14580 avr_edump ("%?: using OP(%s%d, %x) cost %d\n",
14581 best_g.str, best_g.arg, best_g.map, best_g.cost);
14583 /* Do right-shifts arithmetically: They copy the MSB instead of
14584 shifting in a non-usable value (0) as with logic right-shift. */
14586 tbits = fold_convert (signed_char_type_node, tbits);
14587 tbits = fold_build2 (best_g.code, signed_char_type_node, tbits,
14588 build_int_cst (val_type, best_g.arg));
14589 tbits = fold_convert (val_type, tbits);
14591 /* Use map o G^-1 instead of original map to undo the effect of G. */
14593 tmap = wide_int_to_tree (map_type, best_g.map);
14595 return build_call_expr (fndecl, 3, tmap, tbits, tval);
14596 } /* AVR_BUILTIN_INSERT_BITS */
14599 return NULL_TREE;
14604 /* Initialize the GCC target structure. */
14606 #undef TARGET_ASM_ALIGNED_HI_OP
14607 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
14608 #undef TARGET_ASM_ALIGNED_SI_OP
14609 #define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
14610 #undef TARGET_ASM_UNALIGNED_HI_OP
14611 #define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
14612 #undef TARGET_ASM_UNALIGNED_SI_OP
14613 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
14614 #undef TARGET_ASM_INTEGER
14615 #define TARGET_ASM_INTEGER avr_assemble_integer
14616 #undef TARGET_ASM_FILE_START
14617 #define TARGET_ASM_FILE_START avr_file_start
14618 #undef TARGET_ASM_FILE_END
14619 #define TARGET_ASM_FILE_END avr_file_end
14621 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
14622 #define TARGET_ASM_FUNCTION_END_PROLOGUE avr_asm_function_end_prologue
14623 #undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
14624 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE avr_asm_function_begin_epilogue
14626 #undef TARGET_FUNCTION_VALUE
14627 #define TARGET_FUNCTION_VALUE avr_function_value
14628 #undef TARGET_LIBCALL_VALUE
14629 #define TARGET_LIBCALL_VALUE avr_libcall_value
14630 #undef TARGET_FUNCTION_VALUE_REGNO_P
14631 #define TARGET_FUNCTION_VALUE_REGNO_P avr_function_value_regno_p
14633 #undef TARGET_ATTRIBUTE_TABLE
14634 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
14635 #undef TARGET_INSERT_ATTRIBUTES
14636 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
14637 #undef TARGET_SECTION_TYPE_FLAGS
14638 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
14640 #undef TARGET_ASM_NAMED_SECTION
14641 #define TARGET_ASM_NAMED_SECTION avr_asm_named_section
14642 #undef TARGET_ASM_INIT_SECTIONS
14643 #define TARGET_ASM_INIT_SECTIONS avr_asm_init_sections
14644 #undef TARGET_ENCODE_SECTION_INFO
14645 #define TARGET_ENCODE_SECTION_INFO avr_encode_section_info
14646 #undef TARGET_ASM_SELECT_SECTION
14647 #define TARGET_ASM_SELECT_SECTION avr_asm_select_section
14649 #undef TARGET_ASM_FINAL_POSTSCAN_INSN
14650 #define TARGET_ASM_FINAL_POSTSCAN_INSN avr_asm_final_postscan_insn
14652 #undef TARGET_REGISTER_MOVE_COST
14653 #define TARGET_REGISTER_MOVE_COST avr_register_move_cost
14654 #undef TARGET_MEMORY_MOVE_COST
14655 #define TARGET_MEMORY_MOVE_COST avr_memory_move_cost
14656 #undef TARGET_RTX_COSTS
14657 #define TARGET_RTX_COSTS avr_rtx_costs
14658 #undef TARGET_ADDRESS_COST
14659 #define TARGET_ADDRESS_COST avr_address_cost
14660 #undef TARGET_MACHINE_DEPENDENT_REORG
14661 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
14662 #undef TARGET_FUNCTION_ARG
14663 #define TARGET_FUNCTION_ARG avr_function_arg
14664 #undef TARGET_FUNCTION_ARG_ADVANCE
14665 #define TARGET_FUNCTION_ARG_ADVANCE avr_function_arg_advance
14667 #undef TARGET_SET_CURRENT_FUNCTION
14668 #define TARGET_SET_CURRENT_FUNCTION avr_set_current_function
14670 #undef TARGET_RETURN_IN_MEMORY
14671 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
14673 #undef TARGET_STRICT_ARGUMENT_NAMING
14674 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
14676 #undef TARGET_BUILTIN_SETJMP_FRAME_VALUE
14677 #define TARGET_BUILTIN_SETJMP_FRAME_VALUE avr_builtin_setjmp_frame_value
14679 #undef TARGET_CONDITIONAL_REGISTER_USAGE
14680 #define TARGET_CONDITIONAL_REGISTER_USAGE avr_conditional_register_usage
14682 #undef TARGET_HARD_REGNO_MODE_OK
14683 #define TARGET_HARD_REGNO_MODE_OK avr_hard_regno_mode_ok
14684 #undef TARGET_HARD_REGNO_SCRATCH_OK
14685 #define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok
14686 #undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED
14687 #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
14688 avr_hard_regno_call_part_clobbered
14690 #undef TARGET_CASE_VALUES_THRESHOLD
14691 #define TARGET_CASE_VALUES_THRESHOLD avr_case_values_threshold
14693 #undef TARGET_FRAME_POINTER_REQUIRED
14694 #define TARGET_FRAME_POINTER_REQUIRED avr_frame_pointer_required_p
14695 #undef TARGET_CAN_ELIMINATE
14696 #define TARGET_CAN_ELIMINATE avr_can_eliminate
14698 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
14699 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS avr_allocate_stack_slots_for_args
14701 #undef TARGET_WARN_FUNC_RETURN
14702 #define TARGET_WARN_FUNC_RETURN avr_warn_func_return
14704 #undef TARGET_CLASS_LIKELY_SPILLED_P
14705 #define TARGET_CLASS_LIKELY_SPILLED_P avr_class_likely_spilled_p
14707 #undef TARGET_OPTION_OVERRIDE
14708 #define TARGET_OPTION_OVERRIDE avr_option_override
14710 #undef TARGET_CANNOT_MODIFY_JUMPS_P
14711 #define TARGET_CANNOT_MODIFY_JUMPS_P avr_cannot_modify_jumps_p
14713 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
14714 #define TARGET_FUNCTION_OK_FOR_SIBCALL avr_function_ok_for_sibcall
14716 #undef TARGET_INIT_BUILTINS
14717 #define TARGET_INIT_BUILTINS avr_init_builtins
14719 #undef TARGET_BUILTIN_DECL
14720 #define TARGET_BUILTIN_DECL avr_builtin_decl
14722 #undef TARGET_EXPAND_BUILTIN
14723 #define TARGET_EXPAND_BUILTIN avr_expand_builtin
14725 #undef TARGET_FOLD_BUILTIN
14726 #define TARGET_FOLD_BUILTIN avr_fold_builtin
14728 #undef TARGET_SCALAR_MODE_SUPPORTED_P
14729 #define TARGET_SCALAR_MODE_SUPPORTED_P avr_scalar_mode_supported_p
14731 #undef TARGET_BUILD_BUILTIN_VA_LIST
14732 #define TARGET_BUILD_BUILTIN_VA_LIST avr_build_builtin_va_list
14734 #undef TARGET_FIXED_POINT_SUPPORTED_P
14735 #define TARGET_FIXED_POINT_SUPPORTED_P hook_bool_void_true
14737 #undef TARGET_CONVERT_TO_TYPE
14738 #define TARGET_CONVERT_TO_TYPE avr_convert_to_type
14740 #undef TARGET_LRA_P
14741 #define TARGET_LRA_P hook_bool_void_false
14743 #undef TARGET_ADDR_SPACE_SUBSET_P
14744 #define TARGET_ADDR_SPACE_SUBSET_P avr_addr_space_subset_p
14746 #undef TARGET_ADDR_SPACE_CONVERT
14747 #define TARGET_ADDR_SPACE_CONVERT avr_addr_space_convert
14749 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
14750 #define TARGET_ADDR_SPACE_ADDRESS_MODE avr_addr_space_address_mode
14752 #undef TARGET_ADDR_SPACE_POINTER_MODE
14753 #define TARGET_ADDR_SPACE_POINTER_MODE avr_addr_space_pointer_mode
14755 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
14756 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
14757 avr_addr_space_legitimate_address_p
14759 #undef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
14760 #define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS avr_addr_space_legitimize_address
14762 #undef TARGET_ADDR_SPACE_DIAGNOSE_USAGE
14763 #define TARGET_ADDR_SPACE_DIAGNOSE_USAGE avr_addr_space_diagnose_usage
14765 #undef TARGET_MODE_DEPENDENT_ADDRESS_P
14766 #define TARGET_MODE_DEPENDENT_ADDRESS_P avr_mode_dependent_address_p
14768 #undef TARGET_PRINT_OPERAND
14769 #define TARGET_PRINT_OPERAND avr_print_operand
14770 #undef TARGET_PRINT_OPERAND_ADDRESS
14771 #define TARGET_PRINT_OPERAND_ADDRESS avr_print_operand_address
14772 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
14773 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P avr_print_operand_punct_valid_p
14775 #undef TARGET_USE_BY_PIECES_INFRASTRUCTURE_P
14776 #define TARGET_USE_BY_PIECES_INFRASTRUCTURE_P \
14777 avr_use_by_pieces_infrastructure_p
14779 #undef TARGET_LEGITIMATE_COMBINED_INSN
14780 #define TARGET_LEGITIMATE_COMBINED_INSN avr_legitimate_combined_insn
14782 #undef TARGET_STARTING_FRAME_OFFSET
14783 #define TARGET_STARTING_FRAME_OFFSET avr_starting_frame_offset
14785 struct gcc_target targetm = TARGET_INITIALIZER;
14788 #include "gt-avr.h"