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 /* The 4 bits starting at SECTION_MACH_DEP are reserved to store the
67    address space where data is to be located.
68    As the only non-generic address spaces are all located in flash,
69    this can be used to test if data shall go into some .progmem* section.
70    This must be the rightmost field of machine dependent section flags.  */
71 #define AVR_SECTION_PROGMEM (0xf * SECTION_MACH_DEP)
72 
73 /* Similar 4-bit region for SYMBOL_REF_FLAGS.  */
74 #define AVR_SYMBOL_FLAG_PROGMEM (0xf * SYMBOL_FLAG_MACH_DEP)
75 
76 /* Similar 4-bit region in SYMBOL_REF_FLAGS:
77    Set address-space AS in SYMBOL_REF_FLAGS of SYM  */
78 #define AVR_SYMBOL_SET_ADDR_SPACE(SYM,AS)                       \
79   do {                                                          \
80     SYMBOL_REF_FLAGS (sym) &= ~AVR_SYMBOL_FLAG_PROGMEM;         \
81     SYMBOL_REF_FLAGS (sym) |= (AS) * SYMBOL_FLAG_MACH_DEP;      \
82   } while (0)
83 
84 /* Read address-space from SYMBOL_REF_FLAGS of SYM  */
85 #define AVR_SYMBOL_GET_ADDR_SPACE(SYM)                          \
86   ((SYMBOL_REF_FLAGS (sym) & AVR_SYMBOL_FLAG_PROGMEM)           \
87    / SYMBOL_FLAG_MACH_DEP)
88 
89 /* (AVR_TINY only): Symbol has attribute progmem */
90 #define AVR_SYMBOL_FLAG_TINY_PM \
91   (SYMBOL_FLAG_MACH_DEP << 7)
92 
93 /* (AVR_TINY only): Symbol has attribute absdata */
94 #define AVR_SYMBOL_FLAG_TINY_ABSDATA \
95   (SYMBOL_FLAG_MACH_DEP << 8)
96 
97 #define TINY_ADIW(REG1, REG2, I)                                \
98     "subi " #REG1 ",lo8(-(" #I "))" CR_TAB                      \
99     "sbci " #REG2 ",hi8(-(" #I "))"
100 
101 #define TINY_SBIW(REG1, REG2, I)                                \
102     "subi " #REG1 ",lo8((" #I "))" CR_TAB                       \
103     "sbci " #REG2 ",hi8((" #I "))"
104 
105 #define AVR_TMP_REGNO (AVR_TINY ? TMP_REGNO_TINY : TMP_REGNO)
106 #define AVR_ZERO_REGNO (AVR_TINY ? ZERO_REGNO_TINY : ZERO_REGNO)
107 
108 /* Known address spaces.  The order must be the same as in the respective
109    enum from avr.h (or designated initialized must be used).  */
110 const avr_addrspace_t avr_addrspace[ADDR_SPACE_COUNT] =
111 {
112   { ADDR_SPACE_RAM,  0, 2, "", 0, NULL },
113   { ADDR_SPACE_FLASH,  1, 2, "__flash",   0, ".progmem.data" },
114   { ADDR_SPACE_FLASH1, 1, 2, "__flash1",  1, ".progmem1.data" },
115   { ADDR_SPACE_FLASH2, 1, 2, "__flash2",  2, ".progmem2.data" },
116   { ADDR_SPACE_FLASH3, 1, 2, "__flash3",  3, ".progmem3.data" },
117   { ADDR_SPACE_FLASH4, 1, 2, "__flash4",  4, ".progmem4.data" },
118   { ADDR_SPACE_FLASH5, 1, 2, "__flash5",  5, ".progmem5.data" },
119   { ADDR_SPACE_MEMX, 1, 3, "__memx",  0, ".progmemx.data" },
120 };
121 
122 
123 /* Holding RAM addresses of some SFRs used by the compiler and that
124    are unique over all devices in an architecture like 'avr4'.  */
125 
126 typedef struct
127 {
128   /* SREG: The processor status */
129   int sreg;
130 
131   /* RAMPX, RAMPY, RAMPD and CCP of XMEGA */
132   int ccp;
133   int rampd;
134   int rampx;
135   int rampy;
136 
137   /* RAMPZ: The high byte of 24-bit address used with ELPM */
138   int rampz;
139 
140   /* SP: The stack pointer and its low and high byte */
141   int sp_l;
142   int sp_h;
143 } avr_addr_t;
144 
145 static avr_addr_t avr_addr;
146 
147 
148 /* Prototypes for local helper functions.  */
149 
150 static const char* out_movqi_r_mr (rtx_insn *, rtx[], int*);
151 static const char* out_movhi_r_mr (rtx_insn *, rtx[], int*);
152 static const char* out_movsi_r_mr (rtx_insn *, rtx[], int*);
153 static const char* out_movqi_mr_r (rtx_insn *, rtx[], int*);
154 static const char* out_movhi_mr_r (rtx_insn *, rtx[], int*);
155 static const char* out_movsi_mr_r (rtx_insn *, rtx[], int*);
156 
157 static int get_sequence_length (rtx_insn *insns);
158 static int sequent_regs_live (void);
159 static const char *ptrreg_to_str (int);
160 static const char *cond_string (enum rtx_code);
161 static int avr_num_arg_regs (machine_mode, const_tree);
162 static int avr_operand_rtx_cost (rtx, machine_mode, enum rtx_code,
163                                  int, bool);
164 static void output_reload_in_const (rtx*, rtx, int*, bool);
165 static struct machine_function * avr_init_machine_status (void);
166 
167 
168 /* Prototypes for hook implementors if needed before their implementation.  */
169 
170 static bool avr_rtx_costs (rtx, machine_mode, int, int, int*, bool);
171 
172 
173 /* Allocate registers from r25 to r8 for parameters for function calls.  */
174 #define FIRST_CUM_REG 26
175 
176 /* Last call saved register */
177 #define LAST_CALLEE_SAVED_REG (AVR_TINY ? 19 : 17)
178 
179 /* Implicit target register of LPM instruction (R0) */
180 extern GTY(()) rtx lpm_reg_rtx;
181 rtx lpm_reg_rtx;
182 
183 /* (Implicit) address register of LPM instruction (R31:R30 = Z) */
184 extern GTY(()) rtx lpm_addr_reg_rtx;
185 rtx lpm_addr_reg_rtx;
186 
187 /* Temporary register RTX (reg:QI TMP_REGNO) */
188 extern GTY(()) rtx tmp_reg_rtx;
189 rtx tmp_reg_rtx;
190 
191 /* Zeroed register RTX (reg:QI ZERO_REGNO) */
192 extern GTY(()) rtx zero_reg_rtx;
193 rtx zero_reg_rtx;
194 
195 /* Condition Code register RTX (reg:CC REG_CC) */
196 extern GTY(()) rtx cc_reg_rtx;
197 rtx cc_reg_rtx;
198 
199 /* RTXs for all general purpose registers as QImode */
200 extern GTY(()) rtx all_regs_rtx[32];
201 rtx all_regs_rtx[32];
202 
203 /* SREG, the processor status */
204 extern GTY(()) rtx sreg_rtx;
205 rtx sreg_rtx;
206 
207 /* RAMP* special function registers */
208 extern GTY(()) rtx rampd_rtx;
209 extern GTY(()) rtx rampx_rtx;
210 extern GTY(()) rtx rampy_rtx;
211 extern GTY(()) rtx rampz_rtx;
212 rtx rampd_rtx;
213 rtx rampx_rtx;
214 rtx rampy_rtx;
215 rtx rampz_rtx;
216 
217 /* RTX containing the strings "" and "e", respectively */
218 static GTY(()) rtx xstring_empty;
219 static GTY(()) rtx xstring_e;
220 
221 /* Current architecture.  */
222 const avr_arch_t *avr_arch;
223 
224 /* Unnamed sections associated to __attribute__((progmem)) aka. PROGMEM
225    or to address space __flash* or __memx.  Only used as singletons inside
226    avr_asm_select_section, but it must not be local there because of GTY.  */
227 static GTY(()) section *progmem_section[ADDR_SPACE_COUNT];
228 
229 /* Condition for insns/expanders from avr-dimode.md.  */
230 bool avr_have_dimode = true;
231 
232 /* To track if code will use .bss and/or .data.  */
233 bool avr_need_clear_bss_p = false;
234 bool avr_need_copy_data_p = false;
235 
236 
237 /* Transform UP into lowercase and write the result to LO.
238    You must provide enough space for LO.  Return LO.  */
239 
240 static char*
avr_tolower(char * lo,const char * up)241 avr_tolower (char *lo, const char *up)
242 {
243   char *lo0 = lo;
244 
245   for (; *up; up++, lo++)
246     *lo = TOLOWER (*up);
247 
248   *lo = '\0';
249 
250   return lo0;
251 }
252 
253 
254 /* Constraint helper function.  XVAL is a CONST_INT or a CONST_DOUBLE.
255    Return true if the least significant N_BYTES bytes of XVAL all have a
256    popcount in POP_MASK and false, otherwise.  POP_MASK represents a subset
257    of integers which contains an integer N iff bit N of POP_MASK is set.  */
258 
259 bool
avr_popcount_each_byte(rtx xval,int n_bytes,int pop_mask)260 avr_popcount_each_byte (rtx xval, int n_bytes, int pop_mask)
261 {
262   machine_mode mode = GET_MODE (xval);
263 
264   if (VOIDmode == mode)
265     mode = SImode;
266 
267   for (int i = 0; i < n_bytes; i++)
268     {
269       rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
270       unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
271 
272       if ((pop_mask & (1 << popcount_hwi (val8))) == 0)
273         return false;
274     }
275 
276   return true;
277 }
278 
279 
280 /* Access some RTX as INT_MODE.  If X is a CONST_FIXED we can get
281    the bit representation of X by "casting" it to CONST_INT.  */
282 
283 rtx
avr_to_int_mode(rtx x)284 avr_to_int_mode (rtx x)
285 {
286   machine_mode mode = GET_MODE (x);
287 
288   return VOIDmode == mode
289     ? x
290     : simplify_gen_subreg (int_mode_for_mode (mode).require (), x, mode, 0);
291 }
292 
293 namespace {
294 
295 static const pass_data avr_pass_data_recompute_notes =
296 {
297   RTL_PASS,      // type
298   "",            // name (will be patched)
299   OPTGROUP_NONE, // optinfo_flags
300   TV_DF_SCAN,    // tv_id
301   0,             // properties_required
302   0,             // properties_provided
303   0,             // properties_destroyed
304   0,             // todo_flags_start
305   TODO_df_finish | TODO_df_verify // todo_flags_finish
306 };
307 
308 
309 class avr_pass_recompute_notes : public rtl_opt_pass
310 {
311 public:
avr_pass_recompute_notes(gcc::context * ctxt,const char * name)312   avr_pass_recompute_notes (gcc::context *ctxt, const char *name)
313     : rtl_opt_pass (avr_pass_data_recompute_notes, ctxt)
314   {
315     this->name = name;
316   }
317 
execute(function *)318   virtual unsigned int execute (function*)
319   {
320     df_note_add_problem ();
321     df_analyze ();
322 
323     return 0;
324   }
325 }; // avr_pass_recompute_notes
326 
327 static const pass_data avr_pass_data_casesi =
328 {
329   RTL_PASS,      // type
330   "",            // name (will be patched)
331   OPTGROUP_NONE, // optinfo_flags
332   TV_DF_SCAN,    // tv_id
333   0,             // properties_required
334   0,             // properties_provided
335   0,             // properties_destroyed
336   0,             // todo_flags_start
337   0              // todo_flags_finish
338 };
339 
340 
341 class avr_pass_casesi : public rtl_opt_pass
342 {
343 public:
avr_pass_casesi(gcc::context * ctxt,const char * name)344   avr_pass_casesi (gcc::context *ctxt, const char *name)
345     : rtl_opt_pass (avr_pass_data_casesi, ctxt)
346   {
347     this->name = name;
348   }
349 
350   void avr_rest_of_handle_casesi (function*);
351 
gate(function *)352   virtual bool gate (function*) { return optimize > 0; }
353 
execute(function * func)354   virtual unsigned int execute (function *func)
355   {
356     avr_rest_of_handle_casesi (func);
357 
358     return 0;
359   }
360 }; // avr_pass_casesi
361 
362 } // anon namespace
363 
364 rtl_opt_pass*
make_avr_pass_recompute_notes(gcc::context * ctxt)365 make_avr_pass_recompute_notes (gcc::context *ctxt)
366 {
367   return new avr_pass_recompute_notes (ctxt, "avr-notes-free-cfg");
368 }
369 
370 rtl_opt_pass*
make_avr_pass_casesi(gcc::context * ctxt)371 make_avr_pass_casesi (gcc::context *ctxt)
372 {
373   return new avr_pass_casesi (ctxt, "avr-casesi");
374 }
375 
376 
377 /* Make one parallel insn with all the patterns from insns i[0]..i[5].  */
378 
379 static rtx_insn*
avr_parallel_insn_from_insns(rtx_insn * i[5])380 avr_parallel_insn_from_insns (rtx_insn *i[5])
381 {
382   rtvec vec = gen_rtvec (5, PATTERN (i[0]), PATTERN (i[1]), PATTERN (i[2]),
383                          PATTERN (i[3]), PATTERN (i[4]));
384   start_sequence();
385   emit (gen_rtx_PARALLEL (VOIDmode, vec));
386   rtx_insn *insn = get_insns();
387   end_sequence();
388 
389   return insn;
390 }
391 
392 
393 /* Return true if we see an insn stream generated by casesi expander together
394    with an extension to SImode of the switch value.
395 
396    If this is the case, fill in the insns from casesi to INSNS[1..5] and
397    the SImode extension to INSNS[0].  Moreover, extract the operands of
398    pattern casesi_<mode>_sequence forged from the sequence to recog_data.  */
399 
400 static bool
avr_is_casesi_sequence(basic_block bb,rtx_insn * insn,rtx_insn * insns[5])401 avr_is_casesi_sequence (basic_block bb, rtx_insn *insn, rtx_insn *insns[5])
402 {
403   rtx set_4, set_0;
404 
405   /* A first and quick test for a casesi sequences.  As a side effect of
406      the test, harvest respective insns to INSNS[0..4].  */
407 
408   if (!(JUMP_P (insns[4] = insn)
409         // casesi is the only insn that comes up with UNSPEC_INDEX_JMP,
410         // hence the following test ensures that we are actually dealing
411         // with code from casesi.
412         && (set_4 = single_set (insns[4]))
413         && UNSPEC == GET_CODE (SET_SRC (set_4))
414         && UNSPEC_INDEX_JMP == XINT (SET_SRC (set_4), 1)
415 
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 < 5; 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..4] 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[5],rtx * xop)544 avr_optimize_casesi (rtx_insn *insns[5], 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_cbranch)(rtx,rtx,rtx,rtx)
601     = QImode == mode ? gen_cbranchqi4 : gen_cbranchhi4;
602 
603   emit_insn (gen_add (reg, reg, gen_int_mode (-low_idx, mode)));
604   rtx op0 = reg; rtx op1 = gen_int_mode (num_idx, mode);
605   rtx labelref = copy_rtx (xop[4]);
606   emit_jump_insn (gen_cbranch (gen_rtx_fmt_ee (GTU, VOIDmode, op0, op1),
607                                op0, op1,
608                                labelref));
609 
610   seq1 = get_insns();
611   last1 = get_last_insn();
612   end_sequence();
613 
614   emit_insn_after (seq1, insns[2]);
615 
616   // After the out-of-bounds test and corresponding branch, use a
617   // 16-bit index.  If QImode is used, extend it to HImode first.
618   // This will replace insns[4].
619 
620   start_sequence();
621 
622   if (QImode == mode)
623     reg = force_reg (HImode, gen_rtx_fmt_e (code, HImode, reg));
624 
625   rtx pat_4 = AVR_3_BYTE_PC
626     ? gen_movhi (xop[7], reg)
627     : gen_addhi3 (xop[7], reg, gen_rtx_LABEL_REF (VOIDmode, xop[3]));
628 
629   emit_insn (pat_4);
630 
631   seq2 = get_insns();
632   last2 = get_last_insn();
633   end_sequence();
634 
635   emit_insn_after (seq2, insns[3]);
636 
637   if (dump_file)
638     {
639       fprintf (dump_file, ";; New insns: ");
640 
641       for (rtx_insn *insn = seq1; ; insn = NEXT_INSN (insn))
642         {
643           fprintf (dump_file, "%d, ", INSN_UID (insn));
644           if (insn == last1)
645             break;
646         }
647       for (rtx_insn *insn = seq2; ; insn = NEXT_INSN (insn))
648         {
649           fprintf (dump_file, "%d%s", INSN_UID (insn),
650                    insn == last2 ? ".\n\n" : ", ");
651           if (insn == last2)
652             break;
653         }
654 
655       fprintf (dump_file, ";; Deleting insns: %d, %d, %d.\n\n",
656                INSN_UID (insns[1]), INSN_UID (insns[2]), INSN_UID (insns[3]));
657     }
658 
659   // Pseudodelete the SImode and subreg of SImode insns.  We don't care
660   // about the extension insns[0]: Its result is now unused and other
661   // passes will clean it up.
662 
663   SET_INSN_DELETED (insns[1]);
664   SET_INSN_DELETED (insns[2]);
665   SET_INSN_DELETED (insns[3]);
666 }
667 
668 
669 void
avr_rest_of_handle_casesi(function * func)670 avr_pass_casesi::avr_rest_of_handle_casesi (function *func)
671 {
672   basic_block bb;
673 
674   FOR_EACH_BB_FN (bb, func)
675     {
676       rtx_insn *insn, *insns[5];
677 
678       FOR_BB_INSNS (bb, insn)
679         {
680           if (avr_is_casesi_sequence (bb, insn, insns))
681             {
682               avr_optimize_casesi (insns, recog_data.operand);
683             }
684         }
685     }
686 }
687 
688 
689 /* Set `avr_arch' as specified by `-mmcu='.
690    Return true on success.  */
691 
692 static bool
avr_set_core_architecture(void)693 avr_set_core_architecture (void)
694 {
695   /* Search for mcu core architecture.  */
696 
697   if (!avr_mmcu)
698     avr_mmcu = AVR_MMCU_DEFAULT;
699 
700   avr_arch = &avr_arch_types[0];
701 
702   for (const avr_mcu_t *mcu = avr_mcu_types; ; mcu++)
703     {
704       if (mcu->name == NULL)
705         {
706           /* Reached the end of `avr_mcu_types'.  This should actually never
707              happen as options are provided by device-specs.  It could be a
708              typo in a device-specs or calling the compiler proper directly
709              with -mmcu=<device>. */
710 
711           error ("unknown core architecture %qs specified with %qs",
712                  avr_mmcu, "-mmcu=");
713           avr_inform_core_architectures ();
714           break;
715         }
716       else if (strcmp (mcu->name, avr_mmcu) == 0
717                // Is this a proper architecture ?
718 	       && mcu->macro == NULL)
719         {
720           avr_arch = &avr_arch_types[mcu->arch_id];
721           if (avr_n_flash < 0)
722             avr_n_flash = 1 + (mcu->flash_size - 1) / 0x10000;
723 
724           return true;
725         }
726     }
727 
728   return false;
729 }
730 
731 
732 /* Implement `TARGET_OPTION_OVERRIDE'.  */
733 
734 static void
avr_option_override(void)735 avr_option_override (void)
736 {
737   /* caller-save.c looks for call-clobbered hard registers that are assigned
738      to pseudos that cross calls and tries so save-restore them around calls
739      in order to reduce the number of stack slots needed.
740 
741      This might lead to situations where reload is no more able to cope
742      with the challenge of AVR's very few address registers and fails to
743      perform the requested spills.  */
744 
745   if (avr_strict_X)
746     flag_caller_saves = 0;
747 
748   /* Unwind tables currently require a frame pointer for correctness,
749      see toplev.c:process_options().  */
750 
751   if ((flag_unwind_tables
752        || flag_non_call_exceptions
753        || flag_asynchronous_unwind_tables)
754       && !ACCUMULATE_OUTGOING_ARGS)
755     {
756       flag_omit_frame_pointer = 0;
757     }
758 
759   if (flag_pic == 1)
760     warning (OPT_fpic, "%<-fpic%> is not supported");
761   if (flag_pic == 2)
762     warning (OPT_fPIC, "%<-fPIC%> is not supported");
763   if (flag_pie == 1)
764     warning (OPT_fpie, "%<-fpie%> is not supported");
765   if (flag_pie == 2)
766     warning (OPT_fPIE, "%<-fPIE%> is not supported");
767 
768 #if !defined (HAVE_AS_AVR_MGCCISR_OPTION)
769   avr_gasisr_prologues = 0;
770 #endif
771 
772   if (!avr_set_core_architecture())
773     return;
774 
775   /* Sould be set by avr-common.c */
776   gcc_assert (avr_long_double >= avr_double && avr_double >= 32);
777 
778   /* RAM addresses of some SFRs common to all devices in respective arch. */
779 
780   /* SREG: Status Register containing flags like I (global IRQ) */
781   avr_addr.sreg = 0x3F + avr_arch->sfr_offset;
782 
783   /* RAMPZ: Address' high part when loading via ELPM */
784   avr_addr.rampz = 0x3B + avr_arch->sfr_offset;
785 
786   avr_addr.rampy = 0x3A + avr_arch->sfr_offset;
787   avr_addr.rampx = 0x39 + avr_arch->sfr_offset;
788   avr_addr.rampd = 0x38 + avr_arch->sfr_offset;
789   avr_addr.ccp = (AVR_TINY ? 0x3C : 0x34) + avr_arch->sfr_offset;
790 
791   /* SP: Stack Pointer (SP_H:SP_L) */
792   avr_addr.sp_l = 0x3D + avr_arch->sfr_offset;
793   avr_addr.sp_h = avr_addr.sp_l + 1;
794 
795   init_machine_status = avr_init_machine_status;
796 
797   avr_log_set_avr_log();
798 }
799 
800 /* Function to set up the backend function structure.  */
801 
802 static struct machine_function *
avr_init_machine_status(void)803 avr_init_machine_status (void)
804 {
805   return ggc_cleared_alloc<machine_function> ();
806 }
807 
808 
809 /* Implement `INIT_EXPANDERS'.  */
810 /* The function works like a singleton.  */
811 
812 void
avr_init_expanders(void)813 avr_init_expanders (void)
814 {
815   for (int regno = 0; regno < 32; regno ++)
816     all_regs_rtx[regno] = gen_rtx_REG (QImode, regno);
817 
818   lpm_reg_rtx  = all_regs_rtx[LPM_REGNO];
819   tmp_reg_rtx  = all_regs_rtx[AVR_TMP_REGNO];
820   zero_reg_rtx = all_regs_rtx[AVR_ZERO_REGNO];
821 
822   cc_reg_rtx  = gen_rtx_REG (CCmode, REG_CC);
823 
824   lpm_addr_reg_rtx = gen_rtx_REG (HImode, REG_Z);
825 
826   sreg_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.sreg));
827   rampd_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampd));
828   rampx_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampx));
829   rampy_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampy));
830   rampz_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampz));
831 
832   xstring_empty = gen_rtx_CONST_STRING (VOIDmode, "");
833   xstring_e = gen_rtx_CONST_STRING (VOIDmode, "e");
834 
835   /* TINY core does not have regs r10-r16, but avr-dimode.md expects them
836      to be present */
837   if (AVR_TINY)
838     avr_have_dimode = false;
839 }
840 
841 
842 /* Implement `REGNO_REG_CLASS'.  */
843 /* Return register class for register R.  */
844 
845 enum reg_class
avr_regno_reg_class(int r)846 avr_regno_reg_class (int r)
847 {
848   static const enum reg_class reg_class_tab[] =
849     {
850       R0_REG,
851       /* r1 - r15 */
852       NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
853       NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
854       NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
855       NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
856       /* r16 - r23 */
857       SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
858       SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
859       /* r24, r25 */
860       ADDW_REGS, ADDW_REGS,
861       /* X: r26, 27 */
862       POINTER_X_REGS, POINTER_X_REGS,
863       /* Y: r28, r29 */
864       POINTER_Y_REGS, POINTER_Y_REGS,
865       /* Z: r30, r31 */
866       POINTER_Z_REGS, POINTER_Z_REGS,
867       /* SP: SPL, SPH */
868       STACK_REG, STACK_REG
869     };
870 
871   if (r <= 33)
872     return reg_class_tab[r];
873 
874   if (r == REG_CC)
875     return CC_REG;
876 
877   return ALL_REGS;
878 }
879 
880 
881 /* Implement `TARGET_SCALAR_MODE_SUPPORTED_P'.  */
882 
883 static bool
avr_scalar_mode_supported_p(scalar_mode mode)884 avr_scalar_mode_supported_p (scalar_mode mode)
885 {
886   if (ALL_FIXED_POINT_MODE_P (mode))
887     return true;
888 
889   if (PSImode == mode)
890     return true;
891 
892   return default_scalar_mode_supported_p (mode);
893 }
894 
895 
896 /* Return TRUE if DECL is a VAR_DECL located in flash and FALSE, otherwise.  */
897 
898 static bool
avr_decl_flash_p(tree decl)899 avr_decl_flash_p (tree decl)
900 {
901   if (TREE_CODE (decl) != VAR_DECL
902       || TREE_TYPE (decl) == error_mark_node)
903     {
904       return false;
905     }
906 
907   return !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (decl)));
908 }
909 
910 
911 /* Return TRUE if DECL is a VAR_DECL located in the 24-bit flash
912    address space and FALSE, otherwise.  */
913 
914 static bool
avr_decl_memx_p(tree decl)915 avr_decl_memx_p (tree decl)
916 {
917   if (TREE_CODE (decl) != VAR_DECL
918       || TREE_TYPE (decl) == error_mark_node)
919     {
920       return false;
921     }
922 
923   return (ADDR_SPACE_MEMX == TYPE_ADDR_SPACE (TREE_TYPE (decl)));
924 }
925 
926 
927 /* Return TRUE if X is a MEM rtx located in flash and FALSE, otherwise.  */
928 
929 bool
avr_mem_flash_p(rtx x)930 avr_mem_flash_p (rtx x)
931 {
932   return (MEM_P (x)
933           && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x)));
934 }
935 
936 
937 /* Return TRUE if X is a MEM rtx located in the 24-bit flash
938    address space and FALSE, otherwise.  */
939 
940 bool
avr_mem_memx_p(rtx x)941 avr_mem_memx_p (rtx x)
942 {
943   return (MEM_P (x)
944           && ADDR_SPACE_MEMX == MEM_ADDR_SPACE (x));
945 }
946 
947 
948 /* A helper for the subsequent function attribute used to dig for
949    attribute 'name' in a FUNCTION_DECL or FUNCTION_TYPE */
950 
951 static inline int
avr_lookup_function_attribute1(const_tree func,const char * name)952 avr_lookup_function_attribute1 (const_tree func, const char *name)
953 {
954   if (FUNCTION_DECL == TREE_CODE (func))
955     {
956       if (NULL_TREE != lookup_attribute (name, DECL_ATTRIBUTES (func)))
957         {
958           return true;
959         }
960 
961       func = TREE_TYPE (func);
962     }
963 
964   gcc_assert (TREE_CODE (func) == FUNCTION_TYPE
965               || TREE_CODE (func) == METHOD_TYPE);
966 
967   return NULL_TREE != lookup_attribute (name, TYPE_ATTRIBUTES (func));
968 }
969 
970 /* Return nonzero if FUNC is a naked function.  */
971 
972 static int
avr_naked_function_p(tree func)973 avr_naked_function_p (tree func)
974 {
975   return avr_lookup_function_attribute1 (func, "naked");
976 }
977 
978 /* Return nonzero if FUNC is an interrupt function as specified
979    by the "interrupt" attribute.  */
980 
981 static int
avr_interrupt_function_p(tree func)982 avr_interrupt_function_p (tree func)
983 {
984   return avr_lookup_function_attribute1 (func, "interrupt");
985 }
986 
987 /* Return nonzero if FUNC is a signal function as specified
988    by the "signal" attribute.  */
989 
990 static int
avr_signal_function_p(tree func)991 avr_signal_function_p (tree func)
992 {
993   return avr_lookup_function_attribute1 (func, "signal");
994 }
995 
996 /* Return nonzero if FUNC is an OS_task function.  */
997 
998 static int
avr_OS_task_function_p(tree func)999 avr_OS_task_function_p (tree func)
1000 {
1001   return avr_lookup_function_attribute1 (func, "OS_task");
1002 }
1003 
1004 /* Return nonzero if FUNC is an OS_main function.  */
1005 
1006 static int
avr_OS_main_function_p(tree func)1007 avr_OS_main_function_p (tree func)
1008 {
1009   return avr_lookup_function_attribute1 (func, "OS_main");
1010 }
1011 
1012 
1013 /* Return nonzero if FUNC is a no_gccisr function as specified
1014    by the "no_gccisr" attribute.  */
1015 
1016 static int
avr_no_gccisr_function_p(tree func)1017 avr_no_gccisr_function_p (tree func)
1018 {
1019   return avr_lookup_function_attribute1 (func, "no_gccisr");
1020 }
1021 
1022 /* Implement `TARGET_SET_CURRENT_FUNCTION'.  */
1023 /* Sanity cheching for above function attributes.  */
1024 
1025 static void
avr_set_current_function(tree decl)1026 avr_set_current_function (tree decl)
1027 {
1028   if (decl == NULL_TREE
1029       || current_function_decl == NULL_TREE
1030       || current_function_decl == error_mark_node
1031       || ! cfun->machine
1032       || cfun->machine->attributes_checked_p)
1033     return;
1034 
1035   location_t loc = DECL_SOURCE_LOCATION (decl);
1036 
1037   cfun->machine->is_naked = avr_naked_function_p (decl);
1038   cfun->machine->is_signal = avr_signal_function_p (decl);
1039   cfun->machine->is_interrupt = avr_interrupt_function_p (decl);
1040   cfun->machine->is_OS_task = avr_OS_task_function_p (decl);
1041   cfun->machine->is_OS_main = avr_OS_main_function_p (decl);
1042   cfun->machine->is_no_gccisr = avr_no_gccisr_function_p (decl);
1043 
1044   const char *isr = cfun->machine->is_interrupt ? "interrupt" : "signal";
1045 
1046   /* Too much attributes make no sense as they request conflicting features. */
1047 
1048   if (cfun->machine->is_OS_task
1049       && (cfun->machine->is_signal || cfun->machine->is_interrupt))
1050     error_at (loc, "function attributes %qs and %qs are mutually exclusive",
1051               "OS_task", isr);
1052 
1053   if (cfun->machine->is_OS_main
1054       && (cfun->machine->is_signal || cfun->machine->is_interrupt))
1055     error_at (loc, "function attributes %qs and %qs are mutually exclusive",
1056               "OS_main", isr);
1057 
1058   if (cfun->machine->is_interrupt || cfun->machine->is_signal)
1059     {
1060       tree args = TYPE_ARG_TYPES (TREE_TYPE (decl));
1061       tree ret = TREE_TYPE (TREE_TYPE (decl));
1062       const char *name;
1063 
1064       name = DECL_ASSEMBLER_NAME_SET_P (decl)
1065         ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))
1066         : IDENTIFIER_POINTER (DECL_NAME (decl));
1067 
1068       /* Skip a leading '*' that might still prefix the assembler name,
1069          e.g. in non-LTO runs.  */
1070 
1071       name = default_strip_name_encoding (name);
1072 
1073       /* Interrupt handlers must be  void __vector (void)  functions.  */
1074 
1075       if (args && TREE_CODE (TREE_VALUE (args)) != VOID_TYPE)
1076         error_at (loc, "%qs function cannot have arguments", isr);
1077 
1078       if (TREE_CODE (ret) != VOID_TYPE)
1079         error_at (loc, "%qs function cannot return a value", isr);
1080 
1081 #if defined WITH_AVRLIBC
1082       /* Silently ignore 'signal' if 'interrupt' is present.  AVR-LibC startet
1083          using this when it switched from SIGNAL and INTERRUPT to ISR.  */
1084 
1085       if (cfun->machine->is_interrupt)
1086         cfun->machine->is_signal = 0;
1087 
1088       /* If the function has the 'signal' or 'interrupt' attribute, ensure
1089          that the name of the function is "__vector_NN" so as to catch
1090          when the user misspells the vector name.  */
1091 
1092       if (!startswith (name, "__vector"))
1093         warning_at (loc, OPT_Wmisspelled_isr, "%qs appears to be a misspelled "
1094                     "%qs handler, missing %<__vector%> prefix", name, isr);
1095 #endif // AVR-LibC naming conventions
1096     }
1097 
1098 #if defined WITH_AVRLIBC
1099   // Common problem is using "ISR" without first including avr/interrupt.h.
1100   const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
1101   name = default_strip_name_encoding (name);
1102   if (strcmp ("ISR", name) == 0
1103       || strcmp ("INTERRUPT", name) == 0
1104       || strcmp ("SIGNAL", name) == 0)
1105     {
1106       warning_at (loc, OPT_Wmisspelled_isr, "%qs is a reserved identifier"
1107                   " in AVR-LibC.  Consider %<#include <avr/interrupt.h>%>"
1108                   " before using the %qs macro", name, name);
1109     }
1110 #endif // AVR-LibC naming conventions
1111 
1112   /* Don't print the above diagnostics more than once.  */
1113 
1114   cfun->machine->attributes_checked_p = 1;
1115 }
1116 
1117 
1118 /* Implement `ACCUMULATE_OUTGOING_ARGS'.  */
1119 
1120 int
avr_accumulate_outgoing_args(void)1121 avr_accumulate_outgoing_args (void)
1122 {
1123   if (!cfun)
1124     return TARGET_ACCUMULATE_OUTGOING_ARGS;
1125 
1126   /* FIXME: For setjmp and in avr_builtin_setjmp_frame_value we don't know
1127         what offset is correct.  In some cases it is relative to
1128         virtual_outgoing_args_rtx and in others it is relative to
1129         virtual_stack_vars_rtx.  For example code see
1130             gcc.c-torture/execute/built-in-setjmp.c
1131             gcc.c-torture/execute/builtins/sprintf-chk.c   */
1132 
1133   return (TARGET_ACCUMULATE_OUTGOING_ARGS
1134           && !(cfun->calls_setjmp
1135                || cfun->has_nonlocal_label));
1136 }
1137 
1138 
1139 /* Report contribution of accumulated outgoing arguments to stack size.  */
1140 
1141 static inline int
avr_outgoing_args_size(void)1142 avr_outgoing_args_size (void)
1143 {
1144   return (ACCUMULATE_OUTGOING_ARGS
1145 	  ? (HOST_WIDE_INT) crtl->outgoing_args_size : 0);
1146 }
1147 
1148 
1149 /* Implement TARGET_STARTING_FRAME_OFFSET.  */
1150 /* This is the offset from the frame pointer register to the first stack slot
1151    that contains a variable living in the frame.  */
1152 
1153 static HOST_WIDE_INT
avr_starting_frame_offset(void)1154 avr_starting_frame_offset (void)
1155 {
1156   return 1 + avr_outgoing_args_size ();
1157 }
1158 
1159 
1160 /* Return the number of hard registers to push/pop in the prologue/epilogue
1161    of the current function, and optionally store these registers in SET.  */
1162 
1163 static int
avr_regs_to_save(HARD_REG_SET * set)1164 avr_regs_to_save (HARD_REG_SET *set)
1165 {
1166   int count;
1167   int int_or_sig_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1168 
1169   if (set)
1170     CLEAR_HARD_REG_SET (*set);
1171   count = 0;
1172 
1173   /* No need to save any registers if the function never returns or
1174      has the "OS_task" or "OS_main" attribute.  */
1175 
1176   if (TREE_THIS_VOLATILE (current_function_decl)
1177       || cfun->machine->is_OS_task
1178       || cfun->machine->is_OS_main)
1179     return 0;
1180 
1181   for (int reg = 0; reg < 32; reg++)
1182     {
1183       /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
1184          any global register variables.  */
1185 
1186       if (fixed_regs[reg])
1187         continue;
1188 
1189       if ((int_or_sig_p && !crtl->is_leaf && call_used_or_fixed_reg_p (reg))
1190           || (df_regs_ever_live_p (reg)
1191               && (int_or_sig_p || !call_used_or_fixed_reg_p (reg))
1192               /* Don't record frame pointer registers here.  They are treated
1193                  indivitually in prologue.  */
1194               && !(frame_pointer_needed
1195                    && (reg == REG_Y || reg == REG_Y + 1))))
1196         {
1197           if (set)
1198             SET_HARD_REG_BIT (*set, reg);
1199           count++;
1200         }
1201     }
1202   return count;
1203 }
1204 
1205 
1206 /* Implement `TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS' */
1207 
1208 static bool
avr_allocate_stack_slots_for_args(void)1209 avr_allocate_stack_slots_for_args (void)
1210 {
1211   return !cfun->machine->is_naked;
1212 }
1213 
1214 
1215 /* Return true if register FROM can be eliminated via register TO.  */
1216 
1217 static bool
avr_can_eliminate(const int from ATTRIBUTE_UNUSED,const int to)1218 avr_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
1219 {
1220   return ((frame_pointer_needed && to == FRAME_POINTER_REGNUM)
1221           || !frame_pointer_needed);
1222 }
1223 
1224 
1225 /* Implement `TARGET_WARN_FUNC_RETURN'.  */
1226 
1227 static bool
avr_warn_func_return(tree decl)1228 avr_warn_func_return (tree decl)
1229 {
1230   /* Naked functions are implemented entirely in assembly, including the
1231      return sequence, so suppress warnings about this.  */
1232 
1233   return !avr_naked_function_p (decl);
1234 }
1235 
1236 /* Compute offset between arg_pointer and frame_pointer.  */
1237 
1238 int
avr_initial_elimination_offset(int from,int to)1239 avr_initial_elimination_offset (int from, int to)
1240 {
1241   if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
1242     return 0;
1243   else
1244     {
1245       int offset = frame_pointer_needed ? 2 : 0;
1246       int avr_pc_size = AVR_HAVE_EIJMP_EICALL ? 3 : 2;
1247 
1248       // If FROM is ARG_POINTER_REGNUM, we are not in an ISR as ISRs
1249       // might not have arguments.  Hence the following is not affected
1250       // by gasisr prologues.
1251       offset += avr_regs_to_save (NULL);
1252       return (get_frame_size () + avr_outgoing_args_size()
1253               + avr_pc_size + 1 + offset);
1254     }
1255 }
1256 
1257 
1258 /* Helper for the function below.  */
1259 
1260 static void
avr_adjust_type_node(tree * node,machine_mode mode,int sat_p)1261 avr_adjust_type_node (tree *node, machine_mode mode, int sat_p)
1262 {
1263   *node = make_node (FIXED_POINT_TYPE);
1264   TYPE_SATURATING (*node) = sat_p;
1265   TYPE_UNSIGNED (*node) = UNSIGNED_FIXED_POINT_MODE_P (mode);
1266   TYPE_IBIT (*node) = GET_MODE_IBIT (mode);
1267   TYPE_FBIT (*node) = GET_MODE_FBIT (mode);
1268   TYPE_PRECISION (*node) = GET_MODE_BITSIZE (mode);
1269   SET_TYPE_ALIGN (*node, 8);
1270   SET_TYPE_MODE (*node, mode);
1271 
1272   layout_type (*node);
1273 }
1274 
1275 
1276 /* Implement `TARGET_BUILD_BUILTIN_VA_LIST'.  */
1277 
1278 static tree
avr_build_builtin_va_list(void)1279 avr_build_builtin_va_list (void)
1280 {
1281   /* avr-modes.def adjusts [U]TA to be 64-bit modes with 48 fractional bits.
1282      This is more appropriate for the 8-bit machine AVR than 128-bit modes.
1283      The ADJUST_IBIT/FBIT are handled in toplev:init_adjust_machine_modes()
1284      which is auto-generated by genmodes, but the compiler assigns [U]DAmode
1285      to the long long accum modes instead of the desired [U]TAmode.
1286 
1287      Fix this now, right after node setup in tree.c:build_common_tree_nodes().
1288      This must run before c-cppbuiltin.c:builtin_define_fixed_point_constants()
1289      which built-in defines macros like __ULLACCUM_FBIT__ that are used by
1290      libgcc to detect IBIT and FBIT.  */
1291 
1292   avr_adjust_type_node (&ta_type_node, TAmode, 0);
1293   avr_adjust_type_node (&uta_type_node, UTAmode, 0);
1294   avr_adjust_type_node (&sat_ta_type_node, TAmode, 1);
1295   avr_adjust_type_node (&sat_uta_type_node, UTAmode, 1);
1296 
1297   unsigned_long_long_accum_type_node = uta_type_node;
1298   long_long_accum_type_node = ta_type_node;
1299   sat_unsigned_long_long_accum_type_node = sat_uta_type_node;
1300   sat_long_long_accum_type_node = sat_ta_type_node;
1301 
1302   /* Dispatch to the default handler.  */
1303 
1304   return std_build_builtin_va_list ();
1305 }
1306 
1307 
1308 /* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3-byte PC).
1309    This is return address of function.  */
1310 
1311 rtx
avr_return_addr_rtx(int count,rtx tem)1312 avr_return_addr_rtx (int count, rtx tem)
1313 {
1314   rtx r;
1315 
1316   /* Can only return this function's return address. Others not supported.  */
1317   if (count)
1318     return NULL;
1319 
1320   if (AVR_3_BYTE_PC)
1321     {
1322       r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+2");
1323       warning (0, "%<builtin_return_address%> contains only 2 bytes"
1324                " of address");
1325     }
1326   else
1327     r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+1");
1328 
1329   cfun->machine->use_L__stack_usage = 1;
1330 
1331   r = gen_rtx_PLUS (Pmode, tem, r);
1332   r = gen_frame_mem (Pmode, memory_address (Pmode, r));
1333   r = gen_rtx_ROTATE (HImode, r, GEN_INT (8));
1334   return r;
1335 }
1336 
1337 /* Return 1 if the function epilogue is just a single "ret".  */
1338 
1339 int
avr_simple_epilogue(void)1340 avr_simple_epilogue (void)
1341 {
1342   return (! frame_pointer_needed
1343           && get_frame_size () == 0
1344           && avr_outgoing_args_size() == 0
1345           && avr_regs_to_save (NULL) == 0
1346           && ! cfun->machine->is_interrupt
1347           && ! cfun->machine->is_signal
1348           && ! cfun->machine->is_naked
1349           && ! TREE_THIS_VOLATILE (current_function_decl));
1350 }
1351 
1352 /* This function checks sequence of live registers.  */
1353 
1354 static int
sequent_regs_live(void)1355 sequent_regs_live (void)
1356 {
1357   int live_seq = 0;
1358   int cur_seq = 0;
1359 
1360   for (int reg = 0; reg <= LAST_CALLEE_SAVED_REG; ++reg)
1361     {
1362       if (fixed_regs[reg])
1363         {
1364           /* Don't recognize sequences that contain global register
1365              variables.  */
1366 
1367           if (live_seq != 0)
1368             return 0;
1369           else
1370             continue;
1371         }
1372 
1373       if (!call_used_or_fixed_reg_p (reg))
1374         {
1375           if (df_regs_ever_live_p (reg))
1376             {
1377               ++live_seq;
1378               ++cur_seq;
1379             }
1380           else
1381             cur_seq = 0;
1382         }
1383     }
1384 
1385   if (!frame_pointer_needed)
1386     {
1387       if (df_regs_ever_live_p (REG_Y))
1388         {
1389           ++live_seq;
1390           ++cur_seq;
1391         }
1392       else
1393         cur_seq = 0;
1394 
1395       if (df_regs_ever_live_p (REG_Y + 1))
1396         {
1397           ++live_seq;
1398           ++cur_seq;
1399         }
1400       else
1401         cur_seq = 0;
1402     }
1403   else
1404     {
1405       cur_seq += 2;
1406       live_seq += 2;
1407     }
1408   return (cur_seq == live_seq) ? live_seq : 0;
1409 }
1410 
1411 namespace {
1412 static const pass_data avr_pass_data_pre_proep =
1413 {
1414   RTL_PASS,      // type
1415   "",            // name (will be patched)
1416   OPTGROUP_NONE, // optinfo_flags
1417   TV_DF_SCAN,    // tv_id
1418   0,             // properties_required
1419   0,             // properties_provided
1420   0,             // properties_destroyed
1421   0,             // todo_flags_start
1422   0              // todo_flags_finish
1423 };
1424 
1425 
1426 class avr_pass_pre_proep : public rtl_opt_pass
1427 {
1428 public:
avr_pass_pre_proep(gcc::context * ctxt,const char * name)1429   avr_pass_pre_proep (gcc::context *ctxt, const char *name)
1430     : rtl_opt_pass (avr_pass_data_pre_proep, ctxt)
1431   {
1432     this->name = name;
1433   }
1434 
1435   void compute_maybe_gasisr (function*);
1436 
execute(function * fun)1437   virtual unsigned int execute (function *fun)
1438   {
1439     if (avr_gasisr_prologues
1440         // Whether this function is an ISR worth scanning at all.
1441         && !fun->machine->is_no_gccisr
1442         && (fun->machine->is_interrupt
1443             || fun->machine->is_signal)
1444         && !cfun->machine->is_naked
1445         // Paranoia: Non-local gotos and labels that might escape.
1446         && !cfun->calls_setjmp
1447         && !cfun->has_nonlocal_label
1448         && !cfun->has_forced_label_in_static)
1449       {
1450         compute_maybe_gasisr (fun);
1451       }
1452 
1453     return 0;
1454   }
1455 
1456 }; // avr_pass_pre_proep
1457 
1458 } // anon namespace
1459 
1460 rtl_opt_pass*
make_avr_pass_pre_proep(gcc::context * ctxt)1461 make_avr_pass_pre_proep (gcc::context *ctxt)
1462 {
1463   return new avr_pass_pre_proep (ctxt, "avr-pre-proep");
1464 }
1465 
1466 
1467 /* Set fun->machine->gasisr.maybe provided we don't find anything that
1468    prohibits GAS generating parts of ISR prologues / epilogues for us.  */
1469 
1470 void
compute_maybe_gasisr(function * fun)1471 avr_pass_pre_proep::compute_maybe_gasisr (function *fun)
1472 {
1473   // Don't use BB iterators so that we see JUMP_TABLE_DATA.
1474 
1475   for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
1476     {
1477       // Transparent calls always use [R]CALL and are filtered out by GAS.
1478       // ISRs don't use -mcall-prologues, hence what remains to be filtered
1479       // out are open coded (tail) calls.
1480 
1481       if (CALL_P (insn))
1482         return;
1483 
1484       // __tablejump2__ clobbers something and is targeted by JMP so
1485       // that GAS won't see its usage.
1486 
1487       if (AVR_HAVE_JMP_CALL
1488           && JUMP_TABLE_DATA_P (insn))
1489         return;
1490 
1491       // Non-local gotos not seen in *FUN.
1492 
1493       if (JUMP_P (insn)
1494           && find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
1495         return;
1496     }
1497 
1498   fun->machine->gasisr.maybe = 1;
1499 }
1500 
1501 
1502 /* Obtain the length sequence of insns.  */
1503 
1504 int
get_sequence_length(rtx_insn * insns)1505 get_sequence_length (rtx_insn *insns)
1506 {
1507   int length = 0;
1508 
1509   for (rtx_insn *insn = insns; insn; insn = NEXT_INSN (insn))
1510     length += get_attr_length (insn);
1511 
1512   return length;
1513 }
1514 
1515 
1516 /*  Implement `INCOMING_RETURN_ADDR_RTX'.  */
1517 
1518 rtx
avr_incoming_return_addr_rtx(void)1519 avr_incoming_return_addr_rtx (void)
1520 {
1521   /* The return address is at the top of the stack.  Note that the push
1522      was via post-decrement, which means the actual address is off by one.  */
1523   return gen_frame_mem (HImode, plus_constant (Pmode, stack_pointer_rtx, 1));
1524 }
1525 
1526 
1527 /* Unset a bit in *SET.  If successful, return the respective bit number.
1528    Otherwise, return -1 and *SET is unaltered.  */
1529 
1530 static int
avr_hregs_split_reg(HARD_REG_SET * set)1531 avr_hregs_split_reg (HARD_REG_SET *set)
1532 {
1533   for (int regno = 0; regno < 32; regno++)
1534     if (TEST_HARD_REG_BIT (*set, regno))
1535       {
1536         // Don't remove a register from *SET which might indicate that
1537         // some RAMP* register might need ISR prologue / epilogue treatment.
1538 
1539         if (AVR_HAVE_RAMPX
1540             && (REG_X == regno || REG_X + 1 == regno)
1541             && TEST_HARD_REG_BIT (*set, REG_X)
1542             && TEST_HARD_REG_BIT (*set, REG_X + 1))
1543           continue;
1544 
1545         if (AVR_HAVE_RAMPY
1546             && !frame_pointer_needed
1547             && (REG_Y == regno || REG_Y + 1 == regno)
1548             && TEST_HARD_REG_BIT (*set, REG_Y)
1549             && TEST_HARD_REG_BIT (*set, REG_Y + 1))
1550           continue;
1551 
1552         if (AVR_HAVE_RAMPZ
1553             && (REG_Z == regno || REG_Z + 1 == regno)
1554             && TEST_HARD_REG_BIT (*set, REG_Z)
1555             && TEST_HARD_REG_BIT (*set, REG_Z + 1))
1556           continue;
1557 
1558         CLEAR_HARD_REG_BIT (*set, regno);
1559         return regno;
1560       }
1561 
1562   return -1;
1563 }
1564 
1565 
1566 /*  Helper for expand_prologue.  Emit a push of a byte register.  */
1567 
1568 static void
emit_push_byte(unsigned regno,bool frame_related_p)1569 emit_push_byte (unsigned regno, bool frame_related_p)
1570 {
1571   rtx mem, reg;
1572   rtx_insn *insn;
1573 
1574   mem = gen_rtx_POST_DEC (HImode, stack_pointer_rtx);
1575   mem = gen_frame_mem (QImode, mem);
1576   reg = gen_rtx_REG (QImode, regno);
1577 
1578   insn = emit_insn (gen_rtx_SET (mem, reg));
1579   if (frame_related_p)
1580     RTX_FRAME_RELATED_P (insn) = 1;
1581 
1582   cfun->machine->stack_usage++;
1583 }
1584 
1585 
1586 /*  Helper for expand_prologue.  Emit a push of a SFR via register TREG.
1587     SFR is a MEM representing the memory location of the SFR.
1588     If CLR_P then clear the SFR after the push using zero_reg.  */
1589 
1590 static void
emit_push_sfr(rtx sfr,bool frame_related_p,bool clr_p,int treg)1591 emit_push_sfr (rtx sfr, bool frame_related_p, bool clr_p, int treg)
1592 {
1593   rtx_insn *insn;
1594 
1595   gcc_assert (MEM_P (sfr));
1596 
1597   /* IN treg, IO(SFR) */
1598   insn = emit_move_insn (all_regs_rtx[treg], sfr);
1599   if (frame_related_p)
1600     RTX_FRAME_RELATED_P (insn) = 1;
1601 
1602   /* PUSH treg */
1603   emit_push_byte (treg, frame_related_p);
1604 
1605   if (clr_p)
1606     {
1607       /* OUT IO(SFR), __zero_reg__ */
1608       insn = emit_move_insn (sfr, const0_rtx);
1609       if (frame_related_p)
1610         RTX_FRAME_RELATED_P (insn) = 1;
1611     }
1612 }
1613 
1614 static void
avr_prologue_setup_frame(HOST_WIDE_INT size,HARD_REG_SET set)1615 avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
1616 {
1617   rtx_insn *insn;
1618   bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1619   int live_seq = sequent_regs_live ();
1620 
1621   HOST_WIDE_INT size_max
1622     = (HOST_WIDE_INT) GET_MODE_MASK (AVR_HAVE_8BIT_SP ? QImode : Pmode);
1623 
1624   bool minimize = (TARGET_CALL_PROLOGUES
1625                    && size < size_max
1626                    && live_seq
1627                    && !isr_p
1628                    && !cfun->machine->is_OS_task
1629                    && !cfun->machine->is_OS_main
1630                    && !AVR_TINY);
1631 
1632   if (minimize
1633       && (frame_pointer_needed
1634           || avr_outgoing_args_size() > 8
1635           || (AVR_2_BYTE_PC && live_seq > 6)
1636           || live_seq > 7))
1637     {
1638       rtx pattern;
1639       int first_reg, reg, offset;
1640 
1641       emit_move_insn (gen_rtx_REG (HImode, REG_X),
1642                       gen_int_mode (size, HImode));
1643 
1644       pattern = gen_call_prologue_saves (gen_int_mode (live_seq, HImode),
1645                                          gen_int_mode (live_seq+size, HImode));
1646       insn = emit_insn (pattern);
1647       RTX_FRAME_RELATED_P (insn) = 1;
1648 
1649       /* Describe the effect of the unspec_volatile call to prologue_saves.
1650          Note that this formulation assumes that add_reg_note pushes the
1651          notes to the front.  Thus we build them in the reverse order of
1652          how we want dwarf2out to process them.  */
1653 
1654       /* The function does always set frame_pointer_rtx, but whether that
1655          is going to be permanent in the function is frame_pointer_needed.  */
1656 
1657       add_reg_note (insn, REG_CFA_ADJUST_CFA,
1658                     gen_rtx_SET ((frame_pointer_needed
1659 				  ? frame_pointer_rtx
1660 				  : stack_pointer_rtx),
1661                                  plus_constant (Pmode, stack_pointer_rtx,
1662                                                 -(size + live_seq))));
1663 
1664       /* Note that live_seq always contains r28+r29, but the other
1665          registers to be saved are all below 18.  */
1666 
1667       first_reg = (LAST_CALLEE_SAVED_REG + 1) - (live_seq - 2);
1668 
1669       for (reg = 29, offset = -live_seq + 1;
1670            reg >= first_reg;
1671            reg = (reg == 28 ? LAST_CALLEE_SAVED_REG : reg - 1), ++offset)
1672         {
1673           rtx m, r;
1674 
1675           m = gen_rtx_MEM (QImode, plus_constant (Pmode, stack_pointer_rtx,
1676                                                   offset));
1677           r = gen_rtx_REG (QImode, reg);
1678           add_reg_note (insn, REG_CFA_OFFSET, gen_rtx_SET (m, r));
1679         }
1680 
1681       cfun->machine->stack_usage += size + live_seq;
1682     }
1683   else /* !minimize */
1684     {
1685       for (int reg = 0; reg < 32; ++reg)
1686         if (TEST_HARD_REG_BIT (set, reg))
1687           emit_push_byte (reg, true);
1688 
1689       if (frame_pointer_needed
1690           && (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main)))
1691         {
1692           /* Push frame pointer.  Always be consistent about the
1693              ordering of pushes -- epilogue_restores expects the
1694              register pair to be pushed low byte first.  */
1695 
1696           emit_push_byte (REG_Y, true);
1697           emit_push_byte (REG_Y + 1, true);
1698         }
1699 
1700       if (frame_pointer_needed
1701           && size == 0)
1702         {
1703           insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
1704           RTX_FRAME_RELATED_P (insn) = 1;
1705         }
1706 
1707       if (size != 0)
1708         {
1709           /*  Creating a frame can be done by direct manipulation of the
1710               stack or via the frame pointer. These two methods are:
1711                   fp =  sp
1712                   fp -= size
1713                   sp =  fp
1714               or
1715                   sp -= size
1716                   fp =  sp    (*)
1717               the optimum method depends on function type, stack and
1718               frame size.  To avoid a complex logic, both methods are
1719               tested and shortest is selected.
1720 
1721               There is also the case where SIZE != 0 and no frame pointer is
1722               needed; this can occur if ACCUMULATE_OUTGOING_ARGS is on.
1723               In that case, insn (*) is not needed in that case.
1724               We use the X register as scratch. This is save because in X
1725               is call-clobbered.
1726                  In an interrupt routine, the case of SIZE != 0 together with
1727               !frame_pointer_needed can only occur if the function is not a
1728               leaf function and thus X has already been saved.  */
1729 
1730           int irq_state = -1;
1731           HOST_WIDE_INT size_cfa = size, neg_size;
1732           rtx_insn *fp_plus_insns;
1733           rtx fp, my_fp;
1734 
1735           gcc_assert (frame_pointer_needed
1736                       || !isr_p
1737                       || !crtl->is_leaf);
1738 
1739           fp = my_fp = (frame_pointer_needed
1740                         ? frame_pointer_rtx
1741                         : gen_rtx_REG (Pmode, REG_X));
1742 
1743           if (AVR_HAVE_8BIT_SP)
1744             {
1745               /* The high byte (r29) does not change:
1746                  Prefer SUBI (1 cycle) over SBIW (2 cycles, same size).  */
1747 
1748               my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
1749             }
1750 
1751           /* Cut down size and avoid size = 0 so that we don't run
1752              into ICE like PR52488 in the remainder.  */
1753 
1754           if (size > size_max)
1755             {
1756               /* Don't error so that insane code from newlib still compiles
1757                  and does not break building newlib.  As PR51345 is implemented
1758                  now, there are multilib variants with -msp8.
1759 
1760                  If user wants sanity checks he can use -Wstack-usage=
1761                  or similar options.
1762 
1763                  For CFA we emit the original, non-saturated size so that
1764                  the generic machinery is aware of the real stack usage and
1765                  will print the above diagnostic as expected.  */
1766 
1767               size = size_max;
1768             }
1769 
1770           size = trunc_int_for_mode (size, GET_MODE (my_fp));
1771           neg_size = trunc_int_for_mode (-size, GET_MODE (my_fp));
1772 
1773           /************  Method 1: Adjust frame pointer  ************/
1774 
1775           start_sequence ();
1776 
1777           /* Normally, the dwarf2out frame-related-expr interpreter does
1778              not expect to have the CFA change once the frame pointer is
1779              set up.  Thus, we avoid marking the move insn below and
1780              instead indicate that the entire operation is complete after
1781              the frame pointer subtraction is done.  */
1782 
1783           insn = emit_move_insn (fp, stack_pointer_rtx);
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, stack_pointer_rtx));
1789             }
1790 
1791           insn = emit_move_insn (my_fp, plus_constant (GET_MODE (my_fp),
1792                                                        my_fp, neg_size));
1793 
1794           if (frame_pointer_needed)
1795             {
1796               RTX_FRAME_RELATED_P (insn) = 1;
1797               add_reg_note (insn, REG_CFA_ADJUST_CFA,
1798                             gen_rtx_SET (fp, plus_constant (Pmode, fp,
1799 							    -size_cfa)));
1800             }
1801 
1802           /* Copy to stack pointer.  Note that since we've already
1803              changed the CFA to the frame pointer this operation
1804              need not be annotated if frame pointer is needed.
1805              Always move through unspec, see PR50063.
1806              For meaning of irq_state see movhi_sp_r insn.  */
1807 
1808           if (cfun->machine->is_interrupt)
1809             irq_state = 1;
1810 
1811           if (TARGET_NO_INTERRUPTS
1812               || cfun->machine->is_signal
1813               || cfun->machine->is_OS_main)
1814             irq_state = 0;
1815 
1816           if (AVR_HAVE_8BIT_SP)
1817             irq_state = 2;
1818 
1819           insn = emit_insn (gen_movhi_sp_r (stack_pointer_rtx,
1820                                             fp, GEN_INT (irq_state)));
1821           if (!frame_pointer_needed)
1822             {
1823               RTX_FRAME_RELATED_P (insn) = 1;
1824               add_reg_note (insn, REG_CFA_ADJUST_CFA,
1825                             gen_rtx_SET (stack_pointer_rtx,
1826                                          plus_constant (Pmode,
1827                                                         stack_pointer_rtx,
1828                                                         -size_cfa)));
1829             }
1830 
1831           fp_plus_insns = get_insns ();
1832           end_sequence ();
1833 
1834           /************  Method 2: Adjust Stack pointer  ************/
1835 
1836           /* Stack adjustment by means of RCALL . and/or PUSH __TMP_REG__
1837              can only handle specific offsets.  */
1838 
1839           int n_rcall = size / (AVR_3_BYTE_PC ? 3 : 2);
1840 
1841           if (avr_sp_immediate_operand (gen_int_mode (-size, HImode), HImode)
1842               // Don't use more than 3 RCALLs.
1843               && n_rcall <= 3)
1844             {
1845               rtx_insn *sp_plus_insns;
1846 
1847               start_sequence ();
1848 
1849               insn = emit_move_insn (stack_pointer_rtx,
1850                                      plus_constant (Pmode, stack_pointer_rtx,
1851                                                     -size));
1852               RTX_FRAME_RELATED_P (insn) = 1;
1853               add_reg_note (insn, REG_CFA_ADJUST_CFA,
1854                             gen_rtx_SET (stack_pointer_rtx,
1855                                          plus_constant (Pmode,
1856                                                         stack_pointer_rtx,
1857                                                         -size_cfa)));
1858               if (frame_pointer_needed)
1859                 {
1860                   insn = emit_move_insn (fp, stack_pointer_rtx);
1861                   RTX_FRAME_RELATED_P (insn) = 1;
1862                 }
1863 
1864               sp_plus_insns = get_insns ();
1865               end_sequence ();
1866 
1867               /************ Use shortest method  ************/
1868 
1869               emit_insn (get_sequence_length (sp_plus_insns)
1870                          < get_sequence_length (fp_plus_insns)
1871                          ? sp_plus_insns
1872                          : fp_plus_insns);
1873             }
1874           else
1875             {
1876               emit_insn (fp_plus_insns);
1877             }
1878 
1879           cfun->machine->stack_usage += size_cfa;
1880         } /* !minimize && size != 0 */
1881     } /* !minimize */
1882 }
1883 
1884 
1885 /*  Output function prologue.  */
1886 
1887 void
avr_expand_prologue(void)1888 avr_expand_prologue (void)
1889 {
1890   HARD_REG_SET set;
1891   HOST_WIDE_INT size;
1892 
1893   size = get_frame_size() + avr_outgoing_args_size();
1894 
1895   cfun->machine->stack_usage = 0;
1896 
1897   /* Prologue: naked.  */
1898   if (cfun->machine->is_naked)
1899     {
1900       return;
1901     }
1902 
1903   avr_regs_to_save (&set);
1904 
1905   if (cfun->machine->is_interrupt || cfun->machine->is_signal)
1906     {
1907       int treg = AVR_TMP_REGNO;
1908       /* Enable interrupts.  */
1909       if (cfun->machine->is_interrupt)
1910         emit_insn (gen_enable_interrupt ());
1911 
1912       if (cfun->machine->gasisr.maybe)
1913         {
1914           /* Let GAS PR21472 emit prologue preamble for us which handles SREG,
1915              ZERO_REG and TMP_REG and one additional, optional register for
1916              us in an optimal way.  This even scans through inline asm.  */
1917 
1918           cfun->machine->gasisr.yes = 1;
1919 
1920           // The optional reg or TMP_REG if we don't need one.  If we need one,
1921           // remove that reg from SET so that it's not puhed / popped twice.
1922           // We also use it below instead of TMP_REG in some places.
1923 
1924           treg = avr_hregs_split_reg (&set);
1925           if (treg < 0)
1926             treg = AVR_TMP_REGNO;
1927           cfun->machine->gasisr.regno = treg;
1928 
1929           // The worst case of pushes.  The exact number can be inferred
1930           // at assembly time by magic expression __gcc_isr.n_pushed.
1931           cfun->machine->stack_usage += 3 + (treg != AVR_TMP_REGNO);
1932 
1933           // Emit a Prologue chunk.  Epilogue chunk(s) might follow.
1934           // The final Done chunk is emit by final postscan.
1935           emit_insn (gen_gasisr (GEN_INT (GASISR_Prologue), GEN_INT (treg)));
1936         }
1937       else // !TARGET_GASISR_PROLOGUES: Classic, dumb prologue preamble.
1938         {
1939           /* Push zero reg.  */
1940           emit_push_byte (AVR_ZERO_REGNO, true);
1941 
1942           /* Push tmp reg.  */
1943           emit_push_byte (AVR_TMP_REGNO, true);
1944 
1945           /* Push SREG.  */
1946           /* ??? There's no dwarf2 column reserved for SREG.  */
1947           emit_push_sfr (sreg_rtx, false, false /* clr */, AVR_TMP_REGNO);
1948 
1949           /* Clear zero reg.  */
1950           emit_move_insn (zero_reg_rtx, const0_rtx);
1951 
1952           /* Prevent any attempt to delete the setting of ZERO_REG!  */
1953           emit_use (zero_reg_rtx);
1954         }
1955 
1956       /* Push and clear RAMPD/X/Y/Z if present and low-part register is used.
1957          ??? There are no dwarf2 columns reserved for RAMPD/X/Y/Z.  */
1958 
1959       if (AVR_HAVE_RAMPD)
1960         emit_push_sfr (rampd_rtx, false /* frame */, true /* clr */, treg);
1961 
1962       if (AVR_HAVE_RAMPX
1963           && TEST_HARD_REG_BIT (set, REG_X)
1964           && TEST_HARD_REG_BIT (set, REG_X + 1))
1965         {
1966           emit_push_sfr (rampx_rtx, false /* frame */, true /* clr */, treg);
1967         }
1968 
1969       if (AVR_HAVE_RAMPY
1970           && (frame_pointer_needed
1971               || (TEST_HARD_REG_BIT (set, REG_Y)
1972                   && TEST_HARD_REG_BIT (set, REG_Y + 1))))
1973         {
1974           emit_push_sfr (rampy_rtx, false /* frame */, true /* clr */, treg);
1975         }
1976 
1977       if (AVR_HAVE_RAMPZ
1978           && TEST_HARD_REG_BIT (set, REG_Z)
1979           && TEST_HARD_REG_BIT (set, REG_Z + 1))
1980         {
1981           emit_push_sfr (rampz_rtx, false /* frame */, AVR_HAVE_RAMPD, treg);
1982         }
1983     }  /* is_interrupt is_signal */
1984 
1985   avr_prologue_setup_frame (size, set);
1986 
1987   if (flag_stack_usage_info)
1988     current_function_static_stack_size
1989       = cfun->machine->stack_usage + INCOMING_FRAME_SP_OFFSET;
1990 }
1991 
1992 
1993 /* Implement `TARGET_ASM_FUNCTION_END_PROLOGUE'.  */
1994 /* Output summary at end of function prologue.  */
1995 
1996 static void
avr_asm_function_end_prologue(FILE * file)1997 avr_asm_function_end_prologue (FILE *file)
1998 {
1999   if (cfun->machine->is_naked)
2000     {
2001       fputs ("/* prologue: naked */\n", file);
2002     }
2003   else
2004     {
2005       if (cfun->machine->is_interrupt)
2006         {
2007           fputs ("/* prologue: Interrupt */\n", file);
2008         }
2009       else if (cfun->machine->is_signal)
2010         {
2011           fputs ("/* prologue: Signal */\n", file);
2012         }
2013       else
2014         fputs ("/* prologue: function */\n", file);
2015     }
2016 
2017   if (ACCUMULATE_OUTGOING_ARGS)
2018     fprintf (file, "/* outgoing args size = %d */\n",
2019              avr_outgoing_args_size());
2020 
2021   fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n",
2022            (HOST_WIDE_INT) get_frame_size());
2023 
2024   if (!cfun->machine->gasisr.yes)
2025     {
2026       fprintf (file, "/* stack size = %d */\n", cfun->machine->stack_usage);
2027       // Create symbol stack offset so all functions have it. Add 1 to stack
2028       // usage for offset so that SP + .L__stack_offset = return address.
2029       fprintf (file, ".L__stack_usage = %d\n", cfun->machine->stack_usage);
2030     }
2031   else
2032     {
2033       int used_by_gasisr = 3 + (cfun->machine->gasisr.regno != AVR_TMP_REGNO);
2034       int to = cfun->machine->stack_usage;
2035       int from = to - used_by_gasisr;
2036       // Number of pushed regs is only known at assembly-time.
2037       fprintf (file, "/* stack size = %d...%d */\n", from , to);
2038       fprintf (file, ".L__stack_usage = %d + __gcc_isr.n_pushed\n", from);
2039     }
2040 }
2041 
2042 
2043 /* Implement `EPILOGUE_USES'.  */
2044 
2045 int
avr_epilogue_uses(int regno ATTRIBUTE_UNUSED)2046 avr_epilogue_uses (int regno ATTRIBUTE_UNUSED)
2047 {
2048   if (reload_completed
2049       && cfun->machine
2050       && (cfun->machine->is_interrupt || cfun->machine->is_signal))
2051     return 1;
2052   return 0;
2053 }
2054 
2055 /*  Helper for avr_expand_epilogue.  Emit a pop of a byte register.  */
2056 
2057 static void
emit_pop_byte(unsigned regno)2058 emit_pop_byte (unsigned regno)
2059 {
2060   rtx mem, reg;
2061 
2062   mem = gen_rtx_PRE_INC (HImode, stack_pointer_rtx);
2063   mem = gen_frame_mem (QImode, mem);
2064   reg = gen_rtx_REG (QImode, regno);
2065 
2066   emit_insn (gen_rtx_SET (reg, mem));
2067 }
2068 
2069 /*  Output RTL epilogue.  */
2070 
2071 void
avr_expand_epilogue(bool sibcall_p)2072 avr_expand_epilogue (bool sibcall_p)
2073 {
2074   int live_seq;
2075   HARD_REG_SET set;
2076   int minimize;
2077   HOST_WIDE_INT size;
2078   bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
2079 
2080   size = get_frame_size() + avr_outgoing_args_size();
2081 
2082   /* epilogue: naked  */
2083   if (cfun->machine->is_naked)
2084     {
2085       gcc_assert (!sibcall_p);
2086 
2087       emit_jump_insn (gen_return ());
2088       return;
2089     }
2090 
2091   avr_regs_to_save (&set);
2092   live_seq = sequent_regs_live ();
2093 
2094   minimize = (TARGET_CALL_PROLOGUES
2095               && live_seq
2096               && !isr_p
2097               && !cfun->machine->is_OS_task
2098               && !cfun->machine->is_OS_main
2099               && !AVR_TINY);
2100 
2101   if (minimize
2102       && (live_seq > 4
2103           || frame_pointer_needed
2104           || size))
2105     {
2106       /*  Get rid of frame.  */
2107 
2108       if (!frame_pointer_needed)
2109         {
2110           emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
2111         }
2112 
2113       if (size)
2114         {
2115           emit_move_insn (frame_pointer_rtx,
2116                           plus_constant (Pmode, frame_pointer_rtx, size));
2117         }
2118 
2119       emit_insn (gen_epilogue_restores (gen_int_mode (live_seq, HImode)));
2120       return;
2121     }
2122 
2123   if (size)
2124     {
2125       /* Try two methods to adjust stack and select shortest.  */
2126 
2127       int irq_state = -1;
2128       rtx fp, my_fp;
2129       rtx_insn *fp_plus_insns;
2130       HOST_WIDE_INT size_max;
2131 
2132       gcc_assert (frame_pointer_needed
2133                   || !isr_p
2134                   || !crtl->is_leaf);
2135 
2136       fp = my_fp = (frame_pointer_needed
2137                     ? frame_pointer_rtx
2138                     : gen_rtx_REG (Pmode, REG_X));
2139 
2140       if (AVR_HAVE_8BIT_SP)
2141         {
2142           /* The high byte (r29) does not change:
2143              Prefer SUBI (1 cycle) over SBIW (2 cycles).  */
2144 
2145           my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
2146         }
2147 
2148       /* For rationale see comment in prologue generation.  */
2149 
2150       size_max = (HOST_WIDE_INT) GET_MODE_MASK (GET_MODE (my_fp));
2151       if (size > size_max)
2152         size = size_max;
2153       size = trunc_int_for_mode (size, GET_MODE (my_fp));
2154 
2155       /********** Method 1: Adjust fp register  **********/
2156 
2157       start_sequence ();
2158 
2159       if (!frame_pointer_needed)
2160         emit_move_insn (fp, stack_pointer_rtx);
2161 
2162       emit_move_insn (my_fp, plus_constant (GET_MODE (my_fp), my_fp, size));
2163 
2164       /* Copy to stack pointer.  */
2165 
2166       if (TARGET_NO_INTERRUPTS)
2167         irq_state = 0;
2168 
2169       if (AVR_HAVE_8BIT_SP)
2170         irq_state = 2;
2171 
2172       emit_insn (gen_movhi_sp_r (stack_pointer_rtx, fp,
2173                                  GEN_INT (irq_state)));
2174 
2175       fp_plus_insns = get_insns ();
2176       end_sequence ();
2177 
2178       /********** Method 2: Adjust Stack pointer  **********/
2179 
2180       if (avr_sp_immediate_operand (gen_int_mode (size, HImode), HImode))
2181         {
2182           rtx_insn *sp_plus_insns;
2183 
2184           start_sequence ();
2185 
2186           emit_move_insn (stack_pointer_rtx,
2187                           plus_constant (Pmode, stack_pointer_rtx, size));
2188 
2189           sp_plus_insns = get_insns ();
2190           end_sequence ();
2191 
2192           /************ Use shortest method  ************/
2193 
2194           emit_insn (get_sequence_length (sp_plus_insns)
2195                      < get_sequence_length (fp_plus_insns)
2196                      ? sp_plus_insns
2197                      : fp_plus_insns);
2198         }
2199       else
2200         emit_insn (fp_plus_insns);
2201     } /* size != 0 */
2202 
2203   if (frame_pointer_needed
2204       && !(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
2205     {
2206       /* Restore previous frame_pointer.  See avr_expand_prologue for
2207          rationale for not using pophi.  */
2208 
2209       emit_pop_byte (REG_Y + 1);
2210       emit_pop_byte (REG_Y);
2211     }
2212 
2213   /* Restore used registers.  */
2214 
2215   int treg = AVR_TMP_REGNO;
2216 
2217   if (isr_p
2218       && cfun->machine->gasisr.yes)
2219     {
2220       treg = cfun->machine->gasisr.regno;
2221       CLEAR_HARD_REG_BIT (set, treg);
2222     }
2223 
2224   for (int reg = 31; reg >= 0; --reg)
2225     if (TEST_HARD_REG_BIT (set, reg))
2226       emit_pop_byte (reg);
2227 
2228   if (isr_p)
2229     {
2230       /* Restore RAMPZ/Y/X/D using tmp_reg as scratch.
2231          The conditions to restore them must be tha same as in prologue.  */
2232 
2233       if (AVR_HAVE_RAMPZ
2234           && TEST_HARD_REG_BIT (set, REG_Z)
2235           && TEST_HARD_REG_BIT (set, REG_Z + 1))
2236         {
2237           emit_pop_byte (treg);
2238           emit_move_insn (rampz_rtx, all_regs_rtx[treg]);
2239         }
2240 
2241       if (AVR_HAVE_RAMPY
2242           && (frame_pointer_needed
2243               || (TEST_HARD_REG_BIT (set, REG_Y)
2244                   && TEST_HARD_REG_BIT (set, REG_Y + 1))))
2245         {
2246           emit_pop_byte (treg);
2247           emit_move_insn (rampy_rtx, all_regs_rtx[treg]);
2248         }
2249 
2250       if (AVR_HAVE_RAMPX
2251           && TEST_HARD_REG_BIT (set, REG_X)
2252           && TEST_HARD_REG_BIT (set, REG_X + 1))
2253         {
2254           emit_pop_byte (treg);
2255           emit_move_insn (rampx_rtx, all_regs_rtx[treg]);
2256         }
2257 
2258       if (AVR_HAVE_RAMPD)
2259         {
2260           emit_pop_byte (treg);
2261           emit_move_insn (rampd_rtx, all_regs_rtx[treg]);
2262         }
2263 
2264       if (cfun->machine->gasisr.yes)
2265         {
2266           // Emit an Epilogue chunk.
2267           emit_insn (gen_gasisr (GEN_INT (GASISR_Epilogue),
2268                                  GEN_INT (cfun->machine->gasisr.regno)));
2269         }
2270       else // !TARGET_GASISR_PROLOGUES
2271         {
2272           /* Restore SREG using tmp_reg as scratch.  */
2273 
2274           emit_pop_byte (AVR_TMP_REGNO);
2275           emit_move_insn (sreg_rtx, tmp_reg_rtx);
2276 
2277           /* Restore tmp REG.  */
2278           emit_pop_byte (AVR_TMP_REGNO);
2279 
2280           /* Restore zero REG.  */
2281           emit_pop_byte (AVR_ZERO_REGNO);
2282         }
2283     }
2284 
2285   if (!sibcall_p)
2286     emit_jump_insn (gen_return ());
2287 }
2288 
2289 
2290 /* Implement `TARGET_ASM_FUNCTION_BEGIN_EPILOGUE'.  */
2291 
2292 static void
avr_asm_function_begin_epilogue(FILE * file)2293 avr_asm_function_begin_epilogue (FILE *file)
2294 {
2295   app_disable();
2296   fprintf (file, "/* epilogue start */\n");
2297 }
2298 
2299 
2300 /* Implement `TARGET_CANNOT_MODITY_JUMPS_P'.  */
2301 
2302 static bool
avr_cannot_modify_jumps_p(void)2303 avr_cannot_modify_jumps_p (void)
2304 {
2305   /* Naked Functions must not have any instructions after
2306      their epilogue, see PR42240 */
2307 
2308   if (reload_completed
2309       && cfun->machine
2310       && cfun->machine->is_naked)
2311     {
2312       return true;
2313     }
2314 
2315   return false;
2316 }
2317 
2318 
2319 /* Implement `TARGET_MODE_DEPENDENT_ADDRESS_P'.  */
2320 
2321 static bool
avr_mode_dependent_address_p(const_rtx addr ATTRIBUTE_UNUSED,addr_space_t as)2322 avr_mode_dependent_address_p (const_rtx addr ATTRIBUTE_UNUSED, addr_space_t as)
2323 {
2324   /* FIXME:  Non-generic addresses are not mode-dependent in themselves.
2325        This hook just serves to hack around PR rtl-optimization/52543 by
2326        claiming that non-generic addresses were mode-dependent so that
2327        lower-subreg.c will skip these addresses.  lower-subreg.c sets up fake
2328        RTXes to probe SET and MEM costs and assumes that MEM is always in the
2329        generic address space which is not true.  */
2330 
2331   return !ADDR_SPACE_GENERIC_P (as);
2332 }
2333 
2334 
2335 /* Return true if rtx X is a CONST_INT, CONST or SYMBOL_REF
2336    address with the `absdata' variable attribute, i.e. respective
2337    data can be read / written by LDS / STS instruction.
2338    This is used only for AVR_TINY.  */
2339 
2340 static bool
avr_address_tiny_absdata_p(rtx x,machine_mode mode)2341 avr_address_tiny_absdata_p (rtx x, machine_mode mode)
2342 {
2343   if (CONST == GET_CODE (x))
2344     x = XEXP (XEXP (x, 0), 0);
2345 
2346   if (SYMBOL_REF_P (x))
2347     return SYMBOL_REF_FLAGS (x) & AVR_SYMBOL_FLAG_TINY_ABSDATA;
2348 
2349   if (CONST_INT_P (x)
2350       && IN_RANGE (INTVAL (x), 0, 0xc0 - GET_MODE_SIZE (mode)))
2351     return true;
2352 
2353   return false;
2354 }
2355 
2356 
2357 /* Helper function for `avr_legitimate_address_p'.  */
2358 
2359 static inline bool
avr_reg_ok_for_addr_p(rtx reg,addr_space_t as,RTX_CODE outer_code,bool strict)2360 avr_reg_ok_for_addr_p (rtx reg, addr_space_t as,
2361                        RTX_CODE outer_code, bool strict)
2362 {
2363   return (REG_P (reg)
2364           && (avr_regno_mode_code_ok_for_base_p (REGNO (reg), QImode,
2365                                                  as, outer_code, UNKNOWN)
2366               || (!strict
2367                   && REGNO (reg) >= FIRST_PSEUDO_REGISTER)));
2368 }
2369 
2370 
2371 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
2372    machine for a memory operand of mode MODE.  */
2373 
2374 static bool
avr_legitimate_address_p(machine_mode mode,rtx x,bool strict)2375 avr_legitimate_address_p (machine_mode mode, rtx x, bool strict)
2376 {
2377   bool ok = CONSTANT_ADDRESS_P (x);
2378 
2379   switch (GET_CODE (x))
2380     {
2381     case REG:
2382       ok = avr_reg_ok_for_addr_p (x, ADDR_SPACE_GENERIC,
2383                                   MEM, strict);
2384 
2385       if (strict
2386           && GET_MODE_SIZE (mode) > 4
2387           && REG_X == REGNO (x))
2388         {
2389           ok = false;
2390         }
2391       break;
2392 
2393     case POST_INC:
2394     case PRE_DEC:
2395       ok = avr_reg_ok_for_addr_p (XEXP (x, 0), ADDR_SPACE_GENERIC,
2396                                   GET_CODE (x), strict);
2397       break;
2398 
2399     case PLUS:
2400       {
2401         rtx reg = XEXP (x, 0);
2402         rtx op1 = XEXP (x, 1);
2403 
2404         if (REG_P (reg)
2405             && CONST_INT_P (op1)
2406             && INTVAL (op1) >= 0)
2407           {
2408             bool fit = IN_RANGE (INTVAL (op1), 0, MAX_LD_OFFSET (mode));
2409 
2410             if (fit)
2411               {
2412                 ok = (! strict
2413                       || avr_reg_ok_for_addr_p (reg, ADDR_SPACE_GENERIC,
2414                                                 PLUS, strict));
2415 
2416                 if (reg == frame_pointer_rtx
2417                     || reg == arg_pointer_rtx)
2418                   {
2419                     ok = true;
2420                   }
2421               }
2422             else if (frame_pointer_needed
2423                      && reg == frame_pointer_rtx)
2424               {
2425                 ok = true;
2426               }
2427           }
2428       }
2429       break;
2430 
2431     default:
2432       break;
2433     }
2434 
2435   if (AVR_TINY
2436       && CONSTANT_ADDRESS_P (x))
2437     {
2438       /* avrtiny's load / store instructions only cover addresses 0..0xbf:
2439          IN / OUT range is 0..0x3f and LDS / STS can access 0x40..0xbf.  */
2440 
2441       ok = avr_address_tiny_absdata_p (x, mode);
2442     }
2443 
2444   if (avr_log.legitimate_address_p)
2445     {
2446       avr_edump ("\n%?: ret=%d, mode=%m strict=%d "
2447                  "reload_completed=%d reload_in_progress=%d %s:",
2448                  ok, mode, strict, reload_completed, reload_in_progress,
2449                  reg_renumber ? "(reg_renumber)" : "");
2450 
2451       if (GET_CODE (x) == PLUS
2452           && REG_P (XEXP (x, 0))
2453           && CONST_INT_P (XEXP (x, 1))
2454           && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
2455           && reg_renumber)
2456         {
2457           avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
2458                      true_regnum (XEXP (x, 0)));
2459         }
2460 
2461       avr_edump ("\n%r\n", x);
2462     }
2463 
2464   return ok;
2465 }
2466 
2467 
2468 /* Former implementation of TARGET_LEGITIMIZE_ADDRESS,
2469    now only a helper for avr_addr_space_legitimize_address.  */
2470 /* Attempts to replace X with a valid
2471    memory address for an operand of mode MODE  */
2472 
2473 static rtx
avr_legitimize_address(rtx x,rtx oldx,machine_mode mode)2474 avr_legitimize_address (rtx x, rtx oldx, machine_mode mode)
2475 {
2476   bool big_offset_p = false;
2477 
2478   x = oldx;
2479 
2480   if (AVR_TINY)
2481     {
2482       if (CONSTANT_ADDRESS_P (x)
2483           && ! avr_address_tiny_absdata_p (x, mode))
2484         {
2485           x = force_reg (Pmode, x);
2486         }
2487     }
2488 
2489   if (GET_CODE (oldx) == PLUS
2490       && REG_P (XEXP (oldx, 0)))
2491     {
2492       if (REG_P (XEXP (oldx, 1)))
2493         x = force_reg (GET_MODE (oldx), oldx);
2494       else if (CONST_INT_P (XEXP (oldx, 1)))
2495         {
2496           int offs = INTVAL (XEXP (oldx, 1));
2497           if (frame_pointer_rtx != XEXP (oldx, 0)
2498               && offs > MAX_LD_OFFSET (mode))
2499             {
2500               big_offset_p = true;
2501               x = force_reg (GET_MODE (oldx), oldx);
2502             }
2503         }
2504     }
2505 
2506   if (avr_log.legitimize_address)
2507     {
2508       avr_edump ("\n%?: mode=%m\n %r\n", mode, oldx);
2509 
2510       if (x != oldx)
2511         avr_edump (" %s --> %r\n", big_offset_p ? "(big offset)" : "", x);
2512     }
2513 
2514   return x;
2515 }
2516 
2517 
2518 /* Implement `LEGITIMIZE_RELOAD_ADDRESS'.  */
2519 /* This will allow register R26/27 to be used where it is no worse than normal
2520    base pointers R28/29 or R30/31.  For example, if base offset is greater
2521    than 63 bytes or for R++ or --R addressing.  */
2522 
2523 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))2524 avr_legitimize_reload_address (rtx *px, machine_mode mode,
2525                                int opnum, int type, int addr_type,
2526                                int ind_levels ATTRIBUTE_UNUSED,
2527                                rtx (*mk_memloc)(rtx,int))
2528 {
2529   rtx x = *px;
2530 
2531   if (avr_log.legitimize_reload_address)
2532     avr_edump ("\n%?:%m %r\n", mode, x);
2533 
2534   if (1 && (GET_CODE (x) == POST_INC
2535             || GET_CODE (x) == PRE_DEC))
2536     {
2537       push_reload (XEXP (x, 0), XEXP (x, 0), &XEXP (x, 0), &XEXP (x, 0),
2538                    POINTER_REGS, GET_MODE (x), GET_MODE (x), 0, 0,
2539                    opnum, RELOAD_OTHER);
2540 
2541       if (avr_log.legitimize_reload_address)
2542         avr_edump (" RCLASS.1 = %R\n IN = %r\n OUT = %r\n",
2543                    POINTER_REGS, XEXP (x, 0), XEXP (x, 0));
2544 
2545       return x;
2546     }
2547 
2548   if (GET_CODE (x) == PLUS
2549       && REG_P (XEXP (x, 0))
2550       && reg_equiv_constant (REGNO (XEXP (x, 0))) == 0
2551       && CONST_INT_P (XEXP (x, 1))
2552       && INTVAL (XEXP (x, 1)) >= 1)
2553     {
2554       bool fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
2555 
2556       if (fit)
2557         {
2558           if (reg_equiv_address (REGNO (XEXP (x, 0))) != 0)
2559             {
2560               int regno = REGNO (XEXP (x, 0));
2561               rtx mem = mk_memloc (x, regno);
2562 
2563               push_reload (XEXP (mem, 0), NULL_RTX, &XEXP (mem, 0), NULL,
2564                            POINTER_REGS, Pmode, VOIDmode, 0, 0,
2565                            1, (enum reload_type) addr_type);
2566 
2567               if (avr_log.legitimize_reload_address)
2568                 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
2569                            POINTER_REGS, XEXP (mem, 0), NULL_RTX);
2570 
2571               push_reload (mem, NULL_RTX, &XEXP (x, 0), NULL,
2572                            BASE_POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
2573                            opnum, (enum reload_type) type);
2574 
2575               if (avr_log.legitimize_reload_address)
2576                 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
2577                            BASE_POINTER_REGS, mem, NULL_RTX);
2578 
2579               return x;
2580             }
2581         }
2582       else if (! (frame_pointer_needed
2583                   && XEXP (x, 0) == frame_pointer_rtx))
2584         {
2585           push_reload (x, NULL_RTX, px, NULL,
2586                        POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
2587                        opnum, (enum reload_type) type);
2588 
2589           if (avr_log.legitimize_reload_address)
2590             avr_edump (" RCLASS.3 = %R\n IN = %r\n OUT = %r\n",
2591                        POINTER_REGS, x, NULL_RTX);
2592 
2593           return x;
2594         }
2595     }
2596 
2597   return NULL_RTX;
2598 }
2599 
2600 
2601 /* Helper function to print assembler resp. track instruction
2602    sequence lengths.  Always return "".
2603 
2604    If PLEN == NULL:
2605        Output assembler code from template TPL with operands supplied
2606        by OPERANDS.  This is just forwarding to output_asm_insn.
2607 
2608    If PLEN != NULL:
2609        If N_WORDS >= 0  Add N_WORDS to *PLEN.
2610        If N_WORDS < 0   Set *PLEN to -N_WORDS.
2611        Don't output anything.
2612 */
2613 
2614 static const char*
avr_asm_len(const char * tpl,rtx * operands,int * plen,int n_words)2615 avr_asm_len (const char* tpl, rtx* operands, int* plen, int n_words)
2616 {
2617   if (plen == NULL)
2618     output_asm_insn (tpl, operands);
2619   else
2620     {
2621       if (n_words < 0)
2622         *plen = -n_words;
2623       else
2624         *plen += n_words;
2625     }
2626 
2627   return "";
2628 }
2629 
2630 
2631 /* Return a pointer register name as a string.  */
2632 
2633 static const char*
ptrreg_to_str(int regno)2634 ptrreg_to_str (int regno)
2635 {
2636   switch (regno)
2637     {
2638     case REG_X: return "X";
2639     case REG_Y: return "Y";
2640     case REG_Z: return "Z";
2641     default:
2642       output_operand_lossage ("address operand requires constraint for"
2643                               " X, Y, or Z register");
2644     }
2645   return NULL;
2646 }
2647 
2648 /* Return the condition name as a string.
2649    Used in conditional jump constructing  */
2650 
2651 static const char*
cond_string(enum rtx_code code)2652 cond_string (enum rtx_code code)
2653 {
2654   bool cc_overflow_unusable = false;
2655 
2656   switch (code)
2657     {
2658     case NE:
2659       return "ne";
2660     case EQ:
2661       return "eq";
2662     case GE:
2663       if (cc_overflow_unusable)
2664         return "pl";
2665       else
2666         return "ge";
2667     case LT:
2668       if (cc_overflow_unusable)
2669         return "mi";
2670       else
2671         return "lt";
2672     case GEU:
2673       return "sh";
2674     case LTU:
2675       return "lo";
2676     default:
2677       gcc_unreachable ();
2678     }
2679 
2680   return "";
2681 }
2682 
2683 
2684 /* Return true if rtx X is a CONST or SYMBOL_REF with progmem.
2685    This must be used for AVR_TINY only because on other cores
2686    the flash memory is not visible in the RAM address range and
2687    cannot be read by, say,  LD instruction.  */
2688 
2689 static bool
avr_address_tiny_pm_p(rtx x)2690 avr_address_tiny_pm_p (rtx x)
2691 {
2692   if (CONST == GET_CODE (x))
2693     x = XEXP (XEXP (x, 0), 0);
2694 
2695   if (SYMBOL_REF_P (x))
2696     return SYMBOL_REF_FLAGS (x) & AVR_SYMBOL_FLAG_TINY_PM;
2697 
2698   return false;
2699 }
2700 
2701 /* Implement `TARGET_PRINT_OPERAND_ADDRESS'.  */
2702 /* Output ADDR to FILE as address.  */
2703 
2704 static void
avr_print_operand_address(FILE * file,machine_mode,rtx addr)2705 avr_print_operand_address (FILE *file, machine_mode /*mode*/, rtx addr)
2706 {
2707   if (AVR_TINY
2708       && avr_address_tiny_pm_p (addr))
2709     {
2710       addr = plus_constant (Pmode, addr, avr_arch->flash_pm_offset);
2711     }
2712 
2713   switch (GET_CODE (addr))
2714     {
2715     case REG:
2716       fprintf (file, "%s", ptrreg_to_str (REGNO (addr)));
2717       break;
2718 
2719     case PRE_DEC:
2720       fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
2721       break;
2722 
2723     case POST_INC:
2724       fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
2725       break;
2726 
2727     default:
2728       if (CONSTANT_ADDRESS_P (addr)
2729           && text_segment_operand (addr, VOIDmode))
2730         {
2731           rtx x = addr;
2732           if (GET_CODE (x) == CONST)
2733             x = XEXP (x, 0);
2734           if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1)))
2735             {
2736               /* Assembler gs() will implant word address.  Make offset
2737                  a byte offset inside gs() for assembler.  This is
2738                  needed because the more logical (constant+gs(sym)) is not
2739                  accepted by gas.  For 128K and smaller devices this is ok.
2740                  For large devices it will create a trampoline to offset
2741                  from symbol which may not be what the user really wanted.  */
2742 
2743               fprintf (file, "gs(");
2744               output_addr_const (file, XEXP (x, 0));
2745               fprintf (file, "+" HOST_WIDE_INT_PRINT_DEC ")",
2746                        2 * INTVAL (XEXP (x, 1)));
2747               if (AVR_3_BYTE_PC)
2748                 if (warning (0, "pointer offset from symbol maybe incorrect"))
2749                   {
2750                     output_addr_const (stderr, addr);
2751                     fprintf (stderr, "\n");
2752                   }
2753             }
2754           else
2755             {
2756               fprintf (file, "gs(");
2757               output_addr_const (file, addr);
2758               fprintf (file, ")");
2759             }
2760         }
2761       else
2762         output_addr_const (file, addr);
2763     }
2764 }
2765 
2766 
2767 /* Implement `TARGET_PRINT_OPERAND_PUNCT_VALID_P'.  */
2768 
2769 static bool
avr_print_operand_punct_valid_p(unsigned char code)2770 avr_print_operand_punct_valid_p (unsigned char code)
2771 {
2772   return code == '~' || code == '!';
2773 }
2774 
2775 
2776 /* Implement `TARGET_PRINT_OPERAND'.  */
2777 /* Output X as assembler operand to file FILE.
2778    For a description of supported %-codes, see top of avr.md.  */
2779 
2780 static void
avr_print_operand(FILE * file,rtx x,int code)2781 avr_print_operand (FILE *file, rtx x, int code)
2782 {
2783   int abcd = 0, ef = 0, ij = 0;
2784 
2785   if (code >= 'A' && code <= 'D')
2786     abcd = code - 'A';
2787   else if (code == 'E' || code == 'F')
2788     ef = code - 'E';
2789   else if (code == 'I' || code == 'J')
2790     ij = code - 'I';
2791 
2792   if (code == '~')
2793     {
2794       if (!AVR_HAVE_JMP_CALL)
2795         fputc ('r', file);
2796     }
2797   else if (code == '!')
2798     {
2799       if (AVR_HAVE_EIJMP_EICALL)
2800         fputc ('e', file);
2801     }
2802   else if (code == 't'
2803            || code == 'T')
2804     {
2805       static int t_regno = -1;
2806       static int t_nbits = -1;
2807 
2808       if (REG_P (x) && t_regno < 0 && code == 'T')
2809         {
2810           t_regno = REGNO (x);
2811           t_nbits = GET_MODE_BITSIZE (GET_MODE (x));
2812         }
2813       else if (CONST_INT_P (x) && t_regno >= 0
2814                && IN_RANGE (INTVAL (x), 0, t_nbits - 1))
2815         {
2816           int bpos = INTVAL (x);
2817 
2818           fprintf (file, "%s", reg_names[t_regno + bpos / 8]);
2819           if (code == 'T')
2820             fprintf (file, ",%d", bpos % 8);
2821 
2822           t_regno = -1;
2823         }
2824       else
2825         fatal_insn ("operands to %T/%t must be reg + const_int:", x);
2826     }
2827   else if (code == 'E' || code == 'F')
2828     {
2829       rtx op = XEXP (x, 0);
2830       fprintf (file, "%s", reg_names[REGNO (op) + ef]);
2831     }
2832   else if (code == 'I' || code == 'J')
2833     {
2834       rtx op = XEXP (XEXP (x, 0), 0);
2835       fprintf (file, "%s", reg_names[REGNO (op) + ij]);
2836     }
2837   else if (REG_P (x))
2838     {
2839       if (x == zero_reg_rtx)
2840         fprintf (file, "__zero_reg__");
2841       else if (code == 'r' && REGNO (x) < 32)
2842         fprintf (file, "%d", (int) REGNO (x));
2843       else
2844         fprintf (file, "%s", reg_names[REGNO (x) + abcd]);
2845     }
2846   else if (CONST_INT_P (x))
2847     {
2848       HOST_WIDE_INT ival = INTVAL (x);
2849 
2850       if ('i' != code)
2851         fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival + abcd);
2852       else if (low_io_address_operand (x, VOIDmode)
2853                || high_io_address_operand (x, VOIDmode))
2854         {
2855           if (AVR_HAVE_RAMPZ && ival == avr_addr.rampz)
2856             fprintf (file, "__RAMPZ__");
2857           else if (AVR_HAVE_RAMPY && ival == avr_addr.rampy)
2858             fprintf (file, "__RAMPY__");
2859           else if (AVR_HAVE_RAMPX && ival == avr_addr.rampx)
2860             fprintf (file, "__RAMPX__");
2861           else if (AVR_HAVE_RAMPD && ival == avr_addr.rampd)
2862             fprintf (file, "__RAMPD__");
2863           else if ((AVR_XMEGA || AVR_TINY) && ival == avr_addr.ccp)
2864             fprintf (file, "__CCP__");
2865           else if (ival == avr_addr.sreg)   fprintf (file, "__SREG__");
2866           else if (ival == avr_addr.sp_l)   fprintf (file, "__SP_L__");
2867           else if (ival == avr_addr.sp_h)   fprintf (file, "__SP_H__");
2868           else
2869             {
2870               fprintf (file, HOST_WIDE_INT_PRINT_HEX,
2871                        ival - avr_arch->sfr_offset);
2872             }
2873         }
2874       else
2875         fatal_insn ("bad address, not an I/O address:", x);
2876     }
2877   else if (MEM_P (x))
2878     {
2879       rtx addr = XEXP (x, 0);
2880 
2881       if (code == 'm')
2882         {
2883           if (!CONSTANT_P (addr))
2884             fatal_insn ("bad address, not a constant:", addr);
2885           /* Assembler template with m-code is data - not progmem section */
2886           if (text_segment_operand (addr, VOIDmode))
2887             if (warning (0, "accessing data memory with"
2888                          " program memory address"))
2889               {
2890                 output_addr_const (stderr, addr);
2891                 fprintf(stderr,"\n");
2892               }
2893           output_addr_const (file, addr);
2894         }
2895       else if (code == 'i')
2896         {
2897           avr_print_operand (file, addr, 'i');
2898         }
2899       else if (code == 'o')
2900         {
2901           if (GET_CODE (addr) != PLUS)
2902             fatal_insn ("bad address, not (reg+disp):", addr);
2903 
2904           avr_print_operand (file, XEXP (addr, 1), 0);
2905         }
2906       else if (code == 'b')
2907         {
2908           if (GET_CODE (addr) != PLUS)
2909             fatal_insn ("bad address, not (reg+disp):", addr);
2910 
2911           avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
2912         }
2913       else if (code == 'p' || code == 'r')
2914         {
2915           if (GET_CODE (addr) != POST_INC && GET_CODE (addr) != PRE_DEC)
2916             fatal_insn ("bad address, not post_inc or pre_dec:", addr);
2917 
2918           if (code == 'p')
2919             /* X, Y, Z */
2920             avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
2921           else
2922             avr_print_operand (file, XEXP (addr, 0), 0);  /* r26, r28, r30 */
2923         }
2924       else if (GET_CODE (addr) == PLUS)
2925         {
2926           avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
2927           if (REGNO (XEXP (addr, 0)) == REG_X)
2928             fatal_insn ("internal compiler error.  Bad address:"
2929                         ,addr);
2930           fputc ('+', file);
2931           avr_print_operand (file, XEXP (addr, 1), code);
2932         }
2933       else
2934         avr_print_operand_address (file, VOIDmode, addr);
2935     }
2936   else if (code == 'i')
2937     {
2938       if (SYMBOL_REF_P (x) && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO))
2939 	avr_print_operand_address
2940 	  (file, VOIDmode, plus_constant (HImode, x, -avr_arch->sfr_offset));
2941       else
2942 	fatal_insn ("bad address, not an I/O address:", x);
2943     }
2944   else if (code == 'x')
2945     {
2946       /* Constant progmem address - like used in jmp or call */
2947       if (text_segment_operand (x, VOIDmode) == 0)
2948         if (warning (0, "accessing program memory"
2949                      " with data memory address"))
2950           {
2951             output_addr_const (stderr, x);
2952             fprintf(stderr,"\n");
2953           }
2954       /* Use normal symbol for direct address no linker trampoline needed */
2955       output_addr_const (file, x);
2956     }
2957   else if (CONST_FIXED_P (x))
2958     {
2959       HOST_WIDE_INT ival = INTVAL (avr_to_int_mode (x));
2960       if (code != 0)
2961         output_operand_lossage ("Unsupported code '%c' for fixed-point:",
2962                                 code);
2963       fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);
2964     }
2965   else if (CONST_DOUBLE_P (x))
2966     {
2967       long val;
2968       if (GET_MODE (x) != SFmode)
2969         fatal_insn ("internal compiler error.  Unknown mode:", x);
2970       REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), val);
2971       fprintf (file, "0x%lx", val);
2972     }
2973   else if (GET_CODE (x) == CONST_STRING)
2974     fputs (XSTR (x, 0), file);
2975   else if (code == 'j')
2976     fputs (cond_string (GET_CODE (x)), file);
2977   else if (code == 'k')
2978     fputs (cond_string (reverse_condition (GET_CODE (x))), file);
2979   else
2980     avr_print_operand_address (file, VOIDmode, x);
2981 }
2982 
2983 
2984 /* Implement TARGET_USE_BY_PIECES_INFRASTRUCTURE_P.  */
2985 
2986 /* Prefer sequence of loads/stores for moves of size upto
2987    two - two pairs of load/store instructions are always better
2988    than the 5 instruction sequence for a loop (1 instruction
2989    for loop counter setup, and 4 for the body of the loop). */
2990 
2991 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)2992 avr_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size,
2993                                     unsigned int align ATTRIBUTE_UNUSED,
2994                                     enum by_pieces_operation op,
2995                                     bool speed_p)
2996 {
2997   if (op != MOVE_BY_PIECES
2998       || (speed_p && size > MOVE_MAX_PIECES))
2999     return default_use_by_pieces_infrastructure_p (size, align, op, speed_p);
3000 
3001   return size <= MOVE_MAX_PIECES;
3002 }
3003 
3004 /* Choose mode for jump insn:
3005    1 - relative jump in range -63 <= x <= 62 ;
3006    2 - relative jump in range -2046 <= x <= 2045 ;
3007    3 - absolute jump (only for ATmega[16]03).  */
3008 
3009 int
avr_jump_mode(rtx x,rtx_insn * insn)3010 avr_jump_mode (rtx x, rtx_insn *insn)
3011 {
3012   int dest_addr = INSN_ADDRESSES (INSN_UID (GET_CODE (x) == LABEL_REF
3013                                             ? XEXP (x, 0) : x));
3014   int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
3015   int jump_distance = cur_addr - dest_addr;
3016 
3017   if (IN_RANGE (jump_distance, -63, 62))
3018     return 1;
3019   else if (IN_RANGE (jump_distance, -2046, 2045))
3020     return 2;
3021   else if (AVR_HAVE_JMP_CALL)
3022     return 3;
3023 
3024   return 2;
3025 }
3026 
3027 /* Return an AVR condition jump commands.
3028    X is a comparison RTX.
3029    LEN is a number returned by avr_jump_mode function.
3030    If REVERSE nonzero then condition code in X must be reversed.  */
3031 
3032 const char*
ret_cond_branch(rtx x,int len,int reverse)3033 ret_cond_branch (rtx x, int len, int reverse)
3034 {
3035   RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
3036   bool cc_overflow_unusable = false;
3037 
3038   switch (cond)
3039     {
3040     case GT:
3041       if (cc_overflow_unusable)
3042 	return (len == 1 ? ("breq .+2" CR_TAB
3043 			    "brpl %0") :
3044 		len == 2 ? ("breq .+4" CR_TAB
3045 			    "brmi .+2" CR_TAB
3046 			    "rjmp %0") :
3047 		("breq .+6" CR_TAB
3048 		 "brmi .+4" CR_TAB
3049 		 "jmp %0"));
3050 
3051       else
3052 	return (len == 1 ? ("breq .+2" CR_TAB
3053 			    "brge %0") :
3054 		len == 2 ? ("breq .+4" CR_TAB
3055 			    "brlt .+2" CR_TAB
3056 			    "rjmp %0") :
3057 		("breq .+6" CR_TAB
3058 		 "brlt .+4" CR_TAB
3059 		 "jmp %0"));
3060     case GTU:
3061       return (len == 1 ? ("breq .+2" CR_TAB
3062                           "brsh %0") :
3063               len == 2 ? ("breq .+4" CR_TAB
3064                           "brlo .+2" CR_TAB
3065                           "rjmp %0") :
3066               ("breq .+6" CR_TAB
3067                "brlo .+4" CR_TAB
3068                "jmp %0"));
3069     case LE:
3070       if (cc_overflow_unusable)
3071 	return (len == 1 ? ("breq %0" CR_TAB
3072 			    "brmi %0") :
3073 		len == 2 ? ("breq .+2" CR_TAB
3074 			    "brpl .+2" CR_TAB
3075 			    "rjmp %0") :
3076 		("breq .+2" CR_TAB
3077 		 "brpl .+4" CR_TAB
3078 		 "jmp %0"));
3079       else
3080 	return (len == 1 ? ("breq %0" CR_TAB
3081 			    "brlt %0") :
3082 		len == 2 ? ("breq .+2" CR_TAB
3083 			    "brge .+2" CR_TAB
3084 			    "rjmp %0") :
3085 		("breq .+2" CR_TAB
3086 		 "brge .+4" CR_TAB
3087 		 "jmp %0"));
3088     case LEU:
3089       return (len == 1 ? ("breq %0" CR_TAB
3090                           "brlo %0") :
3091               len == 2 ? ("breq .+2" CR_TAB
3092                           "brsh .+2" CR_TAB
3093 			  "rjmp %0") :
3094               ("breq .+2" CR_TAB
3095                "brsh .+4" CR_TAB
3096 	       "jmp %0"));
3097     default:
3098       if (reverse)
3099 	{
3100 	  switch (len)
3101 	    {
3102 	    case 1:
3103 	      return "br%k1 %0";
3104 	    case 2:
3105 	      return ("br%j1 .+2" CR_TAB
3106 		      "rjmp %0");
3107 	    default:
3108 	      return ("br%j1 .+4" CR_TAB
3109 		      "jmp %0");
3110 	    }
3111 	}
3112       else
3113         {
3114           switch (len)
3115             {
3116             case 1:
3117               return "br%j1 %0";
3118             case 2:
3119               return ("br%k1 .+2" CR_TAB
3120                       "rjmp %0");
3121             default:
3122               return ("br%k1 .+4" CR_TAB
3123                       "jmp %0");
3124             }
3125         }
3126     }
3127   return "";
3128 }
3129 
3130 
3131 /* Worker function for `FINAL_PRESCAN_INSN'.  */
3132 /* Output insn cost for next insn.  */
3133 
3134 void
avr_final_prescan_insn(rtx_insn * insn,rtx * operand ATTRIBUTE_UNUSED,int num_operands ATTRIBUTE_UNUSED)3135 avr_final_prescan_insn (rtx_insn *insn, rtx *operand ATTRIBUTE_UNUSED,
3136                         int num_operands ATTRIBUTE_UNUSED)
3137 {
3138   if (avr_log.rtx_costs)
3139     {
3140       rtx set = single_set (insn);
3141 
3142       if (set)
3143         fprintf (asm_out_file, "/* DEBUG: cost = %d.  */\n",
3144                  set_src_cost (SET_SRC (set), GET_MODE (SET_DEST (set)),
3145 			       optimize_insn_for_speed_p ()));
3146       else
3147         fprintf (asm_out_file, "/* DEBUG: pattern-cost = %d.  */\n",
3148                  rtx_cost (PATTERN (insn), VOIDmode, INSN, 0,
3149                            optimize_insn_for_speed_p()));
3150     }
3151 
3152   if (avr_log.insn_addresses)
3153     fprintf (asm_out_file, ";; ADDR = %d\n",
3154              (int) INSN_ADDRESSES (INSN_UID (insn)));
3155 }
3156 
3157 
3158 /* Implement `TARGET_ASM_FINAL_POSTSCAN_INSN'.  */
3159 /* When GAS generates (parts of) ISR prologue / epilogue for us, we must
3160    hint GAS about the end of the code to scan.  There migh be code located
3161    after the last epilogue.  */
3162 
3163 static void
avr_asm_final_postscan_insn(FILE * stream,rtx_insn * insn,rtx *,int)3164 avr_asm_final_postscan_insn (FILE *stream, rtx_insn *insn, rtx*, int)
3165 {
3166   if (cfun->machine->gasisr.yes
3167       && !next_real_insn (insn))
3168     {
3169       app_disable();
3170       fprintf (stream, "\t__gcc_isr %d,r%d\n", GASISR_Done,
3171                cfun->machine->gasisr.regno);
3172     }
3173 }
3174 
3175 
3176 /* Return 0 if undefined, 1 if always true or always false.  */
3177 
3178 int
avr_simplify_comparison_p(machine_mode mode,RTX_CODE op,rtx x)3179 avr_simplify_comparison_p (machine_mode mode, RTX_CODE op, rtx x)
3180 {
3181   unsigned int max = (mode == QImode ? 0xff :
3182                       mode == HImode ? 0xffff :
3183                       mode == PSImode ? 0xffffff :
3184                       mode == SImode ? 0xffffffff : 0);
3185   if (max && op && CONST_INT_P (x))
3186     {
3187       if (unsigned_condition (op) != op)
3188         max >>= 1;
3189 
3190       if (max != (INTVAL (x) & max)
3191           && INTVAL (x) != 0xff)
3192         return 1;
3193     }
3194   return 0;
3195 }
3196 
3197 
3198 /* Worker function for `FUNCTION_ARG_REGNO_P'.  */
3199 /* Returns nonzero if REGNO is the number of a hard
3200    register in which function arguments are sometimes passed.  */
3201 
3202 int
avr_function_arg_regno_p(int r)3203 avr_function_arg_regno_p (int r)
3204 {
3205   return AVR_TINY ? IN_RANGE (r, 20, 25) : IN_RANGE (r, 8, 25);
3206 }
3207 
3208 
3209 /* Worker function for `INIT_CUMULATIVE_ARGS'.  */
3210 /* Initializing the variable cum for the state at the beginning
3211    of the argument list.  */
3212 
3213 void
avr_init_cumulative_args(CUMULATIVE_ARGS * cum,tree fntype,rtx libname,tree fndecl ATTRIBUTE_UNUSED)3214 avr_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
3215                           tree fndecl ATTRIBUTE_UNUSED)
3216 {
3217   cum->nregs = AVR_TINY ? 6 : 18;
3218   cum->regno = FIRST_CUM_REG;
3219   if (!libname && stdarg_p (fntype))
3220     cum->nregs = 0;
3221 
3222   /* Assume the calle may be tail called */
3223 
3224   cfun->machine->sibcall_fails = 0;
3225 }
3226 
3227 /* Returns the number of registers to allocate for a function argument.  */
3228 
3229 static int
avr_num_arg_regs(machine_mode mode,const_tree type)3230 avr_num_arg_regs (machine_mode mode, const_tree type)
3231 {
3232   int size;
3233 
3234   if (mode == BLKmode)
3235     size = int_size_in_bytes (type);
3236   else
3237     size = GET_MODE_SIZE (mode);
3238 
3239   /* Align all function arguments to start in even-numbered registers.
3240      Odd-sized arguments leave holes above them.  */
3241 
3242   return (size + 1) & ~1;
3243 }
3244 
3245 
3246 /* Implement `TARGET_FUNCTION_ARG'.  */
3247 /* Controls whether a function argument is passed
3248    in a register, and which register.  */
3249 
3250 static rtx
avr_function_arg(cumulative_args_t cum_v,const function_arg_info & arg)3251 avr_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
3252 {
3253   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
3254   int bytes = avr_num_arg_regs (arg.mode, arg.type);
3255 
3256   if (cum->nregs && bytes <= cum->nregs)
3257     return gen_rtx_REG (arg.mode, cum->regno - bytes);
3258 
3259   return NULL_RTX;
3260 }
3261 
3262 
3263 /* Implement `TARGET_FUNCTION_ARG_ADVANCE'.  */
3264 /* Update the summarizer variable CUM to advance past an argument
3265    in the argument list.  */
3266 
3267 static void
avr_function_arg_advance(cumulative_args_t cum_v,const function_arg_info & arg)3268 avr_function_arg_advance (cumulative_args_t cum_v,
3269 			  const function_arg_info &arg)
3270 {
3271   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
3272   int bytes = avr_num_arg_regs (arg.mode, arg.type);
3273 
3274   cum->nregs -= bytes;
3275   cum->regno -= bytes;
3276 
3277   /* A parameter is being passed in a call-saved register.  As the original
3278      contents of these regs has to be restored before leaving the function,
3279      a function must not pass arguments in call-saved regs in order to get
3280      tail-called.  */
3281 
3282   if (cum->regno >= 8
3283       && cum->nregs >= 0
3284       && !call_used_or_fixed_reg_p (cum->regno))
3285     {
3286       /* FIXME: We ship info on failing tail-call in struct machine_function.
3287          This uses internals of calls.c:expand_call() and the way args_so_far
3288          is used.  targetm.function_ok_for_sibcall() needs to be extended to
3289          pass &args_so_far, too.  At present, CUMULATIVE_ARGS is target
3290          dependent so that such an extension is not wanted.  */
3291 
3292       cfun->machine->sibcall_fails = 1;
3293     }
3294 
3295   /* Test if all registers needed by the ABI are actually available.  If the
3296      user has fixed a GPR needed to pass an argument, an (implicit) function
3297      call will clobber that fixed register.  See PR45099 for an example.  */
3298 
3299   if (cum->regno >= 8
3300       && cum->nregs >= 0)
3301     {
3302       for (int regno = cum->regno; regno < cum->regno + bytes; regno++)
3303         if (fixed_regs[regno])
3304           warning (0, "fixed register %s used to pass parameter to function",
3305                    reg_names[regno]);
3306     }
3307 
3308   if (cum->nregs <= 0)
3309     {
3310       cum->nregs = 0;
3311       cum->regno = FIRST_CUM_REG;
3312     }
3313 }
3314 
3315 /* Implement `TARGET_FUNCTION_OK_FOR_SIBCALL' */
3316 /* Decide whether we can make a sibling call to a function.  DECL is the
3317    declaration of the function being targeted by the call and EXP is the
3318    CALL_EXPR representing the call.  */
3319 
3320 static bool
avr_function_ok_for_sibcall(tree decl_callee,tree exp_callee)3321 avr_function_ok_for_sibcall (tree decl_callee, tree exp_callee)
3322 {
3323   tree fntype_callee;
3324 
3325   /* Tail-calling must fail if callee-saved regs are used to pass
3326      function args.  We must not tail-call when `epilogue_restores'
3327      is used.  Unfortunately, we cannot tell at this point if that
3328      actually will happen or not, and we cannot step back from
3329      tail-calling.  Thus, we inhibit tail-calling with -mcall-prologues.  */
3330 
3331   if (cfun->machine->sibcall_fails
3332       || TARGET_CALL_PROLOGUES)
3333     {
3334       return false;
3335     }
3336 
3337   fntype_callee = TREE_TYPE (CALL_EXPR_FN (exp_callee));
3338 
3339   if (decl_callee)
3340     {
3341       decl_callee = TREE_TYPE (decl_callee);
3342     }
3343   else
3344     {
3345       decl_callee = fntype_callee;
3346 
3347       while (FUNCTION_TYPE != TREE_CODE (decl_callee)
3348              && METHOD_TYPE != TREE_CODE (decl_callee))
3349         {
3350           decl_callee = TREE_TYPE (decl_callee);
3351         }
3352     }
3353 
3354   /* Ensure that caller and callee have compatible epilogues */
3355 
3356   if (cfun->machine->is_interrupt
3357       || cfun->machine->is_signal
3358       || cfun->machine->is_naked
3359       || avr_naked_function_p (decl_callee))
3360     {
3361       return false;
3362     }
3363 
3364   return true;
3365 }
3366 
3367 /***********************************************************************
3368   Functions for outputting various mov's for a various modes
3369 ************************************************************************/
3370 
3371 /* Return true if a value of mode MODE is read from flash by
3372    __load_* function from libgcc.  */
3373 
3374 bool
avr_load_libgcc_p(rtx op)3375 avr_load_libgcc_p (rtx op)
3376 {
3377   machine_mode mode = GET_MODE (op);
3378   int n_bytes = GET_MODE_SIZE (mode);
3379 
3380   return (n_bytes > 2
3381           && !AVR_HAVE_LPMX
3382           && avr_mem_flash_p (op));
3383 }
3384 
3385 /* Return true if a value of mode MODE is read by __xload_* function.  */
3386 
3387 bool
avr_xload_libgcc_p(machine_mode mode)3388 avr_xload_libgcc_p (machine_mode mode)
3389 {
3390   int n_bytes = GET_MODE_SIZE (mode);
3391 
3392   return (n_bytes > 1
3393           || avr_n_flash > 1);
3394 }
3395 
3396 
3397 /* Fixme: This is a hack because secondary reloads don't works as expected.
3398 
3399    Find an unused d-register to be used as scratch in INSN.
3400    EXCLUDE is either NULL_RTX or some register. In the case where EXCLUDE
3401    is a register, skip all possible return values that overlap EXCLUDE.
3402    The policy for the returned register is similar to that of
3403    `reg_unused_after', i.e. the returned register may overlap the SET_DEST
3404    of INSN.
3405 
3406    Return a QImode d-register or NULL_RTX if nothing found.  */
3407 
3408 static rtx
avr_find_unused_d_reg(rtx_insn * insn,rtx exclude)3409 avr_find_unused_d_reg (rtx_insn *insn, rtx exclude)
3410 {
3411   bool isr_p = (avr_interrupt_function_p (current_function_decl)
3412                 || avr_signal_function_p (current_function_decl));
3413 
3414   for (int regno = 16; regno < 32; regno++)
3415     {
3416       rtx reg = all_regs_rtx[regno];
3417 
3418       if ((exclude
3419            && reg_overlap_mentioned_p (exclude, reg))
3420           || fixed_regs[regno])
3421         {
3422           continue;
3423         }
3424 
3425       /* Try non-live register */
3426 
3427       if (!df_regs_ever_live_p (regno)
3428           && (TREE_THIS_VOLATILE (current_function_decl)
3429               || cfun->machine->is_OS_task
3430               || cfun->machine->is_OS_main
3431               || (!isr_p && call_used_or_fixed_reg_p (regno))))
3432         {
3433           return reg;
3434         }
3435 
3436       /* Any live register can be used if it is unused after.
3437          Prologue/epilogue will care for it as needed.  */
3438 
3439       if (df_regs_ever_live_p (regno)
3440           && reg_unused_after (insn, reg))
3441         {
3442           return reg;
3443         }
3444     }
3445 
3446   return NULL_RTX;
3447 }
3448 
3449 
3450 /* Helper function for the next function in the case where only restricted
3451    version of LPM instruction is available.  */
3452 
3453 static const char*
avr_out_lpm_no_lpmx(rtx_insn * insn,rtx * xop,int * plen)3454 avr_out_lpm_no_lpmx (rtx_insn *insn, rtx *xop, int *plen)
3455 {
3456   rtx dest = xop[0];
3457   rtx addr = xop[1];
3458   int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
3459   int regno_dest;
3460 
3461   regno_dest = REGNO (dest);
3462 
3463   /* The implicit target register of LPM.  */
3464   xop[3] = lpm_reg_rtx;
3465 
3466   switch (GET_CODE (addr))
3467     {
3468     default:
3469       gcc_unreachable();
3470 
3471     case REG:
3472 
3473       gcc_assert (REG_Z == REGNO (addr));
3474 
3475       switch (n_bytes)
3476         {
3477         default:
3478           gcc_unreachable();
3479 
3480         case 1:
3481           avr_asm_len ("%4lpm", xop, plen, 1);
3482 
3483           if (regno_dest != LPM_REGNO)
3484             avr_asm_len ("mov %0,%3", xop, plen, 1);
3485 
3486           return "";
3487 
3488         case 2:
3489           if (REGNO (dest) == REG_Z)
3490             return avr_asm_len ("%4lpm"      CR_TAB
3491                                 "push %3"    CR_TAB
3492                                 "adiw %2,1"  CR_TAB
3493                                 "%4lpm"      CR_TAB
3494                                 "mov %B0,%3" CR_TAB
3495                                 "pop %A0", xop, plen, 6);
3496 
3497           avr_asm_len ("%4lpm"      CR_TAB
3498                        "mov %A0,%3" CR_TAB
3499                        "adiw %2,1"  CR_TAB
3500                        "%4lpm"      CR_TAB
3501                        "mov %B0,%3", xop, plen, 5);
3502 
3503           if (!reg_unused_after (insn, addr))
3504             avr_asm_len ("sbiw %2,1", xop, plen, 1);
3505 
3506           break; /* 2 */
3507         }
3508 
3509       break; /* REG */
3510 
3511     case POST_INC:
3512 
3513       gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
3514                   && n_bytes <= 4);
3515 
3516       if (regno_dest == LPM_REGNO)
3517         avr_asm_len ("%4lpm"      CR_TAB
3518                      "adiw %2,1", xop, plen, 2);
3519       else
3520         avr_asm_len ("%4lpm"      CR_TAB
3521                      "mov %A0,%3" CR_TAB
3522                      "adiw %2,1", xop, plen, 3);
3523 
3524       if (n_bytes >= 2)
3525         avr_asm_len ("%4lpm"      CR_TAB
3526                      "mov %B0,%3" CR_TAB
3527                      "adiw %2,1", xop, plen, 3);
3528 
3529       if (n_bytes >= 3)
3530         avr_asm_len ("%4lpm"      CR_TAB
3531                      "mov %C0,%3" CR_TAB
3532                      "adiw %2,1", xop, plen, 3);
3533 
3534       if (n_bytes >= 4)
3535         avr_asm_len ("%4lpm"      CR_TAB
3536                      "mov %D0,%3" CR_TAB
3537                      "adiw %2,1", xop, plen, 3);
3538 
3539       break; /* POST_INC */
3540 
3541     } /* switch CODE (addr) */
3542 
3543   return "";
3544 }
3545 
3546 
3547 /* If PLEN == NULL: Ouput instructions to load a value from a memory location
3548    OP[1] in AS1 to register OP[0].
3549    If PLEN != 0 set *PLEN to the length in words of the instruction sequence.
3550    Return "".  */
3551 
3552 const char*
avr_out_lpm(rtx_insn * insn,rtx * op,int * plen)3553 avr_out_lpm (rtx_insn *insn, rtx *op, int *plen)
3554 {
3555   rtx xop[7];
3556   rtx dest = op[0];
3557   rtx src = SET_SRC (single_set (insn));
3558   rtx addr;
3559   int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
3560   int segment;
3561   RTX_CODE code;
3562   addr_space_t as = MEM_ADDR_SPACE (src);
3563 
3564   if (plen)
3565     *plen = 0;
3566 
3567   if (MEM_P (dest))
3568     {
3569       warning (0, "writing to address space %qs not supported",
3570                avr_addrspace[MEM_ADDR_SPACE (dest)].name);
3571 
3572       return "";
3573     }
3574 
3575   addr = XEXP (src, 0);
3576   code = GET_CODE (addr);
3577 
3578   gcc_assert (REG_P (dest));
3579   gcc_assert (REG == code || POST_INC == code);
3580 
3581   xop[0] = dest;
3582   xop[1] = addr;
3583   xop[2] = lpm_addr_reg_rtx;
3584   xop[4] = xstring_empty;
3585   xop[5] = tmp_reg_rtx;
3586   xop[6] = XEXP (rampz_rtx, 0);
3587 
3588   segment = avr_addrspace[as].segment;
3589 
3590   /* Set RAMPZ as needed.  */
3591 
3592   if (segment)
3593     {
3594       xop[4] = GEN_INT (segment);
3595       xop[3] = avr_find_unused_d_reg (insn, lpm_addr_reg_rtx);
3596 
3597       if (xop[3] != NULL_RTX)
3598         {
3599           avr_asm_len ("ldi %3,%4" CR_TAB
3600                        "out %i6,%3", xop, plen, 2);
3601         }
3602       else if (segment == 1)
3603         {
3604           avr_asm_len ("clr %5" CR_TAB
3605                        "inc %5" CR_TAB
3606                        "out %i6,%5", xop, plen, 3);
3607         }
3608       else
3609         {
3610           avr_asm_len ("mov %5,%2"   CR_TAB
3611                        "ldi %2,%4"   CR_TAB
3612                        "out %i6,%2"  CR_TAB
3613                        "mov %2,%5", xop, plen, 4);
3614         }
3615 
3616       xop[4] = xstring_e;
3617 
3618       if (!AVR_HAVE_ELPMX)
3619         return avr_out_lpm_no_lpmx (insn, xop, plen);
3620     }
3621   else if (!AVR_HAVE_LPMX)
3622     {
3623       return avr_out_lpm_no_lpmx (insn, xop, plen);
3624     }
3625 
3626   /* We have [E]LPMX: Output reading from Flash the comfortable way.  */
3627 
3628   switch (GET_CODE (addr))
3629     {
3630     default:
3631       gcc_unreachable();
3632 
3633     case REG:
3634 
3635       gcc_assert (REG_Z == REGNO (addr));
3636 
3637       switch (n_bytes)
3638         {
3639         default:
3640           gcc_unreachable();
3641 
3642         case 1:
3643           avr_asm_len ("%4lpm %0,%a2", xop, plen, 1);
3644           break;
3645 
3646         case 2:
3647           if (REGNO (dest) == REG_Z)
3648             avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3649                          "%4lpm %B0,%a2" CR_TAB
3650                          "mov %A0,%5", xop, plen, 3);
3651           else
3652             {
3653               avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3654                            "%4lpm %B0,%a2", xop, plen, 2);
3655 
3656               if (!reg_unused_after (insn, addr))
3657                 avr_asm_len ("sbiw %2,1", xop, plen, 1);
3658             }
3659 
3660           break; /* 2 */
3661 
3662         case 3:
3663 
3664           avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3665                        "%4lpm %B0,%a2+" CR_TAB
3666                        "%4lpm %C0,%a2", xop, plen, 3);
3667 
3668           if (!reg_unused_after (insn, addr))
3669             avr_asm_len ("sbiw %2,2", xop, plen, 1);
3670 
3671           break; /* 3 */
3672 
3673         case 4:
3674 
3675           avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3676                        "%4lpm %B0,%a2+", xop, plen, 2);
3677 
3678           if (REGNO (dest) == REG_Z - 2)
3679             avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3680                          "%4lpm %C0,%a2" CR_TAB
3681                          "mov %D0,%5", xop, plen, 3);
3682           else
3683             {
3684               avr_asm_len ("%4lpm %C0,%a2+" CR_TAB
3685                            "%4lpm %D0,%a2", xop, plen, 2);
3686 
3687               if (!reg_unused_after (insn, addr))
3688                 avr_asm_len ("sbiw %2,3", xop, plen, 1);
3689             }
3690 
3691           break; /* 4 */
3692         } /* n_bytes */
3693 
3694       break; /* REG */
3695 
3696     case POST_INC:
3697 
3698       gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
3699                   && n_bytes <= 4);
3700 
3701       avr_asm_len                    ("%4lpm %A0,%a2+", xop, plen, 1);
3702       if (n_bytes >= 2)  avr_asm_len ("%4lpm %B0,%a2+", xop, plen, 1);
3703       if (n_bytes >= 3)  avr_asm_len ("%4lpm %C0,%a2+", xop, plen, 1);
3704       if (n_bytes >= 4)  avr_asm_len ("%4lpm %D0,%a2+", xop, plen, 1);
3705 
3706       break; /* POST_INC */
3707 
3708     } /* switch CODE (addr) */
3709 
3710   if (xop[4] == xstring_e && AVR_HAVE_RAMPD)
3711     {
3712       /* Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM.  */
3713 
3714       xop[0] = zero_reg_rtx;
3715       avr_asm_len ("out %i6,%0", xop, plen, 1);
3716     }
3717 
3718   return "";
3719 }
3720 
3721 
3722 /* Worker function for xload_8 insn.  */
3723 
3724 const char*
avr_out_xload(rtx_insn * insn ATTRIBUTE_UNUSED,rtx * op,int * plen)3725 avr_out_xload (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
3726 {
3727   rtx xop[4];
3728 
3729   xop[0] = op[0];
3730   xop[1] = op[1];
3731   xop[2] = lpm_addr_reg_rtx;
3732   xop[3] = AVR_HAVE_LPMX ? op[0] : lpm_reg_rtx;
3733 
3734   avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, -1);
3735 
3736   avr_asm_len ("sbrc %1,7" CR_TAB
3737                "ld %3,%a2", xop, plen, 2);
3738 
3739   if (REGNO (xop[0]) != REGNO (xop[3]))
3740     avr_asm_len ("mov %0,%3", xop, plen, 1);
3741 
3742   return "";
3743 }
3744 
3745 
3746 const char*
output_movqi(rtx_insn * insn,rtx operands[],int * plen)3747 output_movqi (rtx_insn *insn, rtx operands[], int *plen)
3748 {
3749   rtx dest = operands[0];
3750   rtx src = operands[1];
3751 
3752   if (avr_mem_flash_p (src)
3753       || avr_mem_flash_p (dest))
3754     {
3755       return avr_out_lpm (insn, operands, plen);
3756     }
3757 
3758   gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 1);
3759 
3760   if (REG_P (dest))
3761     {
3762       if (REG_P (src)) /* mov r,r */
3763         {
3764           if (test_hard_reg_class (STACK_REG, dest))
3765             return avr_asm_len ("out %0,%1", operands, plen, -1);
3766           else if (test_hard_reg_class (STACK_REG, src))
3767             return avr_asm_len ("in %0,%1", operands, plen, -1);
3768 
3769           return avr_asm_len ("mov %0,%1", operands, plen, -1);
3770         }
3771       else if (CONSTANT_P (src))
3772         {
3773           output_reload_in_const (operands, NULL_RTX, plen, false);
3774           return "";
3775         }
3776       else if (MEM_P (src))
3777         return out_movqi_r_mr (insn, operands, plen); /* mov r,m */
3778     }
3779   else if (MEM_P (dest))
3780     {
3781       rtx xop[2];
3782 
3783       xop[0] = dest;
3784       xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
3785 
3786       return out_movqi_mr_r (insn, xop, plen);
3787     }
3788 
3789   return "";
3790 }
3791 
3792 
3793 const char *
output_movhi(rtx_insn * insn,rtx xop[],int * plen)3794 output_movhi (rtx_insn *insn, rtx xop[], int *plen)
3795 {
3796   rtx dest = xop[0];
3797   rtx src = xop[1];
3798 
3799   gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 2);
3800 
3801   if (avr_mem_flash_p (src)
3802       || avr_mem_flash_p (dest))
3803     {
3804       return avr_out_lpm (insn, xop, plen);
3805     }
3806 
3807   if (REG_P (dest))
3808     {
3809       if (REG_P (src)) /* mov r,r */
3810         {
3811           if (test_hard_reg_class (STACK_REG, dest))
3812             {
3813               if (AVR_HAVE_8BIT_SP)
3814                 return avr_asm_len ("out __SP_L__,%A1", xop, plen, -1);
3815 
3816               if (AVR_XMEGA)
3817                 return avr_asm_len ("out __SP_L__,%A1" CR_TAB
3818                                     "out __SP_H__,%B1", xop, plen, -2);
3819 
3820               /* Use simple load of SP if no interrupts are  used.  */
3821 
3822               return TARGET_NO_INTERRUPTS
3823                 ? avr_asm_len ("out __SP_H__,%B1" CR_TAB
3824                                "out __SP_L__,%A1", xop, plen, -2)
3825                 : avr_asm_len ("in __tmp_reg__,__SREG__"  CR_TAB
3826                                "cli"                      CR_TAB
3827                                "out __SP_H__,%B1"         CR_TAB
3828                                "out __SREG__,__tmp_reg__" CR_TAB
3829                                "out __SP_L__,%A1", xop, plen, -5);
3830             }
3831           else if (test_hard_reg_class (STACK_REG, src))
3832             {
3833               return !AVR_HAVE_SPH
3834                 ? avr_asm_len ("in %A0,__SP_L__" CR_TAB
3835                                "clr %B0", xop, plen, -2)
3836 
3837                 : avr_asm_len ("in %A0,__SP_L__" CR_TAB
3838                                "in %B0,__SP_H__", xop, plen, -2);
3839             }
3840 
3841           return AVR_HAVE_MOVW
3842             ? avr_asm_len ("movw %0,%1", xop, plen, -1)
3843 
3844             : avr_asm_len ("mov %A0,%A1" CR_TAB
3845                            "mov %B0,%B1", xop, plen, -2);
3846         } /* REG_P (src) */
3847       else if (CONSTANT_P (src))
3848         {
3849           return output_reload_inhi (xop, NULL, plen);
3850         }
3851       else if (MEM_P (src))
3852         {
3853           return out_movhi_r_mr (insn, xop, plen); /* mov r,m */
3854         }
3855     }
3856   else if (MEM_P (dest))
3857     {
3858       rtx xop[2];
3859 
3860       xop[0] = dest;
3861       xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
3862 
3863       return out_movhi_mr_r (insn, xop, plen);
3864     }
3865 
3866   fatal_insn ("invalid insn:", insn);
3867 
3868   return "";
3869 }
3870 
3871 
3872 /* Same as out_movqi_r_mr, but TINY does not have ADIW or SBIW */
3873 
3874 static const char*
avr_out_movqi_r_mr_reg_disp_tiny(rtx_insn * insn,rtx op[],int * plen)3875 avr_out_movqi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
3876 {
3877   rtx dest = op[0];
3878   rtx src = op[1];
3879   rtx x = XEXP (src, 0);
3880 
3881   avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
3882                "ld %0,%b1" , op, plen, -3);
3883 
3884   if (!reg_overlap_mentioned_p (dest, XEXP (x, 0))
3885       && !reg_unused_after (insn, XEXP (x, 0)))
3886     avr_asm_len (TINY_SBIW (%I1, %J1, %o1), op, plen, 2);
3887 
3888   return "";
3889 }
3890 
3891 static const char*
out_movqi_r_mr(rtx_insn * insn,rtx op[],int * plen)3892 out_movqi_r_mr (rtx_insn *insn, rtx op[], int *plen)
3893 {
3894   rtx dest = op[0];
3895   rtx src = op[1];
3896   rtx x = XEXP (src, 0);
3897 
3898   if (CONSTANT_ADDRESS_P (x))
3899     {
3900       int n_words = AVR_TINY ? 1 : 2;
3901       return io_address_operand (x, QImode)
3902         ? avr_asm_len ("in %0,%i1", op, plen, -1)
3903         : avr_asm_len ("lds %0,%m1", op, plen, -n_words);
3904     }
3905 
3906   if (GET_CODE (x) == PLUS
3907       && REG_P (XEXP (x, 0))
3908       && CONST_INT_P (XEXP (x, 1)))
3909     {
3910       /* memory access by reg+disp */
3911 
3912       int disp = INTVAL (XEXP (x, 1));
3913 
3914       if (AVR_TINY)
3915         return avr_out_movqi_r_mr_reg_disp_tiny (insn, op, plen);
3916 
3917       if (disp - GET_MODE_SIZE (GET_MODE (src)) >= 63)
3918         {
3919           if (REGNO (XEXP (x, 0)) != REG_Y)
3920             fatal_insn ("incorrect insn:",insn);
3921 
3922           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
3923             return avr_asm_len ("adiw r28,%o1-63" CR_TAB
3924                                 "ldd %0,Y+63"     CR_TAB
3925                                 "sbiw r28,%o1-63", op, plen, -3);
3926 
3927           return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
3928                               "sbci r29,hi8(-%o1)" CR_TAB
3929                               "ld %0,Y"            CR_TAB
3930                               "subi r28,lo8(%o1)"  CR_TAB
3931                               "sbci r29,hi8(%o1)", op, plen, -5);
3932         }
3933       else if (REGNO (XEXP (x, 0)) == REG_X)
3934         {
3935           /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
3936              it but I have this situation with extremal optimizing options.  */
3937 
3938           avr_asm_len ("adiw r26,%o1" CR_TAB
3939                        "ld %0,X", op, plen, -2);
3940 
3941           if (!reg_overlap_mentioned_p (dest, XEXP (x, 0))
3942               && !reg_unused_after (insn, XEXP (x, 0)))
3943             {
3944               avr_asm_len ("sbiw r26,%o1", op, plen, 1);
3945             }
3946 
3947           return "";
3948         }
3949 
3950       return avr_asm_len ("ldd %0,%1", op, plen, -1);
3951     }
3952 
3953   return avr_asm_len ("ld %0,%1", op, plen, -1);
3954 }
3955 
3956 
3957 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
3958 
3959 static const char*
avr_out_movhi_r_mr_reg_no_disp_tiny(rtx_insn * insn,rtx op[],int * plen)3960 avr_out_movhi_r_mr_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
3961 {
3962   rtx dest = op[0];
3963   rtx src = op[1];
3964   rtx base = XEXP (src, 0);
3965 
3966   int reg_dest = true_regnum (dest);
3967   int reg_base = true_regnum (base);
3968 
3969   if (reg_dest == reg_base)         /* R = (R) */
3970     return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
3971 			"ld %B0,%1"          CR_TAB
3972 			"mov %A0,__tmp_reg__", op, plen, -3);
3973 
3974   avr_asm_len ("ld %A0,%1+" CR_TAB
3975                "ld %B0,%1", op, plen, -2);
3976 
3977   if (!reg_unused_after (insn, base))
3978     avr_asm_len (TINY_SBIW (%E1, %F1, 1), op, plen, 2);
3979 
3980   return "";
3981 }
3982 
3983 
3984 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
3985 
3986 static const char*
avr_out_movhi_r_mr_reg_disp_tiny(rtx_insn * insn,rtx op[],int * plen)3987 avr_out_movhi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
3988 {
3989   rtx dest = op[0];
3990   rtx src = op[1];
3991   rtx base = XEXP (src, 0);
3992 
3993   int reg_dest = true_regnum (dest);
3994   int reg_base = true_regnum (XEXP (base, 0));
3995 
3996   if (reg_base == reg_dest)
3997     {
3998       return avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
3999                           "ld __tmp_reg__,%b1+"     CR_TAB
4000                           "ld %B0,%b1"              CR_TAB
4001                           "mov %A0,__tmp_reg__", op, plen, -5);
4002     }
4003   else
4004     {
4005       avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4006                    "ld %A0,%b1+"             CR_TAB
4007                    "ld %B0,%b1", op, plen, -4);
4008 
4009       if (!reg_unused_after (insn, XEXP (base, 0)))
4010         avr_asm_len (TINY_SBIW (%I1, %J1, %o1+1), op, plen, 2);
4011 
4012       return "";
4013     }
4014 }
4015 
4016 
4017 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
4018 
4019 static const char*
avr_out_movhi_r_mr_pre_dec_tiny(rtx_insn * insn,rtx op[],int * plen)4020 avr_out_movhi_r_mr_pre_dec_tiny (rtx_insn *insn, rtx op[], int *plen)
4021 {
4022   int mem_volatile_p = 0;
4023   rtx dest = op[0];
4024   rtx src = op[1];
4025   rtx base = XEXP (src, 0);
4026 
4027   /* "volatile" forces reading low byte first, even if less efficient,
4028      for correct operation with 16-bit I/O registers.  */
4029   mem_volatile_p = MEM_VOLATILE_P (src);
4030 
4031   if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
4032     fatal_insn ("incorrect insn:", insn);
4033 
4034   if (!mem_volatile_p)
4035     return avr_asm_len ("ld %B0,%1" CR_TAB
4036                         "ld %A0,%1", op, plen, -2);
4037 
4038   return avr_asm_len (TINY_SBIW (%I1, %J1, 2)  CR_TAB
4039                       "ld %A0,%p1+"            CR_TAB
4040                       "ld %B0,%p1"             CR_TAB
4041                       TINY_SBIW (%I1, %J1, 1), op, plen, -6);
4042 }
4043 
4044 
4045 static const char*
out_movhi_r_mr(rtx_insn * insn,rtx op[],int * plen)4046 out_movhi_r_mr (rtx_insn *insn, rtx op[], int *plen)
4047 {
4048   rtx dest = op[0];
4049   rtx src = op[1];
4050   rtx base = XEXP (src, 0);
4051   int reg_dest = true_regnum (dest);
4052   int reg_base = true_regnum (base);
4053   /* "volatile" forces reading low byte first, even if less efficient,
4054      for correct operation with 16-bit I/O registers.  */
4055   int mem_volatile_p = MEM_VOLATILE_P (src);
4056 
4057   if (reg_base > 0)
4058     {
4059       if (AVR_TINY)
4060         return avr_out_movhi_r_mr_reg_no_disp_tiny (insn, op, plen);
4061 
4062       if (reg_dest == reg_base)         /* R = (R) */
4063         return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
4064                             "ld %B0,%1"          CR_TAB
4065                             "mov %A0,__tmp_reg__", op, plen, -3);
4066 
4067       if (reg_base != REG_X)
4068         return avr_asm_len ("ld %A0,%1" CR_TAB
4069                             "ldd %B0,%1+1", op, plen, -2);
4070 
4071       avr_asm_len ("ld %A0,X+" CR_TAB
4072                    "ld %B0,X", op, plen, -2);
4073 
4074       if (!reg_unused_after (insn, base))
4075         avr_asm_len ("sbiw r26,1", op, plen, 1);
4076 
4077       return "";
4078     }
4079   else if (GET_CODE (base) == PLUS) /* (R + i) */
4080     {
4081       int disp = INTVAL (XEXP (base, 1));
4082       int reg_base = true_regnum (XEXP (base, 0));
4083 
4084       if (AVR_TINY)
4085         return avr_out_movhi_r_mr_reg_disp_tiny (insn, op, plen);
4086 
4087       if (disp > MAX_LD_OFFSET (GET_MODE (src)))
4088         {
4089           if (REGNO (XEXP (base, 0)) != REG_Y)
4090             fatal_insn ("incorrect insn:",insn);
4091 
4092           return disp <= 63 + MAX_LD_OFFSET (GET_MODE (src))
4093             ? avr_asm_len ("adiw r28,%o1-62" CR_TAB
4094                            "ldd %A0,Y+62"    CR_TAB
4095                            "ldd %B0,Y+63"    CR_TAB
4096                            "sbiw r28,%o1-62", op, plen, -4)
4097 
4098             : avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
4099                            "sbci r29,hi8(-%o1)" CR_TAB
4100                            "ld %A0,Y"           CR_TAB
4101                            "ldd %B0,Y+1"        CR_TAB
4102                            "subi r28,lo8(%o1)"  CR_TAB
4103                            "sbci r29,hi8(%o1)", op, plen, -6);
4104         }
4105 
4106       /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
4107          it but I have this situation with extremal
4108          optimization options.  */
4109 
4110       if (reg_base == REG_X)
4111         {
4112           if (reg_base == reg_dest)
4113             return avr_asm_len ("adiw r26,%o1"      CR_TAB
4114                                 "ld __tmp_reg__,X+" CR_TAB
4115                                 "ld %B0,X"          CR_TAB
4116                                 "mov %A0,__tmp_reg__", op, plen, -4);
4117 
4118           avr_asm_len ("adiw r26,%o1" CR_TAB
4119                        "ld %A0,X+"    CR_TAB
4120                        "ld %B0,X", op, plen, -3);
4121 
4122           if (!reg_unused_after (insn, XEXP (base, 0)))
4123             avr_asm_len ("sbiw r26,%o1+1", op, plen, 1);
4124 
4125           return "";
4126         }
4127 
4128       return reg_base == reg_dest
4129         ? avr_asm_len ("ldd __tmp_reg__,%A1" CR_TAB
4130                        "ldd %B0,%B1"         CR_TAB
4131                        "mov %A0,__tmp_reg__", op, plen, -3)
4132 
4133         : avr_asm_len ("ldd %A0,%A1" CR_TAB
4134                        "ldd %B0,%B1", op, plen, -2);
4135     }
4136   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4137     {
4138       if (AVR_TINY)
4139 	return avr_out_movhi_r_mr_pre_dec_tiny (insn, op, plen);
4140 
4141       if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
4142         fatal_insn ("incorrect insn:", insn);
4143 
4144       if (!mem_volatile_p)
4145         return avr_asm_len ("ld %B0,%1" CR_TAB
4146                             "ld %A0,%1", op, plen, -2);
4147 
4148       return REGNO (XEXP (base, 0)) == REG_X
4149         ? avr_asm_len ("sbiw r26,2"  CR_TAB
4150                        "ld %A0,X+"   CR_TAB
4151                        "ld %B0,X"    CR_TAB
4152                        "sbiw r26,1", op, plen, -4)
4153 
4154         : avr_asm_len ("sbiw %r1,2"  CR_TAB
4155                        "ld %A0,%p1"  CR_TAB
4156                        "ldd %B0,%p1+1", op, plen, -3);
4157     }
4158   else if (GET_CODE (base) == POST_INC) /* (R++) */
4159     {
4160       if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
4161         fatal_insn ("incorrect insn:", insn);
4162 
4163       return avr_asm_len ("ld %A0,%1"  CR_TAB
4164                           "ld %B0,%1", op, plen, -2);
4165     }
4166   else if (CONSTANT_ADDRESS_P (base))
4167     {
4168       int n_words = AVR_TINY ? 2 : 4;
4169       return io_address_operand (base, HImode)
4170         ? avr_asm_len ("in %A0,%i1" CR_TAB
4171                        "in %B0,%i1+1", op, plen, -2)
4172 
4173         : avr_asm_len ("lds %A0,%m1" CR_TAB
4174                        "lds %B0,%m1+1", op, plen, -n_words);
4175     }
4176 
4177   fatal_insn ("unknown move insn:",insn);
4178   return "";
4179 }
4180 
4181 static const char*
avr_out_movsi_r_mr_reg_no_disp_tiny(rtx_insn * insn,rtx op[],int * l)4182 avr_out_movsi_r_mr_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *l)
4183 {
4184   rtx dest = op[0];
4185   rtx src = op[1];
4186   rtx base = XEXP (src, 0);
4187   int reg_dest = true_regnum (dest);
4188   int reg_base = true_regnum (base);
4189 
4190   if (reg_dest == reg_base)
4191     {
4192       /* "ld r26,-X" is undefined */
4193       return *l = 9, (TINY_ADIW (%E1, %F1, 3) CR_TAB
4194 		      "ld %D0,%1"             CR_TAB
4195 		      "ld %C0,-%1"            CR_TAB
4196 		      "ld __tmp_reg__,-%1"    CR_TAB
4197 		      TINY_SBIW (%E1, %F1, 1) CR_TAB
4198 		      "ld %A0,%1"             CR_TAB
4199 		      "mov %B0,__tmp_reg__");
4200     }
4201   else if (reg_dest == reg_base - 2)
4202     {
4203       return *l = 5, ("ld %A0,%1+"            CR_TAB
4204 		      "ld %B0,%1+"            CR_TAB
4205 		      "ld __tmp_reg__,%1+"    CR_TAB
4206 		      "ld %D0,%1"             CR_TAB
4207 		      "mov %C0,__tmp_reg__");
4208     }
4209   else if (reg_unused_after (insn, base))
4210     {
4211       return *l = 4, ("ld %A0,%1+"    CR_TAB
4212 		      "ld %B0,%1+"    CR_TAB
4213 		      "ld %C0,%1+"    CR_TAB
4214 		      "ld %D0,%1");
4215     }
4216   else
4217     {
4218       return *l = 6, ("ld %A0,%1+"    CR_TAB
4219 		      "ld %B0,%1+"    CR_TAB
4220 		      "ld %C0,%1+"    CR_TAB
4221 		      "ld %D0,%1"     CR_TAB
4222 		      TINY_SBIW (%E1, %F1, 3));
4223     }
4224 }
4225 
4226 
4227 static const char*
avr_out_movsi_r_mr_reg_disp_tiny(rtx_insn * insn,rtx op[],int * l)4228 avr_out_movsi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *l)
4229 {
4230   rtx dest = op[0];
4231   rtx src = op[1];
4232   rtx base = XEXP (src, 0);
4233   int reg_dest = true_regnum (dest);
4234   int reg_base = true_regnum (XEXP (base, 0));
4235 
4236   if (reg_dest == reg_base)
4237     {
4238       /* "ld r26,-X" is undefined */
4239       return *l = 9, (TINY_ADIW (%I1, %J1, %o1+3) CR_TAB
4240                       "ld %D0,%b1"                CR_TAB
4241                       "ld %C0,-%b1"               CR_TAB
4242                       "ld __tmp_reg__,-%b1"       CR_TAB
4243                       TINY_SBIW (%I1, %J1, 1)     CR_TAB
4244                       "ld %A0,%b1"                CR_TAB
4245                       "mov %B0,__tmp_reg__");
4246     }
4247   else if (reg_dest == reg_base - 2)
4248     {
4249       return *l = 7, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4250                       "ld %A0,%b1+"             CR_TAB
4251                       "ld %B0,%b1+"             CR_TAB
4252                       "ld __tmp_reg__,%b1+"     CR_TAB
4253                       "ld %D0,%b1"              CR_TAB
4254                       "mov %C0,__tmp_reg__");
4255     }
4256   else if (reg_unused_after (insn, XEXP (base, 0)))
4257     {
4258       return *l = 6, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4259                       "ld %A0,%b1+"             CR_TAB
4260                       "ld %B0,%b1+"             CR_TAB
4261                       "ld %C0,%b1+"             CR_TAB
4262                       "ld %D0,%b1");
4263     }
4264   else
4265     {
4266       return *l = 8, (TINY_ADIW (%I1, %J1, %o1)  CR_TAB
4267                       "ld %A0,%b1+"              CR_TAB
4268                       "ld %B0,%b1+"              CR_TAB
4269                       "ld %C0,%b1+"              CR_TAB
4270                       "ld %D0,%b1"               CR_TAB
4271                       TINY_SBIW (%I1, %J1, %o1+3));
4272     }
4273 }
4274 
4275 static const char*
out_movsi_r_mr(rtx_insn * insn,rtx op[],int * l)4276 out_movsi_r_mr (rtx_insn *insn, rtx op[], int *l)
4277 {
4278   rtx dest = op[0];
4279   rtx src = op[1];
4280   rtx base = XEXP (src, 0);
4281   int reg_dest = true_regnum (dest);
4282   int reg_base = true_regnum (base);
4283   int tmp;
4284 
4285   if (!l)
4286     l = &tmp;
4287 
4288   if (reg_base > 0)
4289     {
4290       if (AVR_TINY)
4291         return avr_out_movsi_r_mr_reg_no_disp_tiny (insn, op, l);
4292 
4293       if (reg_base == REG_X)        /* (R26) */
4294         {
4295           if (reg_dest == REG_X)
4296 	    /* "ld r26,-X" is undefined */
4297 	    return *l=7, ("adiw r26,3"        CR_TAB
4298 			  "ld r29,X"          CR_TAB
4299 			  "ld r28,-X"         CR_TAB
4300 			  "ld __tmp_reg__,-X" CR_TAB
4301 			  "sbiw r26,1"        CR_TAB
4302 			  "ld r26,X"          CR_TAB
4303 			  "mov r27,__tmp_reg__");
4304           else if (reg_dest == REG_X - 2)
4305             return *l=5, ("ld %A0,X+"          CR_TAB
4306                           "ld %B0,X+"          CR_TAB
4307                           "ld __tmp_reg__,X+"  CR_TAB
4308                           "ld %D0,X"           CR_TAB
4309                           "mov %C0,__tmp_reg__");
4310           else if (reg_unused_after (insn, base))
4311             return  *l=4, ("ld %A0,X+" CR_TAB
4312                            "ld %B0,X+" CR_TAB
4313                            "ld %C0,X+" CR_TAB
4314                            "ld %D0,X");
4315           else
4316             return  *l=5, ("ld %A0,X+" CR_TAB
4317                            "ld %B0,X+" CR_TAB
4318                            "ld %C0,X+" CR_TAB
4319                            "ld %D0,X"  CR_TAB
4320                            "sbiw r26,3");
4321         }
4322       else
4323         {
4324           if (reg_dest == reg_base)
4325             return *l=5, ("ldd %D0,%1+3" CR_TAB
4326                           "ldd %C0,%1+2" CR_TAB
4327                           "ldd __tmp_reg__,%1+1"  CR_TAB
4328                           "ld %A0,%1"  CR_TAB
4329                           "mov %B0,__tmp_reg__");
4330           else if (reg_base == reg_dest + 2)
4331             return *l=5, ("ld %A0,%1"             CR_TAB
4332                           "ldd %B0,%1+1"          CR_TAB
4333                           "ldd __tmp_reg__,%1+2"  CR_TAB
4334                           "ldd %D0,%1+3"          CR_TAB
4335                           "mov %C0,__tmp_reg__");
4336           else
4337             return *l=4, ("ld %A0,%1"    CR_TAB
4338                           "ldd %B0,%1+1" CR_TAB
4339                           "ldd %C0,%1+2" CR_TAB
4340                           "ldd %D0,%1+3");
4341         }
4342     }
4343   else if (GET_CODE (base) == PLUS) /* (R + i) */
4344     {
4345       int disp = INTVAL (XEXP (base, 1));
4346 
4347       if (AVR_TINY)
4348         return avr_out_movsi_r_mr_reg_disp_tiny (insn, op, l);
4349 
4350       if (disp > MAX_LD_OFFSET (GET_MODE (src)))
4351 	{
4352 	  if (REGNO (XEXP (base, 0)) != REG_Y)
4353 	    fatal_insn ("incorrect insn:",insn);
4354 
4355 	  if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
4356 	    return *l = 6, ("adiw r28,%o1-60" CR_TAB
4357 			    "ldd %A0,Y+60"    CR_TAB
4358 			    "ldd %B0,Y+61"    CR_TAB
4359 			    "ldd %C0,Y+62"    CR_TAB
4360 			    "ldd %D0,Y+63"    CR_TAB
4361 			    "sbiw r28,%o1-60");
4362 
4363 	  return *l = 8, ("subi r28,lo8(-%o1)" CR_TAB
4364 			  "sbci r29,hi8(-%o1)" CR_TAB
4365 			  "ld %A0,Y"           CR_TAB
4366 			  "ldd %B0,Y+1"        CR_TAB
4367 			  "ldd %C0,Y+2"        CR_TAB
4368 			  "ldd %D0,Y+3"        CR_TAB
4369 			  "subi r28,lo8(%o1)"  CR_TAB
4370 			  "sbci r29,hi8(%o1)");
4371 	}
4372 
4373       reg_base = true_regnum (XEXP (base, 0));
4374       if (reg_base == REG_X)
4375 	{
4376 	  /* R = (X + d) */
4377 	  if (reg_dest == REG_X)
4378 	    {
4379 	      *l = 7;
4380 	      /* "ld r26,-X" is undefined */
4381 	      return ("adiw r26,%o1+3"    CR_TAB
4382 		      "ld r29,X"          CR_TAB
4383 		      "ld r28,-X"         CR_TAB
4384 		      "ld __tmp_reg__,-X" CR_TAB
4385 		      "sbiw r26,1"        CR_TAB
4386 		      "ld r26,X"          CR_TAB
4387 		      "mov r27,__tmp_reg__");
4388 	    }
4389 	  *l = 6;
4390 	  if (reg_dest == REG_X - 2)
4391 	    return ("adiw r26,%o1"      CR_TAB
4392 		    "ld r24,X+"         CR_TAB
4393 		    "ld r25,X+"         CR_TAB
4394 		    "ld __tmp_reg__,X+" CR_TAB
4395 		    "ld r27,X"          CR_TAB
4396 		    "mov r26,__tmp_reg__");
4397 
4398 	  return ("adiw r26,%o1" CR_TAB
4399 		  "ld %A0,X+"    CR_TAB
4400 		  "ld %B0,X+"    CR_TAB
4401 		  "ld %C0,X+"    CR_TAB
4402 		  "ld %D0,X"     CR_TAB
4403 		  "sbiw r26,%o1+3");
4404 	}
4405       if (reg_dest == reg_base)
4406         return *l=5, ("ldd %D0,%D1"          CR_TAB
4407                       "ldd %C0,%C1"          CR_TAB
4408                       "ldd __tmp_reg__,%B1"  CR_TAB
4409                       "ldd %A0,%A1"          CR_TAB
4410                       "mov %B0,__tmp_reg__");
4411       else if (reg_dest == reg_base - 2)
4412         return *l=5, ("ldd %A0,%A1"          CR_TAB
4413                       "ldd %B0,%B1"          CR_TAB
4414                       "ldd __tmp_reg__,%C1"  CR_TAB
4415                       "ldd %D0,%D1"          CR_TAB
4416                       "mov %C0,__tmp_reg__");
4417       return *l=4, ("ldd %A0,%A1" CR_TAB
4418                     "ldd %B0,%B1" CR_TAB
4419                     "ldd %C0,%C1" CR_TAB
4420                     "ldd %D0,%D1");
4421     }
4422   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4423     return *l=4, ("ld %D0,%1" CR_TAB
4424 		  "ld %C0,%1" CR_TAB
4425 		  "ld %B0,%1" CR_TAB
4426 		  "ld %A0,%1");
4427   else if (GET_CODE (base) == POST_INC) /* (R++) */
4428     return *l=4, ("ld %A0,%1" CR_TAB
4429 		  "ld %B0,%1" CR_TAB
4430 		  "ld %C0,%1" CR_TAB
4431 		  "ld %D0,%1");
4432   else if (CONSTANT_ADDRESS_P (base))
4433     {
4434       if (io_address_operand (base, SImode))
4435         {
4436           *l = 4;
4437           return ("in %A0,%i1"   CR_TAB
4438                   "in %B0,%i1+1" CR_TAB
4439                   "in %C0,%i1+2" CR_TAB
4440                   "in %D0,%i1+3");
4441         }
4442       else
4443         {
4444           *l = AVR_TINY ? 4 : 8;
4445           return ("lds %A0,%m1"   CR_TAB
4446                   "lds %B0,%m1+1" CR_TAB
4447                   "lds %C0,%m1+2" CR_TAB
4448                   "lds %D0,%m1+3");
4449         }
4450     }
4451 
4452   fatal_insn ("unknown move insn:",insn);
4453   return "";
4454 }
4455 
4456 static const char*
avr_out_movsi_mr_r_reg_no_disp_tiny(rtx_insn * insn,rtx op[],int * l)4457 avr_out_movsi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *l)
4458 {
4459   rtx dest = op[0];
4460   rtx src = op[1];
4461   rtx base = XEXP (dest, 0);
4462   int reg_base = true_regnum (base);
4463   int reg_src = true_regnum (src);
4464 
4465   if (reg_base == reg_src)
4466     {
4467       /* "ld r26,-X" is undefined */
4468       if (reg_unused_after (insn, base))
4469         {
4470           return *l = 7, ("mov __tmp_reg__, %B1"  CR_TAB
4471 			  "st %0,%A1"             CR_TAB
4472 			  TINY_ADIW (%E0, %F0, 1) CR_TAB
4473 			  "st %0+,__tmp_reg__"    CR_TAB
4474 			  "st %0+,%C1"            CR_TAB
4475 			  "st %0+,%D1");
4476         }
4477       else
4478         {
4479           return *l = 9, ("mov __tmp_reg__, %B1"  CR_TAB
4480 			  "st %0,%A1"             CR_TAB
4481 			  TINY_ADIW (%E0, %F0, 1) CR_TAB
4482 			  "st %0+,__tmp_reg__"    CR_TAB
4483 			  "st %0+,%C1"            CR_TAB
4484 			  "st %0+,%D1"            CR_TAB
4485 			  TINY_SBIW (%E0, %F0, 3));
4486         }
4487     }
4488   else if (reg_base == reg_src + 2)
4489     {
4490       if (reg_unused_after (insn, base))
4491 	return *l = 7, ("mov __zero_reg__,%C1" CR_TAB
4492                         "mov __tmp_reg__,%D1"  CR_TAB
4493                         "st %0+,%A1"           CR_TAB
4494                         "st %0+,%B1"           CR_TAB
4495                         "st %0+,__zero_reg__"  CR_TAB
4496                         "st %0,__tmp_reg__"    CR_TAB
4497                         "clr __zero_reg__");
4498       else
4499 	return *l = 9, ("mov __zero_reg__,%C1" CR_TAB
4500 			"mov __tmp_reg__,%D1"  CR_TAB
4501 			"st %0+,%A1"           CR_TAB
4502 			"st %0+,%B1"           CR_TAB
4503 			"st %0+,__zero_reg__"  CR_TAB
4504 			"st %0,__tmp_reg__"    CR_TAB
4505 			"clr __zero_reg__"     CR_TAB
4506 			TINY_SBIW (%E0, %F0, 3));
4507     }
4508 
4509   return *l = 6, ("st %0+,%A1" CR_TAB
4510 		  "st %0+,%B1" CR_TAB
4511 		  "st %0+,%C1" CR_TAB
4512 		  "st %0,%D1"  CR_TAB
4513 		  TINY_SBIW (%E0, %F0, 3));
4514 }
4515 
4516 static const char*
avr_out_movsi_mr_r_reg_disp_tiny(rtx op[],int * l)4517 avr_out_movsi_mr_r_reg_disp_tiny (rtx op[], int *l)
4518 {
4519   rtx dest = op[0];
4520   rtx src = op[1];
4521   rtx base = XEXP (dest, 0);
4522   int reg_base = REGNO (XEXP (base, 0));
4523   int reg_src =true_regnum (src);
4524 
4525   if (reg_base == reg_src)
4526     {
4527       *l = 11;
4528       return ("mov __tmp_reg__,%A2"        CR_TAB
4529               "mov __zero_reg__,%B2"       CR_TAB
4530               TINY_ADIW (%I0, %J0, %o0)    CR_TAB
4531               "st %b0+,__tmp_reg__"        CR_TAB
4532               "st %b0+,__zero_reg__"       CR_TAB
4533               "st %b0+,%C2"                CR_TAB
4534               "st %b0,%D2"                 CR_TAB
4535               "clr __zero_reg__"           CR_TAB
4536               TINY_SBIW (%I0, %J0, %o0+3));
4537     }
4538   else if (reg_src == reg_base - 2)
4539     {
4540       *l = 11;
4541       return ("mov __tmp_reg__,%C2"         CR_TAB
4542               "mov __zero_reg__,%D2"        CR_TAB
4543               TINY_ADIW (%I0, %J0, %o0)     CR_TAB
4544               "st %b0+,%A0"                 CR_TAB
4545               "st %b0+,%B0"                 CR_TAB
4546               "st %b0+,__tmp_reg__"         CR_TAB
4547               "st %b0,__zero_reg__"         CR_TAB
4548               "clr __zero_reg__"            CR_TAB
4549               TINY_SBIW (%I0, %J0, %o0+3));
4550     }
4551   *l = 8;
4552   return (TINY_ADIW (%I0, %J0, %o0)     CR_TAB
4553           "st %b0+,%A1"                 CR_TAB
4554           "st %b0+,%B1"                 CR_TAB
4555           "st %b0+,%C1"                 CR_TAB
4556           "st %b0,%D1"                  CR_TAB
4557           TINY_SBIW (%I0, %J0, %o0+3));
4558 }
4559 
4560 static const char*
out_movsi_mr_r(rtx_insn * insn,rtx op[],int * l)4561 out_movsi_mr_r (rtx_insn *insn, rtx op[], int *l)
4562 {
4563   rtx dest = op[0];
4564   rtx src = op[1];
4565   rtx base = XEXP (dest, 0);
4566   int reg_base = true_regnum (base);
4567   int reg_src = true_regnum (src);
4568   int tmp;
4569 
4570   if (!l)
4571     l = &tmp;
4572 
4573   if (CONSTANT_ADDRESS_P (base))
4574     {
4575       if (io_address_operand (base, SImode))
4576         {
4577           return *l=4,("out %i0, %A1"  CR_TAB
4578                        "out %i0+1,%B1" CR_TAB
4579                        "out %i0+2,%C1" CR_TAB
4580                        "out %i0+3,%D1");
4581         }
4582       else
4583         {
4584           *l = AVR_TINY ? 4 : 8;
4585           return ("sts %m0,%A1"   CR_TAB
4586                   "sts %m0+1,%B1" CR_TAB
4587                   "sts %m0+2,%C1" CR_TAB
4588                   "sts %m0+3,%D1");
4589         }
4590     }
4591 
4592   if (reg_base > 0)                 /* (r) */
4593     {
4594       if (AVR_TINY)
4595         return avr_out_movsi_mr_r_reg_no_disp_tiny (insn, op, l);
4596 
4597       if (reg_base == REG_X)                /* (R26) */
4598         {
4599           if (reg_src == REG_X)
4600             {
4601 	      /* "st X+,r26" is undefined */
4602               if (reg_unused_after (insn, base))
4603 		return *l=6, ("mov __tmp_reg__,r27" CR_TAB
4604 			      "st X,r26"            CR_TAB
4605 			      "adiw r26,1"          CR_TAB
4606 			      "st X+,__tmp_reg__"   CR_TAB
4607 			      "st X+,r28"           CR_TAB
4608 			      "st X,r29");
4609               else
4610                 return *l=7, ("mov __tmp_reg__,r27" CR_TAB
4611 			      "st X,r26"            CR_TAB
4612 			      "adiw r26,1"          CR_TAB
4613 			      "st X+,__tmp_reg__"   CR_TAB
4614 			      "st X+,r28"           CR_TAB
4615 			      "st X,r29"            CR_TAB
4616 			      "sbiw r26,3");
4617             }
4618           else if (reg_base == reg_src + 2)
4619             {
4620               if (reg_unused_after (insn, base))
4621                 return *l=7, ("mov __zero_reg__,%C1" CR_TAB
4622                               "mov __tmp_reg__,%D1"  CR_TAB
4623                               "st %0+,%A1"           CR_TAB
4624                               "st %0+,%B1"           CR_TAB
4625                               "st %0+,__zero_reg__"  CR_TAB
4626                               "st %0,__tmp_reg__"    CR_TAB
4627                               "clr __zero_reg__");
4628               else
4629                 return *l=8, ("mov __zero_reg__,%C1" CR_TAB
4630                               "mov __tmp_reg__,%D1"  CR_TAB
4631                               "st %0+,%A1"           CR_TAB
4632                               "st %0+,%B1"           CR_TAB
4633                               "st %0+,__zero_reg__"  CR_TAB
4634                               "st %0,__tmp_reg__"    CR_TAB
4635                               "clr __zero_reg__"     CR_TAB
4636                               "sbiw r26,3");
4637             }
4638           return *l=5, ("st %0+,%A1" CR_TAB
4639                         "st %0+,%B1" CR_TAB
4640                         "st %0+,%C1" CR_TAB
4641                         "st %0,%D1"  CR_TAB
4642                         "sbiw r26,3");
4643         }
4644       else
4645         return *l=4, ("st %0,%A1"    CR_TAB
4646 		      "std %0+1,%B1" CR_TAB
4647 		      "std %0+2,%C1" CR_TAB
4648 		      "std %0+3,%D1");
4649     }
4650   else if (GET_CODE (base) == PLUS) /* (R + i) */
4651     {
4652       int disp = INTVAL (XEXP (base, 1));
4653 
4654       if (AVR_TINY)
4655         return avr_out_movsi_mr_r_reg_disp_tiny (op, l);
4656 
4657       reg_base = REGNO (XEXP (base, 0));
4658       if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
4659 	{
4660 	  if (reg_base != REG_Y)
4661 	    fatal_insn ("incorrect insn:",insn);
4662 
4663 	  if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
4664 	    return *l = 6, ("adiw r28,%o0-60" CR_TAB
4665 			    "std Y+60,%A1"    CR_TAB
4666 			    "std Y+61,%B1"    CR_TAB
4667 			    "std Y+62,%C1"    CR_TAB
4668 			    "std Y+63,%D1"    CR_TAB
4669 			    "sbiw r28,%o0-60");
4670 
4671 	  return *l = 8, ("subi r28,lo8(-%o0)" CR_TAB
4672 			  "sbci r29,hi8(-%o0)" CR_TAB
4673 			  "st Y,%A1"           CR_TAB
4674 			  "std Y+1,%B1"        CR_TAB
4675 			  "std Y+2,%C1"        CR_TAB
4676 			  "std Y+3,%D1"        CR_TAB
4677 			  "subi r28,lo8(%o0)"  CR_TAB
4678 			  "sbci r29,hi8(%o0)");
4679 	}
4680       if (reg_base == REG_X)
4681 	{
4682 	  /* (X + d) = R */
4683 	  if (reg_src == REG_X)
4684 	    {
4685 	      *l = 9;
4686 	      return ("mov __tmp_reg__,r26"  CR_TAB
4687 		      "mov __zero_reg__,r27" CR_TAB
4688 		      "adiw r26,%o0"         CR_TAB
4689 		      "st X+,__tmp_reg__"    CR_TAB
4690 		      "st X+,__zero_reg__"   CR_TAB
4691 		      "st X+,r28"            CR_TAB
4692 		      "st X,r29"             CR_TAB
4693 		      "clr __zero_reg__"     CR_TAB
4694 		      "sbiw r26,%o0+3");
4695 	    }
4696 	  else if (reg_src == REG_X - 2)
4697 	    {
4698 	      *l = 9;
4699 	      return ("mov __tmp_reg__,r26"  CR_TAB
4700 		      "mov __zero_reg__,r27" CR_TAB
4701 		      "adiw r26,%o0"         CR_TAB
4702 		      "st X+,r24"            CR_TAB
4703 		      "st X+,r25"            CR_TAB
4704 		      "st X+,__tmp_reg__"    CR_TAB
4705 		      "st X,__zero_reg__"    CR_TAB
4706 		      "clr __zero_reg__"     CR_TAB
4707 		      "sbiw r26,%o0+3");
4708 	    }
4709 	  *l = 6;
4710 	  return ("adiw r26,%o0" CR_TAB
4711 		  "st X+,%A1"    CR_TAB
4712 		  "st X+,%B1"    CR_TAB
4713 		  "st X+,%C1"    CR_TAB
4714 		  "st X,%D1"     CR_TAB
4715 		  "sbiw r26,%o0+3");
4716 	}
4717       return *l=4, ("std %A0,%A1" CR_TAB
4718 		    "std %B0,%B1" CR_TAB
4719 		    "std %C0,%C1" CR_TAB
4720 		    "std %D0,%D1");
4721     }
4722   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4723     return *l=4, ("st %0,%D1" CR_TAB
4724 		  "st %0,%C1" CR_TAB
4725 		  "st %0,%B1" CR_TAB
4726 		  "st %0,%A1");
4727   else if (GET_CODE (base) == POST_INC) /* (R++) */
4728     return *l=4, ("st %0,%A1" CR_TAB
4729 		  "st %0,%B1" CR_TAB
4730 		  "st %0,%C1" CR_TAB
4731 		  "st %0,%D1");
4732   fatal_insn ("unknown move insn:",insn);
4733   return "";
4734 }
4735 
4736 const char *
output_movsisf(rtx_insn * insn,rtx operands[],int * l)4737 output_movsisf (rtx_insn *insn, rtx operands[], int *l)
4738 {
4739   int dummy;
4740   rtx dest = operands[0];
4741   rtx src = operands[1];
4742   int *real_l = l;
4743 
4744   if (avr_mem_flash_p (src)
4745       || avr_mem_flash_p (dest))
4746     {
4747       return avr_out_lpm (insn, operands, real_l);
4748     }
4749 
4750   if (!l)
4751     l = &dummy;
4752 
4753   gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 4);
4754 
4755   if (REG_P (dest))
4756     {
4757       if (REG_P (src)) /* mov r,r */
4758 	{
4759 	  if (true_regnum (dest) > true_regnum (src))
4760 	    {
4761 	      if (AVR_HAVE_MOVW)
4762 		{
4763 		  *l = 2;
4764 		  return ("movw %C0,%C1" CR_TAB
4765 			  "movw %A0,%A1");
4766 		}
4767 	      *l = 4;
4768 	      return ("mov %D0,%D1" CR_TAB
4769 		      "mov %C0,%C1" CR_TAB
4770 		      "mov %B0,%B1" CR_TAB
4771 		      "mov %A0,%A1");
4772 	    }
4773 	  else
4774 	    {
4775 	      if (AVR_HAVE_MOVW)
4776 		{
4777 		  *l = 2;
4778 		  return ("movw %A0,%A1" CR_TAB
4779 			  "movw %C0,%C1");
4780 		}
4781 	      *l = 4;
4782 	      return ("mov %A0,%A1" CR_TAB
4783 		      "mov %B0,%B1" CR_TAB
4784 		      "mov %C0,%C1" CR_TAB
4785 		      "mov %D0,%D1");
4786 	    }
4787 	}
4788       else if (CONSTANT_P (src))
4789 	{
4790           return output_reload_insisf (operands, NULL_RTX, real_l);
4791         }
4792       else if (MEM_P (src))
4793 	return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
4794     }
4795   else if (MEM_P (dest))
4796     {
4797       const char *templ;
4798 
4799       if (src == CONST0_RTX (GET_MODE (dest)))
4800         operands[1] = zero_reg_rtx;
4801 
4802       templ = out_movsi_mr_r (insn, operands, real_l);
4803 
4804       if (!real_l)
4805 	output_asm_insn (templ, operands);
4806 
4807       operands[1] = src;
4808       return "";
4809     }
4810   fatal_insn ("invalid insn:", insn);
4811   return "";
4812 }
4813 
4814 
4815 /* Handle loads of 24-bit types from memory to register.  */
4816 
4817 static const char*
avr_out_load_psi_reg_no_disp_tiny(rtx_insn * insn,rtx * op,int * plen)4818 avr_out_load_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
4819 {
4820   rtx dest = op[0];
4821   rtx src = op[1];
4822   rtx base = XEXP (src, 0);
4823   int reg_dest = true_regnum (dest);
4824   int reg_base = true_regnum (base);
4825 
4826   if (reg_base == reg_dest)
4827     {
4828       return avr_asm_len (TINY_ADIW (%E1, %F1, 2)   CR_TAB
4829                           "ld %C0,%1"               CR_TAB
4830                           "ld __tmp_reg__,-%1"      CR_TAB
4831                           TINY_SBIW (%E1, %F1, 1)   CR_TAB
4832                           "ld %A0,%1"               CR_TAB
4833                           "mov %B0,__tmp_reg__", op, plen, -8);
4834     }
4835   else
4836     {
4837       avr_asm_len ("ld %A0,%1+"  CR_TAB
4838 		   "ld %B0,%1+"  CR_TAB
4839 		   "ld %C0,%1", op, plen, -3);
4840 
4841       if (reg_dest != reg_base - 2
4842           && !reg_unused_after (insn, base))
4843         {
4844           avr_asm_len (TINY_SBIW (%E1, %F1, 2), op, plen, 2);
4845         }
4846       return "";
4847     }
4848 }
4849 
4850 static const char*
avr_out_load_psi_reg_disp_tiny(rtx_insn * insn,rtx * op,int * plen)4851 avr_out_load_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
4852 {
4853   rtx dest = op[0];
4854   rtx src = op[1];
4855   rtx base = XEXP (src, 0);
4856   int reg_dest = true_regnum (dest);
4857   int reg_base = true_regnum (base);
4858 
4859   reg_base = true_regnum (XEXP (base, 0));
4860   if (reg_base == reg_dest)
4861     {
4862       return avr_asm_len (TINY_ADIW (%I1, %J1, %o1+2) CR_TAB
4863                           "ld %C0,%b1"                CR_TAB
4864                           "ld __tmp_reg__,-%b1"       CR_TAB
4865                           TINY_SBIW (%I1, %J1, 1)     CR_TAB
4866                           "ld %A0,%b1"                CR_TAB
4867                           "mov %B0,__tmp_reg__", op, plen, -8);
4868     }
4869   else
4870     {
4871       avr_asm_len (TINY_ADIW (%I1, %J1, %o1)   CR_TAB
4872                    "ld %A0,%b1+"               CR_TAB
4873                    "ld %B0,%b1+"               CR_TAB
4874                    "ld %C0,%b1", op, plen, -5);
4875 
4876       if (reg_dest != reg_base - 2
4877           && !reg_unused_after (insn, XEXP (base, 0)))
4878         avr_asm_len (TINY_SBIW (%I1, %J1, %o1+2), op, plen, 2);
4879 
4880       return "";
4881     }
4882 }
4883 
4884 static const char*
avr_out_load_psi(rtx_insn * insn,rtx * op,int * plen)4885 avr_out_load_psi (rtx_insn *insn, rtx *op, int *plen)
4886 {
4887   rtx dest = op[0];
4888   rtx src = op[1];
4889   rtx base = XEXP (src, 0);
4890   int reg_dest = true_regnum (dest);
4891   int reg_base = true_regnum (base);
4892 
4893   if (reg_base > 0)
4894     {
4895       if (AVR_TINY)
4896         return avr_out_load_psi_reg_no_disp_tiny (insn, op, plen);
4897 
4898       if (reg_base == REG_X)        /* (R26) */
4899         {
4900           if (reg_dest == REG_X)
4901             /* "ld r26,-X" is undefined */
4902             return avr_asm_len ("adiw r26,2"        CR_TAB
4903                                 "ld r28,X"          CR_TAB
4904                                 "ld __tmp_reg__,-X" CR_TAB
4905                                 "sbiw r26,1"        CR_TAB
4906                                 "ld r26,X"          CR_TAB
4907                                 "mov r27,__tmp_reg__", op, plen, -6);
4908           else
4909             {
4910               avr_asm_len ("ld %A0,X+" CR_TAB
4911                            "ld %B0,X+" CR_TAB
4912                            "ld %C0,X", op, plen, -3);
4913 
4914               if (reg_dest != REG_X - 2
4915                   && !reg_unused_after (insn, base))
4916                 {
4917                   avr_asm_len ("sbiw r26,2", op, plen, 1);
4918                 }
4919 
4920               return "";
4921             }
4922         }
4923       else /* reg_base != REG_X */
4924         {
4925           if (reg_dest == reg_base)
4926             return avr_asm_len ("ldd %C0,%1+2"          CR_TAB
4927                                 "ldd __tmp_reg__,%1+1"  CR_TAB
4928                                 "ld  %A0,%1"            CR_TAB
4929                                 "mov %B0,__tmp_reg__", op, plen, -4);
4930           else
4931             return avr_asm_len ("ld  %A0,%1"    CR_TAB
4932                                 "ldd %B0,%1+1"  CR_TAB
4933                                 "ldd %C0,%1+2", op, plen, -3);
4934         }
4935     }
4936   else if (GET_CODE (base) == PLUS) /* (R + i) */
4937     {
4938       int disp = INTVAL (XEXP (base, 1));
4939 
4940       if (AVR_TINY)
4941         return avr_out_load_psi_reg_disp_tiny (insn, op, plen);
4942 
4943       if (disp > MAX_LD_OFFSET (GET_MODE (src)))
4944         {
4945           if (REGNO (XEXP (base, 0)) != REG_Y)
4946             fatal_insn ("incorrect insn:",insn);
4947 
4948           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
4949             return avr_asm_len ("adiw r28,%o1-61" CR_TAB
4950                                 "ldd %A0,Y+61"    CR_TAB
4951                                 "ldd %B0,Y+62"    CR_TAB
4952                                 "ldd %C0,Y+63"    CR_TAB
4953                                 "sbiw r28,%o1-61", op, plen, -5);
4954 
4955           return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
4956                               "sbci r29,hi8(-%o1)" CR_TAB
4957                               "ld  %A0,Y"          CR_TAB
4958                               "ldd %B0,Y+1"        CR_TAB
4959                               "ldd %C0,Y+2"        CR_TAB
4960                               "subi r28,lo8(%o1)"  CR_TAB
4961                               "sbci r29,hi8(%o1)", op, plen, -7);
4962         }
4963 
4964       reg_base = true_regnum (XEXP (base, 0));
4965       if (reg_base == REG_X)
4966         {
4967           /* R = (X + d) */
4968           if (reg_dest == REG_X)
4969             {
4970               /* "ld r26,-X" is undefined */
4971               return avr_asm_len ("adiw r26,%o1+2"     CR_TAB
4972                                   "ld  r28,X"          CR_TAB
4973                                   "ld  __tmp_reg__,-X" CR_TAB
4974                                   "sbiw r26,1"         CR_TAB
4975                                   "ld  r26,X"          CR_TAB
4976                                   "mov r27,__tmp_reg__", op, plen, -6);
4977             }
4978 
4979           avr_asm_len ("adiw r26,%o1" CR_TAB
4980                        "ld %A0,X+"    CR_TAB
4981                        "ld %B0,X+"    CR_TAB
4982                        "ld %C0,X", op, plen, -4);
4983 
4984           if (reg_dest != REG_W
4985               && !reg_unused_after (insn, XEXP (base, 0)))
4986             avr_asm_len ("sbiw r26,%o1+2", op, plen, 1);
4987 
4988           return "";
4989         }
4990 
4991       if (reg_dest == reg_base)
4992         return avr_asm_len ("ldd %C0,%C1" CR_TAB
4993                             "ldd __tmp_reg__,%B1"  CR_TAB
4994                             "ldd %A0,%A1" CR_TAB
4995                             "mov %B0,__tmp_reg__", op, plen, -4);
4996 
4997       return avr_asm_len ("ldd %A0,%A1" CR_TAB
4998                           "ldd %B0,%B1" CR_TAB
4999                           "ldd %C0,%C1", op, plen, -3);
5000     }
5001   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5002     return avr_asm_len ("ld %C0,%1" CR_TAB
5003                         "ld %B0,%1" CR_TAB
5004                         "ld %A0,%1", op, plen, -3);
5005   else if (GET_CODE (base) == POST_INC) /* (R++) */
5006     return avr_asm_len ("ld %A0,%1" CR_TAB
5007                         "ld %B0,%1" CR_TAB
5008                         "ld %C0,%1", op, plen, -3);
5009 
5010   else if (CONSTANT_ADDRESS_P (base))
5011     {
5012       int n_words = AVR_TINY ? 3 : 6;
5013       return avr_asm_len ("lds %A0,%m1" CR_TAB
5014                           "lds %B0,%m1+1" CR_TAB
5015                           "lds %C0,%m1+2", op, plen , -n_words);
5016     }
5017 
5018   fatal_insn ("unknown move insn:",insn);
5019   return "";
5020 }
5021 
5022 
5023 static const char*
avr_out_store_psi_reg_no_disp_tiny(rtx_insn * insn,rtx * op,int * plen)5024 avr_out_store_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
5025 {
5026   rtx dest = op[0];
5027   rtx src = op[1];
5028   rtx base = XEXP (dest, 0);
5029   int reg_base = true_regnum (base);
5030   int reg_src = true_regnum (src);
5031 
5032   if (reg_base == reg_src)
5033     {
5034       avr_asm_len ("st %0,%A1"              CR_TAB
5035                    "mov __tmp_reg__,%B1"    CR_TAB
5036                    TINY_ADIW (%E0, %F0, 1)  CR_TAB /* st X+, r27 is undefined */
5037                    "st %0+,__tmp_reg__"     CR_TAB
5038                    "st %0,%C1", op, plen, -6);
5039 
5040     }
5041   else if (reg_src == reg_base - 2)
5042     {
5043       avr_asm_len ("st %0,%A1"              CR_TAB
5044                    "mov __tmp_reg__,%C1"    CR_TAB
5045                    TINY_ADIW (%E0, %F0, 1)  CR_TAB
5046                    "st %0+,%B1"             CR_TAB
5047                    "st %0,__tmp_reg__", op, plen, 6);
5048     }
5049   else
5050     {
5051       avr_asm_len ("st %0+,%A1"  CR_TAB
5052                    "st %0+,%B1" CR_TAB
5053                    "st %0,%C1", op, plen, -3);
5054     }
5055 
5056   if (!reg_unused_after (insn, base))
5057     avr_asm_len (TINY_SBIW (%E0, %F0, 2), op, plen, 2);
5058 
5059   return "";
5060 }
5061 
5062 static const char*
avr_out_store_psi_reg_disp_tiny(rtx_insn * insn,rtx * op,int * plen)5063 avr_out_store_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
5064 {
5065   rtx dest = op[0];
5066   rtx src = op[1];
5067   rtx base = XEXP (dest, 0);
5068   int reg_base = REGNO (XEXP (base, 0));
5069   int reg_src = true_regnum (src);
5070 
5071   if (reg_src == reg_base)
5072     avr_asm_len ("mov __tmp_reg__,%A1"          CR_TAB
5073                  "mov __zero_reg__,%B1"         CR_TAB
5074                  TINY_ADIW (%I0, %J0, %o0)      CR_TAB
5075                  "st %b0+,__tmp_reg__"          CR_TAB
5076                  "st %b0+,__zero_reg__"         CR_TAB
5077                  "st %b0,%C1"                   CR_TAB
5078                  "clr __zero_reg__", op, plen, -8);
5079   else if (reg_src == reg_base - 2)
5080     avr_asm_len ("mov __tmp_reg__,%C1"          CR_TAB
5081                  TINY_ADIW (%I0, %J0, %o0)      CR_TAB
5082                  "st %b0+,%A1"                  CR_TAB
5083                  "st %b0+,%B1"                  CR_TAB
5084                  "st %b0,__tmp_reg__", op, plen, -6);
5085   else
5086     avr_asm_len (TINY_ADIW (%I0, %J0, %o0)      CR_TAB
5087                  "st %b0+,%A1"                  CR_TAB
5088                  "st %b0+,%B1"                  CR_TAB
5089                  "st %b0,%C1", op, plen, -5);
5090 
5091   if (!reg_unused_after (insn, XEXP (base, 0)))
5092     avr_asm_len (TINY_SBIW (%I0, %J0, %o0+2), op, plen, 2);
5093 
5094   return "";
5095 }
5096 
5097 /* Handle store of 24-bit type from register or zero to memory.  */
5098 
5099 static const char*
avr_out_store_psi(rtx_insn * insn,rtx * op,int * plen)5100 avr_out_store_psi (rtx_insn *insn, rtx *op, int *plen)
5101 {
5102   rtx dest = op[0];
5103   rtx src = op[1];
5104   rtx base = XEXP (dest, 0);
5105   int reg_base = true_regnum (base);
5106 
5107   if (CONSTANT_ADDRESS_P (base))
5108     {
5109       int n_words = AVR_TINY ? 3 : 6;
5110       return avr_asm_len ("sts %m0,%A1"   CR_TAB
5111                           "sts %m0+1,%B1" CR_TAB
5112                           "sts %m0+2,%C1", op, plen, -n_words);
5113     }
5114 
5115   if (reg_base > 0)                 /* (r) */
5116     {
5117       if (AVR_TINY)
5118         return avr_out_store_psi_reg_no_disp_tiny (insn, op, plen);
5119 
5120       if (reg_base == REG_X)        /* (R26) */
5121         {
5122           gcc_assert (!reg_overlap_mentioned_p (base, src));
5123 
5124           avr_asm_len ("st %0+,%A1"  CR_TAB
5125                        "st %0+,%B1" CR_TAB
5126                        "st %0,%C1", op, plen, -3);
5127 
5128           if (!reg_unused_after (insn, base))
5129             avr_asm_len ("sbiw r26,2", op, plen, 1);
5130 
5131           return "";
5132         }
5133       else
5134         return avr_asm_len ("st %0,%A1"    CR_TAB
5135                             "std %0+1,%B1" CR_TAB
5136                             "std %0+2,%C1", op, plen, -3);
5137     }
5138   else if (GET_CODE (base) == PLUS) /* (R + i) */
5139     {
5140       int disp = INTVAL (XEXP (base, 1));
5141 
5142       if (AVR_TINY)
5143         return avr_out_store_psi_reg_disp_tiny (insn, op, plen);
5144 
5145       reg_base = REGNO (XEXP (base, 0));
5146 
5147       if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5148         {
5149           if (reg_base != REG_Y)
5150             fatal_insn ("incorrect insn:",insn);
5151 
5152           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
5153             return avr_asm_len ("adiw r28,%o0-61" CR_TAB
5154                                 "std Y+61,%A1"    CR_TAB
5155                                 "std Y+62,%B1"    CR_TAB
5156                                 "std Y+63,%C1"    CR_TAB
5157                                 "sbiw r28,%o0-61", op, plen, -5);
5158 
5159           return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5160                               "sbci r29,hi8(-%o0)" CR_TAB
5161                               "st Y,%A1"           CR_TAB
5162                               "std Y+1,%B1"        CR_TAB
5163                               "std Y+2,%C1"        CR_TAB
5164                               "subi r28,lo8(%o0)"  CR_TAB
5165                               "sbci r29,hi8(%o0)", op, plen, -7);
5166         }
5167       if (reg_base == REG_X)
5168         {
5169           /* (X + d) = R */
5170           gcc_assert (!reg_overlap_mentioned_p (XEXP (base, 0), src));
5171 
5172           avr_asm_len ("adiw r26,%o0" CR_TAB
5173                        "st X+,%A1"    CR_TAB
5174                        "st X+,%B1"    CR_TAB
5175                        "st X,%C1", op, plen, -4);
5176 
5177           if (!reg_unused_after (insn, XEXP (base, 0)))
5178             avr_asm_len ("sbiw r26,%o0+2", op, plen, 1);
5179 
5180           return "";
5181         }
5182 
5183       return avr_asm_len ("std %A0,%A1" CR_TAB
5184                           "std %B0,%B1" CR_TAB
5185                           "std %C0,%C1", op, plen, -3);
5186     }
5187   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5188     return avr_asm_len ("st %0,%C1" CR_TAB
5189                         "st %0,%B1" CR_TAB
5190                         "st %0,%A1", op, plen, -3);
5191   else if (GET_CODE (base) == POST_INC) /* (R++) */
5192     return avr_asm_len ("st %0,%A1" CR_TAB
5193                         "st %0,%B1" CR_TAB
5194                         "st %0,%C1", op, plen, -3);
5195 
5196   fatal_insn ("unknown move insn:",insn);
5197   return "";
5198 }
5199 
5200 
5201 /* Move around 24-bit stuff.  */
5202 
5203 const char *
avr_out_movpsi(rtx_insn * insn,rtx * op,int * plen)5204 avr_out_movpsi (rtx_insn *insn, rtx *op, int *plen)
5205 {
5206   rtx dest = op[0];
5207   rtx src = op[1];
5208 
5209   if (avr_mem_flash_p (src)
5210       || avr_mem_flash_p (dest))
5211     {
5212       return avr_out_lpm (insn, op, plen);
5213     }
5214 
5215   if (register_operand (dest, VOIDmode))
5216     {
5217       if (register_operand (src, VOIDmode)) /* mov r,r */
5218         {
5219           if (true_regnum (dest) > true_regnum (src))
5220             {
5221               avr_asm_len ("mov %C0,%C1", op, plen, -1);
5222 
5223               if (AVR_HAVE_MOVW)
5224                 return avr_asm_len ("movw %A0,%A1", op, plen, 1);
5225               else
5226                 return avr_asm_len ("mov %B0,%B1"  CR_TAB
5227                                     "mov %A0,%A1", op, plen, 2);
5228             }
5229           else
5230             {
5231               if (AVR_HAVE_MOVW)
5232                 avr_asm_len ("movw %A0,%A1", op, plen, -1);
5233               else
5234                 avr_asm_len ("mov %A0,%A1"  CR_TAB
5235                              "mov %B0,%B1", op, plen, -2);
5236 
5237               return avr_asm_len ("mov %C0,%C1", op, plen, 1);
5238             }
5239         }
5240       else if (CONSTANT_P (src))
5241         {
5242           return avr_out_reload_inpsi (op, NULL_RTX, plen);
5243         }
5244       else if (MEM_P (src))
5245         return avr_out_load_psi (insn, op, plen); /* mov r,m */
5246     }
5247   else if (MEM_P (dest))
5248     {
5249       rtx xop[2];
5250 
5251       xop[0] = dest;
5252       xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
5253 
5254       return avr_out_store_psi (insn, xop, plen);
5255     }
5256 
5257   fatal_insn ("invalid insn:", insn);
5258   return "";
5259 }
5260 
5261 static const char*
avr_out_movqi_mr_r_reg_disp_tiny(rtx_insn * insn,rtx op[],int * plen)5262 avr_out_movqi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5263 {
5264   rtx dest = op[0];
5265   rtx src = op[1];
5266   rtx x = XEXP (dest, 0);
5267 
5268   if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
5269     {
5270       avr_asm_len ("mov __tmp_reg__,%1"      CR_TAB
5271                    TINY_ADIW (%I0, %J0, %o0) CR_TAB
5272                    "st %b0,__tmp_reg__", op, plen, -4);
5273     }
5274   else
5275     {
5276       avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
5277                    "st %b0,%1", op, plen, -3);
5278     }
5279 
5280   if (!reg_unused_after (insn, XEXP (x, 0)))
5281     avr_asm_len (TINY_SBIW (%I0, %J0, %o0), op, plen, 2);
5282 
5283   return "";
5284 }
5285 
5286 static const char*
out_movqi_mr_r(rtx_insn * insn,rtx op[],int * plen)5287 out_movqi_mr_r (rtx_insn *insn, rtx op[], int *plen)
5288 {
5289   rtx dest = op[0];
5290   rtx src = op[1];
5291   rtx x = XEXP (dest, 0);
5292 
5293   if (CONSTANT_ADDRESS_P (x))
5294     {
5295       int n_words = AVR_TINY ? 1 : 2;
5296       return io_address_operand (x, QImode)
5297         ? avr_asm_len ("out %i0,%1", op, plen, -1)
5298         : avr_asm_len ("sts %m0,%1", op, plen, -n_words);
5299     }
5300   else if (GET_CODE (x) == PLUS
5301            && REG_P (XEXP (x, 0))
5302            && CONST_INT_P (XEXP (x, 1)))
5303     {
5304       /* memory access by reg+disp */
5305 
5306       int disp = INTVAL (XEXP (x, 1));
5307 
5308       if (AVR_TINY)
5309         return avr_out_movqi_mr_r_reg_disp_tiny (insn, op, plen);
5310 
5311       if (disp - GET_MODE_SIZE (GET_MODE (dest)) >= 63)
5312         {
5313           if (REGNO (XEXP (x, 0)) != REG_Y)
5314             fatal_insn ("incorrect insn:",insn);
5315 
5316           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
5317             return avr_asm_len ("adiw r28,%o0-63" CR_TAB
5318                                 "std Y+63,%1"     CR_TAB
5319                                 "sbiw r28,%o0-63", op, plen, -3);
5320 
5321           return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5322                               "sbci r29,hi8(-%o0)" CR_TAB
5323                               "st Y,%1"            CR_TAB
5324                               "subi r28,lo8(%o0)"  CR_TAB
5325                               "sbci r29,hi8(%o0)", op, plen, -5);
5326         }
5327       else if (REGNO (XEXP (x, 0)) == REG_X)
5328         {
5329           if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
5330             {
5331               avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
5332                            "adiw r26,%o0"       CR_TAB
5333                            "st X,__tmp_reg__", op, plen, -3);
5334             }
5335           else
5336             {
5337               avr_asm_len ("adiw r26,%o0" CR_TAB
5338                            "st X,%1", op, plen, -2);
5339             }
5340 
5341           if (!reg_unused_after (insn, XEXP (x, 0)))
5342             avr_asm_len ("sbiw r26,%o0", op, plen, 1);
5343 
5344           return "";
5345         }
5346 
5347       return avr_asm_len ("std %0,%1", op, plen, -1);
5348     }
5349 
5350   return avr_asm_len ("st %0,%1", op, plen, -1);
5351 }
5352 
5353 
5354 /* Helper for the next function for XMEGA.  It does the same
5355    but with low byte first.  */
5356 
5357 static const char*
avr_out_movhi_mr_r_xmega(rtx_insn * insn,rtx op[],int * plen)5358 avr_out_movhi_mr_r_xmega (rtx_insn *insn, rtx op[], int *plen)
5359 {
5360   rtx dest = op[0];
5361   rtx src = op[1];
5362   rtx base = XEXP (dest, 0);
5363   int reg_base = true_regnum (base);
5364   int reg_src = true_regnum (src);
5365 
5366   /* "volatile" forces writing low byte first, even if less efficient,
5367      for correct operation with 16-bit I/O registers like SP.  */
5368   int mem_volatile_p = MEM_VOLATILE_P (dest);
5369 
5370   if (CONSTANT_ADDRESS_P (base))
5371     {
5372       return io_address_operand (base, HImode)
5373         ? avr_asm_len ("out %i0,%A1" CR_TAB
5374                        "out %i0+1,%B1", op, plen, -2)
5375 
5376         : avr_asm_len ("sts %m0,%A1" CR_TAB
5377                        "sts %m0+1,%B1", op, plen, -4);
5378     }
5379 
5380   if (reg_base > 0)
5381     {
5382       if (reg_base != REG_X)
5383         return avr_asm_len ("st %0,%A1" CR_TAB
5384                             "std %0+1,%B1", op, plen, -2);
5385 
5386       if (reg_src == REG_X)
5387         /* "st X+,r26" and "st -X,r26" are undefined.  */
5388         avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5389                      "st X,r26"            CR_TAB
5390                      "adiw r26,1"          CR_TAB
5391                      "st X,__tmp_reg__", op, plen, -4);
5392       else
5393         avr_asm_len ("st X+,%A1" CR_TAB
5394                      "st X,%B1", op, plen, -2);
5395 
5396       return reg_unused_after (insn, base)
5397         ? ""
5398         : avr_asm_len ("sbiw r26,1", op, plen, 1);
5399     }
5400   else if (GET_CODE (base) == PLUS)
5401     {
5402       int disp = INTVAL (XEXP (base, 1));
5403       reg_base = REGNO (XEXP (base, 0));
5404       if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5405         {
5406           if (reg_base != REG_Y)
5407             fatal_insn ("incorrect insn:",insn);
5408 
5409           return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
5410             ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
5411                            "std Y+62,%A1"    CR_TAB
5412                            "std Y+63,%B1"    CR_TAB
5413                            "sbiw r28,%o0-62", op, plen, -4)
5414 
5415             : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5416                            "sbci r29,hi8(-%o0)" CR_TAB
5417                            "st Y,%A1"           CR_TAB
5418                            "std Y+1,%B1"        CR_TAB
5419                            "subi r28,lo8(%o0)"  CR_TAB
5420                            "sbci r29,hi8(%o0)", op, plen, -6);
5421         }
5422 
5423       if (reg_base != REG_X)
5424         return avr_asm_len ("std %A0,%A1" CR_TAB
5425                             "std %B0,%B1", op, plen, -2);
5426       /* (X + d) = R */
5427       return reg_src == REG_X
5428         ? avr_asm_len ("mov __tmp_reg__,r26"  CR_TAB
5429                        "mov __zero_reg__,r27" CR_TAB
5430                        "adiw r26,%o0"         CR_TAB
5431                        "st X+,__tmp_reg__"    CR_TAB
5432                        "st X,__zero_reg__"    CR_TAB
5433                        "clr __zero_reg__"     CR_TAB
5434                        "sbiw r26,%o0+1", op, plen, -7)
5435 
5436         : avr_asm_len ("adiw r26,%o0" CR_TAB
5437                        "st X+,%A1"    CR_TAB
5438                        "st X,%B1"     CR_TAB
5439                        "sbiw r26,%o0+1", op, plen, -4);
5440     }
5441   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5442     {
5443       if (!mem_volatile_p)
5444         return avr_asm_len ("st %0,%B1" CR_TAB
5445                             "st %0,%A1", op, plen, -2);
5446 
5447       return REGNO (XEXP (base, 0)) == REG_X
5448         ? avr_asm_len ("sbiw r26,2"  CR_TAB
5449                        "st X+,%A1"   CR_TAB
5450                        "st X,%B1"    CR_TAB
5451                        "sbiw r26,1", op, plen, -4)
5452 
5453         : avr_asm_len ("sbiw %r0,2"  CR_TAB
5454                        "st %p0,%A1"  CR_TAB
5455                        "std %p0+1,%B1", op, plen, -3);
5456     }
5457   else if (GET_CODE (base) == POST_INC) /* (R++) */
5458     {
5459       return avr_asm_len ("st %0,%A1"  CR_TAB
5460                           "st %0,%B1", op, plen, -2);
5461 
5462     }
5463   fatal_insn ("unknown move insn:",insn);
5464   return "";
5465 }
5466 
5467 static const char*
avr_out_movhi_mr_r_reg_no_disp_tiny(rtx_insn * insn,rtx op[],int * plen)5468 avr_out_movhi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5469 {
5470   rtx dest = op[0];
5471   rtx src = op[1];
5472   rtx base = XEXP (dest, 0);
5473   int reg_base = true_regnum (base);
5474   int reg_src = true_regnum (src);
5475   int mem_volatile_p = MEM_VOLATILE_P (dest);
5476 
5477   if (reg_base == reg_src)
5478     {
5479       return !mem_volatile_p && reg_unused_after (insn, src)
5480         ? avr_asm_len ("mov __tmp_reg__,%B1"   CR_TAB
5481                        "st %0,%A1"             CR_TAB
5482                        TINY_ADIW (%E0, %F0, 1) CR_TAB
5483                        "st %0,__tmp_reg__", op, plen, -5)
5484         : avr_asm_len ("mov __tmp_reg__,%B1"   CR_TAB
5485                        TINY_ADIW (%E0, %F0, 1) CR_TAB
5486                        "st %0,__tmp_reg__"     CR_TAB
5487                        TINY_SBIW (%E0, %F0, 1) CR_TAB
5488                        "st %0, %A1", op, plen, -7);
5489     }
5490 
5491   return !mem_volatile_p && reg_unused_after (insn, base)
5492     ? avr_asm_len ("st %0+,%A1" CR_TAB
5493                    "st %0,%B1", op, plen, -2)
5494     : avr_asm_len (TINY_ADIW (%E0, %F0, 1) CR_TAB
5495                    "st %0,%B1"             CR_TAB
5496                    "st -%0,%A1", op, plen, -4);
5497 }
5498 
5499 static const char*
avr_out_movhi_mr_r_reg_disp_tiny(rtx_insn * insn,rtx op[],int * plen)5500 avr_out_movhi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5501 {
5502   rtx dest = op[0];
5503   rtx src = op[1];
5504   rtx base = XEXP (dest, 0);
5505   int reg_base = REGNO (XEXP (base, 0));
5506   int reg_src = true_regnum (src);
5507 
5508   if (reg_src == reg_base)
5509     avr_asm_len ("mov __tmp_reg__,%A1"          CR_TAB
5510                  "mov __zero_reg__,%B1"         CR_TAB
5511                  TINY_ADIW (%I0, %J0, %o0+1)    CR_TAB
5512                  "st %b0,__zero_reg__"          CR_TAB
5513                  "st -%b0,__tmp_reg__"          CR_TAB
5514                  "clr __zero_reg__", op, plen, -7);
5515   else
5516     avr_asm_len (TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
5517                  "st %b0,%B1"                CR_TAB
5518                  "st -%b0,%A1", op, plen, -4);
5519 
5520   if (!reg_unused_after (insn, XEXP (base, 0)))
5521     avr_asm_len (TINY_SBIW (%I0, %J0, %o0), op, plen, 2);
5522 
5523   return "";
5524 }
5525 
5526 static const char*
avr_out_movhi_mr_r_post_inc_tiny(rtx op[],int * plen)5527 avr_out_movhi_mr_r_post_inc_tiny (rtx op[], int *plen)
5528 {
5529   return avr_asm_len (TINY_ADIW (%I0, %J0, 1)  CR_TAB
5530                       "st %p0,%B1"    CR_TAB
5531                       "st -%p0,%A1"   CR_TAB
5532                       TINY_ADIW (%I0, %J0, 2), op, plen, -6);
5533 }
5534 
5535 static const char*
out_movhi_mr_r(rtx_insn * insn,rtx op[],int * plen)5536 out_movhi_mr_r (rtx_insn *insn, rtx op[], int *plen)
5537 {
5538   rtx dest = op[0];
5539   rtx src = op[1];
5540   rtx base = XEXP (dest, 0);
5541   int reg_base = true_regnum (base);
5542   int reg_src = true_regnum (src);
5543   int mem_volatile_p;
5544 
5545   /* "volatile" forces writing high-byte first (no-xmega) resp.
5546      low-byte first (xmega) even if less efficient, for correct
5547      operation with 16-bit I/O registers like.  */
5548 
5549   if (AVR_XMEGA)
5550     return avr_out_movhi_mr_r_xmega (insn, op, plen);
5551 
5552   mem_volatile_p = MEM_VOLATILE_P (dest);
5553 
5554   if (CONSTANT_ADDRESS_P (base))
5555     {
5556       int n_words = AVR_TINY ? 2 : 4;
5557       return io_address_operand (base, HImode)
5558         ? avr_asm_len ("out %i0+1,%B1" CR_TAB
5559                        "out %i0,%A1", op, plen, -2)
5560 
5561         : avr_asm_len ("sts %m0+1,%B1" CR_TAB
5562                        "sts %m0,%A1", op, plen, -n_words);
5563     }
5564 
5565   if (reg_base > 0)
5566     {
5567       if (AVR_TINY)
5568         return avr_out_movhi_mr_r_reg_no_disp_tiny (insn, op, plen);
5569 
5570       if (reg_base != REG_X)
5571         return avr_asm_len ("std %0+1,%B1" CR_TAB
5572                             "st %0,%A1", op, plen, -2);
5573 
5574       if (reg_src == REG_X)
5575         /* "st X+,r26" and "st -X,r26" are undefined.  */
5576         return !mem_volatile_p && reg_unused_after (insn, src)
5577           ? avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5578                          "st X,r26"            CR_TAB
5579                          "adiw r26,1"          CR_TAB
5580                          "st X,__tmp_reg__", op, plen, -4)
5581 
5582           : avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5583                          "adiw r26,1"          CR_TAB
5584                          "st X,__tmp_reg__"    CR_TAB
5585                          "sbiw r26,1"          CR_TAB
5586                          "st X,r26", op, plen, -5);
5587 
5588       return !mem_volatile_p && reg_unused_after (insn, base)
5589         ? avr_asm_len ("st X+,%A1" CR_TAB
5590                        "st X,%B1", op, plen, -2)
5591         : avr_asm_len ("adiw r26,1" CR_TAB
5592                        "st X,%B1"   CR_TAB
5593                        "st -X,%A1", op, plen, -3);
5594     }
5595   else if (GET_CODE (base) == PLUS)
5596     {
5597       int disp = INTVAL (XEXP (base, 1));
5598 
5599       if (AVR_TINY)
5600         return avr_out_movhi_mr_r_reg_disp_tiny (insn, op, plen);
5601 
5602       reg_base = REGNO (XEXP (base, 0));
5603       if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5604         {
5605           if (reg_base != REG_Y)
5606             fatal_insn ("incorrect insn:",insn);
5607 
5608           return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
5609             ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
5610                            "std Y+63,%B1"    CR_TAB
5611                            "std Y+62,%A1"    CR_TAB
5612                            "sbiw r28,%o0-62", op, plen, -4)
5613 
5614             : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5615                            "sbci r29,hi8(-%o0)" CR_TAB
5616                            "std Y+1,%B1"        CR_TAB
5617                            "st Y,%A1"           CR_TAB
5618                            "subi r28,lo8(%o0)"  CR_TAB
5619                            "sbci r29,hi8(%o0)", op, plen, -6);
5620         }
5621 
5622       if (reg_base != REG_X)
5623         return avr_asm_len ("std %B0,%B1" CR_TAB
5624                             "std %A0,%A1", op, plen, -2);
5625       /* (X + d) = R */
5626       return reg_src == REG_X
5627         ? avr_asm_len ("mov __tmp_reg__,r26"  CR_TAB
5628                        "mov __zero_reg__,r27" CR_TAB
5629                        "adiw r26,%o0+1"       CR_TAB
5630                        "st X,__zero_reg__"    CR_TAB
5631                        "st -X,__tmp_reg__"    CR_TAB
5632                        "clr __zero_reg__"     CR_TAB
5633                        "sbiw r26,%o0", op, plen, -7)
5634 
5635         : avr_asm_len ("adiw r26,%o0+1" CR_TAB
5636                        "st X,%B1"       CR_TAB
5637                        "st -X,%A1"      CR_TAB
5638                        "sbiw r26,%o0", op, plen, -4);
5639     }
5640   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5641     {
5642       return avr_asm_len ("st %0,%B1" CR_TAB
5643                           "st %0,%A1", op, plen, -2);
5644     }
5645   else if (GET_CODE (base) == POST_INC) /* (R++) */
5646     {
5647       if (!mem_volatile_p)
5648         return avr_asm_len ("st %0,%A1"  CR_TAB
5649                             "st %0,%B1", op, plen, -2);
5650 
5651       if (AVR_TINY)
5652         return avr_out_movhi_mr_r_post_inc_tiny (op, plen);
5653 
5654       return REGNO (XEXP (base, 0)) == REG_X
5655         ? avr_asm_len ("adiw r26,1"  CR_TAB
5656                        "st X,%B1"    CR_TAB
5657                        "st -X,%A1"   CR_TAB
5658                        "adiw r26,2", op, plen, -4)
5659 
5660         : avr_asm_len ("std %p0+1,%B1" CR_TAB
5661                        "st %p0,%A1"    CR_TAB
5662                        "adiw %r0,2", op, plen, -3);
5663     }
5664   fatal_insn ("unknown move insn:",insn);
5665   return "";
5666 }
5667 
5668 /* Return 1 if frame pointer for current function required.  */
5669 
5670 static bool
avr_frame_pointer_required_p(void)5671 avr_frame_pointer_required_p (void)
5672 {
5673   return (cfun->calls_alloca
5674           || cfun->calls_setjmp
5675           || cfun->has_nonlocal_label
5676           || crtl->args.info.nregs == 0
5677           || get_frame_size () > 0);
5678 }
5679 
5680 /* Returns the condition of compare insn INSN, or UNKNOWN.  */
5681 
5682 static RTX_CODE
compare_condition(rtx_insn * insn)5683 compare_condition (rtx_insn *insn)
5684 {
5685   rtx_insn *next = next_real_insn (insn);
5686 
5687   if (next && JUMP_P (next))
5688     {
5689       rtx pat = PATTERN (next);
5690       if (GET_CODE (pat) == PARALLEL)
5691         pat = XVECEXP (pat, 0, 0);
5692       rtx src = SET_SRC (pat);
5693 
5694       if (IF_THEN_ELSE == GET_CODE (src))
5695         return GET_CODE (XEXP (src, 0));
5696     }
5697 
5698   return UNKNOWN;
5699 }
5700 
5701 
5702 /* Returns true iff INSN is a tst insn that only tests the sign.  */
5703 
5704 static bool
compare_sign_p(rtx_insn * insn)5705 compare_sign_p (rtx_insn *insn)
5706 {
5707   RTX_CODE cond = compare_condition (insn);
5708   return (cond == GE || cond == LT);
5709 }
5710 
5711 
5712 /* Returns true iff the next insn is a JUMP_INSN with a condition
5713    that needs to be swapped (GT, GTU, LE, LEU).  */
5714 
5715 static bool
compare_diff_p(rtx_insn * insn)5716 compare_diff_p (rtx_insn *insn)
5717 {
5718   RTX_CODE cond = compare_condition (insn);
5719   return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
5720 }
5721 
5722 /* Returns true iff INSN is a compare insn with the EQ or NE condition.  */
5723 
5724 static bool
compare_eq_p(rtx_insn * insn)5725 compare_eq_p (rtx_insn *insn)
5726 {
5727   RTX_CODE cond = compare_condition (insn);
5728   return (cond == EQ || cond == NE);
5729 }
5730 
5731 
5732 /* Output compare instruction
5733 
5734       compare (XOP[0], XOP[1])
5735 
5736    for a register XOP[0] and a compile-time constant XOP[1].  Return "".
5737    XOP[2] is an 8-bit scratch register as needed.
5738 
5739    PLEN == NULL:  Output instructions.
5740    PLEN != NULL:  Set *PLEN to the length (in words) of the sequence.
5741                   Don't output anything.  */
5742 
5743 const char*
avr_out_compare(rtx_insn * insn,rtx * xop,int * plen)5744 avr_out_compare (rtx_insn *insn, rtx *xop, int *plen)
5745 {
5746   /* Register to compare and value to compare against. */
5747   rtx xreg = xop[0];
5748   rtx xval = xop[1];
5749 
5750   /* MODE of the comparison.  */
5751   machine_mode mode;
5752 
5753   /* Number of bytes to operate on.  */
5754   int n_bytes = GET_MODE_SIZE (GET_MODE (xreg));
5755 
5756   /* Value (0..0xff) held in clobber register xop[2] or -1 if unknown.  */
5757   int clobber_val = -1;
5758 
5759   /* Map fixed mode operands to integer operands with the same binary
5760      representation.  They are easier to handle in the remainder.  */
5761 
5762   if (CONST_FIXED_P (xval))
5763     {
5764       xreg = avr_to_int_mode (xop[0]);
5765       xval = avr_to_int_mode (xop[1]);
5766     }
5767 
5768   mode = GET_MODE (xreg);
5769 
5770   gcc_assert (REG_P (xreg));
5771   gcc_assert ((CONST_INT_P (xval) && n_bytes <= 4)
5772               || (const_double_operand (xval, VOIDmode) && n_bytes == 8));
5773 
5774   if (plen)
5775     *plen = 0;
5776 
5777   /* Comparisons == +/-1 and != +/-1 can be done similar to camparing
5778      against 0 by ORing the bytes.  This is one instruction shorter.
5779      Notice that 64-bit comparisons are always against reg:ALL8 18 (ACC_A)
5780      and therefore don't use this.  */
5781 
5782   if (!test_hard_reg_class (LD_REGS, xreg)
5783       && compare_eq_p (insn)
5784       && reg_unused_after (insn, xreg))
5785     {
5786       if (xval == const1_rtx)
5787         {
5788           avr_asm_len ("dec %A0" CR_TAB
5789                        "or %A0,%B0", xop, plen, 2);
5790 
5791           if (n_bytes >= 3)
5792             avr_asm_len ("or %A0,%C0", xop, plen, 1);
5793 
5794           if (n_bytes >= 4)
5795             avr_asm_len ("or %A0,%D0", xop, plen, 1);
5796 
5797           return "";
5798         }
5799       else if (xval == constm1_rtx)
5800         {
5801           if (n_bytes >= 4)
5802             avr_asm_len ("and %A0,%D0", xop, plen, 1);
5803 
5804           if (n_bytes >= 3)
5805             avr_asm_len ("and %A0,%C0", xop, plen, 1);
5806 
5807           return avr_asm_len ("and %A0,%B0" CR_TAB
5808                               "com %A0", xop, plen, 2);
5809         }
5810     }
5811 
5812   /* Comparisons == -1 and != -1 of a d-register that's used after the
5813      comparison.  (If it's unused after we use CPI / SBCI or ADIW sequence
5814      from below.)  Instead of  CPI Rlo,-1 / LDI Rx,-1 / CPC Rhi,Rx  we can
5815      use  CPI Rlo,-1 / CPC Rhi,Rlo  which is 1 instruction shorter:
5816      If CPI is true then Rlo contains -1 and we can use Rlo instead of Rx
5817      when CPC'ing the high part.  If CPI is false then CPC cannot render
5818      the result to true.  This also works for the more generic case where
5819      the constant is of the form 0xabab.  */
5820 
5821   if (n_bytes == 2
5822       && xval != const0_rtx
5823       && test_hard_reg_class (LD_REGS, xreg)
5824       && compare_eq_p (insn)
5825       && !reg_unused_after (insn, xreg))
5826     {
5827       rtx xlo8 = simplify_gen_subreg (QImode, xval, mode, 0);
5828       rtx xhi8 = simplify_gen_subreg (QImode, xval, mode, 1);
5829 
5830       if (INTVAL (xlo8) == INTVAL (xhi8))
5831         {
5832           xop[0] = xreg;
5833           xop[1] = xlo8;
5834 
5835           return avr_asm_len ("cpi %A0,%1"  CR_TAB
5836                               "cpc %B0,%A0", xop, plen, 2);
5837         }
5838     }
5839 
5840   for (int i = 0; i < n_bytes; i++)
5841     {
5842       /* We compare byte-wise.  */
5843       rtx reg8 = simplify_gen_subreg (QImode, xreg, mode, i);
5844       rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
5845 
5846       /* 8-bit value to compare with this byte.  */
5847       unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
5848 
5849       /* Registers R16..R31 can operate with immediate.  */
5850       bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
5851 
5852       xop[0] = reg8;
5853       xop[1] = gen_int_mode (val8, QImode);
5854 
5855       /* Word registers >= R24 can use SBIW/ADIW with 0..63.  */
5856 
5857       if (i == 0
5858           && test_hard_reg_class (ADDW_REGS, reg8))
5859         {
5860           int val16 = trunc_int_for_mode (INTVAL (xval), HImode);
5861 
5862           if (IN_RANGE (val16, 0, 63)
5863               && (val8 == 0
5864                   || reg_unused_after (insn, xreg)))
5865             {
5866               if (AVR_TINY)
5867                 avr_asm_len (TINY_SBIW (%A0, %B0, %1), xop, plen, 2);
5868               else
5869                 avr_asm_len ("sbiw %0,%1", xop, plen, 1);
5870 
5871               i++;
5872               continue;
5873             }
5874 
5875           if (n_bytes == 2
5876               && IN_RANGE (val16, -63, -1)
5877               && compare_eq_p (insn)
5878               && reg_unused_after (insn, xreg))
5879             {
5880               return AVR_TINY
5881                 ? avr_asm_len (TINY_ADIW (%A0, %B0, %n1), xop, plen, 2)
5882                 : avr_asm_len ("adiw %0,%n1", xop, plen, 1);
5883             }
5884         }
5885 
5886       /* Comparing against 0 is easy.  */
5887 
5888       if (val8 == 0)
5889         {
5890           avr_asm_len (i == 0
5891                        ? "cp %0,__zero_reg__"
5892                        : "cpc %0,__zero_reg__", xop, plen, 1);
5893           continue;
5894         }
5895 
5896       /* Upper registers can compare and subtract-with-carry immediates.
5897          Notice that compare instructions do the same as respective subtract
5898          instruction; the only difference is that comparisons don't write
5899          the result back to the target register.  */
5900 
5901       if (ld_reg_p)
5902         {
5903           if (i == 0)
5904             {
5905               avr_asm_len ("cpi %0,%1", xop, plen, 1);
5906               continue;
5907             }
5908           else if (reg_unused_after (insn, xreg))
5909             {
5910               avr_asm_len ("sbci %0,%1", xop, plen, 1);
5911               continue;
5912             }
5913         }
5914 
5915       /* Must load the value into the scratch register.  */
5916 
5917       gcc_assert (REG_P (xop[2]));
5918 
5919       if (clobber_val != (int) val8)
5920         avr_asm_len ("ldi %2,%1", xop, plen, 1);
5921       clobber_val = (int) val8;
5922 
5923       avr_asm_len (i == 0
5924                    ? "cp %0,%2"
5925                    : "cpc %0,%2", xop, plen, 1);
5926     }
5927 
5928   return "";
5929 }
5930 
5931 
5932 /* Prepare operands of compare_const_di2 to be used with avr_out_compare.  */
5933 
5934 const char*
avr_out_compare64(rtx_insn * insn,rtx * op,int * plen)5935 avr_out_compare64 (rtx_insn *insn, rtx *op, int *plen)
5936 {
5937   rtx xop[3];
5938 
5939   xop[0] = gen_rtx_REG (DImode, 18);
5940   xop[1] = op[0];
5941   xop[2] = op[1];
5942 
5943   return avr_out_compare (insn, xop, plen);
5944 }
5945 
5946 /* Output test instruction for HImode.  */
5947 
5948 const char*
avr_out_tsthi(rtx_insn * insn,rtx * op,int * plen)5949 avr_out_tsthi (rtx_insn *insn, rtx *op, int *plen)
5950 {
5951   if (compare_sign_p (insn))
5952     {
5953       avr_asm_len ("tst %B0", op, plen, -1);
5954     }
5955   else if (reg_unused_after (insn, op[0])
5956            && compare_eq_p (insn))
5957     {
5958       /* Faster than sbiw if we can clobber the operand.  */
5959       avr_asm_len ("or %A0,%B0", op, plen, -1);
5960     }
5961   else
5962     {
5963       avr_out_compare (insn, op, plen);
5964     }
5965 
5966   return "";
5967 }
5968 
5969 
5970 /* Output test instruction for PSImode.  */
5971 
5972 const char*
avr_out_tstpsi(rtx_insn * insn,rtx * op,int * plen)5973 avr_out_tstpsi (rtx_insn *insn, rtx *op, int *plen)
5974 {
5975   if (compare_sign_p (insn))
5976     {
5977       avr_asm_len ("tst %C0", op, plen, -1);
5978     }
5979   else if (reg_unused_after (insn, op[0])
5980            && compare_eq_p (insn))
5981     {
5982       /* Faster than sbiw if we can clobber the operand.  */
5983       avr_asm_len ("or %A0,%B0" CR_TAB
5984                    "or %A0,%C0", op, plen, -2);
5985     }
5986   else
5987     {
5988       avr_out_compare (insn, op, plen);
5989     }
5990 
5991   return "";
5992 }
5993 
5994 
5995 /* Output test instruction for SImode.  */
5996 
5997 const char*
avr_out_tstsi(rtx_insn * insn,rtx * op,int * plen)5998 avr_out_tstsi (rtx_insn *insn, rtx *op, int *plen)
5999 {
6000   if (compare_sign_p (insn))
6001     {
6002       avr_asm_len ("tst %D0", op, plen, -1);
6003     }
6004   else if (reg_unused_after (insn, op[0])
6005            && compare_eq_p (insn))
6006     {
6007       /* Faster than sbiw if we can clobber the operand.  */
6008       avr_asm_len ("or %A0,%B0" CR_TAB
6009                    "or %A0,%C0" CR_TAB
6010                    "or %A0,%D0", op, plen, -3);
6011     }
6012   else
6013     {
6014       avr_out_compare (insn, op, plen);
6015     }
6016 
6017   return "";
6018 }
6019 
6020 
6021 /* Generate asm equivalent for various shifts.  This only handles cases
6022    that are not already carefully hand-optimized in ?sh??i3_out.
6023 
6024    OPERANDS[0] resp. %0 in TEMPL is the operand to be shifted.
6025    OPERANDS[2] is the shift count as CONST_INT, MEM or REG.
6026    OPERANDS[3] is a QImode scratch register from LD regs if
6027                available and SCRATCH, otherwise (no scratch available)
6028 
6029    TEMPL is an assembler template that shifts by one position.
6030    T_LEN is the length of this template.  */
6031 
6032 void
out_shift_with_cnt(const char * templ,rtx_insn * insn,rtx operands[],int * plen,int t_len)6033 out_shift_with_cnt (const char *templ, rtx_insn *insn, rtx operands[],
6034 		    int *plen, int t_len)
6035 {
6036   bool second_label = true;
6037   bool saved_in_tmp = false;
6038   bool use_zero_reg = false;
6039   rtx op[5];
6040 
6041   op[0] = operands[0];
6042   op[1] = operands[1];
6043   op[2] = operands[2];
6044   op[3] = operands[3];
6045 
6046   if (plen)
6047     *plen = 0;
6048 
6049   if (CONST_INT_P (operands[2]))
6050     {
6051       /* Operand 3 is a scratch register if this is a
6052          parallel with three elements i.e. a set,
6053          a clobber of a scratch, and clobber of REG_CC.
6054          If a scratch reg is not available, then the parallel
6055          will contain only a set and clobber of REG_CC. */
6056       bool scratch = (GET_CODE (PATTERN (insn)) == PARALLEL
6057                       && XVECLEN (PATTERN (insn), 0) == 3
6058                       && REG_P (operands[3]));
6059       int count = INTVAL (operands[2]);
6060       int max_len = 10;  /* If larger than this, always use a loop.  */
6061 
6062       if (count <= 0)
6063         return;
6064 
6065       if (count < 8 && !scratch)
6066         use_zero_reg = true;
6067 
6068       if (optimize_size)
6069         max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
6070 
6071       if (t_len * count <= max_len)
6072         {
6073           /* Output shifts inline with no loop - faster.  */
6074 
6075           while (count-- > 0)
6076             avr_asm_len (templ, op, plen, t_len);
6077 
6078           return;
6079         }
6080 
6081       if (scratch)
6082         {
6083           avr_asm_len ("ldi %3,%2", op, plen, 1);
6084         }
6085       else if (use_zero_reg)
6086         {
6087           /* Hack to save one word: use __zero_reg__ as loop counter.
6088              Set one bit, then shift in a loop until it is 0 again.  */
6089 
6090           op[3] = zero_reg_rtx;
6091 
6092           avr_asm_len ("set" CR_TAB
6093                        "bld %3,%2-1", op, plen, 2);
6094         }
6095       else
6096         {
6097           /* No scratch register available, use one from LD_REGS (saved in
6098              __tmp_reg__) that doesn't overlap with registers to shift.  */
6099 
6100           op[3] = all_regs_rtx[((REGNO (op[0]) - 1) & 15) + 16];
6101           op[4] = tmp_reg_rtx;
6102           saved_in_tmp = true;
6103 
6104           avr_asm_len ("mov %4,%3" CR_TAB
6105                        "ldi %3,%2", op, plen, 2);
6106         }
6107 
6108       second_label = false;
6109     }
6110   else if (MEM_P (op[2]))
6111     {
6112       rtx op_mov[2];
6113 
6114       op_mov[0] = op[3] = tmp_reg_rtx;
6115       op_mov[1] = op[2];
6116 
6117       out_movqi_r_mr (insn, op_mov, plen);
6118     }
6119   else if (register_operand (op[2], QImode))
6120     {
6121       op[3] = op[2];
6122 
6123       if (!reg_unused_after (insn, op[2])
6124           || reg_overlap_mentioned_p (op[0], op[2]))
6125         {
6126           op[3] = tmp_reg_rtx;
6127           avr_asm_len ("mov %3,%2", op, plen, 1);
6128         }
6129     }
6130   else
6131     fatal_insn ("bad shift insn:", insn);
6132 
6133   if (second_label)
6134     avr_asm_len ("rjmp 2f", op, plen, 1);
6135 
6136   avr_asm_len ("1:", op, plen, 0);
6137   avr_asm_len (templ, op, plen, t_len);
6138 
6139   if (second_label)
6140     avr_asm_len ("2:", op, plen, 0);
6141 
6142   avr_asm_len (use_zero_reg ? "lsr %3" : "dec %3", op, plen, 1);
6143   avr_asm_len (second_label ? "brpl 1b" : "brne 1b", op, plen, 1);
6144 
6145   if (saved_in_tmp)
6146     avr_asm_len ("mov %3,%4", op, plen, 1);
6147 }
6148 
6149 
6150 /* 8bit shift left ((char)x << i)   */
6151 
6152 const char *
ashlqi3_out(rtx_insn * insn,rtx operands[],int * len)6153 ashlqi3_out (rtx_insn *insn, rtx operands[], int *len)
6154 {
6155   if (CONST_INT_P (operands[2]))
6156     {
6157       int k;
6158 
6159       if (!len)
6160 	len = &k;
6161 
6162       switch (INTVAL (operands[2]))
6163 	{
6164 	default:
6165 	  if (INTVAL (operands[2]) < 8)
6166 	    break;
6167 
6168 	  *len = 1;
6169 	  return "clr %0";
6170 
6171 	case 1:
6172 	  *len = 1;
6173 	  return "lsl %0";
6174 
6175 	case 2:
6176 	  *len = 2;
6177 	  return ("lsl %0" CR_TAB
6178 		  "lsl %0");
6179 
6180 	case 3:
6181 	  *len = 3;
6182 	  return ("lsl %0" CR_TAB
6183 		  "lsl %0" CR_TAB
6184 		  "lsl %0");
6185 
6186 	case 4:
6187 	  if (test_hard_reg_class (LD_REGS, operands[0]))
6188 	    {
6189 	      *len = 2;
6190 	      return ("swap %0" CR_TAB
6191 		      "andi %0,0xf0");
6192 	    }
6193 	  *len = 4;
6194 	  return ("lsl %0" CR_TAB
6195 		  "lsl %0" CR_TAB
6196 		  "lsl %0" CR_TAB
6197 		  "lsl %0");
6198 
6199 	case 5:
6200 	  if (test_hard_reg_class (LD_REGS, operands[0]))
6201 	    {
6202 	      *len = 3;
6203 	      return ("swap %0" CR_TAB
6204 		      "lsl %0"  CR_TAB
6205 		      "andi %0,0xe0");
6206 	    }
6207 	  *len = 5;
6208 	  return ("lsl %0" CR_TAB
6209 		  "lsl %0" CR_TAB
6210 		  "lsl %0" CR_TAB
6211 		  "lsl %0" CR_TAB
6212 		  "lsl %0");
6213 
6214 	case 6:
6215 	  if (test_hard_reg_class (LD_REGS, operands[0]))
6216 	    {
6217 	      *len = 4;
6218 	      return ("swap %0" CR_TAB
6219 		      "lsl %0"  CR_TAB
6220 		      "lsl %0"  CR_TAB
6221 		      "andi %0,0xc0");
6222 	    }
6223 	  *len = 6;
6224 	  return ("lsl %0" CR_TAB
6225 		  "lsl %0" CR_TAB
6226 		  "lsl %0" CR_TAB
6227 		  "lsl %0" CR_TAB
6228 		  "lsl %0" CR_TAB
6229 		  "lsl %0");
6230 
6231 	case 7:
6232 	  *len = 3;
6233 	  return ("ror %0" CR_TAB
6234 		  "clr %0" CR_TAB
6235 		  "ror %0");
6236 	}
6237     }
6238   else if (CONSTANT_P (operands[2]))
6239     fatal_insn ("internal compiler error.  Incorrect shift:", insn);
6240 
6241   out_shift_with_cnt ("lsl %0",
6242                       insn, operands, len, 1);
6243   return "";
6244 }
6245 
6246 
6247 /* 16bit shift left ((short)x << i)   */
6248 
6249 const char *
ashlhi3_out(rtx_insn * insn,rtx operands[],int * len)6250 ashlhi3_out (rtx_insn *insn, rtx operands[], int *len)
6251 {
6252   if (CONST_INT_P (operands[2]))
6253     {
6254       int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL
6255                      && XVECLEN (PATTERN (insn), 0) == 3
6256                      && REG_P (operands[3]));
6257       int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
6258       int k;
6259       int *t = len;
6260 
6261       if (!len)
6262 	len = &k;
6263 
6264       switch (INTVAL (operands[2]))
6265 	{
6266 	default:
6267 	  if (INTVAL (operands[2]) < 16)
6268 	    break;
6269 
6270 	  *len = 2;
6271 	  return ("clr %B0" CR_TAB
6272 		  "clr %A0");
6273 
6274 	case 4:
6275 	  if (optimize_size && scratch)
6276 	    break;  /* 5 */
6277 	  if (ldi_ok)
6278 	    {
6279 	      *len = 6;
6280 	      return ("swap %A0"      CR_TAB
6281 		      "swap %B0"      CR_TAB
6282 		      "andi %B0,0xf0" CR_TAB
6283 		      "eor %B0,%A0"   CR_TAB
6284 		      "andi %A0,0xf0" CR_TAB
6285 		      "eor %B0,%A0");
6286 	    }
6287 	  if (scratch)
6288 	    {
6289 	      *len = 7;
6290 	      return ("swap %A0"    CR_TAB
6291 		      "swap %B0"    CR_TAB
6292 		      "ldi %3,0xf0" CR_TAB
6293 		      "and %B0,%3"  CR_TAB
6294 		      "eor %B0,%A0" CR_TAB
6295 		      "and %A0,%3"  CR_TAB
6296 		      "eor %B0,%A0");
6297 	    }
6298 	  break;  /* optimize_size ? 6 : 8 */
6299 
6300 	case 5:
6301 	  if (optimize_size)
6302 	    break;  /* scratch ? 5 : 6 */
6303 	  if (ldi_ok)
6304 	    {
6305 	      *len = 8;
6306 	      return ("lsl %A0"       CR_TAB
6307 		      "rol %B0"       CR_TAB
6308 		      "swap %A0"      CR_TAB
6309 		      "swap %B0"      CR_TAB
6310 		      "andi %B0,0xf0" CR_TAB
6311 		      "eor %B0,%A0"   CR_TAB
6312 		      "andi %A0,0xf0" CR_TAB
6313 		      "eor %B0,%A0");
6314 	    }
6315 	  if (scratch)
6316 	    {
6317 	      *len = 9;
6318 	      return ("lsl %A0"     CR_TAB
6319 		      "rol %B0"     CR_TAB
6320 		      "swap %A0"    CR_TAB
6321 		      "swap %B0"    CR_TAB
6322 		      "ldi %3,0xf0" CR_TAB
6323 		      "and %B0,%3"  CR_TAB
6324 		      "eor %B0,%A0" CR_TAB
6325 		      "and %A0,%3"  CR_TAB
6326 		      "eor %B0,%A0");
6327 	    }
6328 	  break;  /* 10 */
6329 
6330 	case 6:
6331 	  if (optimize_size)
6332 	    break;  /* scratch ? 5 : 6 */
6333 	  *len = 9;
6334 	  return ("clr __tmp_reg__" CR_TAB
6335 		  "lsr %B0"         CR_TAB
6336 		  "ror %A0"         CR_TAB
6337 		  "ror __tmp_reg__" CR_TAB
6338 		  "lsr %B0"         CR_TAB
6339 		  "ror %A0"         CR_TAB
6340 		  "ror __tmp_reg__" CR_TAB
6341 		  "mov %B0,%A0"     CR_TAB
6342 		  "mov %A0,__tmp_reg__");
6343 
6344 	case 7:
6345 	  *len = 5;
6346 	  return ("lsr %B0"     CR_TAB
6347 		  "mov %B0,%A0" CR_TAB
6348 		  "clr %A0"     CR_TAB
6349 		  "ror %B0"     CR_TAB
6350 		  "ror %A0");
6351 
6352 	case 8:
6353 	  return *len = 2, ("mov %B0,%A1" CR_TAB
6354 			    "clr %A0");
6355 
6356 	case 9:
6357 	  *len = 3;
6358 	  return ("mov %B0,%A0" CR_TAB
6359 		  "clr %A0"     CR_TAB
6360 		  "lsl %B0");
6361 
6362 	case 10:
6363 	  *len = 4;
6364 	  return ("mov %B0,%A0" CR_TAB
6365 		  "clr %A0"     CR_TAB
6366 		  "lsl %B0"     CR_TAB
6367 		  "lsl %B0");
6368 
6369 	case 11:
6370 	  *len = 5;
6371 	  return ("mov %B0,%A0" CR_TAB
6372 		  "clr %A0"     CR_TAB
6373 		  "lsl %B0"     CR_TAB
6374 		  "lsl %B0"     CR_TAB
6375 		  "lsl %B0");
6376 
6377 	case 12:
6378 	  if (ldi_ok)
6379 	    {
6380 	      *len = 4;
6381 	      return ("mov %B0,%A0" CR_TAB
6382 		      "clr %A0"     CR_TAB
6383 		      "swap %B0"    CR_TAB
6384 		      "andi %B0,0xf0");
6385 	    }
6386 	  if (scratch)
6387 	    {
6388 	      *len = 5;
6389 	      return ("mov %B0,%A0" CR_TAB
6390 		      "clr %A0"     CR_TAB
6391 		      "swap %B0"    CR_TAB
6392 		      "ldi %3,0xf0" CR_TAB
6393 		      "and %B0,%3");
6394 	    }
6395 	  *len = 6;
6396 	  return ("mov %B0,%A0" CR_TAB
6397 		  "clr %A0"     CR_TAB
6398 		  "lsl %B0"     CR_TAB
6399 		  "lsl %B0"     CR_TAB
6400 		  "lsl %B0"     CR_TAB
6401 		  "lsl %B0");
6402 
6403 	case 13:
6404 	  if (ldi_ok)
6405 	    {
6406 	      *len = 5;
6407 	      return ("mov %B0,%A0" CR_TAB
6408 		      "clr %A0"     CR_TAB
6409 		      "swap %B0"    CR_TAB
6410 		      "lsl %B0"     CR_TAB
6411 		      "andi %B0,0xe0");
6412 	    }
6413 	  if (AVR_HAVE_MUL && scratch)
6414 	    {
6415 	      *len = 5;
6416 	      return ("ldi %3,0x20" CR_TAB
6417 		      "mul %A0,%3"  CR_TAB
6418 		      "mov %B0,r0"  CR_TAB
6419 		      "clr %A0"     CR_TAB
6420 		      "clr __zero_reg__");
6421 	    }
6422 	  if (optimize_size && scratch)
6423 	    break;  /* 5 */
6424 	  if (scratch)
6425 	    {
6426 	      *len = 6;
6427 	      return ("mov %B0,%A0" CR_TAB
6428 		      "clr %A0"     CR_TAB
6429 		      "swap %B0"    CR_TAB
6430 		      "lsl %B0"     CR_TAB
6431 		      "ldi %3,0xe0" CR_TAB
6432 		      "and %B0,%3");
6433 	    }
6434 	  if (AVR_HAVE_MUL)
6435 	    {
6436 	      *len = 6;
6437 	      return ("set"        CR_TAB
6438 		      "bld r1,5"   CR_TAB
6439 		      "mul %A0,r1" CR_TAB
6440 		      "mov %B0,r0" CR_TAB
6441 		      "clr %A0"    CR_TAB
6442 		      "clr __zero_reg__");
6443 	    }
6444 	  *len = 7;
6445 	  return ("mov %B0,%A0" CR_TAB
6446 		  "clr %A0"     CR_TAB
6447 		  "lsl %B0"     CR_TAB
6448 		  "lsl %B0"     CR_TAB
6449 		  "lsl %B0"     CR_TAB
6450 		  "lsl %B0"     CR_TAB
6451 		  "lsl %B0");
6452 
6453 	case 14:
6454 	  if (AVR_HAVE_MUL && ldi_ok)
6455 	    {
6456 	      *len = 5;
6457 	      return ("ldi %B0,0x40" CR_TAB
6458 		      "mul %A0,%B0"  CR_TAB
6459 		      "mov %B0,r0"   CR_TAB
6460 		      "clr %A0"      CR_TAB
6461 		      "clr __zero_reg__");
6462 	    }
6463 	  if (AVR_HAVE_MUL && scratch)
6464 	    {
6465 	      *len = 5;
6466 	      return ("ldi %3,0x40" CR_TAB
6467 		      "mul %A0,%3"  CR_TAB
6468 		      "mov %B0,r0"  CR_TAB
6469 		      "clr %A0"     CR_TAB
6470 		      "clr __zero_reg__");
6471 	    }
6472 	  if (optimize_size && ldi_ok)
6473 	    {
6474 	      *len = 5;
6475 	      return ("mov %B0,%A0" CR_TAB
6476 		      "ldi %A0,6" "\n1:\t"
6477 		      "lsl %B0"     CR_TAB
6478 		      "dec %A0"     CR_TAB
6479 		      "brne 1b");
6480 	    }
6481 	  if (optimize_size && scratch)
6482 	    break;  /* 5 */
6483 	  *len = 6;
6484 	  return ("clr %B0" CR_TAB
6485 		  "lsr %A0" CR_TAB
6486 		  "ror %B0" CR_TAB
6487 		  "lsr %A0" CR_TAB
6488 		  "ror %B0" CR_TAB
6489 		  "clr %A0");
6490 
6491 	case 15:
6492 	  *len = 4;
6493 	  return ("clr %B0" CR_TAB
6494 		  "lsr %A0" CR_TAB
6495 		  "ror %B0" CR_TAB
6496 		  "clr %A0");
6497 	}
6498       len = t;
6499     }
6500   out_shift_with_cnt ("lsl %A0" CR_TAB
6501                       "rol %B0", insn, operands, len, 2);
6502   return "";
6503 }
6504 
6505 
6506 /* 24-bit shift left */
6507 
6508 const char*
avr_out_ashlpsi3(rtx_insn * insn,rtx * op,int * plen)6509 avr_out_ashlpsi3 (rtx_insn *insn, rtx *op, int *plen)
6510 {
6511   if (plen)
6512     *plen = 0;
6513 
6514   if (CONST_INT_P (op[2]))
6515     {
6516       switch (INTVAL (op[2]))
6517         {
6518         default:
6519           if (INTVAL (op[2]) < 24)
6520             break;
6521 
6522           return avr_asm_len ("clr %A0" CR_TAB
6523                               "clr %B0" CR_TAB
6524                               "clr %C0", op, plen, 3);
6525 
6526         case 8:
6527           {
6528             int reg0 = REGNO (op[0]);
6529             int reg1 = REGNO (op[1]);
6530 
6531             if (reg0 >= reg1)
6532               return avr_asm_len ("mov %C0,%B1"  CR_TAB
6533                                   "mov %B0,%A1"  CR_TAB
6534                                   "clr %A0", op, plen, 3);
6535             else
6536               return avr_asm_len ("clr %A0"      CR_TAB
6537                                   "mov %B0,%A1"  CR_TAB
6538                                   "mov %C0,%B1", op, plen, 3);
6539           }
6540 
6541         case 16:
6542           {
6543             int reg0 = REGNO (op[0]);
6544             int reg1 = REGNO (op[1]);
6545 
6546             if (reg0 + 2 != reg1)
6547               avr_asm_len ("mov %C0,%A0", op, plen, 1);
6548 
6549             return avr_asm_len ("clr %B0"  CR_TAB
6550                                 "clr %A0", op, plen, 2);
6551           }
6552 
6553         case 23:
6554           return avr_asm_len ("clr %C0" CR_TAB
6555                               "lsr %A0" CR_TAB
6556                               "ror %C0" CR_TAB
6557                               "clr %B0" CR_TAB
6558                               "clr %A0", op, plen, 5);
6559         }
6560     }
6561 
6562   out_shift_with_cnt ("lsl %A0" CR_TAB
6563                       "rol %B0" CR_TAB
6564                       "rol %C0", insn, op, plen, 3);
6565   return "";
6566 }
6567 
6568 
6569 /* 32bit shift left ((long)x << i)   */
6570 
6571 const char *
ashlsi3_out(rtx_insn * insn,rtx operands[],int * len)6572 ashlsi3_out (rtx_insn *insn, rtx operands[], int *len)
6573 {
6574   if (CONST_INT_P (operands[2]))
6575     {
6576       int k;
6577       int *t = len;
6578 
6579       if (!len)
6580 	len = &k;
6581 
6582       switch (INTVAL (operands[2]))
6583 	{
6584 	default:
6585 	  if (INTVAL (operands[2]) < 32)
6586 	    break;
6587 
6588 	  if (AVR_HAVE_MOVW)
6589 	    return *len = 3, ("clr %D0" CR_TAB
6590 			      "clr %C0" CR_TAB
6591 			      "movw %A0,%C0");
6592 	  *len = 4;
6593 	  return ("clr %D0" CR_TAB
6594 		  "clr %C0" CR_TAB
6595 		  "clr %B0" CR_TAB
6596 		  "clr %A0");
6597 
6598 	case 8:
6599 	  {
6600 	    int reg0 = true_regnum (operands[0]);
6601 	    int reg1 = true_regnum (operands[1]);
6602 	    *len = 4;
6603 	    if (reg0 >= reg1)
6604 	      return ("mov %D0,%C1"  CR_TAB
6605 		      "mov %C0,%B1"  CR_TAB
6606 		      "mov %B0,%A1"  CR_TAB
6607 		      "clr %A0");
6608 	    else
6609 	      return ("clr %A0"      CR_TAB
6610 		      "mov %B0,%A1"  CR_TAB
6611 		      "mov %C0,%B1"  CR_TAB
6612 		      "mov %D0,%C1");
6613 	  }
6614 
6615 	case 16:
6616 	  {
6617 	    int reg0 = true_regnum (operands[0]);
6618 	    int reg1 = true_regnum (operands[1]);
6619 	    if (reg0 + 2 == reg1)
6620 	      return *len = 2, ("clr %B0"      CR_TAB
6621 				"clr %A0");
6622 	    if (AVR_HAVE_MOVW)
6623 	      return *len = 3, ("movw %C0,%A1" CR_TAB
6624 				"clr %B0"      CR_TAB
6625 				"clr %A0");
6626 	    else
6627 	      return *len = 4, ("mov %C0,%A1"  CR_TAB
6628 				"mov %D0,%B1"  CR_TAB
6629 				"clr %B0"      CR_TAB
6630 				"clr %A0");
6631 	  }
6632 
6633 	case 24:
6634 	  *len = 4;
6635 	  return ("mov %D0,%A1"  CR_TAB
6636 		  "clr %C0"      CR_TAB
6637 		  "clr %B0"      CR_TAB
6638 		  "clr %A0");
6639 
6640 	case 31:
6641 	  *len = 6;
6642 	  return ("clr %D0" CR_TAB
6643 		  "lsr %A0" CR_TAB
6644 		  "ror %D0" CR_TAB
6645 		  "clr %C0" CR_TAB
6646 		  "clr %B0" CR_TAB
6647 		  "clr %A0");
6648 	}
6649       len = t;
6650     }
6651   out_shift_with_cnt ("lsl %A0" CR_TAB
6652                       "rol %B0" CR_TAB
6653                       "rol %C0" CR_TAB
6654                       "rol %D0", insn, operands, len, 4);
6655   return "";
6656 }
6657 
6658 /* 8bit arithmetic shift right  ((signed char)x >> i) */
6659 
6660 const char *
ashrqi3_out(rtx_insn * insn,rtx operands[],int * len)6661 ashrqi3_out (rtx_insn *insn, rtx operands[], int *len)
6662 {
6663   if (CONST_INT_P (operands[2]))
6664     {
6665       int k;
6666 
6667       if (!len)
6668 	len = &k;
6669 
6670       switch (INTVAL (operands[2]))
6671 	{
6672 	case 1:
6673 	  *len = 1;
6674 	  return "asr %0";
6675 
6676 	case 2:
6677 	  *len = 2;
6678 	  return ("asr %0" CR_TAB
6679 		  "asr %0");
6680 
6681 	case 3:
6682 	  *len = 3;
6683 	  return ("asr %0" CR_TAB
6684 		  "asr %0" CR_TAB
6685 		  "asr %0");
6686 
6687 	case 4:
6688 	  *len = 4;
6689 	  return ("asr %0" CR_TAB
6690 		  "asr %0" CR_TAB
6691 		  "asr %0" CR_TAB
6692 		  "asr %0");
6693 
6694 	case 5:
6695 	  *len = 5;
6696 	  return ("asr %0" CR_TAB
6697 		  "asr %0" CR_TAB
6698 		  "asr %0" CR_TAB
6699 		  "asr %0" CR_TAB
6700 		  "asr %0");
6701 
6702 	case 6:
6703 	  *len = 4;
6704 	  return ("bst %0,6"  CR_TAB
6705 		  "lsl %0"    CR_TAB
6706 		  "sbc %0,%0" CR_TAB
6707 		  "bld %0,0");
6708 
6709 	default:
6710 	  if (INTVAL (operands[2]) < 8)
6711 	    break;
6712 
6713 	  /* fall through */
6714 
6715 	case 7:
6716 	  *len = 2;
6717 	  return ("lsl %0" CR_TAB
6718 		  "sbc %0,%0");
6719 	}
6720     }
6721   else if (CONSTANT_P (operands[2]))
6722     fatal_insn ("internal compiler error.  Incorrect shift:", insn);
6723 
6724   out_shift_with_cnt ("asr %0",
6725                       insn, operands, len, 1);
6726   return "";
6727 }
6728 
6729 
6730 /* 16bit arithmetic shift right  ((signed short)x >> i) */
6731 
6732 const char *
ashrhi3_out(rtx_insn * insn,rtx operands[],int * len)6733 ashrhi3_out (rtx_insn *insn, rtx operands[], int *len)
6734 {
6735   if (CONST_INT_P (operands[2]))
6736     {
6737       int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL
6738                      && XVECLEN (PATTERN (insn), 0) == 3
6739                      && REG_P (operands[3]));
6740       int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
6741       int k;
6742       int *t = len;
6743 
6744       if (!len)
6745 	len = &k;
6746 
6747       switch (INTVAL (operands[2]))
6748 	{
6749 	case 4:
6750 	case 5:
6751 	  /* XXX try to optimize this too? */
6752 	  break;
6753 
6754 	case 6:
6755 	  if (optimize_size)
6756 	    break;  /* scratch ? 5 : 6 */
6757 	  *len = 8;
6758 	  return ("mov __tmp_reg__,%A0" CR_TAB
6759 		  "mov %A0,%B0"         CR_TAB
6760 		  "lsl __tmp_reg__"     CR_TAB
6761 		  "rol %A0"             CR_TAB
6762 		  "sbc %B0,%B0"         CR_TAB
6763 		  "lsl __tmp_reg__"     CR_TAB
6764 		  "rol %A0"             CR_TAB
6765 		  "rol %B0");
6766 
6767 	case 7:
6768 	  *len = 4;
6769 	  return ("lsl %A0"     CR_TAB
6770 		  "mov %A0,%B0" CR_TAB
6771 		  "rol %A0"     CR_TAB
6772 		  "sbc %B0,%B0");
6773 
6774 	case 8:
6775 	  {
6776 	    int reg0 = true_regnum (operands[0]);
6777 	    int reg1 = true_regnum (operands[1]);
6778 
6779 	    if (reg0 == reg1)
6780 	      return *len = 3, ("mov %A0,%B0" CR_TAB
6781 				"lsl %B0"     CR_TAB
6782 				"sbc %B0,%B0");
6783 	    else
6784 	      return *len = 4, ("mov %A0,%B1" CR_TAB
6785 			        "clr %B0"     CR_TAB
6786 			        "sbrc %A0,7"  CR_TAB
6787 			        "dec %B0");
6788 	  }
6789 
6790 	case 9:
6791 	  *len = 4;
6792 	  return ("mov %A0,%B0" CR_TAB
6793 		  "lsl %B0"      CR_TAB
6794 		  "sbc %B0,%B0" CR_TAB
6795 		  "asr %A0");
6796 
6797 	case 10:
6798 	  *len = 5;
6799 	  return ("mov %A0,%B0" CR_TAB
6800 		  "lsl %B0"     CR_TAB
6801 		  "sbc %B0,%B0" CR_TAB
6802 		  "asr %A0"     CR_TAB
6803 		  "asr %A0");
6804 
6805 	case 11:
6806 	  if (AVR_HAVE_MUL && ldi_ok)
6807 	    {
6808 	      *len = 5;
6809 	      return ("ldi %A0,0x20" CR_TAB
6810 		      "muls %B0,%A0" CR_TAB
6811 		      "mov %A0,r1"   CR_TAB
6812 		      "sbc %B0,%B0"  CR_TAB
6813 		      "clr __zero_reg__");
6814 	    }
6815 	  if (optimize_size && scratch)
6816 	    break;  /* 5 */
6817 	  *len = 6;
6818 	  return ("mov %A0,%B0" CR_TAB
6819 		  "lsl %B0"     CR_TAB
6820 		  "sbc %B0,%B0" CR_TAB
6821 		  "asr %A0"     CR_TAB
6822 		  "asr %A0"     CR_TAB
6823 		  "asr %A0");
6824 
6825 	case 12:
6826 	  if (AVR_HAVE_MUL && ldi_ok)
6827 	    {
6828 	      *len = 5;
6829 	      return ("ldi %A0,0x10" CR_TAB
6830 		      "muls %B0,%A0" CR_TAB
6831 		      "mov %A0,r1"   CR_TAB
6832 		      "sbc %B0,%B0"  CR_TAB
6833 		      "clr __zero_reg__");
6834 	    }
6835 	  if (optimize_size && scratch)
6836 	    break;  /* 5 */
6837 	  *len = 7;
6838 	  return ("mov %A0,%B0" CR_TAB
6839 		  "lsl %B0"     CR_TAB
6840 		  "sbc %B0,%B0" CR_TAB
6841 		  "asr %A0"     CR_TAB
6842 		  "asr %A0"     CR_TAB
6843 		  "asr %A0"     CR_TAB
6844 		  "asr %A0");
6845 
6846 	case 13:
6847 	  if (AVR_HAVE_MUL && ldi_ok)
6848 	    {
6849 	      *len = 5;
6850 	      return ("ldi %A0,0x08" CR_TAB
6851 		      "muls %B0,%A0" CR_TAB
6852 		      "mov %A0,r1"   CR_TAB
6853 		      "sbc %B0,%B0"  CR_TAB
6854 		      "clr __zero_reg__");
6855 	    }
6856 	  if (optimize_size)
6857 	    break;  /* scratch ? 5 : 7 */
6858 	  *len = 8;
6859 	  return ("mov %A0,%B0" CR_TAB
6860 		  "lsl %B0"     CR_TAB
6861 		  "sbc %B0,%B0" CR_TAB
6862 		  "asr %A0"     CR_TAB
6863 		  "asr %A0"     CR_TAB
6864 		  "asr %A0"     CR_TAB
6865 		  "asr %A0"     CR_TAB
6866 		  "asr %A0");
6867 
6868 	case 14:
6869 	  *len = 5;
6870 	  return ("lsl %B0"     CR_TAB
6871 		  "sbc %A0,%A0" CR_TAB
6872 		  "lsl %B0"     CR_TAB
6873 		  "mov %B0,%A0" CR_TAB
6874 		  "rol %A0");
6875 
6876 	default:
6877 	  if (INTVAL (operands[2]) < 16)
6878 	    break;
6879 
6880 	  /* fall through */
6881 
6882 	case 15:
6883 	  return *len = 3, ("lsl %B0"     CR_TAB
6884 			    "sbc %A0,%A0" CR_TAB
6885 			    "mov %B0,%A0");
6886 	}
6887       len = t;
6888     }
6889   out_shift_with_cnt ("asr %B0" CR_TAB
6890                       "ror %A0", insn, operands, len, 2);
6891   return "";
6892 }
6893 
6894 
6895 /* 24-bit arithmetic shift right */
6896 
6897 const char*
avr_out_ashrpsi3(rtx_insn * insn,rtx * op,int * plen)6898 avr_out_ashrpsi3 (rtx_insn *insn, rtx *op, int *plen)
6899 {
6900   int dest = REGNO (op[0]);
6901   int src = REGNO (op[1]);
6902 
6903   if (CONST_INT_P (op[2]))
6904     {
6905       if (plen)
6906         *plen = 0;
6907 
6908       switch (INTVAL (op[2]))
6909         {
6910         case 8:
6911           if (dest <= src)
6912             return avr_asm_len ("mov %A0,%B1" CR_TAB
6913                                 "mov %B0,%C1" CR_TAB
6914                                 "clr %C0"     CR_TAB
6915                                 "sbrc %B0,7"  CR_TAB
6916                                 "dec %C0", op, plen, 5);
6917           else
6918             return avr_asm_len ("clr %C0"     CR_TAB
6919                                 "sbrc %C1,7"  CR_TAB
6920                                 "dec %C0"     CR_TAB
6921                                 "mov %B0,%C1" CR_TAB
6922                                 "mov %A0,%B1", op, plen, 5);
6923 
6924         case 16:
6925           if (dest != src + 2)
6926             avr_asm_len ("mov %A0,%C1", op, plen, 1);
6927 
6928           return avr_asm_len ("clr %B0"     CR_TAB
6929                               "sbrc %A0,7"  CR_TAB
6930                               "com %B0"     CR_TAB
6931                               "mov %C0,%B0", op, plen, 4);
6932 
6933         default:
6934           if (INTVAL (op[2]) < 24)
6935             break;
6936 
6937           /* fall through */
6938 
6939         case 23:
6940           return avr_asm_len ("lsl %C0"     CR_TAB
6941                               "sbc %A0,%A0" CR_TAB
6942                               "mov %B0,%A0" CR_TAB
6943                               "mov %C0,%A0", op, plen, 4);
6944         } /* switch */
6945     }
6946 
6947   out_shift_with_cnt ("asr %C0" CR_TAB
6948                       "ror %B0" CR_TAB
6949                       "ror %A0", insn, op, plen, 3);
6950   return "";
6951 }
6952 
6953 
6954 /* 32-bit arithmetic shift right  ((signed long)x >> i) */
6955 
6956 const char *
ashrsi3_out(rtx_insn * insn,rtx operands[],int * len)6957 ashrsi3_out (rtx_insn *insn, rtx operands[], int *len)
6958 {
6959   if (CONST_INT_P (operands[2]))
6960     {
6961       int k;
6962       int *t = len;
6963 
6964       if (!len)
6965 	len = &k;
6966 
6967       switch (INTVAL (operands[2]))
6968 	{
6969 	case 8:
6970 	  {
6971 	    int reg0 = true_regnum (operands[0]);
6972 	    int reg1 = true_regnum (operands[1]);
6973 	    *len=6;
6974 	    if (reg0 <= reg1)
6975 	      return ("mov %A0,%B1" CR_TAB
6976 		      "mov %B0,%C1" CR_TAB
6977 		      "mov %C0,%D1" CR_TAB
6978 		      "clr %D0"     CR_TAB
6979 		      "sbrc %C0,7"  CR_TAB
6980 		      "dec %D0");
6981 	    else
6982 	      return ("clr %D0"     CR_TAB
6983 		      "sbrc %D1,7"  CR_TAB
6984 		      "dec %D0"     CR_TAB
6985 		      "mov %C0,%D1" CR_TAB
6986 		      "mov %B0,%C1" CR_TAB
6987 		      "mov %A0,%B1");
6988 	  }
6989 
6990 	case 16:
6991 	  {
6992 	    int reg0 = true_regnum (operands[0]);
6993 	    int reg1 = true_regnum (operands[1]);
6994 
6995 	    if (reg0 == reg1 + 2)
6996 	      return *len = 4, ("clr %D0"     CR_TAB
6997 				"sbrc %B0,7"  CR_TAB
6998 				"com %D0"     CR_TAB
6999 				"mov %C0,%D0");
7000 	    if (AVR_HAVE_MOVW)
7001 	      return *len = 5, ("movw %A0,%C1" CR_TAB
7002 				"clr %D0"      CR_TAB
7003 				"sbrc %B0,7"   CR_TAB
7004 				"com %D0"      CR_TAB
7005 				"mov %C0,%D0");
7006 	    else
7007 	      return *len = 6, ("mov %B0,%D1" CR_TAB
7008 				"mov %A0,%C1" CR_TAB
7009 				"clr %D0"     CR_TAB
7010 				"sbrc %B0,7"  CR_TAB
7011 				"com %D0"     CR_TAB
7012 				"mov %C0,%D0");
7013 	  }
7014 
7015 	case 24:
7016 	  return *len = 6, ("mov %A0,%D1" CR_TAB
7017 			    "clr %D0"     CR_TAB
7018 			    "sbrc %A0,7"  CR_TAB
7019 			    "com %D0"     CR_TAB
7020 			    "mov %B0,%D0" CR_TAB
7021 			    "mov %C0,%D0");
7022 
7023 	default:
7024 	  if (INTVAL (operands[2]) < 32)
7025 	    break;
7026 
7027 	  /* fall through */
7028 
7029 	case 31:
7030 	  if (AVR_HAVE_MOVW)
7031 	    return *len = 4, ("lsl %D0"     CR_TAB
7032 			      "sbc %A0,%A0" CR_TAB
7033 			      "mov %B0,%A0" CR_TAB
7034 			      "movw %C0,%A0");
7035 	  else
7036 	    return *len = 5, ("lsl %D0"     CR_TAB
7037 			      "sbc %A0,%A0" CR_TAB
7038 			      "mov %B0,%A0" CR_TAB
7039 			      "mov %C0,%A0" CR_TAB
7040 			      "mov %D0,%A0");
7041 	}
7042       len = t;
7043     }
7044   out_shift_with_cnt ("asr %D0" CR_TAB
7045                       "ror %C0" CR_TAB
7046                       "ror %B0" CR_TAB
7047                       "ror %A0", insn, operands, len, 4);
7048   return "";
7049 }
7050 
7051 /* 8-bit logic shift right ((unsigned char)x >> i) */
7052 
7053 const char *
lshrqi3_out(rtx_insn * insn,rtx operands[],int * len)7054 lshrqi3_out (rtx_insn *insn, rtx operands[], int *len)
7055 {
7056   if (CONST_INT_P (operands[2]))
7057     {
7058       int k;
7059 
7060       if (!len)
7061 	len = &k;
7062 
7063       switch (INTVAL (operands[2]))
7064 	{
7065 	default:
7066 	  if (INTVAL (operands[2]) < 8)
7067 	    break;
7068 
7069 	  *len = 1;
7070 	  return "clr %0";
7071 
7072 	case 1:
7073 	  *len = 1;
7074 	  return "lsr %0";
7075 
7076 	case 2:
7077 	  *len = 2;
7078 	  return ("lsr %0" CR_TAB
7079 		  "lsr %0");
7080 	case 3:
7081 	  *len = 3;
7082 	  return ("lsr %0" CR_TAB
7083 		  "lsr %0" CR_TAB
7084 		  "lsr %0");
7085 
7086 	case 4:
7087 	  if (test_hard_reg_class (LD_REGS, operands[0]))
7088 	    {
7089 	      *len=2;
7090 	      return ("swap %0" CR_TAB
7091 		      "andi %0,0x0f");
7092 	    }
7093 	  *len = 4;
7094 	  return ("lsr %0" CR_TAB
7095 		  "lsr %0" CR_TAB
7096 		  "lsr %0" CR_TAB
7097 		  "lsr %0");
7098 
7099 	case 5:
7100 	  if (test_hard_reg_class (LD_REGS, operands[0]))
7101 	    {
7102 	      *len = 3;
7103 	      return ("swap %0" CR_TAB
7104 		      "lsr %0"  CR_TAB
7105 		      "andi %0,0x7");
7106 	    }
7107 	  *len = 5;
7108 	  return ("lsr %0" CR_TAB
7109 		  "lsr %0" CR_TAB
7110 		  "lsr %0" CR_TAB
7111 		  "lsr %0" CR_TAB
7112 		  "lsr %0");
7113 
7114 	case 6:
7115 	  if (test_hard_reg_class (LD_REGS, operands[0]))
7116 	    {
7117 	      *len = 4;
7118 	      return ("swap %0" CR_TAB
7119 		      "lsr %0"  CR_TAB
7120 		      "lsr %0"  CR_TAB
7121 		      "andi %0,0x3");
7122 	    }
7123 	  *len = 6;
7124 	  return ("lsr %0" CR_TAB
7125 		  "lsr %0" CR_TAB
7126 		  "lsr %0" CR_TAB
7127 		  "lsr %0" CR_TAB
7128 		  "lsr %0" CR_TAB
7129 		  "lsr %0");
7130 
7131 	case 7:
7132 	  *len = 3;
7133 	  return ("rol %0" CR_TAB
7134 		  "clr %0" CR_TAB
7135 		  "rol %0");
7136 	}
7137     }
7138   else if (CONSTANT_P (operands[2]))
7139     fatal_insn ("internal compiler error.  Incorrect shift:", insn);
7140 
7141   out_shift_with_cnt ("lsr %0",
7142                       insn, operands, len, 1);
7143   return "";
7144 }
7145 
7146 /* 16-bit logic shift right ((unsigned short)x >> i) */
7147 
7148 const char *
lshrhi3_out(rtx_insn * insn,rtx operands[],int * len)7149 lshrhi3_out (rtx_insn *insn, rtx operands[], int *len)
7150 {
7151   if (CONST_INT_P (operands[2]))
7152     {
7153       int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL
7154                      && XVECLEN (PATTERN (insn), 0) == 3
7155                      && REG_P (operands[3]));
7156       int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
7157       int k;
7158       int *t = len;
7159 
7160       if (!len)
7161 	len = &k;
7162 
7163       switch (INTVAL (operands[2]))
7164 	{
7165 	default:
7166 	  if (INTVAL (operands[2]) < 16)
7167 	    break;
7168 
7169 	  *len = 2;
7170 	  return ("clr %B0" CR_TAB
7171 		  "clr %A0");
7172 
7173 	case 4:
7174 	  if (optimize_size && scratch)
7175 	    break;  /* 5 */
7176 	  if (ldi_ok)
7177 	    {
7178 	      *len = 6;
7179 	      return ("swap %B0"      CR_TAB
7180 		      "swap %A0"      CR_TAB
7181 		      "andi %A0,0x0f" CR_TAB
7182 		      "eor %A0,%B0"   CR_TAB
7183 		      "andi %B0,0x0f" CR_TAB
7184 		      "eor %A0,%B0");
7185 	    }
7186 	  if (scratch)
7187 	    {
7188 	      *len = 7;
7189 	      return ("swap %B0"    CR_TAB
7190 		      "swap %A0"    CR_TAB
7191 		      "ldi %3,0x0f" CR_TAB
7192 		      "and %A0,%3"  CR_TAB
7193 		      "eor %A0,%B0" CR_TAB
7194 		      "and %B0,%3"  CR_TAB
7195 		      "eor %A0,%B0");
7196 	    }
7197 	  break;  /* optimize_size ? 6 : 8 */
7198 
7199 	case 5:
7200 	  if (optimize_size)
7201 	    break;  /* scratch ? 5 : 6 */
7202 	  if (ldi_ok)
7203 	    {
7204 	      *len = 8;
7205 	      return ("lsr %B0"       CR_TAB
7206 		      "ror %A0"       CR_TAB
7207 		      "swap %B0"      CR_TAB
7208 		      "swap %A0"      CR_TAB
7209 		      "andi %A0,0x0f" CR_TAB
7210 		      "eor %A0,%B0"   CR_TAB
7211 		      "andi %B0,0x0f" CR_TAB
7212 		      "eor %A0,%B0");
7213 	    }
7214 	  if (scratch)
7215 	    {
7216 	      *len = 9;
7217 	      return ("lsr %B0"     CR_TAB
7218 		      "ror %A0"     CR_TAB
7219 		      "swap %B0"    CR_TAB
7220 		      "swap %A0"    CR_TAB
7221 		      "ldi %3,0x0f" CR_TAB
7222 		      "and %A0,%3"  CR_TAB
7223 		      "eor %A0,%B0" CR_TAB
7224 		      "and %B0,%3"  CR_TAB
7225 		      "eor %A0,%B0");
7226 	    }
7227 	  break;  /* 10 */
7228 
7229 	case 6:
7230 	  if (optimize_size)
7231 	    break;  /* scratch ? 5 : 6 */
7232 	  *len = 9;
7233 	  return ("clr __tmp_reg__" CR_TAB
7234 		  "lsl %A0"         CR_TAB
7235 		  "rol %B0"         CR_TAB
7236 		  "rol __tmp_reg__" CR_TAB
7237 		  "lsl %A0"         CR_TAB
7238 		  "rol %B0"         CR_TAB
7239 		  "rol __tmp_reg__" CR_TAB
7240 		  "mov %A0,%B0"     CR_TAB
7241 		  "mov %B0,__tmp_reg__");
7242 
7243 	case 7:
7244 	  *len = 5;
7245 	  return ("lsl %A0"     CR_TAB
7246 		  "mov %A0,%B0" CR_TAB
7247 		  "rol %A0"     CR_TAB
7248 		  "sbc %B0,%B0" CR_TAB
7249 		  "neg %B0");
7250 
7251 	case 8:
7252 	  return *len = 2, ("mov %A0,%B1" CR_TAB
7253 			    "clr %B0");
7254 
7255 	case 9:
7256 	  *len = 3;
7257 	  return ("mov %A0,%B0" CR_TAB
7258 		  "clr %B0"     CR_TAB
7259 		  "lsr %A0");
7260 
7261 	case 10:
7262 	  *len = 4;
7263 	  return ("mov %A0,%B0" CR_TAB
7264 		  "clr %B0"     CR_TAB
7265 		  "lsr %A0"     CR_TAB
7266 		  "lsr %A0");
7267 
7268 	case 11:
7269 	  *len = 5;
7270 	  return ("mov %A0,%B0" CR_TAB
7271 		  "clr %B0"     CR_TAB
7272 		  "lsr %A0"     CR_TAB
7273 		  "lsr %A0"     CR_TAB
7274 		  "lsr %A0");
7275 
7276 	case 12:
7277 	  if (ldi_ok)
7278 	    {
7279 	      *len = 4;
7280 	      return ("mov %A0,%B0" CR_TAB
7281 		      "clr %B0"     CR_TAB
7282 		      "swap %A0"    CR_TAB
7283 		      "andi %A0,0x0f");
7284 	    }
7285 	  if (scratch)
7286 	    {
7287 	      *len = 5;
7288 	      return ("mov %A0,%B0" CR_TAB
7289 		      "clr %B0"     CR_TAB
7290 		      "swap %A0"    CR_TAB
7291 		      "ldi %3,0x0f" CR_TAB
7292 		      "and %A0,%3");
7293 	    }
7294 	  *len = 6;
7295 	  return ("mov %A0,%B0" CR_TAB
7296 		  "clr %B0"     CR_TAB
7297 		  "lsr %A0"     CR_TAB
7298 		  "lsr %A0"     CR_TAB
7299 		  "lsr %A0"     CR_TAB
7300 		  "lsr %A0");
7301 
7302 	case 13:
7303 	  if (ldi_ok)
7304 	    {
7305 	      *len = 5;
7306 	      return ("mov %A0,%B0" CR_TAB
7307 		      "clr %B0"     CR_TAB
7308 		      "swap %A0"    CR_TAB
7309 		      "lsr %A0"     CR_TAB
7310 		      "andi %A0,0x07");
7311 	    }
7312 	  if (AVR_HAVE_MUL && scratch)
7313 	    {
7314 	      *len = 5;
7315 	      return ("ldi %3,0x08" CR_TAB
7316 		      "mul %B0,%3"  CR_TAB
7317 		      "mov %A0,r1"  CR_TAB
7318 		      "clr %B0"     CR_TAB
7319 		      "clr __zero_reg__");
7320 	    }
7321 	  if (optimize_size && scratch)
7322 	    break;  /* 5 */
7323 	  if (scratch)
7324 	    {
7325 	      *len = 6;
7326 	      return ("mov %A0,%B0" CR_TAB
7327 		      "clr %B0"     CR_TAB
7328 		      "swap %A0"    CR_TAB
7329 		      "lsr %A0"     CR_TAB
7330 		      "ldi %3,0x07" CR_TAB
7331 		      "and %A0,%3");
7332 	    }
7333 	  if (AVR_HAVE_MUL)
7334 	    {
7335 	      *len = 6;
7336 	      return ("set"        CR_TAB
7337 		      "bld r1,3"   CR_TAB
7338 		      "mul %B0,r1" CR_TAB
7339 		      "mov %A0,r1" CR_TAB
7340 		      "clr %B0"    CR_TAB
7341 		      "clr __zero_reg__");
7342 	    }
7343 	  *len = 7;
7344 	  return ("mov %A0,%B0" CR_TAB
7345 		  "clr %B0"     CR_TAB
7346 		  "lsr %A0"     CR_TAB
7347 		  "lsr %A0"     CR_TAB
7348 		  "lsr %A0"     CR_TAB
7349 		  "lsr %A0"     CR_TAB
7350 		  "lsr %A0");
7351 
7352 	case 14:
7353 	  if (AVR_HAVE_MUL && ldi_ok)
7354 	    {
7355 	      *len = 5;
7356 	      return ("ldi %A0,0x04" CR_TAB
7357 		      "mul %B0,%A0"  CR_TAB
7358 		      "mov %A0,r1"   CR_TAB
7359 		      "clr %B0"      CR_TAB
7360 		      "clr __zero_reg__");
7361 	    }
7362 	  if (AVR_HAVE_MUL && scratch)
7363 	    {
7364 	      *len = 5;
7365 	      return ("ldi %3,0x04" CR_TAB
7366 		      "mul %B0,%3"  CR_TAB
7367 		      "mov %A0,r1"  CR_TAB
7368 		      "clr %B0"     CR_TAB
7369 		      "clr __zero_reg__");
7370 	    }
7371 	  if (optimize_size && ldi_ok)
7372 	    {
7373 	      *len = 5;
7374 	      return ("mov %A0,%B0" CR_TAB
7375 		      "ldi %B0,6" "\n1:\t"
7376 		      "lsr %A0"     CR_TAB
7377 		      "dec %B0"     CR_TAB
7378 		      "brne 1b");
7379 	    }
7380 	  if (optimize_size && scratch)
7381 	    break;  /* 5 */
7382 	  *len = 6;
7383 	  return ("clr %A0" CR_TAB
7384 		  "lsl %B0" CR_TAB
7385 		  "rol %A0" CR_TAB
7386 		  "lsl %B0" CR_TAB
7387 		  "rol %A0" CR_TAB
7388 		  "clr %B0");
7389 
7390 	case 15:
7391 	  *len = 4;
7392 	  return ("clr %A0" CR_TAB
7393 		  "lsl %B0" CR_TAB
7394 		  "rol %A0" CR_TAB
7395 		  "clr %B0");
7396 	}
7397       len = t;
7398     }
7399   out_shift_with_cnt ("lsr %B0" CR_TAB
7400                       "ror %A0", insn, operands, len, 2);
7401   return "";
7402 }
7403 
7404 
7405 /* 24-bit logic shift right */
7406 
7407 const char*
avr_out_lshrpsi3(rtx_insn * insn,rtx * op,int * plen)7408 avr_out_lshrpsi3 (rtx_insn *insn, rtx *op, int *plen)
7409 {
7410   int dest = REGNO (op[0]);
7411   int src = REGNO (op[1]);
7412 
7413   if (CONST_INT_P (op[2]))
7414     {
7415       if (plen)
7416         *plen = 0;
7417 
7418       switch (INTVAL (op[2]))
7419         {
7420         case 8:
7421           if (dest <= src)
7422             return avr_asm_len ("mov %A0,%B1" CR_TAB
7423                                 "mov %B0,%C1" CR_TAB
7424                                 "clr %C0", op, plen, 3);
7425           else
7426             return avr_asm_len ("clr %C0"     CR_TAB
7427                                 "mov %B0,%C1" CR_TAB
7428                                 "mov %A0,%B1", op, plen, 3);
7429 
7430         case 16:
7431           if (dest != src + 2)
7432             avr_asm_len ("mov %A0,%C1", op, plen, 1);
7433 
7434           return avr_asm_len ("clr %B0"  CR_TAB
7435                               "clr %C0", op, plen, 2);
7436 
7437         default:
7438           if (INTVAL (op[2]) < 24)
7439             break;
7440 
7441           /* fall through */
7442 
7443         case 23:
7444           return avr_asm_len ("clr %A0"    CR_TAB
7445                               "sbrc %C0,7" CR_TAB
7446                               "inc %A0"    CR_TAB
7447                               "clr %B0"    CR_TAB
7448                               "clr %C0", op, plen, 5);
7449         } /* switch */
7450     }
7451 
7452   out_shift_with_cnt ("lsr %C0" CR_TAB
7453                       "ror %B0" CR_TAB
7454                       "ror %A0", insn, op, plen, 3);
7455   return "";
7456 }
7457 
7458 
7459 /* 32-bit logic shift right ((unsigned int)x >> i) */
7460 
7461 const char *
lshrsi3_out(rtx_insn * insn,rtx operands[],int * len)7462 lshrsi3_out (rtx_insn *insn, rtx operands[], int *len)
7463 {
7464   if (CONST_INT_P (operands[2]))
7465     {
7466       int k;
7467       int *t = len;
7468 
7469       if (!len)
7470 	len = &k;
7471 
7472       switch (INTVAL (operands[2]))
7473 	{
7474 	default:
7475 	  if (INTVAL (operands[2]) < 32)
7476 	    break;
7477 
7478 	  if (AVR_HAVE_MOVW)
7479 	    return *len = 3, ("clr %D0" CR_TAB
7480 			      "clr %C0" CR_TAB
7481 			      "movw %A0,%C0");
7482 	  *len = 4;
7483 	  return ("clr %D0" CR_TAB
7484 		  "clr %C0" CR_TAB
7485 		  "clr %B0" CR_TAB
7486 		  "clr %A0");
7487 
7488 	case 8:
7489 	  {
7490 	    int reg0 = true_regnum (operands[0]);
7491 	    int reg1 = true_regnum (operands[1]);
7492 	    *len = 4;
7493 	    if (reg0 <= reg1)
7494 	      return ("mov %A0,%B1" CR_TAB
7495 		      "mov %B0,%C1" CR_TAB
7496 		      "mov %C0,%D1" CR_TAB
7497 		      "clr %D0");
7498 	    else
7499 	      return ("clr %D0"     CR_TAB
7500 		      "mov %C0,%D1" CR_TAB
7501 		      "mov %B0,%C1" CR_TAB
7502 		      "mov %A0,%B1");
7503 	  }
7504 
7505 	case 16:
7506 	  {
7507 	    int reg0 = true_regnum (operands[0]);
7508 	    int reg1 = true_regnum (operands[1]);
7509 
7510 	    if (reg0 == reg1 + 2)
7511 	      return *len = 2, ("clr %C0"     CR_TAB
7512 				"clr %D0");
7513 	    if (AVR_HAVE_MOVW)
7514 	      return *len = 3, ("movw %A0,%C1" CR_TAB
7515 				"clr %C0"      CR_TAB
7516 				"clr %D0");
7517 	    else
7518 	      return *len = 4, ("mov %B0,%D1" CR_TAB
7519 				"mov %A0,%C1" CR_TAB
7520 				"clr %C0"     CR_TAB
7521 				"clr %D0");
7522 	  }
7523 
7524 	case 24:
7525 	  return *len = 4, ("mov %A0,%D1" CR_TAB
7526 			    "clr %B0"     CR_TAB
7527 			    "clr %C0"     CR_TAB
7528 			    "clr %D0");
7529 
7530 	case 31:
7531 	  *len = 6;
7532 	  return ("clr %A0"    CR_TAB
7533 		  "sbrc %D0,7" CR_TAB
7534 		  "inc %A0"    CR_TAB
7535 		  "clr %B0"    CR_TAB
7536 		  "clr %C0"    CR_TAB
7537 		  "clr %D0");
7538 	}
7539       len = t;
7540     }
7541   out_shift_with_cnt ("lsr %D0" CR_TAB
7542                       "ror %C0" CR_TAB
7543                       "ror %B0" CR_TAB
7544                       "ror %A0", insn, operands, len, 4);
7545   return "";
7546 }
7547 
7548 
7549 /* Output addition of register XOP[0] and compile time constant XOP[2].
7550    CODE == PLUS:  perform addition by using ADD instructions or
7551    CODE == MINUS: perform addition by using SUB instructions:
7552 
7553       XOP[0] = XOP[0] + XOP[2]
7554 
7555    Or perform addition/subtraction with register XOP[2] depending on CODE:
7556 
7557       XOP[0] = XOP[0] +/- XOP[2]
7558 
7559    If PLEN == NULL, print assembler instructions to perform the operation;
7560    otherwise, set *PLEN to the length of the instruction sequence (in words)
7561    printed with PLEN == NULL.  XOP[3] is an 8-bit scratch register or NULL_RTX.
7562    Set *PCC to effect on cc0 according to respective CC_* insn attribute.
7563 
7564    CODE_SAT == UNKNOWN: Perform ordinary, non-saturating operation.
7565    CODE_SAT != UNKNOWN: Perform operation and saturate according to CODE_SAT.
7566    If  CODE_SAT != UNKNOWN  then SIGN contains the sign of the summand resp.
7567    the subtrahend in the original insn, provided it is a compile time constant.
7568    In all other cases, SIGN is 0.
7569 
7570    If OUT_LABEL is true, print the final 0: label which is needed for
7571    saturated addition / subtraction.  The only case where OUT_LABEL = false
7572    is useful is for saturated addition / subtraction performed during
7573    fixed-point rounding, cf. `avr_out_round'.  */
7574 
7575 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)7576 avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc,
7577                 enum rtx_code code_sat, int sign, bool out_label)
7578 {
7579   /* MODE of the operation.  */
7580   machine_mode mode = GET_MODE (xop[0]);
7581 
7582   /* INT_MODE of the same size.  */
7583   scalar_int_mode imode = int_mode_for_mode (mode).require ();
7584 
7585   /* Number of bytes to operate on.  */
7586   int n_bytes = GET_MODE_SIZE (mode);
7587 
7588   /* Value (0..0xff) held in clobber register op[3] or -1 if unknown.  */
7589   int clobber_val = -1;
7590 
7591   /* op[0]: 8-bit destination register
7592      op[1]: 8-bit const int
7593      op[2]: 8-bit scratch register */
7594   rtx op[3];
7595 
7596   /* Started the operation?  Before starting the operation we may skip
7597      adding 0.  This is no more true after the operation started because
7598      carry must be taken into account.  */
7599   bool started = false;
7600 
7601   /* Value to add.  There are two ways to add VAL: R += VAL and R -= -VAL.  */
7602   rtx xval = xop[2];
7603 
7604   /* Output a BRVC instruction.  Only needed with saturation.  */
7605   bool out_brvc = true;
7606 
7607   if (plen)
7608     *plen = 0;
7609 
7610   if (REG_P (xop[2]))
7611     {
7612       *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_CLOBBER;
7613 
7614       for (int i = 0; i < n_bytes; i++)
7615         {
7616           /* We operate byte-wise on the destination.  */
7617           op[0] = simplify_gen_subreg (QImode, xop[0], mode, i);
7618           op[1] = simplify_gen_subreg (QImode, xop[2], mode, i);
7619 
7620           if (i == 0)
7621             avr_asm_len (code == PLUS ? "add %0,%1" : "sub %0,%1",
7622                          op, plen, 1);
7623           else
7624             avr_asm_len (code == PLUS ? "adc %0,%1" : "sbc %0,%1",
7625                          op, plen, 1);
7626         }
7627 
7628       if (reg_overlap_mentioned_p (xop[0], xop[2]))
7629         {
7630           gcc_assert (REGNO (xop[0]) == REGNO (xop[2]));
7631 
7632           if (MINUS == code)
7633             return;
7634         }
7635 
7636       goto saturate;
7637     }
7638 
7639   /* Except in the case of ADIW with 16-bit register (see below)
7640      addition does not set cc0 in a usable way.  */
7641 
7642   *pcc = (MINUS == code) ? CC_SET_CZN : CC_CLOBBER;
7643 
7644   if (CONST_FIXED_P (xval))
7645     xval = avr_to_int_mode (xval);
7646 
7647   /* Adding/Subtracting zero is a no-op.  */
7648 
7649   if (xval == const0_rtx)
7650     {
7651       *pcc = CC_NONE;
7652       return;
7653     }
7654 
7655   if (MINUS == code)
7656     xval = simplify_unary_operation (NEG, imode, xval, imode);
7657 
7658   op[2] = xop[3];
7659 
7660   if (SS_PLUS == code_sat && MINUS == code
7661       && sign < 0
7662       && 0x80 == (INTVAL (simplify_gen_subreg (QImode, xval, imode, n_bytes-1))
7663                   & GET_MODE_MASK (QImode)))
7664     {
7665       /* We compute x + 0x80 by means of SUB instructions.  We negated the
7666          constant subtrahend above and are left with  x - (-128)  so that we
7667          need something like SUBI r,128 which does not exist because SUBI sets
7668          V according to the sign of the subtrahend.  Notice the only case
7669          where this must be done is when NEG overflowed in case [2s] because
7670          the V computation needs the right sign of the subtrahend.  */
7671 
7672       rtx msb = simplify_gen_subreg (QImode, xop[0], mode, n_bytes - 1);
7673 
7674       avr_asm_len ("subi %0,128" CR_TAB
7675                    "brmi 0f", &msb, plen, 2);
7676       out_brvc = false;
7677 
7678       goto saturate;
7679     }
7680 
7681   for (int i = 0; i < n_bytes; i++)
7682     {
7683       /* We operate byte-wise on the destination.  */
7684       rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
7685       rtx xval8 = simplify_gen_subreg (QImode, xval, imode, i);
7686 
7687       /* 8-bit value to operate with this byte. */
7688       unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
7689 
7690       /* Registers R16..R31 can operate with immediate.  */
7691       bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
7692 
7693       op[0] = reg8;
7694       op[1] = gen_int_mode (val8, QImode);
7695 
7696       /* To get usable cc0 no low-bytes must have been skipped.  */
7697 
7698       if (i && !started)
7699         *pcc = CC_CLOBBER;
7700 
7701       if (!started
7702           && i % 2 == 0
7703           && i + 2 <= n_bytes
7704           && test_hard_reg_class (ADDW_REGS, reg8))
7705         {
7706           rtx xval16 = simplify_gen_subreg (HImode, xval, imode, i);
7707           unsigned int val16 = UINTVAL (xval16) & GET_MODE_MASK (HImode);
7708 
7709           /* Registers R24, X, Y, Z can use ADIW/SBIW with constants < 64
7710              i.e. operate word-wise.  */
7711 
7712           if (val16 < 64)
7713             {
7714               if (val16 != 0)
7715                 {
7716                   started = true;
7717                   avr_asm_len (code == PLUS ? "adiw %0,%1" : "sbiw %0,%1",
7718                                op, plen, 1);
7719 
7720                   if (n_bytes == 2 && PLUS == code)
7721                     *pcc = CC_SET_CZN;
7722                 }
7723 
7724               i++;
7725               continue;
7726             }
7727         }
7728 
7729       if (val8 == 0)
7730         {
7731           if (started)
7732             avr_asm_len (code == PLUS
7733                          ? "adc %0,__zero_reg__" : "sbc %0,__zero_reg__",
7734                          op, plen, 1);
7735           continue;
7736         }
7737       else if ((val8 == 1 || val8 == 0xff)
7738                && UNKNOWN == code_sat
7739                && !started
7740                && i == n_bytes - 1)
7741         {
7742           avr_asm_len ((code == PLUS) ^ (val8 == 1) ? "dec %0" : "inc %0",
7743                        op, plen, 1);
7744           *pcc = CC_CLOBBER;
7745           break;
7746         }
7747 
7748       switch (code)
7749         {
7750         case PLUS:
7751 
7752           gcc_assert (plen != NULL || (op[2] && REG_P (op[2])));
7753 
7754           if (plen != NULL && UNKNOWN != code_sat)
7755             {
7756               /* This belongs to the x + 0x80 corner case.  The code with
7757                  ADD instruction is not smaller, thus make this case
7758                  expensive so that the caller won't pick it.  */
7759 
7760               *plen += 10;
7761               break;
7762             }
7763 
7764           if (clobber_val != (int) val8)
7765             avr_asm_len ("ldi %2,%1", op, plen, 1);
7766           clobber_val = (int) val8;
7767 
7768           avr_asm_len (started ? "adc %0,%2" : "add %0,%2", op, plen, 1);
7769 
7770           break; /* PLUS */
7771 
7772         case MINUS:
7773 
7774           if (ld_reg_p)
7775             avr_asm_len (started ? "sbci %0,%1" : "subi %0,%1", op, plen, 1);
7776           else
7777             {
7778               gcc_assert (plen != NULL || REG_P (op[2]));
7779 
7780               if (clobber_val != (int) val8)
7781                 avr_asm_len ("ldi %2,%1", op, plen, 1);
7782               clobber_val = (int) val8;
7783 
7784               avr_asm_len (started ? "sbc %0,%2" : "sub %0,%2", op, plen, 1);
7785             }
7786 
7787           break; /* MINUS */
7788 
7789         default:
7790           /* Unknown code */
7791           gcc_unreachable();
7792         }
7793 
7794       started = true;
7795 
7796     } /* for all sub-bytes */
7797 
7798  saturate:
7799 
7800   if (UNKNOWN == code_sat)
7801     return;
7802 
7803   *pcc = (int) CC_CLOBBER;
7804 
7805   /* Vanilla addition/subtraction is done.  We are left with saturation.
7806 
7807      We have to compute  A = A <op> B  where  A  is a register and
7808      B is a register or a non-zero compile time constant CONST.
7809      A is register class "r" if unsigned && B is REG.  Otherwise, A is in "d".
7810      B stands for the original operand $2 in INSN.  In the case of B = CONST,
7811      SIGN in { -1, 1 } is the sign of B.  Otherwise, SIGN is 0.
7812 
7813      CODE is the instruction flavor we use in the asm sequence to perform <op>.
7814 
7815 
7816      unsigned
7817      operation        |  code |  sat if  |    b is      | sat value |  case
7818      -----------------+-------+----------+--------------+-----------+-------
7819      +  as  a + b     |  add  |  C == 1  |  const, reg  | u+ = 0xff |  [1u]
7820      +  as  a - (-b)  |  sub  |  C == 0  |  const       | u+ = 0xff |  [2u]
7821      -  as  a - b     |  sub  |  C == 1  |  const, reg  | u- = 0    |  [3u]
7822      -  as  a + (-b)  |  add  |  C == 0  |  const       | u- = 0    |  [4u]
7823 
7824 
7825      signed
7826      operation        |  code |  sat if  |    b is      | sat value |  case
7827      -----------------+-------+----------+--------------+-----------+-------
7828      +  as  a + b     |  add  |  V == 1  |  const, reg  | s+        |  [1s]
7829      +  as  a - (-b)  |  sub  |  V == 1  |  const       | s+        |  [2s]
7830      -  as  a - b     |  sub  |  V == 1  |  const, reg  | s-        |  [3s]
7831      -  as  a + (-b)  |  add  |  V == 1  |  const       | s-        |  [4s]
7832 
7833      s+  =  b < 0  ?  -0x80 :  0x7f
7834      s-  =  b < 0  ?   0x7f : -0x80
7835 
7836      The cases a - b actually perform  a - (-(-b))  if B is CONST.
7837   */
7838 
7839   op[0] = simplify_gen_subreg (QImode, xop[0], mode, n_bytes-1);
7840   op[1] = n_bytes > 1
7841     ? simplify_gen_subreg (QImode, xop[0], mode, n_bytes-2)
7842     : NULL_RTX;
7843 
7844   bool need_copy = true;
7845   int len_call = 1 + AVR_HAVE_JMP_CALL;
7846 
7847   switch (code_sat)
7848     {
7849     default:
7850       gcc_unreachable();
7851 
7852     case SS_PLUS:
7853     case SS_MINUS:
7854 
7855       if (out_brvc)
7856         avr_asm_len ("brvc 0f", op, plen, 1);
7857 
7858       if (reg_overlap_mentioned_p (xop[0], xop[2]))
7859         {
7860           /* [1s,reg] */
7861 
7862           if (n_bytes == 1)
7863             avr_asm_len ("ldi %0,0x7f" CR_TAB
7864                          "adc %0,__zero_reg__", op, plen, 2);
7865           else
7866             avr_asm_len ("ldi %0,0x7f" CR_TAB
7867                          "ldi %1,0xff" CR_TAB
7868                          "adc %1,__zero_reg__" CR_TAB
7869                          "adc %0,__zero_reg__", op, plen, 4);
7870         }
7871       else if (sign == 0 && PLUS == code)
7872         {
7873           /* [1s,reg] */
7874 
7875           op[2] = simplify_gen_subreg (QImode, xop[2], mode, n_bytes-1);
7876 
7877           if (n_bytes == 1)
7878             avr_asm_len ("ldi %0,0x80" CR_TAB
7879                          "sbrs %2,7"   CR_TAB
7880                          "dec %0", op, plen, 3);
7881           else
7882             avr_asm_len ("ldi %0,0x80" CR_TAB
7883                          "cp %2,%0"    CR_TAB
7884                          "sbc %1,%1"   CR_TAB
7885                          "sbci %0,0", op, plen, 4);
7886         }
7887       else if (sign == 0 && MINUS == code)
7888         {
7889           /* [3s,reg] */
7890 
7891           op[2] = simplify_gen_subreg (QImode, xop[2], mode, n_bytes-1);
7892 
7893           if (n_bytes == 1)
7894             avr_asm_len ("ldi %0,0x7f" CR_TAB
7895                          "sbrs %2,7"   CR_TAB
7896                          "inc %0", op, plen, 3);
7897           else
7898             avr_asm_len ("ldi %0,0x7f" CR_TAB
7899                          "cp %0,%2"    CR_TAB
7900                          "sbc %1,%1"   CR_TAB
7901                          "sbci %0,-1", op, plen, 4);
7902         }
7903       else if ((sign < 0) ^ (SS_MINUS == code_sat))
7904         {
7905           /* [1s,const,B < 0] [2s,B < 0] */
7906           /* [3s,const,B > 0] [4s,B > 0] */
7907 
7908           if (n_bytes == 8)
7909             {
7910               avr_asm_len ("%~call __clr_8", op, plen, len_call);
7911               need_copy = false;
7912             }
7913 
7914           avr_asm_len ("ldi %0,0x80", op, plen, 1);
7915           if (n_bytes > 1 && need_copy)
7916             avr_asm_len ("clr %1", op, plen, 1);
7917         }
7918       else if ((sign > 0) ^ (SS_MINUS == code_sat))
7919         {
7920           /* [1s,const,B > 0] [2s,B > 0] */
7921           /* [3s,const,B < 0] [4s,B < 0] */
7922 
7923           if (n_bytes == 8)
7924             {
7925               avr_asm_len ("sec" CR_TAB
7926                            "%~call __sbc_8", op, plen, 1 + len_call);
7927               need_copy = false;
7928             }
7929 
7930           avr_asm_len ("ldi %0,0x7f", op, plen, 1);
7931           if (n_bytes > 1 && need_copy)
7932             avr_asm_len ("ldi %1,0xff", op, plen, 1);
7933         }
7934       else
7935         gcc_unreachable();
7936 
7937       break;
7938 
7939     case US_PLUS:
7940       /* [1u] : [2u] */
7941 
7942       avr_asm_len (PLUS == code ? "brcc 0f" : "brcs 0f", op, plen, 1);
7943 
7944       if (n_bytes == 8)
7945         {
7946           if (MINUS == code)
7947             avr_asm_len ("sec", op, plen, 1);
7948           avr_asm_len ("%~call __sbc_8", op, plen, len_call);
7949 
7950           need_copy = false;
7951         }
7952       else
7953         {
7954           if (MINUS == code && !test_hard_reg_class (LD_REGS, op[0]))
7955             avr_asm_len ("sec" CR_TAB
7956                          "sbc %0,%0", op, plen, 2);
7957           else
7958             avr_asm_len (PLUS == code ? "sbc %0,%0" : "ldi %0,0xff",
7959                          op, plen, 1);
7960         }
7961       break; /* US_PLUS */
7962 
7963     case US_MINUS:
7964       /* [4u] : [3u] */
7965 
7966       avr_asm_len (PLUS == code ? "brcs 0f" : "brcc 0f", op, plen, 1);
7967 
7968       if (n_bytes == 8)
7969         {
7970           avr_asm_len ("%~call __clr_8", op, plen, len_call);
7971           need_copy = false;
7972         }
7973       else
7974         avr_asm_len ("clr %0", op, plen, 1);
7975 
7976       break;
7977     }
7978 
7979   /* We set the MSB in the unsigned case and the 2 MSBs in the signed case.
7980      Now copy the right value to the LSBs.  */
7981 
7982   if (need_copy && n_bytes > 1)
7983     {
7984       if (US_MINUS == code_sat || US_PLUS == code_sat)
7985         {
7986           avr_asm_len ("mov %1,%0", op, plen, 1);
7987 
7988           if (n_bytes > 2)
7989             {
7990               op[0] = xop[0];
7991               if (AVR_HAVE_MOVW)
7992                 avr_asm_len ("movw %0,%1", op, plen, 1);
7993               else
7994                 avr_asm_len ("mov %A0,%1" CR_TAB
7995                              "mov %B0,%1", op, plen, 2);
7996             }
7997         }
7998       else if (n_bytes > 2)
7999         {
8000           op[0] = xop[0];
8001           avr_asm_len ("mov %A0,%1" CR_TAB
8002                        "mov %B0,%1", op, plen, 2);
8003         }
8004     }
8005 
8006   if (need_copy && n_bytes == 8)
8007     {
8008       if (AVR_HAVE_MOVW)
8009         avr_asm_len ("movw %r0+2,%0" CR_TAB
8010                      "movw %r0+4,%0", xop, plen, 2);
8011       else
8012         avr_asm_len ("mov %r0+2,%0" CR_TAB
8013                      "mov %r0+3,%0" CR_TAB
8014                      "mov %r0+4,%0" CR_TAB
8015                      "mov %r0+5,%0", xop, plen, 4);
8016     }
8017 
8018   if (out_label)
8019     avr_asm_len ("0:", op, plen, 0);
8020 }
8021 
8022 
8023 /* Output addition/subtraction of register XOP[0] and a constant XOP[2] that
8024    is ont a compile-time constant:
8025 
8026       XOP[0] = XOP[0] +/- XOP[2]
8027 
8028    This is a helper for the function below.  The only insns that need this
8029    are additions/subtraction for pointer modes, i.e. HImode and PSImode.  */
8030 
8031 static const char*
avr_out_plus_symbol(rtx * xop,enum rtx_code code,int * plen,int * pcc)8032 avr_out_plus_symbol (rtx *xop, enum rtx_code code, int *plen, int *pcc)
8033 {
8034   machine_mode mode = GET_MODE (xop[0]);
8035 
8036   /* Only pointer modes want to add symbols.  */
8037 
8038   gcc_assert (mode == HImode || mode == PSImode);
8039 
8040   *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_SET_N;
8041 
8042   avr_asm_len (PLUS == code
8043                ? "subi %A0,lo8(-(%2))" CR_TAB "sbci %B0,hi8(-(%2))"
8044                : "subi %A0,lo8(%2)"    CR_TAB "sbci %B0,hi8(%2)",
8045                xop, plen, -2);
8046 
8047   if (PSImode == mode)
8048     avr_asm_len (PLUS == code
8049                  ? "sbci %C0,hlo8(-(%2))"
8050                  : "sbci %C0,hlo8(%2)", xop, plen, 1);
8051   return "";
8052 }
8053 
8054 
8055 /* Prepare operands of addition/subtraction to be used with avr_out_plus_1.
8056 
8057    INSN is a single_set insn or an insn pattern with a binary operation as
8058    SET_SRC that is one of: PLUS, SS_PLUS, US_PLUS, MINUS, SS_MINUS, US_MINUS.
8059 
8060    XOP are the operands of INSN.  In the case of 64-bit operations with
8061    constant XOP[] has just one element:  The summand/subtrahend in XOP[0].
8062    The non-saturating insns up to 32 bits may or may not supply a "d" class
8063    scratch as XOP[3].
8064 
8065    If PLEN == NULL output the instructions.
8066    If PLEN != NULL set *PLEN to the length of the sequence in words.
8067 
8068    PCC is a pointer to store the instructions' effect on cc0.
8069    PCC may be NULL.
8070 
8071    PLEN and PCC default to NULL.
8072 
8073    OUT_LABEL defaults to TRUE.  For a description, see AVR_OUT_PLUS_1.
8074 
8075    Return ""  */
8076 
8077 const char*
avr_out_plus(rtx insn,rtx * xop,int * plen,int * pcc,bool out_label)8078 avr_out_plus (rtx insn, rtx *xop, int *plen, int *pcc, bool out_label)
8079 {
8080   int cc_plus, cc_minus, cc_dummy;
8081   int len_plus, len_minus;
8082   rtx op[4];
8083   rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
8084   rtx xdest = SET_DEST (xpattern);
8085   machine_mode mode = GET_MODE (xdest);
8086   scalar_int_mode imode = int_mode_for_mode (mode).require ();
8087   int n_bytes = GET_MODE_SIZE (mode);
8088   enum rtx_code code_sat = GET_CODE (SET_SRC (xpattern));
8089   enum rtx_code code
8090     = (PLUS == code_sat || SS_PLUS == code_sat || US_PLUS == code_sat
8091        ? PLUS : MINUS);
8092 
8093   if (!pcc)
8094     pcc = &cc_dummy;
8095 
8096   /* PLUS and MINUS don't saturate:  Use modular wrap-around.  */
8097 
8098   if (PLUS == code_sat || MINUS == code_sat)
8099     code_sat = UNKNOWN;
8100 
8101   if (n_bytes <= 4 && REG_P (xop[2]))
8102     {
8103       avr_out_plus_1 (xop, plen, code, pcc, code_sat, 0, out_label);
8104       return "";
8105     }
8106 
8107   if (n_bytes == 8)
8108     {
8109       op[0] = gen_rtx_REG (DImode, ACC_A);
8110       op[1] = gen_rtx_REG (DImode, ACC_A);
8111       op[2] = avr_to_int_mode (xop[0]);
8112     }
8113   else
8114     {
8115       if (!REG_P (xop[2])
8116           && !CONST_INT_P (xop[2])
8117           && !CONST_FIXED_P (xop[2]))
8118         {
8119           return avr_out_plus_symbol (xop, code, plen, pcc);
8120         }
8121 
8122       op[0] = avr_to_int_mode (xop[0]);
8123       op[1] = avr_to_int_mode (xop[1]);
8124       op[2] = avr_to_int_mode (xop[2]);
8125     }
8126 
8127   /* Saturations and 64-bit operations don't have a clobber operand.
8128      For the other cases, the caller will provide a proper XOP[3].  */
8129 
8130   xpattern = INSN_P (insn) ? PATTERN (insn) : insn;
8131   op[3] = PARALLEL == GET_CODE (xpattern) ? xop[3] : NULL_RTX;
8132 
8133   /* Saturation will need the sign of the original operand.  */
8134 
8135   rtx xmsb = simplify_gen_subreg (QImode, op[2], imode, n_bytes-1);
8136   int sign = INTVAL (xmsb) < 0 ? -1 : 1;
8137 
8138   /* If we subtract and the subtrahend is a constant, then negate it
8139      so that avr_out_plus_1 can be used.  */
8140 
8141   if (MINUS == code)
8142     op[2] = simplify_unary_operation (NEG, imode, op[2], imode);
8143 
8144   /* Work out the shortest sequence.  */
8145 
8146   avr_out_plus_1 (op, &len_minus, MINUS, &cc_minus, code_sat, sign, out_label);
8147   avr_out_plus_1 (op, &len_plus, PLUS, &cc_plus, code_sat, sign, out_label);
8148 
8149   if (plen)
8150     {
8151       *plen = (len_minus <= len_plus) ? len_minus : len_plus;
8152       *pcc  = (len_minus <= len_plus) ? cc_minus : cc_plus;
8153     }
8154   else if (len_minus <= len_plus)
8155     avr_out_plus_1 (op, NULL, MINUS, pcc, code_sat, sign, out_label);
8156   else
8157     avr_out_plus_1 (op, NULL, PLUS, pcc, code_sat, sign, out_label);
8158 
8159   return "";
8160 }
8161 
8162 
8163 /* Output bit operation (IOR, AND, XOR) with register XOP[0] and compile
8164    time constant XOP[2]:
8165 
8166       XOP[0] = XOP[0] <op> XOP[2]
8167 
8168    and return "".  If PLEN == NULL, print assembler instructions to perform the
8169    operation; otherwise, set *PLEN to the length of the instruction sequence
8170    (in words) printed with PLEN == NULL.  XOP[3] is either an 8-bit clobber
8171    register or SCRATCH if no clobber register is needed for the operation.
8172    INSN is an INSN_P or a pattern of an insn.  */
8173 
8174 const char*
avr_out_bitop(rtx insn,rtx * xop,int * plen)8175 avr_out_bitop (rtx insn, rtx *xop, int *plen)
8176 {
8177   /* CODE and MODE of the operation.  */
8178   rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
8179   enum rtx_code code = GET_CODE (SET_SRC (xpattern));
8180   machine_mode mode = GET_MODE (xop[0]);
8181 
8182   /* Number of bytes to operate on.  */
8183   int n_bytes = GET_MODE_SIZE (mode);
8184 
8185   /* Value of T-flag (0 or 1) or -1 if unknow.  */
8186   int set_t = -1;
8187 
8188   /* Value (0..0xff) held in clobber register op[3] or -1 if unknown.  */
8189   int clobber_val = -1;
8190 
8191   /* op[0]: 8-bit destination register
8192      op[1]: 8-bit const int
8193      op[2]: 8-bit clobber register, SCRATCH or NULL_RTX.
8194      op[3]: 8-bit register containing 0xff or NULL_RTX  */
8195   rtx op[4];
8196 
8197   op[2] = QImode == mode ? NULL_RTX : xop[3];
8198   op[3] = NULL_RTX;
8199 
8200   if (plen)
8201     *plen = 0;
8202 
8203   for (int i = 0; i < n_bytes; i++)
8204     {
8205       /* We operate byte-wise on the destination.  */
8206       rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
8207       rtx xval8 = simplify_gen_subreg (QImode, xop[2], mode, i);
8208 
8209       /* 8-bit value to operate with this byte. */
8210       unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
8211 
8212       /* Number of bits set in the current byte of the constant.  */
8213       int pop8 = popcount_hwi (val8);
8214 
8215       /* Registers R16..R31 can operate with immediate.  */
8216       bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
8217 
8218       op[0] = reg8;
8219       op[1] = GEN_INT (val8);
8220 
8221       switch (code)
8222         {
8223         case IOR:
8224 
8225 	  if (pop8 == 0)
8226             continue;
8227           else if (ld_reg_p)
8228             avr_asm_len ("ori %0,%1", op, plen, 1);
8229 	  else if (pop8 == 1)
8230             {
8231               if (set_t != 1)
8232                 avr_asm_len ("set", op, plen, 1);
8233               set_t = 1;
8234 
8235               op[1] = GEN_INT (exact_log2 (val8));
8236               avr_asm_len ("bld %0,%1", op, plen, 1);
8237             }
8238 	  else if (pop8 == 8)
8239             {
8240               if (op[3] != NULL_RTX)
8241                 avr_asm_len ("mov %0,%3", op, plen, 1);
8242               else
8243                 avr_asm_len ("clr %0" CR_TAB
8244                              "dec %0", op, plen, 2);
8245 
8246               op[3] = op[0];
8247             }
8248           else
8249             {
8250               if (clobber_val != (int) val8)
8251                 avr_asm_len ("ldi %2,%1", op, plen, 1);
8252               clobber_val = (int) val8;
8253 
8254               avr_asm_len ("or %0,%2", op, plen, 1);
8255             }
8256 
8257           continue; /* IOR */
8258 
8259         case AND:
8260 
8261 	  if (pop8 == 8)
8262             continue;
8263 	  else if (pop8 == 0)
8264             avr_asm_len ("clr %0", op, plen, 1);
8265           else if (ld_reg_p)
8266             avr_asm_len ("andi %0,%1", op, plen, 1);
8267 	  else if (pop8 == 7)
8268             {
8269               if (set_t != 0)
8270                 avr_asm_len ("clt", op, plen, 1);
8271               set_t = 0;
8272 
8273               op[1] = GEN_INT (exact_log2 (GET_MODE_MASK (QImode) & ~val8));
8274               avr_asm_len ("bld %0,%1", op, plen, 1);
8275             }
8276           else
8277             {
8278               if (clobber_val != (int) val8)
8279                 avr_asm_len ("ldi %2,%1", op, plen, 1);
8280               clobber_val = (int) val8;
8281 
8282               avr_asm_len ("and %0,%2", op, plen, 1);
8283             }
8284 
8285           continue; /* AND */
8286 
8287         case XOR:
8288 
8289 	  if (pop8 == 0)
8290             continue;
8291 	  else if (pop8 == 8)
8292             avr_asm_len ("com %0", op, plen, 1);
8293           else if (ld_reg_p && val8 == (1 << 7))
8294             avr_asm_len ("subi %0,%1", op, plen, 1);
8295           else
8296             {
8297               if (clobber_val != (int) val8)
8298                 avr_asm_len ("ldi %2,%1", op, plen, 1);
8299               clobber_val = (int) val8;
8300 
8301               avr_asm_len ("eor %0,%2", op, plen, 1);
8302             }
8303 
8304           continue; /* XOR */
8305 
8306         default:
8307           /* Unknown rtx_code */
8308           gcc_unreachable();
8309         }
8310     } /* for all sub-bytes */
8311 
8312   return "";
8313 }
8314 
8315 
8316 /* Output sign extension from XOP[1] to XOP[0] and return "".
8317    If PLEN == NULL, print assembler instructions to perform the operation;
8318    otherwise, set *PLEN to the length of the instruction sequence (in words)
8319    as printed with PLEN == NULL.  */
8320 
8321 const char*
avr_out_sign_extend(rtx_insn * insn,rtx * xop,int * plen)8322 avr_out_sign_extend (rtx_insn *insn, rtx *xop, int *plen)
8323 {
8324   // Size in bytes of source resp. destination operand.
8325   unsigned n_src = GET_MODE_SIZE (GET_MODE (xop[1]));
8326   unsigned n_dest = GET_MODE_SIZE (GET_MODE (xop[0]));
8327   rtx r_msb = all_regs_rtx[REGNO (xop[1]) + n_src - 1];
8328 
8329   if (plen)
8330     *plen = 0;
8331 
8332   // Copy destination to source
8333 
8334   if (REGNO (xop[0]) != REGNO (xop[1]))
8335     {
8336       gcc_assert (n_src <= 2);
8337 
8338       if (n_src == 2)
8339         avr_asm_len (AVR_HAVE_MOVW
8340                      ? "movw %0,%1"
8341                      : "mov %B0,%B1", xop, plen, 1);
8342       if (n_src == 1 || !AVR_HAVE_MOVW)
8343         avr_asm_len ("mov %A0,%A1", xop, plen, 1);
8344     }
8345 
8346   // Set Carry to the sign bit MSB.7...
8347 
8348   if (REGNO (xop[0]) == REGNO (xop[1])
8349       || !reg_unused_after (insn, r_msb))
8350     {
8351       avr_asm_len ("mov __tmp_reg__,%0", &r_msb, plen, 1);
8352       r_msb = tmp_reg_rtx;
8353     }
8354 
8355   avr_asm_len ("lsl %0", &r_msb, plen, 1);
8356 
8357   // ...and propagate it to all the new sign bits
8358 
8359   for (unsigned n = n_src; n < n_dest; n++)
8360     avr_asm_len ("sbc %0,%0", &all_regs_rtx[REGNO (xop[0]) + n], plen, 1);
8361 
8362   return "";
8363 }
8364 
8365 
8366 /* PLEN == NULL: Output code to add CONST_INT OP[0] to SP.
8367    PLEN != NULL: Set *PLEN to the length of that sequence.
8368    Return "".  */
8369 
8370 const char*
avr_out_addto_sp(rtx * op,int * plen)8371 avr_out_addto_sp (rtx *op, int *plen)
8372 {
8373   int pc_len = AVR_2_BYTE_PC ? 2 : 3;
8374   int addend = INTVAL (op[0]);
8375 
8376   if (plen)
8377     *plen = 0;
8378 
8379   if (addend < 0)
8380     {
8381       if (flag_verbose_asm || flag_print_asm_name)
8382         avr_asm_len (ASM_COMMENT_START "SP -= %n0", op, plen, 0);
8383 
8384       while (addend <= -pc_len)
8385         {
8386           addend += pc_len;
8387           avr_asm_len ("rcall .", op, plen, 1);
8388         }
8389 
8390       while (addend++ < 0)
8391         avr_asm_len ("push __tmp_reg__", op, plen, 1);
8392     }
8393   else if (addend > 0)
8394     {
8395       if (flag_verbose_asm || flag_print_asm_name)
8396         avr_asm_len (ASM_COMMENT_START "SP += %0", op, plen, 0);
8397 
8398       while (addend-- > 0)
8399         avr_asm_len ("pop __tmp_reg__", op, plen, 1);
8400     }
8401 
8402   return "";
8403 }
8404 
8405 
8406 /* Output instructions to insert an inverted bit into OPERANDS[0]:
8407    $0.$1 = ~$2.$3      if XBITNO = NULL
8408    $0.$1 = ~$2.XBITNO  if XBITNO != NULL.
8409    If PLEN = NULL then output the respective instruction sequence which
8410    is a combination of BST / BLD and some instruction(s) to invert the bit.
8411    If PLEN != NULL then store the length of the sequence (in words) in *PLEN.
8412    Return "".  */
8413 
8414 const char*
avr_out_insert_notbit(rtx_insn * insn,rtx operands[],rtx xbitno,int * plen)8415 avr_out_insert_notbit (rtx_insn *insn, rtx operands[], rtx xbitno, int *plen)
8416 {
8417   rtx op[4] = { operands[0], operands[1], operands[2],
8418                 xbitno == NULL_RTX ? operands [3] : xbitno };
8419 
8420   if (INTVAL (op[1]) == 7
8421       && test_hard_reg_class (LD_REGS, op[0]))
8422     {
8423       /* If the inserted bit number is 7 and we have a d-reg, then invert
8424          the bit after the insertion by means of SUBI *,0x80.  */
8425 
8426       if (INTVAL (op[3]) == 7
8427           && REGNO (op[0]) == REGNO (op[2]))
8428         {
8429           avr_asm_len ("subi %0,0x80", op, plen, -1);
8430         }
8431       else
8432         {
8433           avr_asm_len ("bst %2,%3" CR_TAB
8434                        "bld %0,%1" CR_TAB
8435                        "subi %0,0x80", op, plen, -3);
8436         }
8437     }
8438   else if (test_hard_reg_class (LD_REGS, op[0])
8439            && (INTVAL (op[1]) != INTVAL (op[3])
8440                || !reg_overlap_mentioned_p (op[0], op[2])))
8441     {
8442       /* If the destination bit is in a d-reg we can jump depending
8443          on the source bit and use ANDI / ORI.  This just applies if we
8444          have not an early-clobber situation with the bit.  */
8445 
8446       avr_asm_len ("andi %0,~(1<<%1)" CR_TAB
8447                    "sbrs %2,%3"       CR_TAB
8448                    "ori %0,1<<%1", op, plen, -3);
8449     }
8450   else
8451     {
8452       /* Otherwise, invert the bit by means of COM before we store it with
8453          BST and then undo the COM if needed.  */
8454 
8455       avr_asm_len ("com %2" CR_TAB
8456                    "bst %2,%3", op, plen, -2);
8457 
8458       if (!reg_unused_after (insn, op[2])
8459           // A simple 'reg_unused_after' is not enough because that function
8460           // assumes that the destination register is overwritten completely
8461           // and hence is in order for our purpose.  This is not the case
8462           // with BLD which just changes one bit of the destination.
8463           || reg_overlap_mentioned_p (op[0], op[2]))
8464         {
8465           /* Undo the COM from above.  */
8466           avr_asm_len ("com %2", op, plen, 1);
8467         }
8468 
8469       avr_asm_len ("bld %0,%1", op, plen, 1);
8470     }
8471 
8472   return "";
8473 }
8474 
8475 
8476 /* Outputs instructions needed for fixed point type conversion.
8477    This includes converting between any fixed point type, as well
8478    as converting to any integer type.  Conversion between integer
8479    types is not supported.
8480 
8481    Converting signed fractional types requires a bit shift if converting
8482    to or from any unsigned fractional type because the decimal place is
8483    shifted by 1 bit.  When the destination is a signed fractional, the sign
8484    is stored in either the carry or T bit.  */
8485 
8486 const char*
avr_out_fract(rtx_insn * insn,rtx operands[],bool intsigned,int * plen)8487 avr_out_fract (rtx_insn *insn, rtx operands[], bool intsigned, int *plen)
8488 {
8489   rtx xop[6];
8490   RTX_CODE shift = UNKNOWN;
8491   bool sign_in_carry = false;
8492   bool msb_in_carry = false;
8493   bool lsb_in_tmp_reg = false;
8494   bool lsb_in_carry = false;
8495   bool frac_rounded = false;
8496   const char *code_ashift = "lsl %0";
8497 
8498 
8499 #define MAY_CLOBBER(RR)                                                 \
8500   /* Shorthand used below.  */                                          \
8501   ((sign_bytes                                                          \
8502     && IN_RANGE (RR, dest.regno_msb - sign_bytes + 1, dest.regno_msb))  \
8503    || (offset && IN_RANGE (RR, dest.regno, dest.regno_msb))		\
8504    || (reg_unused_after (insn, all_regs_rtx[RR])                        \
8505        && !IN_RANGE (RR, dest.regno, dest.regno_msb)))
8506 
8507   struct
8508   {
8509     /* bytes       : Length of operand in bytes.
8510        ibyte       : Length of integral part in bytes.
8511        fbyte, fbit : Length of fractional part in bytes, bits.  */
8512 
8513     bool sbit;
8514     unsigned fbit, bytes, ibyte, fbyte;
8515     unsigned regno, regno_msb;
8516   } dest, src, *val[2] = { &dest, &src };
8517 
8518   if (plen)
8519     *plen = 0;
8520 
8521   /* Step 0:  Determine information on source and destination operand we
8522      ======   will need in the remainder.  */
8523 
8524   for (size_t i = 0; i < ARRAY_SIZE (val); i++)
8525     {
8526       machine_mode mode;
8527 
8528       xop[i] = operands[i];
8529 
8530       mode = GET_MODE (xop[i]);
8531 
8532       val[i]->bytes = GET_MODE_SIZE (mode);
8533       val[i]->regno = REGNO (xop[i]);
8534       val[i]->regno_msb = REGNO (xop[i]) + val[i]->bytes - 1;
8535 
8536       if (SCALAR_INT_MODE_P (mode))
8537         {
8538           val[i]->sbit = intsigned;
8539           val[i]->fbit = 0;
8540         }
8541       else if (ALL_SCALAR_FIXED_POINT_MODE_P (mode))
8542         {
8543           val[i]->sbit = SIGNED_SCALAR_FIXED_POINT_MODE_P (mode);
8544           val[i]->fbit = GET_MODE_FBIT (mode);
8545         }
8546       else
8547         fatal_insn ("unsupported fixed-point conversion", insn);
8548 
8549       val[i]->fbyte = (1 + val[i]->fbit) / BITS_PER_UNIT;
8550       val[i]->ibyte = val[i]->bytes - val[i]->fbyte;
8551     }
8552 
8553   // Byte offset of the decimal point taking into account different place
8554   // of the decimal point in input and output and different register numbers
8555   // of input and output.
8556   int offset = dest.regno - src.regno + dest.fbyte - src.fbyte;
8557 
8558   // Number of destination bytes that will come from sign / zero extension.
8559   int sign_bytes = (dest.ibyte - src.ibyte) * (dest.ibyte > src.ibyte);
8560 
8561   // Number of bytes at the low end to be filled with zeros.
8562   int zero_bytes = (dest.fbyte - src.fbyte) * (dest.fbyte > src.fbyte);
8563 
8564   // Do we have a 16-Bit register that is cleared?
8565   rtx clrw = NULL_RTX;
8566 
8567   bool sign_extend = src.sbit && sign_bytes;
8568 
8569   if (dest.fbit % 8 == 0 && src.fbit % 8 == 7)
8570     shift = ASHIFT;
8571   else if (dest.fbit % 8 == 7 && src.fbit % 8 == 0)
8572     shift = ASHIFTRT;
8573   else if (dest.fbit % 8 == src.fbit % 8)
8574     shift = UNKNOWN;
8575   else
8576     gcc_unreachable();
8577 
8578   /* If we need to round the fraction part, we might need to save/round it
8579      before clobbering any of it in Step 1.  Also, we might want to do
8580      the rounding now to make use of LD_REGS.  */
8581   if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8582       && SCALAR_ACCUM_MODE_P (GET_MODE (xop[1]))
8583       && !TARGET_FRACT_CONV_TRUNC)
8584     {
8585       bool overlap
8586         = (src.regno <=
8587            (offset ? dest.regno_msb - sign_bytes : dest.regno + zero_bytes - 1)
8588            && dest.regno - offset -1 >= dest.regno);
8589       unsigned s0 = dest.regno - offset -1;
8590       bool use_src = true;
8591       unsigned sn;
8592       unsigned copied_msb = src.regno_msb;
8593       bool have_carry = false;
8594 
8595       if (src.ibyte > dest.ibyte)
8596         copied_msb -= src.ibyte - dest.ibyte;
8597 
8598       for (sn = s0; sn <= copied_msb; sn++)
8599         if (!IN_RANGE (sn, dest.regno, dest.regno_msb)
8600             && !reg_unused_after (insn, all_regs_rtx[sn]))
8601           use_src = false;
8602       if (use_src && TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], s0))
8603         {
8604           avr_asm_len ("tst %0" CR_TAB "brpl 0f",
8605                        &all_regs_rtx[src.regno_msb], plen, 2);
8606           sn = src.regno;
8607           if (sn < s0)
8608             {
8609               if (TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], sn))
8610                 avr_asm_len ("cpi %0,1", &all_regs_rtx[sn], plen, 1);
8611               else
8612                 avr_asm_len ("sec" CR_TAB
8613                              "cpc %0,__zero_reg__",
8614                              &all_regs_rtx[sn], plen, 2);
8615               have_carry = true;
8616             }
8617           while (++sn < s0)
8618             avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8619 
8620           avr_asm_len (have_carry ? "sbci %0,128" : "subi %0,129",
8621                        &all_regs_rtx[s0], plen, 1);
8622           for (sn = src.regno + src.fbyte; sn <= copied_msb; sn++)
8623             avr_asm_len ("sbci %0,255", &all_regs_rtx[sn], plen, 1);
8624           avr_asm_len ("\n0:", NULL, plen, 0);
8625           frac_rounded = true;
8626         }
8627       else if (use_src && overlap)
8628         {
8629           avr_asm_len ("clr __tmp_reg__" CR_TAB
8630                        "sbrc %1,0"       CR_TAB
8631                        "dec __tmp_reg__", xop, plen, 1);
8632           sn = src.regno;
8633           if (sn < s0)
8634             {
8635               avr_asm_len ("add %0,__tmp_reg__", &all_regs_rtx[sn], plen, 1);
8636               have_carry = true;
8637             }
8638 
8639           while (++sn < s0)
8640             avr_asm_len ("adc %0,__tmp_reg__", &all_regs_rtx[sn], plen, 1);
8641 
8642           if (have_carry)
8643             avr_asm_len ("clt"                CR_TAB
8644                          "bld __tmp_reg__,7"  CR_TAB
8645                          "adc %0,__tmp_reg__",
8646                          &all_regs_rtx[s0], plen, 1);
8647           else
8648             avr_asm_len ("lsr __tmp_reg" CR_TAB
8649                          "add %0,__tmp_reg__",
8650                          &all_regs_rtx[s0], plen, 2);
8651           for (sn = src.regno + src.fbyte; sn <= copied_msb; sn++)
8652             avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8653           frac_rounded = true;
8654         }
8655       else if (overlap)
8656         {
8657           bool use_src
8658             = (TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], s0)
8659                && (IN_RANGE (s0, dest.regno, dest.regno_msb)
8660                    || reg_unused_after (insn, all_regs_rtx[s0])));
8661           xop[2] = all_regs_rtx[s0];
8662           unsigned sn = src.regno;
8663           if (!use_src || sn == s0)
8664             avr_asm_len ("mov __tmp_reg__,%2", xop, plen, 1);
8665           /* We need to consider to-be-discarded bits
8666              if the value is negative.  */
8667           if (sn < s0)
8668             {
8669               avr_asm_len ("tst %0" CR_TAB
8670                            "brpl 0f",
8671                            &all_regs_rtx[src.regno_msb], plen, 2);
8672               /* Test to-be-discarded bytes for any nozero bits.
8673                  ??? Could use OR or SBIW to test two registers at once.  */
8674               if (sn < s0)
8675                 avr_asm_len ("cp %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8676 
8677               while (++sn < s0)
8678                 avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8679               /* Set bit 0 in __tmp_reg__ if any of the lower bits was set.  */
8680               if (use_src)
8681                 avr_asm_len ("breq 0f" CR_TAB
8682                              "ori %2,1"
8683                              "\n0:\t" "mov __tmp_reg__,%2",
8684                              xop, plen, 3);
8685               else
8686                 avr_asm_len ("breq 0f" CR_TAB
8687                              "set"     CR_TAB
8688                              "bld __tmp_reg__,0\n0:",
8689                              xop, plen, 3);
8690             }
8691           lsb_in_tmp_reg = true;
8692         }
8693     }
8694 
8695   /* Step 1:  Clear bytes at the low end and copy payload bits from source
8696      ======   to destination.  */
8697 
8698   int step = offset < 0 ? 1 : -1;
8699   unsigned d0 = offset < 0 ? dest.regno : dest.regno_msb;
8700 
8701   // We cleared at least that number of registers.
8702   int clr_n = 0;
8703 
8704   for (; d0 >= dest.regno && d0 <= dest.regno_msb; d0 += step)
8705     {
8706       // Next regno of destination is needed for MOVW
8707       unsigned d1 = d0 + step;
8708 
8709       // Current and next regno of source
8710       signed s0 = d0 - offset;
8711       signed s1 = s0 + step;
8712 
8713       // Must current resp. next regno be CLRed?  This applies to the low
8714       // bytes of the destination that have no associated source bytes.
8715       bool clr0 = s0 < (signed) src.regno;
8716       bool clr1 = s1 < (signed) src.regno && d1 >= dest.regno;
8717 
8718       // First gather what code to emit (if any) and additional step to
8719       // apply if a MOVW is in use.  xop[2] is destination rtx and xop[3]
8720       // is the source rtx for the current loop iteration.
8721       const char *code = NULL;
8722       int stepw = 0;
8723 
8724       if (clr0)
8725         {
8726           if (AVR_HAVE_MOVW && clr1 && clrw)
8727             {
8728               xop[2] = all_regs_rtx[d0 & ~1];
8729               xop[3] = clrw;
8730               code = "movw %2,%3";
8731               stepw = step;
8732             }
8733           else
8734             {
8735               xop[2] = all_regs_rtx[d0];
8736               code = "clr %2";
8737 
8738               if (++clr_n >= 2
8739                   && !clrw
8740                   && d0 % 2 == (step > 0))
8741                 {
8742                   clrw = all_regs_rtx[d0 & ~1];
8743                 }
8744             }
8745         }
8746       else if (offset && s0 <= (signed) src.regno_msb)
8747         {
8748           int movw = AVR_HAVE_MOVW && offset % 2 == 0
8749             && d0 % 2 == (offset > 0)
8750             && d1 <= dest.regno_msb && d1 >= dest.regno
8751             && s1 <= (signed) src.regno_msb  && s1 >= (signed) src.regno;
8752 
8753           xop[2] = all_regs_rtx[d0 & ~movw];
8754           xop[3] = all_regs_rtx[s0 & ~movw];
8755           code = movw ? "movw %2,%3" : "mov %2,%3";
8756           stepw = step * movw;
8757         }
8758 
8759       if (code)
8760         {
8761           if (sign_extend && shift != ASHIFT && !sign_in_carry
8762               && (d0 == src.regno_msb || d0 + stepw == src.regno_msb))
8763             {
8764               /* We are going to override the sign bit.  If we sign-extend,
8765                  store the sign in the Carry flag.  This is not needed if
8766                  the destination will be ASHIFT in the remainder because
8767                  the ASHIFT will set Carry without extra instruction.  */
8768 
8769               avr_asm_len ("lsl %0", &all_regs_rtx[src.regno_msb], plen, 1);
8770               sign_in_carry = true;
8771             }
8772 
8773           unsigned src_msb = dest.regno_msb - sign_bytes - offset + 1;
8774 
8775           if (!sign_extend && shift == ASHIFTRT && !msb_in_carry
8776               && src.ibyte > dest.ibyte
8777               && (d0 == src_msb || d0 + stepw == src_msb))
8778             {
8779               /* We are going to override the MSB.  If we shift right,
8780                  store the MSB in the Carry flag.  This is only needed if
8781                  we don't sign-extend becaue with sign-extension the MSB
8782                  (the sign) will be produced by the sign extension.  */
8783 
8784               avr_asm_len ("lsr %0", &all_regs_rtx[src_msb], plen, 1);
8785               msb_in_carry = true;
8786             }
8787 
8788           unsigned src_lsb = dest.regno - offset -1;
8789 
8790           if (shift == ASHIFT && src.fbyte > dest.fbyte && !lsb_in_carry
8791 	      && !lsb_in_tmp_reg
8792               && (d0 == src_lsb || d0 + stepw == src_lsb))
8793             {
8794               /* We are going to override the new LSB; store it into carry.  */
8795 
8796               avr_asm_len ("lsl %0", &all_regs_rtx[src_lsb], plen, 1);
8797               code_ashift = "rol %0";
8798               lsb_in_carry = true;
8799             }
8800 
8801           avr_asm_len (code, xop, plen, 1);
8802           d0 += stepw;
8803         }
8804     }
8805 
8806   /* Step 2:  Shift destination left by 1 bit position.  This might be needed
8807      ======   for signed input and unsigned output.  */
8808 
8809   if (shift == ASHIFT && src.fbyte > dest.fbyte && !lsb_in_carry)
8810     {
8811       unsigned s0 = dest.regno - offset -1;
8812 
8813       /* n1169 4.1.4 says:
8814 	 "Conversions from a fixed-point to an integer type round toward zero."
8815 	 Hence, converting a fract type to integer only gives a non-zero result
8816 	 for -1.  */
8817       if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8818 	  && SCALAR_FRACT_MODE_P (GET_MODE (xop[1]))
8819 	  && !TARGET_FRACT_CONV_TRUNC)
8820 	{
8821 	  gcc_assert (s0 == src.regno_msb);
8822 	  /* Check if the input is -1.  We do that by checking if negating
8823 	     the input causes an integer overflow.  */
8824 	  unsigned sn = src.regno;
8825 	  avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx[sn++], plen, 1);
8826 	  while (sn <= s0)
8827 	    avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx[sn++], plen, 1);
8828 
8829 	  /* Overflow goes with set carry.  Clear carry otherwise.  */
8830 	  avr_asm_len ("brvs 0f" CR_TAB
8831                        "clc\n0:", NULL, plen, 2);
8832 	}
8833       /* Likewise, when converting from accumulator types to integer, we
8834 	 need to round up negative values.  */
8835       else if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8836 	       && SCALAR_ACCUM_MODE_P (GET_MODE (xop[1]))
8837 	       && !TARGET_FRACT_CONV_TRUNC
8838 	       && !frac_rounded)
8839 	{
8840 	  bool have_carry = false;
8841 
8842 	  xop[2] = all_regs_rtx[s0];
8843 	  if (!lsb_in_tmp_reg && !MAY_CLOBBER (s0))
8844 	    avr_asm_len ("mov __tmp_reg__,%2", xop, plen, 1);
8845 	  avr_asm_len ("tst %0" CR_TAB "brpl 0f",
8846 		       &all_regs_rtx[src.regno_msb], plen, 2);
8847 	  if (!lsb_in_tmp_reg)
8848 	    {
8849 	      unsigned sn = src.regno;
8850 	      if (sn < s0)
8851 		{
8852 		  avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx[sn],
8853 			       plen, 1);
8854 		  have_carry = true;
8855 		}
8856 	      while (++sn < s0)
8857 		avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx[sn], plen, 1);
8858 	      lsb_in_tmp_reg = !MAY_CLOBBER (s0);
8859 	    }
8860 	  /* Add in C and the rounding value 127.  */
8861 	  /* If the destination msb is a sign byte, and in LD_REGS,
8862 	     grab it as a temporary.  */
8863 	  if (sign_bytes
8864 	      && TEST_HARD_REG_BIT (reg_class_contents[LD_REGS],
8865 				    dest.regno_msb))
8866 	    {
8867 	      xop[3] = all_regs_rtx[dest.regno_msb];
8868 	      avr_asm_len ("ldi %3,127", xop, plen, 1);
8869 	      avr_asm_len ((have_carry && lsb_in_tmp_reg ? "adc __tmp_reg__,%3"
8870 			    : have_carry ? "adc %2,%3"
8871 			    : lsb_in_tmp_reg ? "add __tmp_reg__,%3"
8872 			    : "add %2,%3"),
8873 			   xop, plen, 1);
8874 	    }
8875 	  else
8876 	    {
8877 	      /* Fall back to use __zero_reg__ as a temporary.  */
8878 	      avr_asm_len ("dec __zero_reg__", NULL, plen, 1);
8879 	      if (have_carry)
8880 		avr_asm_len ("clt" CR_TAB
8881                              "bld __zero_reg__,7", NULL, plen, 2);
8882 	      else
8883 		avr_asm_len ("lsr __zero_reg__", NULL, plen, 1);
8884 	      avr_asm_len (have_carry && lsb_in_tmp_reg
8885                            ? "adc __tmp_reg__,__zero_reg__"
8886                            : have_carry ? "adc %2,__zero_reg__"
8887                            : lsb_in_tmp_reg ? "add __tmp_reg__,__zero_reg__"
8888                            : "add %2,__zero_reg__",
8889 			   xop, plen, 1);
8890 	      avr_asm_len ("eor __zero_reg__,__zero_reg__", NULL, plen, 1);
8891 	    }
8892 
8893           for (d0 = dest.regno + zero_bytes;
8894 	       d0 <= dest.regno_msb - sign_bytes; d0++)
8895 	    avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx[d0], plen, 1);
8896 
8897           avr_asm_len (lsb_in_tmp_reg
8898 		       ? "\n0:\t" "lsl __tmp_reg__"
8899                        : "\n0:\t" "lsl %2",
8900 		       xop, plen, 1);
8901 	}
8902       else if (MAY_CLOBBER (s0))
8903         avr_asm_len ("lsl %0", &all_regs_rtx[s0], plen, 1);
8904       else
8905         avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
8906                      "lsl __tmp_reg__", &all_regs_rtx[s0], plen, 2);
8907 
8908       code_ashift = "rol %0";
8909       lsb_in_carry = true;
8910     }
8911 
8912   if (shift == ASHIFT)
8913     {
8914       for (d0 = dest.regno + zero_bytes;
8915            d0 <= dest.regno_msb - sign_bytes; d0++)
8916         {
8917           avr_asm_len (code_ashift, &all_regs_rtx[d0], plen, 1);
8918           code_ashift = "rol %0";
8919         }
8920 
8921       lsb_in_carry = false;
8922       sign_in_carry = true;
8923     }
8924 
8925   /* Step 4a:  Store MSB in carry if we don't already have it or will produce
8926      =======   it in sign-extension below.  */
8927 
8928   if (!sign_extend && shift == ASHIFTRT && !msb_in_carry
8929       && src.ibyte > dest.ibyte)
8930     {
8931       unsigned s0 = dest.regno_msb - sign_bytes - offset + 1;
8932 
8933       if (MAY_CLOBBER (s0))
8934         avr_asm_len ("lsr %0", &all_regs_rtx[s0], plen, 1);
8935       else
8936         avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
8937                      "lsr __tmp_reg__", &all_regs_rtx[s0], plen, 2);
8938 
8939       msb_in_carry = true;
8940     }
8941 
8942   /* Step 3:  Sign-extend or zero-extend the destination as needed.
8943      ======   */
8944 
8945   if (sign_extend && !sign_in_carry)
8946     {
8947       unsigned s0 = src.regno_msb;
8948 
8949       if (MAY_CLOBBER (s0))
8950         avr_asm_len ("lsl %0", &all_regs_rtx[s0], plen, 1);
8951       else
8952         avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
8953                      "lsl __tmp_reg__", &all_regs_rtx[s0], plen, 2);
8954 
8955       sign_in_carry = true;
8956     }
8957 
8958   gcc_assert (sign_in_carry + msb_in_carry + lsb_in_carry <= 1);
8959 
8960   unsigned copies = 0;
8961   rtx movw = sign_extend ? NULL_RTX : clrw;
8962 
8963   for (d0 = dest.regno_msb - sign_bytes + 1; d0 <= dest.regno_msb; d0++)
8964     {
8965       if (AVR_HAVE_MOVW && movw
8966           && d0 % 2 == 0 && d0 + 1 <= dest.regno_msb)
8967         {
8968           xop[2] = all_regs_rtx[d0];
8969           xop[3] = movw;
8970           avr_asm_len ("movw %2,%3", xop, plen, 1);
8971           d0++;
8972         }
8973       else
8974         {
8975           avr_asm_len (sign_extend ? "sbc %0,%0" : "clr %0",
8976                        &all_regs_rtx[d0], plen, 1);
8977 
8978           if (++copies >= 2 && !movw && d0 % 2 == 1)
8979             movw = all_regs_rtx[d0-1];
8980         }
8981     } /* for */
8982 
8983 
8984   /* Step 4:  Right shift the destination.  This might be needed for
8985      ======   conversions from unsigned to signed.  */
8986 
8987   if (shift == ASHIFTRT)
8988     {
8989       const char *code_ashiftrt = "lsr %0";
8990 
8991       if (sign_extend || msb_in_carry)
8992         code_ashiftrt = "ror %0";
8993 
8994       if (src.sbit && src.ibyte == dest.ibyte)
8995         code_ashiftrt = "asr %0";
8996 
8997       for (d0 = dest.regno_msb - sign_bytes;
8998            d0 >= dest.regno + zero_bytes - 1 && d0 >= dest.regno; d0--)
8999         {
9000           avr_asm_len (code_ashiftrt, &all_regs_rtx[d0], plen, 1);
9001           code_ashiftrt = "ror %0";
9002         }
9003     }
9004 
9005 #undef MAY_CLOBBER
9006 
9007   return "";
9008 }
9009 
9010 
9011 /* Output fixed-point rounding.  XOP[0] = XOP[1] is the operand to round.
9012    XOP[2] is the rounding point, a CONST_INT.  The function prints the
9013    instruction sequence if PLEN = NULL and computes the length in words
9014    of the sequence if PLEN != NULL.  Most of this function deals with
9015    preparing operands for calls to `avr_out_plus' and `avr_out_bitop'.  */
9016 
9017 const char*
avr_out_round(rtx_insn * insn ATTRIBUTE_UNUSED,rtx * xop,int * plen)9018 avr_out_round (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *xop, int *plen)
9019 {
9020   scalar_mode mode = as_a <scalar_mode> (GET_MODE (xop[0]));
9021   scalar_int_mode imode = int_mode_for_mode (mode).require ();
9022   // The smallest fractional bit not cleared by the rounding is 2^(-RP).
9023   int fbit = (int) GET_MODE_FBIT (mode);
9024   double_int i_add = double_int_zero.set_bit (fbit-1 - INTVAL (xop[2]));
9025   wide_int wi_add = wi::set_bit_in_zero (fbit-1 - INTVAL (xop[2]),
9026 					 GET_MODE_PRECISION (imode));
9027   // Lengths of PLUS and AND parts.
9028   int len_add = 0, *plen_add = plen ? &len_add : NULL;
9029   int len_and = 0, *plen_and = plen ? &len_and : NULL;
9030 
9031   // Add-Saturate  1/2 * 2^(-RP).  Don't print the label "0:" when printing
9032   // the saturated addition so that we can emit the "rjmp 1f" before the
9033   // "0:" below.
9034 
9035   rtx xadd = const_fixed_from_double_int (i_add, mode);
9036   rtx xpattern, xsrc, op[4];
9037 
9038   xsrc = SIGNED_FIXED_POINT_MODE_P (mode)
9039     ? gen_rtx_SS_PLUS (mode, xop[1], xadd)
9040     : gen_rtx_US_PLUS (mode, xop[1], xadd);
9041   xpattern = gen_rtx_SET (xop[0], xsrc);
9042 
9043   op[0] = xop[0];
9044   op[1] = xop[1];
9045   op[2] = xadd;
9046   avr_out_plus (xpattern, op, plen_add, NULL, false /* Don't print "0:" */);
9047 
9048   avr_asm_len ("rjmp 1f" CR_TAB
9049                "0:", NULL, plen_add, 1);
9050 
9051   // Keep  all bits from RP and higher:   ... 2^(-RP)
9052   // Clear all bits from RP+1 and lower:              2^(-RP-1) ...
9053   // Rounding point                           ^^^^^^^
9054   // Added above                                      ^^^^^^^^^
9055   rtx xreg = simplify_gen_subreg (imode, xop[0], mode, 0);
9056   rtx xmask = immed_wide_int_const (-wi_add - wi_add, imode);
9057 
9058   xpattern = gen_rtx_SET (xreg, gen_rtx_AND (imode, xreg, xmask));
9059 
9060   op[0] = xreg;
9061   op[1] = xreg;
9062   op[2] = xmask;
9063   op[3] = gen_rtx_SCRATCH (QImode);
9064   avr_out_bitop (xpattern, op, plen_and);
9065   avr_asm_len ("1:", NULL, plen, 0);
9066 
9067   if (plen)
9068     *plen = len_add + len_and;
9069 
9070   return "";
9071 }
9072 
9073 
9074 /* Create RTL split patterns for byte sized rotate expressions.  This
9075    produces a series of move instructions and considers overlap situations.
9076    Overlapping non-HImode operands need a scratch register.  */
9077 
9078 bool
avr_rotate_bytes(rtx operands[])9079 avr_rotate_bytes (rtx operands[])
9080 {
9081   machine_mode mode = GET_MODE (operands[0]);
9082   bool overlapped = reg_overlap_mentioned_p (operands[0], operands[1]);
9083   bool same_reg = rtx_equal_p (operands[0], operands[1]);
9084   int num = INTVAL (operands[2]);
9085   rtx scratch = operands[3];
9086   /* Work out if byte or word move is needed.  Odd byte rotates need QImode.
9087      Word move if no scratch is needed, otherwise use size of scratch.  */
9088   machine_mode move_mode = QImode;
9089   int move_size, offset, size;
9090 
9091   if (num & 0xf)
9092     move_mode = QImode;
9093   else if ((mode == SImode && !same_reg) || !overlapped)
9094     move_mode = HImode;
9095   else
9096     move_mode = GET_MODE (scratch);
9097 
9098   /* Force DI rotate to use QI moves since other DI moves are currently split
9099      into QI moves so forward propagation works better.  */
9100   if (mode == DImode)
9101     move_mode = QImode;
9102   /* Make scratch smaller if needed.  */
9103   if (SCRATCH != GET_CODE (scratch)
9104       && HImode == GET_MODE (scratch)
9105       && QImode == move_mode)
9106     scratch = simplify_gen_subreg (move_mode, scratch, HImode, 0);
9107 
9108   move_size = GET_MODE_SIZE (move_mode);
9109   /* Number of bytes/words to rotate.  */
9110   offset = (num  >> 3) / move_size;
9111   /* Number of moves needed.  */
9112   size = GET_MODE_SIZE (mode) / move_size;
9113   /* Himode byte swap is special case to avoid a scratch register.  */
9114   if (mode == HImode && same_reg)
9115     {
9116       /* HImode byte swap, using xor.  This is as quick as using scratch.  */
9117       rtx src, dst;
9118       src = simplify_gen_subreg (move_mode, operands[1], mode, 0);
9119       dst = simplify_gen_subreg (move_mode, operands[0], mode, 1);
9120       if (!rtx_equal_p (dst, src))
9121         {
9122           emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
9123           emit_move_insn (src, gen_rtx_XOR (QImode, src, dst));
9124           emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
9125         }
9126     }
9127   else
9128     {
9129 #define MAX_SIZE 8 /* GET_MODE_SIZE (DImode) / GET_MODE_SIZE (QImode)  */
9130       /* Create linked list of moves to determine move order.  */
9131       struct {
9132         rtx src, dst;
9133         int links;
9134       } move[MAX_SIZE + 8];
9135       int blocked, moves;
9136 
9137       gcc_assert (size <= MAX_SIZE);
9138       /* Generate list of subreg moves.  */
9139       for (int i = 0; i < size; i++)
9140         {
9141           int from = i;
9142           int to = (from + offset) % size;
9143           move[i].src = simplify_gen_subreg (move_mode, operands[1],
9144                                              mode, from * move_size);
9145           move[i].dst = simplify_gen_subreg (move_mode, operands[0],
9146                                              mode, to * move_size);
9147           move[i].links = -1;
9148         }
9149       /* Mark dependence where a dst of one move is the src of another move.
9150          The first move is a conflict as it must wait until second is
9151          performed.  We ignore moves to self - we catch this later.  */
9152       if (overlapped)
9153         for (int i = 0; i < size; i++)
9154           if (reg_overlap_mentioned_p (move[i].dst, operands[1]))
9155             for (int j = 0; j < size; j++)
9156               if (j != i && rtx_equal_p (move[j].src, move[i].dst))
9157                 {
9158                   /* The dst of move i is the src of move j.  */
9159                   move[i].links = j;
9160                   break;
9161                 }
9162 
9163       blocked = -1;
9164       moves = 0;
9165       /* Go through move list and perform non-conflicting moves.  As each
9166          non-overlapping move is made, it may remove other conflicts
9167          so the process is repeated until no conflicts remain.  */
9168       do
9169         {
9170           blocked = -1;
9171           moves = 0;
9172           /* Emit move where dst is not also a src or we have used that
9173              src already.  */
9174           for (int i = 0; i < size; i++)
9175             if (move[i].src != NULL_RTX)
9176               {
9177                 if (move[i].links == -1
9178                     || move[move[i].links].src == NULL_RTX)
9179                   {
9180                     moves++;
9181                     /* Ignore NOP moves to self.  */
9182                     if (!rtx_equal_p (move[i].dst, move[i].src))
9183                       emit_move_insn (move[i].dst, move[i].src);
9184 
9185                     /* Remove  conflict from list.  */
9186                     move[i].src = NULL_RTX;
9187                   }
9188                 else
9189                   blocked = i;
9190               }
9191 
9192           /* Check for deadlock. This is when no moves occurred and we have
9193              at least one blocked move.  */
9194           if (moves == 0 && blocked != -1)
9195             {
9196               /* Need to use scratch register to break deadlock.
9197                  Add move to put dst of blocked move into scratch.
9198                  When this move occurs, it will break chain deadlock.
9199                  The scratch register is substituted for real move.  */
9200 
9201               gcc_assert (SCRATCH != GET_CODE (scratch));
9202 
9203               move[size].src = move[blocked].dst;
9204               move[size].dst =  scratch;
9205               /* Scratch move is never blocked.  */
9206               move[size].links = -1;
9207               /* Make sure we have valid link.  */
9208               gcc_assert (move[blocked].links != -1);
9209               /* Replace src of  blocking move with scratch reg.  */
9210               move[move[blocked].links].src = scratch;
9211               /* Make dependent on scratch move occurring.  */
9212               move[blocked].links = size;
9213               size=size+1;
9214             }
9215         }
9216       while (blocked != -1);
9217     }
9218   return true;
9219 }
9220 
9221 
9222 /* Worker function for `ADJUST_INSN_LENGTH'.  */
9223 /* Modifies the length assigned to instruction INSN
9224    LEN is the initially computed length of the insn.  */
9225 
9226 int
avr_adjust_insn_length(rtx_insn * insn,int len)9227 avr_adjust_insn_length (rtx_insn *insn, int len)
9228 {
9229   rtx *op = recog_data.operand;
9230   enum attr_adjust_len adjust_len;
9231 
9232   /* As we pretend jump tables in .text, fix branch offsets crossing jump
9233      tables now.  */
9234 
9235   if (JUMP_TABLE_DATA_P (insn))
9236     return 0;
9237 
9238   /* Some complex insns don't need length adjustment and therefore
9239      the length need not/must not be adjusted for these insns.
9240      It is easier to state this in an insn attribute "adjust_len" than
9241      to clutter up code here...  */
9242 
9243   if (!NONDEBUG_INSN_P (insn) || recog_memoized (insn) == -1)
9244     {
9245       return len;
9246     }
9247 
9248   /* Read from insn attribute "adjust_len" if/how length is to be adjusted.  */
9249 
9250   adjust_len = get_attr_adjust_len (insn);
9251 
9252   if (adjust_len == ADJUST_LEN_NO)
9253     {
9254       /* Nothing to adjust: The length from attribute "length" is fine.
9255          This is the default.  */
9256 
9257       return len;
9258     }
9259 
9260   /* Extract insn's operands.  */
9261 
9262   extract_constrain_insn_cached (insn);
9263 
9264   /* Dispatch to right function.  */
9265 
9266   switch (adjust_len)
9267     {
9268     case ADJUST_LEN_RELOAD_IN16: output_reload_inhi (op, op[2], &len); break;
9269     case ADJUST_LEN_RELOAD_IN24: avr_out_reload_inpsi (op, op[2], &len); break;
9270     case ADJUST_LEN_RELOAD_IN32: output_reload_insisf (op, op[2], &len); break;
9271 
9272     case ADJUST_LEN_OUT_BITOP: avr_out_bitop (insn, op, &len); break;
9273 
9274     case ADJUST_LEN_PLUS: avr_out_plus (insn, op, &len); break;
9275     case ADJUST_LEN_ADDTO_SP: avr_out_addto_sp (op, &len); break;
9276 
9277     case ADJUST_LEN_MOV8:  output_movqi (insn, op, &len); break;
9278     case ADJUST_LEN_MOV16: output_movhi (insn, op, &len); break;
9279     case ADJUST_LEN_MOV24: avr_out_movpsi (insn, op, &len); break;
9280     case ADJUST_LEN_MOV32: output_movsisf (insn, op, &len); break;
9281     case ADJUST_LEN_CPYMEM: avr_out_cpymem (insn, op, &len); break;
9282     case ADJUST_LEN_XLOAD: avr_out_xload (insn, op, &len); break;
9283     case ADJUST_LEN_SEXT: avr_out_sign_extend (insn, op, &len); break;
9284 
9285     case ADJUST_LEN_SFRACT: avr_out_fract (insn, op, true, &len); break;
9286     case ADJUST_LEN_UFRACT: avr_out_fract (insn, op, false, &len); break;
9287     case ADJUST_LEN_ROUND: avr_out_round (insn, op, &len); break;
9288 
9289     case ADJUST_LEN_TSTHI: avr_out_tsthi (insn, op, &len); break;
9290     case ADJUST_LEN_TSTPSI: avr_out_tstpsi (insn, op, &len); break;
9291     case ADJUST_LEN_TSTSI: avr_out_tstsi (insn, op, &len); break;
9292     case ADJUST_LEN_COMPARE: avr_out_compare (insn, op, &len); break;
9293     case ADJUST_LEN_COMPARE64: avr_out_compare64 (insn, op, &len); break;
9294 
9295     case ADJUST_LEN_LSHRQI: lshrqi3_out (insn, op, &len); break;
9296     case ADJUST_LEN_LSHRHI: lshrhi3_out (insn, op, &len); break;
9297     case ADJUST_LEN_LSHRSI: lshrsi3_out (insn, op, &len); break;
9298 
9299     case ADJUST_LEN_ASHRQI: ashrqi3_out (insn, op, &len); break;
9300     case ADJUST_LEN_ASHRHI: ashrhi3_out (insn, op, &len); break;
9301     case ADJUST_LEN_ASHRSI: ashrsi3_out (insn, op, &len); break;
9302 
9303     case ADJUST_LEN_ASHLQI: ashlqi3_out (insn, op, &len); break;
9304     case ADJUST_LEN_ASHLHI: ashlhi3_out (insn, op, &len); break;
9305     case ADJUST_LEN_ASHLSI: ashlsi3_out (insn, op, &len); break;
9306 
9307     case ADJUST_LEN_ASHLPSI: avr_out_ashlpsi3 (insn, op, &len); break;
9308     case ADJUST_LEN_ASHRPSI: avr_out_ashrpsi3 (insn, op, &len); break;
9309     case ADJUST_LEN_LSHRPSI: avr_out_lshrpsi3 (insn, op, &len); break;
9310 
9311     case ADJUST_LEN_CALL: len = AVR_HAVE_JMP_CALL ? 2 : 1; break;
9312 
9313     case ADJUST_LEN_INSERT_BITS: avr_out_insert_bits (op, &len); break;
9314 
9315     case ADJUST_LEN_INSV_NOTBIT:
9316       avr_out_insert_notbit (insn, op, NULL_RTX, &len);
9317       break;
9318     case ADJUST_LEN_INSV_NOTBIT_0:
9319       avr_out_insert_notbit (insn, op, const0_rtx, &len);
9320       break;
9321     case ADJUST_LEN_INSV_NOTBIT_7:
9322       avr_out_insert_notbit (insn, op, GEN_INT (7), &len);
9323       break;
9324 
9325     default:
9326       gcc_unreachable();
9327     }
9328 
9329   return len;
9330 }
9331 
9332 /* Return nonzero if register REG dead after INSN.  */
9333 
9334 int
reg_unused_after(rtx_insn * insn,rtx reg)9335 reg_unused_after (rtx_insn *insn, rtx reg)
9336 {
9337   return (dead_or_set_p (insn, reg)
9338 	  || (REG_P (reg) && _reg_unused_after (insn, reg)));
9339 }
9340 
9341 /* Return nonzero if REG is not used after INSN.
9342    We assume REG is a reload reg, and therefore does
9343    not live past labels.  It may live past calls or jumps though.  */
9344 
9345 int
_reg_unused_after(rtx_insn * insn,rtx reg)9346 _reg_unused_after (rtx_insn *insn, rtx reg)
9347 {
9348   enum rtx_code code;
9349   rtx set;
9350 
9351   /* If the reg is set by this instruction, then it is safe for our
9352      case.  Disregard the case where this is a store to memory, since
9353      we are checking a register used in the store address.  */
9354   set = single_set (insn);
9355   if (set && !MEM_P (SET_DEST (set))
9356       && reg_overlap_mentioned_p (reg, SET_DEST (set)))
9357     return 1;
9358 
9359   while ((insn = NEXT_INSN (insn)))
9360     {
9361       rtx set;
9362       code = GET_CODE (insn);
9363 
9364 #if 0
9365       /* If this is a label that existed before reload, then the register
9366 	 if dead here.  However, if this is a label added by reorg, then
9367 	 the register may still be live here.  We can't tell the difference,
9368 	 so we just ignore labels completely.  */
9369       if (code == CODE_LABEL)
9370 	return 1;
9371       /* else */
9372 #endif
9373 
9374       if (!INSN_P (insn))
9375 	continue;
9376 
9377       if (code == JUMP_INSN)
9378 	return 0;
9379 
9380       /* If this is a sequence, we must handle them all at once.
9381 	 We could have for instance a call that sets the target register,
9382 	 and an insn in a delay slot that uses the register.  In this case,
9383 	 we must return 0.  */
9384       else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
9385 	{
9386 	  rtx_sequence *seq = as_a <rtx_sequence *> (PATTERN (insn));
9387 	  int retval = 0;
9388 
9389 	  for (int i = 0; i < seq->len (); i++)
9390 	    {
9391 	      rtx_insn *this_insn = seq->insn (i);
9392 	      rtx set = single_set (this_insn);
9393 
9394 	      if (CALL_P (this_insn))
9395 		code = CALL_INSN;
9396 	      else if (JUMP_P (this_insn))
9397 		{
9398 		  if (INSN_ANNULLED_BRANCH_P (this_insn))
9399 		    return 0;
9400 		  code = JUMP_INSN;
9401 		}
9402 
9403 	      if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
9404 		return 0;
9405 	      if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
9406 		{
9407 		  if (!MEM_P (SET_DEST (set)))
9408 		    retval = 1;
9409 		  else
9410 		    return 0;
9411 		}
9412 	      if (set == 0
9413 		  && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
9414 		return 0;
9415 	    }
9416 	  if (retval == 1)
9417 	    return 1;
9418 	  else if (code == JUMP_INSN)
9419 	    return 0;
9420 	}
9421 
9422       if (code == CALL_INSN)
9423 	{
9424 	  rtx tem;
9425 	  for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
9426 	    if (GET_CODE (XEXP (tem, 0)) == USE
9427 		&& REG_P (XEXP (XEXP (tem, 0), 0))
9428 		&& reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
9429 	      return 0;
9430 	  if (call_used_or_fixed_reg_p (REGNO (reg)))
9431 	    return 1;
9432 	}
9433 
9434       set = single_set (insn);
9435 
9436       if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
9437 	return 0;
9438       if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
9439 	return !MEM_P (SET_DEST (set));
9440       if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
9441 	return 0;
9442     }
9443   return 1;
9444 }
9445 
9446 
9447 /* Implement `TARGET_ASM_INTEGER'.  */
9448 /* Target hook for assembling integer objects.  The AVR version needs
9449    special handling for references to certain labels.  */
9450 
9451 static bool
avr_assemble_integer(rtx x,unsigned int size,int aligned_p)9452 avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
9453 {
9454   if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
9455       && text_segment_operand (x, VOIDmode))
9456     {
9457       fputs ("\t.word\tgs(", asm_out_file);
9458       output_addr_const (asm_out_file, x);
9459       fputs (")\n", asm_out_file);
9460 
9461       return true;
9462     }
9463   else if (GET_MODE (x) == PSImode)
9464     {
9465       /* This needs binutils 2.23+, see PR binutils/13503  */
9466 
9467       fputs ("\t.byte\tlo8(", asm_out_file);
9468       output_addr_const (asm_out_file, x);
9469       fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
9470 
9471       fputs ("\t.byte\thi8(", asm_out_file);
9472       output_addr_const (asm_out_file, x);
9473       fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
9474 
9475       fputs ("\t.byte\thh8(", asm_out_file);
9476       output_addr_const (asm_out_file, x);
9477       fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
9478 
9479       return true;
9480     }
9481   else if (CONST_FIXED_P (x))
9482     {
9483       /* varasm fails to handle big fixed modes that don't fit in hwi.  */
9484 
9485       for (unsigned n = 0; n < size; n++)
9486         {
9487           rtx xn = simplify_gen_subreg (QImode, x, GET_MODE (x), n);
9488           default_assemble_integer (xn, 1, aligned_p);
9489         }
9490 
9491       return true;
9492     }
9493 
9494   if (AVR_TINY
9495       && avr_address_tiny_pm_p (x))
9496     {
9497       x = plus_constant (Pmode, x, avr_arch->flash_pm_offset);
9498     }
9499 
9500   return default_assemble_integer (x, size, aligned_p);
9501 }
9502 
9503 /* Implement TARGET_CLASS_MAX_NREGS. Reasons described in comments for
9504    avr_hard_regno_nregs. */
9505 
9506 static unsigned char
avr_class_max_nregs(reg_class_t rclass,machine_mode mode)9507 avr_class_max_nregs (reg_class_t rclass, machine_mode mode)
9508 {
9509   if (rclass == CC_REG && mode == CCmode)
9510 	return 1;
9511 
9512   return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
9513 }
9514 
9515 
9516 /* Implement `TARGET_CLASS_LIKELY_SPILLED_P'.  */
9517 /* Return value is nonzero if pseudos that have been
9518    assigned to registers of class CLASS would likely be spilled
9519    because registers of CLASS are needed for spill registers.  */
9520 
9521 static bool
avr_class_likely_spilled_p(reg_class_t c)9522 avr_class_likely_spilled_p (reg_class_t c)
9523 {
9524   return (c != ALL_REGS &&
9525            (AVR_TINY ? 1 : c != ADDW_REGS));
9526 }
9527 
9528 
9529 /* Valid attributes:
9530    progmem   -  Put data to program memory.
9531    signal    -  Make a function to be hardware interrupt.
9532                 After function prologue interrupts remain disabled.
9533    interrupt -  Make a function to be hardware interrupt. Before function
9534                 prologue interrupts are enabled by means of SEI.
9535    naked     -  Don't generate function prologue/epilogue and RET
9536                 instruction.  */
9537 
9538 /* Handle a "progmem" attribute; arguments as in
9539    struct attribute_spec.handler.  */
9540 
9541 static tree
avr_handle_progmem_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)9542 avr_handle_progmem_attribute (tree *node, tree name,
9543 			      tree args ATTRIBUTE_UNUSED,
9544 			      int flags ATTRIBUTE_UNUSED,
9545 			      bool *no_add_attrs)
9546 {
9547   if (DECL_P (*node))
9548     {
9549       if (TREE_CODE (*node) == TYPE_DECL)
9550 	{
9551 	  /* This is really a decl attribute, not a type attribute,
9552 	     but try to handle it for GCC 3.0 backwards compatibility.  */
9553 
9554 	  tree type = TREE_TYPE (*node);
9555 	  tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
9556 	  tree newtype = build_type_attribute_variant (type, attr);
9557 
9558 	  TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
9559 	  TREE_TYPE (*node) = newtype;
9560 	  *no_add_attrs = true;
9561 	}
9562       else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
9563 	{
9564           *no_add_attrs = false;
9565 	}
9566       else
9567 	{
9568 	  warning (OPT_Wattributes, "%qE attribute ignored",
9569 		   name);
9570 	  *no_add_attrs = true;
9571 	}
9572     }
9573 
9574   return NULL_TREE;
9575 }
9576 
9577 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
9578    struct attribute_spec.handler.  */
9579 
9580 static tree
avr_handle_fndecl_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)9581 avr_handle_fndecl_attribute (tree *node, tree name,
9582 			     tree args ATTRIBUTE_UNUSED,
9583 			     int flags ATTRIBUTE_UNUSED,
9584 			     bool *no_add_attrs)
9585 {
9586   if (TREE_CODE (*node) != FUNCTION_DECL)
9587     {
9588       warning (OPT_Wattributes, "%qE attribute only applies to functions",
9589 	       name);
9590       *no_add_attrs = true;
9591     }
9592 
9593   return NULL_TREE;
9594 }
9595 
9596 static tree
avr_handle_fntype_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)9597 avr_handle_fntype_attribute (tree *node, tree name,
9598                              tree args ATTRIBUTE_UNUSED,
9599                              int flags ATTRIBUTE_UNUSED,
9600                              bool *no_add_attrs)
9601 {
9602   if (TREE_CODE (*node) != FUNCTION_TYPE)
9603     {
9604       warning (OPT_Wattributes, "%qE attribute only applies to functions",
9605 	       name);
9606       *no_add_attrs = true;
9607     }
9608 
9609   return NULL_TREE;
9610 }
9611 
9612 static tree
avr_handle_absdata_attribute(tree * node,tree name,tree,int,bool * no_add)9613 avr_handle_absdata_attribute (tree *node, tree name, tree /* args */,
9614                               int /* flags */, bool *no_add)
9615 {
9616   location_t loc = DECL_SOURCE_LOCATION (*node);
9617 
9618   if (AVR_TINY)
9619     {
9620       if (TREE_CODE (*node) != VAR_DECL
9621           || (!TREE_STATIC (*node) && !DECL_EXTERNAL (*node)))
9622         {
9623           warning_at (loc, OPT_Wattributes, "%qE attribute only applies to"
9624                       " variables in static storage", name);
9625           *no_add = true;
9626         }
9627     }
9628   else
9629     {
9630       warning_at (loc, OPT_Wattributes, "%qE attribute only supported"
9631                   " for reduced Tiny cores", name);
9632       *no_add = true;
9633     }
9634 
9635   return NULL_TREE;
9636 }
9637 
9638 static tree
avr_handle_addr_attribute(tree * node,tree name,tree args,int flags ATTRIBUTE_UNUSED,bool * no_add)9639 avr_handle_addr_attribute (tree *node, tree name, tree args,
9640 			   int flags ATTRIBUTE_UNUSED, bool *no_add)
9641 {
9642   bool io_p = startswith (IDENTIFIER_POINTER (name), "io");
9643   location_t loc = DECL_SOURCE_LOCATION (*node);
9644 
9645   if (!VAR_P (*node))
9646     {
9647       warning_at (loc, OPT_Wattributes, "%qE attribute only applies to "
9648 		  "variables", name);
9649       *no_add = true;
9650       return NULL_TREE;
9651     }
9652 
9653   if (args != NULL_TREE)
9654     {
9655       if (TREE_CODE (TREE_VALUE (args)) == NON_LVALUE_EXPR)
9656 	TREE_VALUE (args) = TREE_OPERAND (TREE_VALUE (args), 0);
9657       tree arg = TREE_VALUE (args);
9658       if (TREE_CODE (arg) != INTEGER_CST)
9659 	{
9660 	  warning_at (loc, OPT_Wattributes, "%qE attribute allows only an "
9661 		      "integer constant argument", name);
9662 	  *no_add = true;
9663 	}
9664       else if (io_p
9665 	       && (!tree_fits_shwi_p (arg)
9666 		   || !(strcmp (IDENTIFIER_POINTER (name), "io_low") == 0
9667 			? low_io_address_operand : io_address_operand)
9668 			 (GEN_INT (TREE_INT_CST_LOW (arg)), QImode)))
9669 	{
9670 	  warning_at (loc, OPT_Wattributes, "%qE attribute address "
9671 		      "out of range", name);
9672 	  *no_add = true;
9673 	}
9674       else
9675 	{
9676 	  tree attribs = DECL_ATTRIBUTES (*node);
9677 	  const char *names[] = { "io", "io_low", "address", NULL };
9678 	  for (const char **p = names; *p; p++)
9679 	    {
9680 	      tree other = lookup_attribute (*p, attribs);
9681 	      if (other && TREE_VALUE (other))
9682 		{
9683 		  warning_at (loc, OPT_Wattributes,
9684 			      "both %s and %qE attribute provide address",
9685 			      *p, name);
9686 		  *no_add = true;
9687 		  break;
9688 		}
9689 	    }
9690 	}
9691     }
9692 
9693   if (*no_add == false && io_p && !TREE_THIS_VOLATILE (*node))
9694     warning_at (loc, OPT_Wattributes, "%qE attribute on non-volatile variable",
9695 		name);
9696 
9697   return NULL_TREE;
9698 }
9699 
9700 rtx
avr_eval_addr_attrib(rtx x)9701 avr_eval_addr_attrib (rtx x)
9702 {
9703   if (SYMBOL_REF_P (x)
9704       && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_ADDRESS))
9705     {
9706       tree decl = SYMBOL_REF_DECL (x);
9707       tree attr = NULL_TREE;
9708 
9709       if (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO)
9710 	{
9711 	  attr = lookup_attribute ("io", DECL_ATTRIBUTES (decl));
9712           if (!attr || !TREE_VALUE (attr))
9713             attr = lookup_attribute ("io_low", DECL_ATTRIBUTES (decl));
9714 	  gcc_assert (attr);
9715 	}
9716       if (!attr || !TREE_VALUE (attr))
9717 	attr = lookup_attribute ("address", DECL_ATTRIBUTES (decl));
9718       gcc_assert (attr && TREE_VALUE (attr) && TREE_VALUE (TREE_VALUE (attr)));
9719       return GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))));
9720     }
9721   return x;
9722 }
9723 
9724 
9725 /* AVR attributes.  */
9726 static const struct attribute_spec avr_attribute_table[] =
9727 {
9728   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
9729        affects_type_identity, handler, exclude } */
9730   { "progmem",   0, 0, false, false, false, false,
9731     avr_handle_progmem_attribute, NULL },
9732   { "signal",    0, 0, true,  false, false, false,
9733     avr_handle_fndecl_attribute, NULL },
9734   { "interrupt", 0, 0, true,  false, false, false,
9735     avr_handle_fndecl_attribute, NULL },
9736   { "no_gccisr", 0, 0, true,  false, false, false,
9737     avr_handle_fndecl_attribute, NULL },
9738   { "naked",     0, 0, false, true,  true,  false,
9739     avr_handle_fntype_attribute, NULL },
9740   { "OS_task",   0, 0, false, true,  true,  false,
9741     avr_handle_fntype_attribute, NULL },
9742   { "OS_main",   0, 0, false, true,  true,  false,
9743     avr_handle_fntype_attribute, NULL },
9744   { "io",        0, 1, true, false, false,  false,
9745     avr_handle_addr_attribute, NULL },
9746   { "io_low",    0, 1, true, false, false,  false,
9747     avr_handle_addr_attribute, NULL },
9748   { "address",   1, 1, true, false, false,  false,
9749     avr_handle_addr_attribute, NULL },
9750   { "absdata",   0, 0, true, false, false,  false,
9751     avr_handle_absdata_attribute, NULL },
9752   { NULL,        0, 0, false, false, false, false, NULL, NULL }
9753 };
9754 
9755 
9756 /* Return true if we support address space AS for the architecture in effect
9757    and false, otherwise.  If LOC is not UNKNOWN_LOCATION then also issue
9758    a respective error.  */
9759 
9760 bool
avr_addr_space_supported_p(addr_space_t as,location_t loc)9761 avr_addr_space_supported_p (addr_space_t as, location_t loc)
9762 {
9763   if (AVR_TINY)
9764     {
9765       if (loc != UNKNOWN_LOCATION)
9766         error_at (loc, "address spaces are not supported for reduced "
9767                   "Tiny devices");
9768       return false;
9769     }
9770   else if (avr_addrspace[as].segment >= avr_n_flash)
9771     {
9772       if (loc != UNKNOWN_LOCATION)
9773         error_at (loc, "address space %qs not supported for devices with "
9774                   "flash size up to %d KiB", avr_addrspace[as].name,
9775                   64 * avr_n_flash);
9776       return false;
9777     }
9778 
9779   return true;
9780 }
9781 
9782 
9783 /* Implement `TARGET_ADDR_SPACE_DIAGNOSE_USAGE'.  */
9784 
9785 static void
avr_addr_space_diagnose_usage(addr_space_t as,location_t loc)9786 avr_addr_space_diagnose_usage (addr_space_t as, location_t loc)
9787 {
9788   (void) avr_addr_space_supported_p (as, loc);
9789 }
9790 
9791 
9792 /* Look if DECL shall be placed in program memory space by
9793    means of attribute `progmem' or some address-space qualifier.
9794    Return non-zero if DECL is data that must end up in Flash and
9795    zero if the data lives in RAM (.bss, .data, .rodata, ...).
9796 
9797    Return 2   if DECL is located in 24-bit flash address-space
9798    Return 1   if DECL is located in 16-bit flash address-space
9799    Return -1  if attribute `progmem' occurs in DECL or ATTRIBUTES
9800    Return 0   otherwise  */
9801 
9802 int
avr_progmem_p(tree decl,tree attributes)9803 avr_progmem_p (tree decl, tree attributes)
9804 {
9805   tree a;
9806 
9807   if (TREE_CODE (decl) != VAR_DECL)
9808     return 0;
9809 
9810   if (avr_decl_memx_p (decl))
9811     return 2;
9812 
9813   if (avr_decl_flash_p (decl))
9814     return 1;
9815 
9816   if (NULL_TREE
9817       != lookup_attribute ("progmem", attributes))
9818     return -1;
9819 
9820   a = decl;
9821 
9822   do
9823     a = TREE_TYPE(a);
9824   while (TREE_CODE (a) == ARRAY_TYPE);
9825 
9826   if (a == error_mark_node)
9827     return 0;
9828 
9829   if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
9830     return -1;
9831 
9832   return 0;
9833 }
9834 
9835 
9836 /* Return true if DECL has attribute `absdata' set.  This function should
9837    only be used for AVR_TINY.  */
9838 
9839 static bool
avr_decl_absdata_p(tree decl,tree attributes)9840 avr_decl_absdata_p (tree decl, tree attributes)
9841 {
9842   return (TREE_CODE (decl) == VAR_DECL
9843           && NULL_TREE != lookup_attribute ("absdata", attributes));
9844 }
9845 
9846 
9847 /* Scan type TYP for pointer references to address space ASn.
9848    Return ADDR_SPACE_GENERIC (i.e. 0) if all pointers targeting
9849    the AS are also declared to be CONST.
9850    Otherwise, return the respective address space, i.e. a value != 0.  */
9851 
9852 static addr_space_t
avr_nonconst_pointer_addrspace(tree typ)9853 avr_nonconst_pointer_addrspace (tree typ)
9854 {
9855   while (ARRAY_TYPE == TREE_CODE (typ))
9856     typ = TREE_TYPE (typ);
9857 
9858   if (POINTER_TYPE_P (typ))
9859     {
9860       addr_space_t as;
9861       tree target = TREE_TYPE (typ);
9862 
9863       /* Pointer to function: Test the function's return type.  */
9864 
9865       if (FUNCTION_TYPE == TREE_CODE (target))
9866         return avr_nonconst_pointer_addrspace (TREE_TYPE (target));
9867 
9868       /* "Ordinary" pointers... */
9869 
9870       while (TREE_CODE (target) == ARRAY_TYPE)
9871         target = TREE_TYPE (target);
9872 
9873       /* Pointers to non-generic address space must be const.  */
9874 
9875       as = TYPE_ADDR_SPACE (target);
9876 
9877       if (!ADDR_SPACE_GENERIC_P (as)
9878           && !TYPE_READONLY (target)
9879           && avr_addr_space_supported_p (as))
9880         {
9881           return as;
9882         }
9883 
9884       /* Scan pointer's target type.  */
9885 
9886       return avr_nonconst_pointer_addrspace (target);
9887     }
9888 
9889   return ADDR_SPACE_GENERIC;
9890 }
9891 
9892 
9893 /* Sanity check NODE so that all pointers targeting non-generic address spaces
9894    go along with CONST qualifier.  Writing to these address spaces should
9895    be detected and complained about as early as possible.  */
9896 
9897 static bool
avr_pgm_check_var_decl(tree node)9898 avr_pgm_check_var_decl (tree node)
9899 {
9900   const char *reason = NULL;
9901 
9902   addr_space_t as = ADDR_SPACE_GENERIC;
9903 
9904   gcc_assert (as == 0);
9905 
9906   if (avr_log.progmem)
9907     avr_edump ("%?: %t\n", node);
9908 
9909   switch (TREE_CODE (node))
9910     {
9911     default:
9912       break;
9913 
9914     case VAR_DECL:
9915       if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
9916         reason = _("variable");
9917       break;
9918 
9919     case PARM_DECL:
9920       if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
9921         reason = _("function parameter");
9922       break;
9923 
9924     case FIELD_DECL:
9925       if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
9926         reason = _("structure field");
9927       break;
9928 
9929     case FUNCTION_DECL:
9930       if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (TREE_TYPE (node))),
9931           as)
9932         reason = _("return type of function");
9933       break;
9934 
9935     case POINTER_TYPE:
9936       if (as = avr_nonconst_pointer_addrspace (node), as)
9937         reason = _("pointer");
9938       break;
9939     }
9940 
9941   if (reason)
9942     {
9943       if (TYPE_P (node))
9944         error ("pointer targeting address space %qs must be const in %qT",
9945                avr_addrspace[as].name, node);
9946       else
9947         error ("pointer targeting address space %qs must be const"
9948                " in %s %q+D",
9949                avr_addrspace[as].name, reason, node);
9950     }
9951 
9952   return reason == NULL;
9953 }
9954 
9955 
9956 /* Implement `TARGET_INSERT_ATTRIBUTES'.  */
9957 
9958 static void
avr_insert_attributes(tree node,tree * attributes)9959 avr_insert_attributes (tree node, tree *attributes)
9960 {
9961   avr_pgm_check_var_decl (node);
9962 
9963   if (TARGET_MAIN_IS_OS_TASK
9964       && TREE_CODE (node) == FUNCTION_DECL
9965       && MAIN_NAME_P (DECL_NAME (node))
9966       // FIXME:  We'd like to also test `flag_hosted' which is only
9967       // available in the C-ish fronts, hence no such test for now.
9968       // Instead, we test the return type of "main" which is not exactly
9969       // the same but good enough.
9970       && INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (node)))
9971       && NULL == lookup_attribute ("OS_task", *attributes))
9972     {
9973       *attributes = tree_cons (get_identifier ("OS_task"),
9974                                NULL, *attributes);
9975     }
9976 
9977   /* Add the section attribute if the variable is in progmem.  */
9978 
9979   if (TREE_CODE (node) == VAR_DECL
9980       && (TREE_STATIC (node) || DECL_EXTERNAL (node))
9981       && avr_progmem_p (node, *attributes))
9982     {
9983       addr_space_t as;
9984       tree node0 = node;
9985 
9986       /* For C++, we have to peel arrays in order to get correct
9987          determination of readonlyness.  */
9988 
9989       do
9990         node0 = TREE_TYPE (node0);
9991       while (TREE_CODE (node0) == ARRAY_TYPE);
9992 
9993       if (error_mark_node == node0)
9994         return;
9995 
9996       as = TYPE_ADDR_SPACE (TREE_TYPE (node));
9997 
9998       if (!TYPE_READONLY (node0)
9999           && !TREE_READONLY (node))
10000         {
10001           const char *reason = "__attribute__((progmem))";
10002 
10003           if (!ADDR_SPACE_GENERIC_P (as))
10004             reason = avr_addrspace[as].name;
10005 
10006           if (avr_log.progmem)
10007             avr_edump ("\n%?: %t\n%t\n", node, node0);
10008 
10009           error ("variable %q+D must be const in order to be put into"
10010                  " read-only section by means of %qs", node, reason);
10011         }
10012     }
10013 }
10014 
10015 
10016 /* Implement `ASM_OUTPUT_ALIGNED_DECL_LOCAL'.  */
10017 /* Implement `ASM_OUTPUT_ALIGNED_DECL_COMMON'.  */
10018 /* Track need of __do_clear_bss.  */
10019 
10020 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)10021 avr_asm_output_aligned_decl_common (FILE * stream,
10022                                     tree decl,
10023                                     const char *name,
10024                                     unsigned HOST_WIDE_INT size,
10025                                     unsigned int align, bool local_p)
10026 {
10027   rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
10028   rtx symbol;
10029 
10030   if (mem != NULL_RTX && MEM_P (mem)
10031       && SYMBOL_REF_P ((symbol = XEXP (mem, 0)))
10032       && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
10033     {
10034       if (!local_p)
10035 	{
10036 	  fprintf (stream, "\t.globl\t");
10037 	  assemble_name (stream, name);
10038 	  fprintf (stream, "\n");
10039 	}
10040       if (SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS)
10041 	{
10042 	  assemble_name (stream, name);
10043 	  fprintf (stream, " = %ld\n",
10044 		   (long) INTVAL (avr_eval_addr_attrib (symbol)));
10045 	}
10046       else if (local_p)
10047 	error_at (DECL_SOURCE_LOCATION (decl),
10048 		  "static IO declaration for %q+D needs an address", decl);
10049       return;
10050     }
10051 
10052   /* __gnu_lto_slim is just a marker for the linker injected by toplev.c.
10053      There is no need to trigger __do_clear_bss code for them.  */
10054 
10055   if (!startswith (name, "__gnu_lto"))
10056     avr_need_clear_bss_p = true;
10057 
10058   if (local_p)
10059     ASM_OUTPUT_ALIGNED_LOCAL (stream, name, size, align);
10060   else
10061     ASM_OUTPUT_ALIGNED_COMMON (stream, name, size, align);
10062 }
10063 
10064 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))10065 avr_asm_asm_output_aligned_bss (FILE *file, tree decl, const char *name,
10066 				unsigned HOST_WIDE_INT size, int align,
10067 				void (*default_func)
10068 				  (FILE *, tree, const char *,
10069 				   unsigned HOST_WIDE_INT, int))
10070 {
10071   rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
10072   rtx symbol;
10073 
10074   if (mem != NULL_RTX && MEM_P (mem)
10075       && SYMBOL_REF_P ((symbol = XEXP (mem, 0)))
10076       && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
10077     {
10078       if (!(SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS))
10079 	error_at (DECL_SOURCE_LOCATION (decl),
10080 		  "IO definition for %q+D needs an address", decl);
10081       avr_asm_output_aligned_decl_common (file, decl, name, size, align, false);
10082     }
10083   else
10084     default_func (file, decl, name, size, align);
10085 }
10086 
10087 
10088 /* Unnamed section callback for data_section
10089    to track need of __do_copy_data.  */
10090 
10091 static void
avr_output_data_section_asm_op(const void * data)10092 avr_output_data_section_asm_op (const void *data)
10093 {
10094   avr_need_copy_data_p = true;
10095 
10096   /* Dispatch to default.  */
10097   output_section_asm_op (data);
10098 }
10099 
10100 
10101 /* Unnamed section callback for bss_section
10102    to track need of __do_clear_bss.  */
10103 
10104 static void
avr_output_bss_section_asm_op(const void * data)10105 avr_output_bss_section_asm_op (const void *data)
10106 {
10107   avr_need_clear_bss_p = true;
10108 
10109   /* Dispatch to default.  */
10110   output_section_asm_op (data);
10111 }
10112 
10113 
10114 /* Unnamed section callback for progmem*.data sections.  */
10115 
10116 static void
avr_output_progmem_section_asm_op(const char * data)10117 avr_output_progmem_section_asm_op (const char *data)
10118 {
10119   fprintf (asm_out_file, "\t.section\t%s,\"a\",@progbits\n", data);
10120 }
10121 
10122 
10123 /* Implement `TARGET_ASM_INIT_SECTIONS'.  */
10124 
10125 static void
avr_asm_init_sections(void)10126 avr_asm_init_sections (void)
10127 {
10128   /* Override section callbacks to keep track of `avr_need_clear_bss_p'
10129      resp. `avr_need_copy_data_p'.  If flash is not mapped to RAM then
10130      we have also to track .rodata because it is located in RAM then.  */
10131 
10132 #if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
10133   if (avr_arch->flash_pm_offset == 0)
10134 #endif
10135     readonly_data_section->unnamed.callback = avr_output_data_section_asm_op;
10136   data_section->unnamed.callback = avr_output_data_section_asm_op;
10137   bss_section->unnamed.callback = avr_output_bss_section_asm_op;
10138 }
10139 
10140 
10141 /* Implement `TARGET_ASM_NAMED_SECTION'.  */
10142 /* Track need of __do_clear_bss, __do_copy_data for named sections.  */
10143 
10144 static void
avr_asm_named_section(const char * name,unsigned int flags,tree decl)10145 avr_asm_named_section (const char *name, unsigned int flags, tree decl)
10146 {
10147   if (flags & AVR_SECTION_PROGMEM)
10148     {
10149       addr_space_t as = (flags & AVR_SECTION_PROGMEM) / SECTION_MACH_DEP;
10150       const char *old_prefix = ".rodata";
10151       const char *new_prefix = avr_addrspace[as].section_name;
10152 
10153       if (startswith (name, old_prefix))
10154         {
10155           const char *sname = ACONCAT ((new_prefix,
10156                                         name + strlen (old_prefix), NULL));
10157           default_elf_asm_named_section (sname, flags, decl);
10158           return;
10159         }
10160 
10161       default_elf_asm_named_section (new_prefix, flags, decl);
10162       return;
10163     }
10164 
10165   if (!avr_need_copy_data_p)
10166     avr_need_copy_data_p = (startswith (name, ".data")
10167 			    || startswith (name, ".gnu.linkonce.d"));
10168 
10169   if (!avr_need_copy_data_p
10170 #if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
10171       && avr_arch->flash_pm_offset == 0
10172 #endif
10173       )
10174     avr_need_copy_data_p = (startswith (name, ".rodata")
10175 			    || startswith (name, ".gnu.linkonce.r"));
10176 
10177   if (!avr_need_clear_bss_p)
10178     avr_need_clear_bss_p = startswith (name, ".bss");
10179 
10180   default_elf_asm_named_section (name, flags, decl);
10181 }
10182 
10183 
10184 /* Implement `TARGET_SECTION_TYPE_FLAGS'.  */
10185 
10186 static unsigned int
avr_section_type_flags(tree decl,const char * name,int reloc)10187 avr_section_type_flags (tree decl, const char *name, int reloc)
10188 {
10189   unsigned int flags = default_section_type_flags (decl, name, reloc);
10190 
10191   if (startswith (name, ".noinit"))
10192     {
10193       if (decl && TREE_CODE (decl) == VAR_DECL
10194 	  && DECL_INITIAL (decl) == NULL_TREE)
10195 	flags |= SECTION_BSS;  /* @nobits */
10196       else
10197 	warning (0, "only uninitialized variables can be placed in the "
10198 		 ".noinit section");
10199     }
10200 
10201   if (decl && DECL_P (decl)
10202       && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
10203     {
10204       addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
10205 
10206       /* Attribute progmem puts data in generic address space.
10207          Set section flags as if it was in __flash to get the right
10208          section prefix in the remainder.  */
10209 
10210       if (ADDR_SPACE_GENERIC_P (as))
10211         as = ADDR_SPACE_FLASH;
10212 
10213       flags |= as * SECTION_MACH_DEP;
10214       flags &= ~SECTION_WRITE;
10215       flags &= ~SECTION_BSS;
10216     }
10217 
10218   return flags;
10219 }
10220 
10221 
10222 /* A helper for the next function.  NODE is a decl that is associated with
10223    a symbol.  Return TRUE if the respective object may be accessed by LDS.
10224    There might still be other reasons for why LDS is not appropriate.
10225    This function is only appropriate for AVR_TINY.  */
10226 
10227 static bool
avr_decl_maybe_lds_p(tree node)10228 avr_decl_maybe_lds_p (tree node)
10229 {
10230   if (!node
10231       || TREE_CODE (node) != VAR_DECL
10232       || DECL_SECTION_NAME (node) != NULL)
10233     return false;
10234 
10235   /* Don't use LDS for objects that go to .rodata.  The current default
10236      linker description file still locates .rodata in RAM, but this is not
10237      a must.  A better linker script would just keep .rodata in flash and
10238      add an offset of 0x4000 to the VMA.  Hence avoid LDS for such data.  */
10239 
10240   if (TREE_READONLY (node))
10241     return false;
10242 
10243   // C++ requires peeling arrays.
10244 
10245   do
10246     node = TREE_TYPE (node);
10247   while (ARRAY_TYPE == TREE_CODE (node));
10248 
10249   return (node != error_mark_node
10250           && !TYPE_READONLY (node));
10251 }
10252 
10253 
10254 /* Implement `TARGET_ENCODE_SECTION_INFO'.  */
10255 
10256 static void
avr_encode_section_info(tree decl,rtx rtl,int new_decl_p)10257 avr_encode_section_info (tree decl, rtx rtl, int new_decl_p)
10258 {
10259   tree addr_attr = NULL_TREE;
10260 
10261   /* In avr_handle_progmem_attribute, DECL_INITIAL is not yet
10262      readily available, see PR34734.  So we postpone the warning
10263      about uninitialized data in program memory section until here.  */
10264 
10265   if (new_decl_p
10266       && decl && DECL_P (decl)
10267       && !DECL_EXTERNAL (decl)
10268       && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
10269     {
10270       if (!TREE_READONLY (decl))
10271         {
10272           // This might happen with C++ if stuff needs constructing.
10273           error ("variable %q+D with dynamic initialization put "
10274                  "into program memory area", decl);
10275         }
10276       else if (NULL_TREE == DECL_INITIAL (decl))
10277         {
10278           // Don't warn for (implicit) aliases like in PR80462.
10279           tree asmname = DECL_ASSEMBLER_NAME (decl);
10280           varpool_node *node = varpool_node::get_for_asmname (asmname);
10281           bool alias_p = node && node->alias;
10282 
10283           if (!alias_p)
10284             warning (OPT_Wuninitialized, "uninitialized variable %q+D put "
10285                      "into program memory area", decl);
10286         }
10287     }
10288 
10289   default_encode_section_info (decl, rtl, new_decl_p);
10290 
10291   if (decl && DECL_P (decl)
10292       && TREE_CODE (decl) != FUNCTION_DECL
10293       && MEM_P (rtl)
10294       && SYMBOL_REF_P (XEXP (rtl, 0)))
10295     {
10296       rtx sym = XEXP (rtl, 0);
10297       tree type = TREE_TYPE (decl);
10298       tree attr = DECL_ATTRIBUTES (decl);
10299       if (type == error_mark_node)
10300 	return;
10301 
10302       addr_space_t as = TYPE_ADDR_SPACE (type);
10303 
10304       /* PSTR strings are in generic space but located in flash:
10305          patch address space.  */
10306 
10307       if (!AVR_TINY && avr_progmem_p (decl, attr) == -1)
10308         as = ADDR_SPACE_FLASH;
10309 
10310       AVR_SYMBOL_SET_ADDR_SPACE (sym, as);
10311 
10312       tree io_low_attr = lookup_attribute ("io_low", attr);
10313       tree io_attr = lookup_attribute ("io", attr);
10314 
10315       if (io_low_attr
10316 	  && TREE_VALUE (io_low_attr) && TREE_VALUE (TREE_VALUE (io_low_attr)))
10317 	addr_attr = io_attr;
10318       else if (io_attr
10319 	       && TREE_VALUE (io_attr) && TREE_VALUE (TREE_VALUE (io_attr)))
10320 	addr_attr = io_attr;
10321       else
10322 	addr_attr = lookup_attribute ("address", attr);
10323       if (io_low_attr
10324 	  || (io_attr && addr_attr
10325               && low_io_address_operand
10326                   (GEN_INT (TREE_INT_CST_LOW
10327                             (TREE_VALUE (TREE_VALUE (addr_attr)))), QImode)))
10328 	SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO_LOW;
10329       if (io_attr || io_low_attr)
10330 	SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO;
10331       /* If we have an (io) address attribute specification, but the variable
10332 	 is external, treat the address as only a tentative definition
10333 	 to be used to determine if an io port is in the lower range, but
10334 	 don't use the exact value for constant propagation.  */
10335       if (addr_attr && !DECL_EXTERNAL (decl))
10336 	SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_ADDRESS;
10337     }
10338 
10339   if (AVR_TINY
10340       && decl
10341       && VAR_DECL == TREE_CODE (decl)
10342       && MEM_P (rtl)
10343       && SYMBOL_REF_P (XEXP (rtl, 0)))
10344     {
10345       rtx sym = XEXP (rtl, 0);
10346       bool progmem_p = avr_progmem_p (decl, DECL_ATTRIBUTES (decl)) == -1;
10347 
10348       if (progmem_p)
10349         {
10350           // Tag symbols for addition of 0x4000 (avr_arch->flash_pm_offset).
10351           SYMBOL_REF_FLAGS (sym) |= AVR_SYMBOL_FLAG_TINY_PM;
10352         }
10353 
10354       if (avr_decl_absdata_p (decl, DECL_ATTRIBUTES (decl))
10355           || (TARGET_ABSDATA
10356               && !progmem_p
10357               && !addr_attr
10358               && avr_decl_maybe_lds_p (decl))
10359           || (addr_attr
10360               // If addr_attr is non-null, it has an argument.  Peek into it.
10361               && TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (addr_attr))) < 0xc0))
10362         {
10363           // May be accessed by LDS / STS.
10364           SYMBOL_REF_FLAGS (sym) |= AVR_SYMBOL_FLAG_TINY_ABSDATA;
10365         }
10366 
10367       if (progmem_p
10368           && avr_decl_absdata_p (decl, DECL_ATTRIBUTES (decl)))
10369         {
10370           error ("%q+D has incompatible attributes %qs and %qs",
10371                  decl, "progmem", "absdata");
10372         }
10373     }
10374 }
10375 
10376 
10377 /* Implement `TARGET_ASM_SELECT_SECTION' */
10378 
10379 static section *
avr_asm_select_section(tree decl,int reloc,unsigned HOST_WIDE_INT align)10380 avr_asm_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
10381 {
10382   section * sect = default_elf_select_section (decl, reloc, align);
10383 
10384   if (decl && DECL_P (decl)
10385       && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
10386     {
10387       addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
10388 
10389       /* __progmem__ goes in generic space but shall be allocated to
10390          .progmem.data  */
10391 
10392       if (ADDR_SPACE_GENERIC_P (as))
10393         as = ADDR_SPACE_FLASH;
10394 
10395       if (sect->common.flags & SECTION_NAMED)
10396         {
10397           const char * name = sect->named.name;
10398           const char * old_prefix = ".rodata";
10399           const char * new_prefix = avr_addrspace[as].section_name;
10400 
10401 	  if (startswith (name, old_prefix))
10402             {
10403               const char *sname = ACONCAT ((new_prefix,
10404                                             name + strlen (old_prefix), NULL));
10405               return get_section (sname,
10406                                   sect->common.flags & ~SECTION_DECLARED,
10407                                   sect->named.decl);
10408             }
10409         }
10410 
10411       if (!progmem_section[as])
10412         {
10413           progmem_section[as]
10414             = get_unnamed_section (0, avr_output_progmem_section_asm_op,
10415                                    avr_addrspace[as].section_name);
10416         }
10417 
10418       return progmem_section[as];
10419     }
10420 
10421   return sect;
10422 }
10423 
10424 /* Implement `TARGET_ASM_FILE_START'.  */
10425 /* Outputs some text at the start of each assembler file.  */
10426 
10427 static void
avr_file_start(void)10428 avr_file_start (void)
10429 {
10430   int sfr_offset = avr_arch->sfr_offset;
10431 
10432   if (avr_arch->asm_only)
10433     error ("architecture %qs supported for assembler only", avr_mmcu);
10434 
10435   default_file_start ();
10436 
10437   /* Print I/O addresses of some SFRs used with IN and OUT.  */
10438 
10439   if (AVR_HAVE_SPH)
10440     fprintf (asm_out_file, "__SP_H__ = 0x%02x\n", avr_addr.sp_h - sfr_offset);
10441 
10442   fprintf (asm_out_file, "__SP_L__ = 0x%02x\n", avr_addr.sp_l - sfr_offset);
10443   fprintf (asm_out_file, "__SREG__ = 0x%02x\n", avr_addr.sreg - sfr_offset);
10444   if (AVR_HAVE_RAMPZ)
10445     fprintf (asm_out_file, "__RAMPZ__ = 0x%02x\n", avr_addr.rampz - sfr_offset);
10446   if (AVR_HAVE_RAMPY)
10447     fprintf (asm_out_file, "__RAMPY__ = 0x%02x\n", avr_addr.rampy - sfr_offset);
10448   if (AVR_HAVE_RAMPX)
10449     fprintf (asm_out_file, "__RAMPX__ = 0x%02x\n", avr_addr.rampx - sfr_offset);
10450   if (AVR_HAVE_RAMPD)
10451     fprintf (asm_out_file, "__RAMPD__ = 0x%02x\n", avr_addr.rampd - sfr_offset);
10452   if (AVR_XMEGA || AVR_TINY)
10453     fprintf (asm_out_file, "__CCP__ = 0x%02x\n", avr_addr.ccp - sfr_offset);
10454   fprintf (asm_out_file, "__tmp_reg__ = %d\n", AVR_TMP_REGNO);
10455   fprintf (asm_out_file, "__zero_reg__ = %d\n", AVR_ZERO_REGNO);
10456 }
10457 
10458 
10459 /* Implement `TARGET_ASM_FILE_END'.  */
10460 /* Outputs to the stdio stream FILE some
10461    appropriate text to go at the end of an assembler file.  */
10462 
10463 static void
avr_file_end(void)10464 avr_file_end (void)
10465 {
10466   /* Output these only if there is anything in the
10467      .data* / .rodata* / .gnu.linkonce.* resp. .bss* or COMMON
10468      input section(s) - some code size can be saved by not
10469      linking in the initialization code from libgcc if resp.
10470      sections are empty, see PR18145.  */
10471 
10472   if (avr_need_copy_data_p)
10473     fputs (".global __do_copy_data\n", asm_out_file);
10474 
10475   if (avr_need_clear_bss_p)
10476     fputs (".global __do_clear_bss\n", asm_out_file);
10477 }
10478 
10479 
10480 /* Worker function for `ADJUST_REG_ALLOC_ORDER'.  */
10481 /* Choose the order in which to allocate hard registers for
10482    pseudo-registers local to a basic block.
10483 
10484    Store the desired register order in the array `reg_alloc_order'.
10485    Element 0 should be the register to allocate first; element 1, the
10486    next register; and so on.  */
10487 
10488 void
avr_adjust_reg_alloc_order(void)10489 avr_adjust_reg_alloc_order (void)
10490 {
10491   static const int order_0[] =
10492     {
10493       24, 25,
10494       18, 19, 20, 21, 22, 23,
10495       30, 31,
10496       26, 27, 28, 29,
10497       17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
10498       0, 1,
10499       32, 33, 34, 35
10500     };
10501   static const int tiny_order_0[] = {
10502     20, 21,
10503     22, 23,
10504     24, 25,
10505     30, 31,
10506     26, 27,
10507     28, 29,
10508     19, 18,
10509     16, 17,
10510     32, 33, 34, 35,
10511     15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
10512   };
10513   static const int order_1[] =
10514     {
10515       18, 19, 20, 21, 22, 23, 24, 25,
10516       30, 31,
10517       26, 27, 28, 29,
10518       17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
10519       0, 1,
10520       32, 33, 34, 35
10521     };
10522   static const int tiny_order_1[] = {
10523     22, 23,
10524     24, 25,
10525     30, 31,
10526     26, 27,
10527     28, 29,
10528     21, 20, 19, 18,
10529     16, 17,
10530     32, 33, 34, 35,
10531     15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
10532   };
10533   static const int order_2[] =
10534     {
10535       25, 24, 23, 22, 21, 20, 19, 18,
10536       30, 31,
10537       26, 27, 28, 29,
10538       17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
10539       1, 0,
10540       32, 33, 34, 35
10541     };
10542 
10543   /* Select specific register allocation order.
10544      Tiny Core (ATtiny4/5/9/10/20/40) devices have only 16 registers,
10545      so different allocation order should be used.  */
10546 
10547   const int *order = (TARGET_ORDER_1 ? (AVR_TINY ? tiny_order_1 : order_1)
10548                       : TARGET_ORDER_2 ? (AVR_TINY ? tiny_order_0 : order_2)
10549                       : (AVR_TINY ? tiny_order_0 : order_0));
10550 
10551   for (size_t i = 0; i < ARRAY_SIZE (order_0); ++i)
10552     reg_alloc_order[i] = order[i];
10553 }
10554 
10555 
10556 /* Implement `TARGET_REGISTER_MOVE_COST' */
10557 
10558 static int
avr_register_move_cost(machine_mode mode ATTRIBUTE_UNUSED,reg_class_t from,reg_class_t to)10559 avr_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
10560                         reg_class_t from, reg_class_t to)
10561 {
10562   return (from == STACK_REG ? 6
10563           : to == STACK_REG ? 12
10564           : 2);
10565 }
10566 
10567 
10568 /* Implement `TARGET_MEMORY_MOVE_COST' */
10569 
10570 static int
avr_memory_move_cost(machine_mode mode,reg_class_t rclass ATTRIBUTE_UNUSED,bool in ATTRIBUTE_UNUSED)10571 avr_memory_move_cost (machine_mode mode,
10572                       reg_class_t rclass ATTRIBUTE_UNUSED,
10573                       bool in ATTRIBUTE_UNUSED)
10574 {
10575   return (mode == QImode ? 2
10576           : mode == HImode ? 4
10577           : mode == SImode ? 8
10578           : mode == SFmode ? 8
10579           : 16);
10580 }
10581 
10582 
10583 /* Cost for mul highpart.  X is a LSHIFTRT, i.e. the outer TRUNCATE is
10584    already stripped off.  */
10585 
10586 static int
avr_mul_highpart_cost(rtx x,int)10587 avr_mul_highpart_cost (rtx x, int)
10588 {
10589   if (AVR_HAVE_MUL
10590       && LSHIFTRT == GET_CODE (x)
10591       && MULT == GET_CODE (XEXP (x, 0))
10592       && CONST_INT_P (XEXP (x, 1)))
10593     {
10594       // This is the wider mode.
10595       machine_mode mode = GET_MODE (x);
10596 
10597       // The middle-end might still have PR81444, i.e. it is calling the cost
10598       // functions with strange modes.  Fix this now by also considering
10599       // PSImode (should actually be SImode instead).
10600       if (HImode == mode || PSImode == mode || SImode == mode)
10601         {
10602           return COSTS_N_INSNS (2);
10603         }
10604     }
10605 
10606   return 10000;
10607 }
10608 
10609 
10610 /* Mutually recursive subroutine of avr_rtx_cost for calculating the
10611    cost of an RTX operand given its context.  X is the rtx of the
10612    operand, MODE is its mode, and OUTER is the rtx_code of this
10613    operand's parent operator.  */
10614 
10615 static int
avr_operand_rtx_cost(rtx x,machine_mode mode,enum rtx_code outer,int opno,bool speed)10616 avr_operand_rtx_cost (rtx x, machine_mode mode, enum rtx_code outer,
10617 		      int opno, bool speed)
10618 {
10619   enum rtx_code code = GET_CODE (x);
10620   int total;
10621 
10622   switch (code)
10623     {
10624     case REG:
10625     case SUBREG:
10626       return 0;
10627 
10628     case CONST_INT:
10629     case CONST_FIXED:
10630     case CONST_DOUBLE:
10631       return COSTS_N_INSNS (GET_MODE_SIZE (mode));
10632 
10633     default:
10634       break;
10635     }
10636 
10637   total = 0;
10638   avr_rtx_costs (x, mode, outer, opno, &total, speed);
10639   return total;
10640 }
10641 
10642 /* Worker function for AVR backend's rtx_cost function.
10643    X is rtx expression whose cost is to be calculated.
10644    Return true if the complete cost has been computed.
10645    Return false if subexpressions should be scanned.
10646    In either case, *TOTAL contains the cost result.  */
10647 
10648 static bool
avr_rtx_costs_1(rtx x,machine_mode mode,int outer_code,int opno ATTRIBUTE_UNUSED,int * total,bool speed)10649 avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
10650                  int opno ATTRIBUTE_UNUSED, int *total, bool speed)
10651 {
10652   enum rtx_code code = GET_CODE (x);
10653   HOST_WIDE_INT val;
10654 
10655   switch (code)
10656     {
10657     case CONST_INT:
10658     case CONST_FIXED:
10659     case CONST_DOUBLE:
10660     case SYMBOL_REF:
10661     case CONST:
10662     case LABEL_REF:
10663       /* Immediate constants are as cheap as registers.  */
10664       *total = 0;
10665       return true;
10666 
10667     case MEM:
10668       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10669       return true;
10670 
10671     case NEG:
10672       switch (mode)
10673 	{
10674 	case E_QImode:
10675 	case E_SFmode:
10676 	  *total = COSTS_N_INSNS (1);
10677 	  break;
10678 
10679         case E_HImode:
10680         case E_PSImode:
10681         case E_SImode:
10682           *total = COSTS_N_INSNS (2 * GET_MODE_SIZE (mode) - 1);
10683           break;
10684 
10685 	default:
10686 	  return false;
10687 	}
10688       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10689       return true;
10690 
10691     case ABS:
10692       switch (mode)
10693 	{
10694 	case E_QImode:
10695 	case E_SFmode:
10696 	  *total = COSTS_N_INSNS (1);
10697 	  break;
10698 
10699 	default:
10700 	  return false;
10701 	}
10702       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10703       return true;
10704 
10705     case NOT:
10706       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10707       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10708       return true;
10709 
10710     case ZERO_EXTEND:
10711       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
10712 			      - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
10713       *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
10714 				      code, 0, speed);
10715       return true;
10716 
10717     case SIGN_EXTEND:
10718       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
10719 			      - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
10720       *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
10721 				      code, 0, speed);
10722       return true;
10723 
10724     case PLUS:
10725       switch (mode)
10726 	{
10727 	case E_QImode:
10728           if (AVR_HAVE_MUL
10729               && MULT == GET_CODE (XEXP (x, 0))
10730               && register_operand (XEXP (x, 1), QImode))
10731             {
10732               /* multiply-add */
10733               *total = COSTS_N_INSNS (speed ? 4 : 3);
10734               /* multiply-add with constant: will be split and load constant. */
10735               if (CONST_INT_P (XEXP (XEXP (x, 0), 1)))
10736                 *total = COSTS_N_INSNS (1) + *total;
10737               return true;
10738             }
10739 	  *total = COSTS_N_INSNS (1);
10740 	  if (!CONST_INT_P (XEXP (x, 1)))
10741 	    *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10742 	  break;
10743 
10744 	case E_HImode:
10745           if (AVR_HAVE_MUL
10746               && (MULT == GET_CODE (XEXP (x, 0))
10747                   || ASHIFT == GET_CODE (XEXP (x, 0)))
10748               && register_operand (XEXP (x, 1), HImode)
10749               && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))
10750                   || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))))
10751             {
10752               /* multiply-add */
10753               *total = COSTS_N_INSNS (speed ? 5 : 4);
10754               /* multiply-add with constant: will be split and load constant. */
10755               if (CONST_INT_P (XEXP (XEXP (x, 0), 1)))
10756                 *total = COSTS_N_INSNS (1) + *total;
10757               return true;
10758             }
10759 	  if (!CONST_INT_P (XEXP (x, 1)))
10760 	    {
10761 	      *total = COSTS_N_INSNS (2);
10762 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10763 					      speed);
10764 	    }
10765 	  else if (IN_RANGE (INTVAL (XEXP (x, 1)), -63, 63))
10766 	    *total = COSTS_N_INSNS (1);
10767 	  else
10768 	    *total = COSTS_N_INSNS (2);
10769 	  break;
10770 
10771         case E_PSImode:
10772           if (!CONST_INT_P (XEXP (x, 1)))
10773             {
10774               *total = COSTS_N_INSNS (3);
10775               *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10776                                               speed);
10777             }
10778           else if (IN_RANGE (INTVAL (XEXP (x, 1)), -63, 63))
10779             *total = COSTS_N_INSNS (2);
10780           else
10781             *total = COSTS_N_INSNS (3);
10782           break;
10783 
10784 	case E_SImode:
10785 	  if (!CONST_INT_P (XEXP (x, 1)))
10786 	    {
10787 	      *total = COSTS_N_INSNS (4);
10788 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10789 					      speed);
10790 	    }
10791 	  else if (IN_RANGE (INTVAL (XEXP (x, 1)), -63, 63))
10792 	    *total = COSTS_N_INSNS (1);
10793 	  else
10794 	    *total = COSTS_N_INSNS (4);
10795 	  break;
10796 
10797 	default:
10798 	  return false;
10799 	}
10800       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10801       return true;
10802 
10803     case MINUS:
10804       if (AVR_HAVE_MUL
10805           && QImode == mode
10806           && register_operand (XEXP (x, 0), QImode)
10807           && MULT == GET_CODE (XEXP (x, 1)))
10808         {
10809           /* multiply-sub */
10810           *total = COSTS_N_INSNS (speed ? 4 : 3);
10811           /* multiply-sub with constant: will be split and load constant. */
10812           if (CONST_INT_P (XEXP (XEXP (x, 1), 1)))
10813             *total = COSTS_N_INSNS (1) + *total;
10814           return true;
10815         }
10816       if (AVR_HAVE_MUL
10817           && HImode == mode
10818           && register_operand (XEXP (x, 0), HImode)
10819           && (MULT == GET_CODE (XEXP (x, 1))
10820               || ASHIFT == GET_CODE (XEXP (x, 1)))
10821           && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))
10822               || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))))
10823         {
10824           /* multiply-sub */
10825           *total = COSTS_N_INSNS (speed ? 5 : 4);
10826           /* multiply-sub with constant: will be split and load constant. */
10827           if (CONST_INT_P (XEXP (XEXP (x, 1), 1)))
10828             *total = COSTS_N_INSNS (1) + *total;
10829           return true;
10830         }
10831       /* FALLTHRU */
10832     case AND:
10833     case IOR:
10834       if (IOR == code
10835           && HImode == mode
10836           && ASHIFT == GET_CODE (XEXP (x, 0)))
10837         {
10838           *total = COSTS_N_INSNS (2);
10839           // Just a rough estimate.  If we see no sign- or zero-extend,
10840           // then increase the cost a little bit.
10841           if (REG_P (XEXP (XEXP (x, 0), 0)))
10842             *total += COSTS_N_INSNS (1);
10843           if (REG_P (XEXP (x, 1)))
10844             *total += COSTS_N_INSNS (1);
10845           return true;
10846         }
10847       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10848       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10849       if (!CONST_INT_P (XEXP (x, 1)))
10850 	*total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10851       return true;
10852 
10853     case XOR:
10854       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10855       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10856       *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10857       return true;
10858 
10859     case MULT:
10860       switch (mode)
10861 	{
10862 	case E_QImode:
10863 	  if (AVR_HAVE_MUL)
10864 	    *total = COSTS_N_INSNS (!speed ? 3 : 4);
10865 	  else if (!speed)
10866 	    *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
10867 	  else
10868 	    return false;
10869 	  break;
10870 
10871 	case E_HImode:
10872 	  if (AVR_HAVE_MUL)
10873             {
10874               rtx op0 = XEXP (x, 0);
10875               rtx op1 = XEXP (x, 1);
10876               enum rtx_code code0 = GET_CODE (op0);
10877               enum rtx_code code1 = GET_CODE (op1);
10878               bool ex0 = SIGN_EXTEND == code0 || ZERO_EXTEND == code0;
10879               bool ex1 = SIGN_EXTEND == code1 || ZERO_EXTEND == code1;
10880 
10881               if (ex0
10882                   && (u8_operand (op1, HImode)
10883                       || s8_operand (op1, HImode)))
10884                 {
10885                   *total = COSTS_N_INSNS (!speed ? 4 : 6);
10886                   return true;
10887                 }
10888               if (ex0
10889                   && register_operand (op1, HImode))
10890                 {
10891                   *total = COSTS_N_INSNS (!speed ? 5 : 8);
10892                   return true;
10893                 }
10894               else if (ex0 || ex1)
10895                 {
10896                   *total = COSTS_N_INSNS (!speed ? 3 : 5);
10897                   return true;
10898                 }
10899               else if (register_operand (op0, HImode)
10900                        && (u8_operand (op1, HImode)
10901                            || s8_operand (op1, HImode)))
10902                 {
10903                   *total = COSTS_N_INSNS (!speed ? 6 : 9);
10904                   return true;
10905                 }
10906               else
10907                 *total = COSTS_N_INSNS (!speed ? 7 : 10);
10908             }
10909 	  else if (!speed)
10910 	    *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
10911 	  else
10912 	    return false;
10913 	  break;
10914 
10915         case E_PSImode:
10916           if (!speed)
10917             *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
10918           else
10919             *total = 10;
10920           break;
10921 
10922 	case E_SImode:
10923 	case E_DImode:
10924 	  if (AVR_HAVE_MUL)
10925             {
10926               if (!speed)
10927                 {
10928                   /* Add some additional costs besides CALL like moves etc.  */
10929 
10930                   *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
10931                 }
10932               else
10933                 {
10934                   /* Just a rough estimate.  Even with -O2 we don't want bulky
10935                      code expanded inline.  */
10936 
10937                   *total = COSTS_N_INSNS (25);
10938                 }
10939             }
10940           else
10941             {
10942               if (speed)
10943                 *total = COSTS_N_INSNS (300);
10944               else
10945                 /* Add some additional costs besides CALL like moves etc.  */
10946                 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
10947             }
10948 
10949 	  if (mode == DImode)
10950 	    *total *= 2;
10951 
10952 	  return true;
10953 
10954 	default:
10955 	  return false;
10956 	}
10957       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10958       *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10959       return true;
10960 
10961     case DIV:
10962     case MOD:
10963     case UDIV:
10964     case UMOD:
10965       if (!speed)
10966         *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
10967       else
10968         *total = COSTS_N_INSNS (15 * GET_MODE_SIZE (mode));
10969       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10970       /* For div/mod with const-int divisor we have at least the cost of
10971          loading the divisor. */
10972       if (CONST_INT_P (XEXP (x, 1)))
10973         *total += COSTS_N_INSNS (GET_MODE_SIZE (mode));
10974       /* Add some overall penaly for clobbering and moving around registers */
10975       *total += COSTS_N_INSNS (2);
10976       return true;
10977 
10978     case ROTATE:
10979       switch (mode)
10980 	{
10981 	case E_QImode:
10982 	  if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 4)
10983 	    *total = COSTS_N_INSNS (1);
10984 
10985 	  break;
10986 
10987 	case E_HImode:
10988 	  if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 8)
10989 	    *total = COSTS_N_INSNS (3);
10990 
10991 	  break;
10992 
10993 	case E_SImode:
10994 	  if (CONST_INT_P (XEXP (x, 1)))
10995 	    switch (INTVAL (XEXP (x, 1)))
10996 	      {
10997 	      case 8:
10998 	      case 24:
10999 		*total = COSTS_N_INSNS (5);
11000 		break;
11001 	      case 16:
11002 		*total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 6);
11003 		break;
11004 	      }
11005 	  break;
11006 
11007 	default:
11008 	  return false;
11009 	}
11010       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11011       return true;
11012 
11013     case ASHIFT:
11014       switch (mode)
11015 	{
11016 	case E_QImode:
11017 	  if (!CONST_INT_P (XEXP (x, 1)))
11018 	    {
11019 	      *total = COSTS_N_INSNS (!speed ? 4 : 17);
11020 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11021 					      speed);
11022 	    }
11023 	  else
11024 	    {
11025 	      val = INTVAL (XEXP (x, 1));
11026 	      if (val == 7)
11027 		*total = COSTS_N_INSNS (3);
11028 	      else if (val >= 0 && val <= 7)
11029 		*total = COSTS_N_INSNS (val);
11030 	      else
11031 		*total = COSTS_N_INSNS (1);
11032 	    }
11033 	  break;
11034 
11035 	case E_HImode:
11036           if (AVR_HAVE_MUL)
11037             {
11038               if (const_2_to_7_operand (XEXP (x, 1), HImode)
11039                   && (SIGN_EXTEND == GET_CODE (XEXP (x, 0))
11040                       || ZERO_EXTEND == GET_CODE (XEXP (x, 0))))
11041                 {
11042                   *total = COSTS_N_INSNS (!speed ? 4 : 6);
11043                   return true;
11044                 }
11045             }
11046 
11047           if (const1_rtx == (XEXP (x, 1))
11048               && SIGN_EXTEND == GET_CODE (XEXP (x, 0)))
11049             {
11050               *total = COSTS_N_INSNS (2);
11051               return true;
11052             }
11053 
11054 	  if (!CONST_INT_P (XEXP (x, 1)))
11055 	    {
11056 	      *total = COSTS_N_INSNS (!speed ? 5 : 41);
11057 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11058 					      speed);
11059 	    }
11060 	  else
11061 	    switch (INTVAL (XEXP (x, 1)))
11062 	      {
11063 	      case 0:
11064 		*total = 0;
11065 		break;
11066 	      case 1:
11067 	      case 8:
11068 		*total = COSTS_N_INSNS (2);
11069 		break;
11070 	      case 9:
11071 		*total = COSTS_N_INSNS (3);
11072 		break;
11073 	      case 2:
11074 	      case 3:
11075 	      case 10:
11076 	      case 15:
11077 		*total = COSTS_N_INSNS (4);
11078 		break;
11079 	      case 7:
11080 	      case 11:
11081 	      case 12:
11082 		*total = COSTS_N_INSNS (5);
11083 		break;
11084 	      case 4:
11085 		*total = COSTS_N_INSNS (!speed ? 5 : 8);
11086 		break;
11087 	      case 6:
11088 		*total = COSTS_N_INSNS (!speed ? 5 : 9);
11089 		break;
11090 	      case 5:
11091 		*total = COSTS_N_INSNS (!speed ? 5 : 10);
11092 		break;
11093 	      default:
11094 	        *total = COSTS_N_INSNS (!speed ? 5 : 41);
11095 	        *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11096 						speed);
11097 	      }
11098 	  break;
11099 
11100         case E_PSImode:
11101           if (!CONST_INT_P (XEXP (x, 1)))
11102             {
11103               *total = COSTS_N_INSNS (!speed ? 6 : 73);
11104             }
11105           else
11106             switch (INTVAL (XEXP (x, 1)))
11107               {
11108               case 0:
11109                 *total = 0;
11110                 break;
11111               case 1:
11112               case 8:
11113               case 16:
11114                 *total = COSTS_N_INSNS (3);
11115                 break;
11116               case 23:
11117                 *total = COSTS_N_INSNS (5);
11118                 break;
11119               default:
11120                 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
11121                 break;
11122               }
11123           break;
11124 
11125 	case E_SImode:
11126 	  if (!CONST_INT_P (XEXP (x, 1)))
11127 	    {
11128 	      *total = COSTS_N_INSNS (!speed ? 7 : 113);
11129 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11130 					      speed);
11131 	    }
11132 	  else
11133 	    switch (INTVAL (XEXP (x, 1)))
11134 	      {
11135 	      case 0:
11136 		*total = 0;
11137 		break;
11138 	      case 24:
11139 		*total = COSTS_N_INSNS (3);
11140 		break;
11141 	      case 1:
11142 	      case 8:
11143 	      case 16:
11144 		*total = COSTS_N_INSNS (4);
11145 		break;
11146 	      case 31:
11147 		*total = COSTS_N_INSNS (6);
11148 		break;
11149 	      case 2:
11150 		*total = COSTS_N_INSNS (!speed ? 7 : 8);
11151 		break;
11152 	      default:
11153 		*total = COSTS_N_INSNS (!speed ? 7 : 113);
11154 		*total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11155 						speed);
11156 	      }
11157 	  break;
11158 
11159 	default:
11160 	  return false;
11161 	}
11162       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11163       return true;
11164 
11165     case ASHIFTRT:
11166       switch (mode)
11167 	{
11168 	case E_QImode:
11169 	  if (!CONST_INT_P (XEXP (x, 1)))
11170 	    {
11171 	      *total = COSTS_N_INSNS (!speed ? 4 : 17);
11172 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11173 					      speed);
11174 	    }
11175 	  else
11176 	    {
11177 	      val = INTVAL (XEXP (x, 1));
11178 	      if (val == 6)
11179 		*total = COSTS_N_INSNS (4);
11180 	      else if (val == 7)
11181 		*total = COSTS_N_INSNS (2);
11182 	      else if (val >= 0 && val <= 7)
11183 		*total = COSTS_N_INSNS (val);
11184 	      else
11185 		*total = COSTS_N_INSNS (1);
11186 	    }
11187 	  break;
11188 
11189 	case E_HImode:
11190 	  if (!CONST_INT_P (XEXP (x, 1)))
11191 	    {
11192 	      *total = COSTS_N_INSNS (!speed ? 5 : 41);
11193 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11194 					      speed);
11195 	    }
11196 	  else
11197 	    switch (INTVAL (XEXP (x, 1)))
11198 	      {
11199 	      case 0:
11200 		*total = 0;
11201 		break;
11202 	      case 1:
11203 		*total = COSTS_N_INSNS (2);
11204 		break;
11205 	      case 15:
11206 		*total = COSTS_N_INSNS (3);
11207 		break;
11208 	      case 2:
11209 	      case 7:
11210               case 8:
11211               case 9:
11212 		*total = COSTS_N_INSNS (4);
11213 		break;
11214               case 10:
11215 	      case 14:
11216 		*total = COSTS_N_INSNS (5);
11217 		break;
11218               case 11:
11219                 *total = COSTS_N_INSNS (!speed ? 5 : 6);
11220 		break;
11221               case 12:
11222                 *total = COSTS_N_INSNS (!speed ? 5 : 7);
11223 		break;
11224               case 6:
11225 	      case 13:
11226                 *total = COSTS_N_INSNS (!speed ? 5 : 8);
11227 		break;
11228 	      default:
11229 	        *total = COSTS_N_INSNS (!speed ? 5 : 41);
11230 	        *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11231 						speed);
11232 	      }
11233 	  break;
11234 
11235         case E_PSImode:
11236           if (!CONST_INT_P (XEXP (x, 1)))
11237             {
11238               *total = COSTS_N_INSNS (!speed ? 6 : 73);
11239             }
11240           else
11241             switch (INTVAL (XEXP (x, 1)))
11242               {
11243               case 0:
11244                 *total = 0;
11245                 break;
11246               case 1:
11247                 *total = COSTS_N_INSNS (3);
11248                 break;
11249               case 16:
11250               case 8:
11251                 *total = COSTS_N_INSNS (5);
11252                 break;
11253               case 23:
11254                 *total = COSTS_N_INSNS (4);
11255                 break;
11256               default:
11257                 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
11258                 break;
11259               }
11260           break;
11261 
11262 	case E_SImode:
11263 	  if (!CONST_INT_P (XEXP (x, 1)))
11264 	    {
11265 	      *total = COSTS_N_INSNS (!speed ? 7 : 113);
11266 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11267 					      speed);
11268 	    }
11269 	  else
11270 	    switch (INTVAL (XEXP (x, 1)))
11271 	      {
11272 	      case 0:
11273 		*total = 0;
11274 		break;
11275 	      case 1:
11276 		*total = COSTS_N_INSNS (4);
11277 		break;
11278 	      case 8:
11279 	      case 16:
11280 	      case 24:
11281 		*total = COSTS_N_INSNS (6);
11282 		break;
11283 	      case 2:
11284 		*total = COSTS_N_INSNS (!speed ? 7 : 8);
11285 		break;
11286 	      case 31:
11287 		*total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 5);
11288 		break;
11289 	      default:
11290 		*total = COSTS_N_INSNS (!speed ? 7 : 113);
11291 		*total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11292 						speed);
11293 	      }
11294 	  break;
11295 
11296 	default:
11297 	  return false;
11298 	}
11299       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11300       return true;
11301 
11302     case LSHIFTRT:
11303       if (outer_code == TRUNCATE)
11304         {
11305           *total = avr_mul_highpart_cost (x, speed);
11306           return true;
11307         }
11308 
11309       switch (mode)
11310 	{
11311 	case E_QImode:
11312 	  if (!CONST_INT_P (XEXP (x, 1)))
11313 	    {
11314 	      *total = COSTS_N_INSNS (!speed ? 4 : 17);
11315 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11316 					      speed);
11317 	    }
11318 	  else
11319 	    {
11320 	      val = INTVAL (XEXP (x, 1));
11321 	      if (val == 7)
11322 		*total = COSTS_N_INSNS (3);
11323 	      else if (val >= 0 && val <= 7)
11324 		*total = COSTS_N_INSNS (val);
11325 	      else
11326 		*total = COSTS_N_INSNS (1);
11327 	    }
11328 	  break;
11329 
11330 	case E_HImode:
11331 	  if (!CONST_INT_P (XEXP (x, 1)))
11332 	    {
11333 	      *total = COSTS_N_INSNS (!speed ? 5 : 41);
11334 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11335 					      speed);
11336 	    }
11337 	  else
11338 	    switch (INTVAL (XEXP (x, 1)))
11339 	      {
11340 	      case 0:
11341 		*total = 0;
11342 		break;
11343 	      case 1:
11344 	      case 8:
11345 		*total = COSTS_N_INSNS (2);
11346 		break;
11347 	      case 9:
11348 		*total = COSTS_N_INSNS (3);
11349 		break;
11350 	      case 2:
11351 	      case 10:
11352 	      case 15:
11353 		*total = COSTS_N_INSNS (4);
11354 		break;
11355 	      case 7:
11356               case 11:
11357 		*total = COSTS_N_INSNS (5);
11358 		break;
11359 	      case 3:
11360 	      case 12:
11361 	      case 13:
11362 	      case 14:
11363 		*total = COSTS_N_INSNS (!speed ? 5 : 6);
11364 		break;
11365 	      case 4:
11366 		*total = COSTS_N_INSNS (!speed ? 5 : 7);
11367 		break;
11368 	      case 5:
11369 	      case 6:
11370 		*total = COSTS_N_INSNS (!speed ? 5 : 9);
11371 		break;
11372 	      default:
11373 	        *total = COSTS_N_INSNS (!speed ? 5 : 41);
11374 	        *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11375 						speed);
11376 	      }
11377 	  break;
11378 
11379         case E_PSImode:
11380           if (!CONST_INT_P (XEXP (x, 1)))
11381             {
11382               *total = COSTS_N_INSNS (!speed ? 6 : 73);
11383             }
11384           else
11385             switch (INTVAL (XEXP (x, 1)))
11386               {
11387               case 0:
11388                 *total = 0;
11389                 break;
11390               case 1:
11391               case 8:
11392               case 16:
11393                 *total = COSTS_N_INSNS (3);
11394                 break;
11395               case 23:
11396                 *total = COSTS_N_INSNS (5);
11397                 break;
11398               default:
11399                 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
11400                 break;
11401               }
11402           break;
11403 
11404 	case E_SImode:
11405 	  if (!CONST_INT_P (XEXP (x, 1)))
11406 	    {
11407 	      *total = COSTS_N_INSNS (!speed ? 7 : 113);
11408 	      *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11409 					      speed);
11410 	    }
11411 	  else
11412 	    switch (INTVAL (XEXP (x, 1)))
11413 	      {
11414 	      case 0:
11415 		*total = 0;
11416 		break;
11417 	      case 1:
11418 		*total = COSTS_N_INSNS (4);
11419 		break;
11420 	      case 2:
11421 		*total = COSTS_N_INSNS (!speed ? 7 : 8);
11422 		break;
11423 	      case 8:
11424 	      case 16:
11425 	      case 24:
11426 		*total = COSTS_N_INSNS (4);
11427 		break;
11428 	      case 31:
11429 		*total = COSTS_N_INSNS (6);
11430 		break;
11431 	      default:
11432 		*total = COSTS_N_INSNS (!speed ? 7 : 113);
11433 		*total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11434 						speed);
11435 	      }
11436 	  break;
11437 
11438 	default:
11439 	  return false;
11440 	}
11441       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11442       return true;
11443 
11444     case COMPARE:
11445       switch (GET_MODE (XEXP (x, 0)))
11446 	{
11447 	case E_QImode:
11448 	  *total = COSTS_N_INSNS (1);
11449 	  if (!CONST_INT_P (XEXP (x, 1)))
11450 	    *total += avr_operand_rtx_cost (XEXP (x, 1), QImode, code,
11451 					    1, speed);
11452 	  break;
11453 
11454         case E_HImode:
11455 	  *total = COSTS_N_INSNS (2);
11456 	  if (!CONST_INT_P (XEXP (x, 1)))
11457             *total += avr_operand_rtx_cost (XEXP (x, 1), HImode, code,
11458 					    1, speed);
11459 	  else if (INTVAL (XEXP (x, 1)) != 0)
11460 	    *total += COSTS_N_INSNS (1);
11461           break;
11462 
11463         case E_PSImode:
11464           *total = COSTS_N_INSNS (3);
11465           if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) != 0)
11466             *total += COSTS_N_INSNS (2);
11467           break;
11468 
11469         case E_SImode:
11470           *total = COSTS_N_INSNS (4);
11471           if (!CONST_INT_P (XEXP (x, 1)))
11472             *total += avr_operand_rtx_cost (XEXP (x, 1), SImode, code,
11473 					    1, speed);
11474 	  else if (INTVAL (XEXP (x, 1)) != 0)
11475 	    *total += COSTS_N_INSNS (3);
11476           break;
11477 
11478 	default:
11479 	  return false;
11480 	}
11481       *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
11482 				      code, 0, speed);
11483       return true;
11484 
11485     case TRUNCATE:
11486       if (LSHIFTRT == GET_CODE (XEXP (x, 0)))
11487         {
11488           *total = avr_mul_highpart_cost (XEXP (x, 0), speed);
11489           return true;
11490         }
11491       break;
11492 
11493     default:
11494       break;
11495     }
11496   return false;
11497 }
11498 
11499 
11500 /* Implement `TARGET_RTX_COSTS'.  */
11501 
11502 static bool
avr_rtx_costs(rtx x,machine_mode mode,int outer_code,int opno,int * total,bool speed)11503 avr_rtx_costs (rtx x, machine_mode mode, int outer_code,
11504 	       int opno, int *total, bool speed)
11505 {
11506   bool done = avr_rtx_costs_1 (x, mode, outer_code, opno, total, speed);
11507 
11508   if (avr_log.rtx_costs)
11509     {
11510       avr_edump ("\n%?=%b (%s) total=%d, outer=%C:\n%r\n",
11511                  done, speed ? "speed" : "size", *total, outer_code, x);
11512     }
11513 
11514   return done;
11515 }
11516 
11517 
11518 /* Implement `TARGET_ADDRESS_COST'.  */
11519 
11520 static int
avr_address_cost(rtx x,machine_mode mode ATTRIBUTE_UNUSED,addr_space_t as ATTRIBUTE_UNUSED,bool speed ATTRIBUTE_UNUSED)11521 avr_address_cost (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
11522                   addr_space_t as ATTRIBUTE_UNUSED,
11523                   bool speed ATTRIBUTE_UNUSED)
11524 {
11525   int cost = 4;
11526 
11527   if (GET_CODE (x) == PLUS
11528       && CONST_INT_P (XEXP (x, 1))
11529       && (REG_P (XEXP (x, 0))
11530           || SUBREG_P (XEXP (x, 0))))
11531     {
11532       if (INTVAL (XEXP (x, 1)) > MAX_LD_OFFSET(mode))
11533         cost = 18;
11534     }
11535   else if (CONSTANT_ADDRESS_P (x))
11536     {
11537       if (io_address_operand (x, QImode))
11538         cost = 2;
11539 
11540       if (AVR_TINY
11541           && avr_address_tiny_absdata_p (x, QImode))
11542         cost = 2;
11543     }
11544 
11545   if (avr_log.address_cost)
11546     avr_edump ("\n%?: %d = %r\n", cost, x);
11547 
11548   return cost;
11549 }
11550 
11551 /* Test for extra memory constraint 'Q'.
11552    It's a memory address based on Y or Z pointer with valid displacement.  */
11553 
11554 int
extra_constraint_Q(rtx x)11555 extra_constraint_Q (rtx x)
11556 {
11557   int ok = 0;
11558   rtx plus = XEXP (x, 0);
11559 
11560   if (GET_CODE (plus) == PLUS
11561       && REG_P (XEXP (plus, 0))
11562       && CONST_INT_P (XEXP (plus, 1))
11563       && (INTVAL (XEXP (plus, 1))
11564 	  <= MAX_LD_OFFSET (GET_MODE (x))))
11565     {
11566       rtx xx = XEXP (plus, 0);
11567       int regno = REGNO (xx);
11568 
11569       ok = (/* allocate pseudos */
11570             regno >= FIRST_PSEUDO_REGISTER
11571             /* strictly check */
11572             || regno == REG_Z || regno == REG_Y
11573             /* XXX frame & arg pointer checks */
11574             || xx == frame_pointer_rtx
11575             || xx == arg_pointer_rtx);
11576 
11577       if (avr_log.constraints)
11578         avr_edump ("\n%?=%d reload_completed=%d reload_in_progress=%d\n %r\n",
11579                    ok, reload_completed, reload_in_progress, x);
11580     }
11581 
11582   return ok;
11583 }
11584 
11585 /* Convert condition code CONDITION to the valid AVR condition code.  */
11586 
11587 RTX_CODE
avr_normalize_condition(RTX_CODE condition)11588 avr_normalize_condition (RTX_CODE condition)
11589 {
11590   switch (condition)
11591     {
11592     case GT:
11593       return GE;
11594     case GTU:
11595       return GEU;
11596     case LE:
11597       return LT;
11598     case LEU:
11599       return LTU;
11600     default:
11601       gcc_unreachable ();
11602     }
11603 }
11604 
11605 /* Helper function for `avr_reorg'.  */
11606 
11607 static rtx
avr_compare_pattern(rtx_insn * insn)11608 avr_compare_pattern (rtx_insn *insn)
11609 {
11610   rtx pattern = single_set (insn);
11611 
11612   if (pattern
11613       && NONJUMP_INSN_P (insn)
11614       && REG_P (SET_DEST (pattern))
11615       && REGNO (SET_DEST (pattern)) == REG_CC
11616       && GET_CODE (SET_SRC (pattern)) == COMPARE)
11617     {
11618       machine_mode mode0 = GET_MODE (XEXP (SET_SRC (pattern), 0));
11619       machine_mode mode1 = GET_MODE (XEXP (SET_SRC (pattern), 1));
11620 
11621       /* The 64-bit comparisons have fixed operands ACC_A and ACC_B.
11622          They must not be swapped, thus skip them.  */
11623 
11624       if ((mode0 == VOIDmode || GET_MODE_SIZE (mode0) <= 4)
11625           && (mode1 == VOIDmode || GET_MODE_SIZE (mode1) <= 4))
11626         return pattern;
11627     }
11628 
11629   return NULL_RTX;
11630 }
11631 
11632 /* Helper function for `avr_reorg'.  */
11633 
11634 /* Expansion of switch/case decision trees leads to code like
11635 
11636        REG_CC = compare (Reg, Num)
11637        if (REG_CC == 0)
11638          goto L1
11639 
11640        REG_CC = compare (Reg, Num)
11641        if (REG_CC > 0)
11642          goto L2
11643 
11644    The second comparison is superfluous and can be deleted.
11645    The second jump condition can be transformed from a
11646    "difficult" one to a "simple" one because "REG_CC > 0" and
11647    "REG_CC >= 0" will have the same effect here.
11648 
11649    This function relies on the way switch/case is being expaned
11650    as binary decision tree.  For example code see PR 49903.
11651 
11652    Return TRUE if optimization performed.
11653    Return FALSE if nothing changed.
11654 
11655    INSN1 is a comparison, i.e. avr_compare_pattern != 0.
11656 
11657    We don't want to do this in text peephole because it is
11658    tedious to work out jump offsets there and the second comparison
11659    might have been transormed by `avr_reorg'.
11660 
11661    RTL peephole won't do because peephole2 does not scan across
11662    basic blocks.  */
11663 
11664 static bool
avr_reorg_remove_redundant_compare(rtx_insn * insn1)11665 avr_reorg_remove_redundant_compare (rtx_insn *insn1)
11666 {
11667   rtx comp1, ifelse1, xcond1;
11668   rtx_insn *branch1;
11669   rtx comp2, ifelse2, xcond2;
11670   rtx_insn *branch2, *insn2;
11671   enum rtx_code code;
11672   rtx_insn *jump;
11673   rtx target, cond;
11674 
11675   /* Look out for:  compare1 - branch1 - compare2 - branch2  */
11676 
11677   branch1 = next_nonnote_nondebug_insn (insn1);
11678   if (!branch1 || !JUMP_P (branch1))
11679     return false;
11680 
11681   insn2 = next_nonnote_nondebug_insn (branch1);
11682   if (!insn2 || !avr_compare_pattern (insn2))
11683     return false;
11684 
11685   branch2 = next_nonnote_nondebug_insn (insn2);
11686   if (!branch2 || !JUMP_P (branch2))
11687     return false;
11688 
11689   comp1 = avr_compare_pattern (insn1);
11690   comp2 = avr_compare_pattern (insn2);
11691   xcond1 = single_set (branch1);
11692   xcond2 = single_set (branch2);
11693 
11694   if (!comp1 || !comp2
11695       || !rtx_equal_p (comp1, comp2)
11696       || !xcond1 || SET_DEST (xcond1) != pc_rtx
11697       || !xcond2 || SET_DEST (xcond2) != pc_rtx
11698       || IF_THEN_ELSE != GET_CODE (SET_SRC (xcond1))
11699       || IF_THEN_ELSE != GET_CODE (SET_SRC (xcond2)))
11700     {
11701       return false;
11702     }
11703 
11704   comp1 = SET_SRC (comp1);
11705   ifelse1 = SET_SRC (xcond1);
11706   ifelse2 = SET_SRC (xcond2);
11707 
11708   /* comp<n> is COMPARE now and ifelse<n> is IF_THEN_ELSE.  */
11709 
11710   if (EQ != GET_CODE (XEXP (ifelse1, 0))
11711       || !REG_P (XEXP (comp1, 0))
11712       || !CONST_INT_P (XEXP (comp1, 1))
11713       || XEXP (ifelse1, 2) != pc_rtx
11714       || XEXP (ifelse2, 2) != pc_rtx
11715       || LABEL_REF != GET_CODE (XEXP (ifelse1, 1))
11716       || LABEL_REF != GET_CODE (XEXP (ifelse2, 1))
11717       || !COMPARISON_P (XEXP (ifelse2, 0))
11718       || REG_CC != REGNO (XEXP (XEXP (ifelse1, 0), 0))
11719       || REG_CC != REGNO (XEXP (XEXP (ifelse2, 0), 0))
11720       || const0_rtx != XEXP (XEXP (ifelse1, 0), 1)
11721       || const0_rtx != XEXP (XEXP (ifelse2, 0), 1))
11722     {
11723       return false;
11724     }
11725 
11726   /* We filtered the insn sequence to look like
11727 
11728         (set (reg:CC cc)
11729              (compare (reg:M N)
11730                       (const_int VAL)))
11731         (set (pc)
11732              (if_then_else (eq (reg:CC cc)
11733                                (const_int 0))
11734                            (label_ref L1)
11735                            (pc)))
11736 
11737         (set (reg:CC cc)
11738              (compare (reg:M N)
11739                       (const_int VAL)))
11740         (set (pc)
11741              (if_then_else (CODE (reg:CC cc)
11742                                  (const_int 0))
11743                            (label_ref L2)
11744                            (pc)))
11745   */
11746 
11747   code = GET_CODE (XEXP (ifelse2, 0));
11748 
11749   /* Map GT/GTU to GE/GEU which is easier for AVR.
11750      The first two instructions compare/branch on EQ
11751      so we may replace the difficult
11752 
11753         if (x == VAL)   goto L1;
11754         if (x > VAL)    goto L2;
11755 
11756      with easy
11757 
11758          if (x == VAL)   goto L1;
11759          if (x >= VAL)   goto L2;
11760 
11761      Similarly, replace LE/LEU by LT/LTU.  */
11762 
11763   switch (code)
11764     {
11765     case EQ:
11766     case LT:  case LTU:
11767     case GE:  case GEU:
11768       break;
11769 
11770     case LE:  case LEU:
11771     case GT:  case GTU:
11772       code = avr_normalize_condition (code);
11773       break;
11774 
11775     default:
11776       return false;
11777     }
11778 
11779   /* Wrap the branches into UNSPECs so they won't be changed or
11780      optimized in the remainder.  */
11781 
11782   target = XEXP (XEXP (ifelse1, 1), 0);
11783   cond = XEXP (ifelse1, 0);
11784   jump = emit_jump_insn_after (gen_branch_unspec (target, cond), insn1);
11785 
11786   JUMP_LABEL (jump) = JUMP_LABEL (branch1);
11787 
11788   target = XEXP (XEXP (ifelse2, 1), 0);
11789   cond = gen_rtx_fmt_ee (code, VOIDmode, cc_reg_rtx, const0_rtx);
11790   jump = emit_jump_insn_after (gen_branch_unspec (target, cond), insn2);
11791 
11792   JUMP_LABEL (jump) = JUMP_LABEL (branch2);
11793 
11794   /* The comparisons in insn1 and insn2 are exactly the same;
11795      insn2 is superfluous so delete it.  */
11796 
11797   delete_insn (insn2);
11798   delete_insn (branch1);
11799   delete_insn (branch2);
11800 
11801   return true;
11802 }
11803 
11804 
11805 /* Implement `TARGET_MACHINE_DEPENDENT_REORG'.  */
11806 /* Optimize conditional jumps.  */
11807 
11808 static void
avr_reorg(void)11809 avr_reorg (void)
11810 {
11811   rtx_insn *insn = get_insns();
11812 
11813   for (insn = next_real_insn (insn); insn; insn = next_real_insn (insn))
11814     {
11815       rtx pattern = avr_compare_pattern (insn);
11816 
11817       if (!pattern)
11818         continue;
11819 
11820       if (optimize
11821           && avr_reorg_remove_redundant_compare (insn))
11822         {
11823           continue;
11824         }
11825 
11826       if (compare_diff_p (insn))
11827 	{
11828           /* Now we work under compare insn with difficult branch.  */
11829 
11830 	  rtx_insn *next = next_real_insn (insn);
11831           rtx pat = PATTERN (next);
11832           if (GET_CODE (pat) == PARALLEL)
11833             pat = XVECEXP (pat, 0, 0);
11834 
11835           pattern = SET_SRC (pattern);
11836 
11837           if (true_regnum (XEXP (pattern, 0)) >= 0
11838               && true_regnum (XEXP (pattern, 1)) >= 0)
11839             {
11840               rtx x = XEXP (pattern, 0);
11841               rtx src = SET_SRC (pat);
11842               rtx t = XEXP (src, 0);
11843               PUT_CODE (t, swap_condition (GET_CODE (t)));
11844               XEXP (pattern, 0) = XEXP (pattern, 1);
11845               XEXP (pattern, 1) = x;
11846               INSN_CODE (next) = -1;
11847             }
11848           else if (true_regnum (XEXP (pattern, 0)) >= 0
11849                    && XEXP (pattern, 1) == const0_rtx)
11850             {
11851               /* This is a tst insn, we can reverse it.  */
11852               rtx src = SET_SRC (pat);
11853               rtx t = XEXP (src, 0);
11854 
11855               PUT_CODE (t, swap_condition (GET_CODE (t)));
11856               XEXP (pattern, 1) = XEXP (pattern, 0);
11857               XEXP (pattern, 0) = const0_rtx;
11858               INSN_CODE (next) = -1;
11859               INSN_CODE (insn) = -1;
11860             }
11861           else if (true_regnum (XEXP (pattern, 0)) >= 0
11862                    && CONST_INT_P (XEXP (pattern, 1)))
11863             {
11864               rtx x = XEXP (pattern, 1);
11865               rtx src = SET_SRC (pat);
11866               rtx t = XEXP (src, 0);
11867               machine_mode mode = GET_MODE (XEXP (pattern, 0));
11868 
11869               if (avr_simplify_comparison_p (mode, GET_CODE (t), x))
11870                 {
11871                   XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
11872                   PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
11873                   INSN_CODE (next) = -1;
11874                   INSN_CODE (insn) = -1;
11875                 }
11876             }
11877         }
11878     }
11879 }
11880 
11881 /* Returns register number for function return value.*/
11882 
11883 static inline unsigned int
avr_ret_register(void)11884 avr_ret_register (void)
11885 {
11886   return 24;
11887 }
11888 
11889 
11890 /* Implement `TARGET_FUNCTION_VALUE_REGNO_P'.  */
11891 
11892 static bool
avr_function_value_regno_p(const unsigned int regno)11893 avr_function_value_regno_p (const unsigned int regno)
11894 {
11895   return (regno == avr_ret_register ());
11896 }
11897 
11898 
11899 /* Implement `TARGET_LIBCALL_VALUE'.  */
11900 /* Create an RTX representing the place where a
11901    library function returns a value of mode MODE.  */
11902 
11903 static rtx
avr_libcall_value(machine_mode mode,const_rtx func ATTRIBUTE_UNUSED)11904 avr_libcall_value (machine_mode mode,
11905 		   const_rtx func ATTRIBUTE_UNUSED)
11906 {
11907   int offs = GET_MODE_SIZE (mode);
11908 
11909   if (offs <= 4)
11910     offs = (offs + 1) & ~1;
11911 
11912   return gen_rtx_REG (mode, avr_ret_register () + 2 - offs);
11913 }
11914 
11915 
11916 /* Implement `TARGET_FUNCTION_VALUE'.  */
11917 /* Create an RTX representing the place where a
11918    function returns a value of data type VALTYPE.  */
11919 
11920 static rtx
avr_function_value(const_tree type,const_tree fn_decl_or_type ATTRIBUTE_UNUSED,bool outgoing ATTRIBUTE_UNUSED)11921 avr_function_value (const_tree type,
11922                     const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
11923                     bool outgoing ATTRIBUTE_UNUSED)
11924 {
11925   unsigned int offs;
11926 
11927   if (TYPE_MODE (type) != BLKmode)
11928     return avr_libcall_value (TYPE_MODE (type), NULL_RTX);
11929 
11930   offs = int_size_in_bytes (type);
11931   if (offs < 2)
11932     offs = 2;
11933   if (offs > 2 && offs < GET_MODE_SIZE (SImode))
11934     offs = GET_MODE_SIZE (SImode);
11935   else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
11936     offs = GET_MODE_SIZE (DImode);
11937 
11938   return gen_rtx_REG (BLKmode, avr_ret_register () + 2 - offs);
11939 }
11940 
11941 int
test_hard_reg_class(enum reg_class rclass,rtx x)11942 test_hard_reg_class (enum reg_class rclass, rtx x)
11943 {
11944   int regno = true_regnum (x);
11945   if (regno < 0)
11946     return 0;
11947 
11948   if (TEST_HARD_REG_CLASS (rclass, regno))
11949     return 1;
11950 
11951   return 0;
11952 }
11953 
11954 
11955 /* Helper for jump_over_one_insn_p:  Test if INSN is a 2-word instruction
11956    and thus is suitable to be skipped by CPSE, SBRC, etc.  */
11957 
11958 static bool
avr_2word_insn_p(rtx_insn * insn)11959 avr_2word_insn_p (rtx_insn *insn)
11960 {
11961   if (TARGET_SKIP_BUG || !insn || get_attr_length (insn) != 2)
11962     {
11963       return false;
11964     }
11965 
11966   switch (INSN_CODE (insn))
11967     {
11968     default:
11969       return false;
11970 
11971     case CODE_FOR_movqi_insn:
11972     case CODE_FOR_movuqq_insn:
11973     case CODE_FOR_movqq_insn:
11974       {
11975         rtx set  = single_set (insn);
11976         rtx src  = SET_SRC (set);
11977         rtx dest = SET_DEST (set);
11978 
11979         /* Factor out LDS and STS from movqi_insn.  */
11980 
11981         if (MEM_P (dest)
11982             && (REG_P (src) || src == CONST0_RTX (GET_MODE (dest))))
11983           {
11984             return CONSTANT_ADDRESS_P (XEXP (dest, 0));
11985           }
11986         else if (REG_P (dest)
11987                  && MEM_P (src))
11988           {
11989             return CONSTANT_ADDRESS_P (XEXP (src, 0));
11990           }
11991 
11992         return false;
11993       }
11994 
11995     case CODE_FOR_call_insn:
11996     case CODE_FOR_call_value_insn:
11997       return true;
11998     }
11999 }
12000 
12001 
12002 int
jump_over_one_insn_p(rtx_insn * insn,rtx dest)12003 jump_over_one_insn_p (rtx_insn *insn, rtx dest)
12004 {
12005   int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
12006 		      ? XEXP (dest, 0)
12007 		      : dest);
12008   int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
12009   int dest_addr = INSN_ADDRESSES (uid);
12010   int jump_offset = dest_addr - jump_addr - get_attr_length (insn);
12011 
12012   return (jump_offset == 1
12013           || (jump_offset == 2
12014               && avr_2word_insn_p (next_active_insn (insn))));
12015 }
12016 
12017 /* Implement TARGET_HARD_REGNO_NREGS. CCmode is four units for historical
12018    reasons. If this hook is not defined, TARGET_HARD_REGNO_NREGS
12019    reports that CCmode requires four registers.
12020    Define this hook to allow CCmode to fit in a single REG_CC. For
12021    other modes and regs, return the number of words in mode (i.e whatever
12022    the default implementation of the hook returned). */
12023 
12024 static unsigned int
avr_hard_regno_nregs(unsigned int regno,machine_mode mode)12025 avr_hard_regno_nregs (unsigned int regno, machine_mode mode)
12026 {
12027   if (regno == REG_CC && mode == CCmode)
12028     return 1;
12029 
12030   return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
12031 }
12032 
12033 
12034 /* Implement TARGET_HARD_REGNO_MODE_OK.  On the enhanced core, anything
12035    larger than 1 byte must start in even numbered register for "movw" to
12036    work (this way we don't have to check for odd registers everywhere).  */
12037 
12038 static bool
avr_hard_regno_mode_ok(unsigned int regno,machine_mode mode)12039 avr_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
12040 {
12041   if (regno == REG_CC)
12042     return mode == CCmode;
12043 
12044   /* NOTE: 8-bit values must not be disallowed for R28 or R29.
12045         Disallowing QI et al. in these regs might lead to code like
12046             (set (subreg:QI (reg:HI 28) n) ...)
12047         which will result in wrong code because reload does not
12048         handle SUBREGs of hard regsisters like this.
12049         This could be fixed in reload.  However, it appears
12050         that fixing reload is not wanted by reload people.  */
12051 
12052   /* Any GENERAL_REGS register can hold 8-bit values.  */
12053 
12054   if (GET_MODE_SIZE (mode) == 1)
12055     return true;
12056 
12057   /* FIXME: Ideally, the following test is not needed.
12058         However, it turned out that it can reduce the number
12059         of spill fails.  AVR and it's poor endowment with
12060         address registers is extreme stress test for reload.  */
12061 
12062   if (GET_MODE_SIZE (mode) >= 4
12063       && regno >= REG_X)
12064     return false;
12065 
12066   /* All modes larger than 8 bits should start in an even register.  */
12067 
12068   return !(regno & 1);
12069 }
12070 
12071 
12072 /* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED.  */
12073 
12074 static bool
avr_hard_regno_call_part_clobbered(unsigned,unsigned regno,machine_mode mode)12075 avr_hard_regno_call_part_clobbered (unsigned, unsigned regno,
12076 				    machine_mode mode)
12077 {
12078   /* FIXME: This hook gets called with MODE:REGNO combinations that don't
12079         represent valid hard registers like, e.g. HI:29.  Returning TRUE
12080         for such registers can lead to performance degradation as mentioned
12081         in PR53595.  Thus, report invalid hard registers as FALSE.  */
12082 
12083   if (!avr_hard_regno_mode_ok (regno, mode))
12084     return 0;
12085 
12086   /* Return true if any of the following boundaries is crossed:
12087      17/18 or 19/20 (if AVR_TINY), 27/28 and 29/30.  */
12088 
12089   return ((regno <= LAST_CALLEE_SAVED_REG
12090            && regno + GET_MODE_SIZE (mode) > 1 + LAST_CALLEE_SAVED_REG)
12091           || (regno < REG_Y && regno + GET_MODE_SIZE (mode) > REG_Y)
12092           || (regno < REG_Z && regno + GET_MODE_SIZE (mode) > REG_Z));
12093 }
12094 
12095 
12096 /* Implement `MODE_CODE_BASE_REG_CLASS'.  */
12097 
12098 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)12099 avr_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED,
12100                               addr_space_t as, RTX_CODE outer_code,
12101                               RTX_CODE index_code ATTRIBUTE_UNUSED)
12102 {
12103   if (!ADDR_SPACE_GENERIC_P (as))
12104     {
12105       return POINTER_Z_REGS;
12106     }
12107 
12108   if (!avr_strict_X)
12109     return reload_completed ? BASE_POINTER_REGS : POINTER_REGS;
12110 
12111   return PLUS == outer_code ? BASE_POINTER_REGS : POINTER_REGS;
12112 }
12113 
12114 
12115 /* Implement `REGNO_MODE_CODE_OK_FOR_BASE_P'.  */
12116 
12117 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)12118 avr_regno_mode_code_ok_for_base_p (int regno,
12119                                    machine_mode mode ATTRIBUTE_UNUSED,
12120                                    addr_space_t as ATTRIBUTE_UNUSED,
12121                                    RTX_CODE outer_code,
12122                                    RTX_CODE index_code ATTRIBUTE_UNUSED)
12123 {
12124   bool ok = false;
12125 
12126   if (!ADDR_SPACE_GENERIC_P (as))
12127     {
12128       if (regno < FIRST_PSEUDO_REGISTER
12129           && regno == REG_Z)
12130         {
12131           return true;
12132         }
12133 
12134       if (reg_renumber)
12135         {
12136           regno = reg_renumber[regno];
12137 
12138           if (regno == REG_Z)
12139             {
12140               return true;
12141             }
12142         }
12143 
12144       return false;
12145     }
12146 
12147   if (regno < FIRST_PSEUDO_REGISTER
12148       && (regno == REG_X
12149           || regno == REG_Y
12150           || regno == REG_Z
12151           || regno == ARG_POINTER_REGNUM))
12152     {
12153       ok = true;
12154     }
12155   else if (reg_renumber)
12156     {
12157       regno = reg_renumber[regno];
12158 
12159       if (regno == REG_X
12160           || regno == REG_Y
12161           || regno == REG_Z
12162           || regno == ARG_POINTER_REGNUM)
12163         {
12164           ok = true;
12165         }
12166     }
12167 
12168   if (avr_strict_X
12169       && PLUS == outer_code
12170       && regno == REG_X)
12171     {
12172       ok = false;
12173     }
12174 
12175   return ok;
12176 }
12177 
12178 
12179 /* A helper for `output_reload_insisf' and `output_reload_inhi'.  */
12180 /* Set 32-bit register OP[0] to compile-time constant OP[1].
12181    CLOBBER_REG is a QI clobber register or NULL_RTX.
12182    LEN == NULL: output instructions.
12183    LEN != NULL: set *LEN to the length of the instruction sequence
12184                 (in words) printed with LEN = NULL.
12185    If CLEAR_P is true, OP[0] had been cleard to Zero already.
12186    If CLEAR_P is false, nothing is known about OP[0].
12187 
12188    The effect on cc0 is as follows:
12189 
12190    Load 0 to any register except ZERO_REG : NONE
12191    Load ld register with any value        : NONE
12192    Anything else:                         : CLOBBER  */
12193 
12194 static void
output_reload_in_const(rtx * op,rtx clobber_reg,int * len,bool clear_p)12195 output_reload_in_const (rtx *op, rtx clobber_reg, int *len, bool clear_p)
12196 {
12197   rtx src = op[1];
12198   rtx dest = op[0];
12199   rtx xval, xdest[4];
12200   int ival[4];
12201   int clobber_val = 1234;
12202   bool cooked_clobber_p = false;
12203   bool set_p = false;
12204   machine_mode mode = GET_MODE (dest);
12205   int n_bytes = GET_MODE_SIZE (mode);
12206 
12207   gcc_assert (REG_P (dest)
12208               && CONSTANT_P (src));
12209 
12210   if (len)
12211     *len = 0;
12212 
12213   /* (REG:SI 14) is special: It's neither in LD_REGS nor in NO_LD_REGS
12214      but has some subregs that are in LD_REGS.  Use the MSB (REG:QI 17).  */
12215 
12216   if (REGNO (dest) < 16
12217       && REGNO (dest) + GET_MODE_SIZE (mode) > 16)
12218     {
12219       clobber_reg = all_regs_rtx[REGNO (dest) + n_bytes - 1];
12220     }
12221 
12222   /* We might need a clobber reg but don't have one.  Look at the value to
12223      be loaded more closely.  A clobber is only needed if it is a symbol
12224      or contains a byte that is neither 0, -1 or a power of 2.  */
12225 
12226   if (NULL_RTX == clobber_reg
12227       && !test_hard_reg_class (LD_REGS, dest)
12228       && (! (CONST_INT_P (src) || CONST_FIXED_P (src) || CONST_DOUBLE_P (src))
12229           || !avr_popcount_each_byte (src, n_bytes,
12230                                       (1 << 0) | (1 << 1) | (1 << 8))))
12231     {
12232       /* We have no clobber register but need one.  Cook one up.
12233          That's cheaper than loading from constant pool.  */
12234 
12235       cooked_clobber_p = true;
12236       clobber_reg = all_regs_rtx[REG_Z + 1];
12237       avr_asm_len ("mov __tmp_reg__,%0", &clobber_reg, len, 1);
12238     }
12239 
12240   /* Now start filling DEST from LSB to MSB.  */
12241 
12242   for (int n = 0; n < n_bytes; n++)
12243     {
12244       int ldreg_p;
12245       bool done_byte = false;
12246       rtx xop[3];
12247 
12248       /* Crop the n-th destination byte.  */
12249 
12250       xdest[n] = simplify_gen_subreg (QImode, dest, mode, n);
12251       ldreg_p = test_hard_reg_class (LD_REGS, xdest[n]);
12252 
12253       if (!CONST_INT_P (src)
12254           && !CONST_FIXED_P (src)
12255           && !CONST_DOUBLE_P (src))
12256         {
12257           static const char* const asm_code[][2] =
12258             {
12259               { "ldi %2,lo8(%1)"  CR_TAB "mov %0,%2",    "ldi %0,lo8(%1)"  },
12260               { "ldi %2,hi8(%1)"  CR_TAB "mov %0,%2",    "ldi %0,hi8(%1)"  },
12261               { "ldi %2,hlo8(%1)" CR_TAB "mov %0,%2",    "ldi %0,hlo8(%1)" },
12262               { "ldi %2,hhi8(%1)" CR_TAB "mov %0,%2",    "ldi %0,hhi8(%1)" }
12263             };
12264 
12265           xop[0] = xdest[n];
12266           xop[1] = src;
12267           xop[2] = clobber_reg;
12268 
12269           avr_asm_len (asm_code[n][ldreg_p], xop, len, ldreg_p ? 1 : 2);
12270 
12271           continue;
12272         }
12273 
12274       /* Crop the n-th source byte.  */
12275 
12276       xval = simplify_gen_subreg (QImode, src, mode, n);
12277       ival[n] = INTVAL (xval);
12278 
12279       /* Look if we can reuse the low word by means of MOVW.  */
12280 
12281       if (n == 2
12282           && n_bytes >= 4
12283           && AVR_HAVE_MOVW)
12284         {
12285           rtx lo16 = simplify_gen_subreg (HImode, src, mode, 0);
12286           rtx hi16 = simplify_gen_subreg (HImode, src, mode, 2);
12287 
12288           if (INTVAL (lo16) == INTVAL (hi16))
12289             {
12290 	      if (INTVAL (lo16) != 0 || !clear_p)
12291 		avr_asm_len ("movw %C0,%A0", &op[0], len, 1);
12292 
12293               break;
12294             }
12295         }
12296 
12297       /* Don't use CLR so that cc0 is set as expected.  */
12298 
12299       if (ival[n] == 0)
12300         {
12301           if (!clear_p)
12302             avr_asm_len (ldreg_p ? "ldi %0,0"
12303                          : AVR_ZERO_REGNO == REGNO (xdest[n]) ? "clr %0"
12304                          : "mov %0,__zero_reg__",
12305                          &xdest[n], len, 1);
12306           continue;
12307         }
12308 
12309       if (clobber_val == ival[n]
12310           && REGNO (clobber_reg) == REGNO (xdest[n]))
12311         {
12312           continue;
12313         }
12314 
12315       /* LD_REGS can use LDI to move a constant value */
12316 
12317       if (ldreg_p)
12318         {
12319           xop[0] = xdest[n];
12320           xop[1] = xval;
12321           avr_asm_len ("ldi %0,lo8(%1)", xop, len, 1);
12322           continue;
12323         }
12324 
12325       /* Try to reuse value already loaded in some lower byte. */
12326 
12327       for (int j = 0; j < n; j++)
12328         if (ival[j] == ival[n])
12329           {
12330             xop[0] = xdest[n];
12331             xop[1] = xdest[j];
12332 
12333             avr_asm_len ("mov %0,%1", xop, len, 1);
12334             done_byte = true;
12335             break;
12336           }
12337 
12338       if (done_byte)
12339         continue;
12340 
12341       /* Need no clobber reg for -1: Use CLR/DEC */
12342 
12343       if (ival[n] == -1)
12344         {
12345           if (!clear_p)
12346             avr_asm_len ("clr %0", &xdest[n], len, 1);
12347 
12348           avr_asm_len ("dec %0", &xdest[n], len, 1);
12349           continue;
12350         }
12351       else if (ival[n] == 1)
12352         {
12353           if (!clear_p)
12354             avr_asm_len ("clr %0", &xdest[n], len, 1);
12355 
12356           avr_asm_len ("inc %0", &xdest[n], len, 1);
12357           continue;
12358         }
12359 
12360       /* Use T flag or INC to manage powers of 2 if we have
12361          no clobber reg.  */
12362 
12363       if (NULL_RTX == clobber_reg
12364           && single_one_operand (xval, QImode))
12365         {
12366           xop[0] = xdest[n];
12367           xop[1] = GEN_INT (exact_log2 (ival[n] & GET_MODE_MASK (QImode)));
12368 
12369           gcc_assert (constm1_rtx != xop[1]);
12370 
12371           if (!set_p)
12372             {
12373               set_p = true;
12374               avr_asm_len ("set", xop, len, 1);
12375             }
12376 
12377           if (!clear_p)
12378             avr_asm_len ("clr %0", xop, len, 1);
12379 
12380           avr_asm_len ("bld %0,%1", xop, len, 1);
12381           continue;
12382         }
12383 
12384       /* We actually need the LD_REGS clobber reg.  */
12385 
12386       gcc_assert (NULL_RTX != clobber_reg);
12387 
12388       xop[0] = xdest[n];
12389       xop[1] = xval;
12390       xop[2] = clobber_reg;
12391       clobber_val = ival[n];
12392 
12393       avr_asm_len ("ldi %2,lo8(%1)" CR_TAB
12394                    "mov %0,%2", xop, len, 2);
12395     }
12396 
12397   /* If we cooked up a clobber reg above, restore it.  */
12398 
12399   if (cooked_clobber_p)
12400     {
12401       avr_asm_len ("mov %0,__tmp_reg__", &clobber_reg, len, 1);
12402     }
12403 }
12404 
12405 
12406 /* Reload the constant OP[1] into the HI register OP[0].
12407    CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
12408    into a NO_LD_REGS register.  If CLOBBER_REG is NULL_RTX we either don't
12409    need a clobber reg or have to cook one up.
12410 
12411    PLEN == NULL: Output instructions.
12412    PLEN != NULL: Output nothing.  Set *PLEN to number of words occupied
12413                  by the insns printed.
12414 
12415    Return "".  */
12416 
12417 const char*
output_reload_inhi(rtx * op,rtx clobber_reg,int * plen)12418 output_reload_inhi (rtx *op, rtx clobber_reg, int *plen)
12419 {
12420   output_reload_in_const (op, clobber_reg, plen, false);
12421   return "";
12422 }
12423 
12424 
12425 /* Reload a SI or SF compile time constant OP[1] into the register OP[0].
12426    CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
12427    into a NO_LD_REGS register.  If CLOBBER_REG is NULL_RTX we either don't
12428    need a clobber reg or have to cook one up.
12429 
12430    LEN == NULL: Output instructions.
12431 
12432    LEN != NULL: Output nothing.  Set *LEN to number of words occupied
12433                 by the insns printed.
12434 
12435    Return "".  */
12436 
12437 const char *
output_reload_insisf(rtx * op,rtx clobber_reg,int * len)12438 output_reload_insisf (rtx *op, rtx clobber_reg, int *len)
12439 {
12440   if (AVR_HAVE_MOVW
12441       && !test_hard_reg_class (LD_REGS, op[0])
12442       && (CONST_INT_P (op[1])
12443           || CONST_FIXED_P (op[1])
12444           || CONST_DOUBLE_P (op[1])))
12445     {
12446       int len_clr, len_noclr;
12447 
12448       /* In some cases it is better to clear the destination beforehand, e.g.
12449 
12450              CLR R2   CLR R3   MOVW R4,R2   INC R2
12451 
12452          is shorther than
12453 
12454              CLR R2   INC R2   CLR  R3      CLR R4   CLR R5
12455 
12456          We find it too tedious to work that out in the print function.
12457          Instead, we call the print function twice to get the lengths of
12458          both methods and use the shortest one.  */
12459 
12460       output_reload_in_const (op, clobber_reg, &len_clr, true);
12461       output_reload_in_const (op, clobber_reg, &len_noclr, false);
12462 
12463       if (len_noclr - len_clr == 4)
12464         {
12465           /* Default needs 4 CLR instructions: clear register beforehand.  */
12466 
12467           avr_asm_len ("mov %A0,__zero_reg__" CR_TAB
12468                        "mov %B0,__zero_reg__" CR_TAB
12469                        "movw %C0,%A0", &op[0], len, 3);
12470 
12471           output_reload_in_const (op, clobber_reg, len, true);
12472 
12473           if (len)
12474             *len += 3;
12475 
12476           return "";
12477         }
12478     }
12479 
12480   /* Default: destination not pre-cleared.  */
12481 
12482   output_reload_in_const (op, clobber_reg, len, false);
12483   return "";
12484 }
12485 
12486 const char*
avr_out_reload_inpsi(rtx * op,rtx clobber_reg,int * len)12487 avr_out_reload_inpsi (rtx *op, rtx clobber_reg, int *len)
12488 {
12489   output_reload_in_const (op, clobber_reg, len, false);
12490   return "";
12491 }
12492 
12493 
12494 /* Worker function for `ASM_OUTPUT_ADDR_VEC'.  */
12495 /* Emit jump tables out-of-line so that branches crossing the table
12496    get shorter offsets.  If we have JUMP + CALL, then put the tables
12497    in a dedicated non-.text section so that CALLs get better chance to
12498    be relaxed to RCALLs.
12499 
12500    We emit the tables by hand because `function_rodata_section' does not
12501    work as expected, cf. PR71151, and we do *NOT* want the table to be
12502    in .rodata, hence setting JUMP_TABLES_IN_TEXT_SECTION = 0 is of limited
12503    use; and setting it to 1 attributes table lengths to branch offsets...
12504    Moreover, fincal.c keeps switching section before each table entry
12505    which we find too fragile as to rely on section caching.  */
12506 
12507 void
avr_output_addr_vec(rtx_insn * labl,rtx table)12508 avr_output_addr_vec (rtx_insn *labl, rtx table)
12509 {
12510   FILE *stream = asm_out_file;
12511 
12512   app_disable();
12513 
12514   // Switch to appropriate (sub)section.
12515 
12516   if (DECL_SECTION_NAME (current_function_decl)
12517       && symtab_node::get (current_function_decl)
12518       && ! symtab_node::get (current_function_decl)->implicit_section)
12519     {
12520       // .subsection will emit the code after the function and in the
12521       // section as chosen by the user.
12522 
12523       switch_to_section (current_function_section ());
12524       fprintf (stream, "\t.subsection\t1\n");
12525     }
12526   else
12527     {
12528       // Since PR63223 there is no restriction where to put the table; it
12529       // may even reside above 128 KiB.  We put it in a section as high as
12530       // possible and avoid progmem in order not to waste flash <= 64 KiB.
12531 
12532       const char *sec_name = ".jumptables.gcc";
12533 
12534       // The table belongs to its host function, therefore use fine
12535       // grained sections so that, if that function is removed by
12536       // --gc-sections, the child table(s) may also be removed.  */
12537 
12538       tree asm_name = DECL_ASSEMBLER_NAME (current_function_decl);
12539       const char *fname = IDENTIFIER_POINTER (asm_name);
12540       fname = targetm.strip_name_encoding (fname);
12541       sec_name = ACONCAT ((sec_name, ".", fname, NULL));
12542 
12543       fprintf (stream, "\t.section\t%s,\"%s\",@progbits\n", sec_name,
12544                AVR_HAVE_JMP_CALL ? "a" : "ax");
12545     }
12546 
12547   // Output the label that preceeds the table.
12548 
12549   ASM_OUTPUT_ALIGN (stream, 1);
12550   targetm.asm_out.internal_label (stream, "L", CODE_LABEL_NUMBER (labl));
12551 
12552   // Output the table's content.
12553 
12554   int vlen = XVECLEN (table, 0);
12555 
12556   for (int idx = 0; idx < vlen; idx++)
12557     {
12558       int value = CODE_LABEL_NUMBER (XEXP (XVECEXP (table, 0, idx), 0));
12559 
12560       if (AVR_HAVE_JMP_CALL)
12561         fprintf (stream, "\t.word gs(.L%d)\n", value);
12562       else
12563         fprintf (stream, "\trjmp .L%d\n", value);
12564     }
12565 
12566   // Switch back to original section.  As we clobbered the section above,
12567   // forget the current section before switching back.
12568 
12569   in_section = NULL;
12570   switch_to_section (current_function_section ());
12571 }
12572 
12573 
12574 /* Implement `TARGET_CONDITIONAL_REGISTER_USAGE'.  */
12575 
12576 static void
avr_conditional_register_usage(void)12577 avr_conditional_register_usage (void)
12578 {
12579   if (AVR_TINY)
12580     {
12581       const int tiny_reg_alloc_order[] = {
12582         24, 25,
12583         22, 23,
12584         30, 31,
12585         26, 27,
12586         28, 29,
12587         21, 20, 19, 18,
12588         16, 17,
12589         32, 33, 34, 35,
12590         15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
12591       };
12592 
12593       /* Set R0-R17 as fixed registers. Reset R0-R17 in call used register list
12594          - R0-R15 are not available in Tiny Core devices
12595          - R16 and R17 are fixed registers.  */
12596 
12597       for (size_t i = 0; i <= 17;  i++)
12598         {
12599           fixed_regs[i] = 1;
12600           call_used_regs[i] = 1;
12601         }
12602 
12603       /* Set R18 to R21 as callee saved registers
12604          - R18, R19, R20 and R21 are the callee saved registers in
12605            Tiny Core devices  */
12606 
12607       for (size_t i = 18; i <= LAST_CALLEE_SAVED_REG; i++)
12608         {
12609           call_used_regs[i] = 0;
12610         }
12611 
12612       /* Update register allocation order for Tiny Core devices */
12613 
12614       for (size_t i = 0; i < ARRAY_SIZE (tiny_reg_alloc_order); i++)
12615         {
12616           reg_alloc_order[i] = tiny_reg_alloc_order[i];
12617         }
12618 
12619       CLEAR_HARD_REG_SET (reg_class_contents[(int) ADDW_REGS]);
12620       CLEAR_HARD_REG_SET (reg_class_contents[(int) NO_LD_REGS]);
12621     }
12622 }
12623 
12624 /* Implement `TARGET_HARD_REGNO_SCRATCH_OK'.  */
12625 /* Returns true if SCRATCH are safe to be allocated as a scratch
12626    registers (for a define_peephole2) in the current function.  */
12627 
12628 static bool
avr_hard_regno_scratch_ok(unsigned int regno)12629 avr_hard_regno_scratch_ok (unsigned int regno)
12630 {
12631   /* Interrupt functions can only use registers that have already been saved
12632      by the prologue, even if they would normally be call-clobbered.  */
12633 
12634   if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
12635       && !df_regs_ever_live_p (regno))
12636     return false;
12637 
12638   /* Don't allow hard registers that might be part of the frame pointer.
12639      Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
12640      and don't care for a frame pointer that spans more than one register.  */
12641 
12642   if ((!reload_completed || frame_pointer_needed)
12643       && (regno == REG_Y || regno == REG_Y + 1))
12644     {
12645       return false;
12646     }
12647 
12648   return true;
12649 }
12650 
12651 
12652 /* Worker function for `HARD_REGNO_RENAME_OK'.  */
12653 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG.  */
12654 
12655 int
avr_hard_regno_rename_ok(unsigned int old_reg,unsigned int new_reg)12656 avr_hard_regno_rename_ok (unsigned int old_reg,
12657 			  unsigned int new_reg)
12658 {
12659   /* Interrupt functions can only use registers that have already been
12660      saved by the prologue, even if they would normally be
12661      call-clobbered.  */
12662 
12663   if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
12664       && !df_regs_ever_live_p (new_reg))
12665     return 0;
12666 
12667   /* Don't allow hard registers that might be part of the frame pointer.
12668      Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
12669      and don't care for a frame pointer that spans more than one register.  */
12670 
12671   if ((!reload_completed || frame_pointer_needed)
12672       && (old_reg == REG_Y || old_reg == REG_Y + 1
12673           || new_reg == REG_Y || new_reg == REG_Y + 1))
12674     {
12675       return 0;
12676     }
12677 
12678   return 1;
12679 }
12680 
12681 /* Output a branch that tests a single bit of a register (QI, HI, SI or DImode)
12682    or memory location in the I/O space (QImode only).
12683 
12684    Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
12685    Operand 1: register operand to test, or CONST_INT memory address.
12686    Operand 2: bit number.
12687    Operand 3: label to jump to if the test is true.  */
12688 
12689 const char*
avr_out_sbxx_branch(rtx_insn * insn,rtx operands[])12690 avr_out_sbxx_branch (rtx_insn *insn, rtx operands[])
12691 {
12692   enum rtx_code comp = GET_CODE (operands[0]);
12693   bool long_jump = get_attr_length (insn) >= 4;
12694   bool reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
12695 
12696   if (comp == GE)
12697     comp = EQ;
12698   else if (comp == LT)
12699     comp = NE;
12700 
12701   if (reverse)
12702     comp = reverse_condition (comp);
12703 
12704   switch (GET_CODE (operands[1]))
12705     {
12706     default:
12707       gcc_unreachable();
12708 
12709     case CONST_INT:
12710     case CONST:
12711     case SYMBOL_REF:
12712 
12713       if (low_io_address_operand (operands[1], QImode))
12714         {
12715           if (comp == EQ)
12716             output_asm_insn ("sbis %i1,%2", operands);
12717           else
12718             output_asm_insn ("sbic %i1,%2", operands);
12719         }
12720       else
12721         {
12722 	  gcc_assert (io_address_operand (operands[1], QImode));
12723           output_asm_insn ("in __tmp_reg__,%i1", operands);
12724           if (comp == EQ)
12725             output_asm_insn ("sbrs __tmp_reg__,%2", operands);
12726           else
12727             output_asm_insn ("sbrc __tmp_reg__,%2", operands);
12728         }
12729 
12730       break; /* CONST_INT */
12731 
12732     case REG:
12733 
12734       if (comp == EQ)
12735         output_asm_insn ("sbrs %T1%T2", operands);
12736       else
12737         output_asm_insn ("sbrc %T1%T2", operands);
12738 
12739       break; /* REG */
12740     }        /* switch */
12741 
12742   if (long_jump)
12743     return ("rjmp .+4" CR_TAB
12744             "jmp %x3");
12745 
12746   if (!reverse)
12747     return "rjmp %x3";
12748 
12749   return "";
12750 }
12751 
12752 /* Worker function for `TARGET_ASM_CONSTRUCTOR'.  */
12753 
12754 static void
avr_asm_out_ctor(rtx symbol,int priority)12755 avr_asm_out_ctor (rtx symbol, int priority)
12756 {
12757   fputs ("\t.global __do_global_ctors\n", asm_out_file);
12758   default_ctor_section_asm_out_constructor (symbol, priority);
12759 }
12760 
12761 
12762 /* Worker function for `TARGET_ASM_DESTRUCTOR'.  */
12763 
12764 static void
avr_asm_out_dtor(rtx symbol,int priority)12765 avr_asm_out_dtor (rtx symbol, int priority)
12766 {
12767   fputs ("\t.global __do_global_dtors\n", asm_out_file);
12768   default_dtor_section_asm_out_destructor (symbol, priority);
12769 }
12770 
12771 
12772 /* Worker function for `TARGET_RETURN_IN_MEMORY'.  */
12773 
12774 static bool
avr_return_in_memory(const_tree type,const_tree fntype ATTRIBUTE_UNUSED)12775 avr_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
12776 {
12777   HOST_WIDE_INT size = int_size_in_bytes (type);
12778   HOST_WIDE_INT ret_size_limit = AVR_TINY ? 4 : 8;
12779 
12780   /* In avr, there are 8 return registers. But, for Tiny Core
12781      (ATtiny4/5/9/10/20/40) devices, only 4 registers are available.
12782      Return true if size is unknown or greater than the limit.  */
12783 
12784   if (size == -1 || size > ret_size_limit)
12785     {
12786       return true;
12787     }
12788   else
12789     {
12790       return false;
12791     }
12792 }
12793 
12794 
12795 /* Implement `CASE_VALUES_THRESHOLD'.  */
12796 /* Supply the default for --param case-values-threshold=0  */
12797 
12798 static unsigned int
avr_case_values_threshold(void)12799 avr_case_values_threshold (void)
12800 {
12801   /* The exact break-even point between a jump table and an if-else tree
12802      depends on several factors not available here like, e.g. if 8-bit
12803      comparisons can be used in the if-else tree or not, on the
12804      range of the case values, if the case value can be reused, on the
12805      register allocation, etc.  '7' appears to be a good choice.  */
12806 
12807   return 7;
12808 }
12809 
12810 
12811 /* Implement `TARGET_ADDR_SPACE_ADDRESS_MODE'.  */
12812 
12813 static scalar_int_mode
avr_addr_space_address_mode(addr_space_t as)12814 avr_addr_space_address_mode (addr_space_t as)
12815 {
12816   return avr_addrspace[as].pointer_size == 3 ? PSImode : HImode;
12817 }
12818 
12819 
12820 /* Implement `TARGET_ADDR_SPACE_POINTER_MODE'.  */
12821 
12822 static scalar_int_mode
avr_addr_space_pointer_mode(addr_space_t as)12823 avr_addr_space_pointer_mode (addr_space_t as)
12824 {
12825   return avr_addr_space_address_mode (as);
12826 }
12827 
12828 
12829 /* Helper for following function.  */
12830 
12831 static bool
avr_reg_ok_for_pgm_addr(rtx reg,bool strict)12832 avr_reg_ok_for_pgm_addr (rtx reg, bool strict)
12833 {
12834   gcc_assert (REG_P (reg));
12835 
12836   if (strict)
12837     {
12838       return REGNO (reg) == REG_Z;
12839     }
12840 
12841   /* Avoid combine to propagate hard regs.  */
12842 
12843   if (can_create_pseudo_p()
12844       && REGNO (reg) < REG_Z)
12845     {
12846       return false;
12847     }
12848 
12849   return true;
12850 }
12851 
12852 
12853 /* Implement `TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P'.  */
12854 
12855 static bool
avr_addr_space_legitimate_address_p(machine_mode mode,rtx x,bool strict,addr_space_t as)12856 avr_addr_space_legitimate_address_p (machine_mode mode, rtx x,
12857                                      bool strict, addr_space_t as)
12858 {
12859   bool ok = false;
12860 
12861   switch (as)
12862     {
12863     default:
12864       gcc_unreachable();
12865 
12866     case ADDR_SPACE_GENERIC:
12867       return avr_legitimate_address_p (mode, x, strict);
12868 
12869     case ADDR_SPACE_FLASH:
12870     case ADDR_SPACE_FLASH1:
12871     case ADDR_SPACE_FLASH2:
12872     case ADDR_SPACE_FLASH3:
12873     case ADDR_SPACE_FLASH4:
12874     case ADDR_SPACE_FLASH5:
12875 
12876       switch (GET_CODE (x))
12877         {
12878         case REG:
12879           ok = avr_reg_ok_for_pgm_addr (x, strict);
12880           break;
12881 
12882         case POST_INC:
12883           ok = avr_reg_ok_for_pgm_addr (XEXP (x, 0), strict);
12884           break;
12885 
12886         default:
12887           break;
12888         }
12889 
12890       break; /* FLASH */
12891 
12892     case ADDR_SPACE_MEMX:
12893       if (REG_P (x))
12894         ok = (!strict
12895               && can_create_pseudo_p());
12896 
12897       if (LO_SUM == GET_CODE (x))
12898         {
12899           rtx hi = XEXP (x, 0);
12900           rtx lo = XEXP (x, 1);
12901 
12902           ok = (REG_P (hi)
12903                 && (!strict || REGNO (hi) < FIRST_PSEUDO_REGISTER)
12904                 && REG_P (lo)
12905                 && REGNO (lo) == REG_Z);
12906         }
12907 
12908       break; /* MEMX */
12909     }
12910 
12911   if (avr_log.legitimate_address_p)
12912     {
12913       avr_edump ("\n%?: ret=%b, mode=%m strict=%d "
12914                  "reload_completed=%d reload_in_progress=%d %s:",
12915                  ok, mode, strict, reload_completed, reload_in_progress,
12916                  reg_renumber ? "(reg_renumber)" : "");
12917 
12918       if (GET_CODE (x) == PLUS
12919           && REG_P (XEXP (x, 0))
12920           && CONST_INT_P (XEXP (x, 1))
12921           && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
12922           && reg_renumber)
12923         {
12924           avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
12925                      true_regnum (XEXP (x, 0)));
12926         }
12927 
12928       avr_edump ("\n%r\n", x);
12929     }
12930 
12931   return ok;
12932 }
12933 
12934 
12935 /* Implement `TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS'.  */
12936 
12937 static rtx
avr_addr_space_legitimize_address(rtx x,rtx old_x,machine_mode mode,addr_space_t as)12938 avr_addr_space_legitimize_address (rtx x, rtx old_x,
12939                                    machine_mode mode, addr_space_t as)
12940 {
12941   if (ADDR_SPACE_GENERIC_P (as))
12942     return avr_legitimize_address (x, old_x, mode);
12943 
12944   if (avr_log.legitimize_address)
12945     {
12946       avr_edump ("\n%?: mode=%m\n %r\n", mode, old_x);
12947     }
12948 
12949   return old_x;
12950 }
12951 
12952 
12953 /* Implement `TARGET_ADDR_SPACE_CONVERT'.  */
12954 
12955 static rtx
avr_addr_space_convert(rtx src,tree type_from,tree type_to)12956 avr_addr_space_convert (rtx src, tree type_from, tree type_to)
12957 {
12958   addr_space_t as_from = TYPE_ADDR_SPACE (TREE_TYPE (type_from));
12959   addr_space_t as_to = TYPE_ADDR_SPACE (TREE_TYPE (type_to));
12960 
12961   if (avr_log.progmem)
12962     avr_edump ("\n%!: op = %r\nfrom = %t\nto = %t\n",
12963                src, type_from, type_to);
12964 
12965   /* Up-casting from 16-bit to 24-bit pointer.  */
12966 
12967   if (as_from != ADDR_SPACE_MEMX
12968       && as_to == ADDR_SPACE_MEMX)
12969     {
12970       int msb;
12971       rtx sym = src;
12972       rtx reg = gen_reg_rtx (PSImode);
12973 
12974       while (CONST == GET_CODE (sym) || PLUS == GET_CODE (sym))
12975         sym = XEXP (sym, 0);
12976 
12977       /* Look at symbol flags:  avr_encode_section_info set the flags
12978          also if attribute progmem was seen so that we get the right
12979          promotion for, e.g. PSTR-like strings that reside in generic space
12980          but are located in flash.  In that case we patch the incoming
12981          address space.  */
12982 
12983       if (SYMBOL_REF_P (sym)
12984           && ADDR_SPACE_FLASH == AVR_SYMBOL_GET_ADDR_SPACE (sym))
12985         {
12986           as_from = ADDR_SPACE_FLASH;
12987         }
12988 
12989       /* Linearize memory: RAM has bit 23 set.  */
12990 
12991       msb = ADDR_SPACE_GENERIC_P (as_from)
12992         ? 0x80
12993         : avr_addrspace[as_from].segment;
12994 
12995       src = force_reg (Pmode, src);
12996 
12997       emit_insn (msb == 0
12998                  ? gen_zero_extendhipsi2 (reg, src)
12999                  : gen_n_extendhipsi2 (reg, gen_int_mode (msb, QImode), src));
13000 
13001       return reg;
13002     }
13003 
13004   /* Down-casting from 24-bit to 16-bit throws away the high byte.  */
13005 
13006   if (as_from == ADDR_SPACE_MEMX
13007       && as_to != ADDR_SPACE_MEMX)
13008     {
13009       rtx new_src = gen_reg_rtx (Pmode);
13010 
13011       src = force_reg (PSImode, src);
13012 
13013       emit_move_insn (new_src,
13014                       simplify_gen_subreg (Pmode, src, PSImode, 0));
13015       return new_src;
13016     }
13017 
13018   return src;
13019 }
13020 
13021 
13022 /* Implement `TARGET_ADDR_SPACE_SUBSET_P'.  */
13023 
13024 static bool
avr_addr_space_subset_p(addr_space_t subset ATTRIBUTE_UNUSED,addr_space_t superset ATTRIBUTE_UNUSED)13025 avr_addr_space_subset_p (addr_space_t subset ATTRIBUTE_UNUSED,
13026                          addr_space_t superset ATTRIBUTE_UNUSED)
13027 {
13028   /* Allow any kind of pointer mess.  */
13029 
13030   return true;
13031 }
13032 
13033 
13034 /* Implement `TARGET_CONVERT_TO_TYPE'.  */
13035 
13036 static tree
avr_convert_to_type(tree type,tree expr)13037 avr_convert_to_type (tree type, tree expr)
13038 {
13039   /* Print a diagnose for pointer conversion that changes the address
13040      space of the pointer target to a non-enclosing address space,
13041      provided -Waddr-space-convert is on.
13042 
13043      FIXME: Filter out cases where the target object is known to
13044             be located in the right memory, like in
13045 
13046                 (const __flash*) PSTR ("text")
13047 
13048             Also try to distinguish between explicit casts requested by
13049             the user and implicit casts like
13050 
13051                 void f (const __flash char*);
13052 
13053                 void g (const char *p)
13054                 {
13055                     f ((const __flash*) p);
13056                 }
13057 
13058             under the assumption that an explicit casts means that the user
13059             knows what he is doing, e.g. interface with PSTR or old style
13060             code with progmem and pgm_read_xxx.
13061   */
13062 
13063   if (avr_warn_addr_space_convert
13064       && expr != error_mark_node
13065       && POINTER_TYPE_P (type)
13066       && POINTER_TYPE_P (TREE_TYPE (expr)))
13067     {
13068       addr_space_t as_old = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (expr)));
13069       addr_space_t as_new = TYPE_ADDR_SPACE (TREE_TYPE (type));
13070 
13071       if (avr_log.progmem)
13072         avr_edump ("%?: type = %t\nexpr = %t\n\n", type, expr);
13073 
13074       if (as_new != ADDR_SPACE_MEMX
13075           && as_new != as_old)
13076         {
13077           location_t loc = EXPR_LOCATION (expr);
13078           const char *name_old = avr_addrspace[as_old].name;
13079           const char *name_new = avr_addrspace[as_new].name;
13080 
13081           warning (OPT_Waddr_space_convert,
13082                    "conversion from address space %qs to address space %qs",
13083                    ADDR_SPACE_GENERIC_P (as_old) ? "generic" : name_old,
13084                    ADDR_SPACE_GENERIC_P (as_new) ? "generic" : name_new);
13085 
13086           return fold_build1_loc (loc, ADDR_SPACE_CONVERT_EXPR, type, expr);
13087         }
13088     }
13089 
13090   return NULL_TREE;
13091 }
13092 
13093 
13094 /* Implement `TARGET_LEGITIMATE_COMBINED_INSN'.  */
13095 
13096 /* PR78883: Filter out paradoxical SUBREGs of MEM which are not handled
13097    properly by following passes.  As INSN_SCHEDULING is off and hence
13098    general_operand accepts such expressions, ditch them now.  */
13099 
13100 static bool
avr_legitimate_combined_insn(rtx_insn * insn)13101 avr_legitimate_combined_insn (rtx_insn *insn)
13102 {
13103   subrtx_iterator::array_type array;
13104 
13105   FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
13106     {
13107       const_rtx op = *iter;
13108 
13109       if (SUBREG_P (op)
13110           && MEM_P (SUBREG_REG (op))
13111           && (GET_MODE_SIZE (GET_MODE (op))
13112               > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))))
13113         {
13114           return false;
13115         }
13116     }
13117 
13118   return true;
13119 }
13120 
13121 
13122 /* PR63633: The middle-end might come up with hard regs as input operands.
13123 
13124    RMASK is a bit mask representing a subset of hard registers R0...R31:
13125    Rn is an element of that set iff bit n of RMASK is set.
13126    OPMASK describes a subset of OP[]:  If bit n of OPMASK is 1 then
13127    OP[n] has to be fixed; otherwise OP[n] is left alone.
13128 
13129    For each element of OPMASK which is a hard register overlapping RMASK,
13130    replace OP[n] with a newly created pseudo register
13131 
13132    HREG == 0:  Also emit a move insn that copies the contents of that
13133                hard register into the new pseudo.
13134 
13135    HREG != 0:  Also set HREG[n] to the hard register.  */
13136 
13137 static void
avr_fix_operands(rtx * op,rtx * hreg,unsigned opmask,unsigned rmask)13138 avr_fix_operands (rtx *op, rtx *hreg, unsigned opmask, unsigned rmask)
13139 {
13140   for (; opmask; opmask >>= 1, op++)
13141     {
13142       rtx reg = *op;
13143 
13144       if (hreg)
13145         *hreg = NULL_RTX;
13146 
13147       if ((opmask & 1)
13148           && REG_P (reg)
13149           && REGNO (reg) < FIRST_PSEUDO_REGISTER
13150           // This hard-reg overlaps other prohibited hard regs?
13151           && (rmask & regmask (GET_MODE (reg), REGNO (reg))))
13152         {
13153           *op = gen_reg_rtx (GET_MODE (reg));
13154           if (hreg == NULL)
13155             emit_move_insn (*op, reg);
13156           else
13157             *hreg = reg;
13158         }
13159 
13160       if (hreg)
13161         hreg++;
13162     }
13163 }
13164 
13165 
13166 void
avr_fix_inputs(rtx * op,unsigned opmask,unsigned rmask)13167 avr_fix_inputs (rtx *op, unsigned opmask, unsigned rmask)
13168 {
13169   avr_fix_operands (op, NULL, opmask, rmask);
13170 }
13171 
13172 
13173 /* Helper for the function below:  If bit n of MASK is set and
13174    HREG[n] != NULL, then emit a move insn to copy OP[n] to HREG[n].
13175    Otherwise do nothing for that n.  Return TRUE.  */
13176 
13177 static bool
avr_move_fixed_operands(rtx * op,rtx * hreg,unsigned mask)13178 avr_move_fixed_operands (rtx *op, rtx *hreg, unsigned mask)
13179 {
13180   for (; mask; mask >>= 1, op++, hreg++)
13181     if ((mask & 1)
13182         && *hreg)
13183       emit_move_insn (*hreg, *op);
13184 
13185   return true;
13186 }
13187 
13188 
13189 /* PR63633: The middle-end might come up with hard regs as output operands.
13190 
13191    GEN is a sequence generating function like gen_mulsi3 with 3 operands OP[].
13192    RMASK is a bit mask representing a subset of hard registers R0...R31:
13193    Rn is an element of that set iff bit n of RMASK is set.
13194    OPMASK describes a subset of OP[]:  If bit n of OPMASK is 1 then
13195    OP[n] has to be fixed; otherwise OP[n] is left alone.
13196 
13197    Emit the insn sequence as generated by GEN() with all elements of OPMASK
13198    which are hard registers overlapping RMASK replaced by newly created
13199    pseudo registers.  After the sequence has been emitted, emit insns that
13200    move the contents of respective pseudos to their hard regs.  */
13201 
13202 bool
avr_emit3_fix_outputs(rtx (* gen)(rtx,rtx,rtx),rtx * op,unsigned opmask,unsigned rmask)13203 avr_emit3_fix_outputs (rtx (*gen)(rtx,rtx,rtx), rtx *op,
13204                        unsigned opmask, unsigned rmask)
13205 {
13206   const int n = 3;
13207   rtx hreg[n];
13208 
13209   /* It is letigimate for GEN to call this function, and in order not to
13210      get self-recursive we use the following static kludge.  This is the
13211      only way not to duplicate all expanders and to avoid ugly and
13212      hard-to-maintain C-code instead of the much more appreciated RTL
13213      representation as supplied by define_expand.  */
13214   static bool lock = false;
13215 
13216   gcc_assert (opmask < (1u << n));
13217 
13218   if (lock)
13219     return false;
13220 
13221   avr_fix_operands (op, hreg, opmask, rmask);
13222 
13223   lock = true;
13224   emit_insn (gen (op[0], op[1], op[2]));
13225   lock = false;
13226 
13227   return avr_move_fixed_operands (op, hreg, opmask);
13228 }
13229 
13230 
13231 /* Worker function for cpymemhi expander.
13232    XOP[0]  Destination as MEM:BLK
13233    XOP[1]  Source      "     "
13234    XOP[2]  # Bytes to copy
13235 
13236    Return TRUE  if the expansion is accomplished.
13237    Return FALSE if the operand compination is not supported.  */
13238 
13239 bool
avr_emit_cpymemhi(rtx * xop)13240 avr_emit_cpymemhi (rtx *xop)
13241 {
13242   HOST_WIDE_INT count;
13243   machine_mode loop_mode;
13244   addr_space_t as = MEM_ADDR_SPACE (xop[1]);
13245   rtx loop_reg, addr1, a_src, a_dest, insn, xas;
13246   rtx a_hi8 = NULL_RTX;
13247 
13248   if (avr_mem_flash_p (xop[0]))
13249     return false;
13250 
13251   if (!CONST_INT_P (xop[2]))
13252     return false;
13253 
13254   count = INTVAL (xop[2]);
13255   if (count <= 0)
13256     return false;
13257 
13258   a_src  = XEXP (xop[1], 0);
13259   a_dest = XEXP (xop[0], 0);
13260 
13261   if (PSImode == GET_MODE (a_src))
13262     {
13263       gcc_assert (as == ADDR_SPACE_MEMX);
13264 
13265       loop_mode = (count < 0x100) ? QImode : HImode;
13266       loop_reg = gen_rtx_REG (loop_mode, 24);
13267       emit_move_insn (loop_reg, gen_int_mode (count, loop_mode));
13268 
13269       addr1 = simplify_gen_subreg (HImode, a_src, PSImode, 0);
13270       a_hi8 = simplify_gen_subreg (QImode, a_src, PSImode, 2);
13271     }
13272   else
13273     {
13274       int segment = avr_addrspace[as].segment;
13275 
13276       if (segment
13277           && avr_n_flash > 1)
13278         {
13279           a_hi8 = GEN_INT (segment);
13280           emit_move_insn (rampz_rtx, a_hi8 = copy_to_mode_reg (QImode, a_hi8));
13281         }
13282       else if (!ADDR_SPACE_GENERIC_P (as))
13283         {
13284           as = ADDR_SPACE_FLASH;
13285         }
13286 
13287       addr1 = a_src;
13288 
13289       loop_mode = (count <= 0x100) ? QImode : HImode;
13290       loop_reg = copy_to_mode_reg (loop_mode, gen_int_mode (count, loop_mode));
13291     }
13292 
13293   xas = GEN_INT (as);
13294 
13295   /* FIXME: Register allocator might come up with spill fails if it is left
13296         on its own.  Thus, we allocate the pointer registers by hand:
13297         Z = source address
13298         X = destination address  */
13299 
13300   emit_move_insn (lpm_addr_reg_rtx, addr1);
13301   emit_move_insn (gen_rtx_REG (HImode, REG_X), a_dest);
13302 
13303   /* FIXME: Register allocator does a bad job and might spill address
13304         register(s) inside the loop leading to additional move instruction
13305         to/from stack which could clobber tmp_reg.  Thus, do *not* emit
13306         load and store as separate insns.  Instead, we perform the copy
13307         by means of one monolithic insn.  */
13308 
13309   gcc_assert (TMP_REGNO == LPM_REGNO);
13310 
13311   if (as != ADDR_SPACE_MEMX)
13312     {
13313       /* Load instruction ([E]LPM or LD) is known at compile time:
13314          Do the copy-loop inline.  */
13315 
13316       rtx (*fun) (rtx, rtx, rtx)
13317         = QImode == loop_mode ? gen_cpymem_qi : gen_cpymem_hi;
13318 
13319       insn = fun (xas, loop_reg, loop_reg);
13320     }
13321   else
13322     {
13323       rtx (*fun) (rtx, rtx)
13324         = QImode == loop_mode ? gen_cpymemx_qi : gen_cpymemx_hi;
13325 
13326       emit_move_insn (gen_rtx_REG (QImode, 23), a_hi8);
13327 
13328       insn = fun (xas, GEN_INT (avr_addr.rampz));
13329     }
13330 
13331   set_mem_addr_space (SET_SRC (XVECEXP (insn, 0, 0)), as);
13332   emit_insn (insn);
13333 
13334   return true;
13335 }
13336 
13337 
13338 /* Print assembler for cpymem_qi, cpymem_hi insns...
13339        $0     : Address Space
13340        $1, $2 : Loop register
13341        Z      : Source address
13342        X      : Destination address
13343 */
13344 
13345 const char*
avr_out_cpymem(rtx_insn * insn ATTRIBUTE_UNUSED,rtx * op,int * plen)13346 avr_out_cpymem (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
13347 {
13348   addr_space_t as = (addr_space_t) INTVAL (op[0]);
13349   machine_mode loop_mode = GET_MODE (op[1]);
13350   bool sbiw_p = test_hard_reg_class (ADDW_REGS, op[1]);
13351   rtx xop[3];
13352 
13353   if (plen)
13354     *plen = 0;
13355 
13356   xop[0] = op[0];
13357   xop[1] = op[1];
13358   xop[2] = tmp_reg_rtx;
13359 
13360   /* Loop label */
13361 
13362   avr_asm_len ("0:", xop, plen, 0);
13363 
13364   /* Load with post-increment */
13365 
13366   switch (as)
13367     {
13368     default:
13369       gcc_unreachable();
13370 
13371     case ADDR_SPACE_GENERIC:
13372 
13373       avr_asm_len ("ld %2,Z+", xop, plen, 1);
13374       break;
13375 
13376     case ADDR_SPACE_FLASH:
13377 
13378       if (AVR_HAVE_LPMX)
13379         avr_asm_len ("lpm %2,Z+", xop, plen, 1);
13380       else
13381         avr_asm_len ("lpm" CR_TAB
13382                      "adiw r30,1", xop, plen, 2);
13383       break;
13384 
13385     case ADDR_SPACE_FLASH1:
13386     case ADDR_SPACE_FLASH2:
13387     case ADDR_SPACE_FLASH3:
13388     case ADDR_SPACE_FLASH4:
13389     case ADDR_SPACE_FLASH5:
13390 
13391       if (AVR_HAVE_ELPMX)
13392         avr_asm_len ("elpm %2,Z+", xop, plen, 1);
13393       else
13394         avr_asm_len ("elpm" CR_TAB
13395                      "adiw r30,1", xop, plen, 2);
13396       break;
13397     }
13398 
13399   /* Store with post-increment */
13400 
13401   avr_asm_len ("st X+,%2", xop, plen, 1);
13402 
13403   /* Decrement loop-counter and set Z-flag */
13404 
13405   if (QImode == loop_mode)
13406     {
13407       avr_asm_len ("dec %1", xop, plen, 1);
13408     }
13409   else if (sbiw_p)
13410     {
13411       avr_asm_len ("sbiw %1,1", xop, plen, 1);
13412     }
13413   else
13414     {
13415       avr_asm_len ("subi %A1,1" CR_TAB
13416                    "sbci %B1,0", xop, plen, 2);
13417     }
13418 
13419   /* Loop until zero */
13420 
13421   return avr_asm_len ("brne 0b", xop, plen, 1);
13422 }
13423 
13424 
13425 
13426 /* Helper for __builtin_avr_delay_cycles */
13427 
13428 static rtx
avr_mem_clobber(void)13429 avr_mem_clobber (void)
13430 {
13431   rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
13432   MEM_VOLATILE_P (mem) = 1;
13433   return mem;
13434 }
13435 
13436 static void
avr_expand_delay_cycles(rtx operands0)13437 avr_expand_delay_cycles (rtx operands0)
13438 {
13439   unsigned HOST_WIDE_INT cycles = UINTVAL (operands0) & GET_MODE_MASK (SImode);
13440   unsigned HOST_WIDE_INT cycles_used;
13441   unsigned HOST_WIDE_INT loop_count;
13442 
13443   if (IN_RANGE (cycles, 83886082, 0xFFFFFFFF))
13444     {
13445       loop_count = ((cycles - 9) / 6) + 1;
13446       cycles_used = ((loop_count - 1) * 6) + 9;
13447       emit_insn (gen_delay_cycles_4 (gen_int_mode (loop_count, SImode),
13448                                      avr_mem_clobber()));
13449       cycles -= cycles_used;
13450     }
13451 
13452   if (IN_RANGE (cycles, 262145, 83886081))
13453     {
13454       loop_count = ((cycles - 7) / 5) + 1;
13455       if (loop_count > 0xFFFFFF)
13456         loop_count = 0xFFFFFF;
13457       cycles_used = ((loop_count - 1) * 5) + 7;
13458       emit_insn (gen_delay_cycles_3 (gen_int_mode (loop_count, SImode),
13459                                      avr_mem_clobber()));
13460       cycles -= cycles_used;
13461     }
13462 
13463   if (IN_RANGE (cycles, 768, 262144))
13464     {
13465       loop_count = ((cycles - 5) / 4) + 1;
13466       if (loop_count > 0xFFFF)
13467         loop_count = 0xFFFF;
13468       cycles_used = ((loop_count - 1) * 4) + 5;
13469       emit_insn (gen_delay_cycles_2 (gen_int_mode (loop_count, HImode),
13470                                      avr_mem_clobber()));
13471       cycles -= cycles_used;
13472     }
13473 
13474   if (IN_RANGE (cycles, 6, 767))
13475     {
13476       loop_count = cycles / 3;
13477       if (loop_count > 255)
13478         loop_count = 255;
13479       cycles_used = loop_count * 3;
13480       emit_insn (gen_delay_cycles_1 (gen_int_mode (loop_count, QImode),
13481                                      avr_mem_clobber()));
13482       cycles -= cycles_used;
13483     }
13484 
13485   while (cycles >= 2)
13486     {
13487       emit_insn (gen_nopv (GEN_INT (2)));
13488       cycles -= 2;
13489     }
13490 
13491   if (cycles == 1)
13492     {
13493       emit_insn (gen_nopv (GEN_INT (1)));
13494       cycles--;
13495     }
13496 }
13497 
13498 
13499 static void
avr_expand_nops(rtx operands0)13500 avr_expand_nops (rtx operands0)
13501 {
13502   unsigned HOST_WIDE_INT n_nops = UINTVAL (operands0) & GET_MODE_MASK (HImode);
13503 
13504   while (n_nops--)
13505     {
13506       emit_insn (gen_nopv (const1_rtx));
13507     }
13508 }
13509 
13510 
13511 /* Compute the image of x under f, i.e. perform   x --> f(x)    */
13512 
13513 static int
avr_map(unsigned int f,int x)13514 avr_map (unsigned int f, int x)
13515 {
13516   return x < 8 ? (f >> (4 * x)) & 0xf : 0;
13517 }
13518 
13519 
13520 /* Return some metrics of map A.  */
13521 
13522 enum
13523   {
13524     /* Number of fixed points in { 0 ... 7 } */
13525     MAP_FIXED_0_7,
13526 
13527     /* Size of preimage of non-fixed points in { 0 ... 7 } */
13528     MAP_NONFIXED_0_7,
13529 
13530     /* Mask representing the fixed points in { 0 ... 7 } */
13531     MAP_MASK_FIXED_0_7,
13532 
13533     /* Size of the preimage of { 0 ... 7 } */
13534     MAP_PREIMAGE_0_7,
13535 
13536     /* Mask that represents the preimage of { f } */
13537     MAP_MASK_PREIMAGE_F
13538   };
13539 
13540 static unsigned
avr_map_metric(unsigned int a,int mode)13541 avr_map_metric (unsigned int a, int mode)
13542 {
13543   unsigned metric = 0;
13544 
13545   for (unsigned i = 0; i < 8; i++)
13546     {
13547       unsigned ai = avr_map (a, i);
13548 
13549       if (mode == MAP_FIXED_0_7)
13550         metric += ai == i;
13551       else if (mode == MAP_NONFIXED_0_7)
13552         metric += ai < 8 && ai != i;
13553       else if (mode == MAP_MASK_FIXED_0_7)
13554         metric |= ((unsigned) (ai == i)) << i;
13555       else if (mode == MAP_PREIMAGE_0_7)
13556         metric += ai < 8;
13557       else if (mode == MAP_MASK_PREIMAGE_F)
13558         metric |= ((unsigned) (ai == 0xf)) << i;
13559       else
13560         gcc_unreachable();
13561     }
13562 
13563   return metric;
13564 }
13565 
13566 
13567 /* Return true if IVAL has a 0xf in its hexadecimal representation
13568    and false, otherwise.  Only nibbles 0..7 are taken into account.
13569    Used as constraint helper for C0f and Cxf.  */
13570 
13571 bool
avr_has_nibble_0xf(rtx ival)13572 avr_has_nibble_0xf (rtx ival)
13573 {
13574   unsigned int map = UINTVAL (ival) & GET_MODE_MASK (SImode);
13575   return avr_map_metric (map, MAP_MASK_PREIMAGE_F) != 0;
13576 }
13577 
13578 
13579 /* We have a set of bits that are mapped by a function F.
13580    Try to decompose F by means of a second function G so that
13581 
13582       F = F o G^-1 o G
13583 
13584    and
13585 
13586       cost (F o G^-1) + cost (G)  <  cost (F)
13587 
13588    Example:  Suppose builtin insert_bits supplies us with the map
13589    F = 0x3210ffff.  Instead of doing 4 bit insertions to get the high
13590    nibble of the result, we can just as well rotate the bits before inserting
13591    them and use the map 0x7654ffff which is cheaper than the original map.
13592    For this example G = G^-1 = 0x32107654 and F o G^-1 = 0x7654ffff.  */
13593 
13594 typedef struct
13595 {
13596   /* tree code of binary function G */
13597   enum tree_code code;
13598 
13599   /* The constant second argument of G */
13600   int arg;
13601 
13602   /* G^-1, the inverse of G (*, arg) */
13603   unsigned ginv;
13604 
13605   /* The cost of applying G (*, arg) */
13606   int cost;
13607 
13608   /* The composition F o G^-1 (*, arg) for some function F */
13609   unsigned int map;
13610 
13611   /* For debug purpose only */
13612   const char *str;
13613 } avr_map_op_t;
13614 
13615 static const avr_map_op_t avr_map_op[] =
13616   {
13617     { LROTATE_EXPR, 0, 0x76543210, 0, 0, "id" },
13618     { LROTATE_EXPR, 1, 0x07654321, 2, 0, "<<<" },
13619     { LROTATE_EXPR, 2, 0x10765432, 4, 0, "<<<" },
13620     { LROTATE_EXPR, 3, 0x21076543, 4, 0, "<<<" },
13621     { LROTATE_EXPR, 4, 0x32107654, 1, 0, "<<<" },
13622     { LROTATE_EXPR, 5, 0x43210765, 3, 0, "<<<" },
13623     { LROTATE_EXPR, 6, 0x54321076, 5, 0, "<<<" },
13624     { LROTATE_EXPR, 7, 0x65432107, 3, 0, "<<<" },
13625     { RSHIFT_EXPR, 1, 0x6543210c, 1, 0, ">>" },
13626     { RSHIFT_EXPR, 1, 0x7543210c, 1, 0, ">>" },
13627     { RSHIFT_EXPR, 2, 0x543210cc, 2, 0, ">>" },
13628     { RSHIFT_EXPR, 2, 0x643210cc, 2, 0, ">>" },
13629     { RSHIFT_EXPR, 2, 0x743210cc, 2, 0, ">>" },
13630     { LSHIFT_EXPR, 1, 0xc7654321, 1, 0, "<<" },
13631     { LSHIFT_EXPR, 2, 0xcc765432, 2, 0, "<<" }
13632   };
13633 
13634 
13635 /* Try to decompose F as F = (F o G^-1) o G as described above.
13636    The result is a struct representing F o G^-1 and G.
13637    If result.cost < 0 then such a decomposition does not exist.  */
13638 
13639 static avr_map_op_t
avr_map_decompose(unsigned int f,const avr_map_op_t * g,bool val_const_p)13640 avr_map_decompose (unsigned int f, const avr_map_op_t *g, bool val_const_p)
13641 {
13642   bool val_used_p = avr_map_metric (f, MAP_MASK_PREIMAGE_F) != 0;
13643   avr_map_op_t f_ginv = *g;
13644   unsigned int ginv = g->ginv;
13645 
13646   f_ginv.cost = -1;
13647 
13648   /* Step 1:  Computing F o G^-1  */
13649 
13650   for (int i = 7; i >= 0; i--)
13651     {
13652       int x = avr_map (f, i);
13653 
13654       if (x <= 7)
13655         {
13656           x = avr_map (ginv, x);
13657 
13658           /* The bit is no element of the image of G: no avail (cost = -1)  */
13659 
13660           if (x > 7)
13661             return f_ginv;
13662         }
13663 
13664       f_ginv.map = (f_ginv.map << 4) + x;
13665     }
13666 
13667   /* Step 2:  Compute the cost of the operations.
13668      The overall cost of doing an operation prior to the insertion is
13669       the cost of the insertion plus the cost of the operation.  */
13670 
13671   /* Step 2a:  Compute cost of F o G^-1  */
13672 
13673   if (avr_map_metric (f_ginv.map, MAP_NONFIXED_0_7) == 0)
13674     /* The mapping consists only of fixed points and can be folded
13675        to AND/OR logic in the remainder.  Reasonable cost is 3. */
13676     f_ginv.cost = 2 + (val_used_p && !val_const_p);
13677   else
13678     {
13679       rtx xop[4];
13680 
13681       /* Get the cost of the insn by calling the output worker with some
13682          fake values.  Mimic effect of reloading xop[3]: Unused operands
13683          are mapped to 0 and used operands are reloaded to xop[0].  */
13684 
13685       xop[0] = all_regs_rtx[24];
13686       xop[1] = gen_int_mode (f_ginv.map, SImode);
13687       xop[2] = all_regs_rtx[25];
13688       xop[3] = val_used_p ? xop[0] : const0_rtx;
13689 
13690       avr_out_insert_bits (xop, &f_ginv.cost);
13691 
13692       f_ginv.cost += val_const_p && val_used_p ? 1 : 0;
13693     }
13694 
13695   /* Step 2b:  Add cost of G  */
13696 
13697   f_ginv.cost += g->cost;
13698 
13699   if (avr_log.builtin)
13700     avr_edump (" %s%d=%d", g->str, g->arg, f_ginv.cost);
13701 
13702   return f_ginv;
13703 }
13704 
13705 
13706 /* Insert bits from XOP[1] into XOP[0] according to MAP.
13707    XOP[0] and XOP[1] don't overlap.
13708    If FIXP_P = true:  Move all bits according to MAP using BLD/BST sequences.
13709    If FIXP_P = false: Just move the bit if its position in the destination
13710    is different to its source position.  */
13711 
13712 static void
avr_move_bits(rtx * xop,unsigned int map,bool fixp_p,int * plen)13713 avr_move_bits (rtx *xop, unsigned int map, bool fixp_p, int *plen)
13714 {
13715   /* T-flag contains this bit of the source, i.e. of XOP[1]  */
13716   int t_bit_src = -1;
13717 
13718   /* We order the operations according to the requested source bit b.  */
13719 
13720   for (int b = 0; b < 8; b++)
13721     for (int bit_dest = 0; bit_dest < 8; bit_dest++)
13722       {
13723         int bit_src = avr_map (map, bit_dest);
13724 
13725         if (b != bit_src
13726             || bit_src >= 8
13727             /* Same position: No need to copy as requested by FIXP_P.  */
13728             || (bit_dest == bit_src && !fixp_p))
13729           continue;
13730 
13731         if (t_bit_src != bit_src)
13732           {
13733             /* Source bit is not yet in T: Store it to T.  */
13734 
13735             t_bit_src = bit_src;
13736 
13737             xop[3] = GEN_INT (bit_src);
13738             avr_asm_len ("bst %T1%T3", xop, plen, 1);
13739           }
13740 
13741         /* Load destination bit with T.  */
13742 
13743         xop[3] = GEN_INT (bit_dest);
13744         avr_asm_len ("bld %T0%T3", xop, plen, 1);
13745       }
13746 }
13747 
13748 
13749 /* PLEN == 0: Print assembler code for `insert_bits'.
13750    PLEN != 0: Compute code length in bytes.
13751 
13752    OP[0]:  Result
13753    OP[1]:  The mapping composed of nibbles. If nibble no. N is
13754            0:   Bit N of result is copied from bit OP[2].0
13755            ...  ...
13756            7:   Bit N of result is copied from bit OP[2].7
13757            0xf: Bit N of result is copied from bit OP[3].N
13758    OP[2]:  Bits to be inserted
13759    OP[3]:  Target value  */
13760 
13761 const char*
avr_out_insert_bits(rtx * op,int * plen)13762 avr_out_insert_bits (rtx *op, int *plen)
13763 {
13764   unsigned int map = UINTVAL (op[1]) & GET_MODE_MASK (SImode);
13765   unsigned mask_fixed;
13766   bool fixp_p = true;
13767   rtx xop[4];
13768 
13769   xop[0] = op[0];
13770   xop[1] = op[2];
13771   xop[2] = op[3];
13772 
13773   gcc_assert (REG_P (xop[2]) || CONST_INT_P (xop[2]));
13774 
13775   if (plen)
13776     *plen = 0;
13777   else if (flag_print_asm_name)
13778     fprintf (asm_out_file, ASM_COMMENT_START "map = 0x%08x\n", map);
13779 
13780   /* If MAP has fixed points it might be better to initialize the result
13781      with the bits to be inserted instead of moving all bits by hand.  */
13782 
13783   mask_fixed = avr_map_metric (map, MAP_MASK_FIXED_0_7);
13784 
13785   if (REGNO (xop[0]) == REGNO (xop[1]))
13786     {
13787       /* Avoid early-clobber conflicts */
13788 
13789       avr_asm_len ("mov __tmp_reg__,%1", xop, plen, 1);
13790       xop[1] = tmp_reg_rtx;
13791       fixp_p = false;
13792     }
13793 
13794   if (avr_map_metric (map, MAP_MASK_PREIMAGE_F))
13795     {
13796       /* XOP[2] is used and reloaded to XOP[0] already */
13797 
13798       int n_fix = 0, n_nofix = 0;
13799 
13800       gcc_assert (REG_P (xop[2]));
13801 
13802       /* Get the code size of the bit insertions; once with all bits
13803          moved and once with fixed points omitted.  */
13804 
13805       avr_move_bits (xop, map, true, &n_fix);
13806       avr_move_bits (xop, map, false, &n_nofix);
13807 
13808       if (fixp_p && n_fix - n_nofix > 3)
13809         {
13810           xop[3] = gen_int_mode (~mask_fixed, QImode);
13811 
13812           avr_asm_len ("eor %0,%1"   CR_TAB
13813                        "andi %0,%3"  CR_TAB
13814                        "eor %0,%1", xop, plen, 3);
13815           fixp_p = false;
13816         }
13817     }
13818   else
13819     {
13820       /* XOP[2] is unused */
13821 
13822       if (fixp_p && mask_fixed)
13823         {
13824           avr_asm_len ("mov %0,%1", xop, plen, 1);
13825           fixp_p = false;
13826         }
13827     }
13828 
13829   /* Move/insert remaining bits.  */
13830 
13831   avr_move_bits (xop, map, fixp_p, plen);
13832 
13833   return "";
13834 }
13835 
13836 
13837 /* IDs for all the AVR builtins.  */
13838 
13839 enum avr_builtin_id
13840   {
13841 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME)  \
13842     AVR_BUILTIN_ ## NAME,
13843 #include "builtins.def"
13844 #undef DEF_BUILTIN
13845 
13846     AVR_BUILTIN_COUNT
13847   };
13848 
13849 struct GTY(()) avr_builtin_description
13850 {
13851   enum insn_code icode;
13852   int n_args;
13853   tree fndecl;
13854 };
13855 
13856 
13857 /* Notice that avr_bdesc[] and avr_builtin_id are initialized in such a way
13858    that a built-in's ID can be used to access the built-in by means of
13859    avr_bdesc[ID]  */
13860 
13861 static GTY(()) struct avr_builtin_description
13862 avr_bdesc[AVR_BUILTIN_COUNT] =
13863   {
13864 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE, LIBNAME)         \
13865     { (enum insn_code) CODE_FOR_ ## ICODE, N_ARGS, NULL_TREE },
13866 #include "builtins.def"
13867 #undef DEF_BUILTIN
13868   };
13869 
13870 
13871 /* Implement `TARGET_BUILTIN_DECL'.  */
13872 
13873 static tree
avr_builtin_decl(unsigned id,bool initialize_p ATTRIBUTE_UNUSED)13874 avr_builtin_decl (unsigned id, bool initialize_p ATTRIBUTE_UNUSED)
13875 {
13876   if (id < AVR_BUILTIN_COUNT)
13877     return avr_bdesc[id].fndecl;
13878 
13879   return error_mark_node;
13880 }
13881 
13882 
13883 static void
avr_init_builtin_int24(void)13884 avr_init_builtin_int24 (void)
13885 {
13886   tree int24_type  = make_signed_type (GET_MODE_BITSIZE (PSImode));
13887   tree uint24_type = make_unsigned_type (GET_MODE_BITSIZE (PSImode));
13888 
13889   lang_hooks.types.register_builtin_type (int24_type, "__int24");
13890   lang_hooks.types.register_builtin_type (uint24_type, "__uint24");
13891 }
13892 
13893 
13894 /* Implement `TARGET_INIT_BUILTINS' */
13895 /* Set up all builtin functions for this target.  */
13896 
13897 static void
avr_init_builtins(void)13898 avr_init_builtins (void)
13899 {
13900   tree void_ftype_void
13901     = build_function_type_list (void_type_node, NULL_TREE);
13902   tree uchar_ftype_uchar
13903     = build_function_type_list (unsigned_char_type_node,
13904                                 unsigned_char_type_node,
13905                                 NULL_TREE);
13906   tree uint_ftype_uchar_uchar
13907     = build_function_type_list (unsigned_type_node,
13908                                 unsigned_char_type_node,
13909                                 unsigned_char_type_node,
13910                                 NULL_TREE);
13911   tree int_ftype_char_char
13912     = build_function_type_list (integer_type_node,
13913                                 char_type_node,
13914                                 char_type_node,
13915                                 NULL_TREE);
13916   tree int_ftype_char_uchar
13917     = build_function_type_list (integer_type_node,
13918                                 char_type_node,
13919                                 unsigned_char_type_node,
13920                                 NULL_TREE);
13921   tree void_ftype_ulong
13922     = build_function_type_list (void_type_node,
13923                                 long_unsigned_type_node,
13924                                 NULL_TREE);
13925 
13926   tree uchar_ftype_ulong_uchar_uchar
13927     = build_function_type_list (unsigned_char_type_node,
13928                                 long_unsigned_type_node,
13929                                 unsigned_char_type_node,
13930                                 unsigned_char_type_node,
13931                                 NULL_TREE);
13932 
13933   tree const_memx_void_node
13934     = build_qualified_type (void_type_node,
13935                             TYPE_QUAL_CONST
13936                             | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_MEMX));
13937 
13938   tree const_memx_ptr_type_node
13939     = build_pointer_type_for_mode (const_memx_void_node, PSImode, false);
13940 
13941   tree char_ftype_const_memx_ptr
13942     = build_function_type_list (char_type_node,
13943                                 const_memx_ptr_type_node,
13944                                 NULL);
13945 
13946 #define ITYP(T)                                                         \
13947   lang_hooks.types.type_for_size (TYPE_PRECISION (T), TYPE_UNSIGNED (T))
13948 
13949 #define FX_FTYPE_FX(fx)                                                 \
13950   tree fx##r_ftype_##fx##r                                              \
13951     = build_function_type_list (node_##fx##r, node_##fx##r, NULL);      \
13952   tree fx##k_ftype_##fx##k                                              \
13953     = build_function_type_list (node_##fx##k, node_##fx##k, NULL)
13954 
13955 #define FX_FTYPE_FX_INT(fx)                                             \
13956   tree fx##r_ftype_##fx##r_int                                          \
13957     = build_function_type_list (node_##fx##r, node_##fx##r,             \
13958                                 integer_type_node, NULL);               \
13959   tree fx##k_ftype_##fx##k_int                                          \
13960     = build_function_type_list (node_##fx##k, node_##fx##k,             \
13961                                 integer_type_node, NULL)
13962 
13963 #define INT_FTYPE_FX(fx)                                                \
13964   tree int_ftype_##fx##r                                                \
13965     = build_function_type_list (integer_type_node, node_##fx##r, NULL); \
13966   tree int_ftype_##fx##k                                                \
13967     = build_function_type_list (integer_type_node, node_##fx##k, NULL)
13968 
13969 #define INTX_FTYPE_FX(fx)                                               \
13970   tree int##fx##r_ftype_##fx##r                                         \
13971     = build_function_type_list (ITYP (node_##fx##r), node_##fx##r, NULL); \
13972   tree int##fx##k_ftype_##fx##k                                         \
13973     = build_function_type_list (ITYP (node_##fx##k), node_##fx##k, NULL)
13974 
13975 #define FX_FTYPE_INTX(fx)                                               \
13976   tree fx##r_ftype_int##fx##r                                           \
13977     = build_function_type_list (node_##fx##r, ITYP (node_##fx##r), NULL); \
13978   tree fx##k_ftype_int##fx##k                                           \
13979     = build_function_type_list (node_##fx##k, ITYP (node_##fx##k), NULL)
13980 
13981   tree node_hr = short_fract_type_node;
13982   tree node_nr = fract_type_node;
13983   tree node_lr = long_fract_type_node;
13984   tree node_llr = long_long_fract_type_node;
13985 
13986   tree node_uhr = unsigned_short_fract_type_node;
13987   tree node_unr = unsigned_fract_type_node;
13988   tree node_ulr = unsigned_long_fract_type_node;
13989   tree node_ullr = unsigned_long_long_fract_type_node;
13990 
13991   tree node_hk = short_accum_type_node;
13992   tree node_nk = accum_type_node;
13993   tree node_lk = long_accum_type_node;
13994   tree node_llk = long_long_accum_type_node;
13995 
13996   tree node_uhk = unsigned_short_accum_type_node;
13997   tree node_unk = unsigned_accum_type_node;
13998   tree node_ulk = unsigned_long_accum_type_node;
13999   tree node_ullk = unsigned_long_long_accum_type_node;
14000 
14001 
14002   /* For absfx builtins.  */
14003 
14004   FX_FTYPE_FX (h);
14005   FX_FTYPE_FX (n);
14006   FX_FTYPE_FX (l);
14007   FX_FTYPE_FX (ll);
14008 
14009   /* For roundfx builtins.  */
14010 
14011   FX_FTYPE_FX_INT (h);
14012   FX_FTYPE_FX_INT (n);
14013   FX_FTYPE_FX_INT (l);
14014   FX_FTYPE_FX_INT (ll);
14015 
14016   FX_FTYPE_FX_INT (uh);
14017   FX_FTYPE_FX_INT (un);
14018   FX_FTYPE_FX_INT (ul);
14019   FX_FTYPE_FX_INT (ull);
14020 
14021   /* For countlsfx builtins.  */
14022 
14023   INT_FTYPE_FX (h);
14024   INT_FTYPE_FX (n);
14025   INT_FTYPE_FX (l);
14026   INT_FTYPE_FX (ll);
14027 
14028   INT_FTYPE_FX (uh);
14029   INT_FTYPE_FX (un);
14030   INT_FTYPE_FX (ul);
14031   INT_FTYPE_FX (ull);
14032 
14033   /* For bitsfx builtins.  */
14034 
14035   INTX_FTYPE_FX (h);
14036   INTX_FTYPE_FX (n);
14037   INTX_FTYPE_FX (l);
14038   INTX_FTYPE_FX (ll);
14039 
14040   INTX_FTYPE_FX (uh);
14041   INTX_FTYPE_FX (un);
14042   INTX_FTYPE_FX (ul);
14043   INTX_FTYPE_FX (ull);
14044 
14045   /* For fxbits builtins.  */
14046 
14047   FX_FTYPE_INTX (h);
14048   FX_FTYPE_INTX (n);
14049   FX_FTYPE_INTX (l);
14050   FX_FTYPE_INTX (ll);
14051 
14052   FX_FTYPE_INTX (uh);
14053   FX_FTYPE_INTX (un);
14054   FX_FTYPE_INTX (ul);
14055   FX_FTYPE_INTX (ull);
14056 
14057 
14058 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME)                  \
14059   {                                                                     \
14060     int id = AVR_BUILTIN_ ## NAME;                                      \
14061     const char *Name = "__builtin_avr_" #NAME;                          \
14062     char *name = (char*) alloca (1 + strlen (Name));                    \
14063                                                                         \
14064     gcc_assert (id < AVR_BUILTIN_COUNT);                                \
14065     avr_bdesc[id].fndecl                                                \
14066       = add_builtin_function (avr_tolower (name, Name), TYPE, id,       \
14067                               BUILT_IN_MD, LIBNAME, NULL_TREE);         \
14068   }
14069 #include "builtins.def"
14070 #undef DEF_BUILTIN
14071 
14072   avr_init_builtin_int24 ();
14073 }
14074 
14075 
14076 /* Subroutine of avr_expand_builtin to expand vanilla builtins
14077    with non-void result and 1 ... 3 arguments.  */
14078 
14079 static rtx
avr_default_expand_builtin(enum insn_code icode,tree exp,rtx target)14080 avr_default_expand_builtin (enum insn_code icode, tree exp, rtx target)
14081 {
14082   rtx pat, xop[3];
14083   int n_args = call_expr_nargs (exp);
14084   machine_mode tmode = insn_data[icode].operand[0].mode;
14085 
14086   gcc_assert (n_args >= 1 && n_args <= 3);
14087 
14088   if (target == NULL_RTX
14089       || GET_MODE (target) != tmode
14090       || !insn_data[icode].operand[0].predicate (target, tmode))
14091     {
14092       target = gen_reg_rtx (tmode);
14093     }
14094 
14095   for (int n = 0; n < n_args; n++)
14096     {
14097       tree arg = CALL_EXPR_ARG (exp, n);
14098       rtx op = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14099       machine_mode opmode = GET_MODE (op);
14100       machine_mode mode = insn_data[icode].operand[n + 1].mode;
14101 
14102       if ((opmode == SImode || opmode == VOIDmode) && mode == HImode)
14103         {
14104           opmode = HImode;
14105           op = gen_lowpart (HImode, op);
14106         }
14107 
14108       /* In case the insn wants input operands in modes different from
14109          the result, abort.  */
14110 
14111       gcc_assert (opmode == mode || opmode == VOIDmode);
14112 
14113       if (!insn_data[icode].operand[n + 1].predicate (op, mode))
14114         op = copy_to_mode_reg (mode, op);
14115 
14116       xop[n] = op;
14117     }
14118 
14119   switch (n_args)
14120     {
14121     case 1: pat = GEN_FCN (icode) (target, xop[0]); break;
14122     case 2: pat = GEN_FCN (icode) (target, xop[0], xop[1]); break;
14123     case 3: pat = GEN_FCN (icode) (target, xop[0], xop[1], xop[2]); break;
14124 
14125     default:
14126       gcc_unreachable();
14127     }
14128 
14129   if (pat == NULL_RTX)
14130     return NULL_RTX;
14131 
14132   emit_insn (pat);
14133 
14134   return target;
14135 }
14136 
14137 
14138 /* Implement `TARGET_EXPAND_BUILTIN'.  */
14139 /* Expand an expression EXP that calls a built-in function,
14140    with result going to TARGET if that's convenient
14141    (and in mode MODE if that's convenient).
14142    SUBTARGET may be used as the target for computing one of EXP's operands.
14143    IGNORE is nonzero if the value is to be ignored.  */
14144 
14145 static rtx
avr_expand_builtin(tree exp,rtx target,rtx subtarget ATTRIBUTE_UNUSED,machine_mode mode ATTRIBUTE_UNUSED,int ignore)14146 avr_expand_builtin (tree exp, rtx target,
14147                     rtx subtarget ATTRIBUTE_UNUSED,
14148                     machine_mode mode ATTRIBUTE_UNUSED,
14149                     int ignore)
14150 {
14151   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
14152   const char *bname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
14153   unsigned int id = DECL_MD_FUNCTION_CODE (fndecl);
14154   const struct avr_builtin_description *d = &avr_bdesc[id];
14155   tree arg0;
14156   rtx op0;
14157 
14158   gcc_assert (id < AVR_BUILTIN_COUNT);
14159 
14160   switch (id)
14161     {
14162     case AVR_BUILTIN_NOP:
14163       emit_insn (gen_nopv (GEN_INT (1)));
14164       return 0;
14165 
14166     case AVR_BUILTIN_DELAY_CYCLES:
14167       {
14168         arg0 = CALL_EXPR_ARG (exp, 0);
14169         op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14170 
14171         if (!CONST_INT_P (op0))
14172           error ("%s expects a compile time integer constant", bname);
14173         else
14174           avr_expand_delay_cycles (op0);
14175 
14176         return NULL_RTX;
14177       }
14178 
14179     case AVR_BUILTIN_NOPS:
14180       {
14181         arg0 = CALL_EXPR_ARG (exp, 0);
14182         op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14183 
14184         if (!CONST_INT_P (op0))
14185           error ("%s expects a compile time integer constant", bname);
14186         else
14187           avr_expand_nops (op0);
14188 
14189         return NULL_RTX;
14190       }
14191 
14192     case AVR_BUILTIN_INSERT_BITS:
14193       {
14194         arg0 = CALL_EXPR_ARG (exp, 0);
14195         op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14196 
14197         if (!CONST_INT_P (op0))
14198           {
14199             error ("%s expects a compile time long integer constant"
14200                    " as first argument", bname);
14201             return target;
14202           }
14203 
14204         break;
14205       }
14206 
14207     case AVR_BUILTIN_ROUNDHR:   case AVR_BUILTIN_ROUNDUHR:
14208     case AVR_BUILTIN_ROUNDR:    case AVR_BUILTIN_ROUNDUR:
14209     case AVR_BUILTIN_ROUNDLR:   case AVR_BUILTIN_ROUNDULR:
14210     case AVR_BUILTIN_ROUNDLLR:  case AVR_BUILTIN_ROUNDULLR:
14211 
14212     case AVR_BUILTIN_ROUNDHK:   case AVR_BUILTIN_ROUNDUHK:
14213     case AVR_BUILTIN_ROUNDK:    case AVR_BUILTIN_ROUNDUK:
14214     case AVR_BUILTIN_ROUNDLK:   case AVR_BUILTIN_ROUNDULK:
14215     case AVR_BUILTIN_ROUNDLLK:  case AVR_BUILTIN_ROUNDULLK:
14216 
14217       /* Warn about odd rounding.  Rounding points >= FBIT will have
14218          no effect.  */
14219 
14220       if (TREE_CODE (CALL_EXPR_ARG (exp, 1)) != INTEGER_CST)
14221         break;
14222 
14223       int rbit = (int) TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1));
14224 
14225       if (rbit >= (int) GET_MODE_FBIT (mode))
14226         {
14227           warning (OPT_Wextra, "rounding to %d bits has no effect for "
14228                    "fixed-point value with %d fractional bits",
14229                    rbit, GET_MODE_FBIT (mode));
14230 
14231           return expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX, mode,
14232                               EXPAND_NORMAL);
14233         }
14234       else if (rbit <= - (int) GET_MODE_IBIT (mode))
14235         {
14236           warning (0, "rounding result will always be 0");
14237           return CONST0_RTX (mode);
14238         }
14239 
14240       /* The rounding points RP satisfies now:  -IBIT < RP < FBIT.
14241 
14242          TR 18037 only specifies results for  RP > 0.  However, the
14243          remaining cases of  -IBIT < RP <= 0  can easily be supported
14244          without any additional overhead.  */
14245 
14246       break; /* round */
14247     }
14248 
14249   /* No fold found and no insn:  Call support function from libgcc.  */
14250 
14251   if (d->icode == CODE_FOR_nothing
14252       && DECL_ASSEMBLER_NAME (get_callee_fndecl (exp)) != NULL_TREE)
14253     {
14254       return expand_call (exp, target, ignore);
14255     }
14256 
14257   /* No special treatment needed: vanilla expand.  */
14258 
14259   gcc_assert (d->icode != CODE_FOR_nothing);
14260   gcc_assert (d->n_args == call_expr_nargs (exp));
14261 
14262   if (d->n_args == 0)
14263     {
14264       emit_insn ((GEN_FCN (d->icode)) (target));
14265       return NULL_RTX;
14266     }
14267 
14268   return avr_default_expand_builtin (d->icode, exp, target);
14269 }
14270 
14271 
14272 /* Helper for `avr_fold_builtin' that folds  absfx (FIXED_CST).  */
14273 
14274 static tree
avr_fold_absfx(tree tval)14275 avr_fold_absfx (tree tval)
14276 {
14277   if (FIXED_CST != TREE_CODE (tval))
14278     return NULL_TREE;
14279 
14280   /* Our fixed-points have no padding:  Use double_int payload directly.  */
14281 
14282   FIXED_VALUE_TYPE fval = TREE_FIXED_CST (tval);
14283   unsigned int bits = GET_MODE_BITSIZE (fval.mode);
14284   double_int ival = fval.data.sext (bits);
14285 
14286   if (!ival.is_negative())
14287     return tval;
14288 
14289   /* ISO/IEC TR 18037, 7.18a.6.2:  The absfx functions are saturating.  */
14290 
14291   fval.data = (ival == double_int::min_value (bits, false).sext (bits))
14292     ? double_int::max_value (bits, false)
14293     : -ival;
14294 
14295   return build_fixed (TREE_TYPE (tval), fval);
14296 }
14297 
14298 
14299 /* Implement `TARGET_FOLD_BUILTIN'.  */
14300 
14301 static tree
avr_fold_builtin(tree fndecl,int n_args ATTRIBUTE_UNUSED,tree * arg,bool ignore ATTRIBUTE_UNUSED)14302 avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg,
14303                   bool ignore ATTRIBUTE_UNUSED)
14304 {
14305   unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
14306   tree val_type = TREE_TYPE (TREE_TYPE (fndecl));
14307 
14308   if (!optimize)
14309     return NULL_TREE;
14310 
14311   switch (fcode)
14312     {
14313     default:
14314       break;
14315 
14316     case AVR_BUILTIN_SWAP:
14317       {
14318         return fold_build2 (LROTATE_EXPR, val_type, arg[0],
14319                             build_int_cst (val_type, 4));
14320       }
14321 
14322     case AVR_BUILTIN_ABSHR:
14323     case AVR_BUILTIN_ABSR:
14324     case AVR_BUILTIN_ABSLR:
14325     case AVR_BUILTIN_ABSLLR:
14326 
14327     case AVR_BUILTIN_ABSHK:
14328     case AVR_BUILTIN_ABSK:
14329     case AVR_BUILTIN_ABSLK:
14330     case AVR_BUILTIN_ABSLLK:
14331       /* GCC is not good with folding ABS for fixed-point.  Do it by hand.  */
14332 
14333       return avr_fold_absfx (arg[0]);
14334 
14335     case AVR_BUILTIN_BITSHR:    case AVR_BUILTIN_HRBITS:
14336     case AVR_BUILTIN_BITSHK:    case AVR_BUILTIN_HKBITS:
14337     case AVR_BUILTIN_BITSUHR:   case AVR_BUILTIN_UHRBITS:
14338     case AVR_BUILTIN_BITSUHK:   case AVR_BUILTIN_UHKBITS:
14339 
14340     case AVR_BUILTIN_BITSR:     case AVR_BUILTIN_RBITS:
14341     case AVR_BUILTIN_BITSK:     case AVR_BUILTIN_KBITS:
14342     case AVR_BUILTIN_BITSUR:    case AVR_BUILTIN_URBITS:
14343     case AVR_BUILTIN_BITSUK:    case AVR_BUILTIN_UKBITS:
14344 
14345     case AVR_BUILTIN_BITSLR:    case AVR_BUILTIN_LRBITS:
14346     case AVR_BUILTIN_BITSLK:    case AVR_BUILTIN_LKBITS:
14347     case AVR_BUILTIN_BITSULR:   case AVR_BUILTIN_ULRBITS:
14348     case AVR_BUILTIN_BITSULK:   case AVR_BUILTIN_ULKBITS:
14349 
14350     case AVR_BUILTIN_BITSLLR:   case AVR_BUILTIN_LLRBITS:
14351     case AVR_BUILTIN_BITSLLK:   case AVR_BUILTIN_LLKBITS:
14352     case AVR_BUILTIN_BITSULLR:  case AVR_BUILTIN_ULLRBITS:
14353     case AVR_BUILTIN_BITSULLK:  case AVR_BUILTIN_ULLKBITS:
14354 
14355       gcc_assert (TYPE_PRECISION (val_type)
14356                   == TYPE_PRECISION (TREE_TYPE (arg[0])));
14357 
14358       return build1 (VIEW_CONVERT_EXPR, val_type, arg[0]);
14359 
14360     case AVR_BUILTIN_INSERT_BITS:
14361       {
14362         tree tbits = arg[1];
14363         tree tval = arg[2];
14364         tree tmap;
14365         tree map_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
14366         unsigned int map;
14367         bool changed = false;
14368         avr_map_op_t best_g;
14369 
14370         if (TREE_CODE (arg[0]) != INTEGER_CST)
14371           {
14372             /* No constant as first argument: Don't fold this and run into
14373                error in avr_expand_builtin.  */
14374 
14375             break;
14376           }
14377 
14378         tmap = wide_int_to_tree (map_type, wi::to_wide (arg[0]));
14379         map = TREE_INT_CST_LOW (tmap);
14380 
14381         if (TREE_CODE (tval) != INTEGER_CST
14382 	    && avr_map_metric (map, MAP_MASK_PREIMAGE_F) == 0)
14383           {
14384             /* There are no F in the map, i.e. 3rd operand is unused.
14385                Replace that argument with some constant to render
14386                respective input unused.  */
14387 
14388             tval = build_int_cst (val_type, 0);
14389             changed = true;
14390           }
14391 
14392         if (TREE_CODE (tbits) != INTEGER_CST
14393 	    && avr_map_metric (map, MAP_PREIMAGE_0_7) == 0)
14394           {
14395             /* Similar for the bits to be inserted. If they are unused,
14396                we can just as well pass 0.  */
14397 
14398             tbits = build_int_cst (val_type, 0);
14399           }
14400 
14401         if (TREE_CODE (tbits) == INTEGER_CST)
14402           {
14403             /* Inserting bits known at compile time is easy and can be
14404                performed by AND and OR with appropriate masks.  */
14405 
14406             int bits = TREE_INT_CST_LOW (tbits);
14407             int mask_ior = 0, mask_and = 0xff;
14408 
14409             for (size_t i = 0; i < 8; i++)
14410               {
14411                 int mi = avr_map (map, i);
14412 
14413                 if (mi < 8)
14414                   {
14415                     if (bits & (1 << mi))     mask_ior |=  (1 << i);
14416                     else                      mask_and &= ~(1 << i);
14417                   }
14418               }
14419 
14420             tval = fold_build2 (BIT_IOR_EXPR, val_type, tval,
14421                                 build_int_cst (val_type, mask_ior));
14422             return fold_build2 (BIT_AND_EXPR, val_type, tval,
14423                                 build_int_cst (val_type, mask_and));
14424           }
14425 
14426         if (changed)
14427           return build_call_expr (fndecl, 3, tmap, tbits, tval);
14428 
14429         /* If bits don't change their position we can use vanilla logic
14430            to merge the two arguments.  */
14431 
14432 	if (avr_map_metric (map, MAP_NONFIXED_0_7) == 0)
14433           {
14434             int mask_f = avr_map_metric (map, MAP_MASK_PREIMAGE_F);
14435             tree tres, tmask = build_int_cst (val_type, mask_f ^ 0xff);
14436 
14437             tres = fold_build2 (BIT_XOR_EXPR, val_type, tbits, tval);
14438             tres = fold_build2 (BIT_AND_EXPR, val_type, tres, tmask);
14439             return fold_build2 (BIT_XOR_EXPR, val_type, tres, tval);
14440           }
14441 
14442         /* Try to decomposing map to reduce overall cost.  */
14443 
14444         if (avr_log.builtin)
14445           avr_edump ("\n%?: %x\n%?: ROL cost: ", map);
14446 
14447         best_g = avr_map_op[0];
14448         best_g.cost = 1000;
14449 
14450         for (size_t i = 0; i < ARRAY_SIZE (avr_map_op); i++)
14451           {
14452             avr_map_op_t g
14453               = avr_map_decompose (map, avr_map_op + i,
14454                                    TREE_CODE (tval) == INTEGER_CST);
14455 
14456             if (g.cost >= 0 && g.cost < best_g.cost)
14457               best_g = g;
14458           }
14459 
14460         if (avr_log.builtin)
14461           avr_edump ("\n");
14462 
14463         if (best_g.arg == 0)
14464           /* No optimization found */
14465           break;
14466 
14467         /* Apply operation G to the 2nd argument.  */
14468 
14469         if (avr_log.builtin)
14470           avr_edump ("%?: using OP(%s%d, %x) cost %d\n",
14471                      best_g.str, best_g.arg, best_g.map, best_g.cost);
14472 
14473         /* Do right-shifts arithmetically: They copy the MSB instead of
14474            shifting in a non-usable value (0) as with logic right-shift.  */
14475 
14476         tbits = fold_convert (signed_char_type_node, tbits);
14477         tbits = fold_build2 (best_g.code, signed_char_type_node, tbits,
14478                              build_int_cst (val_type, best_g.arg));
14479         tbits = fold_convert (val_type, tbits);
14480 
14481         /* Use map o G^-1 instead of original map to undo the effect of G.  */
14482 
14483         tmap = wide_int_to_tree (map_type, best_g.map);
14484 
14485         return build_call_expr (fndecl, 3, tmap, tbits, tval);
14486       } /* AVR_BUILTIN_INSERT_BITS */
14487     }
14488 
14489   return NULL_TREE;
14490 }
14491 
14492 /* Prepend to CLOBBERS hard registers that are automatically clobbered
14493    for an asm. We do this for CC_REGNUM to maintain source compatibility
14494    with the original cc0-based compiler.  */
14495 
14496 static rtx_insn *
avr_md_asm_adjust(vec<rtx> &,vec<rtx> &,vec<machine_mode> &,vec<const char * > &,vec<rtx> & clobbers,HARD_REG_SET & clobbered_regs,location_t)14497 avr_md_asm_adjust (vec<rtx> &/*outputs*/, vec<rtx> &/*inputs*/,
14498                    vec<machine_mode> & /*input_modes*/,
14499                    vec<const char *> &/*constraints*/,
14500                    vec<rtx> &clobbers, HARD_REG_SET &clobbered_regs,
14501 		   location_t /*loc*/)
14502 {
14503   clobbers.safe_push (cc_reg_rtx);
14504   SET_HARD_REG_BIT (clobbered_regs, REG_CC);
14505   return NULL;
14506 }
14507 
14508 
14509 /* Worker function for `FLOAT_LIB_COMPARE_RETURNS_BOOL'.  */
14510 
14511 bool
avr_float_lib_compare_returns_bool(machine_mode mode,enum rtx_code)14512 avr_float_lib_compare_returns_bool (machine_mode mode, enum rtx_code)
14513 {
14514   if (mode == DFmode)
14515     {
14516 #if WITH_DOUBLE_COMPARISON == 2
14517       return true;
14518 #endif
14519     }
14520 
14521   // This is the GCC default and also what AVR-LibC implements.
14522   return false;
14523 }
14524 
14525 
14526 
14527 /* Initialize the GCC target structure.  */
14528 
14529 #undef  TARGET_ASM_ALIGNED_HI_OP
14530 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
14531 #undef  TARGET_ASM_ALIGNED_SI_OP
14532 #define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
14533 #undef  TARGET_ASM_UNALIGNED_HI_OP
14534 #define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
14535 #undef  TARGET_ASM_UNALIGNED_SI_OP
14536 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
14537 #undef  TARGET_ASM_INTEGER
14538 #define TARGET_ASM_INTEGER avr_assemble_integer
14539 #undef  TARGET_ASM_FILE_START
14540 #define TARGET_ASM_FILE_START avr_file_start
14541 #undef  TARGET_ASM_FILE_END
14542 #define TARGET_ASM_FILE_END avr_file_end
14543 
14544 #undef  TARGET_ASM_FUNCTION_END_PROLOGUE
14545 #define TARGET_ASM_FUNCTION_END_PROLOGUE avr_asm_function_end_prologue
14546 #undef  TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
14547 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE avr_asm_function_begin_epilogue
14548 
14549 #undef  TARGET_FUNCTION_VALUE
14550 #define TARGET_FUNCTION_VALUE avr_function_value
14551 #undef  TARGET_LIBCALL_VALUE
14552 #define TARGET_LIBCALL_VALUE avr_libcall_value
14553 #undef  TARGET_FUNCTION_VALUE_REGNO_P
14554 #define TARGET_FUNCTION_VALUE_REGNO_P avr_function_value_regno_p
14555 
14556 #undef  TARGET_ATTRIBUTE_TABLE
14557 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
14558 #undef  TARGET_INSERT_ATTRIBUTES
14559 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
14560 #undef  TARGET_SECTION_TYPE_FLAGS
14561 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
14562 
14563 #undef  TARGET_ASM_NAMED_SECTION
14564 #define TARGET_ASM_NAMED_SECTION avr_asm_named_section
14565 #undef  TARGET_ASM_INIT_SECTIONS
14566 #define TARGET_ASM_INIT_SECTIONS avr_asm_init_sections
14567 #undef  TARGET_ENCODE_SECTION_INFO
14568 #define TARGET_ENCODE_SECTION_INFO avr_encode_section_info
14569 #undef  TARGET_ASM_SELECT_SECTION
14570 #define TARGET_ASM_SELECT_SECTION avr_asm_select_section
14571 
14572 #undef  TARGET_ASM_FINAL_POSTSCAN_INSN
14573 #define TARGET_ASM_FINAL_POSTSCAN_INSN avr_asm_final_postscan_insn
14574 
14575 #undef  TARGET_REGISTER_MOVE_COST
14576 #define TARGET_REGISTER_MOVE_COST avr_register_move_cost
14577 #undef  TARGET_MEMORY_MOVE_COST
14578 #define TARGET_MEMORY_MOVE_COST avr_memory_move_cost
14579 #undef  TARGET_RTX_COSTS
14580 #define TARGET_RTX_COSTS avr_rtx_costs
14581 #undef  TARGET_ADDRESS_COST
14582 #define TARGET_ADDRESS_COST avr_address_cost
14583 #undef  TARGET_MACHINE_DEPENDENT_REORG
14584 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
14585 #undef  TARGET_FUNCTION_ARG
14586 #define TARGET_FUNCTION_ARG avr_function_arg
14587 #undef  TARGET_FUNCTION_ARG_ADVANCE
14588 #define TARGET_FUNCTION_ARG_ADVANCE avr_function_arg_advance
14589 
14590 #undef  TARGET_SET_CURRENT_FUNCTION
14591 #define TARGET_SET_CURRENT_FUNCTION avr_set_current_function
14592 
14593 #undef  TARGET_RETURN_IN_MEMORY
14594 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
14595 
14596 #undef  TARGET_STRICT_ARGUMENT_NAMING
14597 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
14598 
14599 #undef TARGET_CONDITIONAL_REGISTER_USAGE
14600 #define TARGET_CONDITIONAL_REGISTER_USAGE avr_conditional_register_usage
14601 
14602 #undef TARGET_HARD_REGNO_NREGS
14603 #define TARGET_HARD_REGNO_NREGS avr_hard_regno_nregs
14604 
14605 #undef  TARGET_HARD_REGNO_MODE_OK
14606 #define TARGET_HARD_REGNO_MODE_OK avr_hard_regno_mode_ok
14607 #undef  TARGET_HARD_REGNO_SCRATCH_OK
14608 #define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok
14609 #undef  TARGET_HARD_REGNO_CALL_PART_CLOBBERED
14610 #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
14611   avr_hard_regno_call_part_clobbered
14612 
14613 #undef  TARGET_CASE_VALUES_THRESHOLD
14614 #define TARGET_CASE_VALUES_THRESHOLD avr_case_values_threshold
14615 
14616 #undef  TARGET_FRAME_POINTER_REQUIRED
14617 #define TARGET_FRAME_POINTER_REQUIRED avr_frame_pointer_required_p
14618 #undef  TARGET_CAN_ELIMINATE
14619 #define TARGET_CAN_ELIMINATE avr_can_eliminate
14620 
14621 #undef  TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
14622 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS avr_allocate_stack_slots_for_args
14623 
14624 #undef TARGET_WARN_FUNC_RETURN
14625 #define TARGET_WARN_FUNC_RETURN avr_warn_func_return
14626 
14627 #undef  TARGET_CLASS_LIKELY_SPILLED_P
14628 #define TARGET_CLASS_LIKELY_SPILLED_P avr_class_likely_spilled_p
14629 
14630 #undef  TARGET_CLASS_MAX_NREGS
14631 #define TARGET_CLASS_MAX_NREGS avr_class_max_nregs
14632 
14633 #undef  TARGET_OPTION_OVERRIDE
14634 #define TARGET_OPTION_OVERRIDE avr_option_override
14635 
14636 #undef  TARGET_CANNOT_MODIFY_JUMPS_P
14637 #define TARGET_CANNOT_MODIFY_JUMPS_P avr_cannot_modify_jumps_p
14638 
14639 #undef  TARGET_FUNCTION_OK_FOR_SIBCALL
14640 #define TARGET_FUNCTION_OK_FOR_SIBCALL avr_function_ok_for_sibcall
14641 
14642 #undef  TARGET_INIT_BUILTINS
14643 #define TARGET_INIT_BUILTINS avr_init_builtins
14644 
14645 #undef  TARGET_BUILTIN_DECL
14646 #define TARGET_BUILTIN_DECL avr_builtin_decl
14647 
14648 #undef  TARGET_EXPAND_BUILTIN
14649 #define TARGET_EXPAND_BUILTIN avr_expand_builtin
14650 
14651 #undef  TARGET_FOLD_BUILTIN
14652 #define TARGET_FOLD_BUILTIN avr_fold_builtin
14653 
14654 #undef  TARGET_SCALAR_MODE_SUPPORTED_P
14655 #define TARGET_SCALAR_MODE_SUPPORTED_P avr_scalar_mode_supported_p
14656 
14657 #undef  TARGET_BUILD_BUILTIN_VA_LIST
14658 #define TARGET_BUILD_BUILTIN_VA_LIST avr_build_builtin_va_list
14659 
14660 #undef  TARGET_FIXED_POINT_SUPPORTED_P
14661 #define TARGET_FIXED_POINT_SUPPORTED_P hook_bool_void_true
14662 
14663 #undef  TARGET_CONVERT_TO_TYPE
14664 #define TARGET_CONVERT_TO_TYPE avr_convert_to_type
14665 
14666 #undef TARGET_LRA_P
14667 #define TARGET_LRA_P hook_bool_void_false
14668 
14669 #undef  TARGET_ADDR_SPACE_SUBSET_P
14670 #define TARGET_ADDR_SPACE_SUBSET_P avr_addr_space_subset_p
14671 
14672 #undef  TARGET_ADDR_SPACE_CONVERT
14673 #define TARGET_ADDR_SPACE_CONVERT avr_addr_space_convert
14674 
14675 #undef  TARGET_ADDR_SPACE_ADDRESS_MODE
14676 #define TARGET_ADDR_SPACE_ADDRESS_MODE avr_addr_space_address_mode
14677 
14678 #undef  TARGET_ADDR_SPACE_POINTER_MODE
14679 #define TARGET_ADDR_SPACE_POINTER_MODE avr_addr_space_pointer_mode
14680 
14681 #undef  TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
14682 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P  \
14683   avr_addr_space_legitimate_address_p
14684 
14685 #undef  TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
14686 #define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS avr_addr_space_legitimize_address
14687 
14688 #undef  TARGET_ADDR_SPACE_DIAGNOSE_USAGE
14689 #define TARGET_ADDR_SPACE_DIAGNOSE_USAGE avr_addr_space_diagnose_usage
14690 
14691 #undef  TARGET_MODE_DEPENDENT_ADDRESS_P
14692 #define TARGET_MODE_DEPENDENT_ADDRESS_P avr_mode_dependent_address_p
14693 
14694 #undef  TARGET_PRINT_OPERAND
14695 #define TARGET_PRINT_OPERAND avr_print_operand
14696 #undef  TARGET_PRINT_OPERAND_ADDRESS
14697 #define TARGET_PRINT_OPERAND_ADDRESS avr_print_operand_address
14698 #undef  TARGET_PRINT_OPERAND_PUNCT_VALID_P
14699 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P avr_print_operand_punct_valid_p
14700 
14701 #undef TARGET_USE_BY_PIECES_INFRASTRUCTURE_P
14702 #define TARGET_USE_BY_PIECES_INFRASTRUCTURE_P \
14703   avr_use_by_pieces_infrastructure_p
14704 
14705 #undef  TARGET_LEGITIMATE_COMBINED_INSN
14706 #define TARGET_LEGITIMATE_COMBINED_INSN avr_legitimate_combined_insn
14707 
14708 #undef  TARGET_STARTING_FRAME_OFFSET
14709 #define TARGET_STARTING_FRAME_OFFSET avr_starting_frame_offset
14710 
14711 #undef  TARGET_MD_ASM_ADJUST
14712 #define TARGET_MD_ASM_ADJUST avr_md_asm_adjust
14713 
14714 struct gcc_target targetm = TARGET_INITIALIZER;
14715 
14716 
14717 #include "gt-avr.h"
14718