1 /* Subroutines for insn-output.cc for ATMEL AVR micro controllers
2    Copyright (C) 1998-2022 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 
363 static const pass_data avr_pass_data_ifelse =
364 {
365   RTL_PASS,      // type
366   "",            // name (will be patched)
367   OPTGROUP_NONE, // optinfo_flags
368   TV_DF_SCAN,    // tv_id
369   0,             // properties_required
370   0,             // properties_provided
371   0,             // properties_destroyed
372   0,             // todo_flags_start
373   TODO_df_finish | TODO_df_verify // todo_flags_finish
374 };
375 
376 class avr_pass_ifelse : public rtl_opt_pass
377 {
378 public:
avr_pass_ifelse(gcc::context * ctxt,const char * name)379   avr_pass_ifelse (gcc::context *ctxt, const char *name)
380     : rtl_opt_pass (avr_pass_data_ifelse, ctxt)
381   {
382     this->name = name;
383   }
384 
385   void avr_rest_of_handle_ifelse (function*);
386 
gate(function *)387   virtual bool gate (function*) { return optimize > 0; }
388 
execute(function * func)389   virtual unsigned int execute (function *func)
390   {
391     avr_rest_of_handle_ifelse (func);
392 
393     return 0;
394   }
395 }; // avr_pass_ifelse
396 
397 } // anon namespace
398 
399 rtl_opt_pass*
make_avr_pass_recompute_notes(gcc::context * ctxt)400 make_avr_pass_recompute_notes (gcc::context *ctxt)
401 {
402   return new avr_pass_recompute_notes (ctxt, "avr-notes-free-cfg");
403 }
404 
405 rtl_opt_pass*
make_avr_pass_casesi(gcc::context * ctxt)406 make_avr_pass_casesi (gcc::context *ctxt)
407 {
408   return new avr_pass_casesi (ctxt, "avr-casesi");
409 }
410 
411 rtl_opt_pass*
make_avr_pass_ifelse(gcc::context * ctxt)412 make_avr_pass_ifelse (gcc::context *ctxt)
413 {
414   return new avr_pass_ifelse (ctxt, "avr-ifelse");
415 }
416 
417 
418 /* Make one parallel insn with all the patterns from insns i[0]..i[5].  */
419 
420 static rtx_insn*
avr_parallel_insn_from_insns(rtx_insn * i[5])421 avr_parallel_insn_from_insns (rtx_insn *i[5])
422 {
423   rtvec vec = gen_rtvec (5, PATTERN (i[0]), PATTERN (i[1]), PATTERN (i[2]),
424                          PATTERN (i[3]), PATTERN (i[4]));
425   start_sequence();
426   emit (gen_rtx_PARALLEL (VOIDmode, vec));
427   rtx_insn *insn = get_insns();
428   end_sequence();
429 
430   return insn;
431 }
432 
433 
434 /* Return true if we see an insn stream generated by casesi expander together
435    with an extension to SImode of the switch value.
436 
437    If this is the case, fill in the insns from casesi to INSNS[1..5] and
438    the SImode extension to INSNS[0].  Moreover, extract the operands of
439    pattern casesi_<mode>_sequence forged from the sequence to recog_data.  */
440 
441 static bool
avr_is_casesi_sequence(basic_block bb,rtx_insn * insn,rtx_insn * insns[5])442 avr_is_casesi_sequence (basic_block bb, rtx_insn *insn, rtx_insn *insns[5])
443 {
444   rtx set_4, set_0;
445 
446   /* A first and quick test for a casesi sequences.  As a side effect of
447      the test, harvest respective insns to INSNS[0..4].  */
448 
449   if (!(JUMP_P (insns[4] = insn)
450         // casesi is the only insn that comes up with UNSPEC_INDEX_JMP,
451         // hence the following test ensures that we are actually dealing
452         // with code from casesi.
453         && (set_4 = single_set (insns[4]))
454         && UNSPEC == GET_CODE (SET_SRC (set_4))
455         && UNSPEC_INDEX_JMP == XINT (SET_SRC (set_4), 1)
456 
457         && (insns[3] = prev_real_insn (insns[4]))
458         && (insns[2] = prev_real_insn (insns[3]))
459         && (insns[1] = prev_real_insn (insns[2]))
460 
461         // Insn prior to casesi.
462         && (insns[0] = prev_real_insn (insns[1]))
463         && (set_0 = single_set (insns[0]))
464         && extend_operator (SET_SRC (set_0), SImode)))
465     {
466       return false;
467     }
468 
469   if (dump_file)
470     {
471       fprintf (dump_file, ";; Sequence from casesi in "
472                "[bb %d]:\n\n", bb->index);
473       for (int i = 0; i < 5; i++)
474         print_rtl_single (dump_file, insns[i]);
475     }
476 
477   /* We have to deal with quite some operands.  Extracting them by hand
478      would be tedious, therefore wrap the insn patterns into a parallel,
479      run recog against it and then use insn extract to get the operands. */
480 
481   rtx_insn *xinsn = avr_parallel_insn_from_insns (insns);
482 
483   INSN_CODE (xinsn) = recog (PATTERN (xinsn), xinsn, NULL /* num_clobbers */);
484 
485   /* Failing to recognize means that someone changed the casesi expander or
486      that some passes prior to this one performed some unexpected changes.
487      Gracefully drop such situations instead of aborting.  */
488 
489   if (INSN_CODE (xinsn) < 0)
490     {
491       if (dump_file)
492         fprintf (dump_file, ";; Sequence not recognized, giving up.\n\n");
493 
494       return false;
495     }
496 
497   gcc_assert (CODE_FOR_casesi_qi_sequence == INSN_CODE (xinsn)
498               || CODE_FOR_casesi_hi_sequence == INSN_CODE (xinsn));
499 
500   extract_insn (xinsn);
501 
502   // Assert on the anatomy of xinsn's operands we are going to work with.
503 
504   gcc_assert (recog_data.n_operands == 11);
505   gcc_assert (recog_data.n_dups == 4);
506 
507   if (dump_file)
508     {
509       fprintf (dump_file, ";; Operands extracted:\n");
510       for (int i = 0; i < recog_data.n_operands; i++)
511         avr_fdump (dump_file, ";; $%d = %r\n", i, recog_data.operand[i]);
512       fprintf (dump_file, "\n");
513     }
514 
515   return true;
516 }
517 
518 
519 /* Perform some extra checks on operands of casesi_<mode>_sequence.
520    Not all operand dependencies can be described by means of predicates.
521    This function performs left over checks and should always return true.
522    Returning false means that someone changed the casesi expander but did
523    not adjust casesi_<mode>_sequence.  */
524 
525 bool
avr_casei_sequence_check_operands(rtx * xop)526 avr_casei_sequence_check_operands (rtx *xop)
527 {
528   rtx sub_5 = NULL_RTX;
529 
530   if (AVR_HAVE_EIJMP_EICALL
531       // The last clobber op of the tablejump.
532       && xop[8] == all_regs_rtx[24])
533     {
534       // $6 is: (subreg:SI ($5) 0)
535       sub_5 = xop[6];
536     }
537 
538   if (!AVR_HAVE_EIJMP_EICALL
539       // $6 is: (plus:HI (subreg:SI ($5) 0)
540       //                 (label_ref ($3)))
541       && PLUS == GET_CODE (xop[6])
542       && LABEL_REF == GET_CODE (XEXP (xop[6], 1))
543       && rtx_equal_p (xop[3], XEXP (XEXP (xop[6], 1), 0))
544       // The last clobber op of the tablejump.
545       && xop[8] == const0_rtx)
546     {
547       sub_5 = XEXP (xop[6], 0);
548     }
549 
550   if (sub_5
551       && SUBREG_P (sub_5)
552       && SUBREG_BYTE (sub_5) == 0
553       && rtx_equal_p (xop[5], SUBREG_REG (sub_5)))
554     return true;
555 
556   if (dump_file)
557     fprintf (dump_file, "\n;; Failed condition for casesi_<mode>_sequence\n\n");
558 
559   return false;
560 }
561 
562 
563 /* INSNS[1..4] is a sequence as generated by casesi and INSNS[0] is an
564    extension of an 8-bit or 16-bit integer to SImode.  XOP contains the
565    operands of INSNS as extracted by insn_extract from pattern
566    casesi_<mode>_sequence:
567 
568       $0: SImode reg switch value as result of $9.
569       $1: Negative of smallest index in switch.
570       $2: Number of entries in switch.
571       $3: Label to table.
572       $4: Label if out-of-bounds.
573       $5: $0 + $1.
574       $6: 3-byte PC: subreg:HI ($5) + label_ref ($3)
575           2-byte PC: subreg:HI ($5)
576       $7: HI reg index into table (Z or pseudo)
577       $8: R24 or const0_rtx (to be clobbered)
578       $9: Extension to SImode of an 8-bit or 16-bit integer register $10.
579       $10: QImode or HImode register input of $9.
580 
581    Try to optimize this sequence, i.e. use the original HImode / QImode
582    switch value instead of SImode.  */
583 
584 static void
avr_optimize_casesi(rtx_insn * insns[5],rtx * xop)585 avr_optimize_casesi (rtx_insn *insns[5], rtx *xop)
586 {
587   // Original mode of the switch value; this is QImode or HImode.
588   machine_mode mode = GET_MODE (xop[10]);
589 
590   // How the original switch value was extended to SImode; this is
591   // SIGN_EXTEND or ZERO_EXTEND.
592   enum rtx_code code = GET_CODE (xop[9]);
593 
594   // Lower index, upper index (plus one) and range of case calues.
595   HOST_WIDE_INT low_idx = -INTVAL (xop[1]);
596   HOST_WIDE_INT num_idx = INTVAL (xop[2]);
597   HOST_WIDE_INT hig_idx = low_idx + num_idx;
598 
599   // Maximum ranges of (un)signed QImode resp. HImode.
600   unsigned umax = QImode == mode ? 0xff : 0xffff;
601   int imax = QImode == mode ? 0x7f : 0x7fff;
602   int imin = -imax - 1;
603 
604   // Testing the case range and whether it fits into the range of the
605   // (un)signed mode.  This test should actually always pass because it
606   // makes no sense to have case values outside the mode range.  Notice
607   // that case labels which are unreachable because they are outside the
608   // mode of the switch value (e.g. "case -1" for uint8_t) have already
609   // been thrown away by the middle-end.
610 
611   if (SIGN_EXTEND == code
612       && low_idx >= imin
613       && hig_idx <= imax)
614     {
615       // ok
616     }
617   else if (ZERO_EXTEND == code
618            && low_idx >= 0
619            && (unsigned) hig_idx <= umax)
620     {
621       // ok
622     }
623   else
624     {
625       if (dump_file)
626         fprintf (dump_file, ";; Case ranges too big, giving up.\n\n");
627       return;
628     }
629 
630   // Do normalization of switch value $10 and out-of-bound check in its
631   // original mode instead of in SImode.  Use a newly created pseudo.
632   // This will replace insns[1..2].
633 
634   start_sequence();
635 
636   rtx_insn *seq1, *seq2, *last1, *last2;
637 
638   rtx reg = copy_to_mode_reg (mode, xop[10]);
639 
640   rtx (*gen_add)(rtx,rtx,rtx) = QImode == mode ? gen_addqi3 : gen_addhi3;
641   rtx (*gen_cbranch)(rtx,rtx,rtx,rtx)
642     = QImode == mode ? gen_cbranchqi4 : gen_cbranchhi4;
643 
644   emit_insn (gen_add (reg, reg, gen_int_mode (-low_idx, mode)));
645   rtx op0 = reg; rtx op1 = gen_int_mode (num_idx, mode);
646   rtx labelref = copy_rtx (xop[4]);
647   emit_jump_insn (gen_cbranch (gen_rtx_fmt_ee (GTU, VOIDmode, op0, op1),
648                                op0, op1,
649                                labelref));
650 
651   seq1 = get_insns();
652   last1 = get_last_insn();
653   end_sequence();
654 
655   emit_insn_after (seq1, insns[2]);
656 
657   // After the out-of-bounds test and corresponding branch, use a
658   // 16-bit index.  If QImode is used, extend it to HImode first.
659   // This will replace insns[4].
660 
661   start_sequence();
662 
663   if (QImode == mode)
664     reg = force_reg (HImode, gen_rtx_fmt_e (code, HImode, reg));
665 
666   rtx pat_4 = AVR_3_BYTE_PC
667     ? gen_movhi (xop[7], reg)
668     : gen_addhi3 (xop[7], reg, gen_rtx_LABEL_REF (VOIDmode, xop[3]));
669 
670   emit_insn (pat_4);
671 
672   seq2 = get_insns();
673   last2 = get_last_insn();
674   end_sequence();
675 
676   emit_insn_after (seq2, insns[3]);
677 
678   if (dump_file)
679     {
680       fprintf (dump_file, ";; New insns: ");
681 
682       for (rtx_insn *insn = seq1; ; insn = NEXT_INSN (insn))
683         {
684           fprintf (dump_file, "%d, ", INSN_UID (insn));
685           if (insn == last1)
686             break;
687         }
688       for (rtx_insn *insn = seq2; ; insn = NEXT_INSN (insn))
689         {
690           fprintf (dump_file, "%d%s", INSN_UID (insn),
691                    insn == last2 ? ".\n\n" : ", ");
692           if (insn == last2)
693             break;
694         }
695 
696       fprintf (dump_file, ";; Deleting insns: %d, %d, %d.\n\n",
697                INSN_UID (insns[1]), INSN_UID (insns[2]), INSN_UID (insns[3]));
698     }
699 
700   // Pseudodelete the SImode and subreg of SImode insns.  We don't care
701   // about the extension insns[0]: Its result is now unused and other
702   // passes will clean it up.
703 
704   SET_INSN_DELETED (insns[1]);
705   SET_INSN_DELETED (insns[2]);
706   SET_INSN_DELETED (insns[3]);
707 }
708 
709 
710 void
avr_rest_of_handle_casesi(function * func)711 avr_pass_casesi::avr_rest_of_handle_casesi (function *func)
712 {
713   basic_block bb;
714 
715   FOR_EACH_BB_FN (bb, func)
716     {
717       rtx_insn *insn, *insns[5];
718 
719       FOR_BB_INSNS (bb, insn)
720         {
721           if (avr_is_casesi_sequence (bb, insn, insns))
722             {
723               avr_optimize_casesi (insns, recog_data.operand);
724             }
725         }
726     }
727 }
728 
729 
730 /* A helper for the next method.  Suppose we have two conditional branches
731 
732       if (reg <cond1> xval1) goto label1;
733       if (reg <cond2> xval2) goto label2;
734 
735    If the second comparison is redundant and there is a code <cond> such
736    that the sequence can be performed as
737 
738       REG_CC = compare (reg, xval1);
739       if (REG_CC <cond1> 0)  goto label1;
740       if (REG_CC <cond> 0)   goto label2;
741 
742    then return <cond>.  Otherwise, return UNKNOWN.
743    xval1 and xval2 are CONST_INT, and mode is the scalar int mode in which
744    the comparison will be carried out.  reverse_cond1 can be set to reverse
745    condition cond1.  This is useful if the second comparison does not follow
746    the first one, but is located after label1 like in:
747 
748       if (reg <cond1> xval1) goto label1;
749       ...
750       label1:
751       if (reg <cond2> xval2) goto label2;  */
752 
753 static enum rtx_code
avr_redundant_compare(enum rtx_code cond1,rtx xval1,enum rtx_code cond2,rtx xval2,machine_mode mode,bool reverse_cond1)754 avr_redundant_compare (enum rtx_code cond1, rtx xval1,
755                            enum rtx_code cond2, rtx xval2,
756                            machine_mode mode, bool reverse_cond1)
757 {
758   HOST_WIDE_INT ival1 = INTVAL (xval1);
759   HOST_WIDE_INT ival2 = INTVAL (xval2);
760 
761   unsigned HOST_WIDE_INT mask = GET_MODE_MASK (mode);
762   unsigned HOST_WIDE_INT uval1 = mask & UINTVAL (xval1);
763   unsigned HOST_WIDE_INT uval2 = mask & UINTVAL (xval2);
764 
765   if (reverse_cond1)
766     cond1 = reverse_condition (cond1);
767 
768   if (cond1 == EQ)
769     {
770       ////////////////////////////////////////////////
771       // A sequence like
772       //    if (reg == val)  goto label1;
773       //    if (reg > val)   goto label2;
774       // can be re-written using the same, simple comparison like in:
775       //    REG_CC = compare (reg, val)
776       //    if (REG_CC == 0)  goto label1;
777       //    if (REG_CC >= 0)  goto label2;
778       if (ival1 == ival2
779             && (cond2 == GT || cond2 == GTU))
780           return avr_normalize_condition (cond2);
781 
782       // Similar, but the input sequence is like
783       //    if (reg == val)  goto label1;
784       //    if (reg >= val)  goto label2;
785       if (ival1 == ival2
786             && (cond2 == GE || cond2 == GEU))
787           return cond2;
788 
789       // Similar, but the input sequence is like
790       //    if (reg == val)      goto label1;
791       //    if (reg >= val + 1)  goto label2;
792       if ((cond2 == GE && ival2 == 1 + ival1)
793             || (cond2 == GEU && uval2 == 1 + uval1))
794           return cond2;
795 
796       // Similar, but the input sequence is like
797       //    if (reg == val)      goto label1;
798       //    if (reg >  val - 1)  goto label2;
799       if ((cond2 == GT && ival2 == ival1 - 1)
800             || (cond2 == GTU && uval2 == uval1 - 1))
801           return avr_normalize_condition (cond2);
802 
803       /////////////////////////////////////////////////////////
804       // A sequence like
805       //    if (reg == val)      goto label1;
806       //    if (reg < 1 + val)   goto label2;
807       // can be re-written as
808       //    REG_CC = compare (reg, val)
809       //    if (REG_CC == 0)  goto label1;
810       //    if (REG_CC < 0)   goto label2;
811       if ((cond2 == LT && ival2 == 1 + ival1)
812             || (cond2 == LTU && uval2 == 1 + uval1))
813           return cond2;
814 
815       // Similar, but with an input sequence like
816       //    if (reg == val)   goto label1;
817       //    if (reg <= val)   goto label2;
818       if (ival1 == ival2
819             && (cond2 == LE || cond2 == LEU))
820           return avr_normalize_condition (cond2);
821 
822       // Similar, but with an input sequence like
823       //    if (reg == val)  goto label1;
824       //    if (reg < val)   goto label2;
825       if (ival1 == ival2
826             && (cond2 == LT || cond2 == LTU))
827           return cond2;
828 
829       // Similar, but with an input sequence like
830       //    if (reg == val)      goto label1;
831       //    if (reg <= val - 1)  goto label2;
832       if ((cond2 == LE && ival2 == ival1 - 1)
833             || (cond2 == LEU && uval2 == uval1 - 1))
834           return avr_normalize_condition (cond2);
835 
836     } // cond1 == EQ
837 
838   return UNKNOWN;
839 }
840 
841 
842 /* If-else decision trees generated for switch / case may produce sequences
843    like
844 
845       SREG = compare (reg, val);
846             if (SREG == 0)  goto label1;
847       SREG = compare (reg, 1 + val);
848             if (SREG >= 0)  goto label2;
849 
850    which can be optimized to
851 
852       SREG = compare (reg, val);
853             if (SREG == 0)  goto label1;
854             if (SREG >= 0)  goto label2;
855 
856    The optimal place for such a pass would be directly after expand, but
857    it's not possible for a jump insn to target more than one code label.
858    Hence, run a mini pass right before split2 which introduces REG_CC.  */
859 
860 void
avr_rest_of_handle_ifelse(function *)861 avr_pass_ifelse::avr_rest_of_handle_ifelse (function*)
862 {
863   rtx_insn *next_insn;
864 
865   for (rtx_insn *insn = get_insns(); insn; insn = next_insn)
866     {
867       next_insn = next_nonnote_nondebug_insn (insn);
868 
869       if (! next_insn)
870           break;
871 
872       // Search for two cbranch insns.  The first one is a cbranch.
873       // Filter for "cbranch<mode>4_insn" with mode in QI, HI, PSI, SI.
874 
875       if (! JUMP_P (insn))
876           continue;
877 
878       int icode1 = recog_memoized (insn);
879 
880       if (icode1 != CODE_FOR_cbranchqi4_insn
881             && icode1 != CODE_FOR_cbranchhi4_insn
882             && icode1 != CODE_FOR_cbranchpsi4_insn
883             && icode1 != CODE_FOR_cbranchsi4_insn)
884           continue;
885 
886       rtx_jump_insn *insn1 = as_a<rtx_jump_insn *> (insn);
887       rtx_jump_insn *insn2 = nullptr;
888       bool follow_label1 = false;
889 
890       // Extract the operands of the first insn:
891       // $0 = comparison operator ($1, $2)
892       // $1 = reg
893       // $2 = reg or const_int
894       // $3 = code_label
895       // $4 = optional SCRATCH for HI, PSI, SI cases.
896 
897       const auto &op = recog_data.operand;
898 
899       extract_insn (insn1);
900       rtx xop1[5] = { op[0], op[1], op[2], op[3], op[4] };
901       int n_operands = recog_data.n_operands;
902 
903       // For now, we can optimize cbranches that follow an EQ cbranch,
904       // and cbranches that follow the label of a NE cbranch.
905 
906       if (GET_CODE (xop1[0]) == EQ
907             && JUMP_P (next_insn)
908             && recog_memoized (next_insn) == icode1)
909           {
910             // The 2nd cbranch insn follows insn1, i.e. is located in the
911             // fallthrough path of insn1.
912 
913             insn2 = as_a<rtx_jump_insn *> (next_insn);
914           }
915       else if (GET_CODE (xop1[0]) == NE)
916           {
917             // insn1 might branch to a label followed by a cbranch.
918 
919             rtx target1 = JUMP_LABEL (insn1);
920             rtx_insn *code_label1 = JUMP_LABEL_AS_INSN (insn1);
921             rtx_insn *next = next_nonnote_nondebug_insn (code_label1);
922             rtx_insn *barrier = prev_nonnote_nondebug_insn (code_label1);
923 
924             if (// Target label of insn1 is used exactly once and
925                 // is not a fallthru, i.e. is preceded by a barrier.
926                 LABEL_NUSES (target1) == 1
927                 && barrier
928                 && BARRIER_P (barrier)
929                 // Following the target label is a cbranch of the same kind.
930                 && next
931                 && JUMP_P (next)
932                 && recog_memoized (next) == icode1)
933               {
934                 follow_label1 = true;
935                 insn2 = as_a<rtx_jump_insn *> (next);
936               }
937           }
938 
939       if (! insn2)
940           continue;
941 
942       // Also extract operands of insn2, and filter for REG + CONST_INT
943       // comparsons against the same register.
944 
945       extract_insn (insn2);
946       rtx xop2[5] = { op[0], op[1], op[2], op[3], op[4] };
947 
948       if (! rtx_equal_p (xop1[1], xop2[1])
949             || ! CONST_INT_P (xop1[2])
950             || ! CONST_INT_P (xop2[2]))
951           continue;
952 
953       machine_mode mode = GET_MODE (xop1[1]);
954       enum rtx_code code1 = GET_CODE (xop1[0]);
955       enum rtx_code code2 = GET_CODE (xop2[0]);
956 
957       code2 = avr_redundant_compare (code1, xop1[2], code2, xop2[2],
958                                              mode, follow_label1);
959       if (code2 == UNKNOWN)
960           continue;
961 
962       //////////////////////////////////////////////////////
963       // Found a replacement.
964 
965       if (dump_file)
966           {
967             fprintf (dump_file, "\n;; Found chain of jump_insn %d and"
968                        " jump_insn %d, follow_label1=%d:\n",
969                        INSN_UID (insn1), INSN_UID (insn2), follow_label1);
970             print_rtl_single (dump_file, PATTERN (insn1));
971             print_rtl_single (dump_file, PATTERN (insn2));
972           }
973 
974       if (! follow_label1)
975           next_insn = next_nonnote_nondebug_insn (insn2);
976 
977       // Pop the new branch conditions and the new comparison.
978       // Prematurely split into compare + branch so that we can drop
979       // the 2nd comparison.  The following pass, split2, splits all
980       // insns for REG_CC, and it should still work as usual even when
981       // there are already some REG_CC insns around.
982 
983       rtx xcond1 = gen_rtx_fmt_ee (code1, VOIDmode, cc_reg_rtx, const0_rtx);
984       rtx xcond2 = gen_rtx_fmt_ee (code2, VOIDmode, cc_reg_rtx, const0_rtx);
985       rtx xpat1 = gen_branch (xop1[3], xcond1);
986       rtx xpat2 = gen_branch (xop2[3], xcond2);
987       rtx xcompare = NULL_RTX;
988 
989       if (mode == QImode)
990           {
991             gcc_assert (n_operands == 4);
992             xcompare = gen_cmpqi3 (xop1[1], xop1[2]);
993           }
994       else
995           {
996             gcc_assert (n_operands == 5);
997             rtx (*gen_cmp)(rtx,rtx,rtx)
998               = mode == HImode  ? gen_gen_comparehi
999               : mode == PSImode ? gen_gen_comparepsi
1000               : gen_gen_comparesi; // SImode
1001             xcompare = gen_cmp (xop1[1], xop1[2], xop1[4]);
1002           }
1003 
1004       // Emit that stuff.
1005 
1006       rtx_insn *cmp = emit_insn_before (xcompare, insn1);
1007       rtx_jump_insn *branch1 = emit_jump_insn_before (xpat1, insn1);
1008       rtx_jump_insn *branch2 = emit_jump_insn_before (xpat2, insn2);
1009 
1010       JUMP_LABEL (branch1) = xop1[3];
1011       JUMP_LABEL (branch2) = xop2[3];
1012       // delete_insn() decrements LABEL_NUSES when deleting a JUMP_INSN, but
1013       // when we pop a new JUMP_INSN, do it by hand.
1014       ++LABEL_NUSES (xop1[3]);
1015       ++LABEL_NUSES (xop2[3]);
1016 
1017       delete_insn (insn1);
1018       delete_insn (insn2);
1019 
1020       // As a side effect, also recog the new insns.
1021       gcc_assert (valid_insn_p (cmp));
1022       gcc_assert (valid_insn_p (branch1));
1023       gcc_assert (valid_insn_p (branch2));
1024     } // loop insns
1025 }
1026 
1027 
1028 /* Set `avr_arch' as specified by `-mmcu='.
1029    Return true on success.  */
1030 
1031 static bool
avr_set_core_architecture(void)1032 avr_set_core_architecture (void)
1033 {
1034   /* Search for mcu core architecture.  */
1035 
1036   if (!avr_mmcu)
1037     avr_mmcu = AVR_MMCU_DEFAULT;
1038 
1039   avr_arch = &avr_arch_types[0];
1040 
1041   for (const avr_mcu_t *mcu = avr_mcu_types; ; mcu++)
1042     {
1043       if (mcu->name == NULL)
1044         {
1045           /* Reached the end of `avr_mcu_types'.  This should actually never
1046              happen as options are provided by device-specs.  It could be a
1047              typo in a device-specs or calling the compiler proper directly
1048              with -mmcu=<device>. */
1049 
1050           error ("unknown core architecture %qs specified with %qs",
1051                  avr_mmcu, "-mmcu=");
1052           avr_inform_core_architectures ();
1053           break;
1054         }
1055       else if (strcmp (mcu->name, avr_mmcu) == 0
1056                // Is this a proper architecture ?
1057                  && mcu->macro == NULL)
1058         {
1059           avr_arch = &avr_arch_types[mcu->arch_id];
1060           if (avr_n_flash < 0)
1061             avr_n_flash = 1 + (mcu->flash_size - 1) / 0x10000;
1062 
1063           return true;
1064         }
1065     }
1066 
1067   return false;
1068 }
1069 
1070 
1071 /* Implement `TARGET_OPTION_OVERRIDE'.  */
1072 
1073 static void
avr_option_override(void)1074 avr_option_override (void)
1075 {
1076   /* caller-save.cc looks for call-clobbered hard registers that are assigned
1077      to pseudos that cross calls and tries so save-restore them around calls
1078      in order to reduce the number of stack slots needed.
1079 
1080      This might lead to situations where reload is no more able to cope
1081      with the challenge of AVR's very few address registers and fails to
1082      perform the requested spills.  */
1083 
1084   if (avr_strict_X)
1085     flag_caller_saves = 0;
1086 
1087   /* Unwind tables currently require a frame pointer for correctness,
1088      see toplev.cc:process_options().  */
1089 
1090   if ((flag_unwind_tables
1091        || flag_non_call_exceptions
1092        || flag_asynchronous_unwind_tables)
1093       && !ACCUMULATE_OUTGOING_ARGS)
1094     {
1095       flag_omit_frame_pointer = 0;
1096     }
1097 
1098   /* Disable flag_delete_null_pointer_checks if zero is a valid address. */
1099   if (targetm.addr_space.zero_address_valid (ADDR_SPACE_GENERIC))
1100     flag_delete_null_pointer_checks = 0;
1101 
1102   /* PR ipa/92606: Inter-procedural analysis optimizes data across
1103      address-spaces and PROGMEM.  As of v14, the PROGMEM part is
1104      still not fixed (and there is still no target hook as proposed
1105      in PR92932).  Just disable respective bogus optimization.  */
1106   flag_ipa_icf_variables = 0;
1107 
1108   if (flag_pic == 1)
1109     warning (OPT_fpic, "%<-fpic%> is not supported");
1110   if (flag_pic == 2)
1111     warning (OPT_fPIC, "%<-fPIC%> is not supported");
1112   if (flag_pie == 1)
1113     warning (OPT_fpie, "%<-fpie%> is not supported");
1114   if (flag_pie == 2)
1115     warning (OPT_fPIE, "%<-fPIE%> is not supported");
1116 
1117 #if !defined (HAVE_AS_AVR_MGCCISR_OPTION)
1118   avr_gasisr_prologues = 0;
1119 #endif
1120 
1121   if (!avr_set_core_architecture())
1122     return;
1123 
1124   /* Sould be set by avr-common.cc */
1125   gcc_assert (avr_long_double >= avr_double && avr_double >= 32);
1126 
1127   /* RAM addresses of some SFRs common to all devices in respective arch. */
1128 
1129   /* SREG: Status Register containing flags like I (global IRQ) */
1130   avr_addr.sreg = 0x3F + avr_arch->sfr_offset;
1131 
1132   /* RAMPZ: Address' high part when loading via ELPM */
1133   avr_addr.rampz = 0x3B + avr_arch->sfr_offset;
1134 
1135   avr_addr.rampy = 0x3A + avr_arch->sfr_offset;
1136   avr_addr.rampx = 0x39 + avr_arch->sfr_offset;
1137   avr_addr.rampd = 0x38 + avr_arch->sfr_offset;
1138   avr_addr.ccp = (AVR_TINY ? 0x3C : 0x34) + avr_arch->sfr_offset;
1139 
1140   /* SP: Stack Pointer (SP_H:SP_L) */
1141   avr_addr.sp_l = 0x3D + avr_arch->sfr_offset;
1142   avr_addr.sp_h = avr_addr.sp_l + 1;
1143 
1144   init_machine_status = avr_init_machine_status;
1145 
1146   avr_log_set_avr_log();
1147 }
1148 
1149 /* Function to set up the backend function structure.  */
1150 
1151 static struct machine_function *
avr_init_machine_status(void)1152 avr_init_machine_status (void)
1153 {
1154   return ggc_cleared_alloc<machine_function> ();
1155 }
1156 
1157 
1158 /* Implement `INIT_EXPANDERS'.  */
1159 /* The function works like a singleton.  */
1160 
1161 void
avr_init_expanders(void)1162 avr_init_expanders (void)
1163 {
1164   for (int regno = 0; regno < 32; regno ++)
1165     all_regs_rtx[regno] = gen_rtx_REG (QImode, regno);
1166 
1167   lpm_reg_rtx  = all_regs_rtx[LPM_REGNO];
1168   tmp_reg_rtx  = all_regs_rtx[AVR_TMP_REGNO];
1169   zero_reg_rtx = all_regs_rtx[AVR_ZERO_REGNO];
1170 
1171   cc_reg_rtx  = gen_rtx_REG (CCmode, REG_CC);
1172 
1173   lpm_addr_reg_rtx = gen_rtx_REG (HImode, REG_Z);
1174 
1175   sreg_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.sreg));
1176   rampd_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampd));
1177   rampx_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampx));
1178   rampy_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampy));
1179   rampz_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampz));
1180 
1181   xstring_empty = gen_rtx_CONST_STRING (VOIDmode, "");
1182   xstring_e = gen_rtx_CONST_STRING (VOIDmode, "e");
1183 
1184   /* TINY core does not have regs r10-r16, but avr-dimode.md expects them
1185      to be present */
1186   if (AVR_TINY)
1187     avr_have_dimode = false;
1188 }
1189 
1190 
1191 /* Implement `REGNO_REG_CLASS'.  */
1192 /* Return register class for register R.  */
1193 
1194 enum reg_class
avr_regno_reg_class(int r)1195 avr_regno_reg_class (int r)
1196 {
1197   static const enum reg_class reg_class_tab[] =
1198     {
1199       R0_REG,
1200       /* r1 - r15 */
1201       NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
1202       NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
1203       NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
1204       NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
1205       /* r16 - r23 */
1206       SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
1207       SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
1208       /* r24, r25 */
1209       ADDW_REGS, ADDW_REGS,
1210       /* X: r26, 27 */
1211       POINTER_X_REGS, POINTER_X_REGS,
1212       /* Y: r28, r29 */
1213       POINTER_Y_REGS, POINTER_Y_REGS,
1214       /* Z: r30, r31 */
1215       POINTER_Z_REGS, POINTER_Z_REGS,
1216       /* SP: SPL, SPH */
1217       STACK_REG, STACK_REG
1218     };
1219 
1220   if (r <= 33)
1221     return reg_class_tab[r];
1222 
1223   if (r == REG_CC)
1224     return CC_REG;
1225 
1226   return ALL_REGS;
1227 }
1228 
1229 
1230 /* Implement `TARGET_SCALAR_MODE_SUPPORTED_P'.  */
1231 
1232 static bool
avr_scalar_mode_supported_p(scalar_mode mode)1233 avr_scalar_mode_supported_p (scalar_mode mode)
1234 {
1235   if (ALL_FIXED_POINT_MODE_P (mode))
1236     return true;
1237 
1238   if (PSImode == mode)
1239     return true;
1240 
1241   return default_scalar_mode_supported_p (mode);
1242 }
1243 
1244 
1245 /* Return TRUE if DECL is a VAR_DECL located in flash and FALSE, otherwise.  */
1246 
1247 static bool
avr_decl_flash_p(tree decl)1248 avr_decl_flash_p (tree decl)
1249 {
1250   if (TREE_CODE (decl) != VAR_DECL
1251       || TREE_TYPE (decl) == error_mark_node)
1252     {
1253       return false;
1254     }
1255 
1256   return !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (decl)));
1257 }
1258 
1259 
1260 /* Return TRUE if DECL is a VAR_DECL located in the 24-bit flash
1261    address space and FALSE, otherwise.  */
1262 
1263 static bool
avr_decl_memx_p(tree decl)1264 avr_decl_memx_p (tree decl)
1265 {
1266   if (TREE_CODE (decl) != VAR_DECL
1267       || TREE_TYPE (decl) == error_mark_node)
1268     {
1269       return false;
1270     }
1271 
1272   return (ADDR_SPACE_MEMX == TYPE_ADDR_SPACE (TREE_TYPE (decl)));
1273 }
1274 
1275 
1276 /* Return TRUE if X is a MEM rtx located in flash and FALSE, otherwise.  */
1277 
1278 bool
avr_mem_flash_p(rtx x)1279 avr_mem_flash_p (rtx x)
1280 {
1281   return (MEM_P (x)
1282           && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x)));
1283 }
1284 
1285 
1286 /* Return TRUE if X is a MEM rtx located in the 24-bit flash
1287    address space and FALSE, otherwise.  */
1288 
1289 bool
avr_mem_memx_p(rtx x)1290 avr_mem_memx_p (rtx x)
1291 {
1292   return (MEM_P (x)
1293           && ADDR_SPACE_MEMX == MEM_ADDR_SPACE (x));
1294 }
1295 
1296 
1297 /* A helper for the subsequent function attribute used to dig for
1298    attribute 'name' in a FUNCTION_DECL or FUNCTION_TYPE */
1299 
1300 static inline int
avr_lookup_function_attribute1(const_tree func,const char * name)1301 avr_lookup_function_attribute1 (const_tree func, const char *name)
1302 {
1303   if (FUNCTION_DECL == TREE_CODE (func))
1304     {
1305       if (NULL_TREE != lookup_attribute (name, DECL_ATTRIBUTES (func)))
1306         {
1307           return true;
1308         }
1309 
1310       func = TREE_TYPE (func);
1311     }
1312 
1313   gcc_assert (TREE_CODE (func) == FUNCTION_TYPE
1314               || TREE_CODE (func) == METHOD_TYPE);
1315 
1316   return NULL_TREE != lookup_attribute (name, TYPE_ATTRIBUTES (func));
1317 }
1318 
1319 /* Return nonzero if FUNC is a naked function.  */
1320 
1321 static int
avr_naked_function_p(tree func)1322 avr_naked_function_p (tree func)
1323 {
1324   return avr_lookup_function_attribute1 (func, "naked");
1325 }
1326 
1327 /* Return nonzero if FUNC is an interrupt function as specified
1328    by the "interrupt" attribute.  */
1329 
1330 static int
avr_interrupt_function_p(tree func)1331 avr_interrupt_function_p (tree func)
1332 {
1333   return avr_lookup_function_attribute1 (func, "interrupt");
1334 }
1335 
1336 /* Return nonzero if FUNC is a signal function as specified
1337    by the "signal" attribute.  */
1338 
1339 static int
avr_signal_function_p(tree func)1340 avr_signal_function_p (tree func)
1341 {
1342   return avr_lookup_function_attribute1 (func, "signal");
1343 }
1344 
1345 /* Return nonzero if FUNC is an OS_task function.  */
1346 
1347 static int
avr_OS_task_function_p(tree func)1348 avr_OS_task_function_p (tree func)
1349 {
1350   return avr_lookup_function_attribute1 (func, "OS_task");
1351 }
1352 
1353 /* Return nonzero if FUNC is an OS_main function.  */
1354 
1355 static int
avr_OS_main_function_p(tree func)1356 avr_OS_main_function_p (tree func)
1357 {
1358   return avr_lookup_function_attribute1 (func, "OS_main");
1359 }
1360 
1361 
1362 /* Return nonzero if FUNC is a no_gccisr function as specified
1363    by the "no_gccisr" attribute.  */
1364 
1365 static int
avr_no_gccisr_function_p(tree func)1366 avr_no_gccisr_function_p (tree func)
1367 {
1368   return avr_lookup_function_attribute1 (func, "no_gccisr");
1369 }
1370 
1371 
1372 /* Implement `TARGET_CAN_INLINE_P'.  */
1373 /* Some options like -mgas_isr_prologues depend on optimization level,
1374    and the inliner might think that due to different options, inlining
1375    is not permitted; see PR104327.  */
1376 
1377 static bool
avr_can_inline_p(tree,tree)1378 avr_can_inline_p (tree /* caller */, tree /* callee */)
1379 {
1380   // No restrictions whatsoever.
1381   return true;
1382 }
1383 
1384 /* Implement `TARGET_SET_CURRENT_FUNCTION'.  */
1385 /* Sanity cheching for above function attributes.  */
1386 
1387 static void
avr_set_current_function(tree decl)1388 avr_set_current_function (tree decl)
1389 {
1390   if (decl == NULL_TREE
1391       || current_function_decl == NULL_TREE
1392       || current_function_decl == error_mark_node
1393       || ! cfun->machine
1394       || cfun->machine->attributes_checked_p)
1395     return;
1396 
1397   location_t loc = DECL_SOURCE_LOCATION (decl);
1398 
1399   cfun->machine->is_naked = avr_naked_function_p (decl);
1400   cfun->machine->is_signal = avr_signal_function_p (decl);
1401   cfun->machine->is_interrupt = avr_interrupt_function_p (decl);
1402   cfun->machine->is_OS_task = avr_OS_task_function_p (decl);
1403   cfun->machine->is_OS_main = avr_OS_main_function_p (decl);
1404   cfun->machine->is_no_gccisr = avr_no_gccisr_function_p (decl);
1405 
1406   const char *isr = cfun->machine->is_interrupt ? "interrupt" : "signal";
1407 
1408   /* Too much attributes make no sense as they request conflicting features. */
1409 
1410   if (cfun->machine->is_OS_task
1411       && (cfun->machine->is_signal || cfun->machine->is_interrupt))
1412     error_at (loc, "function attributes %qs and %qs are mutually exclusive",
1413               "OS_task", isr);
1414 
1415   if (cfun->machine->is_OS_main
1416       && (cfun->machine->is_signal || cfun->machine->is_interrupt))
1417     error_at (loc, "function attributes %qs and %qs are mutually exclusive",
1418               "OS_main", isr);
1419 
1420   if (cfun->machine->is_interrupt || cfun->machine->is_signal)
1421     {
1422       tree args = TYPE_ARG_TYPES (TREE_TYPE (decl));
1423       tree ret = TREE_TYPE (TREE_TYPE (decl));
1424       const char *name;
1425 
1426       name = DECL_ASSEMBLER_NAME_SET_P (decl)
1427         ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))
1428         : IDENTIFIER_POINTER (DECL_NAME (decl));
1429 
1430       /* Skip a leading '*' that might still prefix the assembler name,
1431          e.g. in non-LTO runs.  */
1432 
1433       name = default_strip_name_encoding (name);
1434 
1435       /* Interrupt handlers must be  void __vector (void)  functions.  */
1436 
1437       if (args && TREE_CODE (TREE_VALUE (args)) != VOID_TYPE)
1438         error_at (loc, "%qs function cannot have arguments", isr);
1439 
1440       if (TREE_CODE (ret) != VOID_TYPE)
1441         error_at (loc, "%qs function cannot return a value", isr);
1442 
1443 #if defined WITH_AVRLIBC
1444       /* Silently ignore 'signal' if 'interrupt' is present.  AVR-LibC startet
1445          using this when it switched from SIGNAL and INTERRUPT to ISR.  */
1446 
1447       if (cfun->machine->is_interrupt)
1448         cfun->machine->is_signal = 0;
1449 
1450       /* If the function has the 'signal' or 'interrupt' attribute, ensure
1451          that the name of the function is "__vector_NN" so as to catch
1452          when the user misspells the vector name.  */
1453 
1454       if (!startswith (name, "__vector"))
1455         warning_at (loc, OPT_Wmisspelled_isr, "%qs appears to be a misspelled "
1456                     "%qs handler, missing %<__vector%> prefix", name, isr);
1457 #endif // AVR-LibC naming conventions
1458     }
1459 
1460 #if defined WITH_AVRLIBC
1461   // Common problem is using "ISR" without first including avr/interrupt.h.
1462   const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
1463   name = default_strip_name_encoding (name);
1464   if (strcmp ("ISR", name) == 0
1465       || strcmp ("INTERRUPT", name) == 0
1466       || strcmp ("SIGNAL", name) == 0)
1467     {
1468       warning_at (loc, OPT_Wmisspelled_isr, "%qs is a reserved identifier"
1469                   " in AVR-LibC.  Consider %<#include <avr/interrupt.h>%>"
1470                   " before using the %qs macro", name, name);
1471     }
1472 #endif // AVR-LibC naming conventions
1473 
1474   /* Don't print the above diagnostics more than once.  */
1475 
1476   cfun->machine->attributes_checked_p = 1;
1477 }
1478 
1479 
1480 /* Implement `ACCUMULATE_OUTGOING_ARGS'.  */
1481 
1482 int
avr_accumulate_outgoing_args(void)1483 avr_accumulate_outgoing_args (void)
1484 {
1485   if (!cfun)
1486     return TARGET_ACCUMULATE_OUTGOING_ARGS;
1487 
1488   /* FIXME: For setjmp and in avr_builtin_setjmp_frame_value we don't know
1489         what offset is correct.  In some cases it is relative to
1490         virtual_outgoing_args_rtx and in others it is relative to
1491         virtual_stack_vars_rtx.  For example code see
1492             gcc.c-torture/execute/built-in-setjmp.c
1493             gcc.c-torture/execute/builtins/sprintf-chk.c   */
1494 
1495   return (TARGET_ACCUMULATE_OUTGOING_ARGS
1496           && !(cfun->calls_setjmp
1497                || cfun->has_nonlocal_label));
1498 }
1499 
1500 
1501 /* Report contribution of accumulated outgoing arguments to stack size.  */
1502 
1503 static inline int
avr_outgoing_args_size(void)1504 avr_outgoing_args_size (void)
1505 {
1506   return (ACCUMULATE_OUTGOING_ARGS
1507             ? (HOST_WIDE_INT) crtl->outgoing_args_size : 0);
1508 }
1509 
1510 
1511 /* Implement TARGET_STARTING_FRAME_OFFSET.  */
1512 /* This is the offset from the frame pointer register to the first stack slot
1513    that contains a variable living in the frame.  */
1514 
1515 static HOST_WIDE_INT
avr_starting_frame_offset(void)1516 avr_starting_frame_offset (void)
1517 {
1518   return 1 + avr_outgoing_args_size ();
1519 }
1520 
1521 
1522 /* Return the number of hard registers to push/pop in the prologue/epilogue
1523    of the current function, and optionally store these registers in SET.  */
1524 
1525 static int
avr_regs_to_save(HARD_REG_SET * set)1526 avr_regs_to_save (HARD_REG_SET *set)
1527 {
1528   int count;
1529   int int_or_sig_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1530 
1531   if (set)
1532     CLEAR_HARD_REG_SET (*set);
1533   count = 0;
1534 
1535   /* No need to save any registers if the function never returns or
1536      has the "OS_task" or "OS_main" attribute.  */
1537 
1538   if (TREE_THIS_VOLATILE (current_function_decl)
1539       || cfun->machine->is_OS_task
1540       || cfun->machine->is_OS_main)
1541     return 0;
1542 
1543   for (int reg = 0; reg < 32; reg++)
1544     {
1545       /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
1546          any global register variables.  */
1547 
1548       if (fixed_regs[reg])
1549         continue;
1550 
1551       if ((int_or_sig_p && !crtl->is_leaf && call_used_or_fixed_reg_p (reg))
1552           || (df_regs_ever_live_p (reg)
1553               && (int_or_sig_p || !call_used_or_fixed_reg_p (reg))
1554               /* Don't record frame pointer registers here.  They are treated
1555                  indivitually in prologue.  */
1556               && !(frame_pointer_needed
1557                    && (reg == REG_Y || reg == REG_Y + 1))))
1558         {
1559           if (set)
1560             SET_HARD_REG_BIT (*set, reg);
1561           count++;
1562         }
1563     }
1564   return count;
1565 }
1566 
1567 
1568 /* Implement `TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS' */
1569 
1570 static bool
avr_allocate_stack_slots_for_args(void)1571 avr_allocate_stack_slots_for_args (void)
1572 {
1573   return !cfun->machine->is_naked;
1574 }
1575 
1576 
1577 /* Return true if register FROM can be eliminated via register TO.  */
1578 
1579 static bool
avr_can_eliminate(const int from ATTRIBUTE_UNUSED,const int to)1580 avr_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
1581 {
1582   return ((frame_pointer_needed && to == FRAME_POINTER_REGNUM)
1583           || !frame_pointer_needed);
1584 }
1585 
1586 
1587 /* Implement `TARGET_WARN_FUNC_RETURN'.  */
1588 
1589 static bool
avr_warn_func_return(tree decl)1590 avr_warn_func_return (tree decl)
1591 {
1592   /* Naked functions are implemented entirely in assembly, including the
1593      return sequence, so suppress warnings about this.  */
1594 
1595   return !avr_naked_function_p (decl);
1596 }
1597 
1598 /* Compute offset between arg_pointer and frame_pointer.  */
1599 
1600 int
avr_initial_elimination_offset(int from,int to)1601 avr_initial_elimination_offset (int from, int to)
1602 {
1603   if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
1604     return 0;
1605   else
1606     {
1607       int offset = frame_pointer_needed ? 2 : 0;
1608       int avr_pc_size = AVR_HAVE_EIJMP_EICALL ? 3 : 2;
1609 
1610       // If FROM is ARG_POINTER_REGNUM, we are not in an ISR as ISRs
1611       // might not have arguments.  Hence the following is not affected
1612       // by gasisr prologues.
1613       offset += avr_regs_to_save (NULL);
1614       return (get_frame_size () + avr_outgoing_args_size()
1615               + avr_pc_size + 1 + offset);
1616     }
1617 }
1618 
1619 
1620 /* Helper for the function below.  */
1621 
1622 static void
avr_adjust_type_node(tree * node,machine_mode mode,int sat_p)1623 avr_adjust_type_node (tree *node, machine_mode mode, int sat_p)
1624 {
1625   *node = make_node (FIXED_POINT_TYPE);
1626   TYPE_SATURATING (*node) = sat_p;
1627   TYPE_UNSIGNED (*node) = UNSIGNED_FIXED_POINT_MODE_P (mode);
1628   TYPE_IBIT (*node) = GET_MODE_IBIT (mode);
1629   TYPE_FBIT (*node) = GET_MODE_FBIT (mode);
1630   TYPE_PRECISION (*node) = GET_MODE_BITSIZE (mode);
1631   SET_TYPE_ALIGN (*node, 8);
1632   SET_TYPE_MODE (*node, mode);
1633 
1634   layout_type (*node);
1635 }
1636 
1637 
1638 /* Implement `TARGET_BUILD_BUILTIN_VA_LIST'.  */
1639 
1640 static tree
avr_build_builtin_va_list(void)1641 avr_build_builtin_va_list (void)
1642 {
1643   /* avr-modes.def adjusts [U]TA to be 64-bit modes with 48 fractional bits.
1644      This is more appropriate for the 8-bit machine AVR than 128-bit modes.
1645      The ADJUST_IBIT/FBIT are handled in toplev:init_adjust_machine_modes()
1646      which is auto-generated by genmodes, but the compiler assigns [U]DAmode
1647      to the long long accum modes instead of the desired [U]TAmode.
1648 
1649      Fix this now, right after node setup in tree.cc:build_common_tree_nodes().
1650      This must run before c-cppbuiltin.cc:builtin_define_fixed_point_constants()
1651      which built-in defines macros like __ULLACCUM_FBIT__ that are used by
1652      libgcc to detect IBIT and FBIT.  */
1653 
1654   avr_adjust_type_node (&ta_type_node, TAmode, 0);
1655   avr_adjust_type_node (&uta_type_node, UTAmode, 0);
1656   avr_adjust_type_node (&sat_ta_type_node, TAmode, 1);
1657   avr_adjust_type_node (&sat_uta_type_node, UTAmode, 1);
1658 
1659   unsigned_long_long_accum_type_node = uta_type_node;
1660   long_long_accum_type_node = ta_type_node;
1661   sat_unsigned_long_long_accum_type_node = sat_uta_type_node;
1662   sat_long_long_accum_type_node = sat_ta_type_node;
1663 
1664   /* Dispatch to the default handler.  */
1665 
1666   return std_build_builtin_va_list ();
1667 }
1668 
1669 
1670 /* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3-byte PC).
1671    This is return address of function.  */
1672 
1673 rtx
avr_return_addr_rtx(int count,rtx tem)1674 avr_return_addr_rtx (int count, rtx tem)
1675 {
1676   rtx r;
1677 
1678   /* Can only return this function's return address. Others not supported.  */
1679   if (count)
1680     return NULL;
1681 
1682   if (AVR_3_BYTE_PC)
1683     {
1684       r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+2");
1685       warning (0, "%<builtin_return_address%> contains only 2 bytes"
1686                " of address");
1687     }
1688   else
1689     r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+1");
1690 
1691   cfun->machine->use_L__stack_usage = 1;
1692 
1693   r = gen_rtx_PLUS (Pmode, tem, r);
1694   r = gen_frame_mem (Pmode, memory_address (Pmode, r));
1695   r = gen_rtx_ROTATE (HImode, r, GEN_INT (8));
1696   return r;
1697 }
1698 
1699 /* Return 1 if the function epilogue is just a single "ret".  */
1700 
1701 int
avr_simple_epilogue(void)1702 avr_simple_epilogue (void)
1703 {
1704   return (! frame_pointer_needed
1705           && get_frame_size () == 0
1706           && avr_outgoing_args_size() == 0
1707           && avr_regs_to_save (NULL) == 0
1708           && ! cfun->machine->is_interrupt
1709           && ! cfun->machine->is_signal
1710           && ! cfun->machine->is_naked
1711           && ! TREE_THIS_VOLATILE (current_function_decl));
1712 }
1713 
1714 /* This function checks sequence of live registers.  */
1715 
1716 static int
sequent_regs_live(void)1717 sequent_regs_live (void)
1718 {
1719   int live_seq = 0;
1720   int cur_seq = 0;
1721 
1722   for (int reg = 0; reg <= LAST_CALLEE_SAVED_REG; ++reg)
1723     {
1724       if (fixed_regs[reg])
1725         {
1726           /* Don't recognize sequences that contain global register
1727              variables.  */
1728 
1729           if (live_seq != 0)
1730             return 0;
1731           else
1732             continue;
1733         }
1734 
1735       if (!call_used_or_fixed_reg_p (reg))
1736         {
1737           if (df_regs_ever_live_p (reg))
1738             {
1739               ++live_seq;
1740               ++cur_seq;
1741             }
1742           else
1743             cur_seq = 0;
1744         }
1745     }
1746 
1747   if (!frame_pointer_needed)
1748     {
1749       if (df_regs_ever_live_p (REG_Y))
1750         {
1751           ++live_seq;
1752           ++cur_seq;
1753         }
1754       else
1755         cur_seq = 0;
1756 
1757       if (df_regs_ever_live_p (REG_Y + 1))
1758         {
1759           ++live_seq;
1760           ++cur_seq;
1761         }
1762       else
1763         cur_seq = 0;
1764     }
1765   else
1766     {
1767       cur_seq += 2;
1768       live_seq += 2;
1769     }
1770   return (cur_seq == live_seq) ? live_seq : 0;
1771 }
1772 
1773 namespace {
1774 static const pass_data avr_pass_data_pre_proep =
1775 {
1776   RTL_PASS,      // type
1777   "",            // name (will be patched)
1778   OPTGROUP_NONE, // optinfo_flags
1779   TV_DF_SCAN,    // tv_id
1780   0,             // properties_required
1781   0,             // properties_provided
1782   0,             // properties_destroyed
1783   0,             // todo_flags_start
1784   0              // todo_flags_finish
1785 };
1786 
1787 
1788 class avr_pass_pre_proep : public rtl_opt_pass
1789 {
1790 public:
avr_pass_pre_proep(gcc::context * ctxt,const char * name)1791   avr_pass_pre_proep (gcc::context *ctxt, const char *name)
1792     : rtl_opt_pass (avr_pass_data_pre_proep, ctxt)
1793   {
1794     this->name = name;
1795   }
1796 
1797   void compute_maybe_gasisr (function*);
1798 
execute(function * fun)1799   virtual unsigned int execute (function *fun)
1800   {
1801     if (avr_gasisr_prologues
1802         // Whether this function is an ISR worth scanning at all.
1803         && !fun->machine->is_no_gccisr
1804         && (fun->machine->is_interrupt
1805             || fun->machine->is_signal)
1806         && !cfun->machine->is_naked
1807         // Paranoia: Non-local gotos and labels that might escape.
1808         && !cfun->calls_setjmp
1809         && !cfun->has_nonlocal_label
1810         && !cfun->has_forced_label_in_static)
1811       {
1812         compute_maybe_gasisr (fun);
1813       }
1814 
1815     return 0;
1816   }
1817 
1818 }; // avr_pass_pre_proep
1819 
1820 } // anon namespace
1821 
1822 rtl_opt_pass*
make_avr_pass_pre_proep(gcc::context * ctxt)1823 make_avr_pass_pre_proep (gcc::context *ctxt)
1824 {
1825   return new avr_pass_pre_proep (ctxt, "avr-pre-proep");
1826 }
1827 
1828 
1829 /* Set fun->machine->gasisr.maybe provided we don't find anything that
1830    prohibits GAS generating parts of ISR prologues / epilogues for us.  */
1831 
1832 void
compute_maybe_gasisr(function * fun)1833 avr_pass_pre_proep::compute_maybe_gasisr (function *fun)
1834 {
1835   // Don't use BB iterators so that we see JUMP_TABLE_DATA.
1836 
1837   for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
1838     {
1839       // Transparent calls always use [R]CALL and are filtered out by GAS.
1840       // ISRs don't use -mcall-prologues, hence what remains to be filtered
1841       // out are open coded (tail) calls.
1842 
1843       if (CALL_P (insn))
1844         return;
1845 
1846       // __tablejump2__ clobbers something and is targeted by JMP so
1847       // that GAS won't see its usage.
1848 
1849       if (AVR_HAVE_JMP_CALL
1850           && JUMP_TABLE_DATA_P (insn))
1851         return;
1852 
1853       // Non-local gotos not seen in *FUN.
1854 
1855       if (JUMP_P (insn)
1856           && find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
1857         return;
1858     }
1859 
1860   fun->machine->gasisr.maybe = 1;
1861 }
1862 
1863 
1864 /* Obtain the length sequence of insns.  */
1865 
1866 int
get_sequence_length(rtx_insn * insns)1867 get_sequence_length (rtx_insn *insns)
1868 {
1869   int length = 0;
1870 
1871   for (rtx_insn *insn = insns; insn; insn = NEXT_INSN (insn))
1872     length += get_attr_length (insn);
1873 
1874   return length;
1875 }
1876 
1877 
1878 /*  Implement `INCOMING_RETURN_ADDR_RTX'.  */
1879 
1880 rtx
avr_incoming_return_addr_rtx(void)1881 avr_incoming_return_addr_rtx (void)
1882 {
1883   /* The return address is at the top of the stack.  Note that the push
1884      was via post-decrement, which means the actual address is off by one.  */
1885   return gen_frame_mem (HImode, plus_constant (Pmode, stack_pointer_rtx, 1));
1886 }
1887 
1888 
1889 /* Unset a bit in *SET.  If successful, return the respective bit number.
1890    Otherwise, return -1 and *SET is unaltered.  */
1891 
1892 static int
avr_hregs_split_reg(HARD_REG_SET * set)1893 avr_hregs_split_reg (HARD_REG_SET *set)
1894 {
1895   for (int regno = 0; regno < 32; regno++)
1896     if (TEST_HARD_REG_BIT (*set, regno))
1897       {
1898         // Don't remove a register from *SET which might indicate that
1899         // some RAMP* register might need ISR prologue / epilogue treatment.
1900 
1901         if (AVR_HAVE_RAMPX
1902             && (REG_X == regno || REG_X + 1 == regno)
1903             && TEST_HARD_REG_BIT (*set, REG_X)
1904             && TEST_HARD_REG_BIT (*set, REG_X + 1))
1905           continue;
1906 
1907         if (AVR_HAVE_RAMPY
1908             && !frame_pointer_needed
1909             && (REG_Y == regno || REG_Y + 1 == regno)
1910             && TEST_HARD_REG_BIT (*set, REG_Y)
1911             && TEST_HARD_REG_BIT (*set, REG_Y + 1))
1912           continue;
1913 
1914         if (AVR_HAVE_RAMPZ
1915             && (REG_Z == regno || REG_Z + 1 == regno)
1916             && TEST_HARD_REG_BIT (*set, REG_Z)
1917             && TEST_HARD_REG_BIT (*set, REG_Z + 1))
1918           continue;
1919 
1920         CLEAR_HARD_REG_BIT (*set, regno);
1921         return regno;
1922       }
1923 
1924   return -1;
1925 }
1926 
1927 
1928 /*  Helper for expand_prologue.  Emit a push of a byte register.  */
1929 
1930 static void
emit_push_byte(unsigned regno,bool frame_related_p)1931 emit_push_byte (unsigned regno, bool frame_related_p)
1932 {
1933   rtx mem, reg;
1934   rtx_insn *insn;
1935 
1936   mem = gen_rtx_POST_DEC (HImode, stack_pointer_rtx);
1937   mem = gen_frame_mem (QImode, mem);
1938   reg = gen_rtx_REG (QImode, regno);
1939 
1940   insn = emit_insn (gen_rtx_SET (mem, reg));
1941   if (frame_related_p)
1942     RTX_FRAME_RELATED_P (insn) = 1;
1943 
1944   cfun->machine->stack_usage++;
1945 }
1946 
1947 
1948 /*  Helper for expand_prologue.  Emit a push of a SFR via register TREG.
1949     SFR is a MEM representing the memory location of the SFR.
1950     If CLR_P then clear the SFR after the push using zero_reg.  */
1951 
1952 static void
emit_push_sfr(rtx sfr,bool frame_related_p,bool clr_p,int treg)1953 emit_push_sfr (rtx sfr, bool frame_related_p, bool clr_p, int treg)
1954 {
1955   rtx_insn *insn;
1956 
1957   gcc_assert (MEM_P (sfr));
1958 
1959   /* IN treg, IO(SFR) */
1960   insn = emit_move_insn (all_regs_rtx[treg], sfr);
1961   if (frame_related_p)
1962     RTX_FRAME_RELATED_P (insn) = 1;
1963 
1964   /* PUSH treg */
1965   emit_push_byte (treg, frame_related_p);
1966 
1967   if (clr_p)
1968     {
1969       /* OUT IO(SFR), __zero_reg__ */
1970       insn = emit_move_insn (sfr, const0_rtx);
1971       if (frame_related_p)
1972         RTX_FRAME_RELATED_P (insn) = 1;
1973     }
1974 }
1975 
1976 static void
avr_prologue_setup_frame(HOST_WIDE_INT size,HARD_REG_SET set)1977 avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
1978 {
1979   rtx_insn *insn;
1980   bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1981   int live_seq = sequent_regs_live ();
1982 
1983   HOST_WIDE_INT size_max
1984     = (HOST_WIDE_INT) GET_MODE_MASK (AVR_HAVE_8BIT_SP ? QImode : Pmode);
1985 
1986   bool minimize = (TARGET_CALL_PROLOGUES
1987                    && size < size_max
1988                    && live_seq
1989                    && !isr_p
1990                    && !cfun->machine->is_OS_task
1991                    && !cfun->machine->is_OS_main
1992                    && !AVR_TINY);
1993 
1994   if (minimize
1995       && (frame_pointer_needed
1996           || avr_outgoing_args_size() > 8
1997           || (AVR_2_BYTE_PC && live_seq > 6)
1998           || live_seq > 7))
1999     {
2000       rtx pattern;
2001       int first_reg, reg, offset;
2002 
2003       emit_move_insn (gen_rtx_REG (HImode, REG_X),
2004                       gen_int_mode (size, HImode));
2005 
2006       pattern = gen_call_prologue_saves (gen_int_mode (live_seq, HImode),
2007                                          gen_int_mode (live_seq+size, HImode));
2008       insn = emit_insn (pattern);
2009       RTX_FRAME_RELATED_P (insn) = 1;
2010 
2011       /* Describe the effect of the unspec_volatile call to prologue_saves.
2012          Note that this formulation assumes that add_reg_note pushes the
2013          notes to the front.  Thus we build them in the reverse order of
2014          how we want dwarf2out to process them.  */
2015 
2016       /* The function does always set frame_pointer_rtx, but whether that
2017          is going to be permanent in the function is frame_pointer_needed.  */
2018 
2019       add_reg_note (insn, REG_CFA_ADJUST_CFA,
2020                     gen_rtx_SET ((frame_pointer_needed
2021                                           ? frame_pointer_rtx
2022                                           : stack_pointer_rtx),
2023                                  plus_constant (Pmode, stack_pointer_rtx,
2024                                                 -(size + live_seq))));
2025 
2026       /* Note that live_seq always contains r28+r29, but the other
2027          registers to be saved are all below 18.  */
2028 
2029       first_reg = (LAST_CALLEE_SAVED_REG + 1) - (live_seq - 2);
2030 
2031       for (reg = 29, offset = -live_seq + 1;
2032            reg >= first_reg;
2033            reg = (reg == 28 ? LAST_CALLEE_SAVED_REG : reg - 1), ++offset)
2034         {
2035           rtx m, r;
2036 
2037           m = gen_rtx_MEM (QImode, plus_constant (Pmode, stack_pointer_rtx,
2038                                                   offset));
2039           r = gen_rtx_REG (QImode, reg);
2040           add_reg_note (insn, REG_CFA_OFFSET, gen_rtx_SET (m, r));
2041         }
2042 
2043       cfun->machine->stack_usage += size + live_seq;
2044     }
2045   else /* !minimize */
2046     {
2047       for (int reg = 0; reg < 32; ++reg)
2048         if (TEST_HARD_REG_BIT (set, reg))
2049           emit_push_byte (reg, true);
2050 
2051       if (frame_pointer_needed
2052           && (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main)))
2053         {
2054           /* Push frame pointer.  Always be consistent about the
2055              ordering of pushes -- epilogue_restores expects the
2056              register pair to be pushed low byte first.  */
2057 
2058           emit_push_byte (REG_Y, true);
2059           emit_push_byte (REG_Y + 1, true);
2060         }
2061 
2062       if (frame_pointer_needed
2063           && size == 0)
2064         {
2065           insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
2066           RTX_FRAME_RELATED_P (insn) = 1;
2067         }
2068 
2069       if (size != 0)
2070         {
2071           /*  Creating a frame can be done by direct manipulation of the
2072               stack or via the frame pointer. These two methods are:
2073                   fp =  sp
2074                   fp -= size
2075                   sp =  fp
2076               or
2077                   sp -= size
2078                   fp =  sp    (*)
2079               the optimum method depends on function type, stack and
2080               frame size.  To avoid a complex logic, both methods are
2081               tested and shortest is selected.
2082 
2083               There is also the case where SIZE != 0 and no frame pointer is
2084               needed; this can occur if ACCUMULATE_OUTGOING_ARGS is on.
2085               In that case, insn (*) is not needed in that case.
2086               We use the X register as scratch. This is save because in X
2087               is call-clobbered.
2088                  In an interrupt routine, the case of SIZE != 0 together with
2089               !frame_pointer_needed can only occur if the function is not a
2090               leaf function and thus X has already been saved.  */
2091 
2092           int irq_state = -1;
2093           HOST_WIDE_INT size_cfa = size, neg_size;
2094           rtx_insn *fp_plus_insns;
2095           rtx fp, my_fp;
2096 
2097           gcc_assert (frame_pointer_needed
2098                       || !isr_p
2099                       || !crtl->is_leaf);
2100 
2101           fp = my_fp = (frame_pointer_needed
2102                         ? frame_pointer_rtx
2103                         : gen_rtx_REG (Pmode, REG_X));
2104 
2105           if (AVR_HAVE_8BIT_SP)
2106             {
2107               /* The high byte (r29) does not change:
2108                  Prefer SUBI (1 cycle) over SBIW (2 cycles, same size).  */
2109 
2110               my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
2111             }
2112 
2113           /* Cut down size and avoid size = 0 so that we don't run
2114              into ICE like PR52488 in the remainder.  */
2115 
2116           if (size > size_max)
2117             {
2118               /* Don't error so that insane code from newlib still compiles
2119                  and does not break building newlib.  As PR51345 is implemented
2120                  now, there are multilib variants with -msp8.
2121 
2122                  If user wants sanity checks he can use -Wstack-usage=
2123                  or similar options.
2124 
2125                  For CFA we emit the original, non-saturated size so that
2126                  the generic machinery is aware of the real stack usage and
2127                  will print the above diagnostic as expected.  */
2128 
2129               size = size_max;
2130             }
2131 
2132           size = trunc_int_for_mode (size, GET_MODE (my_fp));
2133           neg_size = trunc_int_for_mode (-size, GET_MODE (my_fp));
2134 
2135           /************  Method 1: Adjust frame pointer  ************/
2136 
2137           start_sequence ();
2138 
2139           /* Normally, the dwarf2out frame-related-expr interpreter does
2140              not expect to have the CFA change once the frame pointer is
2141              set up.  Thus, we avoid marking the move insn below and
2142              instead indicate that the entire operation is complete after
2143              the frame pointer subtraction is done.  */
2144 
2145           insn = emit_move_insn (fp, stack_pointer_rtx);
2146           if (frame_pointer_needed)
2147             {
2148               RTX_FRAME_RELATED_P (insn) = 1;
2149               add_reg_note (insn, REG_CFA_ADJUST_CFA,
2150                             gen_rtx_SET (fp, stack_pointer_rtx));
2151             }
2152 
2153           insn = emit_move_insn (my_fp, plus_constant (GET_MODE (my_fp),
2154                                                        my_fp, neg_size));
2155 
2156           if (frame_pointer_needed)
2157             {
2158               RTX_FRAME_RELATED_P (insn) = 1;
2159               add_reg_note (insn, REG_CFA_ADJUST_CFA,
2160                             gen_rtx_SET (fp, plus_constant (Pmode, fp,
2161                                                                           -size_cfa)));
2162             }
2163 
2164           /* Copy to stack pointer.  Note that since we've already
2165              changed the CFA to the frame pointer this operation
2166              need not be annotated if frame pointer is needed.
2167              Always move through unspec, see PR50063.
2168              For meaning of irq_state see movhi_sp_r insn.  */
2169 
2170           if (cfun->machine->is_interrupt)
2171             irq_state = 1;
2172 
2173           if (TARGET_NO_INTERRUPTS
2174               || cfun->machine->is_signal
2175               || cfun->machine->is_OS_main)
2176             irq_state = 0;
2177 
2178           if (AVR_HAVE_8BIT_SP)
2179             irq_state = 2;
2180 
2181           insn = emit_insn (gen_movhi_sp_r (stack_pointer_rtx,
2182                                             fp, GEN_INT (irq_state)));
2183           if (!frame_pointer_needed)
2184             {
2185               RTX_FRAME_RELATED_P (insn) = 1;
2186               add_reg_note (insn, REG_CFA_ADJUST_CFA,
2187                             gen_rtx_SET (stack_pointer_rtx,
2188                                          plus_constant (Pmode,
2189                                                         stack_pointer_rtx,
2190                                                         -size_cfa)));
2191             }
2192 
2193           fp_plus_insns = get_insns ();
2194           end_sequence ();
2195 
2196           /************  Method 2: Adjust Stack pointer  ************/
2197 
2198           /* Stack adjustment by means of RCALL . and/or PUSH __TMP_REG__
2199              can only handle specific offsets.  */
2200 
2201           int n_rcall = size / (AVR_3_BYTE_PC ? 3 : 2);
2202 
2203           if (avr_sp_immediate_operand (gen_int_mode (-size, HImode), HImode)
2204               // Don't use more than 3 RCALLs.
2205               && n_rcall <= 3)
2206             {
2207               rtx_insn *sp_plus_insns;
2208 
2209               start_sequence ();
2210 
2211               insn = emit_move_insn (stack_pointer_rtx,
2212                                      plus_constant (Pmode, stack_pointer_rtx,
2213                                                     -size));
2214               RTX_FRAME_RELATED_P (insn) = 1;
2215               add_reg_note (insn, REG_CFA_ADJUST_CFA,
2216                             gen_rtx_SET (stack_pointer_rtx,
2217                                          plus_constant (Pmode,
2218                                                         stack_pointer_rtx,
2219                                                         -size_cfa)));
2220               if (frame_pointer_needed)
2221                 {
2222                   insn = emit_move_insn (fp, stack_pointer_rtx);
2223                   RTX_FRAME_RELATED_P (insn) = 1;
2224                 }
2225 
2226               sp_plus_insns = get_insns ();
2227               end_sequence ();
2228 
2229               /************ Use shortest method  ************/
2230 
2231               emit_insn (get_sequence_length (sp_plus_insns)
2232                          < get_sequence_length (fp_plus_insns)
2233                          ? sp_plus_insns
2234                          : fp_plus_insns);
2235             }
2236           else
2237             {
2238               emit_insn (fp_plus_insns);
2239             }
2240 
2241           cfun->machine->stack_usage += size_cfa;
2242         } /* !minimize && size != 0 */
2243     } /* !minimize */
2244 }
2245 
2246 
2247 /*  Output function prologue.  */
2248 
2249 void
avr_expand_prologue(void)2250 avr_expand_prologue (void)
2251 {
2252   HARD_REG_SET set;
2253   HOST_WIDE_INT size;
2254 
2255   size = get_frame_size() + avr_outgoing_args_size();
2256 
2257   cfun->machine->stack_usage = 0;
2258 
2259   /* Prologue: naked.  */
2260   if (cfun->machine->is_naked)
2261     {
2262       return;
2263     }
2264 
2265   avr_regs_to_save (&set);
2266 
2267   if (cfun->machine->is_interrupt || cfun->machine->is_signal)
2268     {
2269       int treg = AVR_TMP_REGNO;
2270       /* Enable interrupts.  */
2271       if (cfun->machine->is_interrupt)
2272         emit_insn (gen_enable_interrupt ());
2273 
2274       if (cfun->machine->gasisr.maybe)
2275         {
2276           /* Let GAS PR21472 emit prologue preamble for us which handles SREG,
2277              ZERO_REG and TMP_REG and one additional, optional register for
2278              us in an optimal way.  This even scans through inline asm.  */
2279 
2280           cfun->machine->gasisr.yes = 1;
2281 
2282           // The optional reg or TMP_REG if we don't need one.  If we need one,
2283           // remove that reg from SET so that it's not puhed / popped twice.
2284           // We also use it below instead of TMP_REG in some places.
2285 
2286           treg = avr_hregs_split_reg (&set);
2287           if (treg < 0)
2288             treg = AVR_TMP_REGNO;
2289           cfun->machine->gasisr.regno = treg;
2290 
2291           // The worst case of pushes.  The exact number can be inferred
2292           // at assembly time by magic expression __gcc_isr.n_pushed.
2293           cfun->machine->stack_usage += 3 + (treg != AVR_TMP_REGNO);
2294 
2295           // Emit a Prologue chunk.  Epilogue chunk(s) might follow.
2296           // The final Done chunk is emit by final postscan.
2297           emit_insn (gen_gasisr (GEN_INT (GASISR_Prologue), GEN_INT (treg)));
2298         }
2299       else // !TARGET_GASISR_PROLOGUES: Classic, dumb prologue preamble.
2300         {
2301           /* Push zero reg.  */
2302           emit_push_byte (AVR_ZERO_REGNO, true);
2303 
2304           /* Push tmp reg.  */
2305           emit_push_byte (AVR_TMP_REGNO, true);
2306 
2307           /* Push SREG.  */
2308           /* ??? There's no dwarf2 column reserved for SREG.  */
2309           emit_push_sfr (sreg_rtx, false, false /* clr */, AVR_TMP_REGNO);
2310 
2311           /* Clear zero reg.  */
2312           emit_move_insn (zero_reg_rtx, const0_rtx);
2313 
2314           /* Prevent any attempt to delete the setting of ZERO_REG!  */
2315           emit_use (zero_reg_rtx);
2316         }
2317 
2318       /* Push and clear RAMPD/X/Y/Z if present and low-part register is used.
2319          ??? There are no dwarf2 columns reserved for RAMPD/X/Y/Z.  */
2320 
2321       if (AVR_HAVE_RAMPD)
2322         emit_push_sfr (rampd_rtx, false /* frame */, true /* clr */, treg);
2323 
2324       if (AVR_HAVE_RAMPX
2325           && TEST_HARD_REG_BIT (set, REG_X)
2326           && TEST_HARD_REG_BIT (set, REG_X + 1))
2327         {
2328           emit_push_sfr (rampx_rtx, false /* frame */, true /* clr */, treg);
2329         }
2330 
2331       if (AVR_HAVE_RAMPY
2332           && (frame_pointer_needed
2333               || (TEST_HARD_REG_BIT (set, REG_Y)
2334                   && TEST_HARD_REG_BIT (set, REG_Y + 1))))
2335         {
2336           emit_push_sfr (rampy_rtx, false /* frame */, true /* clr */, treg);
2337         }
2338 
2339       if (AVR_HAVE_RAMPZ
2340           && TEST_HARD_REG_BIT (set, REG_Z)
2341           && TEST_HARD_REG_BIT (set, REG_Z + 1))
2342         {
2343           emit_push_sfr (rampz_rtx, false /* frame */, AVR_HAVE_RAMPD, treg);
2344         }
2345     }  /* is_interrupt is_signal */
2346 
2347   avr_prologue_setup_frame (size, set);
2348 
2349   if (flag_stack_usage_info)
2350     current_function_static_stack_size
2351       = cfun->machine->stack_usage + INCOMING_FRAME_SP_OFFSET;
2352 }
2353 
2354 
2355 /* Implement `TARGET_ASM_FUNCTION_END_PROLOGUE'.  */
2356 /* Output summary at end of function prologue.  */
2357 
2358 static void
avr_asm_function_end_prologue(FILE * file)2359 avr_asm_function_end_prologue (FILE *file)
2360 {
2361   if (cfun->machine->is_naked)
2362     {
2363       fputs ("/* prologue: naked */\n", file);
2364     }
2365   else
2366     {
2367       if (cfun->machine->is_interrupt)
2368         {
2369           fputs ("/* prologue: Interrupt */\n", file);
2370         }
2371       else if (cfun->machine->is_signal)
2372         {
2373           fputs ("/* prologue: Signal */\n", file);
2374         }
2375       else
2376         fputs ("/* prologue: function */\n", file);
2377     }
2378 
2379   if (ACCUMULATE_OUTGOING_ARGS)
2380     fprintf (file, "/* outgoing args size = %d */\n",
2381              avr_outgoing_args_size());
2382 
2383   fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n",
2384            (HOST_WIDE_INT) get_frame_size());
2385 
2386   if (!cfun->machine->gasisr.yes)
2387     {
2388       fprintf (file, "/* stack size = %d */\n", cfun->machine->stack_usage);
2389       // Create symbol stack offset so all functions have it. Add 1 to stack
2390       // usage for offset so that SP + .L__stack_offset = return address.
2391       fprintf (file, ".L__stack_usage = %d\n", cfun->machine->stack_usage);
2392     }
2393   else
2394     {
2395       int used_by_gasisr = 3 + (cfun->machine->gasisr.regno != AVR_TMP_REGNO);
2396       int to = cfun->machine->stack_usage;
2397       int from = to - used_by_gasisr;
2398       // Number of pushed regs is only known at assembly-time.
2399       fprintf (file, "/* stack size = %d...%d */\n", from , to);
2400       fprintf (file, ".L__stack_usage = %d + __gcc_isr.n_pushed\n", from);
2401     }
2402 }
2403 
2404 
2405 /* Implement `EPILOGUE_USES'.  */
2406 
2407 int
avr_epilogue_uses(int regno ATTRIBUTE_UNUSED)2408 avr_epilogue_uses (int regno ATTRIBUTE_UNUSED)
2409 {
2410   if (reload_completed
2411       && cfun->machine
2412       && (cfun->machine->is_interrupt || cfun->machine->is_signal))
2413     return 1;
2414   return 0;
2415 }
2416 
2417 /*  Helper for avr_expand_epilogue.  Emit a pop of a byte register.  */
2418 
2419 static void
emit_pop_byte(unsigned regno)2420 emit_pop_byte (unsigned regno)
2421 {
2422   rtx mem, reg;
2423 
2424   mem = gen_rtx_PRE_INC (HImode, stack_pointer_rtx);
2425   mem = gen_frame_mem (QImode, mem);
2426   reg = gen_rtx_REG (QImode, regno);
2427 
2428   emit_insn (gen_rtx_SET (reg, mem));
2429 }
2430 
2431 /*  Output RTL epilogue.  */
2432 
2433 void
avr_expand_epilogue(bool sibcall_p)2434 avr_expand_epilogue (bool sibcall_p)
2435 {
2436   int live_seq;
2437   HARD_REG_SET set;
2438   int minimize;
2439   HOST_WIDE_INT size;
2440   bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
2441 
2442   size = get_frame_size() + avr_outgoing_args_size();
2443 
2444   /* epilogue: naked  */
2445   if (cfun->machine->is_naked)
2446     {
2447       gcc_assert (!sibcall_p);
2448 
2449       emit_jump_insn (gen_return ());
2450       return;
2451     }
2452 
2453   avr_regs_to_save (&set);
2454   live_seq = sequent_regs_live ();
2455 
2456   minimize = (TARGET_CALL_PROLOGUES
2457               && live_seq
2458               && !isr_p
2459               && !cfun->machine->is_OS_task
2460               && !cfun->machine->is_OS_main
2461               && !AVR_TINY);
2462 
2463   if (minimize
2464       && (live_seq > 4
2465           || frame_pointer_needed
2466           || size))
2467     {
2468       /*  Get rid of frame.  */
2469 
2470       if (!frame_pointer_needed)
2471         {
2472           emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
2473         }
2474 
2475       if (size)
2476         {
2477           emit_move_insn (frame_pointer_rtx,
2478                           plus_constant (Pmode, frame_pointer_rtx, size));
2479         }
2480 
2481       emit_insn (gen_epilogue_restores (gen_int_mode (live_seq, HImode)));
2482       return;
2483     }
2484 
2485   if (size)
2486     {
2487       /* Try two methods to adjust stack and select shortest.  */
2488 
2489       int irq_state = -1;
2490       rtx fp, my_fp;
2491       rtx_insn *fp_plus_insns;
2492       HOST_WIDE_INT size_max;
2493 
2494       gcc_assert (frame_pointer_needed
2495                   || !isr_p
2496                   || !crtl->is_leaf);
2497 
2498       fp = my_fp = (frame_pointer_needed
2499                     ? frame_pointer_rtx
2500                     : gen_rtx_REG (Pmode, REG_X));
2501 
2502       if (AVR_HAVE_8BIT_SP)
2503         {
2504           /* The high byte (r29) does not change:
2505              Prefer SUBI (1 cycle) over SBIW (2 cycles).  */
2506 
2507           my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
2508         }
2509 
2510       /* For rationale see comment in prologue generation.  */
2511 
2512       size_max = (HOST_WIDE_INT) GET_MODE_MASK (GET_MODE (my_fp));
2513       if (size > size_max)
2514         size = size_max;
2515       size = trunc_int_for_mode (size, GET_MODE (my_fp));
2516 
2517       /********** Method 1: Adjust fp register  **********/
2518 
2519       start_sequence ();
2520 
2521       if (!frame_pointer_needed)
2522         emit_move_insn (fp, stack_pointer_rtx);
2523 
2524       emit_move_insn (my_fp, plus_constant (GET_MODE (my_fp), my_fp, size));
2525 
2526       /* Copy to stack pointer.  */
2527 
2528       if (TARGET_NO_INTERRUPTS)
2529         irq_state = 0;
2530 
2531       if (AVR_HAVE_8BIT_SP)
2532         irq_state = 2;
2533 
2534       emit_insn (gen_movhi_sp_r (stack_pointer_rtx, fp,
2535                                  GEN_INT (irq_state)));
2536 
2537       fp_plus_insns = get_insns ();
2538       end_sequence ();
2539 
2540       /********** Method 2: Adjust Stack pointer  **********/
2541 
2542       if (avr_sp_immediate_operand (gen_int_mode (size, HImode), HImode))
2543         {
2544           rtx_insn *sp_plus_insns;
2545 
2546           start_sequence ();
2547 
2548           emit_move_insn (stack_pointer_rtx,
2549                           plus_constant (Pmode, stack_pointer_rtx, size));
2550 
2551           sp_plus_insns = get_insns ();
2552           end_sequence ();
2553 
2554           /************ Use shortest method  ************/
2555 
2556           emit_insn (get_sequence_length (sp_plus_insns)
2557                      < get_sequence_length (fp_plus_insns)
2558                      ? sp_plus_insns
2559                      : fp_plus_insns);
2560         }
2561       else
2562         emit_insn (fp_plus_insns);
2563     } /* size != 0 */
2564 
2565   if (frame_pointer_needed
2566       && !(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
2567     {
2568       /* Restore previous frame_pointer.  See avr_expand_prologue for
2569          rationale for not using pophi.  */
2570 
2571       emit_pop_byte (REG_Y + 1);
2572       emit_pop_byte (REG_Y);
2573     }
2574 
2575   /* Restore used registers.  */
2576 
2577   int treg = AVR_TMP_REGNO;
2578 
2579   if (isr_p
2580       && cfun->machine->gasisr.yes)
2581     {
2582       treg = cfun->machine->gasisr.regno;
2583       CLEAR_HARD_REG_BIT (set, treg);
2584     }
2585 
2586   for (int reg = 31; reg >= 0; --reg)
2587     if (TEST_HARD_REG_BIT (set, reg))
2588       emit_pop_byte (reg);
2589 
2590   if (isr_p)
2591     {
2592       /* Restore RAMPZ/Y/X/D using tmp_reg as scratch.
2593          The conditions to restore them must be tha same as in prologue.  */
2594 
2595       if (AVR_HAVE_RAMPZ
2596           && TEST_HARD_REG_BIT (set, REG_Z)
2597           && TEST_HARD_REG_BIT (set, REG_Z + 1))
2598         {
2599           emit_pop_byte (treg);
2600           emit_move_insn (rampz_rtx, all_regs_rtx[treg]);
2601         }
2602 
2603       if (AVR_HAVE_RAMPY
2604           && (frame_pointer_needed
2605               || (TEST_HARD_REG_BIT (set, REG_Y)
2606                   && TEST_HARD_REG_BIT (set, REG_Y + 1))))
2607         {
2608           emit_pop_byte (treg);
2609           emit_move_insn (rampy_rtx, all_regs_rtx[treg]);
2610         }
2611 
2612       if (AVR_HAVE_RAMPX
2613           && TEST_HARD_REG_BIT (set, REG_X)
2614           && TEST_HARD_REG_BIT (set, REG_X + 1))
2615         {
2616           emit_pop_byte (treg);
2617           emit_move_insn (rampx_rtx, all_regs_rtx[treg]);
2618         }
2619 
2620       if (AVR_HAVE_RAMPD)
2621         {
2622           emit_pop_byte (treg);
2623           emit_move_insn (rampd_rtx, all_regs_rtx[treg]);
2624         }
2625 
2626       if (cfun->machine->gasisr.yes)
2627         {
2628           // Emit an Epilogue chunk.
2629           emit_insn (gen_gasisr (GEN_INT (GASISR_Epilogue),
2630                                  GEN_INT (cfun->machine->gasisr.regno)));
2631         }
2632       else // !TARGET_GASISR_PROLOGUES
2633         {
2634           /* Restore SREG using tmp_reg as scratch.  */
2635 
2636           emit_pop_byte (AVR_TMP_REGNO);
2637           emit_move_insn (sreg_rtx, tmp_reg_rtx);
2638 
2639           /* Restore tmp REG.  */
2640           emit_pop_byte (AVR_TMP_REGNO);
2641 
2642           /* Restore zero REG.  */
2643           emit_pop_byte (AVR_ZERO_REGNO);
2644         }
2645     }
2646 
2647   if (!sibcall_p)
2648     emit_jump_insn (gen_return ());
2649 }
2650 
2651 
2652 /* Implement `TARGET_ASM_FUNCTION_BEGIN_EPILOGUE'.  */
2653 
2654 static void
avr_asm_function_begin_epilogue(FILE * file)2655 avr_asm_function_begin_epilogue (FILE *file)
2656 {
2657   app_disable();
2658   fprintf (file, "/* epilogue start */\n");
2659 }
2660 
2661 
2662 /* Implement `TARGET_CANNOT_MODITY_JUMPS_P'.  */
2663 
2664 static bool
avr_cannot_modify_jumps_p(void)2665 avr_cannot_modify_jumps_p (void)
2666 {
2667   /* Naked Functions must not have any instructions after
2668      their epilogue, see PR42240 */
2669 
2670   if (reload_completed
2671       && cfun->machine
2672       && cfun->machine->is_naked)
2673     {
2674       return true;
2675     }
2676 
2677   return false;
2678 }
2679 
2680 
2681 /* Implement `TARGET_MODE_DEPENDENT_ADDRESS_P'.  */
2682 
2683 static bool
avr_mode_dependent_address_p(const_rtx addr ATTRIBUTE_UNUSED,addr_space_t as)2684 avr_mode_dependent_address_p (const_rtx addr ATTRIBUTE_UNUSED, addr_space_t as)
2685 {
2686   /* FIXME:  Non-generic addresses are not mode-dependent in themselves.
2687        This hook just serves to hack around PR rtl-optimization/52543 by
2688        claiming that non-generic addresses were mode-dependent so that
2689        lower-subreg.cc will skip these addresses.  lower-subreg.cc sets up fake
2690        RTXes to probe SET and MEM costs and assumes that MEM is always in the
2691        generic address space which is not true.  */
2692 
2693   return !ADDR_SPACE_GENERIC_P (as);
2694 }
2695 
2696 
2697 /* Return true if rtx X is a CONST_INT, CONST or SYMBOL_REF
2698    address with the `absdata' variable attribute, i.e. respective
2699    data can be read / written by LDS / STS instruction.
2700    This is used only for AVR_TINY.  */
2701 
2702 static bool
avr_address_tiny_absdata_p(rtx x,machine_mode mode)2703 avr_address_tiny_absdata_p (rtx x, machine_mode mode)
2704 {
2705   if (CONST == GET_CODE (x))
2706     x = XEXP (XEXP (x, 0), 0);
2707 
2708   if (SYMBOL_REF_P (x))
2709     return SYMBOL_REF_FLAGS (x) & AVR_SYMBOL_FLAG_TINY_ABSDATA;
2710 
2711   if (CONST_INT_P (x)
2712       && IN_RANGE (INTVAL (x), 0, 0xc0 - GET_MODE_SIZE (mode)))
2713     return true;
2714 
2715   return false;
2716 }
2717 
2718 
2719 /* Helper function for `avr_legitimate_address_p'.  */
2720 
2721 static inline bool
avr_reg_ok_for_addr_p(rtx reg,addr_space_t as,RTX_CODE outer_code,bool strict)2722 avr_reg_ok_for_addr_p (rtx reg, addr_space_t as,
2723                        RTX_CODE outer_code, bool strict)
2724 {
2725   return (REG_P (reg)
2726           && (avr_regno_mode_code_ok_for_base_p (REGNO (reg), QImode,
2727                                                  as, outer_code, UNKNOWN)
2728               || (!strict
2729                   && REGNO (reg) >= FIRST_PSEUDO_REGISTER)));
2730 }
2731 
2732 
2733 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
2734    machine for a memory operand of mode MODE.  */
2735 
2736 static bool
avr_legitimate_address_p(machine_mode mode,rtx x,bool strict)2737 avr_legitimate_address_p (machine_mode mode, rtx x, bool strict)
2738 {
2739   bool ok = CONSTANT_ADDRESS_P (x);
2740 
2741   switch (GET_CODE (x))
2742     {
2743     case REG:
2744       ok = avr_reg_ok_for_addr_p (x, ADDR_SPACE_GENERIC,
2745                                   MEM, strict);
2746 
2747       if (strict
2748           && GET_MODE_SIZE (mode) > 4
2749           && REG_X == REGNO (x))
2750         {
2751           ok = false;
2752         }
2753       break;
2754 
2755     case POST_INC:
2756     case PRE_DEC:
2757       ok = avr_reg_ok_for_addr_p (XEXP (x, 0), ADDR_SPACE_GENERIC,
2758                                   GET_CODE (x), strict);
2759       break;
2760 
2761     case PLUS:
2762       {
2763         rtx reg = XEXP (x, 0);
2764         rtx op1 = XEXP (x, 1);
2765 
2766         if (REG_P (reg)
2767             && CONST_INT_P (op1)
2768             && INTVAL (op1) >= 0)
2769           {
2770             bool fit = IN_RANGE (INTVAL (op1), 0, MAX_LD_OFFSET (mode));
2771 
2772             if (fit)
2773               {
2774                 ok = (! strict
2775                       || avr_reg_ok_for_addr_p (reg, ADDR_SPACE_GENERIC,
2776                                                 PLUS, strict));
2777 
2778                 if (reg == frame_pointer_rtx
2779                     || reg == arg_pointer_rtx)
2780                   {
2781                     ok = true;
2782                   }
2783               }
2784             else if (frame_pointer_needed
2785                      && reg == frame_pointer_rtx)
2786               {
2787                 ok = true;
2788               }
2789           }
2790       }
2791       break;
2792 
2793     default:
2794       break;
2795     }
2796 
2797   if (AVR_TINY
2798       && CONSTANT_ADDRESS_P (x))
2799     {
2800       /* avrtiny's load / store instructions only cover addresses 0..0xbf:
2801          IN / OUT range is 0..0x3f and LDS / STS can access 0x40..0xbf.  */
2802 
2803       ok = avr_address_tiny_absdata_p (x, mode);
2804     }
2805 
2806   if (avr_log.legitimate_address_p)
2807     {
2808       avr_edump ("\n%?: ret=%d, mode=%m strict=%d "
2809                  "reload_completed=%d reload_in_progress=%d %s:",
2810                  ok, mode, strict, reload_completed, reload_in_progress,
2811                  reg_renumber ? "(reg_renumber)" : "");
2812 
2813       if (GET_CODE (x) == PLUS
2814           && REG_P (XEXP (x, 0))
2815           && CONST_INT_P (XEXP (x, 1))
2816           && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
2817           && reg_renumber)
2818         {
2819           avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
2820                      true_regnum (XEXP (x, 0)));
2821         }
2822 
2823       avr_edump ("\n%r\n", x);
2824     }
2825 
2826   return ok;
2827 }
2828 
2829 
2830 /* Former implementation of TARGET_LEGITIMIZE_ADDRESS,
2831    now only a helper for avr_addr_space_legitimize_address.  */
2832 /* Attempts to replace X with a valid
2833    memory address for an operand of mode MODE  */
2834 
2835 static rtx
avr_legitimize_address(rtx x,rtx oldx,machine_mode mode)2836 avr_legitimize_address (rtx x, rtx oldx, machine_mode mode)
2837 {
2838   bool big_offset_p = false;
2839 
2840   x = oldx;
2841 
2842   if (AVR_TINY)
2843     {
2844       if (CONSTANT_ADDRESS_P (x)
2845           && ! avr_address_tiny_absdata_p (x, mode))
2846         {
2847           x = force_reg (Pmode, x);
2848         }
2849     }
2850 
2851   if (GET_CODE (oldx) == PLUS
2852       && REG_P (XEXP (oldx, 0)))
2853     {
2854       if (REG_P (XEXP (oldx, 1)))
2855         x = force_reg (GET_MODE (oldx), oldx);
2856       else if (CONST_INT_P (XEXP (oldx, 1)))
2857         {
2858           int offs = INTVAL (XEXP (oldx, 1));
2859           if (frame_pointer_rtx != XEXP (oldx, 0)
2860               && offs > MAX_LD_OFFSET (mode))
2861             {
2862               big_offset_p = true;
2863               x = force_reg (GET_MODE (oldx), oldx);
2864             }
2865         }
2866     }
2867 
2868   if (avr_log.legitimize_address)
2869     {
2870       avr_edump ("\n%?: mode=%m\n %r\n", mode, oldx);
2871 
2872       if (x != oldx)
2873         avr_edump (" %s --> %r\n", big_offset_p ? "(big offset)" : "", x);
2874     }
2875 
2876   return x;
2877 }
2878 
2879 
2880 /* Implement `LEGITIMIZE_RELOAD_ADDRESS'.  */
2881 /* This will allow register R26/27 to be used where it is no worse than normal
2882    base pointers R28/29 or R30/31.  For example, if base offset is greater
2883    than 63 bytes or for R++ or --R addressing.  */
2884 
2885 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))2886 avr_legitimize_reload_address (rtx *px, machine_mode mode,
2887                                int opnum, int type, int addr_type,
2888                                int ind_levels ATTRIBUTE_UNUSED,
2889                                rtx (*mk_memloc)(rtx,int))
2890 {
2891   rtx x = *px;
2892 
2893   if (avr_log.legitimize_reload_address)
2894     avr_edump ("\n%?:%m %r\n", mode, x);
2895 
2896   if (1 && (GET_CODE (x) == POST_INC
2897             || GET_CODE (x) == PRE_DEC))
2898     {
2899       push_reload (XEXP (x, 0), XEXP (x, 0), &XEXP (x, 0), &XEXP (x, 0),
2900                    POINTER_REGS, GET_MODE (x), GET_MODE (x), 0, 0,
2901                    opnum, RELOAD_OTHER);
2902 
2903       if (avr_log.legitimize_reload_address)
2904         avr_edump (" RCLASS.1 = %R\n IN = %r\n OUT = %r\n",
2905                    POINTER_REGS, XEXP (x, 0), XEXP (x, 0));
2906 
2907       return x;
2908     }
2909 
2910   if (GET_CODE (x) == PLUS
2911       && REG_P (XEXP (x, 0))
2912       && reg_equiv_constant (REGNO (XEXP (x, 0))) == 0
2913       && CONST_INT_P (XEXP (x, 1))
2914       && INTVAL (XEXP (x, 1)) >= 1)
2915     {
2916       bool fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
2917 
2918       if (fit)
2919         {
2920           if (reg_equiv_address (REGNO (XEXP (x, 0))) != 0)
2921             {
2922               int regno = REGNO (XEXP (x, 0));
2923               rtx mem = mk_memloc (x, regno);
2924 
2925               push_reload (XEXP (mem, 0), NULL_RTX, &XEXP (mem, 0), NULL,
2926                            POINTER_REGS, Pmode, VOIDmode, 0, 0,
2927                            1, (enum reload_type) addr_type);
2928 
2929               if (avr_log.legitimize_reload_address)
2930                 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
2931                            POINTER_REGS, XEXP (mem, 0), NULL_RTX);
2932 
2933               push_reload (mem, NULL_RTX, &XEXP (x, 0), NULL,
2934                            BASE_POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
2935                            opnum, (enum reload_type) type);
2936 
2937               if (avr_log.legitimize_reload_address)
2938                 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
2939                            BASE_POINTER_REGS, mem, NULL_RTX);
2940 
2941               return x;
2942             }
2943         }
2944       else if (! (frame_pointer_needed
2945                   && XEXP (x, 0) == frame_pointer_rtx))
2946         {
2947           push_reload (x, NULL_RTX, px, NULL,
2948                        POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
2949                        opnum, (enum reload_type) type);
2950 
2951           if (avr_log.legitimize_reload_address)
2952             avr_edump (" RCLASS.3 = %R\n IN = %r\n OUT = %r\n",
2953                        POINTER_REGS, x, NULL_RTX);
2954 
2955           return x;
2956         }
2957     }
2958 
2959   return NULL_RTX;
2960 }
2961 
2962 
2963 /* Helper function to print assembler resp. track instruction
2964    sequence lengths.  Always return "".
2965 
2966    If PLEN == NULL:
2967        Output assembler code from template TPL with operands supplied
2968        by OPERANDS.  This is just forwarding to output_asm_insn.
2969 
2970    If PLEN != NULL:
2971        If N_WORDS >= 0  Add N_WORDS to *PLEN.
2972        If N_WORDS < 0   Set *PLEN to -N_WORDS.
2973        Don't output anything.
2974 */
2975 
2976 static const char*
avr_asm_len(const char * tpl,rtx * operands,int * plen,int n_words)2977 avr_asm_len (const char* tpl, rtx* operands, int* plen, int n_words)
2978 {
2979   if (plen == NULL)
2980     output_asm_insn (tpl, operands);
2981   else
2982     {
2983       if (n_words < 0)
2984         *plen = -n_words;
2985       else
2986         *plen += n_words;
2987     }
2988 
2989   return "";
2990 }
2991 
2992 
2993 /* Return a pointer register name as a string.  */
2994 
2995 static const char*
ptrreg_to_str(int regno)2996 ptrreg_to_str (int regno)
2997 {
2998   switch (regno)
2999     {
3000     case REG_X: return "X";
3001     case REG_Y: return "Y";
3002     case REG_Z: return "Z";
3003     default:
3004       output_operand_lossage ("address operand requires constraint for"
3005                               " X, Y, or Z register");
3006     }
3007   return NULL;
3008 }
3009 
3010 /* Return the condition name as a string.
3011    Used in conditional jump constructing  */
3012 
3013 static const char*
cond_string(enum rtx_code code)3014 cond_string (enum rtx_code code)
3015 {
3016   bool cc_overflow_unusable = false;
3017 
3018   switch (code)
3019     {
3020     case NE:
3021       return "ne";
3022     case EQ:
3023       return "eq";
3024     case GE:
3025       if (cc_overflow_unusable)
3026         return "pl";
3027       else
3028         return "ge";
3029     case LT:
3030       if (cc_overflow_unusable)
3031         return "mi";
3032       else
3033         return "lt";
3034     case GEU:
3035       return "sh";
3036     case LTU:
3037       return "lo";
3038     default:
3039       gcc_unreachable ();
3040     }
3041 
3042   return "";
3043 }
3044 
3045 
3046 /* Return true if rtx X is a CONST or SYMBOL_REF with progmem.
3047    This must be used for AVR_TINY only because on other cores
3048    the flash memory is not visible in the RAM address range and
3049    cannot be read by, say,  LD instruction.  */
3050 
3051 static bool
avr_address_tiny_pm_p(rtx x)3052 avr_address_tiny_pm_p (rtx x)
3053 {
3054   if (CONST == GET_CODE (x))
3055     x = XEXP (XEXP (x, 0), 0);
3056 
3057   if (SYMBOL_REF_P (x))
3058     return SYMBOL_REF_FLAGS (x) & AVR_SYMBOL_FLAG_TINY_PM;
3059 
3060   return false;
3061 }
3062 
3063 /* Implement `TARGET_PRINT_OPERAND_ADDRESS'.  */
3064 /* Output ADDR to FILE as address.  */
3065 
3066 static void
avr_print_operand_address(FILE * file,machine_mode,rtx addr)3067 avr_print_operand_address (FILE *file, machine_mode /*mode*/, rtx addr)
3068 {
3069   if (AVR_TINY
3070       && avr_address_tiny_pm_p (addr))
3071     {
3072       addr = plus_constant (Pmode, addr, avr_arch->flash_pm_offset);
3073     }
3074 
3075   switch (GET_CODE (addr))
3076     {
3077     case REG:
3078       fprintf (file, "%s", ptrreg_to_str (REGNO (addr)));
3079       break;
3080 
3081     case PRE_DEC:
3082       fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
3083       break;
3084 
3085     case POST_INC:
3086       fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
3087       break;
3088 
3089     default:
3090       if (CONSTANT_ADDRESS_P (addr)
3091           && text_segment_operand (addr, VOIDmode))
3092         {
3093           rtx x = addr;
3094           if (GET_CODE (x) == CONST)
3095             x = XEXP (x, 0);
3096           if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1)))
3097             {
3098               /* Assembler gs() will implant word address.  Make offset
3099                  a byte offset inside gs() for assembler.  This is
3100                  needed because the more logical (constant+gs(sym)) is not
3101                  accepted by gas.  For 128K and smaller devices this is ok.
3102                  For large devices it will create a trampoline to offset
3103                  from symbol which may not be what the user really wanted.  */
3104 
3105               fprintf (file, "gs(");
3106               output_addr_const (file, XEXP (x, 0));
3107               fprintf (file, "+" HOST_WIDE_INT_PRINT_DEC ")",
3108                        2 * INTVAL (XEXP (x, 1)));
3109               if (AVR_3_BYTE_PC)
3110                 if (warning (0, "pointer offset from symbol maybe incorrect"))
3111                   {
3112                     output_addr_const (stderr, addr);
3113                     fprintf (stderr, "\n");
3114                   }
3115             }
3116           else
3117             {
3118               fprintf (file, "gs(");
3119               output_addr_const (file, addr);
3120               fprintf (file, ")");
3121             }
3122         }
3123       else
3124         output_addr_const (file, addr);
3125     }
3126 }
3127 
3128 
3129 /* Implement `TARGET_PRINT_OPERAND_PUNCT_VALID_P'.  */
3130 
3131 static bool
avr_print_operand_punct_valid_p(unsigned char code)3132 avr_print_operand_punct_valid_p (unsigned char code)
3133 {
3134   return code == '~' || code == '!';
3135 }
3136 
3137 
3138 /* Implement `TARGET_PRINT_OPERAND'.  */
3139 /* Output X as assembler operand to file FILE.
3140    For a description of supported %-codes, see top of avr.md.  */
3141 
3142 static void
avr_print_operand(FILE * file,rtx x,int code)3143 avr_print_operand (FILE *file, rtx x, int code)
3144 {
3145   int abcd = 0, ef = 0, ij = 0;
3146 
3147   if (code >= 'A' && code <= 'D')
3148     abcd = code - 'A';
3149   else if (code == 'E' || code == 'F')
3150     ef = code - 'E';
3151   else if (code == 'I' || code == 'J')
3152     ij = code - 'I';
3153 
3154   if (code == '~')
3155     {
3156       if (!AVR_HAVE_JMP_CALL)
3157         fputc ('r', file);
3158     }
3159   else if (code == '!')
3160     {
3161       if (AVR_HAVE_EIJMP_EICALL)
3162         fputc ('e', file);
3163     }
3164   else if (code == 't'
3165            || code == 'T')
3166     {
3167       static int t_regno = -1;
3168       static int t_nbits = -1;
3169 
3170       if (REG_P (x) && t_regno < 0 && code == 'T')
3171         {
3172           t_regno = REGNO (x);
3173           t_nbits = GET_MODE_BITSIZE (GET_MODE (x));
3174         }
3175       else if (CONST_INT_P (x) && t_regno >= 0
3176                && IN_RANGE (INTVAL (x), 0, t_nbits - 1))
3177         {
3178           int bpos = INTVAL (x);
3179 
3180           fprintf (file, "%s", reg_names[t_regno + bpos / 8]);
3181           if (code == 'T')
3182             fprintf (file, ",%d", bpos % 8);
3183 
3184           t_regno = -1;
3185         }
3186       else
3187         fatal_insn ("operands to %T/%t must be reg + const_int:", x);
3188     }
3189   else if (code == 'E' || code == 'F')
3190     {
3191       rtx op = XEXP (x, 0);
3192       fprintf (file, "%s", reg_names[REGNO (op) + ef]);
3193     }
3194   else if (code == 'I' || code == 'J')
3195     {
3196       rtx op = XEXP (XEXP (x, 0), 0);
3197       fprintf (file, "%s", reg_names[REGNO (op) + ij]);
3198     }
3199   else if (REG_P (x))
3200     {
3201       if (x == zero_reg_rtx)
3202         fprintf (file, "__zero_reg__");
3203       else if (code == 'r' && REGNO (x) < 32)
3204         fprintf (file, "%d", (int) REGNO (x));
3205       else
3206         fprintf (file, "%s", reg_names[REGNO (x) + abcd]);
3207     }
3208   else if (CONST_INT_P (x))
3209     {
3210       HOST_WIDE_INT ival = INTVAL (x);
3211 
3212       if ('i' != code)
3213         fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival + abcd);
3214       else if (low_io_address_operand (x, VOIDmode)
3215                || high_io_address_operand (x, VOIDmode))
3216         {
3217           if (AVR_HAVE_RAMPZ && ival == avr_addr.rampz)
3218             fprintf (file, "__RAMPZ__");
3219           else if (AVR_HAVE_RAMPY && ival == avr_addr.rampy)
3220             fprintf (file, "__RAMPY__");
3221           else if (AVR_HAVE_RAMPX && ival == avr_addr.rampx)
3222             fprintf (file, "__RAMPX__");
3223           else if (AVR_HAVE_RAMPD && ival == avr_addr.rampd)
3224             fprintf (file, "__RAMPD__");
3225           else if ((AVR_XMEGA || AVR_TINY) && ival == avr_addr.ccp)
3226             fprintf (file, "__CCP__");
3227           else if (ival == avr_addr.sreg)   fprintf (file, "__SREG__");
3228           else if (ival == avr_addr.sp_l)   fprintf (file, "__SP_L__");
3229           else if (ival == avr_addr.sp_h)   fprintf (file, "__SP_H__");
3230           else
3231             {
3232               fprintf (file, HOST_WIDE_INT_PRINT_HEX,
3233                        ival - avr_arch->sfr_offset);
3234             }
3235         }
3236       else
3237         fatal_insn ("bad address, not an I/O address:", x);
3238     }
3239   else if (MEM_P (x))
3240     {
3241       rtx addr = XEXP (x, 0);
3242 
3243       if (code == 'm')
3244         {
3245           if (!CONSTANT_P (addr))
3246             fatal_insn ("bad address, not a constant:", addr);
3247           /* Assembler template with m-code is data - not progmem section */
3248           if (text_segment_operand (addr, VOIDmode))
3249             if (warning (0, "accessing data memory with"
3250                          " program memory address"))
3251               {
3252                 output_addr_const (stderr, addr);
3253                 fprintf(stderr,"\n");
3254               }
3255           output_addr_const (file, addr);
3256         }
3257       else if (code == 'i')
3258         {
3259           avr_print_operand (file, addr, 'i');
3260         }
3261       else if (code == 'o')
3262         {
3263           if (GET_CODE (addr) != PLUS)
3264             fatal_insn ("bad address, not (reg+disp):", addr);
3265 
3266           avr_print_operand (file, XEXP (addr, 1), 0);
3267         }
3268       else if (code == 'b')
3269         {
3270           if (GET_CODE (addr) != PLUS)
3271             fatal_insn ("bad address, not (reg+disp):", addr);
3272 
3273           avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
3274         }
3275       else if (code == 'p' || code == 'r')
3276         {
3277           if (GET_CODE (addr) != POST_INC && GET_CODE (addr) != PRE_DEC)
3278             fatal_insn ("bad address, not post_inc or pre_dec:", addr);
3279 
3280           if (code == 'p')
3281             /* X, Y, Z */
3282             avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
3283           else
3284             avr_print_operand (file, XEXP (addr, 0), 0);  /* r26, r28, r30 */
3285         }
3286       else if (GET_CODE (addr) == PLUS)
3287         {
3288           avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
3289           if (REGNO (XEXP (addr, 0)) == REG_X)
3290             fatal_insn ("internal compiler error.  Bad address:"
3291                         ,addr);
3292           fputc ('+', file);
3293           avr_print_operand (file, XEXP (addr, 1), code);
3294         }
3295       else
3296         avr_print_operand_address (file, VOIDmode, addr);
3297     }
3298   else if (code == 'i')
3299     {
3300       if (SYMBOL_REF_P (x) && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO))
3301           avr_print_operand_address
3302             (file, VOIDmode, plus_constant (HImode, x, -avr_arch->sfr_offset));
3303       else
3304           fatal_insn ("bad address, not an I/O address:", x);
3305     }
3306   else if (code == 'x')
3307     {
3308       /* Constant progmem address - like used in jmp or call */
3309       if (text_segment_operand (x, VOIDmode) == 0)
3310         if (warning (0, "accessing program memory"
3311                      " with data memory address"))
3312           {
3313             output_addr_const (stderr, x);
3314             fprintf(stderr,"\n");
3315           }
3316       /* Use normal symbol for direct address no linker trampoline needed */
3317       output_addr_const (file, x);
3318     }
3319   else if (CONST_FIXED_P (x))
3320     {
3321       HOST_WIDE_INT ival = INTVAL (avr_to_int_mode (x));
3322       if (code != 0)
3323         output_operand_lossage ("Unsupported code '%c' for fixed-point:",
3324                                 code);
3325       fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);
3326     }
3327   else if (CONST_DOUBLE_P (x))
3328     {
3329       long val;
3330       if (GET_MODE (x) != SFmode)
3331         fatal_insn ("internal compiler error.  Unknown mode:", x);
3332       REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), val);
3333       fprintf (file, "0x%lx", val);
3334     }
3335   else if (GET_CODE (x) == CONST_STRING)
3336     fputs (XSTR (x, 0), file);
3337   else if (code == 'j')
3338     fputs (cond_string (GET_CODE (x)), file);
3339   else if (code == 'k')
3340     fputs (cond_string (reverse_condition (GET_CODE (x))), file);
3341   else
3342     avr_print_operand_address (file, VOIDmode, x);
3343 }
3344 
3345 
3346 /* Implement TARGET_USE_BY_PIECES_INFRASTRUCTURE_P.  */
3347 
3348 /* Prefer sequence of loads/stores for moves of size upto
3349    two - two pairs of load/store instructions are always better
3350    than the 5 instruction sequence for a loop (1 instruction
3351    for loop counter setup, and 4 for the body of the loop). */
3352 
3353 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)3354 avr_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size,
3355                                     unsigned int align ATTRIBUTE_UNUSED,
3356                                     enum by_pieces_operation op,
3357                                     bool speed_p)
3358 {
3359   if (op != MOVE_BY_PIECES
3360       || (speed_p && size > MOVE_MAX_PIECES))
3361     return default_use_by_pieces_infrastructure_p (size, align, op, speed_p);
3362 
3363   return size <= MOVE_MAX_PIECES;
3364 }
3365 
3366 /* Choose mode for jump insn:
3367    1 - relative jump in range -63 <= x <= 62 ;
3368    2 - relative jump in range -2046 <= x <= 2045 ;
3369    3 - absolute jump (only for ATmega[16]03).  */
3370 
3371 int
avr_jump_mode(rtx x,rtx_insn * insn)3372 avr_jump_mode (rtx x, rtx_insn *insn)
3373 {
3374   int dest_addr = INSN_ADDRESSES (INSN_UID (GET_CODE (x) == LABEL_REF
3375                                             ? XEXP (x, 0) : x));
3376   int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
3377   int jump_distance = cur_addr - dest_addr;
3378 
3379   if (IN_RANGE (jump_distance, -63, 62))
3380     return 1;
3381   else if (IN_RANGE (jump_distance, -2046, 2045))
3382     return 2;
3383   else if (AVR_HAVE_JMP_CALL)
3384     return 3;
3385 
3386   return 2;
3387 }
3388 
3389 /* Return an AVR condition jump commands.
3390    X is a comparison RTX.
3391    LEN is a number returned by avr_jump_mode function.
3392    If REVERSE nonzero then condition code in X must be reversed.  */
3393 
3394 const char*
ret_cond_branch(rtx x,int len,int reverse)3395 ret_cond_branch (rtx x, int len, int reverse)
3396 {
3397   RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
3398   bool cc_overflow_unusable = false;
3399 
3400   switch (cond)
3401     {
3402     case GT:
3403       if (cc_overflow_unusable)
3404           return (len == 1 ? ("breq .+2" CR_TAB
3405                                   "brpl %0") :
3406                     len == 2 ? ("breq .+4" CR_TAB
3407                                   "brmi .+2" CR_TAB
3408                                   "rjmp %0") :
3409                     ("breq .+6" CR_TAB
3410                      "brmi .+4" CR_TAB
3411                      "jmp %0"));
3412 
3413       else
3414           return (len == 1 ? ("breq .+2" CR_TAB
3415                                   "brge %0") :
3416                     len == 2 ? ("breq .+4" CR_TAB
3417                                   "brlt .+2" CR_TAB
3418                                   "rjmp %0") :
3419                     ("breq .+6" CR_TAB
3420                      "brlt .+4" CR_TAB
3421                      "jmp %0"));
3422     case GTU:
3423       return (len == 1 ? ("breq .+2" CR_TAB
3424                           "brsh %0") :
3425               len == 2 ? ("breq .+4" CR_TAB
3426                           "brlo .+2" CR_TAB
3427                           "rjmp %0") :
3428               ("breq .+6" CR_TAB
3429                "brlo .+4" CR_TAB
3430                "jmp %0"));
3431     case LE:
3432       if (cc_overflow_unusable)
3433           return (len == 1 ? ("breq %0" CR_TAB
3434                                   "brmi %0") :
3435                     len == 2 ? ("breq .+2" CR_TAB
3436                                   "brpl .+2" CR_TAB
3437                                   "rjmp %0") :
3438                     ("breq .+2" CR_TAB
3439                      "brpl .+4" CR_TAB
3440                      "jmp %0"));
3441       else
3442           return (len == 1 ? ("breq %0" CR_TAB
3443                                   "brlt %0") :
3444                     len == 2 ? ("breq .+2" CR_TAB
3445                                   "brge .+2" CR_TAB
3446                                   "rjmp %0") :
3447                     ("breq .+2" CR_TAB
3448                      "brge .+4" CR_TAB
3449                      "jmp %0"));
3450     case LEU:
3451       return (len == 1 ? ("breq %0" CR_TAB
3452                           "brlo %0") :
3453               len == 2 ? ("breq .+2" CR_TAB
3454                           "brsh .+2" CR_TAB
3455                                 "rjmp %0") :
3456               ("breq .+2" CR_TAB
3457                "brsh .+4" CR_TAB
3458                  "jmp %0"));
3459     default:
3460       if (reverse)
3461           {
3462             switch (len)
3463               {
3464               case 1:
3465                 return "br%k1 %0";
3466               case 2:
3467                 return ("br%j1 .+2" CR_TAB
3468                           "rjmp %0");
3469               default:
3470                 return ("br%j1 .+4" CR_TAB
3471                           "jmp %0");
3472               }
3473           }
3474       else
3475         {
3476           switch (len)
3477             {
3478             case 1:
3479               return "br%j1 %0";
3480             case 2:
3481               return ("br%k1 .+2" CR_TAB
3482                       "rjmp %0");
3483             default:
3484               return ("br%k1 .+4" CR_TAB
3485                       "jmp %0");
3486             }
3487         }
3488     }
3489   return "";
3490 }
3491 
3492 
3493 /* Worker function for `FINAL_PRESCAN_INSN'.  */
3494 /* Output insn cost for next insn.  */
3495 
3496 void
avr_final_prescan_insn(rtx_insn * insn,rtx * operand ATTRIBUTE_UNUSED,int num_operands ATTRIBUTE_UNUSED)3497 avr_final_prescan_insn (rtx_insn *insn, rtx *operand ATTRIBUTE_UNUSED,
3498                         int num_operands ATTRIBUTE_UNUSED)
3499 {
3500   if (avr_log.rtx_costs)
3501     {
3502       rtx set = single_set (insn);
3503 
3504       if (set)
3505         fprintf (asm_out_file, "/* DEBUG: cost = %d.  */\n",
3506                  set_src_cost (SET_SRC (set), GET_MODE (SET_DEST (set)),
3507                                      optimize_insn_for_speed_p ()));
3508       else
3509         fprintf (asm_out_file, "/* DEBUG: pattern-cost = %d.  */\n",
3510                  rtx_cost (PATTERN (insn), VOIDmode, INSN, 0,
3511                            optimize_insn_for_speed_p()));
3512     }
3513 
3514   if (avr_log.insn_addresses)
3515     fprintf (asm_out_file, ";; ADDR = %d\n",
3516              (int) INSN_ADDRESSES (INSN_UID (insn)));
3517 }
3518 
3519 
3520 /* Implement `TARGET_ASM_FINAL_POSTSCAN_INSN'.  */
3521 /* When GAS generates (parts of) ISR prologue / epilogue for us, we must
3522    hint GAS about the end of the code to scan.  There migh be code located
3523    after the last epilogue.  */
3524 
3525 static void
avr_asm_final_postscan_insn(FILE * stream,rtx_insn * insn,rtx *,int)3526 avr_asm_final_postscan_insn (FILE *stream, rtx_insn *insn, rtx*, int)
3527 {
3528   if (cfun->machine->gasisr.yes
3529       && !next_real_insn (insn))
3530     {
3531       app_disable();
3532       fprintf (stream, "\t__gcc_isr %d,r%d\n", GASISR_Done,
3533                cfun->machine->gasisr.regno);
3534     }
3535 }
3536 
3537 
3538 /* Worker function for `FUNCTION_ARG_REGNO_P'.  */
3539 /* Returns nonzero if REGNO is the number of a hard
3540    register in which function arguments are sometimes passed.  */
3541 
3542 int
avr_function_arg_regno_p(int r)3543 avr_function_arg_regno_p (int r)
3544 {
3545   return AVR_TINY ? IN_RANGE (r, 20, 25) : IN_RANGE (r, 8, 25);
3546 }
3547 
3548 
3549 /* Worker function for `INIT_CUMULATIVE_ARGS'.  */
3550 /* Initializing the variable cum for the state at the beginning
3551    of the argument list.  */
3552 
3553 void
avr_init_cumulative_args(CUMULATIVE_ARGS * cum,tree fntype,rtx libname,tree fndecl ATTRIBUTE_UNUSED)3554 avr_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
3555                           tree fndecl ATTRIBUTE_UNUSED)
3556 {
3557   cum->nregs = AVR_TINY ? 6 : 18;
3558   cum->regno = FIRST_CUM_REG;
3559   if (!libname && stdarg_p (fntype))
3560     cum->nregs = 0;
3561 
3562   /* Assume the calle may be tail called */
3563 
3564   cfun->machine->sibcall_fails = 0;
3565 }
3566 
3567 /* Returns the number of registers to allocate for a function argument.  */
3568 
3569 static int
avr_num_arg_regs(machine_mode mode,const_tree type)3570 avr_num_arg_regs (machine_mode mode, const_tree type)
3571 {
3572   int size;
3573 
3574   if (mode == BLKmode)
3575     size = int_size_in_bytes (type);
3576   else
3577     size = GET_MODE_SIZE (mode);
3578 
3579   /* Align all function arguments to start in even-numbered registers.
3580      Odd-sized arguments leave holes above them.  */
3581 
3582   return (size + 1) & ~1;
3583 }
3584 
3585 
3586 /* Implement `TARGET_FUNCTION_ARG'.  */
3587 /* Controls whether a function argument is passed
3588    in a register, and which register.  */
3589 
3590 static rtx
avr_function_arg(cumulative_args_t cum_v,const function_arg_info & arg)3591 avr_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
3592 {
3593   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
3594   int bytes = avr_num_arg_regs (arg.mode, arg.type);
3595 
3596   if (cum->nregs && bytes <= cum->nregs)
3597     return gen_rtx_REG (arg.mode, cum->regno - bytes);
3598 
3599   return NULL_RTX;
3600 }
3601 
3602 
3603 /* Implement `TARGET_FUNCTION_ARG_ADVANCE'.  */
3604 /* Update the summarizer variable CUM to advance past an argument
3605    in the argument list.  */
3606 
3607 static void
avr_function_arg_advance(cumulative_args_t cum_v,const function_arg_info & arg)3608 avr_function_arg_advance (cumulative_args_t cum_v,
3609                                 const function_arg_info &arg)
3610 {
3611   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
3612   int bytes = avr_num_arg_regs (arg.mode, arg.type);
3613 
3614   cum->nregs -= bytes;
3615   cum->regno -= bytes;
3616 
3617   /* A parameter is being passed in a call-saved register.  As the original
3618      contents of these regs has to be restored before leaving the function,
3619      a function must not pass arguments in call-saved regs in order to get
3620      tail-called.  */
3621 
3622   if (cum->regno >= 8
3623       && cum->nregs >= 0
3624       && !call_used_or_fixed_reg_p (cum->regno))
3625     {
3626       /* FIXME: We ship info on failing tail-call in struct machine_function.
3627          This uses internals of calls.cc:expand_call() and the way args_so_far
3628          is used.  targetm.function_ok_for_sibcall() needs to be extended to
3629          pass &args_so_far, too.  At present, CUMULATIVE_ARGS is target
3630          dependent so that such an extension is not wanted.  */
3631 
3632       cfun->machine->sibcall_fails = 1;
3633     }
3634 
3635   /* Test if all registers needed by the ABI are actually available.  If the
3636      user has fixed a GPR needed to pass an argument, an (implicit) function
3637      call will clobber that fixed register.  See PR45099 for an example.  */
3638 
3639   if (cum->regno >= 8
3640       && cum->nregs >= 0)
3641     {
3642       for (int regno = cum->regno; regno < cum->regno + bytes; regno++)
3643         if (fixed_regs[regno])
3644           warning (0, "fixed register %s used to pass parameter to function",
3645                    reg_names[regno]);
3646     }
3647 
3648   if (cum->nregs <= 0)
3649     {
3650       cum->nregs = 0;
3651       cum->regno = FIRST_CUM_REG;
3652     }
3653 }
3654 
3655 /* Implement `TARGET_FUNCTION_OK_FOR_SIBCALL' */
3656 /* Decide whether we can make a sibling call to a function.  DECL is the
3657    declaration of the function being targeted by the call and EXP is the
3658    CALL_EXPR representing the call.  */
3659 
3660 static bool
avr_function_ok_for_sibcall(tree decl_callee,tree exp_callee)3661 avr_function_ok_for_sibcall (tree decl_callee, tree exp_callee)
3662 {
3663   tree fntype_callee;
3664 
3665   /* Tail-calling must fail if callee-saved regs are used to pass
3666      function args.  We must not tail-call when `epilogue_restores'
3667      is used.  Unfortunately, we cannot tell at this point if that
3668      actually will happen or not, and we cannot step back from
3669      tail-calling.  Thus, we inhibit tail-calling with -mcall-prologues.  */
3670 
3671   if (cfun->machine->sibcall_fails
3672       || TARGET_CALL_PROLOGUES)
3673     {
3674       return false;
3675     }
3676 
3677   fntype_callee = TREE_TYPE (CALL_EXPR_FN (exp_callee));
3678 
3679   if (decl_callee)
3680     {
3681       decl_callee = TREE_TYPE (decl_callee);
3682     }
3683   else
3684     {
3685       decl_callee = fntype_callee;
3686 
3687       while (FUNCTION_TYPE != TREE_CODE (decl_callee)
3688              && METHOD_TYPE != TREE_CODE (decl_callee))
3689         {
3690           decl_callee = TREE_TYPE (decl_callee);
3691         }
3692     }
3693 
3694   /* Ensure that caller and callee have compatible epilogues */
3695 
3696   if (cfun->machine->is_interrupt
3697       || cfun->machine->is_signal
3698       || cfun->machine->is_naked
3699       || avr_naked_function_p (decl_callee))
3700     {
3701       return false;
3702     }
3703 
3704   return true;
3705 }
3706 
3707 /***********************************************************************
3708   Functions for outputting various mov's for a various modes
3709 ************************************************************************/
3710 
3711 /* Return true if a value of mode MODE is read from flash by
3712    __load_* function from libgcc.  */
3713 
3714 bool
avr_load_libgcc_p(rtx op)3715 avr_load_libgcc_p (rtx op)
3716 {
3717   machine_mode mode = GET_MODE (op);
3718   int n_bytes = GET_MODE_SIZE (mode);
3719 
3720   return (n_bytes > 2
3721           && !AVR_HAVE_LPMX
3722           && avr_mem_flash_p (op));
3723 }
3724 
3725 /* Return true if a value of mode MODE is read by __xload_* function.  */
3726 
3727 bool
avr_xload_libgcc_p(machine_mode mode)3728 avr_xload_libgcc_p (machine_mode mode)
3729 {
3730   int n_bytes = GET_MODE_SIZE (mode);
3731 
3732   return (n_bytes > 1
3733           || avr_n_flash > 1);
3734 }
3735 
3736 
3737 /* Fixme: This is a hack because secondary reloads don't works as expected.
3738 
3739    Find an unused d-register to be used as scratch in INSN.
3740    EXCLUDE is either NULL_RTX or some register. In the case where EXCLUDE
3741    is a register, skip all possible return values that overlap EXCLUDE.
3742    The policy for the returned register is similar to that of
3743    `reg_unused_after', i.e. the returned register may overlap the SET_DEST
3744    of INSN.
3745 
3746    Return a QImode d-register or NULL_RTX if nothing found.  */
3747 
3748 static rtx
avr_find_unused_d_reg(rtx_insn * insn,rtx exclude)3749 avr_find_unused_d_reg (rtx_insn *insn, rtx exclude)
3750 {
3751   bool isr_p = (avr_interrupt_function_p (current_function_decl)
3752                 || avr_signal_function_p (current_function_decl));
3753 
3754   for (int regno = 16; regno < 32; regno++)
3755     {
3756       rtx reg = all_regs_rtx[regno];
3757 
3758       if ((exclude
3759            && reg_overlap_mentioned_p (exclude, reg))
3760           || fixed_regs[regno])
3761         {
3762           continue;
3763         }
3764 
3765       /* Try non-live register */
3766 
3767       if (!df_regs_ever_live_p (regno)
3768           && (TREE_THIS_VOLATILE (current_function_decl)
3769               || cfun->machine->is_OS_task
3770               || cfun->machine->is_OS_main
3771               || (!isr_p && call_used_or_fixed_reg_p (regno))))
3772         {
3773           return reg;
3774         }
3775 
3776       /* Any live register can be used if it is unused after.
3777          Prologue/epilogue will care for it as needed.  */
3778 
3779       if (df_regs_ever_live_p (regno)
3780           && reg_unused_after (insn, reg))
3781         {
3782           return reg;
3783         }
3784     }
3785 
3786   return NULL_RTX;
3787 }
3788 
3789 
3790 /* Helper function for the next function in the case where only restricted
3791    version of LPM instruction is available.  */
3792 
3793 static const char*
avr_out_lpm_no_lpmx(rtx_insn * insn,rtx * xop,int * plen)3794 avr_out_lpm_no_lpmx (rtx_insn *insn, rtx *xop, int *plen)
3795 {
3796   rtx dest = xop[0];
3797   rtx addr = xop[1];
3798   int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
3799   int regno_dest;
3800 
3801   regno_dest = REGNO (dest);
3802 
3803   /* The implicit target register of LPM.  */
3804   xop[3] = lpm_reg_rtx;
3805 
3806   switch (GET_CODE (addr))
3807     {
3808     default:
3809       gcc_unreachable();
3810 
3811     case REG:
3812 
3813       gcc_assert (REG_Z == REGNO (addr));
3814 
3815       switch (n_bytes)
3816         {
3817         default:
3818           gcc_unreachable();
3819 
3820         case 1:
3821           avr_asm_len ("%4lpm", xop, plen, 1);
3822 
3823           if (regno_dest != LPM_REGNO)
3824             avr_asm_len ("mov %0,%3", xop, plen, 1);
3825 
3826           return "";
3827 
3828         case 2:
3829           if (REGNO (dest) == REG_Z)
3830             return avr_asm_len ("%4lpm"      CR_TAB
3831                                 "push %3"    CR_TAB
3832                                 "adiw %2,1"  CR_TAB
3833                                 "%4lpm"      CR_TAB
3834                                 "mov %B0,%3" CR_TAB
3835                                 "pop %A0", xop, plen, 6);
3836 
3837           avr_asm_len ("%4lpm"      CR_TAB
3838                        "mov %A0,%3" CR_TAB
3839                        "adiw %2,1"  CR_TAB
3840                        "%4lpm"      CR_TAB
3841                        "mov %B0,%3", xop, plen, 5);
3842 
3843           if (!reg_unused_after (insn, addr))
3844             avr_asm_len ("sbiw %2,1", xop, plen, 1);
3845 
3846           break; /* 2 */
3847         }
3848 
3849       break; /* REG */
3850 
3851     case POST_INC:
3852 
3853       gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
3854                   && n_bytes <= 4);
3855 
3856       if (regno_dest == LPM_REGNO)
3857         avr_asm_len ("%4lpm"      CR_TAB
3858                      "adiw %2,1", xop, plen, 2);
3859       else
3860         avr_asm_len ("%4lpm"      CR_TAB
3861                      "mov %A0,%3" CR_TAB
3862                      "adiw %2,1", xop, plen, 3);
3863 
3864       if (n_bytes >= 2)
3865         avr_asm_len ("%4lpm"      CR_TAB
3866                      "mov %B0,%3" CR_TAB
3867                      "adiw %2,1", xop, plen, 3);
3868 
3869       if (n_bytes >= 3)
3870         avr_asm_len ("%4lpm"      CR_TAB
3871                      "mov %C0,%3" CR_TAB
3872                      "adiw %2,1", xop, plen, 3);
3873 
3874       if (n_bytes >= 4)
3875         avr_asm_len ("%4lpm"      CR_TAB
3876                      "mov %D0,%3" CR_TAB
3877                      "adiw %2,1", xop, plen, 3);
3878 
3879       break; /* POST_INC */
3880 
3881     } /* switch CODE (addr) */
3882 
3883   return "";
3884 }
3885 
3886 
3887 /* If PLEN == NULL: Ouput instructions to load a value from a memory location
3888    OP[1] in AS1 to register OP[0].
3889    If PLEN != 0 set *PLEN to the length in words of the instruction sequence.
3890    Return "".  */
3891 
3892 const char*
avr_out_lpm(rtx_insn * insn,rtx * op,int * plen)3893 avr_out_lpm (rtx_insn *insn, rtx *op, int *plen)
3894 {
3895   rtx xop[7];
3896   rtx dest = op[0];
3897   rtx src = SET_SRC (single_set (insn));
3898   rtx addr;
3899   int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
3900   int segment;
3901   RTX_CODE code;
3902   addr_space_t as = MEM_ADDR_SPACE (src);
3903 
3904   if (plen)
3905     *plen = 0;
3906 
3907   if (MEM_P (dest))
3908     {
3909       warning (0, "writing to address space %qs not supported",
3910                avr_addrspace[MEM_ADDR_SPACE (dest)].name);
3911 
3912       return "";
3913     }
3914 
3915   addr = XEXP (src, 0);
3916   code = GET_CODE (addr);
3917 
3918   gcc_assert (REG_P (dest));
3919   gcc_assert (REG == code || POST_INC == code);
3920 
3921   xop[0] = dest;
3922   xop[1] = addr;
3923   xop[2] = lpm_addr_reg_rtx;
3924   xop[4] = xstring_empty;
3925   xop[5] = tmp_reg_rtx;
3926   xop[6] = XEXP (rampz_rtx, 0);
3927 
3928   segment = avr_addrspace[as].segment;
3929 
3930   /* Set RAMPZ as needed.  */
3931 
3932   if (segment)
3933     {
3934       xop[4] = GEN_INT (segment);
3935       xop[3] = avr_find_unused_d_reg (insn, lpm_addr_reg_rtx);
3936 
3937       if (xop[3] != NULL_RTX)
3938         {
3939           avr_asm_len ("ldi %3,%4" CR_TAB
3940                        "out %i6,%3", xop, plen, 2);
3941         }
3942       else if (segment == 1)
3943         {
3944           avr_asm_len ("clr %5" CR_TAB
3945                        "inc %5" CR_TAB
3946                        "out %i6,%5", xop, plen, 3);
3947         }
3948       else
3949         {
3950           avr_asm_len ("mov %5,%2"   CR_TAB
3951                        "ldi %2,%4"   CR_TAB
3952                        "out %i6,%2"  CR_TAB
3953                        "mov %2,%5", xop, plen, 4);
3954         }
3955 
3956       xop[4] = xstring_e;
3957 
3958       if (!AVR_HAVE_ELPMX)
3959         return avr_out_lpm_no_lpmx (insn, xop, plen);
3960     }
3961   else if (!AVR_HAVE_LPMX)
3962     {
3963       return avr_out_lpm_no_lpmx (insn, xop, plen);
3964     }
3965 
3966   /* We have [E]LPMX: Output reading from Flash the comfortable way.  */
3967 
3968   switch (GET_CODE (addr))
3969     {
3970     default:
3971       gcc_unreachable();
3972 
3973     case REG:
3974 
3975       gcc_assert (REG_Z == REGNO (addr));
3976 
3977       switch (n_bytes)
3978         {
3979         default:
3980           gcc_unreachable();
3981 
3982         case 1:
3983           avr_asm_len ("%4lpm %0,%a2", xop, plen, 1);
3984           break;
3985 
3986         case 2:
3987           if (REGNO (dest) == REG_Z)
3988             avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3989                          "%4lpm %B0,%a2" CR_TAB
3990                          "mov %A0,%5", xop, plen, 3);
3991           else
3992             {
3993               avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3994                            "%4lpm %B0,%a2", xop, plen, 2);
3995 
3996               if (!reg_unused_after (insn, addr))
3997                 avr_asm_len ("sbiw %2,1", xop, plen, 1);
3998             }
3999 
4000           break; /* 2 */
4001 
4002         case 3:
4003 
4004           avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
4005                        "%4lpm %B0,%a2+" CR_TAB
4006                        "%4lpm %C0,%a2", xop, plen, 3);
4007 
4008           if (!reg_unused_after (insn, addr))
4009             avr_asm_len ("sbiw %2,2", xop, plen, 1);
4010 
4011           break; /* 3 */
4012 
4013         case 4:
4014 
4015           avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
4016                        "%4lpm %B0,%a2+", xop, plen, 2);
4017 
4018           if (REGNO (dest) == REG_Z - 2)
4019             avr_asm_len ("%4lpm %5,%a2+" CR_TAB
4020                          "%4lpm %C0,%a2" CR_TAB
4021                          "mov %D0,%5", xop, plen, 3);
4022           else
4023             {
4024               avr_asm_len ("%4lpm %C0,%a2+" CR_TAB
4025                            "%4lpm %D0,%a2", xop, plen, 2);
4026 
4027               if (!reg_unused_after (insn, addr))
4028                 avr_asm_len ("sbiw %2,3", xop, plen, 1);
4029             }
4030 
4031           break; /* 4 */
4032         } /* n_bytes */
4033 
4034       break; /* REG */
4035 
4036     case POST_INC:
4037 
4038       gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
4039                   && n_bytes <= 4);
4040 
4041       avr_asm_len                    ("%4lpm %A0,%a2+", xop, plen, 1);
4042       if (n_bytes >= 2)  avr_asm_len ("%4lpm %B0,%a2+", xop, plen, 1);
4043       if (n_bytes >= 3)  avr_asm_len ("%4lpm %C0,%a2+", xop, plen, 1);
4044       if (n_bytes >= 4)  avr_asm_len ("%4lpm %D0,%a2+", xop, plen, 1);
4045 
4046       break; /* POST_INC */
4047 
4048     } /* switch CODE (addr) */
4049 
4050   if (xop[4] == xstring_e && AVR_HAVE_RAMPD)
4051     {
4052       /* Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM.  */
4053 
4054       xop[0] = zero_reg_rtx;
4055       avr_asm_len ("out %i6,%0", xop, plen, 1);
4056     }
4057 
4058   return "";
4059 }
4060 
4061 
4062 /* Worker function for xload_8 insn.  */
4063 
4064 const char*
avr_out_xload(rtx_insn * insn ATTRIBUTE_UNUSED,rtx * op,int * plen)4065 avr_out_xload (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
4066 {
4067   rtx xop[4];
4068 
4069   xop[0] = op[0];
4070   xop[1] = op[1];
4071   xop[2] = lpm_addr_reg_rtx;
4072   xop[3] = AVR_HAVE_LPMX ? op[0] : lpm_reg_rtx;
4073 
4074   avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, -1);
4075 
4076   avr_asm_len ("sbrc %1,7" CR_TAB
4077                "ld %3,%a2", xop, plen, 2);
4078 
4079   if (REGNO (xop[0]) != REGNO (xop[3]))
4080     avr_asm_len ("mov %0,%3", xop, plen, 1);
4081 
4082   return "";
4083 }
4084 
4085 
4086 const char*
output_movqi(rtx_insn * insn,rtx operands[],int * plen)4087 output_movqi (rtx_insn *insn, rtx operands[], int *plen)
4088 {
4089   rtx dest = operands[0];
4090   rtx src = operands[1];
4091 
4092   if (avr_mem_flash_p (src)
4093       || avr_mem_flash_p (dest))
4094     {
4095       return avr_out_lpm (insn, operands, plen);
4096     }
4097 
4098   gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 1);
4099 
4100   if (REG_P (dest))
4101     {
4102       if (REG_P (src)) /* mov r,r */
4103         {
4104           if (test_hard_reg_class (STACK_REG, dest))
4105             return avr_asm_len ("out %0,%1", operands, plen, -1);
4106           else if (test_hard_reg_class (STACK_REG, src))
4107             return avr_asm_len ("in %0,%1", operands, plen, -1);
4108 
4109           return avr_asm_len ("mov %0,%1", operands, plen, -1);
4110         }
4111       else if (CONSTANT_P (src))
4112         {
4113           output_reload_in_const (operands, NULL_RTX, plen, false);
4114           return "";
4115         }
4116       else if (MEM_P (src))
4117         return out_movqi_r_mr (insn, operands, plen); /* mov r,m */
4118     }
4119   else if (MEM_P (dest))
4120     {
4121       rtx xop[2];
4122 
4123       xop[0] = dest;
4124       xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
4125 
4126       return out_movqi_mr_r (insn, xop, plen);
4127     }
4128 
4129   return "";
4130 }
4131 
4132 
4133 const char *
output_movhi(rtx_insn * insn,rtx xop[],int * plen)4134 output_movhi (rtx_insn *insn, rtx xop[], int *plen)
4135 {
4136   rtx dest = xop[0];
4137   rtx src = xop[1];
4138 
4139   gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 2);
4140 
4141   if (avr_mem_flash_p (src)
4142       || avr_mem_flash_p (dest))
4143     {
4144       return avr_out_lpm (insn, xop, plen);
4145     }
4146 
4147   if (REG_P (dest))
4148     {
4149       if (REG_P (src)) /* mov r,r */
4150         {
4151           if (test_hard_reg_class (STACK_REG, dest))
4152             {
4153               if (AVR_HAVE_8BIT_SP)
4154                 return avr_asm_len ("out __SP_L__,%A1", xop, plen, -1);
4155 
4156               if (AVR_XMEGA)
4157                 return avr_asm_len ("out __SP_L__,%A1" CR_TAB
4158                                     "out __SP_H__,%B1", xop, plen, -2);
4159 
4160               /* Use simple load of SP if no interrupts are  used.  */
4161 
4162               return TARGET_NO_INTERRUPTS
4163                 ? avr_asm_len ("out __SP_H__,%B1" CR_TAB
4164                                "out __SP_L__,%A1", xop, plen, -2)
4165                 : avr_asm_len ("in __tmp_reg__,__SREG__"  CR_TAB
4166                                "cli"                      CR_TAB
4167                                "out __SP_H__,%B1"         CR_TAB
4168                                "out __SREG__,__tmp_reg__" CR_TAB
4169                                "out __SP_L__,%A1", xop, plen, -5);
4170             }
4171           else if (test_hard_reg_class (STACK_REG, src))
4172             {
4173               return !AVR_HAVE_SPH
4174                 ? avr_asm_len ("in %A0,__SP_L__" CR_TAB
4175                                "clr %B0", xop, plen, -2)
4176 
4177                 : avr_asm_len ("in %A0,__SP_L__" CR_TAB
4178                                "in %B0,__SP_H__", xop, plen, -2);
4179             }
4180 
4181           return AVR_HAVE_MOVW
4182             ? avr_asm_len ("movw %0,%1", xop, plen, -1)
4183 
4184             : avr_asm_len ("mov %A0,%A1" CR_TAB
4185                            "mov %B0,%B1", xop, plen, -2);
4186         } /* REG_P (src) */
4187       else if (CONSTANT_P (src))
4188         {
4189           return output_reload_inhi (xop, NULL, plen);
4190         }
4191       else if (MEM_P (src))
4192         {
4193           return out_movhi_r_mr (insn, xop, plen); /* mov r,m */
4194         }
4195     }
4196   else if (MEM_P (dest))
4197     {
4198       rtx xop[2];
4199 
4200       xop[0] = dest;
4201       xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
4202 
4203       return out_movhi_mr_r (insn, xop, plen);
4204     }
4205 
4206   fatal_insn ("invalid insn:", insn);
4207 
4208   return "";
4209 }
4210 
4211 
4212 /* Same as out_movqi_r_mr, but TINY does not have ADIW or SBIW */
4213 
4214 static const char*
avr_out_movqi_r_mr_reg_disp_tiny(rtx_insn * insn,rtx op[],int * plen)4215 avr_out_movqi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
4216 {
4217   rtx dest = op[0];
4218   rtx src = op[1];
4219   rtx x = XEXP (src, 0);
4220 
4221   avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4222                "ld %0,%b1" , op, plen, -3);
4223 
4224   if (!reg_overlap_mentioned_p (dest, XEXP (x, 0))
4225       && !reg_unused_after (insn, XEXP (x, 0)))
4226     avr_asm_len (TINY_SBIW (%I1, %J1, %o1), op, plen, 2);
4227 
4228   return "";
4229 }
4230 
4231 static const char*
out_movqi_r_mr(rtx_insn * insn,rtx op[],int * plen)4232 out_movqi_r_mr (rtx_insn *insn, rtx op[], int *plen)
4233 {
4234   rtx dest = op[0];
4235   rtx src = op[1];
4236   rtx x = XEXP (src, 0);
4237 
4238   if (CONSTANT_ADDRESS_P (x))
4239     {
4240       int n_words = AVR_TINY ? 1 : 2;
4241       return io_address_operand (x, QImode)
4242         ? avr_asm_len ("in %0,%i1", op, plen, -1)
4243         : avr_asm_len ("lds %0,%m1", op, plen, -n_words);
4244     }
4245 
4246   if (GET_CODE (x) == PLUS
4247       && REG_P (XEXP (x, 0))
4248       && CONST_INT_P (XEXP (x, 1)))
4249     {
4250       /* memory access by reg+disp */
4251 
4252       int disp = INTVAL (XEXP (x, 1));
4253 
4254       if (AVR_TINY)
4255         return avr_out_movqi_r_mr_reg_disp_tiny (insn, op, plen);
4256 
4257       if (disp - GET_MODE_SIZE (GET_MODE (src)) >= 63)
4258         {
4259           if (REGNO (XEXP (x, 0)) != REG_Y)
4260             fatal_insn ("incorrect insn:",insn);
4261 
4262           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
4263             return avr_asm_len ("adiw r28,%o1-63" CR_TAB
4264                                 "ldd %0,Y+63"     CR_TAB
4265                                 "sbiw r28,%o1-63", op, plen, -3);
4266 
4267           return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
4268                               "sbci r29,hi8(-%o1)" CR_TAB
4269                               "ld %0,Y"            CR_TAB
4270                               "subi r28,lo8(%o1)"  CR_TAB
4271                               "sbci r29,hi8(%o1)", op, plen, -5);
4272         }
4273       else if (REGNO (XEXP (x, 0)) == REG_X)
4274         {
4275           /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
4276              it but I have this situation with extremal optimizing options.  */
4277 
4278           avr_asm_len ("adiw r26,%o1" CR_TAB
4279                        "ld %0,X", op, plen, -2);
4280 
4281           if (!reg_overlap_mentioned_p (dest, XEXP (x, 0))
4282               && !reg_unused_after (insn, XEXP (x, 0)))
4283             {
4284               avr_asm_len ("sbiw r26,%o1", op, plen, 1);
4285             }
4286 
4287           return "";
4288         }
4289 
4290       return avr_asm_len ("ldd %0,%1", op, plen, -1);
4291     }
4292 
4293   return avr_asm_len ("ld %0,%1", op, plen, -1);
4294 }
4295 
4296 
4297 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
4298 
4299 static const char*
avr_out_movhi_r_mr_reg_no_disp_tiny(rtx_insn * insn,rtx op[],int * plen)4300 avr_out_movhi_r_mr_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
4301 {
4302   rtx dest = op[0];
4303   rtx src = op[1];
4304   rtx base = XEXP (src, 0);
4305 
4306   int reg_dest = true_regnum (dest);
4307   int reg_base = true_regnum (base);
4308 
4309   if (reg_dest == reg_base)         /* R = (R) */
4310     return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
4311                               "ld %B0,%1"          CR_TAB
4312                               "mov %A0,__tmp_reg__", op, plen, -3);
4313 
4314   avr_asm_len ("ld %A0,%1+" CR_TAB
4315                "ld %B0,%1", op, plen, -2);
4316 
4317   if (!reg_unused_after (insn, base))
4318     avr_asm_len (TINY_SBIW (%E1, %F1, 1), op, plen, 2);
4319 
4320   return "";
4321 }
4322 
4323 
4324 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
4325 
4326 static const char*
avr_out_movhi_r_mr_reg_disp_tiny(rtx_insn * insn,rtx op[],int * plen)4327 avr_out_movhi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
4328 {
4329   rtx dest = op[0];
4330   rtx src = op[1];
4331   rtx base = XEXP (src, 0);
4332 
4333   int reg_dest = true_regnum (dest);
4334   int reg_base = true_regnum (XEXP (base, 0));
4335 
4336   if (reg_base == reg_dest)
4337     {
4338       return avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4339                           "ld __tmp_reg__,%b1+"     CR_TAB
4340                           "ld %B0,%b1"              CR_TAB
4341                           "mov %A0,__tmp_reg__", op, plen, -5);
4342     }
4343   else
4344     {
4345       avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4346                    "ld %A0,%b1+"             CR_TAB
4347                    "ld %B0,%b1", op, plen, -4);
4348 
4349       if (!reg_unused_after (insn, XEXP (base, 0)))
4350         avr_asm_len (TINY_SBIW (%I1, %J1, %o1+1), op, plen, 2);
4351 
4352       return "";
4353     }
4354 }
4355 
4356 
4357 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
4358 
4359 static const char*
avr_out_movhi_r_mr_pre_dec_tiny(rtx_insn * insn,rtx op[],int * plen)4360 avr_out_movhi_r_mr_pre_dec_tiny (rtx_insn *insn, rtx op[], int *plen)
4361 {
4362   int mem_volatile_p = 0;
4363   rtx dest = op[0];
4364   rtx src = op[1];
4365   rtx base = XEXP (src, 0);
4366 
4367   /* "volatile" forces reading low byte first, even if less efficient,
4368      for correct operation with 16-bit I/O registers.  */
4369   mem_volatile_p = MEM_VOLATILE_P (src);
4370 
4371   if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
4372     fatal_insn ("incorrect insn:", insn);
4373 
4374   if (!mem_volatile_p)
4375     return avr_asm_len ("ld %B0,%1" CR_TAB
4376                         "ld %A0,%1", op, plen, -2);
4377 
4378   return avr_asm_len (TINY_SBIW (%I1, %J1, 2)  CR_TAB
4379                       "ld %A0,%p1+"            CR_TAB
4380                       "ld %B0,%p1"             CR_TAB
4381                       TINY_SBIW (%I1, %J1, 1), op, plen, -6);
4382 }
4383 
4384 
4385 static const char*
out_movhi_r_mr(rtx_insn * insn,rtx op[],int * plen)4386 out_movhi_r_mr (rtx_insn *insn, rtx op[], int *plen)
4387 {
4388   rtx dest = op[0];
4389   rtx src = op[1];
4390   rtx base = XEXP (src, 0);
4391   int reg_dest = true_regnum (dest);
4392   int reg_base = true_regnum (base);
4393   /* "volatile" forces reading low byte first, even if less efficient,
4394      for correct operation with 16-bit I/O registers.  */
4395   int mem_volatile_p = MEM_VOLATILE_P (src);
4396 
4397   if (reg_base > 0)
4398     {
4399       if (AVR_TINY)
4400         return avr_out_movhi_r_mr_reg_no_disp_tiny (insn, op, plen);
4401 
4402       if (reg_dest == reg_base)         /* R = (R) */
4403         return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
4404                             "ld %B0,%1"          CR_TAB
4405                             "mov %A0,__tmp_reg__", op, plen, -3);
4406 
4407       if (reg_base != REG_X)
4408         return avr_asm_len ("ld %A0,%1" CR_TAB
4409                             "ldd %B0,%1+1", op, plen, -2);
4410 
4411       avr_asm_len ("ld %A0,X+" CR_TAB
4412                    "ld %B0,X", op, plen, -2);
4413 
4414       if (!reg_unused_after (insn, base))
4415         avr_asm_len ("sbiw r26,1", op, plen, 1);
4416 
4417       return "";
4418     }
4419   else if (GET_CODE (base) == PLUS) /* (R + i) */
4420     {
4421       int disp = INTVAL (XEXP (base, 1));
4422       int reg_base = true_regnum (XEXP (base, 0));
4423 
4424       if (AVR_TINY)
4425         return avr_out_movhi_r_mr_reg_disp_tiny (insn, op, plen);
4426 
4427       if (disp > MAX_LD_OFFSET (GET_MODE (src)))
4428         {
4429           if (REGNO (XEXP (base, 0)) != REG_Y)
4430             fatal_insn ("incorrect insn:",insn);
4431 
4432           return disp <= 63 + MAX_LD_OFFSET (GET_MODE (src))
4433             ? avr_asm_len ("adiw r28,%o1-62" CR_TAB
4434                            "ldd %A0,Y+62"    CR_TAB
4435                            "ldd %B0,Y+63"    CR_TAB
4436                            "sbiw r28,%o1-62", op, plen, -4)
4437 
4438             : avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
4439                            "sbci r29,hi8(-%o1)" CR_TAB
4440                            "ld %A0,Y"           CR_TAB
4441                            "ldd %B0,Y+1"        CR_TAB
4442                            "subi r28,lo8(%o1)"  CR_TAB
4443                            "sbci r29,hi8(%o1)", op, plen, -6);
4444         }
4445 
4446       /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
4447          it but I have this situation with extremal
4448          optimization options.  */
4449 
4450       if (reg_base == REG_X)
4451         {
4452           if (reg_base == reg_dest)
4453             return avr_asm_len ("adiw r26,%o1"      CR_TAB
4454                                 "ld __tmp_reg__,X+" CR_TAB
4455                                 "ld %B0,X"          CR_TAB
4456                                 "mov %A0,__tmp_reg__", op, plen, -4);
4457 
4458           avr_asm_len ("adiw r26,%o1" CR_TAB
4459                        "ld %A0,X+"    CR_TAB
4460                        "ld %B0,X", op, plen, -3);
4461 
4462           if (!reg_unused_after (insn, XEXP (base, 0)))
4463             avr_asm_len ("sbiw r26,%o1+1", op, plen, 1);
4464 
4465           return "";
4466         }
4467 
4468       return reg_base == reg_dest
4469         ? avr_asm_len ("ldd __tmp_reg__,%A1" CR_TAB
4470                        "ldd %B0,%B1"         CR_TAB
4471                        "mov %A0,__tmp_reg__", op, plen, -3)
4472 
4473         : avr_asm_len ("ldd %A0,%A1" CR_TAB
4474                        "ldd %B0,%B1", op, plen, -2);
4475     }
4476   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4477     {
4478       if (AVR_TINY)
4479           return avr_out_movhi_r_mr_pre_dec_tiny (insn, op, plen);
4480 
4481       if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
4482         fatal_insn ("incorrect insn:", insn);
4483 
4484       if (!mem_volatile_p)
4485         return avr_asm_len ("ld %B0,%1" CR_TAB
4486                             "ld %A0,%1", op, plen, -2);
4487 
4488       return REGNO (XEXP (base, 0)) == REG_X
4489         ? avr_asm_len ("sbiw r26,2"  CR_TAB
4490                        "ld %A0,X+"   CR_TAB
4491                        "ld %B0,X"    CR_TAB
4492                        "sbiw r26,1", op, plen, -4)
4493 
4494         : avr_asm_len ("sbiw %r1,2"  CR_TAB
4495                        "ld %A0,%p1"  CR_TAB
4496                        "ldd %B0,%p1+1", op, plen, -3);
4497     }
4498   else if (GET_CODE (base) == POST_INC) /* (R++) */
4499     {
4500       if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
4501         fatal_insn ("incorrect insn:", insn);
4502 
4503       return avr_asm_len ("ld %A0,%1"  CR_TAB
4504                           "ld %B0,%1", op, plen, -2);
4505     }
4506   else if (CONSTANT_ADDRESS_P (base))
4507     {
4508       int n_words = AVR_TINY ? 2 : 4;
4509       return io_address_operand (base, HImode)
4510         ? avr_asm_len ("in %A0,%i1" CR_TAB
4511                        "in %B0,%i1+1", op, plen, -2)
4512 
4513         : avr_asm_len ("lds %A0,%m1" CR_TAB
4514                        "lds %B0,%m1+1", op, plen, -n_words);
4515     }
4516 
4517   fatal_insn ("unknown move insn:",insn);
4518   return "";
4519 }
4520 
4521 static const char*
avr_out_movsi_r_mr_reg_no_disp_tiny(rtx_insn * insn,rtx op[],int * l)4522 avr_out_movsi_r_mr_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *l)
4523 {
4524   rtx dest = op[0];
4525   rtx src = op[1];
4526   rtx base = XEXP (src, 0);
4527   int reg_dest = true_regnum (dest);
4528   int reg_base = true_regnum (base);
4529 
4530   if (reg_dest == reg_base)
4531     {
4532       /* "ld r26,-X" is undefined */
4533       return *l = 9, (TINY_ADIW (%E1, %F1, 3) CR_TAB
4534                           "ld %D0,%1"             CR_TAB
4535                           "ld %C0,-%1"            CR_TAB
4536                           "ld __tmp_reg__,-%1"    CR_TAB
4537                           TINY_SBIW (%E1, %F1, 1) CR_TAB
4538                           "ld %A0,%1"             CR_TAB
4539                           "mov %B0,__tmp_reg__");
4540     }
4541   else if (reg_dest == reg_base - 2)
4542     {
4543       return *l = 5, ("ld %A0,%1+"            CR_TAB
4544                           "ld %B0,%1+"            CR_TAB
4545                           "ld __tmp_reg__,%1+"    CR_TAB
4546                           "ld %D0,%1"             CR_TAB
4547                           "mov %C0,__tmp_reg__");
4548     }
4549   else if (reg_unused_after (insn, base))
4550     {
4551       return *l = 4, ("ld %A0,%1+"    CR_TAB
4552                           "ld %B0,%1+"    CR_TAB
4553                           "ld %C0,%1+"    CR_TAB
4554                           "ld %D0,%1");
4555     }
4556   else
4557     {
4558       return *l = 6, ("ld %A0,%1+"    CR_TAB
4559                           "ld %B0,%1+"    CR_TAB
4560                           "ld %C0,%1+"    CR_TAB
4561                           "ld %D0,%1"     CR_TAB
4562                           TINY_SBIW (%E1, %F1, 3));
4563     }
4564 }
4565 
4566 
4567 static const char*
avr_out_movsi_r_mr_reg_disp_tiny(rtx_insn * insn,rtx op[],int * l)4568 avr_out_movsi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *l)
4569 {
4570   rtx dest = op[0];
4571   rtx src = op[1];
4572   rtx base = XEXP (src, 0);
4573   int reg_dest = true_regnum (dest);
4574   int reg_base = true_regnum (XEXP (base, 0));
4575 
4576   if (reg_dest == reg_base)
4577     {
4578       /* "ld r26,-X" is undefined */
4579       return *l = 9, (TINY_ADIW (%I1, %J1, %o1+3) CR_TAB
4580                       "ld %D0,%b1"                CR_TAB
4581                       "ld %C0,-%b1"               CR_TAB
4582                       "ld __tmp_reg__,-%b1"       CR_TAB
4583                       TINY_SBIW (%I1, %J1, 1)     CR_TAB
4584                       "ld %A0,%b1"                CR_TAB
4585                       "mov %B0,__tmp_reg__");
4586     }
4587   else if (reg_dest == reg_base - 2)
4588     {
4589       return *l = 7, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4590                       "ld %A0,%b1+"             CR_TAB
4591                       "ld %B0,%b1+"             CR_TAB
4592                       "ld __tmp_reg__,%b1+"     CR_TAB
4593                       "ld %D0,%b1"              CR_TAB
4594                       "mov %C0,__tmp_reg__");
4595     }
4596   else if (reg_unused_after (insn, XEXP (base, 0)))
4597     {
4598       return *l = 6, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4599                       "ld %A0,%b1+"             CR_TAB
4600                       "ld %B0,%b1+"             CR_TAB
4601                       "ld %C0,%b1+"             CR_TAB
4602                       "ld %D0,%b1");
4603     }
4604   else
4605     {
4606       return *l = 8, (TINY_ADIW (%I1, %J1, %o1)  CR_TAB
4607                       "ld %A0,%b1+"              CR_TAB
4608                       "ld %B0,%b1+"              CR_TAB
4609                       "ld %C0,%b1+"              CR_TAB
4610                       "ld %D0,%b1"               CR_TAB
4611                       TINY_SBIW (%I1, %J1, %o1+3));
4612     }
4613 }
4614 
4615 static const char*
out_movsi_r_mr(rtx_insn * insn,rtx op[],int * l)4616 out_movsi_r_mr (rtx_insn *insn, rtx op[], int *l)
4617 {
4618   rtx dest = op[0];
4619   rtx src = op[1];
4620   rtx base = XEXP (src, 0);
4621   int reg_dest = true_regnum (dest);
4622   int reg_base = true_regnum (base);
4623   int tmp;
4624 
4625   if (!l)
4626     l = &tmp;
4627 
4628   if (reg_base > 0)
4629     {
4630       if (AVR_TINY)
4631         return avr_out_movsi_r_mr_reg_no_disp_tiny (insn, op, l);
4632 
4633       if (reg_base == REG_X)        /* (R26) */
4634         {
4635           if (reg_dest == REG_X)
4636               /* "ld r26,-X" is undefined */
4637               return *l=7, ("adiw r26,3"        CR_TAB
4638                                 "ld r29,X"          CR_TAB
4639                                 "ld r28,-X"         CR_TAB
4640                                 "ld __tmp_reg__,-X" CR_TAB
4641                                 "sbiw r26,1"        CR_TAB
4642                                 "ld r26,X"          CR_TAB
4643                                 "mov r27,__tmp_reg__");
4644           else if (reg_dest == REG_X - 2)
4645             return *l=5, ("ld %A0,X+"          CR_TAB
4646                           "ld %B0,X+"          CR_TAB
4647                           "ld __tmp_reg__,X+"  CR_TAB
4648                           "ld %D0,X"           CR_TAB
4649                           "mov %C0,__tmp_reg__");
4650           else if (reg_unused_after (insn, base))
4651             return  *l=4, ("ld %A0,X+" CR_TAB
4652                            "ld %B0,X+" CR_TAB
4653                            "ld %C0,X+" CR_TAB
4654                            "ld %D0,X");
4655           else
4656             return  *l=5, ("ld %A0,X+" CR_TAB
4657                            "ld %B0,X+" CR_TAB
4658                            "ld %C0,X+" CR_TAB
4659                            "ld %D0,X"  CR_TAB
4660                            "sbiw r26,3");
4661         }
4662       else
4663         {
4664           if (reg_dest == reg_base)
4665             return *l=5, ("ldd %D0,%1+3" CR_TAB
4666                           "ldd %C0,%1+2" CR_TAB
4667                           "ldd __tmp_reg__,%1+1"  CR_TAB
4668                           "ld %A0,%1"  CR_TAB
4669                           "mov %B0,__tmp_reg__");
4670           else if (reg_base == reg_dest + 2)
4671             return *l=5, ("ld %A0,%1"             CR_TAB
4672                           "ldd %B0,%1+1"          CR_TAB
4673                           "ldd __tmp_reg__,%1+2"  CR_TAB
4674                           "ldd %D0,%1+3"          CR_TAB
4675                           "mov %C0,__tmp_reg__");
4676           else
4677             return *l=4, ("ld %A0,%1"    CR_TAB
4678                           "ldd %B0,%1+1" CR_TAB
4679                           "ldd %C0,%1+2" CR_TAB
4680                           "ldd %D0,%1+3");
4681         }
4682     }
4683   else if (GET_CODE (base) == PLUS) /* (R + i) */
4684     {
4685       int disp = INTVAL (XEXP (base, 1));
4686 
4687       if (AVR_TINY)
4688         return avr_out_movsi_r_mr_reg_disp_tiny (insn, op, l);
4689 
4690       if (disp > MAX_LD_OFFSET (GET_MODE (src)))
4691           {
4692             if (REGNO (XEXP (base, 0)) != REG_Y)
4693               fatal_insn ("incorrect insn:",insn);
4694 
4695             if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
4696               return *l = 6, ("adiw r28,%o1-60" CR_TAB
4697                                   "ldd %A0,Y+60"    CR_TAB
4698                                   "ldd %B0,Y+61"    CR_TAB
4699                                   "ldd %C0,Y+62"    CR_TAB
4700                                   "ldd %D0,Y+63"    CR_TAB
4701                                   "sbiw r28,%o1-60");
4702 
4703             return *l = 8, ("subi r28,lo8(-%o1)" CR_TAB
4704                                 "sbci r29,hi8(-%o1)" CR_TAB
4705                                 "ld %A0,Y"           CR_TAB
4706                                 "ldd %B0,Y+1"        CR_TAB
4707                                 "ldd %C0,Y+2"        CR_TAB
4708                                 "ldd %D0,Y+3"        CR_TAB
4709                                 "subi r28,lo8(%o1)"  CR_TAB
4710                                 "sbci r29,hi8(%o1)");
4711           }
4712 
4713       reg_base = true_regnum (XEXP (base, 0));
4714       if (reg_base == REG_X)
4715           {
4716             /* R = (X + d) */
4717             if (reg_dest == REG_X)
4718               {
4719                 *l = 7;
4720                 /* "ld r26,-X" is undefined */
4721                 return ("adiw r26,%o1+3"    CR_TAB
4722                           "ld r29,X"          CR_TAB
4723                           "ld r28,-X"         CR_TAB
4724                           "ld __tmp_reg__,-X" CR_TAB
4725                           "sbiw r26,1"        CR_TAB
4726                           "ld r26,X"          CR_TAB
4727                           "mov r27,__tmp_reg__");
4728               }
4729             *l = 6;
4730             if (reg_dest == REG_X - 2)
4731               return ("adiw r26,%o1"      CR_TAB
4732                         "ld r24,X+"         CR_TAB
4733                         "ld r25,X+"         CR_TAB
4734                         "ld __tmp_reg__,X+" CR_TAB
4735                         "ld r27,X"          CR_TAB
4736                         "mov r26,__tmp_reg__");
4737 
4738             return ("adiw r26,%o1" CR_TAB
4739                       "ld %A0,X+"    CR_TAB
4740                       "ld %B0,X+"    CR_TAB
4741                       "ld %C0,X+"    CR_TAB
4742                       "ld %D0,X"     CR_TAB
4743                       "sbiw r26,%o1+3");
4744           }
4745       if (reg_dest == reg_base)
4746         return *l=5, ("ldd %D0,%D1"          CR_TAB
4747                       "ldd %C0,%C1"          CR_TAB
4748                       "ldd __tmp_reg__,%B1"  CR_TAB
4749                       "ldd %A0,%A1"          CR_TAB
4750                       "mov %B0,__tmp_reg__");
4751       else if (reg_dest == reg_base - 2)
4752         return *l=5, ("ldd %A0,%A1"          CR_TAB
4753                       "ldd %B0,%B1"          CR_TAB
4754                       "ldd __tmp_reg__,%C1"  CR_TAB
4755                       "ldd %D0,%D1"          CR_TAB
4756                       "mov %C0,__tmp_reg__");
4757       return *l=4, ("ldd %A0,%A1" CR_TAB
4758                     "ldd %B0,%B1" CR_TAB
4759                     "ldd %C0,%C1" CR_TAB
4760                     "ldd %D0,%D1");
4761     }
4762   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4763     return *l=4, ("ld %D0,%1" CR_TAB
4764                       "ld %C0,%1" CR_TAB
4765                       "ld %B0,%1" CR_TAB
4766                       "ld %A0,%1");
4767   else if (GET_CODE (base) == POST_INC) /* (R++) */
4768     return *l=4, ("ld %A0,%1" CR_TAB
4769                       "ld %B0,%1" CR_TAB
4770                       "ld %C0,%1" CR_TAB
4771                       "ld %D0,%1");
4772   else if (CONSTANT_ADDRESS_P (base))
4773     {
4774       if (io_address_operand (base, SImode))
4775         {
4776           *l = 4;
4777           return ("in %A0,%i1"   CR_TAB
4778                   "in %B0,%i1+1" CR_TAB
4779                   "in %C0,%i1+2" CR_TAB
4780                   "in %D0,%i1+3");
4781         }
4782       else
4783         {
4784           *l = AVR_TINY ? 4 : 8;
4785           return ("lds %A0,%m1"   CR_TAB
4786                   "lds %B0,%m1+1" CR_TAB
4787                   "lds %C0,%m1+2" CR_TAB
4788                   "lds %D0,%m1+3");
4789         }
4790     }
4791 
4792   fatal_insn ("unknown move insn:",insn);
4793   return "";
4794 }
4795 
4796 static const char*
avr_out_movsi_mr_r_reg_no_disp_tiny(rtx_insn * insn,rtx op[],int * l)4797 avr_out_movsi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *l)
4798 {
4799   rtx dest = op[0];
4800   rtx src = op[1];
4801   rtx base = XEXP (dest, 0);
4802   int reg_base = true_regnum (base);
4803   int reg_src = true_regnum (src);
4804 
4805   if (reg_base == reg_src)
4806     {
4807       /* "ld r26,-X" is undefined */
4808       if (reg_unused_after (insn, base))
4809         {
4810           return *l = 7, ("mov __tmp_reg__, %B1"  CR_TAB
4811                                 "st %0,%A1"             CR_TAB
4812                                 TINY_ADIW (%E0, %F0, 1) CR_TAB
4813                                 "st %0+,__tmp_reg__"    CR_TAB
4814                                 "st %0+,%C1"            CR_TAB
4815                                 "st %0+,%D1");
4816         }
4817       else
4818         {
4819           return *l = 9, ("mov __tmp_reg__, %B1"  CR_TAB
4820                                 "st %0,%A1"             CR_TAB
4821                                 TINY_ADIW (%E0, %F0, 1) CR_TAB
4822                                 "st %0+,__tmp_reg__"    CR_TAB
4823                                 "st %0+,%C1"            CR_TAB
4824                                 "st %0+,%D1"            CR_TAB
4825                                 TINY_SBIW (%E0, %F0, 3));
4826         }
4827     }
4828   else if (reg_base == reg_src + 2)
4829     {
4830       if (reg_unused_after (insn, base))
4831           return *l = 7, ("mov __zero_reg__,%C1" CR_TAB
4832                         "mov __tmp_reg__,%D1"  CR_TAB
4833                         "st %0+,%A1"           CR_TAB
4834                         "st %0+,%B1"           CR_TAB
4835                         "st %0+,__zero_reg__"  CR_TAB
4836                         "st %0,__tmp_reg__"    CR_TAB
4837                         "clr __zero_reg__");
4838       else
4839           return *l = 9, ("mov __zero_reg__,%C1" CR_TAB
4840                               "mov __tmp_reg__,%D1"  CR_TAB
4841                               "st %0+,%A1"           CR_TAB
4842                               "st %0+,%B1"           CR_TAB
4843                               "st %0+,__zero_reg__"  CR_TAB
4844                               "st %0,__tmp_reg__"    CR_TAB
4845                               "clr __zero_reg__"     CR_TAB
4846                               TINY_SBIW (%E0, %F0, 3));
4847     }
4848 
4849   return *l = 6, ("st %0+,%A1" CR_TAB
4850                       "st %0+,%B1" CR_TAB
4851                       "st %0+,%C1" CR_TAB
4852                       "st %0,%D1"  CR_TAB
4853                       TINY_SBIW (%E0, %F0, 3));
4854 }
4855 
4856 static const char*
avr_out_movsi_mr_r_reg_disp_tiny(rtx op[],int * l)4857 avr_out_movsi_mr_r_reg_disp_tiny (rtx op[], int *l)
4858 {
4859   rtx dest = op[0];
4860   rtx src = op[1];
4861   rtx base = XEXP (dest, 0);
4862   int reg_base = REGNO (XEXP (base, 0));
4863   int reg_src =true_regnum (src);
4864 
4865   if (reg_base == reg_src)
4866     {
4867       *l = 11;
4868       return ("mov __tmp_reg__,%A2"        CR_TAB
4869               "mov __zero_reg__,%B2"       CR_TAB
4870               TINY_ADIW (%I0, %J0, %o0)    CR_TAB
4871               "st %b0+,__tmp_reg__"        CR_TAB
4872               "st %b0+,__zero_reg__"       CR_TAB
4873               "st %b0+,%C2"                CR_TAB
4874               "st %b0,%D2"                 CR_TAB
4875               "clr __zero_reg__"           CR_TAB
4876               TINY_SBIW (%I0, %J0, %o0+3));
4877     }
4878   else if (reg_src == reg_base - 2)
4879     {
4880       *l = 11;
4881       return ("mov __tmp_reg__,%C2"         CR_TAB
4882               "mov __zero_reg__,%D2"        CR_TAB
4883               TINY_ADIW (%I0, %J0, %o0)     CR_TAB
4884               "st %b0+,%A0"                 CR_TAB
4885               "st %b0+,%B0"                 CR_TAB
4886               "st %b0+,__tmp_reg__"         CR_TAB
4887               "st %b0,__zero_reg__"         CR_TAB
4888               "clr __zero_reg__"            CR_TAB
4889               TINY_SBIW (%I0, %J0, %o0+3));
4890     }
4891   *l = 8;
4892   return (TINY_ADIW (%I0, %J0, %o0)     CR_TAB
4893           "st %b0+,%A1"                 CR_TAB
4894           "st %b0+,%B1"                 CR_TAB
4895           "st %b0+,%C1"                 CR_TAB
4896           "st %b0,%D1"                  CR_TAB
4897           TINY_SBIW (%I0, %J0, %o0+3));
4898 }
4899 
4900 static const char*
out_movsi_mr_r(rtx_insn * insn,rtx op[],int * l)4901 out_movsi_mr_r (rtx_insn *insn, rtx op[], int *l)
4902 {
4903   rtx dest = op[0];
4904   rtx src = op[1];
4905   rtx base = XEXP (dest, 0);
4906   int reg_base = true_regnum (base);
4907   int reg_src = true_regnum (src);
4908   int tmp;
4909 
4910   if (!l)
4911     l = &tmp;
4912 
4913   if (CONSTANT_ADDRESS_P (base))
4914     {
4915       if (io_address_operand (base, SImode))
4916         {
4917           return *l=4,("out %i0, %A1"  CR_TAB
4918                        "out %i0+1,%B1" CR_TAB
4919                        "out %i0+2,%C1" CR_TAB
4920                        "out %i0+3,%D1");
4921         }
4922       else
4923         {
4924           *l = AVR_TINY ? 4 : 8;
4925           return ("sts %m0,%A1"   CR_TAB
4926                   "sts %m0+1,%B1" CR_TAB
4927                   "sts %m0+2,%C1" CR_TAB
4928                   "sts %m0+3,%D1");
4929         }
4930     }
4931 
4932   if (reg_base > 0)                 /* (r) */
4933     {
4934       if (AVR_TINY)
4935         return avr_out_movsi_mr_r_reg_no_disp_tiny (insn, op, l);
4936 
4937       if (reg_base == REG_X)                /* (R26) */
4938         {
4939           if (reg_src == REG_X)
4940             {
4941                 /* "st X+,r26" is undefined */
4942               if (reg_unused_after (insn, base))
4943                     return *l=6, ("mov __tmp_reg__,r27" CR_TAB
4944                                     "st X,r26"            CR_TAB
4945                                     "adiw r26,1"          CR_TAB
4946                                     "st X+,__tmp_reg__"   CR_TAB
4947                                     "st X+,r28"           CR_TAB
4948                                     "st X,r29");
4949               else
4950                 return *l=7, ("mov __tmp_reg__,r27" CR_TAB
4951                                     "st X,r26"            CR_TAB
4952                                     "adiw r26,1"          CR_TAB
4953                                     "st X+,__tmp_reg__"   CR_TAB
4954                                     "st X+,r28"           CR_TAB
4955                                     "st X,r29"            CR_TAB
4956                                     "sbiw r26,3");
4957             }
4958           else if (reg_base == reg_src + 2)
4959             {
4960               if (reg_unused_after (insn, base))
4961                 return *l=7, ("mov __zero_reg__,%C1" CR_TAB
4962                               "mov __tmp_reg__,%D1"  CR_TAB
4963                               "st %0+,%A1"           CR_TAB
4964                               "st %0+,%B1"           CR_TAB
4965                               "st %0+,__zero_reg__"  CR_TAB
4966                               "st %0,__tmp_reg__"    CR_TAB
4967                               "clr __zero_reg__");
4968               else
4969                 return *l=8, ("mov __zero_reg__,%C1" CR_TAB
4970                               "mov __tmp_reg__,%D1"  CR_TAB
4971                               "st %0+,%A1"           CR_TAB
4972                               "st %0+,%B1"           CR_TAB
4973                               "st %0+,__zero_reg__"  CR_TAB
4974                               "st %0,__tmp_reg__"    CR_TAB
4975                               "clr __zero_reg__"     CR_TAB
4976                               "sbiw r26,3");
4977             }
4978           return *l=5, ("st %0+,%A1" CR_TAB
4979                         "st %0+,%B1" CR_TAB
4980                         "st %0+,%C1" CR_TAB
4981                         "st %0,%D1"  CR_TAB
4982                         "sbiw r26,3");
4983         }
4984       else
4985         return *l=4, ("st %0,%A1"    CR_TAB
4986                           "std %0+1,%B1" CR_TAB
4987                           "std %0+2,%C1" CR_TAB
4988                           "std %0+3,%D1");
4989     }
4990   else if (GET_CODE (base) == PLUS) /* (R + i) */
4991     {
4992       int disp = INTVAL (XEXP (base, 1));
4993 
4994       if (AVR_TINY)
4995         return avr_out_movsi_mr_r_reg_disp_tiny (op, l);
4996 
4997       reg_base = REGNO (XEXP (base, 0));
4998       if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
4999           {
5000             if (reg_base != REG_Y)
5001               fatal_insn ("incorrect insn:",insn);
5002 
5003             if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
5004               return *l = 6, ("adiw r28,%o0-60" CR_TAB
5005                                   "std Y+60,%A1"    CR_TAB
5006                                   "std Y+61,%B1"    CR_TAB
5007                                   "std Y+62,%C1"    CR_TAB
5008                                   "std Y+63,%D1"    CR_TAB
5009                                   "sbiw r28,%o0-60");
5010 
5011             return *l = 8, ("subi r28,lo8(-%o0)" CR_TAB
5012                                 "sbci r29,hi8(-%o0)" CR_TAB
5013                                 "st Y,%A1"           CR_TAB
5014                                 "std Y+1,%B1"        CR_TAB
5015                                 "std Y+2,%C1"        CR_TAB
5016                                 "std Y+3,%D1"        CR_TAB
5017                                 "subi r28,lo8(%o0)"  CR_TAB
5018                                 "sbci r29,hi8(%o0)");
5019           }
5020       if (reg_base == REG_X)
5021           {
5022             /* (X + d) = R */
5023             if (reg_src == REG_X)
5024               {
5025                 *l = 9;
5026                 return ("mov __tmp_reg__,r26"  CR_TAB
5027                           "mov __zero_reg__,r27" CR_TAB
5028                           "adiw r26,%o0"         CR_TAB
5029                           "st X+,__tmp_reg__"    CR_TAB
5030                           "st X+,__zero_reg__"   CR_TAB
5031                           "st X+,r28"            CR_TAB
5032                           "st X,r29"             CR_TAB
5033                           "clr __zero_reg__"     CR_TAB
5034                           "sbiw r26,%o0+3");
5035               }
5036             else if (reg_src == REG_X - 2)
5037               {
5038                 *l = 9;
5039                 return ("mov __tmp_reg__,r26"  CR_TAB
5040                           "mov __zero_reg__,r27" CR_TAB
5041                           "adiw r26,%o0"         CR_TAB
5042                           "st X+,r24"            CR_TAB
5043                           "st X+,r25"            CR_TAB
5044                           "st X+,__tmp_reg__"    CR_TAB
5045                           "st X,__zero_reg__"    CR_TAB
5046                           "clr __zero_reg__"     CR_TAB
5047                           "sbiw r26,%o0+3");
5048               }
5049             *l = 6;
5050             return ("adiw r26,%o0" CR_TAB
5051                       "st X+,%A1"    CR_TAB
5052                       "st X+,%B1"    CR_TAB
5053                       "st X+,%C1"    CR_TAB
5054                       "st X,%D1"     CR_TAB
5055                       "sbiw r26,%o0+3");
5056           }
5057       return *l=4, ("std %A0,%A1" CR_TAB
5058                         "std %B0,%B1" CR_TAB
5059                         "std %C0,%C1" CR_TAB
5060                         "std %D0,%D1");
5061     }
5062   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5063     return *l=4, ("st %0,%D1" CR_TAB
5064                       "st %0,%C1" CR_TAB
5065                       "st %0,%B1" CR_TAB
5066                       "st %0,%A1");
5067   else if (GET_CODE (base) == POST_INC) /* (R++) */
5068     return *l=4, ("st %0,%A1" CR_TAB
5069                       "st %0,%B1" CR_TAB
5070                       "st %0,%C1" CR_TAB
5071                       "st %0,%D1");
5072   fatal_insn ("unknown move insn:",insn);
5073   return "";
5074 }
5075 
5076 const char *
output_movsisf(rtx_insn * insn,rtx operands[],int * l)5077 output_movsisf (rtx_insn *insn, rtx operands[], int *l)
5078 {
5079   int dummy;
5080   rtx dest = operands[0];
5081   rtx src = operands[1];
5082   int *real_l = l;
5083 
5084   if (avr_mem_flash_p (src)
5085       || avr_mem_flash_p (dest))
5086     {
5087       return avr_out_lpm (insn, operands, real_l);
5088     }
5089 
5090   if (!l)
5091     l = &dummy;
5092 
5093   gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 4);
5094 
5095   if (REG_P (dest))
5096     {
5097       if (REG_P (src)) /* mov r,r */
5098           {
5099             if (true_regnum (dest) > true_regnum (src))
5100               {
5101                 if (AVR_HAVE_MOVW)
5102                     {
5103                       *l = 2;
5104                       return ("movw %C0,%C1" CR_TAB
5105                                 "movw %A0,%A1");
5106                     }
5107                 *l = 4;
5108                 return ("mov %D0,%D1" CR_TAB
5109                           "mov %C0,%C1" CR_TAB
5110                           "mov %B0,%B1" CR_TAB
5111                           "mov %A0,%A1");
5112               }
5113             else
5114               {
5115                 if (AVR_HAVE_MOVW)
5116                     {
5117                       *l = 2;
5118                       return ("movw %A0,%A1" CR_TAB
5119                                 "movw %C0,%C1");
5120                     }
5121                 *l = 4;
5122                 return ("mov %A0,%A1" CR_TAB
5123                           "mov %B0,%B1" CR_TAB
5124                           "mov %C0,%C1" CR_TAB
5125                           "mov %D0,%D1");
5126               }
5127           }
5128       else if (CONSTANT_P (src))
5129           {
5130           return output_reload_insisf (operands, NULL_RTX, real_l);
5131         }
5132       else if (MEM_P (src))
5133           return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
5134     }
5135   else if (MEM_P (dest))
5136     {
5137       const char *templ;
5138 
5139       if (src == CONST0_RTX (GET_MODE (dest)))
5140         operands[1] = zero_reg_rtx;
5141 
5142       templ = out_movsi_mr_r (insn, operands, real_l);
5143 
5144       if (!real_l)
5145           output_asm_insn (templ, operands);
5146 
5147       operands[1] = src;
5148       return "";
5149     }
5150   fatal_insn ("invalid insn:", insn);
5151   return "";
5152 }
5153 
5154 
5155 /* Handle loads of 24-bit types from memory to register.  */
5156 
5157 static const char*
avr_out_load_psi_reg_no_disp_tiny(rtx_insn * insn,rtx * op,int * plen)5158 avr_out_load_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
5159 {
5160   rtx dest = op[0];
5161   rtx src = op[1];
5162   rtx base = XEXP (src, 0);
5163   int reg_dest = true_regnum (dest);
5164   int reg_base = true_regnum (base);
5165 
5166   if (reg_base == reg_dest)
5167     {
5168       return avr_asm_len (TINY_ADIW (%E1, %F1, 2)   CR_TAB
5169                           "ld %C0,%1"               CR_TAB
5170                           "ld __tmp_reg__,-%1"      CR_TAB
5171                           TINY_SBIW (%E1, %F1, 1)   CR_TAB
5172                           "ld %A0,%1"               CR_TAB
5173                           "mov %B0,__tmp_reg__", op, plen, -8);
5174     }
5175   else
5176     {
5177       avr_asm_len ("ld %A0,%1+"  CR_TAB
5178                        "ld %B0,%1+"  CR_TAB
5179                        "ld %C0,%1", op, plen, -3);
5180 
5181       if (reg_dest != reg_base - 2
5182           && !reg_unused_after (insn, base))
5183         {
5184           avr_asm_len (TINY_SBIW (%E1, %F1, 2), op, plen, 2);
5185         }
5186       return "";
5187     }
5188 }
5189 
5190 static const char*
avr_out_load_psi_reg_disp_tiny(rtx_insn * insn,rtx * op,int * plen)5191 avr_out_load_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
5192 {
5193   rtx dest = op[0];
5194   rtx src = op[1];
5195   rtx base = XEXP (src, 0);
5196   int reg_dest = true_regnum (dest);
5197   int reg_base = true_regnum (base);
5198 
5199   reg_base = true_regnum (XEXP (base, 0));
5200   if (reg_base == reg_dest)
5201     {
5202       return avr_asm_len (TINY_ADIW (%I1, %J1, %o1+2) CR_TAB
5203                           "ld %C0,%b1"                CR_TAB
5204                           "ld __tmp_reg__,-%b1"       CR_TAB
5205                           TINY_SBIW (%I1, %J1, 1)     CR_TAB
5206                           "ld %A0,%b1"                CR_TAB
5207                           "mov %B0,__tmp_reg__", op, plen, -8);
5208     }
5209   else
5210     {
5211       avr_asm_len (TINY_ADIW (%I1, %J1, %o1)   CR_TAB
5212                    "ld %A0,%b1+"               CR_TAB
5213                    "ld %B0,%b1+"               CR_TAB
5214                    "ld %C0,%b1", op, plen, -5);
5215 
5216       if (reg_dest != reg_base - 2
5217           && !reg_unused_after (insn, XEXP (base, 0)))
5218         avr_asm_len (TINY_SBIW (%I1, %J1, %o1+2), op, plen, 2);
5219 
5220       return "";
5221     }
5222 }
5223 
5224 static const char*
avr_out_load_psi(rtx_insn * insn,rtx * op,int * plen)5225 avr_out_load_psi (rtx_insn *insn, rtx *op, int *plen)
5226 {
5227   rtx dest = op[0];
5228   rtx src = op[1];
5229   rtx base = XEXP (src, 0);
5230   int reg_dest = true_regnum (dest);
5231   int reg_base = true_regnum (base);
5232 
5233   if (reg_base > 0)
5234     {
5235       if (AVR_TINY)
5236         return avr_out_load_psi_reg_no_disp_tiny (insn, op, plen);
5237 
5238       if (reg_base == REG_X)        /* (R26) */
5239         {
5240           if (reg_dest == REG_X)
5241             /* "ld r26,-X" is undefined */
5242             return avr_asm_len ("adiw r26,2"        CR_TAB
5243                                 "ld r28,X"          CR_TAB
5244                                 "ld __tmp_reg__,-X" CR_TAB
5245                                 "sbiw r26,1"        CR_TAB
5246                                 "ld r26,X"          CR_TAB
5247                                 "mov r27,__tmp_reg__", op, plen, -6);
5248           else
5249             {
5250               avr_asm_len ("ld %A0,X+" CR_TAB
5251                            "ld %B0,X+" CR_TAB
5252                            "ld %C0,X", op, plen, -3);
5253 
5254               if (reg_dest != REG_X - 2
5255                   && !reg_unused_after (insn, base))
5256                 {
5257                   avr_asm_len ("sbiw r26,2", op, plen, 1);
5258                 }
5259 
5260               return "";
5261             }
5262         }
5263       else /* reg_base != REG_X */
5264         {
5265           if (reg_dest == reg_base)
5266             return avr_asm_len ("ldd %C0,%1+2"          CR_TAB
5267                                 "ldd __tmp_reg__,%1+1"  CR_TAB
5268                                 "ld  %A0,%1"            CR_TAB
5269                                 "mov %B0,__tmp_reg__", op, plen, -4);
5270           else
5271             return avr_asm_len ("ld  %A0,%1"    CR_TAB
5272                                 "ldd %B0,%1+1"  CR_TAB
5273                                 "ldd %C0,%1+2", op, plen, -3);
5274         }
5275     }
5276   else if (GET_CODE (base) == PLUS) /* (R + i) */
5277     {
5278       int disp = INTVAL (XEXP (base, 1));
5279 
5280       if (AVR_TINY)
5281         return avr_out_load_psi_reg_disp_tiny (insn, op, plen);
5282 
5283       if (disp > MAX_LD_OFFSET (GET_MODE (src)))
5284         {
5285           if (REGNO (XEXP (base, 0)) != REG_Y)
5286             fatal_insn ("incorrect insn:",insn);
5287 
5288           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
5289             return avr_asm_len ("adiw r28,%o1-61" CR_TAB
5290                                 "ldd %A0,Y+61"    CR_TAB
5291                                 "ldd %B0,Y+62"    CR_TAB
5292                                 "ldd %C0,Y+63"    CR_TAB
5293                                 "sbiw r28,%o1-61", op, plen, -5);
5294 
5295           return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
5296                               "sbci r29,hi8(-%o1)" CR_TAB
5297                               "ld  %A0,Y"          CR_TAB
5298                               "ldd %B0,Y+1"        CR_TAB
5299                               "ldd %C0,Y+2"        CR_TAB
5300                               "subi r28,lo8(%o1)"  CR_TAB
5301                               "sbci r29,hi8(%o1)", op, plen, -7);
5302         }
5303 
5304       reg_base = true_regnum (XEXP (base, 0));
5305       if (reg_base == REG_X)
5306         {
5307           /* R = (X + d) */
5308           if (reg_dest == REG_X)
5309             {
5310               /* "ld r26,-X" is undefined */
5311               return avr_asm_len ("adiw r26,%o1+2"     CR_TAB
5312                                   "ld  r28,X"          CR_TAB
5313                                   "ld  __tmp_reg__,-X" CR_TAB
5314                                   "sbiw r26,1"         CR_TAB
5315                                   "ld  r26,X"          CR_TAB
5316                                   "mov r27,__tmp_reg__", op, plen, -6);
5317             }
5318 
5319           avr_asm_len ("adiw r26,%o1" CR_TAB
5320                        "ld %A0,X+"    CR_TAB
5321                        "ld %B0,X+"    CR_TAB
5322                        "ld %C0,X", op, plen, -4);
5323 
5324           if (reg_dest != REG_W
5325               && !reg_unused_after (insn, XEXP (base, 0)))
5326             avr_asm_len ("sbiw r26,%o1+2", op, plen, 1);
5327 
5328           return "";
5329         }
5330 
5331       if (reg_dest == reg_base)
5332         return avr_asm_len ("ldd %C0,%C1" CR_TAB
5333                             "ldd __tmp_reg__,%B1"  CR_TAB
5334                             "ldd %A0,%A1" CR_TAB
5335                             "mov %B0,__tmp_reg__", op, plen, -4);
5336 
5337       return avr_asm_len ("ldd %A0,%A1" CR_TAB
5338                           "ldd %B0,%B1" CR_TAB
5339                           "ldd %C0,%C1", op, plen, -3);
5340     }
5341   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5342     return avr_asm_len ("ld %C0,%1" CR_TAB
5343                         "ld %B0,%1" CR_TAB
5344                         "ld %A0,%1", op, plen, -3);
5345   else if (GET_CODE (base) == POST_INC) /* (R++) */
5346     return avr_asm_len ("ld %A0,%1" CR_TAB
5347                         "ld %B0,%1" CR_TAB
5348                         "ld %C0,%1", op, plen, -3);
5349 
5350   else if (CONSTANT_ADDRESS_P (base))
5351     {
5352       int n_words = AVR_TINY ? 3 : 6;
5353       return avr_asm_len ("lds %A0,%m1" CR_TAB
5354                           "lds %B0,%m1+1" CR_TAB
5355                           "lds %C0,%m1+2", op, plen , -n_words);
5356     }
5357 
5358   fatal_insn ("unknown move insn:",insn);
5359   return "";
5360 }
5361 
5362 
5363 static const char*
avr_out_store_psi_reg_no_disp_tiny(rtx_insn * insn,rtx * op,int * plen)5364 avr_out_store_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
5365 {
5366   rtx dest = op[0];
5367   rtx src = op[1];
5368   rtx base = XEXP (dest, 0);
5369   int reg_base = true_regnum (base);
5370   int reg_src = true_regnum (src);
5371 
5372   if (reg_base == reg_src)
5373     {
5374       avr_asm_len ("st %0,%A1"              CR_TAB
5375                    "mov __tmp_reg__,%B1"    CR_TAB
5376                    TINY_ADIW (%E0, %F0, 1)  CR_TAB /* st X+, r27 is undefined */
5377                    "st %0+,__tmp_reg__"     CR_TAB
5378                    "st %0,%C1", op, plen, -6);
5379 
5380     }
5381   else if (reg_src == reg_base - 2)
5382     {
5383       avr_asm_len ("st %0,%A1"              CR_TAB
5384                    "mov __tmp_reg__,%C1"    CR_TAB
5385                    TINY_ADIW (%E0, %F0, 1)  CR_TAB
5386                    "st %0+,%B1"             CR_TAB
5387                    "st %0,__tmp_reg__", op, plen, 6);
5388     }
5389   else
5390     {
5391       avr_asm_len ("st %0+,%A1"  CR_TAB
5392                    "st %0+,%B1" CR_TAB
5393                    "st %0,%C1", op, plen, -3);
5394     }
5395 
5396   if (!reg_unused_after (insn, base))
5397     avr_asm_len (TINY_SBIW (%E0, %F0, 2), op, plen, 2);
5398 
5399   return "";
5400 }
5401 
5402 static const char*
avr_out_store_psi_reg_disp_tiny(rtx_insn * insn,rtx * op,int * plen)5403 avr_out_store_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
5404 {
5405   rtx dest = op[0];
5406   rtx src = op[1];
5407   rtx base = XEXP (dest, 0);
5408   int reg_base = REGNO (XEXP (base, 0));
5409   int reg_src = true_regnum (src);
5410 
5411   if (reg_src == reg_base)
5412     avr_asm_len ("mov __tmp_reg__,%A1"          CR_TAB
5413                  "mov __zero_reg__,%B1"         CR_TAB
5414                  TINY_ADIW (%I0, %J0, %o0)      CR_TAB
5415                  "st %b0+,__tmp_reg__"          CR_TAB
5416                  "st %b0+,__zero_reg__"         CR_TAB
5417                  "st %b0,%C1"                   CR_TAB
5418                  "clr __zero_reg__", op, plen, -8);
5419   else if (reg_src == reg_base - 2)
5420     avr_asm_len ("mov __tmp_reg__,%C1"          CR_TAB
5421                  TINY_ADIW (%I0, %J0, %o0)      CR_TAB
5422                  "st %b0+,%A1"                  CR_TAB
5423                  "st %b0+,%B1"                  CR_TAB
5424                  "st %b0,__tmp_reg__", op, plen, -6);
5425   else
5426     avr_asm_len (TINY_ADIW (%I0, %J0, %o0)      CR_TAB
5427                  "st %b0+,%A1"                  CR_TAB
5428                  "st %b0+,%B1"                  CR_TAB
5429                  "st %b0,%C1", op, plen, -5);
5430 
5431   if (!reg_unused_after (insn, XEXP (base, 0)))
5432     avr_asm_len (TINY_SBIW (%I0, %J0, %o0+2), op, plen, 2);
5433 
5434   return "";
5435 }
5436 
5437 /* Handle store of 24-bit type from register or zero to memory.  */
5438 
5439 static const char*
avr_out_store_psi(rtx_insn * insn,rtx * op,int * plen)5440 avr_out_store_psi (rtx_insn *insn, rtx *op, int *plen)
5441 {
5442   rtx dest = op[0];
5443   rtx src = op[1];
5444   rtx base = XEXP (dest, 0);
5445   int reg_base = true_regnum (base);
5446 
5447   if (CONSTANT_ADDRESS_P (base))
5448     {
5449       int n_words = AVR_TINY ? 3 : 6;
5450       return avr_asm_len ("sts %m0,%A1"   CR_TAB
5451                           "sts %m0+1,%B1" CR_TAB
5452                           "sts %m0+2,%C1", op, plen, -n_words);
5453     }
5454 
5455   if (reg_base > 0)                 /* (r) */
5456     {
5457       if (AVR_TINY)
5458         return avr_out_store_psi_reg_no_disp_tiny (insn, op, plen);
5459 
5460       if (reg_base == REG_X)        /* (R26) */
5461         {
5462           gcc_assert (!reg_overlap_mentioned_p (base, src));
5463 
5464           avr_asm_len ("st %0+,%A1"  CR_TAB
5465                        "st %0+,%B1" CR_TAB
5466                        "st %0,%C1", op, plen, -3);
5467 
5468           if (!reg_unused_after (insn, base))
5469             avr_asm_len ("sbiw r26,2", op, plen, 1);
5470 
5471           return "";
5472         }
5473       else
5474         return avr_asm_len ("st %0,%A1"    CR_TAB
5475                             "std %0+1,%B1" CR_TAB
5476                             "std %0+2,%C1", op, plen, -3);
5477     }
5478   else if (GET_CODE (base) == PLUS) /* (R + i) */
5479     {
5480       int disp = INTVAL (XEXP (base, 1));
5481 
5482       if (AVR_TINY)
5483         return avr_out_store_psi_reg_disp_tiny (insn, op, plen);
5484 
5485       reg_base = REGNO (XEXP (base, 0));
5486 
5487       if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5488         {
5489           if (reg_base != REG_Y)
5490             fatal_insn ("incorrect insn:",insn);
5491 
5492           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
5493             return avr_asm_len ("adiw r28,%o0-61" CR_TAB
5494                                 "std Y+61,%A1"    CR_TAB
5495                                 "std Y+62,%B1"    CR_TAB
5496                                 "std Y+63,%C1"    CR_TAB
5497                                 "sbiw r28,%o0-61", op, plen, -5);
5498 
5499           return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5500                               "sbci r29,hi8(-%o0)" CR_TAB
5501                               "st Y,%A1"           CR_TAB
5502                               "std Y+1,%B1"        CR_TAB
5503                               "std Y+2,%C1"        CR_TAB
5504                               "subi r28,lo8(%o0)"  CR_TAB
5505                               "sbci r29,hi8(%o0)", op, plen, -7);
5506         }
5507       if (reg_base == REG_X)
5508         {
5509           /* (X + d) = R */
5510           gcc_assert (!reg_overlap_mentioned_p (XEXP (base, 0), src));
5511 
5512           avr_asm_len ("adiw r26,%o0" CR_TAB
5513                        "st X+,%A1"    CR_TAB
5514                        "st X+,%B1"    CR_TAB
5515                        "st X,%C1", op, plen, -4);
5516 
5517           if (!reg_unused_after (insn, XEXP (base, 0)))
5518             avr_asm_len ("sbiw r26,%o0+2", op, plen, 1);
5519 
5520           return "";
5521         }
5522 
5523       return avr_asm_len ("std %A0,%A1" CR_TAB
5524                           "std %B0,%B1" CR_TAB
5525                           "std %C0,%C1", op, plen, -3);
5526     }
5527   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5528     return avr_asm_len ("st %0,%C1" CR_TAB
5529                         "st %0,%B1" CR_TAB
5530                         "st %0,%A1", op, plen, -3);
5531   else if (GET_CODE (base) == POST_INC) /* (R++) */
5532     return avr_asm_len ("st %0,%A1" CR_TAB
5533                         "st %0,%B1" CR_TAB
5534                         "st %0,%C1", op, plen, -3);
5535 
5536   fatal_insn ("unknown move insn:",insn);
5537   return "";
5538 }
5539 
5540 
5541 /* Move around 24-bit stuff.  */
5542 
5543 const char *
avr_out_movpsi(rtx_insn * insn,rtx * op,int * plen)5544 avr_out_movpsi (rtx_insn *insn, rtx *op, int *plen)
5545 {
5546   rtx dest = op[0];
5547   rtx src = op[1];
5548 
5549   if (avr_mem_flash_p (src)
5550       || avr_mem_flash_p (dest))
5551     {
5552       return avr_out_lpm (insn, op, plen);
5553     }
5554 
5555   if (register_operand (dest, VOIDmode))
5556     {
5557       if (register_operand (src, VOIDmode)) /* mov r,r */
5558         {
5559           if (true_regnum (dest) > true_regnum (src))
5560             {
5561               avr_asm_len ("mov %C0,%C1", op, plen, -1);
5562 
5563               if (AVR_HAVE_MOVW)
5564                 return avr_asm_len ("movw %A0,%A1", op, plen, 1);
5565               else
5566                 return avr_asm_len ("mov %B0,%B1"  CR_TAB
5567                                     "mov %A0,%A1", op, plen, 2);
5568             }
5569           else
5570             {
5571               if (AVR_HAVE_MOVW)
5572                 avr_asm_len ("movw %A0,%A1", op, plen, -1);
5573               else
5574                 avr_asm_len ("mov %A0,%A1"  CR_TAB
5575                              "mov %B0,%B1", op, plen, -2);
5576 
5577               return avr_asm_len ("mov %C0,%C1", op, plen, 1);
5578             }
5579         }
5580       else if (CONSTANT_P (src))
5581         {
5582           return avr_out_reload_inpsi (op, NULL_RTX, plen);
5583         }
5584       else if (MEM_P (src))
5585         return avr_out_load_psi (insn, op, plen); /* mov r,m */
5586     }
5587   else if (MEM_P (dest))
5588     {
5589       rtx xop[2];
5590 
5591       xop[0] = dest;
5592       xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
5593 
5594       return avr_out_store_psi (insn, xop, plen);
5595     }
5596 
5597   fatal_insn ("invalid insn:", insn);
5598   return "";
5599 }
5600 
5601 static const char*
avr_out_movqi_mr_r_reg_disp_tiny(rtx_insn * insn,rtx op[],int * plen)5602 avr_out_movqi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5603 {
5604   rtx dest = op[0];
5605   rtx src = op[1];
5606   rtx x = XEXP (dest, 0);
5607 
5608   if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
5609     {
5610       avr_asm_len ("mov __tmp_reg__,%1"      CR_TAB
5611                    TINY_ADIW (%I0, %J0, %o0) CR_TAB
5612                    "st %b0,__tmp_reg__", op, plen, -4);
5613     }
5614   else
5615     {
5616       avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
5617                    "st %b0,%1", op, plen, -3);
5618     }
5619 
5620   if (!reg_unused_after (insn, XEXP (x, 0)))
5621     avr_asm_len (TINY_SBIW (%I0, %J0, %o0), op, plen, 2);
5622 
5623   return "";
5624 }
5625 
5626 static const char*
out_movqi_mr_r(rtx_insn * insn,rtx op[],int * plen)5627 out_movqi_mr_r (rtx_insn *insn, rtx op[], int *plen)
5628 {
5629   rtx dest = op[0];
5630   rtx src = op[1];
5631   rtx x = XEXP (dest, 0);
5632 
5633   if (CONSTANT_ADDRESS_P (x))
5634     {
5635       int n_words = AVR_TINY ? 1 : 2;
5636       return io_address_operand (x, QImode)
5637         ? avr_asm_len ("out %i0,%1", op, plen, -1)
5638         : avr_asm_len ("sts %m0,%1", op, plen, -n_words);
5639     }
5640   else if (GET_CODE (x) == PLUS
5641            && REG_P (XEXP (x, 0))
5642            && CONST_INT_P (XEXP (x, 1)))
5643     {
5644       /* memory access by reg+disp */
5645 
5646       int disp = INTVAL (XEXP (x, 1));
5647 
5648       if (AVR_TINY)
5649         return avr_out_movqi_mr_r_reg_disp_tiny (insn, op, plen);
5650 
5651       if (disp - GET_MODE_SIZE (GET_MODE (dest)) >= 63)
5652         {
5653           if (REGNO (XEXP (x, 0)) != REG_Y)
5654             fatal_insn ("incorrect insn:",insn);
5655 
5656           if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
5657             return avr_asm_len ("adiw r28,%o0-63" CR_TAB
5658                                 "std Y+63,%1"     CR_TAB
5659                                 "sbiw r28,%o0-63", op, plen, -3);
5660 
5661           return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5662                               "sbci r29,hi8(-%o0)" CR_TAB
5663                               "st Y,%1"            CR_TAB
5664                               "subi r28,lo8(%o0)"  CR_TAB
5665                               "sbci r29,hi8(%o0)", op, plen, -5);
5666         }
5667       else if (REGNO (XEXP (x, 0)) == REG_X)
5668         {
5669           if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
5670             {
5671               avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
5672                            "adiw r26,%o0"       CR_TAB
5673                            "st X,__tmp_reg__", op, plen, -3);
5674             }
5675           else
5676             {
5677               avr_asm_len ("adiw r26,%o0" CR_TAB
5678                            "st X,%1", op, plen, -2);
5679             }
5680 
5681           if (!reg_unused_after (insn, XEXP (x, 0)))
5682             avr_asm_len ("sbiw r26,%o0", op, plen, 1);
5683 
5684           return "";
5685         }
5686 
5687       return avr_asm_len ("std %0,%1", op, plen, -1);
5688     }
5689 
5690   return avr_asm_len ("st %0,%1", op, plen, -1);
5691 }
5692 
5693 
5694 /* Helper for the next function for XMEGA.  It does the same
5695    but with low byte first.  */
5696 
5697 static const char*
avr_out_movhi_mr_r_xmega(rtx_insn * insn,rtx op[],int * plen)5698 avr_out_movhi_mr_r_xmega (rtx_insn *insn, rtx op[], int *plen)
5699 {
5700   rtx dest = op[0];
5701   rtx src = op[1];
5702   rtx base = XEXP (dest, 0);
5703   int reg_base = true_regnum (base);
5704   int reg_src = true_regnum (src);
5705 
5706   /* "volatile" forces writing low byte first, even if less efficient,
5707      for correct operation with 16-bit I/O registers like SP.  */
5708   int mem_volatile_p = MEM_VOLATILE_P (dest);
5709 
5710   if (CONSTANT_ADDRESS_P (base))
5711     {
5712       return io_address_operand (base, HImode)
5713         ? avr_asm_len ("out %i0,%A1" CR_TAB
5714                        "out %i0+1,%B1", op, plen, -2)
5715 
5716         : avr_asm_len ("sts %m0,%A1" CR_TAB
5717                        "sts %m0+1,%B1", op, plen, -4);
5718     }
5719 
5720   if (reg_base > 0)
5721     {
5722       if (reg_base != REG_X)
5723         return avr_asm_len ("st %0,%A1" CR_TAB
5724                             "std %0+1,%B1", op, plen, -2);
5725 
5726       if (reg_src == REG_X)
5727         /* "st X+,r26" and "st -X,r26" are undefined.  */
5728         avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5729                      "st X,r26"            CR_TAB
5730                      "adiw r26,1"          CR_TAB
5731                      "st X,__tmp_reg__", op, plen, -4);
5732       else
5733         avr_asm_len ("st X+,%A1" CR_TAB
5734                      "st X,%B1", op, plen, -2);
5735 
5736       return reg_unused_after (insn, base)
5737         ? ""
5738         : avr_asm_len ("sbiw r26,1", op, plen, 1);
5739     }
5740   else if (GET_CODE (base) == PLUS)
5741     {
5742       int disp = INTVAL (XEXP (base, 1));
5743       reg_base = REGNO (XEXP (base, 0));
5744       if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5745         {
5746           if (reg_base != REG_Y)
5747             fatal_insn ("incorrect insn:",insn);
5748 
5749           return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
5750             ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
5751                            "std Y+62,%A1"    CR_TAB
5752                            "std Y+63,%B1"    CR_TAB
5753                            "sbiw r28,%o0-62", op, plen, -4)
5754 
5755             : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5756                            "sbci r29,hi8(-%o0)" CR_TAB
5757                            "st Y,%A1"           CR_TAB
5758                            "std Y+1,%B1"        CR_TAB
5759                            "subi r28,lo8(%o0)"  CR_TAB
5760                            "sbci r29,hi8(%o0)", op, plen, -6);
5761         }
5762 
5763       if (reg_base != REG_X)
5764         return avr_asm_len ("std %A0,%A1" CR_TAB
5765                             "std %B0,%B1", op, plen, -2);
5766       /* (X + d) = R */
5767       return reg_src == REG_X
5768         ? avr_asm_len ("mov __tmp_reg__,r26"  CR_TAB
5769                        "mov __zero_reg__,r27" CR_TAB
5770                        "adiw r26,%o0"         CR_TAB
5771                        "st X+,__tmp_reg__"    CR_TAB
5772                        "st X,__zero_reg__"    CR_TAB
5773                        "clr __zero_reg__"     CR_TAB
5774                        "sbiw r26,%o0+1", op, plen, -7)
5775 
5776         : avr_asm_len ("adiw r26,%o0" CR_TAB
5777                        "st X+,%A1"    CR_TAB
5778                        "st X,%B1"     CR_TAB
5779                        "sbiw r26,%o0+1", op, plen, -4);
5780     }
5781   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5782     {
5783       if (!mem_volatile_p)
5784         return avr_asm_len ("st %0,%B1" CR_TAB
5785                             "st %0,%A1", op, plen, -2);
5786 
5787       return REGNO (XEXP (base, 0)) == REG_X
5788         ? avr_asm_len ("sbiw r26,2"  CR_TAB
5789                        "st X+,%A1"   CR_TAB
5790                        "st X,%B1"    CR_TAB
5791                        "sbiw r26,1", op, plen, -4)
5792 
5793         : avr_asm_len ("sbiw %r0,2"  CR_TAB
5794                        "st %p0,%A1"  CR_TAB
5795                        "std %p0+1,%B1", op, plen, -3);
5796     }
5797   else if (GET_CODE (base) == POST_INC) /* (R++) */
5798     {
5799       return avr_asm_len ("st %0,%A1"  CR_TAB
5800                           "st %0,%B1", op, plen, -2);
5801 
5802     }
5803   fatal_insn ("unknown move insn:",insn);
5804   return "";
5805 }
5806 
5807 static const char*
avr_out_movhi_mr_r_reg_no_disp_tiny(rtx_insn * insn,rtx op[],int * plen)5808 avr_out_movhi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5809 {
5810   rtx dest = op[0];
5811   rtx src = op[1];
5812   rtx base = XEXP (dest, 0);
5813   int reg_base = true_regnum (base);
5814   int reg_src = true_regnum (src);
5815   int mem_volatile_p = MEM_VOLATILE_P (dest);
5816 
5817   if (reg_base == reg_src)
5818     {
5819       return !mem_volatile_p && reg_unused_after (insn, src)
5820         ? avr_asm_len ("mov __tmp_reg__,%B1"   CR_TAB
5821                        "st %0,%A1"             CR_TAB
5822                        TINY_ADIW (%E0, %F0, 1) CR_TAB
5823                        "st %0,__tmp_reg__", op, plen, -5)
5824         : avr_asm_len ("mov __tmp_reg__,%B1"   CR_TAB
5825                        TINY_ADIW (%E0, %F0, 1) CR_TAB
5826                        "st %0,__tmp_reg__"     CR_TAB
5827                        TINY_SBIW (%E0, %F0, 1) CR_TAB
5828                        "st %0, %A1", op, plen, -7);
5829     }
5830 
5831   return !mem_volatile_p && reg_unused_after (insn, base)
5832     ? avr_asm_len ("st %0+,%A1" CR_TAB
5833                    "st %0,%B1", op, plen, -2)
5834     : avr_asm_len (TINY_ADIW (%E0, %F0, 1) CR_TAB
5835                    "st %0,%B1"             CR_TAB
5836                    "st -%0,%A1", op, plen, -4);
5837 }
5838 
5839 static const char*
avr_out_movhi_mr_r_reg_disp_tiny(rtx_insn * insn,rtx op[],int * plen)5840 avr_out_movhi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5841 {
5842   rtx dest = op[0];
5843   rtx src = op[1];
5844   rtx base = XEXP (dest, 0);
5845   int reg_base = REGNO (XEXP (base, 0));
5846   int reg_src = true_regnum (src);
5847 
5848   if (reg_src == reg_base)
5849     avr_asm_len ("mov __tmp_reg__,%A1"          CR_TAB
5850                  "mov __zero_reg__,%B1"         CR_TAB
5851                  TINY_ADIW (%I0, %J0, %o0+1)    CR_TAB
5852                  "st %b0,__zero_reg__"          CR_TAB
5853                  "st -%b0,__tmp_reg__"          CR_TAB
5854                  "clr __zero_reg__", op, plen, -7);
5855   else
5856     avr_asm_len (TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
5857                  "st %b0,%B1"                CR_TAB
5858                  "st -%b0,%A1", op, plen, -4);
5859 
5860   if (!reg_unused_after (insn, XEXP (base, 0)))
5861     avr_asm_len (TINY_SBIW (%I0, %J0, %o0), op, plen, 2);
5862 
5863   return "";
5864 }
5865 
5866 static const char*
avr_out_movhi_mr_r_post_inc_tiny(rtx op[],int * plen)5867 avr_out_movhi_mr_r_post_inc_tiny (rtx op[], int *plen)
5868 {
5869   return avr_asm_len (TINY_ADIW (%I0, %J0, 1)  CR_TAB
5870                       "st %p0,%B1"    CR_TAB
5871                       "st -%p0,%A1"   CR_TAB
5872                       TINY_ADIW (%I0, %J0, 2), op, plen, -6);
5873 }
5874 
5875 static const char*
out_movhi_mr_r(rtx_insn * insn,rtx op[],int * plen)5876 out_movhi_mr_r (rtx_insn *insn, rtx op[], int *plen)
5877 {
5878   rtx dest = op[0];
5879   rtx src = op[1];
5880   rtx base = XEXP (dest, 0);
5881   int reg_base = true_regnum (base);
5882   int reg_src = true_regnum (src);
5883   int mem_volatile_p;
5884 
5885   /* "volatile" forces writing high-byte first (no-xmega) resp.
5886      low-byte first (xmega) even if less efficient, for correct
5887      operation with 16-bit I/O registers like.  */
5888 
5889   if (AVR_XMEGA)
5890     return avr_out_movhi_mr_r_xmega (insn, op, plen);
5891 
5892   mem_volatile_p = MEM_VOLATILE_P (dest);
5893 
5894   if (CONSTANT_ADDRESS_P (base))
5895     {
5896       int n_words = AVR_TINY ? 2 : 4;
5897       return io_address_operand (base, HImode)
5898         ? avr_asm_len ("out %i0+1,%B1" CR_TAB
5899                        "out %i0,%A1", op, plen, -2)
5900 
5901         : avr_asm_len ("sts %m0+1,%B1" CR_TAB
5902                        "sts %m0,%A1", op, plen, -n_words);
5903     }
5904 
5905   if (reg_base > 0)
5906     {
5907       if (AVR_TINY)
5908         return avr_out_movhi_mr_r_reg_no_disp_tiny (insn, op, plen);
5909 
5910       if (reg_base != REG_X)
5911         return avr_asm_len ("std %0+1,%B1" CR_TAB
5912                             "st %0,%A1", op, plen, -2);
5913 
5914       if (reg_src == REG_X)
5915         /* "st X+,r26" and "st -X,r26" are undefined.  */
5916         return !mem_volatile_p && reg_unused_after (insn, src)
5917           ? avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5918                          "st X,r26"            CR_TAB
5919                          "adiw r26,1"          CR_TAB
5920                          "st X,__tmp_reg__", op, plen, -4)
5921 
5922           : avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5923                          "adiw r26,1"          CR_TAB
5924                          "st X,__tmp_reg__"    CR_TAB
5925                          "sbiw r26,1"          CR_TAB
5926                          "st X,r26", op, plen, -5);
5927 
5928       return !mem_volatile_p && reg_unused_after (insn, base)
5929         ? avr_asm_len ("st X+,%A1" CR_TAB
5930                        "st X,%B1", op, plen, -2)
5931         : avr_asm_len ("adiw r26,1" CR_TAB
5932                        "st X,%B1"   CR_TAB
5933                        "st -X,%A1", op, plen, -3);
5934     }
5935   else if (GET_CODE (base) == PLUS)
5936     {
5937       int disp = INTVAL (XEXP (base, 1));
5938 
5939       if (AVR_TINY)
5940         return avr_out_movhi_mr_r_reg_disp_tiny (insn, op, plen);
5941 
5942       reg_base = REGNO (XEXP (base, 0));
5943       if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5944         {
5945           if (reg_base != REG_Y)
5946             fatal_insn ("incorrect insn:",insn);
5947 
5948           return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
5949             ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
5950                            "std Y+63,%B1"    CR_TAB
5951                            "std Y+62,%A1"    CR_TAB
5952                            "sbiw r28,%o0-62", op, plen, -4)
5953 
5954             : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5955                            "sbci r29,hi8(-%o0)" CR_TAB
5956                            "std Y+1,%B1"        CR_TAB
5957                            "st Y,%A1"           CR_TAB
5958                            "subi r28,lo8(%o0)"  CR_TAB
5959                            "sbci r29,hi8(%o0)", op, plen, -6);
5960         }
5961 
5962       if (reg_base != REG_X)
5963         return avr_asm_len ("std %B0,%B1" CR_TAB
5964                             "std %A0,%A1", op, plen, -2);
5965       /* (X + d) = R */
5966       return reg_src == REG_X
5967         ? avr_asm_len ("mov __tmp_reg__,r26"  CR_TAB
5968                        "mov __zero_reg__,r27" CR_TAB
5969                        "adiw r26,%o0+1"       CR_TAB
5970                        "st X,__zero_reg__"    CR_TAB
5971                        "st -X,__tmp_reg__"    CR_TAB
5972                        "clr __zero_reg__"     CR_TAB
5973                        "sbiw r26,%o0", op, plen, -7)
5974 
5975         : avr_asm_len ("adiw r26,%o0+1" CR_TAB
5976                        "st X,%B1"       CR_TAB
5977                        "st -X,%A1"      CR_TAB
5978                        "sbiw r26,%o0", op, plen, -4);
5979     }
5980   else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5981     {
5982       return avr_asm_len ("st %0,%B1" CR_TAB
5983                           "st %0,%A1", op, plen, -2);
5984     }
5985   else if (GET_CODE (base) == POST_INC) /* (R++) */
5986     {
5987       if (!mem_volatile_p)
5988         return avr_asm_len ("st %0,%A1"  CR_TAB
5989                             "st %0,%B1", op, plen, -2);
5990 
5991       if (AVR_TINY)
5992         return avr_out_movhi_mr_r_post_inc_tiny (op, plen);
5993 
5994       return REGNO (XEXP (base, 0)) == REG_X
5995         ? avr_asm_len ("adiw r26,1"  CR_TAB
5996                        "st X,%B1"    CR_TAB
5997                        "st -X,%A1"   CR_TAB
5998                        "adiw r26,2", op, plen, -4)
5999 
6000         : avr_asm_len ("std %p0+1,%B1" CR_TAB
6001                        "st %p0,%A1"    CR_TAB
6002                        "adiw %r0,2", op, plen, -3);
6003     }
6004   fatal_insn ("unknown move insn:",insn);
6005   return "";
6006 }
6007 
6008 /* Return 1 if frame pointer for current function required.  */
6009 
6010 static bool
avr_frame_pointer_required_p(void)6011 avr_frame_pointer_required_p (void)
6012 {
6013   return (cfun->calls_alloca
6014           || cfun->calls_setjmp
6015           || cfun->has_nonlocal_label
6016           || crtl->args.info.nregs == 0
6017           || get_frame_size () > 0);
6018 }
6019 
6020 
6021 /* Returns the condition of the branch following INSN, where INSN is some
6022    comparison.  If the next insn is not a branch or the condition code set
6023    by INSN might be used by more insns than the next one, return UNKNOWN.
6024    For now, just look at the next insn, which misses some opportunities like
6025    following jumps.  */
6026 
6027 static RTX_CODE
compare_condition(rtx_insn * insn)6028 compare_condition (rtx_insn *insn)
6029 {
6030   rtx set;
6031   rtx_insn *next = next_real_nondebug_insn (insn);
6032 
6033   if (next
6034       && JUMP_P (next)
6035       // If SREG does not die in the next insn, it is used in more than one
6036       // branch.  This can happen due to pass .avr-ifelse optimizations.
6037       && dead_or_set_regno_p (next, REG_CC)
6038       // Branches are (set (pc) (if_then_else (COND (...)))).
6039       && (set = single_set (next))
6040       && GET_CODE (SET_SRC (set)) == IF_THEN_ELSE)
6041     {
6042       return GET_CODE (XEXP (SET_SRC (set), 0));
6043     }
6044 
6045   return UNKNOWN;
6046 }
6047 
6048 
6049 /* Returns true if INSN is a tst insn that only tests the sign.  */
6050 
6051 static bool
compare_sign_p(rtx_insn * insn)6052 compare_sign_p (rtx_insn *insn)
6053 {
6054   RTX_CODE cond = compare_condition (insn);
6055   return (cond == GE || cond == LT);
6056 }
6057 
6058 
6059 /* Returns true if INSN is a compare insn with the EQ or NE condition.  */
6060 
6061 static bool
compare_eq_p(rtx_insn * insn)6062 compare_eq_p (rtx_insn *insn)
6063 {
6064   RTX_CODE cond = compare_condition (insn);
6065   return (cond == EQ || cond == NE);
6066 }
6067 
6068 
6069 /* Implement `TARGET_CANONICALIZE_COMPARISON'.  */
6070 /* Basically tries to convert "difficult" comparisons like GT[U]
6071    and LE[U] to simple ones.  Some asymmetric comparisons can be
6072    transformed to EQ or NE against zero.  */
6073 
6074 static void
avr_canonicalize_comparison(int * icode,rtx * op0,rtx * op1,bool op0_fixed)6075 avr_canonicalize_comparison (int *icode, rtx *op0, rtx *op1, bool op0_fixed)
6076 {
6077   enum rtx_code code = (enum rtx_code) *icode;
6078   machine_mode mode = GET_MODE (*op0);
6079 
6080   bool signed_p = code == GT || code == LE;
6081   bool unsigned_p = code == GTU || code == LEU;
6082   bool difficult_p = signed_p || unsigned_p;
6083 
6084   if (// Only do integers and fixed-points.
6085       (! SCALAR_INT_MODE_P (mode)
6086        && ! ALL_SCALAR_FIXED_POINT_MODE_P (mode))
6087       // Only do comparisons against a register.
6088       || ! register_operand (*op0, mode))
6089     return;
6090 
6091   // Canonicalize "difficult" reg-reg comparisons.
6092 
6093   if (! op0_fixed
6094       && difficult_p
6095       && register_operand (*op1, mode))
6096     {
6097       std::swap (*op0, *op1);
6098       *icode = (int) swap_condition (code);
6099       return;
6100     }
6101 
6102   // Canonicalize comparisons against compile-time constants.
6103 
6104   if (CONST_INT_P (*op1)
6105       || CONST_FIXED_P (*op1))
6106     {
6107       // INT_MODE of the same size.
6108       scalar_int_mode imode = int_mode_for_mode (mode).require ();
6109 
6110       unsigned HOST_WIDE_INT mask = GET_MODE_MASK (imode);
6111       unsigned HOST_WIDE_INT maxval = signed_p ? mask >> 1 : mask;
6112 
6113       // Convert value *op1 to imode.
6114       rtx xval = simplify_gen_subreg (imode, *op1, mode, 0);
6115 
6116       // Canonicalize difficult comparisons against const.
6117       if (difficult_p
6118             && (UINTVAL (xval) & mask) != maxval)
6119           {
6120             // Convert *op0 > *op1  to *op0 >= 1 + *op1.
6121             // Convert *op0 <= *op1 to *op0 <  1 + *op1.
6122             xval = simplify_binary_operation (PLUS, imode, xval, const1_rtx);
6123 
6124             // Convert value back to its original mode.
6125             *op1 = simplify_gen_subreg (mode, xval, imode, 0);
6126 
6127             // Map  >  to  >=  and  <=  to  <.
6128             *icode = (int) avr_normalize_condition (code);
6129 
6130             return;
6131           }
6132 
6133       // Some asymmetric comparisons can be turned into EQ or NE.
6134       if (code == LTU && xval == const1_rtx)
6135           {
6136             *icode = (int) EQ;
6137             *op1 = CONST0_RTX (mode);
6138             return;
6139           }
6140 
6141       if (code == GEU && xval == const1_rtx)
6142           {
6143             *icode = (int) NE;
6144             *op1 = CONST0_RTX (mode);
6145             return;
6146           }
6147     }
6148 }
6149 
6150 
6151 /* Output compare instruction
6152 
6153       compare (XOP[0], XOP[1])
6154 
6155    for a register XOP[0] and a compile-time constant XOP[1].  Return "".
6156    XOP[2] is an 8-bit scratch register as needed.
6157 
6158    PLEN == NULL:  Output instructions.
6159    PLEN != NULL:  Set *PLEN to the length (in words) of the sequence.
6160                   Don't output anything.  */
6161 
6162 const char*
avr_out_compare(rtx_insn * insn,rtx * xop,int * plen)6163 avr_out_compare (rtx_insn *insn, rtx *xop, int *plen)
6164 {
6165   /* Register to compare and value to compare against. */
6166   rtx xreg = xop[0];
6167   rtx xval = xop[1];
6168 
6169   /* MODE of the comparison.  */
6170   machine_mode mode;
6171 
6172   /* Number of bytes to operate on.  */
6173   int n_bytes = GET_MODE_SIZE (GET_MODE (xreg));
6174 
6175   /* Value (0..0xff) held in clobber register xop[2] or -1 if unknown.  */
6176   int clobber_val = -1;
6177 
6178   /* Map fixed mode operands to integer operands with the same binary
6179      representation.  They are easier to handle in the remainder.  */
6180 
6181   if (CONST_FIXED_P (xval))
6182     {
6183       xreg = avr_to_int_mode (xop[0]);
6184       xval = avr_to_int_mode (xop[1]);
6185     }
6186 
6187   mode = GET_MODE (xreg);
6188 
6189   gcc_assert (REG_P (xreg));
6190   gcc_assert ((CONST_INT_P (xval) && n_bytes <= 4)
6191               || (const_double_operand (xval, VOIDmode) && n_bytes == 8));
6192 
6193   if (plen)
6194     *plen = 0;
6195 
6196   /* Comparisons == +/-1 and != +/-1 can be done similar to camparing
6197      against 0 by ORing the bytes.  This is one instruction shorter.
6198      Notice that 64-bit comparisons are always against reg:ALL8 18 (ACC_A)
6199      and therefore don't use this.  */
6200 
6201   if (!test_hard_reg_class (LD_REGS, xreg)
6202       && compare_eq_p (insn)
6203       && reg_unused_after (insn, xreg))
6204     {
6205       if (xval == const1_rtx)
6206         {
6207           avr_asm_len ("dec %A0" CR_TAB
6208                        "or %A0,%B0", xop, plen, 2);
6209 
6210           if (n_bytes >= 3)
6211             avr_asm_len ("or %A0,%C0", xop, plen, 1);
6212 
6213           if (n_bytes >= 4)
6214             avr_asm_len ("or %A0,%D0", xop, plen, 1);
6215 
6216           return "";
6217         }
6218       else if (xval == constm1_rtx)
6219         {
6220           if (n_bytes >= 4)
6221             avr_asm_len ("and %A0,%D0", xop, plen, 1);
6222 
6223           if (n_bytes >= 3)
6224             avr_asm_len ("and %A0,%C0", xop, plen, 1);
6225 
6226           return avr_asm_len ("and %A0,%B0" CR_TAB
6227                               "com %A0", xop, plen, 2);
6228         }
6229     }
6230 
6231   /* Comparisons == -1 and != -1 of a d-register that's used after the
6232      comparison.  (If it's unused after we use CPI / SBCI or ADIW sequence
6233      from below.)  Instead of  CPI Rlo,-1 / LDI Rx,-1 / CPC Rhi,Rx  we can
6234      use  CPI Rlo,-1 / CPC Rhi,Rlo  which is 1 instruction shorter:
6235      If CPI is true then Rlo contains -1 and we can use Rlo instead of Rx
6236      when CPC'ing the high part.  If CPI is false then CPC cannot render
6237      the result to true.  This also works for the more generic case where
6238      the constant is of the form 0xabab.  */
6239 
6240   if (n_bytes == 2
6241       && xval != const0_rtx
6242       && test_hard_reg_class (LD_REGS, xreg)
6243       && compare_eq_p (insn)
6244       && !reg_unused_after (insn, xreg))
6245     {
6246       rtx xlo8 = simplify_gen_subreg (QImode, xval, mode, 0);
6247       rtx xhi8 = simplify_gen_subreg (QImode, xval, mode, 1);
6248 
6249       if (INTVAL (xlo8) == INTVAL (xhi8))
6250         {
6251           xop[0] = xreg;
6252           xop[1] = xlo8;
6253 
6254           return avr_asm_len ("cpi %A0,%1"  CR_TAB
6255                               "cpc %B0,%A0", xop, plen, 2);
6256         }
6257     }
6258 
6259   for (int i = 0; i < n_bytes; i++)
6260     {
6261       /* We compare byte-wise.  */
6262       rtx reg8 = simplify_gen_subreg (QImode, xreg, mode, i);
6263       rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
6264 
6265       /* 8-bit value to compare with this byte.  */
6266       unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
6267 
6268       /* Registers R16..R31 can operate with immediate.  */
6269       bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
6270 
6271       xop[0] = reg8;
6272       xop[1] = gen_int_mode (val8, QImode);
6273 
6274       /* Word registers >= R24 can use SBIW/ADIW with 0..63.  */
6275 
6276       if (i == 0
6277           && test_hard_reg_class (ADDW_REGS, reg8))
6278         {
6279           int val16 = trunc_int_for_mode (INTVAL (xval), HImode);
6280 
6281           if (IN_RANGE (val16, 0, 63)
6282               && (val8 == 0
6283                   || reg_unused_after (insn, xreg)))
6284             {
6285               if (AVR_TINY)
6286                 avr_asm_len (TINY_SBIW (%A0, %B0, %1), xop, plen, 2);
6287               else
6288                 avr_asm_len ("sbiw %0,%1", xop, plen, 1);
6289 
6290               i++;
6291               continue;
6292             }
6293 
6294           if (n_bytes == 2
6295               && IN_RANGE (val16, -63, -1)
6296               && compare_eq_p (insn)
6297               && reg_unused_after (insn, xreg))
6298             {
6299               return AVR_TINY
6300                 ? avr_asm_len (TINY_ADIW (%A0, %B0, %n1), xop, plen, 2)
6301                 : avr_asm_len ("adiw %0,%n1", xop, plen, 1);
6302             }
6303         }
6304 
6305       /* Comparing against 0 is easy.  */
6306 
6307       if (val8 == 0)
6308         {
6309           avr_asm_len (i == 0
6310                        ? "cp %0,__zero_reg__"
6311                        : "cpc %0,__zero_reg__", xop, plen, 1);
6312           continue;
6313         }
6314 
6315       /* Upper registers can compare and subtract-with-carry immediates.
6316          Notice that compare instructions do the same as respective subtract
6317          instruction; the only difference is that comparisons don't write
6318          the result back to the target register.  */
6319 
6320       if (ld_reg_p)
6321         {
6322           if (i == 0)
6323             {
6324               avr_asm_len ("cpi %0,%1", xop, plen, 1);
6325               continue;
6326             }
6327           else if (reg_unused_after (insn, xreg))
6328             {
6329               avr_asm_len ("sbci %0,%1", xop, plen, 1);
6330               continue;
6331             }
6332         }
6333 
6334       /* Must load the value into the scratch register.  */
6335 
6336       gcc_assert (REG_P (xop[2]));
6337 
6338       if (clobber_val != (int) val8)
6339         avr_asm_len ("ldi %2,%1", xop, plen, 1);
6340       clobber_val = (int) val8;
6341 
6342       avr_asm_len (i == 0
6343                    ? "cp %0,%2"
6344                    : "cpc %0,%2", xop, plen, 1);
6345     }
6346 
6347   return "";
6348 }
6349 
6350 
6351 /* Prepare operands of compare_const_di2 to be used with avr_out_compare.  */
6352 
6353 const char*
avr_out_compare64(rtx_insn * insn,rtx * op,int * plen)6354 avr_out_compare64 (rtx_insn *insn, rtx *op, int *plen)
6355 {
6356   rtx xop[3];
6357 
6358   xop[0] = gen_rtx_REG (DImode, 18);
6359   xop[1] = op[0];
6360   xop[2] = op[1];
6361 
6362   return avr_out_compare (insn, xop, plen);
6363 }
6364 
6365 /* Output test instruction for HImode.  */
6366 
6367 const char*
avr_out_tsthi(rtx_insn * insn,rtx * op,int * plen)6368 avr_out_tsthi (rtx_insn *insn, rtx *op, int *plen)
6369 {
6370   if (compare_sign_p (insn))
6371     {
6372       avr_asm_len ("tst %B0", op, plen, -1);
6373     }
6374   else if (reg_unused_after (insn, op[0])
6375            && compare_eq_p (insn))
6376     {
6377       /* Faster than sbiw if we can clobber the operand.  */
6378       avr_asm_len ("or %A0,%B0", op, plen, -1);
6379     }
6380   else
6381     {
6382       avr_out_compare (insn, op, plen);
6383     }
6384 
6385   return "";
6386 }
6387 
6388 
6389 /* Output test instruction for PSImode.  */
6390 
6391 const char*
avr_out_tstpsi(rtx_insn * insn,rtx * op,int * plen)6392 avr_out_tstpsi (rtx_insn *insn, rtx *op, int *plen)
6393 {
6394   if (compare_sign_p (insn))
6395     {
6396       avr_asm_len ("tst %C0", op, plen, -1);
6397     }
6398   else if (reg_unused_after (insn, op[0])
6399            && compare_eq_p (insn))
6400     {
6401       /* Faster than sbiw if we can clobber the operand.  */
6402       avr_asm_len ("or %A0,%B0" CR_TAB
6403                    "or %A0,%C0", op, plen, -2);
6404     }
6405   else
6406     {
6407       avr_out_compare (insn, op, plen);
6408     }
6409 
6410   return "";
6411 }
6412 
6413 
6414 /* Output test instruction for SImode.  */
6415 
6416 const char*
avr_out_tstsi(rtx_insn * insn,rtx * op,int * plen)6417 avr_out_tstsi (rtx_insn *insn, rtx *op, int *plen)
6418 {
6419   if (compare_sign_p (insn))
6420     {
6421       avr_asm_len ("tst %D0", op, plen, -1);
6422     }
6423   else if (reg_unused_after (insn, op[0])
6424            && compare_eq_p (insn))
6425     {
6426       /* Faster than sbiw if we can clobber the operand.  */
6427       avr_asm_len ("or %A0,%B0" CR_TAB
6428                    "or %A0,%C0" CR_TAB
6429                    "or %A0,%D0", op, plen, -3);
6430     }
6431   else
6432     {
6433       avr_out_compare (insn, op, plen);
6434     }
6435 
6436   return "";
6437 }
6438 
6439 
6440 /* Output a comparison of a zero- or sign-extended register against a
6441    plain register.  CODE is SIGN_EXTEND or ZERO_EXTEND.  Return "".
6442 
6443    PLEN != 0: Set *PLEN to the code length in words. Don't output anything.
6444    PLEN == 0: Print instructions.  */
6445 
6446 const char*
avr_out_cmp_ext(rtx xop[],enum rtx_code code,int * plen)6447 avr_out_cmp_ext (rtx xop[], enum rtx_code code, int *plen)
6448 {
6449   // The smaller reg is the one that's to be extended.  Get its index as z.
6450   int z = GET_MODE_SIZE (GET_MODE (xop[1])) < GET_MODE_SIZE (GET_MODE (xop[0]));
6451   rtx zreg = xop[z];
6452   rtx reg = xop[1 - z];
6453   machine_mode mode = GET_MODE (reg);
6454   machine_mode zmode = GET_MODE (zreg);
6455   rtx zex;
6456 
6457   if (plen)
6458     *plen = 0;
6459 
6460   // zex holds the extended bytes above zreg.  This is 0 for ZERO_EXTEND,
6461   // and 0 or -1 for SIGN_EXTEND.
6462 
6463   if (code == SIGN_EXTEND)
6464     {
6465       // Sign-extend the high-byte of zreg to tmp_reg.
6466       int zmsb = GET_MODE_SIZE (zmode) - 1;
6467       rtx xzmsb = simplify_gen_subreg (QImode, zreg, zmode, zmsb);
6468 
6469       avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
6470                        "rol __tmp_reg__"    CR_TAB
6471                        "sbc __tmp_reg__,__tmp_reg__", &xzmsb, plen, 3);
6472       zex = tmp_reg_rtx;
6473     }
6474   else if (code == ZERO_EXTEND)
6475     {
6476       zex = zero_reg_rtx;
6477     }
6478   else
6479     gcc_unreachable();
6480 
6481   // Now output n_bytes bytes of the very comparison.
6482 
6483   int n_bytes = GET_MODE_SIZE (mode);
6484 
6485   avr_asm_len ("cp %0,%1", xop, plen, 1);
6486 
6487   for (int b = 1; b < n_bytes; ++b)
6488     {
6489       rtx regs[2];
6490       regs[1 - z] = simplify_gen_subreg (QImode, reg, mode, b);
6491       regs[z] = (b < GET_MODE_SIZE (zmode)
6492                      ? simplify_gen_subreg (QImode, zreg, zmode, b)
6493                      : zex);
6494 
6495       avr_asm_len ("cpc %0,%1", regs, plen, 1);
6496     }
6497 
6498   return "";
6499 }
6500 
6501 
6502 /* Generate asm equivalent for various shifts.  This only handles cases
6503    that are not already carefully hand-optimized in ?sh??i3_out.
6504 
6505    OPERANDS[0] resp. %0 in TEMPL is the operand to be shifted.
6506    OPERANDS[2] is the shift count as CONST_INT, MEM or REG.
6507    OPERANDS[3] is a QImode scratch register from LD regs if
6508                available and SCRATCH, otherwise (no scratch available)
6509 
6510    TEMPL is an assembler template that shifts by one position.
6511    T_LEN is the length of this template.  */
6512 
6513 void
out_shift_with_cnt(const char * templ,rtx_insn * insn,rtx operands[],int * plen,int t_len)6514 out_shift_with_cnt (const char *templ, rtx_insn *insn, rtx operands[],
6515                         int *plen, int t_len)
6516 {
6517   bool second_label = true;
6518   bool saved_in_tmp = false;
6519   bool use_zero_reg = false;
6520   rtx op[5];
6521 
6522   op[0] = operands[0];
6523   op[1] = operands[1];
6524   op[2] = operands[2];
6525   op[3] = operands[3];
6526 
6527   if (plen)
6528     *plen = 0;
6529 
6530   if (CONST_INT_P (operands[2]))
6531     {
6532       /* Operand 3 is a scratch register if this is a
6533          parallel with three elements i.e. a set,
6534          a clobber of a scratch, and clobber of REG_CC.
6535          If a scratch reg is not available, then the parallel
6536          will contain only a set and clobber of REG_CC. */
6537       bool scratch = (GET_CODE (PATTERN (insn)) == PARALLEL
6538                       && XVECLEN (PATTERN (insn), 0) == 3
6539                       && REG_P (operands[3]));
6540       int count = INTVAL (operands[2]);
6541       int max_len = 10;  /* If larger than this, always use a loop.  */
6542 
6543       if (count <= 0)
6544         return;
6545 
6546       if (count < 8 && !scratch)
6547         use_zero_reg = true;
6548 
6549       if (optimize_size)
6550         max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
6551 
6552       if (t_len * count <= max_len)
6553         {
6554           /* Output shifts inline with no loop - faster.  */
6555 
6556           while (count-- > 0)
6557             avr_asm_len (templ, op, plen, t_len);
6558 
6559           return;
6560         }
6561 
6562       if (scratch)
6563         {
6564           avr_asm_len ("ldi %3,%2", op, plen, 1);
6565         }
6566       else if (use_zero_reg)
6567         {
6568           /* Hack to save one word: use __zero_reg__ as loop counter.
6569              Set one bit, then shift in a loop until it is 0 again.  */
6570 
6571           op[3] = zero_reg_rtx;
6572 
6573           avr_asm_len ("set" CR_TAB
6574                        "bld %3,%2-1", op, plen, 2);
6575         }
6576       else
6577         {
6578           /* No scratch register available, use one from LD_REGS (saved in
6579              __tmp_reg__) that doesn't overlap with registers to shift.  */
6580 
6581           op[3] = all_regs_rtx[((REGNO (op[0]) - 1) & 15) + 16];
6582           op[4] = tmp_reg_rtx;
6583           saved_in_tmp = true;
6584 
6585           avr_asm_len ("mov %4,%3" CR_TAB
6586                        "ldi %3,%2", op, plen, 2);
6587         }
6588 
6589       second_label = false;
6590     }
6591   else if (MEM_P (op[2]))
6592     {
6593       rtx op_mov[2];
6594 
6595       op_mov[0] = op[3] = tmp_reg_rtx;
6596       op_mov[1] = op[2];
6597 
6598       out_movqi_r_mr (insn, op_mov, plen);
6599     }
6600   else if (register_operand (op[2], QImode))
6601     {
6602       op[3] = op[2];
6603 
6604       if (!reg_unused_after (insn, op[2])
6605           || reg_overlap_mentioned_p (op[0], op[2]))
6606         {
6607           op[3] = tmp_reg_rtx;
6608           avr_asm_len ("mov %3,%2", op, plen, 1);
6609         }
6610     }
6611   else
6612     fatal_insn ("bad shift insn:", insn);
6613 
6614   if (second_label)
6615     avr_asm_len ("rjmp 2f", op, plen, 1);
6616 
6617   avr_asm_len ("1:", op, plen, 0);
6618   avr_asm_len (templ, op, plen, t_len);
6619 
6620   if (second_label)
6621     avr_asm_len ("2:", op, plen, 0);
6622 
6623   avr_asm_len (use_zero_reg ? "lsr %3" : "dec %3", op, plen, 1);
6624   avr_asm_len (second_label ? "brpl 1b" : "brne 1b", op, plen, 1);
6625 
6626   if (saved_in_tmp)
6627     avr_asm_len ("mov %3,%4", op, plen, 1);
6628 }
6629 
6630 
6631 /* 8bit shift left ((char)x << i)   */
6632 
6633 const char *
ashlqi3_out(rtx_insn * insn,rtx operands[],int * len)6634 ashlqi3_out (rtx_insn *insn, rtx operands[], int *len)
6635 {
6636   if (CONST_INT_P (operands[2]))
6637     {
6638       int k;
6639 
6640       if (!len)
6641           len = &k;
6642 
6643       switch (INTVAL (operands[2]))
6644           {
6645           default:
6646             if (INTVAL (operands[2]) < 8)
6647               break;
6648 
6649             *len = 1;
6650             return "clr %0";
6651 
6652           case 1:
6653             *len = 1;
6654             return "lsl %0";
6655 
6656           case 2:
6657             *len = 2;
6658             return ("lsl %0" CR_TAB
6659                       "lsl %0");
6660 
6661           case 3:
6662             *len = 3;
6663             return ("lsl %0" CR_TAB
6664                       "lsl %0" CR_TAB
6665                       "lsl %0");
6666 
6667           case 4:
6668             if (test_hard_reg_class (LD_REGS, operands[0]))
6669               {
6670                 *len = 2;
6671                 return ("swap %0" CR_TAB
6672                           "andi %0,0xf0");
6673               }
6674             *len = 4;
6675             return ("lsl %0" CR_TAB
6676                       "lsl %0" CR_TAB
6677                       "lsl %0" CR_TAB
6678                       "lsl %0");
6679 
6680           case 5:
6681             if (test_hard_reg_class (LD_REGS, operands[0]))
6682               {
6683                 *len = 3;
6684                 return ("swap %0" CR_TAB
6685                           "lsl %0"  CR_TAB
6686                           "andi %0,0xe0");
6687               }
6688             *len = 5;
6689             return ("lsl %0" CR_TAB
6690                       "lsl %0" CR_TAB
6691                       "lsl %0" CR_TAB
6692                       "lsl %0" CR_TAB
6693                       "lsl %0");
6694 
6695           case 6:
6696             if (test_hard_reg_class (LD_REGS, operands[0]))
6697               {
6698                 *len = 4;
6699                 return ("swap %0" CR_TAB
6700                           "lsl %0"  CR_TAB
6701                           "lsl %0"  CR_TAB
6702                           "andi %0,0xc0");
6703               }
6704             *len = 6;
6705             return ("lsl %0" CR_TAB
6706                       "lsl %0" CR_TAB
6707                       "lsl %0" CR_TAB
6708                       "lsl %0" CR_TAB
6709                       "lsl %0" CR_TAB
6710                       "lsl %0");
6711 
6712           case 7:
6713             *len = 3;
6714             return ("ror %0" CR_TAB
6715                       "clr %0" CR_TAB
6716                       "ror %0");
6717           }
6718     }
6719   else if (CONSTANT_P (operands[2]))
6720     fatal_insn ("internal compiler error.  Incorrect shift:", insn);
6721 
6722   out_shift_with_cnt ("lsl %0",
6723                       insn, operands, len, 1);
6724   return "";
6725 }
6726 
6727 
6728 /* 16bit shift left ((short)x << i)   */
6729 
6730 const char *
ashlhi3_out(rtx_insn * insn,rtx operands[],int * len)6731 ashlhi3_out (rtx_insn *insn, rtx operands[], int *len)
6732 {
6733   if (CONST_INT_P (operands[2]))
6734     {
6735       int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL
6736                      && XVECLEN (PATTERN (insn), 0) == 3
6737                      && REG_P (operands[3]));
6738       int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
6739       int k;
6740       int *t = len;
6741 
6742       if (!len)
6743           len = &k;
6744 
6745       switch (INTVAL (operands[2]))
6746           {
6747           default:
6748             if (INTVAL (operands[2]) < 16)
6749               break;
6750 
6751             *len = 2;
6752             return ("clr %B0" CR_TAB
6753                       "clr %A0");
6754 
6755           case 4:
6756             if (optimize_size && scratch)
6757               break;  /* 5 */
6758             if (ldi_ok)
6759               {
6760                 *len = 6;
6761                 return ("swap %A0"      CR_TAB
6762                           "swap %B0"      CR_TAB
6763                           "andi %B0,0xf0" CR_TAB
6764                           "eor %B0,%A0"   CR_TAB
6765                           "andi %A0,0xf0" CR_TAB
6766                           "eor %B0,%A0");
6767               }
6768             if (scratch)
6769               {
6770                 *len = 7;
6771                 return ("swap %A0"    CR_TAB
6772                           "swap %B0"    CR_TAB
6773                           "ldi %3,0xf0" CR_TAB
6774                           "and %B0,%3"  CR_TAB
6775                           "eor %B0,%A0" CR_TAB
6776                           "and %A0,%3"  CR_TAB
6777                           "eor %B0,%A0");
6778               }
6779             break;  /* optimize_size ? 6 : 8 */
6780 
6781           case 5:
6782             if (optimize_size)
6783               break;  /* scratch ? 5 : 6 */
6784             if (ldi_ok)
6785               {
6786                 *len = 8;
6787                 return ("lsl %A0"       CR_TAB
6788                           "rol %B0"       CR_TAB
6789                           "swap %A0"      CR_TAB
6790                           "swap %B0"      CR_TAB
6791                           "andi %B0,0xf0" CR_TAB
6792                           "eor %B0,%A0"   CR_TAB
6793                           "andi %A0,0xf0" CR_TAB
6794                           "eor %B0,%A0");
6795               }
6796             if (scratch)
6797               {
6798                 *len = 9;
6799                 return ("lsl %A0"     CR_TAB
6800                           "rol %B0"     CR_TAB
6801                           "swap %A0"    CR_TAB
6802                           "swap %B0"    CR_TAB
6803                           "ldi %3,0xf0" CR_TAB
6804                           "and %B0,%3"  CR_TAB
6805                           "eor %B0,%A0" CR_TAB
6806                           "and %A0,%3"  CR_TAB
6807                           "eor %B0,%A0");
6808               }
6809             break;  /* 10 */
6810 
6811           case 6:
6812             if (optimize_size)
6813               break;  /* scratch ? 5 : 6 */
6814             *len = 9;
6815             return ("clr __tmp_reg__" CR_TAB
6816                       "lsr %B0"         CR_TAB
6817                       "ror %A0"         CR_TAB
6818                       "ror __tmp_reg__" CR_TAB
6819                       "lsr %B0"         CR_TAB
6820                       "ror %A0"         CR_TAB
6821                       "ror __tmp_reg__" CR_TAB
6822                       "mov %B0,%A0"     CR_TAB
6823                       "mov %A0,__tmp_reg__");
6824 
6825           case 7:
6826             *len = 5;
6827             return ("lsr %B0"     CR_TAB
6828                       "mov %B0,%A0" CR_TAB
6829                       "clr %A0"     CR_TAB
6830                       "ror %B0"     CR_TAB
6831                       "ror %A0");
6832 
6833           case 8:
6834             return *len = 2, ("mov %B0,%A1" CR_TAB
6835                                   "clr %A0");
6836 
6837           case 9:
6838             *len = 3;
6839             return ("mov %B0,%A0" CR_TAB
6840                       "clr %A0"     CR_TAB
6841                       "lsl %B0");
6842 
6843           case 10:
6844             *len = 4;
6845             return ("mov %B0,%A0" CR_TAB
6846                       "clr %A0"     CR_TAB
6847                       "lsl %B0"     CR_TAB
6848                       "lsl %B0");
6849 
6850           case 11:
6851             *len = 5;
6852             return ("mov %B0,%A0" CR_TAB
6853                       "clr %A0"     CR_TAB
6854                       "lsl %B0"     CR_TAB
6855                       "lsl %B0"     CR_TAB
6856                       "lsl %B0");
6857 
6858           case 12:
6859             if (ldi_ok)
6860               {
6861                 *len = 4;
6862                 return ("mov %B0,%A0" CR_TAB
6863                           "clr %A0"     CR_TAB
6864                           "swap %B0"    CR_TAB
6865                           "andi %B0,0xf0");
6866               }
6867             if (scratch)
6868               {
6869                 *len = 5;
6870                 return ("mov %B0,%A0" CR_TAB
6871                           "clr %A0"     CR_TAB
6872                           "swap %B0"    CR_TAB
6873                           "ldi %3,0xf0" CR_TAB
6874                           "and %B0,%3");
6875               }
6876             *len = 6;
6877             return ("mov %B0,%A0" CR_TAB
6878                       "clr %A0"     CR_TAB
6879                       "lsl %B0"     CR_TAB
6880                       "lsl %B0"     CR_TAB
6881                       "lsl %B0"     CR_TAB
6882                       "lsl %B0");
6883 
6884           case 13:
6885             if (ldi_ok)
6886               {
6887                 *len = 5;
6888                 return ("mov %B0,%A0" CR_TAB
6889                           "clr %A0"     CR_TAB
6890                           "swap %B0"    CR_TAB
6891                           "lsl %B0"     CR_TAB
6892                           "andi %B0,0xe0");
6893               }
6894             if (AVR_HAVE_MUL && scratch)
6895               {
6896                 *len = 5;
6897                 return ("ldi %3,0x20" CR_TAB
6898                           "mul %A0,%3"  CR_TAB
6899                           "mov %B0,r0"  CR_TAB
6900                           "clr %A0"     CR_TAB
6901                           "clr __zero_reg__");
6902               }
6903             if (optimize_size && scratch)
6904               break;  /* 5 */
6905             if (scratch)
6906               {
6907                 *len = 6;
6908                 return ("mov %B0,%A0" CR_TAB
6909                           "clr %A0"     CR_TAB
6910                           "swap %B0"    CR_TAB
6911                           "lsl %B0"     CR_TAB
6912                           "ldi %3,0xe0" CR_TAB
6913                           "and %B0,%3");
6914               }
6915             if (AVR_HAVE_MUL)
6916               {
6917                 *len = 6;
6918                 return ("set"        CR_TAB
6919                           "bld r1,5"   CR_TAB
6920                           "mul %A0,r1" CR_TAB
6921                           "mov %B0,r0" CR_TAB
6922                           "clr %A0"    CR_TAB
6923                           "clr __zero_reg__");
6924               }
6925             *len = 7;
6926             return ("mov %B0,%A0" CR_TAB
6927                       "clr %A0"     CR_TAB
6928                       "lsl %B0"     CR_TAB
6929                       "lsl %B0"     CR_TAB
6930                       "lsl %B0"     CR_TAB
6931                       "lsl %B0"     CR_TAB
6932                       "lsl %B0");
6933 
6934           case 14:
6935             if (AVR_HAVE_MUL && ldi_ok)
6936               {
6937                 *len = 5;
6938                 return ("ldi %B0,0x40" CR_TAB
6939                           "mul %A0,%B0"  CR_TAB
6940                           "mov %B0,r0"   CR_TAB
6941                           "clr %A0"      CR_TAB
6942                           "clr __zero_reg__");
6943               }
6944             if (AVR_HAVE_MUL && scratch)
6945               {
6946                 *len = 5;
6947                 return ("ldi %3,0x40" CR_TAB
6948                           "mul %A0,%3"  CR_TAB
6949                           "mov %B0,r0"  CR_TAB
6950                           "clr %A0"     CR_TAB
6951                           "clr __zero_reg__");
6952               }
6953             if (optimize_size && ldi_ok)
6954               {
6955                 *len = 5;
6956                 return ("mov %B0,%A0" CR_TAB
6957                           "ldi %A0,6" "\n1:\t"
6958                           "lsl %B0"     CR_TAB
6959                           "dec %A0"     CR_TAB
6960                           "brne 1b");
6961               }
6962             if (optimize_size && scratch)
6963               break;  /* 5 */
6964             *len = 6;
6965             return ("clr %B0" CR_TAB
6966                       "lsr %A0" CR_TAB
6967                       "ror %B0" CR_TAB
6968                       "lsr %A0" CR_TAB
6969                       "ror %B0" CR_TAB
6970                       "clr %A0");
6971 
6972           case 15:
6973             *len = 4;
6974             return ("clr %B0" CR_TAB
6975                       "lsr %A0" CR_TAB
6976                       "ror %B0" CR_TAB
6977                       "clr %A0");
6978           }
6979       len = t;
6980     }
6981   out_shift_with_cnt ("lsl %A0" CR_TAB
6982                       "rol %B0", insn, operands, len, 2);
6983   return "";
6984 }
6985 
6986 
6987 /* 24-bit shift left */
6988 
6989 const char*
avr_out_ashlpsi3(rtx_insn * insn,rtx * op,int * plen)6990 avr_out_ashlpsi3 (rtx_insn *insn, rtx *op, int *plen)
6991 {
6992   if (plen)
6993     *plen = 0;
6994 
6995   if (CONST_INT_P (op[2]))
6996     {
6997       switch (INTVAL (op[2]))
6998         {
6999         default:
7000           if (INTVAL (op[2]) < 24)
7001             break;
7002 
7003           return avr_asm_len ("clr %A0" CR_TAB
7004                               "clr %B0" CR_TAB
7005                               "clr %C0", op, plen, 3);
7006 
7007         case 8:
7008           {
7009             int reg0 = REGNO (op[0]);
7010             int reg1 = REGNO (op[1]);
7011 
7012             if (reg0 >= reg1)
7013               return avr_asm_len ("mov %C0,%B1"  CR_TAB
7014                                   "mov %B0,%A1"  CR_TAB
7015                                   "clr %A0", op, plen, 3);
7016             else
7017               return avr_asm_len ("clr %A0"      CR_TAB
7018                                   "mov %B0,%A1"  CR_TAB
7019                                   "mov %C0,%B1", op, plen, 3);
7020           }
7021 
7022         case 16:
7023           {
7024             int reg0 = REGNO (op[0]);
7025             int reg1 = REGNO (op[1]);
7026 
7027             if (reg0 + 2 != reg1)
7028               avr_asm_len ("mov %C0,%A0", op, plen, 1);
7029 
7030             return avr_asm_len ("clr %B0"  CR_TAB
7031                                 "clr %A0", op, plen, 2);
7032           }
7033 
7034         case 23:
7035           return avr_asm_len ("clr %C0" CR_TAB
7036                               "lsr %A0" CR_TAB
7037                               "ror %C0" CR_TAB
7038                               "clr %B0" CR_TAB
7039                               "clr %A0", op, plen, 5);
7040         }
7041     }
7042 
7043   out_shift_with_cnt ("lsl %A0" CR_TAB
7044                       "rol %B0" CR_TAB
7045                       "rol %C0", insn, op, plen, 3);
7046   return "";
7047 }
7048 
7049 
7050 /* 32bit shift left ((long)x << i)   */
7051 
7052 const char *
ashlsi3_out(rtx_insn * insn,rtx operands[],int * len)7053 ashlsi3_out (rtx_insn *insn, rtx operands[], int *len)
7054 {
7055   if (CONST_INT_P (operands[2]))
7056     {
7057       int k;
7058       int *t = len;
7059 
7060       if (!len)
7061           len = &k;
7062 
7063       switch (INTVAL (operands[2]))
7064           {
7065           default:
7066             if (INTVAL (operands[2]) < 32)
7067               break;
7068 
7069             if (AVR_HAVE_MOVW)
7070               return *len = 3, ("clr %D0" CR_TAB
7071                                     "clr %C0" CR_TAB
7072                                     "movw %A0,%C0");
7073             *len = 4;
7074             return ("clr %D0" CR_TAB
7075                       "clr %C0" CR_TAB
7076                       "clr %B0" CR_TAB
7077                       "clr %A0");
7078 
7079           case 8:
7080             {
7081               int reg0 = true_regnum (operands[0]);
7082               int reg1 = true_regnum (operands[1]);
7083               *len = 4;
7084               if (reg0 >= reg1)
7085                 return ("mov %D0,%C1"  CR_TAB
7086                           "mov %C0,%B1"  CR_TAB
7087                           "mov %B0,%A1"  CR_TAB
7088                           "clr %A0");
7089               else
7090                 return ("clr %A0"      CR_TAB
7091                           "mov %B0,%A1"  CR_TAB
7092                           "mov %C0,%B1"  CR_TAB
7093                           "mov %D0,%C1");
7094             }
7095 
7096           case 16:
7097             {
7098               int reg0 = true_regnum (operands[0]);
7099               int reg1 = true_regnum (operands[1]);
7100               if (reg0 + 2 == reg1)
7101                 return *len = 2, ("clr %B0"      CR_TAB
7102                                         "clr %A0");
7103               if (AVR_HAVE_MOVW)
7104                 return *len = 3, ("movw %C0,%A1" CR_TAB
7105                                         "clr %B0"      CR_TAB
7106                                         "clr %A0");
7107               else
7108                 return *len = 4, ("mov %C0,%A1"  CR_TAB
7109                                         "mov %D0,%B1"  CR_TAB
7110                                         "clr %B0"      CR_TAB
7111                                         "clr %A0");
7112             }
7113 
7114           case 24:
7115             *len = 4;
7116             return ("mov %D0,%A1"  CR_TAB
7117                       "clr %C0"      CR_TAB
7118                       "clr %B0"      CR_TAB
7119                       "clr %A0");
7120 
7121           case 31:
7122             *len = 6;
7123             return ("clr %D0" CR_TAB
7124                       "lsr %A0" CR_TAB
7125                       "ror %D0" CR_TAB
7126                       "clr %C0" CR_TAB
7127                       "clr %B0" CR_TAB
7128                       "clr %A0");
7129           }
7130       len = t;
7131     }
7132   out_shift_with_cnt ("lsl %A0" CR_TAB
7133                       "rol %B0" CR_TAB
7134                       "rol %C0" CR_TAB
7135                       "rol %D0", insn, operands, len, 4);
7136   return "";
7137 }
7138 
7139 /* 8bit arithmetic shift right  ((signed char)x >> i) */
7140 
7141 const char *
ashrqi3_out(rtx_insn * insn,rtx operands[],int * len)7142 ashrqi3_out (rtx_insn *insn, rtx operands[], int *len)
7143 {
7144   if (CONST_INT_P (operands[2]))
7145     {
7146       int k;
7147 
7148       if (!len)
7149           len = &k;
7150 
7151       switch (INTVAL (operands[2]))
7152           {
7153           case 1:
7154             *len = 1;
7155             return "asr %0";
7156 
7157           case 2:
7158             *len = 2;
7159             return ("asr %0" CR_TAB
7160                       "asr %0");
7161 
7162           case 3:
7163             *len = 3;
7164             return ("asr %0" CR_TAB
7165                       "asr %0" CR_TAB
7166                       "asr %0");
7167 
7168           case 4:
7169             *len = 4;
7170             return ("asr %0" CR_TAB
7171                       "asr %0" CR_TAB
7172                       "asr %0" CR_TAB
7173                       "asr %0");
7174 
7175           case 5:
7176             *len = 5;
7177             return ("asr %0" CR_TAB
7178                       "asr %0" CR_TAB
7179                       "asr %0" CR_TAB
7180                       "asr %0" CR_TAB
7181                       "asr %0");
7182 
7183           case 6:
7184             *len = 4;
7185             return ("bst %0,6"  CR_TAB
7186                       "lsl %0"    CR_TAB
7187                       "sbc %0,%0" CR_TAB
7188                       "bld %0,0");
7189 
7190           default:
7191             if (INTVAL (operands[2]) < 8)
7192               break;
7193 
7194             /* fall through */
7195 
7196           case 7:
7197             *len = 2;
7198             return ("lsl %0" CR_TAB
7199                       "sbc %0,%0");
7200           }
7201     }
7202   else if (CONSTANT_P (operands[2]))
7203     fatal_insn ("internal compiler error.  Incorrect shift:", insn);
7204 
7205   out_shift_with_cnt ("asr %0",
7206                       insn, operands, len, 1);
7207   return "";
7208 }
7209 
7210 
7211 /* 16bit arithmetic shift right  ((signed short)x >> i) */
7212 
7213 const char *
ashrhi3_out(rtx_insn * insn,rtx operands[],int * len)7214 ashrhi3_out (rtx_insn *insn, rtx operands[], int *len)
7215 {
7216   if (CONST_INT_P (operands[2]))
7217     {
7218       int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL
7219                      && XVECLEN (PATTERN (insn), 0) == 3
7220                      && REG_P (operands[3]));
7221       int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
7222       int k;
7223       int *t = len;
7224 
7225       if (!len)
7226           len = &k;
7227 
7228       switch (INTVAL (operands[2]))
7229           {
7230           case 4:
7231           case 5:
7232             /* XXX try to optimize this too? */
7233             break;
7234 
7235           case 6:
7236             if (optimize_size)
7237               break;  /* scratch ? 5 : 6 */
7238             *len = 8;
7239             return ("mov __tmp_reg__,%A0" CR_TAB
7240                       "mov %A0,%B0"         CR_TAB
7241                       "lsl __tmp_reg__"     CR_TAB
7242                       "rol %A0"             CR_TAB
7243                       "sbc %B0,%B0"         CR_TAB
7244                       "lsl __tmp_reg__"     CR_TAB
7245                       "rol %A0"             CR_TAB
7246                       "rol %B0");
7247 
7248           case 7:
7249             *len = 4;
7250             return ("lsl %A0"     CR_TAB
7251                       "mov %A0,%B0" CR_TAB
7252                       "rol %A0"     CR_TAB
7253                       "sbc %B0,%B0");
7254 
7255           case 8:
7256             {
7257               int reg0 = true_regnum (operands[0]);
7258               int reg1 = true_regnum (operands[1]);
7259 
7260               if (reg0 == reg1)
7261                 return *len = 3, ("mov %A0,%B0" CR_TAB
7262                                         "lsl %B0"     CR_TAB
7263                                         "sbc %B0,%B0");
7264               else
7265                 return *len = 4, ("mov %A0,%B1" CR_TAB
7266                                       "clr %B0"     CR_TAB
7267                                       "sbrc %A0,7"  CR_TAB
7268                                       "dec %B0");
7269             }
7270 
7271           case 9:
7272             *len = 4;
7273             return ("mov %A0,%B0" CR_TAB
7274                       "lsl %B0"      CR_TAB
7275                       "sbc %B0,%B0" CR_TAB
7276                       "asr %A0");
7277 
7278           case 10:
7279             *len = 5;
7280             return ("mov %A0,%B0" CR_TAB
7281                       "lsl %B0"     CR_TAB
7282                       "sbc %B0,%B0" CR_TAB
7283                       "asr %A0"     CR_TAB
7284                       "asr %A0");
7285 
7286           case 11:
7287             if (AVR_HAVE_MUL && ldi_ok)
7288               {
7289                 *len = 5;
7290                 return ("ldi %A0,0x20" CR_TAB
7291                           "muls %B0,%A0" CR_TAB
7292                           "mov %A0,r1"   CR_TAB
7293                           "sbc %B0,%B0"  CR_TAB
7294                           "clr __zero_reg__");
7295               }
7296             if (optimize_size && scratch)
7297               break;  /* 5 */
7298             *len = 6;
7299             return ("mov %A0,%B0" CR_TAB
7300                       "lsl %B0"     CR_TAB
7301                       "sbc %B0,%B0" CR_TAB
7302                       "asr %A0"     CR_TAB
7303                       "asr %A0"     CR_TAB
7304                       "asr %A0");
7305 
7306           case 12:
7307             if (AVR_HAVE_MUL && ldi_ok)
7308               {
7309                 *len = 5;
7310                 return ("ldi %A0,0x10" CR_TAB
7311                           "muls %B0,%A0" CR_TAB
7312                           "mov %A0,r1"   CR_TAB
7313                           "sbc %B0,%B0"  CR_TAB
7314                           "clr __zero_reg__");
7315               }
7316             if (optimize_size && scratch)
7317               break;  /* 5 */
7318             *len = 7;
7319             return ("mov %A0,%B0" CR_TAB
7320                       "lsl %B0"     CR_TAB
7321                       "sbc %B0,%B0" CR_TAB
7322                       "asr %A0"     CR_TAB
7323                       "asr %A0"     CR_TAB
7324                       "asr %A0"     CR_TAB
7325                       "asr %A0");
7326 
7327           case 13:
7328             if (AVR_HAVE_MUL && ldi_ok)
7329               {
7330                 *len = 5;
7331                 return ("ldi %A0,0x08" CR_TAB
7332                           "muls %B0,%A0" CR_TAB
7333                           "mov %A0,r1"   CR_TAB
7334                           "sbc %B0,%B0"  CR_TAB
7335                           "clr __zero_reg__");
7336               }
7337             if (optimize_size)
7338               break;  /* scratch ? 5 : 7 */
7339             *len = 8;
7340             return ("mov %A0,%B0" CR_TAB
7341                       "lsl %B0"     CR_TAB
7342                       "sbc %B0,%B0" CR_TAB
7343                       "asr %A0"     CR_TAB
7344                       "asr %A0"     CR_TAB
7345                       "asr %A0"     CR_TAB
7346                       "asr %A0"     CR_TAB
7347                       "asr %A0");
7348 
7349           case 14:
7350             *len = 5;
7351             return ("lsl %B0"     CR_TAB
7352                       "sbc %A0,%A0" CR_TAB
7353                       "lsl %B0"     CR_TAB
7354                       "mov %B0,%A0" CR_TAB
7355                       "rol %A0");
7356 
7357           default:
7358             if (INTVAL (operands[2]) < 16)
7359               break;
7360 
7361             /* fall through */
7362 
7363           case 15:
7364             return *len = 3, ("lsl %B0"     CR_TAB
7365                                   "sbc %A0,%A0" CR_TAB
7366                                   "mov %B0,%A0");
7367           }
7368       len = t;
7369     }
7370   out_shift_with_cnt ("asr %B0" CR_TAB
7371                       "ror %A0", insn, operands, len, 2);
7372   return "";
7373 }
7374 
7375 
7376 /* 24-bit arithmetic shift right */
7377 
7378 const char*
avr_out_ashrpsi3(rtx_insn * insn,rtx * op,int * plen)7379 avr_out_ashrpsi3 (rtx_insn *insn, rtx *op, int *plen)
7380 {
7381   int dest = REGNO (op[0]);
7382   int src = REGNO (op[1]);
7383 
7384   if (CONST_INT_P (op[2]))
7385     {
7386       if (plen)
7387         *plen = 0;
7388 
7389       switch (INTVAL (op[2]))
7390         {
7391         case 8:
7392           if (dest <= src)
7393             return avr_asm_len ("mov %A0,%B1" CR_TAB
7394                                 "mov %B0,%C1" CR_TAB
7395                                 "clr %C0"     CR_TAB
7396                                 "sbrc %B0,7"  CR_TAB
7397                                 "dec %C0", op, plen, 5);
7398           else
7399             return avr_asm_len ("clr %C0"     CR_TAB
7400                                 "sbrc %C1,7"  CR_TAB
7401                                 "dec %C0"     CR_TAB
7402                                 "mov %B0,%C1" CR_TAB
7403                                 "mov %A0,%B1", op, plen, 5);
7404 
7405         case 16:
7406           if (dest != src + 2)
7407             avr_asm_len ("mov %A0,%C1", op, plen, 1);
7408 
7409           return avr_asm_len ("clr %B0"     CR_TAB
7410                               "sbrc %A0,7"  CR_TAB
7411                               "com %B0"     CR_TAB
7412                               "mov %C0,%B0", op, plen, 4);
7413 
7414         default:
7415           if (INTVAL (op[2]) < 24)
7416             break;
7417 
7418           /* fall through */
7419 
7420         case 23:
7421           return avr_asm_len ("lsl %C0"     CR_TAB
7422                               "sbc %A0,%A0" CR_TAB
7423                               "mov %B0,%A0" CR_TAB
7424                               "mov %C0,%A0", op, plen, 4);
7425         } /* switch */
7426     }
7427 
7428   out_shift_with_cnt ("asr %C0" CR_TAB
7429                       "ror %B0" CR_TAB
7430                       "ror %A0", insn, op, plen, 3);
7431   return "";
7432 }
7433 
7434 
7435 /* 32-bit arithmetic shift right  ((signed long)x >> i) */
7436 
7437 const char *
ashrsi3_out(rtx_insn * insn,rtx operands[],int * len)7438 ashrsi3_out (rtx_insn *insn, rtx operands[], int *len)
7439 {
7440   if (CONST_INT_P (operands[2]))
7441     {
7442       int k;
7443       int *t = len;
7444 
7445       if (!len)
7446           len = &k;
7447 
7448       switch (INTVAL (operands[2]))
7449           {
7450           case 8:
7451             {
7452               int reg0 = true_regnum (operands[0]);
7453               int reg1 = true_regnum (operands[1]);
7454               *len=6;
7455               if (reg0 <= reg1)
7456                 return ("mov %A0,%B1" CR_TAB
7457                           "mov %B0,%C1" CR_TAB
7458                           "mov %C0,%D1" CR_TAB
7459                           "clr %D0"     CR_TAB
7460                           "sbrc %C0,7"  CR_TAB
7461                           "dec %D0");
7462               else
7463                 return ("clr %D0"     CR_TAB
7464                           "sbrc %D1,7"  CR_TAB
7465                           "dec %D0"     CR_TAB
7466                           "mov %C0,%D1" CR_TAB
7467                           "mov %B0,%C1" CR_TAB
7468                           "mov %A0,%B1");
7469             }
7470 
7471           case 16:
7472             {
7473               int reg0 = true_regnum (operands[0]);
7474               int reg1 = true_regnum (operands[1]);
7475 
7476               if (reg0 == reg1 + 2)
7477                 return *len = 4, ("clr %D0"     CR_TAB
7478                                         "sbrc %B0,7"  CR_TAB
7479                                         "com %D0"     CR_TAB
7480                                         "mov %C0,%D0");
7481               if (AVR_HAVE_MOVW)
7482                 return *len = 5, ("movw %A0,%C1" CR_TAB
7483                                         "clr %D0"      CR_TAB
7484                                         "sbrc %B0,7"   CR_TAB
7485                                         "com %D0"      CR_TAB
7486                                         "mov %C0,%D0");
7487               else
7488                 return *len = 6, ("mov %B0,%D1" CR_TAB
7489                                         "mov %A0,%C1" CR_TAB
7490                                         "clr %D0"     CR_TAB
7491                                         "sbrc %B0,7"  CR_TAB
7492                                         "com %D0"     CR_TAB
7493                                         "mov %C0,%D0");
7494             }
7495 
7496           case 24:
7497             return *len = 6, ("mov %A0,%D1" CR_TAB
7498                                   "clr %D0"     CR_TAB
7499                                   "sbrc %A0,7"  CR_TAB
7500                                   "com %D0"     CR_TAB
7501                                   "mov %B0,%D0" CR_TAB
7502                                   "mov %C0,%D0");
7503 
7504           default:
7505             if (INTVAL (operands[2]) < 32)
7506               break;
7507 
7508             /* fall through */
7509 
7510           case 31:
7511             if (AVR_HAVE_MOVW)
7512               return *len = 4, ("lsl %D0"     CR_TAB
7513                                     "sbc %A0,%A0" CR_TAB
7514                                     "mov %B0,%A0" CR_TAB
7515                                     "movw %C0,%A0");
7516             else
7517               return *len = 5, ("lsl %D0"     CR_TAB
7518                                     "sbc %A0,%A0" CR_TAB
7519                                     "mov %B0,%A0" CR_TAB
7520                                     "mov %C0,%A0" CR_TAB
7521                                     "mov %D0,%A0");
7522           }
7523       len = t;
7524     }
7525   out_shift_with_cnt ("asr %D0" CR_TAB
7526                       "ror %C0" CR_TAB
7527                       "ror %B0" CR_TAB
7528                       "ror %A0", insn, operands, len, 4);
7529   return "";
7530 }
7531 
7532 /* 8-bit logic shift right ((unsigned char)x >> i) */
7533 
7534 const char *
lshrqi3_out(rtx_insn * insn,rtx operands[],int * len)7535 lshrqi3_out (rtx_insn *insn, rtx operands[], int *len)
7536 {
7537   if (CONST_INT_P (operands[2]))
7538     {
7539       int k;
7540 
7541       if (!len)
7542           len = &k;
7543 
7544       switch (INTVAL (operands[2]))
7545           {
7546           default:
7547             if (INTVAL (operands[2]) < 8)
7548               break;
7549 
7550             *len = 1;
7551             return "clr %0";
7552 
7553           case 1:
7554             *len = 1;
7555             return "lsr %0";
7556 
7557           case 2:
7558             *len = 2;
7559             return ("lsr %0" CR_TAB
7560                       "lsr %0");
7561           case 3:
7562             *len = 3;
7563             return ("lsr %0" CR_TAB
7564                       "lsr %0" CR_TAB
7565                       "lsr %0");
7566 
7567           case 4:
7568             if (test_hard_reg_class (LD_REGS, operands[0]))
7569               {
7570                 *len=2;
7571                 return ("swap %0" CR_TAB
7572                           "andi %0,0x0f");
7573               }
7574             *len = 4;
7575             return ("lsr %0" CR_TAB
7576                       "lsr %0" CR_TAB
7577                       "lsr %0" CR_TAB
7578                       "lsr %0");
7579 
7580           case 5:
7581             if (test_hard_reg_class (LD_REGS, operands[0]))
7582               {
7583                 *len = 3;
7584                 return ("swap %0" CR_TAB
7585                           "lsr %0"  CR_TAB
7586                           "andi %0,0x7");
7587               }
7588             *len = 5;
7589             return ("lsr %0" CR_TAB
7590                       "lsr %0" CR_TAB
7591                       "lsr %0" CR_TAB
7592                       "lsr %0" CR_TAB
7593                       "lsr %0");
7594 
7595           case 6:
7596             if (test_hard_reg_class (LD_REGS, operands[0]))
7597               {
7598                 *len = 4;
7599                 return ("swap %0" CR_TAB
7600                           "lsr %0"  CR_TAB
7601                           "lsr %0"  CR_TAB
7602                           "andi %0,0x3");
7603               }
7604             *len = 6;
7605             return ("lsr %0" CR_TAB
7606                       "lsr %0" CR_TAB
7607                       "lsr %0" CR_TAB
7608                       "lsr %0" CR_TAB
7609                       "lsr %0" CR_TAB
7610                       "lsr %0");
7611 
7612           case 7:
7613             *len = 3;
7614             return ("rol %0" CR_TAB
7615                       "clr %0" CR_TAB
7616                       "rol %0");
7617           }
7618     }
7619   else if (CONSTANT_P (operands[2]))
7620     fatal_insn ("internal compiler error.  Incorrect shift:", insn);
7621 
7622   out_shift_with_cnt ("lsr %0",
7623                       insn, operands, len, 1);
7624   return "";
7625 }
7626 
7627 /* 16-bit logic shift right ((unsigned short)x >> i) */
7628 
7629 const char *
lshrhi3_out(rtx_insn * insn,rtx operands[],int * len)7630 lshrhi3_out (rtx_insn *insn, rtx operands[], int *len)
7631 {
7632   if (CONST_INT_P (operands[2]))
7633     {
7634       int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL
7635                      && XVECLEN (PATTERN (insn), 0) == 3
7636                      && REG_P (operands[3]));
7637       int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
7638       int k;
7639       int *t = len;
7640 
7641       if (!len)
7642           len = &k;
7643 
7644       switch (INTVAL (operands[2]))
7645           {
7646           default:
7647             if (INTVAL (operands[2]) < 16)
7648               break;
7649 
7650             *len = 2;
7651             return ("clr %B0" CR_TAB
7652                       "clr %A0");
7653 
7654           case 4:
7655             if (optimize_size && scratch)
7656               break;  /* 5 */
7657             if (ldi_ok)
7658               {
7659                 *len = 6;
7660                 return ("swap %B0"      CR_TAB
7661                           "swap %A0"      CR_TAB
7662                           "andi %A0,0x0f" CR_TAB
7663                           "eor %A0,%B0"   CR_TAB
7664                           "andi %B0,0x0f" CR_TAB
7665                           "eor %A0,%B0");
7666               }
7667             if (scratch)
7668               {
7669                 *len = 7;
7670                 return ("swap %B0"    CR_TAB
7671                           "swap %A0"    CR_TAB
7672                           "ldi %3,0x0f" CR_TAB
7673                           "and %A0,%3"  CR_TAB
7674                           "eor %A0,%B0" CR_TAB
7675                           "and %B0,%3"  CR_TAB
7676                           "eor %A0,%B0");
7677               }
7678             break;  /* optimize_size ? 6 : 8 */
7679 
7680           case 5:
7681             if (optimize_size)
7682               break;  /* scratch ? 5 : 6 */
7683             if (ldi_ok)
7684               {
7685                 *len = 8;
7686                 return ("lsr %B0"       CR_TAB
7687                           "ror %A0"       CR_TAB
7688                           "swap %B0"      CR_TAB
7689                           "swap %A0"      CR_TAB
7690                           "andi %A0,0x0f" CR_TAB
7691                           "eor %A0,%B0"   CR_TAB
7692                           "andi %B0,0x0f" CR_TAB
7693                           "eor %A0,%B0");
7694               }
7695             if (scratch)
7696               {
7697                 *len = 9;
7698                 return ("lsr %B0"     CR_TAB
7699                           "ror %A0"     CR_TAB
7700                           "swap %B0"    CR_TAB
7701                           "swap %A0"    CR_TAB
7702                           "ldi %3,0x0f" CR_TAB
7703                           "and %A0,%3"  CR_TAB
7704                           "eor %A0,%B0" CR_TAB
7705                           "and %B0,%3"  CR_TAB
7706                           "eor %A0,%B0");
7707               }
7708             break;  /* 10 */
7709 
7710           case 6:
7711             if (optimize_size)
7712               break;  /* scratch ? 5 : 6 */
7713             *len = 9;
7714             return ("clr __tmp_reg__" CR_TAB
7715                       "lsl %A0"         CR_TAB
7716                       "rol %B0"         CR_TAB
7717                       "rol __tmp_reg__" CR_TAB
7718                       "lsl %A0"         CR_TAB
7719                       "rol %B0"         CR_TAB
7720                       "rol __tmp_reg__" CR_TAB
7721                       "mov %A0,%B0"     CR_TAB
7722                       "mov %B0,__tmp_reg__");
7723 
7724           case 7:
7725             *len = 5;
7726             return ("lsl %A0"     CR_TAB
7727                       "mov %A0,%B0" CR_TAB
7728                       "rol %A0"     CR_TAB
7729                       "sbc %B0,%B0" CR_TAB
7730                       "neg %B0");
7731 
7732           case 8:
7733             return *len = 2, ("mov %A0,%B1" CR_TAB
7734                                   "clr %B0");
7735 
7736           case 9:
7737             *len = 3;
7738             return ("mov %A0,%B0" CR_TAB
7739                       "clr %B0"     CR_TAB
7740                       "lsr %A0");
7741 
7742           case 10:
7743             *len = 4;
7744             return ("mov %A0,%B0" CR_TAB
7745                       "clr %B0"     CR_TAB
7746                       "lsr %A0"     CR_TAB
7747                       "lsr %A0");
7748 
7749           case 11:
7750             *len = 5;
7751             return ("mov %A0,%B0" CR_TAB
7752                       "clr %B0"     CR_TAB
7753                       "lsr %A0"     CR_TAB
7754                       "lsr %A0"     CR_TAB
7755                       "lsr %A0");
7756 
7757           case 12:
7758             if (ldi_ok)
7759               {
7760                 *len = 4;
7761                 return ("mov %A0,%B0" CR_TAB
7762                           "clr %B0"     CR_TAB
7763                           "swap %A0"    CR_TAB
7764                           "andi %A0,0x0f");
7765               }
7766             if (scratch)
7767               {
7768                 *len = 5;
7769                 return ("mov %A0,%B0" CR_TAB
7770                           "clr %B0"     CR_TAB
7771                           "swap %A0"    CR_TAB
7772                           "ldi %3,0x0f" CR_TAB
7773                           "and %A0,%3");
7774               }
7775             *len = 6;
7776             return ("mov %A0,%B0" CR_TAB
7777                       "clr %B0"     CR_TAB
7778                       "lsr %A0"     CR_TAB
7779                       "lsr %A0"     CR_TAB
7780                       "lsr %A0"     CR_TAB
7781                       "lsr %A0");
7782 
7783           case 13:
7784             if (ldi_ok)
7785               {
7786                 *len = 5;
7787                 return ("mov %A0,%B0" CR_TAB
7788                           "clr %B0"     CR_TAB
7789                           "swap %A0"    CR_TAB
7790                           "lsr %A0"     CR_TAB
7791                           "andi %A0,0x07");
7792               }
7793             if (AVR_HAVE_MUL && scratch)
7794               {
7795                 *len = 5;
7796                 return ("ldi %3,0x08" CR_TAB
7797                           "mul %B0,%3"  CR_TAB
7798                           "mov %A0,r1"  CR_TAB
7799                           "clr %B0"     CR_TAB
7800                           "clr __zero_reg__");
7801               }
7802             if (optimize_size && scratch)
7803               break;  /* 5 */
7804             if (scratch)
7805               {
7806                 *len = 6;
7807                 return ("mov %A0,%B0" CR_TAB
7808                           "clr %B0"     CR_TAB
7809                           "swap %A0"    CR_TAB
7810                           "lsr %A0"     CR_TAB
7811                           "ldi %3,0x07" CR_TAB
7812                           "and %A0,%3");
7813               }
7814             if (AVR_HAVE_MUL)
7815               {
7816                 *len = 6;
7817                 return ("set"        CR_TAB
7818                           "bld r1,3"   CR_TAB
7819                           "mul %B0,r1" CR_TAB
7820                           "mov %A0,r1" CR_TAB
7821                           "clr %B0"    CR_TAB
7822                           "clr __zero_reg__");
7823               }
7824             *len = 7;
7825             return ("mov %A0,%B0" CR_TAB
7826                       "clr %B0"     CR_TAB
7827                       "lsr %A0"     CR_TAB
7828                       "lsr %A0"     CR_TAB
7829                       "lsr %A0"     CR_TAB
7830                       "lsr %A0"     CR_TAB
7831                       "lsr %A0");
7832 
7833           case 14:
7834             if (AVR_HAVE_MUL && ldi_ok)
7835               {
7836                 *len = 5;
7837                 return ("ldi %A0,0x04" CR_TAB
7838                           "mul %B0,%A0"  CR_TAB
7839                           "mov %A0,r1"   CR_TAB
7840                           "clr %B0"      CR_TAB
7841                           "clr __zero_reg__");
7842               }
7843             if (AVR_HAVE_MUL && scratch)
7844               {
7845                 *len = 5;
7846                 return ("ldi %3,0x04" CR_TAB
7847                           "mul %B0,%3"  CR_TAB
7848                           "mov %A0,r1"  CR_TAB
7849                           "clr %B0"     CR_TAB
7850                           "clr __zero_reg__");
7851               }
7852             if (optimize_size && ldi_ok)
7853               {
7854                 *len = 5;
7855                 return ("mov %A0,%B0" CR_TAB
7856                           "ldi %B0,6" "\n1:\t"
7857                           "lsr %A0"     CR_TAB
7858                           "dec %B0"     CR_TAB
7859                           "brne 1b");
7860               }
7861             if (optimize_size && scratch)
7862               break;  /* 5 */
7863             *len = 6;
7864             return ("clr %A0" CR_TAB
7865                       "lsl %B0" CR_TAB
7866                       "rol %A0" CR_TAB
7867                       "lsl %B0" CR_TAB
7868                       "rol %A0" CR_TAB
7869                       "clr %B0");
7870 
7871           case 15:
7872             *len = 4;
7873             return ("clr %A0" CR_TAB
7874                       "lsl %B0" CR_TAB
7875                       "rol %A0" CR_TAB
7876                       "clr %B0");
7877           }
7878       len = t;
7879     }
7880   out_shift_with_cnt ("lsr %B0" CR_TAB
7881                       "ror %A0", insn, operands, len, 2);
7882   return "";
7883 }
7884 
7885 
7886 /* 24-bit logic shift right */
7887 
7888 const char*
avr_out_lshrpsi3(rtx_insn * insn,rtx * op,int * plen)7889 avr_out_lshrpsi3 (rtx_insn *insn, rtx *op, int *plen)
7890 {
7891   int dest = REGNO (op[0]);
7892   int src = REGNO (op[1]);
7893 
7894   if (CONST_INT_P (op[2]))
7895     {
7896       if (plen)
7897         *plen = 0;
7898 
7899       switch (INTVAL (op[2]))
7900         {
7901         case 8:
7902           if (dest <= src)
7903             return avr_asm_len ("mov %A0,%B1" CR_TAB
7904                                 "mov %B0,%C1" CR_TAB
7905                                 "clr %C0", op, plen, 3);
7906           else
7907             return avr_asm_len ("clr %C0"     CR_TAB
7908                                 "mov %B0,%C1" CR_TAB
7909                                 "mov %A0,%B1", op, plen, 3);
7910 
7911         case 16:
7912           if (dest != src + 2)
7913             avr_asm_len ("mov %A0,%C1", op, plen, 1);
7914 
7915           return avr_asm_len ("clr %B0"  CR_TAB
7916                               "clr %C0", op, plen, 2);
7917 
7918         default:
7919           if (INTVAL (op[2]) < 24)
7920             break;
7921 
7922           /* fall through */
7923 
7924         case 23:
7925           return avr_asm_len ("clr %A0"    CR_TAB
7926                               "sbrc %C0,7" CR_TAB
7927                               "inc %A0"    CR_TAB
7928                               "clr %B0"    CR_TAB
7929                               "clr %C0", op, plen, 5);
7930         } /* switch */
7931     }
7932 
7933   out_shift_with_cnt ("lsr %C0" CR_TAB
7934                       "ror %B0" CR_TAB
7935                       "ror %A0", insn, op, plen, 3);
7936   return "";
7937 }
7938 
7939 
7940 /* 32-bit logic shift right ((unsigned int)x >> i) */
7941 
7942 const char *
lshrsi3_out(rtx_insn * insn,rtx operands[],int * len)7943 lshrsi3_out (rtx_insn *insn, rtx operands[], int *len)
7944 {
7945   if (CONST_INT_P (operands[2]))
7946     {
7947       int k;
7948       int *t = len;
7949 
7950       if (!len)
7951           len = &k;
7952 
7953       switch (INTVAL (operands[2]))
7954           {
7955           default:
7956             if (INTVAL (operands[2]) < 32)
7957               break;
7958 
7959             if (AVR_HAVE_MOVW)
7960               return *len = 3, ("clr %D0" CR_TAB
7961                                     "clr %C0" CR_TAB
7962                                     "movw %A0,%C0");
7963             *len = 4;
7964             return ("clr %D0" CR_TAB
7965                       "clr %C0" CR_TAB
7966                       "clr %B0" CR_TAB
7967                       "clr %A0");
7968 
7969           case 8:
7970             {
7971               int reg0 = true_regnum (operands[0]);
7972               int reg1 = true_regnum (operands[1]);
7973               *len = 4;
7974               if (reg0 <= reg1)
7975                 return ("mov %A0,%B1" CR_TAB
7976                           "mov %B0,%C1" CR_TAB
7977                           "mov %C0,%D1" CR_TAB
7978                           "clr %D0");
7979               else
7980                 return ("clr %D0"     CR_TAB
7981                           "mov %C0,%D1" CR_TAB
7982                           "mov %B0,%C1" CR_TAB
7983                           "mov %A0,%B1");
7984             }
7985 
7986           case 16:
7987             {
7988               int reg0 = true_regnum (operands[0]);
7989               int reg1 = true_regnum (operands[1]);
7990 
7991               if (reg0 == reg1 + 2)
7992                 return *len = 2, ("clr %C0"     CR_TAB
7993                                         "clr %D0");
7994               if (AVR_HAVE_MOVW)
7995                 return *len = 3, ("movw %A0,%C1" CR_TAB
7996                                         "clr %C0"      CR_TAB
7997                                         "clr %D0");
7998               else
7999                 return *len = 4, ("mov %B0,%D1" CR_TAB
8000                                         "mov %A0,%C1" CR_TAB
8001                                         "clr %C0"     CR_TAB
8002                                         "clr %D0");
8003             }
8004 
8005           case 24:
8006             return *len = 4, ("mov %A0,%D1" CR_TAB
8007                                   "clr %B0"     CR_TAB
8008                                   "clr %C0"     CR_TAB
8009                                   "clr %D0");
8010 
8011           case 31:
8012             *len = 6;
8013             return ("clr %A0"    CR_TAB
8014                       "sbrc %D0,7" CR_TAB
8015                       "inc %A0"    CR_TAB
8016                       "clr %B0"    CR_TAB
8017                       "clr %C0"    CR_TAB
8018                       "clr %D0");
8019           }
8020       len = t;
8021     }
8022   out_shift_with_cnt ("lsr %D0" CR_TAB
8023                       "ror %C0" CR_TAB
8024                       "ror %B0" CR_TAB
8025                       "ror %A0", insn, operands, len, 4);
8026   return "";
8027 }
8028 
8029 
8030 /* Output addition of register XOP[0] and compile time constant XOP[2].
8031    CODE == PLUS:  perform addition by using ADD instructions or
8032    CODE == MINUS: perform addition by using SUB instructions:
8033 
8034       XOP[0] = XOP[0] + XOP[2]
8035 
8036    Or perform addition/subtraction with register XOP[2] depending on CODE:
8037 
8038       XOP[0] = XOP[0] +/- XOP[2]
8039 
8040    If PLEN == NULL, print assembler instructions to perform the operation;
8041    otherwise, set *PLEN to the length of the instruction sequence (in words)
8042    printed with PLEN == NULL.  XOP[3] is an 8-bit scratch register or NULL_RTX.
8043    Set *PCC to effect on cc0 according to respective CC_* insn attribute.
8044 
8045    CODE_SAT == UNKNOWN: Perform ordinary, non-saturating operation.
8046    CODE_SAT != UNKNOWN: Perform operation and saturate according to CODE_SAT.
8047    If  CODE_SAT != UNKNOWN  then SIGN contains the sign of the summand resp.
8048    the subtrahend in the original insn, provided it is a compile time constant.
8049    In all other cases, SIGN is 0.
8050 
8051    If OUT_LABEL is true, print the final 0: label which is needed for
8052    saturated addition / subtraction.  The only case where OUT_LABEL = false
8053    is useful is for saturated addition / subtraction performed during
8054    fixed-point rounding, cf. `avr_out_round'.  */
8055 
8056 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)8057 avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc,
8058                 enum rtx_code code_sat, int sign, bool out_label)
8059 {
8060   /* MODE of the operation.  */
8061   machine_mode mode = GET_MODE (xop[0]);
8062 
8063   /* INT_MODE of the same size.  */
8064   scalar_int_mode imode = int_mode_for_mode (mode).require ();
8065 
8066   /* Number of bytes to operate on.  */
8067   int n_bytes = GET_MODE_SIZE (mode);
8068 
8069   /* Value (0..0xff) held in clobber register op[3] or -1 if unknown.  */
8070   int clobber_val = -1;
8071 
8072   /* op[0]: 8-bit destination register
8073      op[1]: 8-bit const int
8074      op[2]: 8-bit scratch register */
8075   rtx op[3];
8076 
8077   /* Started the operation?  Before starting the operation we may skip
8078      adding 0.  This is no more true after the operation started because
8079      carry must be taken into account.  */
8080   bool started = false;
8081 
8082   /* Value to add.  There are two ways to add VAL: R += VAL and R -= -VAL.  */
8083   rtx xval = xop[2];
8084 
8085   /* Output a BRVC instruction.  Only needed with saturation.  */
8086   bool out_brvc = true;
8087 
8088   if (plen)
8089     *plen = 0;
8090 
8091   if (REG_P (xop[2]))
8092     {
8093       *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_CLOBBER;
8094 
8095       for (int i = 0; i < n_bytes; i++)
8096         {
8097           /* We operate byte-wise on the destination.  */
8098           op[0] = simplify_gen_subreg (QImode, xop[0], mode, i);
8099           op[1] = simplify_gen_subreg (QImode, xop[2], mode, i);
8100 
8101           if (i == 0)
8102             avr_asm_len (code == PLUS ? "add %0,%1" : "sub %0,%1",
8103                          op, plen, 1);
8104           else
8105             avr_asm_len (code == PLUS ? "adc %0,%1" : "sbc %0,%1",
8106                          op, plen, 1);
8107         }
8108 
8109       if (reg_overlap_mentioned_p (xop[0], xop[2]))
8110         {
8111           gcc_assert (REGNO (xop[0]) == REGNO (xop[2]));
8112 
8113           if (MINUS == code)
8114             return;
8115         }
8116 
8117       goto saturate;
8118     }
8119 
8120   /* Except in the case of ADIW with 16-bit register (see below)
8121      addition does not set cc0 in a usable way.  */
8122 
8123   *pcc = (MINUS == code) ? CC_SET_CZN : CC_CLOBBER;
8124 
8125   if (CONST_FIXED_P (xval))
8126     xval = avr_to_int_mode (xval);
8127 
8128   /* Adding/Subtracting zero is a no-op.  */
8129 
8130   if (xval == const0_rtx)
8131     {
8132       *pcc = CC_NONE;
8133       return;
8134     }
8135 
8136   if (MINUS == code)
8137     xval = simplify_unary_operation (NEG, imode, xval, imode);
8138 
8139   op[2] = xop[3];
8140 
8141   if (SS_PLUS == code_sat && MINUS == code
8142       && sign < 0
8143       && 0x80 == (INTVAL (simplify_gen_subreg (QImode, xval, imode, n_bytes-1))
8144                   & GET_MODE_MASK (QImode)))
8145     {
8146       /* We compute x + 0x80 by means of SUB instructions.  We negated the
8147          constant subtrahend above and are left with  x - (-128)  so that we
8148          need something like SUBI r,128 which does not exist because SUBI sets
8149          V according to the sign of the subtrahend.  Notice the only case
8150          where this must be done is when NEG overflowed in case [2s] because
8151          the V computation needs the right sign of the subtrahend.  */
8152 
8153       rtx msb = simplify_gen_subreg (QImode, xop[0], mode, n_bytes - 1);
8154 
8155       avr_asm_len ("subi %0,128" CR_TAB
8156                    "brmi 0f", &msb, plen, 2);
8157       out_brvc = false;
8158 
8159       goto saturate;
8160     }
8161 
8162   for (int i = 0; i < n_bytes; i++)
8163     {
8164       /* We operate byte-wise on the destination.  */
8165       rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
8166       rtx xval8 = simplify_gen_subreg (QImode, xval, imode, i);
8167 
8168       /* 8-bit value to operate with this byte. */
8169       unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
8170 
8171       /* Registers R16..R31 can operate with immediate.  */
8172       bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
8173 
8174       op[0] = reg8;
8175       op[1] = gen_int_mode (val8, QImode);
8176 
8177       /* To get usable cc0 no low-bytes must have been skipped.  */
8178 
8179       if (i && !started)
8180         *pcc = CC_CLOBBER;
8181 
8182       if (!started
8183           && i % 2 == 0
8184           && i + 2 <= n_bytes
8185           && test_hard_reg_class (ADDW_REGS, reg8))
8186         {
8187           rtx xval16 = simplify_gen_subreg (HImode, xval, imode, i);
8188           unsigned int val16 = UINTVAL (xval16) & GET_MODE_MASK (HImode);
8189 
8190           /* Registers R24, X, Y, Z can use ADIW/SBIW with constants < 64
8191              i.e. operate word-wise.  */
8192 
8193           if (val16 < 64)
8194             {
8195               if (val16 != 0)
8196                 {
8197                   started = true;
8198                   avr_asm_len (code == PLUS ? "adiw %0,%1" : "sbiw %0,%1",
8199                                op, plen, 1);
8200 
8201                   if (n_bytes == 2 && PLUS == code)
8202                     *pcc = CC_SET_CZN;
8203                 }
8204 
8205               i++;
8206               continue;
8207             }
8208         }
8209 
8210       if (val8 == 0)
8211         {
8212           if (started)
8213             avr_asm_len (code == PLUS
8214                          ? "adc %0,__zero_reg__" : "sbc %0,__zero_reg__",
8215                          op, plen, 1);
8216           continue;
8217         }
8218       else if ((val8 == 1 || val8 == 0xff)
8219                && UNKNOWN == code_sat
8220                && !started
8221                && i == n_bytes - 1)
8222         {
8223           avr_asm_len ((code == PLUS) ^ (val8 == 1) ? "dec %0" : "inc %0",
8224                        op, plen, 1);
8225           *pcc = CC_CLOBBER;
8226           break;
8227         }
8228 
8229       switch (code)
8230         {
8231         case PLUS:
8232 
8233           gcc_assert (plen != NULL || (op[2] && REG_P (op[2])));
8234 
8235           if (plen != NULL && UNKNOWN != code_sat)
8236             {
8237               /* This belongs to the x + 0x80 corner case.  The code with
8238                  ADD instruction is not smaller, thus make this case
8239                  expensive so that the caller won't pick it.  */
8240 
8241               *plen += 10;
8242               break;
8243             }
8244 
8245           if (clobber_val != (int) val8)
8246             avr_asm_len ("ldi %2,%1", op, plen, 1);
8247           clobber_val = (int) val8;
8248 
8249           avr_asm_len (started ? "adc %0,%2" : "add %0,%2", op, plen, 1);
8250 
8251           break; /* PLUS */
8252 
8253         case MINUS:
8254 
8255           if (ld_reg_p)
8256             avr_asm_len (started ? "sbci %0,%1" : "subi %0,%1", op, plen, 1);
8257           else
8258             {
8259               gcc_assert (plen != NULL || REG_P (op[2]));
8260 
8261               if (clobber_val != (int) val8)
8262                 avr_asm_len ("ldi %2,%1", op, plen, 1);
8263               clobber_val = (int) val8;
8264 
8265               avr_asm_len (started ? "sbc %0,%2" : "sub %0,%2", op, plen, 1);
8266             }
8267 
8268           break; /* MINUS */
8269 
8270         default:
8271           /* Unknown code */
8272           gcc_unreachable();
8273         }
8274 
8275       started = true;
8276 
8277     } /* for all sub-bytes */
8278 
8279  saturate:
8280 
8281   if (UNKNOWN == code_sat)
8282     return;
8283 
8284   *pcc = (int) CC_CLOBBER;
8285 
8286   /* Vanilla addition/subtraction is done.  We are left with saturation.
8287 
8288      We have to compute  A = A <op> B  where  A  is a register and
8289      B is a register or a non-zero compile time constant CONST.
8290      A is register class "r" if unsigned && B is REG.  Otherwise, A is in "d".
8291      B stands for the original operand $2 in INSN.  In the case of B = CONST,
8292      SIGN in { -1, 1 } is the sign of B.  Otherwise, SIGN is 0.
8293 
8294      CODE is the instruction flavor we use in the asm sequence to perform <op>.
8295 
8296 
8297      unsigned
8298      operation        |  code |  sat if  |    b is      | sat value |  case
8299      -----------------+-------+----------+--------------+-----------+-------
8300      +  as  a + b     |  add  |  C == 1  |  const, reg  | u+ = 0xff |  [1u]
8301      +  as  a - (-b)  |  sub  |  C == 0  |  const       | u+ = 0xff |  [2u]
8302      -  as  a - b     |  sub  |  C == 1  |  const, reg  | u- = 0    |  [3u]
8303      -  as  a + (-b)  |  add  |  C == 0  |  const       | u- = 0    |  [4u]
8304 
8305 
8306      signed
8307      operation        |  code |  sat if  |    b is      | sat value |  case
8308      -----------------+-------+----------+--------------+-----------+-------
8309      +  as  a + b     |  add  |  V == 1  |  const, reg  | s+        |  [1s]
8310      +  as  a - (-b)  |  sub  |  V == 1  |  const       | s+        |  [2s]
8311      -  as  a - b     |  sub  |  V == 1  |  const, reg  | s-        |  [3s]
8312      -  as  a + (-b)  |  add  |  V == 1  |  const       | s-        |  [4s]
8313 
8314      s+  =  b < 0  ?  -0x80 :  0x7f
8315      s-  =  b < 0  ?   0x7f : -0x80
8316 
8317      The cases a - b actually perform  a - (-(-b))  if B is CONST.
8318   */
8319 
8320   op[0] = simplify_gen_subreg (QImode, xop[0], mode, n_bytes-1);
8321   op[1] = n_bytes > 1
8322     ? simplify_gen_subreg (QImode, xop[0], mode, n_bytes-2)
8323     : NULL_RTX;
8324 
8325   bool need_copy = true;
8326   int len_call = 1 + AVR_HAVE_JMP_CALL;
8327 
8328   switch (code_sat)
8329     {
8330     default:
8331       gcc_unreachable();
8332 
8333     case SS_PLUS:
8334     case SS_MINUS:
8335 
8336       if (out_brvc)
8337         avr_asm_len ("brvc 0f", op, plen, 1);
8338 
8339       if (reg_overlap_mentioned_p (xop[0], xop[2]))
8340         {
8341           /* [1s,reg] */
8342 
8343           if (n_bytes == 1)
8344             avr_asm_len ("ldi %0,0x7f" CR_TAB
8345                          "adc %0,__zero_reg__", op, plen, 2);
8346           else
8347             avr_asm_len ("ldi %0,0x7f" CR_TAB
8348                          "ldi %1,0xff" CR_TAB
8349                          "adc %1,__zero_reg__" CR_TAB
8350                          "adc %0,__zero_reg__", op, plen, 4);
8351         }
8352       else if (sign == 0 && PLUS == code)
8353         {
8354           /* [1s,reg] */
8355 
8356           op[2] = simplify_gen_subreg (QImode, xop[2], mode, n_bytes-1);
8357 
8358           if (n_bytes == 1)
8359             avr_asm_len ("ldi %0,0x80" CR_TAB
8360                          "sbrs %2,7"   CR_TAB
8361                          "dec %0", op, plen, 3);
8362           else
8363             avr_asm_len ("ldi %0,0x80" CR_TAB
8364                          "cp %2,%0"    CR_TAB
8365                          "sbc %1,%1"   CR_TAB
8366                          "sbci %0,0", op, plen, 4);
8367         }
8368       else if (sign == 0 && MINUS == code)
8369         {
8370           /* [3s,reg] */
8371 
8372           op[2] = simplify_gen_subreg (QImode, xop[2], mode, n_bytes-1);
8373 
8374           if (n_bytes == 1)
8375             avr_asm_len ("ldi %0,0x7f" CR_TAB
8376                          "sbrs %2,7"   CR_TAB
8377                          "inc %0", op, plen, 3);
8378           else
8379             avr_asm_len ("ldi %0,0x7f" CR_TAB
8380                          "cp %0,%2"    CR_TAB
8381                          "sbc %1,%1"   CR_TAB
8382                          "sbci %0,-1", op, plen, 4);
8383         }
8384       else if ((sign < 0) ^ (SS_MINUS == code_sat))
8385         {
8386           /* [1s,const,B < 0] [2s,B < 0] */
8387           /* [3s,const,B > 0] [4s,B > 0] */
8388 
8389           if (n_bytes == 8)
8390             {
8391               avr_asm_len ("%~call __clr_8", op, plen, len_call);
8392               need_copy = false;
8393             }
8394 
8395           avr_asm_len ("ldi %0,0x80", op, plen, 1);
8396           if (n_bytes > 1 && need_copy)
8397             avr_asm_len ("clr %1", op, plen, 1);
8398         }
8399       else if ((sign > 0) ^ (SS_MINUS == code_sat))
8400         {
8401           /* [1s,const,B > 0] [2s,B > 0] */
8402           /* [3s,const,B < 0] [4s,B < 0] */
8403 
8404           if (n_bytes == 8)
8405             {
8406               avr_asm_len ("sec" CR_TAB
8407                            "%~call __sbc_8", op, plen, 1 + len_call);
8408               need_copy = false;
8409             }
8410 
8411           avr_asm_len ("ldi %0,0x7f", op, plen, 1);
8412           if (n_bytes > 1 && need_copy)
8413             avr_asm_len ("ldi %1,0xff", op, plen, 1);
8414         }
8415       else
8416         gcc_unreachable();
8417 
8418       break;
8419 
8420     case US_PLUS:
8421       /* [1u] : [2u] */
8422 
8423       avr_asm_len (PLUS == code ? "brcc 0f" : "brcs 0f", op, plen, 1);
8424 
8425       if (n_bytes == 8)
8426         {
8427           if (MINUS == code)
8428             avr_asm_len ("sec", op, plen, 1);
8429           avr_asm_len ("%~call __sbc_8", op, plen, len_call);
8430 
8431           need_copy = false;
8432         }
8433       else
8434         {
8435           if (MINUS == code && !test_hard_reg_class (LD_REGS, op[0]))
8436             avr_asm_len ("sec" CR_TAB
8437                          "sbc %0,%0", op, plen, 2);
8438           else
8439             avr_asm_len (PLUS == code ? "sbc %0,%0" : "ldi %0,0xff",
8440                          op, plen, 1);
8441         }
8442       break; /* US_PLUS */
8443 
8444     case US_MINUS:
8445       /* [4u] : [3u] */
8446 
8447       avr_asm_len (PLUS == code ? "brcs 0f" : "brcc 0f", op, plen, 1);
8448 
8449       if (n_bytes == 8)
8450         {
8451           avr_asm_len ("%~call __clr_8", op, plen, len_call);
8452           need_copy = false;
8453         }
8454       else
8455         avr_asm_len ("clr %0", op, plen, 1);
8456 
8457       break;
8458     }
8459 
8460   /* We set the MSB in the unsigned case and the 2 MSBs in the signed case.
8461      Now copy the right value to the LSBs.  */
8462 
8463   if (need_copy && n_bytes > 1)
8464     {
8465       if (US_MINUS == code_sat || US_PLUS == code_sat)
8466         {
8467           avr_asm_len ("mov %1,%0", op, plen, 1);
8468 
8469           if (n_bytes > 2)
8470             {
8471               op[0] = xop[0];
8472               if (AVR_HAVE_MOVW)
8473                 avr_asm_len ("movw %0,%1", op, plen, 1);
8474               else
8475                 avr_asm_len ("mov %A0,%1" CR_TAB
8476                              "mov %B0,%1", op, plen, 2);
8477             }
8478         }
8479       else if (n_bytes > 2)
8480         {
8481           op[0] = xop[0];
8482           avr_asm_len ("mov %A0,%1" CR_TAB
8483                        "mov %B0,%1", op, plen, 2);
8484         }
8485     }
8486 
8487   if (need_copy && n_bytes == 8)
8488     {
8489       if (AVR_HAVE_MOVW)
8490         avr_asm_len ("movw %r0+2,%0" CR_TAB
8491                      "movw %r0+4,%0", xop, plen, 2);
8492       else
8493         avr_asm_len ("mov %r0+2,%0" CR_TAB
8494                      "mov %r0+3,%0" CR_TAB
8495                      "mov %r0+4,%0" CR_TAB
8496                      "mov %r0+5,%0", xop, plen, 4);
8497     }
8498 
8499   if (out_label)
8500     avr_asm_len ("0:", op, plen, 0);
8501 }
8502 
8503 
8504 /* Output addition/subtraction of register XOP[0] and a constant XOP[2] that
8505    is ont a compile-time constant:
8506 
8507       XOP[0] = XOP[0] +/- XOP[2]
8508 
8509    This is a helper for the function below.  The only insns that need this
8510    are additions/subtraction for pointer modes, i.e. HImode and PSImode.  */
8511 
8512 static const char*
avr_out_plus_symbol(rtx * xop,enum rtx_code code,int * plen,int * pcc)8513 avr_out_plus_symbol (rtx *xop, enum rtx_code code, int *plen, int *pcc)
8514 {
8515   machine_mode mode = GET_MODE (xop[0]);
8516 
8517   /* Only pointer modes want to add symbols.  */
8518 
8519   gcc_assert (mode == HImode || mode == PSImode);
8520 
8521   *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_SET_N;
8522 
8523   avr_asm_len (PLUS == code
8524                ? "subi %A0,lo8(-(%2))" CR_TAB "sbci %B0,hi8(-(%2))"
8525                : "subi %A0,lo8(%2)"    CR_TAB "sbci %B0,hi8(%2)",
8526                xop, plen, -2);
8527 
8528   if (PSImode == mode)
8529     avr_asm_len (PLUS == code
8530                  ? "sbci %C0,hlo8(-(%2))"
8531                  : "sbci %C0,hlo8(%2)", xop, plen, 1);
8532   return "";
8533 }
8534 
8535 
8536 /* Prepare operands of addition/subtraction to be used with avr_out_plus_1.
8537 
8538    INSN is a single_set insn or an insn pattern with a binary operation as
8539    SET_SRC that is one of: PLUS, SS_PLUS, US_PLUS, MINUS, SS_MINUS, US_MINUS.
8540 
8541    XOP are the operands of INSN.  In the case of 64-bit operations with
8542    constant XOP[] has just one element:  The summand/subtrahend in XOP[0].
8543    The non-saturating insns up to 32 bits may or may not supply a "d" class
8544    scratch as XOP[3].
8545 
8546    If PLEN == NULL output the instructions.
8547    If PLEN != NULL set *PLEN to the length of the sequence in words.
8548 
8549    PCC is a pointer to store the instructions' effect on cc0.
8550    PCC may be NULL.
8551 
8552    PLEN and PCC default to NULL.
8553 
8554    OUT_LABEL defaults to TRUE.  For a description, see AVR_OUT_PLUS_1.
8555 
8556    Return ""  */
8557 
8558 const char*
avr_out_plus(rtx insn,rtx * xop,int * plen,int * pcc,bool out_label)8559 avr_out_plus (rtx insn, rtx *xop, int *plen, int *pcc, bool out_label)
8560 {
8561   int cc_plus, cc_minus, cc_dummy;
8562   int len_plus, len_minus;
8563   rtx op[4];
8564   rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
8565   rtx xdest = SET_DEST (xpattern);
8566   machine_mode mode = GET_MODE (xdest);
8567   scalar_int_mode imode = int_mode_for_mode (mode).require ();
8568   int n_bytes = GET_MODE_SIZE (mode);
8569   enum rtx_code code_sat = GET_CODE (SET_SRC (xpattern));
8570   enum rtx_code code
8571     = (PLUS == code_sat || SS_PLUS == code_sat || US_PLUS == code_sat
8572        ? PLUS : MINUS);
8573 
8574   if (!pcc)
8575     pcc = &cc_dummy;
8576 
8577   /* PLUS and MINUS don't saturate:  Use modular wrap-around.  */
8578 
8579   if (PLUS == code_sat || MINUS == code_sat)
8580     code_sat = UNKNOWN;
8581 
8582   if (n_bytes <= 4 && REG_P (xop[2]))
8583     {
8584       avr_out_plus_1 (xop, plen, code, pcc, code_sat, 0, out_label);
8585       return "";
8586     }
8587 
8588   if (n_bytes == 8)
8589     {
8590       op[0] = gen_rtx_REG (DImode, ACC_A);
8591       op[1] = gen_rtx_REG (DImode, ACC_A);
8592       op[2] = avr_to_int_mode (xop[0]);
8593     }
8594   else
8595     {
8596       if (!REG_P (xop[2])
8597           && !CONST_INT_P (xop[2])
8598           && !CONST_FIXED_P (xop[2]))
8599         {
8600           return avr_out_plus_symbol (xop, code, plen, pcc);
8601         }
8602 
8603       op[0] = avr_to_int_mode (xop[0]);
8604       op[1] = avr_to_int_mode (xop[1]);
8605       op[2] = avr_to_int_mode (xop[2]);
8606     }
8607 
8608   /* Saturations and 64-bit operations don't have a clobber operand.
8609      For the other cases, the caller will provide a proper XOP[3].  */
8610 
8611   xpattern = INSN_P (insn) ? PATTERN (insn) : insn;
8612   op[3] = PARALLEL == GET_CODE (xpattern) ? xop[3] : NULL_RTX;
8613 
8614   /* Saturation will need the sign of the original operand.  */
8615 
8616   rtx xmsb = simplify_gen_subreg (QImode, op[2], imode, n_bytes-1);
8617   int sign = INTVAL (xmsb) < 0 ? -1 : 1;
8618 
8619   /* If we subtract and the subtrahend is a constant, then negate it
8620      so that avr_out_plus_1 can be used.  */
8621 
8622   if (MINUS == code)
8623     op[2] = simplify_unary_operation (NEG, imode, op[2], imode);
8624 
8625   /* Work out the shortest sequence.  */
8626 
8627   avr_out_plus_1 (op, &len_minus, MINUS, &cc_minus, code_sat, sign, out_label);
8628   avr_out_plus_1 (op, &len_plus, PLUS, &cc_plus, code_sat, sign, out_label);
8629 
8630   if (plen)
8631     {
8632       *plen = (len_minus <= len_plus) ? len_minus : len_plus;
8633       *pcc  = (len_minus <= len_plus) ? cc_minus : cc_plus;
8634     }
8635   else if (len_minus <= len_plus)
8636     avr_out_plus_1 (op, NULL, MINUS, pcc, code_sat, sign, out_label);
8637   else
8638     avr_out_plus_1 (op, NULL, PLUS, pcc, code_sat, sign, out_label);
8639 
8640   return "";
8641 }
8642 
8643 
8644 /* Output an instruction sequence for addition of REG in XOP[0] and CONST_INT
8645    in XOP[1] in such a way that SREG.Z and SREG.N are set according to the
8646    result.  XOP[2] might be a d-regs clobber register.  If XOP[2] is SCRATCH,
8647    then the addition can be performed without a clobber reg.  Return "".
8648 
8649    If PLEN == NULL, then output the instructions.
8650    If PLEN != NULL, then set *PLEN to the length of the sequence in words. */
8651 
8652 const char*
avr_out_plus_set_ZN(rtx * xop,int * plen)8653 avr_out_plus_set_ZN (rtx *xop, int *plen)
8654 {
8655   if (plen)
8656     *plen = 0;
8657 
8658   // Register to compare and value to compare against.
8659   rtx xreg = xop[0];
8660   rtx xval = xop[1];
8661 
8662   machine_mode mode = GET_MODE (xreg);
8663 
8664   // Number of bytes to operate on.
8665   int n_bytes = GET_MODE_SIZE (mode);
8666 
8667   if (n_bytes == 1)
8668     {
8669       if (INTVAL (xval) == 1)
8670           return avr_asm_len ("inc %0", xop, plen, 1);
8671 
8672       if (INTVAL (xval) == -1)
8673           return avr_asm_len ("dec %0", xop, plen, 1);
8674     }
8675 
8676   if (n_bytes == 2
8677       && test_hard_reg_class (ADDW_REGS, xreg)
8678       && IN_RANGE (INTVAL (xval), 1, 63))
8679     {
8680       // Add 16-bit value in [1..63] to a w register.
8681       return avr_asm_len ("adiw %0, %1", xop, plen, 1);
8682     }
8683 
8684   // Addition won't work; subtract the negative of XVAL instead.
8685   xval = simplify_unary_operation (NEG, mode, xval, mode);
8686 
8687   // Value (0..0xff) held in clobber register xop[2] or -1 if unknown.
8688   int clobber_val = -1;
8689 
8690   // [0] = Current sub-register.
8691   // [1] = Current partial xval.
8692   // [2] = 8-bit clobber d-register or SCRATCH.
8693   rtx op[3];
8694   op[2] = xop[2];
8695 
8696   // Work byte-wise from LSB to MSB.  The lower two bytes might be
8697   // SBIW'ed in one go.
8698   for (int i = 0; i < n_bytes; ++i)
8699     {
8700       op[0] = simplify_gen_subreg (QImode, xreg, mode, i);
8701 
8702       if (i == 0
8703             && n_bytes >= 2
8704             && test_hard_reg_class (ADDW_REGS, op[0]))
8705           {
8706             op[1] = simplify_gen_subreg (HImode, xval, mode, 0);
8707             if (IN_RANGE (INTVAL (op[1]), 0, 63))
8708               {
8709                 // SBIW can handle the lower 16 bits.
8710                 avr_asm_len ("sbiw %0, %1", op, plen, 1);
8711 
8712                 // Next byte has already been handled: Skip it.
8713                 ++i;
8714                 continue;
8715               }
8716           }
8717 
8718       op[1] = simplify_gen_subreg (QImode, xval, mode, i);
8719 
8720       if (test_hard_reg_class (LD_REGS, op[0]))
8721           {
8722             // d-regs can subtract immediates.
8723             avr_asm_len (i == 0
8724                            ? "subi %0, %1"
8725                            : "sbci %0, %1", op, plen, 1);
8726           }
8727       else
8728           {
8729             int val8 = 0xff & INTVAL (op[1]);
8730             if (val8 == 0)
8731               {
8732                 // Any register can subtract 0.
8733                 avr_asm_len (i == 0
8734                                  ? "sub %0, __zero_reg__"
8735                                  : "sbc %0, __zero_reg__", op, plen, 1);
8736               }
8737             else
8738               {
8739                 // Use d-register to hold partial xval.
8740 
8741                 if (val8 != clobber_val)
8742                     {
8743                       // Load partial xval to QI clobber reg and memoize for later.
8744                       gcc_assert (REG_P (op[2]));
8745                       avr_asm_len ("ldi %2, %1", op, plen, 1);
8746                       clobber_val = val8;
8747                     }
8748 
8749                 avr_asm_len (i == 0
8750                                  ? "sub %0, %2"
8751                                  : "sbc %0, %2", op, plen, 1);
8752               }
8753           }
8754     } // Loop bytes.
8755 
8756   return "";
8757 }
8758 
8759 
8760 /* Output bit operation (IOR, AND, XOR) with register XOP[0] and compile
8761    time constant XOP[2]:
8762 
8763       XOP[0] = XOP[0] <op> XOP[2]
8764 
8765    and return "".  If PLEN == NULL, print assembler instructions to perform the
8766    operation; otherwise, set *PLEN to the length of the instruction sequence
8767    (in words) printed with PLEN == NULL.  XOP[3] is either an 8-bit clobber
8768    register or SCRATCH if no clobber register is needed for the operation.
8769    INSN is an INSN_P or a pattern of an insn.  */
8770 
8771 const char*
avr_out_bitop(rtx insn,rtx * xop,int * plen)8772 avr_out_bitop (rtx insn, rtx *xop, int *plen)
8773 {
8774   /* CODE and MODE of the operation.  */
8775   rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
8776   enum rtx_code code = GET_CODE (SET_SRC (xpattern));
8777   machine_mode mode = GET_MODE (xop[0]);
8778 
8779   /* Number of bytes to operate on.  */
8780   int n_bytes = GET_MODE_SIZE (mode);
8781 
8782   /* Value of T-flag (0 or 1) or -1 if unknow.  */
8783   int set_t = -1;
8784 
8785   /* Value (0..0xff) held in clobber register op[3] or -1 if unknown.  */
8786   int clobber_val = -1;
8787 
8788   /* op[0]: 8-bit destination register
8789      op[1]: 8-bit const int
8790      op[2]: 8-bit clobber register, SCRATCH or NULL_RTX.
8791      op[3]: 8-bit register containing 0xff or NULL_RTX  */
8792   rtx op[4];
8793 
8794   op[2] = QImode == mode ? NULL_RTX : xop[3];
8795   op[3] = NULL_RTX;
8796 
8797   if (plen)
8798     *plen = 0;
8799 
8800   for (int i = 0; i < n_bytes; i++)
8801     {
8802       /* We operate byte-wise on the destination.  */
8803       rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
8804       rtx xval8 = simplify_gen_subreg (QImode, xop[2], mode, i);
8805 
8806       /* 8-bit value to operate with this byte. */
8807       unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
8808 
8809       /* Number of bits set in the current byte of the constant.  */
8810       int pop8 = popcount_hwi (val8);
8811 
8812       /* Registers R16..R31 can operate with immediate.  */
8813       bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
8814 
8815       op[0] = reg8;
8816       op[1] = GEN_INT (val8);
8817 
8818       switch (code)
8819         {
8820         case IOR:
8821 
8822             if (pop8 == 0)
8823             continue;
8824           else if (ld_reg_p)
8825             avr_asm_len ("ori %0,%1", op, plen, 1);
8826             else if (pop8 == 1)
8827             {
8828               if (set_t != 1)
8829                 avr_asm_len ("set", op, plen, 1);
8830               set_t = 1;
8831 
8832               op[1] = GEN_INT (exact_log2 (val8));
8833               avr_asm_len ("bld %0,%1", op, plen, 1);
8834             }
8835             else if (pop8 == 8)
8836             {
8837               if (op[3] != NULL_RTX)
8838                 avr_asm_len ("mov %0,%3", op, plen, 1);
8839               else
8840                 avr_asm_len ("clr %0" CR_TAB
8841                              "dec %0", op, plen, 2);
8842 
8843               op[3] = op[0];
8844             }
8845           else
8846             {
8847               if (clobber_val != (int) val8)
8848                 avr_asm_len ("ldi %2,%1", op, plen, 1);
8849               clobber_val = (int) val8;
8850 
8851               avr_asm_len ("or %0,%2", op, plen, 1);
8852             }
8853 
8854           continue; /* IOR */
8855 
8856         case AND:
8857 
8858             if (pop8 == 8)
8859             continue;
8860             else if (pop8 == 0)
8861             avr_asm_len ("clr %0", op, plen, 1);
8862           else if (ld_reg_p)
8863             avr_asm_len ("andi %0,%1", op, plen, 1);
8864             else if (pop8 == 7)
8865             {
8866               if (set_t != 0)
8867                 avr_asm_len ("clt", op, plen, 1);
8868               set_t = 0;
8869 
8870               op[1] = GEN_INT (exact_log2 (GET_MODE_MASK (QImode) & ~val8));
8871               avr_asm_len ("bld %0,%1", op, plen, 1);
8872             }
8873           else
8874             {
8875               if (clobber_val != (int) val8)
8876                 avr_asm_len ("ldi %2,%1", op, plen, 1);
8877               clobber_val = (int) val8;
8878 
8879               avr_asm_len ("and %0,%2", op, plen, 1);
8880             }
8881 
8882           continue; /* AND */
8883 
8884         case XOR:
8885 
8886             if (pop8 == 0)
8887             continue;
8888             else if (pop8 == 8)
8889             avr_asm_len ("com %0", op, plen, 1);
8890           else if (ld_reg_p && val8 == (1 << 7))
8891             avr_asm_len ("subi %0,%1", op, plen, 1);
8892           else
8893             {
8894               if (clobber_val != (int) val8)
8895                 avr_asm_len ("ldi %2,%1", op, plen, 1);
8896               clobber_val = (int) val8;
8897 
8898               avr_asm_len ("eor %0,%2", op, plen, 1);
8899             }
8900 
8901           continue; /* XOR */
8902 
8903         default:
8904           /* Unknown rtx_code */
8905           gcc_unreachable();
8906         }
8907     } /* for all sub-bytes */
8908 
8909   return "";
8910 }
8911 
8912 
8913 /* Output sign extension from XOP[1] to XOP[0] and return "".
8914    If PLEN == NULL, print assembler instructions to perform the operation;
8915    otherwise, set *PLEN to the length of the instruction sequence (in words)
8916    as printed with PLEN == NULL.  */
8917 
8918 const char*
avr_out_sign_extend(rtx_insn * insn,rtx * xop,int * plen)8919 avr_out_sign_extend (rtx_insn *insn, rtx *xop, int *plen)
8920 {
8921   // Size in bytes of source resp. destination operand.
8922   unsigned n_src = GET_MODE_SIZE (GET_MODE (xop[1]));
8923   unsigned n_dest = GET_MODE_SIZE (GET_MODE (xop[0]));
8924   rtx r_msb = all_regs_rtx[REGNO (xop[1]) + n_src - 1];
8925 
8926   if (plen)
8927     *plen = 0;
8928 
8929   // Copy destination to source
8930 
8931   if (REGNO (xop[0]) != REGNO (xop[1]))
8932     {
8933       gcc_assert (n_src <= 2);
8934 
8935       if (n_src == 2)
8936         avr_asm_len (AVR_HAVE_MOVW
8937                      ? "movw %0,%1"
8938                      : "mov %B0,%B1", xop, plen, 1);
8939       if (n_src == 1 || !AVR_HAVE_MOVW)
8940         avr_asm_len ("mov %A0,%A1", xop, plen, 1);
8941     }
8942 
8943   // Set Carry to the sign bit MSB.7...
8944 
8945   if (REGNO (xop[0]) == REGNO (xop[1])
8946       || !reg_unused_after (insn, r_msb))
8947     {
8948       avr_asm_len ("mov __tmp_reg__,%0", &r_msb, plen, 1);
8949       r_msb = tmp_reg_rtx;
8950     }
8951 
8952   avr_asm_len ("lsl %0", &r_msb, plen, 1);
8953 
8954   // ...and propagate it to all the new sign bits
8955 
8956   for (unsigned n = n_src; n < n_dest; n++)
8957     avr_asm_len ("sbc %0,%0", &all_regs_rtx[REGNO (xop[0]) + n], plen, 1);
8958 
8959   return "";
8960 }
8961 
8962 
8963 /* PLEN == NULL: Output code to add CONST_INT OP[0] to SP.
8964    PLEN != NULL: Set *PLEN to the length of that sequence.
8965    Return "".  */
8966 
8967 const char*
avr_out_addto_sp(rtx * op,int * plen)8968 avr_out_addto_sp (rtx *op, int *plen)
8969 {
8970   int pc_len = AVR_2_BYTE_PC ? 2 : 3;
8971   int addend = INTVAL (op[0]);
8972 
8973   if (plen)
8974     *plen = 0;
8975 
8976   if (addend < 0)
8977     {
8978       if (flag_verbose_asm || flag_print_asm_name)
8979         avr_asm_len (ASM_COMMENT_START "SP -= %n0", op, plen, 0);
8980 
8981       while (addend <= -pc_len)
8982         {
8983           addend += pc_len;
8984           avr_asm_len ("rcall .", op, plen, 1);
8985         }
8986 
8987       while (addend++ < 0)
8988         avr_asm_len ("push __tmp_reg__", op, plen, 1);
8989     }
8990   else if (addend > 0)
8991     {
8992       if (flag_verbose_asm || flag_print_asm_name)
8993         avr_asm_len (ASM_COMMENT_START "SP += %0", op, plen, 0);
8994 
8995       while (addend-- > 0)
8996         avr_asm_len ("pop __tmp_reg__", op, plen, 1);
8997     }
8998 
8999   return "";
9000 }
9001 
9002 
9003 /* Output instructions to insert an inverted bit into OPERANDS[0]:
9004    $0.$1 = ~$2.$3      if XBITNO = NULL
9005    $0.$1 = ~$2.XBITNO  if XBITNO != NULL.
9006    If PLEN = NULL then output the respective instruction sequence which
9007    is a combination of BST / BLD and some instruction(s) to invert the bit.
9008    If PLEN != NULL then store the length of the sequence (in words) in *PLEN.
9009    Return "".  */
9010 
9011 const char*
avr_out_insert_notbit(rtx_insn * insn,rtx operands[],rtx xbitno,int * plen)9012 avr_out_insert_notbit (rtx_insn *insn, rtx operands[], rtx xbitno, int *plen)
9013 {
9014   rtx op[4] = { operands[0], operands[1], operands[2],
9015                 xbitno == NULL_RTX ? operands [3] : xbitno };
9016 
9017   if (INTVAL (op[1]) == 7
9018       && test_hard_reg_class (LD_REGS, op[0]))
9019     {
9020       /* If the inserted bit number is 7 and we have a d-reg, then invert
9021          the bit after the insertion by means of SUBI *,0x80.  */
9022 
9023       if (INTVAL (op[3]) == 7
9024           && REGNO (op[0]) == REGNO (op[2]))
9025         {
9026           avr_asm_len ("subi %0,0x80", op, plen, -1);
9027         }
9028       else
9029         {
9030           avr_asm_len ("bst %2,%3" CR_TAB
9031                        "bld %0,%1" CR_TAB
9032                        "subi %0,0x80", op, plen, -3);
9033         }
9034     }
9035   else if (test_hard_reg_class (LD_REGS, op[0])
9036            && (INTVAL (op[1]) != INTVAL (op[3])
9037                || !reg_overlap_mentioned_p (op[0], op[2])))
9038     {
9039       /* If the destination bit is in a d-reg we can jump depending
9040          on the source bit and use ANDI / ORI.  This just applies if we
9041          have not an early-clobber situation with the bit.  */
9042 
9043       avr_asm_len ("andi %0,~(1<<%1)" CR_TAB
9044                    "sbrs %2,%3"       CR_TAB
9045                    "ori %0,1<<%1", op, plen, -3);
9046     }
9047   else
9048     {
9049       /* Otherwise, invert the bit by means of COM before we store it with
9050          BST and then undo the COM if needed.  */
9051 
9052       avr_asm_len ("com %2" CR_TAB
9053                    "bst %2,%3", op, plen, -2);
9054 
9055       if (!reg_unused_after (insn, op[2])
9056           // A simple 'reg_unused_after' is not enough because that function
9057           // assumes that the destination register is overwritten completely
9058           // and hence is in order for our purpose.  This is not the case
9059           // with BLD which just changes one bit of the destination.
9060           || reg_overlap_mentioned_p (op[0], op[2]))
9061         {
9062           /* Undo the COM from above.  */
9063           avr_asm_len ("com %2", op, plen, 1);
9064         }
9065 
9066       avr_asm_len ("bld %0,%1", op, plen, 1);
9067     }
9068 
9069   return "";
9070 }
9071 
9072 
9073 /* Outputs instructions needed for fixed point type conversion.
9074    This includes converting between any fixed point type, as well
9075    as converting to any integer type.  Conversion between integer
9076    types is not supported.
9077 
9078    Converting signed fractional types requires a bit shift if converting
9079    to or from any unsigned fractional type because the decimal place is
9080    shifted by 1 bit.  When the destination is a signed fractional, the sign
9081    is stored in either the carry or T bit.  */
9082 
9083 const char*
avr_out_fract(rtx_insn * insn,rtx operands[],bool intsigned,int * plen)9084 avr_out_fract (rtx_insn *insn, rtx operands[], bool intsigned, int *plen)
9085 {
9086   rtx xop[6];
9087   RTX_CODE shift = UNKNOWN;
9088   bool sign_in_carry = false;
9089   bool msb_in_carry = false;
9090   bool lsb_in_tmp_reg = false;
9091   bool lsb_in_carry = false;
9092   bool frac_rounded = false;
9093   const char *code_ashift = "lsl %0";
9094 
9095 
9096 #define MAY_CLOBBER(RR)                                                 \
9097   /* Shorthand used below.  */                                          \
9098   ((sign_bytes                                                          \
9099     && IN_RANGE (RR, dest.regno_msb - sign_bytes + 1, dest.regno_msb))  \
9100    || (offset && IN_RANGE (RR, dest.regno, dest.regno_msb))           \
9101    || (reg_unused_after (insn, all_regs_rtx[RR])                        \
9102        && !IN_RANGE (RR, dest.regno, dest.regno_msb)))
9103 
9104   struct
9105   {
9106     /* bytes       : Length of operand in bytes.
9107        ibyte       : Length of integral part in bytes.
9108        fbyte, fbit : Length of fractional part in bytes, bits.  */
9109 
9110     bool sbit;
9111     unsigned fbit, bytes, ibyte, fbyte;
9112     unsigned regno, regno_msb;
9113   } dest, src, *val[2] = { &dest, &src };
9114 
9115   if (plen)
9116     *plen = 0;
9117 
9118   /* Step 0:  Determine information on source and destination operand we
9119      ======   will need in the remainder.  */
9120 
9121   for (size_t i = 0; i < ARRAY_SIZE (val); i++)
9122     {
9123       machine_mode mode;
9124 
9125       xop[i] = operands[i];
9126 
9127       mode = GET_MODE (xop[i]);
9128 
9129       val[i]->bytes = GET_MODE_SIZE (mode);
9130       val[i]->regno = REGNO (xop[i]);
9131       val[i]->regno_msb = REGNO (xop[i]) + val[i]->bytes - 1;
9132 
9133       if (SCALAR_INT_MODE_P (mode))
9134         {
9135           val[i]->sbit = intsigned;
9136           val[i]->fbit = 0;
9137         }
9138       else if (ALL_SCALAR_FIXED_POINT_MODE_P (mode))
9139         {
9140           val[i]->sbit = SIGNED_SCALAR_FIXED_POINT_MODE_P (mode);
9141           val[i]->fbit = GET_MODE_FBIT (mode);
9142         }
9143       else
9144         fatal_insn ("unsupported fixed-point conversion", insn);
9145 
9146       val[i]->fbyte = (1 + val[i]->fbit) / BITS_PER_UNIT;
9147       val[i]->ibyte = val[i]->bytes - val[i]->fbyte;
9148     }
9149 
9150   // Byte offset of the decimal point taking into account different place
9151   // of the decimal point in input and output and different register numbers
9152   // of input and output.
9153   int offset = dest.regno - src.regno + dest.fbyte - src.fbyte;
9154 
9155   // Number of destination bytes that will come from sign / zero extension.
9156   int sign_bytes = (dest.ibyte - src.ibyte) * (dest.ibyte > src.ibyte);
9157 
9158   // Number of bytes at the low end to be filled with zeros.
9159   int zero_bytes = (dest.fbyte - src.fbyte) * (dest.fbyte > src.fbyte);
9160 
9161   // Do we have a 16-Bit register that is cleared?
9162   rtx clrw = NULL_RTX;
9163 
9164   bool sign_extend = src.sbit && sign_bytes;
9165 
9166   if (dest.fbit % 8 == 0 && src.fbit % 8 == 7)
9167     shift = ASHIFT;
9168   else if (dest.fbit % 8 == 7 && src.fbit % 8 == 0)
9169     shift = ASHIFTRT;
9170   else if (dest.fbit % 8 == src.fbit % 8)
9171     shift = UNKNOWN;
9172   else
9173     gcc_unreachable();
9174 
9175   /* If we need to round the fraction part, we might need to save/round it
9176      before clobbering any of it in Step 1.  Also, we might want to do
9177      the rounding now to make use of LD_REGS.  */
9178   if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
9179       && SCALAR_ACCUM_MODE_P (GET_MODE (xop[1]))
9180       && !TARGET_FRACT_CONV_TRUNC)
9181     {
9182       bool overlap
9183         = (src.regno <=
9184            (offset ? dest.regno_msb - sign_bytes : dest.regno + zero_bytes - 1)
9185            && dest.regno - offset -1 >= dest.regno);
9186       unsigned s0 = dest.regno - offset -1;
9187       bool use_src = true;
9188       unsigned sn;
9189       unsigned copied_msb = src.regno_msb;
9190       bool have_carry = false;
9191 
9192       if (src.ibyte > dest.ibyte)
9193         copied_msb -= src.ibyte - dest.ibyte;
9194 
9195       for (sn = s0; sn <= copied_msb; sn++)
9196         if (!IN_RANGE (sn, dest.regno, dest.regno_msb)
9197             && !reg_unused_after (insn, all_regs_rtx[sn]))
9198           use_src = false;
9199       if (use_src && TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], s0))
9200         {
9201           avr_asm_len ("tst %0" CR_TAB "brpl 0f",
9202                        &all_regs_rtx[src.regno_msb], plen, 2);
9203           sn = src.regno;
9204           if (sn < s0)
9205             {
9206               if (TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], sn))
9207                 avr_asm_len ("cpi %0,1", &all_regs_rtx[sn], plen, 1);
9208               else
9209                 avr_asm_len ("sec" CR_TAB
9210                              "cpc %0,__zero_reg__",
9211                              &all_regs_rtx[sn], plen, 2);
9212               have_carry = true;
9213             }
9214           while (++sn < s0)
9215             avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
9216 
9217           avr_asm_len (have_carry ? "sbci %0,128" : "subi %0,129",
9218                        &all_regs_rtx[s0], plen, 1);
9219           for (sn = src.regno + src.fbyte; sn <= copied_msb; sn++)
9220             avr_asm_len ("sbci %0,255", &all_regs_rtx[sn], plen, 1);
9221           avr_asm_len ("\n0:", NULL, plen, 0);
9222           frac_rounded = true;
9223         }
9224       else if (use_src && overlap)
9225         {
9226           avr_asm_len ("clr __tmp_reg__" CR_TAB
9227                        "sbrc %1,0"       CR_TAB
9228                        "dec __tmp_reg__", xop, plen, 1);
9229           sn = src.regno;
9230           if (sn < s0)
9231             {
9232               avr_asm_len ("add %0,__tmp_reg__", &all_regs_rtx[sn], plen, 1);
9233               have_carry = true;
9234             }
9235 
9236           while (++sn < s0)
9237             avr_asm_len ("adc %0,__tmp_reg__", &all_regs_rtx[sn], plen, 1);
9238 
9239           if (have_carry)
9240             avr_asm_len ("clt"                CR_TAB
9241                          "bld __tmp_reg__,7"  CR_TAB
9242                          "adc %0,__tmp_reg__",
9243                          &all_regs_rtx[s0], plen, 1);
9244           else
9245             avr_asm_len ("lsr __tmp_reg" CR_TAB
9246                          "add %0,__tmp_reg__",
9247                          &all_regs_rtx[s0], plen, 2);
9248           for (sn = src.regno + src.fbyte; sn <= copied_msb; sn++)
9249             avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
9250           frac_rounded = true;
9251         }
9252       else if (overlap)
9253         {
9254           bool use_src
9255             = (TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], s0)
9256                && (IN_RANGE (s0, dest.regno, dest.regno_msb)
9257                    || reg_unused_after (insn, all_regs_rtx[s0])));
9258           xop[2] = all_regs_rtx[s0];
9259           unsigned sn = src.regno;
9260           if (!use_src || sn == s0)
9261             avr_asm_len ("mov __tmp_reg__,%2", xop, plen, 1);
9262           /* We need to consider to-be-discarded bits
9263              if the value is negative.  */
9264           if (sn < s0)
9265             {
9266               avr_asm_len ("tst %0" CR_TAB
9267                            "brpl 0f",
9268                            &all_regs_rtx[src.regno_msb], plen, 2);
9269               /* Test to-be-discarded bytes for any nozero bits.
9270                  ??? Could use OR or SBIW to test two registers at once.  */
9271               if (sn < s0)
9272                 avr_asm_len ("cp %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
9273 
9274               while (++sn < s0)
9275                 avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
9276               /* Set bit 0 in __tmp_reg__ if any of the lower bits was set.  */
9277               if (use_src)
9278                 avr_asm_len ("breq 0f" CR_TAB
9279                              "ori %2,1"
9280                              "\n0:\t" "mov __tmp_reg__,%2",
9281                              xop, plen, 3);
9282               else
9283                 avr_asm_len ("breq 0f" CR_TAB
9284                              "set"     CR_TAB
9285                              "bld __tmp_reg__,0\n0:",
9286                              xop, plen, 3);
9287             }
9288           lsb_in_tmp_reg = true;
9289         }
9290     }
9291 
9292   /* Step 1:  Clear bytes at the low end and copy payload bits from source
9293      ======   to destination.  */
9294 
9295   int step = offset < 0 ? 1 : -1;
9296   unsigned d0 = offset < 0 ? dest.regno : dest.regno_msb;
9297 
9298   // We cleared at least that number of registers.
9299   int clr_n = 0;
9300 
9301   for (; d0 >= dest.regno && d0 <= dest.regno_msb; d0 += step)
9302     {
9303       // Next regno of destination is needed for MOVW
9304       unsigned d1 = d0 + step;
9305 
9306       // Current and next regno of source
9307       signed s0 = d0 - offset;
9308       signed s1 = s0 + step;
9309 
9310       // Must current resp. next regno be CLRed?  This applies to the low
9311       // bytes of the destination that have no associated source bytes.
9312       bool clr0 = s0 < (signed) src.regno;
9313       bool clr1 = s1 < (signed) src.regno && d1 >= dest.regno;
9314 
9315       // First gather what code to emit (if any) and additional step to
9316       // apply if a MOVW is in use.  xop[2] is destination rtx and xop[3]
9317       // is the source rtx for the current loop iteration.
9318       const char *code = NULL;
9319       int stepw = 0;
9320 
9321       if (clr0)
9322         {
9323           if (AVR_HAVE_MOVW && clr1 && clrw)
9324             {
9325               xop[2] = all_regs_rtx[d0 & ~1];
9326               xop[3] = clrw;
9327               code = "movw %2,%3";
9328               stepw = step;
9329             }
9330           else
9331             {
9332               xop[2] = all_regs_rtx[d0];
9333               code = "clr %2";
9334 
9335               if (++clr_n >= 2
9336                   && !clrw
9337                   && d0 % 2 == (step > 0))
9338                 {
9339                   clrw = all_regs_rtx[d0 & ~1];
9340                 }
9341             }
9342         }
9343       else if (offset && s0 <= (signed) src.regno_msb)
9344         {
9345           int movw = AVR_HAVE_MOVW && offset % 2 == 0
9346             && d0 % 2 == (offset > 0)
9347             && d1 <= dest.regno_msb && d1 >= dest.regno
9348             && s1 <= (signed) src.regno_msb  && s1 >= (signed) src.regno;
9349 
9350           xop[2] = all_regs_rtx[d0 & ~movw];
9351           xop[3] = all_regs_rtx[s0 & ~movw];
9352           code = movw ? "movw %2,%3" : "mov %2,%3";
9353           stepw = step * movw;
9354         }
9355 
9356       if (code)
9357         {
9358           if (sign_extend && shift != ASHIFT && !sign_in_carry
9359               && (d0 == src.regno_msb || d0 + stepw == src.regno_msb))
9360             {
9361               /* We are going to override the sign bit.  If we sign-extend,
9362                  store the sign in the Carry flag.  This is not needed if
9363                  the destination will be ASHIFT in the remainder because
9364                  the ASHIFT will set Carry without extra instruction.  */
9365 
9366               avr_asm_len ("lsl %0", &all_regs_rtx[src.regno_msb], plen, 1);
9367               sign_in_carry = true;
9368             }
9369 
9370           unsigned src_msb = dest.regno_msb - sign_bytes - offset + 1;
9371 
9372           if (!sign_extend && shift == ASHIFTRT && !msb_in_carry
9373               && src.ibyte > dest.ibyte
9374               && (d0 == src_msb || d0 + stepw == src_msb))
9375             {
9376               /* We are going to override the MSB.  If we shift right,
9377                  store the MSB in the Carry flag.  This is only needed if
9378                  we don't sign-extend becaue with sign-extension the MSB
9379                  (the sign) will be produced by the sign extension.  */
9380 
9381               avr_asm_len ("lsr %0", &all_regs_rtx[src_msb], plen, 1);
9382               msb_in_carry = true;
9383             }
9384 
9385           unsigned src_lsb = dest.regno - offset -1;
9386 
9387           if (shift == ASHIFT && src.fbyte > dest.fbyte && !lsb_in_carry
9388                 && !lsb_in_tmp_reg
9389               && (d0 == src_lsb || d0 + stepw == src_lsb))
9390             {
9391               /* We are going to override the new LSB; store it into carry.  */
9392 
9393               avr_asm_len ("lsl %0", &all_regs_rtx[src_lsb], plen, 1);
9394               code_ashift = "rol %0";
9395               lsb_in_carry = true;
9396             }
9397 
9398           avr_asm_len (code, xop, plen, 1);
9399           d0 += stepw;
9400         }
9401     }
9402 
9403   /* Step 2:  Shift destination left by 1 bit position.  This might be needed
9404      ======   for signed input and unsigned output.  */
9405 
9406   if (shift == ASHIFT && src.fbyte > dest.fbyte && !lsb_in_carry)
9407     {
9408       unsigned s0 = dest.regno - offset -1;
9409 
9410       /* n1169 4.1.4 says:
9411            "Conversions from a fixed-point to an integer type round toward zero."
9412            Hence, converting a fract type to integer only gives a non-zero result
9413            for -1.  */
9414       if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
9415             && SCALAR_FRACT_MODE_P (GET_MODE (xop[1]))
9416             && !TARGET_FRACT_CONV_TRUNC)
9417           {
9418             gcc_assert (s0 == src.regno_msb);
9419             /* Check if the input is -1.  We do that by checking if negating
9420                the input causes an integer overflow.  */
9421             unsigned sn = src.regno;
9422             avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx[sn++], plen, 1);
9423             while (sn <= s0)
9424               avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx[sn++], plen, 1);
9425 
9426             /* Overflow goes with set carry.  Clear carry otherwise.  */
9427             avr_asm_len ("brvs 0f" CR_TAB
9428                        "clc\n0:", NULL, plen, 2);
9429           }
9430       /* Likewise, when converting from accumulator types to integer, we
9431            need to round up negative values.  */
9432       else if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
9433                  && SCALAR_ACCUM_MODE_P (GET_MODE (xop[1]))
9434                  && !TARGET_FRACT_CONV_TRUNC
9435                  && !frac_rounded)
9436           {
9437             bool have_carry = false;
9438 
9439             xop[2] = all_regs_rtx[s0];
9440             if (!lsb_in_tmp_reg && !MAY_CLOBBER (s0))
9441               avr_asm_len ("mov __tmp_reg__,%2", xop, plen, 1);
9442             avr_asm_len ("tst %0" CR_TAB "brpl 0f",
9443                            &all_regs_rtx[src.regno_msb], plen, 2);
9444             if (!lsb_in_tmp_reg)
9445               {
9446                 unsigned sn = src.regno;
9447                 if (sn < s0)
9448                     {
9449                       avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx[sn],
9450                                      plen, 1);
9451                       have_carry = true;
9452                     }
9453                 while (++sn < s0)
9454                     avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx[sn], plen, 1);
9455                 lsb_in_tmp_reg = !MAY_CLOBBER (s0);
9456               }
9457             /* Add in C and the rounding value 127.  */
9458             /* If the destination msb is a sign byte, and in LD_REGS,
9459                grab it as a temporary.  */
9460             if (sign_bytes
9461                 && TEST_HARD_REG_BIT (reg_class_contents[LD_REGS],
9462                                             dest.regno_msb))
9463               {
9464                 xop[3] = all_regs_rtx[dest.regno_msb];
9465                 avr_asm_len ("ldi %3,127", xop, plen, 1);
9466                 avr_asm_len ((have_carry && lsb_in_tmp_reg ? "adc __tmp_reg__,%3"
9467                                   : have_carry ? "adc %2,%3"
9468                                   : lsb_in_tmp_reg ? "add __tmp_reg__,%3"
9469                                   : "add %2,%3"),
9470                                  xop, plen, 1);
9471               }
9472             else
9473               {
9474                 /* Fall back to use __zero_reg__ as a temporary.  */
9475                 avr_asm_len ("dec __zero_reg__", NULL, plen, 1);
9476                 if (have_carry)
9477                     avr_asm_len ("clt" CR_TAB
9478                              "bld __zero_reg__,7", NULL, plen, 2);
9479                 else
9480                     avr_asm_len ("lsr __zero_reg__", NULL, plen, 1);
9481                 avr_asm_len (have_carry && lsb_in_tmp_reg
9482                            ? "adc __tmp_reg__,__zero_reg__"
9483                            : have_carry ? "adc %2,__zero_reg__"
9484                            : lsb_in_tmp_reg ? "add __tmp_reg__,__zero_reg__"
9485                            : "add %2,__zero_reg__",
9486                                  xop, plen, 1);
9487                 avr_asm_len ("eor __zero_reg__,__zero_reg__", NULL, plen, 1);
9488               }
9489 
9490           for (d0 = dest.regno + zero_bytes;
9491                  d0 <= dest.regno_msb - sign_bytes; d0++)
9492               avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx[d0], plen, 1);
9493 
9494           avr_asm_len (lsb_in_tmp_reg
9495                            ? "\n0:\t" "lsl __tmp_reg__"
9496                        : "\n0:\t" "lsl %2",
9497                            xop, plen, 1);
9498           }
9499       else if (MAY_CLOBBER (s0))
9500         avr_asm_len ("lsl %0", &all_regs_rtx[s0], plen, 1);
9501       else
9502         avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
9503                      "lsl __tmp_reg__", &all_regs_rtx[s0], plen, 2);
9504 
9505       code_ashift = "rol %0";
9506       lsb_in_carry = true;
9507     }
9508 
9509   if (shift == ASHIFT)
9510     {
9511       for (d0 = dest.regno + zero_bytes;
9512            d0 <= dest.regno_msb - sign_bytes; d0++)
9513         {
9514           avr_asm_len (code_ashift, &all_regs_rtx[d0], plen, 1);
9515           code_ashift = "rol %0";
9516         }
9517 
9518       lsb_in_carry = false;
9519       sign_in_carry = true;
9520     }
9521 
9522   /* Step 4a:  Store MSB in carry if we don't already have it or will produce
9523      =======   it in sign-extension below.  */
9524 
9525   if (!sign_extend && shift == ASHIFTRT && !msb_in_carry
9526       && src.ibyte > dest.ibyte)
9527     {
9528       unsigned s0 = dest.regno_msb - sign_bytes - offset + 1;
9529 
9530       if (MAY_CLOBBER (s0))
9531         avr_asm_len ("lsr %0", &all_regs_rtx[s0], plen, 1);
9532       else
9533         avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
9534                      "lsr __tmp_reg__", &all_regs_rtx[s0], plen, 2);
9535 
9536       msb_in_carry = true;
9537     }
9538 
9539   /* Step 3:  Sign-extend or zero-extend the destination as needed.
9540      ======   */
9541 
9542   if (sign_extend && !sign_in_carry)
9543     {
9544       unsigned s0 = src.regno_msb;
9545 
9546       if (MAY_CLOBBER (s0))
9547         avr_asm_len ("lsl %0", &all_regs_rtx[s0], plen, 1);
9548       else
9549         avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
9550                      "lsl __tmp_reg__", &all_regs_rtx[s0], plen, 2);
9551 
9552       sign_in_carry = true;
9553     }
9554 
9555   gcc_assert (sign_in_carry + msb_in_carry + lsb_in_carry <= 1);
9556 
9557   unsigned copies = 0;
9558   rtx movw = sign_extend ? NULL_RTX : clrw;
9559 
9560   for (d0 = dest.regno_msb - sign_bytes + 1; d0 <= dest.regno_msb; d0++)
9561     {
9562       if (AVR_HAVE_MOVW && movw
9563           && d0 % 2 == 0 && d0 + 1 <= dest.regno_msb)
9564         {
9565           xop[2] = all_regs_rtx[d0];
9566           xop[3] = movw;
9567           avr_asm_len ("movw %2,%3", xop, plen, 1);
9568           d0++;
9569         }
9570       else
9571         {
9572           avr_asm_len (sign_extend ? "sbc %0,%0" : "clr %0",
9573                        &all_regs_rtx[d0], plen, 1);
9574 
9575           if (++copies >= 2 && !movw && d0 % 2 == 1)
9576             movw = all_regs_rtx[d0-1];
9577         }
9578     } /* for */
9579 
9580 
9581   /* Step 4:  Right shift the destination.  This might be needed for
9582      ======   conversions from unsigned to signed.  */
9583 
9584   if (shift == ASHIFTRT)
9585     {
9586       const char *code_ashiftrt = "lsr %0";
9587 
9588       if (sign_extend || msb_in_carry)
9589         code_ashiftrt = "ror %0";
9590 
9591       if (src.sbit && src.ibyte == dest.ibyte)
9592         code_ashiftrt = "asr %0";
9593 
9594       for (d0 = dest.regno_msb - sign_bytes;
9595            d0 >= dest.regno + zero_bytes - 1 && d0 >= dest.regno; d0--)
9596         {
9597           avr_asm_len (code_ashiftrt, &all_regs_rtx[d0], plen, 1);
9598           code_ashiftrt = "ror %0";
9599         }
9600     }
9601 
9602 #undef MAY_CLOBBER
9603 
9604   return "";
9605 }
9606 
9607 
9608 /* Output fixed-point rounding.  XOP[0] = XOP[1] is the operand to round.
9609    XOP[2] is the rounding point, a CONST_INT.  The function prints the
9610    instruction sequence if PLEN = NULL and computes the length in words
9611    of the sequence if PLEN != NULL.  Most of this function deals with
9612    preparing operands for calls to `avr_out_plus' and `avr_out_bitop'.  */
9613 
9614 const char*
avr_out_round(rtx_insn * insn ATTRIBUTE_UNUSED,rtx * xop,int * plen)9615 avr_out_round (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *xop, int *plen)
9616 {
9617   scalar_mode mode = as_a <scalar_mode> (GET_MODE (xop[0]));
9618   scalar_int_mode imode = int_mode_for_mode (mode).require ();
9619   // The smallest fractional bit not cleared by the rounding is 2^(-RP).
9620   int fbit = (int) GET_MODE_FBIT (mode);
9621   double_int i_add = double_int_zero.set_bit (fbit-1 - INTVAL (xop[2]));
9622   wide_int wi_add = wi::set_bit_in_zero (fbit-1 - INTVAL (xop[2]),
9623                                                    GET_MODE_PRECISION (imode));
9624   // Lengths of PLUS and AND parts.
9625   int len_add = 0, *plen_add = plen ? &len_add : NULL;
9626   int len_and = 0, *plen_and = plen ? &len_and : NULL;
9627 
9628   // Add-Saturate  1/2 * 2^(-RP).  Don't print the label "0:" when printing
9629   // the saturated addition so that we can emit the "rjmp 1f" before the
9630   // "0:" below.
9631 
9632   rtx xadd = const_fixed_from_double_int (i_add, mode);
9633   rtx xpattern, xsrc, op[4];
9634 
9635   xsrc = SIGNED_FIXED_POINT_MODE_P (mode)
9636     ? gen_rtx_SS_PLUS (mode, xop[1], xadd)
9637     : gen_rtx_US_PLUS (mode, xop[1], xadd);
9638   xpattern = gen_rtx_SET (xop[0], xsrc);
9639 
9640   op[0] = xop[0];
9641   op[1] = xop[1];
9642   op[2] = xadd;
9643   avr_out_plus (xpattern, op, plen_add, NULL, false /* Don't print "0:" */);
9644 
9645   avr_asm_len ("rjmp 1f" CR_TAB
9646                "0:", NULL, plen_add, 1);
9647 
9648   // Keep  all bits from RP and higher:   ... 2^(-RP)
9649   // Clear all bits from RP+1 and lower:              2^(-RP-1) ...
9650   // Rounding point                           ^^^^^^^
9651   // Added above                                      ^^^^^^^^^
9652   rtx xreg = simplify_gen_subreg (imode, xop[0], mode, 0);
9653   rtx xmask = immed_wide_int_const (-wi_add - wi_add, imode);
9654 
9655   xpattern = gen_rtx_SET (xreg, gen_rtx_AND (imode, xreg, xmask));
9656 
9657   op[0] = xreg;
9658   op[1] = xreg;
9659   op[2] = xmask;
9660   op[3] = gen_rtx_SCRATCH (QImode);
9661   avr_out_bitop (xpattern, op, plen_and);
9662   avr_asm_len ("1:", NULL, plen, 0);
9663 
9664   if (plen)
9665     *plen = len_add + len_and;
9666 
9667   return "";
9668 }
9669 
9670 
9671 /* Create RTL split patterns for byte sized rotate expressions.  This
9672    produces a series of move instructions and considers overlap situations.
9673    Overlapping non-HImode operands need a scratch register.  */
9674 
9675 bool
avr_rotate_bytes(rtx operands[])9676 avr_rotate_bytes (rtx operands[])
9677 {
9678   machine_mode mode = GET_MODE (operands[0]);
9679   bool overlapped = reg_overlap_mentioned_p (operands[0], operands[1]);
9680   bool same_reg = rtx_equal_p (operands[0], operands[1]);
9681   int num = INTVAL (operands[2]);
9682   rtx scratch = operands[3];
9683   /* Work out if byte or word move is needed.  Odd byte rotates need QImode.
9684      Word move if no scratch is needed, otherwise use size of scratch.  */
9685   machine_mode move_mode = QImode;
9686   int move_size, offset, size;
9687 
9688   if (num & 0xf)
9689     move_mode = QImode;
9690   else if ((mode == SImode && !same_reg) || !overlapped)
9691     move_mode = HImode;
9692   else
9693     move_mode = GET_MODE (scratch);
9694 
9695   /* Force DI rotate to use QI moves since other DI moves are currently split
9696      into QI moves so forward propagation works better.  */
9697   if (mode == DImode)
9698     move_mode = QImode;
9699   /* Make scratch smaller if needed.  */
9700   if (SCRATCH != GET_CODE (scratch)
9701       && HImode == GET_MODE (scratch)
9702       && QImode == move_mode)
9703     scratch = simplify_gen_subreg (move_mode, scratch, HImode, 0);
9704 
9705   move_size = GET_MODE_SIZE (move_mode);
9706   /* Number of bytes/words to rotate.  */
9707   offset = (num  >> 3) / move_size;
9708   /* Number of moves needed.  */
9709   size = GET_MODE_SIZE (mode) / move_size;
9710   /* Himode byte swap is special case to avoid a scratch register.  */
9711   if (mode == HImode && same_reg)
9712     {
9713       /* HImode byte swap, using xor.  This is as quick as using scratch.  */
9714       rtx src, dst;
9715       src = simplify_gen_subreg (move_mode, operands[1], mode, 0);
9716       dst = simplify_gen_subreg (move_mode, operands[0], mode, 1);
9717       if (!rtx_equal_p (dst, src))
9718         {
9719           emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
9720           emit_move_insn (src, gen_rtx_XOR (QImode, src, dst));
9721           emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
9722         }
9723     }
9724   else
9725     {
9726 #define MAX_SIZE 8 /* GET_MODE_SIZE (DImode) / GET_MODE_SIZE (QImode)  */
9727       /* Create linked list of moves to determine move order.  */
9728       struct {
9729         rtx src, dst;
9730         int links;
9731       } move[MAX_SIZE + 8];
9732       int blocked, moves;
9733 
9734       gcc_assert (size <= MAX_SIZE);
9735       /* Generate list of subreg moves.  */
9736       for (int i = 0; i < size; i++)
9737         {
9738           int from = i;
9739           int to = (from + offset) % size;
9740           move[i].src = simplify_gen_subreg (move_mode, operands[1],
9741                                              mode, from * move_size);
9742           move[i].dst = simplify_gen_subreg (move_mode, operands[0],
9743                                              mode, to * move_size);
9744           move[i].links = -1;
9745         }
9746       /* Mark dependence where a dst of one move is the src of another move.
9747          The first move is a conflict as it must wait until second is
9748          performed.  We ignore moves to self - we catch this later.  */
9749       if (overlapped)
9750         for (int i = 0; i < size; i++)
9751           if (reg_overlap_mentioned_p (move[i].dst, operands[1]))
9752             for (int j = 0; j < size; j++)
9753               if (j != i && rtx_equal_p (move[j].src, move[i].dst))
9754                 {
9755                   /* The dst of move i is the src of move j.  */
9756                   move[i].links = j;
9757                   break;
9758                 }
9759 
9760       blocked = -1;
9761       moves = 0;
9762       /* Go through move list and perform non-conflicting moves.  As each
9763          non-overlapping move is made, it may remove other conflicts
9764          so the process is repeated until no conflicts remain.  */
9765       do
9766         {
9767           blocked = -1;
9768           moves = 0;
9769           /* Emit move where dst is not also a src or we have used that
9770              src already.  */
9771           for (int i = 0; i < size; i++)
9772             if (move[i].src != NULL_RTX)
9773               {
9774                 if (move[i].links == -1
9775                     || move[move[i].links].src == NULL_RTX)
9776                   {
9777                     moves++;
9778                     /* Ignore NOP moves to self.  */
9779                     if (!rtx_equal_p (move[i].dst, move[i].src))
9780                       emit_move_insn (move[i].dst, move[i].src);
9781 
9782                     /* Remove  conflict from list.  */
9783                     move[i].src = NULL_RTX;
9784                   }
9785                 else
9786                   blocked = i;
9787               }
9788 
9789           /* Check for deadlock. This is when no moves occurred and we have
9790              at least one blocked move.  */
9791           if (moves == 0 && blocked != -1)
9792             {
9793               /* Need to use scratch register to break deadlock.
9794                  Add move to put dst of blocked move into scratch.
9795                  When this move occurs, it will break chain deadlock.
9796                  The scratch register is substituted for real move.  */
9797 
9798               gcc_assert (SCRATCH != GET_CODE (scratch));
9799 
9800               move[size].src = move[blocked].dst;
9801               move[size].dst =  scratch;
9802               /* Scratch move is never blocked.  */
9803               move[size].links = -1;
9804               /* Make sure we have valid link.  */
9805               gcc_assert (move[blocked].links != -1);
9806               /* Replace src of  blocking move with scratch reg.  */
9807               move[move[blocked].links].src = scratch;
9808               /* Make dependent on scratch move occurring.  */
9809               move[blocked].links = size;
9810               size=size+1;
9811             }
9812         }
9813       while (blocked != -1);
9814     }
9815   return true;
9816 }
9817 
9818 
9819 /* Worker function for `ADJUST_INSN_LENGTH'.  */
9820 /* Modifies the length assigned to instruction INSN
9821    LEN is the initially computed length of the insn.  */
9822 
9823 int
avr_adjust_insn_length(rtx_insn * insn,int len)9824 avr_adjust_insn_length (rtx_insn *insn, int len)
9825 {
9826   rtx *op = recog_data.operand;
9827   enum attr_adjust_len adjust_len;
9828 
9829   /* As we pretend jump tables in .text, fix branch offsets crossing jump
9830      tables now.  */
9831 
9832   if (JUMP_TABLE_DATA_P (insn))
9833     return 0;
9834 
9835   /* Some complex insns don't need length adjustment and therefore
9836      the length need not/must not be adjusted for these insns.
9837      It is easier to state this in an insn attribute "adjust_len" than
9838      to clutter up code here...  */
9839 
9840   if (!NONDEBUG_INSN_P (insn) || recog_memoized (insn) == -1)
9841     {
9842       return len;
9843     }
9844 
9845   /* Read from insn attribute "adjust_len" if/how length is to be adjusted.  */
9846 
9847   adjust_len = get_attr_adjust_len (insn);
9848 
9849   if (adjust_len == ADJUST_LEN_NO)
9850     {
9851       /* Nothing to adjust: The length from attribute "length" is fine.
9852          This is the default.  */
9853 
9854       return len;
9855     }
9856 
9857   /* Extract insn's operands.  */
9858 
9859   extract_constrain_insn_cached (insn);
9860 
9861   /* Dispatch to right function.  */
9862 
9863   switch (adjust_len)
9864     {
9865     case ADJUST_LEN_RELOAD_IN16: output_reload_inhi (op, op[2], &len); break;
9866     case ADJUST_LEN_RELOAD_IN24: avr_out_reload_inpsi (op, op[2], &len); break;
9867     case ADJUST_LEN_RELOAD_IN32: output_reload_insisf (op, op[2], &len); break;
9868 
9869     case ADJUST_LEN_OUT_BITOP: avr_out_bitop (insn, op, &len); break;
9870 
9871     case ADJUST_LEN_PLUS: avr_out_plus (insn, op, &len); break;
9872     case ADJUST_LEN_ADDTO_SP: avr_out_addto_sp (op, &len); break;
9873 
9874     case ADJUST_LEN_MOV8:  output_movqi (insn, op, &len); break;
9875     case ADJUST_LEN_MOV16: output_movhi (insn, op, &len); break;
9876     case ADJUST_LEN_MOV24: avr_out_movpsi (insn, op, &len); break;
9877     case ADJUST_LEN_MOV32: output_movsisf (insn, op, &len); break;
9878     case ADJUST_LEN_CPYMEM: avr_out_cpymem (insn, op, &len); break;
9879     case ADJUST_LEN_XLOAD: avr_out_xload (insn, op, &len); break;
9880     case ADJUST_LEN_SEXT: avr_out_sign_extend (insn, op, &len); break;
9881 
9882     case ADJUST_LEN_SFRACT: avr_out_fract (insn, op, true, &len); break;
9883     case ADJUST_LEN_UFRACT: avr_out_fract (insn, op, false, &len); break;
9884     case ADJUST_LEN_ROUND: avr_out_round (insn, op, &len); break;
9885 
9886     case ADJUST_LEN_TSTHI: avr_out_tsthi (insn, op, &len); break;
9887     case ADJUST_LEN_TSTPSI: avr_out_tstpsi (insn, op, &len); break;
9888     case ADJUST_LEN_TSTSI: avr_out_tstsi (insn, op, &len); break;
9889     case ADJUST_LEN_COMPARE: avr_out_compare (insn, op, &len); break;
9890     case ADJUST_LEN_COMPARE64: avr_out_compare64 (insn, op, &len); break;
9891     case ADJUST_LEN_CMP_UEXT: avr_out_cmp_ext (op, ZERO_EXTEND, &len); break;
9892     case ADJUST_LEN_CMP_SEXT: avr_out_cmp_ext (op, SIGN_EXTEND, &len); break;
9893 
9894     case ADJUST_LEN_LSHRQI: lshrqi3_out (insn, op, &len); break;
9895     case ADJUST_LEN_LSHRHI: lshrhi3_out (insn, op, &len); break;
9896     case ADJUST_LEN_LSHRSI: lshrsi3_out (insn, op, &len); break;
9897 
9898     case ADJUST_LEN_ASHRQI: ashrqi3_out (insn, op, &len); break;
9899     case ADJUST_LEN_ASHRHI: ashrhi3_out (insn, op, &len); break;
9900     case ADJUST_LEN_ASHRSI: ashrsi3_out (insn, op, &len); break;
9901 
9902     case ADJUST_LEN_ASHLQI: ashlqi3_out (insn, op, &len); break;
9903     case ADJUST_LEN_ASHLHI: ashlhi3_out (insn, op, &len); break;
9904     case ADJUST_LEN_ASHLSI: ashlsi3_out (insn, op, &len); break;
9905 
9906     case ADJUST_LEN_ASHLPSI: avr_out_ashlpsi3 (insn, op, &len); break;
9907     case ADJUST_LEN_ASHRPSI: avr_out_ashrpsi3 (insn, op, &len); break;
9908     case ADJUST_LEN_LSHRPSI: avr_out_lshrpsi3 (insn, op, &len); break;
9909 
9910     case ADJUST_LEN_CALL: len = AVR_HAVE_JMP_CALL ? 2 : 1; break;
9911 
9912     case ADJUST_LEN_INSERT_BITS: avr_out_insert_bits (op, &len); break;
9913     case ADJUST_LEN_ADD_SET_ZN: avr_out_plus_set_ZN (op, &len); break;
9914 
9915     case ADJUST_LEN_INSV_NOTBIT:
9916       avr_out_insert_notbit (insn, op, NULL_RTX, &len);
9917       break;
9918     case ADJUST_LEN_INSV_NOTBIT_0:
9919       avr_out_insert_notbit (insn, op, const0_rtx, &len);
9920       break;
9921     case ADJUST_LEN_INSV_NOTBIT_7:
9922       avr_out_insert_notbit (insn, op, GEN_INT (7), &len);
9923       break;
9924 
9925     default:
9926       gcc_unreachable();
9927     }
9928 
9929   return len;
9930 }
9931 
9932 /* Return nonzero if register REG dead after INSN.  */
9933 
9934 int
reg_unused_after(rtx_insn * insn,rtx reg)9935 reg_unused_after (rtx_insn *insn, rtx reg)
9936 {
9937   return (dead_or_set_p (insn, reg)
9938             || (REG_P (reg) && _reg_unused_after (insn, reg)));
9939 }
9940 
9941 /* Return nonzero if REG is not used after INSN.
9942    We assume REG is a reload reg, and therefore does
9943    not live past labels.  It may live past calls or jumps though.  */
9944 
9945 int
_reg_unused_after(rtx_insn * insn,rtx reg)9946 _reg_unused_after (rtx_insn *insn, rtx reg)
9947 {
9948   enum rtx_code code;
9949   rtx set;
9950 
9951   /* If the reg is set by this instruction, then it is safe for our
9952      case.  Disregard the case where this is a store to memory, since
9953      we are checking a register used in the store address.  */
9954   set = single_set (insn);
9955   if (set && !MEM_P (SET_DEST (set))
9956       && reg_overlap_mentioned_p (reg, SET_DEST (set)))
9957     return 1;
9958 
9959   while ((insn = NEXT_INSN (insn)))
9960     {
9961       rtx set;
9962       code = GET_CODE (insn);
9963 
9964 #if 0
9965       /* If this is a label that existed before reload, then the register
9966            if dead here.  However, if this is a label added by reorg, then
9967            the register may still be live here.  We can't tell the difference,
9968            so we just ignore labels completely.  */
9969       if (code == CODE_LABEL)
9970           return 1;
9971       /* else */
9972 #endif
9973 
9974       if (!INSN_P (insn))
9975           continue;
9976 
9977       if (code == JUMP_INSN)
9978           return 0;
9979 
9980       /* If this is a sequence, we must handle them all at once.
9981            We could have for instance a call that sets the target register,
9982            and an insn in a delay slot that uses the register.  In this case,
9983            we must return 0.  */
9984       else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
9985           {
9986             rtx_sequence *seq = as_a <rtx_sequence *> (PATTERN (insn));
9987             int retval = 0;
9988 
9989             for (int i = 0; i < seq->len (); i++)
9990               {
9991                 rtx_insn *this_insn = seq->insn (i);
9992                 rtx set = single_set (this_insn);
9993 
9994                 if (CALL_P (this_insn))
9995                     code = CALL_INSN;
9996                 else if (JUMP_P (this_insn))
9997                     {
9998                       if (INSN_ANNULLED_BRANCH_P (this_insn))
9999                         return 0;
10000                       code = JUMP_INSN;
10001                     }
10002 
10003                 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
10004                     return 0;
10005                 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
10006                     {
10007                       if (!MEM_P (SET_DEST (set)))
10008                         retval = 1;
10009                       else
10010                         return 0;
10011                     }
10012                 if (set == 0
10013                       && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
10014                     return 0;
10015               }
10016             if (retval == 1)
10017               return 1;
10018             else if (code == JUMP_INSN)
10019               return 0;
10020           }
10021 
10022       if (code == CALL_INSN)
10023           {
10024             rtx tem;
10025             for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
10026               if (GET_CODE (XEXP (tem, 0)) == USE
10027                     && REG_P (XEXP (XEXP (tem, 0), 0))
10028                     && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
10029                 return 0;
10030             if (call_used_or_fixed_reg_p (REGNO (reg)))
10031               return 1;
10032           }
10033 
10034       set = single_set (insn);
10035 
10036       if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
10037           return 0;
10038       if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
10039           return !MEM_P (SET_DEST (set));
10040       if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
10041           return 0;
10042     }
10043   return 1;
10044 }
10045 
10046 
10047 /* Implement `TARGET_ASM_INTEGER'.  */
10048 /* Target hook for assembling integer objects.  The AVR version needs
10049    special handling for references to certain labels.  */
10050 
10051 static bool
avr_assemble_integer(rtx x,unsigned int size,int aligned_p)10052 avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
10053 {
10054   if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
10055       && text_segment_operand (x, VOIDmode))
10056     {
10057       fputs ("\t.word\tgs(", asm_out_file);
10058       output_addr_const (asm_out_file, x);
10059       fputs (")\n", asm_out_file);
10060 
10061       return true;
10062     }
10063   else if (GET_MODE (x) == PSImode)
10064     {
10065       /* This needs binutils 2.23+, see PR binutils/13503  */
10066 
10067       fputs ("\t.byte\tlo8(", asm_out_file);
10068       output_addr_const (asm_out_file, x);
10069       fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
10070 
10071       fputs ("\t.byte\thi8(", asm_out_file);
10072       output_addr_const (asm_out_file, x);
10073       fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
10074 
10075       fputs ("\t.byte\thh8(", asm_out_file);
10076       output_addr_const (asm_out_file, x);
10077       fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
10078 
10079       return true;
10080     }
10081   else if (CONST_FIXED_P (x))
10082     {
10083       /* varasm fails to handle big fixed modes that don't fit in hwi.  */
10084 
10085       for (unsigned n = 0; n < size; n++)
10086         {
10087           rtx xn = simplify_gen_subreg (QImode, x, GET_MODE (x), n);
10088           default_assemble_integer (xn, 1, aligned_p);
10089         }
10090 
10091       return true;
10092     }
10093 
10094   if (AVR_TINY
10095       && avr_address_tiny_pm_p (x))
10096     {
10097       x = plus_constant (Pmode, x, avr_arch->flash_pm_offset);
10098     }
10099 
10100   return default_assemble_integer (x, size, aligned_p);
10101 }
10102 
10103 /* Implement TARGET_CLASS_MAX_NREGS. Reasons described in comments for
10104    avr_hard_regno_nregs. */
10105 
10106 static unsigned char
avr_class_max_nregs(reg_class_t rclass,machine_mode mode)10107 avr_class_max_nregs (reg_class_t rclass, machine_mode mode)
10108 {
10109   if (rclass == CC_REG && mode == CCmode)
10110           return 1;
10111 
10112   return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
10113 }
10114 
10115 
10116 /* Implement `TARGET_CLASS_LIKELY_SPILLED_P'.  */
10117 /* Return value is nonzero if pseudos that have been
10118    assigned to registers of class CLASS would likely be spilled
10119    because registers of CLASS are needed for spill registers.  */
10120 
10121 static bool
avr_class_likely_spilled_p(reg_class_t c)10122 avr_class_likely_spilled_p (reg_class_t c)
10123 {
10124   return (c != ALL_REGS &&
10125            (AVR_TINY ? 1 : c != ADDW_REGS));
10126 }
10127 
10128 
10129 /* Valid attributes:
10130    progmem   -  Put data to program memory.
10131    signal    -  Make a function to be hardware interrupt.
10132                 After function prologue interrupts remain disabled.
10133    interrupt -  Make a function to be hardware interrupt. Before function
10134                 prologue interrupts are enabled by means of SEI.
10135    naked     -  Don't generate function prologue/epilogue and RET
10136                 instruction.  */
10137 
10138 /* Handle a "progmem" attribute; arguments as in
10139    struct attribute_spec.handler.  */
10140 
10141 static tree
avr_handle_progmem_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)10142 avr_handle_progmem_attribute (tree *node, tree name,
10143                                     tree args ATTRIBUTE_UNUSED,
10144                                     int flags ATTRIBUTE_UNUSED,
10145                                     bool *no_add_attrs)
10146 {
10147   if (DECL_P (*node))
10148     {
10149       if (TREE_CODE (*node) == TYPE_DECL)
10150           {
10151             /* This is really a decl attribute, not a type attribute,
10152                but try to handle it for GCC 3.0 backwards compatibility.  */
10153 
10154             tree type = TREE_TYPE (*node);
10155             tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
10156             tree newtype = build_type_attribute_variant (type, attr);
10157 
10158             TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
10159             TREE_TYPE (*node) = newtype;
10160             *no_add_attrs = true;
10161           }
10162       else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
10163           {
10164           *no_add_attrs = false;
10165           }
10166       else
10167           {
10168             warning (OPT_Wattributes, "%qE attribute ignored",
10169                        name);
10170             *no_add_attrs = true;
10171           }
10172     }
10173 
10174   return NULL_TREE;
10175 }
10176 
10177 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
10178    struct attribute_spec.handler.  */
10179 
10180 static tree
avr_handle_fndecl_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)10181 avr_handle_fndecl_attribute (tree *node, tree name,
10182                                    tree args ATTRIBUTE_UNUSED,
10183                                    int flags ATTRIBUTE_UNUSED,
10184                                    bool *no_add_attrs)
10185 {
10186   if (TREE_CODE (*node) != FUNCTION_DECL)
10187     {
10188       warning (OPT_Wattributes, "%qE attribute only applies to functions",
10189                  name);
10190       *no_add_attrs = true;
10191     }
10192 
10193   return NULL_TREE;
10194 }
10195 
10196 static tree
avr_handle_fntype_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)10197 avr_handle_fntype_attribute (tree *node, tree name,
10198                              tree args ATTRIBUTE_UNUSED,
10199                              int flags ATTRIBUTE_UNUSED,
10200                              bool *no_add_attrs)
10201 {
10202   if (TREE_CODE (*node) != FUNCTION_TYPE)
10203     {
10204       warning (OPT_Wattributes, "%qE attribute only applies to functions",
10205                  name);
10206       *no_add_attrs = true;
10207     }
10208 
10209   return NULL_TREE;
10210 }
10211 
10212 static tree
avr_handle_absdata_attribute(tree * node,tree name,tree,int,bool * no_add)10213 avr_handle_absdata_attribute (tree *node, tree name, tree /* args */,
10214                               int /* flags */, bool *no_add)
10215 {
10216   location_t loc = DECL_SOURCE_LOCATION (*node);
10217 
10218   if (AVR_TINY)
10219     {
10220       if (TREE_CODE (*node) != VAR_DECL
10221           || (!TREE_STATIC (*node) && !DECL_EXTERNAL (*node)))
10222         {
10223           warning_at (loc, OPT_Wattributes, "%qE attribute only applies to"
10224                       " variables in static storage", name);
10225           *no_add = true;
10226         }
10227     }
10228   else
10229     {
10230       warning_at (loc, OPT_Wattributes, "%qE attribute only supported"
10231                   " for reduced Tiny cores", name);
10232       *no_add = true;
10233     }
10234 
10235   return NULL_TREE;
10236 }
10237 
10238 static tree
avr_handle_addr_attribute(tree * node,tree name,tree args,int flags ATTRIBUTE_UNUSED,bool * no_add)10239 avr_handle_addr_attribute (tree *node, tree name, tree args,
10240                                  int flags ATTRIBUTE_UNUSED, bool *no_add)
10241 {
10242   bool io_p = startswith (IDENTIFIER_POINTER (name), "io");
10243   HOST_WIDE_INT io_start = avr_arch->sfr_offset;
10244   HOST_WIDE_INT io_end = strcmp (IDENTIFIER_POINTER (name), "io_low") == 0
10245     ? io_start + 0x1f
10246     : io_start + 0x3f;
10247   location_t loc = DECL_SOURCE_LOCATION (*node);
10248 
10249   if (!VAR_P (*node))
10250     {
10251       warning_at (loc, OPT_Wattributes, "%qE attribute only applies to "
10252                       "variables", name);
10253       *no_add = true;
10254       return NULL_TREE;
10255     }
10256 
10257   if (args != NULL_TREE)
10258     {
10259       if (TREE_CODE (TREE_VALUE (args)) == NON_LVALUE_EXPR)
10260           TREE_VALUE (args) = TREE_OPERAND (TREE_VALUE (args), 0);
10261       tree arg = TREE_VALUE (args);
10262       if (TREE_CODE (arg) != INTEGER_CST)
10263           {
10264             warning_at (loc, OPT_Wattributes, "%qE attribute allows only an "
10265                           "integer constant argument", name);
10266             *no_add = true;
10267           }
10268       else if (io_p
10269                  && (!tree_fits_shwi_p (arg)
10270                        || ! IN_RANGE (TREE_INT_CST_LOW (arg), io_start, io_end)))
10271           {
10272             warning_at (loc, OPT_Wattributes, "%qE attribute address out of range"
10273                           " 0x%x%s0x%x", name, (int) io_start, "...", (int) io_end);
10274             *no_add = true;
10275           }
10276       else
10277           {
10278             tree attribs = DECL_ATTRIBUTES (*node);
10279             const char *names[] = { "io", "io_low", "address", NULL };
10280             for (const char **p = names; *p; p++)
10281               {
10282                 tree other = lookup_attribute (*p, attribs);
10283                 if (other && TREE_VALUE (other))
10284                     {
10285                       warning_at (loc, OPT_Wattributes,
10286                                     "both %s and %qE attribute provide address",
10287                                     *p, name);
10288                       *no_add = true;
10289                       break;
10290                     }
10291               }
10292           }
10293     }
10294 
10295   if (*no_add == false && io_p && !TREE_THIS_VOLATILE (*node))
10296     warning_at (loc, OPT_Wattributes, "%qE attribute on non-volatile variable",
10297                     name);
10298 
10299   // Optimizers must not draw any conclusions from "static int addr;" etc.
10300   // because the contents of `addr' are not given by its initializer but
10301   // by the contents at the address as specified by the attribute.
10302   if (VAR_P (*node) && ! *no_add)
10303     TREE_THIS_VOLATILE (*node) = 1;
10304 
10305   return NULL_TREE;
10306 }
10307 
10308 rtx
avr_eval_addr_attrib(rtx x)10309 avr_eval_addr_attrib (rtx x)
10310 {
10311   if (SYMBOL_REF_P (x)
10312       && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_ADDRESS))
10313     {
10314       tree decl = SYMBOL_REF_DECL (x);
10315       tree attr = NULL_TREE;
10316 
10317       if (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO)
10318           {
10319             attr = lookup_attribute ("io", DECL_ATTRIBUTES (decl));
10320           if (!attr || !TREE_VALUE (attr))
10321             attr = lookup_attribute ("io_low", DECL_ATTRIBUTES (decl));
10322           }
10323       if (!attr || !TREE_VALUE (attr))
10324           attr = lookup_attribute ("address", DECL_ATTRIBUTES (decl));
10325       gcc_assert (attr && TREE_VALUE (attr) && TREE_VALUE (TREE_VALUE (attr)));
10326       return GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))));
10327     }
10328   return x;
10329 }
10330 
10331 
10332 /* AVR attributes.  */
10333 static const struct attribute_spec avr_attribute_table[] =
10334 {
10335   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
10336        affects_type_identity, handler, exclude } */
10337   { "progmem",   0, 0, false, false, false, false,
10338     avr_handle_progmem_attribute, NULL },
10339   { "signal",    0, 0, true,  false, false, false,
10340     avr_handle_fndecl_attribute, NULL },
10341   { "interrupt", 0, 0, true,  false, false, false,
10342     avr_handle_fndecl_attribute, NULL },
10343   { "no_gccisr", 0, 0, true,  false, false, false,
10344     avr_handle_fndecl_attribute, NULL },
10345   { "naked",     0, 0, false, true,  true,  false,
10346     avr_handle_fntype_attribute, NULL },
10347   { "OS_task",   0, 0, false, true,  true,  false,
10348     avr_handle_fntype_attribute, NULL },
10349   { "OS_main",   0, 0, false, true,  true,  false,
10350     avr_handle_fntype_attribute, NULL },
10351   { "io",        0, 1, true, false, false,  false,
10352     avr_handle_addr_attribute, NULL },
10353   { "io_low",    0, 1, true, false, false,  false,
10354     avr_handle_addr_attribute, NULL },
10355   { "address",   1, 1, true, false, false,  false,
10356     avr_handle_addr_attribute, NULL },
10357   { "absdata",   0, 0, true, false, false,  false,
10358     avr_handle_absdata_attribute, NULL },
10359   { NULL,        0, 0, false, false, false, false, NULL, NULL }
10360 };
10361 
10362 
10363 /* Return true if we support address space AS for the architecture in effect
10364    and false, otherwise.  If LOC is not UNKNOWN_LOCATION then also issue
10365    a respective error.  */
10366 
10367 bool
avr_addr_space_supported_p(addr_space_t as,location_t loc)10368 avr_addr_space_supported_p (addr_space_t as, location_t loc)
10369 {
10370   if (AVR_TINY)
10371     {
10372       if (loc != UNKNOWN_LOCATION)
10373         error_at (loc, "address spaces are not supported for reduced "
10374                   "Tiny devices");
10375       return false;
10376     }
10377   else if (avr_addrspace[as].segment >= avr_n_flash)
10378     {
10379       if (loc != UNKNOWN_LOCATION)
10380         error_at (loc, "address space %qs not supported for devices with "
10381                   "flash size up to %d KiB", avr_addrspace[as].name,
10382                   64 * avr_n_flash);
10383       return false;
10384     }
10385 
10386   return true;
10387 }
10388 
10389 
10390 /* Implement `TARGET_ADDR_SPACE_DIAGNOSE_USAGE'.  */
10391 
10392 static void
avr_addr_space_diagnose_usage(addr_space_t as,location_t loc)10393 avr_addr_space_diagnose_usage (addr_space_t as, location_t loc)
10394 {
10395   (void) avr_addr_space_supported_p (as, loc);
10396 }
10397 
10398 
10399 /* Look if DECL shall be placed in program memory space by
10400    means of attribute `progmem' or some address-space qualifier.
10401    Return non-zero if DECL is data that must end up in Flash and
10402    zero if the data lives in RAM (.bss, .data, .rodata, ...).
10403 
10404    Return 2   if DECL is located in 24-bit flash address-space
10405    Return 1   if DECL is located in 16-bit flash address-space
10406    Return -1  if attribute `progmem' occurs in DECL or ATTRIBUTES
10407    Return 0   otherwise  */
10408 
10409 int
avr_progmem_p(tree decl,tree attributes)10410 avr_progmem_p (tree decl, tree attributes)
10411 {
10412   tree a;
10413 
10414   if (TREE_CODE (decl) != VAR_DECL)
10415     return 0;
10416 
10417   if (avr_decl_memx_p (decl))
10418     return 2;
10419 
10420   if (avr_decl_flash_p (decl))
10421     return 1;
10422 
10423   if (NULL_TREE
10424       != lookup_attribute ("progmem", attributes))
10425     return -1;
10426 
10427   a = decl;
10428 
10429   do
10430     a = TREE_TYPE(a);
10431   while (TREE_CODE (a) == ARRAY_TYPE);
10432 
10433   if (a == error_mark_node)
10434     return 0;
10435 
10436   if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
10437     return -1;
10438 
10439   return 0;
10440 }
10441 
10442 
10443 /* Return true if DECL has attribute `absdata' set.  This function should
10444    only be used for AVR_TINY.  */
10445 
10446 static bool
avr_decl_absdata_p(tree decl,tree attributes)10447 avr_decl_absdata_p (tree decl, tree attributes)
10448 {
10449   return (TREE_CODE (decl) == VAR_DECL
10450           && NULL_TREE != lookup_attribute ("absdata", attributes));
10451 }
10452 
10453 
10454 /* Scan type TYP for pointer references to address space ASn.
10455    Return ADDR_SPACE_GENERIC (i.e. 0) if all pointers targeting
10456    the AS are also declared to be CONST.
10457    Otherwise, return the respective address space, i.e. a value != 0.  */
10458 
10459 static addr_space_t
avr_nonconst_pointer_addrspace(tree typ)10460 avr_nonconst_pointer_addrspace (tree typ)
10461 {
10462   while (ARRAY_TYPE == TREE_CODE (typ))
10463     typ = TREE_TYPE (typ);
10464 
10465   if (POINTER_TYPE_P (typ))
10466     {
10467       addr_space_t as;
10468       tree target = TREE_TYPE (typ);
10469 
10470       /* Pointer to function: Test the function's return type.  */
10471 
10472       if (FUNCTION_TYPE == TREE_CODE (target))
10473         return avr_nonconst_pointer_addrspace (TREE_TYPE (target));
10474 
10475       /* "Ordinary" pointers... */
10476 
10477       while (TREE_CODE (target) == ARRAY_TYPE)
10478         target = TREE_TYPE (target);
10479 
10480       /* Pointers to non-generic address space must be const.  */
10481 
10482       as = TYPE_ADDR_SPACE (target);
10483 
10484       if (!ADDR_SPACE_GENERIC_P (as)
10485           && !TYPE_READONLY (target)
10486           && avr_addr_space_supported_p (as))
10487         {
10488           return as;
10489         }
10490 
10491       /* Scan pointer's target type.  */
10492 
10493       return avr_nonconst_pointer_addrspace (target);
10494     }
10495 
10496   return ADDR_SPACE_GENERIC;
10497 }
10498 
10499 
10500 /* Sanity check NODE so that all pointers targeting non-generic address spaces
10501    go along with CONST qualifier.  Writing to these address spaces should
10502    be detected and complained about as early as possible.  */
10503 
10504 static bool
avr_pgm_check_var_decl(tree node)10505 avr_pgm_check_var_decl (tree node)
10506 {
10507   const char *reason = NULL;
10508 
10509   addr_space_t as = ADDR_SPACE_GENERIC;
10510 
10511   gcc_assert (as == 0);
10512 
10513   if (avr_log.progmem)
10514     avr_edump ("%?: %t\n", node);
10515 
10516   switch (TREE_CODE (node))
10517     {
10518     default:
10519       break;
10520 
10521     case VAR_DECL:
10522       if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
10523         reason = _("variable");
10524       break;
10525 
10526     case PARM_DECL:
10527       if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
10528         reason = _("function parameter");
10529       break;
10530 
10531     case FIELD_DECL:
10532       if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
10533         reason = _("structure field");
10534       break;
10535 
10536     case FUNCTION_DECL:
10537       if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (TREE_TYPE (node))),
10538           as)
10539         reason = _("return type of function");
10540       break;
10541 
10542     case POINTER_TYPE:
10543       if (as = avr_nonconst_pointer_addrspace (node), as)
10544         reason = _("pointer");
10545       break;
10546     }
10547 
10548   if (reason)
10549     {
10550       if (TYPE_P (node))
10551         error ("pointer targeting address space %qs must be const in %qT",
10552                avr_addrspace[as].name, node);
10553       else
10554         error ("pointer targeting address space %qs must be const"
10555                " in %s %q+D",
10556                avr_addrspace[as].name, reason, node);
10557     }
10558 
10559   return reason == NULL;
10560 }
10561 
10562 
10563 /* Implement `TARGET_INSERT_ATTRIBUTES'.  */
10564 
10565 static void
avr_insert_attributes(tree node,tree * attributes)10566 avr_insert_attributes (tree node, tree *attributes)
10567 {
10568   if (VAR_P (node)
10569       && ! TREE_STATIC (node)
10570       && ! DECL_EXTERNAL (node))
10571     {
10572       const char *names[] = { "io", "io_low", "address", NULL };
10573       for (const char **p = names; *p; ++p)
10574           if (lookup_attribute (*p, *attributes))
10575             error ("variable %q+D with attribute %qs must be located in "
10576                      "static storage", node, *p);
10577     }
10578 
10579   avr_pgm_check_var_decl (node);
10580 
10581   if (TARGET_MAIN_IS_OS_TASK
10582       && TREE_CODE (node) == FUNCTION_DECL
10583       && MAIN_NAME_P (DECL_NAME (node))
10584       // FIXME:  We'd like to also test `flag_hosted' which is only
10585       // available in the C-ish fronts, hence no such test for now.
10586       // Instead, we test the return type of "main" which is not exactly
10587       // the same but good enough.
10588       && INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (node)))
10589       && NULL == lookup_attribute ("OS_task", *attributes))
10590     {
10591       *attributes = tree_cons (get_identifier ("OS_task"),
10592                                NULL, *attributes);
10593     }
10594 
10595   /* Add the section attribute if the variable is in progmem.  */
10596 
10597   if (TREE_CODE (node) == VAR_DECL
10598       && (TREE_STATIC (node) || DECL_EXTERNAL (node))
10599       && avr_progmem_p (node, *attributes))
10600     {
10601       addr_space_t as;
10602       tree node0 = node;
10603 
10604       /* For C++, we have to peel arrays in order to get correct
10605          determination of readonlyness.  */
10606 
10607       do
10608         node0 = TREE_TYPE (node0);
10609       while (TREE_CODE (node0) == ARRAY_TYPE);
10610 
10611       if (error_mark_node == node0)
10612         return;
10613 
10614       as = TYPE_ADDR_SPACE (TREE_TYPE (node));
10615 
10616       if (!TYPE_READONLY (node0)
10617           && !TREE_READONLY (node))
10618         {
10619           const char *reason = "__attribute__((progmem))";
10620 
10621           if (!ADDR_SPACE_GENERIC_P (as))
10622             reason = avr_addrspace[as].name;
10623 
10624           if (avr_log.progmem)
10625             avr_edump ("\n%?: %t\n%t\n", node, node0);
10626 
10627           error ("variable %q+D must be const in order to be put into"
10628                  " read-only section by means of %qs", node, reason);
10629         }
10630     }
10631 }
10632 
10633 
10634 /* Implement `ASM_OUTPUT_ALIGNED_DECL_LOCAL'.  */
10635 /* Implement `ASM_OUTPUT_ALIGNED_DECL_COMMON'.  */
10636 /* Track need of __do_clear_bss.  */
10637 
10638 void
avr_asm_output_aligned_decl_common(FILE * stream,tree,const char * name,unsigned HOST_WIDE_INT size,unsigned int align,bool local_p)10639 avr_asm_output_aligned_decl_common (FILE *stream, tree /* decl */,
10640                                             const char *name,
10641                                             unsigned HOST_WIDE_INT size,
10642                                             unsigned int align, bool local_p)
10643 {
10644   /* __gnu_lto_slim is just a marker for the linker injected by toplev.cc.
10645      There is no need to trigger __do_clear_bss code for them.  */
10646 
10647   if (!startswith (name, "__gnu_lto"))
10648     avr_need_clear_bss_p = true;
10649 
10650   if (local_p)
10651     ASM_OUTPUT_ALIGNED_LOCAL (stream, name, size, align);
10652   else
10653     ASM_OUTPUT_ALIGNED_COMMON (stream, name, size, align);
10654 }
10655 
10656 
10657 /* Implement `ASM_OUTPUT_ALIGNED_BSS'.  */
10658 
10659 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))10660 avr_asm_asm_output_aligned_bss (FILE *file, tree decl, const char *name,
10661                                         unsigned HOST_WIDE_INT size, int align,
10662                                         void (*default_func)
10663                                           (FILE *, tree, const char *,
10664                                            unsigned HOST_WIDE_INT, int))
10665 {
10666   if (!startswith (name, "__gnu_lto"))
10667     avr_need_clear_bss_p = true;
10668 
10669   default_func (file, decl, name, size, align);
10670 }
10671 
10672 
10673 /* Unnamed section callback for data_section
10674    to track need of __do_copy_data.  */
10675 
10676 static void
avr_output_data_section_asm_op(const char * data)10677 avr_output_data_section_asm_op (const char *data)
10678 {
10679   avr_need_copy_data_p = true;
10680 
10681   /* Dispatch to default.  */
10682   output_section_asm_op (data);
10683 }
10684 
10685 
10686 /* Unnamed section callback for bss_section
10687    to track need of __do_clear_bss.  */
10688 
10689 static void
avr_output_bss_section_asm_op(const char * data)10690 avr_output_bss_section_asm_op (const char *data)
10691 {
10692   avr_need_clear_bss_p = true;
10693 
10694   /* Dispatch to default.  */
10695   output_section_asm_op (data);
10696 }
10697 
10698 
10699 /* Unnamed section callback for progmem*.data sections.  */
10700 
10701 static void
avr_output_progmem_section_asm_op(const char * data)10702 avr_output_progmem_section_asm_op (const char *data)
10703 {
10704   fprintf (asm_out_file, "\t.section\t%s,\"a\",@progbits\n", data);
10705 }
10706 
10707 
10708 /* A noswitch section callback to output symbol definitions for
10709    attributes "io", "io_low" and "address".  */
10710 
10711 static bool
avr_output_addr_attrib(tree decl,const char * name,unsigned HOST_WIDE_INT,unsigned HOST_WIDE_INT)10712 avr_output_addr_attrib (tree decl, const char *name,
10713                               unsigned HOST_WIDE_INT /* size */,
10714                               unsigned HOST_WIDE_INT /* align */)
10715 {
10716   gcc_assert (DECL_RTL_SET_P (decl));
10717 
10718   FILE *stream = asm_out_file;
10719   bool local_p = ! DECL_WEAK (decl) && ! TREE_PUBLIC (decl);
10720   rtx symbol, mem = DECL_RTL (decl);
10721 
10722   if (mem != NULL_RTX && MEM_P (mem)
10723       && SYMBOL_REF_P ((symbol = XEXP (mem, 0)))
10724       && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
10725     {
10726       if (! local_p)
10727           {
10728             fprintf (stream, "\t%s\t", DECL_WEAK (decl) ? ".weak" : ".globl");
10729             assemble_name (stream, name);
10730             fprintf (stream, "\n");
10731           }
10732 
10733       if (SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS)
10734           {
10735             assemble_name (stream, name);
10736             fprintf (stream, " = %ld\n",
10737                        (long) INTVAL (avr_eval_addr_attrib (symbol)));
10738           }
10739       else if (local_p)
10740           {
10741             const char *names[] = { "io", "io_low", "address", NULL };
10742             for (const char **p = names; *p; ++p)
10743               if (lookup_attribute (*p, DECL_ATTRIBUTES (decl)))
10744                 {
10745                     error ("static attribute %qs declaration for %q+D needs an "
10746                            "address", *p, decl);
10747                     break;
10748                 }
10749           }
10750 
10751       return true;
10752     }
10753 
10754   gcc_unreachable();
10755 
10756   return false;
10757 }
10758 
10759 
10760 /* Implement `TARGET_ASM_INIT_SECTIONS'.  */
10761 
10762 static void
avr_asm_init_sections(void)10763 avr_asm_init_sections (void)
10764 {
10765   /* Override section callbacks to keep track of `avr_need_clear_bss_p'
10766      resp. `avr_need_copy_data_p'.  If flash is not mapped to RAM then
10767      we have also to track .rodata because it is located in RAM then.  */
10768 
10769 #if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
10770   if (avr_arch->flash_pm_offset == 0)
10771 #endif
10772     readonly_data_section->unnamed.callback = avr_output_data_section_asm_op;
10773   data_section->unnamed.callback = avr_output_data_section_asm_op;
10774   bss_section->unnamed.callback = avr_output_bss_section_asm_op;
10775   tls_comm_section->noswitch.callback = avr_output_addr_attrib;
10776 }
10777 
10778 
10779 /* Implement `TARGET_ASM_NAMED_SECTION'.  */
10780 /* Track need of __do_clear_bss, __do_copy_data for named sections.  */
10781 
10782 static void
avr_asm_named_section(const char * name,unsigned int flags,tree decl)10783 avr_asm_named_section (const char *name, unsigned int flags, tree decl)
10784 {
10785   if (flags & AVR_SECTION_PROGMEM)
10786     {
10787       addr_space_t as = (flags & AVR_SECTION_PROGMEM) / SECTION_MACH_DEP;
10788       const char *old_prefix = ".rodata";
10789       const char *new_prefix = avr_addrspace[as].section_name;
10790 
10791       if (startswith (name, old_prefix))
10792         {
10793           const char *sname = ACONCAT ((new_prefix,
10794                                         name + strlen (old_prefix), NULL));
10795           default_elf_asm_named_section (sname, flags, decl);
10796           return;
10797         }
10798 
10799       default_elf_asm_named_section (new_prefix, flags, decl);
10800       return;
10801     }
10802 
10803   if (!avr_need_copy_data_p)
10804     avr_need_copy_data_p = (startswith (name, ".data")
10805                                   || startswith (name, ".gnu.linkonce.d"));
10806 
10807   if (!avr_need_copy_data_p
10808 #if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
10809       && avr_arch->flash_pm_offset == 0
10810 #endif
10811       )
10812     avr_need_copy_data_p = (startswith (name, ".rodata")
10813                                   || startswith (name, ".gnu.linkonce.r"));
10814 
10815   if (!avr_need_clear_bss_p)
10816     avr_need_clear_bss_p = startswith (name, ".bss");
10817 
10818   default_elf_asm_named_section (name, flags, decl);
10819 }
10820 
10821 
10822 /* Implement `TARGET_SECTION_TYPE_FLAGS'.  */
10823 
10824 static unsigned int
avr_section_type_flags(tree decl,const char * name,int reloc)10825 avr_section_type_flags (tree decl, const char *name, int reloc)
10826 {
10827   unsigned int flags = default_section_type_flags (decl, name, reloc);
10828 
10829   if (startswith (name, ".noinit"))
10830     {
10831       if (decl && TREE_CODE (decl) == VAR_DECL
10832             && DECL_INITIAL (decl) == NULL_TREE)
10833           flags |= SECTION_BSS;  /* @nobits */
10834       else
10835           warning (0, "only uninitialized variables can be placed in the "
10836                      "%<.noinit%> section");
10837     }
10838 
10839   if (decl && DECL_P (decl)
10840       && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
10841     {
10842       addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
10843 
10844       /* Attribute progmem puts data in generic address space.
10845          Set section flags as if it was in __flash to get the right
10846          section prefix in the remainder.  */
10847 
10848       if (ADDR_SPACE_GENERIC_P (as))
10849         as = ADDR_SPACE_FLASH;
10850 
10851       flags |= as * SECTION_MACH_DEP;
10852       flags &= ~SECTION_WRITE;
10853       flags &= ~SECTION_BSS;
10854     }
10855 
10856   return flags;
10857 }
10858 
10859 
10860 /* A helper for the next function.  NODE is a decl that is associated with
10861    a symbol.  Return TRUE if the respective object may be accessed by LDS.
10862    There might still be other reasons for why LDS is not appropriate.
10863    This function is only appropriate for AVR_TINY.  */
10864 
10865 static bool
avr_decl_maybe_lds_p(tree node)10866 avr_decl_maybe_lds_p (tree node)
10867 {
10868   if (!node
10869       || TREE_CODE (node) != VAR_DECL
10870       || DECL_SECTION_NAME (node) != NULL)
10871     return false;
10872 
10873   /* Don't use LDS for objects that go to .rodata.  The current default
10874      linker description file still locates .rodata in RAM, but this is not
10875      a must.  A better linker script would just keep .rodata in flash and
10876      add an offset of 0x4000 to the VMA.  Hence avoid LDS for such data.  */
10877 
10878   if (TREE_READONLY (node))
10879     return false;
10880 
10881   // C++ requires peeling arrays.
10882 
10883   do
10884     node = TREE_TYPE (node);
10885   while (ARRAY_TYPE == TREE_CODE (node));
10886 
10887   return (node != error_mark_node
10888           && !TYPE_READONLY (node));
10889 }
10890 
10891 
10892 /* Implement `TARGET_ENCODE_SECTION_INFO'.  */
10893 
10894 static void
avr_encode_section_info(tree decl,rtx rtl,int new_decl_p)10895 avr_encode_section_info (tree decl, rtx rtl, int new_decl_p)
10896 {
10897   tree addr_attr = NULL_TREE;
10898 
10899   /* In avr_handle_progmem_attribute, DECL_INITIAL is not yet
10900      readily available, see PR34734.  So we postpone the warning
10901      about uninitialized data in program memory section until here.  */
10902 
10903   if (new_decl_p
10904       && decl && DECL_P (decl)
10905       && !DECL_EXTERNAL (decl)
10906       && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
10907     {
10908       if (!TREE_READONLY (decl))
10909         {
10910           // This might happen with C++ if stuff needs constructing.
10911           error ("variable %q+D with dynamic initialization put "
10912                  "into program memory area", decl);
10913         }
10914       else if (NULL_TREE == DECL_INITIAL (decl))
10915         {
10916           // Don't warn for (implicit) aliases like in PR80462.
10917           tree asmname = DECL_ASSEMBLER_NAME (decl);
10918           varpool_node *node = varpool_node::get_for_asmname (asmname);
10919           bool alias_p = node && node->alias;
10920 
10921           if (!alias_p)
10922             warning (OPT_Wuninitialized, "uninitialized variable %q+D put "
10923                      "into program memory area", decl);
10924         }
10925     }
10926 
10927   default_encode_section_info (decl, rtl, new_decl_p);
10928 
10929   if (decl && DECL_P (decl)
10930       && TREE_CODE (decl) != FUNCTION_DECL
10931       && MEM_P (rtl)
10932       && SYMBOL_REF_P (XEXP (rtl, 0)))
10933     {
10934       rtx sym = XEXP (rtl, 0);
10935       tree type = TREE_TYPE (decl);
10936       tree attr = DECL_ATTRIBUTES (decl);
10937       if (type == error_mark_node)
10938           return;
10939 
10940       addr_space_t as = TYPE_ADDR_SPACE (type);
10941 
10942       /* PSTR strings are in generic space but located in flash:
10943          patch address space.  */
10944 
10945       if (!AVR_TINY && avr_progmem_p (decl, attr) == -1)
10946         as = ADDR_SPACE_FLASH;
10947 
10948       AVR_SYMBOL_SET_ADDR_SPACE (sym, as);
10949 
10950       tree io_low_attr = lookup_attribute ("io_low", attr);
10951       tree io_attr = lookup_attribute ("io", attr);
10952       tree address_attr = lookup_attribute ("address", attr);
10953 
10954       if (io_low_attr
10955             && TREE_VALUE (io_low_attr) && TREE_VALUE (TREE_VALUE (io_low_attr)))
10956           addr_attr = io_low_attr;
10957       else if (io_attr
10958                  && TREE_VALUE (io_attr) && TREE_VALUE (TREE_VALUE (io_attr)))
10959           addr_attr = io_attr;
10960       else
10961           addr_attr = address_attr;
10962 
10963       if (io_low_attr
10964             || (io_attr && addr_attr
10965               && low_io_address_operand
10966                   (GEN_INT (TREE_INT_CST_LOW
10967                             (TREE_VALUE (TREE_VALUE (addr_attr)))), QImode)))
10968           SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO_LOW;
10969       if (io_attr || io_low_attr)
10970           SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO;
10971       /* If we have an (io) address attribute specification, but the variable
10972            is external, treat the address as only a tentative definition
10973            to be used to determine if an io port is in the lower range, but
10974            don't use the exact value for constant propagation.  */
10975       if (addr_attr && !DECL_EXTERNAL (decl))
10976           SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_ADDRESS;
10977 
10978       if (io_attr || io_low_attr || address_attr)
10979           {
10980             if (DECL_INITIAL (decl))
10981               {
10982                 /* Initializers are not yet parsed in TARGET_INSERT_ATTRIBUTES,
10983                      hence deny initializers now.  The values of symbols with an
10984                      address attribute are determined by the attribute, not by
10985                      some initializer.  */
10986 
10987                 error ("variable %q+D with attribute %qs must not have an "
10988                          "initializer", decl,
10989                          io_low_attr ? "io_low" : io_attr ? "io" : "address");
10990               }
10991             else
10992               {
10993                 /* PR112952: The only way to output a variable declaration in a
10994                      custom manner is by means of a noswitch section callback.
10995                      There are only three noswitch sections: comm_section,
10996                      lcomm_section and tls_comm_section.  And there is no way to
10997                      wire a custom noswitch section to a decl.  As lcomm_section
10998                      is bypassed with -fdata-sections -fno-common, there is no
10999                      other way than making use of tls_comm_section.  As we are
11000                      using that section anyway, also use it in the public case.  */
11001 
11002                 DECL_COMMON (decl) = 1;
11003                 set_decl_section_name (decl, (const char*) nullptr);
11004                 set_decl_tls_model (decl, (tls_model) 2);
11005               }
11006           }
11007     }
11008 
11009   if (AVR_TINY
11010       && decl
11011       && VAR_DECL == TREE_CODE (decl)
11012       && MEM_P (rtl)
11013       && SYMBOL_REF_P (XEXP (rtl, 0)))
11014     {
11015       rtx sym = XEXP (rtl, 0);
11016       bool progmem_p = avr_progmem_p (decl, DECL_ATTRIBUTES (decl)) == -1;
11017 
11018       if (progmem_p)
11019         {
11020           // Tag symbols for addition of 0x4000 (avr_arch->flash_pm_offset).
11021           SYMBOL_REF_FLAGS (sym) |= AVR_SYMBOL_FLAG_TINY_PM;
11022         }
11023 
11024       if (avr_decl_absdata_p (decl, DECL_ATTRIBUTES (decl))
11025           || (TARGET_ABSDATA
11026               && !progmem_p
11027               && !addr_attr
11028               && avr_decl_maybe_lds_p (decl))
11029           || (addr_attr
11030               // If addr_attr is non-null, it has an argument.  Peek into it.
11031               && TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (addr_attr))) < 0xc0))
11032         {
11033           // May be accessed by LDS / STS.
11034           SYMBOL_REF_FLAGS (sym) |= AVR_SYMBOL_FLAG_TINY_ABSDATA;
11035         }
11036 
11037       if (progmem_p
11038           && avr_decl_absdata_p (decl, DECL_ATTRIBUTES (decl)))
11039         {
11040           error ("%q+D has incompatible attributes %qs and %qs",
11041                  decl, "progmem", "absdata");
11042         }
11043     }
11044 }
11045 
11046 
11047 /* Implement `TARGET_ASM_SELECT_SECTION' */
11048 
11049 static section *
avr_asm_select_section(tree decl,int reloc,unsigned HOST_WIDE_INT align)11050 avr_asm_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
11051 {
11052   section * sect = default_elf_select_section (decl, reloc, align);
11053 
11054   if (decl && DECL_P (decl)
11055       && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
11056     {
11057       addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
11058 
11059       /* __progmem__ goes in generic space but shall be allocated to
11060          .progmem.data  */
11061 
11062       if (ADDR_SPACE_GENERIC_P (as))
11063         as = ADDR_SPACE_FLASH;
11064 
11065       if (sect->common.flags & SECTION_NAMED)
11066         {
11067           const char * name = sect->named.name;
11068           const char * old_prefix = ".rodata";
11069           const char * new_prefix = avr_addrspace[as].section_name;
11070 
11071             if (startswith (name, old_prefix))
11072             {
11073               const char *sname = ACONCAT ((new_prefix,
11074                                             name + strlen (old_prefix), NULL));
11075               return get_section (sname,
11076                                   sect->common.flags & ~SECTION_DECLARED,
11077                                   sect->named.decl);
11078             }
11079         }
11080 
11081       if (!progmem_section[as])
11082         {
11083           progmem_section[as]
11084             = get_unnamed_section (0, avr_output_progmem_section_asm_op,
11085                                    avr_addrspace[as].section_name);
11086         }
11087 
11088       return progmem_section[as];
11089     }
11090 
11091   return sect;
11092 }
11093 
11094 /* Implement `TARGET_ASM_FILE_START'.  */
11095 /* Outputs some text at the start of each assembler file.  */
11096 
11097 static void
avr_file_start(void)11098 avr_file_start (void)
11099 {
11100   int sfr_offset = avr_arch->sfr_offset;
11101 
11102   if (avr_arch->asm_only)
11103     error ("architecture %qs supported for assembler only", avr_mmcu);
11104 
11105   default_file_start ();
11106 
11107   /* Print I/O addresses of some SFRs used with IN and OUT.  */
11108 
11109   if (AVR_HAVE_SPH)
11110     fprintf (asm_out_file, "__SP_H__ = 0x%02x\n", avr_addr.sp_h - sfr_offset);
11111 
11112   fprintf (asm_out_file, "__SP_L__ = 0x%02x\n", avr_addr.sp_l - sfr_offset);
11113   fprintf (asm_out_file, "__SREG__ = 0x%02x\n", avr_addr.sreg - sfr_offset);
11114   if (AVR_HAVE_RAMPZ)
11115     fprintf (asm_out_file, "__RAMPZ__ = 0x%02x\n", avr_addr.rampz - sfr_offset);
11116   if (AVR_HAVE_RAMPY)
11117     fprintf (asm_out_file, "__RAMPY__ = 0x%02x\n", avr_addr.rampy - sfr_offset);
11118   if (AVR_HAVE_RAMPX)
11119     fprintf (asm_out_file, "__RAMPX__ = 0x%02x\n", avr_addr.rampx - sfr_offset);
11120   if (AVR_HAVE_RAMPD)
11121     fprintf (asm_out_file, "__RAMPD__ = 0x%02x\n", avr_addr.rampd - sfr_offset);
11122   if (AVR_XMEGA || AVR_TINY)
11123     fprintf (asm_out_file, "__CCP__ = 0x%02x\n", avr_addr.ccp - sfr_offset);
11124   fprintf (asm_out_file, "__tmp_reg__ = %d\n", AVR_TMP_REGNO);
11125   fprintf (asm_out_file, "__zero_reg__ = %d\n", AVR_ZERO_REGNO);
11126 }
11127 
11128 
11129 /* Implement `TARGET_ASM_FILE_END'.  */
11130 /* Outputs to the stdio stream FILE some
11131    appropriate text to go at the end of an assembler file.  */
11132 
11133 static void
avr_file_end(void)11134 avr_file_end (void)
11135 {
11136   /* Output these only if there is anything in the
11137      .data* / .rodata* / .gnu.linkonce.* resp. .bss* or COMMON
11138      input section(s) - some code size can be saved by not
11139      linking in the initialization code from libgcc if resp.
11140      sections are empty, see PR18145.  */
11141 
11142   if (avr_need_copy_data_p)
11143     fputs (".global __do_copy_data\n", asm_out_file);
11144 
11145   if (avr_need_clear_bss_p)
11146     fputs (".global __do_clear_bss\n", asm_out_file);
11147 }
11148 
11149 
11150 /* Worker function for `ADJUST_REG_ALLOC_ORDER'.  */
11151 /* Choose the order in which to allocate hard registers for
11152    pseudo-registers local to a basic block.
11153 
11154    Store the desired register order in the array `reg_alloc_order'.
11155    Element 0 should be the register to allocate first; element 1, the
11156    next register; and so on.  */
11157 
11158 void
avr_adjust_reg_alloc_order(void)11159 avr_adjust_reg_alloc_order (void)
11160 {
11161   static const int order_0[] =
11162     {
11163       24, 25,
11164       18, 19, 20, 21, 22, 23,
11165       30, 31,
11166       26, 27, 28, 29,
11167       17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
11168       0, 1,
11169       32, 33, 34, 35
11170     };
11171   static const int tiny_order_0[] = {
11172     20, 21,
11173     22, 23,
11174     24, 25,
11175     30, 31,
11176     26, 27,
11177     28, 29,
11178     19, 18,
11179     16, 17,
11180     32, 33, 34, 35,
11181     15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
11182   };
11183   static const int order_1[] =
11184     {
11185       18, 19, 20, 21, 22, 23, 24, 25,
11186       30, 31,
11187       26, 27, 28, 29,
11188       17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
11189       0, 1,
11190       32, 33, 34, 35
11191     };
11192   static const int tiny_order_1[] = {
11193     22, 23,
11194     24, 25,
11195     30, 31,
11196     26, 27,
11197     28, 29,
11198     21, 20, 19, 18,
11199     16, 17,
11200     32, 33, 34, 35,
11201     15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
11202   };
11203   static const int order_2[] =
11204     {
11205       25, 24, 23, 22, 21, 20, 19, 18,
11206       30, 31,
11207       26, 27, 28, 29,
11208       17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
11209       1, 0,
11210       32, 33, 34, 35
11211     };
11212 
11213   /* Select specific register allocation order.
11214      Tiny Core (ATtiny4/5/9/10/20/40) devices have only 16 registers,
11215      so different allocation order should be used.  */
11216 
11217   const int *order = (TARGET_ORDER_1 ? (AVR_TINY ? tiny_order_1 : order_1)
11218                       : TARGET_ORDER_2 ? (AVR_TINY ? tiny_order_0 : order_2)
11219                       : (AVR_TINY ? tiny_order_0 : order_0));
11220 
11221   for (size_t i = 0; i < ARRAY_SIZE (order_0); ++i)
11222     reg_alloc_order[i] = order[i];
11223 }
11224 
11225 
11226 /* Implement `TARGET_REGISTER_MOVE_COST' */
11227 
11228 static int
avr_register_move_cost(machine_mode mode ATTRIBUTE_UNUSED,reg_class_t from,reg_class_t to)11229 avr_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
11230                         reg_class_t from, reg_class_t to)
11231 {
11232   return (from == STACK_REG ? 6
11233           : to == STACK_REG ? 12
11234           : 2);
11235 }
11236 
11237 
11238 /* Implement `TARGET_MEMORY_MOVE_COST' */
11239 
11240 static int
avr_memory_move_cost(machine_mode mode,reg_class_t rclass ATTRIBUTE_UNUSED,bool in ATTRIBUTE_UNUSED)11241 avr_memory_move_cost (machine_mode mode,
11242                       reg_class_t rclass ATTRIBUTE_UNUSED,
11243                       bool in ATTRIBUTE_UNUSED)
11244 {
11245   return (mode == QImode ? 2
11246           : mode == HImode ? 4
11247           : mode == SImode ? 8
11248           : mode == SFmode ? 8
11249           : 16);
11250 }
11251 
11252 
11253 /* Cost for mul highpart.  X is a LSHIFTRT, i.e. the outer TRUNCATE is
11254    already stripped off.  */
11255 
11256 static int
avr_mul_highpart_cost(rtx x,int)11257 avr_mul_highpart_cost (rtx x, int)
11258 {
11259   if (AVR_HAVE_MUL
11260       && LSHIFTRT == GET_CODE (x)
11261       && MULT == GET_CODE (XEXP (x, 0))
11262       && CONST_INT_P (XEXP (x, 1)))
11263     {
11264       // This is the wider mode.
11265       machine_mode mode = GET_MODE (x);
11266 
11267       // The middle-end might still have PR81444, i.e. it is calling the cost
11268       // functions with strange modes.  Fix this now by also considering
11269       // PSImode (should actually be SImode instead).
11270       if (HImode == mode || PSImode == mode || SImode == mode)
11271         {
11272           return COSTS_N_INSNS (2);
11273         }
11274     }
11275 
11276   return 10000;
11277 }
11278 
11279 
11280 /* Return the expected cost of a conditional branch like
11281    (set (pc)
11282           (if_then_else (X)
11283                           (label_ref *)
11284                           (pc)))
11285    where X is some comparison operator.  */
11286 
11287 static int
avr_cbranch_cost(rtx x)11288 avr_cbranch_cost (rtx x)
11289 {
11290   bool difficult_p = difficult_comparison_operator (x, VOIDmode);
11291 
11292   if (reload_completed)
11293     {
11294       // After reload, we basically just have plain branches.
11295       return COSTS_N_INSNS (1 + difficult_p);
11296     }
11297 
11298   rtx xreg = XEXP (x, 0);
11299   rtx xval = XEXP (x, 1);
11300   machine_mode mode = GET_MODE (xreg);
11301   if (mode == VOIDmode)
11302     mode = GET_MODE (xval);
11303   int size = GET_MODE_SIZE (mode);
11304 
11305   if (GET_CODE (xreg) == ZERO_EXTEND
11306       || GET_CODE (xval) == ZERO_EXTEND)
11307     {
11308       // *cbranch<HISI:mode>.<code><QIPSI:mode>.0/1, code = zero_extend.
11309       return COSTS_N_INSNS (size + 1);
11310     }
11311 
11312   if (GET_CODE (xreg) == SIGN_EXTEND
11313       || GET_CODE (xval) == SIGN_EXTEND)
11314     {
11315       // *cbranch<HISI:mode>.<code><QIPSI:mode>.0/1, code = sign_extend.
11316       // Make it a bit cheaper than it actually is (less reg pressure).
11317       return COSTS_N_INSNS (size + 1 + 1);
11318     }
11319 
11320   bool reg_p = register_operand (xreg, mode);
11321   bool reg_or_0_p = reg_or_0_operand (xval, mode);
11322 
11323   return COSTS_N_INSNS (size
11324                               // For the branch
11325                               + 1 + difficult_p
11326                               // Combine might propagate constants other than zero
11327                               // into the 2nd operand.  Make that more expensive.
11328                               + 1 * (!reg_p || !reg_or_0_p));
11329 }
11330 
11331 
11332 /* Mutually recursive subroutine of avr_rtx_cost for calculating the
11333    cost of an RTX operand given its context.  X is the rtx of the
11334    operand, MODE is its mode, and OUTER is the rtx_code of this
11335    operand's parent operator.  */
11336 
11337 static int
avr_operand_rtx_cost(rtx x,machine_mode mode,enum rtx_code outer,int opno,bool speed)11338 avr_operand_rtx_cost (rtx x, machine_mode mode, enum rtx_code outer,
11339                           int opno, bool speed)
11340 {
11341   enum rtx_code code = GET_CODE (x);
11342   int total;
11343 
11344   switch (code)
11345     {
11346     case REG:
11347     case SUBREG:
11348       return 0;
11349 
11350     case CONST_INT:
11351     case CONST_FIXED:
11352     case CONST_DOUBLE:
11353       return COSTS_N_INSNS (GET_MODE_SIZE (mode));
11354 
11355     default:
11356       break;
11357     }
11358 
11359   total = 0;
11360   avr_rtx_costs (x, mode, outer, opno, &total, speed);
11361   return total;
11362 }
11363 
11364 /* Worker function for AVR backend's rtx_cost function.
11365    X is rtx expression whose cost is to be calculated.
11366    Return true if the complete cost has been computed.
11367    Return false if subexpressions should be scanned.
11368    In either case, *TOTAL contains the cost result.  */
11369 
11370 static bool
avr_rtx_costs_1(rtx x,machine_mode mode,int outer_code,int opno ATTRIBUTE_UNUSED,int * total,bool speed)11371 avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
11372                  int opno ATTRIBUTE_UNUSED, int *total, bool speed)
11373 {
11374   enum rtx_code code = GET_CODE (x);
11375   HOST_WIDE_INT val;
11376 
11377   switch (code)
11378     {
11379     case CONST_INT:
11380     case CONST_FIXED:
11381     case CONST_DOUBLE:
11382     case SYMBOL_REF:
11383     case CONST:
11384     case LABEL_REF:
11385       /* Immediate constants are as cheap as registers.  */
11386       *total = 0;
11387       return true;
11388 
11389     case MEM:
11390       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
11391       return true;
11392 
11393     case NEG:
11394       switch (mode)
11395           {
11396           case E_QImode:
11397           case E_SFmode:
11398             *total = COSTS_N_INSNS (1);
11399             break;
11400 
11401         case E_HImode:
11402         case E_PSImode:
11403         case E_SImode:
11404           *total = COSTS_N_INSNS (2 * GET_MODE_SIZE (mode) - 1);
11405           break;
11406 
11407           default:
11408             return false;
11409           }
11410       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11411       return true;
11412 
11413     case ABS:
11414       switch (mode)
11415           {
11416           case E_QImode:
11417           case E_SFmode:
11418             *total = COSTS_N_INSNS (1);
11419             break;
11420 
11421           default:
11422             return false;
11423           }
11424       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11425       return true;
11426 
11427     case NOT:
11428       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
11429       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11430       return true;
11431 
11432     case ZERO_EXTEND:
11433       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
11434                                     - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
11435       *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
11436                                               code, 0, speed);
11437       return true;
11438 
11439     case SIGN_EXTEND:
11440       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
11441                                     - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
11442       *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
11443                                               code, 0, speed);
11444       return true;
11445 
11446     case PLUS:
11447       switch (mode)
11448           {
11449           case E_QImode:
11450           if (AVR_HAVE_MUL
11451               && MULT == GET_CODE (XEXP (x, 0))
11452               && register_operand (XEXP (x, 1), QImode))
11453             {
11454               /* multiply-add */
11455               *total = COSTS_N_INSNS (speed ? 4 : 3);
11456               /* multiply-add with constant: will be split and load constant. */
11457               if (CONST_INT_P (XEXP (XEXP (x, 0), 1)))
11458                 *total = COSTS_N_INSNS (1) + *total;
11459               return true;
11460             }
11461             *total = COSTS_N_INSNS (1);
11462             if (!CONST_INT_P (XEXP (x, 1)))
11463               *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
11464             break;
11465 
11466           case E_HImode:
11467           if (AVR_HAVE_MUL
11468               && (MULT == GET_CODE (XEXP (x, 0))
11469                   || ASHIFT == GET_CODE (XEXP (x, 0)))
11470               && register_operand (XEXP (x, 1), HImode)
11471               && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))
11472                   || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))))
11473             {
11474               /* multiply-add */
11475               *total = COSTS_N_INSNS (speed ? 5 : 4);
11476               /* multiply-add with constant: will be split and load constant. */
11477               if (CONST_INT_P (XEXP (XEXP (x, 0), 1)))
11478                 *total = COSTS_N_INSNS (1) + *total;
11479               return true;
11480             }
11481             if (!CONST_INT_P (XEXP (x, 1)))
11482               {
11483                 *total = COSTS_N_INSNS (2);
11484                 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11485                                                         speed);
11486               }
11487             else if (IN_RANGE (INTVAL (XEXP (x, 1)), -63, 63))
11488               *total = COSTS_N_INSNS (1);
11489             else
11490               *total = COSTS_N_INSNS (2);
11491             break;
11492 
11493         case E_PSImode:
11494           if (!CONST_INT_P (XEXP (x, 1)))
11495             {
11496               *total = COSTS_N_INSNS (3);
11497               *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11498                                               speed);
11499             }
11500           else if (IN_RANGE (INTVAL (XEXP (x, 1)), -63, 63))
11501             *total = COSTS_N_INSNS (2);
11502           else
11503             *total = COSTS_N_INSNS (3);
11504           break;
11505 
11506           case E_SImode:
11507             if (!CONST_INT_P (XEXP (x, 1)))
11508               {
11509                 *total = COSTS_N_INSNS (4);
11510                 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11511                                                         speed);
11512               }
11513             else if (IN_RANGE (INTVAL (XEXP (x, 1)), -63, 63))
11514               *total = COSTS_N_INSNS (1);
11515             else
11516               *total = COSTS_N_INSNS (4);
11517             break;
11518 
11519           default:
11520             return false;
11521           }
11522       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11523       return true;
11524 
11525     case MINUS:
11526       if (AVR_HAVE_MUL
11527           && QImode == mode
11528           && register_operand (XEXP (x, 0), QImode)
11529           && MULT == GET_CODE (XEXP (x, 1)))
11530         {
11531           /* multiply-sub */
11532           *total = COSTS_N_INSNS (speed ? 4 : 3);
11533           /* multiply-sub with constant: will be split and load constant. */
11534           if (CONST_INT_P (XEXP (XEXP (x, 1), 1)))
11535             *total = COSTS_N_INSNS (1) + *total;
11536           return true;
11537         }
11538       if (AVR_HAVE_MUL
11539           && HImode == mode
11540           && register_operand (XEXP (x, 0), HImode)
11541           && (MULT == GET_CODE (XEXP (x, 1))
11542               || ASHIFT == GET_CODE (XEXP (x, 1)))
11543           && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))
11544               || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))))
11545         {
11546           /* multiply-sub */
11547           *total = COSTS_N_INSNS (speed ? 5 : 4);
11548           /* multiply-sub with constant: will be split and load constant. */
11549           if (CONST_INT_P (XEXP (XEXP (x, 1), 1)))
11550             *total = COSTS_N_INSNS (1) + *total;
11551           return true;
11552         }
11553       /* FALLTHRU */
11554     case AND:
11555     case IOR:
11556       if (IOR == code
11557           && HImode == mode
11558           && ASHIFT == GET_CODE (XEXP (x, 0)))
11559         {
11560           *total = COSTS_N_INSNS (2);
11561           // Just a rough estimate.  If we see no sign- or zero-extend,
11562           // then increase the cost a little bit.
11563           if (REG_P (XEXP (XEXP (x, 0), 0)))
11564             *total += COSTS_N_INSNS (1);
11565           if (REG_P (XEXP (x, 1)))
11566             *total += COSTS_N_INSNS (1);
11567           return true;
11568         }
11569       if (IOR == code
11570           && AND == GET_CODE (XEXP (x, 0))
11571           && AND == GET_CODE (XEXP (x, 1))
11572           && single_zero_operand (XEXP (XEXP (x, 0), 1), mode))
11573         {
11574           // Open-coded bit transfer.
11575           *total = COSTS_N_INSNS (2);
11576           return true;
11577         }
11578       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
11579       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11580       if (!CONST_INT_P (XEXP (x, 1)))
11581           *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
11582       return true;
11583 
11584     case XOR:
11585       *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
11586       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11587       *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
11588       return true;
11589 
11590     case MULT:
11591       switch (mode)
11592           {
11593           case E_QImode:
11594             if (AVR_HAVE_MUL)
11595               *total = COSTS_N_INSNS (!speed ? 3 : 4);
11596             else if (!speed)
11597               *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
11598             else
11599               return false;
11600             break;
11601 
11602           case E_HImode:
11603             if (AVR_HAVE_MUL)
11604             {
11605               rtx op0 = XEXP (x, 0);
11606               rtx op1 = XEXP (x, 1);
11607               enum rtx_code code0 = GET_CODE (op0);
11608               enum rtx_code code1 = GET_CODE (op1);
11609               bool ex0 = SIGN_EXTEND == code0 || ZERO_EXTEND == code0;
11610               bool ex1 = SIGN_EXTEND == code1 || ZERO_EXTEND == code1;
11611 
11612               if (ex0
11613                   && (u8_operand (op1, HImode)
11614                       || s8_operand (op1, HImode)))
11615                 {
11616                   *total = COSTS_N_INSNS (!speed ? 4 : 6);
11617                   return true;
11618                 }
11619               if (ex0
11620                   && register_operand (op1, HImode))
11621                 {
11622                   *total = COSTS_N_INSNS (!speed ? 5 : 8);
11623                   return true;
11624                 }
11625               else if (ex0 || ex1)
11626                 {
11627                   *total = COSTS_N_INSNS (!speed ? 3 : 5);
11628                   return true;
11629                 }
11630               else if (register_operand (op0, HImode)
11631                        && (u8_operand (op1, HImode)
11632                            || s8_operand (op1, HImode)))
11633                 {
11634                   *total = COSTS_N_INSNS (!speed ? 6 : 9);
11635                   return true;
11636                 }
11637               else
11638                 *total = COSTS_N_INSNS (!speed ? 7 : 10);
11639             }
11640             else if (!speed)
11641               *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
11642             else
11643               return false;
11644             break;
11645 
11646         case E_PSImode:
11647           if (!speed)
11648             *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
11649           else
11650             *total = 10;
11651           break;
11652 
11653           case E_SImode:
11654           case E_DImode:
11655             if (AVR_HAVE_MUL)
11656             {
11657               if (!speed)
11658                 {
11659                   /* Add some additional costs besides CALL like moves etc.  */
11660 
11661                   *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
11662                 }
11663               else
11664                 {
11665                   /* Just a rough estimate.  Even with -O2 we don't want bulky
11666                      code expanded inline.  */
11667 
11668                   *total = COSTS_N_INSNS (25);
11669                 }
11670             }
11671           else
11672             {
11673               if (speed)
11674                 *total = COSTS_N_INSNS (300);
11675               else
11676                 /* Add some additional costs besides CALL like moves etc.  */
11677                 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
11678             }
11679 
11680             if (mode == DImode)
11681               *total *= 2;
11682 
11683             return true;
11684 
11685           default:
11686             return false;
11687           }
11688       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11689       *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
11690       return true;
11691 
11692     case DIV:
11693     case MOD:
11694     case UDIV:
11695     case UMOD:
11696       if (!speed)
11697         *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
11698       else
11699         *total = COSTS_N_INSNS (15 * GET_MODE_SIZE (mode));
11700       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11701       /* For div/mod with const-int divisor we have at least the cost of
11702          loading the divisor. */
11703       if (CONST_INT_P (XEXP (x, 1)))
11704         *total += COSTS_N_INSNS (GET_MODE_SIZE (mode));
11705       /* Add some overall penaly for clobbering and moving around registers */
11706       *total += COSTS_N_INSNS (2);
11707       return true;
11708 
11709     case ROTATE:
11710       switch (mode)
11711           {
11712           case E_QImode:
11713             if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 4)
11714               *total = COSTS_N_INSNS (1);
11715 
11716             break;
11717 
11718           case E_HImode:
11719             if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 8)
11720               *total = COSTS_N_INSNS (3);
11721 
11722             break;
11723 
11724           case E_SImode:
11725             if (CONST_INT_P (XEXP (x, 1)))
11726               switch (INTVAL (XEXP (x, 1)))
11727                 {
11728                 case 8:
11729                 case 24:
11730                     *total = COSTS_N_INSNS (5);
11731                     break;
11732                 case 16:
11733                     *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 6);
11734                     break;
11735                 }
11736             break;
11737 
11738           default:
11739             return false;
11740           }
11741       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11742       return true;
11743 
11744     case ASHIFT:
11745       switch (mode)
11746           {
11747           case E_QImode:
11748             if (!CONST_INT_P (XEXP (x, 1)))
11749               {
11750                 *total = COSTS_N_INSNS (!speed ? 4 : 17);
11751                 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11752                                                         speed);
11753               }
11754             else
11755               {
11756                 val = INTVAL (XEXP (x, 1));
11757                 if (val == 7)
11758                     *total = COSTS_N_INSNS (3);
11759                 else if (val >= 0 && val <= 7)
11760                     *total = COSTS_N_INSNS (val);
11761                 else
11762                     *total = COSTS_N_INSNS (1);
11763               }
11764             break;
11765 
11766           case E_HImode:
11767           if (AVR_HAVE_MUL)
11768             {
11769               if (const_2_to_7_operand (XEXP (x, 1), HImode)
11770                   && (SIGN_EXTEND == GET_CODE (XEXP (x, 0))
11771                       || ZERO_EXTEND == GET_CODE (XEXP (x, 0))))
11772                 {
11773                   *total = COSTS_N_INSNS (!speed ? 4 : 6);
11774                   return true;
11775                 }
11776             }
11777 
11778           if (const1_rtx == (XEXP (x, 1))
11779               && SIGN_EXTEND == GET_CODE (XEXP (x, 0)))
11780             {
11781               *total = COSTS_N_INSNS (2);
11782               return true;
11783             }
11784 
11785             if (!CONST_INT_P (XEXP (x, 1)))
11786               {
11787                 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11788                 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11789                                                         speed);
11790               }
11791             else
11792               switch (INTVAL (XEXP (x, 1)))
11793                 {
11794                 case 0:
11795                     *total = 0;
11796                     break;
11797                 case 1:
11798                 case 8:
11799                     *total = COSTS_N_INSNS (2);
11800                     break;
11801                 case 9:
11802                     *total = COSTS_N_INSNS (3);
11803                     break;
11804                 case 2:
11805                 case 3:
11806                 case 10:
11807                 case 15:
11808                     *total = COSTS_N_INSNS (4);
11809                     break;
11810                 case 7:
11811                 case 11:
11812                 case 12:
11813                     *total = COSTS_N_INSNS (5);
11814                     break;
11815                 case 4:
11816                     *total = COSTS_N_INSNS (!speed ? 5 : 8);
11817                     break;
11818                 case 6:
11819                     *total = COSTS_N_INSNS (!speed ? 5 : 9);
11820                     break;
11821                 case 5:
11822                     *total = COSTS_N_INSNS (!speed ? 5 : 10);
11823                     break;
11824                 default:
11825                   *total = COSTS_N_INSNS (!speed ? 5 : 41);
11826                   *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11827                                                             speed);
11828                 }
11829             break;
11830 
11831         case E_PSImode:
11832           if (!CONST_INT_P (XEXP (x, 1)))
11833             {
11834               *total = COSTS_N_INSNS (!speed ? 6 : 73);
11835             }
11836           else
11837             switch (INTVAL (XEXP (x, 1)))
11838               {
11839               case 0:
11840                 *total = 0;
11841                 break;
11842               case 1:
11843               case 8:
11844               case 16:
11845                 *total = COSTS_N_INSNS (3);
11846                 break;
11847               case 23:
11848                 *total = COSTS_N_INSNS (5);
11849                 break;
11850               default:
11851                 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
11852                 break;
11853               }
11854           break;
11855 
11856           case E_SImode:
11857             if (!CONST_INT_P (XEXP (x, 1)))
11858               {
11859                 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11860                 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11861                                                         speed);
11862               }
11863             else
11864               switch (INTVAL (XEXP (x, 1)))
11865                 {
11866                 case 0:
11867                     *total = 0;
11868                     break;
11869                 case 24:
11870                     *total = COSTS_N_INSNS (3);
11871                     break;
11872                 case 1:
11873                 case 8:
11874                 case 16:
11875                     *total = COSTS_N_INSNS (4);
11876                     break;
11877                 case 31:
11878                     *total = COSTS_N_INSNS (6);
11879                     break;
11880                 case 2:
11881                     *total = COSTS_N_INSNS (!speed ? 7 : 8);
11882                     break;
11883                 default:
11884                     *total = COSTS_N_INSNS (!speed ? 7 : 113);
11885                     *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11886                                                             speed);
11887                 }
11888             break;
11889 
11890           default:
11891             return false;
11892           }
11893       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11894       return true;
11895 
11896     case ASHIFTRT:
11897       switch (mode)
11898           {
11899           case E_QImode:
11900             if (!CONST_INT_P (XEXP (x, 1)))
11901               {
11902                 *total = COSTS_N_INSNS (!speed ? 4 : 17);
11903                 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11904                                                         speed);
11905               }
11906             else
11907               {
11908                 val = INTVAL (XEXP (x, 1));
11909                 if (val == 6)
11910                     *total = COSTS_N_INSNS (4);
11911                 else if (val == 7)
11912                     *total = COSTS_N_INSNS (2);
11913                 else if (val >= 0 && val <= 7)
11914                     *total = COSTS_N_INSNS (val);
11915                 else
11916                     *total = COSTS_N_INSNS (1);
11917               }
11918             break;
11919 
11920           case E_HImode:
11921             if (!CONST_INT_P (XEXP (x, 1)))
11922               {
11923                 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11924                 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11925                                                         speed);
11926               }
11927             else
11928               switch (INTVAL (XEXP (x, 1)))
11929                 {
11930                 case 0:
11931                     *total = 0;
11932                     break;
11933                 case 1:
11934                     *total = COSTS_N_INSNS (2);
11935                     break;
11936                 case 15:
11937                     *total = COSTS_N_INSNS (3);
11938                     break;
11939                 case 2:
11940                 case 7:
11941               case 8:
11942               case 9:
11943                     *total = COSTS_N_INSNS (4);
11944                     break;
11945               case 10:
11946                 case 14:
11947                     *total = COSTS_N_INSNS (5);
11948                     break;
11949               case 11:
11950                 *total = COSTS_N_INSNS (!speed ? 5 : 6);
11951                     break;
11952               case 12:
11953                 *total = COSTS_N_INSNS (!speed ? 5 : 7);
11954                     break;
11955               case 6:
11956                 case 13:
11957                 *total = COSTS_N_INSNS (!speed ? 5 : 8);
11958                     break;
11959                 default:
11960                   *total = COSTS_N_INSNS (!speed ? 5 : 41);
11961                   *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11962                                                             speed);
11963                 }
11964             break;
11965 
11966         case E_PSImode:
11967           if (!CONST_INT_P (XEXP (x, 1)))
11968             {
11969               *total = COSTS_N_INSNS (!speed ? 6 : 73);
11970             }
11971           else
11972             switch (INTVAL (XEXP (x, 1)))
11973               {
11974               case 0:
11975                 *total = 0;
11976                 break;
11977               case 1:
11978                 *total = COSTS_N_INSNS (3);
11979                 break;
11980               case 16:
11981               case 8:
11982                 *total = COSTS_N_INSNS (5);
11983                 break;
11984               case 23:
11985                 *total = COSTS_N_INSNS (4);
11986                 break;
11987               default:
11988                 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
11989                 break;
11990               }
11991           break;
11992 
11993           case E_SImode:
11994             if (!CONST_INT_P (XEXP (x, 1)))
11995               {
11996                 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11997                 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11998                                                         speed);
11999               }
12000             else
12001               switch (INTVAL (XEXP (x, 1)))
12002                 {
12003                 case 0:
12004                     *total = 0;
12005                     break;
12006                 case 1:
12007                     *total = COSTS_N_INSNS (4);
12008                     break;
12009                 case 8:
12010                 case 16:
12011                 case 24:
12012                     *total = COSTS_N_INSNS (6);
12013                     break;
12014                 case 2:
12015                     *total = COSTS_N_INSNS (!speed ? 7 : 8);
12016                     break;
12017                 case 31:
12018                     *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 5);
12019                     break;
12020                 default:
12021                     *total = COSTS_N_INSNS (!speed ? 7 : 113);
12022                     *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
12023                                                             speed);
12024                 }
12025             break;
12026 
12027           default:
12028             return false;
12029           }
12030       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
12031       return true;
12032 
12033     case LSHIFTRT:
12034       if (outer_code == TRUNCATE)
12035         {
12036           *total = avr_mul_highpart_cost (x, speed);
12037           return true;
12038         }
12039 
12040       switch (mode)
12041           {
12042           case E_QImode:
12043             if (!CONST_INT_P (XEXP (x, 1)))
12044               {
12045                 *total = COSTS_N_INSNS (!speed ? 4 : 17);
12046                 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
12047                                                         speed);
12048               }
12049             else
12050               {
12051                 val = INTVAL (XEXP (x, 1));
12052                 if (val == 7)
12053                     *total = COSTS_N_INSNS (3);
12054                 else if (val >= 0 && val <= 7)
12055                     *total = COSTS_N_INSNS (val);
12056                 else
12057                     *total = COSTS_N_INSNS (1);
12058               }
12059             break;
12060 
12061           case E_HImode:
12062             if (!CONST_INT_P (XEXP (x, 1)))
12063               {
12064                 *total = COSTS_N_INSNS (!speed ? 5 : 41);
12065                 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
12066                                                         speed);
12067               }
12068             else
12069               switch (INTVAL (XEXP (x, 1)))
12070                 {
12071                 case 0:
12072                     *total = 0;
12073                     break;
12074                 case 1:
12075                 case 8:
12076                     *total = COSTS_N_INSNS (2);
12077                     break;
12078                 case 9:
12079                     *total = COSTS_N_INSNS (3);
12080                     break;
12081                 case 2:
12082                 case 10:
12083                 case 15:
12084                     *total = COSTS_N_INSNS (4);
12085                     break;
12086                 case 7:
12087               case 11:
12088                     *total = COSTS_N_INSNS (5);
12089                     break;
12090                 case 3:
12091                 case 12:
12092                 case 13:
12093                 case 14:
12094                     *total = COSTS_N_INSNS (!speed ? 5 : 6);
12095                     break;
12096                 case 4:
12097                     *total = COSTS_N_INSNS (!speed ? 5 : 7);
12098                     break;
12099                 case 5:
12100                 case 6:
12101                     *total = COSTS_N_INSNS (!speed ? 5 : 9);
12102                     break;
12103                 default:
12104                   *total = COSTS_N_INSNS (!speed ? 5 : 41);
12105                   *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
12106                                                             speed);
12107                 }
12108             break;
12109 
12110         case E_PSImode:
12111           if (!CONST_INT_P (XEXP (x, 1)))
12112             {
12113               *total = COSTS_N_INSNS (!speed ? 6 : 73);
12114             }
12115           else
12116             switch (INTVAL (XEXP (x, 1)))
12117               {
12118               case 0:
12119                 *total = 0;
12120                 break;
12121               case 1:
12122               case 8:
12123               case 16:
12124                 *total = COSTS_N_INSNS (3);
12125                 break;
12126               case 23:
12127                 *total = COSTS_N_INSNS (5);
12128                 break;
12129               default:
12130                 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
12131                 break;
12132               }
12133           break;
12134 
12135           case E_SImode:
12136             if (!CONST_INT_P (XEXP (x, 1)))
12137               {
12138                 *total = COSTS_N_INSNS (!speed ? 7 : 113);
12139                 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
12140                                                         speed);
12141               }
12142             else
12143               switch (INTVAL (XEXP (x, 1)))
12144                 {
12145                 case 0:
12146                     *total = 0;
12147                     break;
12148                 case 1:
12149                     *total = COSTS_N_INSNS (4);
12150                     break;
12151                 case 2:
12152                     *total = COSTS_N_INSNS (!speed ? 7 : 8);
12153                     break;
12154                 case 8:
12155                 case 16:
12156                 case 24:
12157                     *total = COSTS_N_INSNS (4);
12158                     break;
12159                 case 31:
12160                     *total = COSTS_N_INSNS (6);
12161                     break;
12162                 default:
12163                     *total = COSTS_N_INSNS (!speed ? 7 : 113);
12164                     *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
12165                                                             speed);
12166                 }
12167             break;
12168 
12169           default:
12170             return false;
12171           }
12172       *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
12173       return true;
12174 
12175     case COMPARE:
12176       switch (GET_MODE (XEXP (x, 0)))
12177           {
12178           case E_QImode:
12179             *total = COSTS_N_INSNS (1);
12180             if (!CONST_INT_P (XEXP (x, 1)))
12181               *total += avr_operand_rtx_cost (XEXP (x, 1), QImode, code,
12182                                                       1, speed);
12183             break;
12184 
12185         case E_HImode:
12186             *total = COSTS_N_INSNS (2);
12187             if (!CONST_INT_P (XEXP (x, 1)))
12188             *total += avr_operand_rtx_cost (XEXP (x, 1), HImode, code,
12189                                                       1, speed);
12190             else if (INTVAL (XEXP (x, 1)) != 0)
12191               *total += COSTS_N_INSNS (1);
12192           break;
12193 
12194         case E_PSImode:
12195           *total = COSTS_N_INSNS (3);
12196           if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) != 0)
12197             *total += COSTS_N_INSNS (2);
12198           break;
12199 
12200         case E_SImode:
12201           *total = COSTS_N_INSNS (4);
12202           if (!CONST_INT_P (XEXP (x, 1)))
12203             *total += avr_operand_rtx_cost (XEXP (x, 1), SImode, code,
12204                                                       1, speed);
12205             else if (INTVAL (XEXP (x, 1)) != 0)
12206               *total += COSTS_N_INSNS (3);
12207           break;
12208 
12209           default:
12210             return false;
12211           }
12212       *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
12213                                               code, 0, speed);
12214       return true;
12215 
12216     case TRUNCATE:
12217       if (LSHIFTRT == GET_CODE (XEXP (x, 0)))
12218         {
12219           *total = avr_mul_highpart_cost (XEXP (x, 0), speed);
12220           return true;
12221         }
12222       break;
12223 
12224     case IF_THEN_ELSE:
12225       if (outer_code == SET
12226             && XEXP (x, 2) == pc_rtx
12227             && ordered_comparison_operator (XEXP (x, 0), VOIDmode))
12228           {
12229             *total = avr_cbranch_cost (XEXP (x, 0));
12230             return true;
12231           }
12232 
12233     default:
12234       break;
12235     }
12236   return false;
12237 }
12238 
12239 
12240 /* Implement `TARGET_RTX_COSTS'.  */
12241 
12242 static bool
avr_rtx_costs(rtx x,machine_mode mode,int outer_code,int opno,int * total,bool speed)12243 avr_rtx_costs (rtx x, machine_mode mode, int outer_code,
12244                  int opno, int *total, bool speed)
12245 {
12246   bool done = avr_rtx_costs_1 (x, mode, outer_code, opno, total, speed);
12247 
12248   if (avr_log.rtx_costs)
12249     {
12250       avr_edump ("\n%?=%b (%s) total=%d, outer=%C:\n%r\n",
12251                  done, speed ? "speed" : "size", *total, outer_code, x);
12252     }
12253 
12254   return done;
12255 }
12256 
12257 
12258 /* Implement `TARGET_INSN_COST'.  */
12259 /* For some insns, it is not enough to look at the cost of the SET_SRC.
12260    In that case, have a look at the entire insn, e.g. during insn combine.  */
12261 
12262 static int
avr_insn_cost(rtx_insn * insn,bool speed)12263 avr_insn_cost (rtx_insn *insn, bool speed)
12264 {
12265   const int unknown_cost = -1;
12266   int cost = unknown_cost;
12267 
12268   rtx set = single_set (insn);
12269 
12270   if (set
12271       && ZERO_EXTRACT == GET_CODE (SET_DEST (set)))
12272     {
12273       // Try find anything that would flip the extracted bit.
12274       bool not_bit_p = false;
12275 
12276       subrtx_iterator::array_type array;
12277       FOR_EACH_SUBRTX (iter, array, SET_SRC (set), NONCONST)
12278           {
12279             enum rtx_code code = GET_CODE (*iter);
12280             not_bit_p |= code == NOT || code == XOR || code == GE;
12281           }
12282 
12283       // Don't go too deep into the analysis.  In almost all cases,
12284       // using BLD/BST is the best we can do for single-bit moves,
12285       // even considering CSE.
12286       cost = COSTS_N_INSNS (2 + not_bit_p);
12287     }
12288 
12289   if (cost != unknown_cost)
12290     {
12291       if (avr_log.rtx_costs)
12292           avr_edump ("\n%? (%s) insn_cost=%d\n%r\n",
12293                        speed ? "speed" : "size", cost, insn);
12294       return cost;
12295     }
12296 
12297   // Resort to what rtlanal.cc::insn_cost() implements as a default
12298   // when targetm.insn_cost() is not implemented.
12299 
12300   return pattern_cost (PATTERN (insn), speed);
12301 }
12302 
12303 
12304 /* Implement `TARGET_ADDRESS_COST'.  */
12305 
12306 static int
avr_address_cost(rtx x,machine_mode mode ATTRIBUTE_UNUSED,addr_space_t as ATTRIBUTE_UNUSED,bool speed ATTRIBUTE_UNUSED)12307 avr_address_cost (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
12308                   addr_space_t as ATTRIBUTE_UNUSED,
12309                   bool speed ATTRIBUTE_UNUSED)
12310 {
12311   int cost = 4;
12312 
12313   if (GET_CODE (x) == PLUS
12314       && CONST_INT_P (XEXP (x, 1))
12315       && (REG_P (XEXP (x, 0))
12316           || SUBREG_P (XEXP (x, 0))))
12317     {
12318       if (INTVAL (XEXP (x, 1)) > MAX_LD_OFFSET(mode))
12319         cost = 18;
12320     }
12321   else if (CONSTANT_ADDRESS_P (x))
12322     {
12323       if (io_address_operand (x, QImode))
12324         cost = 2;
12325 
12326       if (AVR_TINY
12327           && avr_address_tiny_absdata_p (x, QImode))
12328         cost = 2;
12329     }
12330 
12331   if (avr_log.address_cost)
12332     avr_edump ("\n%?: %d = %r\n", cost, x);
12333 
12334   return cost;
12335 }
12336 
12337 /* Test for extra memory constraint 'Q'.
12338    It's a memory address based on Y or Z pointer with valid displacement.  */
12339 
12340 int
extra_constraint_Q(rtx x)12341 extra_constraint_Q (rtx x)
12342 {
12343   int ok = 0;
12344   rtx plus = XEXP (x, 0);
12345 
12346   if (GET_CODE (plus) == PLUS
12347       && REG_P (XEXP (plus, 0))
12348       && CONST_INT_P (XEXP (plus, 1))
12349       && (INTVAL (XEXP (plus, 1))
12350             <= MAX_LD_OFFSET (GET_MODE (x))))
12351     {
12352       rtx xx = XEXP (plus, 0);
12353       int regno = REGNO (xx);
12354 
12355       ok = (/* allocate pseudos */
12356             regno >= FIRST_PSEUDO_REGISTER
12357             /* strictly check */
12358             || regno == REG_Z || regno == REG_Y
12359             /* XXX frame & arg pointer checks */
12360             || xx == frame_pointer_rtx
12361             || xx == arg_pointer_rtx);
12362 
12363       if (avr_log.constraints)
12364         avr_edump ("\n%?=%d reload_completed=%d reload_in_progress=%d\n %r\n",
12365                    ok, reload_completed, reload_in_progress, x);
12366     }
12367 
12368   return ok;
12369 }
12370 
12371 /* Convert condition code CONDITION to the valid AVR condition code.  */
12372 
12373 RTX_CODE
avr_normalize_condition(RTX_CODE condition)12374 avr_normalize_condition (RTX_CODE condition)
12375 {
12376   switch (condition)
12377     {
12378     case GT:
12379       return GE;
12380     case GTU:
12381       return GEU;
12382     case LE:
12383       return LT;
12384     case LEU:
12385       return LTU;
12386     default:
12387       gcc_unreachable ();
12388     }
12389 }
12390 
12391 
12392 /* Returns register number for function return value.*/
12393 
12394 static inline unsigned int
avr_ret_register(void)12395 avr_ret_register (void)
12396 {
12397   return 24;
12398 }
12399 
12400 
12401 /* Implement `TARGET_FUNCTION_VALUE_REGNO_P'.  */
12402 
12403 static bool
avr_function_value_regno_p(const unsigned int regno)12404 avr_function_value_regno_p (const unsigned int regno)
12405 {
12406   return (regno == avr_ret_register ());
12407 }
12408 
12409 
12410 /* Implement `TARGET_LIBCALL_VALUE'.  */
12411 /* Create an RTX representing the place where a
12412    library function returns a value of mode MODE.  */
12413 
12414 static rtx
avr_libcall_value(machine_mode mode,const_rtx func ATTRIBUTE_UNUSED)12415 avr_libcall_value (machine_mode mode,
12416                        const_rtx func ATTRIBUTE_UNUSED)
12417 {
12418   int offs = GET_MODE_SIZE (mode);
12419 
12420   if (offs <= 4)
12421     offs = (offs + 1) & ~1;
12422 
12423   return gen_rtx_REG (mode, avr_ret_register () + 2 - offs);
12424 }
12425 
12426 
12427 /* Implement `TARGET_FUNCTION_VALUE'.  */
12428 /* Create an RTX representing the place where a
12429    function returns a value of data type VALTYPE.  */
12430 
12431 static rtx
avr_function_value(const_tree type,const_tree fn_decl_or_type ATTRIBUTE_UNUSED,bool outgoing ATTRIBUTE_UNUSED)12432 avr_function_value (const_tree type,
12433                     const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
12434                     bool outgoing ATTRIBUTE_UNUSED)
12435 {
12436   unsigned int offs;
12437 
12438   if (TYPE_MODE (type) != BLKmode)
12439     return avr_libcall_value (TYPE_MODE (type), NULL_RTX);
12440 
12441   offs = int_size_in_bytes (type);
12442   if (offs < 2)
12443     offs = 2;
12444   if (offs > 2 && offs < GET_MODE_SIZE (SImode))
12445     offs = GET_MODE_SIZE (SImode);
12446   else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
12447     offs = GET_MODE_SIZE (DImode);
12448 
12449   return gen_rtx_REG (BLKmode, avr_ret_register () + 2 - offs);
12450 }
12451 
12452 int
test_hard_reg_class(enum reg_class rclass,rtx x)12453 test_hard_reg_class (enum reg_class rclass, rtx x)
12454 {
12455   int regno = true_regnum (x);
12456   if (regno < 0)
12457     return 0;
12458 
12459   if (TEST_HARD_REG_CLASS (rclass, regno))
12460     return 1;
12461 
12462   return 0;
12463 }
12464 
12465 
12466 /* Helper for jump_over_one_insn_p:  Test if INSN is a 2-word instruction
12467    and thus is suitable to be skipped by CPSE, SBRC, etc.  */
12468 
12469 static bool
avr_2word_insn_p(rtx_insn * insn)12470 avr_2word_insn_p (rtx_insn *insn)
12471 {
12472   if (TARGET_SKIP_BUG || !insn || get_attr_length (insn) != 2)
12473     {
12474       return false;
12475     }
12476 
12477   switch (INSN_CODE (insn))
12478     {
12479     default:
12480       return false;
12481 
12482     case CODE_FOR_movqi_insn:
12483     case CODE_FOR_movuqq_insn:
12484     case CODE_FOR_movqq_insn:
12485       {
12486         rtx set  = single_set (insn);
12487         rtx src  = SET_SRC (set);
12488         rtx dest = SET_DEST (set);
12489 
12490         /* Factor out LDS and STS from movqi_insn.  */
12491 
12492         if (MEM_P (dest)
12493             && (REG_P (src) || src == CONST0_RTX (GET_MODE (dest))))
12494           {
12495             return CONSTANT_ADDRESS_P (XEXP (dest, 0));
12496           }
12497         else if (REG_P (dest)
12498                  && MEM_P (src))
12499           {
12500             return CONSTANT_ADDRESS_P (XEXP (src, 0));
12501           }
12502 
12503         return false;
12504       }
12505 
12506     case CODE_FOR_call_insn:
12507     case CODE_FOR_call_value_insn:
12508       return true;
12509     }
12510 }
12511 
12512 
12513 int
jump_over_one_insn_p(rtx_insn * insn,rtx dest)12514 jump_over_one_insn_p (rtx_insn *insn, rtx dest)
12515 {
12516   int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
12517                           ? XEXP (dest, 0)
12518                           : dest);
12519   int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
12520   int dest_addr = INSN_ADDRESSES (uid);
12521   int jump_offset = dest_addr - jump_addr - get_attr_length (insn);
12522 
12523   return (jump_offset == 1
12524           || (jump_offset == 2
12525               && avr_2word_insn_p (next_active_insn (insn))));
12526 }
12527 
12528 /* Implement TARGET_HARD_REGNO_NREGS. CCmode is four units for historical
12529    reasons. If this hook is not defined, TARGET_HARD_REGNO_NREGS
12530    reports that CCmode requires four registers.
12531    Define this hook to allow CCmode to fit in a single REG_CC. For
12532    other modes and regs, return the number of words in mode (i.e whatever
12533    the default implementation of the hook returned). */
12534 
12535 static unsigned int
avr_hard_regno_nregs(unsigned int regno,machine_mode mode)12536 avr_hard_regno_nregs (unsigned int regno, machine_mode mode)
12537 {
12538   if (regno == REG_CC && mode == CCmode)
12539     return 1;
12540 
12541   return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
12542 }
12543 
12544 
12545 /* Implement TARGET_HARD_REGNO_MODE_OK.  On the enhanced core, anything
12546    larger than 1 byte must start in even numbered register for "movw" to
12547    work (this way we don't have to check for odd registers everywhere).  */
12548 
12549 static bool
avr_hard_regno_mode_ok(unsigned int regno,machine_mode mode)12550 avr_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
12551 {
12552   if (regno == REG_CC)
12553     return mode == CCmode;
12554 
12555   /* NOTE: 8-bit values must not be disallowed for R28 or R29.
12556         Disallowing QI et al. in these regs might lead to code like
12557             (set (subreg:QI (reg:HI 28) n) ...)
12558         which will result in wrong code because reload does not
12559         handle SUBREGs of hard regsisters like this.
12560         This could be fixed in reload.  However, it appears
12561         that fixing reload is not wanted by reload people.  */
12562 
12563   /* Any GENERAL_REGS register can hold 8-bit values.  */
12564 
12565   if (GET_MODE_SIZE (mode) == 1)
12566     return true;
12567 
12568   /* FIXME: Ideally, the following test is not needed.
12569         However, it turned out that it can reduce the number
12570         of spill fails.  AVR and it's poor endowment with
12571         address registers is extreme stress test for reload.  */
12572 
12573   if (GET_MODE_SIZE (mode) >= 4
12574       && regno >= REG_X)
12575     return false;
12576 
12577   /* All modes larger than 8 bits should start in an even register.  */
12578 
12579   return !(regno & 1);
12580 }
12581 
12582 
12583 /* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED.  */
12584 
12585 static bool
avr_hard_regno_call_part_clobbered(unsigned,unsigned regno,machine_mode mode)12586 avr_hard_regno_call_part_clobbered (unsigned, unsigned regno,
12587                                             machine_mode mode)
12588 {
12589   /* FIXME: This hook gets called with MODE:REGNO combinations that don't
12590         represent valid hard registers like, e.g. HI:29.  Returning TRUE
12591         for such registers can lead to performance degradation as mentioned
12592         in PR53595.  Thus, report invalid hard registers as FALSE.  */
12593 
12594   if (!avr_hard_regno_mode_ok (regno, mode))
12595     return 0;
12596 
12597   /* Return true if any of the following boundaries is crossed:
12598      17/18 or 19/20 (if AVR_TINY), 27/28 and 29/30.  */
12599 
12600   return ((regno <= LAST_CALLEE_SAVED_REG
12601            && regno + GET_MODE_SIZE (mode) > 1 + LAST_CALLEE_SAVED_REG)
12602           || (regno < REG_Y && regno + GET_MODE_SIZE (mode) > REG_Y)
12603           || (regno < REG_Z && regno + GET_MODE_SIZE (mode) > REG_Z));
12604 }
12605 
12606 
12607 /* Implement `MODE_CODE_BASE_REG_CLASS'.  */
12608 
12609 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)12610 avr_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED,
12611                               addr_space_t as, RTX_CODE outer_code,
12612                               RTX_CODE index_code ATTRIBUTE_UNUSED)
12613 {
12614   if (!ADDR_SPACE_GENERIC_P (as))
12615     {
12616       return POINTER_Z_REGS;
12617     }
12618 
12619   if (!avr_strict_X)
12620     return reload_completed ? BASE_POINTER_REGS : POINTER_REGS;
12621 
12622   return PLUS == outer_code ? BASE_POINTER_REGS : POINTER_REGS;
12623 }
12624 
12625 
12626 /* Implement `REGNO_MODE_CODE_OK_FOR_BASE_P'.  */
12627 
12628 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)12629 avr_regno_mode_code_ok_for_base_p (int regno,
12630                                    machine_mode mode ATTRIBUTE_UNUSED,
12631                                    addr_space_t as ATTRIBUTE_UNUSED,
12632                                    RTX_CODE outer_code,
12633                                    RTX_CODE index_code ATTRIBUTE_UNUSED)
12634 {
12635   bool ok = false;
12636 
12637   if (!ADDR_SPACE_GENERIC_P (as))
12638     {
12639       if (regno < FIRST_PSEUDO_REGISTER
12640           && regno == REG_Z)
12641         {
12642           return true;
12643         }
12644 
12645       if (reg_renumber)
12646         {
12647           regno = reg_renumber[regno];
12648 
12649           if (regno == REG_Z)
12650             {
12651               return true;
12652             }
12653         }
12654 
12655       return false;
12656     }
12657 
12658   if (regno < FIRST_PSEUDO_REGISTER
12659       && (regno == REG_X
12660           || regno == REG_Y
12661           || regno == REG_Z
12662           || regno == ARG_POINTER_REGNUM))
12663     {
12664       ok = true;
12665     }
12666   else if (reg_renumber)
12667     {
12668       regno = reg_renumber[regno];
12669 
12670       if (regno == REG_X
12671           || regno == REG_Y
12672           || regno == REG_Z
12673           || regno == ARG_POINTER_REGNUM)
12674         {
12675           ok = true;
12676         }
12677     }
12678 
12679   if (avr_strict_X
12680       && PLUS == outer_code
12681       && regno == REG_X)
12682     {
12683       ok = false;
12684     }
12685 
12686   return ok;
12687 }
12688 
12689 
12690 /* A helper for `output_reload_insisf' and `output_reload_inhi'.  */
12691 /* Set 32-bit register OP[0] to compile-time constant OP[1].
12692    CLOBBER_REG is a QI clobber register or NULL_RTX.
12693    LEN == NULL: output instructions.
12694    LEN != NULL: set *LEN to the length of the instruction sequence
12695                 (in words) printed with LEN = NULL.
12696    If CLEAR_P is true, OP[0] had been cleard to Zero already.
12697    If CLEAR_P is false, nothing is known about OP[0].
12698 
12699    The effect on cc0 is as follows:
12700 
12701    Load 0 to any register except ZERO_REG : NONE
12702    Load ld register with any value        : NONE
12703    Anything else:                         : CLOBBER  */
12704 
12705 static void
output_reload_in_const(rtx * op,rtx clobber_reg,int * len,bool clear_p)12706 output_reload_in_const (rtx *op, rtx clobber_reg, int *len, bool clear_p)
12707 {
12708   rtx src = op[1];
12709   rtx dest = op[0];
12710   rtx xval, xdest[4];
12711   int ival[4];
12712   int clobber_val = 1234;
12713   bool cooked_clobber_p = false;
12714   bool set_p = false;
12715   machine_mode mode = GET_MODE (dest);
12716   int n_bytes = GET_MODE_SIZE (mode);
12717 
12718   gcc_assert (REG_P (dest)
12719               && CONSTANT_P (src));
12720 
12721   if (len)
12722     *len = 0;
12723 
12724   /* (REG:SI 14) is special: It's neither in LD_REGS nor in NO_LD_REGS
12725      but has some subregs that are in LD_REGS.  Use the MSB (REG:QI 17).  */
12726 
12727   if (REGNO (dest) < 16
12728       && REGNO (dest) + GET_MODE_SIZE (mode) > 16)
12729     {
12730       clobber_reg = all_regs_rtx[REGNO (dest) + n_bytes - 1];
12731     }
12732 
12733   /* We might need a clobber reg but don't have one.  Look at the value to
12734      be loaded more closely.  A clobber is only needed if it is a symbol
12735      or contains a byte that is neither 0, -1 or a power of 2.  */
12736 
12737   if (NULL_RTX == clobber_reg
12738       && !test_hard_reg_class (LD_REGS, dest)
12739       && (! (CONST_INT_P (src) || CONST_FIXED_P (src) || CONST_DOUBLE_P (src))
12740           || !avr_popcount_each_byte (src, n_bytes,
12741                                       (1 << 0) | (1 << 1) | (1 << 8))))
12742     {
12743       /* We have no clobber register but need one.  Cook one up.
12744          That's cheaper than loading from constant pool.  */
12745 
12746       cooked_clobber_p = true;
12747       clobber_reg = all_regs_rtx[REG_Z + 1];
12748       avr_asm_len ("mov __tmp_reg__,%0", &clobber_reg, len, 1);
12749     }
12750 
12751   /* Now start filling DEST from LSB to MSB.  */
12752 
12753   for (int n = 0; n < n_bytes; n++)
12754     {
12755       int ldreg_p;
12756       bool done_byte = false;
12757       rtx xop[3];
12758 
12759       /* Crop the n-th destination byte.  */
12760 
12761       xdest[n] = simplify_gen_subreg (QImode, dest, mode, n);
12762       ldreg_p = test_hard_reg_class (LD_REGS, xdest[n]);
12763 
12764       if (!CONST_INT_P (src)
12765           && !CONST_FIXED_P (src)
12766           && !CONST_DOUBLE_P (src))
12767         {
12768           static const char* const asm_code[][2] =
12769             {
12770               { "ldi %2,lo8(%1)"  CR_TAB "mov %0,%2",    "ldi %0,lo8(%1)"  },
12771               { "ldi %2,hi8(%1)"  CR_TAB "mov %0,%2",    "ldi %0,hi8(%1)"  },
12772               { "ldi %2,hlo8(%1)" CR_TAB "mov %0,%2",    "ldi %0,hlo8(%1)" },
12773               { "ldi %2,hhi8(%1)" CR_TAB "mov %0,%2",    "ldi %0,hhi8(%1)" }
12774             };
12775 
12776           xop[0] = xdest[n];
12777           xop[1] = src;
12778           xop[2] = clobber_reg;
12779 
12780           avr_asm_len (asm_code[n][ldreg_p], xop, len, ldreg_p ? 1 : 2);
12781 
12782           continue;
12783         }
12784 
12785       /* Crop the n-th source byte.  */
12786 
12787       xval = simplify_gen_subreg (QImode, src, mode, n);
12788       ival[n] = INTVAL (xval);
12789 
12790       /* Look if we can reuse the low word by means of MOVW.  */
12791 
12792       if (n == 2
12793           && n_bytes >= 4
12794           && AVR_HAVE_MOVW)
12795         {
12796           rtx lo16 = simplify_gen_subreg (HImode, src, mode, 0);
12797           rtx hi16 = simplify_gen_subreg (HImode, src, mode, 2);
12798 
12799           if (INTVAL (lo16) == INTVAL (hi16))
12800             {
12801                 if (INTVAL (lo16) != 0 || !clear_p)
12802                     avr_asm_len ("movw %C0,%A0", &op[0], len, 1);
12803 
12804               break;
12805             }
12806         }
12807 
12808       /* Don't use CLR so that cc0 is set as expected.  */
12809 
12810       if (ival[n] == 0)
12811         {
12812           if (!clear_p)
12813             avr_asm_len (ldreg_p ? "ldi %0,0"
12814                          : AVR_ZERO_REGNO == REGNO (xdest[n]) ? "clr %0"
12815                          : "mov %0,__zero_reg__",
12816                          &xdest[n], len, 1);
12817           continue;
12818         }
12819 
12820       if (clobber_val == ival[n]
12821           && REGNO (clobber_reg) == REGNO (xdest[n]))
12822         {
12823           continue;
12824         }
12825 
12826       /* LD_REGS can use LDI to move a constant value */
12827 
12828       if (ldreg_p)
12829         {
12830           xop[0] = xdest[n];
12831           xop[1] = xval;
12832           avr_asm_len ("ldi %0,lo8(%1)", xop, len, 1);
12833           continue;
12834         }
12835 
12836       /* Try to reuse value already loaded in some lower byte. */
12837 
12838       for (int j = 0; j < n; j++)
12839         if (ival[j] == ival[n])
12840           {
12841             xop[0] = xdest[n];
12842             xop[1] = xdest[j];
12843 
12844             avr_asm_len ("mov %0,%1", xop, len, 1);
12845             done_byte = true;
12846             break;
12847           }
12848 
12849       if (done_byte)
12850         continue;
12851 
12852       /* Need no clobber reg for -1: Use CLR/DEC */
12853 
12854       if (ival[n] == -1)
12855         {
12856           if (!clear_p)
12857             avr_asm_len ("clr %0", &xdest[n], len, 1);
12858 
12859           avr_asm_len ("dec %0", &xdest[n], len, 1);
12860           continue;
12861         }
12862       else if (ival[n] == 1)
12863         {
12864           if (!clear_p)
12865             avr_asm_len ("clr %0", &xdest[n], len, 1);
12866 
12867           avr_asm_len ("inc %0", &xdest[n], len, 1);
12868           continue;
12869         }
12870 
12871       /* Use T flag or INC to manage powers of 2 if we have
12872          no clobber reg.  */
12873 
12874       if (NULL_RTX == clobber_reg
12875           && single_one_operand (xval, QImode))
12876         {
12877           xop[0] = xdest[n];
12878           xop[1] = GEN_INT (exact_log2 (ival[n] & GET_MODE_MASK (QImode)));
12879 
12880           gcc_assert (constm1_rtx != xop[1]);
12881 
12882           if (!set_p)
12883             {
12884               set_p = true;
12885               avr_asm_len ("set", xop, len, 1);
12886             }
12887 
12888           if (!clear_p)
12889             avr_asm_len ("clr %0", xop, len, 1);
12890 
12891           avr_asm_len ("bld %0,%1", xop, len, 1);
12892           continue;
12893         }
12894 
12895       /* We actually need the LD_REGS clobber reg.  */
12896 
12897       gcc_assert (NULL_RTX != clobber_reg);
12898 
12899       xop[0] = xdest[n];
12900       xop[1] = xval;
12901       xop[2] = clobber_reg;
12902       clobber_val = ival[n];
12903 
12904       avr_asm_len ("ldi %2,lo8(%1)" CR_TAB
12905                    "mov %0,%2", xop, len, 2);
12906     }
12907 
12908   /* If we cooked up a clobber reg above, restore it.  */
12909 
12910   if (cooked_clobber_p)
12911     {
12912       avr_asm_len ("mov %0,__tmp_reg__", &clobber_reg, len, 1);
12913     }
12914 }
12915 
12916 
12917 /* Reload the constant OP[1] into the HI register OP[0].
12918    CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
12919    into a NO_LD_REGS register.  If CLOBBER_REG is NULL_RTX we either don't
12920    need a clobber reg or have to cook one up.
12921 
12922    PLEN == NULL: Output instructions.
12923    PLEN != NULL: Output nothing.  Set *PLEN to number of words occupied
12924                  by the insns printed.
12925 
12926    Return "".  */
12927 
12928 const char*
output_reload_inhi(rtx * op,rtx clobber_reg,int * plen)12929 output_reload_inhi (rtx *op, rtx clobber_reg, int *plen)
12930 {
12931   output_reload_in_const (op, clobber_reg, plen, false);
12932   return "";
12933 }
12934 
12935 
12936 /* Reload a SI or SF compile time constant OP[1] into the register OP[0].
12937    CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
12938    into a NO_LD_REGS register.  If CLOBBER_REG is NULL_RTX we either don't
12939    need a clobber reg or have to cook one up.
12940 
12941    LEN == NULL: Output instructions.
12942 
12943    LEN != NULL: Output nothing.  Set *LEN to number of words occupied
12944                 by the insns printed.
12945 
12946    Return "".  */
12947 
12948 const char *
output_reload_insisf(rtx * op,rtx clobber_reg,int * len)12949 output_reload_insisf (rtx *op, rtx clobber_reg, int *len)
12950 {
12951   if (AVR_HAVE_MOVW
12952       && !test_hard_reg_class (LD_REGS, op[0])
12953       && (CONST_INT_P (op[1])
12954           || CONST_FIXED_P (op[1])
12955           || CONST_DOUBLE_P (op[1])))
12956     {
12957       int len_clr, len_noclr;
12958 
12959       /* In some cases it is better to clear the destination beforehand, e.g.
12960 
12961              CLR R2   CLR R3   MOVW R4,R2   INC R2
12962 
12963          is shorther than
12964 
12965              CLR R2   INC R2   CLR  R3      CLR R4   CLR R5
12966 
12967          We find it too tedious to work that out in the print function.
12968          Instead, we call the print function twice to get the lengths of
12969          both methods and use the shortest one.  */
12970 
12971       output_reload_in_const (op, clobber_reg, &len_clr, true);
12972       output_reload_in_const (op, clobber_reg, &len_noclr, false);
12973 
12974       if (len_noclr - len_clr == 4)
12975         {
12976           /* Default needs 4 CLR instructions: clear register beforehand.  */
12977 
12978           avr_asm_len ("mov %A0,__zero_reg__" CR_TAB
12979                        "mov %B0,__zero_reg__" CR_TAB
12980                        "movw %C0,%A0", &op[0], len, 3);
12981 
12982           output_reload_in_const (op, clobber_reg, len, true);
12983 
12984           if (len)
12985             *len += 3;
12986 
12987           return "";
12988         }
12989     }
12990 
12991   /* Default: destination not pre-cleared.  */
12992 
12993   output_reload_in_const (op, clobber_reg, len, false);
12994   return "";
12995 }
12996 
12997 const char*
avr_out_reload_inpsi(rtx * op,rtx clobber_reg,int * len)12998 avr_out_reload_inpsi (rtx *op, rtx clobber_reg, int *len)
12999 {
13000   output_reload_in_const (op, clobber_reg, len, false);
13001   return "";
13002 }
13003 
13004 
13005 /* Worker function for `ASM_OUTPUT_ADDR_VEC'.  */
13006 /* Emit jump tables out-of-line so that branches crossing the table
13007    get shorter offsets.  If we have JUMP + CALL, then put the tables
13008    in a dedicated non-.text section so that CALLs get better chance to
13009    be relaxed to RCALLs.
13010 
13011    We emit the tables by hand because `function_rodata_section' does not
13012    work as expected, cf. PR71151, and we do *NOT* want the table to be
13013    in .rodata, hence setting JUMP_TABLES_IN_TEXT_SECTION = 0 is of limited
13014    use; and setting it to 1 attributes table lengths to branch offsets...
13015    Moreover, fincal.c keeps switching section before each table entry
13016    which we find too fragile as to rely on section caching.  */
13017 
13018 void
avr_output_addr_vec(rtx_insn * labl,rtx table)13019 avr_output_addr_vec (rtx_insn *labl, rtx table)
13020 {
13021   FILE *stream = asm_out_file;
13022 
13023   app_disable();
13024 
13025   // Switch to appropriate (sub)section.
13026 
13027   if (DECL_SECTION_NAME (current_function_decl)
13028       && symtab_node::get (current_function_decl)
13029       && ! symtab_node::get (current_function_decl)->implicit_section)
13030     {
13031       // .subsection will emit the code after the function and in the
13032       // section as chosen by the user.
13033 
13034       switch_to_section (current_function_section ());
13035       fprintf (stream, "\t.subsection\t1\n");
13036     }
13037   else
13038     {
13039       // Since PR63223 there is no restriction where to put the table; it
13040       // may even reside above 128 KiB.  We put it in a section as high as
13041       // possible and avoid progmem in order not to waste flash <= 64 KiB.
13042 
13043       const char *sec_name = ".jumptables.gcc";
13044 
13045       // The table belongs to its host function, therefore use fine
13046       // grained sections so that, if that function is removed by
13047       // --gc-sections, the child table(s) may also be removed.  */
13048 
13049       tree asm_name = DECL_ASSEMBLER_NAME (current_function_decl);
13050       const char *fname = IDENTIFIER_POINTER (asm_name);
13051       fname = targetm.strip_name_encoding (fname);
13052       sec_name = ACONCAT ((sec_name, ".", fname, NULL));
13053 
13054       fprintf (stream, "\t.section\t%s,\"%s\",@progbits\n", sec_name,
13055                AVR_HAVE_JMP_CALL ? "a" : "ax");
13056     }
13057 
13058   // Output the label that preceeds the table.
13059 
13060   ASM_OUTPUT_ALIGN (stream, 1);
13061   targetm.asm_out.internal_label (stream, "L", CODE_LABEL_NUMBER (labl));
13062 
13063   // Output the table's content.
13064 
13065   int vlen = XVECLEN (table, 0);
13066 
13067   for (int idx = 0; idx < vlen; idx++)
13068     {
13069       int value = CODE_LABEL_NUMBER (XEXP (XVECEXP (table, 0, idx), 0));
13070 
13071       if (AVR_HAVE_JMP_CALL)
13072         fprintf (stream, "\t.word gs(.L%d)\n", value);
13073       else
13074         fprintf (stream, "\trjmp .L%d\n", value);
13075     }
13076 
13077   // Switch back to original section.  As we clobbered the section above,
13078   // forget the current section before switching back.
13079 
13080   in_section = NULL;
13081   switch_to_section (current_function_section ());
13082 }
13083 
13084 
13085 /* Implement `TARGET_CONDITIONAL_REGISTER_USAGE'.  */
13086 
13087 static void
avr_conditional_register_usage(void)13088 avr_conditional_register_usage (void)
13089 {
13090   if (AVR_TINY)
13091     {
13092       const int tiny_reg_alloc_order[] = {
13093         24, 25,
13094         22, 23,
13095         30, 31,
13096         26, 27,
13097         28, 29,
13098         21, 20, 19, 18,
13099         16, 17,
13100         32, 33, 34, 35,
13101         15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
13102       };
13103 
13104       /* Set R0-R17 as fixed registers. Reset R0-R17 in call used register list
13105          - R0-R15 are not available in Tiny Core devices
13106          - R16 and R17 are fixed registers.  */
13107 
13108       for (size_t i = 0; i <= 17;  i++)
13109         {
13110           fixed_regs[i] = 1;
13111           call_used_regs[i] = 1;
13112         }
13113 
13114       /* Set R18 to R21 as callee saved registers
13115          - R18, R19, R20 and R21 are the callee saved registers in
13116            Tiny Core devices  */
13117 
13118       for (size_t i = 18; i <= LAST_CALLEE_SAVED_REG; i++)
13119         {
13120           call_used_regs[i] = 0;
13121         }
13122 
13123       /* Update register allocation order for Tiny Core devices */
13124 
13125       for (size_t i = 0; i < ARRAY_SIZE (tiny_reg_alloc_order); i++)
13126         {
13127           reg_alloc_order[i] = tiny_reg_alloc_order[i];
13128         }
13129 
13130       CLEAR_HARD_REG_SET (reg_class_contents[(int) ADDW_REGS]);
13131       CLEAR_HARD_REG_SET (reg_class_contents[(int) NO_LD_REGS]);
13132     }
13133 }
13134 
13135 /* Implement `TARGET_HARD_REGNO_SCRATCH_OK'.  */
13136 /* Returns true if SCRATCH are safe to be allocated as a scratch
13137    registers (for a define_peephole2) in the current function.  */
13138 
13139 static bool
avr_hard_regno_scratch_ok(unsigned int regno)13140 avr_hard_regno_scratch_ok (unsigned int regno)
13141 {
13142   /* Interrupt functions can only use registers that have already been saved
13143      by the prologue, even if they would normally be call-clobbered.  */
13144 
13145   if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
13146       && !df_regs_ever_live_p (regno))
13147     return false;
13148 
13149   /* Don't allow hard registers that might be part of the frame pointer.
13150      Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
13151      and don't care for a frame pointer that spans more than one register.  */
13152 
13153   if ((!reload_completed || frame_pointer_needed)
13154       && (regno == REG_Y || regno == REG_Y + 1))
13155     {
13156       return false;
13157     }
13158 
13159   return true;
13160 }
13161 
13162 
13163 /* Worker function for `HARD_REGNO_RENAME_OK'.  */
13164 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG.  */
13165 
13166 int
avr_hard_regno_rename_ok(unsigned int old_reg,unsigned int new_reg)13167 avr_hard_regno_rename_ok (unsigned int old_reg,
13168                                 unsigned int new_reg)
13169 {
13170   /* Interrupt functions can only use registers that have already been
13171      saved by the prologue, even if they would normally be
13172      call-clobbered.  */
13173 
13174   if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
13175       && !df_regs_ever_live_p (new_reg))
13176     return 0;
13177 
13178   /* Don't allow hard registers that might be part of the frame pointer.
13179      Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
13180      and don't care for a frame pointer that spans more than one register.  */
13181 
13182   if ((!reload_completed || frame_pointer_needed)
13183       && (old_reg == REG_Y || old_reg == REG_Y + 1
13184           || new_reg == REG_Y || new_reg == REG_Y + 1))
13185     {
13186       return 0;
13187     }
13188 
13189   return 1;
13190 }
13191 
13192 /* Output a branch that tests a single bit of a register (QI, HI, SI or DImode)
13193    or memory location in the I/O space (QImode only).
13194 
13195    Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
13196    Operand 1: register operand to test, or CONST_INT memory address.
13197    Operand 2: bit number.
13198    Operand 3: label to jump to if the test is true.  */
13199 
13200 const char*
avr_out_sbxx_branch(rtx_insn * insn,rtx operands[])13201 avr_out_sbxx_branch (rtx_insn *insn, rtx operands[])
13202 {
13203   enum rtx_code comp = GET_CODE (operands[0]);
13204   bool long_jump = get_attr_length (insn) >= 4;
13205   bool reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
13206 
13207   if (comp == GE)
13208     comp = EQ;
13209   else if (comp == LT)
13210     comp = NE;
13211 
13212   if (reverse)
13213     comp = reverse_condition (comp);
13214 
13215   switch (GET_CODE (operands[1]))
13216     {
13217     default:
13218       gcc_unreachable();
13219 
13220     case CONST_INT:
13221     case CONST:
13222     case SYMBOL_REF:
13223 
13224       if (low_io_address_operand (operands[1], QImode))
13225         {
13226           if (comp == EQ)
13227             output_asm_insn ("sbis %i1,%2", operands);
13228           else
13229             output_asm_insn ("sbic %i1,%2", operands);
13230         }
13231       else
13232         {
13233             gcc_assert (io_address_operand (operands[1], QImode));
13234           output_asm_insn ("in __tmp_reg__,%i1", operands);
13235           if (comp == EQ)
13236             output_asm_insn ("sbrs __tmp_reg__,%2", operands);
13237           else
13238             output_asm_insn ("sbrc __tmp_reg__,%2", operands);
13239         }
13240 
13241       break; /* CONST_INT */
13242 
13243     case REG:
13244 
13245       if (comp == EQ)
13246         output_asm_insn ("sbrs %T1%T2", operands);
13247       else
13248         output_asm_insn ("sbrc %T1%T2", operands);
13249 
13250       break; /* REG */
13251     }        /* switch */
13252 
13253   if (long_jump)
13254     return ("rjmp .+4" CR_TAB
13255             "jmp %x3");
13256 
13257   if (!reverse)
13258     return "rjmp %x3";
13259 
13260   return "";
13261 }
13262 
13263 /* Worker function for `TARGET_ASM_CONSTRUCTOR'.  */
13264 
13265 static void
avr_asm_out_ctor(rtx symbol,int priority)13266 avr_asm_out_ctor (rtx symbol, int priority)
13267 {
13268   fputs ("\t.global __do_global_ctors\n", asm_out_file);
13269   default_ctor_section_asm_out_constructor (symbol, priority);
13270 }
13271 
13272 
13273 /* Worker function for `TARGET_ASM_DESTRUCTOR'.  */
13274 
13275 static void
avr_asm_out_dtor(rtx symbol,int priority)13276 avr_asm_out_dtor (rtx symbol, int priority)
13277 {
13278   fputs ("\t.global __do_global_dtors\n", asm_out_file);
13279   default_dtor_section_asm_out_destructor (symbol, priority);
13280 }
13281 
13282 
13283 /* Worker function for `TARGET_RETURN_IN_MEMORY'.  */
13284 
13285 static bool
avr_return_in_memory(const_tree type,const_tree fntype ATTRIBUTE_UNUSED)13286 avr_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
13287 {
13288   HOST_WIDE_INT size = int_size_in_bytes (type);
13289   HOST_WIDE_INT ret_size_limit = AVR_TINY ? 4 : 8;
13290 
13291   /* In avr, there are 8 return registers. But, for Tiny Core
13292      (ATtiny4/5/9/10/20/40) devices, only 4 registers are available.
13293      Return true if size is unknown or greater than the limit.  */
13294 
13295   if (size == -1 || size > ret_size_limit)
13296     {
13297       return true;
13298     }
13299   else
13300     {
13301       return false;
13302     }
13303 }
13304 
13305 
13306 /* Implement `CASE_VALUES_THRESHOLD'.  */
13307 /* Supply the default for --param case-values-threshold=0  */
13308 
13309 static unsigned int
avr_case_values_threshold(void)13310 avr_case_values_threshold (void)
13311 {
13312   /* The exact break-even point between a jump table and an if-else tree
13313      depends on several factors not available here like, e.g. if 8-bit
13314      comparisons can be used in the if-else tree or not, on the
13315      range of the case values, if the case value can be reused, on the
13316      register allocation, etc.  '7' appears to be a good choice.  */
13317 
13318   return 7;
13319 }
13320 
13321 
13322 /* Implement `TARGET_ADDR_SPACE_ADDRESS_MODE'.  */
13323 
13324 static scalar_int_mode
avr_addr_space_address_mode(addr_space_t as)13325 avr_addr_space_address_mode (addr_space_t as)
13326 {
13327   return avr_addrspace[as].pointer_size == 3 ? PSImode : HImode;
13328 }
13329 
13330 
13331 /* Implement `TARGET_ADDR_SPACE_POINTER_MODE'.  */
13332 
13333 static scalar_int_mode
avr_addr_space_pointer_mode(addr_space_t as)13334 avr_addr_space_pointer_mode (addr_space_t as)
13335 {
13336   return avr_addr_space_address_mode (as);
13337 }
13338 
13339 
13340 /* Helper for following function.  */
13341 
13342 static bool
avr_reg_ok_for_pgm_addr(rtx reg,bool strict)13343 avr_reg_ok_for_pgm_addr (rtx reg, bool strict)
13344 {
13345   gcc_assert (REG_P (reg));
13346 
13347   if (strict)
13348     {
13349       return REGNO (reg) == REG_Z;
13350     }
13351 
13352   /* Avoid combine to propagate hard regs.  */
13353 
13354   if (can_create_pseudo_p()
13355       && REGNO (reg) < REG_Z)
13356     {
13357       return false;
13358     }
13359 
13360   return true;
13361 }
13362 
13363 
13364 /* Implement `TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P'.  */
13365 
13366 static bool
avr_addr_space_legitimate_address_p(machine_mode mode,rtx x,bool strict,addr_space_t as)13367 avr_addr_space_legitimate_address_p (machine_mode mode, rtx x,
13368                                      bool strict, addr_space_t as)
13369 {
13370   bool ok = false;
13371 
13372   switch (as)
13373     {
13374     default:
13375       gcc_unreachable();
13376 
13377     case ADDR_SPACE_GENERIC:
13378       return avr_legitimate_address_p (mode, x, strict);
13379 
13380     case ADDR_SPACE_FLASH:
13381     case ADDR_SPACE_FLASH1:
13382     case ADDR_SPACE_FLASH2:
13383     case ADDR_SPACE_FLASH3:
13384     case ADDR_SPACE_FLASH4:
13385     case ADDR_SPACE_FLASH5:
13386 
13387       switch (GET_CODE (x))
13388         {
13389         case REG:
13390           ok = avr_reg_ok_for_pgm_addr (x, strict);
13391           break;
13392 
13393         case POST_INC:
13394           ok = avr_reg_ok_for_pgm_addr (XEXP (x, 0), strict);
13395           break;
13396 
13397         default:
13398           break;
13399         }
13400 
13401       break; /* FLASH */
13402 
13403     case ADDR_SPACE_MEMX:
13404       if (REG_P (x))
13405         ok = (!strict
13406               && can_create_pseudo_p());
13407 
13408       if (LO_SUM == GET_CODE (x))
13409         {
13410           rtx hi = XEXP (x, 0);
13411           rtx lo = XEXP (x, 1);
13412 
13413           ok = (REG_P (hi)
13414                 && (!strict || REGNO (hi) < FIRST_PSEUDO_REGISTER)
13415                 && REG_P (lo)
13416                 && REGNO (lo) == REG_Z);
13417         }
13418 
13419       break; /* MEMX */
13420     }
13421 
13422   if (avr_log.legitimate_address_p)
13423     {
13424       avr_edump ("\n%?: ret=%b, mode=%m strict=%d "
13425                  "reload_completed=%d reload_in_progress=%d %s:",
13426                  ok, mode, strict, reload_completed, reload_in_progress,
13427                  reg_renumber ? "(reg_renumber)" : "");
13428 
13429       if (GET_CODE (x) == PLUS
13430           && REG_P (XEXP (x, 0))
13431           && CONST_INT_P (XEXP (x, 1))
13432           && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
13433           && reg_renumber)
13434         {
13435           avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
13436                      true_regnum (XEXP (x, 0)));
13437         }
13438 
13439       avr_edump ("\n%r\n", x);
13440     }
13441 
13442   return ok;
13443 }
13444 
13445 
13446 /* Implement `TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS'.  */
13447 
13448 static rtx
avr_addr_space_legitimize_address(rtx x,rtx old_x,machine_mode mode,addr_space_t as)13449 avr_addr_space_legitimize_address (rtx x, rtx old_x,
13450                                    machine_mode mode, addr_space_t as)
13451 {
13452   if (ADDR_SPACE_GENERIC_P (as))
13453     return avr_legitimize_address (x, old_x, mode);
13454 
13455   if (avr_log.legitimize_address)
13456     {
13457       avr_edump ("\n%?: mode=%m\n %r\n", mode, old_x);
13458     }
13459 
13460   return old_x;
13461 }
13462 
13463 
13464 /* Implement `TARGET_ADDR_SPACE_CONVERT'.  */
13465 
13466 static rtx
avr_addr_space_convert(rtx src,tree type_from,tree type_to)13467 avr_addr_space_convert (rtx src, tree type_from, tree type_to)
13468 {
13469   addr_space_t as_from = TYPE_ADDR_SPACE (TREE_TYPE (type_from));
13470   addr_space_t as_to = TYPE_ADDR_SPACE (TREE_TYPE (type_to));
13471 
13472   if (avr_log.progmem)
13473     avr_edump ("\n%!: op = %r\nfrom = %t\nto = %t\n",
13474                src, type_from, type_to);
13475 
13476   /* Up-casting from 16-bit to 24-bit pointer.  */
13477 
13478   if (as_from != ADDR_SPACE_MEMX
13479       && as_to == ADDR_SPACE_MEMX)
13480     {
13481       int msb;
13482       rtx sym = src;
13483       rtx reg = gen_reg_rtx (PSImode);
13484 
13485       while (CONST == GET_CODE (sym) || PLUS == GET_CODE (sym))
13486         sym = XEXP (sym, 0);
13487 
13488       /* Look at symbol flags:  avr_encode_section_info set the flags
13489          also if attribute progmem was seen so that we get the right
13490          promotion for, e.g. PSTR-like strings that reside in generic space
13491          but are located in flash.  In that case we patch the incoming
13492          address space.  */
13493 
13494       if (SYMBOL_REF_P (sym)
13495           && ADDR_SPACE_FLASH == AVR_SYMBOL_GET_ADDR_SPACE (sym))
13496         {
13497           as_from = ADDR_SPACE_FLASH;
13498         }
13499 
13500       /* Linearize memory: RAM has bit 23 set.  */
13501 
13502       msb = ADDR_SPACE_GENERIC_P (as_from)
13503         ? 0x80
13504         : avr_addrspace[as_from].segment;
13505 
13506       src = force_reg (Pmode, src);
13507 
13508       emit_insn (msb == 0
13509                  ? gen_zero_extendhipsi2 (reg, src)
13510                  : gen_n_extendhipsi2 (reg, gen_int_mode (msb, QImode), src));
13511 
13512       return reg;
13513     }
13514 
13515   /* Down-casting from 24-bit to 16-bit throws away the high byte.  */
13516 
13517   if (as_from == ADDR_SPACE_MEMX
13518       && as_to != ADDR_SPACE_MEMX)
13519     {
13520       rtx new_src = gen_reg_rtx (Pmode);
13521 
13522       src = force_reg (PSImode, src);
13523 
13524       emit_move_insn (new_src,
13525                       simplify_gen_subreg (Pmode, src, PSImode, 0));
13526       return new_src;
13527     }
13528 
13529   return src;
13530 }
13531 
13532 
13533 /* Implement `TARGET_ADDR_SPACE_SUBSET_P'.  */
13534 
13535 static bool
avr_addr_space_subset_p(addr_space_t subset ATTRIBUTE_UNUSED,addr_space_t superset ATTRIBUTE_UNUSED)13536 avr_addr_space_subset_p (addr_space_t subset ATTRIBUTE_UNUSED,
13537                          addr_space_t superset ATTRIBUTE_UNUSED)
13538 {
13539   /* Allow any kind of pointer mess.  */
13540 
13541   return true;
13542 }
13543 
13544 
13545 /* Implement `TARGET_CONVERT_TO_TYPE'.  */
13546 
13547 static tree
avr_convert_to_type(tree type,tree expr)13548 avr_convert_to_type (tree type, tree expr)
13549 {
13550   /* Print a diagnose for pointer conversion that changes the address
13551      space of the pointer target to a non-enclosing address space,
13552      provided -Waddr-space-convert is on.
13553 
13554      FIXME: Filter out cases where the target object is known to
13555             be located in the right memory, like in
13556 
13557                 (const __flash*) PSTR ("text")
13558 
13559             Also try to distinguish between explicit casts requested by
13560             the user and implicit casts like
13561 
13562                 void f (const __flash char*);
13563 
13564                 void g (const char *p)
13565                 {
13566                     f ((const __flash*) p);
13567                 }
13568 
13569             under the assumption that an explicit casts means that the user
13570             knows what he is doing, e.g. interface with PSTR or old style
13571             code with progmem and pgm_read_xxx.
13572   */
13573 
13574   if (avr_warn_addr_space_convert
13575       && expr != error_mark_node
13576       && POINTER_TYPE_P (type)
13577       && POINTER_TYPE_P (TREE_TYPE (expr)))
13578     {
13579       addr_space_t as_old = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (expr)));
13580       addr_space_t as_new = TYPE_ADDR_SPACE (TREE_TYPE (type));
13581 
13582       if (avr_log.progmem)
13583         avr_edump ("%?: type = %t\nexpr = %t\n\n", type, expr);
13584 
13585       if (as_new != ADDR_SPACE_MEMX
13586           && as_new != as_old)
13587         {
13588           location_t loc = EXPR_LOCATION (expr);
13589           const char *name_old = avr_addrspace[as_old].name;
13590           const char *name_new = avr_addrspace[as_new].name;
13591 
13592           warning (OPT_Waddr_space_convert,
13593                    "conversion from address space %qs to address space %qs",
13594                    ADDR_SPACE_GENERIC_P (as_old) ? "generic" : name_old,
13595                    ADDR_SPACE_GENERIC_P (as_new) ? "generic" : name_new);
13596 
13597           return fold_build1_loc (loc, ADDR_SPACE_CONVERT_EXPR, type, expr);
13598         }
13599     }
13600 
13601   return NULL_TREE;
13602 }
13603 
13604 
13605 /* Implement `TARGET_LEGITIMATE_COMBINED_INSN'.  */
13606 
13607 /* PR78883: Filter out paradoxical SUBREGs of MEM which are not handled
13608    properly by following passes.  As INSN_SCHEDULING is off and hence
13609    general_operand accepts such expressions, ditch them now.  */
13610 
13611 static bool
avr_legitimate_combined_insn(rtx_insn * insn)13612 avr_legitimate_combined_insn (rtx_insn *insn)
13613 {
13614   subrtx_iterator::array_type array;
13615 
13616   FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
13617     {
13618       const_rtx op = *iter;
13619 
13620       if (SUBREG_P (op)
13621           && MEM_P (SUBREG_REG (op))
13622           && (GET_MODE_SIZE (GET_MODE (op))
13623               > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))))
13624         {
13625           return false;
13626         }
13627     }
13628 
13629   return true;
13630 }
13631 
13632 
13633 /* PR63633: The middle-end might come up with hard regs as input operands.
13634 
13635    RMASK is a bit mask representing a subset of hard registers R0...R31:
13636    Rn is an element of that set iff bit n of RMASK is set.
13637    OPMASK describes a subset of OP[]:  If bit n of OPMASK is 1 then
13638    OP[n] has to be fixed; otherwise OP[n] is left alone.
13639 
13640    For each element of OPMASK which is a hard register overlapping RMASK,
13641    replace OP[n] with a newly created pseudo register
13642 
13643    HREG == 0:  Also emit a move insn that copies the contents of that
13644                hard register into the new pseudo.
13645 
13646    HREG != 0:  Also set HREG[n] to the hard register.  */
13647 
13648 static void
avr_fix_operands(rtx * op,rtx * hreg,unsigned opmask,unsigned rmask)13649 avr_fix_operands (rtx *op, rtx *hreg, unsigned opmask, unsigned rmask)
13650 {
13651   for (; opmask; opmask >>= 1, op++)
13652     {
13653       rtx reg = *op;
13654 
13655       if (hreg)
13656         *hreg = NULL_RTX;
13657 
13658       if ((opmask & 1)
13659           && REG_P (reg)
13660           && REGNO (reg) < FIRST_PSEUDO_REGISTER
13661           // This hard-reg overlaps other prohibited hard regs?
13662           && (rmask & regmask (GET_MODE (reg), REGNO (reg))))
13663         {
13664           *op = gen_reg_rtx (GET_MODE (reg));
13665           if (hreg == NULL)
13666             emit_move_insn (*op, reg);
13667           else
13668             *hreg = reg;
13669         }
13670 
13671       if (hreg)
13672         hreg++;
13673     }
13674 }
13675 
13676 
13677 void
avr_fix_inputs(rtx * op,unsigned opmask,unsigned rmask)13678 avr_fix_inputs (rtx *op, unsigned opmask, unsigned rmask)
13679 {
13680   avr_fix_operands (op, NULL, opmask, rmask);
13681 }
13682 
13683 
13684 /* Helper for the function below:  If bit n of MASK is set and
13685    HREG[n] != NULL, then emit a move insn to copy OP[n] to HREG[n].
13686    Otherwise do nothing for that n.  Return TRUE.  */
13687 
13688 static bool
avr_move_fixed_operands(rtx * op,rtx * hreg,unsigned mask)13689 avr_move_fixed_operands (rtx *op, rtx *hreg, unsigned mask)
13690 {
13691   for (; mask; mask >>= 1, op++, hreg++)
13692     if ((mask & 1)
13693         && *hreg)
13694       emit_move_insn (*hreg, *op);
13695 
13696   return true;
13697 }
13698 
13699 
13700 /* PR63633: The middle-end might come up with hard regs as output operands.
13701 
13702    GEN is a sequence generating function like gen_mulsi3 with 3 operands OP[].
13703    RMASK is a bit mask representing a subset of hard registers R0...R31:
13704    Rn is an element of that set iff bit n of RMASK is set.
13705    OPMASK describes a subset of OP[]:  If bit n of OPMASK is 1 then
13706    OP[n] has to be fixed; otherwise OP[n] is left alone.
13707 
13708    Emit the insn sequence as generated by GEN() with all elements of OPMASK
13709    which are hard registers overlapping RMASK replaced by newly created
13710    pseudo registers.  After the sequence has been emitted, emit insns that
13711    move the contents of respective pseudos to their hard regs.  */
13712 
13713 bool
avr_emit3_fix_outputs(rtx (* gen)(rtx,rtx,rtx),rtx * op,unsigned opmask,unsigned rmask)13714 avr_emit3_fix_outputs (rtx (*gen)(rtx,rtx,rtx), rtx *op,
13715                        unsigned opmask, unsigned rmask)
13716 {
13717   const int n = 3;
13718   rtx hreg[n];
13719 
13720   /* It is letigimate for GEN to call this function, and in order not to
13721      get self-recursive we use the following static kludge.  This is the
13722      only way not to duplicate all expanders and to avoid ugly and
13723      hard-to-maintain C-code instead of the much more appreciated RTL
13724      representation as supplied by define_expand.  */
13725   static bool lock = false;
13726 
13727   gcc_assert (opmask < (1u << n));
13728 
13729   if (lock)
13730     return false;
13731 
13732   avr_fix_operands (op, hreg, opmask, rmask);
13733 
13734   lock = true;
13735   emit_insn (gen (op[0], op[1], op[2]));
13736   lock = false;
13737 
13738   return avr_move_fixed_operands (op, hreg, opmask);
13739 }
13740 
13741 
13742 /* Worker function for cpymemhi expander.
13743    XOP[0]  Destination as MEM:BLK
13744    XOP[1]  Source      "     "
13745    XOP[2]  # Bytes to copy
13746 
13747    Return TRUE  if the expansion is accomplished.
13748    Return FALSE if the operand compination is not supported.  */
13749 
13750 bool
avr_emit_cpymemhi(rtx * xop)13751 avr_emit_cpymemhi (rtx *xop)
13752 {
13753   HOST_WIDE_INT count;
13754   machine_mode loop_mode;
13755   addr_space_t as = MEM_ADDR_SPACE (xop[1]);
13756   rtx loop_reg, addr1, a_src, a_dest, insn, xas;
13757   rtx a_hi8 = NULL_RTX;
13758 
13759   if (avr_mem_flash_p (xop[0]))
13760     return false;
13761 
13762   if (!CONST_INT_P (xop[2]))
13763     return false;
13764 
13765   count = INTVAL (xop[2]);
13766   if (count <= 0)
13767     return false;
13768 
13769   a_src  = XEXP (xop[1], 0);
13770   a_dest = XEXP (xop[0], 0);
13771 
13772   if (PSImode == GET_MODE (a_src))
13773     {
13774       gcc_assert (as == ADDR_SPACE_MEMX);
13775 
13776       loop_mode = (count < 0x100) ? QImode : HImode;
13777       loop_reg = gen_rtx_REG (loop_mode, 24);
13778       emit_move_insn (loop_reg, gen_int_mode (count, loop_mode));
13779 
13780       addr1 = simplify_gen_subreg (HImode, a_src, PSImode, 0);
13781       a_hi8 = simplify_gen_subreg (QImode, a_src, PSImode, 2);
13782     }
13783   else
13784     {
13785       int segment = avr_addrspace[as].segment;
13786 
13787       if (segment
13788           && avr_n_flash > 1)
13789         {
13790           a_hi8 = GEN_INT (segment);
13791           emit_move_insn (rampz_rtx, a_hi8 = copy_to_mode_reg (QImode, a_hi8));
13792         }
13793       else if (!ADDR_SPACE_GENERIC_P (as))
13794         {
13795           as = ADDR_SPACE_FLASH;
13796         }
13797 
13798       addr1 = a_src;
13799 
13800       loop_mode = (count <= 0x100) ? QImode : HImode;
13801       loop_reg = copy_to_mode_reg (loop_mode, gen_int_mode (count, loop_mode));
13802     }
13803 
13804   xas = GEN_INT (as);
13805 
13806   /* FIXME: Register allocator might come up with spill fails if it is left
13807         on its own.  Thus, we allocate the pointer registers by hand:
13808         Z = source address
13809         X = destination address  */
13810 
13811   emit_move_insn (lpm_addr_reg_rtx, addr1);
13812   emit_move_insn (gen_rtx_REG (HImode, REG_X), a_dest);
13813 
13814   /* FIXME: Register allocator does a bad job and might spill address
13815         register(s) inside the loop leading to additional move instruction
13816         to/from stack which could clobber tmp_reg.  Thus, do *not* emit
13817         load and store as separate insns.  Instead, we perform the copy
13818         by means of one monolithic insn.  */
13819 
13820   gcc_assert (TMP_REGNO == LPM_REGNO);
13821 
13822   if (as != ADDR_SPACE_MEMX)
13823     {
13824       /* Load instruction ([E]LPM or LD) is known at compile time:
13825          Do the copy-loop inline.  */
13826 
13827       rtx (*fun) (rtx, rtx, rtx)
13828         = QImode == loop_mode ? gen_cpymem_qi : gen_cpymem_hi;
13829 
13830       insn = fun (xas, loop_reg, loop_reg);
13831     }
13832   else
13833     {
13834       rtx (*fun) (rtx, rtx)
13835         = QImode == loop_mode ? gen_cpymemx_qi : gen_cpymemx_hi;
13836 
13837       emit_move_insn (gen_rtx_REG (QImode, 23), a_hi8);
13838 
13839       insn = fun (xas, GEN_INT (avr_addr.rampz));
13840     }
13841 
13842   set_mem_addr_space (SET_SRC (XVECEXP (insn, 0, 0)), as);
13843   emit_insn (insn);
13844 
13845   return true;
13846 }
13847 
13848 
13849 /* Print assembler for cpymem_qi, cpymem_hi insns...
13850        $0     : Address Space
13851        $1, $2 : Loop register
13852        Z      : Source address
13853        X      : Destination address
13854 */
13855 
13856 const char*
avr_out_cpymem(rtx_insn * insn ATTRIBUTE_UNUSED,rtx * op,int * plen)13857 avr_out_cpymem (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
13858 {
13859   addr_space_t as = (addr_space_t) INTVAL (op[0]);
13860   machine_mode loop_mode = GET_MODE (op[1]);
13861   bool sbiw_p = test_hard_reg_class (ADDW_REGS, op[1]);
13862   rtx xop[3];
13863 
13864   if (plen)
13865     *plen = 0;
13866 
13867   xop[0] = op[0];
13868   xop[1] = op[1];
13869   xop[2] = tmp_reg_rtx;
13870 
13871   /* Loop label */
13872 
13873   avr_asm_len ("0:", xop, plen, 0);
13874 
13875   /* Load with post-increment */
13876 
13877   switch (as)
13878     {
13879     default:
13880       gcc_unreachable();
13881 
13882     case ADDR_SPACE_GENERIC:
13883 
13884       avr_asm_len ("ld %2,Z+", xop, plen, 1);
13885       break;
13886 
13887     case ADDR_SPACE_FLASH:
13888 
13889       if (AVR_HAVE_LPMX)
13890         avr_asm_len ("lpm %2,Z+", xop, plen, 1);
13891       else
13892         avr_asm_len ("lpm" CR_TAB
13893                      "adiw r30,1", xop, plen, 2);
13894       break;
13895 
13896     case ADDR_SPACE_FLASH1:
13897     case ADDR_SPACE_FLASH2:
13898     case ADDR_SPACE_FLASH3:
13899     case ADDR_SPACE_FLASH4:
13900     case ADDR_SPACE_FLASH5:
13901 
13902       if (AVR_HAVE_ELPMX)
13903         avr_asm_len ("elpm %2,Z+", xop, plen, 1);
13904       else
13905         avr_asm_len ("elpm" CR_TAB
13906                      "adiw r30,1", xop, plen, 2);
13907       break;
13908     }
13909 
13910   /* Store with post-increment */
13911 
13912   avr_asm_len ("st X+,%2", xop, plen, 1);
13913 
13914   /* Decrement loop-counter and set Z-flag */
13915 
13916   if (QImode == loop_mode)
13917     {
13918       avr_asm_len ("dec %1", xop, plen, 1);
13919     }
13920   else if (sbiw_p)
13921     {
13922       avr_asm_len ("sbiw %1,1", xop, plen, 1);
13923     }
13924   else
13925     {
13926       avr_asm_len ("subi %A1,1" CR_TAB
13927                    "sbci %B1,0", xop, plen, 2);
13928     }
13929 
13930   /* Loop until zero */
13931 
13932   return avr_asm_len ("brne 0b", xop, plen, 1);
13933 }
13934 
13935 
13936 
13937 /* Helper for __builtin_avr_delay_cycles */
13938 
13939 static rtx
avr_mem_clobber(void)13940 avr_mem_clobber (void)
13941 {
13942   rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
13943   MEM_VOLATILE_P (mem) = 1;
13944   return mem;
13945 }
13946 
13947 static void
avr_expand_delay_cycles(rtx operands0)13948 avr_expand_delay_cycles (rtx operands0)
13949 {
13950   unsigned HOST_WIDE_INT cycles = UINTVAL (operands0) & GET_MODE_MASK (SImode);
13951   unsigned HOST_WIDE_INT cycles_used;
13952   unsigned HOST_WIDE_INT loop_count;
13953 
13954   if (IN_RANGE (cycles, 83886082, 0xFFFFFFFF))
13955     {
13956       loop_count = ((cycles - 9) / 6) + 1;
13957       cycles_used = ((loop_count - 1) * 6) + 9;
13958       emit_insn (gen_delay_cycles_4 (gen_int_mode (loop_count, SImode),
13959                                      avr_mem_clobber()));
13960       cycles -= cycles_used;
13961     }
13962 
13963   if (IN_RANGE (cycles, 262145, 83886081))
13964     {
13965       loop_count = ((cycles - 7) / 5) + 1;
13966       if (loop_count > 0xFFFFFF)
13967         loop_count = 0xFFFFFF;
13968       cycles_used = ((loop_count - 1) * 5) + 7;
13969       emit_insn (gen_delay_cycles_3 (gen_int_mode (loop_count, SImode),
13970                                      avr_mem_clobber()));
13971       cycles -= cycles_used;
13972     }
13973 
13974   if (IN_RANGE (cycles, 768, 262144))
13975     {
13976       loop_count = ((cycles - 5) / 4) + 1;
13977       if (loop_count > 0xFFFF)
13978         loop_count = 0xFFFF;
13979       cycles_used = ((loop_count - 1) * 4) + 5;
13980       emit_insn (gen_delay_cycles_2 (gen_int_mode (loop_count, HImode),
13981                                      avr_mem_clobber()));
13982       cycles -= cycles_used;
13983     }
13984 
13985   if (IN_RANGE (cycles, 6, 767))
13986     {
13987       loop_count = cycles / 3;
13988       if (loop_count > 255)
13989         loop_count = 255;
13990       cycles_used = loop_count * 3;
13991       emit_insn (gen_delay_cycles_1 (gen_int_mode (loop_count, QImode),
13992                                      avr_mem_clobber()));
13993       cycles -= cycles_used;
13994     }
13995 
13996   while (cycles >= 2)
13997     {
13998       emit_insn (gen_nopv (GEN_INT (2)));
13999       cycles -= 2;
14000     }
14001 
14002   if (cycles == 1)
14003     {
14004       emit_insn (gen_nopv (GEN_INT (1)));
14005       cycles--;
14006     }
14007 }
14008 
14009 
14010 static void
avr_expand_nops(rtx operands0)14011 avr_expand_nops (rtx operands0)
14012 {
14013   unsigned HOST_WIDE_INT n_nops = UINTVAL (operands0) & GET_MODE_MASK (HImode);
14014 
14015   while (n_nops--)
14016     {
14017       emit_insn (gen_nopv (const1_rtx));
14018     }
14019 }
14020 
14021 
14022 /* Compute the image of x under f, i.e. perform   x --> f(x)    */
14023 
14024 static int
avr_map(unsigned int f,int x)14025 avr_map (unsigned int f, int x)
14026 {
14027   return x < 8 ? (f >> (4 * x)) & 0xf : 0;
14028 }
14029 
14030 
14031 /* Return some metrics of map A.  */
14032 
14033 enum
14034   {
14035     /* Number of fixed points in { 0 ... 7 } */
14036     MAP_FIXED_0_7,
14037 
14038     /* Size of preimage of non-fixed points in { 0 ... 7 } */
14039     MAP_NONFIXED_0_7,
14040 
14041     /* Mask representing the fixed points in { 0 ... 7 } */
14042     MAP_MASK_FIXED_0_7,
14043 
14044     /* Size of the preimage of { 0 ... 7 } */
14045     MAP_PREIMAGE_0_7,
14046 
14047     /* Mask that represents the preimage of { f } */
14048     MAP_MASK_PREIMAGE_F
14049   };
14050 
14051 static unsigned
avr_map_metric(unsigned int a,int mode)14052 avr_map_metric (unsigned int a, int mode)
14053 {
14054   unsigned metric = 0;
14055 
14056   for (unsigned i = 0; i < 8; i++)
14057     {
14058       unsigned ai = avr_map (a, i);
14059 
14060       if (mode == MAP_FIXED_0_7)
14061         metric += ai == i;
14062       else if (mode == MAP_NONFIXED_0_7)
14063         metric += ai < 8 && ai != i;
14064       else if (mode == MAP_MASK_FIXED_0_7)
14065         metric |= ((unsigned) (ai == i)) << i;
14066       else if (mode == MAP_PREIMAGE_0_7)
14067         metric += ai < 8;
14068       else if (mode == MAP_MASK_PREIMAGE_F)
14069         metric |= ((unsigned) (ai == 0xf)) << i;
14070       else
14071         gcc_unreachable();
14072     }
14073 
14074   return metric;
14075 }
14076 
14077 
14078 /* Return true if IVAL has a 0xf in its hexadecimal representation
14079    and false, otherwise.  Only nibbles 0..7 are taken into account.
14080    Used as constraint helper for C0f and Cxf.  */
14081 
14082 bool
avr_has_nibble_0xf(rtx ival)14083 avr_has_nibble_0xf (rtx ival)
14084 {
14085   unsigned int map = UINTVAL (ival) & GET_MODE_MASK (SImode);
14086   return avr_map_metric (map, MAP_MASK_PREIMAGE_F) != 0;
14087 }
14088 
14089 
14090 /* We have a set of bits that are mapped by a function F.
14091    Try to decompose F by means of a second function G so that
14092 
14093       F = F o G^-1 o G
14094 
14095    and
14096 
14097       cost (F o G^-1) + cost (G)  <  cost (F)
14098 
14099    Example:  Suppose builtin insert_bits supplies us with the map
14100    F = 0x3210ffff.  Instead of doing 4 bit insertions to get the high
14101    nibble of the result, we can just as well rotate the bits before inserting
14102    them and use the map 0x7654ffff which is cheaper than the original map.
14103    For this example G = G^-1 = 0x32107654 and F o G^-1 = 0x7654ffff.  */
14104 
14105 typedef struct
14106 {
14107   /* tree code of binary function G */
14108   enum tree_code code;
14109 
14110   /* The constant second argument of G */
14111   int arg;
14112 
14113   /* G^-1, the inverse of G (*, arg) */
14114   unsigned ginv;
14115 
14116   /* The cost of applying G (*, arg) */
14117   int cost;
14118 
14119   /* The composition F o G^-1 (*, arg) for some function F */
14120   unsigned int map;
14121 
14122   /* For debug purpose only */
14123   const char *str;
14124 } avr_map_op_t;
14125 
14126 static const avr_map_op_t avr_map_op[] =
14127   {
14128     { LROTATE_EXPR, 0, 0x76543210, 0, 0, "id" },
14129     { LROTATE_EXPR, 1, 0x07654321, 2, 0, "<<<" },
14130     { LROTATE_EXPR, 2, 0x10765432, 4, 0, "<<<" },
14131     { LROTATE_EXPR, 3, 0x21076543, 4, 0, "<<<" },
14132     { LROTATE_EXPR, 4, 0x32107654, 1, 0, "<<<" },
14133     { LROTATE_EXPR, 5, 0x43210765, 3, 0, "<<<" },
14134     { LROTATE_EXPR, 6, 0x54321076, 5, 0, "<<<" },
14135     { LROTATE_EXPR, 7, 0x65432107, 3, 0, "<<<" },
14136     { RSHIFT_EXPR, 1, 0x6543210c, 1, 0, ">>" },
14137     { RSHIFT_EXPR, 1, 0x7543210c, 1, 0, ">>" },
14138     { RSHIFT_EXPR, 2, 0x543210cc, 2, 0, ">>" },
14139     { RSHIFT_EXPR, 2, 0x643210cc, 2, 0, ">>" },
14140     { RSHIFT_EXPR, 2, 0x743210cc, 2, 0, ">>" },
14141     { LSHIFT_EXPR, 1, 0xc7654321, 1, 0, "<<" },
14142     { LSHIFT_EXPR, 2, 0xcc765432, 2, 0, "<<" }
14143   };
14144 
14145 
14146 /* Try to decompose F as F = (F o G^-1) o G as described above.
14147    The result is a struct representing F o G^-1 and G.
14148    If result.cost < 0 then such a decomposition does not exist.  */
14149 
14150 static avr_map_op_t
avr_map_decompose(unsigned int f,const avr_map_op_t * g,bool val_const_p)14151 avr_map_decompose (unsigned int f, const avr_map_op_t *g, bool val_const_p)
14152 {
14153   bool val_used_p = avr_map_metric (f, MAP_MASK_PREIMAGE_F) != 0;
14154   avr_map_op_t f_ginv = *g;
14155   unsigned int ginv = g->ginv;
14156 
14157   f_ginv.cost = -1;
14158 
14159   /* Step 1:  Computing F o G^-1  */
14160 
14161   for (int i = 7; i >= 0; i--)
14162     {
14163       int x = avr_map (f, i);
14164 
14165       if (x <= 7)
14166         {
14167           x = avr_map (ginv, x);
14168 
14169           /* The bit is no element of the image of G: no avail (cost = -1)  */
14170 
14171           if (x > 7)
14172             return f_ginv;
14173         }
14174 
14175       f_ginv.map = (f_ginv.map << 4) + x;
14176     }
14177 
14178   /* Step 2:  Compute the cost of the operations.
14179      The overall cost of doing an operation prior to the insertion is
14180       the cost of the insertion plus the cost of the operation.  */
14181 
14182   /* Step 2a:  Compute cost of F o G^-1  */
14183 
14184   if (avr_map_metric (f_ginv.map, MAP_NONFIXED_0_7) == 0)
14185     /* The mapping consists only of fixed points and can be folded
14186        to AND/OR logic in the remainder.  Reasonable cost is 3. */
14187     f_ginv.cost = 2 + (val_used_p && !val_const_p);
14188   else
14189     {
14190       rtx xop[4];
14191 
14192       /* Get the cost of the insn by calling the output worker with some
14193          fake values.  Mimic effect of reloading xop[3]: Unused operands
14194          are mapped to 0 and used operands are reloaded to xop[0].  */
14195 
14196       xop[0] = all_regs_rtx[24];
14197       xop[1] = gen_int_mode (f_ginv.map, SImode);
14198       xop[2] = all_regs_rtx[25];
14199       xop[3] = val_used_p ? xop[0] : const0_rtx;
14200 
14201       avr_out_insert_bits (xop, &f_ginv.cost);
14202 
14203       f_ginv.cost += val_const_p && val_used_p ? 1 : 0;
14204     }
14205 
14206   /* Step 2b:  Add cost of G  */
14207 
14208   f_ginv.cost += g->cost;
14209 
14210   if (avr_log.builtin)
14211     avr_edump (" %s%d=%d", g->str, g->arg, f_ginv.cost);
14212 
14213   return f_ginv;
14214 }
14215 
14216 
14217 /* Insert bits from XOP[1] into XOP[0] according to MAP.
14218    XOP[0] and XOP[1] don't overlap.
14219    If FIXP_P = true:  Move all bits according to MAP using BLD/BST sequences.
14220    If FIXP_P = false: Just move the bit if its position in the destination
14221    is different to its source position.  */
14222 
14223 static void
avr_move_bits(rtx * xop,unsigned int map,bool fixp_p,int * plen)14224 avr_move_bits (rtx *xop, unsigned int map, bool fixp_p, int *plen)
14225 {
14226   /* T-flag contains this bit of the source, i.e. of XOP[1]  */
14227   int t_bit_src = -1;
14228 
14229   /* We order the operations according to the requested source bit b.  */
14230 
14231   for (int b = 0; b < 8; b++)
14232     for (int bit_dest = 0; bit_dest < 8; bit_dest++)
14233       {
14234         int bit_src = avr_map (map, bit_dest);
14235 
14236         if (b != bit_src
14237             || bit_src >= 8
14238             /* Same position: No need to copy as requested by FIXP_P.  */
14239             || (bit_dest == bit_src && !fixp_p))
14240           continue;
14241 
14242         if (t_bit_src != bit_src)
14243           {
14244             /* Source bit is not yet in T: Store it to T.  */
14245 
14246             t_bit_src = bit_src;
14247 
14248             xop[3] = GEN_INT (bit_src);
14249             avr_asm_len ("bst %T1%T3", xop, plen, 1);
14250           }
14251 
14252         /* Load destination bit with T.  */
14253 
14254         xop[3] = GEN_INT (bit_dest);
14255         avr_asm_len ("bld %T0%T3", xop, plen, 1);
14256       }
14257 }
14258 
14259 
14260 /* PLEN == 0: Print assembler code for `insert_bits'.
14261    PLEN != 0: Compute code length in bytes.
14262 
14263    OP[0]:  Result
14264    OP[1]:  The mapping composed of nibbles. If nibble no. N is
14265            0:   Bit N of result is copied from bit OP[2].0
14266            ...  ...
14267            7:   Bit N of result is copied from bit OP[2].7
14268            0xf: Bit N of result is copied from bit OP[3].N
14269    OP[2]:  Bits to be inserted
14270    OP[3]:  Target value  */
14271 
14272 const char*
avr_out_insert_bits(rtx * op,int * plen)14273 avr_out_insert_bits (rtx *op, int *plen)
14274 {
14275   unsigned int map = UINTVAL (op[1]) & GET_MODE_MASK (SImode);
14276   unsigned mask_fixed;
14277   bool fixp_p = true;
14278   rtx xop[4];
14279 
14280   xop[0] = op[0];
14281   xop[1] = op[2];
14282   xop[2] = op[3];
14283 
14284   gcc_assert (REG_P (xop[2]) || CONST_INT_P (xop[2]));
14285 
14286   if (plen)
14287     *plen = 0;
14288   else if (flag_print_asm_name)
14289     fprintf (asm_out_file, ASM_COMMENT_START "map = 0x%08x\n", map);
14290 
14291   /* If MAP has fixed points it might be better to initialize the result
14292      with the bits to be inserted instead of moving all bits by hand.  */
14293 
14294   mask_fixed = avr_map_metric (map, MAP_MASK_FIXED_0_7);
14295 
14296   if (REGNO (xop[0]) == REGNO (xop[1]))
14297     {
14298       /* Avoid early-clobber conflicts */
14299 
14300       avr_asm_len ("mov __tmp_reg__,%1", xop, plen, 1);
14301       xop[1] = tmp_reg_rtx;
14302       fixp_p = false;
14303     }
14304 
14305   if (avr_map_metric (map, MAP_MASK_PREIMAGE_F))
14306     {
14307       /* XOP[2] is used and reloaded to XOP[0] already */
14308 
14309       int n_fix = 0, n_nofix = 0;
14310 
14311       gcc_assert (REG_P (xop[2]));
14312 
14313       /* Get the code size of the bit insertions; once with all bits
14314          moved and once with fixed points omitted.  */
14315 
14316       avr_move_bits (xop, map, true, &n_fix);
14317       avr_move_bits (xop, map, false, &n_nofix);
14318 
14319       if (fixp_p && n_fix - n_nofix > 3)
14320         {
14321           xop[3] = gen_int_mode (~mask_fixed, QImode);
14322 
14323           avr_asm_len ("eor %0,%1"   CR_TAB
14324                        "andi %0,%3"  CR_TAB
14325                        "eor %0,%1", xop, plen, 3);
14326           fixp_p = false;
14327         }
14328     }
14329   else
14330     {
14331       /* XOP[2] is unused */
14332 
14333       if (fixp_p && mask_fixed)
14334         {
14335           avr_asm_len ("mov %0,%1", xop, plen, 1);
14336           fixp_p = false;
14337         }
14338     }
14339 
14340   /* Move/insert remaining bits.  */
14341 
14342   avr_move_bits (xop, map, fixp_p, plen);
14343 
14344   return "";
14345 }
14346 
14347 
14348 /* IDs for all the AVR builtins.  */
14349 
14350 enum avr_builtin_id
14351   {
14352 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME)  \
14353     AVR_BUILTIN_ ## NAME,
14354 #include "builtins.def"
14355 #undef DEF_BUILTIN
14356 
14357     AVR_BUILTIN_COUNT
14358   };
14359 
14360 struct GTY(()) avr_builtin_description
14361 {
14362   enum insn_code icode;
14363   int n_args;
14364   tree fndecl;
14365 };
14366 
14367 
14368 /* Notice that avr_bdesc[] and avr_builtin_id are initialized in such a way
14369    that a built-in's ID can be used to access the built-in by means of
14370    avr_bdesc[ID]  */
14371 
14372 static GTY(()) struct avr_builtin_description
14373 avr_bdesc[AVR_BUILTIN_COUNT] =
14374   {
14375 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE, LIBNAME)         \
14376     { (enum insn_code) CODE_FOR_ ## ICODE, N_ARGS, NULL_TREE },
14377 #include "builtins.def"
14378 #undef DEF_BUILTIN
14379   };
14380 
14381 
14382 /* Implement `TARGET_BUILTIN_DECL'.  */
14383 
14384 static tree
avr_builtin_decl(unsigned id,bool initialize_p ATTRIBUTE_UNUSED)14385 avr_builtin_decl (unsigned id, bool initialize_p ATTRIBUTE_UNUSED)
14386 {
14387   if (id < AVR_BUILTIN_COUNT)
14388     return avr_bdesc[id].fndecl;
14389 
14390   return error_mark_node;
14391 }
14392 
14393 
14394 static void
avr_init_builtin_int24(void)14395 avr_init_builtin_int24 (void)
14396 {
14397   tree int24_type  = make_signed_type (GET_MODE_BITSIZE (PSImode));
14398   tree uint24_type = make_unsigned_type (GET_MODE_BITSIZE (PSImode));
14399 
14400   lang_hooks.types.register_builtin_type (int24_type, "__int24");
14401   lang_hooks.types.register_builtin_type (uint24_type, "__uint24");
14402 }
14403 
14404 
14405 /* Implement `TARGET_INIT_BUILTINS' */
14406 /* Set up all builtin functions for this target.  */
14407 
14408 static void
avr_init_builtins(void)14409 avr_init_builtins (void)
14410 {
14411   tree void_ftype_void
14412     = build_function_type_list (void_type_node, NULL_TREE);
14413   tree uchar_ftype_uchar
14414     = build_function_type_list (unsigned_char_type_node,
14415                                 unsigned_char_type_node,
14416                                 NULL_TREE);
14417   tree uint_ftype_uchar_uchar
14418     = build_function_type_list (unsigned_type_node,
14419                                 unsigned_char_type_node,
14420                                 unsigned_char_type_node,
14421                                 NULL_TREE);
14422   tree int_ftype_char_char
14423     = build_function_type_list (integer_type_node,
14424                                 char_type_node,
14425                                 char_type_node,
14426                                 NULL_TREE);
14427   tree int_ftype_char_uchar
14428     = build_function_type_list (integer_type_node,
14429                                 char_type_node,
14430                                 unsigned_char_type_node,
14431                                 NULL_TREE);
14432   tree void_ftype_ulong
14433     = build_function_type_list (void_type_node,
14434                                 long_unsigned_type_node,
14435                                 NULL_TREE);
14436 
14437   tree uchar_ftype_ulong_uchar_uchar
14438     = build_function_type_list (unsigned_char_type_node,
14439                                 long_unsigned_type_node,
14440                                 unsigned_char_type_node,
14441                                 unsigned_char_type_node,
14442                                 NULL_TREE);
14443 
14444   tree const_memx_void_node
14445     = build_qualified_type (void_type_node,
14446                             TYPE_QUAL_CONST
14447                             | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_MEMX));
14448 
14449   tree const_memx_ptr_type_node
14450     = build_pointer_type_for_mode (const_memx_void_node, PSImode, false);
14451 
14452   tree char_ftype_const_memx_ptr
14453     = build_function_type_list (char_type_node,
14454                                 const_memx_ptr_type_node,
14455                                 NULL);
14456 
14457 #define ITYP(T)                                                         \
14458   lang_hooks.types.type_for_size (TYPE_PRECISION (T), TYPE_UNSIGNED (T))
14459 
14460 #define FX_FTYPE_FX(fx)                                                 \
14461   tree fx##r_ftype_##fx##r                                              \
14462     = build_function_type_list (node_##fx##r, node_##fx##r, NULL);      \
14463   tree fx##k_ftype_##fx##k                                              \
14464     = build_function_type_list (node_##fx##k, node_##fx##k, NULL)
14465 
14466 #define FX_FTYPE_FX_INT(fx)                                             \
14467   tree fx##r_ftype_##fx##r_int                                          \
14468     = build_function_type_list (node_##fx##r, node_##fx##r,             \
14469                                 integer_type_node, NULL);               \
14470   tree fx##k_ftype_##fx##k_int                                          \
14471     = build_function_type_list (node_##fx##k, node_##fx##k,             \
14472                                 integer_type_node, NULL)
14473 
14474 #define INT_FTYPE_FX(fx)                                                \
14475   tree int_ftype_##fx##r                                                \
14476     = build_function_type_list (integer_type_node, node_##fx##r, NULL); \
14477   tree int_ftype_##fx##k                                                \
14478     = build_function_type_list (integer_type_node, node_##fx##k, NULL)
14479 
14480 #define INTX_FTYPE_FX(fx)                                               \
14481   tree int##fx##r_ftype_##fx##r                                         \
14482     = build_function_type_list (ITYP (node_##fx##r), node_##fx##r, NULL); \
14483   tree int##fx##k_ftype_##fx##k                                         \
14484     = build_function_type_list (ITYP (node_##fx##k), node_##fx##k, NULL)
14485 
14486 #define FX_FTYPE_INTX(fx)                                               \
14487   tree fx##r_ftype_int##fx##r                                           \
14488     = build_function_type_list (node_##fx##r, ITYP (node_##fx##r), NULL); \
14489   tree fx##k_ftype_int##fx##k                                           \
14490     = build_function_type_list (node_##fx##k, ITYP (node_##fx##k), NULL)
14491 
14492   tree node_hr = short_fract_type_node;
14493   tree node_nr = fract_type_node;
14494   tree node_lr = long_fract_type_node;
14495   tree node_llr = long_long_fract_type_node;
14496 
14497   tree node_uhr = unsigned_short_fract_type_node;
14498   tree node_unr = unsigned_fract_type_node;
14499   tree node_ulr = unsigned_long_fract_type_node;
14500   tree node_ullr = unsigned_long_long_fract_type_node;
14501 
14502   tree node_hk = short_accum_type_node;
14503   tree node_nk = accum_type_node;
14504   tree node_lk = long_accum_type_node;
14505   tree node_llk = long_long_accum_type_node;
14506 
14507   tree node_uhk = unsigned_short_accum_type_node;
14508   tree node_unk = unsigned_accum_type_node;
14509   tree node_ulk = unsigned_long_accum_type_node;
14510   tree node_ullk = unsigned_long_long_accum_type_node;
14511 
14512 
14513   /* For absfx builtins.  */
14514 
14515   FX_FTYPE_FX (h);
14516   FX_FTYPE_FX (n);
14517   FX_FTYPE_FX (l);
14518   FX_FTYPE_FX (ll);
14519 
14520   /* For roundfx builtins.  */
14521 
14522   FX_FTYPE_FX_INT (h);
14523   FX_FTYPE_FX_INT (n);
14524   FX_FTYPE_FX_INT (l);
14525   FX_FTYPE_FX_INT (ll);
14526 
14527   FX_FTYPE_FX_INT (uh);
14528   FX_FTYPE_FX_INT (un);
14529   FX_FTYPE_FX_INT (ul);
14530   FX_FTYPE_FX_INT (ull);
14531 
14532   /* For countlsfx builtins.  */
14533 
14534   INT_FTYPE_FX (h);
14535   INT_FTYPE_FX (n);
14536   INT_FTYPE_FX (l);
14537   INT_FTYPE_FX (ll);
14538 
14539   INT_FTYPE_FX (uh);
14540   INT_FTYPE_FX (un);
14541   INT_FTYPE_FX (ul);
14542   INT_FTYPE_FX (ull);
14543 
14544   /* For bitsfx builtins.  */
14545 
14546   INTX_FTYPE_FX (h);
14547   INTX_FTYPE_FX (n);
14548   INTX_FTYPE_FX (l);
14549   INTX_FTYPE_FX (ll);
14550 
14551   INTX_FTYPE_FX (uh);
14552   INTX_FTYPE_FX (un);
14553   INTX_FTYPE_FX (ul);
14554   INTX_FTYPE_FX (ull);
14555 
14556   /* For fxbits builtins.  */
14557 
14558   FX_FTYPE_INTX (h);
14559   FX_FTYPE_INTX (n);
14560   FX_FTYPE_INTX (l);
14561   FX_FTYPE_INTX (ll);
14562 
14563   FX_FTYPE_INTX (uh);
14564   FX_FTYPE_INTX (un);
14565   FX_FTYPE_INTX (ul);
14566   FX_FTYPE_INTX (ull);
14567 
14568 
14569 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME)                  \
14570   {                                                                     \
14571     int id = AVR_BUILTIN_ ## NAME;                                      \
14572     const char *Name = "__builtin_avr_" #NAME;                          \
14573     char *name = (char*) alloca (1 + strlen (Name));                    \
14574                                                                         \
14575     gcc_assert (id < AVR_BUILTIN_COUNT);                                \
14576     avr_bdesc[id].fndecl                                                \
14577       = add_builtin_function (avr_tolower (name, Name), TYPE, id,       \
14578                               BUILT_IN_MD, LIBNAME, NULL_TREE);         \
14579   }
14580 #include "builtins.def"
14581 #undef DEF_BUILTIN
14582 
14583   avr_init_builtin_int24 ();
14584 }
14585 
14586 
14587 /* Subroutine of avr_expand_builtin to expand vanilla builtins
14588    with non-void result and 1 ... 3 arguments.  */
14589 
14590 static rtx
avr_default_expand_builtin(enum insn_code icode,tree exp,rtx target)14591 avr_default_expand_builtin (enum insn_code icode, tree exp, rtx target)
14592 {
14593   rtx pat, xop[3];
14594   int n_args = call_expr_nargs (exp);
14595   machine_mode tmode = insn_data[icode].operand[0].mode;
14596 
14597   gcc_assert (n_args >= 1 && n_args <= 3);
14598 
14599   if (target == NULL_RTX
14600       || GET_MODE (target) != tmode
14601       || !insn_data[icode].operand[0].predicate (target, tmode))
14602     {
14603       target = gen_reg_rtx (tmode);
14604     }
14605 
14606   for (int n = 0; n < n_args; n++)
14607     {
14608       tree arg = CALL_EXPR_ARG (exp, n);
14609       rtx op = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14610       machine_mode opmode = GET_MODE (op);
14611       machine_mode mode = insn_data[icode].operand[n + 1].mode;
14612 
14613       if ((opmode == SImode || opmode == VOIDmode) && mode == HImode)
14614         {
14615           opmode = HImode;
14616           op = gen_lowpart (HImode, op);
14617         }
14618 
14619       /* In case the insn wants input operands in modes different from
14620          the result, abort.  */
14621 
14622       gcc_assert (opmode == mode || opmode == VOIDmode);
14623 
14624       if (!insn_data[icode].operand[n + 1].predicate (op, mode))
14625         op = copy_to_mode_reg (mode, op);
14626 
14627       xop[n] = op;
14628     }
14629 
14630   switch (n_args)
14631     {
14632     case 1: pat = GEN_FCN (icode) (target, xop[0]); break;
14633     case 2: pat = GEN_FCN (icode) (target, xop[0], xop[1]); break;
14634     case 3: pat = GEN_FCN (icode) (target, xop[0], xop[1], xop[2]); break;
14635 
14636     default:
14637       gcc_unreachable();
14638     }
14639 
14640   if (pat == NULL_RTX)
14641     return NULL_RTX;
14642 
14643   emit_insn (pat);
14644 
14645   return target;
14646 }
14647 
14648 
14649 /* Implement `TARGET_EXPAND_BUILTIN'.  */
14650 /* Expand an expression EXP that calls a built-in function,
14651    with result going to TARGET if that's convenient
14652    (and in mode MODE if that's convenient).
14653    SUBTARGET may be used as the target for computing one of EXP's operands.
14654    IGNORE is nonzero if the value is to be ignored.  */
14655 
14656 static rtx
avr_expand_builtin(tree exp,rtx target,rtx subtarget ATTRIBUTE_UNUSED,machine_mode mode ATTRIBUTE_UNUSED,int ignore)14657 avr_expand_builtin (tree exp, rtx target,
14658                     rtx subtarget ATTRIBUTE_UNUSED,
14659                     machine_mode mode ATTRIBUTE_UNUSED,
14660                     int ignore)
14661 {
14662   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
14663   const char *bname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
14664   unsigned int id = DECL_MD_FUNCTION_CODE (fndecl);
14665   const struct avr_builtin_description *d = &avr_bdesc[id];
14666   tree arg0;
14667   rtx op0;
14668 
14669   gcc_assert (id < AVR_BUILTIN_COUNT);
14670 
14671   switch (id)
14672     {
14673     case AVR_BUILTIN_NOP:
14674       emit_insn (gen_nopv (GEN_INT (1)));
14675       return 0;
14676 
14677     case AVR_BUILTIN_DELAY_CYCLES:
14678       {
14679         arg0 = CALL_EXPR_ARG (exp, 0);
14680         op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14681 
14682         if (!CONST_INT_P (op0))
14683           error ("%s expects a compile time integer constant", bname);
14684         else
14685           avr_expand_delay_cycles (op0);
14686 
14687         return NULL_RTX;
14688       }
14689 
14690     case AVR_BUILTIN_NOPS:
14691       {
14692         arg0 = CALL_EXPR_ARG (exp, 0);
14693         op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14694 
14695         if (!CONST_INT_P (op0))
14696           error ("%s expects a compile time integer constant", bname);
14697         else
14698           avr_expand_nops (op0);
14699 
14700         return NULL_RTX;
14701       }
14702 
14703     case AVR_BUILTIN_INSERT_BITS:
14704       {
14705         arg0 = CALL_EXPR_ARG (exp, 0);
14706         op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14707 
14708         if (!CONST_INT_P (op0))
14709           {
14710             error ("%s expects a compile time long integer constant"
14711                    " as first argument", bname);
14712             return target;
14713           }
14714 
14715         break;
14716       }
14717 
14718     case AVR_BUILTIN_ROUNDHR:   case AVR_BUILTIN_ROUNDUHR:
14719     case AVR_BUILTIN_ROUNDR:    case AVR_BUILTIN_ROUNDUR:
14720     case AVR_BUILTIN_ROUNDLR:   case AVR_BUILTIN_ROUNDULR:
14721     case AVR_BUILTIN_ROUNDLLR:  case AVR_BUILTIN_ROUNDULLR:
14722 
14723     case AVR_BUILTIN_ROUNDHK:   case AVR_BUILTIN_ROUNDUHK:
14724     case AVR_BUILTIN_ROUNDK:    case AVR_BUILTIN_ROUNDUK:
14725     case AVR_BUILTIN_ROUNDLK:   case AVR_BUILTIN_ROUNDULK:
14726     case AVR_BUILTIN_ROUNDLLK:  case AVR_BUILTIN_ROUNDULLK:
14727 
14728       /* Warn about odd rounding.  Rounding points >= FBIT will have
14729          no effect.  */
14730 
14731       if (TREE_CODE (CALL_EXPR_ARG (exp, 1)) != INTEGER_CST)
14732         break;
14733 
14734       int rbit = (int) TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1));
14735 
14736       if (rbit >= (int) GET_MODE_FBIT (mode))
14737         {
14738           warning (OPT_Wextra, "rounding to %d bits has no effect for "
14739                    "fixed-point value with %d fractional bits",
14740                    rbit, GET_MODE_FBIT (mode));
14741 
14742           return expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX, mode,
14743                               EXPAND_NORMAL);
14744         }
14745       else if (rbit <= - (int) GET_MODE_IBIT (mode))
14746         {
14747           warning (0, "rounding result will always be 0");
14748           return CONST0_RTX (mode);
14749         }
14750 
14751       /* The rounding points RP satisfies now:  -IBIT < RP < FBIT.
14752 
14753          TR 18037 only specifies results for  RP > 0.  However, the
14754          remaining cases of  -IBIT < RP <= 0  can easily be supported
14755          without any additional overhead.  */
14756 
14757       break; /* round */
14758     }
14759 
14760   /* No fold found and no insn:  Call support function from libgcc.  */
14761 
14762   if (d->icode == CODE_FOR_nothing
14763       && DECL_ASSEMBLER_NAME (get_callee_fndecl (exp)) != NULL_TREE)
14764     {
14765       return expand_call (exp, target, ignore);
14766     }
14767 
14768   /* No special treatment needed: vanilla expand.  */
14769 
14770   gcc_assert (d->icode != CODE_FOR_nothing);
14771   gcc_assert (d->n_args == call_expr_nargs (exp));
14772 
14773   if (d->n_args == 0)
14774     {
14775       emit_insn ((GEN_FCN (d->icode)) (target));
14776       return NULL_RTX;
14777     }
14778 
14779   return avr_default_expand_builtin (d->icode, exp, target);
14780 }
14781 
14782 
14783 /* Helper for `avr_fold_builtin' that folds  absfx (FIXED_CST).  */
14784 
14785 static tree
avr_fold_absfx(tree tval)14786 avr_fold_absfx (tree tval)
14787 {
14788   if (FIXED_CST != TREE_CODE (tval))
14789     return NULL_TREE;
14790 
14791   /* Our fixed-points have no padding:  Use double_int payload directly.  */
14792 
14793   FIXED_VALUE_TYPE fval = TREE_FIXED_CST (tval);
14794   unsigned int bits = GET_MODE_BITSIZE (fval.mode);
14795   double_int ival = fval.data.sext (bits);
14796 
14797   if (!ival.is_negative())
14798     return tval;
14799 
14800   /* ISO/IEC TR 18037, 7.18a.6.2:  The absfx functions are saturating.  */
14801 
14802   fval.data = (ival == double_int::min_value (bits, false).sext (bits))
14803     ? double_int::max_value (bits, false)
14804     : -ival;
14805 
14806   return build_fixed (TREE_TYPE (tval), fval);
14807 }
14808 
14809 
14810 /* Implement `TARGET_FOLD_BUILTIN'.  */
14811 
14812 static tree
avr_fold_builtin(tree fndecl,int n_args ATTRIBUTE_UNUSED,tree * arg,bool ignore ATTRIBUTE_UNUSED)14813 avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg,
14814                   bool ignore ATTRIBUTE_UNUSED)
14815 {
14816   unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
14817   tree val_type = TREE_TYPE (TREE_TYPE (fndecl));
14818 
14819   if (!optimize)
14820     return NULL_TREE;
14821 
14822   switch (fcode)
14823     {
14824     default:
14825       break;
14826 
14827     case AVR_BUILTIN_SWAP:
14828       {
14829         return fold_build2 (LROTATE_EXPR, val_type, arg[0],
14830                             build_int_cst (val_type, 4));
14831       }
14832 
14833     case AVR_BUILTIN_ABSHR:
14834     case AVR_BUILTIN_ABSR:
14835     case AVR_BUILTIN_ABSLR:
14836     case AVR_BUILTIN_ABSLLR:
14837 
14838     case AVR_BUILTIN_ABSHK:
14839     case AVR_BUILTIN_ABSK:
14840     case AVR_BUILTIN_ABSLK:
14841     case AVR_BUILTIN_ABSLLK:
14842       /* GCC is not good with folding ABS for fixed-point.  Do it by hand.  */
14843 
14844       return avr_fold_absfx (arg[0]);
14845 
14846     case AVR_BUILTIN_BITSHR:    case AVR_BUILTIN_HRBITS:
14847     case AVR_BUILTIN_BITSHK:    case AVR_BUILTIN_HKBITS:
14848     case AVR_BUILTIN_BITSUHR:   case AVR_BUILTIN_UHRBITS:
14849     case AVR_BUILTIN_BITSUHK:   case AVR_BUILTIN_UHKBITS:
14850 
14851     case AVR_BUILTIN_BITSR:     case AVR_BUILTIN_RBITS:
14852     case AVR_BUILTIN_BITSK:     case AVR_BUILTIN_KBITS:
14853     case AVR_BUILTIN_BITSUR:    case AVR_BUILTIN_URBITS:
14854     case AVR_BUILTIN_BITSUK:    case AVR_BUILTIN_UKBITS:
14855 
14856     case AVR_BUILTIN_BITSLR:    case AVR_BUILTIN_LRBITS:
14857     case AVR_BUILTIN_BITSLK:    case AVR_BUILTIN_LKBITS:
14858     case AVR_BUILTIN_BITSULR:   case AVR_BUILTIN_ULRBITS:
14859     case AVR_BUILTIN_BITSULK:   case AVR_BUILTIN_ULKBITS:
14860 
14861     case AVR_BUILTIN_BITSLLR:   case AVR_BUILTIN_LLRBITS:
14862     case AVR_BUILTIN_BITSLLK:   case AVR_BUILTIN_LLKBITS:
14863     case AVR_BUILTIN_BITSULLR:  case AVR_BUILTIN_ULLRBITS:
14864     case AVR_BUILTIN_BITSULLK:  case AVR_BUILTIN_ULLKBITS:
14865 
14866       gcc_assert (TYPE_PRECISION (val_type)
14867                   == TYPE_PRECISION (TREE_TYPE (arg[0])));
14868 
14869       return build1 (VIEW_CONVERT_EXPR, val_type, arg[0]);
14870 
14871     case AVR_BUILTIN_INSERT_BITS:
14872       {
14873         tree tbits = arg[1];
14874         tree tval = arg[2];
14875         tree tmap;
14876         tree map_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
14877         unsigned int map;
14878         bool changed = false;
14879         avr_map_op_t best_g;
14880 
14881         if (TREE_CODE (arg[0]) != INTEGER_CST)
14882           {
14883             /* No constant as first argument: Don't fold this and run into
14884                error in avr_expand_builtin.  */
14885 
14886             break;
14887           }
14888 
14889         tmap = wide_int_to_tree (map_type, wi::to_wide (arg[0]));
14890         map = TREE_INT_CST_LOW (tmap);
14891 
14892         if (TREE_CODE (tval) != INTEGER_CST
14893               && avr_map_metric (map, MAP_MASK_PREIMAGE_F) == 0)
14894           {
14895             /* There are no F in the map, i.e. 3rd operand is unused.
14896                Replace that argument with some constant to render
14897                respective input unused.  */
14898 
14899             tval = build_int_cst (val_type, 0);
14900             changed = true;
14901           }
14902 
14903         if (TREE_CODE (tbits) != INTEGER_CST
14904               && avr_map_metric (map, MAP_PREIMAGE_0_7) == 0)
14905           {
14906             /* Similar for the bits to be inserted. If they are unused,
14907                we can just as well pass 0.  */
14908 
14909             tbits = build_int_cst (val_type, 0);
14910           }
14911 
14912         if (TREE_CODE (tbits) == INTEGER_CST)
14913           {
14914             /* Inserting bits known at compile time is easy and can be
14915                performed by AND and OR with appropriate masks.  */
14916 
14917             int bits = TREE_INT_CST_LOW (tbits);
14918             int mask_ior = 0, mask_and = 0xff;
14919 
14920             for (size_t i = 0; i < 8; i++)
14921               {
14922                 int mi = avr_map (map, i);
14923 
14924                 if (mi < 8)
14925                   {
14926                     if (bits & (1 << mi))     mask_ior |=  (1 << i);
14927                     else                      mask_and &= ~(1 << i);
14928                   }
14929               }
14930 
14931             tval = fold_build2 (BIT_IOR_EXPR, val_type, tval,
14932                                 build_int_cst (val_type, mask_ior));
14933             return fold_build2 (BIT_AND_EXPR, val_type, tval,
14934                                 build_int_cst (val_type, mask_and));
14935           }
14936 
14937         if (changed)
14938           return build_call_expr (fndecl, 3, tmap, tbits, tval);
14939 
14940         /* If bits don't change their position we can use vanilla logic
14941            to merge the two arguments.  */
14942 
14943           if (avr_map_metric (map, MAP_NONFIXED_0_7) == 0)
14944           {
14945             int mask_f = avr_map_metric (map, MAP_MASK_PREIMAGE_F);
14946             tree tres, tmask = build_int_cst (val_type, mask_f ^ 0xff);
14947 
14948             tres = fold_build2 (BIT_XOR_EXPR, val_type, tbits, tval);
14949             tres = fold_build2 (BIT_AND_EXPR, val_type, tres, tmask);
14950             return fold_build2 (BIT_XOR_EXPR, val_type, tres, tval);
14951           }
14952 
14953         /* Try to decomposing map to reduce overall cost.  */
14954 
14955         if (avr_log.builtin)
14956           avr_edump ("\n%?: %x\n%?: ROL cost: ", map);
14957 
14958         best_g = avr_map_op[0];
14959         best_g.cost = 1000;
14960 
14961         for (size_t i = 0; i < ARRAY_SIZE (avr_map_op); i++)
14962           {
14963             avr_map_op_t g
14964               = avr_map_decompose (map, avr_map_op + i,
14965                                    TREE_CODE (tval) == INTEGER_CST);
14966 
14967             if (g.cost >= 0 && g.cost < best_g.cost)
14968               best_g = g;
14969           }
14970 
14971         if (avr_log.builtin)
14972           avr_edump ("\n");
14973 
14974         if (best_g.arg == 0)
14975           /* No optimization found */
14976           break;
14977 
14978         /* Apply operation G to the 2nd argument.  */
14979 
14980         if (avr_log.builtin)
14981           avr_edump ("%?: using OP(%s%d, %x) cost %d\n",
14982                      best_g.str, best_g.arg, best_g.map, best_g.cost);
14983 
14984         /* Do right-shifts arithmetically: They copy the MSB instead of
14985            shifting in a non-usable value (0) as with logic right-shift.  */
14986 
14987         tbits = fold_convert (signed_char_type_node, tbits);
14988         tbits = fold_build2 (best_g.code, signed_char_type_node, tbits,
14989                              build_int_cst (val_type, best_g.arg));
14990         tbits = fold_convert (val_type, tbits);
14991 
14992         /* Use map o G^-1 instead of original map to undo the effect of G.  */
14993 
14994         tmap = wide_int_to_tree (map_type, best_g.map);
14995 
14996         return build_call_expr (fndecl, 3, tmap, tbits, tval);
14997       } /* AVR_BUILTIN_INSERT_BITS */
14998     }
14999 
15000   return NULL_TREE;
15001 }
15002 
15003 /* Prepend to CLOBBERS hard registers that are automatically clobbered
15004    for an asm. We do this for CC_REGNUM to maintain source compatibility
15005    with the original cc0-based compiler.  */
15006 
15007 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)15008 avr_md_asm_adjust (vec<rtx> &/*outputs*/, vec<rtx> &/*inputs*/,
15009                    vec<machine_mode> & /*input_modes*/,
15010                    vec<const char *> &/*constraints*/,
15011                    vec<rtx> &clobbers, HARD_REG_SET &clobbered_regs,
15012                        location_t /*loc*/)
15013 {
15014   clobbers.safe_push (cc_reg_rtx);
15015   SET_HARD_REG_BIT (clobbered_regs, REG_CC);
15016   return NULL;
15017 }
15018 
15019 
15020 /* Worker function for `FLOAT_LIB_COMPARE_RETURNS_BOOL'.  */
15021 
15022 bool
avr_float_lib_compare_returns_bool(machine_mode mode,enum rtx_code)15023 avr_float_lib_compare_returns_bool (machine_mode mode, enum rtx_code)
15024 {
15025   if (mode == DFmode)
15026     {
15027 #if WITH_DOUBLE_COMPARISON == 2
15028       return true;
15029 #endif
15030     }
15031 
15032   // This is the GCC default and also what AVR-LibC implements.
15033   return false;
15034 }
15035 
15036 
15037 
15038 /* Initialize the GCC target structure.  */
15039 
15040 #undef  TARGET_ASM_ALIGNED_HI_OP
15041 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
15042 #undef  TARGET_ASM_ALIGNED_SI_OP
15043 #define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
15044 #undef  TARGET_ASM_UNALIGNED_HI_OP
15045 #define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
15046 #undef  TARGET_ASM_UNALIGNED_SI_OP
15047 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
15048 #undef  TARGET_ASM_INTEGER
15049 #define TARGET_ASM_INTEGER avr_assemble_integer
15050 #undef  TARGET_ASM_FILE_START
15051 #define TARGET_ASM_FILE_START avr_file_start
15052 #undef  TARGET_ASM_FILE_END
15053 #define TARGET_ASM_FILE_END avr_file_end
15054 
15055 #undef  TARGET_ASM_FUNCTION_END_PROLOGUE
15056 #define TARGET_ASM_FUNCTION_END_PROLOGUE avr_asm_function_end_prologue
15057 #undef  TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
15058 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE avr_asm_function_begin_epilogue
15059 
15060 #undef  TARGET_FUNCTION_VALUE
15061 #define TARGET_FUNCTION_VALUE avr_function_value
15062 #undef  TARGET_LIBCALL_VALUE
15063 #define TARGET_LIBCALL_VALUE avr_libcall_value
15064 #undef  TARGET_FUNCTION_VALUE_REGNO_P
15065 #define TARGET_FUNCTION_VALUE_REGNO_P avr_function_value_regno_p
15066 
15067 #undef  TARGET_ATTRIBUTE_TABLE
15068 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
15069 #undef  TARGET_INSERT_ATTRIBUTES
15070 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
15071 #undef  TARGET_SECTION_TYPE_FLAGS
15072 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
15073 
15074 #undef  TARGET_ASM_NAMED_SECTION
15075 #define TARGET_ASM_NAMED_SECTION avr_asm_named_section
15076 #undef  TARGET_ASM_INIT_SECTIONS
15077 #define TARGET_ASM_INIT_SECTIONS avr_asm_init_sections
15078 #undef  TARGET_ENCODE_SECTION_INFO
15079 #define TARGET_ENCODE_SECTION_INFO avr_encode_section_info
15080 #undef  TARGET_ASM_SELECT_SECTION
15081 #define TARGET_ASM_SELECT_SECTION avr_asm_select_section
15082 
15083 #undef  TARGET_ASM_FINAL_POSTSCAN_INSN
15084 #define TARGET_ASM_FINAL_POSTSCAN_INSN avr_asm_final_postscan_insn
15085 
15086 #undef  TARGET_INSN_COST
15087 #define TARGET_INSN_COST avr_insn_cost
15088 #undef  TARGET_REGISTER_MOVE_COST
15089 #define TARGET_REGISTER_MOVE_COST avr_register_move_cost
15090 #undef  TARGET_MEMORY_MOVE_COST
15091 #define TARGET_MEMORY_MOVE_COST avr_memory_move_cost
15092 #undef  TARGET_RTX_COSTS
15093 #define TARGET_RTX_COSTS avr_rtx_costs
15094 #undef  TARGET_ADDRESS_COST
15095 #define TARGET_ADDRESS_COST avr_address_cost
15096 #undef  TARGET_FUNCTION_ARG
15097 #define TARGET_FUNCTION_ARG avr_function_arg
15098 #undef  TARGET_FUNCTION_ARG_ADVANCE
15099 #define TARGET_FUNCTION_ARG_ADVANCE avr_function_arg_advance
15100 
15101 #undef  TARGET_SET_CURRENT_FUNCTION
15102 #define TARGET_SET_CURRENT_FUNCTION avr_set_current_function
15103 
15104 #undef  TARGET_RETURN_IN_MEMORY
15105 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
15106 
15107 #undef  TARGET_STRICT_ARGUMENT_NAMING
15108 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
15109 
15110 #undef TARGET_CONDITIONAL_REGISTER_USAGE
15111 #define TARGET_CONDITIONAL_REGISTER_USAGE avr_conditional_register_usage
15112 
15113 #undef TARGET_HARD_REGNO_NREGS
15114 #define TARGET_HARD_REGNO_NREGS avr_hard_regno_nregs
15115 
15116 #undef  TARGET_HARD_REGNO_MODE_OK
15117 #define TARGET_HARD_REGNO_MODE_OK avr_hard_regno_mode_ok
15118 #undef  TARGET_HARD_REGNO_SCRATCH_OK
15119 #define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok
15120 #undef  TARGET_HARD_REGNO_CALL_PART_CLOBBERED
15121 #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
15122   avr_hard_regno_call_part_clobbered
15123 
15124 #undef  TARGET_CASE_VALUES_THRESHOLD
15125 #define TARGET_CASE_VALUES_THRESHOLD avr_case_values_threshold
15126 
15127 #undef  TARGET_FRAME_POINTER_REQUIRED
15128 #define TARGET_FRAME_POINTER_REQUIRED avr_frame_pointer_required_p
15129 #undef  TARGET_CAN_ELIMINATE
15130 #define TARGET_CAN_ELIMINATE avr_can_eliminate
15131 
15132 #undef  TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
15133 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS avr_allocate_stack_slots_for_args
15134 
15135 #undef TARGET_WARN_FUNC_RETURN
15136 #define TARGET_WARN_FUNC_RETURN avr_warn_func_return
15137 
15138 #undef  TARGET_CLASS_LIKELY_SPILLED_P
15139 #define TARGET_CLASS_LIKELY_SPILLED_P avr_class_likely_spilled_p
15140 
15141 #undef  TARGET_CLASS_MAX_NREGS
15142 #define TARGET_CLASS_MAX_NREGS avr_class_max_nregs
15143 
15144 #undef  TARGET_OPTION_OVERRIDE
15145 #define TARGET_OPTION_OVERRIDE avr_option_override
15146 
15147 #undef  TARGET_CANNOT_MODIFY_JUMPS_P
15148 #define TARGET_CANNOT_MODIFY_JUMPS_P avr_cannot_modify_jumps_p
15149 
15150 #undef  TARGET_FUNCTION_OK_FOR_SIBCALL
15151 #define TARGET_FUNCTION_OK_FOR_SIBCALL avr_function_ok_for_sibcall
15152 
15153 #undef  TARGET_INIT_BUILTINS
15154 #define TARGET_INIT_BUILTINS avr_init_builtins
15155 
15156 #undef  TARGET_BUILTIN_DECL
15157 #define TARGET_BUILTIN_DECL avr_builtin_decl
15158 
15159 #undef  TARGET_EXPAND_BUILTIN
15160 #define TARGET_EXPAND_BUILTIN avr_expand_builtin
15161 
15162 #undef  TARGET_FOLD_BUILTIN
15163 #define TARGET_FOLD_BUILTIN avr_fold_builtin
15164 
15165 #undef  TARGET_SCALAR_MODE_SUPPORTED_P
15166 #define TARGET_SCALAR_MODE_SUPPORTED_P avr_scalar_mode_supported_p
15167 
15168 #undef  TARGET_BUILD_BUILTIN_VA_LIST
15169 #define TARGET_BUILD_BUILTIN_VA_LIST avr_build_builtin_va_list
15170 
15171 #undef  TARGET_FIXED_POINT_SUPPORTED_P
15172 #define TARGET_FIXED_POINT_SUPPORTED_P hook_bool_void_true
15173 
15174 #undef  TARGET_CONVERT_TO_TYPE
15175 #define TARGET_CONVERT_TO_TYPE avr_convert_to_type
15176 
15177 #undef TARGET_LRA_P
15178 #define TARGET_LRA_P hook_bool_void_false
15179 
15180 #undef  TARGET_ADDR_SPACE_SUBSET_P
15181 #define TARGET_ADDR_SPACE_SUBSET_P avr_addr_space_subset_p
15182 
15183 #undef  TARGET_ADDR_SPACE_CONVERT
15184 #define TARGET_ADDR_SPACE_CONVERT avr_addr_space_convert
15185 
15186 #undef  TARGET_ADDR_SPACE_ADDRESS_MODE
15187 #define TARGET_ADDR_SPACE_ADDRESS_MODE avr_addr_space_address_mode
15188 
15189 #undef  TARGET_ADDR_SPACE_POINTER_MODE
15190 #define TARGET_ADDR_SPACE_POINTER_MODE avr_addr_space_pointer_mode
15191 
15192 #undef  TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
15193 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P  \
15194   avr_addr_space_legitimate_address_p
15195 
15196 #undef  TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
15197 #define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS avr_addr_space_legitimize_address
15198 
15199 #undef  TARGET_ADDR_SPACE_DIAGNOSE_USAGE
15200 #define TARGET_ADDR_SPACE_DIAGNOSE_USAGE avr_addr_space_diagnose_usage
15201 
15202 #undef  TARGET_MODE_DEPENDENT_ADDRESS_P
15203 #define TARGET_MODE_DEPENDENT_ADDRESS_P avr_mode_dependent_address_p
15204 
15205 #undef  TARGET_PRINT_OPERAND
15206 #define TARGET_PRINT_OPERAND avr_print_operand
15207 #undef  TARGET_PRINT_OPERAND_ADDRESS
15208 #define TARGET_PRINT_OPERAND_ADDRESS avr_print_operand_address
15209 #undef  TARGET_PRINT_OPERAND_PUNCT_VALID_P
15210 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P avr_print_operand_punct_valid_p
15211 
15212 #undef TARGET_USE_BY_PIECES_INFRASTRUCTURE_P
15213 #define TARGET_USE_BY_PIECES_INFRASTRUCTURE_P \
15214   avr_use_by_pieces_infrastructure_p
15215 
15216 #undef  TARGET_LEGITIMATE_COMBINED_INSN
15217 #define TARGET_LEGITIMATE_COMBINED_INSN avr_legitimate_combined_insn
15218 
15219 #undef  TARGET_STARTING_FRAME_OFFSET
15220 #define TARGET_STARTING_FRAME_OFFSET avr_starting_frame_offset
15221 
15222 #undef  TARGET_MD_ASM_ADJUST
15223 #define TARGET_MD_ASM_ADJUST avr_md_asm_adjust
15224 
15225 #undef  TARGET_CAN_INLINE_P
15226 #define TARGET_CAN_INLINE_P avr_can_inline_p
15227 
15228 #undef  TARGET_CANONICALIZE_COMPARISON
15229 #define TARGET_CANONICALIZE_COMPARISON avr_canonicalize_comparison
15230 
15231 struct gcc_target targetm = TARGET_INITIALIZER;
15232 
15233 
15234 #include "gt-avr.h"
15235