1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2    Copyright (C) 1998-2021 Free Software Foundation, Inc.
3    Contributed by Denis Chertykov (chertykov@gmail.com)
4 
5    This file is part of GCC.
6 
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.
11 
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.
16 
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/>.  */
20 
21 #define IN_TARGET_CODE 1
22 
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 "builtins.h"
55 #include "context.h"
56 #include "tree-pass.h"
57 #include "print-rtl.h"
58 #include "rtl-iter.h"
59 
60 /* This file should be included last.  */
61 #include "target-def.h"
62 
63 /* Maximal allowed offset for an address in the LD command */
64 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
65 
66 /* Return true if STR starts with PREFIX and false, otherwise.  */
67 #define STR_PREFIX_P(STR,PREFIX) (strncmp (STR, PREFIX, strlen (PREFIX)) == 0)
68 
69 /* The 4 bits starting at SECTION_MACH_DEP are reserved to store the
70    address space where data is to be located.
71    As the only non-generic address spaces are all located in flash,
72    this can be used to test if data shall go into some .progmem* section.
73    This must be the rightmost field of machine dependent section flags.  */
74 #define AVR_SECTION_PROGMEM (0xf * SECTION_MACH_DEP)
75 
76 /* Similar 4-bit region for SYMBOL_REF_FLAGS.  */
77 #define AVR_SYMBOL_FLAG_PROGMEM (0xf * SYMBOL_FLAG_MACH_DEP)
78 
79 /* Similar 4-bit region in SYMBOL_REF_FLAGS:
80    Set address-space AS in SYMBOL_REF_FLAGS of SYM  */
81 #define AVR_SYMBOL_SET_ADDR_SPACE(SYM,AS)                       \
82   do {                                                          \
83     SYMBOL_REF_FLAGS (sym) &= ~AVR_SYMBOL_FLAG_PROGMEM;         \
84     SYMBOL_REF_FLAGS (sym) |= (AS) * SYMBOL_FLAG_MACH_DEP;      \
85   } while (0)
86 
87 /* Read address-space from SYMBOL_REF_FLAGS of SYM  */
88 #define AVR_SYMBOL_GET_ADDR_SPACE(SYM)                          \
89   ((SYMBOL_REF_FLAGS (sym) & AVR_SYMBOL_FLAG_PROGMEM)           \
90    / SYMBOL_FLAG_MACH_DEP)
91 
92 /* (AVR_TINY only): Symbol has attribute progmem */
93 #define AVR_SYMBOL_FLAG_TINY_PM \
94   (SYMBOL_FLAG_MACH_DEP << 7)
95 
96 /* (AVR_TINY only): Symbol has attribute absdata */
97 #define AVR_SYMBOL_FLAG_TINY_ABSDATA \
98   (SYMBOL_FLAG_MACH_DEP << 8)
99 
100 #define TINY_ADIW(REG1, REG2, I)                                \
101     "subi " #REG1 ",lo8(-(" #I "))" CR_TAB                      \
102     "sbci " #REG2 ",hi8(-(" #I "))"
103 
104 #define TINY_SBIW(REG1, REG2, I)                                \
105     "subi " #REG1 ",lo8((" #I "))" CR_TAB                       \
106     "sbci " #REG2 ",hi8((" #I "))"
107 
108 #define AVR_TMP_REGNO (AVR_TINY ? TMP_REGNO_TINY : TMP_REGNO)
109 #define AVR_ZERO_REGNO (AVR_TINY ? ZERO_REGNO_TINY : ZERO_REGNO)
110 
111 /* Known address spaces.  The order must be the same as in the respective
112    enum from avr.h (or designated initialized must be used).  */
113 const avr_addrspace_t avr_addrspace[ADDR_SPACE_COUNT] =
114 {
115   { ADDR_SPACE_RAM,  0, 2, "", 0, NULL },
116   { ADDR_SPACE_FLASH,  1, 2, "__flash",   0, ".progmem.data" },
117   { ADDR_SPACE_FLASH1, 1, 2, "__flash1",  1, ".progmem1.data" },
118   { ADDR_SPACE_FLASH2, 1, 2, "__flash2",  2, ".progmem2.data" },
119   { ADDR_SPACE_FLASH3, 1, 2, "__flash3",  3, ".progmem3.data" },
120   { ADDR_SPACE_FLASH4, 1, 2, "__flash4",  4, ".progmem4.data" },
121   { ADDR_SPACE_FLASH5, 1, 2, "__flash5",  5, ".progmem5.data" },
122   { ADDR_SPACE_MEMX, 1, 3, "__memx",  0, ".progmemx.data" },
123 };
124 
125 
126 /* Holding RAM addresses of some SFRs used by the compiler and that
127    are unique over all devices in an architecture like 'avr4'.  */
128 
129 typedef struct
130 {
131   /* SREG: The processor status */
132   int sreg;
133 
134   /* RAMPX, RAMPY, RAMPD and CCP of XMEGA */
135   int ccp;
136   int rampd;
137   int rampx;
138   int rampy;
139 
140   /* RAMPZ: The high byte of 24-bit address used with ELPM */
141   int rampz;
142 
143   /* SP: The stack pointer and its low and high byte */
144   int sp_l;
145   int sp_h;
146 } avr_addr_t;
147 
148 static avr_addr_t avr_addr;
149 
150 
151 /* Prototypes for local helper functions.  */
152 
153 static const char* out_movqi_r_mr (rtx_insn *, rtx[], int*);
154 static const char* out_movhi_r_mr (rtx_insn *, rtx[], int*);
155 static const char* out_movsi_r_mr (rtx_insn *, rtx[], int*);
156 static const char* out_movqi_mr_r (rtx_insn *, rtx[], int*);
157 static const char* out_movhi_mr_r (rtx_insn *, rtx[], int*);
158 static const char* out_movsi_mr_r (rtx_insn *, rtx[], int*);
159 
160 static int get_sequence_length (rtx_insn *insns);
161 static int sequent_regs_live (void);
162 static const char *ptrreg_to_str (int);
163 static const char *cond_string (enum rtx_code);
164 static int avr_num_arg_regs (machine_mode, const_tree);
165 static int avr_operand_rtx_cost (rtx, machine_mode, enum rtx_code,
166                                  int, bool);
167 static void output_reload_in_const (rtx*, rtx, int*, bool);
168 static struct machine_function * avr_init_machine_status (void);
169 
170 
171 /* Prototypes for hook implementors if needed before their implementation.  */
172 
173 static bool avr_rtx_costs (rtx, machine_mode, int, int, int*, bool);
174 
175 
176 /* Allocate registers from r25 to r8 for parameters for function calls.  */
177 #define FIRST_CUM_REG 26
178 
179 /* Last call saved register */
180 #define LAST_CALLEE_SAVED_REG (AVR_TINY ? 19 : 17)
181 
182 /* Implicit target register of LPM instruction (R0) */
183 extern GTY(()) rtx lpm_reg_rtx;
184 rtx lpm_reg_rtx;
185 
186 /* (Implicit) address register of LPM instruction (R31:R30 = Z) */
187 extern GTY(()) rtx lpm_addr_reg_rtx;
188 rtx lpm_addr_reg_rtx;
189 
190 /* Temporary register RTX (reg:QI TMP_REGNO) */
191 extern GTY(()) rtx tmp_reg_rtx;
192 rtx tmp_reg_rtx;
193 
194 /* Zeroed register RTX (reg:QI ZERO_REGNO) */
195 extern GTY(()) rtx zero_reg_rtx;
196 rtx zero_reg_rtx;
197 
198 /* RTXs for all general purpose registers as QImode */
199 extern GTY(()) rtx all_regs_rtx[32];
200 rtx all_regs_rtx[32];
201 
202 /* SREG, the processor status */
203 extern GTY(()) rtx sreg_rtx;
204 rtx sreg_rtx;
205 
206 /* RAMP* special function registers */
207 extern GTY(()) rtx rampd_rtx;
208 extern GTY(()) rtx rampx_rtx;
209 extern GTY(()) rtx rampy_rtx;
210 extern GTY(()) rtx rampz_rtx;
211 rtx rampd_rtx;
212 rtx rampx_rtx;
213 rtx rampy_rtx;
214 rtx rampz_rtx;
215 
216 /* RTX containing the strings "" and "e", respectively */
217 static GTY(()) rtx xstring_empty;
218 static GTY(()) rtx xstring_e;
219 
220 /* Current architecture.  */
221 const avr_arch_t *avr_arch;
222 
223 /* Unnamed sections associated to __attribute__((progmem)) aka. PROGMEM
224    or to address space __flash* or __memx.  Only used as singletons inside
225    avr_asm_select_section, but it must not be local there because of GTY.  */
226 static GTY(()) section *progmem_section[ADDR_SPACE_COUNT];
227 
228 /* Condition for insns/expanders from avr-dimode.md.  */
229 bool avr_have_dimode = true;
230 
231 /* To track if code will use .bss and/or .data.  */
232 bool avr_need_clear_bss_p = false;
233 bool avr_need_copy_data_p = false;
234 
235 
236 /* Transform UP into lowercase and write the result to LO.
237    You must provide enough space for LO.  Return LO.  */
238 
239 static char*
avr_tolower(char * lo,const char * up)240 avr_tolower (char *lo, const char *up)
241 {
242   char *lo0 = lo;
243 
244   for (; *up; up++, lo++)
245     *lo = TOLOWER (*up);
246 
247   *lo = '\0';
248 
249   return lo0;
250 }
251 
252 
253 /* Constraint helper function.  XVAL is a CONST_INT or a CONST_DOUBLE.
254    Return true if the least significant N_BYTES bytes of XVAL all have a
255    popcount in POP_MASK and false, otherwise.  POP_MASK represents a subset
256    of integers which contains an integer N iff bit N of POP_MASK is set.  */
257 
258 bool
avr_popcount_each_byte(rtx xval,int n_bytes,int pop_mask)259 avr_popcount_each_byte (rtx xval, int n_bytes, int pop_mask)
260 {
261   machine_mode mode = GET_MODE (xval);
262 
263   if (VOIDmode == mode)
264     mode = SImode;
265 
266   for (int i = 0; i < n_bytes; i++)
267     {
268       rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
269       unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
270 
271       if ((pop_mask & (1 << popcount_hwi (val8))) == 0)
272         return false;
273     }
274 
275   return true;
276 }
277 
278 
279 /* Access some RTX as INT_MODE.  If X is a CONST_FIXED we can get
280    the bit representation of X by "casting" it to CONST_INT.  */
281 
282 rtx
avr_to_int_mode(rtx x)283 avr_to_int_mode (rtx x)
284 {
285   machine_mode mode = GET_MODE (x);
286 
287   return VOIDmode == mode
288     ? x
289     : simplify_gen_subreg (int_mode_for_mode (mode).require (), x, mode, 0);
290 }
291 
292 namespace {
293 
294 static const pass_data avr_pass_data_recompute_notes =
295 {
296   RTL_PASS,      // type
297   "",            // name (will be patched)
298   OPTGROUP_NONE, // optinfo_flags
299   TV_DF_SCAN,    // tv_id
300   0,             // properties_required
301   0,             // properties_provided
302   0,             // properties_destroyed
303   0,             // todo_flags_start
304   TODO_df_finish | TODO_df_verify // todo_flags_finish
305 };
306 
307 
308 class avr_pass_recompute_notes : public rtl_opt_pass
309 {
310 public:
avr_pass_recompute_notes(gcc::context * ctxt,const char * name)311   avr_pass_recompute_notes (gcc::context *ctxt, const char *name)
312     : rtl_opt_pass (avr_pass_data_recompute_notes, ctxt)
313   {
314     this->name = name;
315   }
316 
execute(function *)317   virtual unsigned int execute (function*)
318   {
319     df_note_add_problem ();
320     df_analyze ();
321 
322     return 0;
323   }
324 }; // avr_pass_recompute_notes
325 
326 static const pass_data avr_pass_data_casesi =
327 {
328   RTL_PASS,      // type
329   "",            // name (will be patched)
330   OPTGROUP_NONE, // optinfo_flags
331   TV_DF_SCAN,    // tv_id
332   0,             // properties_required
333   0,             // properties_provided
334   0,             // properties_destroyed
335   0,             // todo_flags_start
336   0              // todo_flags_finish
337 };
338 
339 
340 class avr_pass_casesi : public rtl_opt_pass
341 {
342 public:
avr_pass_casesi(gcc::context * ctxt,const char * name)343   avr_pass_casesi (gcc::context *ctxt, const char *name)
344     : rtl_opt_pass (avr_pass_data_casesi, ctxt)
345   {
346     this->name = name;
347   }
348 
349   void avr_rest_of_handle_casesi (function*);
350 
gate(function *)351   virtual bool gate (function*) { return optimize > 0; }
352 
execute(function * func)353   virtual unsigned int execute (function *func)
354   {
355     avr_rest_of_handle_casesi (func);
356 
357     return 0;
358   }
359 }; // avr_pass_casesi
360 
361 } // anon namespace
362 
363 rtl_opt_pass*
make_avr_pass_recompute_notes(gcc::context * ctxt)364 make_avr_pass_recompute_notes (gcc::context *ctxt)
365 {
366   return new avr_pass_recompute_notes (ctxt, "avr-notes-free-cfg");
367 }
368 
369 rtl_opt_pass*
make_avr_pass_casesi(gcc::context * ctxt)370 make_avr_pass_casesi (gcc::context *ctxt)
371 {
372   return new avr_pass_casesi (ctxt, "avr-casesi");
373 }
374 
375 
376 /* Make one parallel insn with all the patterns from insns i[0]..i[5].  */
377 
378 static rtx_insn*
avr_parallel_insn_from_insns(rtx_insn * i[6])379 avr_parallel_insn_from_insns (rtx_insn *i[6])
380 {
381   rtvec vec = gen_rtvec (6, PATTERN (i[0]), PATTERN (i[1]), PATTERN (i[2]),
382                          PATTERN (i[3]), PATTERN (i[4]), PATTERN (i[5]));
383   start_sequence();
384   emit (gen_rtx_PARALLEL (VOIDmode, vec));
385   rtx_insn *insn = get_insns();
386   end_sequence();
387 
388   return insn;
389 }
390 
391 
392 /* Return true if we see an insn stream generated by casesi expander together
393    with an extension to SImode of the switch value.
394 
395    If this is the case, fill in the insns from casesi to INSNS[1..5] and
396    the SImode extension to INSNS[0].  Moreover, extract the operands of
397    pattern casesi_<mode>_sequence forged from the sequence to recog_data.  */
398 
399 static bool
avr_is_casesi_sequence(basic_block bb,rtx_insn * insn,rtx_insn * insns[6])400 avr_is_casesi_sequence (basic_block bb, rtx_insn *insn, rtx_insn *insns[6])
401 {
402   rtx set_5, set_0;
403 
404   /* A first and quick test for a casesi sequences.  As a side effect of
405      the test, harvest respective insns to INSNS[0..5].  */
406 
407   if (!(JUMP_P (insns[5] = insn)
408         // casesi is the only insn that comes up with UNSPEC_INDEX_JMP,
409         // hence the following test ensures that we are actually dealing
410         // with code from casesi.
411         && (set_5 = single_set (insns[5]))
412         && UNSPEC == GET_CODE (SET_SRC (set_5))
413         && UNSPEC_INDEX_JMP == XINT (SET_SRC (set_5), 1)
414 
415         && (insns[4] = prev_real_insn (insns[5]))
416         && (insns[3] = prev_real_insn (insns[4]))
417         && (insns[2] = prev_real_insn (insns[3]))
418         && (insns[1] = prev_real_insn (insns[2]))
419 
420         // Insn prior to casesi.
421         && (insns[0] = prev_real_insn (insns[1]))
422         && (set_0 = single_set (insns[0]))
423         && extend_operator (SET_SRC (set_0), SImode)))
424     {
425       return false;
426     }
427 
428   if (dump_file)
429     {
430       fprintf (dump_file, ";; Sequence from casesi in "
431                "[bb %d]:\n\n", bb->index);
432       for (int i = 0; i < 6; i++)
433         print_rtl_single (dump_file, insns[i]);
434     }
435 
436   /* We have to deal with quite some operands.  Extracting them by hand
437      would be tedious, therefore wrap the insn patterns into a parallel,
438      run recog against it and then use insn extract to get the operands. */
439 
440   rtx_insn *xinsn = avr_parallel_insn_from_insns (insns);
441 
442   INSN_CODE (xinsn) = recog (PATTERN (xinsn), xinsn, NULL /* num_clobbers */);
443 
444   /* Failing to recognize means that someone changed the casesi expander or
445      that some passes prior to this one performed some unexpected changes.
446      Gracefully drop such situations instead of aborting.  */
447 
448   if (INSN_CODE (xinsn) < 0)
449     {
450       if (dump_file)
451         fprintf (dump_file, ";; Sequence not recognized, giving up.\n\n");
452 
453       return false;
454     }
455 
456   gcc_assert (CODE_FOR_casesi_qi_sequence == INSN_CODE (xinsn)
457               || CODE_FOR_casesi_hi_sequence == INSN_CODE (xinsn));
458 
459   extract_insn (xinsn);
460 
461   // Assert on the anatomy of xinsn's operands we are going to work with.
462 
463   gcc_assert (recog_data.n_operands == 11);
464   gcc_assert (recog_data.n_dups == 4);
465 
466   if (dump_file)
467     {
468       fprintf (dump_file, ";; Operands extracted:\n");
469       for (int i = 0; i < recog_data.n_operands; i++)
470         avr_fdump (dump_file, ";; $%d = %r\n", i, recog_data.operand[i]);
471       fprintf (dump_file, "\n");
472     }
473 
474   return true;
475 }
476 
477 
478 /* Perform some extra checks on operands of casesi_<mode>_sequence.
479    Not all operand dependencies can be described by means of predicates.
480    This function performs left over checks and should always return true.
481    Returning false means that someone changed the casesi expander but did
482    not adjust casesi_<mode>_sequence.  */
483 
484 bool
avr_casei_sequence_check_operands(rtx * xop)485 avr_casei_sequence_check_operands (rtx *xop)
486 {
487   rtx sub_5 = NULL_RTX;
488 
489   if (AVR_HAVE_EIJMP_EICALL
490       // The last clobber op of the tablejump.
491       && xop[8] == all_regs_rtx[24])
492     {
493       // $6 is: (subreg:SI ($5) 0)
494       sub_5 = xop[6];
495     }
496 
497   if (!AVR_HAVE_EIJMP_EICALL
498       // $6 is: (plus:HI (subreg:SI ($5) 0)
499       //                 (label_ref ($3)))
500       && PLUS == GET_CODE (xop[6])
501       && LABEL_REF == GET_CODE (XEXP (xop[6], 1))
502       && rtx_equal_p (xop[3], XEXP (XEXP (xop[6], 1), 0))
503       // The last clobber op of the tablejump.
504       && xop[8] == const0_rtx)
505     {
506       sub_5 = XEXP (xop[6], 0);
507     }
508 
509   if (sub_5
510       && SUBREG_P (sub_5)
511       && SUBREG_BYTE (sub_5) == 0
512       && rtx_equal_p (xop[5], SUBREG_REG (sub_5)))
513     return true;
514 
515   if (dump_file)
516     fprintf (dump_file, "\n;; Failed condition for casesi_<mode>_sequence\n\n");
517 
518   return false;
519 }
520 
521 
522 /* INSNS[1..5] is a sequence as generated by casesi and INSNS[0] is an
523    extension of an 8-bit or 16-bit integer to SImode.  XOP contains the
524    operands of INSNS as extracted by insn_extract from pattern
525    casesi_<mode>_sequence:
526 
527       $0: SImode reg switch value as result of $9.
528       $1: Negative of smallest index in switch.
529       $2: Number of entries in switch.
530       $3: Label to table.
531       $4: Label if out-of-bounds.
532       $5: $0 + $1.
533       $6: 3-byte PC: subreg:HI ($5) + label_ref ($3)
534           2-byte PC: subreg:HI ($5)
535       $7: HI reg index into table (Z or pseudo)
536       $8: R24 or const0_rtx (to be clobbered)
537       $9: Extension to SImode of an 8-bit or 16-bit integer register $10.
538       $10: QImode or HImode register input of $9.
539 
540    Try to optimize this sequence, i.e. use the original HImode / QImode
541    switch value instead of SImode.  */
542 
543 static void
avr_optimize_casesi(rtx_insn * insns[6],rtx * xop)544 avr_optimize_casesi (rtx_insn *insns[6], rtx *xop)
545 {
546   // Original mode of the switch value; this is QImode or HImode.
547   machine_mode mode = GET_MODE (xop[10]);
548 
549   // How the original switch value was extended to SImode; this is
550   // SIGN_EXTEND or ZERO_EXTEND.
551   enum rtx_code code = GET_CODE (xop[9]);
552 
553   // Lower index, upper index (plus one) and range of case calues.
554   HOST_WIDE_INT low_idx = -INTVAL (xop[1]);
555   HOST_WIDE_INT num_idx = INTVAL (xop[2]);
556   HOST_WIDE_INT hig_idx = low_idx + num_idx;
557 
558   // Maximum ranges of (un)signed QImode resp. HImode.
559   unsigned umax = QImode == mode ? 0xff : 0xffff;
560   int imax = QImode == mode ? 0x7f : 0x7fff;
561   int imin = -imax - 1;
562 
563   // Testing the case range and whether it fits into the range of the
564   // (un)signed mode.  This test should actually always pass because it
565   // makes no sense to have case values outside the mode range.  Notice
566   // that case labels which are unreachable because they are outside the
567   // mode of the switch value (e.g. "case -1" for uint8_t) have already
568   // been thrown away by the middle-end.
569 
570   if (SIGN_EXTEND == code
571       && low_idx >= imin
572       && hig_idx <= imax)
573     {
574       // ok
575     }
576   else if (ZERO_EXTEND == code
577            && low_idx >= 0
578            && (unsigned) hig_idx <= umax)
579     {
580       // ok
581     }
582   else
583     {
584       if (dump_file)
585         fprintf (dump_file, ";; Case ranges too big, giving up.\n\n");
586       return;
587     }
588 
589   // Do normalization of switch value $10 and out-of-bound check in its
590   // original mode instead of in SImode.  Use a newly created pseudo.
591   // This will replace insns[1..2].
592 
593   start_sequence();
594 
595   rtx_insn *seq1, *seq2, *last1, *last2;
596 
597   rtx reg = copy_to_mode_reg (mode, xop[10]);
598 
599   rtx (*gen_add)(rtx,rtx,rtx) = QImode == mode ? gen_addqi3 : gen_addhi3;
600   rtx (*gen_cmp)(rtx,rtx) = QImode == mode ? gen_cmpqi3 : gen_cmphi3;
601 
602   emit_insn (gen_add (reg, reg, gen_int_mode (-low_idx, mode)));
603   emit_insn (gen_cmp (reg, gen_int_mode (num_idx, mode)));
604 
605   seq1 = get_insns();
606   last1 = get_last_insn();
607   end_sequence();
608 
609   emit_insn_before (seq1, insns[1]);
610 
611   // After the out-of-bounds test and corresponding branch, use a
612   // 16-bit index.  If QImode is used, extend it to HImode first.
613   // This will replace insns[4].
614 
615   start_sequence();
616 
617   if (QImode == mode)
618     reg = force_reg (HImode, gen_rtx_fmt_e (code, HImode, reg));
619 
620   rtx pat_4 = AVR_3_BYTE_PC
621     ? gen_movhi (xop[7], reg)
622     : gen_addhi3 (xop[7], reg, gen_rtx_LABEL_REF (VOIDmode, xop[3]));
623 
624   emit_insn (pat_4);
625 
626   seq2 = get_insns();
627   last2 = get_last_insn();
628   end_sequence();
629 
630   emit_insn_after (seq2, insns[4]);
631 
632   if (dump_file)
633     {
634       fprintf (dump_file, ";; New insns: ");
635 
636       for (rtx_insn *insn = seq1; ; insn = NEXT_INSN (insn))
637         {
638           fprintf (dump_file, "%d, ", INSN_UID (insn));
639           if (insn == last1)
640             break;
641         }
642       for (rtx_insn *insn = seq2; ; insn = NEXT_INSN (insn))
643         {
644           fprintf (dump_file, "%d%s", INSN_UID (insn),
645                    insn == last2 ? ".\n\n" : ", ");
646           if (insn == last2)
647             break;
648         }
649 
650       fprintf (dump_file, ";; Deleting insns: %d, %d, %d.\n\n",
651                INSN_UID (insns[1]), INSN_UID (insns[2]), INSN_UID (insns[4]));
652     }
653 
654   // Pseudodelete the SImode and subreg of SImode insns.  We don't care
655   // about the extension insns[0]: Its result is now unused and other
656   // passes will clean it up.
657 
658   SET_INSN_DELETED (insns[1]);
659   SET_INSN_DELETED (insns[2]);
660   SET_INSN_DELETED (insns[4]);
661 }
662 
663 
664 void
avr_rest_of_handle_casesi(function * func)665 avr_pass_casesi::avr_rest_of_handle_casesi (function *func)
666 {
667   basic_block bb;
668 
669   FOR_EACH_BB_FN (bb, func)
670     {
671       rtx_insn *insn, *insns[6];
672 
673       FOR_BB_INSNS (bb, insn)
674         {
675           if (avr_is_casesi_sequence (bb, insn, insns))
676             {
677               avr_optimize_casesi (insns, recog_data.operand);
678             }
679         }
680     }
681 }
682 
683 
684 /* Set `avr_arch' as specified by `-mmcu='.
685    Return true on success.  */
686 
687 static bool
avr_set_core_architecture(void)688 avr_set_core_architecture (void)
689 {
690   /* Search for mcu core architecture.  */
691 
692   if (!avr_mmcu)
693     avr_mmcu = AVR_MMCU_DEFAULT;
694 
695   avr_arch = &avr_arch_types[0];
696 
697   for (const avr_mcu_t *mcu = avr_mcu_types; ; mcu++)
698     {
699       if (mcu->name == NULL)
700         {
701           /* Reached the end of `avr_mcu_types'.  This should actually never
702              happen as options are provided by device-specs.  It could be a
703              typo in a device-specs or calling the compiler proper directly
704              with -mmcu=<device>. */
705 
706           error ("unknown core architecture %qs specified with %qs",
707                  avr_mmcu, "-mmcu=");
708           avr_inform_core_architectures ();
709           break;
710         }
711       else if (strcmp (mcu->name, avr_mmcu) == 0
712                // Is this a proper architecture ?
713 	       && mcu->macro == NULL)
714         {
715           avr_arch = &avr_arch_types[mcu->arch_id];
716           if (avr_n_flash < 0)
717             avr_n_flash = 1 + (mcu->flash_size - 1) / 0x10000;
718 
719           return true;
720         }
721     }
722 
723   return false;
724 }
725 
726 
727 /* Implement `TARGET_OPTION_OVERRIDE'.  */
728 
729 static void
avr_option_override(void)730 avr_option_override (void)
731 {
732   /* caller-save.c looks for call-clobbered hard registers that are assigned
733      to pseudos that cross calls and tries so save-restore them around calls
734      in order to reduce the number of stack slots needed.
735 
736      This might lead to situations where reload is no more able to cope
737      with the challenge of AVR's very few address registers and fails to
738      perform the requested spills.  */
739 
740   if (avr_strict_X)
741     flag_caller_saves = 0;
742 
743   /* Unwind tables currently require a frame pointer for correctness,
744      see toplev.c:process_options().  */
745 
746   if ((flag_unwind_tables
747        || flag_non_call_exceptions
748        || flag_asynchronous_unwind_tables)
749       && !ACCUMULATE_OUTGOING_ARGS)
750     {
751       flag_omit_frame_pointer = 0;
752     }
753 
754   if (flag_pic == 1)
755     warning (OPT_fpic, "%<-fpic%> is not supported");
756   if (flag_pic == 2)
757     warning (OPT_fPIC, "%<-fPIC%> is not supported");
758   if (flag_pie == 1)
759     warning (OPT_fpie, "%<-fpie%> is not supported");
760   if (flag_pie == 2)
761     warning (OPT_fPIE, "%<-fPIE%> is not supported");
762 
763 #if !defined (HAVE_AS_AVR_MGCCISR_OPTION)
764   avr_gasisr_prologues = 0;
765 #endif
766 
767   if (!avr_set_core_architecture())
768     return;
769 
770   /* Sould be set by avr-common.c */
771   gcc_assert (avr_long_double >= avr_double && avr_double >= 32);
772 
773   /* RAM addresses of some SFRs common to all devices in respective arch. */
774 
775   /* SREG: Status Register containing flags like I (global IRQ) */
776   avr_addr.sreg = 0x3F + avr_arch->sfr_offset;
777 
778   /* RAMPZ: Address' high part when loading via ELPM */
779   avr_addr.rampz = 0x3B + avr_arch->sfr_offset;
780 
781   avr_addr.rampy = 0x3A + avr_arch->sfr_offset;
782   avr_addr.rampx = 0x39 + avr_arch->sfr_offset;
783   avr_addr.rampd = 0x38 + avr_arch->sfr_offset;
784   avr_addr.ccp = (AVR_TINY ? 0x3C : 0x34) + avr_arch->sfr_offset;
785 
786   /* SP: Stack Pointer (SP_H:SP_L) */
787   avr_addr.sp_l = 0x3D + avr_arch->sfr_offset;
788   avr_addr.sp_h = avr_addr.sp_l + 1;
789 
790   init_machine_status = avr_init_machine_status;
791 
792   avr_log_set_avr_log();
793 }
794 
795 /* Function to set up the backend function structure.  */
796 
797 static struct machine_function *
avr_init_machine_status(void)798 avr_init_machine_status (void)
799 {
800   return ggc_cleared_alloc<machine_function> ();
801 }
802 
803 
804 /* Implement `INIT_EXPANDERS'.  */
805 /* The function works like a singleton.  */
806 
807 void
avr_init_expanders(void)808 avr_init_expanders (void)
809 {
810   for (int regno = 0; regno < 32; regno ++)
811     all_regs_rtx[regno] = gen_rtx_REG (QImode, regno);
812 
813   lpm_reg_rtx  = all_regs_rtx[LPM_REGNO];
814   tmp_reg_rtx  = all_regs_rtx[AVR_TMP_REGNO];
815   zero_reg_rtx = all_regs_rtx[AVR_ZERO_REGNO];
816 
817   lpm_addr_reg_rtx = gen_rtx_REG (HImode, REG_Z);
818 
819   sreg_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.sreg));
820   rampd_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampd));
821   rampx_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampx));
822   rampy_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampy));
823   rampz_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampz));
824 
825   xstring_empty = gen_rtx_CONST_STRING (VOIDmode, "");
826   xstring_e = gen_rtx_CONST_STRING (VOIDmode, "e");
827 
828   /* TINY core does not have regs r10-r16, but avr-dimode.md expects them
829      to be present */
830   if (AVR_TINY)
831     avr_have_dimode = false;
832 }
833 
834 
835 /* Implement `REGNO_REG_CLASS'.  */
836 /* Return register class for register R.  */
837 
838 enum reg_class
avr_regno_reg_class(int r)839 avr_regno_reg_class (int r)
840 {
841   static const enum reg_class reg_class_tab[] =
842     {
843       R0_REG,
844       /* r1 - r15 */
845       NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
846       NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
847       NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
848       NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
849       /* r16 - r23 */
850       SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
851       SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
852       /* r24, r25 */
853       ADDW_REGS, ADDW_REGS,
854       /* X: r26, 27 */
855       POINTER_X_REGS, POINTER_X_REGS,
856       /* Y: r28, r29 */
857       POINTER_Y_REGS, POINTER_Y_REGS,
858       /* Z: r30, r31 */
859       POINTER_Z_REGS, POINTER_Z_REGS,
860       /* SP: SPL, SPH */
861       STACK_REG, STACK_REG
862     };
863 
864   if (r <= 33)
865     return reg_class_tab[r];
866 
867   return ALL_REGS;
868 }
869 
870 
871 /* Implement `TARGET_SCALAR_MODE_SUPPORTED_P'.  */
872 
873 static bool
avr_scalar_mode_supported_p(scalar_mode mode)874 avr_scalar_mode_supported_p (scalar_mode mode)
875 {
876   if (ALL_FIXED_POINT_MODE_P (mode))
877     return true;
878 
879   if (PSImode == mode)
880     return true;
881 
882   return default_scalar_mode_supported_p (mode);
883 }
884 
885 
886 /* Return TRUE if DECL is a VAR_DECL located in flash and FALSE, otherwise.  */
887 
888 static bool
avr_decl_flash_p(tree decl)889 avr_decl_flash_p (tree decl)
890 {
891   if (TREE_CODE (decl) != VAR_DECL
892       || TREE_TYPE (decl) == error_mark_node)
893     {
894       return false;
895     }
896 
897   return !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (decl)));
898 }
899 
900 
901 /* Return TRUE if DECL is a VAR_DECL located in the 24-bit flash
902    address space and FALSE, otherwise.  */
903 
904 static bool
avr_decl_memx_p(tree decl)905 avr_decl_memx_p (tree decl)
906 {
907   if (TREE_CODE (decl) != VAR_DECL
908       || TREE_TYPE (decl) == error_mark_node)
909     {
910       return false;
911     }
912 
913   return (ADDR_SPACE_MEMX == TYPE_ADDR_SPACE (TREE_TYPE (decl)));
914 }
915 
916 
917 /* Return TRUE if X is a MEM rtx located in flash and FALSE, otherwise.  */
918 
919 bool
avr_mem_flash_p(rtx x)920 avr_mem_flash_p (rtx x)
921 {
922   return (MEM_P (x)
923           && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x)));
924 }
925 
926 
927 /* Return TRUE if X is a MEM rtx located in the 24-bit flash
928    address space and FALSE, otherwise.  */
929 
930 bool
avr_mem_memx_p(rtx x)931 avr_mem_memx_p (rtx x)
932 {
933   return (MEM_P (x)
934           && ADDR_SPACE_MEMX == MEM_ADDR_SPACE (x));
935 }
936 
937 
938 /* A helper for the subsequent function attribute used to dig for
939    attribute 'name' in a FUNCTION_DECL or FUNCTION_TYPE */
940 
941 static inline int
avr_lookup_function_attribute1(const_tree func,const char * name)942 avr_lookup_function_attribute1 (const_tree func, const char *name)
943 {
944   if (FUNCTION_DECL == TREE_CODE (func))
945     {
946       if (NULL_TREE != lookup_attribute (name, DECL_ATTRIBUTES (func)))
947         {
948           return true;
949         }
950 
951       func = TREE_TYPE (func);
952     }
953 
954   gcc_assert (TREE_CODE (func) == FUNCTION_TYPE
955               || TREE_CODE (func) == METHOD_TYPE);
956 
957   return NULL_TREE != lookup_attribute (name, TYPE_ATTRIBUTES (func));
958 }
959 
960 /* Return nonzero if FUNC is a naked function.  */
961 
962 static int
avr_naked_function_p(tree func)963 avr_naked_function_p (tree func)
964 {
965   return avr_lookup_function_attribute1 (func, "naked");
966 }
967 
968 /* Return nonzero if FUNC is an interrupt function as specified
969    by the "interrupt" attribute.  */
970 
971 static int
avr_interrupt_function_p(tree func)972 avr_interrupt_function_p (tree func)
973 {
974   return avr_lookup_function_attribute1 (func, "interrupt");
975 }
976 
977 /* Return nonzero if FUNC is a signal function as specified
978    by the "signal" attribute.  */
979 
980 static int
avr_signal_function_p(tree func)981 avr_signal_function_p (tree func)
982 {
983   return avr_lookup_function_attribute1 (func, "signal");
984 }
985 
986 /* Return nonzero if FUNC is an OS_task function.  */
987 
988 static int
avr_OS_task_function_p(tree func)989 avr_OS_task_function_p (tree func)
990 {
991   return avr_lookup_function_attribute1 (func, "OS_task");
992 }
993 
994 /* Return nonzero if FUNC is an OS_main function.  */
995 
996 static int
avr_OS_main_function_p(tree func)997 avr_OS_main_function_p (tree func)
998 {
999   return avr_lookup_function_attribute1 (func, "OS_main");
1000 }
1001 
1002 
1003 /* Return nonzero if FUNC is a no_gccisr function as specified
1004    by the "no_gccisr" attribute.  */
1005 
1006 static int
avr_no_gccisr_function_p(tree func)1007 avr_no_gccisr_function_p (tree func)
1008 {
1009   return avr_lookup_function_attribute1 (func, "no_gccisr");
1010 }
1011 
1012 /* Implement `TARGET_SET_CURRENT_FUNCTION'.  */
1013 /* Sanity cheching for above function attributes.  */
1014 
1015 static void
avr_set_current_function(tree decl)1016 avr_set_current_function (tree decl)
1017 {
1018   if (decl == NULL_TREE
1019       || current_function_decl == NULL_TREE
1020       || current_function_decl == error_mark_node
1021       || ! cfun->machine
1022       || cfun->machine->attributes_checked_p)
1023     return;
1024 
1025   location_t loc = DECL_SOURCE_LOCATION (decl);
1026 
1027   cfun->machine->is_naked = avr_naked_function_p (decl);
1028   cfun->machine->is_signal = avr_signal_function_p (decl);
1029   cfun->machine->is_interrupt = avr_interrupt_function_p (decl);
1030   cfun->machine->is_OS_task = avr_OS_task_function_p (decl);
1031   cfun->machine->is_OS_main = avr_OS_main_function_p (decl);
1032   cfun->machine->is_no_gccisr = avr_no_gccisr_function_p (decl);
1033 
1034   const char *isr = cfun->machine->is_interrupt ? "interrupt" : "signal";
1035 
1036   /* Too much attributes make no sense as they request conflicting features. */
1037 
1038   if (cfun->machine->is_OS_task
1039       && (cfun->machine->is_signal || cfun->machine->is_interrupt))
1040     error_at (loc, "function attributes %qs and %qs are mutually exclusive",
1041               "OS_task", isr);
1042 
1043   if (cfun->machine->is_OS_main
1044       && (cfun->machine->is_signal || cfun->machine->is_interrupt))
1045     error_at (loc, "function attributes %qs and %qs are mutually exclusive",
1046               "OS_main", isr);
1047 
1048   if (cfun->machine->is_interrupt || cfun->machine->is_signal)
1049     {
1050       tree args = TYPE_ARG_TYPES (TREE_TYPE (decl));
1051       tree ret = TREE_TYPE (TREE_TYPE (decl));
1052       const char *name;
1053 
1054       name = DECL_ASSEMBLER_NAME_SET_P (decl)
1055         ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))
1056         : IDENTIFIER_POINTER (DECL_NAME (decl));
1057 
1058       /* Skip a leading '*' that might still prefix the assembler name,
1059          e.g. in non-LTO runs.  */
1060 
1061       name = default_strip_name_encoding (name);
1062 
1063       /* Interrupt handlers must be  void __vector (void)  functions.  */
1064 
1065       if (args && TREE_CODE (TREE_VALUE (args)) != VOID_TYPE)
1066         error_at (loc, "%qs function cannot have arguments", isr);
1067 
1068       if (TREE_CODE (ret) != VOID_TYPE)
1069         error_at (loc, "%qs function cannot return a value", isr);
1070 
1071 #if defined WITH_AVRLIBC
1072       /* Silently ignore 'signal' if 'interrupt' is present.  AVR-LibC startet
1073          using this when it switched from SIGNAL and INTERRUPT to ISR.  */
1074 
1075       if (cfun->machine->is_interrupt)
1076         cfun->machine->is_signal = 0;
1077 
1078       /* If the function has the 'signal' or 'interrupt' attribute, ensure
1079          that the name of the function is "__vector_NN" so as to catch
1080          when the user misspells the vector name.  */
1081 
1082       if (!STR_PREFIX_P (name, "__vector"))
1083         warning_at (loc, OPT_Wmisspelled_isr, "%qs appears to be a misspelled "
1084                     "%qs handler, missing %<__vector%> prefix", name, isr);
1085 #endif // AVR-LibC naming conventions
1086     }
1087 
1088 #if defined WITH_AVRLIBC
1089   // Common problem is using "ISR" without first including avr/interrupt.h.
1090   const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
1091   name = default_strip_name_encoding (name);
1092   if (strcmp ("ISR", name) == 0
1093       || strcmp ("INTERRUPT", name) == 0
1094       || strcmp ("SIGNAL", name) == 0)
1095     {
1096       warning_at (loc, OPT_Wmisspelled_isr, "%qs is a reserved identifier"
1097                   " in AVR-LibC.  Consider %<#include <avr/interrupt.h>%>"
1098                   " before using the %qs macro", name, name);
1099     }
1100 #endif // AVR-LibC naming conventions
1101 
1102   /* Don't print the above diagnostics more than once.  */
1103 
1104   cfun->machine->attributes_checked_p = 1;
1105 }
1106 
1107 
1108 /* Implement `ACCUMULATE_OUTGOING_ARGS'.  */
1109 
1110 int
avr_accumulate_outgoing_args(void)1111 avr_accumulate_outgoing_args (void)
1112 {
1113   if (!cfun)
1114     return TARGET_ACCUMULATE_OUTGOING_ARGS;
1115 
1116   /* FIXME: For setjmp and in avr_builtin_setjmp_frame_value we don't know
1117         what offset is correct.  In some cases it is relative to
1118         virtual_outgoing_args_rtx and in others it is relative to
1119         virtual_stack_vars_rtx.  For example code see
1120             gcc.c-torture/execute/built-in-setjmp.c
1121             gcc.c-torture/execute/builtins/sprintf-chk.c   */
1122 
1123   return (TARGET_ACCUMULATE_OUTGOING_ARGS
1124           && !(cfun->calls_setjmp
1125                || cfun->has_nonlocal_label));
1126 }
1127 
1128 
1129 /* Report contribution of accumulated outgoing arguments to stack size.  */
1130 
1131 static inline int
avr_outgoing_args_size(void)1132 avr_outgoing_args_size (void)
1133 {
1134   return (ACCUMULATE_OUTGOING_ARGS
1135 	  ? (HOST_WIDE_INT) crtl->outgoing_args_size : 0);
1136 }
1137 
1138 
1139 /* Implement TARGET_STARTING_FRAME_OFFSET.  */
1140 /* This is the offset from the frame pointer register to the first stack slot
1141    that contains a variable living in the frame.  */
1142 
1143 static HOST_WIDE_INT
avr_starting_frame_offset(void)1144 avr_starting_frame_offset (void)
1145 {
1146   return 1 + avr_outgoing_args_size ();
1147 }
1148 
1149 
1150 /* Return the number of hard registers to push/pop in the prologue/epilogue
1151    of the current function, and optionally store these registers in SET.  */
1152 
1153 static int
avr_regs_to_save(HARD_REG_SET * set)1154 avr_regs_to_save (HARD_REG_SET *set)
1155 {
1156   int count;
1157   int int_or_sig_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1158 
1159   if (set)
1160     CLEAR_HARD_REG_SET (*set);
1161   count = 0;
1162 
1163   /* No need to save any registers if the function never returns or
1164      has the "OS_task" or "OS_main" attribute.  */
1165 
1166   if (TREE_THIS_VOLATILE (current_function_decl)
1167       || cfun->machine->is_OS_task
1168       || cfun->machine->is_OS_main)
1169     return 0;
1170 
1171   for (int reg = 0; reg < 32; reg++)
1172     {
1173       /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
1174          any global register variables.  */
1175 
1176       if (fixed_regs[reg])
1177         continue;
1178 
1179       if ((int_or_sig_p && !crtl->is_leaf && call_used_or_fixed_reg_p (reg))
1180           || (df_regs_ever_live_p (reg)
1181               && (int_or_sig_p || !call_used_or_fixed_reg_p (reg))
1182               /* Don't record frame pointer registers here.  They are treated
1183                  indivitually in prologue.  */
1184               && !(frame_pointer_needed
1185                    && (reg == REG_Y || reg == REG_Y + 1))))
1186         {
1187           if (set)
1188             SET_HARD_REG_BIT (*set, reg);
1189           count++;
1190         }
1191     }
1192   return count;
1193 }
1194 
1195 
1196 /* Implement `TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS' */
1197 
1198 static bool
avr_allocate_stack_slots_for_args(void)1199 avr_allocate_stack_slots_for_args (void)
1200 {
1201   return !cfun->machine->is_naked;
1202 }
1203 
1204 
1205 /* Return true if register FROM can be eliminated via register TO.  */
1206 
1207 static bool
avr_can_eliminate(const int from ATTRIBUTE_UNUSED,const int to)1208 avr_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
1209 {
1210   return ((frame_pointer_needed && to == FRAME_POINTER_REGNUM)
1211           || !frame_pointer_needed);
1212 }
1213 
1214 
1215 /* Implement `TARGET_WARN_FUNC_RETURN'.  */
1216 
1217 static bool
avr_warn_func_return(tree decl)1218 avr_warn_func_return (tree decl)
1219 {
1220   /* Naked functions are implemented entirely in assembly, including the
1221      return sequence, so suppress warnings about this.  */
1222 
1223   return !avr_naked_function_p (decl);
1224 }
1225 
1226 /* Compute offset between arg_pointer and frame_pointer.  */
1227 
1228 int
avr_initial_elimination_offset(int from,int to)1229 avr_initial_elimination_offset (int from, int to)
1230 {
1231   if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
1232     return 0;
1233   else
1234     {
1235       int offset = frame_pointer_needed ? 2 : 0;
1236       int avr_pc_size = AVR_HAVE_EIJMP_EICALL ? 3 : 2;
1237 
1238       // If FROM is ARG_POINTER_REGNUM, we are not in an ISR as ISRs
1239       // might not have arguments.  Hence the following is not affected
1240       // by gasisr prologues.
1241       offset += avr_regs_to_save (NULL);
1242       return (get_frame_size () + avr_outgoing_args_size()
1243               + avr_pc_size + 1 + offset);
1244     }
1245 }
1246 
1247 
1248 /* Helper for the function below.  */
1249 
1250 static void
avr_adjust_type_node(tree * node,machine_mode mode,int sat_p)1251 avr_adjust_type_node (tree *node, machine_mode mode, int sat_p)
1252 {
1253   *node = make_node (FIXED_POINT_TYPE);
1254   TYPE_SATURATING (*node) = sat_p;
1255   TYPE_UNSIGNED (*node) = UNSIGNED_FIXED_POINT_MODE_P (mode);
1256   TYPE_IBIT (*node) = GET_MODE_IBIT (mode);
1257   TYPE_FBIT (*node) = GET_MODE_FBIT (mode);
1258   TYPE_PRECISION (*node) = GET_MODE_BITSIZE (mode);
1259   SET_TYPE_ALIGN (*node, 8);
1260   SET_TYPE_MODE (*node, mode);
1261 
1262   layout_type (*node);
1263 }
1264 
1265 
1266 /* Implement `TARGET_BUILD_BUILTIN_VA_LIST'.  */
1267 
1268 static tree
avr_build_builtin_va_list(void)1269 avr_build_builtin_va_list (void)
1270 {
1271   /* avr-modes.def adjusts [U]TA to be 64-bit modes with 48 fractional bits.
1272      This is more appropriate for the 8-bit machine AVR than 128-bit modes.
1273      The ADJUST_IBIT/FBIT are handled in toplev:init_adjust_machine_modes()
1274      which is auto-generated by genmodes, but the compiler assigns [U]DAmode
1275      to the long long accum modes instead of the desired [U]TAmode.
1276 
1277      Fix this now, right after node setup in tree.c:build_common_tree_nodes().
1278      This must run before c-cppbuiltin.c:builtin_define_fixed_point_constants()
1279      which built-in defines macros like __ULLACCUM_FBIT__ that are used by
1280      libgcc to detect IBIT and FBIT.  */
1281 
1282   avr_adjust_type_node (&ta_type_node, TAmode, 0);
1283   avr_adjust_type_node (&uta_type_node, UTAmode, 0);
1284   avr_adjust_type_node (&sat_ta_type_node, TAmode, 1);
1285   avr_adjust_type_node (&sat_uta_type_node, UTAmode, 1);
1286 
1287   unsigned_long_long_accum_type_node = uta_type_node;
1288   long_long_accum_type_node = ta_type_node;
1289   sat_unsigned_long_long_accum_type_node = sat_uta_type_node;
1290   sat_long_long_accum_type_node = sat_ta_type_node;
1291 
1292   /* Dispatch to the default handler.  */
1293 
1294   return std_build_builtin_va_list ();
1295 }
1296 
1297 
1298 /* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3-byte PC).
1299    This is return address of function.  */
1300 
1301 rtx
avr_return_addr_rtx(int count,rtx tem)1302 avr_return_addr_rtx (int count, rtx tem)
1303 {
1304   rtx r;
1305 
1306   /* Can only return this function's return address. Others not supported.  */
1307   if (count)
1308     return NULL;
1309 
1310   if (AVR_3_BYTE_PC)
1311     {
1312       r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+2");
1313       warning (0, "%<builtin_return_address%> contains only 2 bytes"
1314                " of address");
1315     }
1316   else
1317     r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+1");
1318 
1319   cfun->machine->use_L__stack_usage = 1;
1320 
1321   r = gen_rtx_PLUS (Pmode, tem, r);
1322   r = gen_frame_mem (Pmode, memory_address (Pmode, r));
1323   r = gen_rtx_ROTATE (HImode, r, GEN_INT (8));
1324   return r;
1325 }
1326 
1327 /* Return 1 if the function epilogue is just a single "ret".  */
1328 
1329 int
avr_simple_epilogue(void)1330 avr_simple_epilogue (void)
1331 {
1332   return (! frame_pointer_needed
1333           && get_frame_size () == 0
1334           && avr_outgoing_args_size() == 0
1335           && avr_regs_to_save (NULL) == 0
1336           && ! cfun->machine->is_interrupt
1337           && ! cfun->machine->is_signal
1338           && ! cfun->machine->is_naked
1339           && ! TREE_THIS_VOLATILE (current_function_decl));
1340 }
1341 
1342 /* This function checks sequence of live registers.  */
1343 
1344 static int
sequent_regs_live(void)1345 sequent_regs_live (void)
1346 {
1347   int live_seq = 0;
1348   int cur_seq = 0;
1349 
1350   for (int reg = 0; reg <= LAST_CALLEE_SAVED_REG; ++reg)
1351     {
1352       if (fixed_regs[reg])
1353         {
1354           /* Don't recognize sequences that contain global register
1355              variables.  */
1356 
1357           if (live_seq != 0)
1358             return 0;
1359           else
1360             continue;
1361         }
1362 
1363       if (!call_used_or_fixed_reg_p (reg))
1364         {
1365           if (df_regs_ever_live_p (reg))
1366             {
1367               ++live_seq;
1368               ++cur_seq;
1369             }
1370           else
1371             cur_seq = 0;
1372         }
1373     }
1374 
1375   if (!frame_pointer_needed)
1376     {
1377       if (df_regs_ever_live_p (REG_Y))
1378         {
1379           ++live_seq;
1380           ++cur_seq;
1381         }
1382       else
1383         cur_seq = 0;
1384 
1385       if (df_regs_ever_live_p (REG_Y + 1))
1386         {
1387           ++live_seq;
1388           ++cur_seq;
1389         }
1390       else
1391         cur_seq = 0;
1392     }
1393   else
1394     {
1395       cur_seq += 2;
1396       live_seq += 2;
1397     }
1398   return (cur_seq == live_seq) ? live_seq : 0;
1399 }
1400 
1401 namespace {
1402 static const pass_data avr_pass_data_pre_proep =
1403 {
1404   RTL_PASS,      // type
1405   "",            // name (will be patched)
1406   OPTGROUP_NONE, // optinfo_flags
1407   TV_DF_SCAN,    // tv_id
1408   0,             // properties_required
1409   0,             // properties_provided
1410   0,             // properties_destroyed
1411   0,             // todo_flags_start
1412   0              // todo_flags_finish
1413 };
1414 
1415 
1416 class avr_pass_pre_proep : public rtl_opt_pass
1417 {
1418 public:
avr_pass_pre_proep(gcc::context * ctxt,const char * name)1419   avr_pass_pre_proep (gcc::context *ctxt, const char *name)
1420     : rtl_opt_pass (avr_pass_data_pre_proep, ctxt)
1421   {
1422     this->name = name;
1423   }
1424 
1425   void compute_maybe_gasisr (function*);
1426 
execute(function * fun)1427   virtual unsigned int execute (function *fun)
1428   {
1429     if (avr_gasisr_prologues
1430         // Whether this function is an ISR worth scanning at all.
1431         && !fun->machine->is_no_gccisr
1432         && (fun->machine->is_interrupt
1433             || fun->machine->is_signal)
1434         && !cfun->machine->is_naked
1435         // Paranoia: Non-local gotos and labels that might escape.
1436         && !cfun->calls_setjmp
1437         && !cfun->has_nonlocal_label
1438         && !cfun->has_forced_label_in_static)
1439       {
1440         compute_maybe_gasisr (fun);
1441       }
1442 
1443     return 0;
1444   }
1445 
1446 }; // avr_pass_pre_proep
1447 
1448 } // anon namespace
1449 
1450 rtl_opt_pass*
make_avr_pass_pre_proep(gcc::context * ctxt)1451 make_avr_pass_pre_proep (gcc::context *ctxt)
1452 {
1453   return new avr_pass_pre_proep (ctxt, "avr-pre-proep");
1454 }
1455 
1456 
1457 /* Set fun->machine->gasisr.maybe provided we don't find anything that
1458    prohibits GAS generating parts of ISR prologues / epilogues for us.  */
1459 
1460 void
compute_maybe_gasisr(function * fun)1461 avr_pass_pre_proep::compute_maybe_gasisr (function *fun)
1462 {
1463   // Don't use BB iterators so that we see JUMP_TABLE_DATA.
1464 
1465   for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
1466     {
1467       // Transparent calls always use [R]CALL and are filtered out by GAS.
1468       // ISRs don't use -mcall-prologues, hence what remains to be filtered
1469       // out are open coded (tail) calls.
1470 
1471       if (CALL_P (insn))
1472         return;
1473 
1474       // __tablejump2__ clobbers something and is targeted by JMP so
1475       // that GAS won't see its usage.
1476 
1477       if (AVR_HAVE_JMP_CALL
1478           && JUMP_TABLE_DATA_P (insn))
1479         return;
1480 
1481       // Non-local gotos not seen in *FUN.
1482 
1483       if (JUMP_P (insn)
1484           && find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
1485         return;
1486     }
1487 
1488   fun->machine->gasisr.maybe = 1;
1489 }
1490 
1491 
1492 /* Obtain the length sequence of insns.  */
1493 
1494 int
get_sequence_length(rtx_insn * insns)1495 get_sequence_length (rtx_insn *insns)
1496 {
1497   int length = 0;
1498 
1499   for (rtx_insn *insn = insns; insn; insn = NEXT_INSN (insn))
1500     length += get_attr_length (insn);
1501 
1502   return length;
1503 }
1504 
1505 
1506 /*  Implement `INCOMING_RETURN_ADDR_RTX'.  */
1507 
1508 rtx
avr_incoming_return_addr_rtx(void)1509 avr_incoming_return_addr_rtx (void)
1510 {
1511   /* The return address is at the top of the stack.  Note that the push
1512      was via post-decrement, which means the actual address is off by one.  */
1513   return gen_frame_mem (HImode, plus_constant (Pmode, stack_pointer_rtx, 1));
1514 }
1515 
1516 
1517 /* Unset a bit in *SET.  If successful, return the respective bit number.
1518    Otherwise, return -1 and *SET is unaltered.  */
1519 
1520 static int
avr_hregs_split_reg(HARD_REG_SET * set)1521 avr_hregs_split_reg (HARD_REG_SET *set)
1522 {
1523   for (int regno = 0; regno < 32; regno++)
1524     if (TEST_HARD_REG_BIT (*set, regno))
1525       {
1526         // Don't remove a register from *SET which might indicate that
1527         // some RAMP* register might need ISR prologue / epilogue treatment.
1528 
1529         if (AVR_HAVE_RAMPX
1530             && (REG_X == regno || REG_X + 1 == regno)
1531             && TEST_HARD_REG_BIT (*set, REG_X)
1532             && TEST_HARD_REG_BIT (*set, REG_X + 1))
1533           continue;
1534 
1535         if (AVR_HAVE_RAMPY
1536             && !frame_pointer_needed
1537             && (REG_Y == regno || REG_Y + 1 == regno)
1538             && TEST_HARD_REG_BIT (*set, REG_Y)
1539             && TEST_HARD_REG_BIT (*set, REG_Y + 1))
1540           continue;
1541 
1542         if (AVR_HAVE_RAMPZ
1543             && (REG_Z == regno || REG_Z + 1 == regno)
1544             && TEST_HARD_REG_BIT (*set, REG_Z)
1545             && TEST_HARD_REG_BIT (*set, REG_Z + 1))
1546           continue;
1547 
1548         CLEAR_HARD_REG_BIT (*set, regno);
1549         return regno;
1550       }
1551 
1552   return -1;
1553 }
1554 
1555 
1556 /*  Helper for expand_prologue.  Emit a push of a byte register.  */
1557 
1558 static void
emit_push_byte(unsigned regno,bool frame_related_p)1559 emit_push_byte (unsigned regno, bool frame_related_p)
1560 {
1561   rtx mem, reg;
1562   rtx_insn *insn;
1563 
1564   mem = gen_rtx_POST_DEC (HImode, stack_pointer_rtx);
1565   mem = gen_frame_mem (QImode, mem);
1566   reg = gen_rtx_REG (QImode, regno);
1567 
1568   insn = emit_insn (gen_rtx_SET (mem, reg));
1569   if (frame_related_p)
1570     RTX_FRAME_RELATED_P (insn) = 1;
1571 
1572   cfun->machine->stack_usage++;
1573 }
1574 
1575 
1576 /*  Helper for expand_prologue.  Emit a push of a SFR via register TREG.
1577     SFR is a MEM representing the memory location of the SFR.
1578     If CLR_P then clear the SFR after the push using zero_reg.  */
1579 
1580 static void
emit_push_sfr(rtx sfr,bool frame_related_p,bool clr_p,int treg)1581 emit_push_sfr (rtx sfr, bool frame_related_p, bool clr_p, int treg)
1582 {
1583   rtx_insn *insn;
1584 
1585   gcc_assert (MEM_P (sfr));
1586 
1587   /* IN treg, IO(SFR) */
1588   insn = emit_move_insn (all_regs_rtx[treg], sfr);
1589   if (frame_related_p)
1590     RTX_FRAME_RELATED_P (insn) = 1;
1591 
1592   /* PUSH treg */
1593   emit_push_byte (treg, frame_related_p);
1594 
1595   if (clr_p)
1596     {
1597       /* OUT IO(SFR), __zero_reg__ */
1598       insn = emit_move_insn (sfr, const0_rtx);
1599       if (frame_related_p)
1600         RTX_FRAME_RELATED_P (insn) = 1;
1601     }
1602 }
1603 
1604 static void
avr_prologue_setup_frame(HOST_WIDE_INT size,HARD_REG_SET set)1605 avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
1606 {
1607   rtx_insn *insn;
1608   bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1609   int live_seq = sequent_regs_live ();
1610 
1611   HOST_WIDE_INT size_max
1612     = (HOST_WIDE_INT) GET_MODE_MASK (AVR_HAVE_8BIT_SP ? QImode : Pmode);
1613 
1614   bool minimize = (TARGET_CALL_PROLOGUES
1615                    && size < size_max
1616                    && live_seq
1617                    && !isr_p
1618                    && !cfun->machine->is_OS_task
1619                    && !cfun->machine->is_OS_main
1620                    && !AVR_TINY);
1621 
1622   if (minimize
1623       && (frame_pointer_needed
1624           || avr_outgoing_args_size() > 8
1625           || (AVR_2_BYTE_PC && live_seq > 6)
1626           || live_seq > 7))
1627     {
1628       rtx pattern;
1629       int first_reg, reg, offset;
1630 
1631       emit_move_insn (gen_rtx_REG (HImode, REG_X),
1632                       gen_int_mode (size, HImode));
1633 
1634       pattern = gen_call_prologue_saves (gen_int_mode (live_seq, HImode),
1635                                          gen_int_mode (live_seq+size, HImode));
1636       insn = emit_insn (pattern);
1637       RTX_FRAME_RELATED_P (insn) = 1;
1638 
1639       /* Describe the effect of the unspec_volatile call to prologue_saves.
1640          Note that this formulation assumes that add_reg_note pushes the
1641          notes to the front.  Thus we build them in the reverse order of
1642          how we want dwarf2out to process them.  */
1643 
1644       /* The function does always set frame_pointer_rtx, but whether that
1645          is going to be permanent in the function is frame_pointer_needed.  */
1646 
1647       add_reg_note (insn, REG_CFA_ADJUST_CFA,
1648                     gen_rtx_SET ((frame_pointer_needed
1649 				  ? frame_pointer_rtx
1650 				  : stack_pointer_rtx),
1651                                  plus_constant (Pmode, stack_pointer_rtx,
1652                                                 -(size + live_seq))));
1653 
1654       /* Note that live_seq always contains r28+r29, but the other
1655          registers to be saved are all below 18.  */
1656 
1657       first_reg = (LAST_CALLEE_SAVED_REG + 1) - (live_seq - 2);
1658 
1659       for (reg = 29, offset = -live_seq + 1;
1660            reg >= first_reg;
1661            reg = (reg == 28 ? LAST_CALLEE_SAVED_REG : reg - 1), ++offset)
1662         {
1663           rtx m, r;
1664 
1665           m = gen_rtx_MEM (QImode, plus_constant (Pmode, stack_pointer_rtx,
1666                                                   offset));
1667           r = gen_rtx_REG (QImode, reg);
1668           add_reg_note (insn, REG_CFA_OFFSET, gen_rtx_SET (m, r));
1669         }
1670 
1671       cfun->machine->stack_usage += size + live_seq;
1672     }
1673   else /* !minimize */
1674     {
1675       for (int reg = 0; reg < 32; ++reg)
1676         if (TEST_HARD_REG_BIT (set, reg))
1677           emit_push_byte (reg, true);
1678 
1679       if (frame_pointer_needed
1680           && (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main)))
1681         {
1682           /* Push frame pointer.  Always be consistent about the
1683              ordering of pushes -- epilogue_restores expects the
1684              register pair to be pushed low byte first.  */
1685 
1686           emit_push_byte (REG_Y, true);
1687           emit_push_byte (REG_Y + 1, true);
1688         }
1689 
1690       if (frame_pointer_needed
1691           && size == 0)
1692         {
1693           insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
1694           RTX_FRAME_RELATED_P (insn) = 1;
1695         }
1696 
1697       if (size != 0)
1698         {
1699           /*  Creating a frame can be done by direct manipulation of the
1700               stack or via the frame pointer. These two methods are:
1701                   fp =  sp
1702                   fp -= size
1703                   sp =  fp
1704               or
1705                   sp -= size
1706                   fp =  sp    (*)
1707               the optimum method depends on function type, stack and
1708               frame size.  To avoid a complex logic, both methods are
1709               tested and shortest is selected.
1710 
1711               There is also the case where SIZE != 0 and no frame pointer is
1712               needed; this can occur if ACCUMULATE_OUTGOING_ARGS is on.
1713               In that case, insn (*) is not needed in that case.
1714               We use the X register as scratch. This is save because in X
1715               is call-clobbered.
1716                  In an interrupt routine, the case of SIZE != 0 together with
1717               !frame_pointer_needed can only occur if the function is not a
1718               leaf function and thus X has already been saved.  */
1719 
1720           int irq_state = -1;
1721           HOST_WIDE_INT size_cfa = size, neg_size;
1722           rtx_insn *fp_plus_insns;
1723           rtx fp, my_fp;
1724 
1725           gcc_assert (frame_pointer_needed
1726                       || !isr_p
1727                       || !crtl->is_leaf);
1728 
1729           fp = my_fp = (frame_pointer_needed
1730                         ? frame_pointer_rtx
1731                         : gen_rtx_REG (Pmode, REG_X));
1732 
1733           if (AVR_HAVE_8BIT_SP)
1734             {
1735               /* The high byte (r29) does not change:
1736                  Prefer SUBI (1 cycle) over SBIW (2 cycles, same size).  */
1737 
1738               my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
1739             }
1740 
1741           /* Cut down size and avoid size = 0 so that we don't run
1742              into ICE like PR52488 in the remainder.  */
1743 
1744           if (size > size_max)
1745             {
1746               /* Don't error so that insane code from newlib still compiles
1747                  and does not break building newlib.  As PR51345 is implemented
1748                  now, there are multilib variants with -msp8.
1749 
1750                  If user wants sanity checks he can use -Wstack-usage=
1751                  or similar options.
1752 
1753                  For CFA we emit the original, non-saturated size so that
1754                  the generic machinery is aware of the real stack usage and
1755                  will print the above diagnostic as expected.  */
1756 
1757               size = size_max;
1758             }
1759 
1760           size = trunc_int_for_mode (size, GET_MODE (my_fp));
1761           neg_size = trunc_int_for_mode (-size, GET_MODE (my_fp));
1762 
1763           /************  Method 1: Adjust frame pointer  ************/
1764 
1765           start_sequence ();
1766 
1767           /* Normally, the dwarf2out frame-related-expr interpreter does
1768              not expect to have the CFA change once the frame pointer is
1769              set up.  Thus, we avoid marking the move insn below and
1770              instead indicate that the entire operation is complete after
1771              the frame pointer subtraction is done.  */
1772 
1773           insn = emit_move_insn (fp, stack_pointer_rtx);
1774           if (frame_pointer_needed)
1775             {
1776               RTX_FRAME_RELATED_P (insn) = 1;
1777               add_reg_note (insn, REG_CFA_ADJUST_CFA,
1778                             gen_rtx_SET (fp, stack_pointer_rtx));
1779             }
1780 
1781           insn = emit_move_insn (my_fp, plus_constant (GET_MODE (my_fp),
1782                                                        my_fp, neg_size));
1783 
1784           if (frame_pointer_needed)
1785             {
1786               RTX_FRAME_RELATED_P (insn) = 1;
1787               add_reg_note (insn, REG_CFA_ADJUST_CFA,
1788                             gen_rtx_SET (fp, plus_constant (Pmode, fp,
1789 							    -size_cfa)));
1790             }
1791 
1792           /* Copy to stack pointer.  Note that since we've already
1793              changed the CFA to the frame pointer this operation
1794              need not be annotated if frame pointer is needed.
1795              Always move through unspec, see PR50063.
1796              For meaning of irq_state see movhi_sp_r insn.  */
1797 
1798           if (cfun->machine->is_interrupt)
1799             irq_state = 1;
1800 
1801           if (TARGET_NO_INTERRUPTS
1802               || cfun->machine->is_signal
1803               || cfun->machine->is_OS_main)
1804             irq_state = 0;
1805 
1806           if (AVR_HAVE_8BIT_SP)
1807             irq_state = 2;
1808 
1809           insn = emit_insn (gen_movhi_sp_r (stack_pointer_rtx,
1810                                             fp, GEN_INT (irq_state)));
1811           if (!frame_pointer_needed)
1812             {
1813               RTX_FRAME_RELATED_P (insn) = 1;
1814               add_reg_note (insn, REG_CFA_ADJUST_CFA,
1815                             gen_rtx_SET (stack_pointer_rtx,
1816                                          plus_constant (Pmode,
1817                                                         stack_pointer_rtx,
1818                                                         -size_cfa)));
1819             }
1820 
1821           fp_plus_insns = get_insns ();
1822           end_sequence ();
1823 
1824           /************  Method 2: Adjust Stack pointer  ************/
1825 
1826           /* Stack adjustment by means of RCALL . and/or PUSH __TMP_REG__
1827              can only handle specific offsets.  */
1828 
1829           int n_rcall = size / (AVR_3_BYTE_PC ? 3 : 2);
1830 
1831           if (avr_sp_immediate_operand (gen_int_mode (-size, HImode), HImode)
1832               // Don't use more than 3 RCALLs.
1833               && n_rcall <= 3)
1834             {
1835               rtx_insn *sp_plus_insns;
1836 
1837               start_sequence ();
1838 
1839               insn = emit_move_insn (stack_pointer_rtx,
1840                                      plus_constant (Pmode, stack_pointer_rtx,
1841                                                     -size));
1842               RTX_FRAME_RELATED_P (insn) = 1;
1843               add_reg_note (insn, REG_CFA_ADJUST_CFA,
1844                             gen_rtx_SET (stack_pointer_rtx,
1845                                          plus_constant (Pmode,
1846                                                         stack_pointer_rtx,
1847                                                         -size_cfa)));
1848               if (frame_pointer_needed)
1849                 {
1850                   insn = emit_move_insn (fp, stack_pointer_rtx);
1851                   RTX_FRAME_RELATED_P (insn) = 1;
1852                 }
1853 
1854               sp_plus_insns = get_insns ();
1855               end_sequence ();
1856 
1857               /************ Use shortest method  ************/
1858 
1859               emit_insn (get_sequence_length (sp_plus_insns)
1860                          < get_sequence_length (fp_plus_insns)
1861                          ? sp_plus_insns
1862                          : fp_plus_insns);
1863             }
1864           else
1865             {
1866               emit_insn (fp_plus_insns);
1867             }
1868 
1869           cfun->machine->stack_usage += size_cfa;
1870         } /* !minimize && size != 0 */
1871     } /* !minimize */
1872 }
1873 
1874 
1875 /*  Output function prologue.  */
1876 
1877 void
avr_expand_prologue(void)1878 avr_expand_prologue (void)
1879 {
1880   HARD_REG_SET set;
1881   HOST_WIDE_INT size;
1882 
1883   size = get_frame_size() + avr_outgoing_args_size();
1884 
1885   cfun->machine->stack_usage = 0;
1886 
1887   /* Prologue: naked.  */
1888   if (cfun->machine->is_naked)
1889     {
1890       return;
1891     }
1892 
1893   avr_regs_to_save (&set);
1894 
1895   if (cfun->machine->is_interrupt || cfun->machine->is_signal)
1896     {
1897       int treg = AVR_TMP_REGNO;
1898       /* Enable interrupts.  */
1899       if (cfun->machine->is_interrupt)
1900         emit_insn (gen_enable_interrupt ());
1901 
1902       if (cfun->machine->gasisr.maybe)
1903         {
1904           /* Let GAS PR21472 emit prologue preamble for us which handles SREG,
1905              ZERO_REG and TMP_REG and one additional, optional register for
1906              us in an optimal way.  This even scans through inline asm.  */
1907 
1908           cfun->machine->gasisr.yes = 1;
1909 
1910           // The optional reg or TMP_REG if we don't need one.  If we need one,
1911           // remove that reg from SET so that it's not puhed / popped twice.
1912           // We also use it below instead of TMP_REG in some places.
1913 
1914           treg = avr_hregs_split_reg (&set);
1915           if (treg < 0)
1916             treg = AVR_TMP_REGNO;
1917           cfun->machine->gasisr.regno = treg;
1918 
1919           // The worst case of pushes.  The exact number can be inferred
1920           // at assembly time by magic expression __gcc_isr.n_pushed.
1921           cfun->machine->stack_usage += 3 + (treg != AVR_TMP_REGNO);
1922 
1923           // Emit a Prologue chunk.  Epilogue chunk(s) might follow.
1924           // The final Done chunk is emit by final postscan.
1925           emit_insn (gen_gasisr (GEN_INT (GASISR_Prologue), GEN_INT (treg)));
1926         }
1927       else // !TARGET_GASISR_PROLOGUES: Classic, dumb prologue preamble.
1928         {
1929           /* Push zero reg.  */
1930           emit_push_byte (AVR_ZERO_REGNO, true);
1931 
1932           /* Push tmp reg.  */
1933           emit_push_byte (AVR_TMP_REGNO, true);
1934 
1935           /* Push SREG.  */
1936           /* ??? There's no dwarf2 column reserved for SREG.  */
1937           emit_push_sfr (sreg_rtx, false, false /* clr */, AVR_TMP_REGNO);
1938 
1939           /* Clear zero reg.  */
1940           emit_move_insn (zero_reg_rtx, const0_rtx);
1941 
1942           /* Prevent any attempt to delete the setting of ZERO_REG!  */
1943           emit_use (zero_reg_rtx);
1944         }
1945 
1946       /* Push and clear RAMPD/X/Y/Z if present and low-part register is used.
1947          ??? There are no dwarf2 columns reserved for RAMPD/X/Y/Z.  */
1948 
1949       if (AVR_HAVE_RAMPD)
1950         emit_push_sfr (rampd_rtx, false /* frame */, true /* clr */, treg);
1951 
1952       if (AVR_HAVE_RAMPX
1953           && TEST_HARD_REG_BIT (set, REG_X)
1954           && TEST_HARD_REG_BIT (set, REG_X + 1))
1955         {
1956           emit_push_sfr (rampx_rtx, false /* frame */, true /* clr */, treg);
1957         }
1958 
1959       if (AVR_HAVE_RAMPY
1960           && (frame_pointer_needed
1961               || (TEST_HARD_REG_BIT (set, REG_Y)
1962                   && TEST_HARD_REG_BIT (set, REG_Y + 1))))
1963         {
1964           emit_push_sfr (rampy_rtx, false /* frame */, true /* clr */, treg);
1965         }
1966 
1967       if (AVR_HAVE_RAMPZ
1968           && TEST_HARD_REG_BIT (set, REG_Z)
1969           && TEST_HARD_REG_BIT (set, REG_Z + 1))
1970         {
1971           emit_push_sfr (rampz_rtx, false /* frame */, AVR_HAVE_RAMPD, treg);
1972         }
1973     }  /* is_interrupt is_signal */
1974 
1975   avr_prologue_setup_frame (size, set);
1976 
1977   if (flag_stack_usage_info)
1978     current_function_static_stack_size
1979       = cfun->machine->stack_usage + INCOMING_FRAME_SP_OFFSET;
1980 }
1981 
1982 
1983 /* Implement `TARGET_ASM_FUNCTION_END_PROLOGUE'.  */
1984 /* Output summary at end of function prologue.  */
1985 
1986 static void
avr_asm_function_end_prologue(FILE * file)1987 avr_asm_function_end_prologue (FILE *file)
1988 {
1989   if (cfun->machine->is_naked)
1990     {
1991       fputs ("/* prologue: naked */\n", file);
1992     }
1993   else
1994     {
1995       if (cfun->machine->is_interrupt)
1996         {
1997           fputs ("/* prologue: Interrupt */\n", file);
1998         }
1999       else if (cfun->machine->is_signal)
2000         {
2001           fputs ("/* prologue: Signal */\n", file);
2002         }
2003       else
2004         fputs ("/* prologue: function */\n", file);
2005     }
2006 
2007   if (ACCUMULATE_OUTGOING_ARGS)
2008     fprintf (file, "/* outgoing args size = %d */\n",
2009              avr_outgoing_args_size());
2010 
2011   fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n",
2012            (HOST_WIDE_INT) get_frame_size());
2013 
2014   if (!cfun->machine->gasisr.yes)
2015     {
2016       fprintf (file, "/* stack size = %d */\n", cfun->machine->stack_usage);
2017       // Create symbol stack offset so all functions have it. Add 1 to stack
2018       // usage for offset so that SP + .L__stack_offset = return address.
2019       fprintf (file, ".L__stack_usage = %d\n", cfun->machine->stack_usage);
2020     }
2021   else
2022     {
2023       int used_by_gasisr = 3 + (cfun->machine->gasisr.regno != AVR_TMP_REGNO);
2024       int to = cfun->machine->stack_usage;
2025       int from = to - used_by_gasisr;
2026       // Number of pushed regs is only known at assembly-time.
2027       fprintf (file, "/* stack size = %d...%d */\n", from , to);
2028       fprintf (file, ".L__stack_usage = %d + __gcc_isr.n_pushed\n", from);
2029     }
2030 }
2031 
2032 
2033 /* Implement `EPILOGUE_USES'.  */
2034 
2035 int
avr_epilogue_uses(int regno ATTRIBUTE_UNUSED)2036 avr_epilogue_uses (int regno ATTRIBUTE_UNUSED)
2037 {
2038   if (reload_completed
2039       && cfun->machine
2040       && (cfun->machine->is_interrupt || cfun->machine->is_signal))
2041     return 1;
2042   return 0;
2043 }
2044 
2045 /*  Helper for avr_expand_epilogue.  Emit a pop of a byte register.  */
2046 
2047 static void
emit_pop_byte(unsigned regno)2048 emit_pop_byte (unsigned regno)
2049 {
2050   rtx mem, reg;
2051 
2052   mem = gen_rtx_PRE_INC (HImode, stack_pointer_rtx);
2053   mem = gen_frame_mem (QImode, mem);
2054   reg = gen_rtx_REG (QImode, regno);
2055 
2056   emit_insn (gen_rtx_SET (reg, mem));
2057 }
2058 
2059 /*  Output RTL epilogue.  */
2060 
2061 void
avr_expand_epilogue(bool sibcall_p)2062 avr_expand_epilogue (bool sibcall_p)
2063 {
2064   int live_seq;
2065   HARD_REG_SET set;
2066   int minimize;
2067   HOST_WIDE_INT size;
2068   bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
2069 
2070   size = get_frame_size() + avr_outgoing_args_size();
2071 
2072   /* epilogue: naked  */
2073   if (cfun->machine->is_naked)
2074     {
2075       gcc_assert (!sibcall_p);
2076 
2077       emit_jump_insn (gen_return ());
2078       return;
2079     }
2080 
2081   avr_regs_to_save (&set);
2082   live_seq = sequent_regs_live ();
2083 
2084   minimize = (TARGET_CALL_PROLOGUES
2085               && live_seq
2086               && !isr_p
2087               && !cfun->machine->is_OS_task
2088               && !cfun->machine->is_OS_main
2089               && !AVR_TINY);
2090 
2091   if (minimize
2092       && (live_seq > 4
2093           || frame_pointer_needed
2094           || size))
2095     {
2096       /*  Get rid of frame.  */
2097 
2098       if (!frame_pointer_needed)
2099         {
2100           emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
2101         }
2102 
2103       if (size)
2104         {
2105           emit_move_insn (frame_pointer_rtx,
2106                           plus_constant (Pmode, frame_pointer_rtx, size));
2107         }
2108 
2109       emit_insn (gen_epilogue_restores (gen_int_mode (live_seq, HImode)));
2110       return;
2111     }
2112 
2113   if (size)
2114     {
2115       /* Try two methods to adjust stack and select shortest.  */
2116 
2117       int irq_state = -1;
2118       rtx fp, my_fp;
2119       rtx_insn *fp_plus_insns;
2120       HOST_WIDE_INT size_max;
2121 
2122       gcc_assert (frame_pointer_needed
2123                   || !isr_p
2124                   || !crtl->is_leaf);
2125 
2126       fp = my_fp = (frame_pointer_needed
2127                     ? frame_pointer_rtx
2128                     : gen_rtx_REG (Pmode, REG_X));
2129 
2130       if (AVR_HAVE_8BIT_SP)
2131         {
2132           /* The high byte (r29) does not change:
2133              Prefer SUBI (1 cycle) over SBIW (2 cycles).  */
2134 
2135           my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
2136         }
2137 
2138       /* For rationale see comment in prologue generation.  */
2139 
2140       size_max = (HOST_WIDE_INT) GET_MODE_MASK (GET_MODE (my_fp));
2141       if (size > size_max)
2142         size = size_max;
2143       size = trunc_int_for_mode (size, GET_MODE (my_fp));
2144 
2145       /********** Method 1: Adjust fp register  **********/
2146 
2147       start_sequence ();
2148 
2149       if (!frame_pointer_needed)
2150         emit_move_insn (fp, stack_pointer_rtx);
2151 
2152       emit_move_insn (my_fp, plus_constant (GET_MODE (my_fp), my_fp, size));
2153 
2154       /* Copy to stack pointer.  */
2155 
2156       if (TARGET_NO_INTERRUPTS)
2157         irq_state = 0;
2158 
2159       if (AVR_HAVE_8BIT_SP)
2160         irq_state = 2;
2161 
2162       emit_insn (gen_movhi_sp_r (stack_pointer_rtx, fp,
2163                                  GEN_INT (irq_state)));
2164 
2165       fp_plus_insns = get_insns ();
2166       end_sequence ();
2167 
2168       /********** Method 2: Adjust Stack pointer  **********/
2169 
2170       if (avr_sp_immediate_operand (gen_int_mode (size, HImode), HImode))
2171         {
2172           rtx_insn *sp_plus_insns;
2173 
2174           start_sequence ();
2175 
2176           emit_move_insn (stack_pointer_rtx,
2177                           plus_constant (Pmode, stack_pointer_rtx, size));
2178 
2179           sp_plus_insns = get_insns ();
2180           end_sequence ();
2181 
2182           /************ Use shortest method  ************/
2183 
2184           emit_insn (get_sequence_length (sp_plus_insns)
2185                      < get_sequence_length (fp_plus_insns)
2186                      ? sp_plus_insns
2187                      : fp_plus_insns);
2188         }
2189       else
2190         emit_insn (fp_plus_insns);
2191     } /* size != 0 */
2192 
2193   if (frame_pointer_needed
2194       && !(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
2195     {
2196       /* Restore previous frame_pointer.  See avr_expand_prologue for
2197          rationale for not using pophi.  */
2198 
2199       emit_pop_byte (REG_Y + 1);
2200       emit_pop_byte (REG_Y);
2201     }
2202 
2203   /* Restore used registers.  */
2204 
2205   int treg = AVR_TMP_REGNO;
2206 
2207   if (isr_p
2208       && cfun->machine->gasisr.yes)
2209     {
2210       treg = cfun->machine->gasisr.regno;
2211       CLEAR_HARD_REG_BIT (set, treg);
2212     }
2213 
2214   for (int reg = 31; reg >= 0; --reg)
2215     if (TEST_HARD_REG_BIT (set, reg))
2216       emit_pop_byte (reg);
2217 
2218   if (isr_p)
2219     {
2220       /* Restore RAMPZ/Y/X/D using tmp_reg as scratch.
2221          The conditions to restore them must be tha same as in prologue.  */
2222 
2223       if (AVR_HAVE_RAMPZ
2224           && TEST_HARD_REG_BIT (set, REG_Z)
2225           && TEST_HARD_REG_BIT (set, REG_Z + 1))
2226         {
2227           emit_pop_byte (treg);
2228           emit_move_insn (rampz_rtx, all_regs_rtx[treg]);
2229         }
2230 
2231       if (AVR_HAVE_RAMPY
2232           && (frame_pointer_needed
2233               || (TEST_HARD_REG_BIT (set, REG_Y)
2234                   && TEST_HARD_REG_BIT (set, REG_Y + 1))))
2235         {
2236           emit_pop_byte (treg);
2237           emit_move_insn (rampy_rtx, all_regs_rtx[treg]);
2238         }
2239 
2240       if (AVR_HAVE_RAMPX
2241           && TEST_HARD_REG_BIT (set, REG_X)
2242           && TEST_HARD_REG_BIT (set, REG_X + 1))
2243         {
2244           emit_pop_byte (treg);
2245           emit_move_insn (rampx_rtx, all_regs_rtx[treg]);
2246         }
2247 
2248       if (AVR_HAVE_RAMPD)
2249         {
2250           emit_pop_byte (treg);
2251           emit_move_insn (rampd_rtx, all_regs_rtx[treg]);
2252         }
2253 
2254       if (cfun->machine->gasisr.yes)
2255         {
2256           // Emit an Epilogue chunk.
2257           emit_insn (gen_gasisr (GEN_INT (GASISR_Epilogue),
2258                                  GEN_INT (cfun->machine->gasisr.regno)));
2259         }
2260       else // !TARGET_GASISR_PROLOGUES
2261         {
2262           /* Restore SREG using tmp_reg as scratch.  */
2263 
2264           emit_pop_byte (AVR_TMP_REGNO);
2265           emit_move_insn (sreg_rtx, tmp_reg_rtx);
2266 
2267           /* Restore tmp REG.  */
2268           emit_pop_byte (AVR_TMP_REGNO);
2269 
2270           /* Restore zero REG.  */
2271           emit_pop_byte (AVR_ZERO_REGNO);
2272         }
2273     }
2274 
2275   if (!sibcall_p)
2276     emit_jump_insn (gen_return ());
2277 }
2278 
2279 
2280 /* Implement `TARGET_ASM_FUNCTION_BEGIN_EPILOGUE'.  */
2281 
2282 static void
avr_asm_function_begin_epilogue(FILE * file)2283 avr_asm_function_begin_epilogue (FILE *file)
2284 {
2285   app_disable();
2286   fprintf (file, "/* epilogue start */\n");
2287 }
2288 
2289 
2290 /* Implement `TARGET_CANNOT_MODITY_JUMPS_P'.  */
2291 
2292 static bool
avr_cannot_modify_jumps_p(void)2293 avr_cannot_modify_jumps_p (void)
2294 {
2295   /* Naked Functions must not have any instructions after
2296      their epilogue, see PR42240 */
2297 
2298   if (reload_completed
2299       && cfun->machine
2300       && cfun->machine->is_naked)
2301     {
2302       return true;
2303     }
2304 
2305   return false;
2306 }
2307 
2308 
2309 /* Implement `TARGET_MODE_DEPENDENT_ADDRESS_P'.  */
2310 
2311 static bool
avr_mode_dependent_address_p(const_rtx addr ATTRIBUTE_UNUSED,addr_space_t as)2312 avr_mode_dependent_address_p (const_rtx addr ATTRIBUTE_UNUSED, addr_space_t as)
2313 {
2314   /* FIXME:  Non-generic addresses are not mode-dependent in themselves.
2315        This hook just serves to hack around PR rtl-optimization/52543 by
2316        claiming that non-generic addresses were mode-dependent so that
2317        lower-subreg.c will skip these addresses.  lower-subreg.c sets up fake
2318        RTXes to probe SET and MEM costs and assumes that MEM is always in the
2319        generic address space which is not true.  */
2320 
2321   return !ADDR_SPACE_GENERIC_P (as);
2322 }
2323 
2324 
2325 /* Return true if rtx X is a CONST_INT, CONST or SYMBOL_REF
2326    address with the `absdata' variable attribute, i.e. respective
2327    data can be read / written by LDS / STS instruction.
2328    This is used only for AVR_TINY.  */
2329 
2330 static bool
avr_address_tiny_absdata_p(rtx x,machine_mode mode)2331 avr_address_tiny_absdata_p (rtx x, machine_mode mode)
2332 {
2333   if (CONST == GET_CODE (x))
2334     x = XEXP (XEXP (x, 0), 0);
2335 
2336   if (SYMBOL_REF_P (x))
2337     return SYMBOL_REF_FLAGS (x) & AVR_SYMBOL_FLAG_TINY_ABSDATA;
2338 
2339   if (CONST_INT_P (x)
2340       && IN_RANGE (INTVAL (x), 0, 0xc0 - GET_MODE_SIZE (mode)))
2341     return true;
2342 
2343   return false;
2344 }
2345 
2346 
2347 /* Helper function for `avr_legitimate_address_p'.  */
2348 
2349 static inline bool
avr_reg_ok_for_addr_p(rtx reg,addr_space_t as,RTX_CODE outer_code,bool strict)2350 avr_reg_ok_for_addr_p (rtx reg, addr_space_t as,
2351                        RTX_CODE outer_code, bool strict)
2352 {
2353   return (REG_P (reg)
2354           && (avr_regno_mode_code_ok_for_base_p (REGNO (reg), QImode,
2355                                                  as, outer_code, UNKNOWN)
2356               || (!strict
2357                   && REGNO (reg) >= FIRST_PSEUDO_REGISTER)));
2358 }
2359 
2360 
2361 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
2362    machine for a memory operand of mode MODE.  */
2363 
2364 static bool
avr_legitimate_address_p(machine_mode mode,rtx x,bool strict)2365 avr_legitimate_address_p (machine_mode mode, rtx x, bool strict)
2366 {
2367   bool ok = CONSTANT_ADDRESS_P (x);
2368 
2369   switch (GET_CODE (x))
2370     {
2371     case REG:
2372       ok = avr_reg_ok_for_addr_p (x, ADDR_SPACE_GENERIC,
2373                                   MEM, strict);
2374 
2375       if (strict
2376           && GET_MODE_SIZE (mode) > 4
2377           && REG_X == REGNO (x))
2378         {
2379           ok = false;
2380         }
2381       break;
2382 
2383     case POST_INC:
2384     case PRE_DEC:
2385       ok = avr_reg_ok_for_addr_p (XEXP (x, 0), ADDR_SPACE_GENERIC,
2386                                   GET_CODE (x), strict);
2387       break;
2388 
2389     case PLUS:
2390       {
2391         rtx reg = XEXP (x, 0);
2392         rtx op1 = XEXP (x, 1);
2393 
2394         if (REG_P (reg)
2395             && CONST_INT_P (op1)
2396             && INTVAL (op1) >= 0)
2397           {
2398             bool fit = IN_RANGE (INTVAL (op1), 0, MAX_LD_OFFSET (mode));
2399 
2400             if (fit)
2401               {
2402                 ok = (! strict
2403                       || avr_reg_ok_for_addr_p (reg, ADDR_SPACE_GENERIC,
2404                                                 PLUS, strict));
2405 
2406                 if (reg == frame_pointer_rtx
2407                     || reg == arg_pointer_rtx)
2408                   {
2409                     ok = true;
2410                   }
2411               }
2412             else if (frame_pointer_needed
2413                      && reg == frame_pointer_rtx)
2414               {
2415                 ok = true;
2416               }
2417           }
2418       }
2419       break;
2420 
2421     default:
2422       break;
2423     }
2424 
2425   if (AVR_TINY
2426       && CONSTANT_ADDRESS_P (x))
2427     {
2428       /* avrtiny's load / store instructions only cover addresses 0..0xbf:
2429          IN / OUT range is 0..0x3f and LDS / STS can access 0x40..0xbf.  */
2430 
2431       ok = avr_address_tiny_absdata_p (x, mode);
2432     }
2433 
2434   if (avr_log.legitimate_address_p)
2435     {
2436       avr_edump ("\n%?: ret=%d, mode=%m strict=%d "
2437                  "reload_completed=%d reload_in_progress=%d %s:",
2438                  ok, mode, strict, reload_completed, reload_in_progress,
2439                  reg_renumber ? "(reg_renumber)" : "");
2440 
2441       if (GET_CODE (x) == PLUS
2442           && REG_P (XEXP (x, 0))
2443           && CONST_INT_P (XEXP (x, 1))
2444           && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
2445           && reg_renumber)
2446         {
2447           avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
2448                      true_regnum (XEXP (x, 0)));
2449         }
2450 
2451       avr_edump ("\n%r\n", x);
2452     }
2453 
2454   return ok;
2455 }
2456 
2457 
2458 /* Former implementation of TARGET_LEGITIMIZE_ADDRESS,
2459    now only a helper for avr_addr_space_legitimize_address.  */
2460 /* Attempts to replace X with a valid
2461    memory address for an operand of mode MODE  */
2462 
2463 static rtx
avr_legitimize_address(rtx x,rtx oldx,machine_mode mode)2464 avr_legitimize_address (rtx x, rtx oldx, machine_mode mode)
2465 {
2466   bool big_offset_p = false;
2467 
2468   x = oldx;
2469 
2470   if (AVR_TINY)
2471     {
2472       if (CONSTANT_ADDRESS_P (x)
2473           && ! avr_address_tiny_absdata_p (x, mode))
2474         {
2475           x = force_reg (Pmode, x);
2476         }
2477     }
2478 
2479   if (GET_CODE (oldx) == PLUS
2480       && REG_P (XEXP (oldx, 0)))
2481     {
2482       if (REG_P (XEXP (oldx, 1)))
2483         x = force_reg (GET_MODE (oldx), oldx);
2484       else if (CONST_INT_P (XEXP (oldx, 1)))
2485         {
2486           int offs = INTVAL (XEXP (oldx, 1));
2487           if (frame_pointer_rtx != XEXP (oldx, 0)
2488               && offs > MAX_LD_OFFSET (mode))
2489             {
2490               big_offset_p = true;
2491               x = force_reg (GET_MODE (oldx), oldx);
2492             }
2493         }
2494     }
2495 
2496   if (avr_log.legitimize_address)
2497     {
2498       avr_edump ("\n%?: mode=%m\n %r\n", mode, oldx);
2499 
2500       if (x != oldx)
2501         avr_edump (" %s --> %r\n", big_offset_p ? "(big offset)" : "", x);
2502     }
2503 
2504   return x;
2505 }
2506 
2507 
2508 /* Implement `LEGITIMIZE_RELOAD_ADDRESS'.  */
2509 /* This will allow register R26/27 to be used where it is no worse than normal
2510    base pointers R28/29 or R30/31.  For example, if base offset is greater
2511    than 63 bytes or for R++ or --R addressing.  */
2512 
2513 rtx
avr_legitimize_reload_address(rtx * px,machine_mode mode,int opnum,int type,int addr_type,int ind_levels ATTRIBUTE_UNUSED,rtx (* mk_memloc)(rtx,int))2514 avr_legitimize_reload_address (rtx *px, machine_mode mode,
2515                                int opnum, int type, int addr_type,
2516                                int ind_levels ATTRIBUTE_UNUSED,
2517                                rtx (*mk_memloc)(rtx,int))
2518 {
2519   rtx x = *px;
2520 
2521   if (avr_log.legitimize_reload_address)
2522     avr_edump ("\n%?:%m %r\n", mode, x);
2523 
2524   if (1 && (GET_CODE (x) == POST_INC
2525             || GET_CODE (x) == PRE_DEC))
2526     {
2527       push_reload (XEXP (x, 0), XEXP (x, 0), &XEXP (x, 0), &XEXP (x, 0),
2528                    POINTER_REGS, GET_MODE (x), GET_MODE (x), 0, 0,
2529                    opnum, RELOAD_OTHER);
2530 
2531       if (avr_log.legitimize_reload_address)
2532         avr_edump (" RCLASS.1 = %R\n IN = %r\n OUT = %r\n",
2533                    POINTER_REGS, XEXP (x, 0), XEXP (x, 0));
2534 
2535       return x;
2536     }
2537 
2538   if (GET_CODE (x) == PLUS
2539       && REG_P (XEXP (x, 0))
2540       && reg_equiv_constant (REGNO (XEXP (x, 0))) == 0
2541       && CONST_INT_P (XEXP (x, 1))
2542       && INTVAL (XEXP (x, 1)) >= 1)
2543     {
2544       bool fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
2545 
2546       if (fit)
2547         {
2548           if (reg_equiv_address (REGNO (XEXP (x, 0))) != 0)
2549             {
2550               int regno = REGNO (XEXP (x, 0));
2551               rtx mem = mk_memloc (x, regno);
2552 
2553               push_reload (XEXP (mem, 0), NULL_RTX, &XEXP (mem, 0), NULL,
2554                            POINTER_REGS, Pmode, VOIDmode, 0, 0,
2555                            1, (enum reload_type) addr_type);
2556 
2557               if (avr_log.legitimize_reload_address)
2558                 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
2559                            POINTER_REGS, XEXP (mem, 0), NULL_RTX);
2560 
2561               push_reload (mem, NULL_RTX, &XEXP (x, 0), NULL,
2562                            BASE_POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
2563                            opnum, (enum reload_type) type);
2564 
2565               if (avr_log.legitimize_reload_address)
2566                 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
2567                            BASE_POINTER_REGS, mem, NULL_RTX);
2568 
2569               return x;
2570             }
2571         }
2572       else if (! (frame_pointer_needed
2573                   && XEXP (x, 0) == frame_pointer_rtx))
2574         {
2575           push_reload (x, NULL_RTX, px, NULL,
2576                        POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
2577                        opnum, (enum reload_type) type);
2578 
2579           if (avr_log.legitimize_reload_address)
2580             avr_edump (" RCLASS.3 = %R\n IN = %r\n OUT = %r\n",
2581                        POINTER_REGS, x, NULL_RTX);
2582 
2583           return x;
2584         }
2585     }
2586 
2587   return NULL_RTX;
2588 }
2589 
2590 
2591 /* Helper function to print assembler resp. track instruction
2592    sequence lengths.  Always return "".
2593 
2594    If PLEN == NULL:
2595        Output assembler code from template TPL with operands supplied
2596        by OPERANDS.  This is just forwarding to output_asm_insn.
2597 
2598    If PLEN != NULL:
2599        If N_WORDS >= 0  Add N_WORDS to *PLEN.
2600        If N_WORDS < 0   Set *PLEN to -N_WORDS.
2601        Don't output anything.
2602 */
2603 
2604 static const char*
avr_asm_len(const char * tpl,rtx * operands,int * plen,int n_words)2605 avr_asm_len (const char* tpl, rtx* operands, int* plen, int n_words)
2606 {
2607   if (plen == NULL)
2608     output_asm_insn (tpl, operands);
2609   else
2610     {
2611       if (n_words < 0)
2612         *plen = -n_words;
2613       else
2614         *plen += n_words;
2615     }
2616 
2617   return "";
2618 }
2619 
2620 
2621 /* Return a pointer register name as a string.  */
2622 
2623 static const char*
ptrreg_to_str(int regno)2624 ptrreg_to_str (int regno)
2625 {
2626   switch (regno)
2627     {
2628     case REG_X: return "X";
2629     case REG_Y: return "Y";
2630     case REG_Z: return "Z";
2631     default:
2632       output_operand_lossage ("address operand requires constraint for"
2633                               " X, Y, or Z register");
2634     }
2635   return NULL;
2636 }
2637 
2638 /* Return the condition name as a string.
2639    Used in conditional jump constructing  */
2640 
2641 static const char*
cond_string(enum rtx_code code)2642 cond_string (enum rtx_code code)
2643 {
2644   switch (code)
2645     {
2646     case NE:
2647       return "ne";
2648     case EQ:
2649       return "eq";
2650     case GE:
2651       if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
2652         return "pl";
2653       else
2654         return "ge";
2655     case LT:
2656       if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
2657         return "mi";
2658       else
2659         return "lt";
2660     case GEU:
2661       return "sh";
2662     case LTU:
2663       return "lo";
2664     default:
2665       gcc_unreachable ();
2666     }
2667 
2668   return "";
2669 }
2670 
2671 
2672 /* Return true if rtx X is a CONST or SYMBOL_REF with progmem.
2673    This must be used for AVR_TINY only because on other cores
2674    the flash memory is not visible in the RAM address range and
2675    cannot be read by, say,  LD instruction.  */
2676 
2677 static bool
avr_address_tiny_pm_p(rtx x)2678 avr_address_tiny_pm_p (rtx x)
2679 {
2680   if (CONST == GET_CODE (x))
2681     x = XEXP (XEXP (x, 0), 0);
2682 
2683   if (SYMBOL_REF_P (x))
2684     return SYMBOL_REF_FLAGS (x) & AVR_SYMBOL_FLAG_TINY_PM;
2685 
2686   return false;
2687 }
2688 
2689 /* Implement `TARGET_PRINT_OPERAND_ADDRESS'.  */
2690 /* Output ADDR to FILE as address.  */
2691 
2692 static void
avr_print_operand_address(FILE * file,machine_mode,rtx addr)2693 avr_print_operand_address (FILE *file, machine_mode /*mode*/, rtx addr)
2694 {
2695   if (AVR_TINY
2696       && avr_address_tiny_pm_p (addr))
2697     {
2698       addr = plus_constant (Pmode, addr, avr_arch->flash_pm_offset);
2699     }
2700 
2701   switch (GET_CODE (addr))
2702     {
2703     case REG:
2704       fprintf (file, "%s", ptrreg_to_str (REGNO (addr)));
2705       break;
2706 
2707     case PRE_DEC:
2708       fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
2709       break;
2710 
2711     case POST_INC:
2712       fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
2713       break;
2714 
2715     default:
2716       if (CONSTANT_ADDRESS_P (addr)
2717           && text_segment_operand (addr, VOIDmode))
2718         {
2719           rtx x = addr;
2720           if (GET_CODE (x) == CONST)
2721             x = XEXP (x, 0);
2722           if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1)))
2723             {
2724               /* Assembler gs() will implant word address.  Make offset
2725                  a byte offset inside gs() for assembler.  This is
2726                  needed because the more logical (constant+gs(sym)) is not
2727                  accepted by gas.  For 128K and smaller devices this is ok.
2728                  For large devices it will create a trampoline to offset
2729                  from symbol which may not be what the user really wanted.  */
2730 
2731               fprintf (file, "gs(");
2732               output_addr_const (file, XEXP (x, 0));
2733               fprintf (file, "+" HOST_WIDE_INT_PRINT_DEC ")",
2734                        2 * INTVAL (XEXP (x, 1)));
2735               if (AVR_3_BYTE_PC)
2736                 if (warning (0, "pointer offset from symbol maybe incorrect"))
2737                   {
2738                     output_addr_const (stderr, addr);
2739                     fprintf (stderr, "\n");
2740                   }
2741             }
2742           else
2743             {
2744               fprintf (file, "gs(");
2745               output_addr_const (file, addr);
2746               fprintf (file, ")");
2747             }
2748         }
2749       else
2750         output_addr_const (file, addr);
2751     }
2752 }
2753 
2754 
2755 /* Implement `TARGET_PRINT_OPERAND_PUNCT_VALID_P'.  */
2756 
2757 static bool
avr_print_operand_punct_valid_p(unsigned char code)2758 avr_print_operand_punct_valid_p (unsigned char code)
2759 {
2760   return code == '~' || code == '!';
2761 }
2762 
2763 
2764 /* Implement `TARGET_PRINT_OPERAND'.  */
2765 /* Output X as assembler operand to file FILE.
2766    For a description of supported %-codes, see top of avr.md.  */
2767 
2768 static void
avr_print_operand(FILE * file,rtx x,int code)2769 avr_print_operand (FILE *file, rtx x, int code)
2770 {
2771   int abcd = 0, ef = 0, ij = 0;
2772 
2773   if (code >= 'A' && code <= 'D')
2774     abcd = code - 'A';
2775   else if (code == 'E' || code == 'F')
2776     ef = code - 'E';
2777   else if (code == 'I' || code == 'J')
2778     ij = code - 'I';
2779 
2780   if (code == '~')
2781     {
2782       if (!AVR_HAVE_JMP_CALL)
2783         fputc ('r', file);
2784     }
2785   else if (code == '!')
2786     {
2787       if (AVR_HAVE_EIJMP_EICALL)
2788         fputc ('e', file);
2789     }
2790   else if (code == 't'
2791            || code == 'T')
2792     {
2793       static int t_regno = -1;
2794       static int t_nbits = -1;
2795 
2796       if (REG_P (x) && t_regno < 0 && code == 'T')
2797         {
2798           t_regno = REGNO (x);
2799           t_nbits = GET_MODE_BITSIZE (GET_MODE (x));
2800         }
2801       else if (CONST_INT_P (x) && t_regno >= 0
2802                && IN_RANGE (INTVAL (x), 0, t_nbits - 1))
2803         {
2804           int bpos = INTVAL (x);
2805 
2806           fprintf (file, "%s", reg_names[t_regno + bpos / 8]);
2807           if (code == 'T')
2808             fprintf (file, ",%d", bpos % 8);
2809 
2810           t_regno = -1;
2811         }
2812       else
2813         fatal_insn ("operands to %T/%t must be reg + const_int:", x);
2814     }
2815   else if (code == 'E' || code == 'F')
2816     {
2817       rtx op = XEXP (x, 0);
2818       fprintf (file, "%s", reg_names[REGNO (op) + ef]);
2819     }
2820   else if (code == 'I' || code == 'J')
2821     {
2822       rtx op = XEXP (XEXP (x, 0), 0);
2823       fprintf (file, "%s", reg_names[REGNO (op) + ij]);
2824     }
2825   else if (REG_P (x))
2826     {
2827       if (x == zero_reg_rtx)
2828         fprintf (file, "__zero_reg__");
2829       else if (code == 'r' && REGNO (x) < 32)
2830         fprintf (file, "%d", (int) REGNO (x));
2831       else
2832         fprintf (file, "%s", reg_names[REGNO (x) + abcd]);
2833     }
2834   else if (CONST_INT_P (x))
2835     {
2836       HOST_WIDE_INT ival = INTVAL (x);
2837 
2838       if ('i' != code)
2839         fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival + abcd);
2840       else if (low_io_address_operand (x, VOIDmode)
2841                || high_io_address_operand (x, VOIDmode))
2842         {
2843           if (AVR_HAVE_RAMPZ && ival == avr_addr.rampz)
2844             fprintf (file, "__RAMPZ__");
2845           else if (AVR_HAVE_RAMPY && ival == avr_addr.rampy)
2846             fprintf (file, "__RAMPY__");
2847           else if (AVR_HAVE_RAMPX && ival == avr_addr.rampx)
2848             fprintf (file, "__RAMPX__");
2849           else if (AVR_HAVE_RAMPD && ival == avr_addr.rampd)
2850             fprintf (file, "__RAMPD__");
2851           else if ((AVR_XMEGA || AVR_TINY) && ival == avr_addr.ccp)
2852             fprintf (file, "__CCP__");
2853           else if (ival == avr_addr.sreg)   fprintf (file, "__SREG__");
2854           else if (ival == avr_addr.sp_l)   fprintf (file, "__SP_L__");
2855           else if (ival == avr_addr.sp_h)   fprintf (file, "__SP_H__");
2856           else
2857             {
2858               fprintf (file, HOST_WIDE_INT_PRINT_HEX,
2859                        ival - avr_arch->sfr_offset);
2860             }
2861         }
2862       else
2863         fatal_insn ("bad address, not an I/O address:", x);
2864     }
2865   else if (MEM_P (x))
2866     {
2867       rtx addr = XEXP (x, 0);
2868 
2869       if (code == 'm')
2870         {
2871           if (!CONSTANT_P (addr))
2872             fatal_insn ("bad address, not a constant:", addr);
2873           /* Assembler template with m-code is data - not progmem section */
2874           if (text_segment_operand (addr, VOIDmode))
2875             if (warning (0, "accessing data memory with"
2876                          " program memory address"))
2877               {
2878                 output_addr_const (stderr, addr);
2879                 fprintf(stderr,"\n");
2880               }
2881           output_addr_const (file, addr);
2882         }
2883       else if (code == 'i')
2884         {
2885           avr_print_operand (file, addr, 'i');
2886         }
2887       else if (code == 'o')
2888         {
2889           if (GET_CODE (addr) != PLUS)
2890             fatal_insn ("bad address, not (reg+disp):", addr);
2891 
2892           avr_print_operand (file, XEXP (addr, 1), 0);
2893         }
2894       else if (code == 'b')
2895         {
2896           if (GET_CODE (addr) != PLUS)
2897             fatal_insn ("bad address, not (reg+disp):", addr);
2898 
2899           avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
2900         }
2901       else if (code == 'p' || code == 'r')
2902         {
2903           if (GET_CODE (addr) != POST_INC && GET_CODE (addr) != PRE_DEC)
2904             fatal_insn ("bad address, not post_inc or pre_dec:", addr);
2905 
2906           if (code == 'p')
2907             /* X, Y, Z */
2908             avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
2909           else
2910             avr_print_operand (file, XEXP (addr, 0), 0);  /* r26, r28, r30 */
2911         }
2912       else if (GET_CODE (addr) == PLUS)
2913         {
2914           avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
2915           if (REGNO (XEXP (addr, 0)) == REG_X)
2916             fatal_insn ("internal compiler error.  Bad address:"
2917                         ,addr);
2918           fputc ('+', file);
2919           avr_print_operand (file, XEXP (addr, 1), code);
2920         }
2921       else
2922         avr_print_operand_address (file, VOIDmode, addr);
2923     }
2924   else if (code == 'i')
2925     {
2926       if (SYMBOL_REF_P (x) && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO))
2927 	avr_print_operand_address
2928 	  (file, VOIDmode, plus_constant (HImode, x, -avr_arch->sfr_offset));
2929       else
2930 	fatal_insn ("bad address, not an I/O address:", x);
2931     }
2932   else if (code == 'x')
2933     {
2934       /* Constant progmem address - like used in jmp or call */
2935       if (text_segment_operand (x, VOIDmode) == 0)
2936         if (warning (0, "accessing program memory"
2937                      " with data memory address"))
2938           {
2939             output_addr_const (stderr, x);
2940             fprintf(stderr,"\n");
2941           }
2942       /* Use normal symbol for direct address no linker trampoline needed */
2943       output_addr_const (file, x);
2944     }
2945   else if (CONST_FIXED_P (x))
2946     {
2947       HOST_WIDE_INT ival = INTVAL (avr_to_int_mode (x));
2948       if (code != 0)
2949         output_operand_lossage ("Unsupported code '%c' for fixed-point:",
2950                                 code);
2951       fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);
2952     }
2953   else if (CONST_DOUBLE_P (x))
2954     {
2955       long val;
2956       if (GET_MODE (x) != SFmode)
2957         fatal_insn ("internal compiler error.  Unknown mode:", x);
2958       REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), val);
2959       fprintf (file, "0x%lx", val);
2960     }
2961   else if (GET_CODE (x) == CONST_STRING)
2962     fputs (XSTR (x, 0), file);
2963   else if (code == 'j')
2964     fputs (cond_string (GET_CODE (x)), file);
2965   else if (code == 'k')
2966     fputs (cond_string (reverse_condition (GET_CODE (x))), file);
2967   else
2968     avr_print_operand_address (file, VOIDmode, x);
2969 }
2970 
2971 
2972 /* Implement TARGET_USE_BY_PIECES_INFRASTRUCTURE_P.  */
2973 
2974 /* Prefer sequence of loads/stores for moves of size upto
2975    two - two pairs of load/store instructions are always better
2976    than the 5 instruction sequence for a loop (1 instruction
2977    for loop counter setup, and 4 for the body of the loop). */
2978 
2979 static bool
avr_use_by_pieces_infrastructure_p(unsigned HOST_WIDE_INT size,unsigned int align ATTRIBUTE_UNUSED,enum by_pieces_operation op,bool speed_p)2980 avr_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size,
2981                                     unsigned int align ATTRIBUTE_UNUSED,
2982                                     enum by_pieces_operation op,
2983                                     bool speed_p)
2984 {
2985   if (op != MOVE_BY_PIECES
2986       || (speed_p && size > MOVE_MAX_PIECES))
2987     return default_use_by_pieces_infrastructure_p (size, align, op, speed_p);
2988 
2989   return size <= MOVE_MAX_PIECES;
2990 }
2991 
2992 
2993 /* Worker function for `NOTICE_UPDATE_CC'.  */
2994 /* Update the condition code in the INSN.  */
2995 
2996 void
avr_notice_update_cc(rtx body ATTRIBUTE_UNUSED,rtx_insn * insn)2997 avr_notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx_insn *insn)
2998 {
2999   rtx set;
3000   enum attr_cc cc = get_attr_cc (insn);
3001 
3002   switch (cc)
3003     {
3004     default:
3005       break;
3006 
3007     case CC_PLUS:
3008     case CC_LDI:
3009       {
3010         rtx *op = recog_data.operand;
3011         int len_dummy, icc;
3012 
3013         /* Extract insn's operands.  */
3014         extract_constrain_insn_cached (insn);
3015 
3016         switch (cc)
3017           {
3018           default:
3019             gcc_unreachable();
3020 
3021           case CC_PLUS:
3022             avr_out_plus (insn, op, &len_dummy, &icc);
3023             cc = (enum attr_cc) icc;
3024             break;
3025 
3026           case CC_LDI:
3027 
3028             cc = (op[1] == CONST0_RTX (GET_MODE (op[0]))
3029                   && reg_overlap_mentioned_p (op[0], zero_reg_rtx))
3030               /* Loading zero-reg with 0 uses CLR and thus clobbers cc0.  */
3031               ? CC_CLOBBER
3032               /* Any other "r,rL" combination does not alter cc0.  */
3033               : CC_NONE;
3034 
3035             break;
3036           } /* inner switch */
3037 
3038         break;
3039       }
3040     } /* outer swicth */
3041 
3042   switch (cc)
3043     {
3044     default:
3045       /* Special values like CC_OUT_PLUS from above have been
3046          mapped to "standard" CC_* values so we never come here.  */
3047 
3048       gcc_unreachable();
3049       break;
3050 
3051     case CC_NONE:
3052       /* Insn does not affect CC at all, but it might set some registers
3053          that are stored in cc_status.  If such a register is affected by
3054          the current insn, for example by means of a SET or a CLOBBER,
3055          then we must reset cc_status; cf. PR77326.
3056 
3057          Unfortunately, set_of cannot be used as reg_overlap_mentioned_p
3058          will abort on COMPARE (which might be found in cc_status.value1/2).
3059          Thus work out the registers set by the insn and regs mentioned
3060          in cc_status.value1/2.  */
3061 
3062       if (cc_status.value1
3063           || cc_status.value2)
3064         {
3065           HARD_REG_SET regs_used;
3066           HARD_REG_SET regs_set;
3067           CLEAR_HARD_REG_SET (regs_used);
3068 
3069           if (cc_status.value1
3070               && !CONSTANT_P (cc_status.value1))
3071             {
3072               find_all_hard_regs (cc_status.value1, &regs_used);
3073             }
3074 
3075           if (cc_status.value2
3076               && !CONSTANT_P (cc_status.value2))
3077             {
3078               find_all_hard_regs (cc_status.value2, &regs_used);
3079             }
3080 
3081           find_all_hard_reg_sets (insn, &regs_set, false);
3082 
3083           if (hard_reg_set_intersect_p (regs_used, regs_set))
3084             {
3085               CC_STATUS_INIT;
3086             }
3087         }
3088 
3089       break; // CC_NONE
3090 
3091     case CC_SET_N:
3092       CC_STATUS_INIT;
3093       break;
3094 
3095     case CC_SET_ZN:
3096       set = single_set (insn);
3097       CC_STATUS_INIT;
3098       if (set)
3099         {
3100           cc_status.flags |= CC_NO_OVERFLOW;
3101           cc_status.value1 = SET_DEST (set);
3102         }
3103       break;
3104 
3105     case CC_SET_VZN:
3106       /* Insn like INC, DEC, NEG that set Z,N,V.  We currently don't make use
3107          of this combination, cf. also PR61055.  */
3108       CC_STATUS_INIT;
3109       break;
3110 
3111     case CC_SET_CZN:
3112       /* Insn sets the Z,N,C flags of CC to recog_operand[0].
3113          The V flag may or may not be known but that's ok because
3114          alter_cond will change tests to use EQ/NE.  */
3115       set = single_set (insn);
3116       CC_STATUS_INIT;
3117       if (set)
3118         {
3119           cc_status.value1 = SET_DEST (set);
3120           cc_status.flags |= CC_OVERFLOW_UNUSABLE;
3121         }
3122       break;
3123 
3124     case CC_COMPARE:
3125       set = single_set (insn);
3126       CC_STATUS_INIT;
3127       if (set)
3128         cc_status.value1 = SET_SRC (set);
3129       break;
3130 
3131     case CC_CLOBBER:
3132       /* Insn doesn't leave CC in a usable state.  */
3133       CC_STATUS_INIT;
3134       break;
3135     }
3136 }
3137 
3138 /* Choose mode for jump insn:
3139    1 - relative jump in range -63 <= x <= 62 ;
3140    2 - relative jump in range -2046 <= x <= 2045 ;
3141    3 - absolute jump (only for ATmega[16]03).  */
3142 
3143 int
avr_jump_mode(rtx x,rtx_insn * insn)3144 avr_jump_mode (rtx x, rtx_insn *insn)
3145 {
3146   int dest_addr = INSN_ADDRESSES (INSN_UID (GET_CODE (x) == LABEL_REF
3147                                             ? XEXP (x, 0) : x));
3148   int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
3149   int jump_distance = cur_addr - dest_addr;
3150 
3151   if (IN_RANGE (jump_distance, -63, 62))
3152     return 1;
3153   else if (IN_RANGE (jump_distance, -2046, 2045))
3154     return 2;
3155   else if (AVR_HAVE_JMP_CALL)
3156     return 3;
3157 
3158   return 2;
3159 }
3160 
3161 /* Return an AVR condition jump commands.
3162    X is a comparison RTX.
3163    LEN is a number returned by avr_jump_mode function.
3164    If REVERSE nonzero then condition code in X must be reversed.  */
3165 
3166 const char*
ret_cond_branch(rtx x,int len,int reverse)3167 ret_cond_branch (rtx x, int len, int reverse)
3168 {
3169   RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
3170 
3171   switch (cond)
3172     {
3173     case GT:
3174       if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
3175 	return (len == 1 ? ("breq .+2" CR_TAB
3176 			    "brpl %0") :
3177 		len == 2 ? ("breq .+4" CR_TAB
3178 			    "brmi .+2" CR_TAB
3179 			    "rjmp %0") :
3180 		("breq .+6" CR_TAB
3181 		 "brmi .+4" CR_TAB
3182 		 "jmp %0"));
3183 
3184       else
3185 	return (len == 1 ? ("breq .+2" CR_TAB
3186 			    "brge %0") :
3187 		len == 2 ? ("breq .+4" CR_TAB
3188 			    "brlt .+2" CR_TAB
3189 			    "rjmp %0") :
3190 		("breq .+6" CR_TAB
3191 		 "brlt .+4" CR_TAB
3192 		 "jmp %0"));
3193     case GTU:
3194       return (len == 1 ? ("breq .+2" CR_TAB
3195                           "brsh %0") :
3196               len == 2 ? ("breq .+4" CR_TAB
3197                           "brlo .+2" CR_TAB
3198                           "rjmp %0") :
3199               ("breq .+6" CR_TAB
3200                "brlo .+4" CR_TAB
3201                "jmp %0"));
3202     case LE:
3203       if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
3204 	return (len == 1 ? ("breq %0" CR_TAB
3205 			    "brmi %0") :
3206 		len == 2 ? ("breq .+2" CR_TAB
3207 			    "brpl .+2" CR_TAB
3208 			    "rjmp %0") :
3209 		("breq .+2" CR_TAB
3210 		 "brpl .+4" CR_TAB
3211 		 "jmp %0"));
3212       else
3213 	return (len == 1 ? ("breq %0" CR_TAB
3214 			    "brlt %0") :
3215 		len == 2 ? ("breq .+2" CR_TAB
3216 			    "brge .+2" CR_TAB
3217 			    "rjmp %0") :
3218 		("breq .+2" CR_TAB
3219 		 "brge .+4" CR_TAB
3220 		 "jmp %0"));
3221     case LEU:
3222       return (len == 1 ? ("breq %0" CR_TAB
3223                           "brlo %0") :
3224               len == 2 ? ("breq .+2" CR_TAB
3225                           "brsh .+2" CR_TAB
3226 			  "rjmp %0") :
3227               ("breq .+2" CR_TAB
3228                "brsh .+4" CR_TAB
3229 	       "jmp %0"));
3230     default:
3231       if (reverse)
3232 	{
3233 	  switch (len)
3234 	    {
3235 	    case 1:
3236 	      return "br%k1 %0";
3237 	    case 2:
3238 	      return ("br%j1 .+2" CR_TAB
3239 		      "rjmp %0");
3240 	    default:
3241 	      return ("br%j1 .+4" CR_TAB
3242 		      "jmp %0");
3243 	    }
3244 	}
3245       else
3246         {
3247           switch (len)
3248             {
3249             case 1:
3250               return "br%j1 %0";
3251             case 2:
3252               return ("br%k1 .+2" CR_TAB
3253                       "rjmp %0");
3254             default:
3255               return ("br%k1 .+4" CR_TAB
3256                       "jmp %0");
3257             }
3258         }
3259     }
3260   return "";
3261 }
3262 
3263 
3264 /* Worker function for `FINAL_PRESCAN_INSN'.  */
3265 /* Output insn cost for next insn.  */
3266 
3267 void
avr_final_prescan_insn(rtx_insn * insn,rtx * operand ATTRIBUTE_UNUSED,int num_operands ATTRIBUTE_UNUSED)3268 avr_final_prescan_insn (rtx_insn *insn, rtx *operand ATTRIBUTE_UNUSED,
3269                         int num_operands ATTRIBUTE_UNUSED)
3270 {
3271   if (avr_log.rtx_costs)
3272     {
3273       rtx set = single_set (insn);
3274 
3275       if (set)
3276         fprintf (asm_out_file, "/* DEBUG: cost = %d.  */\n",
3277                  set_src_cost (SET_SRC (set), GET_MODE (SET_DEST (set)),
3278 			       optimize_insn_for_speed_p ()));
3279       else
3280         fprintf (asm_out_file, "/* DEBUG: pattern-cost = %d.  */\n",
3281                  rtx_cost (PATTERN (insn), VOIDmode, INSN, 0,
3282                            optimize_insn_for_speed_p()));
3283     }
3284 
3285   if (avr_log.insn_addresses)
3286     fprintf (asm_out_file, ";; ADDR = %d\n",
3287              (int) INSN_ADDRESSES (INSN_UID (insn)));
3288 }
3289 
3290 
3291 /* Implement `TARGET_ASM_FINAL_POSTSCAN_INSN'.  */
3292 /* When GAS generates (parts of) ISR prologue / epilogue for us, we must
3293    hint GAS about the end of the code to scan.  There migh be code located
3294    after the last epilogue.  */
3295 
3296 static void
avr_asm_final_postscan_insn(FILE * stream,rtx_insn * insn,rtx *,int)3297 avr_asm_final_postscan_insn (FILE *stream, rtx_insn *insn, rtx*, int)
3298 {
3299   if (cfun->machine->gasisr.yes
3300       && !next_real_insn (insn))
3301     {
3302       app_disable();
3303       fprintf (stream, "\t__gcc_isr %d,r%d\n", GASISR_Done,
3304                cfun->machine->gasisr.regno);
3305     }
3306 }
3307 
3308 
3309 /* Return 0 if undefined, 1 if always true or always false.  */
3310 
3311 int
avr_simplify_comparison_p(machine_mode mode,RTX_CODE op,rtx x)3312 avr_simplify_comparison_p (machine_mode mode, RTX_CODE op, rtx x)
3313 {
3314   unsigned int max = (mode == QImode ? 0xff :
3315                       mode == HImode ? 0xffff :
3316                       mode == PSImode ? 0xffffff :
3317                       mode == SImode ? 0xffffffff : 0);
3318   if (max && op && CONST_INT_P (x))
3319     {
3320       if (unsigned_condition (op) != op)
3321         max >>= 1;
3322 
3323       if (max != (INTVAL (x) & max)
3324           && INTVAL (x) != 0xff)
3325         return 1;
3326     }
3327   return 0;
3328 }
3329 
3330 
3331 /* Worker function for `FUNCTION_ARG_REGNO_P'.  */
3332 /* Returns nonzero if REGNO is the number of a hard
3333    register in which function arguments are sometimes passed.  */
3334 
3335 int
avr_function_arg_regno_p(int r)3336 avr_function_arg_regno_p (int r)
3337 {
3338   return AVR_TINY ? IN_RANGE (r, 20, 25) : IN_RANGE (r, 8, 25);
3339 }
3340 
3341 
3342 /* Worker function for `INIT_CUMULATIVE_ARGS'.  */
3343 /* Initializing the variable cum for the state at the beginning
3344    of the argument list.  */
3345 
3346 void
avr_init_cumulative_args(CUMULATIVE_ARGS * cum,tree fntype,rtx libname,tree fndecl ATTRIBUTE_UNUSED)3347 avr_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
3348                           tree fndecl ATTRIBUTE_UNUSED)
3349 {
3350   cum->nregs = AVR_TINY ? 6 : 18;
3351   cum->regno = FIRST_CUM_REG;
3352   if (!libname && stdarg_p (fntype))
3353     cum->nregs = 0;
3354 
3355   /* Assume the calle may be tail called */
3356 
3357   cfun->machine->sibcall_fails = 0;
3358 }
3359 
3360 /* Returns the number of registers to allocate for a function argument.  */
3361 
3362 static int
avr_num_arg_regs(machine_mode mode,const_tree type)3363 avr_num_arg_regs (machine_mode mode, const_tree type)
3364 {
3365   int size;
3366 
3367   if (mode == BLKmode)
3368     size = int_size_in_bytes (type);
3369   else
3370     size = GET_MODE_SIZE (mode);
3371 
3372   /* Align all function arguments to start in even-numbered registers.
3373      Odd-sized arguments leave holes above them.  */
3374 
3375   return (size + 1) & ~1;
3376 }
3377 
3378 
3379 /* Implement `TARGET_FUNCTION_ARG'.  */
3380 /* Controls whether a function argument is passed
3381    in a register, and which register.  */
3382 
3383 static rtx
avr_function_arg(cumulative_args_t cum_v,const function_arg_info & arg)3384 avr_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
3385 {
3386   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
3387   int bytes = avr_num_arg_regs (arg.mode, arg.type);
3388 
3389   if (cum->nregs && bytes <= cum->nregs)
3390     return gen_rtx_REG (arg.mode, cum->regno - bytes);
3391 
3392   return NULL_RTX;
3393 }
3394 
3395 
3396 /* Implement `TARGET_FUNCTION_ARG_ADVANCE'.  */
3397 /* Update the summarizer variable CUM to advance past an argument
3398    in the argument list.  */
3399 
3400 static void
avr_function_arg_advance(cumulative_args_t cum_v,const function_arg_info & arg)3401 avr_function_arg_advance (cumulative_args_t cum_v,
3402 			  const function_arg_info &arg)
3403 {
3404   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
3405   int bytes = avr_num_arg_regs (arg.mode, arg.type);
3406 
3407   cum->nregs -= bytes;
3408   cum->regno -= bytes;
3409 
3410   /* A parameter is being passed in a call-saved register.  As the original
3411      contents of these regs has to be restored before leaving the function,
3412      a function must not pass arguments in call-saved regs in order to get
3413      tail-called.  */
3414 
3415   if (cum->regno >= 8
3416       && cum->nregs >= 0
3417       && !call_used_or_fixed_reg_p (cum->regno))
3418     {
3419       /* FIXME: We ship info on failing tail-call in struct machine_function.
3420          This uses internals of calls.c:expand_call() and the way args_so_far
3421          is used.  targetm.function_ok_for_sibcall() needs to be extended to
3422          pass &args_so_far, too.  At present, CUMULATIVE_ARGS is target
3423          dependent so that such an extension is not wanted.  */
3424 
3425       cfun->machine->sibcall_fails = 1;
3426     }
3427 
3428   /* Test if all registers needed by the ABI are actually available.  If the
3429      user has fixed a GPR needed to pass an argument, an (implicit) function
3430      call will clobber that fixed register.  See PR45099 for an example.  */
3431 
3432   if (cum->regno >= 8
3433       && cum->nregs >= 0)
3434     {
3435       for (int regno = cum->regno; regno < cum->regno + bytes; regno++)
3436         if (fixed_regs[regno])
3437           warning (0, "fixed register %s used to pass parameter to function",
3438                    reg_names[regno]);
3439     }
3440 
3441   if (cum->nregs <= 0)
3442     {
3443       cum->nregs = 0;
3444       cum->regno = FIRST_CUM_REG;
3445     }
3446 }
3447 
3448 /* Implement `TARGET_FUNCTION_OK_FOR_SIBCALL' */
3449 /* Decide whether we can make a sibling call to a function.  DECL is the
3450    declaration of the function being targeted by the call and EXP is the
3451    CALL_EXPR representing the call.  */
3452 
3453 static bool
avr_function_ok_for_sibcall(tree decl_callee,tree exp_callee)3454 avr_function_ok_for_sibcall (tree decl_callee, tree exp_callee)
3455 {
3456   tree fntype_callee;
3457 
3458   /* Tail-calling must fail if callee-saved regs are used to pass
3459      function args.  We must not tail-call when `epilogue_restores'
3460      is used.  Unfortunately, we cannot tell at this point if that
3461      actually will happen or not, and we cannot step back from
3462      tail-calling.  Thus, we inhibit tail-calling with -mcall-prologues.  */
3463 
3464   if (cfun->machine->sibcall_fails
3465       || TARGET_CALL_PROLOGUES)
3466     {
3467       return false;
3468     }
3469 
3470   fntype_callee = TREE_TYPE (CALL_EXPR_FN (exp_callee));
3471 
3472   if (decl_callee)
3473     {
3474       decl_callee = TREE_TYPE (decl_callee);
3475     }
3476   else
3477     {
3478       decl_callee = fntype_callee;
3479 
3480       while (FUNCTION_TYPE != TREE_CODE (decl_callee)
3481              && METHOD_TYPE != TREE_CODE (decl_callee))
3482         {
3483           decl_callee = TREE_TYPE (decl_callee);
3484         }
3485     }
3486 
3487   /* Ensure that caller and callee have compatible epilogues */
3488 
3489   if (cfun->machine->is_interrupt
3490       || cfun->machine->is_signal
3491       || cfun->machine->is_naked
3492       || avr_naked_function_p (decl_callee))
3493     {
3494       return false;
3495     }
3496 
3497   return true;
3498 }
3499 
3500 /***********************************************************************
3501   Functions for outputting various mov's for a various modes
3502 ************************************************************************/
3503 
3504 /* Return true if a value of mode MODE is read from flash by
3505    __load_* function from libgcc.  */
3506 
3507 bool
avr_load_libgcc_p(rtx op)3508 avr_load_libgcc_p (rtx op)
3509 {
3510   machine_mode mode = GET_MODE (op);
3511   int n_bytes = GET_MODE_SIZE (mode);
3512 
3513   return (n_bytes > 2
3514           && !AVR_HAVE_LPMX
3515           && avr_mem_flash_p (op));
3516 }
3517 
3518 /* Return true if a value of mode MODE is read by __xload_* function.  */
3519 
3520 bool
avr_xload_libgcc_p(machine_mode mode)3521 avr_xload_libgcc_p (machine_mode mode)
3522 {
3523   int n_bytes = GET_MODE_SIZE (mode);
3524 
3525   return (n_bytes > 1
3526           || avr_n_flash > 1);
3527 }
3528 
3529 
3530 /* Fixme: This is a hack because secondary reloads don't works as expected.
3531 
3532    Find an unused d-register to be used as scratch in INSN.
3533    EXCLUDE is either NULL_RTX or some register. In the case where EXCLUDE
3534    is a register, skip all possible return values that overlap EXCLUDE.
3535    The policy for the returned register is similar to that of
3536    `reg_unused_after', i.e. the returned register may overlap the SET_DEST
3537    of INSN.
3538 
3539    Return a QImode d-register or NULL_RTX if nothing found.  */
3540 
3541 static rtx
avr_find_unused_d_reg(rtx_insn * insn,rtx exclude)3542 avr_find_unused_d_reg (rtx_insn *insn, rtx exclude)
3543 {
3544   bool isr_p = (avr_interrupt_function_p (current_function_decl)
3545                 || avr_signal_function_p (current_function_decl));
3546 
3547   for (int regno = 16; regno < 32; regno++)
3548     {
3549       rtx reg = all_regs_rtx[regno];
3550 
3551       if ((exclude
3552            && reg_overlap_mentioned_p (exclude, reg))
3553           || fixed_regs[regno])
3554         {
3555           continue;
3556         }
3557 
3558       /* Try non-live register */
3559 
3560       if (!df_regs_ever_live_p (regno)
3561           && (TREE_THIS_VOLATILE (current_function_decl)
3562               || cfun->machine->is_OS_task
3563               || cfun->machine->is_OS_main
3564               || (!isr_p && call_used_or_fixed_reg_p (regno))))
3565         {
3566           return reg;
3567         }
3568 
3569       /* Any live register can be used if it is unused after.
3570          Prologue/epilogue will care for it as needed.  */
3571 
3572       if (df_regs_ever_live_p (regno)
3573           && reg_unused_after (insn, reg))
3574         {
3575           return reg;
3576         }
3577     }
3578 
3579   return NULL_RTX;
3580 }
3581 
3582 
3583 /* Helper function for the next function in the case where only restricted
3584    version of LPM instruction is available.  */
3585 
3586 static const char*
avr_out_lpm_no_lpmx(rtx_insn * insn,rtx * xop,int * plen)3587 avr_out_lpm_no_lpmx (rtx_insn *insn, rtx *xop, int *plen)
3588 {
3589   rtx dest = xop[0];
3590   rtx addr = xop[1];
3591   int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
3592   int regno_dest;
3593 
3594   regno_dest = REGNO (dest);
3595 
3596   /* The implicit target register of LPM.  */
3597   xop[3] = lpm_reg_rtx;
3598 
3599   switch (GET_CODE (addr))
3600     {
3601     default:
3602       gcc_unreachable();
3603 
3604     case REG:
3605 
3606       gcc_assert (REG_Z == REGNO (addr));
3607 
3608       switch (n_bytes)
3609         {
3610         default:
3611           gcc_unreachable();
3612 
3613         case 1:
3614           avr_asm_len ("%4lpm", xop, plen, 1);
3615 
3616           if (regno_dest != LPM_REGNO)
3617             avr_asm_len ("mov %0,%3", xop, plen, 1);
3618 
3619           return "";
3620 
3621         case 2:
3622           if (REGNO (dest) == REG_Z)
3623             return avr_asm_len ("%4lpm"      CR_TAB
3624                                 "push %3"    CR_TAB
3625                                 "adiw %2,1"  CR_TAB
3626                                 "%4lpm"      CR_TAB
3627                                 "mov %B0,%3" CR_TAB
3628                                 "pop %A0", xop, plen, 6);
3629 
3630           avr_asm_len ("%4lpm"      CR_TAB
3631                        "mov %A0,%3" CR_TAB
3632                        "adiw %2,1"  CR_TAB
3633                        "%4lpm"      CR_TAB
3634                        "mov %B0,%3", xop, plen, 5);
3635 
3636           if (!reg_unused_after (insn, addr))
3637             avr_asm_len ("sbiw %2,1", xop, plen, 1);
3638 
3639           break; /* 2 */
3640         }
3641 
3642       break; /* REG */
3643 
3644     case POST_INC:
3645 
3646       gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
3647                   && n_bytes <= 4);
3648 
3649       if (regno_dest == LPM_REGNO)
3650         avr_asm_len ("%4lpm"      CR_TAB
3651                      "adiw %2,1", xop, plen, 2);
3652       else
3653         avr_asm_len ("%4lpm"      CR_TAB
3654                      "mov %A0,%3" CR_TAB
3655                      "adiw %2,1", xop, plen, 3);
3656 
3657       if (n_bytes >= 2)
3658         avr_asm_len ("%4lpm"      CR_TAB
3659                      "mov %B0,%3" CR_TAB
3660                      "adiw %2,1", xop, plen, 3);
3661 
3662       if (n_bytes >= 3)
3663         avr_asm_len ("%4lpm"      CR_TAB
3664                      "mov %C0,%3" CR_TAB
3665                      "adiw %2,1", xop, plen, 3);
3666 
3667       if (n_bytes >= 4)
3668         avr_asm_len ("%4lpm"      CR_TAB
3669                      "mov %D0,%3" CR_TAB
3670                      "adiw %2,1", xop, plen, 3);
3671 
3672       break; /* POST_INC */
3673 
3674     } /* switch CODE (addr) */
3675 
3676   return "";
3677 }
3678 
3679 
3680 /* If PLEN == NULL: Ouput instructions to load a value from a memory location
3681    OP[1] in AS1 to register OP[0].
3682    If PLEN != 0 set *PLEN to the length in words of the instruction sequence.
3683    Return "".  */
3684 
3685 const char*
avr_out_lpm(rtx_insn * insn,rtx * op,int * plen)3686 avr_out_lpm (rtx_insn *insn, rtx *op, int *plen)
3687 {
3688   rtx xop[7];
3689   rtx dest = op[0];
3690   rtx src = SET_SRC (single_set (insn));
3691   rtx addr;
3692   int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
3693   int segment;
3694   RTX_CODE code;
3695   addr_space_t as = MEM_ADDR_SPACE (src);
3696 
3697   if (plen)
3698     *plen = 0;
3699 
3700   if (MEM_P (dest))
3701     {
3702       warning (0, "writing to address space %qs not supported",
3703                avr_addrspace[MEM_ADDR_SPACE (dest)].name);
3704 
3705       return "";
3706     }
3707 
3708   addr = XEXP (src, 0);
3709   code = GET_CODE (addr);
3710 
3711   gcc_assert (REG_P (dest));
3712   gcc_assert (REG == code || POST_INC == code);
3713 
3714   xop[0] = dest;
3715   xop[1] = addr;
3716   xop[2] = lpm_addr_reg_rtx;
3717   xop[4] = xstring_empty;
3718   xop[5] = tmp_reg_rtx;
3719   xop[6] = XEXP (rampz_rtx, 0);
3720 
3721   segment = avr_addrspace[as].segment;
3722 
3723   /* Set RAMPZ as needed.  */
3724 
3725   if (segment)
3726     {
3727       xop[4] = GEN_INT (segment);
3728       xop[3] = avr_find_unused_d_reg (insn, lpm_addr_reg_rtx);
3729 
3730       if (xop[3] != NULL_RTX)
3731         {
3732           avr_asm_len ("ldi %3,%4" CR_TAB
3733                        "out %i6,%3", xop, plen, 2);
3734         }
3735       else if (segment == 1)
3736         {
3737           avr_asm_len ("clr %5" CR_TAB
3738                        "inc %5" CR_TAB
3739                        "out %i6,%5", xop, plen, 3);
3740         }
3741       else
3742         {
3743           avr_asm_len ("mov %5,%2"   CR_TAB
3744                        "ldi %2,%4"   CR_TAB
3745                        "out %i6,%2"  CR_TAB
3746                        "mov %2,%5", xop, plen, 4);
3747         }
3748 
3749       xop[4] = xstring_e;
3750 
3751       if (!AVR_HAVE_ELPMX)
3752         return avr_out_lpm_no_lpmx (insn, xop, plen);
3753     }
3754   else if (!AVR_HAVE_LPMX)
3755     {
3756       return avr_out_lpm_no_lpmx (insn, xop, plen);
3757     }
3758 
3759   /* We have [E]LPMX: Output reading from Flash the comfortable way.  */
3760 
3761   switch (GET_CODE (addr))
3762     {
3763     default:
3764       gcc_unreachable();
3765 
3766     case REG:
3767 
3768       gcc_assert (REG_Z == REGNO (addr));
3769 
3770       switch (n_bytes)
3771         {
3772         default:
3773           gcc_unreachable();
3774 
3775         case 1:
3776           avr_asm_len ("%4lpm %0,%a2", xop, plen, 1);
3777           break;
3778 
3779         case 2:
3780           if (REGNO (dest) == REG_Z)
3781             avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3782                          "%4lpm %B0,%a2" CR_TAB
3783                          "mov %A0,%5", xop, plen, 3);
3784           else
3785             {
3786               avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3787                            "%4lpm %B0,%a2", xop, plen, 2);
3788 
3789               if (!reg_unused_after (insn, addr))
3790                 avr_asm_len ("sbiw %2,1", xop, plen, 1);
3791             }
3792 
3793           break; /* 2 */
3794 
3795         case 3:
3796 
3797           avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3798                        "%4lpm %B0,%a2+" CR_TAB
3799                        "%4lpm %C0,%a2", xop, plen, 3);
3800 
3801           if (!reg_unused_after (insn, addr))
3802             avr_asm_len ("sbiw %2,2", xop, plen, 1);
3803 
3804           break; /* 3 */
3805 
3806         case 4:
3807 
3808           avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3809                        "%4lpm %B0,%a2+", xop, plen, 2);
3810 
3811           if (REGNO (dest) == REG_Z - 2)
3812             avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3813                          "%4lpm %C0,%a2" CR_TAB
3814                          "mov %D0,%5", xop, plen, 3);
3815           else
3816             {
3817               avr_asm_len ("%4lpm %C0,%a2+" CR_TAB
3818                            "%4lpm %D0,%a2", xop, plen, 2);
3819 
3820               if (!reg_unused_after (insn, addr))
3821                 avr_asm_len ("sbiw %2,3", xop, plen, 1);
3822             }
3823 
3824           break; /* 4 */
3825         } /* n_bytes */
3826 
3827       break; /* REG */
3828 
3829     case POST_INC:
3830 
3831       gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
3832                   && n_bytes <= 4);
3833 
3834       avr_asm_len                    ("%4lpm %A0,%a2+", xop, plen, 1);
3835       if (n_bytes >= 2)  avr_asm_len ("%4lpm %B0,%a2+", xop, plen, 1);
3836       if (n_bytes >= 3)  avr_asm_len ("%4lpm %C0,%a2+", xop, plen, 1);
3837       if (n_bytes >= 4)  avr_asm_len ("%4lpm %D0,%a2+", xop, plen, 1);
3838 
3839       break; /* POST_INC */
3840 
3841     } /* switch CODE (addr) */
3842 
3843   if (xop[4] == xstring_e && AVR_HAVE_RAMPD)
3844     {
3845       /* Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM.  */
3846 
3847       xop[0] = zero_reg_rtx;
3848       avr_asm_len ("out %i6,%0", xop, plen, 1);
3849     }
3850 
3851   return "";
3852 }
3853 
3854 
3855 /* Worker function for xload_8 insn.  */
3856 
3857 const char*
avr_out_xload(rtx_insn * insn ATTRIBUTE_UNUSED,rtx * op,int * plen)3858 avr_out_xload (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
3859 {
3860   rtx xop[4];
3861 
3862   xop[0] = op[0];
3863   xop[1] = op[1];
3864   xop[2] = lpm_addr_reg_rtx;
3865   xop[3] = AVR_HAVE_LPMX ? op[0] : lpm_reg_rtx;
3866 
3867   avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, -1);
3868 
3869   avr_asm_len ("sbrc %1,7" CR_TAB
3870                "ld %3,%a2", xop, plen, 2);
3871 
3872   if (REGNO (xop[0]) != REGNO (xop[3]))
3873     avr_asm_len ("mov %0,%3", xop, plen, 1);
3874 
3875   return "";
3876 }
3877 
3878 
3879 const char*
output_movqi(rtx_insn * insn,rtx operands[],int * plen)3880 output_movqi (rtx_insn *insn, rtx operands[], int *plen)
3881 {
3882   rtx dest = operands[0];
3883   rtx src = operands[1];
3884 
3885   if (avr_mem_flash_p (src)
3886       || avr_mem_flash_p (dest))
3887     {
3888       return avr_out_lpm (insn, operands, plen);
3889     }
3890 
3891   gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 1);
3892 
3893   if (REG_P (dest))
3894     {
3895       if (REG_P (src)) /* mov r,r */
3896         {
3897           if (test_hard_reg_class (STACK_REG, dest))
3898             return avr_asm_len ("out %0,%1", operands, plen, -1);
3899           else if (test_hard_reg_class (STACK_REG, src))
3900             return avr_asm_len ("in %0,%1", operands, plen, -1);
3901 
3902           return avr_asm_len ("mov %0,%1", operands, plen, -1);
3903         }
3904       else if (CONSTANT_P (src))
3905         {
3906           output_reload_in_const (operands, NULL_RTX, plen, false);
3907           return "";
3908         }
3909       else if (MEM_P (src))
3910         return out_movqi_r_mr (insn, operands, plen); /* mov r,m */
3911     }
3912   else if (MEM_P (dest))
3913     {
3914       rtx xop[2];
3915 
3916       xop[0] = dest;
3917       xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
3918 
3919       return out_movqi_mr_r (insn, xop, plen);
3920     }
3921 
3922   return "";
3923 }
3924 
3925 
3926 const char *
output_movhi(rtx_insn * insn,rtx xop[],int * plen)3927 output_movhi (rtx_insn *insn, rtx xop[], int *plen)
3928 {
3929   rtx dest = xop[0];
3930   rtx src = xop[1];
3931 
3932   gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 2);
3933 
3934   if (avr_mem_flash_p (src)
3935       || avr_mem_flash_p (dest))
3936     {
3937       return avr_out_lpm (insn, xop, plen);
3938     }
3939 
3940   if (REG_P (dest))
3941     {
3942       if (REG_P (src)) /* mov r,r */
3943         {
3944           if (test_hard_reg_class (STACK_REG, dest))
3945             {
3946               if (AVR_HAVE_8BIT_SP)
3947                 return avr_asm_len ("out __SP_L__,%A1", xop, plen, -1);
3948 
3949               if (AVR_XMEGA)
3950                 return avr_asm_len ("out __SP_L__,%A1" CR_TAB
3951                                     "out __SP_H__,%B1", xop, plen, -2);
3952 
3953               /* Use simple load of SP if no interrupts are  used.  */
3954 
3955               return TARGET_NO_INTERRUPTS
3956                 ? avr_asm_len ("out __SP_H__,%B1" CR_TAB
3957                                "out __SP_L__,%A1", xop, plen, -2)
3958                 : avr_asm_len ("in __tmp_reg__,__SREG__"  CR_TAB
3959                                "cli"                      CR_TAB
3960                                "out __SP_H__,%B1"         CR_TAB
3961                                "out __SREG__,__tmp_reg__" CR_TAB
3962                                "out __SP_L__,%A1", xop, plen, -5);
3963             }
3964           else if (test_hard_reg_class (STACK_REG, src))
3965             {
3966               return !AVR_HAVE_SPH
3967                 ? avr_asm_len ("in %A0,__SP_L__" CR_TAB
3968                                "clr %B0", xop, plen, -2)
3969 
3970                 : avr_asm_len ("in %A0,__SP_L__" CR_TAB
3971                                "in %B0,__SP_H__", xop, plen, -2);
3972             }
3973 
3974           return AVR_HAVE_MOVW
3975             ? avr_asm_len ("movw %0,%1", xop, plen, -1)
3976 
3977             : avr_asm_len ("mov %A0,%A1" CR_TAB
3978                            "mov %B0,%B1", xop, plen, -2);
3979         } /* REG_P (src) */
3980       else if (CONSTANT_P (src))
3981         {
3982           return output_reload_inhi (xop, NULL, plen);
3983         }
3984       else if (MEM_P (src))
3985         {
3986           return out_movhi_r_mr (insn, xop, plen); /* mov r,m */
3987         }
3988     }
3989   else if (MEM_P (dest))
3990     {
3991       rtx xop[2];
3992 
3993       xop[0] = dest;
3994       xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
3995 
3996       return out_movhi_mr_r (insn, xop, plen);
3997     }
3998 
3999   fatal_insn ("invalid insn:", insn);
4000 
4001   return "";
4002 }
4003 
4004 
4005 /* Same as out_movqi_r_mr, but TINY does not have ADIW or SBIW */
4006 
4007 static const char*
avr_out_movqi_r_mr_reg_disp_tiny(rtx_insn * insn,rtx op[],int * plen)4008 avr_out_movqi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
4009 {
4010   rtx dest = op[0];
4011   rtx src = op[1];
4012   rtx x = XEXP (src, 0);
4013 
4014   avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4015                "ld %0,%b1" , op, plen, -3);
4016 
4017   if (!reg_overlap_mentioned_p (dest, XEXP (x, 0))
4018       && !reg_unused_after (insn, XEXP (x, 0)))
4019     avr_asm_len (TINY_SBIW (%I1, %J1, %o1), op, plen, 2);
4020 
4021   return "";
4022 }
4023 
4024 static const char*
out_movqi_r_mr(rtx_insn * insn,rtx op[],int * plen)4025 out_movqi_r_mr (rtx_insn *insn, rtx op[], int *plen)
4026 {
4027   rtx dest = op[0];
4028   rtx src = op[1];
4029   rtx x = XEXP (src, 0);
4030 
4031   if (CONSTANT_ADDRESS_P (x))
4032     {
4033       int n_words = AVR_TINY ? 1 : 2;
4034       return io_address_operand (x, QImode)
4035         ? avr_asm_len ("in %0,%i1", op, plen, -1)
4036         : avr_asm_len ("lds %0,%m1", op, plen, -n_words);
4037     }
4038 
4039   if (GET_CODE (x) == PLUS
4040       && REG_P (XEXP (x, 0))
4041       && CONST_INT_P (XEXP (x, 1)))
4042     {
4043       /* memory access by reg+disp */
4044 
4045       int disp = INTVAL (XEXP (x, 1));
4046 
4047       if (AVR_TINY)
4048         return avr_out_movqi_r_mr_reg_disp_tiny (insn, op, plen);
4049 
4050       if (disp - GET_MODE_SIZE (GET_MODE (src)) >= 63)
4051         {
4052           if (REGNO (XEXP (x, 0)) != REG_Y)
4053             fatal_insn ("incorrect insn:",insn);
4054 
4055           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
4056             return avr_asm_len ("adiw r28,%o1-63" CR_TAB
4057                                 "ldd %0,Y+63"     CR_TAB
4058                                 "sbiw r28,%o1-63", op, plen, -3);
4059 
4060           return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
4061                               "sbci r29,hi8(-%o1)" CR_TAB
4062                               "ld %0,Y"            CR_TAB
4063                               "subi r28,lo8(%o1)"  CR_TAB
4064                               "sbci r29,hi8(%o1)", op, plen, -5);
4065         }
4066       else if (REGNO (XEXP (x, 0)) == REG_X)
4067         {
4068           /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
4069              it but I have this situation with extremal optimizing options.  */
4070 
4071           avr_asm_len ("adiw r26,%o1" CR_TAB
4072                        "ld %0,X", op, plen, -2);
4073 
4074           if (!reg_overlap_mentioned_p (dest, XEXP (x, 0))
4075               && !reg_unused_after (insn, XEXP (x, 0)))
4076             {
4077               avr_asm_len ("sbiw r26,%o1", op, plen, 1);
4078             }
4079 
4080           return "";
4081         }
4082 
4083       return avr_asm_len ("ldd %0,%1", op, plen, -1);
4084     }
4085 
4086   return avr_asm_len ("ld %0,%1", op, plen, -1);
4087 }
4088 
4089 
4090 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
4091 
4092 static const char*
avr_out_movhi_r_mr_reg_no_disp_tiny(rtx_insn * insn,rtx op[],int * plen)4093 avr_out_movhi_r_mr_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
4094 {
4095   rtx dest = op[0];
4096   rtx src = op[1];
4097   rtx base = XEXP (src, 0);
4098 
4099   int reg_dest = true_regnum (dest);
4100   int reg_base = true_regnum (base);
4101 
4102   if (reg_dest == reg_base)         /* R = (R) */
4103     return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
4104 			"ld %B0,%1"          CR_TAB
4105 			"mov %A0,__tmp_reg__", op, plen, -3);
4106 
4107   avr_asm_len ("ld %A0,%1+" CR_TAB
4108                "ld %B0,%1", op, plen, -2);
4109 
4110   if (!reg_unused_after (insn, base))
4111     avr_asm_len (TINY_SBIW (%E1, %F1, 1), op, plen, 2);
4112 
4113   return "";
4114 }
4115 
4116 
4117 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
4118 
4119 static const char*
avr_out_movhi_r_mr_reg_disp_tiny(rtx_insn * insn,rtx op[],int * plen)4120 avr_out_movhi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
4121 {
4122   rtx dest = op[0];
4123   rtx src = op[1];
4124   rtx base = XEXP (src, 0);
4125 
4126   int reg_dest = true_regnum (dest);
4127   int reg_base = true_regnum (XEXP (base, 0));
4128 
4129   if (reg_base == reg_dest)
4130     {
4131       return avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4132                           "ld __tmp_reg__,%b1+"     CR_TAB
4133                           "ld %B0,%b1"              CR_TAB
4134                           "mov %A0,__tmp_reg__", op, plen, -5);
4135     }
4136   else
4137     {
4138       avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4139                    "ld %A0,%b1+"             CR_TAB
4140                    "ld %B0,%b1", op, plen, -4);
4141 
4142       if (!reg_unused_after (insn, XEXP (base, 0)))
4143         avr_asm_len (TINY_SBIW (%I1, %J1, %o1+1), op, plen, 2);
4144 
4145       return "";
4146     }
4147 }
4148 
4149 
4150 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
4151 
4152 static const char*
avr_out_movhi_r_mr_pre_dec_tiny(rtx_insn * insn,rtx op[],int * plen)4153 avr_out_movhi_r_mr_pre_dec_tiny (rtx_insn *insn, rtx op[], int *plen)
4154 {
4155   int mem_volatile_p = 0;
4156   rtx dest = op[0];
4157   rtx src = op[1];
4158   rtx base = XEXP (src, 0);
4159 
4160   /* "volatile" forces reading low byte first, even if less efficient,
4161      for correct operation with 16-bit I/O registers.  */
4162   mem_volatile_p = MEM_VOLATILE_P (src);
4163 
4164   if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
4165     fatal_insn ("incorrect insn:", insn);
4166 
4167   if (!mem_volatile_p)
4168     return avr_asm_len ("ld %B0,%1" CR_TAB
4169                         "ld %A0,%1", op, plen, -2);
4170 
4171   return avr_asm_len (TINY_SBIW (%I1, %J1, 2)  CR_TAB
4172                       "ld %A0,%p1+"            CR_TAB
4173                       "ld %B0,%p1"             CR_TAB
4174                       TINY_SBIW (%I1, %J1, 1), op, plen, -6);
4175 }
4176 
4177 
4178 static const char*
out_movhi_r_mr(rtx_insn * insn,rtx op[],int * plen)4179 out_movhi_r_mr (rtx_insn *insn, rtx op[], int *plen)
4180 {
4181   rtx dest = op[0];
4182   rtx src = op[1];
4183   rtx base = XEXP (src, 0);
4184   int reg_dest = true_regnum (dest);
4185   int reg_base = true_regnum (base);
4186   /* "volatile" forces reading low byte first, even if less efficient,
4187      for correct operation with 16-bit I/O registers.  */
4188   int mem_volatile_p = MEM_VOLATILE_P (src);
4189 
4190   if (reg_base > 0)
4191     {
4192       if (AVR_TINY)
4193         return avr_out_movhi_r_mr_reg_no_disp_tiny (insn, op, plen);
4194 
4195       if (reg_dest == reg_base)         /* R = (R) */
4196         return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
4197                             "ld %B0,%1"          CR_TAB
4198                             "mov %A0,__tmp_reg__", op, plen, -3);
4199 
4200       if (reg_base != REG_X)
4201         return avr_asm_len ("ld %A0,%1" CR_TAB
4202                             "ldd %B0,%1+1", op, plen, -2);
4203 
4204       avr_asm_len ("ld %A0,X+" CR_TAB
4205                    "ld %B0,X", op, plen, -2);
4206 
4207       if (!reg_unused_after (insn, base))
4208         avr_asm_len ("sbiw r26,1", op, plen, 1);
4209 
4210       return "";
4211     }
4212   else if (GET_CODE (base) == PLUS) /* (R + i) */
4213     {
4214       int disp = INTVAL (XEXP (base, 1));
4215       int reg_base = true_regnum (XEXP (base, 0));
4216 
4217       if (AVR_TINY)
4218         return avr_out_movhi_r_mr_reg_disp_tiny (insn, op, plen);
4219 
4220       if (disp > MAX_LD_OFFSET (GET_MODE (src)))
4221         {
4222           if (REGNO (XEXP (base, 0)) != REG_Y)
4223             fatal_insn ("incorrect insn:",insn);
4224 
4225           return disp <= 63 + MAX_LD_OFFSET (GET_MODE (src))
4226             ? avr_asm_len ("adiw r28,%o1-62" CR_TAB
4227                            "ldd %A0,Y+62"    CR_TAB
4228                            "ldd %B0,Y+63"    CR_TAB
4229                            "sbiw r28,%o1-62", op, plen, -4)
4230 
4231             : avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
4232                            "sbci r29,hi8(-%o1)" CR_TAB
4233                            "ld %A0,Y"           CR_TAB
4234                            "ldd %B0,Y+1"        CR_TAB
4235                            "subi r28,lo8(%o1)"  CR_TAB
4236                            "sbci r29,hi8(%o1)", op, plen, -6);
4237         }
4238 
4239       /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
4240          it but I have this situation with extremal
4241          optimization options.  */
4242 
4243       if (reg_base == REG_X)
4244         {
4245           if (reg_base == reg_dest)
4246             return avr_asm_len ("adiw r26,%o1"      CR_TAB
4247                                 "ld __tmp_reg__,X+" CR_TAB
4248                                 "ld %B0,X"          CR_TAB
4249                                 "mov %A0,__tmp_reg__", op, plen, -4);
4250 
4251           avr_asm_len ("adiw r26,%o1" CR_TAB
4252                        "ld %A0,X+"    CR_TAB
4253                        "ld %B0,X", op, plen, -3);
4254 
4255           if (!reg_unused_after (insn, XEXP (base, 0)))
4256             avr_asm_len ("sbiw r26,%o1+1", op, plen, 1);
4257 
4258           return "";
4259         }
4260 
4261       return reg_base == reg_dest
4262         ? avr_asm_len ("ldd __tmp_reg__,%A1" CR_TAB
4263                        "ldd %B0,%B1"         CR_TAB
4264                        "mov %A0,__tmp_reg__", op, plen, -3)
4265 
4266         : avr_asm_len ("ldd %A0,%A1" CR_TAB
4267                        "ldd %B0,%B1", op, plen, -2);
4268     }
4269   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4270     {
4271       if (AVR_TINY)
4272 	return avr_out_movhi_r_mr_pre_dec_tiny (insn, op, plen);
4273 
4274       if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
4275         fatal_insn ("incorrect insn:", insn);
4276 
4277       if (!mem_volatile_p)
4278         return avr_asm_len ("ld %B0,%1" CR_TAB
4279                             "ld %A0,%1", op, plen, -2);
4280 
4281       return REGNO (XEXP (base, 0)) == REG_X
4282         ? avr_asm_len ("sbiw r26,2"  CR_TAB
4283                        "ld %A0,X+"   CR_TAB
4284                        "ld %B0,X"    CR_TAB
4285                        "sbiw r26,1", op, plen, -4)
4286 
4287         : avr_asm_len ("sbiw %r1,2"  CR_TAB
4288                        "ld %A0,%p1"  CR_TAB
4289                        "ldd %B0,%p1+1", op, plen, -3);
4290     }
4291   else if (GET_CODE (base) == POST_INC) /* (R++) */
4292     {
4293       if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
4294         fatal_insn ("incorrect insn:", insn);
4295 
4296       return avr_asm_len ("ld %A0,%1"  CR_TAB
4297                           "ld %B0,%1", op, plen, -2);
4298     }
4299   else if (CONSTANT_ADDRESS_P (base))
4300     {
4301       int n_words = AVR_TINY ? 2 : 4;
4302       return io_address_operand (base, HImode)
4303         ? avr_asm_len ("in %A0,%i1" CR_TAB
4304                        "in %B0,%i1+1", op, plen, -2)
4305 
4306         : avr_asm_len ("lds %A0,%m1" CR_TAB
4307                        "lds %B0,%m1+1", op, plen, -n_words);
4308     }
4309 
4310   fatal_insn ("unknown move insn:",insn);
4311   return "";
4312 }
4313 
4314 static const char*
avr_out_movsi_r_mr_reg_no_disp_tiny(rtx_insn * insn,rtx op[],int * l)4315 avr_out_movsi_r_mr_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *l)
4316 {
4317   rtx dest = op[0];
4318   rtx src = op[1];
4319   rtx base = XEXP (src, 0);
4320   int reg_dest = true_regnum (dest);
4321   int reg_base = true_regnum (base);
4322 
4323   if (reg_dest == reg_base)
4324     {
4325       /* "ld r26,-X" is undefined */
4326       return *l = 9, (TINY_ADIW (%E1, %F1, 3) CR_TAB
4327 		      "ld %D0,%1"             CR_TAB
4328 		      "ld %C0,-%1"            CR_TAB
4329 		      "ld __tmp_reg__,-%1"    CR_TAB
4330 		      TINY_SBIW (%E1, %F1, 1) CR_TAB
4331 		      "ld %A0,%1"             CR_TAB
4332 		      "mov %B0,__tmp_reg__");
4333     }
4334   else if (reg_dest == reg_base - 2)
4335     {
4336       return *l = 5, ("ld %A0,%1+"            CR_TAB
4337 		      "ld %B0,%1+"            CR_TAB
4338 		      "ld __tmp_reg__,%1+"    CR_TAB
4339 		      "ld %D0,%1"             CR_TAB
4340 		      "mov %C0,__tmp_reg__");
4341     }
4342   else if (reg_unused_after (insn, base))
4343     {
4344       return *l = 4, ("ld %A0,%1+"    CR_TAB
4345 		      "ld %B0,%1+"    CR_TAB
4346 		      "ld %C0,%1+"    CR_TAB
4347 		      "ld %D0,%1");
4348     }
4349   else
4350     {
4351       return *l = 6, ("ld %A0,%1+"    CR_TAB
4352 		      "ld %B0,%1+"    CR_TAB
4353 		      "ld %C0,%1+"    CR_TAB
4354 		      "ld %D0,%1"     CR_TAB
4355 		      TINY_SBIW (%E1, %F1, 3));
4356     }
4357 }
4358 
4359 
4360 static const char*
avr_out_movsi_r_mr_reg_disp_tiny(rtx_insn * insn,rtx op[],int * l)4361 avr_out_movsi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *l)
4362 {
4363   rtx dest = op[0];
4364   rtx src = op[1];
4365   rtx base = XEXP (src, 0);
4366   int reg_dest = true_regnum (dest);
4367   int reg_base = true_regnum (XEXP (base, 0));
4368 
4369   if (reg_dest == reg_base)
4370     {
4371       /* "ld r26,-X" is undefined */
4372       return *l = 9, (TINY_ADIW (%I1, %J1, %o1+3) CR_TAB
4373                       "ld %D0,%b1"                CR_TAB
4374                       "ld %C0,-%b1"               CR_TAB
4375                       "ld __tmp_reg__,-%b1"       CR_TAB
4376                       TINY_SBIW (%I1, %J1, 1)     CR_TAB
4377                       "ld %A0,%b1"                CR_TAB
4378                       "mov %B0,__tmp_reg__");
4379     }
4380   else if (reg_dest == reg_base - 2)
4381     {
4382       return *l = 7, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4383                       "ld %A0,%b1+"             CR_TAB
4384                       "ld %B0,%b1+"             CR_TAB
4385                       "ld __tmp_reg__,%b1+"     CR_TAB
4386                       "ld %D0,%b1"              CR_TAB
4387                       "mov %C0,__tmp_reg__");
4388     }
4389   else if (reg_unused_after (insn, XEXP (base, 0)))
4390     {
4391       return *l = 6, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4392                       "ld %A0,%b1+"             CR_TAB
4393                       "ld %B0,%b1+"             CR_TAB
4394                       "ld %C0,%b1+"             CR_TAB
4395                       "ld %D0,%b1");
4396     }
4397   else
4398     {
4399       return *l = 8, (TINY_ADIW (%I1, %J1, %o1)  CR_TAB
4400                       "ld %A0,%b1+"              CR_TAB
4401                       "ld %B0,%b1+"              CR_TAB
4402                       "ld %C0,%b1+"              CR_TAB
4403                       "ld %D0,%b1"               CR_TAB
4404                       TINY_SBIW (%I1, %J1, %o1+3));
4405     }
4406 }
4407 
4408 static const char*
out_movsi_r_mr(rtx_insn * insn,rtx op[],int * l)4409 out_movsi_r_mr (rtx_insn *insn, rtx op[], int *l)
4410 {
4411   rtx dest = op[0];
4412   rtx src = op[1];
4413   rtx base = XEXP (src, 0);
4414   int reg_dest = true_regnum (dest);
4415   int reg_base = true_regnum (base);
4416   int tmp;
4417 
4418   if (!l)
4419     l = &tmp;
4420 
4421   if (reg_base > 0)
4422     {
4423       if (AVR_TINY)
4424         return avr_out_movsi_r_mr_reg_no_disp_tiny (insn, op, l);
4425 
4426       if (reg_base == REG_X)        /* (R26) */
4427         {
4428           if (reg_dest == REG_X)
4429 	    /* "ld r26,-X" is undefined */
4430 	    return *l=7, ("adiw r26,3"        CR_TAB
4431 			  "ld r29,X"          CR_TAB
4432 			  "ld r28,-X"         CR_TAB
4433 			  "ld __tmp_reg__,-X" CR_TAB
4434 			  "sbiw r26,1"        CR_TAB
4435 			  "ld r26,X"          CR_TAB
4436 			  "mov r27,__tmp_reg__");
4437           else if (reg_dest == REG_X - 2)
4438             return *l=5, ("ld %A0,X+"          CR_TAB
4439                           "ld %B0,X+"          CR_TAB
4440                           "ld __tmp_reg__,X+"  CR_TAB
4441                           "ld %D0,X"           CR_TAB
4442                           "mov %C0,__tmp_reg__");
4443           else if (reg_unused_after (insn, base))
4444             return  *l=4, ("ld %A0,X+" CR_TAB
4445                            "ld %B0,X+" CR_TAB
4446                            "ld %C0,X+" CR_TAB
4447                            "ld %D0,X");
4448           else
4449             return  *l=5, ("ld %A0,X+" CR_TAB
4450                            "ld %B0,X+" CR_TAB
4451                            "ld %C0,X+" CR_TAB
4452                            "ld %D0,X"  CR_TAB
4453                            "sbiw r26,3");
4454         }
4455       else
4456         {
4457           if (reg_dest == reg_base)
4458             return *l=5, ("ldd %D0,%1+3" CR_TAB
4459                           "ldd %C0,%1+2" CR_TAB
4460                           "ldd __tmp_reg__,%1+1"  CR_TAB
4461                           "ld %A0,%1"  CR_TAB
4462                           "mov %B0,__tmp_reg__");
4463           else if (reg_base == reg_dest + 2)
4464             return *l=5, ("ld %A0,%1"             CR_TAB
4465                           "ldd %B0,%1+1"          CR_TAB
4466                           "ldd __tmp_reg__,%1+2"  CR_TAB
4467                           "ldd %D0,%1+3"          CR_TAB
4468                           "mov %C0,__tmp_reg__");
4469           else
4470             return *l=4, ("ld %A0,%1"    CR_TAB
4471                           "ldd %B0,%1+1" CR_TAB
4472                           "ldd %C0,%1+2" CR_TAB
4473                           "ldd %D0,%1+3");
4474         }
4475     }
4476   else if (GET_CODE (base) == PLUS) /* (R + i) */
4477     {
4478       int disp = INTVAL (XEXP (base, 1));
4479 
4480       if (AVR_TINY)
4481         return avr_out_movsi_r_mr_reg_disp_tiny (insn, op, l);
4482 
4483       if (disp > MAX_LD_OFFSET (GET_MODE (src)))
4484 	{
4485 	  if (REGNO (XEXP (base, 0)) != REG_Y)
4486 	    fatal_insn ("incorrect insn:",insn);
4487 
4488 	  if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
4489 	    return *l = 6, ("adiw r28,%o1-60" CR_TAB
4490 			    "ldd %A0,Y+60"    CR_TAB
4491 			    "ldd %B0,Y+61"    CR_TAB
4492 			    "ldd %C0,Y+62"    CR_TAB
4493 			    "ldd %D0,Y+63"    CR_TAB
4494 			    "sbiw r28,%o1-60");
4495 
4496 	  return *l = 8, ("subi r28,lo8(-%o1)" CR_TAB
4497 			  "sbci r29,hi8(-%o1)" CR_TAB
4498 			  "ld %A0,Y"           CR_TAB
4499 			  "ldd %B0,Y+1"        CR_TAB
4500 			  "ldd %C0,Y+2"        CR_TAB
4501 			  "ldd %D0,Y+3"        CR_TAB
4502 			  "subi r28,lo8(%o1)"  CR_TAB
4503 			  "sbci r29,hi8(%o1)");
4504 	}
4505 
4506       reg_base = true_regnum (XEXP (base, 0));
4507       if (reg_base == REG_X)
4508 	{
4509 	  /* R = (X + d) */
4510 	  if (reg_dest == REG_X)
4511 	    {
4512 	      *l = 7;
4513 	      /* "ld r26,-X" is undefined */
4514 	      return ("adiw r26,%o1+3"    CR_TAB
4515 		      "ld r29,X"          CR_TAB
4516 		      "ld r28,-X"         CR_TAB
4517 		      "ld __tmp_reg__,-X" CR_TAB
4518 		      "sbiw r26,1"        CR_TAB
4519 		      "ld r26,X"          CR_TAB
4520 		      "mov r27,__tmp_reg__");
4521 	    }
4522 	  *l = 6;
4523 	  if (reg_dest == REG_X - 2)
4524 	    return ("adiw r26,%o1"      CR_TAB
4525 		    "ld r24,X+"         CR_TAB
4526 		    "ld r25,X+"         CR_TAB
4527 		    "ld __tmp_reg__,X+" CR_TAB
4528 		    "ld r27,X"          CR_TAB
4529 		    "mov r26,__tmp_reg__");
4530 
4531 	  return ("adiw r26,%o1" CR_TAB
4532 		  "ld %A0,X+"    CR_TAB
4533 		  "ld %B0,X+"    CR_TAB
4534 		  "ld %C0,X+"    CR_TAB
4535 		  "ld %D0,X"     CR_TAB
4536 		  "sbiw r26,%o1+3");
4537 	}
4538       if (reg_dest == reg_base)
4539         return *l=5, ("ldd %D0,%D1"          CR_TAB
4540                       "ldd %C0,%C1"          CR_TAB
4541                       "ldd __tmp_reg__,%B1"  CR_TAB
4542                       "ldd %A0,%A1"          CR_TAB
4543                       "mov %B0,__tmp_reg__");
4544       else if (reg_dest == reg_base - 2)
4545         return *l=5, ("ldd %A0,%A1"          CR_TAB
4546                       "ldd %B0,%B1"          CR_TAB
4547                       "ldd __tmp_reg__,%C1"  CR_TAB
4548                       "ldd %D0,%D1"          CR_TAB
4549                       "mov %C0,__tmp_reg__");
4550       return *l=4, ("ldd %A0,%A1" CR_TAB
4551                     "ldd %B0,%B1" CR_TAB
4552                     "ldd %C0,%C1" CR_TAB
4553                     "ldd %D0,%D1");
4554     }
4555   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4556     return *l=4, ("ld %D0,%1" CR_TAB
4557 		  "ld %C0,%1" CR_TAB
4558 		  "ld %B0,%1" CR_TAB
4559 		  "ld %A0,%1");
4560   else if (GET_CODE (base) == POST_INC) /* (R++) */
4561     return *l=4, ("ld %A0,%1" CR_TAB
4562 		  "ld %B0,%1" CR_TAB
4563 		  "ld %C0,%1" CR_TAB
4564 		  "ld %D0,%1");
4565   else if (CONSTANT_ADDRESS_P (base))
4566     {
4567       if (io_address_operand (base, SImode))
4568         {
4569           *l = 4;
4570           return ("in %A0,%i1"   CR_TAB
4571                   "in %B0,%i1+1" CR_TAB
4572                   "in %C0,%i1+2" CR_TAB
4573                   "in %D0,%i1+3");
4574         }
4575       else
4576         {
4577           *l = AVR_TINY ? 4 : 8;
4578           return ("lds %A0,%m1"   CR_TAB
4579                   "lds %B0,%m1+1" CR_TAB
4580                   "lds %C0,%m1+2" CR_TAB
4581                   "lds %D0,%m1+3");
4582         }
4583     }
4584 
4585   fatal_insn ("unknown move insn:",insn);
4586   return "";
4587 }
4588 
4589 static const char*
avr_out_movsi_mr_r_reg_no_disp_tiny(rtx_insn * insn,rtx op[],int * l)4590 avr_out_movsi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *l)
4591 {
4592   rtx dest = op[0];
4593   rtx src = op[1];
4594   rtx base = XEXP (dest, 0);
4595   int reg_base = true_regnum (base);
4596   int reg_src = true_regnum (src);
4597 
4598   if (reg_base == reg_src)
4599     {
4600       /* "ld r26,-X" is undefined */
4601       if (reg_unused_after (insn, base))
4602         {
4603           return *l = 7, ("mov __tmp_reg__, %B1"  CR_TAB
4604 			  "st %0,%A1"             CR_TAB
4605 			  TINY_ADIW (%E0, %F0, 1) CR_TAB
4606 			  "st %0+,__tmp_reg__"    CR_TAB
4607 			  "st %0+,%C1"            CR_TAB
4608 			  "st %0+,%D1");
4609         }
4610       else
4611         {
4612           return *l = 9, ("mov __tmp_reg__, %B1"  CR_TAB
4613 			  "st %0,%A1"             CR_TAB
4614 			  TINY_ADIW (%E0, %F0, 1) CR_TAB
4615 			  "st %0+,__tmp_reg__"    CR_TAB
4616 			  "st %0+,%C1"            CR_TAB
4617 			  "st %0+,%D1"            CR_TAB
4618 			  TINY_SBIW (%E0, %F0, 3));
4619         }
4620     }
4621   else if (reg_base == reg_src + 2)
4622     {
4623       if (reg_unused_after (insn, base))
4624 	return *l = 7, ("mov __zero_reg__,%C1" CR_TAB
4625                         "mov __tmp_reg__,%D1"  CR_TAB
4626                         "st %0+,%A1"           CR_TAB
4627                         "st %0+,%B1"           CR_TAB
4628                         "st %0+,__zero_reg__"  CR_TAB
4629                         "st %0,__tmp_reg__"    CR_TAB
4630                         "clr __zero_reg__");
4631       else
4632 	return *l = 9, ("mov __zero_reg__,%C1" CR_TAB
4633 			"mov __tmp_reg__,%D1"  CR_TAB
4634 			"st %0+,%A1"           CR_TAB
4635 			"st %0+,%B1"           CR_TAB
4636 			"st %0+,__zero_reg__"  CR_TAB
4637 			"st %0,__tmp_reg__"    CR_TAB
4638 			"clr __zero_reg__"     CR_TAB
4639 			TINY_SBIW (%E0, %F0, 3));
4640     }
4641 
4642   return *l = 6, ("st %0+,%A1" CR_TAB
4643 		  "st %0+,%B1" CR_TAB
4644 		  "st %0+,%C1" CR_TAB
4645 		  "st %0,%D1"  CR_TAB
4646 		  TINY_SBIW (%E0, %F0, 3));
4647 }
4648 
4649 static const char*
avr_out_movsi_mr_r_reg_disp_tiny(rtx op[],int * l)4650 avr_out_movsi_mr_r_reg_disp_tiny (rtx op[], int *l)
4651 {
4652   rtx dest = op[0];
4653   rtx src = op[1];
4654   rtx base = XEXP (dest, 0);
4655   int reg_base = REGNO (XEXP (base, 0));
4656   int reg_src =true_regnum (src);
4657 
4658   if (reg_base == reg_src)
4659     {
4660       *l = 11;
4661       return ("mov __tmp_reg__,%A2"        CR_TAB
4662               "mov __zero_reg__,%B2"       CR_TAB
4663               TINY_ADIW (%I0, %J0, %o0)    CR_TAB
4664               "st %b0+,__tmp_reg__"        CR_TAB
4665               "st %b0+,__zero_reg__"       CR_TAB
4666               "st %b0+,%C2"                CR_TAB
4667               "st %b0,%D2"                 CR_TAB
4668               "clr __zero_reg__"           CR_TAB
4669               TINY_SBIW (%I0, %J0, %o0+3));
4670     }
4671   else if (reg_src == reg_base - 2)
4672     {
4673       *l = 11;
4674       return ("mov __tmp_reg__,%C2"         CR_TAB
4675               "mov __zero_reg__,%D2"        CR_TAB
4676               TINY_ADIW (%I0, %J0, %o0)     CR_TAB
4677               "st %b0+,%A0"                 CR_TAB
4678               "st %b0+,%B0"                 CR_TAB
4679               "st %b0+,__tmp_reg__"         CR_TAB
4680               "st %b0,__zero_reg__"         CR_TAB
4681               "clr __zero_reg__"            CR_TAB
4682               TINY_SBIW (%I0, %J0, %o0+3));
4683     }
4684   *l = 8;
4685   return (TINY_ADIW (%I0, %J0, %o0)     CR_TAB
4686           "st %b0+,%A1"                 CR_TAB
4687           "st %b0+,%B1"                 CR_TAB
4688           "st %b0+,%C1"                 CR_TAB
4689           "st %b0,%D1"                  CR_TAB
4690           TINY_SBIW (%I0, %J0, %o0+3));
4691 }
4692 
4693 static const char*
out_movsi_mr_r(rtx_insn * insn,rtx op[],int * l)4694 out_movsi_mr_r (rtx_insn *insn, rtx op[], int *l)
4695 {
4696   rtx dest = op[0];
4697   rtx src = op[1];
4698   rtx base = XEXP (dest, 0);
4699   int reg_base = true_regnum (base);
4700   int reg_src = true_regnum (src);
4701   int tmp;
4702 
4703   if (!l)
4704     l = &tmp;
4705 
4706   if (CONSTANT_ADDRESS_P (base))
4707     {
4708       if (io_address_operand (base, SImode))
4709         {
4710           return *l=4,("out %i0, %A1"  CR_TAB
4711                        "out %i0+1,%B1" CR_TAB
4712                        "out %i0+2,%C1" CR_TAB
4713                        "out %i0+3,%D1");
4714         }
4715       else
4716         {
4717           *l = AVR_TINY ? 4 : 8;
4718           return ("sts %m0,%A1"   CR_TAB
4719                   "sts %m0+1,%B1" CR_TAB
4720                   "sts %m0+2,%C1" CR_TAB
4721                   "sts %m0+3,%D1");
4722         }
4723     }
4724 
4725   if (reg_base > 0)                 /* (r) */
4726     {
4727       if (AVR_TINY)
4728         return avr_out_movsi_mr_r_reg_no_disp_tiny (insn, op, l);
4729 
4730       if (reg_base == REG_X)                /* (R26) */
4731         {
4732           if (reg_src == REG_X)
4733             {
4734 	      /* "st X+,r26" is undefined */
4735               if (reg_unused_after (insn, base))
4736 		return *l=6, ("mov __tmp_reg__,r27" CR_TAB
4737 			      "st X,r26"            CR_TAB
4738 			      "adiw r26,1"          CR_TAB
4739 			      "st X+,__tmp_reg__"   CR_TAB
4740 			      "st X+,r28"           CR_TAB
4741 			      "st X,r29");
4742               else
4743                 return *l=7, ("mov __tmp_reg__,r27" CR_TAB
4744 			      "st X,r26"            CR_TAB
4745 			      "adiw r26,1"          CR_TAB
4746 			      "st X+,__tmp_reg__"   CR_TAB
4747 			      "st X+,r28"           CR_TAB
4748 			      "st X,r29"            CR_TAB
4749 			      "sbiw r26,3");
4750             }
4751           else if (reg_base == reg_src + 2)
4752             {
4753               if (reg_unused_after (insn, base))
4754                 return *l=7, ("mov __zero_reg__,%C1" CR_TAB
4755                               "mov __tmp_reg__,%D1"  CR_TAB
4756                               "st %0+,%A1"           CR_TAB
4757                               "st %0+,%B1"           CR_TAB
4758                               "st %0+,__zero_reg__"  CR_TAB
4759                               "st %0,__tmp_reg__"    CR_TAB
4760                               "clr __zero_reg__");
4761               else
4762                 return *l=8, ("mov __zero_reg__,%C1" CR_TAB
4763                               "mov __tmp_reg__,%D1"  CR_TAB
4764                               "st %0+,%A1"           CR_TAB
4765                               "st %0+,%B1"           CR_TAB
4766                               "st %0+,__zero_reg__"  CR_TAB
4767                               "st %0,__tmp_reg__"    CR_TAB
4768                               "clr __zero_reg__"     CR_TAB
4769                               "sbiw r26,3");
4770             }
4771           return *l=5, ("st %0+,%A1" CR_TAB
4772                         "st %0+,%B1" CR_TAB
4773                         "st %0+,%C1" CR_TAB
4774                         "st %0,%D1"  CR_TAB
4775                         "sbiw r26,3");
4776         }
4777       else
4778         return *l=4, ("st %0,%A1"    CR_TAB
4779 		      "std %0+1,%B1" CR_TAB
4780 		      "std %0+2,%C1" CR_TAB
4781 		      "std %0+3,%D1");
4782     }
4783   else if (GET_CODE (base) == PLUS) /* (R + i) */
4784     {
4785       int disp = INTVAL (XEXP (base, 1));
4786 
4787       if (AVR_TINY)
4788         return avr_out_movsi_mr_r_reg_disp_tiny (op, l);
4789 
4790       reg_base = REGNO (XEXP (base, 0));
4791       if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
4792 	{
4793 	  if (reg_base != REG_Y)
4794 	    fatal_insn ("incorrect insn:",insn);
4795 
4796 	  if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
4797 	    return *l = 6, ("adiw r28,%o0-60" CR_TAB
4798 			    "std Y+60,%A1"    CR_TAB
4799 			    "std Y+61,%B1"    CR_TAB
4800 			    "std Y+62,%C1"    CR_TAB
4801 			    "std Y+63,%D1"    CR_TAB
4802 			    "sbiw r28,%o0-60");
4803 
4804 	  return *l = 8, ("subi r28,lo8(-%o0)" CR_TAB
4805 			  "sbci r29,hi8(-%o0)" CR_TAB
4806 			  "st Y,%A1"           CR_TAB
4807 			  "std Y+1,%B1"        CR_TAB
4808 			  "std Y+2,%C1"        CR_TAB
4809 			  "std Y+3,%D1"        CR_TAB
4810 			  "subi r28,lo8(%o0)"  CR_TAB
4811 			  "sbci r29,hi8(%o0)");
4812 	}
4813       if (reg_base == REG_X)
4814 	{
4815 	  /* (X + d) = R */
4816 	  if (reg_src == REG_X)
4817 	    {
4818 	      *l = 9;
4819 	      return ("mov __tmp_reg__,r26"  CR_TAB
4820 		      "mov __zero_reg__,r27" CR_TAB
4821 		      "adiw r26,%o0"         CR_TAB
4822 		      "st X+,__tmp_reg__"    CR_TAB
4823 		      "st X+,__zero_reg__"   CR_TAB
4824 		      "st X+,r28"            CR_TAB
4825 		      "st X,r29"             CR_TAB
4826 		      "clr __zero_reg__"     CR_TAB
4827 		      "sbiw r26,%o0+3");
4828 	    }
4829 	  else if (reg_src == REG_X - 2)
4830 	    {
4831 	      *l = 9;
4832 	      return ("mov __tmp_reg__,r26"  CR_TAB
4833 		      "mov __zero_reg__,r27" CR_TAB
4834 		      "adiw r26,%o0"         CR_TAB
4835 		      "st X+,r24"            CR_TAB
4836 		      "st X+,r25"            CR_TAB
4837 		      "st X+,__tmp_reg__"    CR_TAB
4838 		      "st X,__zero_reg__"    CR_TAB
4839 		      "clr __zero_reg__"     CR_TAB
4840 		      "sbiw r26,%o0+3");
4841 	    }
4842 	  *l = 6;
4843 	  return ("adiw r26,%o0" CR_TAB
4844 		  "st X+,%A1"    CR_TAB
4845 		  "st X+,%B1"    CR_TAB
4846 		  "st X+,%C1"    CR_TAB
4847 		  "st X,%D1"     CR_TAB
4848 		  "sbiw r26,%o0+3");
4849 	}
4850       return *l=4, ("std %A0,%A1" CR_TAB
4851 		    "std %B0,%B1" CR_TAB
4852 		    "std %C0,%C1" CR_TAB
4853 		    "std %D0,%D1");
4854     }
4855   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4856     return *l=4, ("st %0,%D1" CR_TAB
4857 		  "st %0,%C1" CR_TAB
4858 		  "st %0,%B1" CR_TAB
4859 		  "st %0,%A1");
4860   else if (GET_CODE (base) == POST_INC) /* (R++) */
4861     return *l=4, ("st %0,%A1" CR_TAB
4862 		  "st %0,%B1" CR_TAB
4863 		  "st %0,%C1" CR_TAB
4864 		  "st %0,%D1");
4865   fatal_insn ("unknown move insn:",insn);
4866   return "";
4867 }
4868 
4869 const char *
output_movsisf(rtx_insn * insn,rtx operands[],int * l)4870 output_movsisf (rtx_insn *insn, rtx operands[], int *l)
4871 {
4872   int dummy;
4873   rtx dest = operands[0];
4874   rtx src = operands[1];
4875   int *real_l = l;
4876 
4877   if (avr_mem_flash_p (src)
4878       || avr_mem_flash_p (dest))
4879     {
4880       return avr_out_lpm (insn, operands, real_l);
4881     }
4882 
4883   if (!l)
4884     l = &dummy;
4885 
4886   gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 4);
4887 
4888   if (REG_P (dest))
4889     {
4890       if (REG_P (src)) /* mov r,r */
4891 	{
4892 	  if (true_regnum (dest) > true_regnum (src))
4893 	    {
4894 	      if (AVR_HAVE_MOVW)
4895 		{
4896 		  *l = 2;
4897 		  return ("movw %C0,%C1" CR_TAB
4898 			  "movw %A0,%A1");
4899 		}
4900 	      *l = 4;
4901 	      return ("mov %D0,%D1" CR_TAB
4902 		      "mov %C0,%C1" CR_TAB
4903 		      "mov %B0,%B1" CR_TAB
4904 		      "mov %A0,%A1");
4905 	    }
4906 	  else
4907 	    {
4908 	      if (AVR_HAVE_MOVW)
4909 		{
4910 		  *l = 2;
4911 		  return ("movw %A0,%A1" CR_TAB
4912 			  "movw %C0,%C1");
4913 		}
4914 	      *l = 4;
4915 	      return ("mov %A0,%A1" CR_TAB
4916 		      "mov %B0,%B1" CR_TAB
4917 		      "mov %C0,%C1" CR_TAB
4918 		      "mov %D0,%D1");
4919 	    }
4920 	}
4921       else if (CONSTANT_P (src))
4922 	{
4923           return output_reload_insisf (operands, NULL_RTX, real_l);
4924         }
4925       else if (MEM_P (src))
4926 	return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
4927     }
4928   else if (MEM_P (dest))
4929     {
4930       const char *templ;
4931 
4932       if (src == CONST0_RTX (GET_MODE (dest)))
4933         operands[1] = zero_reg_rtx;
4934 
4935       templ = out_movsi_mr_r (insn, operands, real_l);
4936 
4937       if (!real_l)
4938 	output_asm_insn (templ, operands);
4939 
4940       operands[1] = src;
4941       return "";
4942     }
4943   fatal_insn ("invalid insn:", insn);
4944   return "";
4945 }
4946 
4947 
4948 /* Handle loads of 24-bit types from memory to register.  */
4949 
4950 static const char*
avr_out_load_psi_reg_no_disp_tiny(rtx_insn * insn,rtx * op,int * plen)4951 avr_out_load_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
4952 {
4953   rtx dest = op[0];
4954   rtx src = op[1];
4955   rtx base = XEXP (src, 0);
4956   int reg_dest = true_regnum (dest);
4957   int reg_base = true_regnum (base);
4958 
4959   if (reg_base == reg_dest)
4960     {
4961       return avr_asm_len (TINY_ADIW (%E1, %F1, 2)   CR_TAB
4962                           "ld %C0,%1"               CR_TAB
4963                           "ld __tmp_reg__,-%1"      CR_TAB
4964                           TINY_SBIW (%E1, %F1, 1)   CR_TAB
4965                           "ld %A0,%1"               CR_TAB
4966                           "mov %B0,__tmp_reg__", op, plen, -8);
4967     }
4968   else
4969     {
4970       avr_asm_len ("ld %A0,%1+"  CR_TAB
4971 		   "ld %B0,%1+"  CR_TAB
4972 		   "ld %C0,%1", op, plen, -3);
4973 
4974       if (reg_dest != reg_base - 2
4975           && !reg_unused_after (insn, base))
4976         {
4977           avr_asm_len (TINY_SBIW (%E1, %F1, 2), op, plen, 2);
4978         }
4979       return "";
4980     }
4981 }
4982 
4983 static const char*
avr_out_load_psi_reg_disp_tiny(rtx_insn * insn,rtx * op,int * plen)4984 avr_out_load_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
4985 {
4986   rtx dest = op[0];
4987   rtx src = op[1];
4988   rtx base = XEXP (src, 0);
4989   int reg_dest = true_regnum (dest);
4990   int reg_base = true_regnum (base);
4991 
4992   reg_base = true_regnum (XEXP (base, 0));
4993   if (reg_base == reg_dest)
4994     {
4995       return avr_asm_len (TINY_ADIW (%I1, %J1, %o1+2) CR_TAB
4996                           "ld %C0,%b1"                CR_TAB
4997                           "ld __tmp_reg__,-%b1"       CR_TAB
4998                           TINY_SBIW (%I1, %J1, 1)     CR_TAB
4999                           "ld %A0,%b1"                CR_TAB
5000                           "mov %B0,__tmp_reg__", op, plen, -8);
5001     }
5002   else
5003     {
5004       avr_asm_len (TINY_ADIW (%I1, %J1, %o1)   CR_TAB
5005                    "ld %A0,%b1+"               CR_TAB
5006                    "ld %B0,%b1+"               CR_TAB
5007                    "ld %C0,%b1", op, plen, -5);
5008 
5009       if (reg_dest != reg_base - 2
5010           && !reg_unused_after (insn, XEXP (base, 0)))
5011         avr_asm_len (TINY_SBIW (%I1, %J1, %o1+2), op, plen, 2);
5012 
5013       return "";
5014     }
5015 }
5016 
5017 static const char*
avr_out_load_psi(rtx_insn * insn,rtx * op,int * plen)5018 avr_out_load_psi (rtx_insn *insn, rtx *op, int *plen)
5019 {
5020   rtx dest = op[0];
5021   rtx src = op[1];
5022   rtx base = XEXP (src, 0);
5023   int reg_dest = true_regnum (dest);
5024   int reg_base = true_regnum (base);
5025 
5026   if (reg_base > 0)
5027     {
5028       if (AVR_TINY)
5029         return avr_out_load_psi_reg_no_disp_tiny (insn, op, plen);
5030 
5031       if (reg_base == REG_X)        /* (R26) */
5032         {
5033           if (reg_dest == REG_X)
5034             /* "ld r26,-X" is undefined */
5035             return avr_asm_len ("adiw r26,2"        CR_TAB
5036                                 "ld r28,X"          CR_TAB
5037                                 "ld __tmp_reg__,-X" CR_TAB
5038                                 "sbiw r26,1"        CR_TAB
5039                                 "ld r26,X"          CR_TAB
5040                                 "mov r27,__tmp_reg__", op, plen, -6);
5041           else
5042             {
5043               avr_asm_len ("ld %A0,X+" CR_TAB
5044                            "ld %B0,X+" CR_TAB
5045                            "ld %C0,X", op, plen, -3);
5046 
5047               if (reg_dest != REG_X - 2
5048                   && !reg_unused_after (insn, base))
5049                 {
5050                   avr_asm_len ("sbiw r26,2", op, plen, 1);
5051                 }
5052 
5053               return "";
5054             }
5055         }
5056       else /* reg_base != REG_X */
5057         {
5058           if (reg_dest == reg_base)
5059             return avr_asm_len ("ldd %C0,%1+2"          CR_TAB
5060                                 "ldd __tmp_reg__,%1+1"  CR_TAB
5061                                 "ld  %A0,%1"            CR_TAB
5062                                 "mov %B0,__tmp_reg__", op, plen, -4);
5063           else
5064             return avr_asm_len ("ld  %A0,%1"    CR_TAB
5065                                 "ldd %B0,%1+1"  CR_TAB
5066                                 "ldd %C0,%1+2", op, plen, -3);
5067         }
5068     }
5069   else if (GET_CODE (base) == PLUS) /* (R + i) */
5070     {
5071       int disp = INTVAL (XEXP (base, 1));
5072 
5073       if (AVR_TINY)
5074         return avr_out_load_psi_reg_disp_tiny (insn, op, plen);
5075 
5076       if (disp > MAX_LD_OFFSET (GET_MODE (src)))
5077         {
5078           if (REGNO (XEXP (base, 0)) != REG_Y)
5079             fatal_insn ("incorrect insn:",insn);
5080 
5081           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
5082             return avr_asm_len ("adiw r28,%o1-61" CR_TAB
5083                                 "ldd %A0,Y+61"    CR_TAB
5084                                 "ldd %B0,Y+62"    CR_TAB
5085                                 "ldd %C0,Y+63"    CR_TAB
5086                                 "sbiw r28,%o1-61", op, plen, -5);
5087 
5088           return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
5089                               "sbci r29,hi8(-%o1)" CR_TAB
5090                               "ld  %A0,Y"          CR_TAB
5091                               "ldd %B0,Y+1"        CR_TAB
5092                               "ldd %C0,Y+2"        CR_TAB
5093                               "subi r28,lo8(%o1)"  CR_TAB
5094                               "sbci r29,hi8(%o1)", op, plen, -7);
5095         }
5096 
5097       reg_base = true_regnum (XEXP (base, 0));
5098       if (reg_base == REG_X)
5099         {
5100           /* R = (X + d) */
5101           if (reg_dest == REG_X)
5102             {
5103               /* "ld r26,-X" is undefined */
5104               return avr_asm_len ("adiw r26,%o1+2"     CR_TAB
5105                                   "ld  r28,X"          CR_TAB
5106                                   "ld  __tmp_reg__,-X" CR_TAB
5107                                   "sbiw r26,1"         CR_TAB
5108                                   "ld  r26,X"          CR_TAB
5109                                   "mov r27,__tmp_reg__", op, plen, -6);
5110             }
5111 
5112           avr_asm_len ("adiw r26,%o1" CR_TAB
5113                        "ld %A0,X+"    CR_TAB
5114                        "ld %B0,X+"    CR_TAB
5115                        "ld %C0,X", op, plen, -4);
5116 
5117           if (reg_dest != REG_W
5118               && !reg_unused_after (insn, XEXP (base, 0)))
5119             avr_asm_len ("sbiw r26,%o1+2", op, plen, 1);
5120 
5121           return "";
5122         }
5123 
5124       if (reg_dest == reg_base)
5125         return avr_asm_len ("ldd %C0,%C1" CR_TAB
5126                             "ldd __tmp_reg__,%B1"  CR_TAB
5127                             "ldd %A0,%A1" CR_TAB
5128                             "mov %B0,__tmp_reg__", op, plen, -4);
5129 
5130       return avr_asm_len ("ldd %A0,%A1" CR_TAB
5131                           "ldd %B0,%B1" CR_TAB
5132                           "ldd %C0,%C1", op, plen, -3);
5133     }
5134   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5135     return avr_asm_len ("ld %C0,%1" CR_TAB
5136                         "ld %B0,%1" CR_TAB
5137                         "ld %A0,%1", op, plen, -3);
5138   else if (GET_CODE (base) == POST_INC) /* (R++) */
5139     return avr_asm_len ("ld %A0,%1" CR_TAB
5140                         "ld %B0,%1" CR_TAB
5141                         "ld %C0,%1", op, plen, -3);
5142 
5143   else if (CONSTANT_ADDRESS_P (base))
5144     {
5145       int n_words = AVR_TINY ? 3 : 6;
5146       return avr_asm_len ("lds %A0,%m1" CR_TAB
5147                           "lds %B0,%m1+1" CR_TAB
5148                           "lds %C0,%m1+2", op, plen , -n_words);
5149     }
5150 
5151   fatal_insn ("unknown move insn:",insn);
5152   return "";
5153 }
5154 
5155 
5156 static const char*
avr_out_store_psi_reg_no_disp_tiny(rtx_insn * insn,rtx * op,int * plen)5157 avr_out_store_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
5158 {
5159   rtx dest = op[0];
5160   rtx src = op[1];
5161   rtx base = XEXP (dest, 0);
5162   int reg_base = true_regnum (base);
5163   int reg_src = true_regnum (src);
5164 
5165   if (reg_base == reg_src)
5166     {
5167       avr_asm_len ("st %0,%A1"              CR_TAB
5168                    "mov __tmp_reg__,%B1"    CR_TAB
5169                    TINY_ADIW (%E0, %F0, 1)  CR_TAB /* st X+, r27 is undefined */
5170                    "st %0+,__tmp_reg__"     CR_TAB
5171                    "st %0,%C1", op, plen, -6);
5172 
5173     }
5174   else if (reg_src == reg_base - 2)
5175     {
5176       avr_asm_len ("st %0,%A1"              CR_TAB
5177                    "mov __tmp_reg__,%C1"    CR_TAB
5178                    TINY_ADIW (%E0, %F0, 1)  CR_TAB
5179                    "st %0+,%B1"             CR_TAB
5180                    "st %0,__tmp_reg__", op, plen, 6);
5181     }
5182   else
5183     {
5184       avr_asm_len ("st %0+,%A1"  CR_TAB
5185                    "st %0+,%B1" CR_TAB
5186                    "st %0,%C1", op, plen, -3);
5187     }
5188 
5189   if (!reg_unused_after (insn, base))
5190     avr_asm_len (TINY_SBIW (%E0, %F0, 2), op, plen, 2);
5191 
5192   return "";
5193 }
5194 
5195 static const char*
avr_out_store_psi_reg_disp_tiny(rtx_insn * insn,rtx * op,int * plen)5196 avr_out_store_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
5197 {
5198   rtx dest = op[0];
5199   rtx src = op[1];
5200   rtx base = XEXP (dest, 0);
5201   int reg_base = REGNO (XEXP (base, 0));
5202   int reg_src = true_regnum (src);
5203 
5204   if (reg_src == reg_base)
5205     avr_asm_len ("mov __tmp_reg__,%A1"          CR_TAB
5206                  "mov __zero_reg__,%B1"         CR_TAB
5207                  TINY_ADIW (%I0, %J0, %o0)      CR_TAB
5208                  "st %b0+,__tmp_reg__"          CR_TAB
5209                  "st %b0+,__zero_reg__"         CR_TAB
5210                  "st %b0,%C1"                   CR_TAB
5211                  "clr __zero_reg__", op, plen, -8);
5212   else if (reg_src == reg_base - 2)
5213     avr_asm_len ("mov __tmp_reg__,%C1"          CR_TAB
5214                  TINY_ADIW (%I0, %J0, %o0)      CR_TAB
5215                  "st %b0+,%A1"                  CR_TAB
5216                  "st %b0+,%B1"                  CR_TAB
5217                  "st %b0,__tmp_reg__", op, plen, -6);
5218   else
5219     avr_asm_len (TINY_ADIW (%I0, %J0, %o0)      CR_TAB
5220                  "st %b0+,%A1"                  CR_TAB
5221                  "st %b0+,%B1"                  CR_TAB
5222                  "st %b0,%C1", op, plen, -5);
5223 
5224   if (!reg_unused_after (insn, XEXP (base, 0)))
5225     avr_asm_len (TINY_SBIW (%I0, %J0, %o0+2), op, plen, 2);
5226 
5227   return "";
5228 }
5229 
5230 /* Handle store of 24-bit type from register or zero to memory.  */
5231 
5232 static const char*
avr_out_store_psi(rtx_insn * insn,rtx * op,int * plen)5233 avr_out_store_psi (rtx_insn *insn, rtx *op, int *plen)
5234 {
5235   rtx dest = op[0];
5236   rtx src = op[1];
5237   rtx base = XEXP (dest, 0);
5238   int reg_base = true_regnum (base);
5239 
5240   if (CONSTANT_ADDRESS_P (base))
5241     {
5242       int n_words = AVR_TINY ? 3 : 6;
5243       return avr_asm_len ("sts %m0,%A1"   CR_TAB
5244                           "sts %m0+1,%B1" CR_TAB
5245                           "sts %m0+2,%C1", op, plen, -n_words);
5246     }
5247 
5248   if (reg_base > 0)                 /* (r) */
5249     {
5250       if (AVR_TINY)
5251         return avr_out_store_psi_reg_no_disp_tiny (insn, op, plen);
5252 
5253       if (reg_base == REG_X)        /* (R26) */
5254         {
5255           gcc_assert (!reg_overlap_mentioned_p (base, src));
5256 
5257           avr_asm_len ("st %0+,%A1"  CR_TAB
5258                        "st %0+,%B1" CR_TAB
5259                        "st %0,%C1", op, plen, -3);
5260 
5261           if (!reg_unused_after (insn, base))
5262             avr_asm_len ("sbiw r26,2", op, plen, 1);
5263 
5264           return "";
5265         }
5266       else
5267         return avr_asm_len ("st %0,%A1"    CR_TAB
5268                             "std %0+1,%B1" CR_TAB
5269                             "std %0+2,%C1", op, plen, -3);
5270     }
5271   else if (GET_CODE (base) == PLUS) /* (R + i) */
5272     {
5273       int disp = INTVAL (XEXP (base, 1));
5274 
5275       if (AVR_TINY)
5276         return avr_out_store_psi_reg_disp_tiny (insn, op, plen);
5277 
5278       reg_base = REGNO (XEXP (base, 0));
5279 
5280       if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5281         {
5282           if (reg_base != REG_Y)
5283             fatal_insn ("incorrect insn:",insn);
5284 
5285           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
5286             return avr_asm_len ("adiw r28,%o0-61" CR_TAB
5287                                 "std Y+61,%A1"    CR_TAB
5288                                 "std Y+62,%B1"    CR_TAB
5289                                 "std Y+63,%C1"    CR_TAB
5290                                 "sbiw r28,%o0-61", op, plen, -5);
5291 
5292           return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5293                               "sbci r29,hi8(-%o0)" CR_TAB
5294                               "st Y,%A1"           CR_TAB
5295                               "std Y+1,%B1"        CR_TAB
5296                               "std Y+2,%C1"        CR_TAB
5297                               "subi r28,lo8(%o0)"  CR_TAB
5298                               "sbci r29,hi8(%o0)", op, plen, -7);
5299         }
5300       if (reg_base == REG_X)
5301         {
5302           /* (X + d) = R */
5303           gcc_assert (!reg_overlap_mentioned_p (XEXP (base, 0), src));
5304 
5305           avr_asm_len ("adiw r26,%o0" CR_TAB
5306                        "st X+,%A1"    CR_TAB
5307                        "st X+,%B1"    CR_TAB
5308                        "st X,%C1", op, plen, -4);
5309 
5310           if (!reg_unused_after (insn, XEXP (base, 0)))
5311             avr_asm_len ("sbiw r26,%o0+2", op, plen, 1);
5312 
5313           return "";
5314         }
5315 
5316       return avr_asm_len ("std %A0,%A1" CR_TAB
5317                           "std %B0,%B1" CR_TAB
5318                           "std %C0,%C1", op, plen, -3);
5319     }
5320   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5321     return avr_asm_len ("st %0,%C1" CR_TAB
5322                         "st %0,%B1" CR_TAB
5323                         "st %0,%A1", op, plen, -3);
5324   else if (GET_CODE (base) == POST_INC) /* (R++) */
5325     return avr_asm_len ("st %0,%A1" CR_TAB
5326                         "st %0,%B1" CR_TAB
5327                         "st %0,%C1", op, plen, -3);
5328 
5329   fatal_insn ("unknown move insn:",insn);
5330   return "";
5331 }
5332 
5333 
5334 /* Move around 24-bit stuff.  */
5335 
5336 const char *
avr_out_movpsi(rtx_insn * insn,rtx * op,int * plen)5337 avr_out_movpsi (rtx_insn *insn, rtx *op, int *plen)
5338 {
5339   rtx dest = op[0];
5340   rtx src = op[1];
5341 
5342   if (avr_mem_flash_p (src)
5343       || avr_mem_flash_p (dest))
5344     {
5345       return avr_out_lpm (insn, op, plen);
5346     }
5347 
5348   if (register_operand (dest, VOIDmode))
5349     {
5350       if (register_operand (src, VOIDmode)) /* mov r,r */
5351         {
5352           if (true_regnum (dest) > true_regnum (src))
5353             {
5354               avr_asm_len ("mov %C0,%C1", op, plen, -1);
5355 
5356               if (AVR_HAVE_MOVW)
5357                 return avr_asm_len ("movw %A0,%A1", op, plen, 1);
5358               else
5359                 return avr_asm_len ("mov %B0,%B1"  CR_TAB
5360                                     "mov %A0,%A1", op, plen, 2);
5361             }
5362           else
5363             {
5364               if (AVR_HAVE_MOVW)
5365                 avr_asm_len ("movw %A0,%A1", op, plen, -1);
5366               else
5367                 avr_asm_len ("mov %A0,%A1"  CR_TAB
5368                              "mov %B0,%B1", op, plen, -2);
5369 
5370               return avr_asm_len ("mov %C0,%C1", op, plen, 1);
5371             }
5372         }
5373       else if (CONSTANT_P (src))
5374         {
5375           return avr_out_reload_inpsi (op, NULL_RTX, plen);
5376         }
5377       else if (MEM_P (src))
5378         return avr_out_load_psi (insn, op, plen); /* mov r,m */
5379     }
5380   else if (MEM_P (dest))
5381     {
5382       rtx xop[2];
5383 
5384       xop[0] = dest;
5385       xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
5386 
5387       return avr_out_store_psi (insn, xop, plen);
5388     }
5389 
5390   fatal_insn ("invalid insn:", insn);
5391   return "";
5392 }
5393 
5394 static const char*
avr_out_movqi_mr_r_reg_disp_tiny(rtx_insn * insn,rtx op[],int * plen)5395 avr_out_movqi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5396 {
5397   rtx dest = op[0];
5398   rtx src = op[1];
5399   rtx x = XEXP (dest, 0);
5400 
5401   if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
5402     {
5403       avr_asm_len ("mov __tmp_reg__,%1"      CR_TAB
5404                    TINY_ADIW (%I0, %J0, %o0) CR_TAB
5405                    "st %b0,__tmp_reg__", op, plen, -4);
5406     }
5407   else
5408     {
5409       avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
5410                    "st %b0,%1", op, plen, -3);
5411     }
5412 
5413   if (!reg_unused_after (insn, XEXP (x, 0)))
5414     avr_asm_len (TINY_SBIW (%I0, %J0, %o0), op, plen, 2);
5415 
5416   return "";
5417 }
5418 
5419 static const char*
out_movqi_mr_r(rtx_insn * insn,rtx op[],int * plen)5420 out_movqi_mr_r (rtx_insn *insn, rtx op[], int *plen)
5421 {
5422   rtx dest = op[0];
5423   rtx src = op[1];
5424   rtx x = XEXP (dest, 0);
5425 
5426   if (CONSTANT_ADDRESS_P (x))
5427     {
5428       int n_words = AVR_TINY ? 1 : 2;
5429       return io_address_operand (x, QImode)
5430         ? avr_asm_len ("out %i0,%1", op, plen, -1)
5431         : avr_asm_len ("sts %m0,%1", op, plen, -n_words);
5432     }
5433   else if (GET_CODE (x) == PLUS
5434            && REG_P (XEXP (x, 0))
5435            && CONST_INT_P (XEXP (x, 1)))
5436     {
5437       /* memory access by reg+disp */
5438 
5439       int disp = INTVAL (XEXP (x, 1));
5440 
5441       if (AVR_TINY)
5442         return avr_out_movqi_mr_r_reg_disp_tiny (insn, op, plen);
5443 
5444       if (disp - GET_MODE_SIZE (GET_MODE (dest)) >= 63)
5445         {
5446           if (REGNO (XEXP (x, 0)) != REG_Y)
5447             fatal_insn ("incorrect insn:",insn);
5448 
5449           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
5450             return avr_asm_len ("adiw r28,%o0-63" CR_TAB
5451                                 "std Y+63,%1"     CR_TAB
5452                                 "sbiw r28,%o0-63", op, plen, -3);
5453 
5454           return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5455                               "sbci r29,hi8(-%o0)" CR_TAB
5456                               "st Y,%1"            CR_TAB
5457                               "subi r28,lo8(%o0)"  CR_TAB
5458                               "sbci r29,hi8(%o0)", op, plen, -5);
5459         }
5460       else if (REGNO (XEXP (x, 0)) == REG_X)
5461         {
5462           if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
5463             {
5464               avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
5465                            "adiw r26,%o0"       CR_TAB
5466                            "st X,__tmp_reg__", op, plen, -3);
5467             }
5468           else
5469             {
5470               avr_asm_len ("adiw r26,%o0" CR_TAB
5471                            "st X,%1", op, plen, -2);
5472             }
5473 
5474           if (!reg_unused_after (insn, XEXP (x, 0)))
5475             avr_asm_len ("sbiw r26,%o0", op, plen, 1);
5476 
5477           return "";
5478         }
5479 
5480       return avr_asm_len ("std %0,%1", op, plen, -1);
5481     }
5482 
5483   return avr_asm_len ("st %0,%1", op, plen, -1);
5484 }
5485 
5486 
5487 /* Helper for the next function for XMEGA.  It does the same
5488    but with low byte first.  */
5489 
5490 static const char*
avr_out_movhi_mr_r_xmega(rtx_insn * insn,rtx op[],int * plen)5491 avr_out_movhi_mr_r_xmega (rtx_insn *insn, rtx op[], int *plen)
5492 {
5493   rtx dest = op[0];
5494   rtx src = op[1];
5495   rtx base = XEXP (dest, 0);
5496   int reg_base = true_regnum (base);
5497   int reg_src = true_regnum (src);
5498 
5499   /* "volatile" forces writing low byte first, even if less efficient,
5500      for correct operation with 16-bit I/O registers like SP.  */
5501   int mem_volatile_p = MEM_VOLATILE_P (dest);
5502 
5503   if (CONSTANT_ADDRESS_P (base))
5504     {
5505       return io_address_operand (base, HImode)
5506         ? avr_asm_len ("out %i0,%A1" CR_TAB
5507                        "out %i0+1,%B1", op, plen, -2)
5508 
5509         : avr_asm_len ("sts %m0,%A1" CR_TAB
5510                        "sts %m0+1,%B1", op, plen, -4);
5511     }
5512 
5513   if (reg_base > 0)
5514     {
5515       if (reg_base != REG_X)
5516         return avr_asm_len ("st %0,%A1" CR_TAB
5517                             "std %0+1,%B1", op, plen, -2);
5518 
5519       if (reg_src == REG_X)
5520         /* "st X+,r26" and "st -X,r26" are undefined.  */
5521         avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5522                      "st X,r26"            CR_TAB
5523                      "adiw r26,1"          CR_TAB
5524                      "st X,__tmp_reg__", op, plen, -4);
5525       else
5526         avr_asm_len ("st X+,%A1" CR_TAB
5527                      "st X,%B1", op, plen, -2);
5528 
5529       return reg_unused_after (insn, base)
5530         ? ""
5531         : avr_asm_len ("sbiw r26,1", op, plen, 1);
5532     }
5533   else if (GET_CODE (base) == PLUS)
5534     {
5535       int disp = INTVAL (XEXP (base, 1));
5536       reg_base = REGNO (XEXP (base, 0));
5537       if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5538         {
5539           if (reg_base != REG_Y)
5540             fatal_insn ("incorrect insn:",insn);
5541 
5542           return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
5543             ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
5544                            "std Y+62,%A1"    CR_TAB
5545                            "std Y+63,%B1"    CR_TAB
5546                            "sbiw r28,%o0-62", op, plen, -4)
5547 
5548             : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5549                            "sbci r29,hi8(-%o0)" CR_TAB
5550                            "st Y,%A1"           CR_TAB
5551                            "std Y+1,%B1"        CR_TAB
5552                            "subi r28,lo8(%o0)"  CR_TAB
5553                            "sbci r29,hi8(%o0)", op, plen, -6);
5554         }
5555 
5556       if (reg_base != REG_X)
5557         return avr_asm_len ("std %A0,%A1" CR_TAB
5558                             "std %B0,%B1", op, plen, -2);
5559       /* (X + d) = R */
5560       return reg_src == REG_X
5561         ? avr_asm_len ("mov __tmp_reg__,r26"  CR_TAB
5562                        "mov __zero_reg__,r27" CR_TAB
5563                        "adiw r26,%o0"         CR_TAB
5564                        "st X+,__tmp_reg__"    CR_TAB
5565                        "st X,__zero_reg__"    CR_TAB
5566                        "clr __zero_reg__"     CR_TAB
5567                        "sbiw r26,%o0+1", op, plen, -7)
5568 
5569         : avr_asm_len ("adiw r26,%o0" CR_TAB
5570                        "st X+,%A1"    CR_TAB
5571                        "st X,%B1"     CR_TAB
5572                        "sbiw r26,%o0+1", op, plen, -4);
5573     }
5574   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5575     {
5576       if (!mem_volatile_p)
5577         return avr_asm_len ("st %0,%B1" CR_TAB
5578                             "st %0,%A1", op, plen, -2);
5579 
5580       return REGNO (XEXP (base, 0)) == REG_X
5581         ? avr_asm_len ("sbiw r26,2"  CR_TAB
5582                        "st X+,%A1"   CR_TAB
5583                        "st X,%B1"    CR_TAB
5584                        "sbiw r26,1", op, plen, -4)
5585 
5586         : avr_asm_len ("sbiw %r0,2"  CR_TAB
5587                        "st %p0,%A1"  CR_TAB
5588                        "std %p0+1,%B1", op, plen, -3);
5589     }
5590   else if (GET_CODE (base) == POST_INC) /* (R++) */
5591     {
5592       return avr_asm_len ("st %0,%A1"  CR_TAB
5593                           "st %0,%B1", op, plen, -2);
5594 
5595     }
5596   fatal_insn ("unknown move insn:",insn);
5597   return "";
5598 }
5599 
5600 static const char*
avr_out_movhi_mr_r_reg_no_disp_tiny(rtx_insn * insn,rtx op[],int * plen)5601 avr_out_movhi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5602 {
5603   rtx dest = op[0];
5604   rtx src = op[1];
5605   rtx base = XEXP (dest, 0);
5606   int reg_base = true_regnum (base);
5607   int reg_src = true_regnum (src);
5608   int mem_volatile_p = MEM_VOLATILE_P (dest);
5609 
5610   if (reg_base == reg_src)
5611     {
5612       return !mem_volatile_p && reg_unused_after (insn, src)
5613         ? avr_asm_len ("mov __tmp_reg__,%B1"   CR_TAB
5614                        "st %0,%A1"             CR_TAB
5615                        TINY_ADIW (%E0, %F0, 1) CR_TAB
5616                        "st %0,__tmp_reg__", op, plen, -5)
5617         : avr_asm_len ("mov __tmp_reg__,%B1"   CR_TAB
5618                        TINY_ADIW (%E0, %F0, 1) CR_TAB
5619                        "st %0,__tmp_reg__"     CR_TAB
5620                        TINY_SBIW (%E0, %F0, 1) CR_TAB
5621                        "st %0, %A1", op, plen, -7);
5622     }
5623 
5624   return !mem_volatile_p && reg_unused_after (insn, base)
5625     ? avr_asm_len ("st %0+,%A1" CR_TAB
5626                    "st %0,%B1", op, plen, -2)
5627     : avr_asm_len (TINY_ADIW (%E0, %F0, 1) CR_TAB
5628                    "st %0,%B1"             CR_TAB
5629                    "st -%0,%A1", op, plen, -4);
5630 }
5631 
5632 static const char*
avr_out_movhi_mr_r_reg_disp_tiny(rtx_insn * insn,rtx op[],int * plen)5633 avr_out_movhi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5634 {
5635   rtx dest = op[0];
5636   rtx src = op[1];
5637   rtx base = XEXP (dest, 0);
5638   int reg_base = REGNO (XEXP (base, 0));
5639   int reg_src = true_regnum (src);
5640 
5641   if (reg_src == reg_base)
5642     avr_asm_len ("mov __tmp_reg__,%A1"          CR_TAB
5643                  "mov __zero_reg__,%B1"         CR_TAB
5644                  TINY_ADIW (%I0, %J0, %o0+1)    CR_TAB
5645                  "st %b0,__zero_reg__"          CR_TAB
5646                  "st -%b0,__tmp_reg__"          CR_TAB
5647                  "clr __zero_reg__", op, plen, -7);
5648   else
5649     avr_asm_len (TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
5650                  "st %b0,%B1"                CR_TAB
5651                  "st -%b0,%A1", op, plen, -4);
5652 
5653   if (!reg_unused_after (insn, XEXP (base, 0)))
5654     avr_asm_len (TINY_SBIW (%I0, %J0, %o0), op, plen, 2);
5655 
5656   return "";
5657 }
5658 
5659 static const char*
avr_out_movhi_mr_r_post_inc_tiny(rtx op[],int * plen)5660 avr_out_movhi_mr_r_post_inc_tiny (rtx op[], int *plen)
5661 {
5662   return avr_asm_len (TINY_ADIW (%I0, %J0, 1)  CR_TAB
5663                       "st %p0,%B1"    CR_TAB
5664                       "st -%p0,%A1"   CR_TAB
5665                       TINY_ADIW (%I0, %J0, 2), op, plen, -6);
5666 }
5667 
5668 static const char*
out_movhi_mr_r(rtx_insn * insn,rtx op[],int * plen)5669 out_movhi_mr_r (rtx_insn *insn, rtx op[], int *plen)
5670 {
5671   rtx dest = op[0];
5672   rtx src = op[1];
5673   rtx base = XEXP (dest, 0);
5674   int reg_base = true_regnum (base);
5675   int reg_src = true_regnum (src);
5676   int mem_volatile_p;
5677 
5678   /* "volatile" forces writing high-byte first (no-xmega) resp.
5679      low-byte first (xmega) even if less efficient, for correct
5680      operation with 16-bit I/O registers like.  */
5681 
5682   if (AVR_XMEGA)
5683     return avr_out_movhi_mr_r_xmega (insn, op, plen);
5684 
5685   mem_volatile_p = MEM_VOLATILE_P (dest);
5686 
5687   if (CONSTANT_ADDRESS_P (base))
5688     {
5689       int n_words = AVR_TINY ? 2 : 4;
5690       return io_address_operand (base, HImode)
5691         ? avr_asm_len ("out %i0+1,%B1" CR_TAB
5692                        "out %i0,%A1", op, plen, -2)
5693 
5694         : avr_asm_len ("sts %m0+1,%B1" CR_TAB
5695                        "sts %m0,%A1", op, plen, -n_words);
5696     }
5697 
5698   if (reg_base > 0)
5699     {
5700       if (AVR_TINY)
5701         return avr_out_movhi_mr_r_reg_no_disp_tiny (insn, op, plen);
5702 
5703       if (reg_base != REG_X)
5704         return avr_asm_len ("std %0+1,%B1" CR_TAB
5705                             "st %0,%A1", op, plen, -2);
5706 
5707       if (reg_src == REG_X)
5708         /* "st X+,r26" and "st -X,r26" are undefined.  */
5709         return !mem_volatile_p && reg_unused_after (insn, src)
5710           ? avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5711                          "st X,r26"            CR_TAB
5712                          "adiw r26,1"          CR_TAB
5713                          "st X,__tmp_reg__", op, plen, -4)
5714 
5715           : avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5716                          "adiw r26,1"          CR_TAB
5717                          "st X,__tmp_reg__"    CR_TAB
5718                          "sbiw r26,1"          CR_TAB
5719                          "st X,r26", op, plen, -5);
5720 
5721       return !mem_volatile_p && reg_unused_after (insn, base)
5722         ? avr_asm_len ("st X+,%A1" CR_TAB
5723                        "st X,%B1", op, plen, -2)
5724         : avr_asm_len ("adiw r26,1" CR_TAB
5725                        "st X,%B1"   CR_TAB
5726                        "st -X,%A1", op, plen, -3);
5727     }
5728   else if (GET_CODE (base) == PLUS)
5729     {
5730       int disp = INTVAL (XEXP (base, 1));
5731 
5732       if (AVR_TINY)
5733         return avr_out_movhi_mr_r_reg_disp_tiny (insn, op, plen);
5734 
5735       reg_base = REGNO (XEXP (base, 0));
5736       if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5737         {
5738           if (reg_base != REG_Y)
5739             fatal_insn ("incorrect insn:",insn);
5740 
5741           return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
5742             ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
5743                            "std Y+63,%B1"    CR_TAB
5744                            "std Y+62,%A1"    CR_TAB
5745                            "sbiw r28,%o0-62", op, plen, -4)
5746 
5747             : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5748                            "sbci r29,hi8(-%o0)" CR_TAB
5749                            "std Y+1,%B1"        CR_TAB
5750                            "st Y,%A1"           CR_TAB
5751                            "subi r28,lo8(%o0)"  CR_TAB
5752                            "sbci r29,hi8(%o0)", op, plen, -6);
5753         }
5754 
5755       if (reg_base != REG_X)
5756         return avr_asm_len ("std %B0,%B1" CR_TAB
5757                             "std %A0,%A1", op, plen, -2);
5758       /* (X + d) = R */
5759       return reg_src == REG_X
5760         ? avr_asm_len ("mov __tmp_reg__,r26"  CR_TAB
5761                        "mov __zero_reg__,r27" CR_TAB
5762                        "adiw r26,%o0+1"       CR_TAB
5763                        "st X,__zero_reg__"    CR_TAB
5764                        "st -X,__tmp_reg__"    CR_TAB
5765                        "clr __zero_reg__"     CR_TAB
5766                        "sbiw r26,%o0", op, plen, -7)
5767 
5768         : avr_asm_len ("adiw r26,%o0+1" CR_TAB
5769                        "st X,%B1"       CR_TAB
5770                        "st -X,%A1"      CR_TAB
5771                        "sbiw r26,%o0", op, plen, -4);
5772     }
5773   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5774     {
5775       return avr_asm_len ("st %0,%B1" CR_TAB
5776                           "st %0,%A1", op, plen, -2);
5777     }
5778   else if (GET_CODE (base) == POST_INC) /* (R++) */
5779     {
5780       if (!mem_volatile_p)
5781         return avr_asm_len ("st %0,%A1"  CR_TAB
5782                             "st %0,%B1", op, plen, -2);
5783 
5784       if (AVR_TINY)
5785         return avr_out_movhi_mr_r_post_inc_tiny (op, plen);
5786 
5787       return REGNO (XEXP (base, 0)) == REG_X
5788         ? avr_asm_len ("adiw r26,1"  CR_TAB
5789                        "st X,%B1"    CR_TAB
5790                        "st -X,%A1"   CR_TAB
5791                        "adiw r26,2", op, plen, -4)
5792 
5793         : avr_asm_len ("std %p0+1,%B1" CR_TAB
5794                        "st %p0,%A1"    CR_TAB
5795                        "adiw %r0,2", op, plen, -3);
5796     }
5797   fatal_insn ("unknown move insn:",insn);
5798   return "";
5799 }
5800 
5801 /* Return 1 if frame pointer for current function required.  */
5802 
5803 static bool
avr_frame_pointer_required_p(void)5804 avr_frame_pointer_required_p (void)
5805 {
5806   return (cfun->calls_alloca
5807           || cfun->calls_setjmp
5808           || cfun->has_nonlocal_label
5809           || crtl->args.info.nregs == 0
5810           || get_frame_size () > 0);
5811 }
5812 
5813 /* Returns the condition of compare insn INSN, or UNKNOWN.  */
5814 
5815 static RTX_CODE
compare_condition(rtx_insn * insn)5816 compare_condition (rtx_insn *insn)
5817 {
5818   rtx_insn *next = next_real_insn (insn);
5819 
5820   if (next && JUMP_P (next))
5821     {
5822       rtx pat = PATTERN (next);
5823       rtx src = SET_SRC (pat);
5824 
5825       if (IF_THEN_ELSE == GET_CODE (src))
5826         return GET_CODE (XEXP (src, 0));
5827     }
5828 
5829   return UNKNOWN;
5830 }
5831 
5832 
5833 /* Returns true iff INSN is a tst insn that only tests the sign.  */
5834 
5835 static bool
compare_sign_p(rtx_insn * insn)5836 compare_sign_p (rtx_insn *insn)
5837 {
5838   RTX_CODE cond = compare_condition (insn);
5839   return (cond == GE || cond == LT);
5840 }
5841 
5842 
5843 /* Returns true iff the next insn is a JUMP_INSN with a condition
5844    that needs to be swapped (GT, GTU, LE, LEU).  */
5845 
5846 static bool
compare_diff_p(rtx_insn * insn)5847 compare_diff_p (rtx_insn *insn)
5848 {
5849   RTX_CODE cond = compare_condition (insn);
5850   return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
5851 }
5852 
5853 /* Returns true iff INSN is a compare insn with the EQ or NE condition.  */
5854 
5855 static bool
compare_eq_p(rtx_insn * insn)5856 compare_eq_p (rtx_insn *insn)
5857 {
5858   RTX_CODE cond = compare_condition (insn);
5859   return (cond == EQ || cond == NE);
5860 }
5861 
5862 
5863 /* Output compare instruction
5864 
5865       compare (XOP[0], XOP[1])
5866 
5867    for a register XOP[0] and a compile-time constant XOP[1].  Return "".
5868    XOP[2] is an 8-bit scratch register as needed.
5869 
5870    PLEN == NULL:  Output instructions.
5871    PLEN != NULL:  Set *PLEN to the length (in words) of the sequence.
5872                   Don't output anything.  */
5873 
5874 const char*
avr_out_compare(rtx_insn * insn,rtx * xop,int * plen)5875 avr_out_compare (rtx_insn *insn, rtx *xop, int *plen)
5876 {
5877   /* Register to compare and value to compare against. */
5878   rtx xreg = xop[0];
5879   rtx xval = xop[1];
5880 
5881   /* MODE of the comparison.  */
5882   machine_mode mode;
5883 
5884   /* Number of bytes to operate on.  */
5885   int n_bytes = GET_MODE_SIZE (GET_MODE (xreg));
5886 
5887   /* Value (0..0xff) held in clobber register xop[2] or -1 if unknown.  */
5888   int clobber_val = -1;
5889 
5890   /* Map fixed mode operands to integer operands with the same binary
5891      representation.  They are easier to handle in the remainder.  */
5892 
5893   if (CONST_FIXED_P (xval))
5894     {
5895       xreg = avr_to_int_mode (xop[0]);
5896       xval = avr_to_int_mode (xop[1]);
5897     }
5898 
5899   mode = GET_MODE (xreg);
5900 
5901   gcc_assert (REG_P (xreg));
5902   gcc_assert ((CONST_INT_P (xval) && n_bytes <= 4)
5903               || (const_double_operand (xval, VOIDmode) && n_bytes == 8));
5904 
5905   if (plen)
5906     *plen = 0;
5907 
5908   /* Comparisons == +/-1 and != +/-1 can be done similar to camparing
5909      against 0 by ORing the bytes.  This is one instruction shorter.
5910      Notice that 64-bit comparisons are always against reg:ALL8 18 (ACC_A)
5911      and therefore don't use this.  */
5912 
5913   if (!test_hard_reg_class (LD_REGS, xreg)
5914       && compare_eq_p (insn)
5915       && reg_unused_after (insn, xreg))
5916     {
5917       if (xval == const1_rtx)
5918         {
5919           avr_asm_len ("dec %A0" CR_TAB
5920                        "or %A0,%B0", xop, plen, 2);
5921 
5922           if (n_bytes >= 3)
5923             avr_asm_len ("or %A0,%C0", xop, plen, 1);
5924 
5925           if (n_bytes >= 4)
5926             avr_asm_len ("or %A0,%D0", xop, plen, 1);
5927 
5928           return "";
5929         }
5930       else if (xval == constm1_rtx)
5931         {
5932           if (n_bytes >= 4)
5933             avr_asm_len ("and %A0,%D0", xop, plen, 1);
5934 
5935           if (n_bytes >= 3)
5936             avr_asm_len ("and %A0,%C0", xop, plen, 1);
5937 
5938           return avr_asm_len ("and %A0,%B0" CR_TAB
5939                               "com %A0", xop, plen, 2);
5940         }
5941     }
5942 
5943   /* Comparisons == -1 and != -1 of a d-register that's used after the
5944      comparison.  (If it's unused after we use CPI / SBCI or ADIW sequence
5945      from below.)  Instead of  CPI Rlo,-1 / LDI Rx,-1 / CPC Rhi,Rx  we can
5946      use  CPI Rlo,-1 / CPC Rhi,Rlo  which is 1 instruction shorter:
5947      If CPI is true then Rlo contains -1 and we can use Rlo instead of Rx
5948      when CPC'ing the high part.  If CPI is false then CPC cannot render
5949      the result to true.  This also works for the more generic case where
5950      the constant is of the form 0xabab.  */
5951 
5952   if (n_bytes == 2
5953       && xval != const0_rtx
5954       && test_hard_reg_class (LD_REGS, xreg)
5955       && compare_eq_p (insn)
5956       && !reg_unused_after (insn, xreg))
5957     {
5958       rtx xlo8 = simplify_gen_subreg (QImode, xval, mode, 0);
5959       rtx xhi8 = simplify_gen_subreg (QImode, xval, mode, 1);
5960 
5961       if (INTVAL (xlo8) == INTVAL (xhi8))
5962         {
5963           xop[0] = xreg;
5964           xop[1] = xlo8;
5965 
5966           return avr_asm_len ("cpi %A0,%1"  CR_TAB
5967                               "cpc %B0,%A0", xop, plen, 2);
5968         }
5969     }
5970 
5971   for (int i = 0; i < n_bytes; i++)
5972     {
5973       /* We compare byte-wise.  */
5974       rtx reg8 = simplify_gen_subreg (QImode, xreg, mode, i);
5975       rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
5976 
5977       /* 8-bit value to compare with this byte.  */
5978       unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
5979 
5980       /* Registers R16..R31 can operate with immediate.  */
5981       bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
5982 
5983       xop[0] = reg8;
5984       xop[1] = gen_int_mode (val8, QImode);
5985 
5986       /* Word registers >= R24 can use SBIW/ADIW with 0..63.  */
5987 
5988       if (i == 0
5989           && test_hard_reg_class (ADDW_REGS, reg8))
5990         {
5991           int val16 = trunc_int_for_mode (INTVAL (xval), HImode);
5992 
5993           if (IN_RANGE (val16, 0, 63)
5994               && (val8 == 0
5995                   || reg_unused_after (insn, xreg)))
5996             {
5997               if (AVR_TINY)
5998                 avr_asm_len (TINY_SBIW (%A0, %B0, %1), xop, plen, 2);
5999               else
6000                 avr_asm_len ("sbiw %0,%1", xop, plen, 1);
6001 
6002               i++;
6003               continue;
6004             }
6005 
6006           if (n_bytes == 2
6007               && IN_RANGE (val16, -63, -1)
6008               && compare_eq_p (insn)
6009               && reg_unused_after (insn, xreg))
6010             {
6011               return AVR_TINY
6012                 ? avr_asm_len (TINY_ADIW (%A0, %B0, %n1), xop, plen, 2)
6013                 : avr_asm_len ("adiw %0,%n1", xop, plen, 1);
6014             }
6015         }
6016 
6017       /* Comparing against 0 is easy.  */
6018 
6019       if (val8 == 0)
6020         {
6021           avr_asm_len (i == 0
6022                        ? "cp %0,__zero_reg__"
6023                        : "cpc %0,__zero_reg__", xop, plen, 1);
6024           continue;
6025         }
6026 
6027       /* Upper registers can compare and subtract-with-carry immediates.
6028          Notice that compare instructions do the same as respective subtract
6029          instruction; the only difference is that comparisons don't write
6030          the result back to the target register.  */
6031 
6032       if (ld_reg_p)
6033         {
6034           if (i == 0)
6035             {
6036               avr_asm_len ("cpi %0,%1", xop, plen, 1);
6037               continue;
6038             }
6039           else if (reg_unused_after (insn, xreg))
6040             {
6041               avr_asm_len ("sbci %0,%1", xop, plen, 1);
6042               continue;
6043             }
6044         }
6045 
6046       /* Must load the value into the scratch register.  */
6047 
6048       gcc_assert (REG_P (xop[2]));
6049 
6050       if (clobber_val != (int) val8)
6051         avr_asm_len ("ldi %2,%1", xop, plen, 1);
6052       clobber_val = (int) val8;
6053 
6054       avr_asm_len (i == 0
6055                    ? "cp %0,%2"
6056                    : "cpc %0,%2", xop, plen, 1);
6057     }
6058 
6059   return "";
6060 }
6061 
6062 
6063 /* Prepare operands of compare_const_di2 to be used with avr_out_compare.  */
6064 
6065 const char*
avr_out_compare64(rtx_insn * insn,rtx * op,int * plen)6066 avr_out_compare64 (rtx_insn *insn, rtx *op, int *plen)
6067 {
6068   rtx xop[3];
6069 
6070   xop[0] = gen_rtx_REG (DImode, 18);
6071   xop[1] = op[0];
6072   xop[2] = op[1];
6073 
6074   return avr_out_compare (insn, xop, plen);
6075 }
6076 
6077 /* Output test instruction for HImode.  */
6078 
6079 const char*
avr_out_tsthi(rtx_insn * insn,rtx * op,int * plen)6080 avr_out_tsthi (rtx_insn *insn, rtx *op, int *plen)
6081 {
6082   if (compare_sign_p (insn))
6083     {
6084       avr_asm_len ("tst %B0", op, plen, -1);
6085     }
6086   else if (reg_unused_after (insn, op[0])
6087            && compare_eq_p (insn))
6088     {
6089       /* Faster than sbiw if we can clobber the operand.  */
6090       avr_asm_len ("or %A0,%B0", op, plen, -1);
6091     }
6092   else
6093     {
6094       avr_out_compare (insn, op, plen);
6095     }
6096 
6097   return "";
6098 }
6099 
6100 
6101 /* Output test instruction for PSImode.  */
6102 
6103 const char*
avr_out_tstpsi(rtx_insn * insn,rtx * op,int * plen)6104 avr_out_tstpsi (rtx_insn *insn, rtx *op, int *plen)
6105 {
6106   if (compare_sign_p (insn))
6107     {
6108       avr_asm_len ("tst %C0", op, plen, -1);
6109     }
6110   else if (reg_unused_after (insn, op[0])
6111            && compare_eq_p (insn))
6112     {
6113       /* Faster than sbiw if we can clobber the operand.  */
6114       avr_asm_len ("or %A0,%B0" CR_TAB
6115                    "or %A0,%C0", op, plen, -2);
6116     }
6117   else
6118     {
6119       avr_out_compare (insn, op, plen);
6120     }
6121 
6122   return "";
6123 }
6124 
6125 
6126 /* Output test instruction for SImode.  */
6127 
6128 const char*
avr_out_tstsi(rtx_insn * insn,rtx * op,int * plen)6129 avr_out_tstsi (rtx_insn *insn, rtx *op, int *plen)
6130 {
6131   if (compare_sign_p (insn))
6132     {
6133       avr_asm_len ("tst %D0", op, plen, -1);
6134     }
6135   else if (reg_unused_after (insn, op[0])
6136            && compare_eq_p (insn))
6137     {
6138       /* Faster than sbiw if we can clobber the operand.  */
6139       avr_asm_len ("or %A0,%B0" CR_TAB
6140                    "or %A0,%C0" CR_TAB
6141                    "or %A0,%D0", op, plen, -3);
6142     }
6143   else
6144     {
6145       avr_out_compare (insn, op, plen);
6146     }
6147 
6148   return "";
6149 }
6150 
6151 
6152 /* Generate asm equivalent for various shifts.  This only handles cases
6153    that are not already carefully hand-optimized in ?sh??i3_out.
6154 
6155    OPERANDS[0] resp. %0 in TEMPL is the operand to be shifted.
6156    OPERANDS[2] is the shift count as CONST_INT, MEM or REG.
6157    OPERANDS[3] is a QImode scratch register from LD regs if
6158                available and SCRATCH, otherwise (no scratch available)
6159 
6160    TEMPL is an assembler template that shifts by one position.
6161    T_LEN is the length of this template.  */
6162 
6163 void
out_shift_with_cnt(const char * templ,rtx_insn * insn,rtx operands[],int * plen,int t_len)6164 out_shift_with_cnt (const char *templ, rtx_insn *insn, rtx operands[],
6165 		    int *plen, int t_len)
6166 {
6167   bool second_label = true;
6168   bool saved_in_tmp = false;
6169   bool use_zero_reg = false;
6170   rtx op[5];
6171 
6172   op[0] = operands[0];
6173   op[1] = operands[1];
6174   op[2] = operands[2];
6175   op[3] = operands[3];
6176 
6177   if (plen)
6178     *plen = 0;
6179 
6180   if (CONST_INT_P (operands[2]))
6181     {
6182       bool scratch = (GET_CODE (PATTERN (insn)) == PARALLEL
6183                       && REG_P (operands[3]));
6184       int count = INTVAL (operands[2]);
6185       int max_len = 10;  /* If larger than this, always use a loop.  */
6186 
6187       if (count <= 0)
6188         return;
6189 
6190       if (count < 8 && !scratch)
6191         use_zero_reg = true;
6192 
6193       if (optimize_size)
6194         max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
6195 
6196       if (t_len * count <= max_len)
6197         {
6198           /* Output shifts inline with no loop - faster.  */
6199 
6200           while (count-- > 0)
6201             avr_asm_len (templ, op, plen, t_len);
6202 
6203           return;
6204         }
6205 
6206       if (scratch)
6207         {
6208           avr_asm_len ("ldi %3,%2", op, plen, 1);
6209         }
6210       else if (use_zero_reg)
6211         {
6212           /* Hack to save one word: use __zero_reg__ as loop counter.
6213              Set one bit, then shift in a loop until it is 0 again.  */
6214 
6215           op[3] = zero_reg_rtx;
6216 
6217           avr_asm_len ("set" CR_TAB
6218                        "bld %3,%2-1", op, plen, 2);
6219         }
6220       else
6221         {
6222           /* No scratch register available, use one from LD_REGS (saved in
6223              __tmp_reg__) that doesn't overlap with registers to shift.  */
6224 
6225           op[3] = all_regs_rtx[((REGNO (op[0]) - 1) & 15) + 16];
6226           op[4] = tmp_reg_rtx;
6227           saved_in_tmp = true;
6228 
6229           avr_asm_len ("mov %4,%3" CR_TAB
6230                        "ldi %3,%2", op, plen, 2);
6231         }
6232 
6233       second_label = false;
6234     }
6235   else if (MEM_P (op[2]))
6236     {
6237       rtx op_mov[2];
6238 
6239       op_mov[0] = op[3] = tmp_reg_rtx;
6240       op_mov[1] = op[2];
6241 
6242       out_movqi_r_mr (insn, op_mov, plen);
6243     }
6244   else if (register_operand (op[2], QImode))
6245     {
6246       op[3] = op[2];
6247 
6248       if (!reg_unused_after (insn, op[2])
6249           || reg_overlap_mentioned_p (op[0], op[2]))
6250         {
6251           op[3] = tmp_reg_rtx;
6252           avr_asm_len ("mov %3,%2", op, plen, 1);
6253         }
6254     }
6255   else
6256     fatal_insn ("bad shift insn:", insn);
6257 
6258   if (second_label)
6259     avr_asm_len ("rjmp 2f", op, plen, 1);
6260 
6261   avr_asm_len ("1:", op, plen, 0);
6262   avr_asm_len (templ, op, plen, t_len);
6263 
6264   if (second_label)
6265     avr_asm_len ("2:", op, plen, 0);
6266 
6267   avr_asm_len (use_zero_reg ? "lsr %3" : "dec %3", op, plen, 1);
6268   avr_asm_len (second_label ? "brpl 1b" : "brne 1b", op, plen, 1);
6269 
6270   if (saved_in_tmp)
6271     avr_asm_len ("mov %3,%4", op, plen, 1);
6272 }
6273 
6274 
6275 /* 8bit shift left ((char)x << i)   */
6276 
6277 const char *
ashlqi3_out(rtx_insn * insn,rtx operands[],int * len)6278 ashlqi3_out (rtx_insn *insn, rtx operands[], int *len)
6279 {
6280   if (CONST_INT_P (operands[2]))
6281     {
6282       int k;
6283 
6284       if (!len)
6285 	len = &k;
6286 
6287       switch (INTVAL (operands[2]))
6288 	{
6289 	default:
6290 	  if (INTVAL (operands[2]) < 8)
6291 	    break;
6292 
6293 	  *len = 1;
6294 	  return "clr %0";
6295 
6296 	case 1:
6297 	  *len = 1;
6298 	  return "lsl %0";
6299 
6300 	case 2:
6301 	  *len = 2;
6302 	  return ("lsl %0" CR_TAB
6303 		  "lsl %0");
6304 
6305 	case 3:
6306 	  *len = 3;
6307 	  return ("lsl %0" CR_TAB
6308 		  "lsl %0" CR_TAB
6309 		  "lsl %0");
6310 
6311 	case 4:
6312 	  if (test_hard_reg_class (LD_REGS, operands[0]))
6313 	    {
6314 	      *len = 2;
6315 	      return ("swap %0" CR_TAB
6316 		      "andi %0,0xf0");
6317 	    }
6318 	  *len = 4;
6319 	  return ("lsl %0" CR_TAB
6320 		  "lsl %0" CR_TAB
6321 		  "lsl %0" CR_TAB
6322 		  "lsl %0");
6323 
6324 	case 5:
6325 	  if (test_hard_reg_class (LD_REGS, operands[0]))
6326 	    {
6327 	      *len = 3;
6328 	      return ("swap %0" CR_TAB
6329 		      "lsl %0"  CR_TAB
6330 		      "andi %0,0xe0");
6331 	    }
6332 	  *len = 5;
6333 	  return ("lsl %0" CR_TAB
6334 		  "lsl %0" CR_TAB
6335 		  "lsl %0" CR_TAB
6336 		  "lsl %0" CR_TAB
6337 		  "lsl %0");
6338 
6339 	case 6:
6340 	  if (test_hard_reg_class (LD_REGS, operands[0]))
6341 	    {
6342 	      *len = 4;
6343 	      return ("swap %0" CR_TAB
6344 		      "lsl %0"  CR_TAB
6345 		      "lsl %0"  CR_TAB
6346 		      "andi %0,0xc0");
6347 	    }
6348 	  *len = 6;
6349 	  return ("lsl %0" CR_TAB
6350 		  "lsl %0" CR_TAB
6351 		  "lsl %0" CR_TAB
6352 		  "lsl %0" CR_TAB
6353 		  "lsl %0" CR_TAB
6354 		  "lsl %0");
6355 
6356 	case 7:
6357 	  *len = 3;
6358 	  return ("ror %0" CR_TAB
6359 		  "clr %0" CR_TAB
6360 		  "ror %0");
6361 	}
6362     }
6363   else if (CONSTANT_P (operands[2]))
6364     fatal_insn ("internal compiler error.  Incorrect shift:", insn);
6365 
6366   out_shift_with_cnt ("lsl %0",
6367                       insn, operands, len, 1);
6368   return "";
6369 }
6370 
6371 
6372 /* 16bit shift left ((short)x << i)   */
6373 
6374 const char *
ashlhi3_out(rtx_insn * insn,rtx operands[],int * len)6375 ashlhi3_out (rtx_insn *insn, rtx operands[], int *len)
6376 {
6377   if (CONST_INT_P (operands[2]))
6378     {
6379       int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
6380       int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
6381       int k;
6382       int *t = len;
6383 
6384       if (!len)
6385 	len = &k;
6386 
6387       switch (INTVAL (operands[2]))
6388 	{
6389 	default:
6390 	  if (INTVAL (operands[2]) < 16)
6391 	    break;
6392 
6393 	  *len = 2;
6394 	  return ("clr %B0" CR_TAB
6395 		  "clr %A0");
6396 
6397 	case 4:
6398 	  if (optimize_size && scratch)
6399 	    break;  /* 5 */
6400 	  if (ldi_ok)
6401 	    {
6402 	      *len = 6;
6403 	      return ("swap %A0"      CR_TAB
6404 		      "swap %B0"      CR_TAB
6405 		      "andi %B0,0xf0" CR_TAB
6406 		      "eor %B0,%A0"   CR_TAB
6407 		      "andi %A0,0xf0" CR_TAB
6408 		      "eor %B0,%A0");
6409 	    }
6410 	  if (scratch)
6411 	    {
6412 	      *len = 7;
6413 	      return ("swap %A0"    CR_TAB
6414 		      "swap %B0"    CR_TAB
6415 		      "ldi %3,0xf0" CR_TAB
6416 		      "and %B0,%3"  CR_TAB
6417 		      "eor %B0,%A0" CR_TAB
6418 		      "and %A0,%3"  CR_TAB
6419 		      "eor %B0,%A0");
6420 	    }
6421 	  break;  /* optimize_size ? 6 : 8 */
6422 
6423 	case 5:
6424 	  if (optimize_size)
6425 	    break;  /* scratch ? 5 : 6 */
6426 	  if (ldi_ok)
6427 	    {
6428 	      *len = 8;
6429 	      return ("lsl %A0"       CR_TAB
6430 		      "rol %B0"       CR_TAB
6431 		      "swap %A0"      CR_TAB
6432 		      "swap %B0"      CR_TAB
6433 		      "andi %B0,0xf0" CR_TAB
6434 		      "eor %B0,%A0"   CR_TAB
6435 		      "andi %A0,0xf0" CR_TAB
6436 		      "eor %B0,%A0");
6437 	    }
6438 	  if (scratch)
6439 	    {
6440 	      *len = 9;
6441 	      return ("lsl %A0"     CR_TAB
6442 		      "rol %B0"     CR_TAB
6443 		      "swap %A0"    CR_TAB
6444 		      "swap %B0"    CR_TAB
6445 		      "ldi %3,0xf0" CR_TAB
6446 		      "and %B0,%3"  CR_TAB
6447 		      "eor %B0,%A0" CR_TAB
6448 		      "and %A0,%3"  CR_TAB
6449 		      "eor %B0,%A0");
6450 	    }
6451 	  break;  /* 10 */
6452 
6453 	case 6:
6454 	  if (optimize_size)
6455 	    break;  /* scratch ? 5 : 6 */
6456 	  *len = 9;
6457 	  return ("clr __tmp_reg__" CR_TAB
6458 		  "lsr %B0"         CR_TAB
6459 		  "ror %A0"         CR_TAB
6460 		  "ror __tmp_reg__" CR_TAB
6461 		  "lsr %B0"         CR_TAB
6462 		  "ror %A0"         CR_TAB
6463 		  "ror __tmp_reg__" CR_TAB
6464 		  "mov %B0,%A0"     CR_TAB
6465 		  "mov %A0,__tmp_reg__");
6466 
6467 	case 7:
6468 	  *len = 5;
6469 	  return ("lsr %B0"     CR_TAB
6470 		  "mov %B0,%A0" CR_TAB
6471 		  "clr %A0"     CR_TAB
6472 		  "ror %B0"     CR_TAB
6473 		  "ror %A0");
6474 
6475 	case 8:
6476 	  return *len = 2, ("mov %B0,%A1" CR_TAB
6477 			    "clr %A0");
6478 
6479 	case 9:
6480 	  *len = 3;
6481 	  return ("mov %B0,%A0" CR_TAB
6482 		  "clr %A0"     CR_TAB
6483 		  "lsl %B0");
6484 
6485 	case 10:
6486 	  *len = 4;
6487 	  return ("mov %B0,%A0" CR_TAB
6488 		  "clr %A0"     CR_TAB
6489 		  "lsl %B0"     CR_TAB
6490 		  "lsl %B0");
6491 
6492 	case 11:
6493 	  *len = 5;
6494 	  return ("mov %B0,%A0" CR_TAB
6495 		  "clr %A0"     CR_TAB
6496 		  "lsl %B0"     CR_TAB
6497 		  "lsl %B0"     CR_TAB
6498 		  "lsl %B0");
6499 
6500 	case 12:
6501 	  if (ldi_ok)
6502 	    {
6503 	      *len = 4;
6504 	      return ("mov %B0,%A0" CR_TAB
6505 		      "clr %A0"     CR_TAB
6506 		      "swap %B0"    CR_TAB
6507 		      "andi %B0,0xf0");
6508 	    }
6509 	  if (scratch)
6510 	    {
6511 	      *len = 5;
6512 	      return ("mov %B0,%A0" CR_TAB
6513 		      "clr %A0"     CR_TAB
6514 		      "swap %B0"    CR_TAB
6515 		      "ldi %3,0xf0" CR_TAB
6516 		      "and %B0,%3");
6517 	    }
6518 	  *len = 6;
6519 	  return ("mov %B0,%A0" CR_TAB
6520 		  "clr %A0"     CR_TAB
6521 		  "lsl %B0"     CR_TAB
6522 		  "lsl %B0"     CR_TAB
6523 		  "lsl %B0"     CR_TAB
6524 		  "lsl %B0");
6525 
6526 	case 13:
6527 	  if (ldi_ok)
6528 	    {
6529 	      *len = 5;
6530 	      return ("mov %B0,%A0" CR_TAB
6531 		      "clr %A0"     CR_TAB
6532 		      "swap %B0"    CR_TAB
6533 		      "lsl %B0"     CR_TAB
6534 		      "andi %B0,0xe0");
6535 	    }
6536 	  if (AVR_HAVE_MUL && scratch)
6537 	    {
6538 	      *len = 5;
6539 	      return ("ldi %3,0x20" CR_TAB
6540 		      "mul %A0,%3"  CR_TAB
6541 		      "mov %B0,r0"  CR_TAB
6542 		      "clr %A0"     CR_TAB
6543 		      "clr __zero_reg__");
6544 	    }
6545 	  if (optimize_size && scratch)
6546 	    break;  /* 5 */
6547 	  if (scratch)
6548 	    {
6549 	      *len = 6;
6550 	      return ("mov %B0,%A0" CR_TAB
6551 		      "clr %A0"     CR_TAB
6552 		      "swap %B0"    CR_TAB
6553 		      "lsl %B0"     CR_TAB
6554 		      "ldi %3,0xe0" CR_TAB
6555 		      "and %B0,%3");
6556 	    }
6557 	  if (AVR_HAVE_MUL)
6558 	    {
6559 	      *len = 6;
6560 	      return ("set"        CR_TAB
6561 		      "bld r1,5"   CR_TAB
6562 		      "mul %A0,r1" CR_TAB
6563 		      "mov %B0,r0" CR_TAB
6564 		      "clr %A0"    CR_TAB
6565 		      "clr __zero_reg__");
6566 	    }
6567 	  *len = 7;
6568 	  return ("mov %B0,%A0" CR_TAB
6569 		  "clr %A0"     CR_TAB
6570 		  "lsl %B0"     CR_TAB
6571 		  "lsl %B0"     CR_TAB
6572 		  "lsl %B0"     CR_TAB
6573 		  "lsl %B0"     CR_TAB
6574 		  "lsl %B0");
6575 
6576 	case 14:
6577 	  if (AVR_HAVE_MUL && ldi_ok)
6578 	    {
6579 	      *len = 5;
6580 	      return ("ldi %B0,0x40" CR_TAB
6581 		      "mul %A0,%B0"  CR_TAB
6582 		      "mov %B0,r0"   CR_TAB
6583 		      "clr %A0"      CR_TAB
6584 		      "clr __zero_reg__");
6585 	    }
6586 	  if (AVR_HAVE_MUL && scratch)
6587 	    {
6588 	      *len = 5;
6589 	      return ("ldi %3,0x40" CR_TAB
6590 		      "mul %A0,%3"  CR_TAB
6591 		      "mov %B0,r0"  CR_TAB
6592 		      "clr %A0"     CR_TAB
6593 		      "clr __zero_reg__");
6594 	    }
6595 	  if (optimize_size && ldi_ok)
6596 	    {
6597 	      *len = 5;
6598 	      return ("mov %B0,%A0" CR_TAB
6599 		      "ldi %A0,6" "\n1:\t"
6600 		      "lsl %B0"     CR_TAB
6601 		      "dec %A0"     CR_TAB
6602 		      "brne 1b");
6603 	    }
6604 	  if (optimize_size && scratch)
6605 	    break;  /* 5 */
6606 	  *len = 6;
6607 	  return ("clr %B0" CR_TAB
6608 		  "lsr %A0" CR_TAB
6609 		  "ror %B0" CR_TAB
6610 		  "lsr %A0" CR_TAB
6611 		  "ror %B0" CR_TAB
6612 		  "clr %A0");
6613 
6614 	case 15:
6615 	  *len = 4;
6616 	  return ("clr %B0" CR_TAB
6617 		  "lsr %A0" CR_TAB
6618 		  "ror %B0" CR_TAB
6619 		  "clr %A0");
6620 	}
6621       len = t;
6622     }
6623   out_shift_with_cnt ("lsl %A0" CR_TAB
6624                       "rol %B0", insn, operands, len, 2);
6625   return "";
6626 }
6627 
6628 
6629 /* 24-bit shift left */
6630 
6631 const char*
avr_out_ashlpsi3(rtx_insn * insn,rtx * op,int * plen)6632 avr_out_ashlpsi3 (rtx_insn *insn, rtx *op, int *plen)
6633 {
6634   if (plen)
6635     *plen = 0;
6636 
6637   if (CONST_INT_P (op[2]))
6638     {
6639       switch (INTVAL (op[2]))
6640         {
6641         default:
6642           if (INTVAL (op[2]) < 24)
6643             break;
6644 
6645           return avr_asm_len ("clr %A0" CR_TAB
6646                               "clr %B0" CR_TAB
6647                               "clr %C0", op, plen, 3);
6648 
6649         case 8:
6650           {
6651             int reg0 = REGNO (op[0]);
6652             int reg1 = REGNO (op[1]);
6653 
6654             if (reg0 >= reg1)
6655               return avr_asm_len ("mov %C0,%B1"  CR_TAB
6656                                   "mov %B0,%A1"  CR_TAB
6657                                   "clr %A0", op, plen, 3);
6658             else
6659               return avr_asm_len ("clr %A0"      CR_TAB
6660                                   "mov %B0,%A1"  CR_TAB
6661                                   "mov %C0,%B1", op, plen, 3);
6662           }
6663 
6664         case 16:
6665           {
6666             int reg0 = REGNO (op[0]);
6667             int reg1 = REGNO (op[1]);
6668 
6669             if (reg0 + 2 != reg1)
6670               avr_asm_len ("mov %C0,%A0", op, plen, 1);
6671 
6672             return avr_asm_len ("clr %B0"  CR_TAB
6673                                 "clr %A0", op, plen, 2);
6674           }
6675 
6676         case 23:
6677           return avr_asm_len ("clr %C0" CR_TAB
6678                               "lsr %A0" CR_TAB
6679                               "ror %C0" CR_TAB
6680                               "clr %B0" CR_TAB
6681                               "clr %A0", op, plen, 5);
6682         }
6683     }
6684 
6685   out_shift_with_cnt ("lsl %A0" CR_TAB
6686                       "rol %B0" CR_TAB
6687                       "rol %C0", insn, op, plen, 3);
6688   return "";
6689 }
6690 
6691 
6692 /* 32bit shift left ((long)x << i)   */
6693 
6694 const char *
ashlsi3_out(rtx_insn * insn,rtx operands[],int * len)6695 ashlsi3_out (rtx_insn *insn, rtx operands[], int *len)
6696 {
6697   if (CONST_INT_P (operands[2]))
6698     {
6699       int k;
6700       int *t = len;
6701 
6702       if (!len)
6703 	len = &k;
6704 
6705       switch (INTVAL (operands[2]))
6706 	{
6707 	default:
6708 	  if (INTVAL (operands[2]) < 32)
6709 	    break;
6710 
6711 	  if (AVR_HAVE_MOVW)
6712 	    return *len = 3, ("clr %D0" CR_TAB
6713 			      "clr %C0" CR_TAB
6714 			      "movw %A0,%C0");
6715 	  *len = 4;
6716 	  return ("clr %D0" CR_TAB
6717 		  "clr %C0" CR_TAB
6718 		  "clr %B0" CR_TAB
6719 		  "clr %A0");
6720 
6721 	case 8:
6722 	  {
6723 	    int reg0 = true_regnum (operands[0]);
6724 	    int reg1 = true_regnum (operands[1]);
6725 	    *len = 4;
6726 	    if (reg0 >= reg1)
6727 	      return ("mov %D0,%C1"  CR_TAB
6728 		      "mov %C0,%B1"  CR_TAB
6729 		      "mov %B0,%A1"  CR_TAB
6730 		      "clr %A0");
6731 	    else
6732 	      return ("clr %A0"      CR_TAB
6733 		      "mov %B0,%A1"  CR_TAB
6734 		      "mov %C0,%B1"  CR_TAB
6735 		      "mov %D0,%C1");
6736 	  }
6737 
6738 	case 16:
6739 	  {
6740 	    int reg0 = true_regnum (operands[0]);
6741 	    int reg1 = true_regnum (operands[1]);
6742 	    if (reg0 + 2 == reg1)
6743 	      return *len = 2, ("clr %B0"      CR_TAB
6744 				"clr %A0");
6745 	    if (AVR_HAVE_MOVW)
6746 	      return *len = 3, ("movw %C0,%A1" CR_TAB
6747 				"clr %B0"      CR_TAB
6748 				"clr %A0");
6749 	    else
6750 	      return *len = 4, ("mov %C0,%A1"  CR_TAB
6751 				"mov %D0,%B1"  CR_TAB
6752 				"clr %B0"      CR_TAB
6753 				"clr %A0");
6754 	  }
6755 
6756 	case 24:
6757 	  *len = 4;
6758 	  return ("mov %D0,%A1"  CR_TAB
6759 		  "clr %C0"      CR_TAB
6760 		  "clr %B0"      CR_TAB
6761 		  "clr %A0");
6762 
6763 	case 31:
6764 	  *len = 6;
6765 	  return ("clr %D0" CR_TAB
6766 		  "lsr %A0" CR_TAB
6767 		  "ror %D0" CR_TAB
6768 		  "clr %C0" CR_TAB
6769 		  "clr %B0" CR_TAB
6770 		  "clr %A0");
6771 	}
6772       len = t;
6773     }
6774   out_shift_with_cnt ("lsl %A0" CR_TAB
6775                       "rol %B0" CR_TAB
6776                       "rol %C0" CR_TAB
6777                       "rol %D0", insn, operands, len, 4);
6778   return "";
6779 }
6780 
6781 /* 8bit arithmetic shift right  ((signed char)x >> i) */
6782 
6783 const char *
ashrqi3_out(rtx_insn * insn,rtx operands[],int * len)6784 ashrqi3_out (rtx_insn *insn, rtx operands[], int *len)
6785 {
6786   if (CONST_INT_P (operands[2]))
6787     {
6788       int k;
6789 
6790       if (!len)
6791 	len = &k;
6792 
6793       switch (INTVAL (operands[2]))
6794 	{
6795 	case 1:
6796 	  *len = 1;
6797 	  return "asr %0";
6798 
6799 	case 2:
6800 	  *len = 2;
6801 	  return ("asr %0" CR_TAB
6802 		  "asr %0");
6803 
6804 	case 3:
6805 	  *len = 3;
6806 	  return ("asr %0" CR_TAB
6807 		  "asr %0" CR_TAB
6808 		  "asr %0");
6809 
6810 	case 4:
6811 	  *len = 4;
6812 	  return ("asr %0" CR_TAB
6813 		  "asr %0" CR_TAB
6814 		  "asr %0" CR_TAB
6815 		  "asr %0");
6816 
6817 	case 5:
6818 	  *len = 5;
6819 	  return ("asr %0" CR_TAB
6820 		  "asr %0" CR_TAB
6821 		  "asr %0" CR_TAB
6822 		  "asr %0" CR_TAB
6823 		  "asr %0");
6824 
6825 	case 6:
6826 	  *len = 4;
6827 	  return ("bst %0,6"  CR_TAB
6828 		  "lsl %0"    CR_TAB
6829 		  "sbc %0,%0" CR_TAB
6830 		  "bld %0,0");
6831 
6832 	default:
6833 	  if (INTVAL (operands[2]) < 8)
6834 	    break;
6835 
6836 	  /* fall through */
6837 
6838 	case 7:
6839 	  *len = 2;
6840 	  return ("lsl %0" CR_TAB
6841 		  "sbc %0,%0");
6842 	}
6843     }
6844   else if (CONSTANT_P (operands[2]))
6845     fatal_insn ("internal compiler error.  Incorrect shift:", insn);
6846 
6847   out_shift_with_cnt ("asr %0",
6848                       insn, operands, len, 1);
6849   return "";
6850 }
6851 
6852 
6853 /* 16bit arithmetic shift right  ((signed short)x >> i) */
6854 
6855 const char *
ashrhi3_out(rtx_insn * insn,rtx operands[],int * len)6856 ashrhi3_out (rtx_insn *insn, rtx operands[], int *len)
6857 {
6858   if (CONST_INT_P (operands[2]))
6859     {
6860       int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
6861       int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
6862       int k;
6863       int *t = len;
6864 
6865       if (!len)
6866 	len = &k;
6867 
6868       switch (INTVAL (operands[2]))
6869 	{
6870 	case 4:
6871 	case 5:
6872 	  /* XXX try to optimize this too? */
6873 	  break;
6874 
6875 	case 6:
6876 	  if (optimize_size)
6877 	    break;  /* scratch ? 5 : 6 */
6878 	  *len = 8;
6879 	  return ("mov __tmp_reg__,%A0" CR_TAB
6880 		  "mov %A0,%B0"         CR_TAB
6881 		  "lsl __tmp_reg__"     CR_TAB
6882 		  "rol %A0"             CR_TAB
6883 		  "sbc %B0,%B0"         CR_TAB
6884 		  "lsl __tmp_reg__"     CR_TAB
6885 		  "rol %A0"             CR_TAB
6886 		  "rol %B0");
6887 
6888 	case 7:
6889 	  *len = 4;
6890 	  return ("lsl %A0"     CR_TAB
6891 		  "mov %A0,%B0" CR_TAB
6892 		  "rol %A0"     CR_TAB
6893 		  "sbc %B0,%B0");
6894 
6895 	case 8:
6896 	  {
6897 	    int reg0 = true_regnum (operands[0]);
6898 	    int reg1 = true_regnum (operands[1]);
6899 
6900 	    if (reg0 == reg1)
6901 	      return *len = 3, ("mov %A0,%B0" CR_TAB
6902 				"lsl %B0"     CR_TAB
6903 				"sbc %B0,%B0");
6904 	    else
6905 	      return *len = 4, ("mov %A0,%B1" CR_TAB
6906 			        "clr %B0"     CR_TAB
6907 			        "sbrc %A0,7"  CR_TAB
6908 			        "dec %B0");
6909 	  }
6910 
6911 	case 9:
6912 	  *len = 4;
6913 	  return ("mov %A0,%B0" CR_TAB
6914 		  "lsl %B0"      CR_TAB
6915 		  "sbc %B0,%B0" CR_TAB
6916 		  "asr %A0");
6917 
6918 	case 10:
6919 	  *len = 5;
6920 	  return ("mov %A0,%B0" CR_TAB
6921 		  "lsl %B0"     CR_TAB
6922 		  "sbc %B0,%B0" CR_TAB
6923 		  "asr %A0"     CR_TAB
6924 		  "asr %A0");
6925 
6926 	case 11:
6927 	  if (AVR_HAVE_MUL && ldi_ok)
6928 	    {
6929 	      *len = 5;
6930 	      return ("ldi %A0,0x20" CR_TAB
6931 		      "muls %B0,%A0" CR_TAB
6932 		      "mov %A0,r1"   CR_TAB
6933 		      "sbc %B0,%B0"  CR_TAB
6934 		      "clr __zero_reg__");
6935 	    }
6936 	  if (optimize_size && scratch)
6937 	    break;  /* 5 */
6938 	  *len = 6;
6939 	  return ("mov %A0,%B0" CR_TAB
6940 		  "lsl %B0"     CR_TAB
6941 		  "sbc %B0,%B0" CR_TAB
6942 		  "asr %A0"     CR_TAB
6943 		  "asr %A0"     CR_TAB
6944 		  "asr %A0");
6945 
6946 	case 12:
6947 	  if (AVR_HAVE_MUL && ldi_ok)
6948 	    {
6949 	      *len = 5;
6950 	      return ("ldi %A0,0x10" CR_TAB
6951 		      "muls %B0,%A0" CR_TAB
6952 		      "mov %A0,r1"   CR_TAB
6953 		      "sbc %B0,%B0"  CR_TAB
6954 		      "clr __zero_reg__");
6955 	    }
6956 	  if (optimize_size && scratch)
6957 	    break;  /* 5 */
6958 	  *len = 7;
6959 	  return ("mov %A0,%B0" CR_TAB
6960 		  "lsl %B0"     CR_TAB
6961 		  "sbc %B0,%B0" CR_TAB
6962 		  "asr %A0"     CR_TAB
6963 		  "asr %A0"     CR_TAB
6964 		  "asr %A0"     CR_TAB
6965 		  "asr %A0");
6966 
6967 	case 13:
6968 	  if (AVR_HAVE_MUL && ldi_ok)
6969 	    {
6970 	      *len = 5;
6971 	      return ("ldi %A0,0x08" CR_TAB
6972 		      "muls %B0,%A0" CR_TAB
6973 		      "mov %A0,r1"   CR_TAB
6974 		      "sbc %B0,%B0"  CR_TAB
6975 		      "clr __zero_reg__");
6976 	    }
6977 	  if (optimize_size)
6978 	    break;  /* scratch ? 5 : 7 */
6979 	  *len = 8;
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"     CR_TAB
6986 		  "asr %A0"     CR_TAB
6987 		  "asr %A0");
6988 
6989 	case 14:
6990 	  *len = 5;
6991 	  return ("lsl %B0"     CR_TAB
6992 		  "sbc %A0,%A0" CR_TAB
6993 		  "lsl %B0"     CR_TAB
6994 		  "mov %B0,%A0" CR_TAB
6995 		  "rol %A0");
6996 
6997 	default:
6998 	  if (INTVAL (operands[2]) < 16)
6999 	    break;
7000 
7001 	  /* fall through */
7002 
7003 	case 15:
7004 	  return *len = 3, ("lsl %B0"     CR_TAB
7005 			    "sbc %A0,%A0" CR_TAB
7006 			    "mov %B0,%A0");
7007 	}
7008       len = t;
7009     }
7010   out_shift_with_cnt ("asr %B0" CR_TAB
7011                       "ror %A0", insn, operands, len, 2);
7012   return "";
7013 }
7014 
7015 
7016 /* 24-bit arithmetic shift right */
7017 
7018 const char*
avr_out_ashrpsi3(rtx_insn * insn,rtx * op,int * plen)7019 avr_out_ashrpsi3 (rtx_insn *insn, rtx *op, int *plen)
7020 {
7021   int dest = REGNO (op[0]);
7022   int src = REGNO (op[1]);
7023 
7024   if (CONST_INT_P (op[2]))
7025     {
7026       if (plen)
7027         *plen = 0;
7028 
7029       switch (INTVAL (op[2]))
7030         {
7031         case 8:
7032           if (dest <= src)
7033             return avr_asm_len ("mov %A0,%B1" CR_TAB
7034                                 "mov %B0,%C1" CR_TAB
7035                                 "clr %C0"     CR_TAB
7036                                 "sbrc %B0,7"  CR_TAB
7037                                 "dec %C0", op, plen, 5);
7038           else
7039             return avr_asm_len ("clr %C0"     CR_TAB
7040                                 "sbrc %C1,7"  CR_TAB
7041                                 "dec %C0"     CR_TAB
7042                                 "mov %B0,%C1" CR_TAB
7043                                 "mov %A0,%B1", op, plen, 5);
7044 
7045         case 16:
7046           if (dest != src + 2)
7047             avr_asm_len ("mov %A0,%C1", op, plen, 1);
7048 
7049           return avr_asm_len ("clr %B0"     CR_TAB
7050                               "sbrc %A0,7"  CR_TAB
7051                               "com %B0"     CR_TAB
7052                               "mov %C0,%B0", op, plen, 4);
7053 
7054         default:
7055           if (INTVAL (op[2]) < 24)
7056             break;
7057 
7058           /* fall through */
7059 
7060         case 23:
7061           return avr_asm_len ("lsl %C0"     CR_TAB
7062                               "sbc %A0,%A0" CR_TAB
7063                               "mov %B0,%A0" CR_TAB
7064                               "mov %C0,%A0", op, plen, 4);
7065         } /* switch */
7066     }
7067 
7068   out_shift_with_cnt ("asr %C0" CR_TAB
7069                       "ror %B0" CR_TAB
7070                       "ror %A0", insn, op, plen, 3);
7071   return "";
7072 }
7073 
7074 
7075 /* 32-bit arithmetic shift right  ((signed long)x >> i) */
7076 
7077 const char *
ashrsi3_out(rtx_insn * insn,rtx operands[],int * len)7078 ashrsi3_out (rtx_insn *insn, rtx operands[], int *len)
7079 {
7080   if (CONST_INT_P (operands[2]))
7081     {
7082       int k;
7083       int *t = len;
7084 
7085       if (!len)
7086 	len = &k;
7087 
7088       switch (INTVAL (operands[2]))
7089 	{
7090 	case 8:
7091 	  {
7092 	    int reg0 = true_regnum (operands[0]);
7093 	    int reg1 = true_regnum (operands[1]);
7094 	    *len=6;
7095 	    if (reg0 <= reg1)
7096 	      return ("mov %A0,%B1" CR_TAB
7097 		      "mov %B0,%C1" CR_TAB
7098 		      "mov %C0,%D1" CR_TAB
7099 		      "clr %D0"     CR_TAB
7100 		      "sbrc %C0,7"  CR_TAB
7101 		      "dec %D0");
7102 	    else
7103 	      return ("clr %D0"     CR_TAB
7104 		      "sbrc %D1,7"  CR_TAB
7105 		      "dec %D0"     CR_TAB
7106 		      "mov %C0,%D1" CR_TAB
7107 		      "mov %B0,%C1" CR_TAB
7108 		      "mov %A0,%B1");
7109 	  }
7110 
7111 	case 16:
7112 	  {
7113 	    int reg0 = true_regnum (operands[0]);
7114 	    int reg1 = true_regnum (operands[1]);
7115 
7116 	    if (reg0 == reg1 + 2)
7117 	      return *len = 4, ("clr %D0"     CR_TAB
7118 				"sbrc %B0,7"  CR_TAB
7119 				"com %D0"     CR_TAB
7120 				"mov %C0,%D0");
7121 	    if (AVR_HAVE_MOVW)
7122 	      return *len = 5, ("movw %A0,%C1" CR_TAB
7123 				"clr %D0"      CR_TAB
7124 				"sbrc %B0,7"   CR_TAB
7125 				"com %D0"      CR_TAB
7126 				"mov %C0,%D0");
7127 	    else
7128 	      return *len = 6, ("mov %B0,%D1" CR_TAB
7129 				"mov %A0,%C1" CR_TAB
7130 				"clr %D0"     CR_TAB
7131 				"sbrc %B0,7"  CR_TAB
7132 				"com %D0"     CR_TAB
7133 				"mov %C0,%D0");
7134 	  }
7135 
7136 	case 24:
7137 	  return *len = 6, ("mov %A0,%D1" CR_TAB
7138 			    "clr %D0"     CR_TAB
7139 			    "sbrc %A0,7"  CR_TAB
7140 			    "com %D0"     CR_TAB
7141 			    "mov %B0,%D0" CR_TAB
7142 			    "mov %C0,%D0");
7143 
7144 	default:
7145 	  if (INTVAL (operands[2]) < 32)
7146 	    break;
7147 
7148 	  /* fall through */
7149 
7150 	case 31:
7151 	  if (AVR_HAVE_MOVW)
7152 	    return *len = 4, ("lsl %D0"     CR_TAB
7153 			      "sbc %A0,%A0" CR_TAB
7154 			      "mov %B0,%A0" CR_TAB
7155 			      "movw %C0,%A0");
7156 	  else
7157 	    return *len = 5, ("lsl %D0"     CR_TAB
7158 			      "sbc %A0,%A0" CR_TAB
7159 			      "mov %B0,%A0" CR_TAB
7160 			      "mov %C0,%A0" CR_TAB
7161 			      "mov %D0,%A0");
7162 	}
7163       len = t;
7164     }
7165   out_shift_with_cnt ("asr %D0" CR_TAB
7166                       "ror %C0" CR_TAB
7167                       "ror %B0" CR_TAB
7168                       "ror %A0", insn, operands, len, 4);
7169   return "";
7170 }
7171 
7172 /* 8-bit logic shift right ((unsigned char)x >> i) */
7173 
7174 const char *
lshrqi3_out(rtx_insn * insn,rtx operands[],int * len)7175 lshrqi3_out (rtx_insn *insn, rtx operands[], int *len)
7176 {
7177   if (CONST_INT_P (operands[2]))
7178     {
7179       int k;
7180 
7181       if (!len)
7182 	len = &k;
7183 
7184       switch (INTVAL (operands[2]))
7185 	{
7186 	default:
7187 	  if (INTVAL (operands[2]) < 8)
7188 	    break;
7189 
7190 	  *len = 1;
7191 	  return "clr %0";
7192 
7193 	case 1:
7194 	  *len = 1;
7195 	  return "lsr %0";
7196 
7197 	case 2:
7198 	  *len = 2;
7199 	  return ("lsr %0" CR_TAB
7200 		  "lsr %0");
7201 	case 3:
7202 	  *len = 3;
7203 	  return ("lsr %0" CR_TAB
7204 		  "lsr %0" CR_TAB
7205 		  "lsr %0");
7206 
7207 	case 4:
7208 	  if (test_hard_reg_class (LD_REGS, operands[0]))
7209 	    {
7210 	      *len=2;
7211 	      return ("swap %0" CR_TAB
7212 		      "andi %0,0x0f");
7213 	    }
7214 	  *len = 4;
7215 	  return ("lsr %0" CR_TAB
7216 		  "lsr %0" CR_TAB
7217 		  "lsr %0" CR_TAB
7218 		  "lsr %0");
7219 
7220 	case 5:
7221 	  if (test_hard_reg_class (LD_REGS, operands[0]))
7222 	    {
7223 	      *len = 3;
7224 	      return ("swap %0" CR_TAB
7225 		      "lsr %0"  CR_TAB
7226 		      "andi %0,0x7");
7227 	    }
7228 	  *len = 5;
7229 	  return ("lsr %0" CR_TAB
7230 		  "lsr %0" CR_TAB
7231 		  "lsr %0" CR_TAB
7232 		  "lsr %0" CR_TAB
7233 		  "lsr %0");
7234 
7235 	case 6:
7236 	  if (test_hard_reg_class (LD_REGS, operands[0]))
7237 	    {
7238 	      *len = 4;
7239 	      return ("swap %0" CR_TAB
7240 		      "lsr %0"  CR_TAB
7241 		      "lsr %0"  CR_TAB
7242 		      "andi %0,0x3");
7243 	    }
7244 	  *len = 6;
7245 	  return ("lsr %0" CR_TAB
7246 		  "lsr %0" CR_TAB
7247 		  "lsr %0" CR_TAB
7248 		  "lsr %0" CR_TAB
7249 		  "lsr %0" CR_TAB
7250 		  "lsr %0");
7251 
7252 	case 7:
7253 	  *len = 3;
7254 	  return ("rol %0" CR_TAB
7255 		  "clr %0" CR_TAB
7256 		  "rol %0");
7257 	}
7258     }
7259   else if (CONSTANT_P (operands[2]))
7260     fatal_insn ("internal compiler error.  Incorrect shift:", insn);
7261 
7262   out_shift_with_cnt ("lsr %0",
7263                       insn, operands, len, 1);
7264   return "";
7265 }
7266 
7267 /* 16-bit logic shift right ((unsigned short)x >> i) */
7268 
7269 const char *
lshrhi3_out(rtx_insn * insn,rtx operands[],int * len)7270 lshrhi3_out (rtx_insn *insn, rtx operands[], int *len)
7271 {
7272   if (CONST_INT_P (operands[2]))
7273     {
7274       int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
7275       int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
7276       int k;
7277       int *t = len;
7278 
7279       if (!len)
7280 	len = &k;
7281 
7282       switch (INTVAL (operands[2]))
7283 	{
7284 	default:
7285 	  if (INTVAL (operands[2]) < 16)
7286 	    break;
7287 
7288 	  *len = 2;
7289 	  return ("clr %B0" CR_TAB
7290 		  "clr %A0");
7291 
7292 	case 4:
7293 	  if (optimize_size && scratch)
7294 	    break;  /* 5 */
7295 	  if (ldi_ok)
7296 	    {
7297 	      *len = 6;
7298 	      return ("swap %B0"      CR_TAB
7299 		      "swap %A0"      CR_TAB
7300 		      "andi %A0,0x0f" CR_TAB
7301 		      "eor %A0,%B0"   CR_TAB
7302 		      "andi %B0,0x0f" CR_TAB
7303 		      "eor %A0,%B0");
7304 	    }
7305 	  if (scratch)
7306 	    {
7307 	      *len = 7;
7308 	      return ("swap %B0"    CR_TAB
7309 		      "swap %A0"    CR_TAB
7310 		      "ldi %3,0x0f" CR_TAB
7311 		      "and %A0,%3"  CR_TAB
7312 		      "eor %A0,%B0" CR_TAB
7313 		      "and %B0,%3"  CR_TAB
7314 		      "eor %A0,%B0");
7315 	    }
7316 	  break;  /* optimize_size ? 6 : 8 */
7317 
7318 	case 5:
7319 	  if (optimize_size)
7320 	    break;  /* scratch ? 5 : 6 */
7321 	  if (ldi_ok)
7322 	    {
7323 	      *len = 8;
7324 	      return ("lsr %B0"       CR_TAB
7325 		      "ror %A0"       CR_TAB
7326 		      "swap %B0"      CR_TAB
7327 		      "swap %A0"      CR_TAB
7328 		      "andi %A0,0x0f" CR_TAB
7329 		      "eor %A0,%B0"   CR_TAB
7330 		      "andi %B0,0x0f" CR_TAB
7331 		      "eor %A0,%B0");
7332 	    }
7333 	  if (scratch)
7334 	    {
7335 	      *len = 9;
7336 	      return ("lsr %B0"     CR_TAB
7337 		      "ror %A0"     CR_TAB
7338 		      "swap %B0"    CR_TAB
7339 		      "swap %A0"    CR_TAB
7340 		      "ldi %3,0x0f" CR_TAB
7341 		      "and %A0,%3"  CR_TAB
7342 		      "eor %A0,%B0" CR_TAB
7343 		      "and %B0,%3"  CR_TAB
7344 		      "eor %A0,%B0");
7345 	    }
7346 	  break;  /* 10 */
7347 
7348 	case 6:
7349 	  if (optimize_size)
7350 	    break;  /* scratch ? 5 : 6 */
7351 	  *len = 9;
7352 	  return ("clr __tmp_reg__" CR_TAB
7353 		  "lsl %A0"         CR_TAB
7354 		  "rol %B0"         CR_TAB
7355 		  "rol __tmp_reg__" CR_TAB
7356 		  "lsl %A0"         CR_TAB
7357 		  "rol %B0"         CR_TAB
7358 		  "rol __tmp_reg__" CR_TAB
7359 		  "mov %A0,%B0"     CR_TAB
7360 		  "mov %B0,__tmp_reg__");
7361 
7362 	case 7:
7363 	  *len = 5;
7364 	  return ("lsl %A0"     CR_TAB
7365 		  "mov %A0,%B0" CR_TAB
7366 		  "rol %A0"     CR_TAB
7367 		  "sbc %B0,%B0" CR_TAB
7368 		  "neg %B0");
7369 
7370 	case 8:
7371 	  return *len = 2, ("mov %A0,%B1" CR_TAB
7372 			    "clr %B0");
7373 
7374 	case 9:
7375 	  *len = 3;
7376 	  return ("mov %A0,%B0" CR_TAB
7377 		  "clr %B0"     CR_TAB
7378 		  "lsr %A0");
7379 
7380 	case 10:
7381 	  *len = 4;
7382 	  return ("mov %A0,%B0" CR_TAB
7383 		  "clr %B0"     CR_TAB
7384 		  "lsr %A0"     CR_TAB
7385 		  "lsr %A0");
7386 
7387 	case 11:
7388 	  *len = 5;
7389 	  return ("mov %A0,%B0" CR_TAB
7390 		  "clr %B0"     CR_TAB
7391 		  "lsr %A0"     CR_TAB
7392 		  "lsr %A0"     CR_TAB
7393 		  "lsr %A0");
7394 
7395 	case 12:
7396 	  if (ldi_ok)
7397 	    {
7398 	      *len = 4;
7399 	      return ("mov %A0,%B0" CR_TAB
7400 		      "clr %B0"     CR_TAB
7401 		      "swap %A0"    CR_TAB
7402 		      "andi %A0,0x0f");
7403 	    }
7404 	  if (scratch)
7405 	    {
7406 	      *len = 5;
7407 	      return ("mov %A0,%B0" CR_TAB
7408 		      "clr %B0"     CR_TAB
7409 		      "swap %A0"    CR_TAB
7410 		      "ldi %3,0x0f" CR_TAB
7411 		      "and %A0,%3");
7412 	    }
7413 	  *len = 6;
7414 	  return ("mov %A0,%B0" CR_TAB
7415 		  "clr %B0"     CR_TAB
7416 		  "lsr %A0"     CR_TAB
7417 		  "lsr %A0"     CR_TAB
7418 		  "lsr %A0"     CR_TAB
7419 		  "lsr %A0");
7420 
7421 	case 13:
7422 	  if (ldi_ok)
7423 	    {
7424 	      *len = 5;
7425 	      return ("mov %A0,%B0" CR_TAB
7426 		      "clr %B0"     CR_TAB
7427 		      "swap %A0"    CR_TAB
7428 		      "lsr %A0"     CR_TAB
7429 		      "andi %A0,0x07");
7430 	    }
7431 	  if (AVR_HAVE_MUL && scratch)
7432 	    {
7433 	      *len = 5;
7434 	      return ("ldi %3,0x08" CR_TAB
7435 		      "mul %B0,%3"  CR_TAB
7436 		      "mov %A0,r1"  CR_TAB
7437 		      "clr %B0"     CR_TAB
7438 		      "clr __zero_reg__");
7439 	    }
7440 	  if (optimize_size && scratch)
7441 	    break;  /* 5 */
7442 	  if (scratch)
7443 	    {
7444 	      *len = 6;
7445 	      return ("mov %A0,%B0" CR_TAB
7446 		      "clr %B0"     CR_TAB
7447 		      "swap %A0"    CR_TAB
7448 		      "lsr %A0"     CR_TAB
7449 		      "ldi %3,0x07" CR_TAB
7450 		      "and %A0,%3");
7451 	    }
7452 	  if (AVR_HAVE_MUL)
7453 	    {
7454 	      *len = 6;
7455 	      return ("set"        CR_TAB
7456 		      "bld r1,3"   CR_TAB
7457 		      "mul %B0,r1" CR_TAB
7458 		      "mov %A0,r1" CR_TAB
7459 		      "clr %B0"    CR_TAB
7460 		      "clr __zero_reg__");
7461 	    }
7462 	  *len = 7;
7463 	  return ("mov %A0,%B0" CR_TAB
7464 		  "clr %B0"     CR_TAB
7465 		  "lsr %A0"     CR_TAB
7466 		  "lsr %A0"     CR_TAB
7467 		  "lsr %A0"     CR_TAB
7468 		  "lsr %A0"     CR_TAB
7469 		  "lsr %A0");
7470 
7471 	case 14:
7472 	  if (AVR_HAVE_MUL && ldi_ok)
7473 	    {
7474 	      *len = 5;
7475 	      return ("ldi %A0,0x04" CR_TAB
7476 		      "mul %B0,%A0"  CR_TAB
7477 		      "mov %A0,r1"   CR_TAB
7478 		      "clr %B0"      CR_TAB
7479 		      "clr __zero_reg__");
7480 	    }
7481 	  if (AVR_HAVE_MUL && scratch)
7482 	    {
7483 	      *len = 5;
7484 	      return ("ldi %3,0x04" CR_TAB
7485 		      "mul %B0,%3"  CR_TAB
7486 		      "mov %A0,r1"  CR_TAB
7487 		      "clr %B0"     CR_TAB
7488 		      "clr __zero_reg__");
7489 	    }
7490 	  if (optimize_size && ldi_ok)
7491 	    {
7492 	      *len = 5;
7493 	      return ("mov %A0,%B0" CR_TAB
7494 		      "ldi %B0,6" "\n1:\t"
7495 		      "lsr %A0"     CR_TAB
7496 		      "dec %B0"     CR_TAB
7497 		      "brne 1b");
7498 	    }
7499 	  if (optimize_size && scratch)
7500 	    break;  /* 5 */
7501 	  *len = 6;
7502 	  return ("clr %A0" CR_TAB
7503 		  "lsl %B0" CR_TAB
7504 		  "rol %A0" CR_TAB
7505 		  "lsl %B0" CR_TAB
7506 		  "rol %A0" CR_TAB
7507 		  "clr %B0");
7508 
7509 	case 15:
7510 	  *len = 4;
7511 	  return ("clr %A0" CR_TAB
7512 		  "lsl %B0" CR_TAB
7513 		  "rol %A0" CR_TAB
7514 		  "clr %B0");
7515 	}
7516       len = t;
7517     }
7518   out_shift_with_cnt ("lsr %B0" CR_TAB
7519                       "ror %A0", insn, operands, len, 2);
7520   return "";
7521 }
7522 
7523 
7524 /* 24-bit logic shift right */
7525 
7526 const char*
avr_out_lshrpsi3(rtx_insn * insn,rtx * op,int * plen)7527 avr_out_lshrpsi3 (rtx_insn *insn, rtx *op, int *plen)
7528 {
7529   int dest = REGNO (op[0]);
7530   int src = REGNO (op[1]);
7531 
7532   if (CONST_INT_P (op[2]))
7533     {
7534       if (plen)
7535         *plen = 0;
7536 
7537       switch (INTVAL (op[2]))
7538         {
7539         case 8:
7540           if (dest <= src)
7541             return avr_asm_len ("mov %A0,%B1" CR_TAB
7542                                 "mov %B0,%C1" CR_TAB
7543                                 "clr %C0", op, plen, 3);
7544           else
7545             return avr_asm_len ("clr %C0"     CR_TAB
7546                                 "mov %B0,%C1" CR_TAB
7547                                 "mov %A0,%B1", op, plen, 3);
7548 
7549         case 16:
7550           if (dest != src + 2)
7551             avr_asm_len ("mov %A0,%C1", op, plen, 1);
7552 
7553           return avr_asm_len ("clr %B0"  CR_TAB
7554                               "clr %C0", op, plen, 2);
7555 
7556         default:
7557           if (INTVAL (op[2]) < 24)
7558             break;
7559 
7560           /* fall through */
7561 
7562         case 23:
7563           return avr_asm_len ("clr %A0"    CR_TAB
7564                               "sbrc %C0,7" CR_TAB
7565                               "inc %A0"    CR_TAB
7566                               "clr %B0"    CR_TAB
7567                               "clr %C0", op, plen, 5);
7568         } /* switch */
7569     }
7570 
7571   out_shift_with_cnt ("lsr %C0" CR_TAB
7572                       "ror %B0" CR_TAB
7573                       "ror %A0", insn, op, plen, 3);
7574   return "";
7575 }
7576 
7577 
7578 /* 32-bit logic shift right ((unsigned int)x >> i) */
7579 
7580 const char *
lshrsi3_out(rtx_insn * insn,rtx operands[],int * len)7581 lshrsi3_out (rtx_insn *insn, rtx operands[], int *len)
7582 {
7583   if (CONST_INT_P (operands[2]))
7584     {
7585       int k;
7586       int *t = len;
7587 
7588       if (!len)
7589 	len = &k;
7590 
7591       switch (INTVAL (operands[2]))
7592 	{
7593 	default:
7594 	  if (INTVAL (operands[2]) < 32)
7595 	    break;
7596 
7597 	  if (AVR_HAVE_MOVW)
7598 	    return *len = 3, ("clr %D0" CR_TAB
7599 			      "clr %C0" CR_TAB
7600 			      "movw %A0,%C0");
7601 	  *len = 4;
7602 	  return ("clr %D0" CR_TAB
7603 		  "clr %C0" CR_TAB
7604 		  "clr %B0" CR_TAB
7605 		  "clr %A0");
7606 
7607 	case 8:
7608 	  {
7609 	    int reg0 = true_regnum (operands[0]);
7610 	    int reg1 = true_regnum (operands[1]);
7611 	    *len = 4;
7612 	    if (reg0 <= reg1)
7613 	      return ("mov %A0,%B1" CR_TAB
7614 		      "mov %B0,%C1" CR_TAB
7615 		      "mov %C0,%D1" CR_TAB
7616 		      "clr %D0");
7617 	    else
7618 	      return ("clr %D0"     CR_TAB
7619 		      "mov %C0,%D1" CR_TAB
7620 		      "mov %B0,%C1" CR_TAB
7621 		      "mov %A0,%B1");
7622 	  }
7623 
7624 	case 16:
7625 	  {
7626 	    int reg0 = true_regnum (operands[0]);
7627 	    int reg1 = true_regnum (operands[1]);
7628 
7629 	    if (reg0 == reg1 + 2)
7630 	      return *len = 2, ("clr %C0"     CR_TAB
7631 				"clr %D0");
7632 	    if (AVR_HAVE_MOVW)
7633 	      return *len = 3, ("movw %A0,%C1" CR_TAB
7634 				"clr %C0"      CR_TAB
7635 				"clr %D0");
7636 	    else
7637 	      return *len = 4, ("mov %B0,%D1" CR_TAB
7638 				"mov %A0,%C1" CR_TAB
7639 				"clr %C0"     CR_TAB
7640 				"clr %D0");
7641 	  }
7642 
7643 	case 24:
7644 	  return *len = 4, ("mov %A0,%D1" CR_TAB
7645 			    "clr %B0"     CR_TAB
7646 			    "clr %C0"     CR_TAB
7647 			    "clr %D0");
7648 
7649 	case 31:
7650 	  *len = 6;
7651 	  return ("clr %A0"    CR_TAB
7652 		  "sbrc %D0,7" CR_TAB
7653 		  "inc %A0"    CR_TAB
7654 		  "clr %B0"    CR_TAB
7655 		  "clr %C0"    CR_TAB
7656 		  "clr %D0");
7657 	}
7658       len = t;
7659     }
7660   out_shift_with_cnt ("lsr %D0" CR_TAB
7661                       "ror %C0" CR_TAB
7662                       "ror %B0" CR_TAB
7663                       "ror %A0", insn, operands, len, 4);
7664   return "";
7665 }
7666 
7667 
7668 /* Output addition of register XOP[0] and compile time constant XOP[2].
7669    CODE == PLUS:  perform addition by using ADD instructions or
7670    CODE == MINUS: perform addition by using SUB instructions:
7671 
7672       XOP[0] = XOP[0] + XOP[2]
7673 
7674    Or perform addition/subtraction with register XOP[2] depending on CODE:
7675 
7676       XOP[0] = XOP[0] +/- XOP[2]
7677 
7678    If PLEN == NULL, print assembler instructions to perform the operation;
7679    otherwise, set *PLEN to the length of the instruction sequence (in words)
7680    printed with PLEN == NULL.  XOP[3] is an 8-bit scratch register or NULL_RTX.
7681    Set *PCC to effect on cc0 according to respective CC_* insn attribute.
7682 
7683    CODE_SAT == UNKNOWN: Perform ordinary, non-saturating operation.
7684    CODE_SAT != UNKNOWN: Perform operation and saturate according to CODE_SAT.
7685    If  CODE_SAT != UNKNOWN  then SIGN contains the sign of the summand resp.
7686    the subtrahend in the original insn, provided it is a compile time constant.
7687    In all other cases, SIGN is 0.
7688 
7689    If OUT_LABEL is true, print the final 0: label which is needed for
7690    saturated addition / subtraction.  The only case where OUT_LABEL = false
7691    is useful is for saturated addition / subtraction performed during
7692    fixed-point rounding, cf. `avr_out_round'.  */
7693 
7694 static void
avr_out_plus_1(rtx * xop,int * plen,enum rtx_code code,int * pcc,enum rtx_code code_sat,int sign,bool out_label)7695 avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc,
7696                 enum rtx_code code_sat, int sign, bool out_label)
7697 {
7698   /* MODE of the operation.  */
7699   machine_mode mode = GET_MODE (xop[0]);
7700 
7701   /* INT_MODE of the same size.  */
7702   scalar_int_mode imode = int_mode_for_mode (mode).require ();
7703 
7704   /* Number of bytes to operate on.  */
7705   int n_bytes = GET_MODE_SIZE (mode);
7706 
7707   /* Value (0..0xff) held in clobber register op[3] or -1 if unknown.  */
7708   int clobber_val = -1;
7709 
7710   /* op[0]: 8-bit destination register
7711      op[1]: 8-bit const int
7712      op[2]: 8-bit scratch register */
7713   rtx op[3];
7714 
7715   /* Started the operation?  Before starting the operation we may skip
7716      adding 0.  This is no more true after the operation started because
7717      carry must be taken into account.  */
7718   bool started = false;
7719 
7720   /* Value to add.  There are two ways to add VAL: R += VAL and R -= -VAL.  */
7721   rtx xval = xop[2];
7722 
7723   /* Output a BRVC instruction.  Only needed with saturation.  */
7724   bool out_brvc = true;
7725 
7726   if (plen)
7727     *plen = 0;
7728 
7729   if (REG_P (xop[2]))
7730     {
7731       *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_CLOBBER;
7732 
7733       for (int i = 0; i < n_bytes; i++)
7734         {
7735           /* We operate byte-wise on the destination.  */
7736           op[0] = simplify_gen_subreg (QImode, xop[0], mode, i);
7737           op[1] = simplify_gen_subreg (QImode, xop[2], mode, i);
7738 
7739           if (i == 0)
7740             avr_asm_len (code == PLUS ? "add %0,%1" : "sub %0,%1",
7741                          op, plen, 1);
7742           else
7743             avr_asm_len (code == PLUS ? "adc %0,%1" : "sbc %0,%1",
7744                          op, plen, 1);
7745         }
7746 
7747       if (reg_overlap_mentioned_p (xop[0], xop[2]))
7748         {
7749           gcc_assert (REGNO (xop[0]) == REGNO (xop[2]));
7750 
7751           if (MINUS == code)
7752             return;
7753         }
7754 
7755       goto saturate;
7756     }
7757 
7758   /* Except in the case of ADIW with 16-bit register (see below)
7759      addition does not set cc0 in a usable way.  */
7760 
7761   *pcc = (MINUS == code) ? CC_SET_CZN : CC_CLOBBER;
7762 
7763   if (CONST_FIXED_P (xval))
7764     xval = avr_to_int_mode (xval);
7765 
7766   /* Adding/Subtracting zero is a no-op.  */
7767 
7768   if (xval == const0_rtx)
7769     {
7770       *pcc = CC_NONE;
7771       return;
7772     }
7773 
7774   if (MINUS == code)
7775     xval = simplify_unary_operation (NEG, imode, xval, imode);
7776 
7777   op[2] = xop[3];
7778 
7779   if (SS_PLUS == code_sat && MINUS == code
7780       && sign < 0
7781       && 0x80 == (INTVAL (simplify_gen_subreg (QImode, xval, imode, n_bytes-1))
7782                   & GET_MODE_MASK (QImode)))
7783     {
7784       /* We compute x + 0x80 by means of SUB instructions.  We negated the
7785          constant subtrahend above and are left with  x - (-128)  so that we
7786          need something like SUBI r,128 which does not exist because SUBI sets
7787          V according to the sign of the subtrahend.  Notice the only case
7788          where this must be done is when NEG overflowed in case [2s] because
7789          the V computation needs the right sign of the subtrahend.  */
7790 
7791       rtx msb = simplify_gen_subreg (QImode, xop[0], mode, n_bytes - 1);
7792 
7793       avr_asm_len ("subi %0,128" CR_TAB
7794                    "brmi 0f", &msb, plen, 2);
7795       out_brvc = false;
7796 
7797       goto saturate;
7798     }
7799 
7800   for (int i = 0; i < n_bytes; i++)
7801     {
7802       /* We operate byte-wise on the destination.  */
7803       rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
7804       rtx xval8 = simplify_gen_subreg (QImode, xval, imode, i);
7805 
7806       /* 8-bit value to operate with this byte. */
7807       unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
7808 
7809       /* Registers R16..R31 can operate with immediate.  */
7810       bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
7811 
7812       op[0] = reg8;
7813       op[1] = gen_int_mode (val8, QImode);
7814 
7815       /* To get usable cc0 no low-bytes must have been skipped.  */
7816 
7817       if (i && !started)
7818         *pcc = CC_CLOBBER;
7819 
7820       if (!started
7821           && i % 2 == 0
7822           && i + 2 <= n_bytes
7823           && test_hard_reg_class (ADDW_REGS, reg8))
7824         {
7825           rtx xval16 = simplify_gen_subreg (HImode, xval, imode, i);
7826           unsigned int val16 = UINTVAL (xval16) & GET_MODE_MASK (HImode);
7827 
7828           /* Registers R24, X, Y, Z can use ADIW/SBIW with constants < 64
7829              i.e. operate word-wise.  */
7830 
7831           if (val16 < 64)
7832             {
7833               if (val16 != 0)
7834                 {
7835                   started = true;
7836                   avr_asm_len (code == PLUS ? "adiw %0,%1" : "sbiw %0,%1",
7837                                op, plen, 1);
7838 
7839                   if (n_bytes == 2 && PLUS == code)
7840                     *pcc = CC_SET_CZN;
7841                 }
7842 
7843               i++;
7844               continue;
7845             }
7846         }
7847 
7848       if (val8 == 0)
7849         {
7850           if (started)
7851             avr_asm_len (code == PLUS
7852                          ? "adc %0,__zero_reg__" : "sbc %0,__zero_reg__",
7853                          op, plen, 1);
7854           continue;
7855         }
7856       else if ((val8 == 1 || val8 == 0xff)
7857                && UNKNOWN == code_sat
7858                && !started
7859                && i == n_bytes - 1)
7860         {
7861           avr_asm_len ((code == PLUS) ^ (val8 == 1) ? "dec %0" : "inc %0",
7862                        op, plen, 1);
7863           *pcc = CC_CLOBBER;
7864           break;
7865         }
7866 
7867       switch (code)
7868         {
7869         case PLUS:
7870 
7871           gcc_assert (plen != NULL || (op[2] && REG_P (op[2])));
7872 
7873           if (plen != NULL && UNKNOWN != code_sat)
7874             {
7875               /* This belongs to the x + 0x80 corner case.  The code with
7876                  ADD instruction is not smaller, thus make this case
7877                  expensive so that the caller won't pick it.  */
7878 
7879               *plen += 10;
7880               break;
7881             }
7882 
7883           if (clobber_val != (int) val8)
7884             avr_asm_len ("ldi %2,%1", op, plen, 1);
7885           clobber_val = (int) val8;
7886 
7887           avr_asm_len (started ? "adc %0,%2" : "add %0,%2", op, plen, 1);
7888 
7889           break; /* PLUS */
7890 
7891         case MINUS:
7892 
7893           if (ld_reg_p)
7894             avr_asm_len (started ? "sbci %0,%1" : "subi %0,%1", op, plen, 1);
7895           else
7896             {
7897               gcc_assert (plen != NULL || REG_P (op[2]));
7898 
7899               if (clobber_val != (int) val8)
7900                 avr_asm_len ("ldi %2,%1", op, plen, 1);
7901               clobber_val = (int) val8;
7902 
7903               avr_asm_len (started ? "sbc %0,%2" : "sub %0,%2", op, plen, 1);
7904             }
7905 
7906           break; /* MINUS */
7907 
7908         default:
7909           /* Unknown code */
7910           gcc_unreachable();
7911         }
7912 
7913       started = true;
7914 
7915     } /* for all sub-bytes */
7916 
7917  saturate:
7918 
7919   if (UNKNOWN == code_sat)
7920     return;
7921 
7922   *pcc = (int) CC_CLOBBER;
7923 
7924   /* Vanilla addition/subtraction is done.  We are left with saturation.
7925 
7926      We have to compute  A = A <op> B  where  A  is a register and
7927      B is a register or a non-zero compile time constant CONST.
7928      A is register class "r" if unsigned && B is REG.  Otherwise, A is in "d".
7929      B stands for the original operand $2 in INSN.  In the case of B = CONST,
7930      SIGN in { -1, 1 } is the sign of B.  Otherwise, SIGN is 0.
7931 
7932      CODE is the instruction flavor we use in the asm sequence to perform <op>.
7933 
7934 
7935      unsigned
7936      operation        |  code |  sat if  |    b is      | sat value |  case
7937      -----------------+-------+----------+--------------+-----------+-------
7938      +  as  a + b     |  add  |  C == 1  |  const, reg  | u+ = 0xff |  [1u]
7939      +  as  a - (-b)  |  sub  |  C == 0  |  const       | u+ = 0xff |  [2u]
7940      -  as  a - b     |  sub  |  C == 1  |  const, reg  | u- = 0    |  [3u]
7941      -  as  a + (-b)  |  add  |  C == 0  |  const       | u- = 0    |  [4u]
7942 
7943 
7944      signed
7945      operation        |  code |  sat if  |    b is      | sat value |  case
7946      -----------------+-------+----------+--------------+-----------+-------
7947      +  as  a + b     |  add  |  V == 1  |  const, reg  | s+        |  [1s]
7948      +  as  a - (-b)  |  sub  |  V == 1  |  const       | s+        |  [2s]
7949      -  as  a - b     |  sub  |  V == 1  |  const, reg  | s-        |  [3s]
7950      -  as  a + (-b)  |  add  |  V == 1  |  const       | s-        |  [4s]
7951 
7952      s+  =  b < 0  ?  -0x80 :  0x7f
7953      s-  =  b < 0  ?   0x7f : -0x80
7954 
7955      The cases a - b actually perform  a - (-(-b))  if B is CONST.
7956   */
7957 
7958   op[0] = simplify_gen_subreg (QImode, xop[0], mode, n_bytes-1);
7959   op[1] = n_bytes > 1
7960     ? simplify_gen_subreg (QImode, xop[0], mode, n_bytes-2)
7961     : NULL_RTX;
7962 
7963   bool need_copy = true;
7964   int len_call = 1 + AVR_HAVE_JMP_CALL;
7965 
7966   switch (code_sat)
7967     {
7968     default:
7969       gcc_unreachable();
7970 
7971     case SS_PLUS:
7972     case SS_MINUS:
7973 
7974       if (out_brvc)
7975         avr_asm_len ("brvc 0f", op, plen, 1);
7976 
7977       if (reg_overlap_mentioned_p (xop[0], xop[2]))
7978         {
7979           /* [1s,reg] */
7980 
7981           if (n_bytes == 1)
7982             avr_asm_len ("ldi %0,0x7f" CR_TAB
7983                          "adc %0,__zero_reg__", op, plen, 2);
7984           else
7985             avr_asm_len ("ldi %0,0x7f" CR_TAB
7986                          "ldi %1,0xff" CR_TAB
7987                          "adc %1,__zero_reg__" CR_TAB
7988                          "adc %0,__zero_reg__", op, plen, 4);
7989         }
7990       else if (sign == 0 && PLUS == code)
7991         {
7992           /* [1s,reg] */
7993 
7994           op[2] = simplify_gen_subreg (QImode, xop[2], mode, n_bytes-1);
7995 
7996           if (n_bytes == 1)
7997             avr_asm_len ("ldi %0,0x80" CR_TAB
7998                          "sbrs %2,7"   CR_TAB
7999                          "dec %0", op, plen, 3);
8000           else
8001             avr_asm_len ("ldi %0,0x80" CR_TAB
8002                          "cp %2,%0"    CR_TAB
8003                          "sbc %1,%1"   CR_TAB
8004                          "sbci %0,0", op, plen, 4);
8005         }
8006       else if (sign == 0 && MINUS == code)
8007         {
8008           /* [3s,reg] */
8009 
8010           op[2] = simplify_gen_subreg (QImode, xop[2], mode, n_bytes-1);
8011 
8012           if (n_bytes == 1)
8013             avr_asm_len ("ldi %0,0x7f" CR_TAB
8014                          "sbrs %2,7"   CR_TAB
8015                          "inc %0", op, plen, 3);
8016           else
8017             avr_asm_len ("ldi %0,0x7f" CR_TAB
8018                          "cp %0,%2"    CR_TAB
8019                          "sbc %1,%1"   CR_TAB
8020                          "sbci %0,-1", op, plen, 4);
8021         }
8022       else if ((sign < 0) ^ (SS_MINUS == code_sat))
8023         {
8024           /* [1s,const,B < 0] [2s,B < 0] */
8025           /* [3s,const,B > 0] [4s,B > 0] */
8026 
8027           if (n_bytes == 8)
8028             {
8029               avr_asm_len ("%~call __clr_8", op, plen, len_call);
8030               need_copy = false;
8031             }
8032 
8033           avr_asm_len ("ldi %0,0x80", op, plen, 1);
8034           if (n_bytes > 1 && need_copy)
8035             avr_asm_len ("clr %1", op, plen, 1);
8036         }
8037       else if ((sign > 0) ^ (SS_MINUS == code_sat))
8038         {
8039           /* [1s,const,B > 0] [2s,B > 0] */
8040           /* [3s,const,B < 0] [4s,B < 0] */
8041 
8042           if (n_bytes == 8)
8043             {
8044               avr_asm_len ("sec" CR_TAB
8045                            "%~call __sbc_8", op, plen, 1 + len_call);
8046               need_copy = false;
8047             }
8048 
8049           avr_asm_len ("ldi %0,0x7f", op, plen, 1);
8050           if (n_bytes > 1 && need_copy)
8051             avr_asm_len ("ldi %1,0xff", op, plen, 1);
8052         }
8053       else
8054         gcc_unreachable();
8055 
8056       break;
8057 
8058     case US_PLUS:
8059       /* [1u] : [2u] */
8060 
8061       avr_asm_len (PLUS == code ? "brcc 0f" : "brcs 0f", op, plen, 1);
8062 
8063       if (n_bytes == 8)
8064         {
8065           if (MINUS == code)
8066             avr_asm_len ("sec", op, plen, 1);
8067           avr_asm_len ("%~call __sbc_8", op, plen, len_call);
8068 
8069           need_copy = false;
8070         }
8071       else
8072         {
8073           if (MINUS == code && !test_hard_reg_class (LD_REGS, op[0]))
8074             avr_asm_len ("sec" CR_TAB
8075                          "sbc %0,%0", op, plen, 2);
8076           else
8077             avr_asm_len (PLUS == code ? "sbc %0,%0" : "ldi %0,0xff",
8078                          op, plen, 1);
8079         }
8080       break; /* US_PLUS */
8081 
8082     case US_MINUS:
8083       /* [4u] : [3u] */
8084 
8085       avr_asm_len (PLUS == code ? "brcs 0f" : "brcc 0f", op, plen, 1);
8086 
8087       if (n_bytes == 8)
8088         {
8089           avr_asm_len ("%~call __clr_8", op, plen, len_call);
8090           need_copy = false;
8091         }
8092       else
8093         avr_asm_len ("clr %0", op, plen, 1);
8094 
8095       break;
8096     }
8097 
8098   /* We set the MSB in the unsigned case and the 2 MSBs in the signed case.
8099      Now copy the right value to the LSBs.  */
8100 
8101   if (need_copy && n_bytes > 1)
8102     {
8103       if (US_MINUS == code_sat || US_PLUS == code_sat)
8104         {
8105           avr_asm_len ("mov %1,%0", op, plen, 1);
8106 
8107           if (n_bytes > 2)
8108             {
8109               op[0] = xop[0];
8110               if (AVR_HAVE_MOVW)
8111                 avr_asm_len ("movw %0,%1", op, plen, 1);
8112               else
8113                 avr_asm_len ("mov %A0,%1" CR_TAB
8114                              "mov %B0,%1", op, plen, 2);
8115             }
8116         }
8117       else if (n_bytes > 2)
8118         {
8119           op[0] = xop[0];
8120           avr_asm_len ("mov %A0,%1" CR_TAB
8121                        "mov %B0,%1", op, plen, 2);
8122         }
8123     }
8124 
8125   if (need_copy && n_bytes == 8)
8126     {
8127       if (AVR_HAVE_MOVW)
8128         avr_asm_len ("movw %r0+2,%0" CR_TAB
8129                      "movw %r0+4,%0", xop, plen, 2);
8130       else
8131         avr_asm_len ("mov %r0+2,%0" CR_TAB
8132                      "mov %r0+3,%0" CR_TAB
8133                      "mov %r0+4,%0" CR_TAB
8134                      "mov %r0+5,%0", xop, plen, 4);
8135     }
8136 
8137   if (out_label)
8138     avr_asm_len ("0:", op, plen, 0);
8139 }
8140 
8141 
8142 /* Output addition/subtraction of register XOP[0] and a constant XOP[2] that
8143    is ont a compile-time constant:
8144 
8145       XOP[0] = XOP[0] +/- XOP[2]
8146 
8147    This is a helper for the function below.  The only insns that need this
8148    are additions/subtraction for pointer modes, i.e. HImode and PSImode.  */
8149 
8150 static const char*
avr_out_plus_symbol(rtx * xop,enum rtx_code code,int * plen,int * pcc)8151 avr_out_plus_symbol (rtx *xop, enum rtx_code code, int *plen, int *pcc)
8152 {
8153   machine_mode mode = GET_MODE (xop[0]);
8154 
8155   /* Only pointer modes want to add symbols.  */
8156 
8157   gcc_assert (mode == HImode || mode == PSImode);
8158 
8159   *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_SET_N;
8160 
8161   avr_asm_len (PLUS == code
8162                ? "subi %A0,lo8(-(%2))" CR_TAB "sbci %B0,hi8(-(%2))"
8163                : "subi %A0,lo8(%2)"    CR_TAB "sbci %B0,hi8(%2)",
8164                xop, plen, -2);
8165 
8166   if (PSImode == mode)
8167     avr_asm_len (PLUS == code
8168                  ? "sbci %C0,hlo8(-(%2))"
8169                  : "sbci %C0,hlo8(%2)", xop, plen, 1);
8170   return "";
8171 }
8172 
8173 
8174 /* Prepare operands of addition/subtraction to be used with avr_out_plus_1.
8175 
8176    INSN is a single_set insn or an insn pattern with a binary operation as
8177    SET_SRC that is one of: PLUS, SS_PLUS, US_PLUS, MINUS, SS_MINUS, US_MINUS.
8178 
8179    XOP are the operands of INSN.  In the case of 64-bit operations with
8180    constant XOP[] has just one element:  The summand/subtrahend in XOP[0].
8181    The non-saturating insns up to 32 bits may or may not supply a "d" class
8182    scratch as XOP[3].
8183 
8184    If PLEN == NULL output the instructions.
8185    If PLEN != NULL set *PLEN to the length of the sequence in words.
8186 
8187    PCC is a pointer to store the instructions' effect on cc0.
8188    PCC may be NULL.
8189 
8190    PLEN and PCC default to NULL.
8191 
8192    OUT_LABEL defaults to TRUE.  For a description, see AVR_OUT_PLUS_1.
8193 
8194    Return ""  */
8195 
8196 const char*
avr_out_plus(rtx insn,rtx * xop,int * plen,int * pcc,bool out_label)8197 avr_out_plus (rtx insn, rtx *xop, int *plen, int *pcc, bool out_label)
8198 {
8199   int cc_plus, cc_minus, cc_dummy;
8200   int len_plus, len_minus;
8201   rtx op[4];
8202   rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
8203   rtx xdest = SET_DEST (xpattern);
8204   machine_mode mode = GET_MODE (xdest);
8205   scalar_int_mode imode = int_mode_for_mode (mode).require ();
8206   int n_bytes = GET_MODE_SIZE (mode);
8207   enum rtx_code code_sat = GET_CODE (SET_SRC (xpattern));
8208   enum rtx_code code
8209     = (PLUS == code_sat || SS_PLUS == code_sat || US_PLUS == code_sat
8210        ? PLUS : MINUS);
8211 
8212   if (!pcc)
8213     pcc = &cc_dummy;
8214 
8215   /* PLUS and MINUS don't saturate:  Use modular wrap-around.  */
8216 
8217   if (PLUS == code_sat || MINUS == code_sat)
8218     code_sat = UNKNOWN;
8219 
8220   if (n_bytes <= 4 && REG_P (xop[2]))
8221     {
8222       avr_out_plus_1 (xop, plen, code, pcc, code_sat, 0, out_label);
8223       return "";
8224     }
8225 
8226   if (n_bytes == 8)
8227     {
8228       op[0] = gen_rtx_REG (DImode, ACC_A);
8229       op[1] = gen_rtx_REG (DImode, ACC_A);
8230       op[2] = avr_to_int_mode (xop[0]);
8231     }
8232   else
8233     {
8234       if (!REG_P (xop[2])
8235           && !CONST_INT_P (xop[2])
8236           && !CONST_FIXED_P (xop[2]))
8237         {
8238           return avr_out_plus_symbol (xop, code, plen, pcc);
8239         }
8240 
8241       op[0] = avr_to_int_mode (xop[0]);
8242       op[1] = avr_to_int_mode (xop[1]);
8243       op[2] = avr_to_int_mode (xop[2]);
8244     }
8245 
8246   /* Saturations and 64-bit operations don't have a clobber operand.
8247      For the other cases, the caller will provide a proper XOP[3].  */
8248 
8249   xpattern = INSN_P (insn) ? PATTERN (insn) : insn;
8250   op[3] = PARALLEL == GET_CODE (xpattern) ? xop[3] : NULL_RTX;
8251 
8252   /* Saturation will need the sign of the original operand.  */
8253 
8254   rtx xmsb = simplify_gen_subreg (QImode, op[2], imode, n_bytes-1);
8255   int sign = INTVAL (xmsb) < 0 ? -1 : 1;
8256 
8257   /* If we subtract and the subtrahend is a constant, then negate it
8258      so that avr_out_plus_1 can be used.  */
8259 
8260   if (MINUS == code)
8261     op[2] = simplify_unary_operation (NEG, imode, op[2], imode);
8262 
8263   /* Work out the shortest sequence.  */
8264 
8265   avr_out_plus_1 (op, &len_minus, MINUS, &cc_minus, code_sat, sign, out_label);
8266   avr_out_plus_1 (op, &len_plus, PLUS, &cc_plus, code_sat, sign, out_label);
8267 
8268   if (plen)
8269     {
8270       *plen = (len_minus <= len_plus) ? len_minus : len_plus;
8271       *pcc  = (len_minus <= len_plus) ? cc_minus : cc_plus;
8272     }
8273   else if (len_minus <= len_plus)
8274     avr_out_plus_1 (op, NULL, MINUS, pcc, code_sat, sign, out_label);
8275   else
8276     avr_out_plus_1 (op, NULL, PLUS, pcc, code_sat, sign, out_label);
8277 
8278   return "";
8279 }
8280 
8281 
8282 /* Output bit operation (IOR, AND, XOR) with register XOP[0] and compile
8283    time constant XOP[2]:
8284 
8285       XOP[0] = XOP[0] <op> XOP[2]
8286 
8287    and return "".  If PLEN == NULL, print assembler instructions to perform the
8288    operation; otherwise, set *PLEN to the length of the instruction sequence
8289    (in words) printed with PLEN == NULL.  XOP[3] is either an 8-bit clobber
8290    register or SCRATCH if no clobber register is needed for the operation.
8291    INSN is an INSN_P or a pattern of an insn.  */
8292 
8293 const char*
avr_out_bitop(rtx insn,rtx * xop,int * plen)8294 avr_out_bitop (rtx insn, rtx *xop, int *plen)
8295 {
8296   /* CODE and MODE of the operation.  */
8297   rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
8298   enum rtx_code code = GET_CODE (SET_SRC (xpattern));
8299   machine_mode mode = GET_MODE (xop[0]);
8300 
8301   /* Number of bytes to operate on.  */
8302   int n_bytes = GET_MODE_SIZE (mode);
8303 
8304   /* Value of T-flag (0 or 1) or -1 if unknow.  */
8305   int set_t = -1;
8306 
8307   /* Value (0..0xff) held in clobber register op[3] or -1 if unknown.  */
8308   int clobber_val = -1;
8309 
8310   /* op[0]: 8-bit destination register
8311      op[1]: 8-bit const int
8312      op[2]: 8-bit clobber register, SCRATCH or NULL_RTX.
8313      op[3]: 8-bit register containing 0xff or NULL_RTX  */
8314   rtx op[4];
8315 
8316   op[2] = QImode == mode ? NULL_RTX : xop[3];
8317   op[3] = NULL_RTX;
8318 
8319   if (plen)
8320     *plen = 0;
8321 
8322   for (int i = 0; i < n_bytes; i++)
8323     {
8324       /* We operate byte-wise on the destination.  */
8325       rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
8326       rtx xval8 = simplify_gen_subreg (QImode, xop[2], mode, i);
8327 
8328       /* 8-bit value to operate with this byte. */
8329       unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
8330 
8331       /* Number of bits set in the current byte of the constant.  */
8332       int pop8 = popcount_hwi (val8);
8333 
8334       /* Registers R16..R31 can operate with immediate.  */
8335       bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
8336 
8337       op[0] = reg8;
8338       op[1] = GEN_INT (val8);
8339 
8340       switch (code)
8341         {
8342         case IOR:
8343 
8344 	  if (pop8 == 0)
8345             continue;
8346           else if (ld_reg_p)
8347             avr_asm_len ("ori %0,%1", op, plen, 1);
8348 	  else if (pop8 == 1)
8349             {
8350               if (set_t != 1)
8351                 avr_asm_len ("set", op, plen, 1);
8352               set_t = 1;
8353 
8354               op[1] = GEN_INT (exact_log2 (val8));
8355               avr_asm_len ("bld %0,%1", op, plen, 1);
8356             }
8357 	  else if (pop8 == 8)
8358             {
8359               if (op[3] != NULL_RTX)
8360                 avr_asm_len ("mov %0,%3", op, plen, 1);
8361               else
8362                 avr_asm_len ("clr %0" CR_TAB
8363                              "dec %0", op, plen, 2);
8364 
8365               op[3] = op[0];
8366             }
8367           else
8368             {
8369               if (clobber_val != (int) val8)
8370                 avr_asm_len ("ldi %2,%1", op, plen, 1);
8371               clobber_val = (int) val8;
8372 
8373               avr_asm_len ("or %0,%2", op, plen, 1);
8374             }
8375 
8376           continue; /* IOR */
8377 
8378         case AND:
8379 
8380 	  if (pop8 == 8)
8381             continue;
8382 	  else if (pop8 == 0)
8383             avr_asm_len ("clr %0", op, plen, 1);
8384           else if (ld_reg_p)
8385             avr_asm_len ("andi %0,%1", op, plen, 1);
8386 	  else if (pop8 == 7)
8387             {
8388               if (set_t != 0)
8389                 avr_asm_len ("clt", op, plen, 1);
8390               set_t = 0;
8391 
8392               op[1] = GEN_INT (exact_log2 (GET_MODE_MASK (QImode) & ~val8));
8393               avr_asm_len ("bld %0,%1", op, plen, 1);
8394             }
8395           else
8396             {
8397               if (clobber_val != (int) val8)
8398                 avr_asm_len ("ldi %2,%1", op, plen, 1);
8399               clobber_val = (int) val8;
8400 
8401               avr_asm_len ("and %0,%2", op, plen, 1);
8402             }
8403 
8404           continue; /* AND */
8405 
8406         case XOR:
8407 
8408 	  if (pop8 == 0)
8409             continue;
8410 	  else if (pop8 == 8)
8411             avr_asm_len ("com %0", op, plen, 1);
8412           else if (ld_reg_p && val8 == (1 << 7))
8413             avr_asm_len ("subi %0,%1", op, plen, 1);
8414           else
8415             {
8416               if (clobber_val != (int) val8)
8417                 avr_asm_len ("ldi %2,%1", op, plen, 1);
8418               clobber_val = (int) val8;
8419 
8420               avr_asm_len ("eor %0,%2", op, plen, 1);
8421             }
8422 
8423           continue; /* XOR */
8424 
8425         default:
8426           /* Unknown rtx_code */
8427           gcc_unreachable();
8428         }
8429     } /* for all sub-bytes */
8430 
8431   return "";
8432 }
8433 
8434 
8435 /* Output sign extension from XOP[1] to XOP[0] and return "".
8436    If PLEN == NULL, print assembler instructions to perform the operation;
8437    otherwise, set *PLEN to the length of the instruction sequence (in words)
8438    as printed with PLEN == NULL.  */
8439 
8440 const char*
avr_out_sign_extend(rtx_insn * insn,rtx * xop,int * plen)8441 avr_out_sign_extend (rtx_insn *insn, rtx *xop, int *plen)
8442 {
8443   // Size in bytes of source resp. destination operand.
8444   unsigned n_src = GET_MODE_SIZE (GET_MODE (xop[1]));
8445   unsigned n_dest = GET_MODE_SIZE (GET_MODE (xop[0]));
8446   rtx r_msb = all_regs_rtx[REGNO (xop[1]) + n_src - 1];
8447 
8448   if (plen)
8449     *plen = 0;
8450 
8451   // Copy destination to source
8452 
8453   if (REGNO (xop[0]) != REGNO (xop[1]))
8454     {
8455       gcc_assert (n_src <= 2);
8456 
8457       if (n_src == 2)
8458         avr_asm_len (AVR_HAVE_MOVW
8459                      ? "movw %0,%1"
8460                      : "mov %B0,%B1", xop, plen, 1);
8461       if (n_src == 1 || !AVR_HAVE_MOVW)
8462         avr_asm_len ("mov %A0,%A1", xop, plen, 1);
8463     }
8464 
8465   // Set Carry to the sign bit MSB.7...
8466 
8467   if (REGNO (xop[0]) == REGNO (xop[1])
8468       || !reg_unused_after (insn, r_msb))
8469     {
8470       avr_asm_len ("mov __tmp_reg__,%0", &r_msb, plen, 1);
8471       r_msb = tmp_reg_rtx;
8472     }
8473 
8474   avr_asm_len ("lsl %0", &r_msb, plen, 1);
8475 
8476   // ...and propagate it to all the new sign bits
8477 
8478   for (unsigned n = n_src; n < n_dest; n++)
8479     avr_asm_len ("sbc %0,%0", &all_regs_rtx[REGNO (xop[0]) + n], plen, 1);
8480 
8481   return "";
8482 }
8483 
8484 
8485 /* PLEN == NULL: Output code to add CONST_INT OP[0] to SP.
8486    PLEN != NULL: Set *PLEN to the length of that sequence.
8487    Return "".  */
8488 
8489 const char*
avr_out_addto_sp(rtx * op,int * plen)8490 avr_out_addto_sp (rtx *op, int *plen)
8491 {
8492   int pc_len = AVR_2_BYTE_PC ? 2 : 3;
8493   int addend = INTVAL (op[0]);
8494 
8495   if (plen)
8496     *plen = 0;
8497 
8498   if (addend < 0)
8499     {
8500       if (flag_verbose_asm || flag_print_asm_name)
8501         avr_asm_len (ASM_COMMENT_START "SP -= %n0", op, plen, 0);
8502 
8503       while (addend <= -pc_len)
8504         {
8505           addend += pc_len;
8506           avr_asm_len ("rcall .", op, plen, 1);
8507         }
8508 
8509       while (addend++ < 0)
8510         avr_asm_len ("push __tmp_reg__", op, plen, 1);
8511     }
8512   else if (addend > 0)
8513     {
8514       if (flag_verbose_asm || flag_print_asm_name)
8515         avr_asm_len (ASM_COMMENT_START "SP += %0", op, plen, 0);
8516 
8517       while (addend-- > 0)
8518         avr_asm_len ("pop __tmp_reg__", op, plen, 1);
8519     }
8520 
8521   return "";
8522 }
8523 
8524 
8525 /* Output instructions to insert an inverted bit into OPERANDS[0]:
8526    $0.$1 = ~$2.$3      if XBITNO = NULL
8527    $0.$1 = ~$2.XBITNO  if XBITNO != NULL.
8528    If PLEN = NULL then output the respective instruction sequence which
8529    is a combination of BST / BLD and some instruction(s) to invert the bit.
8530    If PLEN != NULL then store the length of the sequence (in words) in *PLEN.
8531    Return "".  */
8532 
8533 const char*
avr_out_insert_notbit(rtx_insn * insn,rtx operands[],rtx xbitno,int * plen)8534 avr_out_insert_notbit (rtx_insn *insn, rtx operands[], rtx xbitno, int *plen)
8535 {
8536   rtx op[4] = { operands[0], operands[1], operands[2],
8537                 xbitno == NULL_RTX ? operands [3] : xbitno };
8538 
8539   if (INTVAL (op[1]) == 7
8540       && test_hard_reg_class (LD_REGS, op[0]))
8541     {
8542       /* If the inserted bit number is 7 and we have a d-reg, then invert
8543          the bit after the insertion by means of SUBI *,0x80.  */
8544 
8545       if (INTVAL (op[3]) == 7
8546           && REGNO (op[0]) == REGNO (op[2]))
8547         {
8548           avr_asm_len ("subi %0,0x80", op, plen, -1);
8549         }
8550       else
8551         {
8552           avr_asm_len ("bst %2,%3" CR_TAB
8553                        "bld %0,%1" CR_TAB
8554                        "subi %0,0x80", op, plen, -3);
8555         }
8556     }
8557   else if (test_hard_reg_class (LD_REGS, op[0])
8558            && (INTVAL (op[1]) != INTVAL (op[3])
8559                || !reg_overlap_mentioned_p (op[0], op[2])))
8560     {
8561       /* If the destination bit is in a d-reg we can jump depending
8562          on the source bit and use ANDI / ORI.  This just applies if we
8563          have not an early-clobber situation with the bit.  */
8564 
8565       avr_asm_len ("andi %0,~(1<<%1)" CR_TAB
8566                    "sbrs %2,%3"       CR_TAB
8567                    "ori %0,1<<%1", op, plen, -3);
8568     }
8569   else
8570     {
8571       /* Otherwise, invert the bit by means of COM before we store it with
8572          BST and then undo the COM if needed.  */
8573 
8574       avr_asm_len ("com %2" CR_TAB
8575                    "bst %2,%3", op, plen, -2);
8576 
8577       if (!reg_unused_after (insn, op[2])
8578           // A simple 'reg_unused_after' is not enough because that function
8579           // assumes that the destination register is overwritten completely
8580           // and hence is in order for our purpose.  This is not the case
8581           // with BLD which just changes one bit of the destination.
8582           || reg_overlap_mentioned_p (op[0], op[2]))
8583         {
8584           /* Undo the COM from above.  */
8585           avr_asm_len ("com %2", op, plen, 1);
8586         }
8587 
8588       avr_asm_len ("bld %0,%1", op, plen, 1);
8589     }
8590 
8591   return "";
8592 }
8593 
8594 
8595 /* Outputs instructions needed for fixed point type conversion.
8596    This includes converting between any fixed point type, as well
8597    as converting to any integer type.  Conversion between integer
8598    types is not supported.
8599 
8600    Converting signed fractional types requires a bit shift if converting
8601    to or from any unsigned fractional type because the decimal place is
8602    shifted by 1 bit.  When the destination is a signed fractional, the sign
8603    is stored in either the carry or T bit.  */
8604 
8605 const char*
avr_out_fract(rtx_insn * insn,rtx operands[],bool intsigned,int * plen)8606 avr_out_fract (rtx_insn *insn, rtx operands[], bool intsigned, int *plen)
8607 {
8608   rtx xop[6];
8609   RTX_CODE shift = UNKNOWN;
8610   bool sign_in_carry = false;
8611   bool msb_in_carry = false;
8612   bool lsb_in_tmp_reg = false;
8613   bool lsb_in_carry = false;
8614   bool frac_rounded = false;
8615   const char *code_ashift = "lsl %0";
8616 
8617 
8618 #define MAY_CLOBBER(RR)                                                 \
8619   /* Shorthand used below.  */                                          \
8620   ((sign_bytes                                                          \
8621     && IN_RANGE (RR, dest.regno_msb - sign_bytes + 1, dest.regno_msb))  \
8622    || (offset && IN_RANGE (RR, dest.regno, dest.regno_msb))		\
8623    || (reg_unused_after (insn, all_regs_rtx[RR])                        \
8624        && !IN_RANGE (RR, dest.regno, dest.regno_msb)))
8625 
8626   struct
8627   {
8628     /* bytes       : Length of operand in bytes.
8629        ibyte       : Length of integral part in bytes.
8630        fbyte, fbit : Length of fractional part in bytes, bits.  */
8631 
8632     bool sbit;
8633     unsigned fbit, bytes, ibyte, fbyte;
8634     unsigned regno, regno_msb;
8635   } dest, src, *val[2] = { &dest, &src };
8636 
8637   if (plen)
8638     *plen = 0;
8639 
8640   /* Step 0:  Determine information on source and destination operand we
8641      ======   will need in the remainder.  */
8642 
8643   for (size_t i = 0; i < ARRAY_SIZE (val); i++)
8644     {
8645       machine_mode mode;
8646 
8647       xop[i] = operands[i];
8648 
8649       mode = GET_MODE (xop[i]);
8650 
8651       val[i]->bytes = GET_MODE_SIZE (mode);
8652       val[i]->regno = REGNO (xop[i]);
8653       val[i]->regno_msb = REGNO (xop[i]) + val[i]->bytes - 1;
8654 
8655       if (SCALAR_INT_MODE_P (mode))
8656         {
8657           val[i]->sbit = intsigned;
8658           val[i]->fbit = 0;
8659         }
8660       else if (ALL_SCALAR_FIXED_POINT_MODE_P (mode))
8661         {
8662           val[i]->sbit = SIGNED_SCALAR_FIXED_POINT_MODE_P (mode);
8663           val[i]->fbit = GET_MODE_FBIT (mode);
8664         }
8665       else
8666         fatal_insn ("unsupported fixed-point conversion", insn);
8667 
8668       val[i]->fbyte = (1 + val[i]->fbit) / BITS_PER_UNIT;
8669       val[i]->ibyte = val[i]->bytes - val[i]->fbyte;
8670     }
8671 
8672   // Byte offset of the decimal point taking into account different place
8673   // of the decimal point in input and output and different register numbers
8674   // of input and output.
8675   int offset = dest.regno - src.regno + dest.fbyte - src.fbyte;
8676 
8677   // Number of destination bytes that will come from sign / zero extension.
8678   int sign_bytes = (dest.ibyte - src.ibyte) * (dest.ibyte > src.ibyte);
8679 
8680   // Number of bytes at the low end to be filled with zeros.
8681   int zero_bytes = (dest.fbyte - src.fbyte) * (dest.fbyte > src.fbyte);
8682 
8683   // Do we have a 16-Bit register that is cleared?
8684   rtx clrw = NULL_RTX;
8685 
8686   bool sign_extend = src.sbit && sign_bytes;
8687 
8688   if (dest.fbit % 8 == 0 && src.fbit % 8 == 7)
8689     shift = ASHIFT;
8690   else if (dest.fbit % 8 == 7 && src.fbit % 8 == 0)
8691     shift = ASHIFTRT;
8692   else if (dest.fbit % 8 == src.fbit % 8)
8693     shift = UNKNOWN;
8694   else
8695     gcc_unreachable();
8696 
8697   /* If we need to round the fraction part, we might need to save/round it
8698      before clobbering any of it in Step 1.  Also, we might want to do
8699      the rounding now to make use of LD_REGS.  */
8700   if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8701       && SCALAR_ACCUM_MODE_P (GET_MODE (xop[1]))
8702       && !TARGET_FRACT_CONV_TRUNC)
8703     {
8704       bool overlap
8705         = (src.regno <=
8706            (offset ? dest.regno_msb - sign_bytes : dest.regno + zero_bytes - 1)
8707            && dest.regno - offset -1 >= dest.regno);
8708       unsigned s0 = dest.regno - offset -1;
8709       bool use_src = true;
8710       unsigned sn;
8711       unsigned copied_msb = src.regno_msb;
8712       bool have_carry = false;
8713 
8714       if (src.ibyte > dest.ibyte)
8715         copied_msb -= src.ibyte - dest.ibyte;
8716 
8717       for (sn = s0; sn <= copied_msb; sn++)
8718         if (!IN_RANGE (sn, dest.regno, dest.regno_msb)
8719             && !reg_unused_after (insn, all_regs_rtx[sn]))
8720           use_src = false;
8721       if (use_src && TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], s0))
8722         {
8723           avr_asm_len ("tst %0" CR_TAB "brpl 0f",
8724                        &all_regs_rtx[src.regno_msb], plen, 2);
8725           sn = src.regno;
8726           if (sn < s0)
8727             {
8728               if (TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], sn))
8729                 avr_asm_len ("cpi %0,1", &all_regs_rtx[sn], plen, 1);
8730               else
8731                 avr_asm_len ("sec" CR_TAB
8732                              "cpc %0,__zero_reg__",
8733                              &all_regs_rtx[sn], plen, 2);
8734               have_carry = true;
8735             }
8736           while (++sn < s0)
8737             avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8738 
8739           avr_asm_len (have_carry ? "sbci %0,128" : "subi %0,129",
8740                        &all_regs_rtx[s0], plen, 1);
8741           for (sn = src.regno + src.fbyte; sn <= copied_msb; sn++)
8742             avr_asm_len ("sbci %0,255", &all_regs_rtx[sn], plen, 1);
8743           avr_asm_len ("\n0:", NULL, plen, 0);
8744           frac_rounded = true;
8745         }
8746       else if (use_src && overlap)
8747         {
8748           avr_asm_len ("clr __tmp_reg__" CR_TAB
8749                        "sbrc %1,0"       CR_TAB
8750                        "dec __tmp_reg__", xop, plen, 1);
8751           sn = src.regno;
8752           if (sn < s0)
8753             {
8754               avr_asm_len ("add %0,__tmp_reg__", &all_regs_rtx[sn], plen, 1);
8755               have_carry = true;
8756             }
8757 
8758           while (++sn < s0)
8759             avr_asm_len ("adc %0,__tmp_reg__", &all_regs_rtx[sn], plen, 1);
8760 
8761           if (have_carry)
8762             avr_asm_len ("clt"                CR_TAB
8763                          "bld __tmp_reg__,7"  CR_TAB
8764                          "adc %0,__tmp_reg__",
8765                          &all_regs_rtx[s0], plen, 1);
8766           else
8767             avr_asm_len ("lsr __tmp_reg" CR_TAB
8768                          "add %0,__tmp_reg__",
8769                          &all_regs_rtx[s0], plen, 2);
8770           for (sn = src.regno + src.fbyte; sn <= copied_msb; sn++)
8771             avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8772           frac_rounded = true;
8773         }
8774       else if (overlap)
8775         {
8776           bool use_src
8777             = (TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], s0)
8778                && (IN_RANGE (s0, dest.regno, dest.regno_msb)
8779                    || reg_unused_after (insn, all_regs_rtx[s0])));
8780           xop[2] = all_regs_rtx[s0];
8781           unsigned sn = src.regno;
8782           if (!use_src || sn == s0)
8783             avr_asm_len ("mov __tmp_reg__,%2", xop, plen, 1);
8784           /* We need to consider to-be-discarded bits
8785              if the value is negative.  */
8786           if (sn < s0)
8787             {
8788               avr_asm_len ("tst %0" CR_TAB
8789                            "brpl 0f",
8790                            &all_regs_rtx[src.regno_msb], plen, 2);
8791               /* Test to-be-discarded bytes for any nozero bits.
8792                  ??? Could use OR or SBIW to test two registers at once.  */
8793               if (sn < s0)
8794                 avr_asm_len ("cp %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8795 
8796               while (++sn < s0)
8797                 avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8798               /* Set bit 0 in __tmp_reg__ if any of the lower bits was set.  */
8799               if (use_src)
8800                 avr_asm_len ("breq 0f" CR_TAB
8801                              "ori %2,1"
8802                              "\n0:\t" "mov __tmp_reg__,%2",
8803                              xop, plen, 3);
8804               else
8805                 avr_asm_len ("breq 0f" CR_TAB
8806                              "set"     CR_TAB
8807                              "bld __tmp_reg__,0\n0:",
8808                              xop, plen, 3);
8809             }
8810           lsb_in_tmp_reg = true;
8811         }
8812     }
8813 
8814   /* Step 1:  Clear bytes at the low end and copy payload bits from source
8815      ======   to destination.  */
8816 
8817   int step = offset < 0 ? 1 : -1;
8818   unsigned d0 = offset < 0 ? dest.regno : dest.regno_msb;
8819 
8820   // We cleared at least that number of registers.
8821   int clr_n = 0;
8822 
8823   for (; d0 >= dest.regno && d0 <= dest.regno_msb; d0 += step)
8824     {
8825       // Next regno of destination is needed for MOVW
8826       unsigned d1 = d0 + step;
8827 
8828       // Current and next regno of source
8829       signed s0 = d0 - offset;
8830       signed s1 = s0 + step;
8831 
8832       // Must current resp. next regno be CLRed?  This applies to the low
8833       // bytes of the destination that have no associated source bytes.
8834       bool clr0 = s0 < (signed) src.regno;
8835       bool clr1 = s1 < (signed) src.regno && d1 >= dest.regno;
8836 
8837       // First gather what code to emit (if any) and additional step to
8838       // apply if a MOVW is in use.  xop[2] is destination rtx and xop[3]
8839       // is the source rtx for the current loop iteration.
8840       const char *code = NULL;
8841       int stepw = 0;
8842 
8843       if (clr0)
8844         {
8845           if (AVR_HAVE_MOVW && clr1 && clrw)
8846             {
8847               xop[2] = all_regs_rtx[d0 & ~1];
8848               xop[3] = clrw;
8849               code = "movw %2,%3";
8850               stepw = step;
8851             }
8852           else
8853             {
8854               xop[2] = all_regs_rtx[d0];
8855               code = "clr %2";
8856 
8857               if (++clr_n >= 2
8858                   && !clrw
8859                   && d0 % 2 == (step > 0))
8860                 {
8861                   clrw = all_regs_rtx[d0 & ~1];
8862                 }
8863             }
8864         }
8865       else if (offset && s0 <= (signed) src.regno_msb)
8866         {
8867           int movw = AVR_HAVE_MOVW && offset % 2 == 0
8868             && d0 % 2 == (offset > 0)
8869             && d1 <= dest.regno_msb && d1 >= dest.regno
8870             && s1 <= (signed) src.regno_msb  && s1 >= (signed) src.regno;
8871 
8872           xop[2] = all_regs_rtx[d0 & ~movw];
8873           xop[3] = all_regs_rtx[s0 & ~movw];
8874           code = movw ? "movw %2,%3" : "mov %2,%3";
8875           stepw = step * movw;
8876         }
8877 
8878       if (code)
8879         {
8880           if (sign_extend && shift != ASHIFT && !sign_in_carry
8881               && (d0 == src.regno_msb || d0 + stepw == src.regno_msb))
8882             {
8883               /* We are going to override the sign bit.  If we sign-extend,
8884                  store the sign in the Carry flag.  This is not needed if
8885                  the destination will be ASHIFT in the remainder because
8886                  the ASHIFT will set Carry without extra instruction.  */
8887 
8888               avr_asm_len ("lsl %0", &all_regs_rtx[src.regno_msb], plen, 1);
8889               sign_in_carry = true;
8890             }
8891 
8892           unsigned src_msb = dest.regno_msb - sign_bytes - offset + 1;
8893 
8894           if (!sign_extend && shift == ASHIFTRT && !msb_in_carry
8895               && src.ibyte > dest.ibyte
8896               && (d0 == src_msb || d0 + stepw == src_msb))
8897             {
8898               /* We are going to override the MSB.  If we shift right,
8899                  store the MSB in the Carry flag.  This is only needed if
8900                  we don't sign-extend becaue with sign-extension the MSB
8901                  (the sign) will be produced by the sign extension.  */
8902 
8903               avr_asm_len ("lsr %0", &all_regs_rtx[src_msb], plen, 1);
8904               msb_in_carry = true;
8905             }
8906 
8907           unsigned src_lsb = dest.regno - offset -1;
8908 
8909           if (shift == ASHIFT && src.fbyte > dest.fbyte && !lsb_in_carry
8910 	      && !lsb_in_tmp_reg
8911               && (d0 == src_lsb || d0 + stepw == src_lsb))
8912             {
8913               /* We are going to override the new LSB; store it into carry.  */
8914 
8915               avr_asm_len ("lsl %0", &all_regs_rtx[src_lsb], plen, 1);
8916               code_ashift = "rol %0";
8917               lsb_in_carry = true;
8918             }
8919 
8920           avr_asm_len (code, xop, plen, 1);
8921           d0 += stepw;
8922         }
8923     }
8924 
8925   /* Step 2:  Shift destination left by 1 bit position.  This might be needed
8926      ======   for signed input and unsigned output.  */
8927 
8928   if (shift == ASHIFT && src.fbyte > dest.fbyte && !lsb_in_carry)
8929     {
8930       unsigned s0 = dest.regno - offset -1;
8931 
8932       /* n1169 4.1.4 says:
8933 	 "Conversions from a fixed-point to an integer type round toward zero."
8934 	 Hence, converting a fract type to integer only gives a non-zero result
8935 	 for -1.  */
8936       if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8937 	  && SCALAR_FRACT_MODE_P (GET_MODE (xop[1]))
8938 	  && !TARGET_FRACT_CONV_TRUNC)
8939 	{
8940 	  gcc_assert (s0 == src.regno_msb);
8941 	  /* Check if the input is -1.  We do that by checking if negating
8942 	     the input causes an integer overflow.  */
8943 	  unsigned sn = src.regno;
8944 	  avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx[sn++], plen, 1);
8945 	  while (sn <= s0)
8946 	    avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx[sn++], plen, 1);
8947 
8948 	  /* Overflow goes with set carry.  Clear carry otherwise.  */
8949 	  avr_asm_len ("brvs 0f" CR_TAB
8950                        "clc\n0:", NULL, plen, 2);
8951 	}
8952       /* Likewise, when converting from accumulator types to integer, we
8953 	 need to round up negative values.  */
8954       else if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8955 	       && SCALAR_ACCUM_MODE_P (GET_MODE (xop[1]))
8956 	       && !TARGET_FRACT_CONV_TRUNC
8957 	       && !frac_rounded)
8958 	{
8959 	  bool have_carry = false;
8960 
8961 	  xop[2] = all_regs_rtx[s0];
8962 	  if (!lsb_in_tmp_reg && !MAY_CLOBBER (s0))
8963 	    avr_asm_len ("mov __tmp_reg__,%2", xop, plen, 1);
8964 	  avr_asm_len ("tst %0" CR_TAB "brpl 0f",
8965 		       &all_regs_rtx[src.regno_msb], plen, 2);
8966 	  if (!lsb_in_tmp_reg)
8967 	    {
8968 	      unsigned sn = src.regno;
8969 	      if (sn < s0)
8970 		{
8971 		  avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx[sn],
8972 			       plen, 1);
8973 		  have_carry = true;
8974 		}
8975 	      while (++sn < s0)
8976 		avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx[sn], plen, 1);
8977 	      lsb_in_tmp_reg = !MAY_CLOBBER (s0);
8978 	    }
8979 	  /* Add in C and the rounding value 127.  */
8980 	  /* If the destination msb is a sign byte, and in LD_REGS,
8981 	     grab it as a temporary.  */
8982 	  if (sign_bytes
8983 	      && TEST_HARD_REG_BIT (reg_class_contents[LD_REGS],
8984 				    dest.regno_msb))
8985 	    {
8986 	      xop[3] = all_regs_rtx[dest.regno_msb];
8987 	      avr_asm_len ("ldi %3,127", xop, plen, 1);
8988 	      avr_asm_len ((have_carry && lsb_in_tmp_reg ? "adc __tmp_reg__,%3"
8989 			    : have_carry ? "adc %2,%3"
8990 			    : lsb_in_tmp_reg ? "add __tmp_reg__,%3"
8991 			    : "add %2,%3"),
8992 			   xop, plen, 1);
8993 	    }
8994 	  else
8995 	    {
8996 	      /* Fall back to use __zero_reg__ as a temporary.  */
8997 	      avr_asm_len ("dec __zero_reg__", NULL, plen, 1);
8998 	      if (have_carry)
8999 		avr_asm_len ("clt" CR_TAB
9000                              "bld __zero_reg__,7", NULL, plen, 2);
9001 	      else
9002 		avr_asm_len ("lsr __zero_reg__", NULL, plen, 1);
9003 	      avr_asm_len (have_carry && lsb_in_tmp_reg
9004                            ? "adc __tmp_reg__,__zero_reg__"
9005                            : have_carry ? "adc %2,__zero_reg__"
9006                            : lsb_in_tmp_reg ? "add __tmp_reg__,__zero_reg__"
9007                            : "add %2,__zero_reg__",
9008 			   xop, plen, 1);
9009 	      avr_asm_len ("eor __zero_reg__,__zero_reg__", NULL, plen, 1);
9010 	    }
9011 
9012           for (d0 = dest.regno + zero_bytes;
9013 	       d0 <= dest.regno_msb - sign_bytes; d0++)
9014 	    avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx[d0], plen, 1);
9015 
9016           avr_asm_len (lsb_in_tmp_reg
9017 		       ? "\n0:\t" "lsl __tmp_reg__"
9018                        : "\n0:\t" "lsl %2",
9019 		       xop, plen, 1);
9020 	}
9021       else if (MAY_CLOBBER (s0))
9022         avr_asm_len ("lsl %0", &all_regs_rtx[s0], plen, 1);
9023       else
9024         avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
9025                      "lsl __tmp_reg__", &all_regs_rtx[s0], plen, 2);
9026 
9027       code_ashift = "rol %0";
9028       lsb_in_carry = true;
9029     }
9030 
9031   if (shift == ASHIFT)
9032     {
9033       for (d0 = dest.regno + zero_bytes;
9034            d0 <= dest.regno_msb - sign_bytes; d0++)
9035         {
9036           avr_asm_len (code_ashift, &all_regs_rtx[d0], plen, 1);
9037           code_ashift = "rol %0";
9038         }
9039 
9040       lsb_in_carry = false;
9041       sign_in_carry = true;
9042     }
9043 
9044   /* Step 4a:  Store MSB in carry if we don't already have it or will produce
9045      =======   it in sign-extension below.  */
9046 
9047   if (!sign_extend && shift == ASHIFTRT && !msb_in_carry
9048       && src.ibyte > dest.ibyte)
9049     {
9050       unsigned s0 = dest.regno_msb - sign_bytes - offset + 1;
9051 
9052       if (MAY_CLOBBER (s0))
9053         avr_asm_len ("lsr %0", &all_regs_rtx[s0], plen, 1);
9054       else
9055         avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
9056                      "lsr __tmp_reg__", &all_regs_rtx[s0], plen, 2);
9057 
9058       msb_in_carry = true;
9059     }
9060 
9061   /* Step 3:  Sign-extend or zero-extend the destination as needed.
9062      ======   */
9063 
9064   if (sign_extend && !sign_in_carry)
9065     {
9066       unsigned s0 = src.regno_msb;
9067 
9068       if (MAY_CLOBBER (s0))
9069         avr_asm_len ("lsl %0", &all_regs_rtx[s0], plen, 1);
9070       else
9071         avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
9072                      "lsl __tmp_reg__", &all_regs_rtx[s0], plen, 2);
9073 
9074       sign_in_carry = true;
9075     }
9076 
9077   gcc_assert (sign_in_carry + msb_in_carry + lsb_in_carry <= 1);
9078 
9079   unsigned copies = 0;
9080   rtx movw = sign_extend ? NULL_RTX : clrw;
9081 
9082   for (d0 = dest.regno_msb - sign_bytes + 1; d0 <= dest.regno_msb; d0++)
9083     {
9084       if (AVR_HAVE_MOVW && movw
9085           && d0 % 2 == 0 && d0 + 1 <= dest.regno_msb)
9086         {
9087           xop[2] = all_regs_rtx[d0];
9088           xop[3] = movw;
9089           avr_asm_len ("movw %2,%3", xop, plen, 1);
9090           d0++;
9091         }
9092       else
9093         {
9094           avr_asm_len (sign_extend ? "sbc %0,%0" : "clr %0",
9095                        &all_regs_rtx[d0], plen, 1);
9096 
9097           if (++copies >= 2 && !movw && d0 % 2 == 1)
9098             movw = all_regs_rtx[d0-1];
9099         }
9100     } /* for */
9101 
9102 
9103   /* Step 4:  Right shift the destination.  This might be needed for
9104      ======   conversions from unsigned to signed.  */
9105 
9106   if (shift == ASHIFTRT)
9107     {
9108       const char *code_ashiftrt = "lsr %0";
9109 
9110       if (sign_extend || msb_in_carry)
9111         code_ashiftrt = "ror %0";
9112 
9113       if (src.sbit && src.ibyte == dest.ibyte)
9114         code_ashiftrt = "asr %0";
9115 
9116       for (d0 = dest.regno_msb - sign_bytes;
9117            d0 >= dest.regno + zero_bytes - 1 && d0 >= dest.regno; d0--)
9118         {
9119           avr_asm_len (code_ashiftrt, &all_regs_rtx[d0], plen, 1);
9120           code_ashiftrt = "ror %0";
9121         }
9122     }
9123 
9124 #undef MAY_CLOBBER
9125 
9126   return "";
9127 }
9128 
9129 
9130 /* Output fixed-point rounding.  XOP[0] = XOP[1] is the operand to round.
9131    XOP[2] is the rounding point, a CONST_INT.  The function prints the
9132    instruction sequence if PLEN = NULL and computes the length in words
9133    of the sequence if PLEN != NULL.  Most of this function deals with
9134    preparing operands for calls to `avr_out_plus' and `avr_out_bitop'.  */
9135 
9136 const char*
avr_out_round(rtx_insn * insn ATTRIBUTE_UNUSED,rtx * xop,int * plen)9137 avr_out_round (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *xop, int *plen)
9138 {
9139   scalar_mode mode = as_a <scalar_mode> (GET_MODE (xop[0]));
9140   scalar_int_mode imode = int_mode_for_mode (mode).require ();
9141   // The smallest fractional bit not cleared by the rounding is 2^(-RP).
9142   int fbit = (int) GET_MODE_FBIT (mode);
9143   double_int i_add = double_int_zero.set_bit (fbit-1 - INTVAL (xop[2]));
9144   wide_int wi_add = wi::set_bit_in_zero (fbit-1 - INTVAL (xop[2]),
9145 					 GET_MODE_PRECISION (imode));
9146   // Lengths of PLUS and AND parts.
9147   int len_add = 0, *plen_add = plen ? &len_add : NULL;
9148   int len_and = 0, *plen_and = plen ? &len_and : NULL;
9149 
9150   // Add-Saturate  1/2 * 2^(-RP).  Don't print the label "0:" when printing
9151   // the saturated addition so that we can emit the "rjmp 1f" before the
9152   // "0:" below.
9153 
9154   rtx xadd = const_fixed_from_double_int (i_add, mode);
9155   rtx xpattern, xsrc, op[4];
9156 
9157   xsrc = SIGNED_FIXED_POINT_MODE_P (mode)
9158     ? gen_rtx_SS_PLUS (mode, xop[1], xadd)
9159     : gen_rtx_US_PLUS (mode, xop[1], xadd);
9160   xpattern = gen_rtx_SET (xop[0], xsrc);
9161 
9162   op[0] = xop[0];
9163   op[1] = xop[1];
9164   op[2] = xadd;
9165   avr_out_plus (xpattern, op, plen_add, NULL, false /* Don't print "0:" */);
9166 
9167   avr_asm_len ("rjmp 1f" CR_TAB
9168                "0:", NULL, plen_add, 1);
9169 
9170   // Keep  all bits from RP and higher:   ... 2^(-RP)
9171   // Clear all bits from RP+1 and lower:              2^(-RP-1) ...
9172   // Rounding point                           ^^^^^^^
9173   // Added above                                      ^^^^^^^^^
9174   rtx xreg = simplify_gen_subreg (imode, xop[0], mode, 0);
9175   rtx xmask = immed_wide_int_const (-wi_add - wi_add, imode);
9176 
9177   xpattern = gen_rtx_SET (xreg, gen_rtx_AND (imode, xreg, xmask));
9178 
9179   op[0] = xreg;
9180   op[1] = xreg;
9181   op[2] = xmask;
9182   op[3] = gen_rtx_SCRATCH (QImode);
9183   avr_out_bitop (xpattern, op, plen_and);
9184   avr_asm_len ("1:", NULL, plen, 0);
9185 
9186   if (plen)
9187     *plen = len_add + len_and;
9188 
9189   return "";
9190 }
9191 
9192 
9193 /* Create RTL split patterns for byte sized rotate expressions.  This
9194    produces a series of move instructions and considers overlap situations.
9195    Overlapping non-HImode operands need a scratch register.  */
9196 
9197 bool
avr_rotate_bytes(rtx operands[])9198 avr_rotate_bytes (rtx operands[])
9199 {
9200   machine_mode mode = GET_MODE (operands[0]);
9201   bool overlapped = reg_overlap_mentioned_p (operands[0], operands[1]);
9202   bool same_reg = rtx_equal_p (operands[0], operands[1]);
9203   int num = INTVAL (operands[2]);
9204   rtx scratch = operands[3];
9205   /* Work out if byte or word move is needed.  Odd byte rotates need QImode.
9206      Word move if no scratch is needed, otherwise use size of scratch.  */
9207   machine_mode move_mode = QImode;
9208   int move_size, offset, size;
9209 
9210   if (num & 0xf)
9211     move_mode = QImode;
9212   else if ((mode == SImode && !same_reg) || !overlapped)
9213     move_mode = HImode;
9214   else
9215     move_mode = GET_MODE (scratch);
9216 
9217   /* Force DI rotate to use QI moves since other DI moves are currently split
9218      into QI moves so forward propagation works better.  */
9219   if (mode == DImode)
9220     move_mode = QImode;
9221   /* Make scratch smaller if needed.  */
9222   if (SCRATCH != GET_CODE (scratch)
9223       && HImode == GET_MODE (scratch)
9224       && QImode == move_mode)
9225     scratch = simplify_gen_subreg (move_mode, scratch, HImode, 0);
9226 
9227   move_size = GET_MODE_SIZE (move_mode);
9228   /* Number of bytes/words to rotate.  */
9229   offset = (num  >> 3) / move_size;
9230   /* Number of moves needed.  */
9231   size = GET_MODE_SIZE (mode) / move_size;
9232   /* Himode byte swap is special case to avoid a scratch register.  */
9233   if (mode == HImode && same_reg)
9234     {
9235       /* HImode byte swap, using xor.  This is as quick as using scratch.  */
9236       rtx src, dst;
9237       src = simplify_gen_subreg (move_mode, operands[1], mode, 0);
9238       dst = simplify_gen_subreg (move_mode, operands[0], mode, 1);
9239       if (!rtx_equal_p (dst, src))
9240         {
9241           emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
9242           emit_move_insn (src, gen_rtx_XOR (QImode, src, dst));
9243           emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
9244         }
9245     }
9246   else
9247     {
9248 #define MAX_SIZE 8 /* GET_MODE_SIZE (DImode) / GET_MODE_SIZE (QImode)  */
9249       /* Create linked list of moves to determine move order.  */
9250       struct {
9251         rtx src, dst;
9252         int links;
9253       } move[MAX_SIZE + 8];
9254       int blocked, moves;
9255 
9256       gcc_assert (size <= MAX_SIZE);
9257       /* Generate list of subreg moves.  */
9258       for (int i = 0; i < size; i++)
9259         {
9260           int from = i;
9261           int to = (from + offset) % size;
9262           move[i].src = simplify_gen_subreg (move_mode, operands[1],
9263                                              mode, from * move_size);
9264           move[i].dst = simplify_gen_subreg (move_mode, operands[0],
9265                                              mode, to * move_size);
9266           move[i].links = -1;
9267         }
9268       /* Mark dependence where a dst of one move is the src of another move.
9269          The first move is a conflict as it must wait until second is
9270          performed.  We ignore moves to self - we catch this later.  */
9271       if (overlapped)
9272         for (int i = 0; i < size; i++)
9273           if (reg_overlap_mentioned_p (move[i].dst, operands[1]))
9274             for (int j = 0; j < size; j++)
9275               if (j != i && rtx_equal_p (move[j].src, move[i].dst))
9276                 {
9277                   /* The dst of move i is the src of move j.  */
9278                   move[i].links = j;
9279                   break;
9280                 }
9281 
9282       blocked = -1;
9283       moves = 0;
9284       /* Go through move list and perform non-conflicting moves.  As each
9285          non-overlapping move is made, it may remove other conflicts
9286          so the process is repeated until no conflicts remain.  */
9287       do
9288         {
9289           blocked = -1;
9290           moves = 0;
9291           /* Emit move where dst is not also a src or we have used that
9292              src already.  */
9293           for (int i = 0; i < size; i++)
9294             if (move[i].src != NULL_RTX)
9295               {
9296                 if (move[i].links == -1
9297                     || move[move[i].links].src == NULL_RTX)
9298                   {
9299                     moves++;
9300                     /* Ignore NOP moves to self.  */
9301                     if (!rtx_equal_p (move[i].dst, move[i].src))
9302                       emit_move_insn (move[i].dst, move[i].src);
9303 
9304                     /* Remove  conflict from list.  */
9305                     move[i].src = NULL_RTX;
9306                   }
9307                 else
9308                   blocked = i;
9309               }
9310 
9311           /* Check for deadlock. This is when no moves occurred and we have
9312              at least one blocked move.  */
9313           if (moves == 0 && blocked != -1)
9314             {
9315               /* Need to use scratch register to break deadlock.
9316                  Add move to put dst of blocked move into scratch.
9317                  When this move occurs, it will break chain deadlock.
9318                  The scratch register is substituted for real move.  */
9319 
9320               gcc_assert (SCRATCH != GET_CODE (scratch));
9321 
9322               move[size].src = move[blocked].dst;
9323               move[size].dst =  scratch;
9324               /* Scratch move is never blocked.  */
9325               move[size].links = -1;
9326               /* Make sure we have valid link.  */
9327               gcc_assert (move[blocked].links != -1);
9328               /* Replace src of  blocking move with scratch reg.  */
9329               move[move[blocked].links].src = scratch;
9330               /* Make dependent on scratch move occurring.  */
9331               move[blocked].links = size;
9332               size=size+1;
9333             }
9334         }
9335       while (blocked != -1);
9336     }
9337   return true;
9338 }
9339 
9340 
9341 /* Worker function for `ADJUST_INSN_LENGTH'.  */
9342 /* Modifies the length assigned to instruction INSN
9343    LEN is the initially computed length of the insn.  */
9344 
9345 int
avr_adjust_insn_length(rtx_insn * insn,int len)9346 avr_adjust_insn_length (rtx_insn *insn, int len)
9347 {
9348   rtx *op = recog_data.operand;
9349   enum attr_adjust_len adjust_len;
9350 
9351   /* As we pretend jump tables in .text, fix branch offsets crossing jump
9352      tables now.  */
9353 
9354   if (JUMP_TABLE_DATA_P (insn))
9355     return 0;
9356 
9357   /* Some complex insns don't need length adjustment and therefore
9358      the length need not/must not be adjusted for these insns.
9359      It is easier to state this in an insn attribute "adjust_len" than
9360      to clutter up code here...  */
9361 
9362   if (!NONDEBUG_INSN_P (insn) || recog_memoized (insn) == -1)
9363     {
9364       return len;
9365     }
9366 
9367   /* Read from insn attribute "adjust_len" if/how length is to be adjusted.  */
9368 
9369   adjust_len = get_attr_adjust_len (insn);
9370 
9371   if (adjust_len == ADJUST_LEN_NO)
9372     {
9373       /* Nothing to adjust: The length from attribute "length" is fine.
9374          This is the default.  */
9375 
9376       return len;
9377     }
9378 
9379   /* Extract insn's operands.  */
9380 
9381   extract_constrain_insn_cached (insn);
9382 
9383   /* Dispatch to right function.  */
9384 
9385   switch (adjust_len)
9386     {
9387     case ADJUST_LEN_RELOAD_IN16: output_reload_inhi (op, op[2], &len); break;
9388     case ADJUST_LEN_RELOAD_IN24: avr_out_reload_inpsi (op, op[2], &len); break;
9389     case ADJUST_LEN_RELOAD_IN32: output_reload_insisf (op, op[2], &len); break;
9390 
9391     case ADJUST_LEN_OUT_BITOP: avr_out_bitop (insn, op, &len); break;
9392 
9393     case ADJUST_LEN_PLUS: avr_out_plus (insn, op, &len); break;
9394     case ADJUST_LEN_ADDTO_SP: avr_out_addto_sp (op, &len); break;
9395 
9396     case ADJUST_LEN_MOV8:  output_movqi (insn, op, &len); break;
9397     case ADJUST_LEN_MOV16: output_movhi (insn, op, &len); break;
9398     case ADJUST_LEN_MOV24: avr_out_movpsi (insn, op, &len); break;
9399     case ADJUST_LEN_MOV32: output_movsisf (insn, op, &len); break;
9400     case ADJUST_LEN_CPYMEM: avr_out_cpymem (insn, op, &len); break;
9401     case ADJUST_LEN_XLOAD: avr_out_xload (insn, op, &len); break;
9402     case ADJUST_LEN_SEXT: avr_out_sign_extend (insn, op, &len); break;
9403 
9404     case ADJUST_LEN_SFRACT: avr_out_fract (insn, op, true, &len); break;
9405     case ADJUST_LEN_UFRACT: avr_out_fract (insn, op, false, &len); break;
9406     case ADJUST_LEN_ROUND: avr_out_round (insn, op, &len); break;
9407 
9408     case ADJUST_LEN_TSTHI: avr_out_tsthi (insn, op, &len); break;
9409     case ADJUST_LEN_TSTPSI: avr_out_tstpsi (insn, op, &len); break;
9410     case ADJUST_LEN_TSTSI: avr_out_tstsi (insn, op, &len); break;
9411     case ADJUST_LEN_COMPARE: avr_out_compare (insn, op, &len); break;
9412     case ADJUST_LEN_COMPARE64: avr_out_compare64 (insn, op, &len); break;
9413 
9414     case ADJUST_LEN_LSHRQI: lshrqi3_out (insn, op, &len); break;
9415     case ADJUST_LEN_LSHRHI: lshrhi3_out (insn, op, &len); break;
9416     case ADJUST_LEN_LSHRSI: lshrsi3_out (insn, op, &len); break;
9417 
9418     case ADJUST_LEN_ASHRQI: ashrqi3_out (insn, op, &len); break;
9419     case ADJUST_LEN_ASHRHI: ashrhi3_out (insn, op, &len); break;
9420     case ADJUST_LEN_ASHRSI: ashrsi3_out (insn, op, &len); break;
9421 
9422     case ADJUST_LEN_ASHLQI: ashlqi3_out (insn, op, &len); break;
9423     case ADJUST_LEN_ASHLHI: ashlhi3_out (insn, op, &len); break;
9424     case ADJUST_LEN_ASHLSI: ashlsi3_out (insn, op, &len); break;
9425 
9426     case ADJUST_LEN_ASHLPSI: avr_out_ashlpsi3 (insn, op, &len); break;
9427     case ADJUST_LEN_ASHRPSI: avr_out_ashrpsi3 (insn, op, &len); break;
9428     case ADJUST_LEN_LSHRPSI: avr_out_lshrpsi3 (insn, op, &len); break;
9429 
9430     case ADJUST_LEN_CALL: len = AVR_HAVE_JMP_CALL ? 2 : 1; break;
9431 
9432     case ADJUST_LEN_INSERT_BITS: avr_out_insert_bits (op, &len); break;
9433 
9434     case ADJUST_LEN_INSV_NOTBIT:
9435       avr_out_insert_notbit (insn, op, NULL_RTX, &len);
9436       break;
9437     case ADJUST_LEN_INSV_NOTBIT_0:
9438       avr_out_insert_notbit (insn, op, const0_rtx, &len);
9439       break;
9440     case ADJUST_LEN_INSV_NOTBIT_7:
9441       avr_out_insert_notbit (insn, op, GEN_INT (7), &len);
9442       break;
9443 
9444     default:
9445       gcc_unreachable();
9446     }
9447 
9448   return len;
9449 }
9450 
9451 /* Return nonzero if register REG dead after INSN.  */
9452 
9453 int
reg_unused_after(rtx_insn * insn,rtx reg)9454 reg_unused_after (rtx_insn *insn, rtx reg)
9455 {
9456   return (dead_or_set_p (insn, reg)
9457 	  || (REG_P (reg) && _reg_unused_after (insn, reg)));
9458 }
9459 
9460 /* Return nonzero if REG is not used after INSN.
9461    We assume REG is a reload reg, and therefore does
9462    not live past labels.  It may live past calls or jumps though.  */
9463 
9464 int
_reg_unused_after(rtx_insn * insn,rtx reg)9465 _reg_unused_after (rtx_insn *insn, rtx reg)
9466 {
9467   enum rtx_code code;
9468   rtx set;
9469 
9470   /* If the reg is set by this instruction, then it is safe for our
9471      case.  Disregard the case where this is a store to memory, since
9472      we are checking a register used in the store address.  */
9473   set = single_set (insn);
9474   if (set && !MEM_P (SET_DEST (set))
9475       && reg_overlap_mentioned_p (reg, SET_DEST (set)))
9476     return 1;
9477 
9478   while ((insn = NEXT_INSN (insn)))
9479     {
9480       rtx set;
9481       code = GET_CODE (insn);
9482 
9483 #if 0
9484       /* If this is a label that existed before reload, then the register
9485 	 if dead here.  However, if this is a label added by reorg, then
9486 	 the register may still be live here.  We can't tell the difference,
9487 	 so we just ignore labels completely.  */
9488       if (code == CODE_LABEL)
9489 	return 1;
9490       /* else */
9491 #endif
9492 
9493       if (!INSN_P (insn))
9494 	continue;
9495 
9496       if (code == JUMP_INSN)
9497 	return 0;
9498 
9499       /* If this is a sequence, we must handle them all at once.
9500 	 We could have for instance a call that sets the target register,
9501 	 and an insn in a delay slot that uses the register.  In this case,
9502 	 we must return 0.  */
9503       else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
9504 	{
9505 	  rtx_sequence *seq = as_a <rtx_sequence *> (PATTERN (insn));
9506 	  int retval = 0;
9507 
9508 	  for (int i = 0; i < seq->len (); i++)
9509 	    {
9510 	      rtx_insn *this_insn = seq->insn (i);
9511 	      rtx set = single_set (this_insn);
9512 
9513 	      if (CALL_P (this_insn))
9514 		code = CALL_INSN;
9515 	      else if (JUMP_P (this_insn))
9516 		{
9517 		  if (INSN_ANNULLED_BRANCH_P (this_insn))
9518 		    return 0;
9519 		  code = JUMP_INSN;
9520 		}
9521 
9522 	      if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
9523 		return 0;
9524 	      if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
9525 		{
9526 		  if (!MEM_P (SET_DEST (set)))
9527 		    retval = 1;
9528 		  else
9529 		    return 0;
9530 		}
9531 	      if (set == 0
9532 		  && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
9533 		return 0;
9534 	    }
9535 	  if (retval == 1)
9536 	    return 1;
9537 	  else if (code == JUMP_INSN)
9538 	    return 0;
9539 	}
9540 
9541       if (code == CALL_INSN)
9542 	{
9543 	  rtx tem;
9544 	  for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
9545 	    if (GET_CODE (XEXP (tem, 0)) == USE
9546 		&& REG_P (XEXP (XEXP (tem, 0), 0))
9547 		&& reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
9548 	      return 0;
9549 	  if (call_used_or_fixed_reg_p (REGNO (reg)))
9550 	    return 1;
9551 	}
9552 
9553       set = single_set (insn);
9554 
9555       if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
9556 	return 0;
9557       if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
9558 	return !MEM_P (SET_DEST (set));
9559       if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
9560 	return 0;
9561     }
9562   return 1;
9563 }
9564 
9565 
9566 /* Implement `TARGET_ASM_INTEGER'.  */
9567 /* Target hook for assembling integer objects.  The AVR version needs
9568    special handling for references to certain labels.  */
9569 
9570 static bool
avr_assemble_integer(rtx x,unsigned int size,int aligned_p)9571 avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
9572 {
9573   if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
9574       && text_segment_operand (x, VOIDmode))
9575     {
9576       fputs ("\t.word\tgs(", asm_out_file);
9577       output_addr_const (asm_out_file, x);
9578       fputs (")\n", asm_out_file);
9579 
9580       return true;
9581     }
9582   else if (GET_MODE (x) == PSImode)
9583     {
9584       /* This needs binutils 2.23+, see PR binutils/13503  */
9585 
9586       fputs ("\t.byte\tlo8(", asm_out_file);
9587       output_addr_const (asm_out_file, x);
9588       fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
9589 
9590       fputs ("\t.byte\thi8(", asm_out_file);
9591       output_addr_const (asm_out_file, x);
9592       fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
9593 
9594       fputs ("\t.byte\thh8(", asm_out_file);
9595       output_addr_const (asm_out_file, x);
9596       fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
9597 
9598       return true;
9599     }
9600   else if (CONST_FIXED_P (x))
9601     {
9602       /* varasm fails to handle big fixed modes that don't fit in hwi.  */
9603 
9604       for (unsigned n = 0; n < size; n++)
9605         {
9606           rtx xn = simplify_gen_subreg (QImode, x, GET_MODE (x), n);
9607           default_assemble_integer (xn, 1, aligned_p);
9608         }
9609 
9610       return true;
9611     }
9612 
9613   if (AVR_TINY
9614       && avr_address_tiny_pm_p (x))
9615     {
9616       x = plus_constant (Pmode, x, avr_arch->flash_pm_offset);
9617     }
9618 
9619   return default_assemble_integer (x, size, aligned_p);
9620 }
9621 
9622 
9623 /* Implement `TARGET_CLASS_LIKELY_SPILLED_P'.  */
9624 /* Return value is nonzero if pseudos that have been
9625    assigned to registers of class CLASS would likely be spilled
9626    because registers of CLASS are needed for spill registers.  */
9627 
9628 static bool
avr_class_likely_spilled_p(reg_class_t c)9629 avr_class_likely_spilled_p (reg_class_t c)
9630 {
9631   return (c != ALL_REGS &&
9632            (AVR_TINY ? 1 : c != ADDW_REGS));
9633 }
9634 
9635 
9636 /* Valid attributes:
9637    progmem   -  Put data to program memory.
9638    signal    -  Make a function to be hardware interrupt.
9639                 After function prologue interrupts remain disabled.
9640    interrupt -  Make a function to be hardware interrupt. Before function
9641                 prologue interrupts are enabled by means of SEI.
9642    naked     -  Don't generate function prologue/epilogue and RET
9643                 instruction.  */
9644 
9645 /* Handle a "progmem" attribute; arguments as in
9646    struct attribute_spec.handler.  */
9647 
9648 static tree
avr_handle_progmem_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)9649 avr_handle_progmem_attribute (tree *node, tree name,
9650 			      tree args ATTRIBUTE_UNUSED,
9651 			      int flags ATTRIBUTE_UNUSED,
9652 			      bool *no_add_attrs)
9653 {
9654   if (DECL_P (*node))
9655     {
9656       if (TREE_CODE (*node) == TYPE_DECL)
9657 	{
9658 	  /* This is really a decl attribute, not a type attribute,
9659 	     but try to handle it for GCC 3.0 backwards compatibility.  */
9660 
9661 	  tree type = TREE_TYPE (*node);
9662 	  tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
9663 	  tree newtype = build_type_attribute_variant (type, attr);
9664 
9665 	  TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
9666 	  TREE_TYPE (*node) = newtype;
9667 	  *no_add_attrs = true;
9668 	}
9669       else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
9670 	{
9671           *no_add_attrs = false;
9672 	}
9673       else
9674 	{
9675 	  warning (OPT_Wattributes, "%qE attribute ignored",
9676 		   name);
9677 	  *no_add_attrs = true;
9678 	}
9679     }
9680 
9681   return NULL_TREE;
9682 }
9683 
9684 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
9685    struct attribute_spec.handler.  */
9686 
9687 static tree
avr_handle_fndecl_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)9688 avr_handle_fndecl_attribute (tree *node, tree name,
9689 			     tree args ATTRIBUTE_UNUSED,
9690 			     int flags ATTRIBUTE_UNUSED,
9691 			     bool *no_add_attrs)
9692 {
9693   if (TREE_CODE (*node) != FUNCTION_DECL)
9694     {
9695       warning (OPT_Wattributes, "%qE attribute only applies to functions",
9696 	       name);
9697       *no_add_attrs = true;
9698     }
9699 
9700   return NULL_TREE;
9701 }
9702 
9703 static tree
avr_handle_fntype_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)9704 avr_handle_fntype_attribute (tree *node, tree name,
9705                              tree args ATTRIBUTE_UNUSED,
9706                              int flags ATTRIBUTE_UNUSED,
9707                              bool *no_add_attrs)
9708 {
9709   if (TREE_CODE (*node) != FUNCTION_TYPE)
9710     {
9711       warning (OPT_Wattributes, "%qE attribute only applies to functions",
9712 	       name);
9713       *no_add_attrs = true;
9714     }
9715 
9716   return NULL_TREE;
9717 }
9718 
9719 static tree
avr_handle_absdata_attribute(tree * node,tree name,tree,int,bool * no_add)9720 avr_handle_absdata_attribute (tree *node, tree name, tree /* args */,
9721                               int /* flags */, bool *no_add)
9722 {
9723   location_t loc = DECL_SOURCE_LOCATION (*node);
9724 
9725   if (AVR_TINY)
9726     {
9727       if (TREE_CODE (*node) != VAR_DECL
9728           || (!TREE_STATIC (*node) && !DECL_EXTERNAL (*node)))
9729         {
9730           warning_at (loc, OPT_Wattributes, "%qE attribute only applies to"
9731                       " variables in static storage", name);
9732           *no_add = true;
9733         }
9734     }
9735   else
9736     {
9737       warning_at (loc, OPT_Wattributes, "%qE attribute only supported"
9738                   " for reduced Tiny cores", name);
9739       *no_add = true;
9740     }
9741 
9742   return NULL_TREE;
9743 }
9744 
9745 static tree
avr_handle_addr_attribute(tree * node,tree name,tree args,int flags ATTRIBUTE_UNUSED,bool * no_add)9746 avr_handle_addr_attribute (tree *node, tree name, tree args,
9747 			   int flags ATTRIBUTE_UNUSED, bool *no_add)
9748 {
9749   bool io_p = (strncmp (IDENTIFIER_POINTER (name), "io", 2) == 0);
9750   location_t loc = DECL_SOURCE_LOCATION (*node);
9751 
9752   if (!VAR_P (*node))
9753     {
9754       warning_at (loc, OPT_Wattributes, "%qE attribute only applies to "
9755 		  "variables", name);
9756       *no_add = true;
9757       return NULL_TREE;
9758     }
9759 
9760   if (args != NULL_TREE)
9761     {
9762       if (TREE_CODE (TREE_VALUE (args)) == NON_LVALUE_EXPR)
9763 	TREE_VALUE (args) = TREE_OPERAND (TREE_VALUE (args), 0);
9764       tree arg = TREE_VALUE (args);
9765       if (TREE_CODE (arg) != INTEGER_CST)
9766 	{
9767 	  warning_at (loc, OPT_Wattributes, "%qE attribute allows only an "
9768 		      "integer constant argument", name);
9769 	  *no_add = true;
9770 	}
9771       else if (io_p
9772 	       && (!tree_fits_shwi_p (arg)
9773 		   || !(strcmp (IDENTIFIER_POINTER (name), "io_low") == 0
9774 			? low_io_address_operand : io_address_operand)
9775 			 (GEN_INT (TREE_INT_CST_LOW (arg)), QImode)))
9776 	{
9777 	  warning_at (loc, OPT_Wattributes, "%qE attribute address "
9778 		      "out of range", name);
9779 	  *no_add = true;
9780 	}
9781       else
9782 	{
9783 	  tree attribs = DECL_ATTRIBUTES (*node);
9784 	  const char *names[] = { "io", "io_low", "address", NULL };
9785 	  for (const char **p = names; *p; p++)
9786 	    {
9787 	      tree other = lookup_attribute (*p, attribs);
9788 	      if (other && TREE_VALUE (other))
9789 		{
9790 		  warning_at (loc, OPT_Wattributes,
9791 			      "both %s and %qE attribute provide address",
9792 			      *p, name);
9793 		  *no_add = true;
9794 		  break;
9795 		}
9796 	    }
9797 	}
9798     }
9799 
9800   if (*no_add == false && io_p && !TREE_THIS_VOLATILE (*node))
9801     warning_at (loc, OPT_Wattributes, "%qE attribute on non-volatile variable",
9802 		name);
9803 
9804   return NULL_TREE;
9805 }
9806 
9807 rtx
avr_eval_addr_attrib(rtx x)9808 avr_eval_addr_attrib (rtx x)
9809 {
9810   if (SYMBOL_REF_P (x)
9811       && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_ADDRESS))
9812     {
9813       tree decl = SYMBOL_REF_DECL (x);
9814       tree attr = NULL_TREE;
9815 
9816       if (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO)
9817 	{
9818 	  attr = lookup_attribute ("io", DECL_ATTRIBUTES (decl));
9819           if (!attr || !TREE_VALUE (attr))
9820             attr = lookup_attribute ("io_low", DECL_ATTRIBUTES (decl));
9821 	  gcc_assert (attr);
9822 	}
9823       if (!attr || !TREE_VALUE (attr))
9824 	attr = lookup_attribute ("address", DECL_ATTRIBUTES (decl));
9825       gcc_assert (attr && TREE_VALUE (attr) && TREE_VALUE (TREE_VALUE (attr)));
9826       return GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))));
9827     }
9828   return x;
9829 }
9830 
9831 
9832 /* AVR attributes.  */
9833 static const struct attribute_spec avr_attribute_table[] =
9834 {
9835   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
9836        affects_type_identity, handler, exclude } */
9837   { "progmem",   0, 0, false, false, false, false,
9838     avr_handle_progmem_attribute, NULL },
9839   { "signal",    0, 0, true,  false, false, false,
9840     avr_handle_fndecl_attribute, NULL },
9841   { "interrupt", 0, 0, true,  false, false, false,
9842     avr_handle_fndecl_attribute, NULL },
9843   { "no_gccisr", 0, 0, true,  false, false, false,
9844     avr_handle_fndecl_attribute, NULL },
9845   { "naked",     0, 0, false, true,  true,  false,
9846     avr_handle_fntype_attribute, NULL },
9847   { "OS_task",   0, 0, false, true,  true,  false,
9848     avr_handle_fntype_attribute, NULL },
9849   { "OS_main",   0, 0, false, true,  true,  false,
9850     avr_handle_fntype_attribute, NULL },
9851   { "io",        0, 1, true, false, false,  false,
9852     avr_handle_addr_attribute, NULL },
9853   { "io_low",    0, 1, true, false, false,  false,
9854     avr_handle_addr_attribute, NULL },
9855   { "address",   1, 1, true, false, false,  false,
9856     avr_handle_addr_attribute, NULL },
9857   { "absdata",   0, 0, true, false, false,  false,
9858     avr_handle_absdata_attribute, NULL },
9859   { NULL,        0, 0, false, false, false, false, NULL, NULL }
9860 };
9861 
9862 
9863 /* Return true if we support address space AS for the architecture in effect
9864    and false, otherwise.  If LOC is not UNKNOWN_LOCATION then also issue
9865    a respective error.  */
9866 
9867 bool
avr_addr_space_supported_p(addr_space_t as,location_t loc)9868 avr_addr_space_supported_p (addr_space_t as, location_t loc)
9869 {
9870   if (AVR_TINY)
9871     {
9872       if (loc != UNKNOWN_LOCATION)
9873         error_at (loc, "address spaces are not supported for reduced "
9874                   "Tiny devices");
9875       return false;
9876     }
9877   else if (avr_addrspace[as].segment >= avr_n_flash)
9878     {
9879       if (loc != UNKNOWN_LOCATION)
9880         error_at (loc, "address space %qs not supported for devices with "
9881                   "flash size up to %d KiB", avr_addrspace[as].name,
9882                   64 * avr_n_flash);
9883       return false;
9884     }
9885 
9886   return true;
9887 }
9888 
9889 
9890 /* Implement `TARGET_ADDR_SPACE_DIAGNOSE_USAGE'.  */
9891 
9892 static void
avr_addr_space_diagnose_usage(addr_space_t as,location_t loc)9893 avr_addr_space_diagnose_usage (addr_space_t as, location_t loc)
9894 {
9895   (void) avr_addr_space_supported_p (as, loc);
9896 }
9897 
9898 
9899 /* Look if DECL shall be placed in program memory space by
9900    means of attribute `progmem' or some address-space qualifier.
9901    Return non-zero if DECL is data that must end up in Flash and
9902    zero if the data lives in RAM (.bss, .data, .rodata, ...).
9903 
9904    Return 2   if DECL is located in 24-bit flash address-space
9905    Return 1   if DECL is located in 16-bit flash address-space
9906    Return -1  if attribute `progmem' occurs in DECL or ATTRIBUTES
9907    Return 0   otherwise  */
9908 
9909 int
avr_progmem_p(tree decl,tree attributes)9910 avr_progmem_p (tree decl, tree attributes)
9911 {
9912   tree a;
9913 
9914   if (TREE_CODE (decl) != VAR_DECL)
9915     return 0;
9916 
9917   if (avr_decl_memx_p (decl))
9918     return 2;
9919 
9920   if (avr_decl_flash_p (decl))
9921     return 1;
9922 
9923   if (NULL_TREE
9924       != lookup_attribute ("progmem", attributes))
9925     return -1;
9926 
9927   a = decl;
9928 
9929   do
9930     a = TREE_TYPE(a);
9931   while (TREE_CODE (a) == ARRAY_TYPE);
9932 
9933   if (a == error_mark_node)
9934     return 0;
9935 
9936   if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
9937     return -1;
9938 
9939   return 0;
9940 }
9941 
9942 
9943 /* Return true if DECL has attribute `absdata' set.  This function should
9944    only be used for AVR_TINY.  */
9945 
9946 static bool
avr_decl_absdata_p(tree decl,tree attributes)9947 avr_decl_absdata_p (tree decl, tree attributes)
9948 {
9949   return (TREE_CODE (decl) == VAR_DECL
9950           && NULL_TREE != lookup_attribute ("absdata", attributes));
9951 }
9952 
9953 
9954 /* Scan type TYP for pointer references to address space ASn.
9955    Return ADDR_SPACE_GENERIC (i.e. 0) if all pointers targeting
9956    the AS are also declared to be CONST.
9957    Otherwise, return the respective address space, i.e. a value != 0.  */
9958 
9959 static addr_space_t
avr_nonconst_pointer_addrspace(tree typ)9960 avr_nonconst_pointer_addrspace (tree typ)
9961 {
9962   while (ARRAY_TYPE == TREE_CODE (typ))
9963     typ = TREE_TYPE (typ);
9964 
9965   if (POINTER_TYPE_P (typ))
9966     {
9967       addr_space_t as;
9968       tree target = TREE_TYPE (typ);
9969 
9970       /* Pointer to function: Test the function's return type.  */
9971 
9972       if (FUNCTION_TYPE == TREE_CODE (target))
9973         return avr_nonconst_pointer_addrspace (TREE_TYPE (target));
9974 
9975       /* "Ordinary" pointers... */
9976 
9977       while (TREE_CODE (target) == ARRAY_TYPE)
9978         target = TREE_TYPE (target);
9979 
9980       /* Pointers to non-generic address space must be const.  */
9981 
9982       as = TYPE_ADDR_SPACE (target);
9983 
9984       if (!ADDR_SPACE_GENERIC_P (as)
9985           && !TYPE_READONLY (target)
9986           && avr_addr_space_supported_p (as))
9987         {
9988           return as;
9989         }
9990 
9991       /* Scan pointer's target type.  */
9992 
9993       return avr_nonconst_pointer_addrspace (target);
9994     }
9995 
9996   return ADDR_SPACE_GENERIC;
9997 }
9998 
9999 
10000 /* Sanity check NODE so that all pointers targeting non-generic address spaces
10001    go along with CONST qualifier.  Writing to these address spaces should
10002    be detected and complained about as early as possible.  */
10003 
10004 static bool
avr_pgm_check_var_decl(tree node)10005 avr_pgm_check_var_decl (tree node)
10006 {
10007   const char *reason = NULL;
10008 
10009   addr_space_t as = ADDR_SPACE_GENERIC;
10010 
10011   gcc_assert (as == 0);
10012 
10013   if (avr_log.progmem)
10014     avr_edump ("%?: %t\n", node);
10015 
10016   switch (TREE_CODE (node))
10017     {
10018     default:
10019       break;
10020 
10021     case VAR_DECL:
10022       if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
10023         reason = _("variable");
10024       break;
10025 
10026     case PARM_DECL:
10027       if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
10028         reason = _("function parameter");
10029       break;
10030 
10031     case FIELD_DECL:
10032       if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
10033         reason = _("structure field");
10034       break;
10035 
10036     case FUNCTION_DECL:
10037       if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (TREE_TYPE (node))),
10038           as)
10039         reason = _("return type of function");
10040       break;
10041 
10042     case POINTER_TYPE:
10043       if (as = avr_nonconst_pointer_addrspace (node), as)
10044         reason = _("pointer");
10045       break;
10046     }
10047 
10048   if (reason)
10049     {
10050       if (TYPE_P (node))
10051         error ("pointer targeting address space %qs must be const in %qT",
10052                avr_addrspace[as].name, node);
10053       else
10054         error ("pointer targeting address space %qs must be const"
10055                " in %s %q+D",
10056                avr_addrspace[as].name, reason, node);
10057     }
10058 
10059   return reason == NULL;
10060 }
10061 
10062 
10063 /* Implement `TARGET_INSERT_ATTRIBUTES'.  */
10064 
10065 static void
avr_insert_attributes(tree node,tree * attributes)10066 avr_insert_attributes (tree node, tree *attributes)
10067 {
10068   avr_pgm_check_var_decl (node);
10069 
10070   if (TARGET_MAIN_IS_OS_TASK
10071       && TREE_CODE (node) == FUNCTION_DECL
10072       && MAIN_NAME_P (DECL_NAME (node))
10073       // FIXME:  We'd like to also test `flag_hosted' which is only
10074       // available in the C-ish fronts, hence no such test for now.
10075       // Instead, we test the return type of "main" which is not exactly
10076       // the same but good enough.
10077       && INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (node)))
10078       && NULL == lookup_attribute ("OS_task", *attributes))
10079     {
10080       *attributes = tree_cons (get_identifier ("OS_task"),
10081                                NULL, *attributes);
10082     }
10083 
10084   /* Add the section attribute if the variable is in progmem.  */
10085 
10086   if (TREE_CODE (node) == VAR_DECL
10087       && (TREE_STATIC (node) || DECL_EXTERNAL (node))
10088       && avr_progmem_p (node, *attributes))
10089     {
10090       addr_space_t as;
10091       tree node0 = node;
10092 
10093       /* For C++, we have to peel arrays in order to get correct
10094          determination of readonlyness.  */
10095 
10096       do
10097         node0 = TREE_TYPE (node0);
10098       while (TREE_CODE (node0) == ARRAY_TYPE);
10099 
10100       if (error_mark_node == node0)
10101         return;
10102 
10103       as = TYPE_ADDR_SPACE (TREE_TYPE (node));
10104 
10105       if (!TYPE_READONLY (node0)
10106           && !TREE_READONLY (node))
10107         {
10108           const char *reason = "__attribute__((progmem))";
10109 
10110           if (!ADDR_SPACE_GENERIC_P (as))
10111             reason = avr_addrspace[as].name;
10112 
10113           if (avr_log.progmem)
10114             avr_edump ("\n%?: %t\n%t\n", node, node0);
10115 
10116           error ("variable %q+D must be const in order to be put into"
10117                  " read-only section by means of %qs", node, reason);
10118         }
10119     }
10120 }
10121 
10122 
10123 /* Implement `ASM_OUTPUT_ALIGNED_DECL_LOCAL'.  */
10124 /* Implement `ASM_OUTPUT_ALIGNED_DECL_COMMON'.  */
10125 /* Track need of __do_clear_bss.  */
10126 
10127 void
avr_asm_output_aligned_decl_common(FILE * stream,tree decl,const char * name,unsigned HOST_WIDE_INT size,unsigned int align,bool local_p)10128 avr_asm_output_aligned_decl_common (FILE * stream,
10129                                     tree decl,
10130                                     const char *name,
10131                                     unsigned HOST_WIDE_INT size,
10132                                     unsigned int align, bool local_p)
10133 {
10134   rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
10135   rtx symbol;
10136 
10137   if (mem != NULL_RTX && MEM_P (mem)
10138       && SYMBOL_REF_P ((symbol = XEXP (mem, 0)))
10139       && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
10140     {
10141       if (!local_p)
10142 	{
10143 	  fprintf (stream, "\t.globl\t");
10144 	  assemble_name (stream, name);
10145 	  fprintf (stream, "\n");
10146 	}
10147       if (SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS)
10148 	{
10149 	  assemble_name (stream, name);
10150 	  fprintf (stream, " = %ld\n",
10151 		   (long) INTVAL (avr_eval_addr_attrib (symbol)));
10152 	}
10153       else if (local_p)
10154 	error_at (DECL_SOURCE_LOCATION (decl),
10155 		  "static IO declaration for %q+D needs an address", decl);
10156       return;
10157     }
10158 
10159   /* __gnu_lto_slim is just a marker for the linker injected by toplev.c.
10160      There is no need to trigger __do_clear_bss code for them.  */
10161 
10162   if (!STR_PREFIX_P (name, "__gnu_lto"))
10163     avr_need_clear_bss_p = true;
10164 
10165   if (local_p)
10166     ASM_OUTPUT_ALIGNED_LOCAL (stream, name, size, align);
10167   else
10168     ASM_OUTPUT_ALIGNED_COMMON (stream, name, size, align);
10169 }
10170 
10171 void
avr_asm_asm_output_aligned_bss(FILE * file,tree decl,const char * name,unsigned HOST_WIDE_INT size,int align,void (* default_func)(FILE *,tree,const char *,unsigned HOST_WIDE_INT,int))10172 avr_asm_asm_output_aligned_bss (FILE *file, tree decl, const char *name,
10173 				unsigned HOST_WIDE_INT size, int align,
10174 				void (*default_func)
10175 				  (FILE *, tree, const char *,
10176 				   unsigned HOST_WIDE_INT, int))
10177 {
10178   rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
10179   rtx symbol;
10180 
10181   if (mem != NULL_RTX && MEM_P (mem)
10182       && SYMBOL_REF_P ((symbol = XEXP (mem, 0)))
10183       && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
10184     {
10185       if (!(SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS))
10186 	error_at (DECL_SOURCE_LOCATION (decl),
10187 		  "IO definition for %q+D needs an address", decl);
10188       avr_asm_output_aligned_decl_common (file, decl, name, size, align, false);
10189     }
10190   else
10191     default_func (file, decl, name, size, align);
10192 }
10193 
10194 
10195 /* Unnamed section callback for data_section
10196    to track need of __do_copy_data.  */
10197 
10198 static void
avr_output_data_section_asm_op(const void * data)10199 avr_output_data_section_asm_op (const void *data)
10200 {
10201   avr_need_copy_data_p = true;
10202 
10203   /* Dispatch to default.  */
10204   output_section_asm_op (data);
10205 }
10206 
10207 
10208 /* Unnamed section callback for bss_section
10209    to track need of __do_clear_bss.  */
10210 
10211 static void
avr_output_bss_section_asm_op(const void * data)10212 avr_output_bss_section_asm_op (const void *data)
10213 {
10214   avr_need_clear_bss_p = true;
10215 
10216   /* Dispatch to default.  */
10217   output_section_asm_op (data);
10218 }
10219 
10220 
10221 /* Unnamed section callback for progmem*.data sections.  */
10222 
10223 static void
avr_output_progmem_section_asm_op(const void * data)10224 avr_output_progmem_section_asm_op (const void *data)
10225 {
10226   fprintf (asm_out_file, "\t.section\t%s,\"a\",@progbits\n",
10227            (const char*) data);
10228 }
10229 
10230 
10231 /* Implement `TARGET_ASM_INIT_SECTIONS'.  */
10232 
10233 static void
avr_asm_init_sections(void)10234 avr_asm_init_sections (void)
10235 {
10236   /* Override section callbacks to keep track of `avr_need_clear_bss_p'
10237      resp. `avr_need_copy_data_p'.  If flash is not mapped to RAM then
10238      we have also to track .rodata because it is located in RAM then.  */
10239 
10240 #if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
10241   if (avr_arch->flash_pm_offset == 0)
10242 #endif
10243     readonly_data_section->unnamed.callback = avr_output_data_section_asm_op;
10244   data_section->unnamed.callback = avr_output_data_section_asm_op;
10245   bss_section->unnamed.callback = avr_output_bss_section_asm_op;
10246 }
10247 
10248 
10249 /* Implement `TARGET_ASM_NAMED_SECTION'.  */
10250 /* Track need of __do_clear_bss, __do_copy_data for named sections.  */
10251 
10252 static void
avr_asm_named_section(const char * name,unsigned int flags,tree decl)10253 avr_asm_named_section (const char *name, unsigned int flags, tree decl)
10254 {
10255   if (flags & AVR_SECTION_PROGMEM)
10256     {
10257       addr_space_t as = (flags & AVR_SECTION_PROGMEM) / SECTION_MACH_DEP;
10258       const char *old_prefix = ".rodata";
10259       const char *new_prefix = avr_addrspace[as].section_name;
10260 
10261       if (STR_PREFIX_P (name, old_prefix))
10262         {
10263           const char *sname = ACONCAT ((new_prefix,
10264                                         name + strlen (old_prefix), NULL));
10265           default_elf_asm_named_section (sname, flags, decl);
10266           return;
10267         }
10268 
10269       default_elf_asm_named_section (new_prefix, flags, decl);
10270       return;
10271     }
10272 
10273   if (!avr_need_copy_data_p)
10274     avr_need_copy_data_p = (STR_PREFIX_P (name, ".data")
10275                             || STR_PREFIX_P (name, ".gnu.linkonce.d"));
10276 
10277   if (!avr_need_copy_data_p
10278 #if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
10279       && avr_arch->flash_pm_offset == 0
10280 #endif
10281       )
10282     avr_need_copy_data_p = (STR_PREFIX_P (name, ".rodata")
10283                             || STR_PREFIX_P (name, ".gnu.linkonce.r"));
10284 
10285   if (!avr_need_clear_bss_p)
10286     avr_need_clear_bss_p = STR_PREFIX_P (name, ".bss");
10287 
10288   default_elf_asm_named_section (name, flags, decl);
10289 }
10290 
10291 
10292 /* Implement `TARGET_SECTION_TYPE_FLAGS'.  */
10293 
10294 static unsigned int
avr_section_type_flags(tree decl,const char * name,int reloc)10295 avr_section_type_flags (tree decl, const char *name, int reloc)
10296 {
10297   unsigned int flags = default_section_type_flags (decl, name, reloc);
10298 
10299   if (STR_PREFIX_P (name, ".noinit"))
10300     {
10301       if (decl && TREE_CODE (decl) == VAR_DECL
10302 	  && DECL_INITIAL (decl) == NULL_TREE)
10303 	flags |= SECTION_BSS;  /* @nobits */
10304       else
10305 	warning (0, "only uninitialized variables can be placed in the "
10306 		 ".noinit section");
10307     }
10308 
10309   if (decl && DECL_P (decl)
10310       && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
10311     {
10312       addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
10313 
10314       /* Attribute progmem puts data in generic address space.
10315          Set section flags as if it was in __flash to get the right
10316          section prefix in the remainder.  */
10317 
10318       if (ADDR_SPACE_GENERIC_P (as))
10319         as = ADDR_SPACE_FLASH;
10320 
10321       flags |= as * SECTION_MACH_DEP;
10322       flags &= ~SECTION_WRITE;
10323       flags &= ~SECTION_BSS;
10324     }
10325 
10326   return flags;
10327 }
10328 
10329 
10330 /* A helper for the next function.  NODE is a decl that is associated with
10331    a symbol.  Return TRUE if the respective object may be accessed by LDS.
10332    There might still be other reasons for why LDS is not appropriate.
10333    This function is only appropriate for AVR_TINY.  */
10334 
10335 static bool
avr_decl_maybe_lds_p(tree node)10336 avr_decl_maybe_lds_p (tree node)
10337 {
10338   if (!node
10339       || TREE_CODE (node) != VAR_DECL
10340       || DECL_SECTION_NAME (node) != NULL)
10341     return false;
10342 
10343   /* Don't use LDS for objects that go to .rodata.  The current default
10344      linker description file still locates .rodata in RAM, but this is not
10345      a must.  A better linker script would just keep .rodata in flash and
10346      add an offset of 0x4000 to the VMA.  Hence avoid LDS for such data.  */
10347 
10348   if (TREE_READONLY (node))
10349     return false;
10350 
10351   // C++ requires peeling arrays.
10352 
10353   do
10354     node = TREE_TYPE (node);
10355   while (ARRAY_TYPE == TREE_CODE (node));
10356 
10357   return (node != error_mark_node
10358           && !TYPE_READONLY (node));
10359 }
10360 
10361 
10362 /* Implement `TARGET_ENCODE_SECTION_INFO'.  */
10363 
10364 static void
avr_encode_section_info(tree decl,rtx rtl,int new_decl_p)10365 avr_encode_section_info (tree decl, rtx rtl, int new_decl_p)
10366 {
10367   tree addr_attr = NULL_TREE;
10368 
10369   /* In avr_handle_progmem_attribute, DECL_INITIAL is not yet
10370      readily available, see PR34734.  So we postpone the warning
10371      about uninitialized data in program memory section until here.  */
10372 
10373   if (new_decl_p
10374       && decl && DECL_P (decl)
10375       && !DECL_EXTERNAL (decl)
10376       && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
10377     {
10378       if (!TREE_READONLY (decl))
10379         {
10380           // This might happen with C++ if stuff needs constructing.
10381           error ("variable %q+D with dynamic initialization put "
10382                  "into program memory area", decl);
10383         }
10384       else if (NULL_TREE == DECL_INITIAL (decl))
10385         {
10386           // Don't warn for (implicit) aliases like in PR80462.
10387           tree asmname = DECL_ASSEMBLER_NAME (decl);
10388           varpool_node *node = varpool_node::get_for_asmname (asmname);
10389           bool alias_p = node && node->alias;
10390 
10391           if (!alias_p)
10392             warning (OPT_Wuninitialized, "uninitialized variable %q+D put "
10393                      "into program memory area", decl);
10394         }
10395     }
10396 
10397   default_encode_section_info (decl, rtl, new_decl_p);
10398 
10399   if (decl && DECL_P (decl)
10400       && TREE_CODE (decl) != FUNCTION_DECL
10401       && MEM_P (rtl)
10402       && SYMBOL_REF_P (XEXP (rtl, 0)))
10403     {
10404       rtx sym = XEXP (rtl, 0);
10405       tree type = TREE_TYPE (decl);
10406       tree attr = DECL_ATTRIBUTES (decl);
10407       if (type == error_mark_node)
10408 	return;
10409 
10410       addr_space_t as = TYPE_ADDR_SPACE (type);
10411 
10412       /* PSTR strings are in generic space but located in flash:
10413          patch address space.  */
10414 
10415       if (!AVR_TINY && avr_progmem_p (decl, attr) == -1)
10416         as = ADDR_SPACE_FLASH;
10417 
10418       AVR_SYMBOL_SET_ADDR_SPACE (sym, as);
10419 
10420       tree io_low_attr = lookup_attribute ("io_low", attr);
10421       tree io_attr = lookup_attribute ("io", attr);
10422 
10423       if (io_low_attr
10424 	  && TREE_VALUE (io_low_attr) && TREE_VALUE (TREE_VALUE (io_low_attr)))
10425 	addr_attr = io_attr;
10426       else if (io_attr
10427 	       && TREE_VALUE (io_attr) && TREE_VALUE (TREE_VALUE (io_attr)))
10428 	addr_attr = io_attr;
10429       else
10430 	addr_attr = lookup_attribute ("address", attr);
10431       if (io_low_attr
10432 	  || (io_attr && addr_attr
10433               && low_io_address_operand
10434                   (GEN_INT (TREE_INT_CST_LOW
10435                             (TREE_VALUE (TREE_VALUE (addr_attr)))), QImode)))
10436 	SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO_LOW;
10437       if (io_attr || io_low_attr)
10438 	SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO;
10439       /* If we have an (io) address attribute specification, but the variable
10440 	 is external, treat the address as only a tentative definition
10441 	 to be used to determine if an io port is in the lower range, but
10442 	 don't use the exact value for constant propagation.  */
10443       if (addr_attr && !DECL_EXTERNAL (decl))
10444 	SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_ADDRESS;
10445     }
10446 
10447   if (AVR_TINY
10448       && decl
10449       && VAR_DECL == TREE_CODE (decl)
10450       && MEM_P (rtl)
10451       && SYMBOL_REF_P (XEXP (rtl, 0)))
10452     {
10453       rtx sym = XEXP (rtl, 0);
10454       bool progmem_p = avr_progmem_p (decl, DECL_ATTRIBUTES (decl)) == -1;
10455 
10456       if (progmem_p)
10457         {
10458           // Tag symbols for addition of 0x4000 (avr_arch->flash_pm_offset).
10459           SYMBOL_REF_FLAGS (sym) |= AVR_SYMBOL_FLAG_TINY_PM;
10460         }
10461 
10462       if (avr_decl_absdata_p (decl, DECL_ATTRIBUTES (decl))
10463           || (TARGET_ABSDATA
10464               && !progmem_p
10465               && !addr_attr
10466               && avr_decl_maybe_lds_p (decl))
10467           || (addr_attr
10468               // If addr_attr is non-null, it has an argument.  Peek into it.
10469               && TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (addr_attr))) < 0xc0))
10470         {
10471           // May be accessed by LDS / STS.
10472           SYMBOL_REF_FLAGS (sym) |= AVR_SYMBOL_FLAG_TINY_ABSDATA;
10473         }
10474 
10475       if (progmem_p
10476           && avr_decl_absdata_p (decl, DECL_ATTRIBUTES (decl)))
10477         {
10478           error ("%q+D has incompatible attributes %qs and %qs",
10479                  decl, "progmem", "absdata");
10480         }
10481     }
10482 }
10483 
10484 
10485 /* Implement `TARGET_ASM_SELECT_SECTION' */
10486 
10487 static section *
avr_asm_select_section(tree decl,int reloc,unsigned HOST_WIDE_INT align)10488 avr_asm_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
10489 {
10490   section * sect = default_elf_select_section (decl, reloc, align);
10491 
10492   if (decl && DECL_P (decl)
10493       && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
10494     {
10495       addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
10496 
10497       /* __progmem__ goes in generic space but shall be allocated to
10498          .progmem.data  */
10499 
10500       if (ADDR_SPACE_GENERIC_P (as))
10501         as = ADDR_SPACE_FLASH;
10502 
10503       if (sect->common.flags & SECTION_NAMED)
10504         {
10505           const char * name = sect->named.name;
10506           const char * old_prefix = ".rodata";
10507           const char * new_prefix = avr_addrspace[as].section_name;
10508 
10509           if (STR_PREFIX_P (name, old_prefix))
10510             {
10511               const char *sname = ACONCAT ((new_prefix,
10512                                             name + strlen (old_prefix), NULL));
10513               return get_section (sname,
10514                                   sect->common.flags & ~SECTION_DECLARED,
10515                                   sect->named.decl);
10516             }
10517         }
10518 
10519       if (!progmem_section[as])
10520         {
10521           progmem_section[as]
10522             = get_unnamed_section (0, avr_output_progmem_section_asm_op,
10523                                    avr_addrspace[as].section_name);
10524         }
10525 
10526       return progmem_section[as];
10527     }
10528 
10529   return sect;
10530 }
10531 
10532 /* Implement `TARGET_ASM_FILE_START'.  */
10533 /* Outputs some text at the start of each assembler file.  */
10534 
10535 static void
avr_file_start(void)10536 avr_file_start (void)
10537 {
10538   int sfr_offset = avr_arch->sfr_offset;
10539 
10540   if (avr_arch->asm_only)
10541     error ("architecture %qs supported for assembler only", avr_mmcu);
10542 
10543   default_file_start ();
10544 
10545   /* Print I/O addresses of some SFRs used with IN and OUT.  */
10546 
10547   if (AVR_HAVE_SPH)
10548     fprintf (asm_out_file, "__SP_H__ = 0x%02x\n", avr_addr.sp_h - sfr_offset);
10549 
10550   fprintf (asm_out_file, "__SP_L__ = 0x%02x\n", avr_addr.sp_l - sfr_offset);
10551   fprintf (asm_out_file, "__SREG__ = 0x%02x\n", avr_addr.sreg - sfr_offset);
10552   if (AVR_HAVE_RAMPZ)
10553     fprintf (asm_out_file, "__RAMPZ__ = 0x%02x\n", avr_addr.rampz - sfr_offset);
10554   if (AVR_HAVE_RAMPY)
10555     fprintf (asm_out_file, "__RAMPY__ = 0x%02x\n", avr_addr.rampy - sfr_offset);
10556   if (AVR_HAVE_RAMPX)
10557     fprintf (asm_out_file, "__RAMPX__ = 0x%02x\n", avr_addr.rampx - sfr_offset);
10558   if (AVR_HAVE_RAMPD)
10559     fprintf (asm_out_file, "__RAMPD__ = 0x%02x\n", avr_addr.rampd - sfr_offset);
10560   if (AVR_XMEGA || AVR_TINY)
10561     fprintf (asm_out_file, "__CCP__ = 0x%02x\n", avr_addr.ccp - sfr_offset);
10562   fprintf (asm_out_file, "__tmp_reg__ = %d\n", AVR_TMP_REGNO);
10563   fprintf (asm_out_file, "__zero_reg__ = %d\n", AVR_ZERO_REGNO);
10564 }
10565 
10566 
10567 /* Implement `TARGET_ASM_FILE_END'.  */
10568 /* Outputs to the stdio stream FILE some
10569    appropriate text to go at the end of an assembler file.  */
10570 
10571 static void
avr_file_end(void)10572 avr_file_end (void)
10573 {
10574   /* Output these only if there is anything in the
10575      .data* / .rodata* / .gnu.linkonce.* resp. .bss* or COMMON
10576      input section(s) - some code size can be saved by not
10577      linking in the initialization code from libgcc if resp.
10578      sections are empty, see PR18145.  */
10579 
10580   if (avr_need_copy_data_p)
10581     fputs (".global __do_copy_data\n", asm_out_file);
10582 
10583   if (avr_need_clear_bss_p)
10584     fputs (".global __do_clear_bss\n", asm_out_file);
10585 }
10586 
10587 
10588 /* Worker function for `ADJUST_REG_ALLOC_ORDER'.  */
10589 /* Choose the order in which to allocate hard registers for
10590    pseudo-registers local to a basic block.
10591 
10592    Store the desired register order in the array `reg_alloc_order'.
10593    Element 0 should be the register to allocate first; element 1, the
10594    next register; and so on.  */
10595 
10596 void
avr_adjust_reg_alloc_order(void)10597 avr_adjust_reg_alloc_order (void)
10598 {
10599   static const int order_0[] =
10600     {
10601       24, 25,
10602       18, 19, 20, 21, 22, 23,
10603       30, 31,
10604       26, 27, 28, 29,
10605       17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
10606       0, 1,
10607       32, 33, 34, 35
10608     };
10609   static const int tiny_order_0[] = {
10610     20, 21,
10611     22, 23,
10612     24, 25,
10613     30, 31,
10614     26, 27,
10615     28, 29,
10616     19, 18,
10617     16, 17,
10618     32, 33, 34, 35,
10619     15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
10620   };
10621   static const int order_1[] =
10622     {
10623       18, 19, 20, 21, 22, 23, 24, 25,
10624       30, 31,
10625       26, 27, 28, 29,
10626       17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
10627       0, 1,
10628       32, 33, 34, 35
10629     };
10630   static const int tiny_order_1[] = {
10631     22, 23,
10632     24, 25,
10633     30, 31,
10634     26, 27,
10635     28, 29,
10636     21, 20, 19, 18,
10637     16, 17,
10638     32, 33, 34, 35,
10639     15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
10640   };
10641   static const int order_2[] =
10642     {
10643       25, 24, 23, 22, 21, 20, 19, 18,
10644       30, 31,
10645       26, 27, 28, 29,
10646       17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
10647       1, 0,
10648       32, 33, 34, 35
10649     };
10650 
10651   /* Select specific register allocation order.
10652      Tiny Core (ATtiny4/5/9/10/20/40) devices have only 16 registers,
10653      so different allocation order should be used.  */
10654 
10655   const int *order = (TARGET_ORDER_1 ? (AVR_TINY ? tiny_order_1 : order_1)
10656                       : TARGET_ORDER_2 ? (AVR_TINY ? tiny_order_0 : order_2)
10657                       : (AVR_TINY ? tiny_order_0 : order_0));
10658 
10659   for (size_t i = 0; i < ARRAY_SIZE (order_0); ++i)
10660     reg_alloc_order[i] = order[i];
10661 }
10662 
10663 
10664 /* Implement `TARGET_REGISTER_MOVE_COST' */
10665 
10666 static int
avr_register_move_cost(machine_mode mode ATTRIBUTE_UNUSED,reg_class_t from,reg_class_t to)10667 avr_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
10668                         reg_class_t from, reg_class_t to)
10669 {
10670   return (from == STACK_REG ? 6
10671           : to == STACK_REG ? 12
10672           : 2);
10673 }
10674 
10675 
10676 /* Implement `TARGET_MEMORY_MOVE_COST' */
10677 
10678 static int
avr_memory_move_cost(machine_mode mode,reg_class_t rclass ATTRIBUTE_UNUSED,bool in ATTRIBUTE_UNUSED)10679 avr_memory_move_cost (machine_mode mode,
10680                       reg_class_t rclass ATTRIBUTE_UNUSED,
10681                       bool in ATTRIBUTE_UNUSED)
10682 {
10683   return (mode == QImode ? 2
10684           : mode == HImode ? 4
10685           : mode == SImode ? 8
10686           : mode == SFmode ? 8
10687           : 16);
10688 }
10689 
10690 
10691 /* Cost for mul highpart.  X is a LSHIFTRT, i.e. the outer TRUNCATE is
10692    already stripped off.  */
10693 
10694 static int
avr_mul_highpart_cost(rtx x,int)10695 avr_mul_highpart_cost (rtx x, int)
10696 {
10697   if (AVR_HAVE_MUL
10698       && LSHIFTRT == GET_CODE (x)
10699       && MULT == GET_CODE (XEXP (x, 0))
10700       && CONST_INT_P (XEXP (x, 1)))
10701     {
10702       // This is the wider mode.
10703       machine_mode mode = GET_MODE (x);
10704 
10705       // The middle-end might still have PR81444, i.e. it is calling the cost
10706       // functions with strange modes.  Fix this now by also considering
10707       // PSImode (should actually be SImode instead).
10708       if (HImode == mode || PSImode == mode || SImode == mode)
10709         {
10710           return COSTS_N_INSNS (2);
10711         }
10712     }
10713 
10714   return 10000;
10715 }
10716 
10717 
10718 /* Mutually recursive subroutine of avr_rtx_cost for calculating the
10719    cost of an RTX operand given its context.  X is the rtx of the
10720    operand, MODE is its mode, and OUTER is the rtx_code of this
10721    operand's parent operator.  */
10722 
10723 static int
avr_operand_rtx_cost(rtx x,machine_mode mode,enum rtx_code outer,int opno,bool speed)10724 avr_operand_rtx_cost (rtx x, machine_mode mode, enum rtx_code outer,
10725 		      int opno, bool speed)
10726 {
10727   enum rtx_code code = GET_CODE (x);
10728   int total;
10729 
10730   switch (code)
10731     {
10732     case REG:
10733     case SUBREG:
10734       return 0;
10735 
10736     case CONST_INT:
10737     case CONST_FIXED:
10738     case CONST_DOUBLE:
10739       return COSTS_N_INSNS (GET_MODE_SIZE (mode));
10740 
10741     default:
10742       break;
10743     }
10744 
10745   total = 0;
10746   avr_rtx_costs (x, mode, outer, opno, &total, speed);
10747   return total;
10748 }
10749 
10750 /* Worker function for AVR backend's rtx_cost function.
10751    X is rtx expression whose cost is to be calculated.
10752    Return true if the complete cost has been computed.
10753    Return false if subexpressions should be scanned.
10754    In either case, *TOTAL contains the cost result.  */
10755 
10756 static bool
avr_rtx_costs_1(rtx x,machine_mode mode,int outer_code,int opno ATTRIBUTE_UNUSED,int * total,bool speed)10757 avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
10758                  int opno ATTRIBUTE_UNUSED, int *total, bool speed)
10759 {
10760   enum rtx_code code = GET_CODE (x);
10761   HOST_WIDE_INT val;
10762 
10763   switch (code)
10764     {
10765     case CONST_INT:
10766     case CONST_FIXED:
10767     case CONST_DOUBLE:
10768     case SYMBOL_REF:
10769     case CONST:
10770     case LABEL_REF:
10771       /* Immediate constants are as cheap as registers.  */
10772       *total = 0;
10773       return true;
10774 
10775     case MEM:
10776       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10777       return true;
10778 
10779     case NEG:
10780       switch (mode)
10781 	{
10782 	case E_QImode:
10783 	case E_SFmode:
10784 	  *total = COSTS_N_INSNS (1);
10785 	  break;
10786 
10787         case E_HImode:
10788         case E_PSImode:
10789         case E_SImode:
10790           *total = COSTS_N_INSNS (2 * GET_MODE_SIZE (mode) - 1);
10791           break;
10792 
10793 	default:
10794 	  return false;
10795 	}
10796       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10797       return true;
10798 
10799     case ABS:
10800       switch (mode)
10801 	{
10802 	case E_QImode:
10803 	case E_SFmode:
10804 	  *total = COSTS_N_INSNS (1);
10805 	  break;
10806 
10807 	default:
10808 	  return false;
10809 	}
10810       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10811       return true;
10812 
10813     case NOT:
10814       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10815       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10816       return true;
10817 
10818     case ZERO_EXTEND:
10819       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
10820 			      - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
10821       *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
10822 				      code, 0, speed);
10823       return true;
10824 
10825     case SIGN_EXTEND:
10826       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
10827 			      - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
10828       *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
10829 				      code, 0, speed);
10830       return true;
10831 
10832     case PLUS:
10833       switch (mode)
10834 	{
10835 	case E_QImode:
10836           if (AVR_HAVE_MUL
10837               && MULT == GET_CODE (XEXP (x, 0))
10838               && register_operand (XEXP (x, 1), QImode))
10839             {
10840               /* multiply-add */
10841               *total = COSTS_N_INSNS (speed ? 4 : 3);
10842               /* multiply-add with constant: will be split and load constant. */
10843               if (CONST_INT_P (XEXP (XEXP (x, 0), 1)))
10844                 *total = COSTS_N_INSNS (1) + *total;
10845               return true;
10846             }
10847 	  *total = COSTS_N_INSNS (1);
10848 	  if (!CONST_INT_P (XEXP (x, 1)))
10849 	    *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10850 	  break;
10851 
10852 	case E_HImode:
10853           if (AVR_HAVE_MUL
10854               && (MULT == GET_CODE (XEXP (x, 0))
10855                   || ASHIFT == GET_CODE (XEXP (x, 0)))
10856               && register_operand (XEXP (x, 1), HImode)
10857               && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))
10858                   || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))))
10859             {
10860               /* multiply-add */
10861               *total = COSTS_N_INSNS (speed ? 5 : 4);
10862               /* multiply-add with constant: will be split and load constant. */
10863               if (CONST_INT_P (XEXP (XEXP (x, 0), 1)))
10864                 *total = COSTS_N_INSNS (1) + *total;
10865               return true;
10866             }
10867 	  if (!CONST_INT_P (XEXP (x, 1)))
10868 	    {
10869 	      *total = COSTS_N_INSNS (2);
10870 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10871 					      speed);
10872 	    }
10873 	  else if (IN_RANGE (INTVAL (XEXP (x, 1)), -63, 63))
10874 	    *total = COSTS_N_INSNS (1);
10875 	  else
10876 	    *total = COSTS_N_INSNS (2);
10877 	  break;
10878 
10879         case E_PSImode:
10880           if (!CONST_INT_P (XEXP (x, 1)))
10881             {
10882               *total = COSTS_N_INSNS (3);
10883               *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10884                                               speed);
10885             }
10886           else if (IN_RANGE (INTVAL (XEXP (x, 1)), -63, 63))
10887             *total = COSTS_N_INSNS (2);
10888           else
10889             *total = COSTS_N_INSNS (3);
10890           break;
10891 
10892 	case E_SImode:
10893 	  if (!CONST_INT_P (XEXP (x, 1)))
10894 	    {
10895 	      *total = COSTS_N_INSNS (4);
10896 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10897 					      speed);
10898 	    }
10899 	  else if (IN_RANGE (INTVAL (XEXP (x, 1)), -63, 63))
10900 	    *total = COSTS_N_INSNS (1);
10901 	  else
10902 	    *total = COSTS_N_INSNS (4);
10903 	  break;
10904 
10905 	default:
10906 	  return false;
10907 	}
10908       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10909       return true;
10910 
10911     case MINUS:
10912       if (AVR_HAVE_MUL
10913           && QImode == mode
10914           && register_operand (XEXP (x, 0), QImode)
10915           && MULT == GET_CODE (XEXP (x, 1)))
10916         {
10917           /* multiply-sub */
10918           *total = COSTS_N_INSNS (speed ? 4 : 3);
10919           /* multiply-sub with constant: will be split and load constant. */
10920           if (CONST_INT_P (XEXP (XEXP (x, 1), 1)))
10921             *total = COSTS_N_INSNS (1) + *total;
10922           return true;
10923         }
10924       if (AVR_HAVE_MUL
10925           && HImode == mode
10926           && register_operand (XEXP (x, 0), HImode)
10927           && (MULT == GET_CODE (XEXP (x, 1))
10928               || ASHIFT == GET_CODE (XEXP (x, 1)))
10929           && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))
10930               || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))))
10931         {
10932           /* multiply-sub */
10933           *total = COSTS_N_INSNS (speed ? 5 : 4);
10934           /* multiply-sub with constant: will be split and load constant. */
10935           if (CONST_INT_P (XEXP (XEXP (x, 1), 1)))
10936             *total = COSTS_N_INSNS (1) + *total;
10937           return true;
10938         }
10939       /* FALLTHRU */
10940     case AND:
10941     case IOR:
10942       if (IOR == code
10943           && HImode == mode
10944           && ASHIFT == GET_CODE (XEXP (x, 0)))
10945         {
10946           *total = COSTS_N_INSNS (2);
10947           // Just a rough estimate.  If we see no sign- or zero-extend,
10948           // then increase the cost a little bit.
10949           if (REG_P (XEXP (XEXP (x, 0), 0)))
10950             *total += COSTS_N_INSNS (1);
10951           if (REG_P (XEXP (x, 1)))
10952             *total += COSTS_N_INSNS (1);
10953           return true;
10954         }
10955       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10956       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10957       if (!CONST_INT_P (XEXP (x, 1)))
10958 	*total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10959       return true;
10960 
10961     case XOR:
10962       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10963       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10964       *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10965       return true;
10966 
10967     case MULT:
10968       switch (mode)
10969 	{
10970 	case E_QImode:
10971 	  if (AVR_HAVE_MUL)
10972 	    *total = COSTS_N_INSNS (!speed ? 3 : 4);
10973 	  else if (!speed)
10974 	    *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
10975 	  else
10976 	    return false;
10977 	  break;
10978 
10979 	case E_HImode:
10980 	  if (AVR_HAVE_MUL)
10981             {
10982               rtx op0 = XEXP (x, 0);
10983               rtx op1 = XEXP (x, 1);
10984               enum rtx_code code0 = GET_CODE (op0);
10985               enum rtx_code code1 = GET_CODE (op1);
10986               bool ex0 = SIGN_EXTEND == code0 || ZERO_EXTEND == code0;
10987               bool ex1 = SIGN_EXTEND == code1 || ZERO_EXTEND == code1;
10988 
10989               if (ex0
10990                   && (u8_operand (op1, HImode)
10991                       || s8_operand (op1, HImode)))
10992                 {
10993                   *total = COSTS_N_INSNS (!speed ? 4 : 6);
10994                   return true;
10995                 }
10996               if (ex0
10997                   && register_operand (op1, HImode))
10998                 {
10999                   *total = COSTS_N_INSNS (!speed ? 5 : 8);
11000                   return true;
11001                 }
11002               else if (ex0 || ex1)
11003                 {
11004                   *total = COSTS_N_INSNS (!speed ? 3 : 5);
11005                   return true;
11006                 }
11007               else if (register_operand (op0, HImode)
11008                        && (u8_operand (op1, HImode)
11009                            || s8_operand (op1, HImode)))
11010                 {
11011                   *total = COSTS_N_INSNS (!speed ? 6 : 9);
11012                   return true;
11013                 }
11014               else
11015                 *total = COSTS_N_INSNS (!speed ? 7 : 10);
11016             }
11017 	  else if (!speed)
11018 	    *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
11019 	  else
11020 	    return false;
11021 	  break;
11022 
11023         case E_PSImode:
11024           if (!speed)
11025             *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
11026           else
11027             *total = 10;
11028           break;
11029 
11030 	case E_SImode:
11031 	case E_DImode:
11032 	  if (AVR_HAVE_MUL)
11033             {
11034               if (!speed)
11035                 {
11036                   /* Add some additional costs besides CALL like moves etc.  */
11037 
11038                   *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
11039                 }
11040               else
11041                 {
11042                   /* Just a rough estimate.  Even with -O2 we don't want bulky
11043                      code expanded inline.  */
11044 
11045                   *total = COSTS_N_INSNS (25);
11046                 }
11047             }
11048           else
11049             {
11050               if (speed)
11051                 *total = COSTS_N_INSNS (300);
11052               else
11053                 /* Add some additional costs besides CALL like moves etc.  */
11054                 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
11055             }
11056 
11057 	  if (mode == DImode)
11058 	    *total *= 2;
11059 
11060 	  return true;
11061 
11062 	default:
11063 	  return false;
11064 	}
11065       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11066       *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
11067       return true;
11068 
11069     case DIV:
11070     case MOD:
11071     case UDIV:
11072     case UMOD:
11073       if (!speed)
11074         *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
11075       else
11076         *total = COSTS_N_INSNS (15 * GET_MODE_SIZE (mode));
11077       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11078       /* For div/mod with const-int divisor we have at least the cost of
11079          loading the divisor. */
11080       if (CONST_INT_P (XEXP (x, 1)))
11081         *total += COSTS_N_INSNS (GET_MODE_SIZE (mode));
11082       /* Add some overall penaly for clobbering and moving around registers */
11083       *total += COSTS_N_INSNS (2);
11084       return true;
11085 
11086     case ROTATE:
11087       switch (mode)
11088 	{
11089 	case E_QImode:
11090 	  if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 4)
11091 	    *total = COSTS_N_INSNS (1);
11092 
11093 	  break;
11094 
11095 	case E_HImode:
11096 	  if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 8)
11097 	    *total = COSTS_N_INSNS (3);
11098 
11099 	  break;
11100 
11101 	case E_SImode:
11102 	  if (CONST_INT_P (XEXP (x, 1)))
11103 	    switch (INTVAL (XEXP (x, 1)))
11104 	      {
11105 	      case 8:
11106 	      case 24:
11107 		*total = COSTS_N_INSNS (5);
11108 		break;
11109 	      case 16:
11110 		*total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 6);
11111 		break;
11112 	      }
11113 	  break;
11114 
11115 	default:
11116 	  return false;
11117 	}
11118       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11119       return true;
11120 
11121     case ASHIFT:
11122       switch (mode)
11123 	{
11124 	case E_QImode:
11125 	  if (!CONST_INT_P (XEXP (x, 1)))
11126 	    {
11127 	      *total = COSTS_N_INSNS (!speed ? 4 : 17);
11128 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11129 					      speed);
11130 	    }
11131 	  else
11132 	    {
11133 	      val = INTVAL (XEXP (x, 1));
11134 	      if (val == 7)
11135 		*total = COSTS_N_INSNS (3);
11136 	      else if (val >= 0 && val <= 7)
11137 		*total = COSTS_N_INSNS (val);
11138 	      else
11139 		*total = COSTS_N_INSNS (1);
11140 	    }
11141 	  break;
11142 
11143 	case E_HImode:
11144           if (AVR_HAVE_MUL)
11145             {
11146               if (const_2_to_7_operand (XEXP (x, 1), HImode)
11147                   && (SIGN_EXTEND == GET_CODE (XEXP (x, 0))
11148                       || ZERO_EXTEND == GET_CODE (XEXP (x, 0))))
11149                 {
11150                   *total = COSTS_N_INSNS (!speed ? 4 : 6);
11151                   return true;
11152                 }
11153             }
11154 
11155           if (const1_rtx == (XEXP (x, 1))
11156               && SIGN_EXTEND == GET_CODE (XEXP (x, 0)))
11157             {
11158               *total = COSTS_N_INSNS (2);
11159               return true;
11160             }
11161 
11162 	  if (!CONST_INT_P (XEXP (x, 1)))
11163 	    {
11164 	      *total = COSTS_N_INSNS (!speed ? 5 : 41);
11165 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11166 					      speed);
11167 	    }
11168 	  else
11169 	    switch (INTVAL (XEXP (x, 1)))
11170 	      {
11171 	      case 0:
11172 		*total = 0;
11173 		break;
11174 	      case 1:
11175 	      case 8:
11176 		*total = COSTS_N_INSNS (2);
11177 		break;
11178 	      case 9:
11179 		*total = COSTS_N_INSNS (3);
11180 		break;
11181 	      case 2:
11182 	      case 3:
11183 	      case 10:
11184 	      case 15:
11185 		*total = COSTS_N_INSNS (4);
11186 		break;
11187 	      case 7:
11188 	      case 11:
11189 	      case 12:
11190 		*total = COSTS_N_INSNS (5);
11191 		break;
11192 	      case 4:
11193 		*total = COSTS_N_INSNS (!speed ? 5 : 8);
11194 		break;
11195 	      case 6:
11196 		*total = COSTS_N_INSNS (!speed ? 5 : 9);
11197 		break;
11198 	      case 5:
11199 		*total = COSTS_N_INSNS (!speed ? 5 : 10);
11200 		break;
11201 	      default:
11202 	        *total = COSTS_N_INSNS (!speed ? 5 : 41);
11203 	        *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11204 						speed);
11205 	      }
11206 	  break;
11207 
11208         case E_PSImode:
11209           if (!CONST_INT_P (XEXP (x, 1)))
11210             {
11211               *total = COSTS_N_INSNS (!speed ? 6 : 73);
11212             }
11213           else
11214             switch (INTVAL (XEXP (x, 1)))
11215               {
11216               case 0:
11217                 *total = 0;
11218                 break;
11219               case 1:
11220               case 8:
11221               case 16:
11222                 *total = COSTS_N_INSNS (3);
11223                 break;
11224               case 23:
11225                 *total = COSTS_N_INSNS (5);
11226                 break;
11227               default:
11228                 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
11229                 break;
11230               }
11231           break;
11232 
11233 	case E_SImode:
11234 	  if (!CONST_INT_P (XEXP (x, 1)))
11235 	    {
11236 	      *total = COSTS_N_INSNS (!speed ? 7 : 113);
11237 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11238 					      speed);
11239 	    }
11240 	  else
11241 	    switch (INTVAL (XEXP (x, 1)))
11242 	      {
11243 	      case 0:
11244 		*total = 0;
11245 		break;
11246 	      case 24:
11247 		*total = COSTS_N_INSNS (3);
11248 		break;
11249 	      case 1:
11250 	      case 8:
11251 	      case 16:
11252 		*total = COSTS_N_INSNS (4);
11253 		break;
11254 	      case 31:
11255 		*total = COSTS_N_INSNS (6);
11256 		break;
11257 	      case 2:
11258 		*total = COSTS_N_INSNS (!speed ? 7 : 8);
11259 		break;
11260 	      default:
11261 		*total = COSTS_N_INSNS (!speed ? 7 : 113);
11262 		*total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11263 						speed);
11264 	      }
11265 	  break;
11266 
11267 	default:
11268 	  return false;
11269 	}
11270       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11271       return true;
11272 
11273     case ASHIFTRT:
11274       switch (mode)
11275 	{
11276 	case E_QImode:
11277 	  if (!CONST_INT_P (XEXP (x, 1)))
11278 	    {
11279 	      *total = COSTS_N_INSNS (!speed ? 4 : 17);
11280 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11281 					      speed);
11282 	    }
11283 	  else
11284 	    {
11285 	      val = INTVAL (XEXP (x, 1));
11286 	      if (val == 6)
11287 		*total = COSTS_N_INSNS (4);
11288 	      else if (val == 7)
11289 		*total = COSTS_N_INSNS (2);
11290 	      else if (val >= 0 && val <= 7)
11291 		*total = COSTS_N_INSNS (val);
11292 	      else
11293 		*total = COSTS_N_INSNS (1);
11294 	    }
11295 	  break;
11296 
11297 	case E_HImode:
11298 	  if (!CONST_INT_P (XEXP (x, 1)))
11299 	    {
11300 	      *total = COSTS_N_INSNS (!speed ? 5 : 41);
11301 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11302 					      speed);
11303 	    }
11304 	  else
11305 	    switch (INTVAL (XEXP (x, 1)))
11306 	      {
11307 	      case 0:
11308 		*total = 0;
11309 		break;
11310 	      case 1:
11311 		*total = COSTS_N_INSNS (2);
11312 		break;
11313 	      case 15:
11314 		*total = COSTS_N_INSNS (3);
11315 		break;
11316 	      case 2:
11317 	      case 7:
11318               case 8:
11319               case 9:
11320 		*total = COSTS_N_INSNS (4);
11321 		break;
11322               case 10:
11323 	      case 14:
11324 		*total = COSTS_N_INSNS (5);
11325 		break;
11326               case 11:
11327                 *total = COSTS_N_INSNS (!speed ? 5 : 6);
11328 		break;
11329               case 12:
11330                 *total = COSTS_N_INSNS (!speed ? 5 : 7);
11331 		break;
11332               case 6:
11333 	      case 13:
11334                 *total = COSTS_N_INSNS (!speed ? 5 : 8);
11335 		break;
11336 	      default:
11337 	        *total = COSTS_N_INSNS (!speed ? 5 : 41);
11338 	        *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11339 						speed);
11340 	      }
11341 	  break;
11342 
11343         case E_PSImode:
11344           if (!CONST_INT_P (XEXP (x, 1)))
11345             {
11346               *total = COSTS_N_INSNS (!speed ? 6 : 73);
11347             }
11348           else
11349             switch (INTVAL (XEXP (x, 1)))
11350               {
11351               case 0:
11352                 *total = 0;
11353                 break;
11354               case 1:
11355                 *total = COSTS_N_INSNS (3);
11356                 break;
11357               case 16:
11358               case 8:
11359                 *total = COSTS_N_INSNS (5);
11360                 break;
11361               case 23:
11362                 *total = COSTS_N_INSNS (4);
11363                 break;
11364               default:
11365                 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
11366                 break;
11367               }
11368           break;
11369 
11370 	case E_SImode:
11371 	  if (!CONST_INT_P (XEXP (x, 1)))
11372 	    {
11373 	      *total = COSTS_N_INSNS (!speed ? 7 : 113);
11374 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11375 					      speed);
11376 	    }
11377 	  else
11378 	    switch (INTVAL (XEXP (x, 1)))
11379 	      {
11380 	      case 0:
11381 		*total = 0;
11382 		break;
11383 	      case 1:
11384 		*total = COSTS_N_INSNS (4);
11385 		break;
11386 	      case 8:
11387 	      case 16:
11388 	      case 24:
11389 		*total = COSTS_N_INSNS (6);
11390 		break;
11391 	      case 2:
11392 		*total = COSTS_N_INSNS (!speed ? 7 : 8);
11393 		break;
11394 	      case 31:
11395 		*total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 5);
11396 		break;
11397 	      default:
11398 		*total = COSTS_N_INSNS (!speed ? 7 : 113);
11399 		*total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11400 						speed);
11401 	      }
11402 	  break;
11403 
11404 	default:
11405 	  return false;
11406 	}
11407       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11408       return true;
11409 
11410     case LSHIFTRT:
11411       if (outer_code == TRUNCATE)
11412         {
11413           *total = avr_mul_highpart_cost (x, speed);
11414           return true;
11415         }
11416 
11417       switch (mode)
11418 	{
11419 	case E_QImode:
11420 	  if (!CONST_INT_P (XEXP (x, 1)))
11421 	    {
11422 	      *total = COSTS_N_INSNS (!speed ? 4 : 17);
11423 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11424 					      speed);
11425 	    }
11426 	  else
11427 	    {
11428 	      val = INTVAL (XEXP (x, 1));
11429 	      if (val == 7)
11430 		*total = COSTS_N_INSNS (3);
11431 	      else if (val >= 0 && val <= 7)
11432 		*total = COSTS_N_INSNS (val);
11433 	      else
11434 		*total = COSTS_N_INSNS (1);
11435 	    }
11436 	  break;
11437 
11438 	case E_HImode:
11439 	  if (!CONST_INT_P (XEXP (x, 1)))
11440 	    {
11441 	      *total = COSTS_N_INSNS (!speed ? 5 : 41);
11442 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11443 					      speed);
11444 	    }
11445 	  else
11446 	    switch (INTVAL (XEXP (x, 1)))
11447 	      {
11448 	      case 0:
11449 		*total = 0;
11450 		break;
11451 	      case 1:
11452 	      case 8:
11453 		*total = COSTS_N_INSNS (2);
11454 		break;
11455 	      case 9:
11456 		*total = COSTS_N_INSNS (3);
11457 		break;
11458 	      case 2:
11459 	      case 10:
11460 	      case 15:
11461 		*total = COSTS_N_INSNS (4);
11462 		break;
11463 	      case 7:
11464               case 11:
11465 		*total = COSTS_N_INSNS (5);
11466 		break;
11467 	      case 3:
11468 	      case 12:
11469 	      case 13:
11470 	      case 14:
11471 		*total = COSTS_N_INSNS (!speed ? 5 : 6);
11472 		break;
11473 	      case 4:
11474 		*total = COSTS_N_INSNS (!speed ? 5 : 7);
11475 		break;
11476 	      case 5:
11477 	      case 6:
11478 		*total = COSTS_N_INSNS (!speed ? 5 : 9);
11479 		break;
11480 	      default:
11481 	        *total = COSTS_N_INSNS (!speed ? 5 : 41);
11482 	        *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11483 						speed);
11484 	      }
11485 	  break;
11486 
11487         case E_PSImode:
11488           if (!CONST_INT_P (XEXP (x, 1)))
11489             {
11490               *total = COSTS_N_INSNS (!speed ? 6 : 73);
11491             }
11492           else
11493             switch (INTVAL (XEXP (x, 1)))
11494               {
11495               case 0:
11496                 *total = 0;
11497                 break;
11498               case 1:
11499               case 8:
11500               case 16:
11501                 *total = COSTS_N_INSNS (3);
11502                 break;
11503               case 23:
11504                 *total = COSTS_N_INSNS (5);
11505                 break;
11506               default:
11507                 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
11508                 break;
11509               }
11510           break;
11511 
11512 	case E_SImode:
11513 	  if (!CONST_INT_P (XEXP (x, 1)))
11514 	    {
11515 	      *total = COSTS_N_INSNS (!speed ? 7 : 113);
11516 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11517 					      speed);
11518 	    }
11519 	  else
11520 	    switch (INTVAL (XEXP (x, 1)))
11521 	      {
11522 	      case 0:
11523 		*total = 0;
11524 		break;
11525 	      case 1:
11526 		*total = COSTS_N_INSNS (4);
11527 		break;
11528 	      case 2:
11529 		*total = COSTS_N_INSNS (!speed ? 7 : 8);
11530 		break;
11531 	      case 8:
11532 	      case 16:
11533 	      case 24:
11534 		*total = COSTS_N_INSNS (4);
11535 		break;
11536 	      case 31:
11537 		*total = COSTS_N_INSNS (6);
11538 		break;
11539 	      default:
11540 		*total = COSTS_N_INSNS (!speed ? 7 : 113);
11541 		*total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11542 						speed);
11543 	      }
11544 	  break;
11545 
11546 	default:
11547 	  return false;
11548 	}
11549       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11550       return true;
11551 
11552     case COMPARE:
11553       switch (GET_MODE (XEXP (x, 0)))
11554 	{
11555 	case E_QImode:
11556 	  *total = COSTS_N_INSNS (1);
11557 	  if (!CONST_INT_P (XEXP (x, 1)))
11558 	    *total += avr_operand_rtx_cost (XEXP (x, 1), QImode, code,
11559 					    1, speed);
11560 	  break;
11561 
11562         case E_HImode:
11563 	  *total = COSTS_N_INSNS (2);
11564 	  if (!CONST_INT_P (XEXP (x, 1)))
11565             *total += avr_operand_rtx_cost (XEXP (x, 1), HImode, code,
11566 					    1, speed);
11567 	  else if (INTVAL (XEXP (x, 1)) != 0)
11568 	    *total += COSTS_N_INSNS (1);
11569           break;
11570 
11571         case E_PSImode:
11572           *total = COSTS_N_INSNS (3);
11573           if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) != 0)
11574             *total += COSTS_N_INSNS (2);
11575           break;
11576 
11577         case E_SImode:
11578           *total = COSTS_N_INSNS (4);
11579           if (!CONST_INT_P (XEXP (x, 1)))
11580             *total += avr_operand_rtx_cost (XEXP (x, 1), SImode, code,
11581 					    1, speed);
11582 	  else if (INTVAL (XEXP (x, 1)) != 0)
11583 	    *total += COSTS_N_INSNS (3);
11584           break;
11585 
11586 	default:
11587 	  return false;
11588 	}
11589       *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
11590 				      code, 0, speed);
11591       return true;
11592 
11593     case TRUNCATE:
11594       if (LSHIFTRT == GET_CODE (XEXP (x, 0)))
11595         {
11596           *total = avr_mul_highpart_cost (XEXP (x, 0), speed);
11597           return true;
11598         }
11599       break;
11600 
11601     default:
11602       break;
11603     }
11604   return false;
11605 }
11606 
11607 
11608 /* Implement `TARGET_RTX_COSTS'.  */
11609 
11610 static bool
avr_rtx_costs(rtx x,machine_mode mode,int outer_code,int opno,int * total,bool speed)11611 avr_rtx_costs (rtx x, machine_mode mode, int outer_code,
11612 	       int opno, int *total, bool speed)
11613 {
11614   bool done = avr_rtx_costs_1 (x, mode, outer_code, opno, total, speed);
11615 
11616   if (avr_log.rtx_costs)
11617     {
11618       avr_edump ("\n%?=%b (%s) total=%d, outer=%C:\n%r\n",
11619                  done, speed ? "speed" : "size", *total, outer_code, x);
11620     }
11621 
11622   return done;
11623 }
11624 
11625 
11626 /* Implement `TARGET_ADDRESS_COST'.  */
11627 
11628 static int
avr_address_cost(rtx x,machine_mode mode ATTRIBUTE_UNUSED,addr_space_t as ATTRIBUTE_UNUSED,bool speed ATTRIBUTE_UNUSED)11629 avr_address_cost (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
11630                   addr_space_t as ATTRIBUTE_UNUSED,
11631                   bool speed ATTRIBUTE_UNUSED)
11632 {
11633   int cost = 4;
11634 
11635   if (GET_CODE (x) == PLUS
11636       && CONST_INT_P (XEXP (x, 1))
11637       && (REG_P (XEXP (x, 0))
11638           || SUBREG_P (XEXP (x, 0))))
11639     {
11640       if (INTVAL (XEXP (x, 1)) > MAX_LD_OFFSET(mode))
11641         cost = 18;
11642     }
11643   else if (CONSTANT_ADDRESS_P (x))
11644     {
11645       if (io_address_operand (x, QImode))
11646         cost = 2;
11647 
11648       if (AVR_TINY
11649           && avr_address_tiny_absdata_p (x, QImode))
11650         cost = 2;
11651     }
11652 
11653   if (avr_log.address_cost)
11654     avr_edump ("\n%?: %d = %r\n", cost, x);
11655 
11656   return cost;
11657 }
11658 
11659 /* Test for extra memory constraint 'Q'.
11660    It's a memory address based on Y or Z pointer with valid displacement.  */
11661 
11662 int
extra_constraint_Q(rtx x)11663 extra_constraint_Q (rtx x)
11664 {
11665   int ok = 0;
11666   rtx plus = XEXP (x, 0);
11667 
11668   if (GET_CODE (plus) == PLUS
11669       && REG_P (XEXP (plus, 0))
11670       && CONST_INT_P (XEXP (plus, 1))
11671       && (INTVAL (XEXP (plus, 1))
11672 	  <= MAX_LD_OFFSET (GET_MODE (x))))
11673     {
11674       rtx xx = XEXP (plus, 0);
11675       int regno = REGNO (xx);
11676 
11677       ok = (/* allocate pseudos */
11678             regno >= FIRST_PSEUDO_REGISTER
11679             /* strictly check */
11680             || regno == REG_Z || regno == REG_Y
11681             /* XXX frame & arg pointer checks */
11682             || xx == frame_pointer_rtx
11683             || xx == arg_pointer_rtx);
11684 
11685       if (avr_log.constraints)
11686         avr_edump ("\n%?=%d reload_completed=%d reload_in_progress=%d\n %r\n",
11687                    ok, reload_completed, reload_in_progress, x);
11688     }
11689 
11690   return ok;
11691 }
11692 
11693 /* Convert condition code CONDITION to the valid AVR condition code.  */
11694 
11695 RTX_CODE
avr_normalize_condition(RTX_CODE condition)11696 avr_normalize_condition (RTX_CODE condition)
11697 {
11698   switch (condition)
11699     {
11700     case GT:
11701       return GE;
11702     case GTU:
11703       return GEU;
11704     case LE:
11705       return LT;
11706     case LEU:
11707       return LTU;
11708     default:
11709       gcc_unreachable ();
11710     }
11711 }
11712 
11713 /* Helper function for `avr_reorg'.  */
11714 
11715 static rtx
avr_compare_pattern(rtx_insn * insn)11716 avr_compare_pattern (rtx_insn *insn)
11717 {
11718   rtx pattern = single_set (insn);
11719 
11720   if (pattern
11721       && NONJUMP_INSN_P (insn)
11722       && SET_DEST (pattern) == cc0_rtx
11723       && GET_CODE (SET_SRC (pattern)) == COMPARE)
11724     {
11725       machine_mode mode0 = GET_MODE (XEXP (SET_SRC (pattern), 0));
11726       machine_mode mode1 = GET_MODE (XEXP (SET_SRC (pattern), 1));
11727 
11728       /* The 64-bit comparisons have fixed operands ACC_A and ACC_B.
11729          They must not be swapped, thus skip them.  */
11730 
11731       if ((mode0 == VOIDmode || GET_MODE_SIZE (mode0) <= 4)
11732           && (mode1 == VOIDmode || GET_MODE_SIZE (mode1) <= 4))
11733         return pattern;
11734     }
11735 
11736   return NULL_RTX;
11737 }
11738 
11739 /* Helper function for `avr_reorg'.  */
11740 
11741 /* Expansion of switch/case decision trees leads to code like
11742 
11743        cc0 = compare (Reg, Num)
11744        if (cc0 == 0)
11745          goto L1
11746 
11747        cc0 = compare (Reg, Num)
11748        if (cc0 > 0)
11749          goto L2
11750 
11751    The second comparison is superfluous and can be deleted.
11752    The second jump condition can be transformed from a
11753    "difficult" one to a "simple" one because "cc0 > 0" and
11754    "cc0 >= 0" will have the same effect here.
11755 
11756    This function relies on the way switch/case is being expaned
11757    as binary decision tree.  For example code see PR 49903.
11758 
11759    Return TRUE if optimization performed.
11760    Return FALSE if nothing changed.
11761 
11762    INSN1 is a comparison, i.e. avr_compare_pattern != 0.
11763 
11764    We don't want to do this in text peephole because it is
11765    tedious to work out jump offsets there and the second comparison
11766    might have been transormed by `avr_reorg'.
11767 
11768    RTL peephole won't do because peephole2 does not scan across
11769    basic blocks.  */
11770 
11771 static bool
avr_reorg_remove_redundant_compare(rtx_insn * insn1)11772 avr_reorg_remove_redundant_compare (rtx_insn *insn1)
11773 {
11774   rtx comp1, ifelse1, xcond1;
11775   rtx_insn *branch1;
11776   rtx comp2, ifelse2, xcond2;
11777   rtx_insn *branch2, *insn2;
11778   enum rtx_code code;
11779   rtx_insn *jump;
11780   rtx target, cond;
11781 
11782   /* Look out for:  compare1 - branch1 - compare2 - branch2  */
11783 
11784   branch1 = next_nonnote_nondebug_insn (insn1);
11785   if (!branch1 || !JUMP_P (branch1))
11786     return false;
11787 
11788   insn2 = next_nonnote_nondebug_insn (branch1);
11789   if (!insn2 || !avr_compare_pattern (insn2))
11790     return false;
11791 
11792   branch2 = next_nonnote_nondebug_insn (insn2);
11793   if (!branch2 || !JUMP_P (branch2))
11794     return false;
11795 
11796   comp1 = avr_compare_pattern (insn1);
11797   comp2 = avr_compare_pattern (insn2);
11798   xcond1 = single_set (branch1);
11799   xcond2 = single_set (branch2);
11800 
11801   if (!comp1 || !comp2
11802       || !rtx_equal_p (comp1, comp2)
11803       || !xcond1 || SET_DEST (xcond1) != pc_rtx
11804       || !xcond2 || SET_DEST (xcond2) != pc_rtx
11805       || IF_THEN_ELSE != GET_CODE (SET_SRC (xcond1))
11806       || IF_THEN_ELSE != GET_CODE (SET_SRC (xcond2)))
11807     {
11808       return false;
11809     }
11810 
11811   comp1 = SET_SRC (comp1);
11812   ifelse1 = SET_SRC (xcond1);
11813   ifelse2 = SET_SRC (xcond2);
11814 
11815   /* comp<n> is COMPARE now and ifelse<n> is IF_THEN_ELSE.  */
11816 
11817   if (EQ != GET_CODE (XEXP (ifelse1, 0))
11818       || !REG_P (XEXP (comp1, 0))
11819       || !CONST_INT_P (XEXP (comp1, 1))
11820       || XEXP (ifelse1, 2) != pc_rtx
11821       || XEXP (ifelse2, 2) != pc_rtx
11822       || LABEL_REF != GET_CODE (XEXP (ifelse1, 1))
11823       || LABEL_REF != GET_CODE (XEXP (ifelse2, 1))
11824       || !COMPARISON_P (XEXP (ifelse2, 0))
11825       || cc0_rtx != XEXP (XEXP (ifelse1, 0), 0)
11826       || cc0_rtx != XEXP (XEXP (ifelse2, 0), 0)
11827       || const0_rtx != XEXP (XEXP (ifelse1, 0), 1)
11828       || const0_rtx != XEXP (XEXP (ifelse2, 0), 1))
11829     {
11830       return false;
11831     }
11832 
11833   /* We filtered the insn sequence to look like
11834 
11835         (set (cc0)
11836              (compare (reg:M N)
11837                       (const_int VAL)))
11838         (set (pc)
11839              (if_then_else (eq (cc0)
11840                                (const_int 0))
11841                            (label_ref L1)
11842                            (pc)))
11843 
11844         (set (cc0)
11845              (compare (reg:M N)
11846                       (const_int VAL)))
11847         (set (pc)
11848              (if_then_else (CODE (cc0)
11849                                  (const_int 0))
11850                            (label_ref L2)
11851                            (pc)))
11852   */
11853 
11854   code = GET_CODE (XEXP (ifelse2, 0));
11855 
11856   /* Map GT/GTU to GE/GEU which is easier for AVR.
11857      The first two instructions compare/branch on EQ
11858      so we may replace the difficult
11859 
11860         if (x == VAL)   goto L1;
11861         if (x > VAL)    goto L2;
11862 
11863      with easy
11864 
11865          if (x == VAL)   goto L1;
11866          if (x >= VAL)   goto L2;
11867 
11868      Similarly, replace LE/LEU by LT/LTU.  */
11869 
11870   switch (code)
11871     {
11872     case EQ:
11873     case LT:  case LTU:
11874     case GE:  case GEU:
11875       break;
11876 
11877     case LE:  case LEU:
11878     case GT:  case GTU:
11879       code = avr_normalize_condition (code);
11880       break;
11881 
11882     default:
11883       return false;
11884     }
11885 
11886   /* Wrap the branches into UNSPECs so they won't be changed or
11887      optimized in the remainder.  */
11888 
11889   target = XEXP (XEXP (ifelse1, 1), 0);
11890   cond = XEXP (ifelse1, 0);
11891   jump = emit_jump_insn_after (gen_branch_unspec (target, cond), insn1);
11892 
11893   JUMP_LABEL (jump) = JUMP_LABEL (branch1);
11894 
11895   target = XEXP (XEXP (ifelse2, 1), 0);
11896   cond = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
11897   jump = emit_jump_insn_after (gen_branch_unspec (target, cond), insn2);
11898 
11899   JUMP_LABEL (jump) = JUMP_LABEL (branch2);
11900 
11901   /* The comparisons in insn1 and insn2 are exactly the same;
11902      insn2 is superfluous so delete it.  */
11903 
11904   delete_insn (insn2);
11905   delete_insn (branch1);
11906   delete_insn (branch2);
11907 
11908   return true;
11909 }
11910 
11911 
11912 /* Implement `TARGET_MACHINE_DEPENDENT_REORG'.  */
11913 /* Optimize conditional jumps.  */
11914 
11915 static void
avr_reorg(void)11916 avr_reorg (void)
11917 {
11918   rtx_insn *insn = get_insns();
11919 
11920   for (insn = next_real_insn (insn); insn; insn = next_real_insn (insn))
11921     {
11922       rtx pattern = avr_compare_pattern (insn);
11923 
11924       if (!pattern)
11925         continue;
11926 
11927       if (optimize
11928           && avr_reorg_remove_redundant_compare (insn))
11929         {
11930           continue;
11931         }
11932 
11933       if (compare_diff_p (insn))
11934 	{
11935           /* Now we work under compare insn with difficult branch.  */
11936 
11937 	  rtx_insn *next = next_real_insn (insn);
11938           rtx pat = PATTERN (next);
11939 
11940           pattern = SET_SRC (pattern);
11941 
11942           if (true_regnum (XEXP (pattern, 0)) >= 0
11943               && true_regnum (XEXP (pattern, 1)) >= 0)
11944             {
11945               rtx x = XEXP (pattern, 0);
11946               rtx src = SET_SRC (pat);
11947               rtx t = XEXP (src, 0);
11948               PUT_CODE (t, swap_condition (GET_CODE (t)));
11949               XEXP (pattern, 0) = XEXP (pattern, 1);
11950               XEXP (pattern, 1) = x;
11951               INSN_CODE (next) = -1;
11952             }
11953           else if (true_regnum (XEXP (pattern, 0)) >= 0
11954                    && XEXP (pattern, 1) == const0_rtx)
11955             {
11956               /* This is a tst insn, we can reverse it.  */
11957               rtx src = SET_SRC (pat);
11958               rtx t = XEXP (src, 0);
11959 
11960               PUT_CODE (t, swap_condition (GET_CODE (t)));
11961               XEXP (pattern, 1) = XEXP (pattern, 0);
11962               XEXP (pattern, 0) = const0_rtx;
11963               INSN_CODE (next) = -1;
11964               INSN_CODE (insn) = -1;
11965             }
11966           else if (true_regnum (XEXP (pattern, 0)) >= 0
11967                    && CONST_INT_P (XEXP (pattern, 1)))
11968             {
11969               rtx x = XEXP (pattern, 1);
11970               rtx src = SET_SRC (pat);
11971               rtx t = XEXP (src, 0);
11972               machine_mode mode = GET_MODE (XEXP (pattern, 0));
11973 
11974               if (avr_simplify_comparison_p (mode, GET_CODE (t), x))
11975                 {
11976                   XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
11977                   PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
11978                   INSN_CODE (next) = -1;
11979                   INSN_CODE (insn) = -1;
11980                 }
11981             }
11982         }
11983     }
11984 }
11985 
11986 /* Returns register number for function return value.*/
11987 
11988 static inline unsigned int
avr_ret_register(void)11989 avr_ret_register (void)
11990 {
11991   return 24;
11992 }
11993 
11994 
11995 /* Implement `TARGET_FUNCTION_VALUE_REGNO_P'.  */
11996 
11997 static bool
avr_function_value_regno_p(const unsigned int regno)11998 avr_function_value_regno_p (const unsigned int regno)
11999 {
12000   return (regno == avr_ret_register ());
12001 }
12002 
12003 
12004 /* Implement `TARGET_LIBCALL_VALUE'.  */
12005 /* Create an RTX representing the place where a
12006    library function returns a value of mode MODE.  */
12007 
12008 static rtx
avr_libcall_value(machine_mode mode,const_rtx func ATTRIBUTE_UNUSED)12009 avr_libcall_value (machine_mode mode,
12010 		   const_rtx func ATTRIBUTE_UNUSED)
12011 {
12012   int offs = GET_MODE_SIZE (mode);
12013 
12014   if (offs <= 4)
12015     offs = (offs + 1) & ~1;
12016 
12017   return gen_rtx_REG (mode, avr_ret_register () + 2 - offs);
12018 }
12019 
12020 
12021 /* Implement `TARGET_FUNCTION_VALUE'.  */
12022 /* Create an RTX representing the place where a
12023    function returns a value of data type VALTYPE.  */
12024 
12025 static rtx
avr_function_value(const_tree type,const_tree fn_decl_or_type ATTRIBUTE_UNUSED,bool outgoing ATTRIBUTE_UNUSED)12026 avr_function_value (const_tree type,
12027                     const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
12028                     bool outgoing ATTRIBUTE_UNUSED)
12029 {
12030   unsigned int offs;
12031 
12032   if (TYPE_MODE (type) != BLKmode)
12033     return avr_libcall_value (TYPE_MODE (type), NULL_RTX);
12034 
12035   offs = int_size_in_bytes (type);
12036   if (offs < 2)
12037     offs = 2;
12038   if (offs > 2 && offs < GET_MODE_SIZE (SImode))
12039     offs = GET_MODE_SIZE (SImode);
12040   else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
12041     offs = GET_MODE_SIZE (DImode);
12042 
12043   return gen_rtx_REG (BLKmode, avr_ret_register () + 2 - offs);
12044 }
12045 
12046 int
test_hard_reg_class(enum reg_class rclass,rtx x)12047 test_hard_reg_class (enum reg_class rclass, rtx x)
12048 {
12049   int regno = true_regnum (x);
12050   if (regno < 0)
12051     return 0;
12052 
12053   if (TEST_HARD_REG_CLASS (rclass, regno))
12054     return 1;
12055 
12056   return 0;
12057 }
12058 
12059 
12060 /* Helper for jump_over_one_insn_p:  Test if INSN is a 2-word instruction
12061    and thus is suitable to be skipped by CPSE, SBRC, etc.  */
12062 
12063 static bool
avr_2word_insn_p(rtx_insn * insn)12064 avr_2word_insn_p (rtx_insn *insn)
12065 {
12066   if (TARGET_SKIP_BUG || !insn || get_attr_length (insn) != 2)
12067     {
12068       return false;
12069     }
12070 
12071   switch (INSN_CODE (insn))
12072     {
12073     default:
12074       return false;
12075 
12076     case CODE_FOR_movqi_insn:
12077     case CODE_FOR_movuqq_insn:
12078     case CODE_FOR_movqq_insn:
12079       {
12080         rtx set  = single_set (insn);
12081         rtx src  = SET_SRC (set);
12082         rtx dest = SET_DEST (set);
12083 
12084         /* Factor out LDS and STS from movqi_insn.  */
12085 
12086         if (MEM_P (dest)
12087             && (REG_P (src) || src == CONST0_RTX (GET_MODE (dest))))
12088           {
12089             return CONSTANT_ADDRESS_P (XEXP (dest, 0));
12090           }
12091         else if (REG_P (dest)
12092                  && MEM_P (src))
12093           {
12094             return CONSTANT_ADDRESS_P (XEXP (src, 0));
12095           }
12096 
12097         return false;
12098       }
12099 
12100     case CODE_FOR_call_insn:
12101     case CODE_FOR_call_value_insn:
12102       return true;
12103     }
12104 }
12105 
12106 
12107 int
jump_over_one_insn_p(rtx_insn * insn,rtx dest)12108 jump_over_one_insn_p (rtx_insn *insn, rtx dest)
12109 {
12110   int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
12111 		      ? XEXP (dest, 0)
12112 		      : dest);
12113   int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
12114   int dest_addr = INSN_ADDRESSES (uid);
12115   int jump_offset = dest_addr - jump_addr - get_attr_length (insn);
12116 
12117   return (jump_offset == 1
12118           || (jump_offset == 2
12119               && avr_2word_insn_p (next_active_insn (insn))));
12120 }
12121 
12122 
12123 /* Implement TARGET_HARD_REGNO_MODE_OK.  On the enhanced core, anything
12124    larger than 1 byte must start in even numbered register for "movw" to
12125    work (this way we don't have to check for odd registers everywhere).  */
12126 
12127 static bool
avr_hard_regno_mode_ok(unsigned int regno,machine_mode mode)12128 avr_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
12129 {
12130   /* NOTE: 8-bit values must not be disallowed for R28 or R29.
12131         Disallowing QI et al. in these regs might lead to code like
12132             (set (subreg:QI (reg:HI 28) n) ...)
12133         which will result in wrong code because reload does not
12134         handle SUBREGs of hard regsisters like this.
12135         This could be fixed in reload.  However, it appears
12136         that fixing reload is not wanted by reload people.  */
12137 
12138   /* Any GENERAL_REGS register can hold 8-bit values.  */
12139 
12140   if (GET_MODE_SIZE (mode) == 1)
12141     return true;
12142 
12143   /* FIXME: Ideally, the following test is not needed.
12144         However, it turned out that it can reduce the number
12145         of spill fails.  AVR and it's poor endowment with
12146         address registers is extreme stress test for reload.  */
12147 
12148   if (GET_MODE_SIZE (mode) >= 4
12149       && regno >= REG_X)
12150     return false;
12151 
12152   /* All modes larger than 8 bits should start in an even register.  */
12153 
12154   return !(regno & 1);
12155 }
12156 
12157 
12158 /* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED.  */
12159 
12160 static bool
avr_hard_regno_call_part_clobbered(unsigned,unsigned regno,machine_mode mode)12161 avr_hard_regno_call_part_clobbered (unsigned, unsigned regno,
12162 				    machine_mode mode)
12163 {
12164   /* FIXME: This hook gets called with MODE:REGNO combinations that don't
12165         represent valid hard registers like, e.g. HI:29.  Returning TRUE
12166         for such registers can lead to performance degradation as mentioned
12167         in PR53595.  Thus, report invalid hard registers as FALSE.  */
12168 
12169   if (!avr_hard_regno_mode_ok (regno, mode))
12170     return 0;
12171 
12172   /* Return true if any of the following boundaries is crossed:
12173      17/18 or 19/20 (if AVR_TINY), 27/28 and 29/30.  */
12174 
12175   return ((regno <= LAST_CALLEE_SAVED_REG
12176            && regno + GET_MODE_SIZE (mode) > 1 + LAST_CALLEE_SAVED_REG)
12177           || (regno < REG_Y && regno + GET_MODE_SIZE (mode) > REG_Y)
12178           || (regno < REG_Z && regno + GET_MODE_SIZE (mode) > REG_Z));
12179 }
12180 
12181 
12182 /* Implement `MODE_CODE_BASE_REG_CLASS'.  */
12183 
12184 enum reg_class
avr_mode_code_base_reg_class(machine_mode mode ATTRIBUTE_UNUSED,addr_space_t as,RTX_CODE outer_code,RTX_CODE index_code ATTRIBUTE_UNUSED)12185 avr_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED,
12186                               addr_space_t as, RTX_CODE outer_code,
12187                               RTX_CODE index_code ATTRIBUTE_UNUSED)
12188 {
12189   if (!ADDR_SPACE_GENERIC_P (as))
12190     {
12191       return POINTER_Z_REGS;
12192     }
12193 
12194   if (!avr_strict_X)
12195     return reload_completed ? BASE_POINTER_REGS : POINTER_REGS;
12196 
12197   return PLUS == outer_code ? BASE_POINTER_REGS : POINTER_REGS;
12198 }
12199 
12200 
12201 /* Implement `REGNO_MODE_CODE_OK_FOR_BASE_P'.  */
12202 
12203 bool
avr_regno_mode_code_ok_for_base_p(int regno,machine_mode mode ATTRIBUTE_UNUSED,addr_space_t as ATTRIBUTE_UNUSED,RTX_CODE outer_code,RTX_CODE index_code ATTRIBUTE_UNUSED)12204 avr_regno_mode_code_ok_for_base_p (int regno,
12205                                    machine_mode mode ATTRIBUTE_UNUSED,
12206                                    addr_space_t as ATTRIBUTE_UNUSED,
12207                                    RTX_CODE outer_code,
12208                                    RTX_CODE index_code ATTRIBUTE_UNUSED)
12209 {
12210   bool ok = false;
12211 
12212   if (!ADDR_SPACE_GENERIC_P (as))
12213     {
12214       if (regno < FIRST_PSEUDO_REGISTER
12215           && regno == REG_Z)
12216         {
12217           return true;
12218         }
12219 
12220       if (reg_renumber)
12221         {
12222           regno = reg_renumber[regno];
12223 
12224           if (regno == REG_Z)
12225             {
12226               return true;
12227             }
12228         }
12229 
12230       return false;
12231     }
12232 
12233   if (regno < FIRST_PSEUDO_REGISTER
12234       && (regno == REG_X
12235           || regno == REG_Y
12236           || regno == REG_Z
12237           || regno == ARG_POINTER_REGNUM))
12238     {
12239       ok = true;
12240     }
12241   else if (reg_renumber)
12242     {
12243       regno = reg_renumber[regno];
12244 
12245       if (regno == REG_X
12246           || regno == REG_Y
12247           || regno == REG_Z
12248           || regno == ARG_POINTER_REGNUM)
12249         {
12250           ok = true;
12251         }
12252     }
12253 
12254   if (avr_strict_X
12255       && PLUS == outer_code
12256       && regno == REG_X)
12257     {
12258       ok = false;
12259     }
12260 
12261   return ok;
12262 }
12263 
12264 
12265 /* A helper for `output_reload_insisf' and `output_reload_inhi'.  */
12266 /* Set 32-bit register OP[0] to compile-time constant OP[1].
12267    CLOBBER_REG is a QI clobber register or NULL_RTX.
12268    LEN == NULL: output instructions.
12269    LEN != NULL: set *LEN to the length of the instruction sequence
12270                 (in words) printed with LEN = NULL.
12271    If CLEAR_P is true, OP[0] had been cleard to Zero already.
12272    If CLEAR_P is false, nothing is known about OP[0].
12273 
12274    The effect on cc0 is as follows:
12275 
12276    Load 0 to any register except ZERO_REG : NONE
12277    Load ld register with any value        : NONE
12278    Anything else:                         : CLOBBER  */
12279 
12280 static void
output_reload_in_const(rtx * op,rtx clobber_reg,int * len,bool clear_p)12281 output_reload_in_const (rtx *op, rtx clobber_reg, int *len, bool clear_p)
12282 {
12283   rtx src = op[1];
12284   rtx dest = op[0];
12285   rtx xval, xdest[4];
12286   int ival[4];
12287   int clobber_val = 1234;
12288   bool cooked_clobber_p = false;
12289   bool set_p = false;
12290   machine_mode mode = GET_MODE (dest);
12291   int n_bytes = GET_MODE_SIZE (mode);
12292 
12293   gcc_assert (REG_P (dest)
12294               && CONSTANT_P (src));
12295 
12296   if (len)
12297     *len = 0;
12298 
12299   /* (REG:SI 14) is special: It's neither in LD_REGS nor in NO_LD_REGS
12300      but has some subregs that are in LD_REGS.  Use the MSB (REG:QI 17).  */
12301 
12302   if (REGNO (dest) < 16
12303       && REGNO (dest) + GET_MODE_SIZE (mode) > 16)
12304     {
12305       clobber_reg = all_regs_rtx[REGNO (dest) + n_bytes - 1];
12306     }
12307 
12308   /* We might need a clobber reg but don't have one.  Look at the value to
12309      be loaded more closely.  A clobber is only needed if it is a symbol
12310      or contains a byte that is neither 0, -1 or a power of 2.  */
12311 
12312   if (NULL_RTX == clobber_reg
12313       && !test_hard_reg_class (LD_REGS, dest)
12314       && (! (CONST_INT_P (src) || CONST_FIXED_P (src) || CONST_DOUBLE_P (src))
12315           || !avr_popcount_each_byte (src, n_bytes,
12316                                       (1 << 0) | (1 << 1) | (1 << 8))))
12317     {
12318       /* We have no clobber register but need one.  Cook one up.
12319          That's cheaper than loading from constant pool.  */
12320 
12321       cooked_clobber_p = true;
12322       clobber_reg = all_regs_rtx[REG_Z + 1];
12323       avr_asm_len ("mov __tmp_reg__,%0", &clobber_reg, len, 1);
12324     }
12325 
12326   /* Now start filling DEST from LSB to MSB.  */
12327 
12328   for (int n = 0; n < n_bytes; n++)
12329     {
12330       int ldreg_p;
12331       bool done_byte = false;
12332       rtx xop[3];
12333 
12334       /* Crop the n-th destination byte.  */
12335 
12336       xdest[n] = simplify_gen_subreg (QImode, dest, mode, n);
12337       ldreg_p = test_hard_reg_class (LD_REGS, xdest[n]);
12338 
12339       if (!CONST_INT_P (src)
12340           && !CONST_FIXED_P (src)
12341           && !CONST_DOUBLE_P (src))
12342         {
12343           static const char* const asm_code[][2] =
12344             {
12345               { "ldi %2,lo8(%1)"  CR_TAB "mov %0,%2",    "ldi %0,lo8(%1)"  },
12346               { "ldi %2,hi8(%1)"  CR_TAB "mov %0,%2",    "ldi %0,hi8(%1)"  },
12347               { "ldi %2,hlo8(%1)" CR_TAB "mov %0,%2",    "ldi %0,hlo8(%1)" },
12348               { "ldi %2,hhi8(%1)" CR_TAB "mov %0,%2",    "ldi %0,hhi8(%1)" }
12349             };
12350 
12351           xop[0] = xdest[n];
12352           xop[1] = src;
12353           xop[2] = clobber_reg;
12354 
12355           avr_asm_len (asm_code[n][ldreg_p], xop, len, ldreg_p ? 1 : 2);
12356 
12357           continue;
12358         }
12359 
12360       /* Crop the n-th source byte.  */
12361 
12362       xval = simplify_gen_subreg (QImode, src, mode, n);
12363       ival[n] = INTVAL (xval);
12364 
12365       /* Look if we can reuse the low word by means of MOVW.  */
12366 
12367       if (n == 2
12368           && n_bytes >= 4
12369           && AVR_HAVE_MOVW)
12370         {
12371           rtx lo16 = simplify_gen_subreg (HImode, src, mode, 0);
12372           rtx hi16 = simplify_gen_subreg (HImode, src, mode, 2);
12373 
12374           if (INTVAL (lo16) == INTVAL (hi16))
12375             {
12376 	      if (INTVAL (lo16) != 0 || !clear_p)
12377 		avr_asm_len ("movw %C0,%A0", &op[0], len, 1);
12378 
12379               break;
12380             }
12381         }
12382 
12383       /* Don't use CLR so that cc0 is set as expected.  */
12384 
12385       if (ival[n] == 0)
12386         {
12387           if (!clear_p)
12388             avr_asm_len (ldreg_p ? "ldi %0,0"
12389                          : AVR_ZERO_REGNO == REGNO (xdest[n]) ? "clr %0"
12390                          : "mov %0,__zero_reg__",
12391                          &xdest[n], len, 1);
12392           continue;
12393         }
12394 
12395       if (clobber_val == ival[n]
12396           && REGNO (clobber_reg) == REGNO (xdest[n]))
12397         {
12398           continue;
12399         }
12400 
12401       /* LD_REGS can use LDI to move a constant value */
12402 
12403       if (ldreg_p)
12404         {
12405           xop[0] = xdest[n];
12406           xop[1] = xval;
12407           avr_asm_len ("ldi %0,lo8(%1)", xop, len, 1);
12408           continue;
12409         }
12410 
12411       /* Try to reuse value already loaded in some lower byte. */
12412 
12413       for (int j = 0; j < n; j++)
12414         if (ival[j] == ival[n])
12415           {
12416             xop[0] = xdest[n];
12417             xop[1] = xdest[j];
12418 
12419             avr_asm_len ("mov %0,%1", xop, len, 1);
12420             done_byte = true;
12421             break;
12422           }
12423 
12424       if (done_byte)
12425         continue;
12426 
12427       /* Need no clobber reg for -1: Use CLR/DEC */
12428 
12429       if (ival[n] == -1)
12430         {
12431           if (!clear_p)
12432             avr_asm_len ("clr %0", &xdest[n], len, 1);
12433 
12434           avr_asm_len ("dec %0", &xdest[n], len, 1);
12435           continue;
12436         }
12437       else if (ival[n] == 1)
12438         {
12439           if (!clear_p)
12440             avr_asm_len ("clr %0", &xdest[n], len, 1);
12441 
12442           avr_asm_len ("inc %0", &xdest[n], len, 1);
12443           continue;
12444         }
12445 
12446       /* Use T flag or INC to manage powers of 2 if we have
12447          no clobber reg.  */
12448 
12449       if (NULL_RTX == clobber_reg
12450           && single_one_operand (xval, QImode))
12451         {
12452           xop[0] = xdest[n];
12453           xop[1] = GEN_INT (exact_log2 (ival[n] & GET_MODE_MASK (QImode)));
12454 
12455           gcc_assert (constm1_rtx != xop[1]);
12456 
12457           if (!set_p)
12458             {
12459               set_p = true;
12460               avr_asm_len ("set", xop, len, 1);
12461             }
12462 
12463           if (!clear_p)
12464             avr_asm_len ("clr %0", xop, len, 1);
12465 
12466           avr_asm_len ("bld %0,%1", xop, len, 1);
12467           continue;
12468         }
12469 
12470       /* We actually need the LD_REGS clobber reg.  */
12471 
12472       gcc_assert (NULL_RTX != clobber_reg);
12473 
12474       xop[0] = xdest[n];
12475       xop[1] = xval;
12476       xop[2] = clobber_reg;
12477       clobber_val = ival[n];
12478 
12479       avr_asm_len ("ldi %2,lo8(%1)" CR_TAB
12480                    "mov %0,%2", xop, len, 2);
12481     }
12482 
12483   /* If we cooked up a clobber reg above, restore it.  */
12484 
12485   if (cooked_clobber_p)
12486     {
12487       avr_asm_len ("mov %0,__tmp_reg__", &clobber_reg, len, 1);
12488     }
12489 }
12490 
12491 
12492 /* Reload the constant OP[1] into the HI register OP[0].
12493    CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
12494    into a NO_LD_REGS register.  If CLOBBER_REG is NULL_RTX we either don't
12495    need a clobber reg or have to cook one up.
12496 
12497    PLEN == NULL: Output instructions.
12498    PLEN != NULL: Output nothing.  Set *PLEN to number of words occupied
12499                  by the insns printed.
12500 
12501    Return "".  */
12502 
12503 const char*
output_reload_inhi(rtx * op,rtx clobber_reg,int * plen)12504 output_reload_inhi (rtx *op, rtx clobber_reg, int *plen)
12505 {
12506   output_reload_in_const (op, clobber_reg, plen, false);
12507   return "";
12508 }
12509 
12510 
12511 /* Reload a SI or SF compile time constant OP[1] into the register OP[0].
12512    CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
12513    into a NO_LD_REGS register.  If CLOBBER_REG is NULL_RTX we either don't
12514    need a clobber reg or have to cook one up.
12515 
12516    LEN == NULL: Output instructions.
12517 
12518    LEN != NULL: Output nothing.  Set *LEN to number of words occupied
12519                 by the insns printed.
12520 
12521    Return "".  */
12522 
12523 const char *
output_reload_insisf(rtx * op,rtx clobber_reg,int * len)12524 output_reload_insisf (rtx *op, rtx clobber_reg, int *len)
12525 {
12526   if (AVR_HAVE_MOVW
12527       && !test_hard_reg_class (LD_REGS, op[0])
12528       && (CONST_INT_P (op[1])
12529           || CONST_FIXED_P (op[1])
12530           || CONST_DOUBLE_P (op[1])))
12531     {
12532       int len_clr, len_noclr;
12533 
12534       /* In some cases it is better to clear the destination beforehand, e.g.
12535 
12536              CLR R2   CLR R3   MOVW R4,R2   INC R2
12537 
12538          is shorther than
12539 
12540              CLR R2   INC R2   CLR  R3      CLR R4   CLR R5
12541 
12542          We find it too tedious to work that out in the print function.
12543          Instead, we call the print function twice to get the lengths of
12544          both methods and use the shortest one.  */
12545 
12546       output_reload_in_const (op, clobber_reg, &len_clr, true);
12547       output_reload_in_const (op, clobber_reg, &len_noclr, false);
12548 
12549       if (len_noclr - len_clr == 4)
12550         {
12551           /* Default needs 4 CLR instructions: clear register beforehand.  */
12552 
12553           avr_asm_len ("mov %A0,__zero_reg__" CR_TAB
12554                        "mov %B0,__zero_reg__" CR_TAB
12555                        "movw %C0,%A0", &op[0], len, 3);
12556 
12557           output_reload_in_const (op, clobber_reg, len, true);
12558 
12559           if (len)
12560             *len += 3;
12561 
12562           return "";
12563         }
12564     }
12565 
12566   /* Default: destination not pre-cleared.  */
12567 
12568   output_reload_in_const (op, clobber_reg, len, false);
12569   return "";
12570 }
12571 
12572 const char*
avr_out_reload_inpsi(rtx * op,rtx clobber_reg,int * len)12573 avr_out_reload_inpsi (rtx *op, rtx clobber_reg, int *len)
12574 {
12575   output_reload_in_const (op, clobber_reg, len, false);
12576   return "";
12577 }
12578 
12579 
12580 /* Worker function for `ASM_OUTPUT_ADDR_VEC'.  */
12581 /* Emit jump tables out-of-line so that branches crossing the table
12582    get shorter offsets.  If we have JUMP + CALL, then put the tables
12583    in a dedicated non-.text section so that CALLs get better chance to
12584    be relaxed to RCALLs.
12585 
12586    We emit the tables by hand because `function_rodata_section' does not
12587    work as expected, cf. PR71151, and we do *NOT* want the table to be
12588    in .rodata, hence setting JUMP_TABLES_IN_TEXT_SECTION = 0 is of limited
12589    use; and setting it to 1 attributes table lengths to branch offsets...
12590    Moreover, fincal.c keeps switching section before each table entry
12591    which we find too fragile as to rely on section caching.  */
12592 
12593 void
avr_output_addr_vec(rtx_insn * labl,rtx table)12594 avr_output_addr_vec (rtx_insn *labl, rtx table)
12595 {
12596   FILE *stream = asm_out_file;
12597 
12598   app_disable();
12599 
12600   // Switch to appropriate (sub)section.
12601 
12602   if (DECL_SECTION_NAME (current_function_decl)
12603       && symtab_node::get (current_function_decl)
12604       && ! symtab_node::get (current_function_decl)->implicit_section)
12605     {
12606       // .subsection will emit the code after the function and in the
12607       // section as chosen by the user.
12608 
12609       switch_to_section (current_function_section ());
12610       fprintf (stream, "\t.subsection\t1\n");
12611     }
12612   else
12613     {
12614       // Since PR63223 there is no restriction where to put the table; it
12615       // may even reside above 128 KiB.  We put it in a section as high as
12616       // possible and avoid progmem in order not to waste flash <= 64 KiB.
12617 
12618       const char *sec_name = ".jumptables.gcc";
12619 
12620       // The table belongs to its host function, therefore use fine
12621       // grained sections so that, if that function is removed by
12622       // --gc-sections, the child table(s) may also be removed.  */
12623 
12624       tree asm_name = DECL_ASSEMBLER_NAME (current_function_decl);
12625       const char *fname = IDENTIFIER_POINTER (asm_name);
12626       fname = targetm.strip_name_encoding (fname);
12627       sec_name = ACONCAT ((sec_name, ".", fname, NULL));
12628 
12629       fprintf (stream, "\t.section\t%s,\"%s\",@progbits\n", sec_name,
12630                AVR_HAVE_JMP_CALL ? "a" : "ax");
12631     }
12632 
12633   // Output the label that preceeds the table.
12634 
12635   ASM_OUTPUT_ALIGN (stream, 1);
12636   targetm.asm_out.internal_label (stream, "L", CODE_LABEL_NUMBER (labl));
12637 
12638   // Output the table's content.
12639 
12640   int vlen = XVECLEN (table, 0);
12641 
12642   for (int idx = 0; idx < vlen; idx++)
12643     {
12644       int value = CODE_LABEL_NUMBER (XEXP (XVECEXP (table, 0, idx), 0));
12645 
12646       if (AVR_HAVE_JMP_CALL)
12647         fprintf (stream, "\t.word gs(.L%d)\n", value);
12648       else
12649         fprintf (stream, "\trjmp .L%d\n", value);
12650     }
12651 
12652   // Switch back to original section.  As we clobbered the section above,
12653   // forget the current section before switching back.
12654 
12655   in_section = NULL;
12656   switch_to_section (current_function_section ());
12657 }
12658 
12659 
12660 /* Implement `TARGET_CONDITIONAL_REGISTER_USAGE'.  */
12661 
12662 static void
avr_conditional_register_usage(void)12663 avr_conditional_register_usage (void)
12664 {
12665   if (AVR_TINY)
12666     {
12667       const int tiny_reg_alloc_order[] = {
12668         24, 25,
12669         22, 23,
12670         30, 31,
12671         26, 27,
12672         28, 29,
12673         21, 20, 19, 18,
12674         16, 17,
12675         32, 33, 34, 35,
12676         15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
12677       };
12678 
12679       /* Set R0-R17 as fixed registers. Reset R0-R17 in call used register list
12680          - R0-R15 are not available in Tiny Core devices
12681          - R16 and R17 are fixed registers.  */
12682 
12683       for (size_t i = 0; i <= 17;  i++)
12684         {
12685           fixed_regs[i] = 1;
12686           call_used_regs[i] = 1;
12687         }
12688 
12689       /* Set R18 to R21 as callee saved registers
12690          - R18, R19, R20 and R21 are the callee saved registers in
12691            Tiny Core devices  */
12692 
12693       for (size_t i = 18; i <= LAST_CALLEE_SAVED_REG; i++)
12694         {
12695           call_used_regs[i] = 0;
12696         }
12697 
12698       /* Update register allocation order for Tiny Core devices */
12699 
12700       for (size_t i = 0; i < ARRAY_SIZE (tiny_reg_alloc_order); i++)
12701         {
12702           reg_alloc_order[i] = tiny_reg_alloc_order[i];
12703         }
12704 
12705       CLEAR_HARD_REG_SET (reg_class_contents[(int) ADDW_REGS]);
12706       CLEAR_HARD_REG_SET (reg_class_contents[(int) NO_LD_REGS]);
12707     }
12708 }
12709 
12710 /* Implement `TARGET_HARD_REGNO_SCRATCH_OK'.  */
12711 /* Returns true if SCRATCH are safe to be allocated as a scratch
12712    registers (for a define_peephole2) in the current function.  */
12713 
12714 static bool
avr_hard_regno_scratch_ok(unsigned int regno)12715 avr_hard_regno_scratch_ok (unsigned int regno)
12716 {
12717   /* Interrupt functions can only use registers that have already been saved
12718      by the prologue, even if they would normally be call-clobbered.  */
12719 
12720   if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
12721       && !df_regs_ever_live_p (regno))
12722     return false;
12723 
12724   /* Don't allow hard registers that might be part of the frame pointer.
12725      Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
12726      and don't care for a frame pointer that spans more than one register.  */
12727 
12728   if ((!reload_completed || frame_pointer_needed)
12729       && (regno == REG_Y || regno == REG_Y + 1))
12730     {
12731       return false;
12732     }
12733 
12734   return true;
12735 }
12736 
12737 
12738 /* Worker function for `HARD_REGNO_RENAME_OK'.  */
12739 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG.  */
12740 
12741 int
avr_hard_regno_rename_ok(unsigned int old_reg,unsigned int new_reg)12742 avr_hard_regno_rename_ok (unsigned int old_reg,
12743 			  unsigned int new_reg)
12744 {
12745   /* Interrupt functions can only use registers that have already been
12746      saved by the prologue, even if they would normally be
12747      call-clobbered.  */
12748 
12749   if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
12750       && !df_regs_ever_live_p (new_reg))
12751     return 0;
12752 
12753   /* Don't allow hard registers that might be part of the frame pointer.
12754      Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
12755      and don't care for a frame pointer that spans more than one register.  */
12756 
12757   if ((!reload_completed || frame_pointer_needed)
12758       && (old_reg == REG_Y || old_reg == REG_Y + 1
12759           || new_reg == REG_Y || new_reg == REG_Y + 1))
12760     {
12761       return 0;
12762     }
12763 
12764   return 1;
12765 }
12766 
12767 /* Output a branch that tests a single bit of a register (QI, HI, SI or DImode)
12768    or memory location in the I/O space (QImode only).
12769 
12770    Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
12771    Operand 1: register operand to test, or CONST_INT memory address.
12772    Operand 2: bit number.
12773    Operand 3: label to jump to if the test is true.  */
12774 
12775 const char*
avr_out_sbxx_branch(rtx_insn * insn,rtx operands[])12776 avr_out_sbxx_branch (rtx_insn *insn, rtx operands[])
12777 {
12778   enum rtx_code comp = GET_CODE (operands[0]);
12779   bool long_jump = get_attr_length (insn) >= 4;
12780   bool reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
12781 
12782   if (comp == GE)
12783     comp = EQ;
12784   else if (comp == LT)
12785     comp = NE;
12786 
12787   if (reverse)
12788     comp = reverse_condition (comp);
12789 
12790   switch (GET_CODE (operands[1]))
12791     {
12792     default:
12793       gcc_unreachable();
12794 
12795     case CONST_INT:
12796     case CONST:
12797     case SYMBOL_REF:
12798 
12799       if (low_io_address_operand (operands[1], QImode))
12800         {
12801           if (comp == EQ)
12802             output_asm_insn ("sbis %i1,%2", operands);
12803           else
12804             output_asm_insn ("sbic %i1,%2", operands);
12805         }
12806       else
12807         {
12808 	  gcc_assert (io_address_operand (operands[1], QImode));
12809           output_asm_insn ("in __tmp_reg__,%i1", operands);
12810           if (comp == EQ)
12811             output_asm_insn ("sbrs __tmp_reg__,%2", operands);
12812           else
12813             output_asm_insn ("sbrc __tmp_reg__,%2", operands);
12814         }
12815 
12816       break; /* CONST_INT */
12817 
12818     case REG:
12819 
12820       if (comp == EQ)
12821         output_asm_insn ("sbrs %T1%T2", operands);
12822       else
12823         output_asm_insn ("sbrc %T1%T2", operands);
12824 
12825       break; /* REG */
12826     }        /* switch */
12827 
12828   if (long_jump)
12829     return ("rjmp .+4" CR_TAB
12830             "jmp %x3");
12831 
12832   if (!reverse)
12833     return "rjmp %x3";
12834 
12835   return "";
12836 }
12837 
12838 /* Worker function for `TARGET_ASM_CONSTRUCTOR'.  */
12839 
12840 static void
avr_asm_out_ctor(rtx symbol,int priority)12841 avr_asm_out_ctor (rtx symbol, int priority)
12842 {
12843   fputs ("\t.global __do_global_ctors\n", asm_out_file);
12844   default_ctor_section_asm_out_constructor (symbol, priority);
12845 }
12846 
12847 
12848 /* Worker function for `TARGET_ASM_DESTRUCTOR'.  */
12849 
12850 static void
avr_asm_out_dtor(rtx symbol,int priority)12851 avr_asm_out_dtor (rtx symbol, int priority)
12852 {
12853   fputs ("\t.global __do_global_dtors\n", asm_out_file);
12854   default_dtor_section_asm_out_destructor (symbol, priority);
12855 }
12856 
12857 
12858 /* Worker function for `TARGET_RETURN_IN_MEMORY'.  */
12859 
12860 static bool
avr_return_in_memory(const_tree type,const_tree fntype ATTRIBUTE_UNUSED)12861 avr_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
12862 {
12863   HOST_WIDE_INT size = int_size_in_bytes (type);
12864   HOST_WIDE_INT ret_size_limit = AVR_TINY ? 4 : 8;
12865 
12866   /* In avr, there are 8 return registers. But, for Tiny Core
12867      (ATtiny4/5/9/10/20/40) devices, only 4 registers are available.
12868      Return true if size is unknown or greater than the limit.  */
12869 
12870   if (size == -1 || size > ret_size_limit)
12871     {
12872       return true;
12873     }
12874   else
12875     {
12876       return false;
12877     }
12878 }
12879 
12880 
12881 /* Implement `CASE_VALUES_THRESHOLD'.  */
12882 /* Supply the default for --param case-values-threshold=0  */
12883 
12884 static unsigned int
avr_case_values_threshold(void)12885 avr_case_values_threshold (void)
12886 {
12887   /* The exact break-even point between a jump table and an if-else tree
12888      depends on several factors not available here like, e.g. if 8-bit
12889      comparisons can be used in the if-else tree or not, on the
12890      range of the case values, if the case value can be reused, on the
12891      register allocation, etc.  '7' appears to be a good choice.  */
12892 
12893   return 7;
12894 }
12895 
12896 
12897 /* Implement `TARGET_ADDR_SPACE_ADDRESS_MODE'.  */
12898 
12899 static scalar_int_mode
avr_addr_space_address_mode(addr_space_t as)12900 avr_addr_space_address_mode (addr_space_t as)
12901 {
12902   return avr_addrspace[as].pointer_size == 3 ? PSImode : HImode;
12903 }
12904 
12905 
12906 /* Implement `TARGET_ADDR_SPACE_POINTER_MODE'.  */
12907 
12908 static scalar_int_mode
avr_addr_space_pointer_mode(addr_space_t as)12909 avr_addr_space_pointer_mode (addr_space_t as)
12910 {
12911   return avr_addr_space_address_mode (as);
12912 }
12913 
12914 
12915 /* Helper for following function.  */
12916 
12917 static bool
avr_reg_ok_for_pgm_addr(rtx reg,bool strict)12918 avr_reg_ok_for_pgm_addr (rtx reg, bool strict)
12919 {
12920   gcc_assert (REG_P (reg));
12921 
12922   if (strict)
12923     {
12924       return REGNO (reg) == REG_Z;
12925     }
12926 
12927   /* Avoid combine to propagate hard regs.  */
12928 
12929   if (can_create_pseudo_p()
12930       && REGNO (reg) < REG_Z)
12931     {
12932       return false;
12933     }
12934 
12935   return true;
12936 }
12937 
12938 
12939 /* Implement `TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P'.  */
12940 
12941 static bool
avr_addr_space_legitimate_address_p(machine_mode mode,rtx x,bool strict,addr_space_t as)12942 avr_addr_space_legitimate_address_p (machine_mode mode, rtx x,
12943                                      bool strict, addr_space_t as)
12944 {
12945   bool ok = false;
12946 
12947   switch (as)
12948     {
12949     default:
12950       gcc_unreachable();
12951 
12952     case ADDR_SPACE_GENERIC:
12953       return avr_legitimate_address_p (mode, x, strict);
12954 
12955     case ADDR_SPACE_FLASH:
12956     case ADDR_SPACE_FLASH1:
12957     case ADDR_SPACE_FLASH2:
12958     case ADDR_SPACE_FLASH3:
12959     case ADDR_SPACE_FLASH4:
12960     case ADDR_SPACE_FLASH5:
12961 
12962       switch (GET_CODE (x))
12963         {
12964         case REG:
12965           ok = avr_reg_ok_for_pgm_addr (x, strict);
12966           break;
12967 
12968         case POST_INC:
12969           ok = avr_reg_ok_for_pgm_addr (XEXP (x, 0), strict);
12970           break;
12971 
12972         default:
12973           break;
12974         }
12975 
12976       break; /* FLASH */
12977 
12978     case ADDR_SPACE_MEMX:
12979       if (REG_P (x))
12980         ok = (!strict
12981               && can_create_pseudo_p());
12982 
12983       if (LO_SUM == GET_CODE (x))
12984         {
12985           rtx hi = XEXP (x, 0);
12986           rtx lo = XEXP (x, 1);
12987 
12988           ok = (REG_P (hi)
12989                 && (!strict || REGNO (hi) < FIRST_PSEUDO_REGISTER)
12990                 && REG_P (lo)
12991                 && REGNO (lo) == REG_Z);
12992         }
12993 
12994       break; /* MEMX */
12995     }
12996 
12997   if (avr_log.legitimate_address_p)
12998     {
12999       avr_edump ("\n%?: ret=%b, mode=%m strict=%d "
13000                  "reload_completed=%d reload_in_progress=%d %s:",
13001                  ok, mode, strict, reload_completed, reload_in_progress,
13002                  reg_renumber ? "(reg_renumber)" : "");
13003 
13004       if (GET_CODE (x) == PLUS
13005           && REG_P (XEXP (x, 0))
13006           && CONST_INT_P (XEXP (x, 1))
13007           && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
13008           && reg_renumber)
13009         {
13010           avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
13011                      true_regnum (XEXP (x, 0)));
13012         }
13013 
13014       avr_edump ("\n%r\n", x);
13015     }
13016 
13017   return ok;
13018 }
13019 
13020 
13021 /* Implement `TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS'.  */
13022 
13023 static rtx
avr_addr_space_legitimize_address(rtx x,rtx old_x,machine_mode mode,addr_space_t as)13024 avr_addr_space_legitimize_address (rtx x, rtx old_x,
13025                                    machine_mode mode, addr_space_t as)
13026 {
13027   if (ADDR_SPACE_GENERIC_P (as))
13028     return avr_legitimize_address (x, old_x, mode);
13029 
13030   if (avr_log.legitimize_address)
13031     {
13032       avr_edump ("\n%?: mode=%m\n %r\n", mode, old_x);
13033     }
13034 
13035   return old_x;
13036 }
13037 
13038 
13039 /* Implement `TARGET_ADDR_SPACE_CONVERT'.  */
13040 
13041 static rtx
avr_addr_space_convert(rtx src,tree type_from,tree type_to)13042 avr_addr_space_convert (rtx src, tree type_from, tree type_to)
13043 {
13044   addr_space_t as_from = TYPE_ADDR_SPACE (TREE_TYPE (type_from));
13045   addr_space_t as_to = TYPE_ADDR_SPACE (TREE_TYPE (type_to));
13046 
13047   if (avr_log.progmem)
13048     avr_edump ("\n%!: op = %r\nfrom = %t\nto = %t\n",
13049                src, type_from, type_to);
13050 
13051   /* Up-casting from 16-bit to 24-bit pointer.  */
13052 
13053   if (as_from != ADDR_SPACE_MEMX
13054       && as_to == ADDR_SPACE_MEMX)
13055     {
13056       int msb;
13057       rtx sym = src;
13058       rtx reg = gen_reg_rtx (PSImode);
13059 
13060       while (CONST == GET_CODE (sym) || PLUS == GET_CODE (sym))
13061         sym = XEXP (sym, 0);
13062 
13063       /* Look at symbol flags:  avr_encode_section_info set the flags
13064          also if attribute progmem was seen so that we get the right
13065          promotion for, e.g. PSTR-like strings that reside in generic space
13066          but are located in flash.  In that case we patch the incoming
13067          address space.  */
13068 
13069       if (SYMBOL_REF_P (sym)
13070           && ADDR_SPACE_FLASH == AVR_SYMBOL_GET_ADDR_SPACE (sym))
13071         {
13072           as_from = ADDR_SPACE_FLASH;
13073         }
13074 
13075       /* Linearize memory: RAM has bit 23 set.  */
13076 
13077       msb = ADDR_SPACE_GENERIC_P (as_from)
13078         ? 0x80
13079         : avr_addrspace[as_from].segment;
13080 
13081       src = force_reg (Pmode, src);
13082 
13083       emit_insn (msb == 0
13084                  ? gen_zero_extendhipsi2 (reg, src)
13085                  : gen_n_extendhipsi2 (reg, gen_int_mode (msb, QImode), src));
13086 
13087       return reg;
13088     }
13089 
13090   /* Down-casting from 24-bit to 16-bit throws away the high byte.  */
13091 
13092   if (as_from == ADDR_SPACE_MEMX
13093       && as_to != ADDR_SPACE_MEMX)
13094     {
13095       rtx new_src = gen_reg_rtx (Pmode);
13096 
13097       src = force_reg (PSImode, src);
13098 
13099       emit_move_insn (new_src,
13100                       simplify_gen_subreg (Pmode, src, PSImode, 0));
13101       return new_src;
13102     }
13103 
13104   return src;
13105 }
13106 
13107 
13108 /* Implement `TARGET_ADDR_SPACE_SUBSET_P'.  */
13109 
13110 static bool
avr_addr_space_subset_p(addr_space_t subset ATTRIBUTE_UNUSED,addr_space_t superset ATTRIBUTE_UNUSED)13111 avr_addr_space_subset_p (addr_space_t subset ATTRIBUTE_UNUSED,
13112                          addr_space_t superset ATTRIBUTE_UNUSED)
13113 {
13114   /* Allow any kind of pointer mess.  */
13115 
13116   return true;
13117 }
13118 
13119 
13120 /* Implement `TARGET_CONVERT_TO_TYPE'.  */
13121 
13122 static tree
avr_convert_to_type(tree type,tree expr)13123 avr_convert_to_type (tree type, tree expr)
13124 {
13125   /* Print a diagnose for pointer conversion that changes the address
13126      space of the pointer target to a non-enclosing address space,
13127      provided -Waddr-space-convert is on.
13128 
13129      FIXME: Filter out cases where the target object is known to
13130             be located in the right memory, like in
13131 
13132                 (const __flash*) PSTR ("text")
13133 
13134             Also try to distinguish between explicit casts requested by
13135             the user and implicit casts like
13136 
13137                 void f (const __flash char*);
13138 
13139                 void g (const char *p)
13140                 {
13141                     f ((const __flash*) p);
13142                 }
13143 
13144             under the assumption that an explicit casts means that the user
13145             knows what he is doing, e.g. interface with PSTR or old style
13146             code with progmem and pgm_read_xxx.
13147   */
13148 
13149   if (avr_warn_addr_space_convert
13150       && expr != error_mark_node
13151       && POINTER_TYPE_P (type)
13152       && POINTER_TYPE_P (TREE_TYPE (expr)))
13153     {
13154       addr_space_t as_old = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (expr)));
13155       addr_space_t as_new = TYPE_ADDR_SPACE (TREE_TYPE (type));
13156 
13157       if (avr_log.progmem)
13158         avr_edump ("%?: type = %t\nexpr = %t\n\n", type, expr);
13159 
13160       if (as_new != ADDR_SPACE_MEMX
13161           && as_new != as_old)
13162         {
13163           location_t loc = EXPR_LOCATION (expr);
13164           const char *name_old = avr_addrspace[as_old].name;
13165           const char *name_new = avr_addrspace[as_new].name;
13166 
13167           warning (OPT_Waddr_space_convert,
13168                    "conversion from address space %qs to address space %qs",
13169                    ADDR_SPACE_GENERIC_P (as_old) ? "generic" : name_old,
13170                    ADDR_SPACE_GENERIC_P (as_new) ? "generic" : name_new);
13171 
13172           return fold_build1_loc (loc, ADDR_SPACE_CONVERT_EXPR, type, expr);
13173         }
13174     }
13175 
13176   return NULL_TREE;
13177 }
13178 
13179 
13180 /* Implement `TARGET_LEGITIMATE_COMBINED_INSN'.  */
13181 
13182 /* PR78883: Filter out paradoxical SUBREGs of MEM which are not handled
13183    properly by following passes.  As INSN_SCHEDULING is off and hence
13184    general_operand accepts such expressions, ditch them now.  */
13185 
13186 static bool
avr_legitimate_combined_insn(rtx_insn * insn)13187 avr_legitimate_combined_insn (rtx_insn *insn)
13188 {
13189   subrtx_iterator::array_type array;
13190 
13191   FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
13192     {
13193       const_rtx op = *iter;
13194 
13195       if (SUBREG_P (op)
13196           && MEM_P (SUBREG_REG (op))
13197           && (GET_MODE_SIZE (GET_MODE (op))
13198               > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))))
13199         {
13200           return false;
13201         }
13202     }
13203 
13204   return true;
13205 }
13206 
13207 
13208 /* PR63633: The middle-end might come up with hard regs as input operands.
13209 
13210    RMASK is a bit mask representing a subset of hard registers R0...R31:
13211    Rn is an element of that set iff bit n of RMASK is set.
13212    OPMASK describes a subset of OP[]:  If bit n of OPMASK is 1 then
13213    OP[n] has to be fixed; otherwise OP[n] is left alone.
13214 
13215    For each element of OPMASK which is a hard register overlapping RMASK,
13216    replace OP[n] with a newly created pseudo register
13217 
13218    HREG == 0:  Also emit a move insn that copies the contents of that
13219                hard register into the new pseudo.
13220 
13221    HREG != 0:  Also set HREG[n] to the hard register.  */
13222 
13223 static void
avr_fix_operands(rtx * op,rtx * hreg,unsigned opmask,unsigned rmask)13224 avr_fix_operands (rtx *op, rtx *hreg, unsigned opmask, unsigned rmask)
13225 {
13226   for (; opmask; opmask >>= 1, op++)
13227     {
13228       rtx reg = *op;
13229 
13230       if (hreg)
13231         *hreg = NULL_RTX;
13232 
13233       if ((opmask & 1)
13234           && REG_P (reg)
13235           && REGNO (reg) < FIRST_PSEUDO_REGISTER
13236           // This hard-reg overlaps other prohibited hard regs?
13237           && (rmask & regmask (GET_MODE (reg), REGNO (reg))))
13238         {
13239           *op = gen_reg_rtx (GET_MODE (reg));
13240           if (hreg == NULL)
13241             emit_move_insn (*op, reg);
13242           else
13243             *hreg = reg;
13244         }
13245 
13246       if (hreg)
13247         hreg++;
13248     }
13249 }
13250 
13251 
13252 void
avr_fix_inputs(rtx * op,unsigned opmask,unsigned rmask)13253 avr_fix_inputs (rtx *op, unsigned opmask, unsigned rmask)
13254 {
13255   avr_fix_operands (op, NULL, opmask, rmask);
13256 }
13257 
13258 
13259 /* Helper for the function below:  If bit n of MASK is set and
13260    HREG[n] != NULL, then emit a move insn to copy OP[n] to HREG[n].
13261    Otherwise do nothing for that n.  Return TRUE.  */
13262 
13263 static bool
avr_move_fixed_operands(rtx * op,rtx * hreg,unsigned mask)13264 avr_move_fixed_operands (rtx *op, rtx *hreg, unsigned mask)
13265 {
13266   for (; mask; mask >>= 1, op++, hreg++)
13267     if ((mask & 1)
13268         && *hreg)
13269       emit_move_insn (*hreg, *op);
13270 
13271   return true;
13272 }
13273 
13274 
13275 /* PR63633: The middle-end might come up with hard regs as output operands.
13276 
13277    GEN is a sequence generating function like gen_mulsi3 with 3 operands OP[].
13278    RMASK is a bit mask representing a subset of hard registers R0...R31:
13279    Rn is an element of that set iff bit n of RMASK is set.
13280    OPMASK describes a subset of OP[]:  If bit n of OPMASK is 1 then
13281    OP[n] has to be fixed; otherwise OP[n] is left alone.
13282 
13283    Emit the insn sequence as generated by GEN() with all elements of OPMASK
13284    which are hard registers overlapping RMASK replaced by newly created
13285    pseudo registers.  After the sequence has been emitted, emit insns that
13286    move the contents of respective pseudos to their hard regs.  */
13287 
13288 bool
avr_emit3_fix_outputs(rtx (* gen)(rtx,rtx,rtx),rtx * op,unsigned opmask,unsigned rmask)13289 avr_emit3_fix_outputs (rtx (*gen)(rtx,rtx,rtx), rtx *op,
13290                        unsigned opmask, unsigned rmask)
13291 {
13292   const int n = 3;
13293   rtx hreg[n];
13294 
13295   /* It is letigimate for GEN to call this function, and in order not to
13296      get self-recursive we use the following static kludge.  This is the
13297      only way not to duplicate all expanders and to avoid ugly and
13298      hard-to-maintain C-code instead of the much more appreciated RTL
13299      representation as supplied by define_expand.  */
13300   static bool lock = false;
13301 
13302   gcc_assert (opmask < (1u << n));
13303 
13304   if (lock)
13305     return false;
13306 
13307   avr_fix_operands (op, hreg, opmask, rmask);
13308 
13309   lock = true;
13310   emit_insn (gen (op[0], op[1], op[2]));
13311   lock = false;
13312 
13313   return avr_move_fixed_operands (op, hreg, opmask);
13314 }
13315 
13316 
13317 /* Worker function for cpymemhi expander.
13318    XOP[0]  Destination as MEM:BLK
13319    XOP[1]  Source      "     "
13320    XOP[2]  # Bytes to copy
13321 
13322    Return TRUE  if the expansion is accomplished.
13323    Return FALSE if the operand compination is not supported.  */
13324 
13325 bool
avr_emit_cpymemhi(rtx * xop)13326 avr_emit_cpymemhi (rtx *xop)
13327 {
13328   HOST_WIDE_INT count;
13329   machine_mode loop_mode;
13330   addr_space_t as = MEM_ADDR_SPACE (xop[1]);
13331   rtx loop_reg, addr1, a_src, a_dest, insn, xas;
13332   rtx a_hi8 = NULL_RTX;
13333 
13334   if (avr_mem_flash_p (xop[0]))
13335     return false;
13336 
13337   if (!CONST_INT_P (xop[2]))
13338     return false;
13339 
13340   count = INTVAL (xop[2]);
13341   if (count <= 0)
13342     return false;
13343 
13344   a_src  = XEXP (xop[1], 0);
13345   a_dest = XEXP (xop[0], 0);
13346 
13347   if (PSImode == GET_MODE (a_src))
13348     {
13349       gcc_assert (as == ADDR_SPACE_MEMX);
13350 
13351       loop_mode = (count < 0x100) ? QImode : HImode;
13352       loop_reg = gen_rtx_REG (loop_mode, 24);
13353       emit_move_insn (loop_reg, gen_int_mode (count, loop_mode));
13354 
13355       addr1 = simplify_gen_subreg (HImode, a_src, PSImode, 0);
13356       a_hi8 = simplify_gen_subreg (QImode, a_src, PSImode, 2);
13357     }
13358   else
13359     {
13360       int segment = avr_addrspace[as].segment;
13361 
13362       if (segment
13363           && avr_n_flash > 1)
13364         {
13365           a_hi8 = GEN_INT (segment);
13366           emit_move_insn (rampz_rtx, a_hi8 = copy_to_mode_reg (QImode, a_hi8));
13367         }
13368       else if (!ADDR_SPACE_GENERIC_P (as))
13369         {
13370           as = ADDR_SPACE_FLASH;
13371         }
13372 
13373       addr1 = a_src;
13374 
13375       loop_mode = (count <= 0x100) ? QImode : HImode;
13376       loop_reg = copy_to_mode_reg (loop_mode, gen_int_mode (count, loop_mode));
13377     }
13378 
13379   xas = GEN_INT (as);
13380 
13381   /* FIXME: Register allocator might come up with spill fails if it is left
13382         on its own.  Thus, we allocate the pointer registers by hand:
13383         Z = source address
13384         X = destination address  */
13385 
13386   emit_move_insn (lpm_addr_reg_rtx, addr1);
13387   emit_move_insn (gen_rtx_REG (HImode, REG_X), a_dest);
13388 
13389   /* FIXME: Register allocator does a bad job and might spill address
13390         register(s) inside the loop leading to additional move instruction
13391         to/from stack which could clobber tmp_reg.  Thus, do *not* emit
13392         load and store as separate insns.  Instead, we perform the copy
13393         by means of one monolithic insn.  */
13394 
13395   gcc_assert (TMP_REGNO == LPM_REGNO);
13396 
13397   if (as != ADDR_SPACE_MEMX)
13398     {
13399       /* Load instruction ([E]LPM or LD) is known at compile time:
13400          Do the copy-loop inline.  */
13401 
13402       rtx (*fun) (rtx, rtx, rtx)
13403         = QImode == loop_mode ? gen_cpymem_qi : gen_cpymem_hi;
13404 
13405       insn = fun (xas, loop_reg, loop_reg);
13406     }
13407   else
13408     {
13409       rtx (*fun) (rtx, rtx)
13410         = QImode == loop_mode ? gen_cpymemx_qi : gen_cpymemx_hi;
13411 
13412       emit_move_insn (gen_rtx_REG (QImode, 23), a_hi8);
13413 
13414       insn = fun (xas, GEN_INT (avr_addr.rampz));
13415     }
13416 
13417   set_mem_addr_space (SET_SRC (XVECEXP (insn, 0, 0)), as);
13418   emit_insn (insn);
13419 
13420   return true;
13421 }
13422 
13423 
13424 /* Print assembler for cpymem_qi, cpymem_hi insns...
13425        $0     : Address Space
13426        $1, $2 : Loop register
13427        Z      : Source address
13428        X      : Destination address
13429 */
13430 
13431 const char*
avr_out_cpymem(rtx_insn * insn ATTRIBUTE_UNUSED,rtx * op,int * plen)13432 avr_out_cpymem (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
13433 {
13434   addr_space_t as = (addr_space_t) INTVAL (op[0]);
13435   machine_mode loop_mode = GET_MODE (op[1]);
13436   bool sbiw_p = test_hard_reg_class (ADDW_REGS, op[1]);
13437   rtx xop[3];
13438 
13439   if (plen)
13440     *plen = 0;
13441 
13442   xop[0] = op[0];
13443   xop[1] = op[1];
13444   xop[2] = tmp_reg_rtx;
13445 
13446   /* Loop label */
13447 
13448   avr_asm_len ("0:", xop, plen, 0);
13449 
13450   /* Load with post-increment */
13451 
13452   switch (as)
13453     {
13454     default:
13455       gcc_unreachable();
13456 
13457     case ADDR_SPACE_GENERIC:
13458 
13459       avr_asm_len ("ld %2,Z+", xop, plen, 1);
13460       break;
13461 
13462     case ADDR_SPACE_FLASH:
13463 
13464       if (AVR_HAVE_LPMX)
13465         avr_asm_len ("lpm %2,Z+", xop, plen, 1);
13466       else
13467         avr_asm_len ("lpm" CR_TAB
13468                      "adiw r30,1", xop, plen, 2);
13469       break;
13470 
13471     case ADDR_SPACE_FLASH1:
13472     case ADDR_SPACE_FLASH2:
13473     case ADDR_SPACE_FLASH3:
13474     case ADDR_SPACE_FLASH4:
13475     case ADDR_SPACE_FLASH5:
13476 
13477       if (AVR_HAVE_ELPMX)
13478         avr_asm_len ("elpm %2,Z+", xop, plen, 1);
13479       else
13480         avr_asm_len ("elpm" CR_TAB
13481                      "adiw r30,1", xop, plen, 2);
13482       break;
13483     }
13484 
13485   /* Store with post-increment */
13486 
13487   avr_asm_len ("st X+,%2", xop, plen, 1);
13488 
13489   /* Decrement loop-counter and set Z-flag */
13490 
13491   if (QImode == loop_mode)
13492     {
13493       avr_asm_len ("dec %1", xop, plen, 1);
13494     }
13495   else if (sbiw_p)
13496     {
13497       avr_asm_len ("sbiw %1,1", xop, plen, 1);
13498     }
13499   else
13500     {
13501       avr_asm_len ("subi %A1,1" CR_TAB
13502                    "sbci %B1,0", xop, plen, 2);
13503     }
13504 
13505   /* Loop until zero */
13506 
13507   return avr_asm_len ("brne 0b", xop, plen, 1);
13508 }
13509 
13510 
13511 
13512 /* Helper for __builtin_avr_delay_cycles */
13513 
13514 static rtx
avr_mem_clobber(void)13515 avr_mem_clobber (void)
13516 {
13517   rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
13518   MEM_VOLATILE_P (mem) = 1;
13519   return mem;
13520 }
13521 
13522 static void
avr_expand_delay_cycles(rtx operands0)13523 avr_expand_delay_cycles (rtx operands0)
13524 {
13525   unsigned HOST_WIDE_INT cycles = UINTVAL (operands0) & GET_MODE_MASK (SImode);
13526   unsigned HOST_WIDE_INT cycles_used;
13527   unsigned HOST_WIDE_INT loop_count;
13528 
13529   if (IN_RANGE (cycles, 83886082, 0xFFFFFFFF))
13530     {
13531       loop_count = ((cycles - 9) / 6) + 1;
13532       cycles_used = ((loop_count - 1) * 6) + 9;
13533       emit_insn (gen_delay_cycles_4 (gen_int_mode (loop_count, SImode),
13534                                      avr_mem_clobber()));
13535       cycles -= cycles_used;
13536     }
13537 
13538   if (IN_RANGE (cycles, 262145, 83886081))
13539     {
13540       loop_count = ((cycles - 7) / 5) + 1;
13541       if (loop_count > 0xFFFFFF)
13542         loop_count = 0xFFFFFF;
13543       cycles_used = ((loop_count - 1) * 5) + 7;
13544       emit_insn (gen_delay_cycles_3 (gen_int_mode (loop_count, SImode),
13545                                      avr_mem_clobber()));
13546       cycles -= cycles_used;
13547     }
13548 
13549   if (IN_RANGE (cycles, 768, 262144))
13550     {
13551       loop_count = ((cycles - 5) / 4) + 1;
13552       if (loop_count > 0xFFFF)
13553         loop_count = 0xFFFF;
13554       cycles_used = ((loop_count - 1) * 4) + 5;
13555       emit_insn (gen_delay_cycles_2 (gen_int_mode (loop_count, HImode),
13556                                      avr_mem_clobber()));
13557       cycles -= cycles_used;
13558     }
13559 
13560   if (IN_RANGE (cycles, 6, 767))
13561     {
13562       loop_count = cycles / 3;
13563       if (loop_count > 255)
13564         loop_count = 255;
13565       cycles_used = loop_count * 3;
13566       emit_insn (gen_delay_cycles_1 (gen_int_mode (loop_count, QImode),
13567                                      avr_mem_clobber()));
13568       cycles -= cycles_used;
13569     }
13570 
13571   while (cycles >= 2)
13572     {
13573       emit_insn (gen_nopv (GEN_INT (2)));
13574       cycles -= 2;
13575     }
13576 
13577   if (cycles == 1)
13578     {
13579       emit_insn (gen_nopv (GEN_INT (1)));
13580       cycles--;
13581     }
13582 }
13583 
13584 
13585 static void
avr_expand_nops(rtx operands0)13586 avr_expand_nops (rtx operands0)
13587 {
13588   unsigned HOST_WIDE_INT n_nops = UINTVAL (operands0) & GET_MODE_MASK (HImode);
13589 
13590   while (n_nops--)
13591     {
13592       emit_insn (gen_nopv (const1_rtx));
13593     }
13594 }
13595 
13596 
13597 /* Compute the image of x under f, i.e. perform   x --> f(x)    */
13598 
13599 static int
avr_map(unsigned int f,int x)13600 avr_map (unsigned int f, int x)
13601 {
13602   return x < 8 ? (f >> (4 * x)) & 0xf : 0;
13603 }
13604 
13605 
13606 /* Return some metrics of map A.  */
13607 
13608 enum
13609   {
13610     /* Number of fixed points in { 0 ... 7 } */
13611     MAP_FIXED_0_7,
13612 
13613     /* Size of preimage of non-fixed points in { 0 ... 7 } */
13614     MAP_NONFIXED_0_7,
13615 
13616     /* Mask representing the fixed points in { 0 ... 7 } */
13617     MAP_MASK_FIXED_0_7,
13618 
13619     /* Size of the preimage of { 0 ... 7 } */
13620     MAP_PREIMAGE_0_7,
13621 
13622     /* Mask that represents the preimage of { f } */
13623     MAP_MASK_PREIMAGE_F
13624   };
13625 
13626 static unsigned
avr_map_metric(unsigned int a,int mode)13627 avr_map_metric (unsigned int a, int mode)
13628 {
13629   unsigned metric = 0;
13630 
13631   for (unsigned i = 0; i < 8; i++)
13632     {
13633       unsigned ai = avr_map (a, i);
13634 
13635       if (mode == MAP_FIXED_0_7)
13636         metric += ai == i;
13637       else if (mode == MAP_NONFIXED_0_7)
13638         metric += ai < 8 && ai != i;
13639       else if (mode == MAP_MASK_FIXED_0_7)
13640         metric |= ((unsigned) (ai == i)) << i;
13641       else if (mode == MAP_PREIMAGE_0_7)
13642         metric += ai < 8;
13643       else if (mode == MAP_MASK_PREIMAGE_F)
13644         metric |= ((unsigned) (ai == 0xf)) << i;
13645       else
13646         gcc_unreachable();
13647     }
13648 
13649   return metric;
13650 }
13651 
13652 
13653 /* Return true if IVAL has a 0xf in its hexadecimal representation
13654    and false, otherwise.  Only nibbles 0..7 are taken into account.
13655    Used as constraint helper for C0f and Cxf.  */
13656 
13657 bool
avr_has_nibble_0xf(rtx ival)13658 avr_has_nibble_0xf (rtx ival)
13659 {
13660   unsigned int map = UINTVAL (ival) & GET_MODE_MASK (SImode);
13661   return avr_map_metric (map, MAP_MASK_PREIMAGE_F) != 0;
13662 }
13663 
13664 
13665 /* We have a set of bits that are mapped by a function F.
13666    Try to decompose F by means of a second function G so that
13667 
13668       F = F o G^-1 o G
13669 
13670    and
13671 
13672       cost (F o G^-1) + cost (G)  <  cost (F)
13673 
13674    Example:  Suppose builtin insert_bits supplies us with the map
13675    F = 0x3210ffff.  Instead of doing 4 bit insertions to get the high
13676    nibble of the result, we can just as well rotate the bits before inserting
13677    them and use the map 0x7654ffff which is cheaper than the original map.
13678    For this example G = G^-1 = 0x32107654 and F o G^-1 = 0x7654ffff.  */
13679 
13680 typedef struct
13681 {
13682   /* tree code of binary function G */
13683   enum tree_code code;
13684 
13685   /* The constant second argument of G */
13686   int arg;
13687 
13688   /* G^-1, the inverse of G (*, arg) */
13689   unsigned ginv;
13690 
13691   /* The cost of applying G (*, arg) */
13692   int cost;
13693 
13694   /* The composition F o G^-1 (*, arg) for some function F */
13695   unsigned int map;
13696 
13697   /* For debug purpose only */
13698   const char *str;
13699 } avr_map_op_t;
13700 
13701 static const avr_map_op_t avr_map_op[] =
13702   {
13703     { LROTATE_EXPR, 0, 0x76543210, 0, 0, "id" },
13704     { LROTATE_EXPR, 1, 0x07654321, 2, 0, "<<<" },
13705     { LROTATE_EXPR, 2, 0x10765432, 4, 0, "<<<" },
13706     { LROTATE_EXPR, 3, 0x21076543, 4, 0, "<<<" },
13707     { LROTATE_EXPR, 4, 0x32107654, 1, 0, "<<<" },
13708     { LROTATE_EXPR, 5, 0x43210765, 3, 0, "<<<" },
13709     { LROTATE_EXPR, 6, 0x54321076, 5, 0, "<<<" },
13710     { LROTATE_EXPR, 7, 0x65432107, 3, 0, "<<<" },
13711     { RSHIFT_EXPR, 1, 0x6543210c, 1, 0, ">>" },
13712     { RSHIFT_EXPR, 1, 0x7543210c, 1, 0, ">>" },
13713     { RSHIFT_EXPR, 2, 0x543210cc, 2, 0, ">>" },
13714     { RSHIFT_EXPR, 2, 0x643210cc, 2, 0, ">>" },
13715     { RSHIFT_EXPR, 2, 0x743210cc, 2, 0, ">>" },
13716     { LSHIFT_EXPR, 1, 0xc7654321, 1, 0, "<<" },
13717     { LSHIFT_EXPR, 2, 0xcc765432, 2, 0, "<<" }
13718   };
13719 
13720 
13721 /* Try to decompose F as F = (F o G^-1) o G as described above.
13722    The result is a struct representing F o G^-1 and G.
13723    If result.cost < 0 then such a decomposition does not exist.  */
13724 
13725 static avr_map_op_t
avr_map_decompose(unsigned int f,const avr_map_op_t * g,bool val_const_p)13726 avr_map_decompose (unsigned int f, const avr_map_op_t *g, bool val_const_p)
13727 {
13728   bool val_used_p = avr_map_metric (f, MAP_MASK_PREIMAGE_F) != 0;
13729   avr_map_op_t f_ginv = *g;
13730   unsigned int ginv = g->ginv;
13731 
13732   f_ginv.cost = -1;
13733 
13734   /* Step 1:  Computing F o G^-1  */
13735 
13736   for (int i = 7; i >= 0; i--)
13737     {
13738       int x = avr_map (f, i);
13739 
13740       if (x <= 7)
13741         {
13742           x = avr_map (ginv, x);
13743 
13744           /* The bit is no element of the image of G: no avail (cost = -1)  */
13745 
13746           if (x > 7)
13747             return f_ginv;
13748         }
13749 
13750       f_ginv.map = (f_ginv.map << 4) + x;
13751     }
13752 
13753   /* Step 2:  Compute the cost of the operations.
13754      The overall cost of doing an operation prior to the insertion is
13755       the cost of the insertion plus the cost of the operation.  */
13756 
13757   /* Step 2a:  Compute cost of F o G^-1  */
13758 
13759   if (avr_map_metric (f_ginv.map, MAP_NONFIXED_0_7) == 0)
13760     /* The mapping consists only of fixed points and can be folded
13761        to AND/OR logic in the remainder.  Reasonable cost is 3. */
13762     f_ginv.cost = 2 + (val_used_p && !val_const_p);
13763   else
13764     {
13765       rtx xop[4];
13766 
13767       /* Get the cost of the insn by calling the output worker with some
13768          fake values.  Mimic effect of reloading xop[3]: Unused operands
13769          are mapped to 0 and used operands are reloaded to xop[0].  */
13770 
13771       xop[0] = all_regs_rtx[24];
13772       xop[1] = gen_int_mode (f_ginv.map, SImode);
13773       xop[2] = all_regs_rtx[25];
13774       xop[3] = val_used_p ? xop[0] : const0_rtx;
13775 
13776       avr_out_insert_bits (xop, &f_ginv.cost);
13777 
13778       f_ginv.cost += val_const_p && val_used_p ? 1 : 0;
13779     }
13780 
13781   /* Step 2b:  Add cost of G  */
13782 
13783   f_ginv.cost += g->cost;
13784 
13785   if (avr_log.builtin)
13786     avr_edump (" %s%d=%d", g->str, g->arg, f_ginv.cost);
13787 
13788   return f_ginv;
13789 }
13790 
13791 
13792 /* Insert bits from XOP[1] into XOP[0] according to MAP.
13793    XOP[0] and XOP[1] don't overlap.
13794    If FIXP_P = true:  Move all bits according to MAP using BLD/BST sequences.
13795    If FIXP_P = false: Just move the bit if its position in the destination
13796    is different to its source position.  */
13797 
13798 static void
avr_move_bits(rtx * xop,unsigned int map,bool fixp_p,int * plen)13799 avr_move_bits (rtx *xop, unsigned int map, bool fixp_p, int *plen)
13800 {
13801   /* T-flag contains this bit of the source, i.e. of XOP[1]  */
13802   int t_bit_src = -1;
13803 
13804   /* We order the operations according to the requested source bit b.  */
13805 
13806   for (int b = 0; b < 8; b++)
13807     for (int bit_dest = 0; bit_dest < 8; bit_dest++)
13808       {
13809         int bit_src = avr_map (map, bit_dest);
13810 
13811         if (b != bit_src
13812             || bit_src >= 8
13813             /* Same position: No need to copy as requested by FIXP_P.  */
13814             || (bit_dest == bit_src && !fixp_p))
13815           continue;
13816 
13817         if (t_bit_src != bit_src)
13818           {
13819             /* Source bit is not yet in T: Store it to T.  */
13820 
13821             t_bit_src = bit_src;
13822 
13823             xop[3] = GEN_INT (bit_src);
13824             avr_asm_len ("bst %T1%T3", xop, plen, 1);
13825           }
13826 
13827         /* Load destination bit with T.  */
13828 
13829         xop[3] = GEN_INT (bit_dest);
13830         avr_asm_len ("bld %T0%T3", xop, plen, 1);
13831       }
13832 }
13833 
13834 
13835 /* PLEN == 0: Print assembler code for `insert_bits'.
13836    PLEN != 0: Compute code length in bytes.
13837 
13838    OP[0]:  Result
13839    OP[1]:  The mapping composed of nibbles. If nibble no. N is
13840            0:   Bit N of result is copied from bit OP[2].0
13841            ...  ...
13842            7:   Bit N of result is copied from bit OP[2].7
13843            0xf: Bit N of result is copied from bit OP[3].N
13844    OP[2]:  Bits to be inserted
13845    OP[3]:  Target value  */
13846 
13847 const char*
avr_out_insert_bits(rtx * op,int * plen)13848 avr_out_insert_bits (rtx *op, int *plen)
13849 {
13850   unsigned int map = UINTVAL (op[1]) & GET_MODE_MASK (SImode);
13851   unsigned mask_fixed;
13852   bool fixp_p = true;
13853   rtx xop[4];
13854 
13855   xop[0] = op[0];
13856   xop[1] = op[2];
13857   xop[2] = op[3];
13858 
13859   gcc_assert (REG_P (xop[2]) || CONST_INT_P (xop[2]));
13860 
13861   if (plen)
13862     *plen = 0;
13863   else if (flag_print_asm_name)
13864     fprintf (asm_out_file, ASM_COMMENT_START "map = 0x%08x\n", map);
13865 
13866   /* If MAP has fixed points it might be better to initialize the result
13867      with the bits to be inserted instead of moving all bits by hand.  */
13868 
13869   mask_fixed = avr_map_metric (map, MAP_MASK_FIXED_0_7);
13870 
13871   if (REGNO (xop[0]) == REGNO (xop[1]))
13872     {
13873       /* Avoid early-clobber conflicts */
13874 
13875       avr_asm_len ("mov __tmp_reg__,%1", xop, plen, 1);
13876       xop[1] = tmp_reg_rtx;
13877       fixp_p = false;
13878     }
13879 
13880   if (avr_map_metric (map, MAP_MASK_PREIMAGE_F))
13881     {
13882       /* XOP[2] is used and reloaded to XOP[0] already */
13883 
13884       int n_fix = 0, n_nofix = 0;
13885 
13886       gcc_assert (REG_P (xop[2]));
13887 
13888       /* Get the code size of the bit insertions; once with all bits
13889          moved and once with fixed points omitted.  */
13890 
13891       avr_move_bits (xop, map, true, &n_fix);
13892       avr_move_bits (xop, map, false, &n_nofix);
13893 
13894       if (fixp_p && n_fix - n_nofix > 3)
13895         {
13896           xop[3] = gen_int_mode (~mask_fixed, QImode);
13897 
13898           avr_asm_len ("eor %0,%1"   CR_TAB
13899                        "andi %0,%3"  CR_TAB
13900                        "eor %0,%1", xop, plen, 3);
13901           fixp_p = false;
13902         }
13903     }
13904   else
13905     {
13906       /* XOP[2] is unused */
13907 
13908       if (fixp_p && mask_fixed)
13909         {
13910           avr_asm_len ("mov %0,%1", xop, plen, 1);
13911           fixp_p = false;
13912         }
13913     }
13914 
13915   /* Move/insert remaining bits.  */
13916 
13917   avr_move_bits (xop, map, fixp_p, plen);
13918 
13919   return "";
13920 }
13921 
13922 
13923 /* IDs for all the AVR builtins.  */
13924 
13925 enum avr_builtin_id
13926   {
13927 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME)  \
13928     AVR_BUILTIN_ ## NAME,
13929 #include "builtins.def"
13930 #undef DEF_BUILTIN
13931 
13932     AVR_BUILTIN_COUNT
13933   };
13934 
13935 struct GTY(()) avr_builtin_description
13936 {
13937   enum insn_code icode;
13938   int n_args;
13939   tree fndecl;
13940 };
13941 
13942 
13943 /* Notice that avr_bdesc[] and avr_builtin_id are initialized in such a way
13944    that a built-in's ID can be used to access the built-in by means of
13945    avr_bdesc[ID]  */
13946 
13947 static GTY(()) struct avr_builtin_description
13948 avr_bdesc[AVR_BUILTIN_COUNT] =
13949   {
13950 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE, LIBNAME)         \
13951     { (enum insn_code) CODE_FOR_ ## ICODE, N_ARGS, NULL_TREE },
13952 #include "builtins.def"
13953 #undef DEF_BUILTIN
13954   };
13955 
13956 
13957 /* Implement `TARGET_BUILTIN_DECL'.  */
13958 
13959 static tree
avr_builtin_decl(unsigned id,bool initialize_p ATTRIBUTE_UNUSED)13960 avr_builtin_decl (unsigned id, bool initialize_p ATTRIBUTE_UNUSED)
13961 {
13962   if (id < AVR_BUILTIN_COUNT)
13963     return avr_bdesc[id].fndecl;
13964 
13965   return error_mark_node;
13966 }
13967 
13968 
13969 static void
avr_init_builtin_int24(void)13970 avr_init_builtin_int24 (void)
13971 {
13972   tree int24_type  = make_signed_type (GET_MODE_BITSIZE (PSImode));
13973   tree uint24_type = make_unsigned_type (GET_MODE_BITSIZE (PSImode));
13974 
13975   lang_hooks.types.register_builtin_type (int24_type, "__int24");
13976   lang_hooks.types.register_builtin_type (uint24_type, "__uint24");
13977 }
13978 
13979 
13980 /* Implement `TARGET_INIT_BUILTINS' */
13981 /* Set up all builtin functions for this target.  */
13982 
13983 static void
avr_init_builtins(void)13984 avr_init_builtins (void)
13985 {
13986   tree void_ftype_void
13987     = build_function_type_list (void_type_node, NULL_TREE);
13988   tree uchar_ftype_uchar
13989     = build_function_type_list (unsigned_char_type_node,
13990                                 unsigned_char_type_node,
13991                                 NULL_TREE);
13992   tree uint_ftype_uchar_uchar
13993     = build_function_type_list (unsigned_type_node,
13994                                 unsigned_char_type_node,
13995                                 unsigned_char_type_node,
13996                                 NULL_TREE);
13997   tree int_ftype_char_char
13998     = build_function_type_list (integer_type_node,
13999                                 char_type_node,
14000                                 char_type_node,
14001                                 NULL_TREE);
14002   tree int_ftype_char_uchar
14003     = build_function_type_list (integer_type_node,
14004                                 char_type_node,
14005                                 unsigned_char_type_node,
14006                                 NULL_TREE);
14007   tree void_ftype_ulong
14008     = build_function_type_list (void_type_node,
14009                                 long_unsigned_type_node,
14010                                 NULL_TREE);
14011 
14012   tree uchar_ftype_ulong_uchar_uchar
14013     = build_function_type_list (unsigned_char_type_node,
14014                                 long_unsigned_type_node,
14015                                 unsigned_char_type_node,
14016                                 unsigned_char_type_node,
14017                                 NULL_TREE);
14018 
14019   tree const_memx_void_node
14020     = build_qualified_type (void_type_node,
14021                             TYPE_QUAL_CONST
14022                             | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_MEMX));
14023 
14024   tree const_memx_ptr_type_node
14025     = build_pointer_type_for_mode (const_memx_void_node, PSImode, false);
14026 
14027   tree char_ftype_const_memx_ptr
14028     = build_function_type_list (char_type_node,
14029                                 const_memx_ptr_type_node,
14030                                 NULL);
14031 
14032 #define ITYP(T)                                                         \
14033   lang_hooks.types.type_for_size (TYPE_PRECISION (T), TYPE_UNSIGNED (T))
14034 
14035 #define FX_FTYPE_FX(fx)                                                 \
14036   tree fx##r_ftype_##fx##r                                              \
14037     = build_function_type_list (node_##fx##r, node_##fx##r, NULL);      \
14038   tree fx##k_ftype_##fx##k                                              \
14039     = build_function_type_list (node_##fx##k, node_##fx##k, NULL)
14040 
14041 #define FX_FTYPE_FX_INT(fx)                                             \
14042   tree fx##r_ftype_##fx##r_int                                          \
14043     = build_function_type_list (node_##fx##r, node_##fx##r,             \
14044                                 integer_type_node, NULL);               \
14045   tree fx##k_ftype_##fx##k_int                                          \
14046     = build_function_type_list (node_##fx##k, node_##fx##k,             \
14047                                 integer_type_node, NULL)
14048 
14049 #define INT_FTYPE_FX(fx)                                                \
14050   tree int_ftype_##fx##r                                                \
14051     = build_function_type_list (integer_type_node, node_##fx##r, NULL); \
14052   tree int_ftype_##fx##k                                                \
14053     = build_function_type_list (integer_type_node, node_##fx##k, NULL)
14054 
14055 #define INTX_FTYPE_FX(fx)                                               \
14056   tree int##fx##r_ftype_##fx##r                                         \
14057     = build_function_type_list (ITYP (node_##fx##r), node_##fx##r, NULL); \
14058   tree int##fx##k_ftype_##fx##k                                         \
14059     = build_function_type_list (ITYP (node_##fx##k), node_##fx##k, NULL)
14060 
14061 #define FX_FTYPE_INTX(fx)                                               \
14062   tree fx##r_ftype_int##fx##r                                           \
14063     = build_function_type_list (node_##fx##r, ITYP (node_##fx##r), NULL); \
14064   tree fx##k_ftype_int##fx##k                                           \
14065     = build_function_type_list (node_##fx##k, ITYP (node_##fx##k), NULL)
14066 
14067   tree node_hr = short_fract_type_node;
14068   tree node_nr = fract_type_node;
14069   tree node_lr = long_fract_type_node;
14070   tree node_llr = long_long_fract_type_node;
14071 
14072   tree node_uhr = unsigned_short_fract_type_node;
14073   tree node_unr = unsigned_fract_type_node;
14074   tree node_ulr = unsigned_long_fract_type_node;
14075   tree node_ullr = unsigned_long_long_fract_type_node;
14076 
14077   tree node_hk = short_accum_type_node;
14078   tree node_nk = accum_type_node;
14079   tree node_lk = long_accum_type_node;
14080   tree node_llk = long_long_accum_type_node;
14081 
14082   tree node_uhk = unsigned_short_accum_type_node;
14083   tree node_unk = unsigned_accum_type_node;
14084   tree node_ulk = unsigned_long_accum_type_node;
14085   tree node_ullk = unsigned_long_long_accum_type_node;
14086 
14087 
14088   /* For absfx builtins.  */
14089 
14090   FX_FTYPE_FX (h);
14091   FX_FTYPE_FX (n);
14092   FX_FTYPE_FX (l);
14093   FX_FTYPE_FX (ll);
14094 
14095   /* For roundfx builtins.  */
14096 
14097   FX_FTYPE_FX_INT (h);
14098   FX_FTYPE_FX_INT (n);
14099   FX_FTYPE_FX_INT (l);
14100   FX_FTYPE_FX_INT (ll);
14101 
14102   FX_FTYPE_FX_INT (uh);
14103   FX_FTYPE_FX_INT (un);
14104   FX_FTYPE_FX_INT (ul);
14105   FX_FTYPE_FX_INT (ull);
14106 
14107   /* For countlsfx builtins.  */
14108 
14109   INT_FTYPE_FX (h);
14110   INT_FTYPE_FX (n);
14111   INT_FTYPE_FX (l);
14112   INT_FTYPE_FX (ll);
14113 
14114   INT_FTYPE_FX (uh);
14115   INT_FTYPE_FX (un);
14116   INT_FTYPE_FX (ul);
14117   INT_FTYPE_FX (ull);
14118 
14119   /* For bitsfx builtins.  */
14120 
14121   INTX_FTYPE_FX (h);
14122   INTX_FTYPE_FX (n);
14123   INTX_FTYPE_FX (l);
14124   INTX_FTYPE_FX (ll);
14125 
14126   INTX_FTYPE_FX (uh);
14127   INTX_FTYPE_FX (un);
14128   INTX_FTYPE_FX (ul);
14129   INTX_FTYPE_FX (ull);
14130 
14131   /* For fxbits builtins.  */
14132 
14133   FX_FTYPE_INTX (h);
14134   FX_FTYPE_INTX (n);
14135   FX_FTYPE_INTX (l);
14136   FX_FTYPE_INTX (ll);
14137 
14138   FX_FTYPE_INTX (uh);
14139   FX_FTYPE_INTX (un);
14140   FX_FTYPE_INTX (ul);
14141   FX_FTYPE_INTX (ull);
14142 
14143 
14144 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME)                  \
14145   {                                                                     \
14146     int id = AVR_BUILTIN_ ## NAME;                                      \
14147     const char *Name = "__builtin_avr_" #NAME;                          \
14148     char *name = (char*) alloca (1 + strlen (Name));                    \
14149                                                                         \
14150     gcc_assert (id < AVR_BUILTIN_COUNT);                                \
14151     avr_bdesc[id].fndecl                                                \
14152       = add_builtin_function (avr_tolower (name, Name), TYPE, id,       \
14153                               BUILT_IN_MD, LIBNAME, NULL_TREE);         \
14154   }
14155 #include "builtins.def"
14156 #undef DEF_BUILTIN
14157 
14158   avr_init_builtin_int24 ();
14159 }
14160 
14161 
14162 /* Subroutine of avr_expand_builtin to expand vanilla builtins
14163    with non-void result and 1 ... 3 arguments.  */
14164 
14165 static rtx
avr_default_expand_builtin(enum insn_code icode,tree exp,rtx target)14166 avr_default_expand_builtin (enum insn_code icode, tree exp, rtx target)
14167 {
14168   rtx pat, xop[3];
14169   int n_args = call_expr_nargs (exp);
14170   machine_mode tmode = insn_data[icode].operand[0].mode;
14171 
14172   gcc_assert (n_args >= 1 && n_args <= 3);
14173 
14174   if (target == NULL_RTX
14175       || GET_MODE (target) != tmode
14176       || !insn_data[icode].operand[0].predicate (target, tmode))
14177     {
14178       target = gen_reg_rtx (tmode);
14179     }
14180 
14181   for (int n = 0; n < n_args; n++)
14182     {
14183       tree arg = CALL_EXPR_ARG (exp, n);
14184       rtx op = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14185       machine_mode opmode = GET_MODE (op);
14186       machine_mode mode = insn_data[icode].operand[n + 1].mode;
14187 
14188       if ((opmode == SImode || opmode == VOIDmode) && mode == HImode)
14189         {
14190           opmode = HImode;
14191           op = gen_lowpart (HImode, op);
14192         }
14193 
14194       /* In case the insn wants input operands in modes different from
14195          the result, abort.  */
14196 
14197       gcc_assert (opmode == mode || opmode == VOIDmode);
14198 
14199       if (!insn_data[icode].operand[n + 1].predicate (op, mode))
14200         op = copy_to_mode_reg (mode, op);
14201 
14202       xop[n] = op;
14203     }
14204 
14205   switch (n_args)
14206     {
14207     case 1: pat = GEN_FCN (icode) (target, xop[0]); break;
14208     case 2: pat = GEN_FCN (icode) (target, xop[0], xop[1]); break;
14209     case 3: pat = GEN_FCN (icode) (target, xop[0], xop[1], xop[2]); break;
14210 
14211     default:
14212       gcc_unreachable();
14213     }
14214 
14215   if (pat == NULL_RTX)
14216     return NULL_RTX;
14217 
14218   emit_insn (pat);
14219 
14220   return target;
14221 }
14222 
14223 
14224 /* Implement `TARGET_EXPAND_BUILTIN'.  */
14225 /* Expand an expression EXP that calls a built-in function,
14226    with result going to TARGET if that's convenient
14227    (and in mode MODE if that's convenient).
14228    SUBTARGET may be used as the target for computing one of EXP's operands.
14229    IGNORE is nonzero if the value is to be ignored.  */
14230 
14231 static rtx
avr_expand_builtin(tree exp,rtx target,rtx subtarget ATTRIBUTE_UNUSED,machine_mode mode ATTRIBUTE_UNUSED,int ignore)14232 avr_expand_builtin (tree exp, rtx target,
14233                     rtx subtarget ATTRIBUTE_UNUSED,
14234                     machine_mode mode ATTRIBUTE_UNUSED,
14235                     int ignore)
14236 {
14237   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
14238   const char *bname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
14239   unsigned int id = DECL_MD_FUNCTION_CODE (fndecl);
14240   const struct avr_builtin_description *d = &avr_bdesc[id];
14241   tree arg0;
14242   rtx op0;
14243 
14244   gcc_assert (id < AVR_BUILTIN_COUNT);
14245 
14246   switch (id)
14247     {
14248     case AVR_BUILTIN_NOP:
14249       emit_insn (gen_nopv (GEN_INT (1)));
14250       return 0;
14251 
14252     case AVR_BUILTIN_DELAY_CYCLES:
14253       {
14254         arg0 = CALL_EXPR_ARG (exp, 0);
14255         op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14256 
14257         if (!CONST_INT_P (op0))
14258           error ("%s expects a compile time integer constant", bname);
14259         else
14260           avr_expand_delay_cycles (op0);
14261 
14262         return NULL_RTX;
14263       }
14264 
14265     case AVR_BUILTIN_NOPS:
14266       {
14267         arg0 = CALL_EXPR_ARG (exp, 0);
14268         op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14269 
14270         if (!CONST_INT_P (op0))
14271           error ("%s expects a compile time integer constant", bname);
14272         else
14273           avr_expand_nops (op0);
14274 
14275         return NULL_RTX;
14276       }
14277 
14278     case AVR_BUILTIN_INSERT_BITS:
14279       {
14280         arg0 = CALL_EXPR_ARG (exp, 0);
14281         op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14282 
14283         if (!CONST_INT_P (op0))
14284           {
14285             error ("%s expects a compile time long integer constant"
14286                    " as first argument", bname);
14287             return target;
14288           }
14289 
14290         break;
14291       }
14292 
14293     case AVR_BUILTIN_ROUNDHR:   case AVR_BUILTIN_ROUNDUHR:
14294     case AVR_BUILTIN_ROUNDR:    case AVR_BUILTIN_ROUNDUR:
14295     case AVR_BUILTIN_ROUNDLR:   case AVR_BUILTIN_ROUNDULR:
14296     case AVR_BUILTIN_ROUNDLLR:  case AVR_BUILTIN_ROUNDULLR:
14297 
14298     case AVR_BUILTIN_ROUNDHK:   case AVR_BUILTIN_ROUNDUHK:
14299     case AVR_BUILTIN_ROUNDK:    case AVR_BUILTIN_ROUNDUK:
14300     case AVR_BUILTIN_ROUNDLK:   case AVR_BUILTIN_ROUNDULK:
14301     case AVR_BUILTIN_ROUNDLLK:  case AVR_BUILTIN_ROUNDULLK:
14302 
14303       /* Warn about odd rounding.  Rounding points >= FBIT will have
14304          no effect.  */
14305 
14306       if (TREE_CODE (CALL_EXPR_ARG (exp, 1)) != INTEGER_CST)
14307         break;
14308 
14309       int rbit = (int) TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1));
14310 
14311       if (rbit >= (int) GET_MODE_FBIT (mode))
14312         {
14313           warning (OPT_Wextra, "rounding to %d bits has no effect for "
14314                    "fixed-point value with %d fractional bits",
14315                    rbit, GET_MODE_FBIT (mode));
14316 
14317           return expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX, mode,
14318                               EXPAND_NORMAL);
14319         }
14320       else if (rbit <= - (int) GET_MODE_IBIT (mode))
14321         {
14322           warning (0, "rounding result will always be 0");
14323           return CONST0_RTX (mode);
14324         }
14325 
14326       /* The rounding points RP satisfies now:  -IBIT < RP < FBIT.
14327 
14328          TR 18037 only specifies results for  RP > 0.  However, the
14329          remaining cases of  -IBIT < RP <= 0  can easily be supported
14330          without any additional overhead.  */
14331 
14332       break; /* round */
14333     }
14334 
14335   /* No fold found and no insn:  Call support function from libgcc.  */
14336 
14337   if (d->icode == CODE_FOR_nothing
14338       && DECL_ASSEMBLER_NAME (get_callee_fndecl (exp)) != NULL_TREE)
14339     {
14340       return expand_call (exp, target, ignore);
14341     }
14342 
14343   /* No special treatment needed: vanilla expand.  */
14344 
14345   gcc_assert (d->icode != CODE_FOR_nothing);
14346   gcc_assert (d->n_args == call_expr_nargs (exp));
14347 
14348   if (d->n_args == 0)
14349     {
14350       emit_insn ((GEN_FCN (d->icode)) (target));
14351       return NULL_RTX;
14352     }
14353 
14354   return avr_default_expand_builtin (d->icode, exp, target);
14355 }
14356 
14357 
14358 /* Helper for `avr_fold_builtin' that folds  absfx (FIXED_CST).  */
14359 
14360 static tree
avr_fold_absfx(tree tval)14361 avr_fold_absfx (tree tval)
14362 {
14363   if (FIXED_CST != TREE_CODE (tval))
14364     return NULL_TREE;
14365 
14366   /* Our fixed-points have no padding:  Use double_int payload directly.  */
14367 
14368   FIXED_VALUE_TYPE fval = TREE_FIXED_CST (tval);
14369   unsigned int bits = GET_MODE_BITSIZE (fval.mode);
14370   double_int ival = fval.data.sext (bits);
14371 
14372   if (!ival.is_negative())
14373     return tval;
14374 
14375   /* ISO/IEC TR 18037, 7.18a.6.2:  The absfx functions are saturating.  */
14376 
14377   fval.data = (ival == double_int::min_value (bits, false).sext (bits))
14378     ? double_int::max_value (bits, false)
14379     : -ival;
14380 
14381   return build_fixed (TREE_TYPE (tval), fval);
14382 }
14383 
14384 
14385 /* Implement `TARGET_FOLD_BUILTIN'.  */
14386 
14387 static tree
avr_fold_builtin(tree fndecl,int n_args ATTRIBUTE_UNUSED,tree * arg,bool ignore ATTRIBUTE_UNUSED)14388 avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg,
14389                   bool ignore ATTRIBUTE_UNUSED)
14390 {
14391   unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
14392   tree val_type = TREE_TYPE (TREE_TYPE (fndecl));
14393 
14394   if (!optimize)
14395     return NULL_TREE;
14396 
14397   switch (fcode)
14398     {
14399     default:
14400       break;
14401 
14402     case AVR_BUILTIN_SWAP:
14403       {
14404         return fold_build2 (LROTATE_EXPR, val_type, arg[0],
14405                             build_int_cst (val_type, 4));
14406       }
14407 
14408     case AVR_BUILTIN_ABSHR:
14409     case AVR_BUILTIN_ABSR:
14410     case AVR_BUILTIN_ABSLR:
14411     case AVR_BUILTIN_ABSLLR:
14412 
14413     case AVR_BUILTIN_ABSHK:
14414     case AVR_BUILTIN_ABSK:
14415     case AVR_BUILTIN_ABSLK:
14416     case AVR_BUILTIN_ABSLLK:
14417       /* GCC is not good with folding ABS for fixed-point.  Do it by hand.  */
14418 
14419       return avr_fold_absfx (arg[0]);
14420 
14421     case AVR_BUILTIN_BITSHR:    case AVR_BUILTIN_HRBITS:
14422     case AVR_BUILTIN_BITSHK:    case AVR_BUILTIN_HKBITS:
14423     case AVR_BUILTIN_BITSUHR:   case AVR_BUILTIN_UHRBITS:
14424     case AVR_BUILTIN_BITSUHK:   case AVR_BUILTIN_UHKBITS:
14425 
14426     case AVR_BUILTIN_BITSR:     case AVR_BUILTIN_RBITS:
14427     case AVR_BUILTIN_BITSK:     case AVR_BUILTIN_KBITS:
14428     case AVR_BUILTIN_BITSUR:    case AVR_BUILTIN_URBITS:
14429     case AVR_BUILTIN_BITSUK:    case AVR_BUILTIN_UKBITS:
14430 
14431     case AVR_BUILTIN_BITSLR:    case AVR_BUILTIN_LRBITS:
14432     case AVR_BUILTIN_BITSLK:    case AVR_BUILTIN_LKBITS:
14433     case AVR_BUILTIN_BITSULR:   case AVR_BUILTIN_ULRBITS:
14434     case AVR_BUILTIN_BITSULK:   case AVR_BUILTIN_ULKBITS:
14435 
14436     case AVR_BUILTIN_BITSLLR:   case AVR_BUILTIN_LLRBITS:
14437     case AVR_BUILTIN_BITSLLK:   case AVR_BUILTIN_LLKBITS:
14438     case AVR_BUILTIN_BITSULLR:  case AVR_BUILTIN_ULLRBITS:
14439     case AVR_BUILTIN_BITSULLK:  case AVR_BUILTIN_ULLKBITS:
14440 
14441       gcc_assert (TYPE_PRECISION (val_type)
14442                   == TYPE_PRECISION (TREE_TYPE (arg[0])));
14443 
14444       return build1 (VIEW_CONVERT_EXPR, val_type, arg[0]);
14445 
14446     case AVR_BUILTIN_INSERT_BITS:
14447       {
14448         tree tbits = arg[1];
14449         tree tval = arg[2];
14450         tree tmap;
14451         tree map_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
14452         unsigned int map;
14453         bool changed = false;
14454         avr_map_op_t best_g;
14455 
14456         if (TREE_CODE (arg[0]) != INTEGER_CST)
14457           {
14458             /* No constant as first argument: Don't fold this and run into
14459                error in avr_expand_builtin.  */
14460 
14461             break;
14462           }
14463 
14464         tmap = wide_int_to_tree (map_type, wi::to_wide (arg[0]));
14465         map = TREE_INT_CST_LOW (tmap);
14466 
14467         if (TREE_CODE (tval) != INTEGER_CST
14468 	    && avr_map_metric (map, MAP_MASK_PREIMAGE_F) == 0)
14469           {
14470             /* There are no F in the map, i.e. 3rd operand is unused.
14471                Replace that argument with some constant to render
14472                respective input unused.  */
14473 
14474             tval = build_int_cst (val_type, 0);
14475             changed = true;
14476           }
14477 
14478         if (TREE_CODE (tbits) != INTEGER_CST
14479 	    && avr_map_metric (map, MAP_PREIMAGE_0_7) == 0)
14480           {
14481             /* Similar for the bits to be inserted. If they are unused,
14482                we can just as well pass 0.  */
14483 
14484             tbits = build_int_cst (val_type, 0);
14485           }
14486 
14487         if (TREE_CODE (tbits) == INTEGER_CST)
14488           {
14489             /* Inserting bits known at compile time is easy and can be
14490                performed by AND and OR with appropriate masks.  */
14491 
14492             int bits = TREE_INT_CST_LOW (tbits);
14493             int mask_ior = 0, mask_and = 0xff;
14494 
14495             for (size_t i = 0; i < 8; i++)
14496               {
14497                 int mi = avr_map (map, i);
14498 
14499                 if (mi < 8)
14500                   {
14501                     if (bits & (1 << mi))     mask_ior |=  (1 << i);
14502                     else                      mask_and &= ~(1 << i);
14503                   }
14504               }
14505 
14506             tval = fold_build2 (BIT_IOR_EXPR, val_type, tval,
14507                                 build_int_cst (val_type, mask_ior));
14508             return fold_build2 (BIT_AND_EXPR, val_type, tval,
14509                                 build_int_cst (val_type, mask_and));
14510           }
14511 
14512         if (changed)
14513           return build_call_expr (fndecl, 3, tmap, tbits, tval);
14514 
14515         /* If bits don't change their position we can use vanilla logic
14516            to merge the two arguments.  */
14517 
14518 	if (avr_map_metric (map, MAP_NONFIXED_0_7) == 0)
14519           {
14520             int mask_f = avr_map_metric (map, MAP_MASK_PREIMAGE_F);
14521             tree tres, tmask = build_int_cst (val_type, mask_f ^ 0xff);
14522 
14523             tres = fold_build2 (BIT_XOR_EXPR, val_type, tbits, tval);
14524             tres = fold_build2 (BIT_AND_EXPR, val_type, tres, tmask);
14525             return fold_build2 (BIT_XOR_EXPR, val_type, tres, tval);
14526           }
14527 
14528         /* Try to decomposing map to reduce overall cost.  */
14529 
14530         if (avr_log.builtin)
14531           avr_edump ("\n%?: %x\n%?: ROL cost: ", map);
14532 
14533         best_g = avr_map_op[0];
14534         best_g.cost = 1000;
14535 
14536         for (size_t i = 0; i < ARRAY_SIZE (avr_map_op); i++)
14537           {
14538             avr_map_op_t g
14539               = avr_map_decompose (map, avr_map_op + i,
14540                                    TREE_CODE (tval) == INTEGER_CST);
14541 
14542             if (g.cost >= 0 && g.cost < best_g.cost)
14543               best_g = g;
14544           }
14545 
14546         if (avr_log.builtin)
14547           avr_edump ("\n");
14548 
14549         if (best_g.arg == 0)
14550           /* No optimization found */
14551           break;
14552 
14553         /* Apply operation G to the 2nd argument.  */
14554 
14555         if (avr_log.builtin)
14556           avr_edump ("%?: using OP(%s%d, %x) cost %d\n",
14557                      best_g.str, best_g.arg, best_g.map, best_g.cost);
14558 
14559         /* Do right-shifts arithmetically: They copy the MSB instead of
14560            shifting in a non-usable value (0) as with logic right-shift.  */
14561 
14562         tbits = fold_convert (signed_char_type_node, tbits);
14563         tbits = fold_build2 (best_g.code, signed_char_type_node, tbits,
14564                              build_int_cst (val_type, best_g.arg));
14565         tbits = fold_convert (val_type, tbits);
14566 
14567         /* Use map o G^-1 instead of original map to undo the effect of G.  */
14568 
14569         tmap = wide_int_to_tree (map_type, best_g.map);
14570 
14571         return build_call_expr (fndecl, 3, tmap, tbits, tval);
14572       } /* AVR_BUILTIN_INSERT_BITS */
14573     }
14574 
14575   return NULL_TREE;
14576 }
14577 
14578 
14579 /* Worker function for `FLOAT_LIB_COMPARE_RETURNS_BOOL'.  */
14580 
14581 bool
avr_float_lib_compare_returns_bool(machine_mode mode,enum rtx_code)14582 avr_float_lib_compare_returns_bool (machine_mode mode, enum rtx_code)
14583 {
14584   if (mode == DFmode)
14585     {
14586 #if WITH_DOUBLE_COMPARISON == 2
14587       return true;
14588 #endif
14589     }
14590 
14591   // This is the GCC default and also what AVR-LibC implements.
14592   return false;
14593 }
14594 
14595 
14596 
14597 /* Initialize the GCC target structure.  */
14598 
14599 #undef  TARGET_ASM_ALIGNED_HI_OP
14600 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
14601 #undef  TARGET_ASM_ALIGNED_SI_OP
14602 #define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
14603 #undef  TARGET_ASM_UNALIGNED_HI_OP
14604 #define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
14605 #undef  TARGET_ASM_UNALIGNED_SI_OP
14606 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
14607 #undef  TARGET_ASM_INTEGER
14608 #define TARGET_ASM_INTEGER avr_assemble_integer
14609 #undef  TARGET_ASM_FILE_START
14610 #define TARGET_ASM_FILE_START avr_file_start
14611 #undef  TARGET_ASM_FILE_END
14612 #define TARGET_ASM_FILE_END avr_file_end
14613 
14614 #undef  TARGET_ASM_FUNCTION_END_PROLOGUE
14615 #define TARGET_ASM_FUNCTION_END_PROLOGUE avr_asm_function_end_prologue
14616 #undef  TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
14617 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE avr_asm_function_begin_epilogue
14618 
14619 #undef  TARGET_FUNCTION_VALUE
14620 #define TARGET_FUNCTION_VALUE avr_function_value
14621 #undef  TARGET_LIBCALL_VALUE
14622 #define TARGET_LIBCALL_VALUE avr_libcall_value
14623 #undef  TARGET_FUNCTION_VALUE_REGNO_P
14624 #define TARGET_FUNCTION_VALUE_REGNO_P avr_function_value_regno_p
14625 
14626 #undef  TARGET_ATTRIBUTE_TABLE
14627 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
14628 #undef  TARGET_INSERT_ATTRIBUTES
14629 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
14630 #undef  TARGET_SECTION_TYPE_FLAGS
14631 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
14632 
14633 #undef  TARGET_ASM_NAMED_SECTION
14634 #define TARGET_ASM_NAMED_SECTION avr_asm_named_section
14635 #undef  TARGET_ASM_INIT_SECTIONS
14636 #define TARGET_ASM_INIT_SECTIONS avr_asm_init_sections
14637 #undef  TARGET_ENCODE_SECTION_INFO
14638 #define TARGET_ENCODE_SECTION_INFO avr_encode_section_info
14639 #undef  TARGET_ASM_SELECT_SECTION
14640 #define TARGET_ASM_SELECT_SECTION avr_asm_select_section
14641 
14642 #undef  TARGET_ASM_FINAL_POSTSCAN_INSN
14643 #define TARGET_ASM_FINAL_POSTSCAN_INSN avr_asm_final_postscan_insn
14644 
14645 #undef  TARGET_REGISTER_MOVE_COST
14646 #define TARGET_REGISTER_MOVE_COST avr_register_move_cost
14647 #undef  TARGET_MEMORY_MOVE_COST
14648 #define TARGET_MEMORY_MOVE_COST avr_memory_move_cost
14649 #undef  TARGET_RTX_COSTS
14650 #define TARGET_RTX_COSTS avr_rtx_costs
14651 #undef  TARGET_ADDRESS_COST
14652 #define TARGET_ADDRESS_COST avr_address_cost
14653 #undef  TARGET_MACHINE_DEPENDENT_REORG
14654 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
14655 #undef  TARGET_FUNCTION_ARG
14656 #define TARGET_FUNCTION_ARG avr_function_arg
14657 #undef  TARGET_FUNCTION_ARG_ADVANCE
14658 #define TARGET_FUNCTION_ARG_ADVANCE avr_function_arg_advance
14659 
14660 #undef  TARGET_SET_CURRENT_FUNCTION
14661 #define TARGET_SET_CURRENT_FUNCTION avr_set_current_function
14662 
14663 #undef  TARGET_RETURN_IN_MEMORY
14664 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
14665 
14666 #undef  TARGET_STRICT_ARGUMENT_NAMING
14667 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
14668 
14669 #undef TARGET_CONDITIONAL_REGISTER_USAGE
14670 #define TARGET_CONDITIONAL_REGISTER_USAGE avr_conditional_register_usage
14671 
14672 #undef  TARGET_HARD_REGNO_MODE_OK
14673 #define TARGET_HARD_REGNO_MODE_OK avr_hard_regno_mode_ok
14674 #undef  TARGET_HARD_REGNO_SCRATCH_OK
14675 #define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok
14676 #undef  TARGET_HARD_REGNO_CALL_PART_CLOBBERED
14677 #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
14678   avr_hard_regno_call_part_clobbered
14679 
14680 #undef  TARGET_CASE_VALUES_THRESHOLD
14681 #define TARGET_CASE_VALUES_THRESHOLD avr_case_values_threshold
14682 
14683 #undef  TARGET_FRAME_POINTER_REQUIRED
14684 #define TARGET_FRAME_POINTER_REQUIRED avr_frame_pointer_required_p
14685 #undef  TARGET_CAN_ELIMINATE
14686 #define TARGET_CAN_ELIMINATE avr_can_eliminate
14687 
14688 #undef  TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
14689 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS avr_allocate_stack_slots_for_args
14690 
14691 #undef TARGET_WARN_FUNC_RETURN
14692 #define TARGET_WARN_FUNC_RETURN avr_warn_func_return
14693 
14694 #undef  TARGET_CLASS_LIKELY_SPILLED_P
14695 #define TARGET_CLASS_LIKELY_SPILLED_P avr_class_likely_spilled_p
14696 
14697 #undef  TARGET_OPTION_OVERRIDE
14698 #define TARGET_OPTION_OVERRIDE avr_option_override
14699 
14700 #undef  TARGET_CANNOT_MODIFY_JUMPS_P
14701 #define TARGET_CANNOT_MODIFY_JUMPS_P avr_cannot_modify_jumps_p
14702 
14703 #undef  TARGET_FUNCTION_OK_FOR_SIBCALL
14704 #define TARGET_FUNCTION_OK_FOR_SIBCALL avr_function_ok_for_sibcall
14705 
14706 #undef  TARGET_INIT_BUILTINS
14707 #define TARGET_INIT_BUILTINS avr_init_builtins
14708 
14709 #undef  TARGET_BUILTIN_DECL
14710 #define TARGET_BUILTIN_DECL avr_builtin_decl
14711 
14712 #undef  TARGET_EXPAND_BUILTIN
14713 #define TARGET_EXPAND_BUILTIN avr_expand_builtin
14714 
14715 #undef  TARGET_FOLD_BUILTIN
14716 #define TARGET_FOLD_BUILTIN avr_fold_builtin
14717 
14718 #undef  TARGET_SCALAR_MODE_SUPPORTED_P
14719 #define TARGET_SCALAR_MODE_SUPPORTED_P avr_scalar_mode_supported_p
14720 
14721 #undef  TARGET_BUILD_BUILTIN_VA_LIST
14722 #define TARGET_BUILD_BUILTIN_VA_LIST avr_build_builtin_va_list
14723 
14724 #undef  TARGET_FIXED_POINT_SUPPORTED_P
14725 #define TARGET_FIXED_POINT_SUPPORTED_P hook_bool_void_true
14726 
14727 #undef  TARGET_CONVERT_TO_TYPE
14728 #define TARGET_CONVERT_TO_TYPE avr_convert_to_type
14729 
14730 #undef TARGET_LRA_P
14731 #define TARGET_LRA_P hook_bool_void_false
14732 
14733 #undef  TARGET_ADDR_SPACE_SUBSET_P
14734 #define TARGET_ADDR_SPACE_SUBSET_P avr_addr_space_subset_p
14735 
14736 #undef  TARGET_ADDR_SPACE_CONVERT
14737 #define TARGET_ADDR_SPACE_CONVERT avr_addr_space_convert
14738 
14739 #undef  TARGET_ADDR_SPACE_ADDRESS_MODE
14740 #define TARGET_ADDR_SPACE_ADDRESS_MODE avr_addr_space_address_mode
14741 
14742 #undef  TARGET_ADDR_SPACE_POINTER_MODE
14743 #define TARGET_ADDR_SPACE_POINTER_MODE avr_addr_space_pointer_mode
14744 
14745 #undef  TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
14746 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P  \
14747   avr_addr_space_legitimate_address_p
14748 
14749 #undef  TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
14750 #define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS avr_addr_space_legitimize_address
14751 
14752 #undef  TARGET_ADDR_SPACE_DIAGNOSE_USAGE
14753 #define TARGET_ADDR_SPACE_DIAGNOSE_USAGE avr_addr_space_diagnose_usage
14754 
14755 #undef  TARGET_MODE_DEPENDENT_ADDRESS_P
14756 #define TARGET_MODE_DEPENDENT_ADDRESS_P avr_mode_dependent_address_p
14757 
14758 #undef  TARGET_PRINT_OPERAND
14759 #define TARGET_PRINT_OPERAND avr_print_operand
14760 #undef  TARGET_PRINT_OPERAND_ADDRESS
14761 #define TARGET_PRINT_OPERAND_ADDRESS avr_print_operand_address
14762 #undef  TARGET_PRINT_OPERAND_PUNCT_VALID_P
14763 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P avr_print_operand_punct_valid_p
14764 
14765 #undef TARGET_USE_BY_PIECES_INFRASTRUCTURE_P
14766 #define TARGET_USE_BY_PIECES_INFRASTRUCTURE_P \
14767   avr_use_by_pieces_infrastructure_p
14768 
14769 #undef  TARGET_LEGITIMATE_COMBINED_INSN
14770 #define TARGET_LEGITIMATE_COMBINED_INSN avr_legitimate_combined_insn
14771 
14772 #undef  TARGET_STARTING_FRAME_OFFSET
14773 #define TARGET_STARTING_FRAME_OFFSET avr_starting_frame_offset
14774 
14775 struct gcc_target targetm = TARGET_INITIALIZER;
14776 
14777 
14778 #include "gt-avr.h"
14779