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