1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2 Copyright (C) 1998-2021 Free Software Foundation, Inc.
3 Contributed by Denis Chertykov (chertykov@gmail.com)
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21 #define IN_TARGET_CODE 1
22
23 #include "config.h"
24 #include "system.h"
25 #include "intl.h"
26 #include "coretypes.h"
27 #include "backend.h"
28 #include "target.h"
29 #include "rtl.h"
30 #include "tree.h"
31 #include "stringpool.h"
32 #include "attribs.h"
33 #include "cgraph.h"
34 #include "c-family/c-common.h"
35 #include "cfghooks.h"
36 #include "df.h"
37 #include "memmodel.h"
38 #include "tm_p.h"
39 #include "optabs.h"
40 #include "regs.h"
41 #include "emit-rtl.h"
42 #include "recog.h"
43 #include "conditions.h"
44 #include "insn-attr.h"
45 #include "reload.h"
46 #include "varasm.h"
47 #include "calls.h"
48 #include "stor-layout.h"
49 #include "output.h"
50 #include "explow.h"
51 #include "expr.h"
52 #include "langhooks.h"
53 #include "cfgrtl.h"
54 #include "builtins.h"
55 #include "context.h"
56 #include "tree-pass.h"
57 #include "print-rtl.h"
58 #include "rtl-iter.h"
59
60 /* This file should be included last. */
61 #include "target-def.h"
62
63 /* Maximal allowed offset for an address in the LD command */
64 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
65
66 /* Return true if STR starts with PREFIX and false, otherwise. */
67 #define STR_PREFIX_P(STR,PREFIX) (strncmp (STR, PREFIX, strlen (PREFIX)) == 0)
68
69 /* The 4 bits starting at SECTION_MACH_DEP are reserved to store the
70 address space where data is to be located.
71 As the only non-generic address spaces are all located in flash,
72 this can be used to test if data shall go into some .progmem* section.
73 This must be the rightmost field of machine dependent section flags. */
74 #define AVR_SECTION_PROGMEM (0xf * SECTION_MACH_DEP)
75
76 /* Similar 4-bit region for SYMBOL_REF_FLAGS. */
77 #define AVR_SYMBOL_FLAG_PROGMEM (0xf * SYMBOL_FLAG_MACH_DEP)
78
79 /* Similar 4-bit region in SYMBOL_REF_FLAGS:
80 Set address-space AS in SYMBOL_REF_FLAGS of SYM */
81 #define AVR_SYMBOL_SET_ADDR_SPACE(SYM,AS) \
82 do { \
83 SYMBOL_REF_FLAGS (sym) &= ~AVR_SYMBOL_FLAG_PROGMEM; \
84 SYMBOL_REF_FLAGS (sym) |= (AS) * SYMBOL_FLAG_MACH_DEP; \
85 } while (0)
86
87 /* Read address-space from SYMBOL_REF_FLAGS of SYM */
88 #define AVR_SYMBOL_GET_ADDR_SPACE(SYM) \
89 ((SYMBOL_REF_FLAGS (sym) & AVR_SYMBOL_FLAG_PROGMEM) \
90 / SYMBOL_FLAG_MACH_DEP)
91
92 /* (AVR_TINY only): Symbol has attribute progmem */
93 #define AVR_SYMBOL_FLAG_TINY_PM \
94 (SYMBOL_FLAG_MACH_DEP << 7)
95
96 /* (AVR_TINY only): Symbol has attribute absdata */
97 #define AVR_SYMBOL_FLAG_TINY_ABSDATA \
98 (SYMBOL_FLAG_MACH_DEP << 8)
99
100 #define TINY_ADIW(REG1, REG2, I) \
101 "subi " #REG1 ",lo8(-(" #I "))" CR_TAB \
102 "sbci " #REG2 ",hi8(-(" #I "))"
103
104 #define TINY_SBIW(REG1, REG2, I) \
105 "subi " #REG1 ",lo8((" #I "))" CR_TAB \
106 "sbci " #REG2 ",hi8((" #I "))"
107
108 #define AVR_TMP_REGNO (AVR_TINY ? TMP_REGNO_TINY : TMP_REGNO)
109 #define AVR_ZERO_REGNO (AVR_TINY ? ZERO_REGNO_TINY : ZERO_REGNO)
110
111 /* Known address spaces. The order must be the same as in the respective
112 enum from avr.h (or designated initialized must be used). */
113 const avr_addrspace_t avr_addrspace[ADDR_SPACE_COUNT] =
114 {
115 { ADDR_SPACE_RAM, 0, 2, "", 0, NULL },
116 { ADDR_SPACE_FLASH, 1, 2, "__flash", 0, ".progmem.data" },
117 { ADDR_SPACE_FLASH1, 1, 2, "__flash1", 1, ".progmem1.data" },
118 { ADDR_SPACE_FLASH2, 1, 2, "__flash2", 2, ".progmem2.data" },
119 { ADDR_SPACE_FLASH3, 1, 2, "__flash3", 3, ".progmem3.data" },
120 { ADDR_SPACE_FLASH4, 1, 2, "__flash4", 4, ".progmem4.data" },
121 { ADDR_SPACE_FLASH5, 1, 2, "__flash5", 5, ".progmem5.data" },
122 { ADDR_SPACE_MEMX, 1, 3, "__memx", 0, ".progmemx.data" },
123 };
124
125
126 /* Holding RAM addresses of some SFRs used by the compiler and that
127 are unique over all devices in an architecture like 'avr4'. */
128
129 typedef struct
130 {
131 /* SREG: The processor status */
132 int sreg;
133
134 /* RAMPX, RAMPY, RAMPD and CCP of XMEGA */
135 int ccp;
136 int rampd;
137 int rampx;
138 int rampy;
139
140 /* RAMPZ: The high byte of 24-bit address used with ELPM */
141 int rampz;
142
143 /* SP: The stack pointer and its low and high byte */
144 int sp_l;
145 int sp_h;
146 } avr_addr_t;
147
148 static avr_addr_t avr_addr;
149
150
151 /* Prototypes for local helper functions. */
152
153 static const char* out_movqi_r_mr (rtx_insn *, rtx[], int*);
154 static const char* out_movhi_r_mr (rtx_insn *, rtx[], int*);
155 static const char* out_movsi_r_mr (rtx_insn *, rtx[], int*);
156 static const char* out_movqi_mr_r (rtx_insn *, rtx[], int*);
157 static const char* out_movhi_mr_r (rtx_insn *, rtx[], int*);
158 static const char* out_movsi_mr_r (rtx_insn *, rtx[], int*);
159
160 static int get_sequence_length (rtx_insn *insns);
161 static int sequent_regs_live (void);
162 static const char *ptrreg_to_str (int);
163 static const char *cond_string (enum rtx_code);
164 static int avr_num_arg_regs (machine_mode, const_tree);
165 static int avr_operand_rtx_cost (rtx, machine_mode, enum rtx_code,
166 int, bool);
167 static void output_reload_in_const (rtx*, rtx, int*, bool);
168 static struct machine_function * avr_init_machine_status (void);
169
170
171 /* Prototypes for hook implementors if needed before their implementation. */
172
173 static bool avr_rtx_costs (rtx, machine_mode, int, int, int*, bool);
174
175
176 /* Allocate registers from r25 to r8 for parameters for function calls. */
177 #define FIRST_CUM_REG 26
178
179 /* Last call saved register */
180 #define LAST_CALLEE_SAVED_REG (AVR_TINY ? 19 : 17)
181
182 /* Implicit target register of LPM instruction (R0) */
183 extern GTY(()) rtx lpm_reg_rtx;
184 rtx lpm_reg_rtx;
185
186 /* (Implicit) address register of LPM instruction (R31:R30 = Z) */
187 extern GTY(()) rtx lpm_addr_reg_rtx;
188 rtx lpm_addr_reg_rtx;
189
190 /* Temporary register RTX (reg:QI TMP_REGNO) */
191 extern GTY(()) rtx tmp_reg_rtx;
192 rtx tmp_reg_rtx;
193
194 /* Zeroed register RTX (reg:QI ZERO_REGNO) */
195 extern GTY(()) rtx zero_reg_rtx;
196 rtx zero_reg_rtx;
197
198 /* RTXs for all general purpose registers as QImode */
199 extern GTY(()) rtx all_regs_rtx[32];
200 rtx all_regs_rtx[32];
201
202 /* SREG, the processor status */
203 extern GTY(()) rtx sreg_rtx;
204 rtx sreg_rtx;
205
206 /* RAMP* special function registers */
207 extern GTY(()) rtx rampd_rtx;
208 extern GTY(()) rtx rampx_rtx;
209 extern GTY(()) rtx rampy_rtx;
210 extern GTY(()) rtx rampz_rtx;
211 rtx rampd_rtx;
212 rtx rampx_rtx;
213 rtx rampy_rtx;
214 rtx rampz_rtx;
215
216 /* RTX containing the strings "" and "e", respectively */
217 static GTY(()) rtx xstring_empty;
218 static GTY(()) rtx xstring_e;
219
220 /* Current architecture. */
221 const avr_arch_t *avr_arch;
222
223 /* Unnamed sections associated to __attribute__((progmem)) aka. PROGMEM
224 or to address space __flash* or __memx. Only used as singletons inside
225 avr_asm_select_section, but it must not be local there because of GTY. */
226 static GTY(()) section *progmem_section[ADDR_SPACE_COUNT];
227
228 /* Condition for insns/expanders from avr-dimode.md. */
229 bool avr_have_dimode = true;
230
231 /* To track if code will use .bss and/or .data. */
232 bool avr_need_clear_bss_p = false;
233 bool avr_need_copy_data_p = false;
234
235
236 /* Transform UP into lowercase and write the result to LO.
237 You must provide enough space for LO. Return LO. */
238
239 static char*
avr_tolower(char * lo,const char * up)240 avr_tolower (char *lo, const char *up)
241 {
242 char *lo0 = lo;
243
244 for (; *up; up++, lo++)
245 *lo = TOLOWER (*up);
246
247 *lo = '\0';
248
249 return lo0;
250 }
251
252
253 /* Constraint helper function. XVAL is a CONST_INT or a CONST_DOUBLE.
254 Return true if the least significant N_BYTES bytes of XVAL all have a
255 popcount in POP_MASK and false, otherwise. POP_MASK represents a subset
256 of integers which contains an integer N iff bit N of POP_MASK is set. */
257
258 bool
avr_popcount_each_byte(rtx xval,int n_bytes,int pop_mask)259 avr_popcount_each_byte (rtx xval, int n_bytes, int pop_mask)
260 {
261 machine_mode mode = GET_MODE (xval);
262
263 if (VOIDmode == mode)
264 mode = SImode;
265
266 for (int i = 0; i < n_bytes; i++)
267 {
268 rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
269 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
270
271 if ((pop_mask & (1 << popcount_hwi (val8))) == 0)
272 return false;
273 }
274
275 return true;
276 }
277
278
279 /* Access some RTX as INT_MODE. If X is a CONST_FIXED we can get
280 the bit representation of X by "casting" it to CONST_INT. */
281
282 rtx
avr_to_int_mode(rtx x)283 avr_to_int_mode (rtx x)
284 {
285 machine_mode mode = GET_MODE (x);
286
287 return VOIDmode == mode
288 ? x
289 : simplify_gen_subreg (int_mode_for_mode (mode).require (), x, mode, 0);
290 }
291
292 namespace {
293
294 static const pass_data avr_pass_data_recompute_notes =
295 {
296 RTL_PASS, // type
297 "", // name (will be patched)
298 OPTGROUP_NONE, // optinfo_flags
299 TV_DF_SCAN, // tv_id
300 0, // properties_required
301 0, // properties_provided
302 0, // properties_destroyed
303 0, // todo_flags_start
304 TODO_df_finish | TODO_df_verify // todo_flags_finish
305 };
306
307
308 class avr_pass_recompute_notes : public rtl_opt_pass
309 {
310 public:
avr_pass_recompute_notes(gcc::context * ctxt,const char * name)311 avr_pass_recompute_notes (gcc::context *ctxt, const char *name)
312 : rtl_opt_pass (avr_pass_data_recompute_notes, ctxt)
313 {
314 this->name = name;
315 }
316
execute(function *)317 virtual unsigned int execute (function*)
318 {
319 df_note_add_problem ();
320 df_analyze ();
321
322 return 0;
323 }
324 }; // avr_pass_recompute_notes
325
326 static const pass_data avr_pass_data_casesi =
327 {
328 RTL_PASS, // type
329 "", // name (will be patched)
330 OPTGROUP_NONE, // optinfo_flags
331 TV_DF_SCAN, // tv_id
332 0, // properties_required
333 0, // properties_provided
334 0, // properties_destroyed
335 0, // todo_flags_start
336 0 // todo_flags_finish
337 };
338
339
340 class avr_pass_casesi : public rtl_opt_pass
341 {
342 public:
avr_pass_casesi(gcc::context * ctxt,const char * name)343 avr_pass_casesi (gcc::context *ctxt, const char *name)
344 : rtl_opt_pass (avr_pass_data_casesi, ctxt)
345 {
346 this->name = name;
347 }
348
349 void avr_rest_of_handle_casesi (function*);
350
gate(function *)351 virtual bool gate (function*) { return optimize > 0; }
352
execute(function * func)353 virtual unsigned int execute (function *func)
354 {
355 avr_rest_of_handle_casesi (func);
356
357 return 0;
358 }
359 }; // avr_pass_casesi
360
361 } // anon namespace
362
363 rtl_opt_pass*
make_avr_pass_recompute_notes(gcc::context * ctxt)364 make_avr_pass_recompute_notes (gcc::context *ctxt)
365 {
366 return new avr_pass_recompute_notes (ctxt, "avr-notes-free-cfg");
367 }
368
369 rtl_opt_pass*
make_avr_pass_casesi(gcc::context * ctxt)370 make_avr_pass_casesi (gcc::context *ctxt)
371 {
372 return new avr_pass_casesi (ctxt, "avr-casesi");
373 }
374
375
376 /* Make one parallel insn with all the patterns from insns i[0]..i[5]. */
377
378 static rtx_insn*
avr_parallel_insn_from_insns(rtx_insn * i[6])379 avr_parallel_insn_from_insns (rtx_insn *i[6])
380 {
381 rtvec vec = gen_rtvec (6, PATTERN (i[0]), PATTERN (i[1]), PATTERN (i[2]),
382 PATTERN (i[3]), PATTERN (i[4]), PATTERN (i[5]));
383 start_sequence();
384 emit (gen_rtx_PARALLEL (VOIDmode, vec));
385 rtx_insn *insn = get_insns();
386 end_sequence();
387
388 return insn;
389 }
390
391
392 /* Return true if we see an insn stream generated by casesi expander together
393 with an extension to SImode of the switch value.
394
395 If this is the case, fill in the insns from casesi to INSNS[1..5] and
396 the SImode extension to INSNS[0]. Moreover, extract the operands of
397 pattern casesi_<mode>_sequence forged from the sequence to recog_data. */
398
399 static bool
avr_is_casesi_sequence(basic_block bb,rtx_insn * insn,rtx_insn * insns[6])400 avr_is_casesi_sequence (basic_block bb, rtx_insn *insn, rtx_insn *insns[6])
401 {
402 rtx set_5, set_0;
403
404 /* A first and quick test for a casesi sequences. As a side effect of
405 the test, harvest respective insns to INSNS[0..5]. */
406
407 if (!(JUMP_P (insns[5] = insn)
408 // casesi is the only insn that comes up with UNSPEC_INDEX_JMP,
409 // hence the following test ensures that we are actually dealing
410 // with code from casesi.
411 && (set_5 = single_set (insns[5]))
412 && UNSPEC == GET_CODE (SET_SRC (set_5))
413 && UNSPEC_INDEX_JMP == XINT (SET_SRC (set_5), 1)
414
415 && (insns[4] = prev_real_insn (insns[5]))
416 && (insns[3] = prev_real_insn (insns[4]))
417 && (insns[2] = prev_real_insn (insns[3]))
418 && (insns[1] = prev_real_insn (insns[2]))
419
420 // Insn prior to casesi.
421 && (insns[0] = prev_real_insn (insns[1]))
422 && (set_0 = single_set (insns[0]))
423 && extend_operator (SET_SRC (set_0), SImode)))
424 {
425 return false;
426 }
427
428 if (dump_file)
429 {
430 fprintf (dump_file, ";; Sequence from casesi in "
431 "[bb %d]:\n\n", bb->index);
432 for (int i = 0; i < 6; i++)
433 print_rtl_single (dump_file, insns[i]);
434 }
435
436 /* We have to deal with quite some operands. Extracting them by hand
437 would be tedious, therefore wrap the insn patterns into a parallel,
438 run recog against it and then use insn extract to get the operands. */
439
440 rtx_insn *xinsn = avr_parallel_insn_from_insns (insns);
441
442 INSN_CODE (xinsn) = recog (PATTERN (xinsn), xinsn, NULL /* num_clobbers */);
443
444 /* Failing to recognize means that someone changed the casesi expander or
445 that some passes prior to this one performed some unexpected changes.
446 Gracefully drop such situations instead of aborting. */
447
448 if (INSN_CODE (xinsn) < 0)
449 {
450 if (dump_file)
451 fprintf (dump_file, ";; Sequence not recognized, giving up.\n\n");
452
453 return false;
454 }
455
456 gcc_assert (CODE_FOR_casesi_qi_sequence == INSN_CODE (xinsn)
457 || CODE_FOR_casesi_hi_sequence == INSN_CODE (xinsn));
458
459 extract_insn (xinsn);
460
461 // Assert on the anatomy of xinsn's operands we are going to work with.
462
463 gcc_assert (recog_data.n_operands == 11);
464 gcc_assert (recog_data.n_dups == 4);
465
466 if (dump_file)
467 {
468 fprintf (dump_file, ";; Operands extracted:\n");
469 for (int i = 0; i < recog_data.n_operands; i++)
470 avr_fdump (dump_file, ";; $%d = %r\n", i, recog_data.operand[i]);
471 fprintf (dump_file, "\n");
472 }
473
474 return true;
475 }
476
477
478 /* Perform some extra checks on operands of casesi_<mode>_sequence.
479 Not all operand dependencies can be described by means of predicates.
480 This function performs left over checks and should always return true.
481 Returning false means that someone changed the casesi expander but did
482 not adjust casesi_<mode>_sequence. */
483
484 bool
avr_casei_sequence_check_operands(rtx * xop)485 avr_casei_sequence_check_operands (rtx *xop)
486 {
487 rtx sub_5 = NULL_RTX;
488
489 if (AVR_HAVE_EIJMP_EICALL
490 // The last clobber op of the tablejump.
491 && xop[8] == all_regs_rtx[24])
492 {
493 // $6 is: (subreg:SI ($5) 0)
494 sub_5 = xop[6];
495 }
496
497 if (!AVR_HAVE_EIJMP_EICALL
498 // $6 is: (plus:HI (subreg:SI ($5) 0)
499 // (label_ref ($3)))
500 && PLUS == GET_CODE (xop[6])
501 && LABEL_REF == GET_CODE (XEXP (xop[6], 1))
502 && rtx_equal_p (xop[3], XEXP (XEXP (xop[6], 1), 0))
503 // The last clobber op of the tablejump.
504 && xop[8] == const0_rtx)
505 {
506 sub_5 = XEXP (xop[6], 0);
507 }
508
509 if (sub_5
510 && SUBREG_P (sub_5)
511 && SUBREG_BYTE (sub_5) == 0
512 && rtx_equal_p (xop[5], SUBREG_REG (sub_5)))
513 return true;
514
515 if (dump_file)
516 fprintf (dump_file, "\n;; Failed condition for casesi_<mode>_sequence\n\n");
517
518 return false;
519 }
520
521
522 /* INSNS[1..5] is a sequence as generated by casesi and INSNS[0] is an
523 extension of an 8-bit or 16-bit integer to SImode. XOP contains the
524 operands of INSNS as extracted by insn_extract from pattern
525 casesi_<mode>_sequence:
526
527 $0: SImode reg switch value as result of $9.
528 $1: Negative of smallest index in switch.
529 $2: Number of entries in switch.
530 $3: Label to table.
531 $4: Label if out-of-bounds.
532 $5: $0 + $1.
533 $6: 3-byte PC: subreg:HI ($5) + label_ref ($3)
534 2-byte PC: subreg:HI ($5)
535 $7: HI reg index into table (Z or pseudo)
536 $8: R24 or const0_rtx (to be clobbered)
537 $9: Extension to SImode of an 8-bit or 16-bit integer register $10.
538 $10: QImode or HImode register input of $9.
539
540 Try to optimize this sequence, i.e. use the original HImode / QImode
541 switch value instead of SImode. */
542
543 static void
avr_optimize_casesi(rtx_insn * insns[6],rtx * xop)544 avr_optimize_casesi (rtx_insn *insns[6], rtx *xop)
545 {
546 // Original mode of the switch value; this is QImode or HImode.
547 machine_mode mode = GET_MODE (xop[10]);
548
549 // How the original switch value was extended to SImode; this is
550 // SIGN_EXTEND or ZERO_EXTEND.
551 enum rtx_code code = GET_CODE (xop[9]);
552
553 // Lower index, upper index (plus one) and range of case calues.
554 HOST_WIDE_INT low_idx = -INTVAL (xop[1]);
555 HOST_WIDE_INT num_idx = INTVAL (xop[2]);
556 HOST_WIDE_INT hig_idx = low_idx + num_idx;
557
558 // Maximum ranges of (un)signed QImode resp. HImode.
559 unsigned umax = QImode == mode ? 0xff : 0xffff;
560 int imax = QImode == mode ? 0x7f : 0x7fff;
561 int imin = -imax - 1;
562
563 // Testing the case range and whether it fits into the range of the
564 // (un)signed mode. This test should actually always pass because it
565 // makes no sense to have case values outside the mode range. Notice
566 // that case labels which are unreachable because they are outside the
567 // mode of the switch value (e.g. "case -1" for uint8_t) have already
568 // been thrown away by the middle-end.
569
570 if (SIGN_EXTEND == code
571 && low_idx >= imin
572 && hig_idx <= imax)
573 {
574 // ok
575 }
576 else if (ZERO_EXTEND == code
577 && low_idx >= 0
578 && (unsigned) hig_idx <= umax)
579 {
580 // ok
581 }
582 else
583 {
584 if (dump_file)
585 fprintf (dump_file, ";; Case ranges too big, giving up.\n\n");
586 return;
587 }
588
589 // Do normalization of switch value $10 and out-of-bound check in its
590 // original mode instead of in SImode. Use a newly created pseudo.
591 // This will replace insns[1..2].
592
593 start_sequence();
594
595 rtx_insn *seq1, *seq2, *last1, *last2;
596
597 rtx reg = copy_to_mode_reg (mode, xop[10]);
598
599 rtx (*gen_add)(rtx,rtx,rtx) = QImode == mode ? gen_addqi3 : gen_addhi3;
600 rtx (*gen_cmp)(rtx,rtx) = QImode == mode ? gen_cmpqi3 : gen_cmphi3;
601
602 emit_insn (gen_add (reg, reg, gen_int_mode (-low_idx, mode)));
603 emit_insn (gen_cmp (reg, gen_int_mode (num_idx, mode)));
604
605 seq1 = get_insns();
606 last1 = get_last_insn();
607 end_sequence();
608
609 emit_insn_before (seq1, insns[1]);
610
611 // After the out-of-bounds test and corresponding branch, use a
612 // 16-bit index. If QImode is used, extend it to HImode first.
613 // This will replace insns[4].
614
615 start_sequence();
616
617 if (QImode == mode)
618 reg = force_reg (HImode, gen_rtx_fmt_e (code, HImode, reg));
619
620 rtx pat_4 = AVR_3_BYTE_PC
621 ? gen_movhi (xop[7], reg)
622 : gen_addhi3 (xop[7], reg, gen_rtx_LABEL_REF (VOIDmode, xop[3]));
623
624 emit_insn (pat_4);
625
626 seq2 = get_insns();
627 last2 = get_last_insn();
628 end_sequence();
629
630 emit_insn_after (seq2, insns[4]);
631
632 if (dump_file)
633 {
634 fprintf (dump_file, ";; New insns: ");
635
636 for (rtx_insn *insn = seq1; ; insn = NEXT_INSN (insn))
637 {
638 fprintf (dump_file, "%d, ", INSN_UID (insn));
639 if (insn == last1)
640 break;
641 }
642 for (rtx_insn *insn = seq2; ; insn = NEXT_INSN (insn))
643 {
644 fprintf (dump_file, "%d%s", INSN_UID (insn),
645 insn == last2 ? ".\n\n" : ", ");
646 if (insn == last2)
647 break;
648 }
649
650 fprintf (dump_file, ";; Deleting insns: %d, %d, %d.\n\n",
651 INSN_UID (insns[1]), INSN_UID (insns[2]), INSN_UID (insns[4]));
652 }
653
654 // Pseudodelete the SImode and subreg of SImode insns. We don't care
655 // about the extension insns[0]: Its result is now unused and other
656 // passes will clean it up.
657
658 SET_INSN_DELETED (insns[1]);
659 SET_INSN_DELETED (insns[2]);
660 SET_INSN_DELETED (insns[4]);
661 }
662
663
664 void
avr_rest_of_handle_casesi(function * func)665 avr_pass_casesi::avr_rest_of_handle_casesi (function *func)
666 {
667 basic_block bb;
668
669 FOR_EACH_BB_FN (bb, func)
670 {
671 rtx_insn *insn, *insns[6];
672
673 FOR_BB_INSNS (bb, insn)
674 {
675 if (avr_is_casesi_sequence (bb, insn, insns))
676 {
677 avr_optimize_casesi (insns, recog_data.operand);
678 }
679 }
680 }
681 }
682
683
684 /* Set `avr_arch' as specified by `-mmcu='.
685 Return true on success. */
686
687 static bool
avr_set_core_architecture(void)688 avr_set_core_architecture (void)
689 {
690 /* Search for mcu core architecture. */
691
692 if (!avr_mmcu)
693 avr_mmcu = AVR_MMCU_DEFAULT;
694
695 avr_arch = &avr_arch_types[0];
696
697 for (const avr_mcu_t *mcu = avr_mcu_types; ; mcu++)
698 {
699 if (mcu->name == NULL)
700 {
701 /* Reached the end of `avr_mcu_types'. This should actually never
702 happen as options are provided by device-specs. It could be a
703 typo in a device-specs or calling the compiler proper directly
704 with -mmcu=<device>. */
705
706 error ("unknown core architecture %qs specified with %qs",
707 avr_mmcu, "-mmcu=");
708 avr_inform_core_architectures ();
709 break;
710 }
711 else if (strcmp (mcu->name, avr_mmcu) == 0
712 // Is this a proper architecture ?
713 && mcu->macro == NULL)
714 {
715 avr_arch = &avr_arch_types[mcu->arch_id];
716 if (avr_n_flash < 0)
717 avr_n_flash = 1 + (mcu->flash_size - 1) / 0x10000;
718
719 return true;
720 }
721 }
722
723 return false;
724 }
725
726
727 /* Implement `TARGET_OPTION_OVERRIDE'. */
728
729 static void
avr_option_override(void)730 avr_option_override (void)
731 {
732 /* caller-save.c looks for call-clobbered hard registers that are assigned
733 to pseudos that cross calls and tries so save-restore them around calls
734 in order to reduce the number of stack slots needed.
735
736 This might lead to situations where reload is no more able to cope
737 with the challenge of AVR's very few address registers and fails to
738 perform the requested spills. */
739
740 if (avr_strict_X)
741 flag_caller_saves = 0;
742
743 /* Unwind tables currently require a frame pointer for correctness,
744 see toplev.c:process_options(). */
745
746 if ((flag_unwind_tables
747 || flag_non_call_exceptions
748 || flag_asynchronous_unwind_tables)
749 && !ACCUMULATE_OUTGOING_ARGS)
750 {
751 flag_omit_frame_pointer = 0;
752 }
753
754 if (flag_pic == 1)
755 warning (OPT_fpic, "%<-fpic%> is not supported");
756 if (flag_pic == 2)
757 warning (OPT_fPIC, "%<-fPIC%> is not supported");
758 if (flag_pie == 1)
759 warning (OPT_fpie, "%<-fpie%> is not supported");
760 if (flag_pie == 2)
761 warning (OPT_fPIE, "%<-fPIE%> is not supported");
762
763 #if !defined (HAVE_AS_AVR_MGCCISR_OPTION)
764 avr_gasisr_prologues = 0;
765 #endif
766
767 if (!avr_set_core_architecture())
768 return;
769
770 /* Sould be set by avr-common.c */
771 gcc_assert (avr_long_double >= avr_double && avr_double >= 32);
772
773 /* RAM addresses of some SFRs common to all devices in respective arch. */
774
775 /* SREG: Status Register containing flags like I (global IRQ) */
776 avr_addr.sreg = 0x3F + avr_arch->sfr_offset;
777
778 /* RAMPZ: Address' high part when loading via ELPM */
779 avr_addr.rampz = 0x3B + avr_arch->sfr_offset;
780
781 avr_addr.rampy = 0x3A + avr_arch->sfr_offset;
782 avr_addr.rampx = 0x39 + avr_arch->sfr_offset;
783 avr_addr.rampd = 0x38 + avr_arch->sfr_offset;
784 avr_addr.ccp = (AVR_TINY ? 0x3C : 0x34) + avr_arch->sfr_offset;
785
786 /* SP: Stack Pointer (SP_H:SP_L) */
787 avr_addr.sp_l = 0x3D + avr_arch->sfr_offset;
788 avr_addr.sp_h = avr_addr.sp_l + 1;
789
790 init_machine_status = avr_init_machine_status;
791
792 avr_log_set_avr_log();
793 }
794
795 /* Function to set up the backend function structure. */
796
797 static struct machine_function *
avr_init_machine_status(void)798 avr_init_machine_status (void)
799 {
800 return ggc_cleared_alloc<machine_function> ();
801 }
802
803
804 /* Implement `INIT_EXPANDERS'. */
805 /* The function works like a singleton. */
806
807 void
avr_init_expanders(void)808 avr_init_expanders (void)
809 {
810 for (int regno = 0; regno < 32; regno ++)
811 all_regs_rtx[regno] = gen_rtx_REG (QImode, regno);
812
813 lpm_reg_rtx = all_regs_rtx[LPM_REGNO];
814 tmp_reg_rtx = all_regs_rtx[AVR_TMP_REGNO];
815 zero_reg_rtx = all_regs_rtx[AVR_ZERO_REGNO];
816
817 lpm_addr_reg_rtx = gen_rtx_REG (HImode, REG_Z);
818
819 sreg_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.sreg));
820 rampd_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampd));
821 rampx_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampx));
822 rampy_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampy));
823 rampz_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampz));
824
825 xstring_empty = gen_rtx_CONST_STRING (VOIDmode, "");
826 xstring_e = gen_rtx_CONST_STRING (VOIDmode, "e");
827
828 /* TINY core does not have regs r10-r16, but avr-dimode.md expects them
829 to be present */
830 if (AVR_TINY)
831 avr_have_dimode = false;
832 }
833
834
835 /* Implement `REGNO_REG_CLASS'. */
836 /* Return register class for register R. */
837
838 enum reg_class
avr_regno_reg_class(int r)839 avr_regno_reg_class (int r)
840 {
841 static const enum reg_class reg_class_tab[] =
842 {
843 R0_REG,
844 /* r1 - r15 */
845 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
846 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
847 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
848 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
849 /* r16 - r23 */
850 SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
851 SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
852 /* r24, r25 */
853 ADDW_REGS, ADDW_REGS,
854 /* X: r26, 27 */
855 POINTER_X_REGS, POINTER_X_REGS,
856 /* Y: r28, r29 */
857 POINTER_Y_REGS, POINTER_Y_REGS,
858 /* Z: r30, r31 */
859 POINTER_Z_REGS, POINTER_Z_REGS,
860 /* SP: SPL, SPH */
861 STACK_REG, STACK_REG
862 };
863
864 if (r <= 33)
865 return reg_class_tab[r];
866
867 return ALL_REGS;
868 }
869
870
871 /* Implement `TARGET_SCALAR_MODE_SUPPORTED_P'. */
872
873 static bool
avr_scalar_mode_supported_p(scalar_mode mode)874 avr_scalar_mode_supported_p (scalar_mode mode)
875 {
876 if (ALL_FIXED_POINT_MODE_P (mode))
877 return true;
878
879 if (PSImode == mode)
880 return true;
881
882 return default_scalar_mode_supported_p (mode);
883 }
884
885
886 /* Return TRUE if DECL is a VAR_DECL located in flash and FALSE, otherwise. */
887
888 static bool
avr_decl_flash_p(tree decl)889 avr_decl_flash_p (tree decl)
890 {
891 if (TREE_CODE (decl) != VAR_DECL
892 || TREE_TYPE (decl) == error_mark_node)
893 {
894 return false;
895 }
896
897 return !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (decl)));
898 }
899
900
901 /* Return TRUE if DECL is a VAR_DECL located in the 24-bit flash
902 address space and FALSE, otherwise. */
903
904 static bool
avr_decl_memx_p(tree decl)905 avr_decl_memx_p (tree decl)
906 {
907 if (TREE_CODE (decl) != VAR_DECL
908 || TREE_TYPE (decl) == error_mark_node)
909 {
910 return false;
911 }
912
913 return (ADDR_SPACE_MEMX == TYPE_ADDR_SPACE (TREE_TYPE (decl)));
914 }
915
916
917 /* Return TRUE if X is a MEM rtx located in flash and FALSE, otherwise. */
918
919 bool
avr_mem_flash_p(rtx x)920 avr_mem_flash_p (rtx x)
921 {
922 return (MEM_P (x)
923 && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x)));
924 }
925
926
927 /* Return TRUE if X is a MEM rtx located in the 24-bit flash
928 address space and FALSE, otherwise. */
929
930 bool
avr_mem_memx_p(rtx x)931 avr_mem_memx_p (rtx x)
932 {
933 return (MEM_P (x)
934 && ADDR_SPACE_MEMX == MEM_ADDR_SPACE (x));
935 }
936
937
938 /* A helper for the subsequent function attribute used to dig for
939 attribute 'name' in a FUNCTION_DECL or FUNCTION_TYPE */
940
941 static inline int
avr_lookup_function_attribute1(const_tree func,const char * name)942 avr_lookup_function_attribute1 (const_tree func, const char *name)
943 {
944 if (FUNCTION_DECL == TREE_CODE (func))
945 {
946 if (NULL_TREE != lookup_attribute (name, DECL_ATTRIBUTES (func)))
947 {
948 return true;
949 }
950
951 func = TREE_TYPE (func);
952 }
953
954 gcc_assert (TREE_CODE (func) == FUNCTION_TYPE
955 || TREE_CODE (func) == METHOD_TYPE);
956
957 return NULL_TREE != lookup_attribute (name, TYPE_ATTRIBUTES (func));
958 }
959
960 /* Return nonzero if FUNC is a naked function. */
961
962 static int
avr_naked_function_p(tree func)963 avr_naked_function_p (tree func)
964 {
965 return avr_lookup_function_attribute1 (func, "naked");
966 }
967
968 /* Return nonzero if FUNC is an interrupt function as specified
969 by the "interrupt" attribute. */
970
971 static int
avr_interrupt_function_p(tree func)972 avr_interrupt_function_p (tree func)
973 {
974 return avr_lookup_function_attribute1 (func, "interrupt");
975 }
976
977 /* Return nonzero if FUNC is a signal function as specified
978 by the "signal" attribute. */
979
980 static int
avr_signal_function_p(tree func)981 avr_signal_function_p (tree func)
982 {
983 return avr_lookup_function_attribute1 (func, "signal");
984 }
985
986 /* Return nonzero if FUNC is an OS_task function. */
987
988 static int
avr_OS_task_function_p(tree func)989 avr_OS_task_function_p (tree func)
990 {
991 return avr_lookup_function_attribute1 (func, "OS_task");
992 }
993
994 /* Return nonzero if FUNC is an OS_main function. */
995
996 static int
avr_OS_main_function_p(tree func)997 avr_OS_main_function_p (tree func)
998 {
999 return avr_lookup_function_attribute1 (func, "OS_main");
1000 }
1001
1002
1003 /* Return nonzero if FUNC is a no_gccisr function as specified
1004 by the "no_gccisr" attribute. */
1005
1006 static int
avr_no_gccisr_function_p(tree func)1007 avr_no_gccisr_function_p (tree func)
1008 {
1009 return avr_lookup_function_attribute1 (func, "no_gccisr");
1010 }
1011
1012 /* Implement `TARGET_SET_CURRENT_FUNCTION'. */
1013 /* Sanity cheching for above function attributes. */
1014
1015 static void
avr_set_current_function(tree decl)1016 avr_set_current_function (tree decl)
1017 {
1018 if (decl == NULL_TREE
1019 || current_function_decl == NULL_TREE
1020 || current_function_decl == error_mark_node
1021 || ! cfun->machine
1022 || cfun->machine->attributes_checked_p)
1023 return;
1024
1025 location_t loc = DECL_SOURCE_LOCATION (decl);
1026
1027 cfun->machine->is_naked = avr_naked_function_p (decl);
1028 cfun->machine->is_signal = avr_signal_function_p (decl);
1029 cfun->machine->is_interrupt = avr_interrupt_function_p (decl);
1030 cfun->machine->is_OS_task = avr_OS_task_function_p (decl);
1031 cfun->machine->is_OS_main = avr_OS_main_function_p (decl);
1032 cfun->machine->is_no_gccisr = avr_no_gccisr_function_p (decl);
1033
1034 const char *isr = cfun->machine->is_interrupt ? "interrupt" : "signal";
1035
1036 /* Too much attributes make no sense as they request conflicting features. */
1037
1038 if (cfun->machine->is_OS_task
1039 && (cfun->machine->is_signal || cfun->machine->is_interrupt))
1040 error_at (loc, "function attributes %qs and %qs are mutually exclusive",
1041 "OS_task", isr);
1042
1043 if (cfun->machine->is_OS_main
1044 && (cfun->machine->is_signal || cfun->machine->is_interrupt))
1045 error_at (loc, "function attributes %qs and %qs are mutually exclusive",
1046 "OS_main", isr);
1047
1048 if (cfun->machine->is_interrupt || cfun->machine->is_signal)
1049 {
1050 tree args = TYPE_ARG_TYPES (TREE_TYPE (decl));
1051 tree ret = TREE_TYPE (TREE_TYPE (decl));
1052 const char *name;
1053
1054 name = DECL_ASSEMBLER_NAME_SET_P (decl)
1055 ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))
1056 : IDENTIFIER_POINTER (DECL_NAME (decl));
1057
1058 /* Skip a leading '*' that might still prefix the assembler name,
1059 e.g. in non-LTO runs. */
1060
1061 name = default_strip_name_encoding (name);
1062
1063 /* Interrupt handlers must be void __vector (void) functions. */
1064
1065 if (args && TREE_CODE (TREE_VALUE (args)) != VOID_TYPE)
1066 error_at (loc, "%qs function cannot have arguments", isr);
1067
1068 if (TREE_CODE (ret) != VOID_TYPE)
1069 error_at (loc, "%qs function cannot return a value", isr);
1070
1071 #if defined WITH_AVRLIBC
1072 /* Silently ignore 'signal' if 'interrupt' is present. AVR-LibC startet
1073 using this when it switched from SIGNAL and INTERRUPT to ISR. */
1074
1075 if (cfun->machine->is_interrupt)
1076 cfun->machine->is_signal = 0;
1077
1078 /* If the function has the 'signal' or 'interrupt' attribute, ensure
1079 that the name of the function is "__vector_NN" so as to catch
1080 when the user misspells the vector name. */
1081
1082 if (!STR_PREFIX_P (name, "__vector"))
1083 warning_at (loc, OPT_Wmisspelled_isr, "%qs appears to be a misspelled "
1084 "%qs handler, missing %<__vector%> prefix", name, isr);
1085 #endif // AVR-LibC naming conventions
1086 }
1087
1088 #if defined WITH_AVRLIBC
1089 // Common problem is using "ISR" without first including avr/interrupt.h.
1090 const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
1091 name = default_strip_name_encoding (name);
1092 if (strcmp ("ISR", name) == 0
1093 || strcmp ("INTERRUPT", name) == 0
1094 || strcmp ("SIGNAL", name) == 0)
1095 {
1096 warning_at (loc, OPT_Wmisspelled_isr, "%qs is a reserved identifier"
1097 " in AVR-LibC. Consider %<#include <avr/interrupt.h>%>"
1098 " before using the %qs macro", name, name);
1099 }
1100 #endif // AVR-LibC naming conventions
1101
1102 /* Don't print the above diagnostics more than once. */
1103
1104 cfun->machine->attributes_checked_p = 1;
1105 }
1106
1107
1108 /* Implement `ACCUMULATE_OUTGOING_ARGS'. */
1109
1110 int
avr_accumulate_outgoing_args(void)1111 avr_accumulate_outgoing_args (void)
1112 {
1113 if (!cfun)
1114 return TARGET_ACCUMULATE_OUTGOING_ARGS;
1115
1116 /* FIXME: For setjmp and in avr_builtin_setjmp_frame_value we don't know
1117 what offset is correct. In some cases it is relative to
1118 virtual_outgoing_args_rtx and in others it is relative to
1119 virtual_stack_vars_rtx. For example code see
1120 gcc.c-torture/execute/built-in-setjmp.c
1121 gcc.c-torture/execute/builtins/sprintf-chk.c */
1122
1123 return (TARGET_ACCUMULATE_OUTGOING_ARGS
1124 && !(cfun->calls_setjmp
1125 || cfun->has_nonlocal_label));
1126 }
1127
1128
1129 /* Report contribution of accumulated outgoing arguments to stack size. */
1130
1131 static inline int
avr_outgoing_args_size(void)1132 avr_outgoing_args_size (void)
1133 {
1134 return (ACCUMULATE_OUTGOING_ARGS
1135 ? (HOST_WIDE_INT) crtl->outgoing_args_size : 0);
1136 }
1137
1138
1139 /* Implement TARGET_STARTING_FRAME_OFFSET. */
1140 /* This is the offset from the frame pointer register to the first stack slot
1141 that contains a variable living in the frame. */
1142
1143 static HOST_WIDE_INT
avr_starting_frame_offset(void)1144 avr_starting_frame_offset (void)
1145 {
1146 return 1 + avr_outgoing_args_size ();
1147 }
1148
1149
1150 /* Return the number of hard registers to push/pop in the prologue/epilogue
1151 of the current function, and optionally store these registers in SET. */
1152
1153 static int
avr_regs_to_save(HARD_REG_SET * set)1154 avr_regs_to_save (HARD_REG_SET *set)
1155 {
1156 int count;
1157 int int_or_sig_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1158
1159 if (set)
1160 CLEAR_HARD_REG_SET (*set);
1161 count = 0;
1162
1163 /* No need to save any registers if the function never returns or
1164 has the "OS_task" or "OS_main" attribute. */
1165
1166 if (TREE_THIS_VOLATILE (current_function_decl)
1167 || cfun->machine->is_OS_task
1168 || cfun->machine->is_OS_main)
1169 return 0;
1170
1171 for (int reg = 0; reg < 32; reg++)
1172 {
1173 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
1174 any global register variables. */
1175
1176 if (fixed_regs[reg])
1177 continue;
1178
1179 if ((int_or_sig_p && !crtl->is_leaf && call_used_or_fixed_reg_p (reg))
1180 || (df_regs_ever_live_p (reg)
1181 && (int_or_sig_p || !call_used_or_fixed_reg_p (reg))
1182 /* Don't record frame pointer registers here. They are treated
1183 indivitually in prologue. */
1184 && !(frame_pointer_needed
1185 && (reg == REG_Y || reg == REG_Y + 1))))
1186 {
1187 if (set)
1188 SET_HARD_REG_BIT (*set, reg);
1189 count++;
1190 }
1191 }
1192 return count;
1193 }
1194
1195
1196 /* Implement `TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS' */
1197
1198 static bool
avr_allocate_stack_slots_for_args(void)1199 avr_allocate_stack_slots_for_args (void)
1200 {
1201 return !cfun->machine->is_naked;
1202 }
1203
1204
1205 /* Return true if register FROM can be eliminated via register TO. */
1206
1207 static bool
avr_can_eliminate(const int from ATTRIBUTE_UNUSED,const int to)1208 avr_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
1209 {
1210 return ((frame_pointer_needed && to == FRAME_POINTER_REGNUM)
1211 || !frame_pointer_needed);
1212 }
1213
1214
1215 /* Implement `TARGET_WARN_FUNC_RETURN'. */
1216
1217 static bool
avr_warn_func_return(tree decl)1218 avr_warn_func_return (tree decl)
1219 {
1220 /* Naked functions are implemented entirely in assembly, including the
1221 return sequence, so suppress warnings about this. */
1222
1223 return !avr_naked_function_p (decl);
1224 }
1225
1226 /* Compute offset between arg_pointer and frame_pointer. */
1227
1228 int
avr_initial_elimination_offset(int from,int to)1229 avr_initial_elimination_offset (int from, int to)
1230 {
1231 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
1232 return 0;
1233 else
1234 {
1235 int offset = frame_pointer_needed ? 2 : 0;
1236 int avr_pc_size = AVR_HAVE_EIJMP_EICALL ? 3 : 2;
1237
1238 // If FROM is ARG_POINTER_REGNUM, we are not in an ISR as ISRs
1239 // might not have arguments. Hence the following is not affected
1240 // by gasisr prologues.
1241 offset += avr_regs_to_save (NULL);
1242 return (get_frame_size () + avr_outgoing_args_size()
1243 + avr_pc_size + 1 + offset);
1244 }
1245 }
1246
1247
1248 /* Helper for the function below. */
1249
1250 static void
avr_adjust_type_node(tree * node,machine_mode mode,int sat_p)1251 avr_adjust_type_node (tree *node, machine_mode mode, int sat_p)
1252 {
1253 *node = make_node (FIXED_POINT_TYPE);
1254 TYPE_SATURATING (*node) = sat_p;
1255 TYPE_UNSIGNED (*node) = UNSIGNED_FIXED_POINT_MODE_P (mode);
1256 TYPE_IBIT (*node) = GET_MODE_IBIT (mode);
1257 TYPE_FBIT (*node) = GET_MODE_FBIT (mode);
1258 TYPE_PRECISION (*node) = GET_MODE_BITSIZE (mode);
1259 SET_TYPE_ALIGN (*node, 8);
1260 SET_TYPE_MODE (*node, mode);
1261
1262 layout_type (*node);
1263 }
1264
1265
1266 /* Implement `TARGET_BUILD_BUILTIN_VA_LIST'. */
1267
1268 static tree
avr_build_builtin_va_list(void)1269 avr_build_builtin_va_list (void)
1270 {
1271 /* avr-modes.def adjusts [U]TA to be 64-bit modes with 48 fractional bits.
1272 This is more appropriate for the 8-bit machine AVR than 128-bit modes.
1273 The ADJUST_IBIT/FBIT are handled in toplev:init_adjust_machine_modes()
1274 which is auto-generated by genmodes, but the compiler assigns [U]DAmode
1275 to the long long accum modes instead of the desired [U]TAmode.
1276
1277 Fix this now, right after node setup in tree.c:build_common_tree_nodes().
1278 This must run before c-cppbuiltin.c:builtin_define_fixed_point_constants()
1279 which built-in defines macros like __ULLACCUM_FBIT__ that are used by
1280 libgcc to detect IBIT and FBIT. */
1281
1282 avr_adjust_type_node (&ta_type_node, TAmode, 0);
1283 avr_adjust_type_node (&uta_type_node, UTAmode, 0);
1284 avr_adjust_type_node (&sat_ta_type_node, TAmode, 1);
1285 avr_adjust_type_node (&sat_uta_type_node, UTAmode, 1);
1286
1287 unsigned_long_long_accum_type_node = uta_type_node;
1288 long_long_accum_type_node = ta_type_node;
1289 sat_unsigned_long_long_accum_type_node = sat_uta_type_node;
1290 sat_long_long_accum_type_node = sat_ta_type_node;
1291
1292 /* Dispatch to the default handler. */
1293
1294 return std_build_builtin_va_list ();
1295 }
1296
1297
1298 /* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3-byte PC).
1299 This is return address of function. */
1300
1301 rtx
avr_return_addr_rtx(int count,rtx tem)1302 avr_return_addr_rtx (int count, rtx tem)
1303 {
1304 rtx r;
1305
1306 /* Can only return this function's return address. Others not supported. */
1307 if (count)
1308 return NULL;
1309
1310 if (AVR_3_BYTE_PC)
1311 {
1312 r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+2");
1313 warning (0, "%<builtin_return_address%> contains only 2 bytes"
1314 " of address");
1315 }
1316 else
1317 r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+1");
1318
1319 cfun->machine->use_L__stack_usage = 1;
1320
1321 r = gen_rtx_PLUS (Pmode, tem, r);
1322 r = gen_frame_mem (Pmode, memory_address (Pmode, r));
1323 r = gen_rtx_ROTATE (HImode, r, GEN_INT (8));
1324 return r;
1325 }
1326
1327 /* Return 1 if the function epilogue is just a single "ret". */
1328
1329 int
avr_simple_epilogue(void)1330 avr_simple_epilogue (void)
1331 {
1332 return (! frame_pointer_needed
1333 && get_frame_size () == 0
1334 && avr_outgoing_args_size() == 0
1335 && avr_regs_to_save (NULL) == 0
1336 && ! cfun->machine->is_interrupt
1337 && ! cfun->machine->is_signal
1338 && ! cfun->machine->is_naked
1339 && ! TREE_THIS_VOLATILE (current_function_decl));
1340 }
1341
1342 /* This function checks sequence of live registers. */
1343
1344 static int
sequent_regs_live(void)1345 sequent_regs_live (void)
1346 {
1347 int live_seq = 0;
1348 int cur_seq = 0;
1349
1350 for (int reg = 0; reg <= LAST_CALLEE_SAVED_REG; ++reg)
1351 {
1352 if (fixed_regs[reg])
1353 {
1354 /* Don't recognize sequences that contain global register
1355 variables. */
1356
1357 if (live_seq != 0)
1358 return 0;
1359 else
1360 continue;
1361 }
1362
1363 if (!call_used_or_fixed_reg_p (reg))
1364 {
1365 if (df_regs_ever_live_p (reg))
1366 {
1367 ++live_seq;
1368 ++cur_seq;
1369 }
1370 else
1371 cur_seq = 0;
1372 }
1373 }
1374
1375 if (!frame_pointer_needed)
1376 {
1377 if (df_regs_ever_live_p (REG_Y))
1378 {
1379 ++live_seq;
1380 ++cur_seq;
1381 }
1382 else
1383 cur_seq = 0;
1384
1385 if (df_regs_ever_live_p (REG_Y + 1))
1386 {
1387 ++live_seq;
1388 ++cur_seq;
1389 }
1390 else
1391 cur_seq = 0;
1392 }
1393 else
1394 {
1395 cur_seq += 2;
1396 live_seq += 2;
1397 }
1398 return (cur_seq == live_seq) ? live_seq : 0;
1399 }
1400
1401 namespace {
1402 static const pass_data avr_pass_data_pre_proep =
1403 {
1404 RTL_PASS, // type
1405 "", // name (will be patched)
1406 OPTGROUP_NONE, // optinfo_flags
1407 TV_DF_SCAN, // tv_id
1408 0, // properties_required
1409 0, // properties_provided
1410 0, // properties_destroyed
1411 0, // todo_flags_start
1412 0 // todo_flags_finish
1413 };
1414
1415
1416 class avr_pass_pre_proep : public rtl_opt_pass
1417 {
1418 public:
avr_pass_pre_proep(gcc::context * ctxt,const char * name)1419 avr_pass_pre_proep (gcc::context *ctxt, const char *name)
1420 : rtl_opt_pass (avr_pass_data_pre_proep, ctxt)
1421 {
1422 this->name = name;
1423 }
1424
1425 void compute_maybe_gasisr (function*);
1426
execute(function * fun)1427 virtual unsigned int execute (function *fun)
1428 {
1429 if (avr_gasisr_prologues
1430 // Whether this function is an ISR worth scanning at all.
1431 && !fun->machine->is_no_gccisr
1432 && (fun->machine->is_interrupt
1433 || fun->machine->is_signal)
1434 && !cfun->machine->is_naked
1435 // Paranoia: Non-local gotos and labels that might escape.
1436 && !cfun->calls_setjmp
1437 && !cfun->has_nonlocal_label
1438 && !cfun->has_forced_label_in_static)
1439 {
1440 compute_maybe_gasisr (fun);
1441 }
1442
1443 return 0;
1444 }
1445
1446 }; // avr_pass_pre_proep
1447
1448 } // anon namespace
1449
1450 rtl_opt_pass*
make_avr_pass_pre_proep(gcc::context * ctxt)1451 make_avr_pass_pre_proep (gcc::context *ctxt)
1452 {
1453 return new avr_pass_pre_proep (ctxt, "avr-pre-proep");
1454 }
1455
1456
1457 /* Set fun->machine->gasisr.maybe provided we don't find anything that
1458 prohibits GAS generating parts of ISR prologues / epilogues for us. */
1459
1460 void
compute_maybe_gasisr(function * fun)1461 avr_pass_pre_proep::compute_maybe_gasisr (function *fun)
1462 {
1463 // Don't use BB iterators so that we see JUMP_TABLE_DATA.
1464
1465 for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
1466 {
1467 // Transparent calls always use [R]CALL and are filtered out by GAS.
1468 // ISRs don't use -mcall-prologues, hence what remains to be filtered
1469 // out are open coded (tail) calls.
1470
1471 if (CALL_P (insn))
1472 return;
1473
1474 // __tablejump2__ clobbers something and is targeted by JMP so
1475 // that GAS won't see its usage.
1476
1477 if (AVR_HAVE_JMP_CALL
1478 && JUMP_TABLE_DATA_P (insn))
1479 return;
1480
1481 // Non-local gotos not seen in *FUN.
1482
1483 if (JUMP_P (insn)
1484 && find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
1485 return;
1486 }
1487
1488 fun->machine->gasisr.maybe = 1;
1489 }
1490
1491
1492 /* Obtain the length sequence of insns. */
1493
1494 int
get_sequence_length(rtx_insn * insns)1495 get_sequence_length (rtx_insn *insns)
1496 {
1497 int length = 0;
1498
1499 for (rtx_insn *insn = insns; insn; insn = NEXT_INSN (insn))
1500 length += get_attr_length (insn);
1501
1502 return length;
1503 }
1504
1505
1506 /* Implement `INCOMING_RETURN_ADDR_RTX'. */
1507
1508 rtx
avr_incoming_return_addr_rtx(void)1509 avr_incoming_return_addr_rtx (void)
1510 {
1511 /* The return address is at the top of the stack. Note that the push
1512 was via post-decrement, which means the actual address is off by one. */
1513 return gen_frame_mem (HImode, plus_constant (Pmode, stack_pointer_rtx, 1));
1514 }
1515
1516
1517 /* Unset a bit in *SET. If successful, return the respective bit number.
1518 Otherwise, return -1 and *SET is unaltered. */
1519
1520 static int
avr_hregs_split_reg(HARD_REG_SET * set)1521 avr_hregs_split_reg (HARD_REG_SET *set)
1522 {
1523 for (int regno = 0; regno < 32; regno++)
1524 if (TEST_HARD_REG_BIT (*set, regno))
1525 {
1526 // Don't remove a register from *SET which might indicate that
1527 // some RAMP* register might need ISR prologue / epilogue treatment.
1528
1529 if (AVR_HAVE_RAMPX
1530 && (REG_X == regno || REG_X + 1 == regno)
1531 && TEST_HARD_REG_BIT (*set, REG_X)
1532 && TEST_HARD_REG_BIT (*set, REG_X + 1))
1533 continue;
1534
1535 if (AVR_HAVE_RAMPY
1536 && !frame_pointer_needed
1537 && (REG_Y == regno || REG_Y + 1 == regno)
1538 && TEST_HARD_REG_BIT (*set, REG_Y)
1539 && TEST_HARD_REG_BIT (*set, REG_Y + 1))
1540 continue;
1541
1542 if (AVR_HAVE_RAMPZ
1543 && (REG_Z == regno || REG_Z + 1 == regno)
1544 && TEST_HARD_REG_BIT (*set, REG_Z)
1545 && TEST_HARD_REG_BIT (*set, REG_Z + 1))
1546 continue;
1547
1548 CLEAR_HARD_REG_BIT (*set, regno);
1549 return regno;
1550 }
1551
1552 return -1;
1553 }
1554
1555
1556 /* Helper for expand_prologue. Emit a push of a byte register. */
1557
1558 static void
emit_push_byte(unsigned regno,bool frame_related_p)1559 emit_push_byte (unsigned regno, bool frame_related_p)
1560 {
1561 rtx mem, reg;
1562 rtx_insn *insn;
1563
1564 mem = gen_rtx_POST_DEC (HImode, stack_pointer_rtx);
1565 mem = gen_frame_mem (QImode, mem);
1566 reg = gen_rtx_REG (QImode, regno);
1567
1568 insn = emit_insn (gen_rtx_SET (mem, reg));
1569 if (frame_related_p)
1570 RTX_FRAME_RELATED_P (insn) = 1;
1571
1572 cfun->machine->stack_usage++;
1573 }
1574
1575
1576 /* Helper for expand_prologue. Emit a push of a SFR via register TREG.
1577 SFR is a MEM representing the memory location of the SFR.
1578 If CLR_P then clear the SFR after the push using zero_reg. */
1579
1580 static void
emit_push_sfr(rtx sfr,bool frame_related_p,bool clr_p,int treg)1581 emit_push_sfr (rtx sfr, bool frame_related_p, bool clr_p, int treg)
1582 {
1583 rtx_insn *insn;
1584
1585 gcc_assert (MEM_P (sfr));
1586
1587 /* IN treg, IO(SFR) */
1588 insn = emit_move_insn (all_regs_rtx[treg], sfr);
1589 if (frame_related_p)
1590 RTX_FRAME_RELATED_P (insn) = 1;
1591
1592 /* PUSH treg */
1593 emit_push_byte (treg, frame_related_p);
1594
1595 if (clr_p)
1596 {
1597 /* OUT IO(SFR), __zero_reg__ */
1598 insn = emit_move_insn (sfr, const0_rtx);
1599 if (frame_related_p)
1600 RTX_FRAME_RELATED_P (insn) = 1;
1601 }
1602 }
1603
1604 static void
avr_prologue_setup_frame(HOST_WIDE_INT size,HARD_REG_SET set)1605 avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
1606 {
1607 rtx_insn *insn;
1608 bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1609 int live_seq = sequent_regs_live ();
1610
1611 HOST_WIDE_INT size_max
1612 = (HOST_WIDE_INT) GET_MODE_MASK (AVR_HAVE_8BIT_SP ? QImode : Pmode);
1613
1614 bool minimize = (TARGET_CALL_PROLOGUES
1615 && size < size_max
1616 && live_seq
1617 && !isr_p
1618 && !cfun->machine->is_OS_task
1619 && !cfun->machine->is_OS_main
1620 && !AVR_TINY);
1621
1622 if (minimize
1623 && (frame_pointer_needed
1624 || avr_outgoing_args_size() > 8
1625 || (AVR_2_BYTE_PC && live_seq > 6)
1626 || live_seq > 7))
1627 {
1628 rtx pattern;
1629 int first_reg, reg, offset;
1630
1631 emit_move_insn (gen_rtx_REG (HImode, REG_X),
1632 gen_int_mode (size, HImode));
1633
1634 pattern = gen_call_prologue_saves (gen_int_mode (live_seq, HImode),
1635 gen_int_mode (live_seq+size, HImode));
1636 insn = emit_insn (pattern);
1637 RTX_FRAME_RELATED_P (insn) = 1;
1638
1639 /* Describe the effect of the unspec_volatile call to prologue_saves.
1640 Note that this formulation assumes that add_reg_note pushes the
1641 notes to the front. Thus we build them in the reverse order of
1642 how we want dwarf2out to process them. */
1643
1644 /* The function does always set frame_pointer_rtx, but whether that
1645 is going to be permanent in the function is frame_pointer_needed. */
1646
1647 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1648 gen_rtx_SET ((frame_pointer_needed
1649 ? frame_pointer_rtx
1650 : stack_pointer_rtx),
1651 plus_constant (Pmode, stack_pointer_rtx,
1652 -(size + live_seq))));
1653
1654 /* Note that live_seq always contains r28+r29, but the other
1655 registers to be saved are all below 18. */
1656
1657 first_reg = (LAST_CALLEE_SAVED_REG + 1) - (live_seq - 2);
1658
1659 for (reg = 29, offset = -live_seq + 1;
1660 reg >= first_reg;
1661 reg = (reg == 28 ? LAST_CALLEE_SAVED_REG : reg - 1), ++offset)
1662 {
1663 rtx m, r;
1664
1665 m = gen_rtx_MEM (QImode, plus_constant (Pmode, stack_pointer_rtx,
1666 offset));
1667 r = gen_rtx_REG (QImode, reg);
1668 add_reg_note (insn, REG_CFA_OFFSET, gen_rtx_SET (m, r));
1669 }
1670
1671 cfun->machine->stack_usage += size + live_seq;
1672 }
1673 else /* !minimize */
1674 {
1675 for (int reg = 0; reg < 32; ++reg)
1676 if (TEST_HARD_REG_BIT (set, reg))
1677 emit_push_byte (reg, true);
1678
1679 if (frame_pointer_needed
1680 && (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main)))
1681 {
1682 /* Push frame pointer. Always be consistent about the
1683 ordering of pushes -- epilogue_restores expects the
1684 register pair to be pushed low byte first. */
1685
1686 emit_push_byte (REG_Y, true);
1687 emit_push_byte (REG_Y + 1, true);
1688 }
1689
1690 if (frame_pointer_needed
1691 && size == 0)
1692 {
1693 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
1694 RTX_FRAME_RELATED_P (insn) = 1;
1695 }
1696
1697 if (size != 0)
1698 {
1699 /* Creating a frame can be done by direct manipulation of the
1700 stack or via the frame pointer. These two methods are:
1701 fp = sp
1702 fp -= size
1703 sp = fp
1704 or
1705 sp -= size
1706 fp = sp (*)
1707 the optimum method depends on function type, stack and
1708 frame size. To avoid a complex logic, both methods are
1709 tested and shortest is selected.
1710
1711 There is also the case where SIZE != 0 and no frame pointer is
1712 needed; this can occur if ACCUMULATE_OUTGOING_ARGS is on.
1713 In that case, insn (*) is not needed in that case.
1714 We use the X register as scratch. This is save because in X
1715 is call-clobbered.
1716 In an interrupt routine, the case of SIZE != 0 together with
1717 !frame_pointer_needed can only occur if the function is not a
1718 leaf function and thus X has already been saved. */
1719
1720 int irq_state = -1;
1721 HOST_WIDE_INT size_cfa = size, neg_size;
1722 rtx_insn *fp_plus_insns;
1723 rtx fp, my_fp;
1724
1725 gcc_assert (frame_pointer_needed
1726 || !isr_p
1727 || !crtl->is_leaf);
1728
1729 fp = my_fp = (frame_pointer_needed
1730 ? frame_pointer_rtx
1731 : gen_rtx_REG (Pmode, REG_X));
1732
1733 if (AVR_HAVE_8BIT_SP)
1734 {
1735 /* The high byte (r29) does not change:
1736 Prefer SUBI (1 cycle) over SBIW (2 cycles, same size). */
1737
1738 my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
1739 }
1740
1741 /* Cut down size and avoid size = 0 so that we don't run
1742 into ICE like PR52488 in the remainder. */
1743
1744 if (size > size_max)
1745 {
1746 /* Don't error so that insane code from newlib still compiles
1747 and does not break building newlib. As PR51345 is implemented
1748 now, there are multilib variants with -msp8.
1749
1750 If user wants sanity checks he can use -Wstack-usage=
1751 or similar options.
1752
1753 For CFA we emit the original, non-saturated size so that
1754 the generic machinery is aware of the real stack usage and
1755 will print the above diagnostic as expected. */
1756
1757 size = size_max;
1758 }
1759
1760 size = trunc_int_for_mode (size, GET_MODE (my_fp));
1761 neg_size = trunc_int_for_mode (-size, GET_MODE (my_fp));
1762
1763 /************ Method 1: Adjust frame pointer ************/
1764
1765 start_sequence ();
1766
1767 /* Normally, the dwarf2out frame-related-expr interpreter does
1768 not expect to have the CFA change once the frame pointer is
1769 set up. Thus, we avoid marking the move insn below and
1770 instead indicate that the entire operation is complete after
1771 the frame pointer subtraction is done. */
1772
1773 insn = emit_move_insn (fp, stack_pointer_rtx);
1774 if (frame_pointer_needed)
1775 {
1776 RTX_FRAME_RELATED_P (insn) = 1;
1777 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1778 gen_rtx_SET (fp, stack_pointer_rtx));
1779 }
1780
1781 insn = emit_move_insn (my_fp, plus_constant (GET_MODE (my_fp),
1782 my_fp, neg_size));
1783
1784 if (frame_pointer_needed)
1785 {
1786 RTX_FRAME_RELATED_P (insn) = 1;
1787 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1788 gen_rtx_SET (fp, plus_constant (Pmode, fp,
1789 -size_cfa)));
1790 }
1791
1792 /* Copy to stack pointer. Note that since we've already
1793 changed the CFA to the frame pointer this operation
1794 need not be annotated if frame pointer is needed.
1795 Always move through unspec, see PR50063.
1796 For meaning of irq_state see movhi_sp_r insn. */
1797
1798 if (cfun->machine->is_interrupt)
1799 irq_state = 1;
1800
1801 if (TARGET_NO_INTERRUPTS
1802 || cfun->machine->is_signal
1803 || cfun->machine->is_OS_main)
1804 irq_state = 0;
1805
1806 if (AVR_HAVE_8BIT_SP)
1807 irq_state = 2;
1808
1809 insn = emit_insn (gen_movhi_sp_r (stack_pointer_rtx,
1810 fp, GEN_INT (irq_state)));
1811 if (!frame_pointer_needed)
1812 {
1813 RTX_FRAME_RELATED_P (insn) = 1;
1814 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1815 gen_rtx_SET (stack_pointer_rtx,
1816 plus_constant (Pmode,
1817 stack_pointer_rtx,
1818 -size_cfa)));
1819 }
1820
1821 fp_plus_insns = get_insns ();
1822 end_sequence ();
1823
1824 /************ Method 2: Adjust Stack pointer ************/
1825
1826 /* Stack adjustment by means of RCALL . and/or PUSH __TMP_REG__
1827 can only handle specific offsets. */
1828
1829 int n_rcall = size / (AVR_3_BYTE_PC ? 3 : 2);
1830
1831 if (avr_sp_immediate_operand (gen_int_mode (-size, HImode), HImode)
1832 // Don't use more than 3 RCALLs.
1833 && n_rcall <= 3)
1834 {
1835 rtx_insn *sp_plus_insns;
1836
1837 start_sequence ();
1838
1839 insn = emit_move_insn (stack_pointer_rtx,
1840 plus_constant (Pmode, stack_pointer_rtx,
1841 -size));
1842 RTX_FRAME_RELATED_P (insn) = 1;
1843 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1844 gen_rtx_SET (stack_pointer_rtx,
1845 plus_constant (Pmode,
1846 stack_pointer_rtx,
1847 -size_cfa)));
1848 if (frame_pointer_needed)
1849 {
1850 insn = emit_move_insn (fp, stack_pointer_rtx);
1851 RTX_FRAME_RELATED_P (insn) = 1;
1852 }
1853
1854 sp_plus_insns = get_insns ();
1855 end_sequence ();
1856
1857 /************ Use shortest method ************/
1858
1859 emit_insn (get_sequence_length (sp_plus_insns)
1860 < get_sequence_length (fp_plus_insns)
1861 ? sp_plus_insns
1862 : fp_plus_insns);
1863 }
1864 else
1865 {
1866 emit_insn (fp_plus_insns);
1867 }
1868
1869 cfun->machine->stack_usage += size_cfa;
1870 } /* !minimize && size != 0 */
1871 } /* !minimize */
1872 }
1873
1874
1875 /* Output function prologue. */
1876
1877 void
avr_expand_prologue(void)1878 avr_expand_prologue (void)
1879 {
1880 HARD_REG_SET set;
1881 HOST_WIDE_INT size;
1882
1883 size = get_frame_size() + avr_outgoing_args_size();
1884
1885 cfun->machine->stack_usage = 0;
1886
1887 /* Prologue: naked. */
1888 if (cfun->machine->is_naked)
1889 {
1890 return;
1891 }
1892
1893 avr_regs_to_save (&set);
1894
1895 if (cfun->machine->is_interrupt || cfun->machine->is_signal)
1896 {
1897 int treg = AVR_TMP_REGNO;
1898 /* Enable interrupts. */
1899 if (cfun->machine->is_interrupt)
1900 emit_insn (gen_enable_interrupt ());
1901
1902 if (cfun->machine->gasisr.maybe)
1903 {
1904 /* Let GAS PR21472 emit prologue preamble for us which handles SREG,
1905 ZERO_REG and TMP_REG and one additional, optional register for
1906 us in an optimal way. This even scans through inline asm. */
1907
1908 cfun->machine->gasisr.yes = 1;
1909
1910 // The optional reg or TMP_REG if we don't need one. If we need one,
1911 // remove that reg from SET so that it's not puhed / popped twice.
1912 // We also use it below instead of TMP_REG in some places.
1913
1914 treg = avr_hregs_split_reg (&set);
1915 if (treg < 0)
1916 treg = AVR_TMP_REGNO;
1917 cfun->machine->gasisr.regno = treg;
1918
1919 // The worst case of pushes. The exact number can be inferred
1920 // at assembly time by magic expression __gcc_isr.n_pushed.
1921 cfun->machine->stack_usage += 3 + (treg != AVR_TMP_REGNO);
1922
1923 // Emit a Prologue chunk. Epilogue chunk(s) might follow.
1924 // The final Done chunk is emit by final postscan.
1925 emit_insn (gen_gasisr (GEN_INT (GASISR_Prologue), GEN_INT (treg)));
1926 }
1927 else // !TARGET_GASISR_PROLOGUES: Classic, dumb prologue preamble.
1928 {
1929 /* Push zero reg. */
1930 emit_push_byte (AVR_ZERO_REGNO, true);
1931
1932 /* Push tmp reg. */
1933 emit_push_byte (AVR_TMP_REGNO, true);
1934
1935 /* Push SREG. */
1936 /* ??? There's no dwarf2 column reserved for SREG. */
1937 emit_push_sfr (sreg_rtx, false, false /* clr */, AVR_TMP_REGNO);
1938
1939 /* Clear zero reg. */
1940 emit_move_insn (zero_reg_rtx, const0_rtx);
1941
1942 /* Prevent any attempt to delete the setting of ZERO_REG! */
1943 emit_use (zero_reg_rtx);
1944 }
1945
1946 /* Push and clear RAMPD/X/Y/Z if present and low-part register is used.
1947 ??? There are no dwarf2 columns reserved for RAMPD/X/Y/Z. */
1948
1949 if (AVR_HAVE_RAMPD)
1950 emit_push_sfr (rampd_rtx, false /* frame */, true /* clr */, treg);
1951
1952 if (AVR_HAVE_RAMPX
1953 && TEST_HARD_REG_BIT (set, REG_X)
1954 && TEST_HARD_REG_BIT (set, REG_X + 1))
1955 {
1956 emit_push_sfr (rampx_rtx, false /* frame */, true /* clr */, treg);
1957 }
1958
1959 if (AVR_HAVE_RAMPY
1960 && (frame_pointer_needed
1961 || (TEST_HARD_REG_BIT (set, REG_Y)
1962 && TEST_HARD_REG_BIT (set, REG_Y + 1))))
1963 {
1964 emit_push_sfr (rampy_rtx, false /* frame */, true /* clr */, treg);
1965 }
1966
1967 if (AVR_HAVE_RAMPZ
1968 && TEST_HARD_REG_BIT (set, REG_Z)
1969 && TEST_HARD_REG_BIT (set, REG_Z + 1))
1970 {
1971 emit_push_sfr (rampz_rtx, false /* frame */, AVR_HAVE_RAMPD, treg);
1972 }
1973 } /* is_interrupt is_signal */
1974
1975 avr_prologue_setup_frame (size, set);
1976
1977 if (flag_stack_usage_info)
1978 current_function_static_stack_size
1979 = cfun->machine->stack_usage + INCOMING_FRAME_SP_OFFSET;
1980 }
1981
1982
1983 /* Implement `TARGET_ASM_FUNCTION_END_PROLOGUE'. */
1984 /* Output summary at end of function prologue. */
1985
1986 static void
avr_asm_function_end_prologue(FILE * file)1987 avr_asm_function_end_prologue (FILE *file)
1988 {
1989 if (cfun->machine->is_naked)
1990 {
1991 fputs ("/* prologue: naked */\n", file);
1992 }
1993 else
1994 {
1995 if (cfun->machine->is_interrupt)
1996 {
1997 fputs ("/* prologue: Interrupt */\n", file);
1998 }
1999 else if (cfun->machine->is_signal)
2000 {
2001 fputs ("/* prologue: Signal */\n", file);
2002 }
2003 else
2004 fputs ("/* prologue: function */\n", file);
2005 }
2006
2007 if (ACCUMULATE_OUTGOING_ARGS)
2008 fprintf (file, "/* outgoing args size = %d */\n",
2009 avr_outgoing_args_size());
2010
2011 fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n",
2012 (HOST_WIDE_INT) get_frame_size());
2013
2014 if (!cfun->machine->gasisr.yes)
2015 {
2016 fprintf (file, "/* stack size = %d */\n", cfun->machine->stack_usage);
2017 // Create symbol stack offset so all functions have it. Add 1 to stack
2018 // usage for offset so that SP + .L__stack_offset = return address.
2019 fprintf (file, ".L__stack_usage = %d\n", cfun->machine->stack_usage);
2020 }
2021 else
2022 {
2023 int used_by_gasisr = 3 + (cfun->machine->gasisr.regno != AVR_TMP_REGNO);
2024 int to = cfun->machine->stack_usage;
2025 int from = to - used_by_gasisr;
2026 // Number of pushed regs is only known at assembly-time.
2027 fprintf (file, "/* stack size = %d...%d */\n", from , to);
2028 fprintf (file, ".L__stack_usage = %d + __gcc_isr.n_pushed\n", from);
2029 }
2030 }
2031
2032
2033 /* Implement `EPILOGUE_USES'. */
2034
2035 int
avr_epilogue_uses(int regno ATTRIBUTE_UNUSED)2036 avr_epilogue_uses (int regno ATTRIBUTE_UNUSED)
2037 {
2038 if (reload_completed
2039 && cfun->machine
2040 && (cfun->machine->is_interrupt || cfun->machine->is_signal))
2041 return 1;
2042 return 0;
2043 }
2044
2045 /* Helper for avr_expand_epilogue. Emit a pop of a byte register. */
2046
2047 static void
emit_pop_byte(unsigned regno)2048 emit_pop_byte (unsigned regno)
2049 {
2050 rtx mem, reg;
2051
2052 mem = gen_rtx_PRE_INC (HImode, stack_pointer_rtx);
2053 mem = gen_frame_mem (QImode, mem);
2054 reg = gen_rtx_REG (QImode, regno);
2055
2056 emit_insn (gen_rtx_SET (reg, mem));
2057 }
2058
2059 /* Output RTL epilogue. */
2060
2061 void
avr_expand_epilogue(bool sibcall_p)2062 avr_expand_epilogue (bool sibcall_p)
2063 {
2064 int live_seq;
2065 HARD_REG_SET set;
2066 int minimize;
2067 HOST_WIDE_INT size;
2068 bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
2069
2070 size = get_frame_size() + avr_outgoing_args_size();
2071
2072 /* epilogue: naked */
2073 if (cfun->machine->is_naked)
2074 {
2075 gcc_assert (!sibcall_p);
2076
2077 emit_jump_insn (gen_return ());
2078 return;
2079 }
2080
2081 avr_regs_to_save (&set);
2082 live_seq = sequent_regs_live ();
2083
2084 minimize = (TARGET_CALL_PROLOGUES
2085 && live_seq
2086 && !isr_p
2087 && !cfun->machine->is_OS_task
2088 && !cfun->machine->is_OS_main
2089 && !AVR_TINY);
2090
2091 if (minimize
2092 && (live_seq > 4
2093 || frame_pointer_needed
2094 || size))
2095 {
2096 /* Get rid of frame. */
2097
2098 if (!frame_pointer_needed)
2099 {
2100 emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
2101 }
2102
2103 if (size)
2104 {
2105 emit_move_insn (frame_pointer_rtx,
2106 plus_constant (Pmode, frame_pointer_rtx, size));
2107 }
2108
2109 emit_insn (gen_epilogue_restores (gen_int_mode (live_seq, HImode)));
2110 return;
2111 }
2112
2113 if (size)
2114 {
2115 /* Try two methods to adjust stack and select shortest. */
2116
2117 int irq_state = -1;
2118 rtx fp, my_fp;
2119 rtx_insn *fp_plus_insns;
2120 HOST_WIDE_INT size_max;
2121
2122 gcc_assert (frame_pointer_needed
2123 || !isr_p
2124 || !crtl->is_leaf);
2125
2126 fp = my_fp = (frame_pointer_needed
2127 ? frame_pointer_rtx
2128 : gen_rtx_REG (Pmode, REG_X));
2129
2130 if (AVR_HAVE_8BIT_SP)
2131 {
2132 /* The high byte (r29) does not change:
2133 Prefer SUBI (1 cycle) over SBIW (2 cycles). */
2134
2135 my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
2136 }
2137
2138 /* For rationale see comment in prologue generation. */
2139
2140 size_max = (HOST_WIDE_INT) GET_MODE_MASK (GET_MODE (my_fp));
2141 if (size > size_max)
2142 size = size_max;
2143 size = trunc_int_for_mode (size, GET_MODE (my_fp));
2144
2145 /********** Method 1: Adjust fp register **********/
2146
2147 start_sequence ();
2148
2149 if (!frame_pointer_needed)
2150 emit_move_insn (fp, stack_pointer_rtx);
2151
2152 emit_move_insn (my_fp, plus_constant (GET_MODE (my_fp), my_fp, size));
2153
2154 /* Copy to stack pointer. */
2155
2156 if (TARGET_NO_INTERRUPTS)
2157 irq_state = 0;
2158
2159 if (AVR_HAVE_8BIT_SP)
2160 irq_state = 2;
2161
2162 emit_insn (gen_movhi_sp_r (stack_pointer_rtx, fp,
2163 GEN_INT (irq_state)));
2164
2165 fp_plus_insns = get_insns ();
2166 end_sequence ();
2167
2168 /********** Method 2: Adjust Stack pointer **********/
2169
2170 if (avr_sp_immediate_operand (gen_int_mode (size, HImode), HImode))
2171 {
2172 rtx_insn *sp_plus_insns;
2173
2174 start_sequence ();
2175
2176 emit_move_insn (stack_pointer_rtx,
2177 plus_constant (Pmode, stack_pointer_rtx, size));
2178
2179 sp_plus_insns = get_insns ();
2180 end_sequence ();
2181
2182 /************ Use shortest method ************/
2183
2184 emit_insn (get_sequence_length (sp_plus_insns)
2185 < get_sequence_length (fp_plus_insns)
2186 ? sp_plus_insns
2187 : fp_plus_insns);
2188 }
2189 else
2190 emit_insn (fp_plus_insns);
2191 } /* size != 0 */
2192
2193 if (frame_pointer_needed
2194 && !(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
2195 {
2196 /* Restore previous frame_pointer. See avr_expand_prologue for
2197 rationale for not using pophi. */
2198
2199 emit_pop_byte (REG_Y + 1);
2200 emit_pop_byte (REG_Y);
2201 }
2202
2203 /* Restore used registers. */
2204
2205 int treg = AVR_TMP_REGNO;
2206
2207 if (isr_p
2208 && cfun->machine->gasisr.yes)
2209 {
2210 treg = cfun->machine->gasisr.regno;
2211 CLEAR_HARD_REG_BIT (set, treg);
2212 }
2213
2214 for (int reg = 31; reg >= 0; --reg)
2215 if (TEST_HARD_REG_BIT (set, reg))
2216 emit_pop_byte (reg);
2217
2218 if (isr_p)
2219 {
2220 /* Restore RAMPZ/Y/X/D using tmp_reg as scratch.
2221 The conditions to restore them must be tha same as in prologue. */
2222
2223 if (AVR_HAVE_RAMPZ
2224 && TEST_HARD_REG_BIT (set, REG_Z)
2225 && TEST_HARD_REG_BIT (set, REG_Z + 1))
2226 {
2227 emit_pop_byte (treg);
2228 emit_move_insn (rampz_rtx, all_regs_rtx[treg]);
2229 }
2230
2231 if (AVR_HAVE_RAMPY
2232 && (frame_pointer_needed
2233 || (TEST_HARD_REG_BIT (set, REG_Y)
2234 && TEST_HARD_REG_BIT (set, REG_Y + 1))))
2235 {
2236 emit_pop_byte (treg);
2237 emit_move_insn (rampy_rtx, all_regs_rtx[treg]);
2238 }
2239
2240 if (AVR_HAVE_RAMPX
2241 && TEST_HARD_REG_BIT (set, REG_X)
2242 && TEST_HARD_REG_BIT (set, REG_X + 1))
2243 {
2244 emit_pop_byte (treg);
2245 emit_move_insn (rampx_rtx, all_regs_rtx[treg]);
2246 }
2247
2248 if (AVR_HAVE_RAMPD)
2249 {
2250 emit_pop_byte (treg);
2251 emit_move_insn (rampd_rtx, all_regs_rtx[treg]);
2252 }
2253
2254 if (cfun->machine->gasisr.yes)
2255 {
2256 // Emit an Epilogue chunk.
2257 emit_insn (gen_gasisr (GEN_INT (GASISR_Epilogue),
2258 GEN_INT (cfun->machine->gasisr.regno)));
2259 }
2260 else // !TARGET_GASISR_PROLOGUES
2261 {
2262 /* Restore SREG using tmp_reg as scratch. */
2263
2264 emit_pop_byte (AVR_TMP_REGNO);
2265 emit_move_insn (sreg_rtx, tmp_reg_rtx);
2266
2267 /* Restore tmp REG. */
2268 emit_pop_byte (AVR_TMP_REGNO);
2269
2270 /* Restore zero REG. */
2271 emit_pop_byte (AVR_ZERO_REGNO);
2272 }
2273 }
2274
2275 if (!sibcall_p)
2276 emit_jump_insn (gen_return ());
2277 }
2278
2279
2280 /* Implement `TARGET_ASM_FUNCTION_BEGIN_EPILOGUE'. */
2281
2282 static void
avr_asm_function_begin_epilogue(FILE * file)2283 avr_asm_function_begin_epilogue (FILE *file)
2284 {
2285 app_disable();
2286 fprintf (file, "/* epilogue start */\n");
2287 }
2288
2289
2290 /* Implement `TARGET_CANNOT_MODITY_JUMPS_P'. */
2291
2292 static bool
avr_cannot_modify_jumps_p(void)2293 avr_cannot_modify_jumps_p (void)
2294 {
2295 /* Naked Functions must not have any instructions after
2296 their epilogue, see PR42240 */
2297
2298 if (reload_completed
2299 && cfun->machine
2300 && cfun->machine->is_naked)
2301 {
2302 return true;
2303 }
2304
2305 return false;
2306 }
2307
2308
2309 /* Implement `TARGET_MODE_DEPENDENT_ADDRESS_P'. */
2310
2311 static bool
avr_mode_dependent_address_p(const_rtx addr ATTRIBUTE_UNUSED,addr_space_t as)2312 avr_mode_dependent_address_p (const_rtx addr ATTRIBUTE_UNUSED, addr_space_t as)
2313 {
2314 /* FIXME: Non-generic addresses are not mode-dependent in themselves.
2315 This hook just serves to hack around PR rtl-optimization/52543 by
2316 claiming that non-generic addresses were mode-dependent so that
2317 lower-subreg.c will skip these addresses. lower-subreg.c sets up fake
2318 RTXes to probe SET and MEM costs and assumes that MEM is always in the
2319 generic address space which is not true. */
2320
2321 return !ADDR_SPACE_GENERIC_P (as);
2322 }
2323
2324
2325 /* Return true if rtx X is a CONST_INT, CONST or SYMBOL_REF
2326 address with the `absdata' variable attribute, i.e. respective
2327 data can be read / written by LDS / STS instruction.
2328 This is used only for AVR_TINY. */
2329
2330 static bool
avr_address_tiny_absdata_p(rtx x,machine_mode mode)2331 avr_address_tiny_absdata_p (rtx x, machine_mode mode)
2332 {
2333 if (CONST == GET_CODE (x))
2334 x = XEXP (XEXP (x, 0), 0);
2335
2336 if (SYMBOL_REF_P (x))
2337 return SYMBOL_REF_FLAGS (x) & AVR_SYMBOL_FLAG_TINY_ABSDATA;
2338
2339 if (CONST_INT_P (x)
2340 && IN_RANGE (INTVAL (x), 0, 0xc0 - GET_MODE_SIZE (mode)))
2341 return true;
2342
2343 return false;
2344 }
2345
2346
2347 /* Helper function for `avr_legitimate_address_p'. */
2348
2349 static inline bool
avr_reg_ok_for_addr_p(rtx reg,addr_space_t as,RTX_CODE outer_code,bool strict)2350 avr_reg_ok_for_addr_p (rtx reg, addr_space_t as,
2351 RTX_CODE outer_code, bool strict)
2352 {
2353 return (REG_P (reg)
2354 && (avr_regno_mode_code_ok_for_base_p (REGNO (reg), QImode,
2355 as, outer_code, UNKNOWN)
2356 || (!strict
2357 && REGNO (reg) >= FIRST_PSEUDO_REGISTER)));
2358 }
2359
2360
2361 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
2362 machine for a memory operand of mode MODE. */
2363
2364 static bool
avr_legitimate_address_p(machine_mode mode,rtx x,bool strict)2365 avr_legitimate_address_p (machine_mode mode, rtx x, bool strict)
2366 {
2367 bool ok = CONSTANT_ADDRESS_P (x);
2368
2369 switch (GET_CODE (x))
2370 {
2371 case REG:
2372 ok = avr_reg_ok_for_addr_p (x, ADDR_SPACE_GENERIC,
2373 MEM, strict);
2374
2375 if (strict
2376 && GET_MODE_SIZE (mode) > 4
2377 && REG_X == REGNO (x))
2378 {
2379 ok = false;
2380 }
2381 break;
2382
2383 case POST_INC:
2384 case PRE_DEC:
2385 ok = avr_reg_ok_for_addr_p (XEXP (x, 0), ADDR_SPACE_GENERIC,
2386 GET_CODE (x), strict);
2387 break;
2388
2389 case PLUS:
2390 {
2391 rtx reg = XEXP (x, 0);
2392 rtx op1 = XEXP (x, 1);
2393
2394 if (REG_P (reg)
2395 && CONST_INT_P (op1)
2396 && INTVAL (op1) >= 0)
2397 {
2398 bool fit = IN_RANGE (INTVAL (op1), 0, MAX_LD_OFFSET (mode));
2399
2400 if (fit)
2401 {
2402 ok = (! strict
2403 || avr_reg_ok_for_addr_p (reg, ADDR_SPACE_GENERIC,
2404 PLUS, strict));
2405
2406 if (reg == frame_pointer_rtx
2407 || reg == arg_pointer_rtx)
2408 {
2409 ok = true;
2410 }
2411 }
2412 else if (frame_pointer_needed
2413 && reg == frame_pointer_rtx)
2414 {
2415 ok = true;
2416 }
2417 }
2418 }
2419 break;
2420
2421 default:
2422 break;
2423 }
2424
2425 if (AVR_TINY
2426 && CONSTANT_ADDRESS_P (x))
2427 {
2428 /* avrtiny's load / store instructions only cover addresses 0..0xbf:
2429 IN / OUT range is 0..0x3f and LDS / STS can access 0x40..0xbf. */
2430
2431 ok = avr_address_tiny_absdata_p (x, mode);
2432 }
2433
2434 if (avr_log.legitimate_address_p)
2435 {
2436 avr_edump ("\n%?: ret=%d, mode=%m strict=%d "
2437 "reload_completed=%d reload_in_progress=%d %s:",
2438 ok, mode, strict, reload_completed, reload_in_progress,
2439 reg_renumber ? "(reg_renumber)" : "");
2440
2441 if (GET_CODE (x) == PLUS
2442 && REG_P (XEXP (x, 0))
2443 && CONST_INT_P (XEXP (x, 1))
2444 && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
2445 && reg_renumber)
2446 {
2447 avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
2448 true_regnum (XEXP (x, 0)));
2449 }
2450
2451 avr_edump ("\n%r\n", x);
2452 }
2453
2454 return ok;
2455 }
2456
2457
2458 /* Former implementation of TARGET_LEGITIMIZE_ADDRESS,
2459 now only a helper for avr_addr_space_legitimize_address. */
2460 /* Attempts to replace X with a valid
2461 memory address for an operand of mode MODE */
2462
2463 static rtx
avr_legitimize_address(rtx x,rtx oldx,machine_mode mode)2464 avr_legitimize_address (rtx x, rtx oldx, machine_mode mode)
2465 {
2466 bool big_offset_p = false;
2467
2468 x = oldx;
2469
2470 if (AVR_TINY)
2471 {
2472 if (CONSTANT_ADDRESS_P (x)
2473 && ! avr_address_tiny_absdata_p (x, mode))
2474 {
2475 x = force_reg (Pmode, x);
2476 }
2477 }
2478
2479 if (GET_CODE (oldx) == PLUS
2480 && REG_P (XEXP (oldx, 0)))
2481 {
2482 if (REG_P (XEXP (oldx, 1)))
2483 x = force_reg (GET_MODE (oldx), oldx);
2484 else if (CONST_INT_P (XEXP (oldx, 1)))
2485 {
2486 int offs = INTVAL (XEXP (oldx, 1));
2487 if (frame_pointer_rtx != XEXP (oldx, 0)
2488 && offs > MAX_LD_OFFSET (mode))
2489 {
2490 big_offset_p = true;
2491 x = force_reg (GET_MODE (oldx), oldx);
2492 }
2493 }
2494 }
2495
2496 if (avr_log.legitimize_address)
2497 {
2498 avr_edump ("\n%?: mode=%m\n %r\n", mode, oldx);
2499
2500 if (x != oldx)
2501 avr_edump (" %s --> %r\n", big_offset_p ? "(big offset)" : "", x);
2502 }
2503
2504 return x;
2505 }
2506
2507
2508 /* Implement `LEGITIMIZE_RELOAD_ADDRESS'. */
2509 /* This will allow register R26/27 to be used where it is no worse than normal
2510 base pointers R28/29 or R30/31. For example, if base offset is greater
2511 than 63 bytes or for R++ or --R addressing. */
2512
2513 rtx
avr_legitimize_reload_address(rtx * px,machine_mode mode,int opnum,int type,int addr_type,int ind_levels ATTRIBUTE_UNUSED,rtx (* mk_memloc)(rtx,int))2514 avr_legitimize_reload_address (rtx *px, machine_mode mode,
2515 int opnum, int type, int addr_type,
2516 int ind_levels ATTRIBUTE_UNUSED,
2517 rtx (*mk_memloc)(rtx,int))
2518 {
2519 rtx x = *px;
2520
2521 if (avr_log.legitimize_reload_address)
2522 avr_edump ("\n%?:%m %r\n", mode, x);
2523
2524 if (1 && (GET_CODE (x) == POST_INC
2525 || GET_CODE (x) == PRE_DEC))
2526 {
2527 push_reload (XEXP (x, 0), XEXP (x, 0), &XEXP (x, 0), &XEXP (x, 0),
2528 POINTER_REGS, GET_MODE (x), GET_MODE (x), 0, 0,
2529 opnum, RELOAD_OTHER);
2530
2531 if (avr_log.legitimize_reload_address)
2532 avr_edump (" RCLASS.1 = %R\n IN = %r\n OUT = %r\n",
2533 POINTER_REGS, XEXP (x, 0), XEXP (x, 0));
2534
2535 return x;
2536 }
2537
2538 if (GET_CODE (x) == PLUS
2539 && REG_P (XEXP (x, 0))
2540 && reg_equiv_constant (REGNO (XEXP (x, 0))) == 0
2541 && CONST_INT_P (XEXP (x, 1))
2542 && INTVAL (XEXP (x, 1)) >= 1)
2543 {
2544 bool fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
2545
2546 if (fit)
2547 {
2548 if (reg_equiv_address (REGNO (XEXP (x, 0))) != 0)
2549 {
2550 int regno = REGNO (XEXP (x, 0));
2551 rtx mem = mk_memloc (x, regno);
2552
2553 push_reload (XEXP (mem, 0), NULL_RTX, &XEXP (mem, 0), NULL,
2554 POINTER_REGS, Pmode, VOIDmode, 0, 0,
2555 1, (enum reload_type) addr_type);
2556
2557 if (avr_log.legitimize_reload_address)
2558 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
2559 POINTER_REGS, XEXP (mem, 0), NULL_RTX);
2560
2561 push_reload (mem, NULL_RTX, &XEXP (x, 0), NULL,
2562 BASE_POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
2563 opnum, (enum reload_type) type);
2564
2565 if (avr_log.legitimize_reload_address)
2566 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
2567 BASE_POINTER_REGS, mem, NULL_RTX);
2568
2569 return x;
2570 }
2571 }
2572 else if (! (frame_pointer_needed
2573 && XEXP (x, 0) == frame_pointer_rtx))
2574 {
2575 push_reload (x, NULL_RTX, px, NULL,
2576 POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
2577 opnum, (enum reload_type) type);
2578
2579 if (avr_log.legitimize_reload_address)
2580 avr_edump (" RCLASS.3 = %R\n IN = %r\n OUT = %r\n",
2581 POINTER_REGS, x, NULL_RTX);
2582
2583 return x;
2584 }
2585 }
2586
2587 return NULL_RTX;
2588 }
2589
2590
2591 /* Helper function to print assembler resp. track instruction
2592 sequence lengths. Always return "".
2593
2594 If PLEN == NULL:
2595 Output assembler code from template TPL with operands supplied
2596 by OPERANDS. This is just forwarding to output_asm_insn.
2597
2598 If PLEN != NULL:
2599 If N_WORDS >= 0 Add N_WORDS to *PLEN.
2600 If N_WORDS < 0 Set *PLEN to -N_WORDS.
2601 Don't output anything.
2602 */
2603
2604 static const char*
avr_asm_len(const char * tpl,rtx * operands,int * plen,int n_words)2605 avr_asm_len (const char* tpl, rtx* operands, int* plen, int n_words)
2606 {
2607 if (plen == NULL)
2608 output_asm_insn (tpl, operands);
2609 else
2610 {
2611 if (n_words < 0)
2612 *plen = -n_words;
2613 else
2614 *plen += n_words;
2615 }
2616
2617 return "";
2618 }
2619
2620
2621 /* Return a pointer register name as a string. */
2622
2623 static const char*
ptrreg_to_str(int regno)2624 ptrreg_to_str (int regno)
2625 {
2626 switch (regno)
2627 {
2628 case REG_X: return "X";
2629 case REG_Y: return "Y";
2630 case REG_Z: return "Z";
2631 default:
2632 output_operand_lossage ("address operand requires constraint for"
2633 " X, Y, or Z register");
2634 }
2635 return NULL;
2636 }
2637
2638 /* Return the condition name as a string.
2639 Used in conditional jump constructing */
2640
2641 static const char*
cond_string(enum rtx_code code)2642 cond_string (enum rtx_code code)
2643 {
2644 switch (code)
2645 {
2646 case NE:
2647 return "ne";
2648 case EQ:
2649 return "eq";
2650 case GE:
2651 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
2652 return "pl";
2653 else
2654 return "ge";
2655 case LT:
2656 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
2657 return "mi";
2658 else
2659 return "lt";
2660 case GEU:
2661 return "sh";
2662 case LTU:
2663 return "lo";
2664 default:
2665 gcc_unreachable ();
2666 }
2667
2668 return "";
2669 }
2670
2671
2672 /* Return true if rtx X is a CONST or SYMBOL_REF with progmem.
2673 This must be used for AVR_TINY only because on other cores
2674 the flash memory is not visible in the RAM address range and
2675 cannot be read by, say, LD instruction. */
2676
2677 static bool
avr_address_tiny_pm_p(rtx x)2678 avr_address_tiny_pm_p (rtx x)
2679 {
2680 if (CONST == GET_CODE (x))
2681 x = XEXP (XEXP (x, 0), 0);
2682
2683 if (SYMBOL_REF_P (x))
2684 return SYMBOL_REF_FLAGS (x) & AVR_SYMBOL_FLAG_TINY_PM;
2685
2686 return false;
2687 }
2688
2689 /* Implement `TARGET_PRINT_OPERAND_ADDRESS'. */
2690 /* Output ADDR to FILE as address. */
2691
2692 static void
avr_print_operand_address(FILE * file,machine_mode,rtx addr)2693 avr_print_operand_address (FILE *file, machine_mode /*mode*/, rtx addr)
2694 {
2695 if (AVR_TINY
2696 && avr_address_tiny_pm_p (addr))
2697 {
2698 addr = plus_constant (Pmode, addr, avr_arch->flash_pm_offset);
2699 }
2700
2701 switch (GET_CODE (addr))
2702 {
2703 case REG:
2704 fprintf (file, "%s", ptrreg_to_str (REGNO (addr)));
2705 break;
2706
2707 case PRE_DEC:
2708 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
2709 break;
2710
2711 case POST_INC:
2712 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
2713 break;
2714
2715 default:
2716 if (CONSTANT_ADDRESS_P (addr)
2717 && text_segment_operand (addr, VOIDmode))
2718 {
2719 rtx x = addr;
2720 if (GET_CODE (x) == CONST)
2721 x = XEXP (x, 0);
2722 if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1)))
2723 {
2724 /* Assembler gs() will implant word address. Make offset
2725 a byte offset inside gs() for assembler. This is
2726 needed because the more logical (constant+gs(sym)) is not
2727 accepted by gas. For 128K and smaller devices this is ok.
2728 For large devices it will create a trampoline to offset
2729 from symbol which may not be what the user really wanted. */
2730
2731 fprintf (file, "gs(");
2732 output_addr_const (file, XEXP (x, 0));
2733 fprintf (file, "+" HOST_WIDE_INT_PRINT_DEC ")",
2734 2 * INTVAL (XEXP (x, 1)));
2735 if (AVR_3_BYTE_PC)
2736 if (warning (0, "pointer offset from symbol maybe incorrect"))
2737 {
2738 output_addr_const (stderr, addr);
2739 fprintf (stderr, "\n");
2740 }
2741 }
2742 else
2743 {
2744 fprintf (file, "gs(");
2745 output_addr_const (file, addr);
2746 fprintf (file, ")");
2747 }
2748 }
2749 else
2750 output_addr_const (file, addr);
2751 }
2752 }
2753
2754
2755 /* Implement `TARGET_PRINT_OPERAND_PUNCT_VALID_P'. */
2756
2757 static bool
avr_print_operand_punct_valid_p(unsigned char code)2758 avr_print_operand_punct_valid_p (unsigned char code)
2759 {
2760 return code == '~' || code == '!';
2761 }
2762
2763
2764 /* Implement `TARGET_PRINT_OPERAND'. */
2765 /* Output X as assembler operand to file FILE.
2766 For a description of supported %-codes, see top of avr.md. */
2767
2768 static void
avr_print_operand(FILE * file,rtx x,int code)2769 avr_print_operand (FILE *file, rtx x, int code)
2770 {
2771 int abcd = 0, ef = 0, ij = 0;
2772
2773 if (code >= 'A' && code <= 'D')
2774 abcd = code - 'A';
2775 else if (code == 'E' || code == 'F')
2776 ef = code - 'E';
2777 else if (code == 'I' || code == 'J')
2778 ij = code - 'I';
2779
2780 if (code == '~')
2781 {
2782 if (!AVR_HAVE_JMP_CALL)
2783 fputc ('r', file);
2784 }
2785 else if (code == '!')
2786 {
2787 if (AVR_HAVE_EIJMP_EICALL)
2788 fputc ('e', file);
2789 }
2790 else if (code == 't'
2791 || code == 'T')
2792 {
2793 static int t_regno = -1;
2794 static int t_nbits = -1;
2795
2796 if (REG_P (x) && t_regno < 0 && code == 'T')
2797 {
2798 t_regno = REGNO (x);
2799 t_nbits = GET_MODE_BITSIZE (GET_MODE (x));
2800 }
2801 else if (CONST_INT_P (x) && t_regno >= 0
2802 && IN_RANGE (INTVAL (x), 0, t_nbits - 1))
2803 {
2804 int bpos = INTVAL (x);
2805
2806 fprintf (file, "%s", reg_names[t_regno + bpos / 8]);
2807 if (code == 'T')
2808 fprintf (file, ",%d", bpos % 8);
2809
2810 t_regno = -1;
2811 }
2812 else
2813 fatal_insn ("operands to %T/%t must be reg + const_int:", x);
2814 }
2815 else if (code == 'E' || code == 'F')
2816 {
2817 rtx op = XEXP (x, 0);
2818 fprintf (file, "%s", reg_names[REGNO (op) + ef]);
2819 }
2820 else if (code == 'I' || code == 'J')
2821 {
2822 rtx op = XEXP (XEXP (x, 0), 0);
2823 fprintf (file, "%s", reg_names[REGNO (op) + ij]);
2824 }
2825 else if (REG_P (x))
2826 {
2827 if (x == zero_reg_rtx)
2828 fprintf (file, "__zero_reg__");
2829 else if (code == 'r' && REGNO (x) < 32)
2830 fprintf (file, "%d", (int) REGNO (x));
2831 else
2832 fprintf (file, "%s", reg_names[REGNO (x) + abcd]);
2833 }
2834 else if (CONST_INT_P (x))
2835 {
2836 HOST_WIDE_INT ival = INTVAL (x);
2837
2838 if ('i' != code)
2839 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival + abcd);
2840 else if (low_io_address_operand (x, VOIDmode)
2841 || high_io_address_operand (x, VOIDmode))
2842 {
2843 if (AVR_HAVE_RAMPZ && ival == avr_addr.rampz)
2844 fprintf (file, "__RAMPZ__");
2845 else if (AVR_HAVE_RAMPY && ival == avr_addr.rampy)
2846 fprintf (file, "__RAMPY__");
2847 else if (AVR_HAVE_RAMPX && ival == avr_addr.rampx)
2848 fprintf (file, "__RAMPX__");
2849 else if (AVR_HAVE_RAMPD && ival == avr_addr.rampd)
2850 fprintf (file, "__RAMPD__");
2851 else if ((AVR_XMEGA || AVR_TINY) && ival == avr_addr.ccp)
2852 fprintf (file, "__CCP__");
2853 else if (ival == avr_addr.sreg) fprintf (file, "__SREG__");
2854 else if (ival == avr_addr.sp_l) fprintf (file, "__SP_L__");
2855 else if (ival == avr_addr.sp_h) fprintf (file, "__SP_H__");
2856 else
2857 {
2858 fprintf (file, HOST_WIDE_INT_PRINT_HEX,
2859 ival - avr_arch->sfr_offset);
2860 }
2861 }
2862 else
2863 fatal_insn ("bad address, not an I/O address:", x);
2864 }
2865 else if (MEM_P (x))
2866 {
2867 rtx addr = XEXP (x, 0);
2868
2869 if (code == 'm')
2870 {
2871 if (!CONSTANT_P (addr))
2872 fatal_insn ("bad address, not a constant:", addr);
2873 /* Assembler template with m-code is data - not progmem section */
2874 if (text_segment_operand (addr, VOIDmode))
2875 if (warning (0, "accessing data memory with"
2876 " program memory address"))
2877 {
2878 output_addr_const (stderr, addr);
2879 fprintf(stderr,"\n");
2880 }
2881 output_addr_const (file, addr);
2882 }
2883 else if (code == 'i')
2884 {
2885 avr_print_operand (file, addr, 'i');
2886 }
2887 else if (code == 'o')
2888 {
2889 if (GET_CODE (addr) != PLUS)
2890 fatal_insn ("bad address, not (reg+disp):", addr);
2891
2892 avr_print_operand (file, XEXP (addr, 1), 0);
2893 }
2894 else if (code == 'b')
2895 {
2896 if (GET_CODE (addr) != PLUS)
2897 fatal_insn ("bad address, not (reg+disp):", addr);
2898
2899 avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
2900 }
2901 else if (code == 'p' || code == 'r')
2902 {
2903 if (GET_CODE (addr) != POST_INC && GET_CODE (addr) != PRE_DEC)
2904 fatal_insn ("bad address, not post_inc or pre_dec:", addr);
2905
2906 if (code == 'p')
2907 /* X, Y, Z */
2908 avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
2909 else
2910 avr_print_operand (file, XEXP (addr, 0), 0); /* r26, r28, r30 */
2911 }
2912 else if (GET_CODE (addr) == PLUS)
2913 {
2914 avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
2915 if (REGNO (XEXP (addr, 0)) == REG_X)
2916 fatal_insn ("internal compiler error. Bad address:"
2917 ,addr);
2918 fputc ('+', file);
2919 avr_print_operand (file, XEXP (addr, 1), code);
2920 }
2921 else
2922 avr_print_operand_address (file, VOIDmode, addr);
2923 }
2924 else if (code == 'i')
2925 {
2926 if (SYMBOL_REF_P (x) && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO))
2927 avr_print_operand_address
2928 (file, VOIDmode, plus_constant (HImode, x, -avr_arch->sfr_offset));
2929 else
2930 fatal_insn ("bad address, not an I/O address:", x);
2931 }
2932 else if (code == 'x')
2933 {
2934 /* Constant progmem address - like used in jmp or call */
2935 if (text_segment_operand (x, VOIDmode) == 0)
2936 if (warning (0, "accessing program memory"
2937 " with data memory address"))
2938 {
2939 output_addr_const (stderr, x);
2940 fprintf(stderr,"\n");
2941 }
2942 /* Use normal symbol for direct address no linker trampoline needed */
2943 output_addr_const (file, x);
2944 }
2945 else if (CONST_FIXED_P (x))
2946 {
2947 HOST_WIDE_INT ival = INTVAL (avr_to_int_mode (x));
2948 if (code != 0)
2949 output_operand_lossage ("Unsupported code '%c' for fixed-point:",
2950 code);
2951 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);
2952 }
2953 else if (CONST_DOUBLE_P (x))
2954 {
2955 long val;
2956 if (GET_MODE (x) != SFmode)
2957 fatal_insn ("internal compiler error. Unknown mode:", x);
2958 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), val);
2959 fprintf (file, "0x%lx", val);
2960 }
2961 else if (GET_CODE (x) == CONST_STRING)
2962 fputs (XSTR (x, 0), file);
2963 else if (code == 'j')
2964 fputs (cond_string (GET_CODE (x)), file);
2965 else if (code == 'k')
2966 fputs (cond_string (reverse_condition (GET_CODE (x))), file);
2967 else
2968 avr_print_operand_address (file, VOIDmode, x);
2969 }
2970
2971
2972 /* Implement TARGET_USE_BY_PIECES_INFRASTRUCTURE_P. */
2973
2974 /* Prefer sequence of loads/stores for moves of size upto
2975 two - two pairs of load/store instructions are always better
2976 than the 5 instruction sequence for a loop (1 instruction
2977 for loop counter setup, and 4 for the body of the loop). */
2978
2979 static bool
avr_use_by_pieces_infrastructure_p(unsigned HOST_WIDE_INT size,unsigned int align ATTRIBUTE_UNUSED,enum by_pieces_operation op,bool speed_p)2980 avr_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size,
2981 unsigned int align ATTRIBUTE_UNUSED,
2982 enum by_pieces_operation op,
2983 bool speed_p)
2984 {
2985 if (op != MOVE_BY_PIECES
2986 || (speed_p && size > MOVE_MAX_PIECES))
2987 return default_use_by_pieces_infrastructure_p (size, align, op, speed_p);
2988
2989 return size <= MOVE_MAX_PIECES;
2990 }
2991
2992
2993 /* Worker function for `NOTICE_UPDATE_CC'. */
2994 /* Update the condition code in the INSN. */
2995
2996 void
avr_notice_update_cc(rtx body ATTRIBUTE_UNUSED,rtx_insn * insn)2997 avr_notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx_insn *insn)
2998 {
2999 rtx set;
3000 enum attr_cc cc = get_attr_cc (insn);
3001
3002 switch (cc)
3003 {
3004 default:
3005 break;
3006
3007 case CC_PLUS:
3008 case CC_LDI:
3009 {
3010 rtx *op = recog_data.operand;
3011 int len_dummy, icc;
3012
3013 /* Extract insn's operands. */
3014 extract_constrain_insn_cached (insn);
3015
3016 switch (cc)
3017 {
3018 default:
3019 gcc_unreachable();
3020
3021 case CC_PLUS:
3022 avr_out_plus (insn, op, &len_dummy, &icc);
3023 cc = (enum attr_cc) icc;
3024 break;
3025
3026 case CC_LDI:
3027
3028 cc = (op[1] == CONST0_RTX (GET_MODE (op[0]))
3029 && reg_overlap_mentioned_p (op[0], zero_reg_rtx))
3030 /* Loading zero-reg with 0 uses CLR and thus clobbers cc0. */
3031 ? CC_CLOBBER
3032 /* Any other "r,rL" combination does not alter cc0. */
3033 : CC_NONE;
3034
3035 break;
3036 } /* inner switch */
3037
3038 break;
3039 }
3040 } /* outer swicth */
3041
3042 switch (cc)
3043 {
3044 default:
3045 /* Special values like CC_OUT_PLUS from above have been
3046 mapped to "standard" CC_* values so we never come here. */
3047
3048 gcc_unreachable();
3049 break;
3050
3051 case CC_NONE:
3052 /* Insn does not affect CC at all, but it might set some registers
3053 that are stored in cc_status. If such a register is affected by
3054 the current insn, for example by means of a SET or a CLOBBER,
3055 then we must reset cc_status; cf. PR77326.
3056
3057 Unfortunately, set_of cannot be used as reg_overlap_mentioned_p
3058 will abort on COMPARE (which might be found in cc_status.value1/2).
3059 Thus work out the registers set by the insn and regs mentioned
3060 in cc_status.value1/2. */
3061
3062 if (cc_status.value1
3063 || cc_status.value2)
3064 {
3065 HARD_REG_SET regs_used;
3066 HARD_REG_SET regs_set;
3067 CLEAR_HARD_REG_SET (regs_used);
3068
3069 if (cc_status.value1
3070 && !CONSTANT_P (cc_status.value1))
3071 {
3072 find_all_hard_regs (cc_status.value1, ®s_used);
3073 }
3074
3075 if (cc_status.value2
3076 && !CONSTANT_P (cc_status.value2))
3077 {
3078 find_all_hard_regs (cc_status.value2, ®s_used);
3079 }
3080
3081 find_all_hard_reg_sets (insn, ®s_set, false);
3082
3083 if (hard_reg_set_intersect_p (regs_used, regs_set))
3084 {
3085 CC_STATUS_INIT;
3086 }
3087 }
3088
3089 break; // CC_NONE
3090
3091 case CC_SET_N:
3092 CC_STATUS_INIT;
3093 break;
3094
3095 case CC_SET_ZN:
3096 set = single_set (insn);
3097 CC_STATUS_INIT;
3098 if (set)
3099 {
3100 cc_status.flags |= CC_NO_OVERFLOW;
3101 cc_status.value1 = SET_DEST (set);
3102 }
3103 break;
3104
3105 case CC_SET_VZN:
3106 /* Insn like INC, DEC, NEG that set Z,N,V. We currently don't make use
3107 of this combination, cf. also PR61055. */
3108 CC_STATUS_INIT;
3109 break;
3110
3111 case CC_SET_CZN:
3112 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
3113 The V flag may or may not be known but that's ok because
3114 alter_cond will change tests to use EQ/NE. */
3115 set = single_set (insn);
3116 CC_STATUS_INIT;
3117 if (set)
3118 {
3119 cc_status.value1 = SET_DEST (set);
3120 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
3121 }
3122 break;
3123
3124 case CC_COMPARE:
3125 set = single_set (insn);
3126 CC_STATUS_INIT;
3127 if (set)
3128 cc_status.value1 = SET_SRC (set);
3129 break;
3130
3131 case CC_CLOBBER:
3132 /* Insn doesn't leave CC in a usable state. */
3133 CC_STATUS_INIT;
3134 break;
3135 }
3136 }
3137
3138 /* Choose mode for jump insn:
3139 1 - relative jump in range -63 <= x <= 62 ;
3140 2 - relative jump in range -2046 <= x <= 2045 ;
3141 3 - absolute jump (only for ATmega[16]03). */
3142
3143 int
avr_jump_mode(rtx x,rtx_insn * insn)3144 avr_jump_mode (rtx x, rtx_insn *insn)
3145 {
3146 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_CODE (x) == LABEL_REF
3147 ? XEXP (x, 0) : x));
3148 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
3149 int jump_distance = cur_addr - dest_addr;
3150
3151 if (IN_RANGE (jump_distance, -63, 62))
3152 return 1;
3153 else if (IN_RANGE (jump_distance, -2046, 2045))
3154 return 2;
3155 else if (AVR_HAVE_JMP_CALL)
3156 return 3;
3157
3158 return 2;
3159 }
3160
3161 /* Return an AVR condition jump commands.
3162 X is a comparison RTX.
3163 LEN is a number returned by avr_jump_mode function.
3164 If REVERSE nonzero then condition code in X must be reversed. */
3165
3166 const char*
ret_cond_branch(rtx x,int len,int reverse)3167 ret_cond_branch (rtx x, int len, int reverse)
3168 {
3169 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
3170
3171 switch (cond)
3172 {
3173 case GT:
3174 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
3175 return (len == 1 ? ("breq .+2" CR_TAB
3176 "brpl %0") :
3177 len == 2 ? ("breq .+4" CR_TAB
3178 "brmi .+2" CR_TAB
3179 "rjmp %0") :
3180 ("breq .+6" CR_TAB
3181 "brmi .+4" CR_TAB
3182 "jmp %0"));
3183
3184 else
3185 return (len == 1 ? ("breq .+2" CR_TAB
3186 "brge %0") :
3187 len == 2 ? ("breq .+4" CR_TAB
3188 "brlt .+2" CR_TAB
3189 "rjmp %0") :
3190 ("breq .+6" CR_TAB
3191 "brlt .+4" CR_TAB
3192 "jmp %0"));
3193 case GTU:
3194 return (len == 1 ? ("breq .+2" CR_TAB
3195 "brsh %0") :
3196 len == 2 ? ("breq .+4" CR_TAB
3197 "brlo .+2" CR_TAB
3198 "rjmp %0") :
3199 ("breq .+6" CR_TAB
3200 "brlo .+4" CR_TAB
3201 "jmp %0"));
3202 case LE:
3203 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
3204 return (len == 1 ? ("breq %0" CR_TAB
3205 "brmi %0") :
3206 len == 2 ? ("breq .+2" CR_TAB
3207 "brpl .+2" CR_TAB
3208 "rjmp %0") :
3209 ("breq .+2" CR_TAB
3210 "brpl .+4" CR_TAB
3211 "jmp %0"));
3212 else
3213 return (len == 1 ? ("breq %0" CR_TAB
3214 "brlt %0") :
3215 len == 2 ? ("breq .+2" CR_TAB
3216 "brge .+2" CR_TAB
3217 "rjmp %0") :
3218 ("breq .+2" CR_TAB
3219 "brge .+4" CR_TAB
3220 "jmp %0"));
3221 case LEU:
3222 return (len == 1 ? ("breq %0" CR_TAB
3223 "brlo %0") :
3224 len == 2 ? ("breq .+2" CR_TAB
3225 "brsh .+2" CR_TAB
3226 "rjmp %0") :
3227 ("breq .+2" CR_TAB
3228 "brsh .+4" CR_TAB
3229 "jmp %0"));
3230 default:
3231 if (reverse)
3232 {
3233 switch (len)
3234 {
3235 case 1:
3236 return "br%k1 %0";
3237 case 2:
3238 return ("br%j1 .+2" CR_TAB
3239 "rjmp %0");
3240 default:
3241 return ("br%j1 .+4" CR_TAB
3242 "jmp %0");
3243 }
3244 }
3245 else
3246 {
3247 switch (len)
3248 {
3249 case 1:
3250 return "br%j1 %0";
3251 case 2:
3252 return ("br%k1 .+2" CR_TAB
3253 "rjmp %0");
3254 default:
3255 return ("br%k1 .+4" CR_TAB
3256 "jmp %0");
3257 }
3258 }
3259 }
3260 return "";
3261 }
3262
3263
3264 /* Worker function for `FINAL_PRESCAN_INSN'. */
3265 /* Output insn cost for next insn. */
3266
3267 void
avr_final_prescan_insn(rtx_insn * insn,rtx * operand ATTRIBUTE_UNUSED,int num_operands ATTRIBUTE_UNUSED)3268 avr_final_prescan_insn (rtx_insn *insn, rtx *operand ATTRIBUTE_UNUSED,
3269 int num_operands ATTRIBUTE_UNUSED)
3270 {
3271 if (avr_log.rtx_costs)
3272 {
3273 rtx set = single_set (insn);
3274
3275 if (set)
3276 fprintf (asm_out_file, "/* DEBUG: cost = %d. */\n",
3277 set_src_cost (SET_SRC (set), GET_MODE (SET_DEST (set)),
3278 optimize_insn_for_speed_p ()));
3279 else
3280 fprintf (asm_out_file, "/* DEBUG: pattern-cost = %d. */\n",
3281 rtx_cost (PATTERN (insn), VOIDmode, INSN, 0,
3282 optimize_insn_for_speed_p()));
3283 }
3284
3285 if (avr_log.insn_addresses)
3286 fprintf (asm_out_file, ";; ADDR = %d\n",
3287 (int) INSN_ADDRESSES (INSN_UID (insn)));
3288 }
3289
3290
3291 /* Implement `TARGET_ASM_FINAL_POSTSCAN_INSN'. */
3292 /* When GAS generates (parts of) ISR prologue / epilogue for us, we must
3293 hint GAS about the end of the code to scan. There migh be code located
3294 after the last epilogue. */
3295
3296 static void
avr_asm_final_postscan_insn(FILE * stream,rtx_insn * insn,rtx *,int)3297 avr_asm_final_postscan_insn (FILE *stream, rtx_insn *insn, rtx*, int)
3298 {
3299 if (cfun->machine->gasisr.yes
3300 && !next_real_insn (insn))
3301 {
3302 app_disable();
3303 fprintf (stream, "\t__gcc_isr %d,r%d\n", GASISR_Done,
3304 cfun->machine->gasisr.regno);
3305 }
3306 }
3307
3308
3309 /* Return 0 if undefined, 1 if always true or always false. */
3310
3311 int
avr_simplify_comparison_p(machine_mode mode,RTX_CODE op,rtx x)3312 avr_simplify_comparison_p (machine_mode mode, RTX_CODE op, rtx x)
3313 {
3314 unsigned int max = (mode == QImode ? 0xff :
3315 mode == HImode ? 0xffff :
3316 mode == PSImode ? 0xffffff :
3317 mode == SImode ? 0xffffffff : 0);
3318 if (max && op && CONST_INT_P (x))
3319 {
3320 if (unsigned_condition (op) != op)
3321 max >>= 1;
3322
3323 if (max != (INTVAL (x) & max)
3324 && INTVAL (x) != 0xff)
3325 return 1;
3326 }
3327 return 0;
3328 }
3329
3330
3331 /* Worker function for `FUNCTION_ARG_REGNO_P'. */
3332 /* Returns nonzero if REGNO is the number of a hard
3333 register in which function arguments are sometimes passed. */
3334
3335 int
avr_function_arg_regno_p(int r)3336 avr_function_arg_regno_p (int r)
3337 {
3338 return AVR_TINY ? IN_RANGE (r, 20, 25) : IN_RANGE (r, 8, 25);
3339 }
3340
3341
3342 /* Worker function for `INIT_CUMULATIVE_ARGS'. */
3343 /* Initializing the variable cum for the state at the beginning
3344 of the argument list. */
3345
3346 void
avr_init_cumulative_args(CUMULATIVE_ARGS * cum,tree fntype,rtx libname,tree fndecl ATTRIBUTE_UNUSED)3347 avr_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
3348 tree fndecl ATTRIBUTE_UNUSED)
3349 {
3350 cum->nregs = AVR_TINY ? 6 : 18;
3351 cum->regno = FIRST_CUM_REG;
3352 if (!libname && stdarg_p (fntype))
3353 cum->nregs = 0;
3354
3355 /* Assume the calle may be tail called */
3356
3357 cfun->machine->sibcall_fails = 0;
3358 }
3359
3360 /* Returns the number of registers to allocate for a function argument. */
3361
3362 static int
avr_num_arg_regs(machine_mode mode,const_tree type)3363 avr_num_arg_regs (machine_mode mode, const_tree type)
3364 {
3365 int size;
3366
3367 if (mode == BLKmode)
3368 size = int_size_in_bytes (type);
3369 else
3370 size = GET_MODE_SIZE (mode);
3371
3372 /* Align all function arguments to start in even-numbered registers.
3373 Odd-sized arguments leave holes above them. */
3374
3375 return (size + 1) & ~1;
3376 }
3377
3378
3379 /* Implement `TARGET_FUNCTION_ARG'. */
3380 /* Controls whether a function argument is passed
3381 in a register, and which register. */
3382
3383 static rtx
avr_function_arg(cumulative_args_t cum_v,const function_arg_info & arg)3384 avr_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
3385 {
3386 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
3387 int bytes = avr_num_arg_regs (arg.mode, arg.type);
3388
3389 if (cum->nregs && bytes <= cum->nregs)
3390 return gen_rtx_REG (arg.mode, cum->regno - bytes);
3391
3392 return NULL_RTX;
3393 }
3394
3395
3396 /* Implement `TARGET_FUNCTION_ARG_ADVANCE'. */
3397 /* Update the summarizer variable CUM to advance past an argument
3398 in the argument list. */
3399
3400 static void
avr_function_arg_advance(cumulative_args_t cum_v,const function_arg_info & arg)3401 avr_function_arg_advance (cumulative_args_t cum_v,
3402 const function_arg_info &arg)
3403 {
3404 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
3405 int bytes = avr_num_arg_regs (arg.mode, arg.type);
3406
3407 cum->nregs -= bytes;
3408 cum->regno -= bytes;
3409
3410 /* A parameter is being passed in a call-saved register. As the original
3411 contents of these regs has to be restored before leaving the function,
3412 a function must not pass arguments in call-saved regs in order to get
3413 tail-called. */
3414
3415 if (cum->regno >= 8
3416 && cum->nregs >= 0
3417 && !call_used_or_fixed_reg_p (cum->regno))
3418 {
3419 /* FIXME: We ship info on failing tail-call in struct machine_function.
3420 This uses internals of calls.c:expand_call() and the way args_so_far
3421 is used. targetm.function_ok_for_sibcall() needs to be extended to
3422 pass &args_so_far, too. At present, CUMULATIVE_ARGS is target
3423 dependent so that such an extension is not wanted. */
3424
3425 cfun->machine->sibcall_fails = 1;
3426 }
3427
3428 /* Test if all registers needed by the ABI are actually available. If the
3429 user has fixed a GPR needed to pass an argument, an (implicit) function
3430 call will clobber that fixed register. See PR45099 for an example. */
3431
3432 if (cum->regno >= 8
3433 && cum->nregs >= 0)
3434 {
3435 for (int regno = cum->regno; regno < cum->regno + bytes; regno++)
3436 if (fixed_regs[regno])
3437 warning (0, "fixed register %s used to pass parameter to function",
3438 reg_names[regno]);
3439 }
3440
3441 if (cum->nregs <= 0)
3442 {
3443 cum->nregs = 0;
3444 cum->regno = FIRST_CUM_REG;
3445 }
3446 }
3447
3448 /* Implement `TARGET_FUNCTION_OK_FOR_SIBCALL' */
3449 /* Decide whether we can make a sibling call to a function. DECL is the
3450 declaration of the function being targeted by the call and EXP is the
3451 CALL_EXPR representing the call. */
3452
3453 static bool
avr_function_ok_for_sibcall(tree decl_callee,tree exp_callee)3454 avr_function_ok_for_sibcall (tree decl_callee, tree exp_callee)
3455 {
3456 tree fntype_callee;
3457
3458 /* Tail-calling must fail if callee-saved regs are used to pass
3459 function args. We must not tail-call when `epilogue_restores'
3460 is used. Unfortunately, we cannot tell at this point if that
3461 actually will happen or not, and we cannot step back from
3462 tail-calling. Thus, we inhibit tail-calling with -mcall-prologues. */
3463
3464 if (cfun->machine->sibcall_fails
3465 || TARGET_CALL_PROLOGUES)
3466 {
3467 return false;
3468 }
3469
3470 fntype_callee = TREE_TYPE (CALL_EXPR_FN (exp_callee));
3471
3472 if (decl_callee)
3473 {
3474 decl_callee = TREE_TYPE (decl_callee);
3475 }
3476 else
3477 {
3478 decl_callee = fntype_callee;
3479
3480 while (FUNCTION_TYPE != TREE_CODE (decl_callee)
3481 && METHOD_TYPE != TREE_CODE (decl_callee))
3482 {
3483 decl_callee = TREE_TYPE (decl_callee);
3484 }
3485 }
3486
3487 /* Ensure that caller and callee have compatible epilogues */
3488
3489 if (cfun->machine->is_interrupt
3490 || cfun->machine->is_signal
3491 || cfun->machine->is_naked
3492 || avr_naked_function_p (decl_callee))
3493 {
3494 return false;
3495 }
3496
3497 return true;
3498 }
3499
3500 /***********************************************************************
3501 Functions for outputting various mov's for a various modes
3502 ************************************************************************/
3503
3504 /* Return true if a value of mode MODE is read from flash by
3505 __load_* function from libgcc. */
3506
3507 bool
avr_load_libgcc_p(rtx op)3508 avr_load_libgcc_p (rtx op)
3509 {
3510 machine_mode mode = GET_MODE (op);
3511 int n_bytes = GET_MODE_SIZE (mode);
3512
3513 return (n_bytes > 2
3514 && !AVR_HAVE_LPMX
3515 && avr_mem_flash_p (op));
3516 }
3517
3518 /* Return true if a value of mode MODE is read by __xload_* function. */
3519
3520 bool
avr_xload_libgcc_p(machine_mode mode)3521 avr_xload_libgcc_p (machine_mode mode)
3522 {
3523 int n_bytes = GET_MODE_SIZE (mode);
3524
3525 return (n_bytes > 1
3526 || avr_n_flash > 1);
3527 }
3528
3529
3530 /* Fixme: This is a hack because secondary reloads don't works as expected.
3531
3532 Find an unused d-register to be used as scratch in INSN.
3533 EXCLUDE is either NULL_RTX or some register. In the case where EXCLUDE
3534 is a register, skip all possible return values that overlap EXCLUDE.
3535 The policy for the returned register is similar to that of
3536 `reg_unused_after', i.e. the returned register may overlap the SET_DEST
3537 of INSN.
3538
3539 Return a QImode d-register or NULL_RTX if nothing found. */
3540
3541 static rtx
avr_find_unused_d_reg(rtx_insn * insn,rtx exclude)3542 avr_find_unused_d_reg (rtx_insn *insn, rtx exclude)
3543 {
3544 bool isr_p = (avr_interrupt_function_p (current_function_decl)
3545 || avr_signal_function_p (current_function_decl));
3546
3547 for (int regno = 16; regno < 32; regno++)
3548 {
3549 rtx reg = all_regs_rtx[regno];
3550
3551 if ((exclude
3552 && reg_overlap_mentioned_p (exclude, reg))
3553 || fixed_regs[regno])
3554 {
3555 continue;
3556 }
3557
3558 /* Try non-live register */
3559
3560 if (!df_regs_ever_live_p (regno)
3561 && (TREE_THIS_VOLATILE (current_function_decl)
3562 || cfun->machine->is_OS_task
3563 || cfun->machine->is_OS_main
3564 || (!isr_p && call_used_or_fixed_reg_p (regno))))
3565 {
3566 return reg;
3567 }
3568
3569 /* Any live register can be used if it is unused after.
3570 Prologue/epilogue will care for it as needed. */
3571
3572 if (df_regs_ever_live_p (regno)
3573 && reg_unused_after (insn, reg))
3574 {
3575 return reg;
3576 }
3577 }
3578
3579 return NULL_RTX;
3580 }
3581
3582
3583 /* Helper function for the next function in the case where only restricted
3584 version of LPM instruction is available. */
3585
3586 static const char*
avr_out_lpm_no_lpmx(rtx_insn * insn,rtx * xop,int * plen)3587 avr_out_lpm_no_lpmx (rtx_insn *insn, rtx *xop, int *plen)
3588 {
3589 rtx dest = xop[0];
3590 rtx addr = xop[1];
3591 int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
3592 int regno_dest;
3593
3594 regno_dest = REGNO (dest);
3595
3596 /* The implicit target register of LPM. */
3597 xop[3] = lpm_reg_rtx;
3598
3599 switch (GET_CODE (addr))
3600 {
3601 default:
3602 gcc_unreachable();
3603
3604 case REG:
3605
3606 gcc_assert (REG_Z == REGNO (addr));
3607
3608 switch (n_bytes)
3609 {
3610 default:
3611 gcc_unreachable();
3612
3613 case 1:
3614 avr_asm_len ("%4lpm", xop, plen, 1);
3615
3616 if (regno_dest != LPM_REGNO)
3617 avr_asm_len ("mov %0,%3", xop, plen, 1);
3618
3619 return "";
3620
3621 case 2:
3622 if (REGNO (dest) == REG_Z)
3623 return avr_asm_len ("%4lpm" CR_TAB
3624 "push %3" CR_TAB
3625 "adiw %2,1" CR_TAB
3626 "%4lpm" CR_TAB
3627 "mov %B0,%3" CR_TAB
3628 "pop %A0", xop, plen, 6);
3629
3630 avr_asm_len ("%4lpm" CR_TAB
3631 "mov %A0,%3" CR_TAB
3632 "adiw %2,1" CR_TAB
3633 "%4lpm" CR_TAB
3634 "mov %B0,%3", xop, plen, 5);
3635
3636 if (!reg_unused_after (insn, addr))
3637 avr_asm_len ("sbiw %2,1", xop, plen, 1);
3638
3639 break; /* 2 */
3640 }
3641
3642 break; /* REG */
3643
3644 case POST_INC:
3645
3646 gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
3647 && n_bytes <= 4);
3648
3649 if (regno_dest == LPM_REGNO)
3650 avr_asm_len ("%4lpm" CR_TAB
3651 "adiw %2,1", xop, plen, 2);
3652 else
3653 avr_asm_len ("%4lpm" CR_TAB
3654 "mov %A0,%3" CR_TAB
3655 "adiw %2,1", xop, plen, 3);
3656
3657 if (n_bytes >= 2)
3658 avr_asm_len ("%4lpm" CR_TAB
3659 "mov %B0,%3" CR_TAB
3660 "adiw %2,1", xop, plen, 3);
3661
3662 if (n_bytes >= 3)
3663 avr_asm_len ("%4lpm" CR_TAB
3664 "mov %C0,%3" CR_TAB
3665 "adiw %2,1", xop, plen, 3);
3666
3667 if (n_bytes >= 4)
3668 avr_asm_len ("%4lpm" CR_TAB
3669 "mov %D0,%3" CR_TAB
3670 "adiw %2,1", xop, plen, 3);
3671
3672 break; /* POST_INC */
3673
3674 } /* switch CODE (addr) */
3675
3676 return "";
3677 }
3678
3679
3680 /* If PLEN == NULL: Ouput instructions to load a value from a memory location
3681 OP[1] in AS1 to register OP[0].
3682 If PLEN != 0 set *PLEN to the length in words of the instruction sequence.
3683 Return "". */
3684
3685 const char*
avr_out_lpm(rtx_insn * insn,rtx * op,int * plen)3686 avr_out_lpm (rtx_insn *insn, rtx *op, int *plen)
3687 {
3688 rtx xop[7];
3689 rtx dest = op[0];
3690 rtx src = SET_SRC (single_set (insn));
3691 rtx addr;
3692 int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
3693 int segment;
3694 RTX_CODE code;
3695 addr_space_t as = MEM_ADDR_SPACE (src);
3696
3697 if (plen)
3698 *plen = 0;
3699
3700 if (MEM_P (dest))
3701 {
3702 warning (0, "writing to address space %qs not supported",
3703 avr_addrspace[MEM_ADDR_SPACE (dest)].name);
3704
3705 return "";
3706 }
3707
3708 addr = XEXP (src, 0);
3709 code = GET_CODE (addr);
3710
3711 gcc_assert (REG_P (dest));
3712 gcc_assert (REG == code || POST_INC == code);
3713
3714 xop[0] = dest;
3715 xop[1] = addr;
3716 xop[2] = lpm_addr_reg_rtx;
3717 xop[4] = xstring_empty;
3718 xop[5] = tmp_reg_rtx;
3719 xop[6] = XEXP (rampz_rtx, 0);
3720
3721 segment = avr_addrspace[as].segment;
3722
3723 /* Set RAMPZ as needed. */
3724
3725 if (segment)
3726 {
3727 xop[4] = GEN_INT (segment);
3728 xop[3] = avr_find_unused_d_reg (insn, lpm_addr_reg_rtx);
3729
3730 if (xop[3] != NULL_RTX)
3731 {
3732 avr_asm_len ("ldi %3,%4" CR_TAB
3733 "out %i6,%3", xop, plen, 2);
3734 }
3735 else if (segment == 1)
3736 {
3737 avr_asm_len ("clr %5" CR_TAB
3738 "inc %5" CR_TAB
3739 "out %i6,%5", xop, plen, 3);
3740 }
3741 else
3742 {
3743 avr_asm_len ("mov %5,%2" CR_TAB
3744 "ldi %2,%4" CR_TAB
3745 "out %i6,%2" CR_TAB
3746 "mov %2,%5", xop, plen, 4);
3747 }
3748
3749 xop[4] = xstring_e;
3750
3751 if (!AVR_HAVE_ELPMX)
3752 return avr_out_lpm_no_lpmx (insn, xop, plen);
3753 }
3754 else if (!AVR_HAVE_LPMX)
3755 {
3756 return avr_out_lpm_no_lpmx (insn, xop, plen);
3757 }
3758
3759 /* We have [E]LPMX: Output reading from Flash the comfortable way. */
3760
3761 switch (GET_CODE (addr))
3762 {
3763 default:
3764 gcc_unreachable();
3765
3766 case REG:
3767
3768 gcc_assert (REG_Z == REGNO (addr));
3769
3770 switch (n_bytes)
3771 {
3772 default:
3773 gcc_unreachable();
3774
3775 case 1:
3776 avr_asm_len ("%4lpm %0,%a2", xop, plen, 1);
3777 break;
3778
3779 case 2:
3780 if (REGNO (dest) == REG_Z)
3781 avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3782 "%4lpm %B0,%a2" CR_TAB
3783 "mov %A0,%5", xop, plen, 3);
3784 else
3785 {
3786 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3787 "%4lpm %B0,%a2", xop, plen, 2);
3788
3789 if (!reg_unused_after (insn, addr))
3790 avr_asm_len ("sbiw %2,1", xop, plen, 1);
3791 }
3792
3793 break; /* 2 */
3794
3795 case 3:
3796
3797 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3798 "%4lpm %B0,%a2+" CR_TAB
3799 "%4lpm %C0,%a2", xop, plen, 3);
3800
3801 if (!reg_unused_after (insn, addr))
3802 avr_asm_len ("sbiw %2,2", xop, plen, 1);
3803
3804 break; /* 3 */
3805
3806 case 4:
3807
3808 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3809 "%4lpm %B0,%a2+", xop, plen, 2);
3810
3811 if (REGNO (dest) == REG_Z - 2)
3812 avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3813 "%4lpm %C0,%a2" CR_TAB
3814 "mov %D0,%5", xop, plen, 3);
3815 else
3816 {
3817 avr_asm_len ("%4lpm %C0,%a2+" CR_TAB
3818 "%4lpm %D0,%a2", xop, plen, 2);
3819
3820 if (!reg_unused_after (insn, addr))
3821 avr_asm_len ("sbiw %2,3", xop, plen, 1);
3822 }
3823
3824 break; /* 4 */
3825 } /* n_bytes */
3826
3827 break; /* REG */
3828
3829 case POST_INC:
3830
3831 gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
3832 && n_bytes <= 4);
3833
3834 avr_asm_len ("%4lpm %A0,%a2+", xop, plen, 1);
3835 if (n_bytes >= 2) avr_asm_len ("%4lpm %B0,%a2+", xop, plen, 1);
3836 if (n_bytes >= 3) avr_asm_len ("%4lpm %C0,%a2+", xop, plen, 1);
3837 if (n_bytes >= 4) avr_asm_len ("%4lpm %D0,%a2+", xop, plen, 1);
3838
3839 break; /* POST_INC */
3840
3841 } /* switch CODE (addr) */
3842
3843 if (xop[4] == xstring_e && AVR_HAVE_RAMPD)
3844 {
3845 /* Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM. */
3846
3847 xop[0] = zero_reg_rtx;
3848 avr_asm_len ("out %i6,%0", xop, plen, 1);
3849 }
3850
3851 return "";
3852 }
3853
3854
3855 /* Worker function for xload_8 insn. */
3856
3857 const char*
avr_out_xload(rtx_insn * insn ATTRIBUTE_UNUSED,rtx * op,int * plen)3858 avr_out_xload (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
3859 {
3860 rtx xop[4];
3861
3862 xop[0] = op[0];
3863 xop[1] = op[1];
3864 xop[2] = lpm_addr_reg_rtx;
3865 xop[3] = AVR_HAVE_LPMX ? op[0] : lpm_reg_rtx;
3866
3867 avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, -1);
3868
3869 avr_asm_len ("sbrc %1,7" CR_TAB
3870 "ld %3,%a2", xop, plen, 2);
3871
3872 if (REGNO (xop[0]) != REGNO (xop[3]))
3873 avr_asm_len ("mov %0,%3", xop, plen, 1);
3874
3875 return "";
3876 }
3877
3878
3879 const char*
output_movqi(rtx_insn * insn,rtx operands[],int * plen)3880 output_movqi (rtx_insn *insn, rtx operands[], int *plen)
3881 {
3882 rtx dest = operands[0];
3883 rtx src = operands[1];
3884
3885 if (avr_mem_flash_p (src)
3886 || avr_mem_flash_p (dest))
3887 {
3888 return avr_out_lpm (insn, operands, plen);
3889 }
3890
3891 gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 1);
3892
3893 if (REG_P (dest))
3894 {
3895 if (REG_P (src)) /* mov r,r */
3896 {
3897 if (test_hard_reg_class (STACK_REG, dest))
3898 return avr_asm_len ("out %0,%1", operands, plen, -1);
3899 else if (test_hard_reg_class (STACK_REG, src))
3900 return avr_asm_len ("in %0,%1", operands, plen, -1);
3901
3902 return avr_asm_len ("mov %0,%1", operands, plen, -1);
3903 }
3904 else if (CONSTANT_P (src))
3905 {
3906 output_reload_in_const (operands, NULL_RTX, plen, false);
3907 return "";
3908 }
3909 else if (MEM_P (src))
3910 return out_movqi_r_mr (insn, operands, plen); /* mov r,m */
3911 }
3912 else if (MEM_P (dest))
3913 {
3914 rtx xop[2];
3915
3916 xop[0] = dest;
3917 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
3918
3919 return out_movqi_mr_r (insn, xop, plen);
3920 }
3921
3922 return "";
3923 }
3924
3925
3926 const char *
output_movhi(rtx_insn * insn,rtx xop[],int * plen)3927 output_movhi (rtx_insn *insn, rtx xop[], int *plen)
3928 {
3929 rtx dest = xop[0];
3930 rtx src = xop[1];
3931
3932 gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 2);
3933
3934 if (avr_mem_flash_p (src)
3935 || avr_mem_flash_p (dest))
3936 {
3937 return avr_out_lpm (insn, xop, plen);
3938 }
3939
3940 if (REG_P (dest))
3941 {
3942 if (REG_P (src)) /* mov r,r */
3943 {
3944 if (test_hard_reg_class (STACK_REG, dest))
3945 {
3946 if (AVR_HAVE_8BIT_SP)
3947 return avr_asm_len ("out __SP_L__,%A1", xop, plen, -1);
3948
3949 if (AVR_XMEGA)
3950 return avr_asm_len ("out __SP_L__,%A1" CR_TAB
3951 "out __SP_H__,%B1", xop, plen, -2);
3952
3953 /* Use simple load of SP if no interrupts are used. */
3954
3955 return TARGET_NO_INTERRUPTS
3956 ? avr_asm_len ("out __SP_H__,%B1" CR_TAB
3957 "out __SP_L__,%A1", xop, plen, -2)
3958 : avr_asm_len ("in __tmp_reg__,__SREG__" CR_TAB
3959 "cli" CR_TAB
3960 "out __SP_H__,%B1" CR_TAB
3961 "out __SREG__,__tmp_reg__" CR_TAB
3962 "out __SP_L__,%A1", xop, plen, -5);
3963 }
3964 else if (test_hard_reg_class (STACK_REG, src))
3965 {
3966 return !AVR_HAVE_SPH
3967 ? avr_asm_len ("in %A0,__SP_L__" CR_TAB
3968 "clr %B0", xop, plen, -2)
3969
3970 : avr_asm_len ("in %A0,__SP_L__" CR_TAB
3971 "in %B0,__SP_H__", xop, plen, -2);
3972 }
3973
3974 return AVR_HAVE_MOVW
3975 ? avr_asm_len ("movw %0,%1", xop, plen, -1)
3976
3977 : avr_asm_len ("mov %A0,%A1" CR_TAB
3978 "mov %B0,%B1", xop, plen, -2);
3979 } /* REG_P (src) */
3980 else if (CONSTANT_P (src))
3981 {
3982 return output_reload_inhi (xop, NULL, plen);
3983 }
3984 else if (MEM_P (src))
3985 {
3986 return out_movhi_r_mr (insn, xop, plen); /* mov r,m */
3987 }
3988 }
3989 else if (MEM_P (dest))
3990 {
3991 rtx xop[2];
3992
3993 xop[0] = dest;
3994 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
3995
3996 return out_movhi_mr_r (insn, xop, plen);
3997 }
3998
3999 fatal_insn ("invalid insn:", insn);
4000
4001 return "";
4002 }
4003
4004
4005 /* Same as out_movqi_r_mr, but TINY does not have ADIW or SBIW */
4006
4007 static const char*
avr_out_movqi_r_mr_reg_disp_tiny(rtx_insn * insn,rtx op[],int * plen)4008 avr_out_movqi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
4009 {
4010 rtx dest = op[0];
4011 rtx src = op[1];
4012 rtx x = XEXP (src, 0);
4013
4014 avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4015 "ld %0,%b1" , op, plen, -3);
4016
4017 if (!reg_overlap_mentioned_p (dest, XEXP (x, 0))
4018 && !reg_unused_after (insn, XEXP (x, 0)))
4019 avr_asm_len (TINY_SBIW (%I1, %J1, %o1), op, plen, 2);
4020
4021 return "";
4022 }
4023
4024 static const char*
out_movqi_r_mr(rtx_insn * insn,rtx op[],int * plen)4025 out_movqi_r_mr (rtx_insn *insn, rtx op[], int *plen)
4026 {
4027 rtx dest = op[0];
4028 rtx src = op[1];
4029 rtx x = XEXP (src, 0);
4030
4031 if (CONSTANT_ADDRESS_P (x))
4032 {
4033 int n_words = AVR_TINY ? 1 : 2;
4034 return io_address_operand (x, QImode)
4035 ? avr_asm_len ("in %0,%i1", op, plen, -1)
4036 : avr_asm_len ("lds %0,%m1", op, plen, -n_words);
4037 }
4038
4039 if (GET_CODE (x) == PLUS
4040 && REG_P (XEXP (x, 0))
4041 && CONST_INT_P (XEXP (x, 1)))
4042 {
4043 /* memory access by reg+disp */
4044
4045 int disp = INTVAL (XEXP (x, 1));
4046
4047 if (AVR_TINY)
4048 return avr_out_movqi_r_mr_reg_disp_tiny (insn, op, plen);
4049
4050 if (disp - GET_MODE_SIZE (GET_MODE (src)) >= 63)
4051 {
4052 if (REGNO (XEXP (x, 0)) != REG_Y)
4053 fatal_insn ("incorrect insn:",insn);
4054
4055 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
4056 return avr_asm_len ("adiw r28,%o1-63" CR_TAB
4057 "ldd %0,Y+63" CR_TAB
4058 "sbiw r28,%o1-63", op, plen, -3);
4059
4060 return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
4061 "sbci r29,hi8(-%o1)" CR_TAB
4062 "ld %0,Y" CR_TAB
4063 "subi r28,lo8(%o1)" CR_TAB
4064 "sbci r29,hi8(%o1)", op, plen, -5);
4065 }
4066 else if (REGNO (XEXP (x, 0)) == REG_X)
4067 {
4068 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
4069 it but I have this situation with extremal optimizing options. */
4070
4071 avr_asm_len ("adiw r26,%o1" CR_TAB
4072 "ld %0,X", op, plen, -2);
4073
4074 if (!reg_overlap_mentioned_p (dest, XEXP (x, 0))
4075 && !reg_unused_after (insn, XEXP (x, 0)))
4076 {
4077 avr_asm_len ("sbiw r26,%o1", op, plen, 1);
4078 }
4079
4080 return "";
4081 }
4082
4083 return avr_asm_len ("ldd %0,%1", op, plen, -1);
4084 }
4085
4086 return avr_asm_len ("ld %0,%1", op, plen, -1);
4087 }
4088
4089
4090 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
4091
4092 static const char*
avr_out_movhi_r_mr_reg_no_disp_tiny(rtx_insn * insn,rtx op[],int * plen)4093 avr_out_movhi_r_mr_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
4094 {
4095 rtx dest = op[0];
4096 rtx src = op[1];
4097 rtx base = XEXP (src, 0);
4098
4099 int reg_dest = true_regnum (dest);
4100 int reg_base = true_regnum (base);
4101
4102 if (reg_dest == reg_base) /* R = (R) */
4103 return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
4104 "ld %B0,%1" CR_TAB
4105 "mov %A0,__tmp_reg__", op, plen, -3);
4106
4107 avr_asm_len ("ld %A0,%1+" CR_TAB
4108 "ld %B0,%1", op, plen, -2);
4109
4110 if (!reg_unused_after (insn, base))
4111 avr_asm_len (TINY_SBIW (%E1, %F1, 1), op, plen, 2);
4112
4113 return "";
4114 }
4115
4116
4117 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
4118
4119 static const char*
avr_out_movhi_r_mr_reg_disp_tiny(rtx_insn * insn,rtx op[],int * plen)4120 avr_out_movhi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
4121 {
4122 rtx dest = op[0];
4123 rtx src = op[1];
4124 rtx base = XEXP (src, 0);
4125
4126 int reg_dest = true_regnum (dest);
4127 int reg_base = true_regnum (XEXP (base, 0));
4128
4129 if (reg_base == reg_dest)
4130 {
4131 return avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4132 "ld __tmp_reg__,%b1+" CR_TAB
4133 "ld %B0,%b1" CR_TAB
4134 "mov %A0,__tmp_reg__", op, plen, -5);
4135 }
4136 else
4137 {
4138 avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4139 "ld %A0,%b1+" CR_TAB
4140 "ld %B0,%b1", op, plen, -4);
4141
4142 if (!reg_unused_after (insn, XEXP (base, 0)))
4143 avr_asm_len (TINY_SBIW (%I1, %J1, %o1+1), op, plen, 2);
4144
4145 return "";
4146 }
4147 }
4148
4149
4150 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
4151
4152 static const char*
avr_out_movhi_r_mr_pre_dec_tiny(rtx_insn * insn,rtx op[],int * plen)4153 avr_out_movhi_r_mr_pre_dec_tiny (rtx_insn *insn, rtx op[], int *plen)
4154 {
4155 int mem_volatile_p = 0;
4156 rtx dest = op[0];
4157 rtx src = op[1];
4158 rtx base = XEXP (src, 0);
4159
4160 /* "volatile" forces reading low byte first, even if less efficient,
4161 for correct operation with 16-bit I/O registers. */
4162 mem_volatile_p = MEM_VOLATILE_P (src);
4163
4164 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
4165 fatal_insn ("incorrect insn:", insn);
4166
4167 if (!mem_volatile_p)
4168 return avr_asm_len ("ld %B0,%1" CR_TAB
4169 "ld %A0,%1", op, plen, -2);
4170
4171 return avr_asm_len (TINY_SBIW (%I1, %J1, 2) CR_TAB
4172 "ld %A0,%p1+" CR_TAB
4173 "ld %B0,%p1" CR_TAB
4174 TINY_SBIW (%I1, %J1, 1), op, plen, -6);
4175 }
4176
4177
4178 static const char*
out_movhi_r_mr(rtx_insn * insn,rtx op[],int * plen)4179 out_movhi_r_mr (rtx_insn *insn, rtx op[], int *plen)
4180 {
4181 rtx dest = op[0];
4182 rtx src = op[1];
4183 rtx base = XEXP (src, 0);
4184 int reg_dest = true_regnum (dest);
4185 int reg_base = true_regnum (base);
4186 /* "volatile" forces reading low byte first, even if less efficient,
4187 for correct operation with 16-bit I/O registers. */
4188 int mem_volatile_p = MEM_VOLATILE_P (src);
4189
4190 if (reg_base > 0)
4191 {
4192 if (AVR_TINY)
4193 return avr_out_movhi_r_mr_reg_no_disp_tiny (insn, op, plen);
4194
4195 if (reg_dest == reg_base) /* R = (R) */
4196 return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
4197 "ld %B0,%1" CR_TAB
4198 "mov %A0,__tmp_reg__", op, plen, -3);
4199
4200 if (reg_base != REG_X)
4201 return avr_asm_len ("ld %A0,%1" CR_TAB
4202 "ldd %B0,%1+1", op, plen, -2);
4203
4204 avr_asm_len ("ld %A0,X+" CR_TAB
4205 "ld %B0,X", op, plen, -2);
4206
4207 if (!reg_unused_after (insn, base))
4208 avr_asm_len ("sbiw r26,1", op, plen, 1);
4209
4210 return "";
4211 }
4212 else if (GET_CODE (base) == PLUS) /* (R + i) */
4213 {
4214 int disp = INTVAL (XEXP (base, 1));
4215 int reg_base = true_regnum (XEXP (base, 0));
4216
4217 if (AVR_TINY)
4218 return avr_out_movhi_r_mr_reg_disp_tiny (insn, op, plen);
4219
4220 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
4221 {
4222 if (REGNO (XEXP (base, 0)) != REG_Y)
4223 fatal_insn ("incorrect insn:",insn);
4224
4225 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (src))
4226 ? avr_asm_len ("adiw r28,%o1-62" CR_TAB
4227 "ldd %A0,Y+62" CR_TAB
4228 "ldd %B0,Y+63" CR_TAB
4229 "sbiw r28,%o1-62", op, plen, -4)
4230
4231 : avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
4232 "sbci r29,hi8(-%o1)" CR_TAB
4233 "ld %A0,Y" CR_TAB
4234 "ldd %B0,Y+1" CR_TAB
4235 "subi r28,lo8(%o1)" CR_TAB
4236 "sbci r29,hi8(%o1)", op, plen, -6);
4237 }
4238
4239 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
4240 it but I have this situation with extremal
4241 optimization options. */
4242
4243 if (reg_base == REG_X)
4244 {
4245 if (reg_base == reg_dest)
4246 return avr_asm_len ("adiw r26,%o1" CR_TAB
4247 "ld __tmp_reg__,X+" CR_TAB
4248 "ld %B0,X" CR_TAB
4249 "mov %A0,__tmp_reg__", op, plen, -4);
4250
4251 avr_asm_len ("adiw r26,%o1" CR_TAB
4252 "ld %A0,X+" CR_TAB
4253 "ld %B0,X", op, plen, -3);
4254
4255 if (!reg_unused_after (insn, XEXP (base, 0)))
4256 avr_asm_len ("sbiw r26,%o1+1", op, plen, 1);
4257
4258 return "";
4259 }
4260
4261 return reg_base == reg_dest
4262 ? avr_asm_len ("ldd __tmp_reg__,%A1" CR_TAB
4263 "ldd %B0,%B1" CR_TAB
4264 "mov %A0,__tmp_reg__", op, plen, -3)
4265
4266 : avr_asm_len ("ldd %A0,%A1" CR_TAB
4267 "ldd %B0,%B1", op, plen, -2);
4268 }
4269 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4270 {
4271 if (AVR_TINY)
4272 return avr_out_movhi_r_mr_pre_dec_tiny (insn, op, plen);
4273
4274 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
4275 fatal_insn ("incorrect insn:", insn);
4276
4277 if (!mem_volatile_p)
4278 return avr_asm_len ("ld %B0,%1" CR_TAB
4279 "ld %A0,%1", op, plen, -2);
4280
4281 return REGNO (XEXP (base, 0)) == REG_X
4282 ? avr_asm_len ("sbiw r26,2" CR_TAB
4283 "ld %A0,X+" CR_TAB
4284 "ld %B0,X" CR_TAB
4285 "sbiw r26,1", op, plen, -4)
4286
4287 : avr_asm_len ("sbiw %r1,2" CR_TAB
4288 "ld %A0,%p1" CR_TAB
4289 "ldd %B0,%p1+1", op, plen, -3);
4290 }
4291 else if (GET_CODE (base) == POST_INC) /* (R++) */
4292 {
4293 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
4294 fatal_insn ("incorrect insn:", insn);
4295
4296 return avr_asm_len ("ld %A0,%1" CR_TAB
4297 "ld %B0,%1", op, plen, -2);
4298 }
4299 else if (CONSTANT_ADDRESS_P (base))
4300 {
4301 int n_words = AVR_TINY ? 2 : 4;
4302 return io_address_operand (base, HImode)
4303 ? avr_asm_len ("in %A0,%i1" CR_TAB
4304 "in %B0,%i1+1", op, plen, -2)
4305
4306 : avr_asm_len ("lds %A0,%m1" CR_TAB
4307 "lds %B0,%m1+1", op, plen, -n_words);
4308 }
4309
4310 fatal_insn ("unknown move insn:",insn);
4311 return "";
4312 }
4313
4314 static const char*
avr_out_movsi_r_mr_reg_no_disp_tiny(rtx_insn * insn,rtx op[],int * l)4315 avr_out_movsi_r_mr_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *l)
4316 {
4317 rtx dest = op[0];
4318 rtx src = op[1];
4319 rtx base = XEXP (src, 0);
4320 int reg_dest = true_regnum (dest);
4321 int reg_base = true_regnum (base);
4322
4323 if (reg_dest == reg_base)
4324 {
4325 /* "ld r26,-X" is undefined */
4326 return *l = 9, (TINY_ADIW (%E1, %F1, 3) CR_TAB
4327 "ld %D0,%1" CR_TAB
4328 "ld %C0,-%1" CR_TAB
4329 "ld __tmp_reg__,-%1" CR_TAB
4330 TINY_SBIW (%E1, %F1, 1) CR_TAB
4331 "ld %A0,%1" CR_TAB
4332 "mov %B0,__tmp_reg__");
4333 }
4334 else if (reg_dest == reg_base - 2)
4335 {
4336 return *l = 5, ("ld %A0,%1+" CR_TAB
4337 "ld %B0,%1+" CR_TAB
4338 "ld __tmp_reg__,%1+" CR_TAB
4339 "ld %D0,%1" CR_TAB
4340 "mov %C0,__tmp_reg__");
4341 }
4342 else if (reg_unused_after (insn, base))
4343 {
4344 return *l = 4, ("ld %A0,%1+" CR_TAB
4345 "ld %B0,%1+" CR_TAB
4346 "ld %C0,%1+" CR_TAB
4347 "ld %D0,%1");
4348 }
4349 else
4350 {
4351 return *l = 6, ("ld %A0,%1+" CR_TAB
4352 "ld %B0,%1+" CR_TAB
4353 "ld %C0,%1+" CR_TAB
4354 "ld %D0,%1" CR_TAB
4355 TINY_SBIW (%E1, %F1, 3));
4356 }
4357 }
4358
4359
4360 static const char*
avr_out_movsi_r_mr_reg_disp_tiny(rtx_insn * insn,rtx op[],int * l)4361 avr_out_movsi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *l)
4362 {
4363 rtx dest = op[0];
4364 rtx src = op[1];
4365 rtx base = XEXP (src, 0);
4366 int reg_dest = true_regnum (dest);
4367 int reg_base = true_regnum (XEXP (base, 0));
4368
4369 if (reg_dest == reg_base)
4370 {
4371 /* "ld r26,-X" is undefined */
4372 return *l = 9, (TINY_ADIW (%I1, %J1, %o1+3) CR_TAB
4373 "ld %D0,%b1" CR_TAB
4374 "ld %C0,-%b1" CR_TAB
4375 "ld __tmp_reg__,-%b1" CR_TAB
4376 TINY_SBIW (%I1, %J1, 1) CR_TAB
4377 "ld %A0,%b1" CR_TAB
4378 "mov %B0,__tmp_reg__");
4379 }
4380 else if (reg_dest == reg_base - 2)
4381 {
4382 return *l = 7, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4383 "ld %A0,%b1+" CR_TAB
4384 "ld %B0,%b1+" CR_TAB
4385 "ld __tmp_reg__,%b1+" CR_TAB
4386 "ld %D0,%b1" CR_TAB
4387 "mov %C0,__tmp_reg__");
4388 }
4389 else if (reg_unused_after (insn, XEXP (base, 0)))
4390 {
4391 return *l = 6, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4392 "ld %A0,%b1+" CR_TAB
4393 "ld %B0,%b1+" CR_TAB
4394 "ld %C0,%b1+" CR_TAB
4395 "ld %D0,%b1");
4396 }
4397 else
4398 {
4399 return *l = 8, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4400 "ld %A0,%b1+" CR_TAB
4401 "ld %B0,%b1+" CR_TAB
4402 "ld %C0,%b1+" CR_TAB
4403 "ld %D0,%b1" CR_TAB
4404 TINY_SBIW (%I1, %J1, %o1+3));
4405 }
4406 }
4407
4408 static const char*
out_movsi_r_mr(rtx_insn * insn,rtx op[],int * l)4409 out_movsi_r_mr (rtx_insn *insn, rtx op[], int *l)
4410 {
4411 rtx dest = op[0];
4412 rtx src = op[1];
4413 rtx base = XEXP (src, 0);
4414 int reg_dest = true_regnum (dest);
4415 int reg_base = true_regnum (base);
4416 int tmp;
4417
4418 if (!l)
4419 l = &tmp;
4420
4421 if (reg_base > 0)
4422 {
4423 if (AVR_TINY)
4424 return avr_out_movsi_r_mr_reg_no_disp_tiny (insn, op, l);
4425
4426 if (reg_base == REG_X) /* (R26) */
4427 {
4428 if (reg_dest == REG_X)
4429 /* "ld r26,-X" is undefined */
4430 return *l=7, ("adiw r26,3" CR_TAB
4431 "ld r29,X" CR_TAB
4432 "ld r28,-X" CR_TAB
4433 "ld __tmp_reg__,-X" CR_TAB
4434 "sbiw r26,1" CR_TAB
4435 "ld r26,X" CR_TAB
4436 "mov r27,__tmp_reg__");
4437 else if (reg_dest == REG_X - 2)
4438 return *l=5, ("ld %A0,X+" CR_TAB
4439 "ld %B0,X+" CR_TAB
4440 "ld __tmp_reg__,X+" CR_TAB
4441 "ld %D0,X" CR_TAB
4442 "mov %C0,__tmp_reg__");
4443 else if (reg_unused_after (insn, base))
4444 return *l=4, ("ld %A0,X+" CR_TAB
4445 "ld %B0,X+" CR_TAB
4446 "ld %C0,X+" CR_TAB
4447 "ld %D0,X");
4448 else
4449 return *l=5, ("ld %A0,X+" CR_TAB
4450 "ld %B0,X+" CR_TAB
4451 "ld %C0,X+" CR_TAB
4452 "ld %D0,X" CR_TAB
4453 "sbiw r26,3");
4454 }
4455 else
4456 {
4457 if (reg_dest == reg_base)
4458 return *l=5, ("ldd %D0,%1+3" CR_TAB
4459 "ldd %C0,%1+2" CR_TAB
4460 "ldd __tmp_reg__,%1+1" CR_TAB
4461 "ld %A0,%1" CR_TAB
4462 "mov %B0,__tmp_reg__");
4463 else if (reg_base == reg_dest + 2)
4464 return *l=5, ("ld %A0,%1" CR_TAB
4465 "ldd %B0,%1+1" CR_TAB
4466 "ldd __tmp_reg__,%1+2" CR_TAB
4467 "ldd %D0,%1+3" CR_TAB
4468 "mov %C0,__tmp_reg__");
4469 else
4470 return *l=4, ("ld %A0,%1" CR_TAB
4471 "ldd %B0,%1+1" CR_TAB
4472 "ldd %C0,%1+2" CR_TAB
4473 "ldd %D0,%1+3");
4474 }
4475 }
4476 else if (GET_CODE (base) == PLUS) /* (R + i) */
4477 {
4478 int disp = INTVAL (XEXP (base, 1));
4479
4480 if (AVR_TINY)
4481 return avr_out_movsi_r_mr_reg_disp_tiny (insn, op, l);
4482
4483 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
4484 {
4485 if (REGNO (XEXP (base, 0)) != REG_Y)
4486 fatal_insn ("incorrect insn:",insn);
4487
4488 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
4489 return *l = 6, ("adiw r28,%o1-60" CR_TAB
4490 "ldd %A0,Y+60" CR_TAB
4491 "ldd %B0,Y+61" CR_TAB
4492 "ldd %C0,Y+62" CR_TAB
4493 "ldd %D0,Y+63" CR_TAB
4494 "sbiw r28,%o1-60");
4495
4496 return *l = 8, ("subi r28,lo8(-%o1)" CR_TAB
4497 "sbci r29,hi8(-%o1)" CR_TAB
4498 "ld %A0,Y" CR_TAB
4499 "ldd %B0,Y+1" CR_TAB
4500 "ldd %C0,Y+2" CR_TAB
4501 "ldd %D0,Y+3" CR_TAB
4502 "subi r28,lo8(%o1)" CR_TAB
4503 "sbci r29,hi8(%o1)");
4504 }
4505
4506 reg_base = true_regnum (XEXP (base, 0));
4507 if (reg_base == REG_X)
4508 {
4509 /* R = (X + d) */
4510 if (reg_dest == REG_X)
4511 {
4512 *l = 7;
4513 /* "ld r26,-X" is undefined */
4514 return ("adiw r26,%o1+3" CR_TAB
4515 "ld r29,X" CR_TAB
4516 "ld r28,-X" CR_TAB
4517 "ld __tmp_reg__,-X" CR_TAB
4518 "sbiw r26,1" CR_TAB
4519 "ld r26,X" CR_TAB
4520 "mov r27,__tmp_reg__");
4521 }
4522 *l = 6;
4523 if (reg_dest == REG_X - 2)
4524 return ("adiw r26,%o1" CR_TAB
4525 "ld r24,X+" CR_TAB
4526 "ld r25,X+" CR_TAB
4527 "ld __tmp_reg__,X+" CR_TAB
4528 "ld r27,X" CR_TAB
4529 "mov r26,__tmp_reg__");
4530
4531 return ("adiw r26,%o1" CR_TAB
4532 "ld %A0,X+" CR_TAB
4533 "ld %B0,X+" CR_TAB
4534 "ld %C0,X+" CR_TAB
4535 "ld %D0,X" CR_TAB
4536 "sbiw r26,%o1+3");
4537 }
4538 if (reg_dest == reg_base)
4539 return *l=5, ("ldd %D0,%D1" CR_TAB
4540 "ldd %C0,%C1" CR_TAB
4541 "ldd __tmp_reg__,%B1" CR_TAB
4542 "ldd %A0,%A1" CR_TAB
4543 "mov %B0,__tmp_reg__");
4544 else if (reg_dest == reg_base - 2)
4545 return *l=5, ("ldd %A0,%A1" CR_TAB
4546 "ldd %B0,%B1" CR_TAB
4547 "ldd __tmp_reg__,%C1" CR_TAB
4548 "ldd %D0,%D1" CR_TAB
4549 "mov %C0,__tmp_reg__");
4550 return *l=4, ("ldd %A0,%A1" CR_TAB
4551 "ldd %B0,%B1" CR_TAB
4552 "ldd %C0,%C1" CR_TAB
4553 "ldd %D0,%D1");
4554 }
4555 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4556 return *l=4, ("ld %D0,%1" CR_TAB
4557 "ld %C0,%1" CR_TAB
4558 "ld %B0,%1" CR_TAB
4559 "ld %A0,%1");
4560 else if (GET_CODE (base) == POST_INC) /* (R++) */
4561 return *l=4, ("ld %A0,%1" CR_TAB
4562 "ld %B0,%1" CR_TAB
4563 "ld %C0,%1" CR_TAB
4564 "ld %D0,%1");
4565 else if (CONSTANT_ADDRESS_P (base))
4566 {
4567 if (io_address_operand (base, SImode))
4568 {
4569 *l = 4;
4570 return ("in %A0,%i1" CR_TAB
4571 "in %B0,%i1+1" CR_TAB
4572 "in %C0,%i1+2" CR_TAB
4573 "in %D0,%i1+3");
4574 }
4575 else
4576 {
4577 *l = AVR_TINY ? 4 : 8;
4578 return ("lds %A0,%m1" CR_TAB
4579 "lds %B0,%m1+1" CR_TAB
4580 "lds %C0,%m1+2" CR_TAB
4581 "lds %D0,%m1+3");
4582 }
4583 }
4584
4585 fatal_insn ("unknown move insn:",insn);
4586 return "";
4587 }
4588
4589 static const char*
avr_out_movsi_mr_r_reg_no_disp_tiny(rtx_insn * insn,rtx op[],int * l)4590 avr_out_movsi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *l)
4591 {
4592 rtx dest = op[0];
4593 rtx src = op[1];
4594 rtx base = XEXP (dest, 0);
4595 int reg_base = true_regnum (base);
4596 int reg_src = true_regnum (src);
4597
4598 if (reg_base == reg_src)
4599 {
4600 /* "ld r26,-X" is undefined */
4601 if (reg_unused_after (insn, base))
4602 {
4603 return *l = 7, ("mov __tmp_reg__, %B1" CR_TAB
4604 "st %0,%A1" CR_TAB
4605 TINY_ADIW (%E0, %F0, 1) CR_TAB
4606 "st %0+,__tmp_reg__" CR_TAB
4607 "st %0+,%C1" CR_TAB
4608 "st %0+,%D1");
4609 }
4610 else
4611 {
4612 return *l = 9, ("mov __tmp_reg__, %B1" CR_TAB
4613 "st %0,%A1" CR_TAB
4614 TINY_ADIW (%E0, %F0, 1) CR_TAB
4615 "st %0+,__tmp_reg__" CR_TAB
4616 "st %0+,%C1" CR_TAB
4617 "st %0+,%D1" CR_TAB
4618 TINY_SBIW (%E0, %F0, 3));
4619 }
4620 }
4621 else if (reg_base == reg_src + 2)
4622 {
4623 if (reg_unused_after (insn, base))
4624 return *l = 7, ("mov __zero_reg__,%C1" CR_TAB
4625 "mov __tmp_reg__,%D1" CR_TAB
4626 "st %0+,%A1" CR_TAB
4627 "st %0+,%B1" CR_TAB
4628 "st %0+,__zero_reg__" CR_TAB
4629 "st %0,__tmp_reg__" CR_TAB
4630 "clr __zero_reg__");
4631 else
4632 return *l = 9, ("mov __zero_reg__,%C1" CR_TAB
4633 "mov __tmp_reg__,%D1" CR_TAB
4634 "st %0+,%A1" CR_TAB
4635 "st %0+,%B1" CR_TAB
4636 "st %0+,__zero_reg__" CR_TAB
4637 "st %0,__tmp_reg__" CR_TAB
4638 "clr __zero_reg__" CR_TAB
4639 TINY_SBIW (%E0, %F0, 3));
4640 }
4641
4642 return *l = 6, ("st %0+,%A1" CR_TAB
4643 "st %0+,%B1" CR_TAB
4644 "st %0+,%C1" CR_TAB
4645 "st %0,%D1" CR_TAB
4646 TINY_SBIW (%E0, %F0, 3));
4647 }
4648
4649 static const char*
avr_out_movsi_mr_r_reg_disp_tiny(rtx op[],int * l)4650 avr_out_movsi_mr_r_reg_disp_tiny (rtx op[], int *l)
4651 {
4652 rtx dest = op[0];
4653 rtx src = op[1];
4654 rtx base = XEXP (dest, 0);
4655 int reg_base = REGNO (XEXP (base, 0));
4656 int reg_src =true_regnum (src);
4657
4658 if (reg_base == reg_src)
4659 {
4660 *l = 11;
4661 return ("mov __tmp_reg__,%A2" CR_TAB
4662 "mov __zero_reg__,%B2" CR_TAB
4663 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4664 "st %b0+,__tmp_reg__" CR_TAB
4665 "st %b0+,__zero_reg__" CR_TAB
4666 "st %b0+,%C2" CR_TAB
4667 "st %b0,%D2" CR_TAB
4668 "clr __zero_reg__" CR_TAB
4669 TINY_SBIW (%I0, %J0, %o0+3));
4670 }
4671 else if (reg_src == reg_base - 2)
4672 {
4673 *l = 11;
4674 return ("mov __tmp_reg__,%C2" CR_TAB
4675 "mov __zero_reg__,%D2" CR_TAB
4676 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4677 "st %b0+,%A0" CR_TAB
4678 "st %b0+,%B0" CR_TAB
4679 "st %b0+,__tmp_reg__" CR_TAB
4680 "st %b0,__zero_reg__" CR_TAB
4681 "clr __zero_reg__" CR_TAB
4682 TINY_SBIW (%I0, %J0, %o0+3));
4683 }
4684 *l = 8;
4685 return (TINY_ADIW (%I0, %J0, %o0) CR_TAB
4686 "st %b0+,%A1" CR_TAB
4687 "st %b0+,%B1" CR_TAB
4688 "st %b0+,%C1" CR_TAB
4689 "st %b0,%D1" CR_TAB
4690 TINY_SBIW (%I0, %J0, %o0+3));
4691 }
4692
4693 static const char*
out_movsi_mr_r(rtx_insn * insn,rtx op[],int * l)4694 out_movsi_mr_r (rtx_insn *insn, rtx op[], int *l)
4695 {
4696 rtx dest = op[0];
4697 rtx src = op[1];
4698 rtx base = XEXP (dest, 0);
4699 int reg_base = true_regnum (base);
4700 int reg_src = true_regnum (src);
4701 int tmp;
4702
4703 if (!l)
4704 l = &tmp;
4705
4706 if (CONSTANT_ADDRESS_P (base))
4707 {
4708 if (io_address_operand (base, SImode))
4709 {
4710 return *l=4,("out %i0, %A1" CR_TAB
4711 "out %i0+1,%B1" CR_TAB
4712 "out %i0+2,%C1" CR_TAB
4713 "out %i0+3,%D1");
4714 }
4715 else
4716 {
4717 *l = AVR_TINY ? 4 : 8;
4718 return ("sts %m0,%A1" CR_TAB
4719 "sts %m0+1,%B1" CR_TAB
4720 "sts %m0+2,%C1" CR_TAB
4721 "sts %m0+3,%D1");
4722 }
4723 }
4724
4725 if (reg_base > 0) /* (r) */
4726 {
4727 if (AVR_TINY)
4728 return avr_out_movsi_mr_r_reg_no_disp_tiny (insn, op, l);
4729
4730 if (reg_base == REG_X) /* (R26) */
4731 {
4732 if (reg_src == REG_X)
4733 {
4734 /* "st X+,r26" is undefined */
4735 if (reg_unused_after (insn, base))
4736 return *l=6, ("mov __tmp_reg__,r27" CR_TAB
4737 "st X,r26" CR_TAB
4738 "adiw r26,1" CR_TAB
4739 "st X+,__tmp_reg__" CR_TAB
4740 "st X+,r28" CR_TAB
4741 "st X,r29");
4742 else
4743 return *l=7, ("mov __tmp_reg__,r27" CR_TAB
4744 "st X,r26" CR_TAB
4745 "adiw r26,1" CR_TAB
4746 "st X+,__tmp_reg__" CR_TAB
4747 "st X+,r28" CR_TAB
4748 "st X,r29" CR_TAB
4749 "sbiw r26,3");
4750 }
4751 else if (reg_base == reg_src + 2)
4752 {
4753 if (reg_unused_after (insn, base))
4754 return *l=7, ("mov __zero_reg__,%C1" CR_TAB
4755 "mov __tmp_reg__,%D1" CR_TAB
4756 "st %0+,%A1" CR_TAB
4757 "st %0+,%B1" CR_TAB
4758 "st %0+,__zero_reg__" CR_TAB
4759 "st %0,__tmp_reg__" CR_TAB
4760 "clr __zero_reg__");
4761 else
4762 return *l=8, ("mov __zero_reg__,%C1" CR_TAB
4763 "mov __tmp_reg__,%D1" CR_TAB
4764 "st %0+,%A1" CR_TAB
4765 "st %0+,%B1" CR_TAB
4766 "st %0+,__zero_reg__" CR_TAB
4767 "st %0,__tmp_reg__" CR_TAB
4768 "clr __zero_reg__" CR_TAB
4769 "sbiw r26,3");
4770 }
4771 return *l=5, ("st %0+,%A1" CR_TAB
4772 "st %0+,%B1" CR_TAB
4773 "st %0+,%C1" CR_TAB
4774 "st %0,%D1" CR_TAB
4775 "sbiw r26,3");
4776 }
4777 else
4778 return *l=4, ("st %0,%A1" CR_TAB
4779 "std %0+1,%B1" CR_TAB
4780 "std %0+2,%C1" CR_TAB
4781 "std %0+3,%D1");
4782 }
4783 else if (GET_CODE (base) == PLUS) /* (R + i) */
4784 {
4785 int disp = INTVAL (XEXP (base, 1));
4786
4787 if (AVR_TINY)
4788 return avr_out_movsi_mr_r_reg_disp_tiny (op, l);
4789
4790 reg_base = REGNO (XEXP (base, 0));
4791 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
4792 {
4793 if (reg_base != REG_Y)
4794 fatal_insn ("incorrect insn:",insn);
4795
4796 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
4797 return *l = 6, ("adiw r28,%o0-60" CR_TAB
4798 "std Y+60,%A1" CR_TAB
4799 "std Y+61,%B1" CR_TAB
4800 "std Y+62,%C1" CR_TAB
4801 "std Y+63,%D1" CR_TAB
4802 "sbiw r28,%o0-60");
4803
4804 return *l = 8, ("subi r28,lo8(-%o0)" CR_TAB
4805 "sbci r29,hi8(-%o0)" CR_TAB
4806 "st Y,%A1" CR_TAB
4807 "std Y+1,%B1" CR_TAB
4808 "std Y+2,%C1" CR_TAB
4809 "std Y+3,%D1" CR_TAB
4810 "subi r28,lo8(%o0)" CR_TAB
4811 "sbci r29,hi8(%o0)");
4812 }
4813 if (reg_base == REG_X)
4814 {
4815 /* (X + d) = R */
4816 if (reg_src == REG_X)
4817 {
4818 *l = 9;
4819 return ("mov __tmp_reg__,r26" CR_TAB
4820 "mov __zero_reg__,r27" CR_TAB
4821 "adiw r26,%o0" CR_TAB
4822 "st X+,__tmp_reg__" CR_TAB
4823 "st X+,__zero_reg__" CR_TAB
4824 "st X+,r28" CR_TAB
4825 "st X,r29" CR_TAB
4826 "clr __zero_reg__" CR_TAB
4827 "sbiw r26,%o0+3");
4828 }
4829 else if (reg_src == REG_X - 2)
4830 {
4831 *l = 9;
4832 return ("mov __tmp_reg__,r26" CR_TAB
4833 "mov __zero_reg__,r27" CR_TAB
4834 "adiw r26,%o0" CR_TAB
4835 "st X+,r24" CR_TAB
4836 "st X+,r25" CR_TAB
4837 "st X+,__tmp_reg__" CR_TAB
4838 "st X,__zero_reg__" CR_TAB
4839 "clr __zero_reg__" CR_TAB
4840 "sbiw r26,%o0+3");
4841 }
4842 *l = 6;
4843 return ("adiw r26,%o0" CR_TAB
4844 "st X+,%A1" CR_TAB
4845 "st X+,%B1" CR_TAB
4846 "st X+,%C1" CR_TAB
4847 "st X,%D1" CR_TAB
4848 "sbiw r26,%o0+3");
4849 }
4850 return *l=4, ("std %A0,%A1" CR_TAB
4851 "std %B0,%B1" CR_TAB
4852 "std %C0,%C1" CR_TAB
4853 "std %D0,%D1");
4854 }
4855 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4856 return *l=4, ("st %0,%D1" CR_TAB
4857 "st %0,%C1" CR_TAB
4858 "st %0,%B1" CR_TAB
4859 "st %0,%A1");
4860 else if (GET_CODE (base) == POST_INC) /* (R++) */
4861 return *l=4, ("st %0,%A1" CR_TAB
4862 "st %0,%B1" CR_TAB
4863 "st %0,%C1" CR_TAB
4864 "st %0,%D1");
4865 fatal_insn ("unknown move insn:",insn);
4866 return "";
4867 }
4868
4869 const char *
output_movsisf(rtx_insn * insn,rtx operands[],int * l)4870 output_movsisf (rtx_insn *insn, rtx operands[], int *l)
4871 {
4872 int dummy;
4873 rtx dest = operands[0];
4874 rtx src = operands[1];
4875 int *real_l = l;
4876
4877 if (avr_mem_flash_p (src)
4878 || avr_mem_flash_p (dest))
4879 {
4880 return avr_out_lpm (insn, operands, real_l);
4881 }
4882
4883 if (!l)
4884 l = &dummy;
4885
4886 gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 4);
4887
4888 if (REG_P (dest))
4889 {
4890 if (REG_P (src)) /* mov r,r */
4891 {
4892 if (true_regnum (dest) > true_regnum (src))
4893 {
4894 if (AVR_HAVE_MOVW)
4895 {
4896 *l = 2;
4897 return ("movw %C0,%C1" CR_TAB
4898 "movw %A0,%A1");
4899 }
4900 *l = 4;
4901 return ("mov %D0,%D1" CR_TAB
4902 "mov %C0,%C1" CR_TAB
4903 "mov %B0,%B1" CR_TAB
4904 "mov %A0,%A1");
4905 }
4906 else
4907 {
4908 if (AVR_HAVE_MOVW)
4909 {
4910 *l = 2;
4911 return ("movw %A0,%A1" CR_TAB
4912 "movw %C0,%C1");
4913 }
4914 *l = 4;
4915 return ("mov %A0,%A1" CR_TAB
4916 "mov %B0,%B1" CR_TAB
4917 "mov %C0,%C1" CR_TAB
4918 "mov %D0,%D1");
4919 }
4920 }
4921 else if (CONSTANT_P (src))
4922 {
4923 return output_reload_insisf (operands, NULL_RTX, real_l);
4924 }
4925 else if (MEM_P (src))
4926 return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
4927 }
4928 else if (MEM_P (dest))
4929 {
4930 const char *templ;
4931
4932 if (src == CONST0_RTX (GET_MODE (dest)))
4933 operands[1] = zero_reg_rtx;
4934
4935 templ = out_movsi_mr_r (insn, operands, real_l);
4936
4937 if (!real_l)
4938 output_asm_insn (templ, operands);
4939
4940 operands[1] = src;
4941 return "";
4942 }
4943 fatal_insn ("invalid insn:", insn);
4944 return "";
4945 }
4946
4947
4948 /* Handle loads of 24-bit types from memory to register. */
4949
4950 static const char*
avr_out_load_psi_reg_no_disp_tiny(rtx_insn * insn,rtx * op,int * plen)4951 avr_out_load_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
4952 {
4953 rtx dest = op[0];
4954 rtx src = op[1];
4955 rtx base = XEXP (src, 0);
4956 int reg_dest = true_regnum (dest);
4957 int reg_base = true_regnum (base);
4958
4959 if (reg_base == reg_dest)
4960 {
4961 return avr_asm_len (TINY_ADIW (%E1, %F1, 2) CR_TAB
4962 "ld %C0,%1" CR_TAB
4963 "ld __tmp_reg__,-%1" CR_TAB
4964 TINY_SBIW (%E1, %F1, 1) CR_TAB
4965 "ld %A0,%1" CR_TAB
4966 "mov %B0,__tmp_reg__", op, plen, -8);
4967 }
4968 else
4969 {
4970 avr_asm_len ("ld %A0,%1+" CR_TAB
4971 "ld %B0,%1+" CR_TAB
4972 "ld %C0,%1", op, plen, -3);
4973
4974 if (reg_dest != reg_base - 2
4975 && !reg_unused_after (insn, base))
4976 {
4977 avr_asm_len (TINY_SBIW (%E1, %F1, 2), op, plen, 2);
4978 }
4979 return "";
4980 }
4981 }
4982
4983 static const char*
avr_out_load_psi_reg_disp_tiny(rtx_insn * insn,rtx * op,int * plen)4984 avr_out_load_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
4985 {
4986 rtx dest = op[0];
4987 rtx src = op[1];
4988 rtx base = XEXP (src, 0);
4989 int reg_dest = true_regnum (dest);
4990 int reg_base = true_regnum (base);
4991
4992 reg_base = true_regnum (XEXP (base, 0));
4993 if (reg_base == reg_dest)
4994 {
4995 return avr_asm_len (TINY_ADIW (%I1, %J1, %o1+2) CR_TAB
4996 "ld %C0,%b1" CR_TAB
4997 "ld __tmp_reg__,-%b1" CR_TAB
4998 TINY_SBIW (%I1, %J1, 1) CR_TAB
4999 "ld %A0,%b1" CR_TAB
5000 "mov %B0,__tmp_reg__", op, plen, -8);
5001 }
5002 else
5003 {
5004 avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
5005 "ld %A0,%b1+" CR_TAB
5006 "ld %B0,%b1+" CR_TAB
5007 "ld %C0,%b1", op, plen, -5);
5008
5009 if (reg_dest != reg_base - 2
5010 && !reg_unused_after (insn, XEXP (base, 0)))
5011 avr_asm_len (TINY_SBIW (%I1, %J1, %o1+2), op, plen, 2);
5012
5013 return "";
5014 }
5015 }
5016
5017 static const char*
avr_out_load_psi(rtx_insn * insn,rtx * op,int * plen)5018 avr_out_load_psi (rtx_insn *insn, rtx *op, int *plen)
5019 {
5020 rtx dest = op[0];
5021 rtx src = op[1];
5022 rtx base = XEXP (src, 0);
5023 int reg_dest = true_regnum (dest);
5024 int reg_base = true_regnum (base);
5025
5026 if (reg_base > 0)
5027 {
5028 if (AVR_TINY)
5029 return avr_out_load_psi_reg_no_disp_tiny (insn, op, plen);
5030
5031 if (reg_base == REG_X) /* (R26) */
5032 {
5033 if (reg_dest == REG_X)
5034 /* "ld r26,-X" is undefined */
5035 return avr_asm_len ("adiw r26,2" CR_TAB
5036 "ld r28,X" CR_TAB
5037 "ld __tmp_reg__,-X" CR_TAB
5038 "sbiw r26,1" CR_TAB
5039 "ld r26,X" CR_TAB
5040 "mov r27,__tmp_reg__", op, plen, -6);
5041 else
5042 {
5043 avr_asm_len ("ld %A0,X+" CR_TAB
5044 "ld %B0,X+" CR_TAB
5045 "ld %C0,X", op, plen, -3);
5046
5047 if (reg_dest != REG_X - 2
5048 && !reg_unused_after (insn, base))
5049 {
5050 avr_asm_len ("sbiw r26,2", op, plen, 1);
5051 }
5052
5053 return "";
5054 }
5055 }
5056 else /* reg_base != REG_X */
5057 {
5058 if (reg_dest == reg_base)
5059 return avr_asm_len ("ldd %C0,%1+2" CR_TAB
5060 "ldd __tmp_reg__,%1+1" CR_TAB
5061 "ld %A0,%1" CR_TAB
5062 "mov %B0,__tmp_reg__", op, plen, -4);
5063 else
5064 return avr_asm_len ("ld %A0,%1" CR_TAB
5065 "ldd %B0,%1+1" CR_TAB
5066 "ldd %C0,%1+2", op, plen, -3);
5067 }
5068 }
5069 else if (GET_CODE (base) == PLUS) /* (R + i) */
5070 {
5071 int disp = INTVAL (XEXP (base, 1));
5072
5073 if (AVR_TINY)
5074 return avr_out_load_psi_reg_disp_tiny (insn, op, plen);
5075
5076 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
5077 {
5078 if (REGNO (XEXP (base, 0)) != REG_Y)
5079 fatal_insn ("incorrect insn:",insn);
5080
5081 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
5082 return avr_asm_len ("adiw r28,%o1-61" CR_TAB
5083 "ldd %A0,Y+61" CR_TAB
5084 "ldd %B0,Y+62" CR_TAB
5085 "ldd %C0,Y+63" CR_TAB
5086 "sbiw r28,%o1-61", op, plen, -5);
5087
5088 return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
5089 "sbci r29,hi8(-%o1)" CR_TAB
5090 "ld %A0,Y" CR_TAB
5091 "ldd %B0,Y+1" CR_TAB
5092 "ldd %C0,Y+2" CR_TAB
5093 "subi r28,lo8(%o1)" CR_TAB
5094 "sbci r29,hi8(%o1)", op, plen, -7);
5095 }
5096
5097 reg_base = true_regnum (XEXP (base, 0));
5098 if (reg_base == REG_X)
5099 {
5100 /* R = (X + d) */
5101 if (reg_dest == REG_X)
5102 {
5103 /* "ld r26,-X" is undefined */
5104 return avr_asm_len ("adiw r26,%o1+2" CR_TAB
5105 "ld r28,X" CR_TAB
5106 "ld __tmp_reg__,-X" CR_TAB
5107 "sbiw r26,1" CR_TAB
5108 "ld r26,X" CR_TAB
5109 "mov r27,__tmp_reg__", op, plen, -6);
5110 }
5111
5112 avr_asm_len ("adiw r26,%o1" CR_TAB
5113 "ld %A0,X+" CR_TAB
5114 "ld %B0,X+" CR_TAB
5115 "ld %C0,X", op, plen, -4);
5116
5117 if (reg_dest != REG_W
5118 && !reg_unused_after (insn, XEXP (base, 0)))
5119 avr_asm_len ("sbiw r26,%o1+2", op, plen, 1);
5120
5121 return "";
5122 }
5123
5124 if (reg_dest == reg_base)
5125 return avr_asm_len ("ldd %C0,%C1" CR_TAB
5126 "ldd __tmp_reg__,%B1" CR_TAB
5127 "ldd %A0,%A1" CR_TAB
5128 "mov %B0,__tmp_reg__", op, plen, -4);
5129
5130 return avr_asm_len ("ldd %A0,%A1" CR_TAB
5131 "ldd %B0,%B1" CR_TAB
5132 "ldd %C0,%C1", op, plen, -3);
5133 }
5134 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5135 return avr_asm_len ("ld %C0,%1" CR_TAB
5136 "ld %B0,%1" CR_TAB
5137 "ld %A0,%1", op, plen, -3);
5138 else if (GET_CODE (base) == POST_INC) /* (R++) */
5139 return avr_asm_len ("ld %A0,%1" CR_TAB
5140 "ld %B0,%1" CR_TAB
5141 "ld %C0,%1", op, plen, -3);
5142
5143 else if (CONSTANT_ADDRESS_P (base))
5144 {
5145 int n_words = AVR_TINY ? 3 : 6;
5146 return avr_asm_len ("lds %A0,%m1" CR_TAB
5147 "lds %B0,%m1+1" CR_TAB
5148 "lds %C0,%m1+2", op, plen , -n_words);
5149 }
5150
5151 fatal_insn ("unknown move insn:",insn);
5152 return "";
5153 }
5154
5155
5156 static const char*
avr_out_store_psi_reg_no_disp_tiny(rtx_insn * insn,rtx * op,int * plen)5157 avr_out_store_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
5158 {
5159 rtx dest = op[0];
5160 rtx src = op[1];
5161 rtx base = XEXP (dest, 0);
5162 int reg_base = true_regnum (base);
5163 int reg_src = true_regnum (src);
5164
5165 if (reg_base == reg_src)
5166 {
5167 avr_asm_len ("st %0,%A1" CR_TAB
5168 "mov __tmp_reg__,%B1" CR_TAB
5169 TINY_ADIW (%E0, %F0, 1) CR_TAB /* st X+, r27 is undefined */
5170 "st %0+,__tmp_reg__" CR_TAB
5171 "st %0,%C1", op, plen, -6);
5172
5173 }
5174 else if (reg_src == reg_base - 2)
5175 {
5176 avr_asm_len ("st %0,%A1" CR_TAB
5177 "mov __tmp_reg__,%C1" CR_TAB
5178 TINY_ADIW (%E0, %F0, 1) CR_TAB
5179 "st %0+,%B1" CR_TAB
5180 "st %0,__tmp_reg__", op, plen, 6);
5181 }
5182 else
5183 {
5184 avr_asm_len ("st %0+,%A1" CR_TAB
5185 "st %0+,%B1" CR_TAB
5186 "st %0,%C1", op, plen, -3);
5187 }
5188
5189 if (!reg_unused_after (insn, base))
5190 avr_asm_len (TINY_SBIW (%E0, %F0, 2), op, plen, 2);
5191
5192 return "";
5193 }
5194
5195 static const char*
avr_out_store_psi_reg_disp_tiny(rtx_insn * insn,rtx * op,int * plen)5196 avr_out_store_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
5197 {
5198 rtx dest = op[0];
5199 rtx src = op[1];
5200 rtx base = XEXP (dest, 0);
5201 int reg_base = REGNO (XEXP (base, 0));
5202 int reg_src = true_regnum (src);
5203
5204 if (reg_src == reg_base)
5205 avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
5206 "mov __zero_reg__,%B1" CR_TAB
5207 TINY_ADIW (%I0, %J0, %o0) CR_TAB
5208 "st %b0+,__tmp_reg__" CR_TAB
5209 "st %b0+,__zero_reg__" CR_TAB
5210 "st %b0,%C1" CR_TAB
5211 "clr __zero_reg__", op, plen, -8);
5212 else if (reg_src == reg_base - 2)
5213 avr_asm_len ("mov __tmp_reg__,%C1" CR_TAB
5214 TINY_ADIW (%I0, %J0, %o0) CR_TAB
5215 "st %b0+,%A1" CR_TAB
5216 "st %b0+,%B1" CR_TAB
5217 "st %b0,__tmp_reg__", op, plen, -6);
5218 else
5219 avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
5220 "st %b0+,%A1" CR_TAB
5221 "st %b0+,%B1" CR_TAB
5222 "st %b0,%C1", op, plen, -5);
5223
5224 if (!reg_unused_after (insn, XEXP (base, 0)))
5225 avr_asm_len (TINY_SBIW (%I0, %J0, %o0+2), op, plen, 2);
5226
5227 return "";
5228 }
5229
5230 /* Handle store of 24-bit type from register or zero to memory. */
5231
5232 static const char*
avr_out_store_psi(rtx_insn * insn,rtx * op,int * plen)5233 avr_out_store_psi (rtx_insn *insn, rtx *op, int *plen)
5234 {
5235 rtx dest = op[0];
5236 rtx src = op[1];
5237 rtx base = XEXP (dest, 0);
5238 int reg_base = true_regnum (base);
5239
5240 if (CONSTANT_ADDRESS_P (base))
5241 {
5242 int n_words = AVR_TINY ? 3 : 6;
5243 return avr_asm_len ("sts %m0,%A1" CR_TAB
5244 "sts %m0+1,%B1" CR_TAB
5245 "sts %m0+2,%C1", op, plen, -n_words);
5246 }
5247
5248 if (reg_base > 0) /* (r) */
5249 {
5250 if (AVR_TINY)
5251 return avr_out_store_psi_reg_no_disp_tiny (insn, op, plen);
5252
5253 if (reg_base == REG_X) /* (R26) */
5254 {
5255 gcc_assert (!reg_overlap_mentioned_p (base, src));
5256
5257 avr_asm_len ("st %0+,%A1" CR_TAB
5258 "st %0+,%B1" CR_TAB
5259 "st %0,%C1", op, plen, -3);
5260
5261 if (!reg_unused_after (insn, base))
5262 avr_asm_len ("sbiw r26,2", op, plen, 1);
5263
5264 return "";
5265 }
5266 else
5267 return avr_asm_len ("st %0,%A1" CR_TAB
5268 "std %0+1,%B1" CR_TAB
5269 "std %0+2,%C1", op, plen, -3);
5270 }
5271 else if (GET_CODE (base) == PLUS) /* (R + i) */
5272 {
5273 int disp = INTVAL (XEXP (base, 1));
5274
5275 if (AVR_TINY)
5276 return avr_out_store_psi_reg_disp_tiny (insn, op, plen);
5277
5278 reg_base = REGNO (XEXP (base, 0));
5279
5280 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5281 {
5282 if (reg_base != REG_Y)
5283 fatal_insn ("incorrect insn:",insn);
5284
5285 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
5286 return avr_asm_len ("adiw r28,%o0-61" CR_TAB
5287 "std Y+61,%A1" CR_TAB
5288 "std Y+62,%B1" CR_TAB
5289 "std Y+63,%C1" CR_TAB
5290 "sbiw r28,%o0-61", op, plen, -5);
5291
5292 return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5293 "sbci r29,hi8(-%o0)" CR_TAB
5294 "st Y,%A1" CR_TAB
5295 "std Y+1,%B1" CR_TAB
5296 "std Y+2,%C1" CR_TAB
5297 "subi r28,lo8(%o0)" CR_TAB
5298 "sbci r29,hi8(%o0)", op, plen, -7);
5299 }
5300 if (reg_base == REG_X)
5301 {
5302 /* (X + d) = R */
5303 gcc_assert (!reg_overlap_mentioned_p (XEXP (base, 0), src));
5304
5305 avr_asm_len ("adiw r26,%o0" CR_TAB
5306 "st X+,%A1" CR_TAB
5307 "st X+,%B1" CR_TAB
5308 "st X,%C1", op, plen, -4);
5309
5310 if (!reg_unused_after (insn, XEXP (base, 0)))
5311 avr_asm_len ("sbiw r26,%o0+2", op, plen, 1);
5312
5313 return "";
5314 }
5315
5316 return avr_asm_len ("std %A0,%A1" CR_TAB
5317 "std %B0,%B1" CR_TAB
5318 "std %C0,%C1", op, plen, -3);
5319 }
5320 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5321 return avr_asm_len ("st %0,%C1" CR_TAB
5322 "st %0,%B1" CR_TAB
5323 "st %0,%A1", op, plen, -3);
5324 else if (GET_CODE (base) == POST_INC) /* (R++) */
5325 return avr_asm_len ("st %0,%A1" CR_TAB
5326 "st %0,%B1" CR_TAB
5327 "st %0,%C1", op, plen, -3);
5328
5329 fatal_insn ("unknown move insn:",insn);
5330 return "";
5331 }
5332
5333
5334 /* Move around 24-bit stuff. */
5335
5336 const char *
avr_out_movpsi(rtx_insn * insn,rtx * op,int * plen)5337 avr_out_movpsi (rtx_insn *insn, rtx *op, int *plen)
5338 {
5339 rtx dest = op[0];
5340 rtx src = op[1];
5341
5342 if (avr_mem_flash_p (src)
5343 || avr_mem_flash_p (dest))
5344 {
5345 return avr_out_lpm (insn, op, plen);
5346 }
5347
5348 if (register_operand (dest, VOIDmode))
5349 {
5350 if (register_operand (src, VOIDmode)) /* mov r,r */
5351 {
5352 if (true_regnum (dest) > true_regnum (src))
5353 {
5354 avr_asm_len ("mov %C0,%C1", op, plen, -1);
5355
5356 if (AVR_HAVE_MOVW)
5357 return avr_asm_len ("movw %A0,%A1", op, plen, 1);
5358 else
5359 return avr_asm_len ("mov %B0,%B1" CR_TAB
5360 "mov %A0,%A1", op, plen, 2);
5361 }
5362 else
5363 {
5364 if (AVR_HAVE_MOVW)
5365 avr_asm_len ("movw %A0,%A1", op, plen, -1);
5366 else
5367 avr_asm_len ("mov %A0,%A1" CR_TAB
5368 "mov %B0,%B1", op, plen, -2);
5369
5370 return avr_asm_len ("mov %C0,%C1", op, plen, 1);
5371 }
5372 }
5373 else if (CONSTANT_P (src))
5374 {
5375 return avr_out_reload_inpsi (op, NULL_RTX, plen);
5376 }
5377 else if (MEM_P (src))
5378 return avr_out_load_psi (insn, op, plen); /* mov r,m */
5379 }
5380 else if (MEM_P (dest))
5381 {
5382 rtx xop[2];
5383
5384 xop[0] = dest;
5385 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
5386
5387 return avr_out_store_psi (insn, xop, plen);
5388 }
5389
5390 fatal_insn ("invalid insn:", insn);
5391 return "";
5392 }
5393
5394 static const char*
avr_out_movqi_mr_r_reg_disp_tiny(rtx_insn * insn,rtx op[],int * plen)5395 avr_out_movqi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5396 {
5397 rtx dest = op[0];
5398 rtx src = op[1];
5399 rtx x = XEXP (dest, 0);
5400
5401 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
5402 {
5403 avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
5404 TINY_ADIW (%I0, %J0, %o0) CR_TAB
5405 "st %b0,__tmp_reg__", op, plen, -4);
5406 }
5407 else
5408 {
5409 avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
5410 "st %b0,%1", op, plen, -3);
5411 }
5412
5413 if (!reg_unused_after (insn, XEXP (x, 0)))
5414 avr_asm_len (TINY_SBIW (%I0, %J0, %o0), op, plen, 2);
5415
5416 return "";
5417 }
5418
5419 static const char*
out_movqi_mr_r(rtx_insn * insn,rtx op[],int * plen)5420 out_movqi_mr_r (rtx_insn *insn, rtx op[], int *plen)
5421 {
5422 rtx dest = op[0];
5423 rtx src = op[1];
5424 rtx x = XEXP (dest, 0);
5425
5426 if (CONSTANT_ADDRESS_P (x))
5427 {
5428 int n_words = AVR_TINY ? 1 : 2;
5429 return io_address_operand (x, QImode)
5430 ? avr_asm_len ("out %i0,%1", op, plen, -1)
5431 : avr_asm_len ("sts %m0,%1", op, plen, -n_words);
5432 }
5433 else if (GET_CODE (x) == PLUS
5434 && REG_P (XEXP (x, 0))
5435 && CONST_INT_P (XEXP (x, 1)))
5436 {
5437 /* memory access by reg+disp */
5438
5439 int disp = INTVAL (XEXP (x, 1));
5440
5441 if (AVR_TINY)
5442 return avr_out_movqi_mr_r_reg_disp_tiny (insn, op, plen);
5443
5444 if (disp - GET_MODE_SIZE (GET_MODE (dest)) >= 63)
5445 {
5446 if (REGNO (XEXP (x, 0)) != REG_Y)
5447 fatal_insn ("incorrect insn:",insn);
5448
5449 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
5450 return avr_asm_len ("adiw r28,%o0-63" CR_TAB
5451 "std Y+63,%1" CR_TAB
5452 "sbiw r28,%o0-63", op, plen, -3);
5453
5454 return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5455 "sbci r29,hi8(-%o0)" CR_TAB
5456 "st Y,%1" CR_TAB
5457 "subi r28,lo8(%o0)" CR_TAB
5458 "sbci r29,hi8(%o0)", op, plen, -5);
5459 }
5460 else if (REGNO (XEXP (x, 0)) == REG_X)
5461 {
5462 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
5463 {
5464 avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
5465 "adiw r26,%o0" CR_TAB
5466 "st X,__tmp_reg__", op, plen, -3);
5467 }
5468 else
5469 {
5470 avr_asm_len ("adiw r26,%o0" CR_TAB
5471 "st X,%1", op, plen, -2);
5472 }
5473
5474 if (!reg_unused_after (insn, XEXP (x, 0)))
5475 avr_asm_len ("sbiw r26,%o0", op, plen, 1);
5476
5477 return "";
5478 }
5479
5480 return avr_asm_len ("std %0,%1", op, plen, -1);
5481 }
5482
5483 return avr_asm_len ("st %0,%1", op, plen, -1);
5484 }
5485
5486
5487 /* Helper for the next function for XMEGA. It does the same
5488 but with low byte first. */
5489
5490 static const char*
avr_out_movhi_mr_r_xmega(rtx_insn * insn,rtx op[],int * plen)5491 avr_out_movhi_mr_r_xmega (rtx_insn *insn, rtx op[], int *plen)
5492 {
5493 rtx dest = op[0];
5494 rtx src = op[1];
5495 rtx base = XEXP (dest, 0);
5496 int reg_base = true_regnum (base);
5497 int reg_src = true_regnum (src);
5498
5499 /* "volatile" forces writing low byte first, even if less efficient,
5500 for correct operation with 16-bit I/O registers like SP. */
5501 int mem_volatile_p = MEM_VOLATILE_P (dest);
5502
5503 if (CONSTANT_ADDRESS_P (base))
5504 {
5505 return io_address_operand (base, HImode)
5506 ? avr_asm_len ("out %i0,%A1" CR_TAB
5507 "out %i0+1,%B1", op, plen, -2)
5508
5509 : avr_asm_len ("sts %m0,%A1" CR_TAB
5510 "sts %m0+1,%B1", op, plen, -4);
5511 }
5512
5513 if (reg_base > 0)
5514 {
5515 if (reg_base != REG_X)
5516 return avr_asm_len ("st %0,%A1" CR_TAB
5517 "std %0+1,%B1", op, plen, -2);
5518
5519 if (reg_src == REG_X)
5520 /* "st X+,r26" and "st -X,r26" are undefined. */
5521 avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5522 "st X,r26" CR_TAB
5523 "adiw r26,1" CR_TAB
5524 "st X,__tmp_reg__", op, plen, -4);
5525 else
5526 avr_asm_len ("st X+,%A1" CR_TAB
5527 "st X,%B1", op, plen, -2);
5528
5529 return reg_unused_after (insn, base)
5530 ? ""
5531 : avr_asm_len ("sbiw r26,1", op, plen, 1);
5532 }
5533 else if (GET_CODE (base) == PLUS)
5534 {
5535 int disp = INTVAL (XEXP (base, 1));
5536 reg_base = REGNO (XEXP (base, 0));
5537 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5538 {
5539 if (reg_base != REG_Y)
5540 fatal_insn ("incorrect insn:",insn);
5541
5542 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
5543 ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
5544 "std Y+62,%A1" CR_TAB
5545 "std Y+63,%B1" CR_TAB
5546 "sbiw r28,%o0-62", op, plen, -4)
5547
5548 : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5549 "sbci r29,hi8(-%o0)" CR_TAB
5550 "st Y,%A1" CR_TAB
5551 "std Y+1,%B1" CR_TAB
5552 "subi r28,lo8(%o0)" CR_TAB
5553 "sbci r29,hi8(%o0)", op, plen, -6);
5554 }
5555
5556 if (reg_base != REG_X)
5557 return avr_asm_len ("std %A0,%A1" CR_TAB
5558 "std %B0,%B1", op, plen, -2);
5559 /* (X + d) = R */
5560 return reg_src == REG_X
5561 ? avr_asm_len ("mov __tmp_reg__,r26" CR_TAB
5562 "mov __zero_reg__,r27" CR_TAB
5563 "adiw r26,%o0" CR_TAB
5564 "st X+,__tmp_reg__" CR_TAB
5565 "st X,__zero_reg__" CR_TAB
5566 "clr __zero_reg__" CR_TAB
5567 "sbiw r26,%o0+1", op, plen, -7)
5568
5569 : avr_asm_len ("adiw r26,%o0" CR_TAB
5570 "st X+,%A1" CR_TAB
5571 "st X,%B1" CR_TAB
5572 "sbiw r26,%o0+1", op, plen, -4);
5573 }
5574 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5575 {
5576 if (!mem_volatile_p)
5577 return avr_asm_len ("st %0,%B1" CR_TAB
5578 "st %0,%A1", op, plen, -2);
5579
5580 return REGNO (XEXP (base, 0)) == REG_X
5581 ? avr_asm_len ("sbiw r26,2" CR_TAB
5582 "st X+,%A1" CR_TAB
5583 "st X,%B1" CR_TAB
5584 "sbiw r26,1", op, plen, -4)
5585
5586 : avr_asm_len ("sbiw %r0,2" CR_TAB
5587 "st %p0,%A1" CR_TAB
5588 "std %p0+1,%B1", op, plen, -3);
5589 }
5590 else if (GET_CODE (base) == POST_INC) /* (R++) */
5591 {
5592 return avr_asm_len ("st %0,%A1" CR_TAB
5593 "st %0,%B1", op, plen, -2);
5594
5595 }
5596 fatal_insn ("unknown move insn:",insn);
5597 return "";
5598 }
5599
5600 static const char*
avr_out_movhi_mr_r_reg_no_disp_tiny(rtx_insn * insn,rtx op[],int * plen)5601 avr_out_movhi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5602 {
5603 rtx dest = op[0];
5604 rtx src = op[1];
5605 rtx base = XEXP (dest, 0);
5606 int reg_base = true_regnum (base);
5607 int reg_src = true_regnum (src);
5608 int mem_volatile_p = MEM_VOLATILE_P (dest);
5609
5610 if (reg_base == reg_src)
5611 {
5612 return !mem_volatile_p && reg_unused_after (insn, src)
5613 ? avr_asm_len ("mov __tmp_reg__,%B1" CR_TAB
5614 "st %0,%A1" CR_TAB
5615 TINY_ADIW (%E0, %F0, 1) CR_TAB
5616 "st %0,__tmp_reg__", op, plen, -5)
5617 : avr_asm_len ("mov __tmp_reg__,%B1" CR_TAB
5618 TINY_ADIW (%E0, %F0, 1) CR_TAB
5619 "st %0,__tmp_reg__" CR_TAB
5620 TINY_SBIW (%E0, %F0, 1) CR_TAB
5621 "st %0, %A1", op, plen, -7);
5622 }
5623
5624 return !mem_volatile_p && reg_unused_after (insn, base)
5625 ? avr_asm_len ("st %0+,%A1" CR_TAB
5626 "st %0,%B1", op, plen, -2)
5627 : avr_asm_len (TINY_ADIW (%E0, %F0, 1) CR_TAB
5628 "st %0,%B1" CR_TAB
5629 "st -%0,%A1", op, plen, -4);
5630 }
5631
5632 static const char*
avr_out_movhi_mr_r_reg_disp_tiny(rtx_insn * insn,rtx op[],int * plen)5633 avr_out_movhi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5634 {
5635 rtx dest = op[0];
5636 rtx src = op[1];
5637 rtx base = XEXP (dest, 0);
5638 int reg_base = REGNO (XEXP (base, 0));
5639 int reg_src = true_regnum (src);
5640
5641 if (reg_src == reg_base)
5642 avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
5643 "mov __zero_reg__,%B1" CR_TAB
5644 TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
5645 "st %b0,__zero_reg__" CR_TAB
5646 "st -%b0,__tmp_reg__" CR_TAB
5647 "clr __zero_reg__", op, plen, -7);
5648 else
5649 avr_asm_len (TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
5650 "st %b0,%B1" CR_TAB
5651 "st -%b0,%A1", op, plen, -4);
5652
5653 if (!reg_unused_after (insn, XEXP (base, 0)))
5654 avr_asm_len (TINY_SBIW (%I0, %J0, %o0), op, plen, 2);
5655
5656 return "";
5657 }
5658
5659 static const char*
avr_out_movhi_mr_r_post_inc_tiny(rtx op[],int * plen)5660 avr_out_movhi_mr_r_post_inc_tiny (rtx op[], int *plen)
5661 {
5662 return avr_asm_len (TINY_ADIW (%I0, %J0, 1) CR_TAB
5663 "st %p0,%B1" CR_TAB
5664 "st -%p0,%A1" CR_TAB
5665 TINY_ADIW (%I0, %J0, 2), op, plen, -6);
5666 }
5667
5668 static const char*
out_movhi_mr_r(rtx_insn * insn,rtx op[],int * plen)5669 out_movhi_mr_r (rtx_insn *insn, rtx op[], int *plen)
5670 {
5671 rtx dest = op[0];
5672 rtx src = op[1];
5673 rtx base = XEXP (dest, 0);
5674 int reg_base = true_regnum (base);
5675 int reg_src = true_regnum (src);
5676 int mem_volatile_p;
5677
5678 /* "volatile" forces writing high-byte first (no-xmega) resp.
5679 low-byte first (xmega) even if less efficient, for correct
5680 operation with 16-bit I/O registers like. */
5681
5682 if (AVR_XMEGA)
5683 return avr_out_movhi_mr_r_xmega (insn, op, plen);
5684
5685 mem_volatile_p = MEM_VOLATILE_P (dest);
5686
5687 if (CONSTANT_ADDRESS_P (base))
5688 {
5689 int n_words = AVR_TINY ? 2 : 4;
5690 return io_address_operand (base, HImode)
5691 ? avr_asm_len ("out %i0+1,%B1" CR_TAB
5692 "out %i0,%A1", op, plen, -2)
5693
5694 : avr_asm_len ("sts %m0+1,%B1" CR_TAB
5695 "sts %m0,%A1", op, plen, -n_words);
5696 }
5697
5698 if (reg_base > 0)
5699 {
5700 if (AVR_TINY)
5701 return avr_out_movhi_mr_r_reg_no_disp_tiny (insn, op, plen);
5702
5703 if (reg_base != REG_X)
5704 return avr_asm_len ("std %0+1,%B1" CR_TAB
5705 "st %0,%A1", op, plen, -2);
5706
5707 if (reg_src == REG_X)
5708 /* "st X+,r26" and "st -X,r26" are undefined. */
5709 return !mem_volatile_p && reg_unused_after (insn, src)
5710 ? avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5711 "st X,r26" CR_TAB
5712 "adiw r26,1" CR_TAB
5713 "st X,__tmp_reg__", op, plen, -4)
5714
5715 : avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5716 "adiw r26,1" CR_TAB
5717 "st X,__tmp_reg__" CR_TAB
5718 "sbiw r26,1" CR_TAB
5719 "st X,r26", op, plen, -5);
5720
5721 return !mem_volatile_p && reg_unused_after (insn, base)
5722 ? avr_asm_len ("st X+,%A1" CR_TAB
5723 "st X,%B1", op, plen, -2)
5724 : avr_asm_len ("adiw r26,1" CR_TAB
5725 "st X,%B1" CR_TAB
5726 "st -X,%A1", op, plen, -3);
5727 }
5728 else if (GET_CODE (base) == PLUS)
5729 {
5730 int disp = INTVAL (XEXP (base, 1));
5731
5732 if (AVR_TINY)
5733 return avr_out_movhi_mr_r_reg_disp_tiny (insn, op, plen);
5734
5735 reg_base = REGNO (XEXP (base, 0));
5736 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5737 {
5738 if (reg_base != REG_Y)
5739 fatal_insn ("incorrect insn:",insn);
5740
5741 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
5742 ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
5743 "std Y+63,%B1" CR_TAB
5744 "std Y+62,%A1" CR_TAB
5745 "sbiw r28,%o0-62", op, plen, -4)
5746
5747 : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5748 "sbci r29,hi8(-%o0)" CR_TAB
5749 "std Y+1,%B1" CR_TAB
5750 "st Y,%A1" CR_TAB
5751 "subi r28,lo8(%o0)" CR_TAB
5752 "sbci r29,hi8(%o0)", op, plen, -6);
5753 }
5754
5755 if (reg_base != REG_X)
5756 return avr_asm_len ("std %B0,%B1" CR_TAB
5757 "std %A0,%A1", op, plen, -2);
5758 /* (X + d) = R */
5759 return reg_src == REG_X
5760 ? avr_asm_len ("mov __tmp_reg__,r26" CR_TAB
5761 "mov __zero_reg__,r27" CR_TAB
5762 "adiw r26,%o0+1" CR_TAB
5763 "st X,__zero_reg__" CR_TAB
5764 "st -X,__tmp_reg__" CR_TAB
5765 "clr __zero_reg__" CR_TAB
5766 "sbiw r26,%o0", op, plen, -7)
5767
5768 : avr_asm_len ("adiw r26,%o0+1" CR_TAB
5769 "st X,%B1" CR_TAB
5770 "st -X,%A1" CR_TAB
5771 "sbiw r26,%o0", op, plen, -4);
5772 }
5773 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5774 {
5775 return avr_asm_len ("st %0,%B1" CR_TAB
5776 "st %0,%A1", op, plen, -2);
5777 }
5778 else if (GET_CODE (base) == POST_INC) /* (R++) */
5779 {
5780 if (!mem_volatile_p)
5781 return avr_asm_len ("st %0,%A1" CR_TAB
5782 "st %0,%B1", op, plen, -2);
5783
5784 if (AVR_TINY)
5785 return avr_out_movhi_mr_r_post_inc_tiny (op, plen);
5786
5787 return REGNO (XEXP (base, 0)) == REG_X
5788 ? avr_asm_len ("adiw r26,1" CR_TAB
5789 "st X,%B1" CR_TAB
5790 "st -X,%A1" CR_TAB
5791 "adiw r26,2", op, plen, -4)
5792
5793 : avr_asm_len ("std %p0+1,%B1" CR_TAB
5794 "st %p0,%A1" CR_TAB
5795 "adiw %r0,2", op, plen, -3);
5796 }
5797 fatal_insn ("unknown move insn:",insn);
5798 return "";
5799 }
5800
5801 /* Return 1 if frame pointer for current function required. */
5802
5803 static bool
avr_frame_pointer_required_p(void)5804 avr_frame_pointer_required_p (void)
5805 {
5806 return (cfun->calls_alloca
5807 || cfun->calls_setjmp
5808 || cfun->has_nonlocal_label
5809 || crtl->args.info.nregs == 0
5810 || get_frame_size () > 0);
5811 }
5812
5813 /* Returns the condition of compare insn INSN, or UNKNOWN. */
5814
5815 static RTX_CODE
compare_condition(rtx_insn * insn)5816 compare_condition (rtx_insn *insn)
5817 {
5818 rtx_insn *next = next_real_insn (insn);
5819
5820 if (next && JUMP_P (next))
5821 {
5822 rtx pat = PATTERN (next);
5823 rtx src = SET_SRC (pat);
5824
5825 if (IF_THEN_ELSE == GET_CODE (src))
5826 return GET_CODE (XEXP (src, 0));
5827 }
5828
5829 return UNKNOWN;
5830 }
5831
5832
5833 /* Returns true iff INSN is a tst insn that only tests the sign. */
5834
5835 static bool
compare_sign_p(rtx_insn * insn)5836 compare_sign_p (rtx_insn *insn)
5837 {
5838 RTX_CODE cond = compare_condition (insn);
5839 return (cond == GE || cond == LT);
5840 }
5841
5842
5843 /* Returns true iff the next insn is a JUMP_INSN with a condition
5844 that needs to be swapped (GT, GTU, LE, LEU). */
5845
5846 static bool
compare_diff_p(rtx_insn * insn)5847 compare_diff_p (rtx_insn *insn)
5848 {
5849 RTX_CODE cond = compare_condition (insn);
5850 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
5851 }
5852
5853 /* Returns true iff INSN is a compare insn with the EQ or NE condition. */
5854
5855 static bool
compare_eq_p(rtx_insn * insn)5856 compare_eq_p (rtx_insn *insn)
5857 {
5858 RTX_CODE cond = compare_condition (insn);
5859 return (cond == EQ || cond == NE);
5860 }
5861
5862
5863 /* Output compare instruction
5864
5865 compare (XOP[0], XOP[1])
5866
5867 for a register XOP[0] and a compile-time constant XOP[1]. Return "".
5868 XOP[2] is an 8-bit scratch register as needed.
5869
5870 PLEN == NULL: Output instructions.
5871 PLEN != NULL: Set *PLEN to the length (in words) of the sequence.
5872 Don't output anything. */
5873
5874 const char*
avr_out_compare(rtx_insn * insn,rtx * xop,int * plen)5875 avr_out_compare (rtx_insn *insn, rtx *xop, int *plen)
5876 {
5877 /* Register to compare and value to compare against. */
5878 rtx xreg = xop[0];
5879 rtx xval = xop[1];
5880
5881 /* MODE of the comparison. */
5882 machine_mode mode;
5883
5884 /* Number of bytes to operate on. */
5885 int n_bytes = GET_MODE_SIZE (GET_MODE (xreg));
5886
5887 /* Value (0..0xff) held in clobber register xop[2] or -1 if unknown. */
5888 int clobber_val = -1;
5889
5890 /* Map fixed mode operands to integer operands with the same binary
5891 representation. They are easier to handle in the remainder. */
5892
5893 if (CONST_FIXED_P (xval))
5894 {
5895 xreg = avr_to_int_mode (xop[0]);
5896 xval = avr_to_int_mode (xop[1]);
5897 }
5898
5899 mode = GET_MODE (xreg);
5900
5901 gcc_assert (REG_P (xreg));
5902 gcc_assert ((CONST_INT_P (xval) && n_bytes <= 4)
5903 || (const_double_operand (xval, VOIDmode) && n_bytes == 8));
5904
5905 if (plen)
5906 *plen = 0;
5907
5908 /* Comparisons == +/-1 and != +/-1 can be done similar to camparing
5909 against 0 by ORing the bytes. This is one instruction shorter.
5910 Notice that 64-bit comparisons are always against reg:ALL8 18 (ACC_A)
5911 and therefore don't use this. */
5912
5913 if (!test_hard_reg_class (LD_REGS, xreg)
5914 && compare_eq_p (insn)
5915 && reg_unused_after (insn, xreg))
5916 {
5917 if (xval == const1_rtx)
5918 {
5919 avr_asm_len ("dec %A0" CR_TAB
5920 "or %A0,%B0", xop, plen, 2);
5921
5922 if (n_bytes >= 3)
5923 avr_asm_len ("or %A0,%C0", xop, plen, 1);
5924
5925 if (n_bytes >= 4)
5926 avr_asm_len ("or %A0,%D0", xop, plen, 1);
5927
5928 return "";
5929 }
5930 else if (xval == constm1_rtx)
5931 {
5932 if (n_bytes >= 4)
5933 avr_asm_len ("and %A0,%D0", xop, plen, 1);
5934
5935 if (n_bytes >= 3)
5936 avr_asm_len ("and %A0,%C0", xop, plen, 1);
5937
5938 return avr_asm_len ("and %A0,%B0" CR_TAB
5939 "com %A0", xop, plen, 2);
5940 }
5941 }
5942
5943 /* Comparisons == -1 and != -1 of a d-register that's used after the
5944 comparison. (If it's unused after we use CPI / SBCI or ADIW sequence
5945 from below.) Instead of CPI Rlo,-1 / LDI Rx,-1 / CPC Rhi,Rx we can
5946 use CPI Rlo,-1 / CPC Rhi,Rlo which is 1 instruction shorter:
5947 If CPI is true then Rlo contains -1 and we can use Rlo instead of Rx
5948 when CPC'ing the high part. If CPI is false then CPC cannot render
5949 the result to true. This also works for the more generic case where
5950 the constant is of the form 0xabab. */
5951
5952 if (n_bytes == 2
5953 && xval != const0_rtx
5954 && test_hard_reg_class (LD_REGS, xreg)
5955 && compare_eq_p (insn)
5956 && !reg_unused_after (insn, xreg))
5957 {
5958 rtx xlo8 = simplify_gen_subreg (QImode, xval, mode, 0);
5959 rtx xhi8 = simplify_gen_subreg (QImode, xval, mode, 1);
5960
5961 if (INTVAL (xlo8) == INTVAL (xhi8))
5962 {
5963 xop[0] = xreg;
5964 xop[1] = xlo8;
5965
5966 return avr_asm_len ("cpi %A0,%1" CR_TAB
5967 "cpc %B0,%A0", xop, plen, 2);
5968 }
5969 }
5970
5971 for (int i = 0; i < n_bytes; i++)
5972 {
5973 /* We compare byte-wise. */
5974 rtx reg8 = simplify_gen_subreg (QImode, xreg, mode, i);
5975 rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
5976
5977 /* 8-bit value to compare with this byte. */
5978 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
5979
5980 /* Registers R16..R31 can operate with immediate. */
5981 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
5982
5983 xop[0] = reg8;
5984 xop[1] = gen_int_mode (val8, QImode);
5985
5986 /* Word registers >= R24 can use SBIW/ADIW with 0..63. */
5987
5988 if (i == 0
5989 && test_hard_reg_class (ADDW_REGS, reg8))
5990 {
5991 int val16 = trunc_int_for_mode (INTVAL (xval), HImode);
5992
5993 if (IN_RANGE (val16, 0, 63)
5994 && (val8 == 0
5995 || reg_unused_after (insn, xreg)))
5996 {
5997 if (AVR_TINY)
5998 avr_asm_len (TINY_SBIW (%A0, %B0, %1), xop, plen, 2);
5999 else
6000 avr_asm_len ("sbiw %0,%1", xop, plen, 1);
6001
6002 i++;
6003 continue;
6004 }
6005
6006 if (n_bytes == 2
6007 && IN_RANGE (val16, -63, -1)
6008 && compare_eq_p (insn)
6009 && reg_unused_after (insn, xreg))
6010 {
6011 return AVR_TINY
6012 ? avr_asm_len (TINY_ADIW (%A0, %B0, %n1), xop, plen, 2)
6013 : avr_asm_len ("adiw %0,%n1", xop, plen, 1);
6014 }
6015 }
6016
6017 /* Comparing against 0 is easy. */
6018
6019 if (val8 == 0)
6020 {
6021 avr_asm_len (i == 0
6022 ? "cp %0,__zero_reg__"
6023 : "cpc %0,__zero_reg__", xop, plen, 1);
6024 continue;
6025 }
6026
6027 /* Upper registers can compare and subtract-with-carry immediates.
6028 Notice that compare instructions do the same as respective subtract
6029 instruction; the only difference is that comparisons don't write
6030 the result back to the target register. */
6031
6032 if (ld_reg_p)
6033 {
6034 if (i == 0)
6035 {
6036 avr_asm_len ("cpi %0,%1", xop, plen, 1);
6037 continue;
6038 }
6039 else if (reg_unused_after (insn, xreg))
6040 {
6041 avr_asm_len ("sbci %0,%1", xop, plen, 1);
6042 continue;
6043 }
6044 }
6045
6046 /* Must load the value into the scratch register. */
6047
6048 gcc_assert (REG_P (xop[2]));
6049
6050 if (clobber_val != (int) val8)
6051 avr_asm_len ("ldi %2,%1", xop, plen, 1);
6052 clobber_val = (int) val8;
6053
6054 avr_asm_len (i == 0
6055 ? "cp %0,%2"
6056 : "cpc %0,%2", xop, plen, 1);
6057 }
6058
6059 return "";
6060 }
6061
6062
6063 /* Prepare operands of compare_const_di2 to be used with avr_out_compare. */
6064
6065 const char*
avr_out_compare64(rtx_insn * insn,rtx * op,int * plen)6066 avr_out_compare64 (rtx_insn *insn, rtx *op, int *plen)
6067 {
6068 rtx xop[3];
6069
6070 xop[0] = gen_rtx_REG (DImode, 18);
6071 xop[1] = op[0];
6072 xop[2] = op[1];
6073
6074 return avr_out_compare (insn, xop, plen);
6075 }
6076
6077 /* Output test instruction for HImode. */
6078
6079 const char*
avr_out_tsthi(rtx_insn * insn,rtx * op,int * plen)6080 avr_out_tsthi (rtx_insn *insn, rtx *op, int *plen)
6081 {
6082 if (compare_sign_p (insn))
6083 {
6084 avr_asm_len ("tst %B0", op, plen, -1);
6085 }
6086 else if (reg_unused_after (insn, op[0])
6087 && compare_eq_p (insn))
6088 {
6089 /* Faster than sbiw if we can clobber the operand. */
6090 avr_asm_len ("or %A0,%B0", op, plen, -1);
6091 }
6092 else
6093 {
6094 avr_out_compare (insn, op, plen);
6095 }
6096
6097 return "";
6098 }
6099
6100
6101 /* Output test instruction for PSImode. */
6102
6103 const char*
avr_out_tstpsi(rtx_insn * insn,rtx * op,int * plen)6104 avr_out_tstpsi (rtx_insn *insn, rtx *op, int *plen)
6105 {
6106 if (compare_sign_p (insn))
6107 {
6108 avr_asm_len ("tst %C0", op, plen, -1);
6109 }
6110 else if (reg_unused_after (insn, op[0])
6111 && compare_eq_p (insn))
6112 {
6113 /* Faster than sbiw if we can clobber the operand. */
6114 avr_asm_len ("or %A0,%B0" CR_TAB
6115 "or %A0,%C0", op, plen, -2);
6116 }
6117 else
6118 {
6119 avr_out_compare (insn, op, plen);
6120 }
6121
6122 return "";
6123 }
6124
6125
6126 /* Output test instruction for SImode. */
6127
6128 const char*
avr_out_tstsi(rtx_insn * insn,rtx * op,int * plen)6129 avr_out_tstsi (rtx_insn *insn, rtx *op, int *plen)
6130 {
6131 if (compare_sign_p (insn))
6132 {
6133 avr_asm_len ("tst %D0", op, plen, -1);
6134 }
6135 else if (reg_unused_after (insn, op[0])
6136 && compare_eq_p (insn))
6137 {
6138 /* Faster than sbiw if we can clobber the operand. */
6139 avr_asm_len ("or %A0,%B0" CR_TAB
6140 "or %A0,%C0" CR_TAB
6141 "or %A0,%D0", op, plen, -3);
6142 }
6143 else
6144 {
6145 avr_out_compare (insn, op, plen);
6146 }
6147
6148 return "";
6149 }
6150
6151
6152 /* Generate asm equivalent for various shifts. This only handles cases
6153 that are not already carefully hand-optimized in ?sh??i3_out.
6154
6155 OPERANDS[0] resp. %0 in TEMPL is the operand to be shifted.
6156 OPERANDS[2] is the shift count as CONST_INT, MEM or REG.
6157 OPERANDS[3] is a QImode scratch register from LD regs if
6158 available and SCRATCH, otherwise (no scratch available)
6159
6160 TEMPL is an assembler template that shifts by one position.
6161 T_LEN is the length of this template. */
6162
6163 void
out_shift_with_cnt(const char * templ,rtx_insn * insn,rtx operands[],int * plen,int t_len)6164 out_shift_with_cnt (const char *templ, rtx_insn *insn, rtx operands[],
6165 int *plen, int t_len)
6166 {
6167 bool second_label = true;
6168 bool saved_in_tmp = false;
6169 bool use_zero_reg = false;
6170 rtx op[5];
6171
6172 op[0] = operands[0];
6173 op[1] = operands[1];
6174 op[2] = operands[2];
6175 op[3] = operands[3];
6176
6177 if (plen)
6178 *plen = 0;
6179
6180 if (CONST_INT_P (operands[2]))
6181 {
6182 bool scratch = (GET_CODE (PATTERN (insn)) == PARALLEL
6183 && REG_P (operands[3]));
6184 int count = INTVAL (operands[2]);
6185 int max_len = 10; /* If larger than this, always use a loop. */
6186
6187 if (count <= 0)
6188 return;
6189
6190 if (count < 8 && !scratch)
6191 use_zero_reg = true;
6192
6193 if (optimize_size)
6194 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
6195
6196 if (t_len * count <= max_len)
6197 {
6198 /* Output shifts inline with no loop - faster. */
6199
6200 while (count-- > 0)
6201 avr_asm_len (templ, op, plen, t_len);
6202
6203 return;
6204 }
6205
6206 if (scratch)
6207 {
6208 avr_asm_len ("ldi %3,%2", op, plen, 1);
6209 }
6210 else if (use_zero_reg)
6211 {
6212 /* Hack to save one word: use __zero_reg__ as loop counter.
6213 Set one bit, then shift in a loop until it is 0 again. */
6214
6215 op[3] = zero_reg_rtx;
6216
6217 avr_asm_len ("set" CR_TAB
6218 "bld %3,%2-1", op, plen, 2);
6219 }
6220 else
6221 {
6222 /* No scratch register available, use one from LD_REGS (saved in
6223 __tmp_reg__) that doesn't overlap with registers to shift. */
6224
6225 op[3] = all_regs_rtx[((REGNO (op[0]) - 1) & 15) + 16];
6226 op[4] = tmp_reg_rtx;
6227 saved_in_tmp = true;
6228
6229 avr_asm_len ("mov %4,%3" CR_TAB
6230 "ldi %3,%2", op, plen, 2);
6231 }
6232
6233 second_label = false;
6234 }
6235 else if (MEM_P (op[2]))
6236 {
6237 rtx op_mov[2];
6238
6239 op_mov[0] = op[3] = tmp_reg_rtx;
6240 op_mov[1] = op[2];
6241
6242 out_movqi_r_mr (insn, op_mov, plen);
6243 }
6244 else if (register_operand (op[2], QImode))
6245 {
6246 op[3] = op[2];
6247
6248 if (!reg_unused_after (insn, op[2])
6249 || reg_overlap_mentioned_p (op[0], op[2]))
6250 {
6251 op[3] = tmp_reg_rtx;
6252 avr_asm_len ("mov %3,%2", op, plen, 1);
6253 }
6254 }
6255 else
6256 fatal_insn ("bad shift insn:", insn);
6257
6258 if (second_label)
6259 avr_asm_len ("rjmp 2f", op, plen, 1);
6260
6261 avr_asm_len ("1:", op, plen, 0);
6262 avr_asm_len (templ, op, plen, t_len);
6263
6264 if (second_label)
6265 avr_asm_len ("2:", op, plen, 0);
6266
6267 avr_asm_len (use_zero_reg ? "lsr %3" : "dec %3", op, plen, 1);
6268 avr_asm_len (second_label ? "brpl 1b" : "brne 1b", op, plen, 1);
6269
6270 if (saved_in_tmp)
6271 avr_asm_len ("mov %3,%4", op, plen, 1);
6272 }
6273
6274
6275 /* 8bit shift left ((char)x << i) */
6276
6277 const char *
ashlqi3_out(rtx_insn * insn,rtx operands[],int * len)6278 ashlqi3_out (rtx_insn *insn, rtx operands[], int *len)
6279 {
6280 if (CONST_INT_P (operands[2]))
6281 {
6282 int k;
6283
6284 if (!len)
6285 len = &k;
6286
6287 switch (INTVAL (operands[2]))
6288 {
6289 default:
6290 if (INTVAL (operands[2]) < 8)
6291 break;
6292
6293 *len = 1;
6294 return "clr %0";
6295
6296 case 1:
6297 *len = 1;
6298 return "lsl %0";
6299
6300 case 2:
6301 *len = 2;
6302 return ("lsl %0" CR_TAB
6303 "lsl %0");
6304
6305 case 3:
6306 *len = 3;
6307 return ("lsl %0" CR_TAB
6308 "lsl %0" CR_TAB
6309 "lsl %0");
6310
6311 case 4:
6312 if (test_hard_reg_class (LD_REGS, operands[0]))
6313 {
6314 *len = 2;
6315 return ("swap %0" CR_TAB
6316 "andi %0,0xf0");
6317 }
6318 *len = 4;
6319 return ("lsl %0" CR_TAB
6320 "lsl %0" CR_TAB
6321 "lsl %0" CR_TAB
6322 "lsl %0");
6323
6324 case 5:
6325 if (test_hard_reg_class (LD_REGS, operands[0]))
6326 {
6327 *len = 3;
6328 return ("swap %0" CR_TAB
6329 "lsl %0" CR_TAB
6330 "andi %0,0xe0");
6331 }
6332 *len = 5;
6333 return ("lsl %0" CR_TAB
6334 "lsl %0" CR_TAB
6335 "lsl %0" CR_TAB
6336 "lsl %0" CR_TAB
6337 "lsl %0");
6338
6339 case 6:
6340 if (test_hard_reg_class (LD_REGS, operands[0]))
6341 {
6342 *len = 4;
6343 return ("swap %0" CR_TAB
6344 "lsl %0" CR_TAB
6345 "lsl %0" CR_TAB
6346 "andi %0,0xc0");
6347 }
6348 *len = 6;
6349 return ("lsl %0" CR_TAB
6350 "lsl %0" CR_TAB
6351 "lsl %0" CR_TAB
6352 "lsl %0" CR_TAB
6353 "lsl %0" CR_TAB
6354 "lsl %0");
6355
6356 case 7:
6357 *len = 3;
6358 return ("ror %0" CR_TAB
6359 "clr %0" CR_TAB
6360 "ror %0");
6361 }
6362 }
6363 else if (CONSTANT_P (operands[2]))
6364 fatal_insn ("internal compiler error. Incorrect shift:", insn);
6365
6366 out_shift_with_cnt ("lsl %0",
6367 insn, operands, len, 1);
6368 return "";
6369 }
6370
6371
6372 /* 16bit shift left ((short)x << i) */
6373
6374 const char *
ashlhi3_out(rtx_insn * insn,rtx operands[],int * len)6375 ashlhi3_out (rtx_insn *insn, rtx operands[], int *len)
6376 {
6377 if (CONST_INT_P (operands[2]))
6378 {
6379 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
6380 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
6381 int k;
6382 int *t = len;
6383
6384 if (!len)
6385 len = &k;
6386
6387 switch (INTVAL (operands[2]))
6388 {
6389 default:
6390 if (INTVAL (operands[2]) < 16)
6391 break;
6392
6393 *len = 2;
6394 return ("clr %B0" CR_TAB
6395 "clr %A0");
6396
6397 case 4:
6398 if (optimize_size && scratch)
6399 break; /* 5 */
6400 if (ldi_ok)
6401 {
6402 *len = 6;
6403 return ("swap %A0" CR_TAB
6404 "swap %B0" CR_TAB
6405 "andi %B0,0xf0" CR_TAB
6406 "eor %B0,%A0" CR_TAB
6407 "andi %A0,0xf0" CR_TAB
6408 "eor %B0,%A0");
6409 }
6410 if (scratch)
6411 {
6412 *len = 7;
6413 return ("swap %A0" CR_TAB
6414 "swap %B0" CR_TAB
6415 "ldi %3,0xf0" CR_TAB
6416 "and %B0,%3" CR_TAB
6417 "eor %B0,%A0" CR_TAB
6418 "and %A0,%3" CR_TAB
6419 "eor %B0,%A0");
6420 }
6421 break; /* optimize_size ? 6 : 8 */
6422
6423 case 5:
6424 if (optimize_size)
6425 break; /* scratch ? 5 : 6 */
6426 if (ldi_ok)
6427 {
6428 *len = 8;
6429 return ("lsl %A0" CR_TAB
6430 "rol %B0" CR_TAB
6431 "swap %A0" CR_TAB
6432 "swap %B0" CR_TAB
6433 "andi %B0,0xf0" CR_TAB
6434 "eor %B0,%A0" CR_TAB
6435 "andi %A0,0xf0" CR_TAB
6436 "eor %B0,%A0");
6437 }
6438 if (scratch)
6439 {
6440 *len = 9;
6441 return ("lsl %A0" CR_TAB
6442 "rol %B0" CR_TAB
6443 "swap %A0" CR_TAB
6444 "swap %B0" CR_TAB
6445 "ldi %3,0xf0" CR_TAB
6446 "and %B0,%3" CR_TAB
6447 "eor %B0,%A0" CR_TAB
6448 "and %A0,%3" CR_TAB
6449 "eor %B0,%A0");
6450 }
6451 break; /* 10 */
6452
6453 case 6:
6454 if (optimize_size)
6455 break; /* scratch ? 5 : 6 */
6456 *len = 9;
6457 return ("clr __tmp_reg__" CR_TAB
6458 "lsr %B0" CR_TAB
6459 "ror %A0" CR_TAB
6460 "ror __tmp_reg__" CR_TAB
6461 "lsr %B0" CR_TAB
6462 "ror %A0" CR_TAB
6463 "ror __tmp_reg__" CR_TAB
6464 "mov %B0,%A0" CR_TAB
6465 "mov %A0,__tmp_reg__");
6466
6467 case 7:
6468 *len = 5;
6469 return ("lsr %B0" CR_TAB
6470 "mov %B0,%A0" CR_TAB
6471 "clr %A0" CR_TAB
6472 "ror %B0" CR_TAB
6473 "ror %A0");
6474
6475 case 8:
6476 return *len = 2, ("mov %B0,%A1" CR_TAB
6477 "clr %A0");
6478
6479 case 9:
6480 *len = 3;
6481 return ("mov %B0,%A0" CR_TAB
6482 "clr %A0" CR_TAB
6483 "lsl %B0");
6484
6485 case 10:
6486 *len = 4;
6487 return ("mov %B0,%A0" CR_TAB
6488 "clr %A0" CR_TAB
6489 "lsl %B0" CR_TAB
6490 "lsl %B0");
6491
6492 case 11:
6493 *len = 5;
6494 return ("mov %B0,%A0" CR_TAB
6495 "clr %A0" CR_TAB
6496 "lsl %B0" CR_TAB
6497 "lsl %B0" CR_TAB
6498 "lsl %B0");
6499
6500 case 12:
6501 if (ldi_ok)
6502 {
6503 *len = 4;
6504 return ("mov %B0,%A0" CR_TAB
6505 "clr %A0" CR_TAB
6506 "swap %B0" CR_TAB
6507 "andi %B0,0xf0");
6508 }
6509 if (scratch)
6510 {
6511 *len = 5;
6512 return ("mov %B0,%A0" CR_TAB
6513 "clr %A0" CR_TAB
6514 "swap %B0" CR_TAB
6515 "ldi %3,0xf0" CR_TAB
6516 "and %B0,%3");
6517 }
6518 *len = 6;
6519 return ("mov %B0,%A0" CR_TAB
6520 "clr %A0" CR_TAB
6521 "lsl %B0" CR_TAB
6522 "lsl %B0" CR_TAB
6523 "lsl %B0" CR_TAB
6524 "lsl %B0");
6525
6526 case 13:
6527 if (ldi_ok)
6528 {
6529 *len = 5;
6530 return ("mov %B0,%A0" CR_TAB
6531 "clr %A0" CR_TAB
6532 "swap %B0" CR_TAB
6533 "lsl %B0" CR_TAB
6534 "andi %B0,0xe0");
6535 }
6536 if (AVR_HAVE_MUL && scratch)
6537 {
6538 *len = 5;
6539 return ("ldi %3,0x20" CR_TAB
6540 "mul %A0,%3" CR_TAB
6541 "mov %B0,r0" CR_TAB
6542 "clr %A0" CR_TAB
6543 "clr __zero_reg__");
6544 }
6545 if (optimize_size && scratch)
6546 break; /* 5 */
6547 if (scratch)
6548 {
6549 *len = 6;
6550 return ("mov %B0,%A0" CR_TAB
6551 "clr %A0" CR_TAB
6552 "swap %B0" CR_TAB
6553 "lsl %B0" CR_TAB
6554 "ldi %3,0xe0" CR_TAB
6555 "and %B0,%3");
6556 }
6557 if (AVR_HAVE_MUL)
6558 {
6559 *len = 6;
6560 return ("set" CR_TAB
6561 "bld r1,5" CR_TAB
6562 "mul %A0,r1" CR_TAB
6563 "mov %B0,r0" CR_TAB
6564 "clr %A0" CR_TAB
6565 "clr __zero_reg__");
6566 }
6567 *len = 7;
6568 return ("mov %B0,%A0" CR_TAB
6569 "clr %A0" CR_TAB
6570 "lsl %B0" CR_TAB
6571 "lsl %B0" CR_TAB
6572 "lsl %B0" CR_TAB
6573 "lsl %B0" CR_TAB
6574 "lsl %B0");
6575
6576 case 14:
6577 if (AVR_HAVE_MUL && ldi_ok)
6578 {
6579 *len = 5;
6580 return ("ldi %B0,0x40" CR_TAB
6581 "mul %A0,%B0" CR_TAB
6582 "mov %B0,r0" CR_TAB
6583 "clr %A0" CR_TAB
6584 "clr __zero_reg__");
6585 }
6586 if (AVR_HAVE_MUL && scratch)
6587 {
6588 *len = 5;
6589 return ("ldi %3,0x40" CR_TAB
6590 "mul %A0,%3" CR_TAB
6591 "mov %B0,r0" CR_TAB
6592 "clr %A0" CR_TAB
6593 "clr __zero_reg__");
6594 }
6595 if (optimize_size && ldi_ok)
6596 {
6597 *len = 5;
6598 return ("mov %B0,%A0" CR_TAB
6599 "ldi %A0,6" "\n1:\t"
6600 "lsl %B0" CR_TAB
6601 "dec %A0" CR_TAB
6602 "brne 1b");
6603 }
6604 if (optimize_size && scratch)
6605 break; /* 5 */
6606 *len = 6;
6607 return ("clr %B0" CR_TAB
6608 "lsr %A0" CR_TAB
6609 "ror %B0" CR_TAB
6610 "lsr %A0" CR_TAB
6611 "ror %B0" CR_TAB
6612 "clr %A0");
6613
6614 case 15:
6615 *len = 4;
6616 return ("clr %B0" CR_TAB
6617 "lsr %A0" CR_TAB
6618 "ror %B0" CR_TAB
6619 "clr %A0");
6620 }
6621 len = t;
6622 }
6623 out_shift_with_cnt ("lsl %A0" CR_TAB
6624 "rol %B0", insn, operands, len, 2);
6625 return "";
6626 }
6627
6628
6629 /* 24-bit shift left */
6630
6631 const char*
avr_out_ashlpsi3(rtx_insn * insn,rtx * op,int * plen)6632 avr_out_ashlpsi3 (rtx_insn *insn, rtx *op, int *plen)
6633 {
6634 if (plen)
6635 *plen = 0;
6636
6637 if (CONST_INT_P (op[2]))
6638 {
6639 switch (INTVAL (op[2]))
6640 {
6641 default:
6642 if (INTVAL (op[2]) < 24)
6643 break;
6644
6645 return avr_asm_len ("clr %A0" CR_TAB
6646 "clr %B0" CR_TAB
6647 "clr %C0", op, plen, 3);
6648
6649 case 8:
6650 {
6651 int reg0 = REGNO (op[0]);
6652 int reg1 = REGNO (op[1]);
6653
6654 if (reg0 >= reg1)
6655 return avr_asm_len ("mov %C0,%B1" CR_TAB
6656 "mov %B0,%A1" CR_TAB
6657 "clr %A0", op, plen, 3);
6658 else
6659 return avr_asm_len ("clr %A0" CR_TAB
6660 "mov %B0,%A1" CR_TAB
6661 "mov %C0,%B1", op, plen, 3);
6662 }
6663
6664 case 16:
6665 {
6666 int reg0 = REGNO (op[0]);
6667 int reg1 = REGNO (op[1]);
6668
6669 if (reg0 + 2 != reg1)
6670 avr_asm_len ("mov %C0,%A0", op, plen, 1);
6671
6672 return avr_asm_len ("clr %B0" CR_TAB
6673 "clr %A0", op, plen, 2);
6674 }
6675
6676 case 23:
6677 return avr_asm_len ("clr %C0" CR_TAB
6678 "lsr %A0" CR_TAB
6679 "ror %C0" CR_TAB
6680 "clr %B0" CR_TAB
6681 "clr %A0", op, plen, 5);
6682 }
6683 }
6684
6685 out_shift_with_cnt ("lsl %A0" CR_TAB
6686 "rol %B0" CR_TAB
6687 "rol %C0", insn, op, plen, 3);
6688 return "";
6689 }
6690
6691
6692 /* 32bit shift left ((long)x << i) */
6693
6694 const char *
ashlsi3_out(rtx_insn * insn,rtx operands[],int * len)6695 ashlsi3_out (rtx_insn *insn, rtx operands[], int *len)
6696 {
6697 if (CONST_INT_P (operands[2]))
6698 {
6699 int k;
6700 int *t = len;
6701
6702 if (!len)
6703 len = &k;
6704
6705 switch (INTVAL (operands[2]))
6706 {
6707 default:
6708 if (INTVAL (operands[2]) < 32)
6709 break;
6710
6711 if (AVR_HAVE_MOVW)
6712 return *len = 3, ("clr %D0" CR_TAB
6713 "clr %C0" CR_TAB
6714 "movw %A0,%C0");
6715 *len = 4;
6716 return ("clr %D0" CR_TAB
6717 "clr %C0" CR_TAB
6718 "clr %B0" CR_TAB
6719 "clr %A0");
6720
6721 case 8:
6722 {
6723 int reg0 = true_regnum (operands[0]);
6724 int reg1 = true_regnum (operands[1]);
6725 *len = 4;
6726 if (reg0 >= reg1)
6727 return ("mov %D0,%C1" CR_TAB
6728 "mov %C0,%B1" CR_TAB
6729 "mov %B0,%A1" CR_TAB
6730 "clr %A0");
6731 else
6732 return ("clr %A0" CR_TAB
6733 "mov %B0,%A1" CR_TAB
6734 "mov %C0,%B1" CR_TAB
6735 "mov %D0,%C1");
6736 }
6737
6738 case 16:
6739 {
6740 int reg0 = true_regnum (operands[0]);
6741 int reg1 = true_regnum (operands[1]);
6742 if (reg0 + 2 == reg1)
6743 return *len = 2, ("clr %B0" CR_TAB
6744 "clr %A0");
6745 if (AVR_HAVE_MOVW)
6746 return *len = 3, ("movw %C0,%A1" CR_TAB
6747 "clr %B0" CR_TAB
6748 "clr %A0");
6749 else
6750 return *len = 4, ("mov %C0,%A1" CR_TAB
6751 "mov %D0,%B1" CR_TAB
6752 "clr %B0" CR_TAB
6753 "clr %A0");
6754 }
6755
6756 case 24:
6757 *len = 4;
6758 return ("mov %D0,%A1" CR_TAB
6759 "clr %C0" CR_TAB
6760 "clr %B0" CR_TAB
6761 "clr %A0");
6762
6763 case 31:
6764 *len = 6;
6765 return ("clr %D0" CR_TAB
6766 "lsr %A0" CR_TAB
6767 "ror %D0" CR_TAB
6768 "clr %C0" CR_TAB
6769 "clr %B0" CR_TAB
6770 "clr %A0");
6771 }
6772 len = t;
6773 }
6774 out_shift_with_cnt ("lsl %A0" CR_TAB
6775 "rol %B0" CR_TAB
6776 "rol %C0" CR_TAB
6777 "rol %D0", insn, operands, len, 4);
6778 return "";
6779 }
6780
6781 /* 8bit arithmetic shift right ((signed char)x >> i) */
6782
6783 const char *
ashrqi3_out(rtx_insn * insn,rtx operands[],int * len)6784 ashrqi3_out (rtx_insn *insn, rtx operands[], int *len)
6785 {
6786 if (CONST_INT_P (operands[2]))
6787 {
6788 int k;
6789
6790 if (!len)
6791 len = &k;
6792
6793 switch (INTVAL (operands[2]))
6794 {
6795 case 1:
6796 *len = 1;
6797 return "asr %0";
6798
6799 case 2:
6800 *len = 2;
6801 return ("asr %0" CR_TAB
6802 "asr %0");
6803
6804 case 3:
6805 *len = 3;
6806 return ("asr %0" CR_TAB
6807 "asr %0" CR_TAB
6808 "asr %0");
6809
6810 case 4:
6811 *len = 4;
6812 return ("asr %0" CR_TAB
6813 "asr %0" CR_TAB
6814 "asr %0" CR_TAB
6815 "asr %0");
6816
6817 case 5:
6818 *len = 5;
6819 return ("asr %0" CR_TAB
6820 "asr %0" CR_TAB
6821 "asr %0" CR_TAB
6822 "asr %0" CR_TAB
6823 "asr %0");
6824
6825 case 6:
6826 *len = 4;
6827 return ("bst %0,6" CR_TAB
6828 "lsl %0" CR_TAB
6829 "sbc %0,%0" CR_TAB
6830 "bld %0,0");
6831
6832 default:
6833 if (INTVAL (operands[2]) < 8)
6834 break;
6835
6836 /* fall through */
6837
6838 case 7:
6839 *len = 2;
6840 return ("lsl %0" CR_TAB
6841 "sbc %0,%0");
6842 }
6843 }
6844 else if (CONSTANT_P (operands[2]))
6845 fatal_insn ("internal compiler error. Incorrect shift:", insn);
6846
6847 out_shift_with_cnt ("asr %0",
6848 insn, operands, len, 1);
6849 return "";
6850 }
6851
6852
6853 /* 16bit arithmetic shift right ((signed short)x >> i) */
6854
6855 const char *
ashrhi3_out(rtx_insn * insn,rtx operands[],int * len)6856 ashrhi3_out (rtx_insn *insn, rtx operands[], int *len)
6857 {
6858 if (CONST_INT_P (operands[2]))
6859 {
6860 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
6861 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
6862 int k;
6863 int *t = len;
6864
6865 if (!len)
6866 len = &k;
6867
6868 switch (INTVAL (operands[2]))
6869 {
6870 case 4:
6871 case 5:
6872 /* XXX try to optimize this too? */
6873 break;
6874
6875 case 6:
6876 if (optimize_size)
6877 break; /* scratch ? 5 : 6 */
6878 *len = 8;
6879 return ("mov __tmp_reg__,%A0" CR_TAB
6880 "mov %A0,%B0" CR_TAB
6881 "lsl __tmp_reg__" CR_TAB
6882 "rol %A0" CR_TAB
6883 "sbc %B0,%B0" CR_TAB
6884 "lsl __tmp_reg__" CR_TAB
6885 "rol %A0" CR_TAB
6886 "rol %B0");
6887
6888 case 7:
6889 *len = 4;
6890 return ("lsl %A0" CR_TAB
6891 "mov %A0,%B0" CR_TAB
6892 "rol %A0" CR_TAB
6893 "sbc %B0,%B0");
6894
6895 case 8:
6896 {
6897 int reg0 = true_regnum (operands[0]);
6898 int reg1 = true_regnum (operands[1]);
6899
6900 if (reg0 == reg1)
6901 return *len = 3, ("mov %A0,%B0" CR_TAB
6902 "lsl %B0" CR_TAB
6903 "sbc %B0,%B0");
6904 else
6905 return *len = 4, ("mov %A0,%B1" CR_TAB
6906 "clr %B0" CR_TAB
6907 "sbrc %A0,7" CR_TAB
6908 "dec %B0");
6909 }
6910
6911 case 9:
6912 *len = 4;
6913 return ("mov %A0,%B0" CR_TAB
6914 "lsl %B0" CR_TAB
6915 "sbc %B0,%B0" CR_TAB
6916 "asr %A0");
6917
6918 case 10:
6919 *len = 5;
6920 return ("mov %A0,%B0" CR_TAB
6921 "lsl %B0" CR_TAB
6922 "sbc %B0,%B0" CR_TAB
6923 "asr %A0" CR_TAB
6924 "asr %A0");
6925
6926 case 11:
6927 if (AVR_HAVE_MUL && ldi_ok)
6928 {
6929 *len = 5;
6930 return ("ldi %A0,0x20" CR_TAB
6931 "muls %B0,%A0" CR_TAB
6932 "mov %A0,r1" CR_TAB
6933 "sbc %B0,%B0" CR_TAB
6934 "clr __zero_reg__");
6935 }
6936 if (optimize_size && scratch)
6937 break; /* 5 */
6938 *len = 6;
6939 return ("mov %A0,%B0" CR_TAB
6940 "lsl %B0" CR_TAB
6941 "sbc %B0,%B0" CR_TAB
6942 "asr %A0" CR_TAB
6943 "asr %A0" CR_TAB
6944 "asr %A0");
6945
6946 case 12:
6947 if (AVR_HAVE_MUL && ldi_ok)
6948 {
6949 *len = 5;
6950 return ("ldi %A0,0x10" CR_TAB
6951 "muls %B0,%A0" CR_TAB
6952 "mov %A0,r1" CR_TAB
6953 "sbc %B0,%B0" CR_TAB
6954 "clr __zero_reg__");
6955 }
6956 if (optimize_size && scratch)
6957 break; /* 5 */
6958 *len = 7;
6959 return ("mov %A0,%B0" CR_TAB
6960 "lsl %B0" CR_TAB
6961 "sbc %B0,%B0" CR_TAB
6962 "asr %A0" CR_TAB
6963 "asr %A0" CR_TAB
6964 "asr %A0" CR_TAB
6965 "asr %A0");
6966
6967 case 13:
6968 if (AVR_HAVE_MUL && ldi_ok)
6969 {
6970 *len = 5;
6971 return ("ldi %A0,0x08" CR_TAB
6972 "muls %B0,%A0" CR_TAB
6973 "mov %A0,r1" CR_TAB
6974 "sbc %B0,%B0" CR_TAB
6975 "clr __zero_reg__");
6976 }
6977 if (optimize_size)
6978 break; /* scratch ? 5 : 7 */
6979 *len = 8;
6980 return ("mov %A0,%B0" CR_TAB
6981 "lsl %B0" CR_TAB
6982 "sbc %B0,%B0" CR_TAB
6983 "asr %A0" CR_TAB
6984 "asr %A0" CR_TAB
6985 "asr %A0" CR_TAB
6986 "asr %A0" CR_TAB
6987 "asr %A0");
6988
6989 case 14:
6990 *len = 5;
6991 return ("lsl %B0" CR_TAB
6992 "sbc %A0,%A0" CR_TAB
6993 "lsl %B0" CR_TAB
6994 "mov %B0,%A0" CR_TAB
6995 "rol %A0");
6996
6997 default:
6998 if (INTVAL (operands[2]) < 16)
6999 break;
7000
7001 /* fall through */
7002
7003 case 15:
7004 return *len = 3, ("lsl %B0" CR_TAB
7005 "sbc %A0,%A0" CR_TAB
7006 "mov %B0,%A0");
7007 }
7008 len = t;
7009 }
7010 out_shift_with_cnt ("asr %B0" CR_TAB
7011 "ror %A0", insn, operands, len, 2);
7012 return "";
7013 }
7014
7015
7016 /* 24-bit arithmetic shift right */
7017
7018 const char*
avr_out_ashrpsi3(rtx_insn * insn,rtx * op,int * plen)7019 avr_out_ashrpsi3 (rtx_insn *insn, rtx *op, int *plen)
7020 {
7021 int dest = REGNO (op[0]);
7022 int src = REGNO (op[1]);
7023
7024 if (CONST_INT_P (op[2]))
7025 {
7026 if (plen)
7027 *plen = 0;
7028
7029 switch (INTVAL (op[2]))
7030 {
7031 case 8:
7032 if (dest <= src)
7033 return avr_asm_len ("mov %A0,%B1" CR_TAB
7034 "mov %B0,%C1" CR_TAB
7035 "clr %C0" CR_TAB
7036 "sbrc %B0,7" CR_TAB
7037 "dec %C0", op, plen, 5);
7038 else
7039 return avr_asm_len ("clr %C0" CR_TAB
7040 "sbrc %C1,7" CR_TAB
7041 "dec %C0" CR_TAB
7042 "mov %B0,%C1" CR_TAB
7043 "mov %A0,%B1", op, plen, 5);
7044
7045 case 16:
7046 if (dest != src + 2)
7047 avr_asm_len ("mov %A0,%C1", op, plen, 1);
7048
7049 return avr_asm_len ("clr %B0" CR_TAB
7050 "sbrc %A0,7" CR_TAB
7051 "com %B0" CR_TAB
7052 "mov %C0,%B0", op, plen, 4);
7053
7054 default:
7055 if (INTVAL (op[2]) < 24)
7056 break;
7057
7058 /* fall through */
7059
7060 case 23:
7061 return avr_asm_len ("lsl %C0" CR_TAB
7062 "sbc %A0,%A0" CR_TAB
7063 "mov %B0,%A0" CR_TAB
7064 "mov %C0,%A0", op, plen, 4);
7065 } /* switch */
7066 }
7067
7068 out_shift_with_cnt ("asr %C0" CR_TAB
7069 "ror %B0" CR_TAB
7070 "ror %A0", insn, op, plen, 3);
7071 return "";
7072 }
7073
7074
7075 /* 32-bit arithmetic shift right ((signed long)x >> i) */
7076
7077 const char *
ashrsi3_out(rtx_insn * insn,rtx operands[],int * len)7078 ashrsi3_out (rtx_insn *insn, rtx operands[], int *len)
7079 {
7080 if (CONST_INT_P (operands[2]))
7081 {
7082 int k;
7083 int *t = len;
7084
7085 if (!len)
7086 len = &k;
7087
7088 switch (INTVAL (operands[2]))
7089 {
7090 case 8:
7091 {
7092 int reg0 = true_regnum (operands[0]);
7093 int reg1 = true_regnum (operands[1]);
7094 *len=6;
7095 if (reg0 <= reg1)
7096 return ("mov %A0,%B1" CR_TAB
7097 "mov %B0,%C1" CR_TAB
7098 "mov %C0,%D1" CR_TAB
7099 "clr %D0" CR_TAB
7100 "sbrc %C0,7" CR_TAB
7101 "dec %D0");
7102 else
7103 return ("clr %D0" CR_TAB
7104 "sbrc %D1,7" CR_TAB
7105 "dec %D0" CR_TAB
7106 "mov %C0,%D1" CR_TAB
7107 "mov %B0,%C1" CR_TAB
7108 "mov %A0,%B1");
7109 }
7110
7111 case 16:
7112 {
7113 int reg0 = true_regnum (operands[0]);
7114 int reg1 = true_regnum (operands[1]);
7115
7116 if (reg0 == reg1 + 2)
7117 return *len = 4, ("clr %D0" CR_TAB
7118 "sbrc %B0,7" CR_TAB
7119 "com %D0" CR_TAB
7120 "mov %C0,%D0");
7121 if (AVR_HAVE_MOVW)
7122 return *len = 5, ("movw %A0,%C1" CR_TAB
7123 "clr %D0" CR_TAB
7124 "sbrc %B0,7" CR_TAB
7125 "com %D0" CR_TAB
7126 "mov %C0,%D0");
7127 else
7128 return *len = 6, ("mov %B0,%D1" CR_TAB
7129 "mov %A0,%C1" CR_TAB
7130 "clr %D0" CR_TAB
7131 "sbrc %B0,7" CR_TAB
7132 "com %D0" CR_TAB
7133 "mov %C0,%D0");
7134 }
7135
7136 case 24:
7137 return *len = 6, ("mov %A0,%D1" CR_TAB
7138 "clr %D0" CR_TAB
7139 "sbrc %A0,7" CR_TAB
7140 "com %D0" CR_TAB
7141 "mov %B0,%D0" CR_TAB
7142 "mov %C0,%D0");
7143
7144 default:
7145 if (INTVAL (operands[2]) < 32)
7146 break;
7147
7148 /* fall through */
7149
7150 case 31:
7151 if (AVR_HAVE_MOVW)
7152 return *len = 4, ("lsl %D0" CR_TAB
7153 "sbc %A0,%A0" CR_TAB
7154 "mov %B0,%A0" CR_TAB
7155 "movw %C0,%A0");
7156 else
7157 return *len = 5, ("lsl %D0" CR_TAB
7158 "sbc %A0,%A0" CR_TAB
7159 "mov %B0,%A0" CR_TAB
7160 "mov %C0,%A0" CR_TAB
7161 "mov %D0,%A0");
7162 }
7163 len = t;
7164 }
7165 out_shift_with_cnt ("asr %D0" CR_TAB
7166 "ror %C0" CR_TAB
7167 "ror %B0" CR_TAB
7168 "ror %A0", insn, operands, len, 4);
7169 return "";
7170 }
7171
7172 /* 8-bit logic shift right ((unsigned char)x >> i) */
7173
7174 const char *
lshrqi3_out(rtx_insn * insn,rtx operands[],int * len)7175 lshrqi3_out (rtx_insn *insn, rtx operands[], int *len)
7176 {
7177 if (CONST_INT_P (operands[2]))
7178 {
7179 int k;
7180
7181 if (!len)
7182 len = &k;
7183
7184 switch (INTVAL (operands[2]))
7185 {
7186 default:
7187 if (INTVAL (operands[2]) < 8)
7188 break;
7189
7190 *len = 1;
7191 return "clr %0";
7192
7193 case 1:
7194 *len = 1;
7195 return "lsr %0";
7196
7197 case 2:
7198 *len = 2;
7199 return ("lsr %0" CR_TAB
7200 "lsr %0");
7201 case 3:
7202 *len = 3;
7203 return ("lsr %0" CR_TAB
7204 "lsr %0" CR_TAB
7205 "lsr %0");
7206
7207 case 4:
7208 if (test_hard_reg_class (LD_REGS, operands[0]))
7209 {
7210 *len=2;
7211 return ("swap %0" CR_TAB
7212 "andi %0,0x0f");
7213 }
7214 *len = 4;
7215 return ("lsr %0" CR_TAB
7216 "lsr %0" CR_TAB
7217 "lsr %0" CR_TAB
7218 "lsr %0");
7219
7220 case 5:
7221 if (test_hard_reg_class (LD_REGS, operands[0]))
7222 {
7223 *len = 3;
7224 return ("swap %0" CR_TAB
7225 "lsr %0" CR_TAB
7226 "andi %0,0x7");
7227 }
7228 *len = 5;
7229 return ("lsr %0" CR_TAB
7230 "lsr %0" CR_TAB
7231 "lsr %0" CR_TAB
7232 "lsr %0" CR_TAB
7233 "lsr %0");
7234
7235 case 6:
7236 if (test_hard_reg_class (LD_REGS, operands[0]))
7237 {
7238 *len = 4;
7239 return ("swap %0" CR_TAB
7240 "lsr %0" CR_TAB
7241 "lsr %0" CR_TAB
7242 "andi %0,0x3");
7243 }
7244 *len = 6;
7245 return ("lsr %0" CR_TAB
7246 "lsr %0" CR_TAB
7247 "lsr %0" CR_TAB
7248 "lsr %0" CR_TAB
7249 "lsr %0" CR_TAB
7250 "lsr %0");
7251
7252 case 7:
7253 *len = 3;
7254 return ("rol %0" CR_TAB
7255 "clr %0" CR_TAB
7256 "rol %0");
7257 }
7258 }
7259 else if (CONSTANT_P (operands[2]))
7260 fatal_insn ("internal compiler error. Incorrect shift:", insn);
7261
7262 out_shift_with_cnt ("lsr %0",
7263 insn, operands, len, 1);
7264 return "";
7265 }
7266
7267 /* 16-bit logic shift right ((unsigned short)x >> i) */
7268
7269 const char *
lshrhi3_out(rtx_insn * insn,rtx operands[],int * len)7270 lshrhi3_out (rtx_insn *insn, rtx operands[], int *len)
7271 {
7272 if (CONST_INT_P (operands[2]))
7273 {
7274 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
7275 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
7276 int k;
7277 int *t = len;
7278
7279 if (!len)
7280 len = &k;
7281
7282 switch (INTVAL (operands[2]))
7283 {
7284 default:
7285 if (INTVAL (operands[2]) < 16)
7286 break;
7287
7288 *len = 2;
7289 return ("clr %B0" CR_TAB
7290 "clr %A0");
7291
7292 case 4:
7293 if (optimize_size && scratch)
7294 break; /* 5 */
7295 if (ldi_ok)
7296 {
7297 *len = 6;
7298 return ("swap %B0" CR_TAB
7299 "swap %A0" CR_TAB
7300 "andi %A0,0x0f" CR_TAB
7301 "eor %A0,%B0" CR_TAB
7302 "andi %B0,0x0f" CR_TAB
7303 "eor %A0,%B0");
7304 }
7305 if (scratch)
7306 {
7307 *len = 7;
7308 return ("swap %B0" CR_TAB
7309 "swap %A0" CR_TAB
7310 "ldi %3,0x0f" CR_TAB
7311 "and %A0,%3" CR_TAB
7312 "eor %A0,%B0" CR_TAB
7313 "and %B0,%3" CR_TAB
7314 "eor %A0,%B0");
7315 }
7316 break; /* optimize_size ? 6 : 8 */
7317
7318 case 5:
7319 if (optimize_size)
7320 break; /* scratch ? 5 : 6 */
7321 if (ldi_ok)
7322 {
7323 *len = 8;
7324 return ("lsr %B0" CR_TAB
7325 "ror %A0" CR_TAB
7326 "swap %B0" CR_TAB
7327 "swap %A0" CR_TAB
7328 "andi %A0,0x0f" CR_TAB
7329 "eor %A0,%B0" CR_TAB
7330 "andi %B0,0x0f" CR_TAB
7331 "eor %A0,%B0");
7332 }
7333 if (scratch)
7334 {
7335 *len = 9;
7336 return ("lsr %B0" CR_TAB
7337 "ror %A0" CR_TAB
7338 "swap %B0" CR_TAB
7339 "swap %A0" CR_TAB
7340 "ldi %3,0x0f" CR_TAB
7341 "and %A0,%3" CR_TAB
7342 "eor %A0,%B0" CR_TAB
7343 "and %B0,%3" CR_TAB
7344 "eor %A0,%B0");
7345 }
7346 break; /* 10 */
7347
7348 case 6:
7349 if (optimize_size)
7350 break; /* scratch ? 5 : 6 */
7351 *len = 9;
7352 return ("clr __tmp_reg__" CR_TAB
7353 "lsl %A0" CR_TAB
7354 "rol %B0" CR_TAB
7355 "rol __tmp_reg__" CR_TAB
7356 "lsl %A0" CR_TAB
7357 "rol %B0" CR_TAB
7358 "rol __tmp_reg__" CR_TAB
7359 "mov %A0,%B0" CR_TAB
7360 "mov %B0,__tmp_reg__");
7361
7362 case 7:
7363 *len = 5;
7364 return ("lsl %A0" CR_TAB
7365 "mov %A0,%B0" CR_TAB
7366 "rol %A0" CR_TAB
7367 "sbc %B0,%B0" CR_TAB
7368 "neg %B0");
7369
7370 case 8:
7371 return *len = 2, ("mov %A0,%B1" CR_TAB
7372 "clr %B0");
7373
7374 case 9:
7375 *len = 3;
7376 return ("mov %A0,%B0" CR_TAB
7377 "clr %B0" CR_TAB
7378 "lsr %A0");
7379
7380 case 10:
7381 *len = 4;
7382 return ("mov %A0,%B0" CR_TAB
7383 "clr %B0" CR_TAB
7384 "lsr %A0" CR_TAB
7385 "lsr %A0");
7386
7387 case 11:
7388 *len = 5;
7389 return ("mov %A0,%B0" CR_TAB
7390 "clr %B0" CR_TAB
7391 "lsr %A0" CR_TAB
7392 "lsr %A0" CR_TAB
7393 "lsr %A0");
7394
7395 case 12:
7396 if (ldi_ok)
7397 {
7398 *len = 4;
7399 return ("mov %A0,%B0" CR_TAB
7400 "clr %B0" CR_TAB
7401 "swap %A0" CR_TAB
7402 "andi %A0,0x0f");
7403 }
7404 if (scratch)
7405 {
7406 *len = 5;
7407 return ("mov %A0,%B0" CR_TAB
7408 "clr %B0" CR_TAB
7409 "swap %A0" CR_TAB
7410 "ldi %3,0x0f" CR_TAB
7411 "and %A0,%3");
7412 }
7413 *len = 6;
7414 return ("mov %A0,%B0" CR_TAB
7415 "clr %B0" CR_TAB
7416 "lsr %A0" CR_TAB
7417 "lsr %A0" CR_TAB
7418 "lsr %A0" CR_TAB
7419 "lsr %A0");
7420
7421 case 13:
7422 if (ldi_ok)
7423 {
7424 *len = 5;
7425 return ("mov %A0,%B0" CR_TAB
7426 "clr %B0" CR_TAB
7427 "swap %A0" CR_TAB
7428 "lsr %A0" CR_TAB
7429 "andi %A0,0x07");
7430 }
7431 if (AVR_HAVE_MUL && scratch)
7432 {
7433 *len = 5;
7434 return ("ldi %3,0x08" CR_TAB
7435 "mul %B0,%3" CR_TAB
7436 "mov %A0,r1" CR_TAB
7437 "clr %B0" CR_TAB
7438 "clr __zero_reg__");
7439 }
7440 if (optimize_size && scratch)
7441 break; /* 5 */
7442 if (scratch)
7443 {
7444 *len = 6;
7445 return ("mov %A0,%B0" CR_TAB
7446 "clr %B0" CR_TAB
7447 "swap %A0" CR_TAB
7448 "lsr %A0" CR_TAB
7449 "ldi %3,0x07" CR_TAB
7450 "and %A0,%3");
7451 }
7452 if (AVR_HAVE_MUL)
7453 {
7454 *len = 6;
7455 return ("set" CR_TAB
7456 "bld r1,3" CR_TAB
7457 "mul %B0,r1" CR_TAB
7458 "mov %A0,r1" CR_TAB
7459 "clr %B0" CR_TAB
7460 "clr __zero_reg__");
7461 }
7462 *len = 7;
7463 return ("mov %A0,%B0" CR_TAB
7464 "clr %B0" CR_TAB
7465 "lsr %A0" CR_TAB
7466 "lsr %A0" CR_TAB
7467 "lsr %A0" CR_TAB
7468 "lsr %A0" CR_TAB
7469 "lsr %A0");
7470
7471 case 14:
7472 if (AVR_HAVE_MUL && ldi_ok)
7473 {
7474 *len = 5;
7475 return ("ldi %A0,0x04" CR_TAB
7476 "mul %B0,%A0" CR_TAB
7477 "mov %A0,r1" CR_TAB
7478 "clr %B0" CR_TAB
7479 "clr __zero_reg__");
7480 }
7481 if (AVR_HAVE_MUL && scratch)
7482 {
7483 *len = 5;
7484 return ("ldi %3,0x04" CR_TAB
7485 "mul %B0,%3" CR_TAB
7486 "mov %A0,r1" CR_TAB
7487 "clr %B0" CR_TAB
7488 "clr __zero_reg__");
7489 }
7490 if (optimize_size && ldi_ok)
7491 {
7492 *len = 5;
7493 return ("mov %A0,%B0" CR_TAB
7494 "ldi %B0,6" "\n1:\t"
7495 "lsr %A0" CR_TAB
7496 "dec %B0" CR_TAB
7497 "brne 1b");
7498 }
7499 if (optimize_size && scratch)
7500 break; /* 5 */
7501 *len = 6;
7502 return ("clr %A0" CR_TAB
7503 "lsl %B0" CR_TAB
7504 "rol %A0" CR_TAB
7505 "lsl %B0" CR_TAB
7506 "rol %A0" CR_TAB
7507 "clr %B0");
7508
7509 case 15:
7510 *len = 4;
7511 return ("clr %A0" CR_TAB
7512 "lsl %B0" CR_TAB
7513 "rol %A0" CR_TAB
7514 "clr %B0");
7515 }
7516 len = t;
7517 }
7518 out_shift_with_cnt ("lsr %B0" CR_TAB
7519 "ror %A0", insn, operands, len, 2);
7520 return "";
7521 }
7522
7523
7524 /* 24-bit logic shift right */
7525
7526 const char*
avr_out_lshrpsi3(rtx_insn * insn,rtx * op,int * plen)7527 avr_out_lshrpsi3 (rtx_insn *insn, rtx *op, int *plen)
7528 {
7529 int dest = REGNO (op[0]);
7530 int src = REGNO (op[1]);
7531
7532 if (CONST_INT_P (op[2]))
7533 {
7534 if (plen)
7535 *plen = 0;
7536
7537 switch (INTVAL (op[2]))
7538 {
7539 case 8:
7540 if (dest <= src)
7541 return avr_asm_len ("mov %A0,%B1" CR_TAB
7542 "mov %B0,%C1" CR_TAB
7543 "clr %C0", op, plen, 3);
7544 else
7545 return avr_asm_len ("clr %C0" CR_TAB
7546 "mov %B0,%C1" CR_TAB
7547 "mov %A0,%B1", op, plen, 3);
7548
7549 case 16:
7550 if (dest != src + 2)
7551 avr_asm_len ("mov %A0,%C1", op, plen, 1);
7552
7553 return avr_asm_len ("clr %B0" CR_TAB
7554 "clr %C0", op, plen, 2);
7555
7556 default:
7557 if (INTVAL (op[2]) < 24)
7558 break;
7559
7560 /* fall through */
7561
7562 case 23:
7563 return avr_asm_len ("clr %A0" CR_TAB
7564 "sbrc %C0,7" CR_TAB
7565 "inc %A0" CR_TAB
7566 "clr %B0" CR_TAB
7567 "clr %C0", op, plen, 5);
7568 } /* switch */
7569 }
7570
7571 out_shift_with_cnt ("lsr %C0" CR_TAB
7572 "ror %B0" CR_TAB
7573 "ror %A0", insn, op, plen, 3);
7574 return "";
7575 }
7576
7577
7578 /* 32-bit logic shift right ((unsigned int)x >> i) */
7579
7580 const char *
lshrsi3_out(rtx_insn * insn,rtx operands[],int * len)7581 lshrsi3_out (rtx_insn *insn, rtx operands[], int *len)
7582 {
7583 if (CONST_INT_P (operands[2]))
7584 {
7585 int k;
7586 int *t = len;
7587
7588 if (!len)
7589 len = &k;
7590
7591 switch (INTVAL (operands[2]))
7592 {
7593 default:
7594 if (INTVAL (operands[2]) < 32)
7595 break;
7596
7597 if (AVR_HAVE_MOVW)
7598 return *len = 3, ("clr %D0" CR_TAB
7599 "clr %C0" CR_TAB
7600 "movw %A0,%C0");
7601 *len = 4;
7602 return ("clr %D0" CR_TAB
7603 "clr %C0" CR_TAB
7604 "clr %B0" CR_TAB
7605 "clr %A0");
7606
7607 case 8:
7608 {
7609 int reg0 = true_regnum (operands[0]);
7610 int reg1 = true_regnum (operands[1]);
7611 *len = 4;
7612 if (reg0 <= reg1)
7613 return ("mov %A0,%B1" CR_TAB
7614 "mov %B0,%C1" CR_TAB
7615 "mov %C0,%D1" CR_TAB
7616 "clr %D0");
7617 else
7618 return ("clr %D0" CR_TAB
7619 "mov %C0,%D1" CR_TAB
7620 "mov %B0,%C1" CR_TAB
7621 "mov %A0,%B1");
7622 }
7623
7624 case 16:
7625 {
7626 int reg0 = true_regnum (operands[0]);
7627 int reg1 = true_regnum (operands[1]);
7628
7629 if (reg0 == reg1 + 2)
7630 return *len = 2, ("clr %C0" CR_TAB
7631 "clr %D0");
7632 if (AVR_HAVE_MOVW)
7633 return *len = 3, ("movw %A0,%C1" CR_TAB
7634 "clr %C0" CR_TAB
7635 "clr %D0");
7636 else
7637 return *len = 4, ("mov %B0,%D1" CR_TAB
7638 "mov %A0,%C1" CR_TAB
7639 "clr %C0" CR_TAB
7640 "clr %D0");
7641 }
7642
7643 case 24:
7644 return *len = 4, ("mov %A0,%D1" CR_TAB
7645 "clr %B0" CR_TAB
7646 "clr %C0" CR_TAB
7647 "clr %D0");
7648
7649 case 31:
7650 *len = 6;
7651 return ("clr %A0" CR_TAB
7652 "sbrc %D0,7" CR_TAB
7653 "inc %A0" CR_TAB
7654 "clr %B0" CR_TAB
7655 "clr %C0" CR_TAB
7656 "clr %D0");
7657 }
7658 len = t;
7659 }
7660 out_shift_with_cnt ("lsr %D0" CR_TAB
7661 "ror %C0" CR_TAB
7662 "ror %B0" CR_TAB
7663 "ror %A0", insn, operands, len, 4);
7664 return "";
7665 }
7666
7667
7668 /* Output addition of register XOP[0] and compile time constant XOP[2].
7669 CODE == PLUS: perform addition by using ADD instructions or
7670 CODE == MINUS: perform addition by using SUB instructions:
7671
7672 XOP[0] = XOP[0] + XOP[2]
7673
7674 Or perform addition/subtraction with register XOP[2] depending on CODE:
7675
7676 XOP[0] = XOP[0] +/- XOP[2]
7677
7678 If PLEN == NULL, print assembler instructions to perform the operation;
7679 otherwise, set *PLEN to the length of the instruction sequence (in words)
7680 printed with PLEN == NULL. XOP[3] is an 8-bit scratch register or NULL_RTX.
7681 Set *PCC to effect on cc0 according to respective CC_* insn attribute.
7682
7683 CODE_SAT == UNKNOWN: Perform ordinary, non-saturating operation.
7684 CODE_SAT != UNKNOWN: Perform operation and saturate according to CODE_SAT.
7685 If CODE_SAT != UNKNOWN then SIGN contains the sign of the summand resp.
7686 the subtrahend in the original insn, provided it is a compile time constant.
7687 In all other cases, SIGN is 0.
7688
7689 If OUT_LABEL is true, print the final 0: label which is needed for
7690 saturated addition / subtraction. The only case where OUT_LABEL = false
7691 is useful is for saturated addition / subtraction performed during
7692 fixed-point rounding, cf. `avr_out_round'. */
7693
7694 static void
avr_out_plus_1(rtx * xop,int * plen,enum rtx_code code,int * pcc,enum rtx_code code_sat,int sign,bool out_label)7695 avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc,
7696 enum rtx_code code_sat, int sign, bool out_label)
7697 {
7698 /* MODE of the operation. */
7699 machine_mode mode = GET_MODE (xop[0]);
7700
7701 /* INT_MODE of the same size. */
7702 scalar_int_mode imode = int_mode_for_mode (mode).require ();
7703
7704 /* Number of bytes to operate on. */
7705 int n_bytes = GET_MODE_SIZE (mode);
7706
7707 /* Value (0..0xff) held in clobber register op[3] or -1 if unknown. */
7708 int clobber_val = -1;
7709
7710 /* op[0]: 8-bit destination register
7711 op[1]: 8-bit const int
7712 op[2]: 8-bit scratch register */
7713 rtx op[3];
7714
7715 /* Started the operation? Before starting the operation we may skip
7716 adding 0. This is no more true after the operation started because
7717 carry must be taken into account. */
7718 bool started = false;
7719
7720 /* Value to add. There are two ways to add VAL: R += VAL and R -= -VAL. */
7721 rtx xval = xop[2];
7722
7723 /* Output a BRVC instruction. Only needed with saturation. */
7724 bool out_brvc = true;
7725
7726 if (plen)
7727 *plen = 0;
7728
7729 if (REG_P (xop[2]))
7730 {
7731 *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_CLOBBER;
7732
7733 for (int i = 0; i < n_bytes; i++)
7734 {
7735 /* We operate byte-wise on the destination. */
7736 op[0] = simplify_gen_subreg (QImode, xop[0], mode, i);
7737 op[1] = simplify_gen_subreg (QImode, xop[2], mode, i);
7738
7739 if (i == 0)
7740 avr_asm_len (code == PLUS ? "add %0,%1" : "sub %0,%1",
7741 op, plen, 1);
7742 else
7743 avr_asm_len (code == PLUS ? "adc %0,%1" : "sbc %0,%1",
7744 op, plen, 1);
7745 }
7746
7747 if (reg_overlap_mentioned_p (xop[0], xop[2]))
7748 {
7749 gcc_assert (REGNO (xop[0]) == REGNO (xop[2]));
7750
7751 if (MINUS == code)
7752 return;
7753 }
7754
7755 goto saturate;
7756 }
7757
7758 /* Except in the case of ADIW with 16-bit register (see below)
7759 addition does not set cc0 in a usable way. */
7760
7761 *pcc = (MINUS == code) ? CC_SET_CZN : CC_CLOBBER;
7762
7763 if (CONST_FIXED_P (xval))
7764 xval = avr_to_int_mode (xval);
7765
7766 /* Adding/Subtracting zero is a no-op. */
7767
7768 if (xval == const0_rtx)
7769 {
7770 *pcc = CC_NONE;
7771 return;
7772 }
7773
7774 if (MINUS == code)
7775 xval = simplify_unary_operation (NEG, imode, xval, imode);
7776
7777 op[2] = xop[3];
7778
7779 if (SS_PLUS == code_sat && MINUS == code
7780 && sign < 0
7781 && 0x80 == (INTVAL (simplify_gen_subreg (QImode, xval, imode, n_bytes-1))
7782 & GET_MODE_MASK (QImode)))
7783 {
7784 /* We compute x + 0x80 by means of SUB instructions. We negated the
7785 constant subtrahend above and are left with x - (-128) so that we
7786 need something like SUBI r,128 which does not exist because SUBI sets
7787 V according to the sign of the subtrahend. Notice the only case
7788 where this must be done is when NEG overflowed in case [2s] because
7789 the V computation needs the right sign of the subtrahend. */
7790
7791 rtx msb = simplify_gen_subreg (QImode, xop[0], mode, n_bytes - 1);
7792
7793 avr_asm_len ("subi %0,128" CR_TAB
7794 "brmi 0f", &msb, plen, 2);
7795 out_brvc = false;
7796
7797 goto saturate;
7798 }
7799
7800 for (int i = 0; i < n_bytes; i++)
7801 {
7802 /* We operate byte-wise on the destination. */
7803 rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
7804 rtx xval8 = simplify_gen_subreg (QImode, xval, imode, i);
7805
7806 /* 8-bit value to operate with this byte. */
7807 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
7808
7809 /* Registers R16..R31 can operate with immediate. */
7810 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
7811
7812 op[0] = reg8;
7813 op[1] = gen_int_mode (val8, QImode);
7814
7815 /* To get usable cc0 no low-bytes must have been skipped. */
7816
7817 if (i && !started)
7818 *pcc = CC_CLOBBER;
7819
7820 if (!started
7821 && i % 2 == 0
7822 && i + 2 <= n_bytes
7823 && test_hard_reg_class (ADDW_REGS, reg8))
7824 {
7825 rtx xval16 = simplify_gen_subreg (HImode, xval, imode, i);
7826 unsigned int val16 = UINTVAL (xval16) & GET_MODE_MASK (HImode);
7827
7828 /* Registers R24, X, Y, Z can use ADIW/SBIW with constants < 64
7829 i.e. operate word-wise. */
7830
7831 if (val16 < 64)
7832 {
7833 if (val16 != 0)
7834 {
7835 started = true;
7836 avr_asm_len (code == PLUS ? "adiw %0,%1" : "sbiw %0,%1",
7837 op, plen, 1);
7838
7839 if (n_bytes == 2 && PLUS == code)
7840 *pcc = CC_SET_CZN;
7841 }
7842
7843 i++;
7844 continue;
7845 }
7846 }
7847
7848 if (val8 == 0)
7849 {
7850 if (started)
7851 avr_asm_len (code == PLUS
7852 ? "adc %0,__zero_reg__" : "sbc %0,__zero_reg__",
7853 op, plen, 1);
7854 continue;
7855 }
7856 else if ((val8 == 1 || val8 == 0xff)
7857 && UNKNOWN == code_sat
7858 && !started
7859 && i == n_bytes - 1)
7860 {
7861 avr_asm_len ((code == PLUS) ^ (val8 == 1) ? "dec %0" : "inc %0",
7862 op, plen, 1);
7863 *pcc = CC_CLOBBER;
7864 break;
7865 }
7866
7867 switch (code)
7868 {
7869 case PLUS:
7870
7871 gcc_assert (plen != NULL || (op[2] && REG_P (op[2])));
7872
7873 if (plen != NULL && UNKNOWN != code_sat)
7874 {
7875 /* This belongs to the x + 0x80 corner case. The code with
7876 ADD instruction is not smaller, thus make this case
7877 expensive so that the caller won't pick it. */
7878
7879 *plen += 10;
7880 break;
7881 }
7882
7883 if (clobber_val != (int) val8)
7884 avr_asm_len ("ldi %2,%1", op, plen, 1);
7885 clobber_val = (int) val8;
7886
7887 avr_asm_len (started ? "adc %0,%2" : "add %0,%2", op, plen, 1);
7888
7889 break; /* PLUS */
7890
7891 case MINUS:
7892
7893 if (ld_reg_p)
7894 avr_asm_len (started ? "sbci %0,%1" : "subi %0,%1", op, plen, 1);
7895 else
7896 {
7897 gcc_assert (plen != NULL || REG_P (op[2]));
7898
7899 if (clobber_val != (int) val8)
7900 avr_asm_len ("ldi %2,%1", op, plen, 1);
7901 clobber_val = (int) val8;
7902
7903 avr_asm_len (started ? "sbc %0,%2" : "sub %0,%2", op, plen, 1);
7904 }
7905
7906 break; /* MINUS */
7907
7908 default:
7909 /* Unknown code */
7910 gcc_unreachable();
7911 }
7912
7913 started = true;
7914
7915 } /* for all sub-bytes */
7916
7917 saturate:
7918
7919 if (UNKNOWN == code_sat)
7920 return;
7921
7922 *pcc = (int) CC_CLOBBER;
7923
7924 /* Vanilla addition/subtraction is done. We are left with saturation.
7925
7926 We have to compute A = A <op> B where A is a register and
7927 B is a register or a non-zero compile time constant CONST.
7928 A is register class "r" if unsigned && B is REG. Otherwise, A is in "d".
7929 B stands for the original operand $2 in INSN. In the case of B = CONST,
7930 SIGN in { -1, 1 } is the sign of B. Otherwise, SIGN is 0.
7931
7932 CODE is the instruction flavor we use in the asm sequence to perform <op>.
7933
7934
7935 unsigned
7936 operation | code | sat if | b is | sat value | case
7937 -----------------+-------+----------+--------------+-----------+-------
7938 + as a + b | add | C == 1 | const, reg | u+ = 0xff | [1u]
7939 + as a - (-b) | sub | C == 0 | const | u+ = 0xff | [2u]
7940 - as a - b | sub | C == 1 | const, reg | u- = 0 | [3u]
7941 - as a + (-b) | add | C == 0 | const | u- = 0 | [4u]
7942
7943
7944 signed
7945 operation | code | sat if | b is | sat value | case
7946 -----------------+-------+----------+--------------+-----------+-------
7947 + as a + b | add | V == 1 | const, reg | s+ | [1s]
7948 + as a - (-b) | sub | V == 1 | const | s+ | [2s]
7949 - as a - b | sub | V == 1 | const, reg | s- | [3s]
7950 - as a + (-b) | add | V == 1 | const | s- | [4s]
7951
7952 s+ = b < 0 ? -0x80 : 0x7f
7953 s- = b < 0 ? 0x7f : -0x80
7954
7955 The cases a - b actually perform a - (-(-b)) if B is CONST.
7956 */
7957
7958 op[0] = simplify_gen_subreg (QImode, xop[0], mode, n_bytes-1);
7959 op[1] = n_bytes > 1
7960 ? simplify_gen_subreg (QImode, xop[0], mode, n_bytes-2)
7961 : NULL_RTX;
7962
7963 bool need_copy = true;
7964 int len_call = 1 + AVR_HAVE_JMP_CALL;
7965
7966 switch (code_sat)
7967 {
7968 default:
7969 gcc_unreachable();
7970
7971 case SS_PLUS:
7972 case SS_MINUS:
7973
7974 if (out_brvc)
7975 avr_asm_len ("brvc 0f", op, plen, 1);
7976
7977 if (reg_overlap_mentioned_p (xop[0], xop[2]))
7978 {
7979 /* [1s,reg] */
7980
7981 if (n_bytes == 1)
7982 avr_asm_len ("ldi %0,0x7f" CR_TAB
7983 "adc %0,__zero_reg__", op, plen, 2);
7984 else
7985 avr_asm_len ("ldi %0,0x7f" CR_TAB
7986 "ldi %1,0xff" CR_TAB
7987 "adc %1,__zero_reg__" CR_TAB
7988 "adc %0,__zero_reg__", op, plen, 4);
7989 }
7990 else if (sign == 0 && PLUS == code)
7991 {
7992 /* [1s,reg] */
7993
7994 op[2] = simplify_gen_subreg (QImode, xop[2], mode, n_bytes-1);
7995
7996 if (n_bytes == 1)
7997 avr_asm_len ("ldi %0,0x80" CR_TAB
7998 "sbrs %2,7" CR_TAB
7999 "dec %0", op, plen, 3);
8000 else
8001 avr_asm_len ("ldi %0,0x80" CR_TAB
8002 "cp %2,%0" CR_TAB
8003 "sbc %1,%1" CR_TAB
8004 "sbci %0,0", op, plen, 4);
8005 }
8006 else if (sign == 0 && MINUS == code)
8007 {
8008 /* [3s,reg] */
8009
8010 op[2] = simplify_gen_subreg (QImode, xop[2], mode, n_bytes-1);
8011
8012 if (n_bytes == 1)
8013 avr_asm_len ("ldi %0,0x7f" CR_TAB
8014 "sbrs %2,7" CR_TAB
8015 "inc %0", op, plen, 3);
8016 else
8017 avr_asm_len ("ldi %0,0x7f" CR_TAB
8018 "cp %0,%2" CR_TAB
8019 "sbc %1,%1" CR_TAB
8020 "sbci %0,-1", op, plen, 4);
8021 }
8022 else if ((sign < 0) ^ (SS_MINUS == code_sat))
8023 {
8024 /* [1s,const,B < 0] [2s,B < 0] */
8025 /* [3s,const,B > 0] [4s,B > 0] */
8026
8027 if (n_bytes == 8)
8028 {
8029 avr_asm_len ("%~call __clr_8", op, plen, len_call);
8030 need_copy = false;
8031 }
8032
8033 avr_asm_len ("ldi %0,0x80", op, plen, 1);
8034 if (n_bytes > 1 && need_copy)
8035 avr_asm_len ("clr %1", op, plen, 1);
8036 }
8037 else if ((sign > 0) ^ (SS_MINUS == code_sat))
8038 {
8039 /* [1s,const,B > 0] [2s,B > 0] */
8040 /* [3s,const,B < 0] [4s,B < 0] */
8041
8042 if (n_bytes == 8)
8043 {
8044 avr_asm_len ("sec" CR_TAB
8045 "%~call __sbc_8", op, plen, 1 + len_call);
8046 need_copy = false;
8047 }
8048
8049 avr_asm_len ("ldi %0,0x7f", op, plen, 1);
8050 if (n_bytes > 1 && need_copy)
8051 avr_asm_len ("ldi %1,0xff", op, plen, 1);
8052 }
8053 else
8054 gcc_unreachable();
8055
8056 break;
8057
8058 case US_PLUS:
8059 /* [1u] : [2u] */
8060
8061 avr_asm_len (PLUS == code ? "brcc 0f" : "brcs 0f", op, plen, 1);
8062
8063 if (n_bytes == 8)
8064 {
8065 if (MINUS == code)
8066 avr_asm_len ("sec", op, plen, 1);
8067 avr_asm_len ("%~call __sbc_8", op, plen, len_call);
8068
8069 need_copy = false;
8070 }
8071 else
8072 {
8073 if (MINUS == code && !test_hard_reg_class (LD_REGS, op[0]))
8074 avr_asm_len ("sec" CR_TAB
8075 "sbc %0,%0", op, plen, 2);
8076 else
8077 avr_asm_len (PLUS == code ? "sbc %0,%0" : "ldi %0,0xff",
8078 op, plen, 1);
8079 }
8080 break; /* US_PLUS */
8081
8082 case US_MINUS:
8083 /* [4u] : [3u] */
8084
8085 avr_asm_len (PLUS == code ? "brcs 0f" : "brcc 0f", op, plen, 1);
8086
8087 if (n_bytes == 8)
8088 {
8089 avr_asm_len ("%~call __clr_8", op, plen, len_call);
8090 need_copy = false;
8091 }
8092 else
8093 avr_asm_len ("clr %0", op, plen, 1);
8094
8095 break;
8096 }
8097
8098 /* We set the MSB in the unsigned case and the 2 MSBs in the signed case.
8099 Now copy the right value to the LSBs. */
8100
8101 if (need_copy && n_bytes > 1)
8102 {
8103 if (US_MINUS == code_sat || US_PLUS == code_sat)
8104 {
8105 avr_asm_len ("mov %1,%0", op, plen, 1);
8106
8107 if (n_bytes > 2)
8108 {
8109 op[0] = xop[0];
8110 if (AVR_HAVE_MOVW)
8111 avr_asm_len ("movw %0,%1", op, plen, 1);
8112 else
8113 avr_asm_len ("mov %A0,%1" CR_TAB
8114 "mov %B0,%1", op, plen, 2);
8115 }
8116 }
8117 else if (n_bytes > 2)
8118 {
8119 op[0] = xop[0];
8120 avr_asm_len ("mov %A0,%1" CR_TAB
8121 "mov %B0,%1", op, plen, 2);
8122 }
8123 }
8124
8125 if (need_copy && n_bytes == 8)
8126 {
8127 if (AVR_HAVE_MOVW)
8128 avr_asm_len ("movw %r0+2,%0" CR_TAB
8129 "movw %r0+4,%0", xop, plen, 2);
8130 else
8131 avr_asm_len ("mov %r0+2,%0" CR_TAB
8132 "mov %r0+3,%0" CR_TAB
8133 "mov %r0+4,%0" CR_TAB
8134 "mov %r0+5,%0", xop, plen, 4);
8135 }
8136
8137 if (out_label)
8138 avr_asm_len ("0:", op, plen, 0);
8139 }
8140
8141
8142 /* Output addition/subtraction of register XOP[0] and a constant XOP[2] that
8143 is ont a compile-time constant:
8144
8145 XOP[0] = XOP[0] +/- XOP[2]
8146
8147 This is a helper for the function below. The only insns that need this
8148 are additions/subtraction for pointer modes, i.e. HImode and PSImode. */
8149
8150 static const char*
avr_out_plus_symbol(rtx * xop,enum rtx_code code,int * plen,int * pcc)8151 avr_out_plus_symbol (rtx *xop, enum rtx_code code, int *plen, int *pcc)
8152 {
8153 machine_mode mode = GET_MODE (xop[0]);
8154
8155 /* Only pointer modes want to add symbols. */
8156
8157 gcc_assert (mode == HImode || mode == PSImode);
8158
8159 *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_SET_N;
8160
8161 avr_asm_len (PLUS == code
8162 ? "subi %A0,lo8(-(%2))" CR_TAB "sbci %B0,hi8(-(%2))"
8163 : "subi %A0,lo8(%2)" CR_TAB "sbci %B0,hi8(%2)",
8164 xop, plen, -2);
8165
8166 if (PSImode == mode)
8167 avr_asm_len (PLUS == code
8168 ? "sbci %C0,hlo8(-(%2))"
8169 : "sbci %C0,hlo8(%2)", xop, plen, 1);
8170 return "";
8171 }
8172
8173
8174 /* Prepare operands of addition/subtraction to be used with avr_out_plus_1.
8175
8176 INSN is a single_set insn or an insn pattern with a binary operation as
8177 SET_SRC that is one of: PLUS, SS_PLUS, US_PLUS, MINUS, SS_MINUS, US_MINUS.
8178
8179 XOP are the operands of INSN. In the case of 64-bit operations with
8180 constant XOP[] has just one element: The summand/subtrahend in XOP[0].
8181 The non-saturating insns up to 32 bits may or may not supply a "d" class
8182 scratch as XOP[3].
8183
8184 If PLEN == NULL output the instructions.
8185 If PLEN != NULL set *PLEN to the length of the sequence in words.
8186
8187 PCC is a pointer to store the instructions' effect on cc0.
8188 PCC may be NULL.
8189
8190 PLEN and PCC default to NULL.
8191
8192 OUT_LABEL defaults to TRUE. For a description, see AVR_OUT_PLUS_1.
8193
8194 Return "" */
8195
8196 const char*
avr_out_plus(rtx insn,rtx * xop,int * plen,int * pcc,bool out_label)8197 avr_out_plus (rtx insn, rtx *xop, int *plen, int *pcc, bool out_label)
8198 {
8199 int cc_plus, cc_minus, cc_dummy;
8200 int len_plus, len_minus;
8201 rtx op[4];
8202 rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
8203 rtx xdest = SET_DEST (xpattern);
8204 machine_mode mode = GET_MODE (xdest);
8205 scalar_int_mode imode = int_mode_for_mode (mode).require ();
8206 int n_bytes = GET_MODE_SIZE (mode);
8207 enum rtx_code code_sat = GET_CODE (SET_SRC (xpattern));
8208 enum rtx_code code
8209 = (PLUS == code_sat || SS_PLUS == code_sat || US_PLUS == code_sat
8210 ? PLUS : MINUS);
8211
8212 if (!pcc)
8213 pcc = &cc_dummy;
8214
8215 /* PLUS and MINUS don't saturate: Use modular wrap-around. */
8216
8217 if (PLUS == code_sat || MINUS == code_sat)
8218 code_sat = UNKNOWN;
8219
8220 if (n_bytes <= 4 && REG_P (xop[2]))
8221 {
8222 avr_out_plus_1 (xop, plen, code, pcc, code_sat, 0, out_label);
8223 return "";
8224 }
8225
8226 if (n_bytes == 8)
8227 {
8228 op[0] = gen_rtx_REG (DImode, ACC_A);
8229 op[1] = gen_rtx_REG (DImode, ACC_A);
8230 op[2] = avr_to_int_mode (xop[0]);
8231 }
8232 else
8233 {
8234 if (!REG_P (xop[2])
8235 && !CONST_INT_P (xop[2])
8236 && !CONST_FIXED_P (xop[2]))
8237 {
8238 return avr_out_plus_symbol (xop, code, plen, pcc);
8239 }
8240
8241 op[0] = avr_to_int_mode (xop[0]);
8242 op[1] = avr_to_int_mode (xop[1]);
8243 op[2] = avr_to_int_mode (xop[2]);
8244 }
8245
8246 /* Saturations and 64-bit operations don't have a clobber operand.
8247 For the other cases, the caller will provide a proper XOP[3]. */
8248
8249 xpattern = INSN_P (insn) ? PATTERN (insn) : insn;
8250 op[3] = PARALLEL == GET_CODE (xpattern) ? xop[3] : NULL_RTX;
8251
8252 /* Saturation will need the sign of the original operand. */
8253
8254 rtx xmsb = simplify_gen_subreg (QImode, op[2], imode, n_bytes-1);
8255 int sign = INTVAL (xmsb) < 0 ? -1 : 1;
8256
8257 /* If we subtract and the subtrahend is a constant, then negate it
8258 so that avr_out_plus_1 can be used. */
8259
8260 if (MINUS == code)
8261 op[2] = simplify_unary_operation (NEG, imode, op[2], imode);
8262
8263 /* Work out the shortest sequence. */
8264
8265 avr_out_plus_1 (op, &len_minus, MINUS, &cc_minus, code_sat, sign, out_label);
8266 avr_out_plus_1 (op, &len_plus, PLUS, &cc_plus, code_sat, sign, out_label);
8267
8268 if (plen)
8269 {
8270 *plen = (len_minus <= len_plus) ? len_minus : len_plus;
8271 *pcc = (len_minus <= len_plus) ? cc_minus : cc_plus;
8272 }
8273 else if (len_minus <= len_plus)
8274 avr_out_plus_1 (op, NULL, MINUS, pcc, code_sat, sign, out_label);
8275 else
8276 avr_out_plus_1 (op, NULL, PLUS, pcc, code_sat, sign, out_label);
8277
8278 return "";
8279 }
8280
8281
8282 /* Output bit operation (IOR, AND, XOR) with register XOP[0] and compile
8283 time constant XOP[2]:
8284
8285 XOP[0] = XOP[0] <op> XOP[2]
8286
8287 and return "". If PLEN == NULL, print assembler instructions to perform the
8288 operation; otherwise, set *PLEN to the length of the instruction sequence
8289 (in words) printed with PLEN == NULL. XOP[3] is either an 8-bit clobber
8290 register or SCRATCH if no clobber register is needed for the operation.
8291 INSN is an INSN_P or a pattern of an insn. */
8292
8293 const char*
avr_out_bitop(rtx insn,rtx * xop,int * plen)8294 avr_out_bitop (rtx insn, rtx *xop, int *plen)
8295 {
8296 /* CODE and MODE of the operation. */
8297 rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
8298 enum rtx_code code = GET_CODE (SET_SRC (xpattern));
8299 machine_mode mode = GET_MODE (xop[0]);
8300
8301 /* Number of bytes to operate on. */
8302 int n_bytes = GET_MODE_SIZE (mode);
8303
8304 /* Value of T-flag (0 or 1) or -1 if unknow. */
8305 int set_t = -1;
8306
8307 /* Value (0..0xff) held in clobber register op[3] or -1 if unknown. */
8308 int clobber_val = -1;
8309
8310 /* op[0]: 8-bit destination register
8311 op[1]: 8-bit const int
8312 op[2]: 8-bit clobber register, SCRATCH or NULL_RTX.
8313 op[3]: 8-bit register containing 0xff or NULL_RTX */
8314 rtx op[4];
8315
8316 op[2] = QImode == mode ? NULL_RTX : xop[3];
8317 op[3] = NULL_RTX;
8318
8319 if (plen)
8320 *plen = 0;
8321
8322 for (int i = 0; i < n_bytes; i++)
8323 {
8324 /* We operate byte-wise on the destination. */
8325 rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
8326 rtx xval8 = simplify_gen_subreg (QImode, xop[2], mode, i);
8327
8328 /* 8-bit value to operate with this byte. */
8329 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
8330
8331 /* Number of bits set in the current byte of the constant. */
8332 int pop8 = popcount_hwi (val8);
8333
8334 /* Registers R16..R31 can operate with immediate. */
8335 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
8336
8337 op[0] = reg8;
8338 op[1] = GEN_INT (val8);
8339
8340 switch (code)
8341 {
8342 case IOR:
8343
8344 if (pop8 == 0)
8345 continue;
8346 else if (ld_reg_p)
8347 avr_asm_len ("ori %0,%1", op, plen, 1);
8348 else if (pop8 == 1)
8349 {
8350 if (set_t != 1)
8351 avr_asm_len ("set", op, plen, 1);
8352 set_t = 1;
8353
8354 op[1] = GEN_INT (exact_log2 (val8));
8355 avr_asm_len ("bld %0,%1", op, plen, 1);
8356 }
8357 else if (pop8 == 8)
8358 {
8359 if (op[3] != NULL_RTX)
8360 avr_asm_len ("mov %0,%3", op, plen, 1);
8361 else
8362 avr_asm_len ("clr %0" CR_TAB
8363 "dec %0", op, plen, 2);
8364
8365 op[3] = op[0];
8366 }
8367 else
8368 {
8369 if (clobber_val != (int) val8)
8370 avr_asm_len ("ldi %2,%1", op, plen, 1);
8371 clobber_val = (int) val8;
8372
8373 avr_asm_len ("or %0,%2", op, plen, 1);
8374 }
8375
8376 continue; /* IOR */
8377
8378 case AND:
8379
8380 if (pop8 == 8)
8381 continue;
8382 else if (pop8 == 0)
8383 avr_asm_len ("clr %0", op, plen, 1);
8384 else if (ld_reg_p)
8385 avr_asm_len ("andi %0,%1", op, plen, 1);
8386 else if (pop8 == 7)
8387 {
8388 if (set_t != 0)
8389 avr_asm_len ("clt", op, plen, 1);
8390 set_t = 0;
8391
8392 op[1] = GEN_INT (exact_log2 (GET_MODE_MASK (QImode) & ~val8));
8393 avr_asm_len ("bld %0,%1", op, plen, 1);
8394 }
8395 else
8396 {
8397 if (clobber_val != (int) val8)
8398 avr_asm_len ("ldi %2,%1", op, plen, 1);
8399 clobber_val = (int) val8;
8400
8401 avr_asm_len ("and %0,%2", op, plen, 1);
8402 }
8403
8404 continue; /* AND */
8405
8406 case XOR:
8407
8408 if (pop8 == 0)
8409 continue;
8410 else if (pop8 == 8)
8411 avr_asm_len ("com %0", op, plen, 1);
8412 else if (ld_reg_p && val8 == (1 << 7))
8413 avr_asm_len ("subi %0,%1", op, plen, 1);
8414 else
8415 {
8416 if (clobber_val != (int) val8)
8417 avr_asm_len ("ldi %2,%1", op, plen, 1);
8418 clobber_val = (int) val8;
8419
8420 avr_asm_len ("eor %0,%2", op, plen, 1);
8421 }
8422
8423 continue; /* XOR */
8424
8425 default:
8426 /* Unknown rtx_code */
8427 gcc_unreachable();
8428 }
8429 } /* for all sub-bytes */
8430
8431 return "";
8432 }
8433
8434
8435 /* Output sign extension from XOP[1] to XOP[0] and return "".
8436 If PLEN == NULL, print assembler instructions to perform the operation;
8437 otherwise, set *PLEN to the length of the instruction sequence (in words)
8438 as printed with PLEN == NULL. */
8439
8440 const char*
avr_out_sign_extend(rtx_insn * insn,rtx * xop,int * plen)8441 avr_out_sign_extend (rtx_insn *insn, rtx *xop, int *plen)
8442 {
8443 // Size in bytes of source resp. destination operand.
8444 unsigned n_src = GET_MODE_SIZE (GET_MODE (xop[1]));
8445 unsigned n_dest = GET_MODE_SIZE (GET_MODE (xop[0]));
8446 rtx r_msb = all_regs_rtx[REGNO (xop[1]) + n_src - 1];
8447
8448 if (plen)
8449 *plen = 0;
8450
8451 // Copy destination to source
8452
8453 if (REGNO (xop[0]) != REGNO (xop[1]))
8454 {
8455 gcc_assert (n_src <= 2);
8456
8457 if (n_src == 2)
8458 avr_asm_len (AVR_HAVE_MOVW
8459 ? "movw %0,%1"
8460 : "mov %B0,%B1", xop, plen, 1);
8461 if (n_src == 1 || !AVR_HAVE_MOVW)
8462 avr_asm_len ("mov %A0,%A1", xop, plen, 1);
8463 }
8464
8465 // Set Carry to the sign bit MSB.7...
8466
8467 if (REGNO (xop[0]) == REGNO (xop[1])
8468 || !reg_unused_after (insn, r_msb))
8469 {
8470 avr_asm_len ("mov __tmp_reg__,%0", &r_msb, plen, 1);
8471 r_msb = tmp_reg_rtx;
8472 }
8473
8474 avr_asm_len ("lsl %0", &r_msb, plen, 1);
8475
8476 // ...and propagate it to all the new sign bits
8477
8478 for (unsigned n = n_src; n < n_dest; n++)
8479 avr_asm_len ("sbc %0,%0", &all_regs_rtx[REGNO (xop[0]) + n], plen, 1);
8480
8481 return "";
8482 }
8483
8484
8485 /* PLEN == NULL: Output code to add CONST_INT OP[0] to SP.
8486 PLEN != NULL: Set *PLEN to the length of that sequence.
8487 Return "". */
8488
8489 const char*
avr_out_addto_sp(rtx * op,int * plen)8490 avr_out_addto_sp (rtx *op, int *plen)
8491 {
8492 int pc_len = AVR_2_BYTE_PC ? 2 : 3;
8493 int addend = INTVAL (op[0]);
8494
8495 if (plen)
8496 *plen = 0;
8497
8498 if (addend < 0)
8499 {
8500 if (flag_verbose_asm || flag_print_asm_name)
8501 avr_asm_len (ASM_COMMENT_START "SP -= %n0", op, plen, 0);
8502
8503 while (addend <= -pc_len)
8504 {
8505 addend += pc_len;
8506 avr_asm_len ("rcall .", op, plen, 1);
8507 }
8508
8509 while (addend++ < 0)
8510 avr_asm_len ("push __tmp_reg__", op, plen, 1);
8511 }
8512 else if (addend > 0)
8513 {
8514 if (flag_verbose_asm || flag_print_asm_name)
8515 avr_asm_len (ASM_COMMENT_START "SP += %0", op, plen, 0);
8516
8517 while (addend-- > 0)
8518 avr_asm_len ("pop __tmp_reg__", op, plen, 1);
8519 }
8520
8521 return "";
8522 }
8523
8524
8525 /* Output instructions to insert an inverted bit into OPERANDS[0]:
8526 $0.$1 = ~$2.$3 if XBITNO = NULL
8527 $0.$1 = ~$2.XBITNO if XBITNO != NULL.
8528 If PLEN = NULL then output the respective instruction sequence which
8529 is a combination of BST / BLD and some instruction(s) to invert the bit.
8530 If PLEN != NULL then store the length of the sequence (in words) in *PLEN.
8531 Return "". */
8532
8533 const char*
avr_out_insert_notbit(rtx_insn * insn,rtx operands[],rtx xbitno,int * plen)8534 avr_out_insert_notbit (rtx_insn *insn, rtx operands[], rtx xbitno, int *plen)
8535 {
8536 rtx op[4] = { operands[0], operands[1], operands[2],
8537 xbitno == NULL_RTX ? operands [3] : xbitno };
8538
8539 if (INTVAL (op[1]) == 7
8540 && test_hard_reg_class (LD_REGS, op[0]))
8541 {
8542 /* If the inserted bit number is 7 and we have a d-reg, then invert
8543 the bit after the insertion by means of SUBI *,0x80. */
8544
8545 if (INTVAL (op[3]) == 7
8546 && REGNO (op[0]) == REGNO (op[2]))
8547 {
8548 avr_asm_len ("subi %0,0x80", op, plen, -1);
8549 }
8550 else
8551 {
8552 avr_asm_len ("bst %2,%3" CR_TAB
8553 "bld %0,%1" CR_TAB
8554 "subi %0,0x80", op, plen, -3);
8555 }
8556 }
8557 else if (test_hard_reg_class (LD_REGS, op[0])
8558 && (INTVAL (op[1]) != INTVAL (op[3])
8559 || !reg_overlap_mentioned_p (op[0], op[2])))
8560 {
8561 /* If the destination bit is in a d-reg we can jump depending
8562 on the source bit and use ANDI / ORI. This just applies if we
8563 have not an early-clobber situation with the bit. */
8564
8565 avr_asm_len ("andi %0,~(1<<%1)" CR_TAB
8566 "sbrs %2,%3" CR_TAB
8567 "ori %0,1<<%1", op, plen, -3);
8568 }
8569 else
8570 {
8571 /* Otherwise, invert the bit by means of COM before we store it with
8572 BST and then undo the COM if needed. */
8573
8574 avr_asm_len ("com %2" CR_TAB
8575 "bst %2,%3", op, plen, -2);
8576
8577 if (!reg_unused_after (insn, op[2])
8578 // A simple 'reg_unused_after' is not enough because that function
8579 // assumes that the destination register is overwritten completely
8580 // and hence is in order for our purpose. This is not the case
8581 // with BLD which just changes one bit of the destination.
8582 || reg_overlap_mentioned_p (op[0], op[2]))
8583 {
8584 /* Undo the COM from above. */
8585 avr_asm_len ("com %2", op, plen, 1);
8586 }
8587
8588 avr_asm_len ("bld %0,%1", op, plen, 1);
8589 }
8590
8591 return "";
8592 }
8593
8594
8595 /* Outputs instructions needed for fixed point type conversion.
8596 This includes converting between any fixed point type, as well
8597 as converting to any integer type. Conversion between integer
8598 types is not supported.
8599
8600 Converting signed fractional types requires a bit shift if converting
8601 to or from any unsigned fractional type because the decimal place is
8602 shifted by 1 bit. When the destination is a signed fractional, the sign
8603 is stored in either the carry or T bit. */
8604
8605 const char*
avr_out_fract(rtx_insn * insn,rtx operands[],bool intsigned,int * plen)8606 avr_out_fract (rtx_insn *insn, rtx operands[], bool intsigned, int *plen)
8607 {
8608 rtx xop[6];
8609 RTX_CODE shift = UNKNOWN;
8610 bool sign_in_carry = false;
8611 bool msb_in_carry = false;
8612 bool lsb_in_tmp_reg = false;
8613 bool lsb_in_carry = false;
8614 bool frac_rounded = false;
8615 const char *code_ashift = "lsl %0";
8616
8617
8618 #define MAY_CLOBBER(RR) \
8619 /* Shorthand used below. */ \
8620 ((sign_bytes \
8621 && IN_RANGE (RR, dest.regno_msb - sign_bytes + 1, dest.regno_msb)) \
8622 || (offset && IN_RANGE (RR, dest.regno, dest.regno_msb)) \
8623 || (reg_unused_after (insn, all_regs_rtx[RR]) \
8624 && !IN_RANGE (RR, dest.regno, dest.regno_msb)))
8625
8626 struct
8627 {
8628 /* bytes : Length of operand in bytes.
8629 ibyte : Length of integral part in bytes.
8630 fbyte, fbit : Length of fractional part in bytes, bits. */
8631
8632 bool sbit;
8633 unsigned fbit, bytes, ibyte, fbyte;
8634 unsigned regno, regno_msb;
8635 } dest, src, *val[2] = { &dest, &src };
8636
8637 if (plen)
8638 *plen = 0;
8639
8640 /* Step 0: Determine information on source and destination operand we
8641 ====== will need in the remainder. */
8642
8643 for (size_t i = 0; i < ARRAY_SIZE (val); i++)
8644 {
8645 machine_mode mode;
8646
8647 xop[i] = operands[i];
8648
8649 mode = GET_MODE (xop[i]);
8650
8651 val[i]->bytes = GET_MODE_SIZE (mode);
8652 val[i]->regno = REGNO (xop[i]);
8653 val[i]->regno_msb = REGNO (xop[i]) + val[i]->bytes - 1;
8654
8655 if (SCALAR_INT_MODE_P (mode))
8656 {
8657 val[i]->sbit = intsigned;
8658 val[i]->fbit = 0;
8659 }
8660 else if (ALL_SCALAR_FIXED_POINT_MODE_P (mode))
8661 {
8662 val[i]->sbit = SIGNED_SCALAR_FIXED_POINT_MODE_P (mode);
8663 val[i]->fbit = GET_MODE_FBIT (mode);
8664 }
8665 else
8666 fatal_insn ("unsupported fixed-point conversion", insn);
8667
8668 val[i]->fbyte = (1 + val[i]->fbit) / BITS_PER_UNIT;
8669 val[i]->ibyte = val[i]->bytes - val[i]->fbyte;
8670 }
8671
8672 // Byte offset of the decimal point taking into account different place
8673 // of the decimal point in input and output and different register numbers
8674 // of input and output.
8675 int offset = dest.regno - src.regno + dest.fbyte - src.fbyte;
8676
8677 // Number of destination bytes that will come from sign / zero extension.
8678 int sign_bytes = (dest.ibyte - src.ibyte) * (dest.ibyte > src.ibyte);
8679
8680 // Number of bytes at the low end to be filled with zeros.
8681 int zero_bytes = (dest.fbyte - src.fbyte) * (dest.fbyte > src.fbyte);
8682
8683 // Do we have a 16-Bit register that is cleared?
8684 rtx clrw = NULL_RTX;
8685
8686 bool sign_extend = src.sbit && sign_bytes;
8687
8688 if (dest.fbit % 8 == 0 && src.fbit % 8 == 7)
8689 shift = ASHIFT;
8690 else if (dest.fbit % 8 == 7 && src.fbit % 8 == 0)
8691 shift = ASHIFTRT;
8692 else if (dest.fbit % 8 == src.fbit % 8)
8693 shift = UNKNOWN;
8694 else
8695 gcc_unreachable();
8696
8697 /* If we need to round the fraction part, we might need to save/round it
8698 before clobbering any of it in Step 1. Also, we might want to do
8699 the rounding now to make use of LD_REGS. */
8700 if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8701 && SCALAR_ACCUM_MODE_P (GET_MODE (xop[1]))
8702 && !TARGET_FRACT_CONV_TRUNC)
8703 {
8704 bool overlap
8705 = (src.regno <=
8706 (offset ? dest.regno_msb - sign_bytes : dest.regno + zero_bytes - 1)
8707 && dest.regno - offset -1 >= dest.regno);
8708 unsigned s0 = dest.regno - offset -1;
8709 bool use_src = true;
8710 unsigned sn;
8711 unsigned copied_msb = src.regno_msb;
8712 bool have_carry = false;
8713
8714 if (src.ibyte > dest.ibyte)
8715 copied_msb -= src.ibyte - dest.ibyte;
8716
8717 for (sn = s0; sn <= copied_msb; sn++)
8718 if (!IN_RANGE (sn, dest.regno, dest.regno_msb)
8719 && !reg_unused_after (insn, all_regs_rtx[sn]))
8720 use_src = false;
8721 if (use_src && TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], s0))
8722 {
8723 avr_asm_len ("tst %0" CR_TAB "brpl 0f",
8724 &all_regs_rtx[src.regno_msb], plen, 2);
8725 sn = src.regno;
8726 if (sn < s0)
8727 {
8728 if (TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], sn))
8729 avr_asm_len ("cpi %0,1", &all_regs_rtx[sn], plen, 1);
8730 else
8731 avr_asm_len ("sec" CR_TAB
8732 "cpc %0,__zero_reg__",
8733 &all_regs_rtx[sn], plen, 2);
8734 have_carry = true;
8735 }
8736 while (++sn < s0)
8737 avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8738
8739 avr_asm_len (have_carry ? "sbci %0,128" : "subi %0,129",
8740 &all_regs_rtx[s0], plen, 1);
8741 for (sn = src.regno + src.fbyte; sn <= copied_msb; sn++)
8742 avr_asm_len ("sbci %0,255", &all_regs_rtx[sn], plen, 1);
8743 avr_asm_len ("\n0:", NULL, plen, 0);
8744 frac_rounded = true;
8745 }
8746 else if (use_src && overlap)
8747 {
8748 avr_asm_len ("clr __tmp_reg__" CR_TAB
8749 "sbrc %1,0" CR_TAB
8750 "dec __tmp_reg__", xop, plen, 1);
8751 sn = src.regno;
8752 if (sn < s0)
8753 {
8754 avr_asm_len ("add %0,__tmp_reg__", &all_regs_rtx[sn], plen, 1);
8755 have_carry = true;
8756 }
8757
8758 while (++sn < s0)
8759 avr_asm_len ("adc %0,__tmp_reg__", &all_regs_rtx[sn], plen, 1);
8760
8761 if (have_carry)
8762 avr_asm_len ("clt" CR_TAB
8763 "bld __tmp_reg__,7" CR_TAB
8764 "adc %0,__tmp_reg__",
8765 &all_regs_rtx[s0], plen, 1);
8766 else
8767 avr_asm_len ("lsr __tmp_reg" CR_TAB
8768 "add %0,__tmp_reg__",
8769 &all_regs_rtx[s0], plen, 2);
8770 for (sn = src.regno + src.fbyte; sn <= copied_msb; sn++)
8771 avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8772 frac_rounded = true;
8773 }
8774 else if (overlap)
8775 {
8776 bool use_src
8777 = (TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], s0)
8778 && (IN_RANGE (s0, dest.regno, dest.regno_msb)
8779 || reg_unused_after (insn, all_regs_rtx[s0])));
8780 xop[2] = all_regs_rtx[s0];
8781 unsigned sn = src.regno;
8782 if (!use_src || sn == s0)
8783 avr_asm_len ("mov __tmp_reg__,%2", xop, plen, 1);
8784 /* We need to consider to-be-discarded bits
8785 if the value is negative. */
8786 if (sn < s0)
8787 {
8788 avr_asm_len ("tst %0" CR_TAB
8789 "brpl 0f",
8790 &all_regs_rtx[src.regno_msb], plen, 2);
8791 /* Test to-be-discarded bytes for any nozero bits.
8792 ??? Could use OR or SBIW to test two registers at once. */
8793 if (sn < s0)
8794 avr_asm_len ("cp %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8795
8796 while (++sn < s0)
8797 avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8798 /* Set bit 0 in __tmp_reg__ if any of the lower bits was set. */
8799 if (use_src)
8800 avr_asm_len ("breq 0f" CR_TAB
8801 "ori %2,1"
8802 "\n0:\t" "mov __tmp_reg__,%2",
8803 xop, plen, 3);
8804 else
8805 avr_asm_len ("breq 0f" CR_TAB
8806 "set" CR_TAB
8807 "bld __tmp_reg__,0\n0:",
8808 xop, plen, 3);
8809 }
8810 lsb_in_tmp_reg = true;
8811 }
8812 }
8813
8814 /* Step 1: Clear bytes at the low end and copy payload bits from source
8815 ====== to destination. */
8816
8817 int step = offset < 0 ? 1 : -1;
8818 unsigned d0 = offset < 0 ? dest.regno : dest.regno_msb;
8819
8820 // We cleared at least that number of registers.
8821 int clr_n = 0;
8822
8823 for (; d0 >= dest.regno && d0 <= dest.regno_msb; d0 += step)
8824 {
8825 // Next regno of destination is needed for MOVW
8826 unsigned d1 = d0 + step;
8827
8828 // Current and next regno of source
8829 signed s0 = d0 - offset;
8830 signed s1 = s0 + step;
8831
8832 // Must current resp. next regno be CLRed? This applies to the low
8833 // bytes of the destination that have no associated source bytes.
8834 bool clr0 = s0 < (signed) src.regno;
8835 bool clr1 = s1 < (signed) src.regno && d1 >= dest.regno;
8836
8837 // First gather what code to emit (if any) and additional step to
8838 // apply if a MOVW is in use. xop[2] is destination rtx and xop[3]
8839 // is the source rtx for the current loop iteration.
8840 const char *code = NULL;
8841 int stepw = 0;
8842
8843 if (clr0)
8844 {
8845 if (AVR_HAVE_MOVW && clr1 && clrw)
8846 {
8847 xop[2] = all_regs_rtx[d0 & ~1];
8848 xop[3] = clrw;
8849 code = "movw %2,%3";
8850 stepw = step;
8851 }
8852 else
8853 {
8854 xop[2] = all_regs_rtx[d0];
8855 code = "clr %2";
8856
8857 if (++clr_n >= 2
8858 && !clrw
8859 && d0 % 2 == (step > 0))
8860 {
8861 clrw = all_regs_rtx[d0 & ~1];
8862 }
8863 }
8864 }
8865 else if (offset && s0 <= (signed) src.regno_msb)
8866 {
8867 int movw = AVR_HAVE_MOVW && offset % 2 == 0
8868 && d0 % 2 == (offset > 0)
8869 && d1 <= dest.regno_msb && d1 >= dest.regno
8870 && s1 <= (signed) src.regno_msb && s1 >= (signed) src.regno;
8871
8872 xop[2] = all_regs_rtx[d0 & ~movw];
8873 xop[3] = all_regs_rtx[s0 & ~movw];
8874 code = movw ? "movw %2,%3" : "mov %2,%3";
8875 stepw = step * movw;
8876 }
8877
8878 if (code)
8879 {
8880 if (sign_extend && shift != ASHIFT && !sign_in_carry
8881 && (d0 == src.regno_msb || d0 + stepw == src.regno_msb))
8882 {
8883 /* We are going to override the sign bit. If we sign-extend,
8884 store the sign in the Carry flag. This is not needed if
8885 the destination will be ASHIFT in the remainder because
8886 the ASHIFT will set Carry without extra instruction. */
8887
8888 avr_asm_len ("lsl %0", &all_regs_rtx[src.regno_msb], plen, 1);
8889 sign_in_carry = true;
8890 }
8891
8892 unsigned src_msb = dest.regno_msb - sign_bytes - offset + 1;
8893
8894 if (!sign_extend && shift == ASHIFTRT && !msb_in_carry
8895 && src.ibyte > dest.ibyte
8896 && (d0 == src_msb || d0 + stepw == src_msb))
8897 {
8898 /* We are going to override the MSB. If we shift right,
8899 store the MSB in the Carry flag. This is only needed if
8900 we don't sign-extend becaue with sign-extension the MSB
8901 (the sign) will be produced by the sign extension. */
8902
8903 avr_asm_len ("lsr %0", &all_regs_rtx[src_msb], plen, 1);
8904 msb_in_carry = true;
8905 }
8906
8907 unsigned src_lsb = dest.regno - offset -1;
8908
8909 if (shift == ASHIFT && src.fbyte > dest.fbyte && !lsb_in_carry
8910 && !lsb_in_tmp_reg
8911 && (d0 == src_lsb || d0 + stepw == src_lsb))
8912 {
8913 /* We are going to override the new LSB; store it into carry. */
8914
8915 avr_asm_len ("lsl %0", &all_regs_rtx[src_lsb], plen, 1);
8916 code_ashift = "rol %0";
8917 lsb_in_carry = true;
8918 }
8919
8920 avr_asm_len (code, xop, plen, 1);
8921 d0 += stepw;
8922 }
8923 }
8924
8925 /* Step 2: Shift destination left by 1 bit position. This might be needed
8926 ====== for signed input and unsigned output. */
8927
8928 if (shift == ASHIFT && src.fbyte > dest.fbyte && !lsb_in_carry)
8929 {
8930 unsigned s0 = dest.regno - offset -1;
8931
8932 /* n1169 4.1.4 says:
8933 "Conversions from a fixed-point to an integer type round toward zero."
8934 Hence, converting a fract type to integer only gives a non-zero result
8935 for -1. */
8936 if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8937 && SCALAR_FRACT_MODE_P (GET_MODE (xop[1]))
8938 && !TARGET_FRACT_CONV_TRUNC)
8939 {
8940 gcc_assert (s0 == src.regno_msb);
8941 /* Check if the input is -1. We do that by checking if negating
8942 the input causes an integer overflow. */
8943 unsigned sn = src.regno;
8944 avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx[sn++], plen, 1);
8945 while (sn <= s0)
8946 avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx[sn++], plen, 1);
8947
8948 /* Overflow goes with set carry. Clear carry otherwise. */
8949 avr_asm_len ("brvs 0f" CR_TAB
8950 "clc\n0:", NULL, plen, 2);
8951 }
8952 /* Likewise, when converting from accumulator types to integer, we
8953 need to round up negative values. */
8954 else if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8955 && SCALAR_ACCUM_MODE_P (GET_MODE (xop[1]))
8956 && !TARGET_FRACT_CONV_TRUNC
8957 && !frac_rounded)
8958 {
8959 bool have_carry = false;
8960
8961 xop[2] = all_regs_rtx[s0];
8962 if (!lsb_in_tmp_reg && !MAY_CLOBBER (s0))
8963 avr_asm_len ("mov __tmp_reg__,%2", xop, plen, 1);
8964 avr_asm_len ("tst %0" CR_TAB "brpl 0f",
8965 &all_regs_rtx[src.regno_msb], plen, 2);
8966 if (!lsb_in_tmp_reg)
8967 {
8968 unsigned sn = src.regno;
8969 if (sn < s0)
8970 {
8971 avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx[sn],
8972 plen, 1);
8973 have_carry = true;
8974 }
8975 while (++sn < s0)
8976 avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx[sn], plen, 1);
8977 lsb_in_tmp_reg = !MAY_CLOBBER (s0);
8978 }
8979 /* Add in C and the rounding value 127. */
8980 /* If the destination msb is a sign byte, and in LD_REGS,
8981 grab it as a temporary. */
8982 if (sign_bytes
8983 && TEST_HARD_REG_BIT (reg_class_contents[LD_REGS],
8984 dest.regno_msb))
8985 {
8986 xop[3] = all_regs_rtx[dest.regno_msb];
8987 avr_asm_len ("ldi %3,127", xop, plen, 1);
8988 avr_asm_len ((have_carry && lsb_in_tmp_reg ? "adc __tmp_reg__,%3"
8989 : have_carry ? "adc %2,%3"
8990 : lsb_in_tmp_reg ? "add __tmp_reg__,%3"
8991 : "add %2,%3"),
8992 xop, plen, 1);
8993 }
8994 else
8995 {
8996 /* Fall back to use __zero_reg__ as a temporary. */
8997 avr_asm_len ("dec __zero_reg__", NULL, plen, 1);
8998 if (have_carry)
8999 avr_asm_len ("clt" CR_TAB
9000 "bld __zero_reg__,7", NULL, plen, 2);
9001 else
9002 avr_asm_len ("lsr __zero_reg__", NULL, plen, 1);
9003 avr_asm_len (have_carry && lsb_in_tmp_reg
9004 ? "adc __tmp_reg__,__zero_reg__"
9005 : have_carry ? "adc %2,__zero_reg__"
9006 : lsb_in_tmp_reg ? "add __tmp_reg__,__zero_reg__"
9007 : "add %2,__zero_reg__",
9008 xop, plen, 1);
9009 avr_asm_len ("eor __zero_reg__,__zero_reg__", NULL, plen, 1);
9010 }
9011
9012 for (d0 = dest.regno + zero_bytes;
9013 d0 <= dest.regno_msb - sign_bytes; d0++)
9014 avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx[d0], plen, 1);
9015
9016 avr_asm_len (lsb_in_tmp_reg
9017 ? "\n0:\t" "lsl __tmp_reg__"
9018 : "\n0:\t" "lsl %2",
9019 xop, plen, 1);
9020 }
9021 else if (MAY_CLOBBER (s0))
9022 avr_asm_len ("lsl %0", &all_regs_rtx[s0], plen, 1);
9023 else
9024 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
9025 "lsl __tmp_reg__", &all_regs_rtx[s0], plen, 2);
9026
9027 code_ashift = "rol %0";
9028 lsb_in_carry = true;
9029 }
9030
9031 if (shift == ASHIFT)
9032 {
9033 for (d0 = dest.regno + zero_bytes;
9034 d0 <= dest.regno_msb - sign_bytes; d0++)
9035 {
9036 avr_asm_len (code_ashift, &all_regs_rtx[d0], plen, 1);
9037 code_ashift = "rol %0";
9038 }
9039
9040 lsb_in_carry = false;
9041 sign_in_carry = true;
9042 }
9043
9044 /* Step 4a: Store MSB in carry if we don't already have it or will produce
9045 ======= it in sign-extension below. */
9046
9047 if (!sign_extend && shift == ASHIFTRT && !msb_in_carry
9048 && src.ibyte > dest.ibyte)
9049 {
9050 unsigned s0 = dest.regno_msb - sign_bytes - offset + 1;
9051
9052 if (MAY_CLOBBER (s0))
9053 avr_asm_len ("lsr %0", &all_regs_rtx[s0], plen, 1);
9054 else
9055 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
9056 "lsr __tmp_reg__", &all_regs_rtx[s0], plen, 2);
9057
9058 msb_in_carry = true;
9059 }
9060
9061 /* Step 3: Sign-extend or zero-extend the destination as needed.
9062 ====== */
9063
9064 if (sign_extend && !sign_in_carry)
9065 {
9066 unsigned s0 = src.regno_msb;
9067
9068 if (MAY_CLOBBER (s0))
9069 avr_asm_len ("lsl %0", &all_regs_rtx[s0], plen, 1);
9070 else
9071 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
9072 "lsl __tmp_reg__", &all_regs_rtx[s0], plen, 2);
9073
9074 sign_in_carry = true;
9075 }
9076
9077 gcc_assert (sign_in_carry + msb_in_carry + lsb_in_carry <= 1);
9078
9079 unsigned copies = 0;
9080 rtx movw = sign_extend ? NULL_RTX : clrw;
9081
9082 for (d0 = dest.regno_msb - sign_bytes + 1; d0 <= dest.regno_msb; d0++)
9083 {
9084 if (AVR_HAVE_MOVW && movw
9085 && d0 % 2 == 0 && d0 + 1 <= dest.regno_msb)
9086 {
9087 xop[2] = all_regs_rtx[d0];
9088 xop[3] = movw;
9089 avr_asm_len ("movw %2,%3", xop, plen, 1);
9090 d0++;
9091 }
9092 else
9093 {
9094 avr_asm_len (sign_extend ? "sbc %0,%0" : "clr %0",
9095 &all_regs_rtx[d0], plen, 1);
9096
9097 if (++copies >= 2 && !movw && d0 % 2 == 1)
9098 movw = all_regs_rtx[d0-1];
9099 }
9100 } /* for */
9101
9102
9103 /* Step 4: Right shift the destination. This might be needed for
9104 ====== conversions from unsigned to signed. */
9105
9106 if (shift == ASHIFTRT)
9107 {
9108 const char *code_ashiftrt = "lsr %0";
9109
9110 if (sign_extend || msb_in_carry)
9111 code_ashiftrt = "ror %0";
9112
9113 if (src.sbit && src.ibyte == dest.ibyte)
9114 code_ashiftrt = "asr %0";
9115
9116 for (d0 = dest.regno_msb - sign_bytes;
9117 d0 >= dest.regno + zero_bytes - 1 && d0 >= dest.regno; d0--)
9118 {
9119 avr_asm_len (code_ashiftrt, &all_regs_rtx[d0], plen, 1);
9120 code_ashiftrt = "ror %0";
9121 }
9122 }
9123
9124 #undef MAY_CLOBBER
9125
9126 return "";
9127 }
9128
9129
9130 /* Output fixed-point rounding. XOP[0] = XOP[1] is the operand to round.
9131 XOP[2] is the rounding point, a CONST_INT. The function prints the
9132 instruction sequence if PLEN = NULL and computes the length in words
9133 of the sequence if PLEN != NULL. Most of this function deals with
9134 preparing operands for calls to `avr_out_plus' and `avr_out_bitop'. */
9135
9136 const char*
avr_out_round(rtx_insn * insn ATTRIBUTE_UNUSED,rtx * xop,int * plen)9137 avr_out_round (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *xop, int *plen)
9138 {
9139 scalar_mode mode = as_a <scalar_mode> (GET_MODE (xop[0]));
9140 scalar_int_mode imode = int_mode_for_mode (mode).require ();
9141 // The smallest fractional bit not cleared by the rounding is 2^(-RP).
9142 int fbit = (int) GET_MODE_FBIT (mode);
9143 double_int i_add = double_int_zero.set_bit (fbit-1 - INTVAL (xop[2]));
9144 wide_int wi_add = wi::set_bit_in_zero (fbit-1 - INTVAL (xop[2]),
9145 GET_MODE_PRECISION (imode));
9146 // Lengths of PLUS and AND parts.
9147 int len_add = 0, *plen_add = plen ? &len_add : NULL;
9148 int len_and = 0, *plen_and = plen ? &len_and : NULL;
9149
9150 // Add-Saturate 1/2 * 2^(-RP). Don't print the label "0:" when printing
9151 // the saturated addition so that we can emit the "rjmp 1f" before the
9152 // "0:" below.
9153
9154 rtx xadd = const_fixed_from_double_int (i_add, mode);
9155 rtx xpattern, xsrc, op[4];
9156
9157 xsrc = SIGNED_FIXED_POINT_MODE_P (mode)
9158 ? gen_rtx_SS_PLUS (mode, xop[1], xadd)
9159 : gen_rtx_US_PLUS (mode, xop[1], xadd);
9160 xpattern = gen_rtx_SET (xop[0], xsrc);
9161
9162 op[0] = xop[0];
9163 op[1] = xop[1];
9164 op[2] = xadd;
9165 avr_out_plus (xpattern, op, plen_add, NULL, false /* Don't print "0:" */);
9166
9167 avr_asm_len ("rjmp 1f" CR_TAB
9168 "0:", NULL, plen_add, 1);
9169
9170 // Keep all bits from RP and higher: ... 2^(-RP)
9171 // Clear all bits from RP+1 and lower: 2^(-RP-1) ...
9172 // Rounding point ^^^^^^^
9173 // Added above ^^^^^^^^^
9174 rtx xreg = simplify_gen_subreg (imode, xop[0], mode, 0);
9175 rtx xmask = immed_wide_int_const (-wi_add - wi_add, imode);
9176
9177 xpattern = gen_rtx_SET (xreg, gen_rtx_AND (imode, xreg, xmask));
9178
9179 op[0] = xreg;
9180 op[1] = xreg;
9181 op[2] = xmask;
9182 op[3] = gen_rtx_SCRATCH (QImode);
9183 avr_out_bitop (xpattern, op, plen_and);
9184 avr_asm_len ("1:", NULL, plen, 0);
9185
9186 if (plen)
9187 *plen = len_add + len_and;
9188
9189 return "";
9190 }
9191
9192
9193 /* Create RTL split patterns for byte sized rotate expressions. This
9194 produces a series of move instructions and considers overlap situations.
9195 Overlapping non-HImode operands need a scratch register. */
9196
9197 bool
avr_rotate_bytes(rtx operands[])9198 avr_rotate_bytes (rtx operands[])
9199 {
9200 machine_mode mode = GET_MODE (operands[0]);
9201 bool overlapped = reg_overlap_mentioned_p (operands[0], operands[1]);
9202 bool same_reg = rtx_equal_p (operands[0], operands[1]);
9203 int num = INTVAL (operands[2]);
9204 rtx scratch = operands[3];
9205 /* Work out if byte or word move is needed. Odd byte rotates need QImode.
9206 Word move if no scratch is needed, otherwise use size of scratch. */
9207 machine_mode move_mode = QImode;
9208 int move_size, offset, size;
9209
9210 if (num & 0xf)
9211 move_mode = QImode;
9212 else if ((mode == SImode && !same_reg) || !overlapped)
9213 move_mode = HImode;
9214 else
9215 move_mode = GET_MODE (scratch);
9216
9217 /* Force DI rotate to use QI moves since other DI moves are currently split
9218 into QI moves so forward propagation works better. */
9219 if (mode == DImode)
9220 move_mode = QImode;
9221 /* Make scratch smaller if needed. */
9222 if (SCRATCH != GET_CODE (scratch)
9223 && HImode == GET_MODE (scratch)
9224 && QImode == move_mode)
9225 scratch = simplify_gen_subreg (move_mode, scratch, HImode, 0);
9226
9227 move_size = GET_MODE_SIZE (move_mode);
9228 /* Number of bytes/words to rotate. */
9229 offset = (num >> 3) / move_size;
9230 /* Number of moves needed. */
9231 size = GET_MODE_SIZE (mode) / move_size;
9232 /* Himode byte swap is special case to avoid a scratch register. */
9233 if (mode == HImode && same_reg)
9234 {
9235 /* HImode byte swap, using xor. This is as quick as using scratch. */
9236 rtx src, dst;
9237 src = simplify_gen_subreg (move_mode, operands[1], mode, 0);
9238 dst = simplify_gen_subreg (move_mode, operands[0], mode, 1);
9239 if (!rtx_equal_p (dst, src))
9240 {
9241 emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
9242 emit_move_insn (src, gen_rtx_XOR (QImode, src, dst));
9243 emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
9244 }
9245 }
9246 else
9247 {
9248 #define MAX_SIZE 8 /* GET_MODE_SIZE (DImode) / GET_MODE_SIZE (QImode) */
9249 /* Create linked list of moves to determine move order. */
9250 struct {
9251 rtx src, dst;
9252 int links;
9253 } move[MAX_SIZE + 8];
9254 int blocked, moves;
9255
9256 gcc_assert (size <= MAX_SIZE);
9257 /* Generate list of subreg moves. */
9258 for (int i = 0; i < size; i++)
9259 {
9260 int from = i;
9261 int to = (from + offset) % size;
9262 move[i].src = simplify_gen_subreg (move_mode, operands[1],
9263 mode, from * move_size);
9264 move[i].dst = simplify_gen_subreg (move_mode, operands[0],
9265 mode, to * move_size);
9266 move[i].links = -1;
9267 }
9268 /* Mark dependence where a dst of one move is the src of another move.
9269 The first move is a conflict as it must wait until second is
9270 performed. We ignore moves to self - we catch this later. */
9271 if (overlapped)
9272 for (int i = 0; i < size; i++)
9273 if (reg_overlap_mentioned_p (move[i].dst, operands[1]))
9274 for (int j = 0; j < size; j++)
9275 if (j != i && rtx_equal_p (move[j].src, move[i].dst))
9276 {
9277 /* The dst of move i is the src of move j. */
9278 move[i].links = j;
9279 break;
9280 }
9281
9282 blocked = -1;
9283 moves = 0;
9284 /* Go through move list and perform non-conflicting moves. As each
9285 non-overlapping move is made, it may remove other conflicts
9286 so the process is repeated until no conflicts remain. */
9287 do
9288 {
9289 blocked = -1;
9290 moves = 0;
9291 /* Emit move where dst is not also a src or we have used that
9292 src already. */
9293 for (int i = 0; i < size; i++)
9294 if (move[i].src != NULL_RTX)
9295 {
9296 if (move[i].links == -1
9297 || move[move[i].links].src == NULL_RTX)
9298 {
9299 moves++;
9300 /* Ignore NOP moves to self. */
9301 if (!rtx_equal_p (move[i].dst, move[i].src))
9302 emit_move_insn (move[i].dst, move[i].src);
9303
9304 /* Remove conflict from list. */
9305 move[i].src = NULL_RTX;
9306 }
9307 else
9308 blocked = i;
9309 }
9310
9311 /* Check for deadlock. This is when no moves occurred and we have
9312 at least one blocked move. */
9313 if (moves == 0 && blocked != -1)
9314 {
9315 /* Need to use scratch register to break deadlock.
9316 Add move to put dst of blocked move into scratch.
9317 When this move occurs, it will break chain deadlock.
9318 The scratch register is substituted for real move. */
9319
9320 gcc_assert (SCRATCH != GET_CODE (scratch));
9321
9322 move[size].src = move[blocked].dst;
9323 move[size].dst = scratch;
9324 /* Scratch move is never blocked. */
9325 move[size].links = -1;
9326 /* Make sure we have valid link. */
9327 gcc_assert (move[blocked].links != -1);
9328 /* Replace src of blocking move with scratch reg. */
9329 move[move[blocked].links].src = scratch;
9330 /* Make dependent on scratch move occurring. */
9331 move[blocked].links = size;
9332 size=size+1;
9333 }
9334 }
9335 while (blocked != -1);
9336 }
9337 return true;
9338 }
9339
9340
9341 /* Worker function for `ADJUST_INSN_LENGTH'. */
9342 /* Modifies the length assigned to instruction INSN
9343 LEN is the initially computed length of the insn. */
9344
9345 int
avr_adjust_insn_length(rtx_insn * insn,int len)9346 avr_adjust_insn_length (rtx_insn *insn, int len)
9347 {
9348 rtx *op = recog_data.operand;
9349 enum attr_adjust_len adjust_len;
9350
9351 /* As we pretend jump tables in .text, fix branch offsets crossing jump
9352 tables now. */
9353
9354 if (JUMP_TABLE_DATA_P (insn))
9355 return 0;
9356
9357 /* Some complex insns don't need length adjustment and therefore
9358 the length need not/must not be adjusted for these insns.
9359 It is easier to state this in an insn attribute "adjust_len" than
9360 to clutter up code here... */
9361
9362 if (!NONDEBUG_INSN_P (insn) || recog_memoized (insn) == -1)
9363 {
9364 return len;
9365 }
9366
9367 /* Read from insn attribute "adjust_len" if/how length is to be adjusted. */
9368
9369 adjust_len = get_attr_adjust_len (insn);
9370
9371 if (adjust_len == ADJUST_LEN_NO)
9372 {
9373 /* Nothing to adjust: The length from attribute "length" is fine.
9374 This is the default. */
9375
9376 return len;
9377 }
9378
9379 /* Extract insn's operands. */
9380
9381 extract_constrain_insn_cached (insn);
9382
9383 /* Dispatch to right function. */
9384
9385 switch (adjust_len)
9386 {
9387 case ADJUST_LEN_RELOAD_IN16: output_reload_inhi (op, op[2], &len); break;
9388 case ADJUST_LEN_RELOAD_IN24: avr_out_reload_inpsi (op, op[2], &len); break;
9389 case ADJUST_LEN_RELOAD_IN32: output_reload_insisf (op, op[2], &len); break;
9390
9391 case ADJUST_LEN_OUT_BITOP: avr_out_bitop (insn, op, &len); break;
9392
9393 case ADJUST_LEN_PLUS: avr_out_plus (insn, op, &len); break;
9394 case ADJUST_LEN_ADDTO_SP: avr_out_addto_sp (op, &len); break;
9395
9396 case ADJUST_LEN_MOV8: output_movqi (insn, op, &len); break;
9397 case ADJUST_LEN_MOV16: output_movhi (insn, op, &len); break;
9398 case ADJUST_LEN_MOV24: avr_out_movpsi (insn, op, &len); break;
9399 case ADJUST_LEN_MOV32: output_movsisf (insn, op, &len); break;
9400 case ADJUST_LEN_CPYMEM: avr_out_cpymem (insn, op, &len); break;
9401 case ADJUST_LEN_XLOAD: avr_out_xload (insn, op, &len); break;
9402 case ADJUST_LEN_SEXT: avr_out_sign_extend (insn, op, &len); break;
9403
9404 case ADJUST_LEN_SFRACT: avr_out_fract (insn, op, true, &len); break;
9405 case ADJUST_LEN_UFRACT: avr_out_fract (insn, op, false, &len); break;
9406 case ADJUST_LEN_ROUND: avr_out_round (insn, op, &len); break;
9407
9408 case ADJUST_LEN_TSTHI: avr_out_tsthi (insn, op, &len); break;
9409 case ADJUST_LEN_TSTPSI: avr_out_tstpsi (insn, op, &len); break;
9410 case ADJUST_LEN_TSTSI: avr_out_tstsi (insn, op, &len); break;
9411 case ADJUST_LEN_COMPARE: avr_out_compare (insn, op, &len); break;
9412 case ADJUST_LEN_COMPARE64: avr_out_compare64 (insn, op, &len); break;
9413
9414 case ADJUST_LEN_LSHRQI: lshrqi3_out (insn, op, &len); break;
9415 case ADJUST_LEN_LSHRHI: lshrhi3_out (insn, op, &len); break;
9416 case ADJUST_LEN_LSHRSI: lshrsi3_out (insn, op, &len); break;
9417
9418 case ADJUST_LEN_ASHRQI: ashrqi3_out (insn, op, &len); break;
9419 case ADJUST_LEN_ASHRHI: ashrhi3_out (insn, op, &len); break;
9420 case ADJUST_LEN_ASHRSI: ashrsi3_out (insn, op, &len); break;
9421
9422 case ADJUST_LEN_ASHLQI: ashlqi3_out (insn, op, &len); break;
9423 case ADJUST_LEN_ASHLHI: ashlhi3_out (insn, op, &len); break;
9424 case ADJUST_LEN_ASHLSI: ashlsi3_out (insn, op, &len); break;
9425
9426 case ADJUST_LEN_ASHLPSI: avr_out_ashlpsi3 (insn, op, &len); break;
9427 case ADJUST_LEN_ASHRPSI: avr_out_ashrpsi3 (insn, op, &len); break;
9428 case ADJUST_LEN_LSHRPSI: avr_out_lshrpsi3 (insn, op, &len); break;
9429
9430 case ADJUST_LEN_CALL: len = AVR_HAVE_JMP_CALL ? 2 : 1; break;
9431
9432 case ADJUST_LEN_INSERT_BITS: avr_out_insert_bits (op, &len); break;
9433
9434 case ADJUST_LEN_INSV_NOTBIT:
9435 avr_out_insert_notbit (insn, op, NULL_RTX, &len);
9436 break;
9437 case ADJUST_LEN_INSV_NOTBIT_0:
9438 avr_out_insert_notbit (insn, op, const0_rtx, &len);
9439 break;
9440 case ADJUST_LEN_INSV_NOTBIT_7:
9441 avr_out_insert_notbit (insn, op, GEN_INT (7), &len);
9442 break;
9443
9444 default:
9445 gcc_unreachable();
9446 }
9447
9448 return len;
9449 }
9450
9451 /* Return nonzero if register REG dead after INSN. */
9452
9453 int
reg_unused_after(rtx_insn * insn,rtx reg)9454 reg_unused_after (rtx_insn *insn, rtx reg)
9455 {
9456 return (dead_or_set_p (insn, reg)
9457 || (REG_P (reg) && _reg_unused_after (insn, reg)));
9458 }
9459
9460 /* Return nonzero if REG is not used after INSN.
9461 We assume REG is a reload reg, and therefore does
9462 not live past labels. It may live past calls or jumps though. */
9463
9464 int
_reg_unused_after(rtx_insn * insn,rtx reg)9465 _reg_unused_after (rtx_insn *insn, rtx reg)
9466 {
9467 enum rtx_code code;
9468 rtx set;
9469
9470 /* If the reg is set by this instruction, then it is safe for our
9471 case. Disregard the case where this is a store to memory, since
9472 we are checking a register used in the store address. */
9473 set = single_set (insn);
9474 if (set && !MEM_P (SET_DEST (set))
9475 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
9476 return 1;
9477
9478 while ((insn = NEXT_INSN (insn)))
9479 {
9480 rtx set;
9481 code = GET_CODE (insn);
9482
9483 #if 0
9484 /* If this is a label that existed before reload, then the register
9485 if dead here. However, if this is a label added by reorg, then
9486 the register may still be live here. We can't tell the difference,
9487 so we just ignore labels completely. */
9488 if (code == CODE_LABEL)
9489 return 1;
9490 /* else */
9491 #endif
9492
9493 if (!INSN_P (insn))
9494 continue;
9495
9496 if (code == JUMP_INSN)
9497 return 0;
9498
9499 /* If this is a sequence, we must handle them all at once.
9500 We could have for instance a call that sets the target register,
9501 and an insn in a delay slot that uses the register. In this case,
9502 we must return 0. */
9503 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
9504 {
9505 rtx_sequence *seq = as_a <rtx_sequence *> (PATTERN (insn));
9506 int retval = 0;
9507
9508 for (int i = 0; i < seq->len (); i++)
9509 {
9510 rtx_insn *this_insn = seq->insn (i);
9511 rtx set = single_set (this_insn);
9512
9513 if (CALL_P (this_insn))
9514 code = CALL_INSN;
9515 else if (JUMP_P (this_insn))
9516 {
9517 if (INSN_ANNULLED_BRANCH_P (this_insn))
9518 return 0;
9519 code = JUMP_INSN;
9520 }
9521
9522 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
9523 return 0;
9524 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
9525 {
9526 if (!MEM_P (SET_DEST (set)))
9527 retval = 1;
9528 else
9529 return 0;
9530 }
9531 if (set == 0
9532 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
9533 return 0;
9534 }
9535 if (retval == 1)
9536 return 1;
9537 else if (code == JUMP_INSN)
9538 return 0;
9539 }
9540
9541 if (code == CALL_INSN)
9542 {
9543 rtx tem;
9544 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
9545 if (GET_CODE (XEXP (tem, 0)) == USE
9546 && REG_P (XEXP (XEXP (tem, 0), 0))
9547 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
9548 return 0;
9549 if (call_used_or_fixed_reg_p (REGNO (reg)))
9550 return 1;
9551 }
9552
9553 set = single_set (insn);
9554
9555 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
9556 return 0;
9557 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
9558 return !MEM_P (SET_DEST (set));
9559 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
9560 return 0;
9561 }
9562 return 1;
9563 }
9564
9565
9566 /* Implement `TARGET_ASM_INTEGER'. */
9567 /* Target hook for assembling integer objects. The AVR version needs
9568 special handling for references to certain labels. */
9569
9570 static bool
avr_assemble_integer(rtx x,unsigned int size,int aligned_p)9571 avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
9572 {
9573 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
9574 && text_segment_operand (x, VOIDmode))
9575 {
9576 fputs ("\t.word\tgs(", asm_out_file);
9577 output_addr_const (asm_out_file, x);
9578 fputs (")\n", asm_out_file);
9579
9580 return true;
9581 }
9582 else if (GET_MODE (x) == PSImode)
9583 {
9584 /* This needs binutils 2.23+, see PR binutils/13503 */
9585
9586 fputs ("\t.byte\tlo8(", asm_out_file);
9587 output_addr_const (asm_out_file, x);
9588 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
9589
9590 fputs ("\t.byte\thi8(", asm_out_file);
9591 output_addr_const (asm_out_file, x);
9592 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
9593
9594 fputs ("\t.byte\thh8(", asm_out_file);
9595 output_addr_const (asm_out_file, x);
9596 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
9597
9598 return true;
9599 }
9600 else if (CONST_FIXED_P (x))
9601 {
9602 /* varasm fails to handle big fixed modes that don't fit in hwi. */
9603
9604 for (unsigned n = 0; n < size; n++)
9605 {
9606 rtx xn = simplify_gen_subreg (QImode, x, GET_MODE (x), n);
9607 default_assemble_integer (xn, 1, aligned_p);
9608 }
9609
9610 return true;
9611 }
9612
9613 if (AVR_TINY
9614 && avr_address_tiny_pm_p (x))
9615 {
9616 x = plus_constant (Pmode, x, avr_arch->flash_pm_offset);
9617 }
9618
9619 return default_assemble_integer (x, size, aligned_p);
9620 }
9621
9622
9623 /* Implement `TARGET_CLASS_LIKELY_SPILLED_P'. */
9624 /* Return value is nonzero if pseudos that have been
9625 assigned to registers of class CLASS would likely be spilled
9626 because registers of CLASS are needed for spill registers. */
9627
9628 static bool
avr_class_likely_spilled_p(reg_class_t c)9629 avr_class_likely_spilled_p (reg_class_t c)
9630 {
9631 return (c != ALL_REGS &&
9632 (AVR_TINY ? 1 : c != ADDW_REGS));
9633 }
9634
9635
9636 /* Valid attributes:
9637 progmem - Put data to program memory.
9638 signal - Make a function to be hardware interrupt.
9639 After function prologue interrupts remain disabled.
9640 interrupt - Make a function to be hardware interrupt. Before function
9641 prologue interrupts are enabled by means of SEI.
9642 naked - Don't generate function prologue/epilogue and RET
9643 instruction. */
9644
9645 /* Handle a "progmem" attribute; arguments as in
9646 struct attribute_spec.handler. */
9647
9648 static tree
avr_handle_progmem_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)9649 avr_handle_progmem_attribute (tree *node, tree name,
9650 tree args ATTRIBUTE_UNUSED,
9651 int flags ATTRIBUTE_UNUSED,
9652 bool *no_add_attrs)
9653 {
9654 if (DECL_P (*node))
9655 {
9656 if (TREE_CODE (*node) == TYPE_DECL)
9657 {
9658 /* This is really a decl attribute, not a type attribute,
9659 but try to handle it for GCC 3.0 backwards compatibility. */
9660
9661 tree type = TREE_TYPE (*node);
9662 tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
9663 tree newtype = build_type_attribute_variant (type, attr);
9664
9665 TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
9666 TREE_TYPE (*node) = newtype;
9667 *no_add_attrs = true;
9668 }
9669 else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
9670 {
9671 *no_add_attrs = false;
9672 }
9673 else
9674 {
9675 warning (OPT_Wattributes, "%qE attribute ignored",
9676 name);
9677 *no_add_attrs = true;
9678 }
9679 }
9680
9681 return NULL_TREE;
9682 }
9683
9684 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
9685 struct attribute_spec.handler. */
9686
9687 static tree
avr_handle_fndecl_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)9688 avr_handle_fndecl_attribute (tree *node, tree name,
9689 tree args ATTRIBUTE_UNUSED,
9690 int flags ATTRIBUTE_UNUSED,
9691 bool *no_add_attrs)
9692 {
9693 if (TREE_CODE (*node) != FUNCTION_DECL)
9694 {
9695 warning (OPT_Wattributes, "%qE attribute only applies to functions",
9696 name);
9697 *no_add_attrs = true;
9698 }
9699
9700 return NULL_TREE;
9701 }
9702
9703 static tree
avr_handle_fntype_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)9704 avr_handle_fntype_attribute (tree *node, tree name,
9705 tree args ATTRIBUTE_UNUSED,
9706 int flags ATTRIBUTE_UNUSED,
9707 bool *no_add_attrs)
9708 {
9709 if (TREE_CODE (*node) != FUNCTION_TYPE)
9710 {
9711 warning (OPT_Wattributes, "%qE attribute only applies to functions",
9712 name);
9713 *no_add_attrs = true;
9714 }
9715
9716 return NULL_TREE;
9717 }
9718
9719 static tree
avr_handle_absdata_attribute(tree * node,tree name,tree,int,bool * no_add)9720 avr_handle_absdata_attribute (tree *node, tree name, tree /* args */,
9721 int /* flags */, bool *no_add)
9722 {
9723 location_t loc = DECL_SOURCE_LOCATION (*node);
9724
9725 if (AVR_TINY)
9726 {
9727 if (TREE_CODE (*node) != VAR_DECL
9728 || (!TREE_STATIC (*node) && !DECL_EXTERNAL (*node)))
9729 {
9730 warning_at (loc, OPT_Wattributes, "%qE attribute only applies to"
9731 " variables in static storage", name);
9732 *no_add = true;
9733 }
9734 }
9735 else
9736 {
9737 warning_at (loc, OPT_Wattributes, "%qE attribute only supported"
9738 " for reduced Tiny cores", name);
9739 *no_add = true;
9740 }
9741
9742 return NULL_TREE;
9743 }
9744
9745 static tree
avr_handle_addr_attribute(tree * node,tree name,tree args,int flags ATTRIBUTE_UNUSED,bool * no_add)9746 avr_handle_addr_attribute (tree *node, tree name, tree args,
9747 int flags ATTRIBUTE_UNUSED, bool *no_add)
9748 {
9749 bool io_p = (strncmp (IDENTIFIER_POINTER (name), "io", 2) == 0);
9750 location_t loc = DECL_SOURCE_LOCATION (*node);
9751
9752 if (!VAR_P (*node))
9753 {
9754 warning_at (loc, OPT_Wattributes, "%qE attribute only applies to "
9755 "variables", name);
9756 *no_add = true;
9757 return NULL_TREE;
9758 }
9759
9760 if (args != NULL_TREE)
9761 {
9762 if (TREE_CODE (TREE_VALUE (args)) == NON_LVALUE_EXPR)
9763 TREE_VALUE (args) = TREE_OPERAND (TREE_VALUE (args), 0);
9764 tree arg = TREE_VALUE (args);
9765 if (TREE_CODE (arg) != INTEGER_CST)
9766 {
9767 warning_at (loc, OPT_Wattributes, "%qE attribute allows only an "
9768 "integer constant argument", name);
9769 *no_add = true;
9770 }
9771 else if (io_p
9772 && (!tree_fits_shwi_p (arg)
9773 || !(strcmp (IDENTIFIER_POINTER (name), "io_low") == 0
9774 ? low_io_address_operand : io_address_operand)
9775 (GEN_INT (TREE_INT_CST_LOW (arg)), QImode)))
9776 {
9777 warning_at (loc, OPT_Wattributes, "%qE attribute address "
9778 "out of range", name);
9779 *no_add = true;
9780 }
9781 else
9782 {
9783 tree attribs = DECL_ATTRIBUTES (*node);
9784 const char *names[] = { "io", "io_low", "address", NULL };
9785 for (const char **p = names; *p; p++)
9786 {
9787 tree other = lookup_attribute (*p, attribs);
9788 if (other && TREE_VALUE (other))
9789 {
9790 warning_at (loc, OPT_Wattributes,
9791 "both %s and %qE attribute provide address",
9792 *p, name);
9793 *no_add = true;
9794 break;
9795 }
9796 }
9797 }
9798 }
9799
9800 if (*no_add == false && io_p && !TREE_THIS_VOLATILE (*node))
9801 warning_at (loc, OPT_Wattributes, "%qE attribute on non-volatile variable",
9802 name);
9803
9804 return NULL_TREE;
9805 }
9806
9807 rtx
avr_eval_addr_attrib(rtx x)9808 avr_eval_addr_attrib (rtx x)
9809 {
9810 if (SYMBOL_REF_P (x)
9811 && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_ADDRESS))
9812 {
9813 tree decl = SYMBOL_REF_DECL (x);
9814 tree attr = NULL_TREE;
9815
9816 if (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO)
9817 {
9818 attr = lookup_attribute ("io", DECL_ATTRIBUTES (decl));
9819 if (!attr || !TREE_VALUE (attr))
9820 attr = lookup_attribute ("io_low", DECL_ATTRIBUTES (decl));
9821 gcc_assert (attr);
9822 }
9823 if (!attr || !TREE_VALUE (attr))
9824 attr = lookup_attribute ("address", DECL_ATTRIBUTES (decl));
9825 gcc_assert (attr && TREE_VALUE (attr) && TREE_VALUE (TREE_VALUE (attr)));
9826 return GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))));
9827 }
9828 return x;
9829 }
9830
9831
9832 /* AVR attributes. */
9833 static const struct attribute_spec avr_attribute_table[] =
9834 {
9835 /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
9836 affects_type_identity, handler, exclude } */
9837 { "progmem", 0, 0, false, false, false, false,
9838 avr_handle_progmem_attribute, NULL },
9839 { "signal", 0, 0, true, false, false, false,
9840 avr_handle_fndecl_attribute, NULL },
9841 { "interrupt", 0, 0, true, false, false, false,
9842 avr_handle_fndecl_attribute, NULL },
9843 { "no_gccisr", 0, 0, true, false, false, false,
9844 avr_handle_fndecl_attribute, NULL },
9845 { "naked", 0, 0, false, true, true, false,
9846 avr_handle_fntype_attribute, NULL },
9847 { "OS_task", 0, 0, false, true, true, false,
9848 avr_handle_fntype_attribute, NULL },
9849 { "OS_main", 0, 0, false, true, true, false,
9850 avr_handle_fntype_attribute, NULL },
9851 { "io", 0, 1, true, false, false, false,
9852 avr_handle_addr_attribute, NULL },
9853 { "io_low", 0, 1, true, false, false, false,
9854 avr_handle_addr_attribute, NULL },
9855 { "address", 1, 1, true, false, false, false,
9856 avr_handle_addr_attribute, NULL },
9857 { "absdata", 0, 0, true, false, false, false,
9858 avr_handle_absdata_attribute, NULL },
9859 { NULL, 0, 0, false, false, false, false, NULL, NULL }
9860 };
9861
9862
9863 /* Return true if we support address space AS for the architecture in effect
9864 and false, otherwise. If LOC is not UNKNOWN_LOCATION then also issue
9865 a respective error. */
9866
9867 bool
avr_addr_space_supported_p(addr_space_t as,location_t loc)9868 avr_addr_space_supported_p (addr_space_t as, location_t loc)
9869 {
9870 if (AVR_TINY)
9871 {
9872 if (loc != UNKNOWN_LOCATION)
9873 error_at (loc, "address spaces are not supported for reduced "
9874 "Tiny devices");
9875 return false;
9876 }
9877 else if (avr_addrspace[as].segment >= avr_n_flash)
9878 {
9879 if (loc != UNKNOWN_LOCATION)
9880 error_at (loc, "address space %qs not supported for devices with "
9881 "flash size up to %d KiB", avr_addrspace[as].name,
9882 64 * avr_n_flash);
9883 return false;
9884 }
9885
9886 return true;
9887 }
9888
9889
9890 /* Implement `TARGET_ADDR_SPACE_DIAGNOSE_USAGE'. */
9891
9892 static void
avr_addr_space_diagnose_usage(addr_space_t as,location_t loc)9893 avr_addr_space_diagnose_usage (addr_space_t as, location_t loc)
9894 {
9895 (void) avr_addr_space_supported_p (as, loc);
9896 }
9897
9898
9899 /* Look if DECL shall be placed in program memory space by
9900 means of attribute `progmem' or some address-space qualifier.
9901 Return non-zero if DECL is data that must end up in Flash and
9902 zero if the data lives in RAM (.bss, .data, .rodata, ...).
9903
9904 Return 2 if DECL is located in 24-bit flash address-space
9905 Return 1 if DECL is located in 16-bit flash address-space
9906 Return -1 if attribute `progmem' occurs in DECL or ATTRIBUTES
9907 Return 0 otherwise */
9908
9909 int
avr_progmem_p(tree decl,tree attributes)9910 avr_progmem_p (tree decl, tree attributes)
9911 {
9912 tree a;
9913
9914 if (TREE_CODE (decl) != VAR_DECL)
9915 return 0;
9916
9917 if (avr_decl_memx_p (decl))
9918 return 2;
9919
9920 if (avr_decl_flash_p (decl))
9921 return 1;
9922
9923 if (NULL_TREE
9924 != lookup_attribute ("progmem", attributes))
9925 return -1;
9926
9927 a = decl;
9928
9929 do
9930 a = TREE_TYPE(a);
9931 while (TREE_CODE (a) == ARRAY_TYPE);
9932
9933 if (a == error_mark_node)
9934 return 0;
9935
9936 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
9937 return -1;
9938
9939 return 0;
9940 }
9941
9942
9943 /* Return true if DECL has attribute `absdata' set. This function should
9944 only be used for AVR_TINY. */
9945
9946 static bool
avr_decl_absdata_p(tree decl,tree attributes)9947 avr_decl_absdata_p (tree decl, tree attributes)
9948 {
9949 return (TREE_CODE (decl) == VAR_DECL
9950 && NULL_TREE != lookup_attribute ("absdata", attributes));
9951 }
9952
9953
9954 /* Scan type TYP for pointer references to address space ASn.
9955 Return ADDR_SPACE_GENERIC (i.e. 0) if all pointers targeting
9956 the AS are also declared to be CONST.
9957 Otherwise, return the respective address space, i.e. a value != 0. */
9958
9959 static addr_space_t
avr_nonconst_pointer_addrspace(tree typ)9960 avr_nonconst_pointer_addrspace (tree typ)
9961 {
9962 while (ARRAY_TYPE == TREE_CODE (typ))
9963 typ = TREE_TYPE (typ);
9964
9965 if (POINTER_TYPE_P (typ))
9966 {
9967 addr_space_t as;
9968 tree target = TREE_TYPE (typ);
9969
9970 /* Pointer to function: Test the function's return type. */
9971
9972 if (FUNCTION_TYPE == TREE_CODE (target))
9973 return avr_nonconst_pointer_addrspace (TREE_TYPE (target));
9974
9975 /* "Ordinary" pointers... */
9976
9977 while (TREE_CODE (target) == ARRAY_TYPE)
9978 target = TREE_TYPE (target);
9979
9980 /* Pointers to non-generic address space must be const. */
9981
9982 as = TYPE_ADDR_SPACE (target);
9983
9984 if (!ADDR_SPACE_GENERIC_P (as)
9985 && !TYPE_READONLY (target)
9986 && avr_addr_space_supported_p (as))
9987 {
9988 return as;
9989 }
9990
9991 /* Scan pointer's target type. */
9992
9993 return avr_nonconst_pointer_addrspace (target);
9994 }
9995
9996 return ADDR_SPACE_GENERIC;
9997 }
9998
9999
10000 /* Sanity check NODE so that all pointers targeting non-generic address spaces
10001 go along with CONST qualifier. Writing to these address spaces should
10002 be detected and complained about as early as possible. */
10003
10004 static bool
avr_pgm_check_var_decl(tree node)10005 avr_pgm_check_var_decl (tree node)
10006 {
10007 const char *reason = NULL;
10008
10009 addr_space_t as = ADDR_SPACE_GENERIC;
10010
10011 gcc_assert (as == 0);
10012
10013 if (avr_log.progmem)
10014 avr_edump ("%?: %t\n", node);
10015
10016 switch (TREE_CODE (node))
10017 {
10018 default:
10019 break;
10020
10021 case VAR_DECL:
10022 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
10023 reason = _("variable");
10024 break;
10025
10026 case PARM_DECL:
10027 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
10028 reason = _("function parameter");
10029 break;
10030
10031 case FIELD_DECL:
10032 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
10033 reason = _("structure field");
10034 break;
10035
10036 case FUNCTION_DECL:
10037 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (TREE_TYPE (node))),
10038 as)
10039 reason = _("return type of function");
10040 break;
10041
10042 case POINTER_TYPE:
10043 if (as = avr_nonconst_pointer_addrspace (node), as)
10044 reason = _("pointer");
10045 break;
10046 }
10047
10048 if (reason)
10049 {
10050 if (TYPE_P (node))
10051 error ("pointer targeting address space %qs must be const in %qT",
10052 avr_addrspace[as].name, node);
10053 else
10054 error ("pointer targeting address space %qs must be const"
10055 " in %s %q+D",
10056 avr_addrspace[as].name, reason, node);
10057 }
10058
10059 return reason == NULL;
10060 }
10061
10062
10063 /* Implement `TARGET_INSERT_ATTRIBUTES'. */
10064
10065 static void
avr_insert_attributes(tree node,tree * attributes)10066 avr_insert_attributes (tree node, tree *attributes)
10067 {
10068 avr_pgm_check_var_decl (node);
10069
10070 if (TARGET_MAIN_IS_OS_TASK
10071 && TREE_CODE (node) == FUNCTION_DECL
10072 && MAIN_NAME_P (DECL_NAME (node))
10073 // FIXME: We'd like to also test `flag_hosted' which is only
10074 // available in the C-ish fronts, hence no such test for now.
10075 // Instead, we test the return type of "main" which is not exactly
10076 // the same but good enough.
10077 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (node)))
10078 && NULL == lookup_attribute ("OS_task", *attributes))
10079 {
10080 *attributes = tree_cons (get_identifier ("OS_task"),
10081 NULL, *attributes);
10082 }
10083
10084 /* Add the section attribute if the variable is in progmem. */
10085
10086 if (TREE_CODE (node) == VAR_DECL
10087 && (TREE_STATIC (node) || DECL_EXTERNAL (node))
10088 && avr_progmem_p (node, *attributes))
10089 {
10090 addr_space_t as;
10091 tree node0 = node;
10092
10093 /* For C++, we have to peel arrays in order to get correct
10094 determination of readonlyness. */
10095
10096 do
10097 node0 = TREE_TYPE (node0);
10098 while (TREE_CODE (node0) == ARRAY_TYPE);
10099
10100 if (error_mark_node == node0)
10101 return;
10102
10103 as = TYPE_ADDR_SPACE (TREE_TYPE (node));
10104
10105 if (!TYPE_READONLY (node0)
10106 && !TREE_READONLY (node))
10107 {
10108 const char *reason = "__attribute__((progmem))";
10109
10110 if (!ADDR_SPACE_GENERIC_P (as))
10111 reason = avr_addrspace[as].name;
10112
10113 if (avr_log.progmem)
10114 avr_edump ("\n%?: %t\n%t\n", node, node0);
10115
10116 error ("variable %q+D must be const in order to be put into"
10117 " read-only section by means of %qs", node, reason);
10118 }
10119 }
10120 }
10121
10122
10123 /* Implement `ASM_OUTPUT_ALIGNED_DECL_LOCAL'. */
10124 /* Implement `ASM_OUTPUT_ALIGNED_DECL_COMMON'. */
10125 /* Track need of __do_clear_bss. */
10126
10127 void
avr_asm_output_aligned_decl_common(FILE * stream,tree decl,const char * name,unsigned HOST_WIDE_INT size,unsigned int align,bool local_p)10128 avr_asm_output_aligned_decl_common (FILE * stream,
10129 tree decl,
10130 const char *name,
10131 unsigned HOST_WIDE_INT size,
10132 unsigned int align, bool local_p)
10133 {
10134 rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
10135 rtx symbol;
10136
10137 if (mem != NULL_RTX && MEM_P (mem)
10138 && SYMBOL_REF_P ((symbol = XEXP (mem, 0)))
10139 && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
10140 {
10141 if (!local_p)
10142 {
10143 fprintf (stream, "\t.globl\t");
10144 assemble_name (stream, name);
10145 fprintf (stream, "\n");
10146 }
10147 if (SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS)
10148 {
10149 assemble_name (stream, name);
10150 fprintf (stream, " = %ld\n",
10151 (long) INTVAL (avr_eval_addr_attrib (symbol)));
10152 }
10153 else if (local_p)
10154 error_at (DECL_SOURCE_LOCATION (decl),
10155 "static IO declaration for %q+D needs an address", decl);
10156 return;
10157 }
10158
10159 /* __gnu_lto_slim is just a marker for the linker injected by toplev.c.
10160 There is no need to trigger __do_clear_bss code for them. */
10161
10162 if (!STR_PREFIX_P (name, "__gnu_lto"))
10163 avr_need_clear_bss_p = true;
10164
10165 if (local_p)
10166 ASM_OUTPUT_ALIGNED_LOCAL (stream, name, size, align);
10167 else
10168 ASM_OUTPUT_ALIGNED_COMMON (stream, name, size, align);
10169 }
10170
10171 void
avr_asm_asm_output_aligned_bss(FILE * file,tree decl,const char * name,unsigned HOST_WIDE_INT size,int align,void (* default_func)(FILE *,tree,const char *,unsigned HOST_WIDE_INT,int))10172 avr_asm_asm_output_aligned_bss (FILE *file, tree decl, const char *name,
10173 unsigned HOST_WIDE_INT size, int align,
10174 void (*default_func)
10175 (FILE *, tree, const char *,
10176 unsigned HOST_WIDE_INT, int))
10177 {
10178 rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
10179 rtx symbol;
10180
10181 if (mem != NULL_RTX && MEM_P (mem)
10182 && SYMBOL_REF_P ((symbol = XEXP (mem, 0)))
10183 && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
10184 {
10185 if (!(SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS))
10186 error_at (DECL_SOURCE_LOCATION (decl),
10187 "IO definition for %q+D needs an address", decl);
10188 avr_asm_output_aligned_decl_common (file, decl, name, size, align, false);
10189 }
10190 else
10191 default_func (file, decl, name, size, align);
10192 }
10193
10194
10195 /* Unnamed section callback for data_section
10196 to track need of __do_copy_data. */
10197
10198 static void
avr_output_data_section_asm_op(const void * data)10199 avr_output_data_section_asm_op (const void *data)
10200 {
10201 avr_need_copy_data_p = true;
10202
10203 /* Dispatch to default. */
10204 output_section_asm_op (data);
10205 }
10206
10207
10208 /* Unnamed section callback for bss_section
10209 to track need of __do_clear_bss. */
10210
10211 static void
avr_output_bss_section_asm_op(const void * data)10212 avr_output_bss_section_asm_op (const void *data)
10213 {
10214 avr_need_clear_bss_p = true;
10215
10216 /* Dispatch to default. */
10217 output_section_asm_op (data);
10218 }
10219
10220
10221 /* Unnamed section callback for progmem*.data sections. */
10222
10223 static void
avr_output_progmem_section_asm_op(const void * data)10224 avr_output_progmem_section_asm_op (const void *data)
10225 {
10226 fprintf (asm_out_file, "\t.section\t%s,\"a\",@progbits\n",
10227 (const char*) data);
10228 }
10229
10230
10231 /* Implement `TARGET_ASM_INIT_SECTIONS'. */
10232
10233 static void
avr_asm_init_sections(void)10234 avr_asm_init_sections (void)
10235 {
10236 /* Override section callbacks to keep track of `avr_need_clear_bss_p'
10237 resp. `avr_need_copy_data_p'. If flash is not mapped to RAM then
10238 we have also to track .rodata because it is located in RAM then. */
10239
10240 #if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
10241 if (avr_arch->flash_pm_offset == 0)
10242 #endif
10243 readonly_data_section->unnamed.callback = avr_output_data_section_asm_op;
10244 data_section->unnamed.callback = avr_output_data_section_asm_op;
10245 bss_section->unnamed.callback = avr_output_bss_section_asm_op;
10246 }
10247
10248
10249 /* Implement `TARGET_ASM_NAMED_SECTION'. */
10250 /* Track need of __do_clear_bss, __do_copy_data for named sections. */
10251
10252 static void
avr_asm_named_section(const char * name,unsigned int flags,tree decl)10253 avr_asm_named_section (const char *name, unsigned int flags, tree decl)
10254 {
10255 if (flags & AVR_SECTION_PROGMEM)
10256 {
10257 addr_space_t as = (flags & AVR_SECTION_PROGMEM) / SECTION_MACH_DEP;
10258 const char *old_prefix = ".rodata";
10259 const char *new_prefix = avr_addrspace[as].section_name;
10260
10261 if (STR_PREFIX_P (name, old_prefix))
10262 {
10263 const char *sname = ACONCAT ((new_prefix,
10264 name + strlen (old_prefix), NULL));
10265 default_elf_asm_named_section (sname, flags, decl);
10266 return;
10267 }
10268
10269 default_elf_asm_named_section (new_prefix, flags, decl);
10270 return;
10271 }
10272
10273 if (!avr_need_copy_data_p)
10274 avr_need_copy_data_p = (STR_PREFIX_P (name, ".data")
10275 || STR_PREFIX_P (name, ".gnu.linkonce.d"));
10276
10277 if (!avr_need_copy_data_p
10278 #if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
10279 && avr_arch->flash_pm_offset == 0
10280 #endif
10281 )
10282 avr_need_copy_data_p = (STR_PREFIX_P (name, ".rodata")
10283 || STR_PREFIX_P (name, ".gnu.linkonce.r"));
10284
10285 if (!avr_need_clear_bss_p)
10286 avr_need_clear_bss_p = STR_PREFIX_P (name, ".bss");
10287
10288 default_elf_asm_named_section (name, flags, decl);
10289 }
10290
10291
10292 /* Implement `TARGET_SECTION_TYPE_FLAGS'. */
10293
10294 static unsigned int
avr_section_type_flags(tree decl,const char * name,int reloc)10295 avr_section_type_flags (tree decl, const char *name, int reloc)
10296 {
10297 unsigned int flags = default_section_type_flags (decl, name, reloc);
10298
10299 if (STR_PREFIX_P (name, ".noinit"))
10300 {
10301 if (decl && TREE_CODE (decl) == VAR_DECL
10302 && DECL_INITIAL (decl) == NULL_TREE)
10303 flags |= SECTION_BSS; /* @nobits */
10304 else
10305 warning (0, "only uninitialized variables can be placed in the "
10306 ".noinit section");
10307 }
10308
10309 if (decl && DECL_P (decl)
10310 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
10311 {
10312 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
10313
10314 /* Attribute progmem puts data in generic address space.
10315 Set section flags as if it was in __flash to get the right
10316 section prefix in the remainder. */
10317
10318 if (ADDR_SPACE_GENERIC_P (as))
10319 as = ADDR_SPACE_FLASH;
10320
10321 flags |= as * SECTION_MACH_DEP;
10322 flags &= ~SECTION_WRITE;
10323 flags &= ~SECTION_BSS;
10324 }
10325
10326 return flags;
10327 }
10328
10329
10330 /* A helper for the next function. NODE is a decl that is associated with
10331 a symbol. Return TRUE if the respective object may be accessed by LDS.
10332 There might still be other reasons for why LDS is not appropriate.
10333 This function is only appropriate for AVR_TINY. */
10334
10335 static bool
avr_decl_maybe_lds_p(tree node)10336 avr_decl_maybe_lds_p (tree node)
10337 {
10338 if (!node
10339 || TREE_CODE (node) != VAR_DECL
10340 || DECL_SECTION_NAME (node) != NULL)
10341 return false;
10342
10343 /* Don't use LDS for objects that go to .rodata. The current default
10344 linker description file still locates .rodata in RAM, but this is not
10345 a must. A better linker script would just keep .rodata in flash and
10346 add an offset of 0x4000 to the VMA. Hence avoid LDS for such data. */
10347
10348 if (TREE_READONLY (node))
10349 return false;
10350
10351 // C++ requires peeling arrays.
10352
10353 do
10354 node = TREE_TYPE (node);
10355 while (ARRAY_TYPE == TREE_CODE (node));
10356
10357 return (node != error_mark_node
10358 && !TYPE_READONLY (node));
10359 }
10360
10361
10362 /* Implement `TARGET_ENCODE_SECTION_INFO'. */
10363
10364 static void
avr_encode_section_info(tree decl,rtx rtl,int new_decl_p)10365 avr_encode_section_info (tree decl, rtx rtl, int new_decl_p)
10366 {
10367 tree addr_attr = NULL_TREE;
10368
10369 /* In avr_handle_progmem_attribute, DECL_INITIAL is not yet
10370 readily available, see PR34734. So we postpone the warning
10371 about uninitialized data in program memory section until here. */
10372
10373 if (new_decl_p
10374 && decl && DECL_P (decl)
10375 && !DECL_EXTERNAL (decl)
10376 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
10377 {
10378 if (!TREE_READONLY (decl))
10379 {
10380 // This might happen with C++ if stuff needs constructing.
10381 error ("variable %q+D with dynamic initialization put "
10382 "into program memory area", decl);
10383 }
10384 else if (NULL_TREE == DECL_INITIAL (decl))
10385 {
10386 // Don't warn for (implicit) aliases like in PR80462.
10387 tree asmname = DECL_ASSEMBLER_NAME (decl);
10388 varpool_node *node = varpool_node::get_for_asmname (asmname);
10389 bool alias_p = node && node->alias;
10390
10391 if (!alias_p)
10392 warning (OPT_Wuninitialized, "uninitialized variable %q+D put "
10393 "into program memory area", decl);
10394 }
10395 }
10396
10397 default_encode_section_info (decl, rtl, new_decl_p);
10398
10399 if (decl && DECL_P (decl)
10400 && TREE_CODE (decl) != FUNCTION_DECL
10401 && MEM_P (rtl)
10402 && SYMBOL_REF_P (XEXP (rtl, 0)))
10403 {
10404 rtx sym = XEXP (rtl, 0);
10405 tree type = TREE_TYPE (decl);
10406 tree attr = DECL_ATTRIBUTES (decl);
10407 if (type == error_mark_node)
10408 return;
10409
10410 addr_space_t as = TYPE_ADDR_SPACE (type);
10411
10412 /* PSTR strings are in generic space but located in flash:
10413 patch address space. */
10414
10415 if (!AVR_TINY && avr_progmem_p (decl, attr) == -1)
10416 as = ADDR_SPACE_FLASH;
10417
10418 AVR_SYMBOL_SET_ADDR_SPACE (sym, as);
10419
10420 tree io_low_attr = lookup_attribute ("io_low", attr);
10421 tree io_attr = lookup_attribute ("io", attr);
10422
10423 if (io_low_attr
10424 && TREE_VALUE (io_low_attr) && TREE_VALUE (TREE_VALUE (io_low_attr)))
10425 addr_attr = io_attr;
10426 else if (io_attr
10427 && TREE_VALUE (io_attr) && TREE_VALUE (TREE_VALUE (io_attr)))
10428 addr_attr = io_attr;
10429 else
10430 addr_attr = lookup_attribute ("address", attr);
10431 if (io_low_attr
10432 || (io_attr && addr_attr
10433 && low_io_address_operand
10434 (GEN_INT (TREE_INT_CST_LOW
10435 (TREE_VALUE (TREE_VALUE (addr_attr)))), QImode)))
10436 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO_LOW;
10437 if (io_attr || io_low_attr)
10438 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO;
10439 /* If we have an (io) address attribute specification, but the variable
10440 is external, treat the address as only a tentative definition
10441 to be used to determine if an io port is in the lower range, but
10442 don't use the exact value for constant propagation. */
10443 if (addr_attr && !DECL_EXTERNAL (decl))
10444 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_ADDRESS;
10445 }
10446
10447 if (AVR_TINY
10448 && decl
10449 && VAR_DECL == TREE_CODE (decl)
10450 && MEM_P (rtl)
10451 && SYMBOL_REF_P (XEXP (rtl, 0)))
10452 {
10453 rtx sym = XEXP (rtl, 0);
10454 bool progmem_p = avr_progmem_p (decl, DECL_ATTRIBUTES (decl)) == -1;
10455
10456 if (progmem_p)
10457 {
10458 // Tag symbols for addition of 0x4000 (avr_arch->flash_pm_offset).
10459 SYMBOL_REF_FLAGS (sym) |= AVR_SYMBOL_FLAG_TINY_PM;
10460 }
10461
10462 if (avr_decl_absdata_p (decl, DECL_ATTRIBUTES (decl))
10463 || (TARGET_ABSDATA
10464 && !progmem_p
10465 && !addr_attr
10466 && avr_decl_maybe_lds_p (decl))
10467 || (addr_attr
10468 // If addr_attr is non-null, it has an argument. Peek into it.
10469 && TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (addr_attr))) < 0xc0))
10470 {
10471 // May be accessed by LDS / STS.
10472 SYMBOL_REF_FLAGS (sym) |= AVR_SYMBOL_FLAG_TINY_ABSDATA;
10473 }
10474
10475 if (progmem_p
10476 && avr_decl_absdata_p (decl, DECL_ATTRIBUTES (decl)))
10477 {
10478 error ("%q+D has incompatible attributes %qs and %qs",
10479 decl, "progmem", "absdata");
10480 }
10481 }
10482 }
10483
10484
10485 /* Implement `TARGET_ASM_SELECT_SECTION' */
10486
10487 static section *
avr_asm_select_section(tree decl,int reloc,unsigned HOST_WIDE_INT align)10488 avr_asm_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
10489 {
10490 section * sect = default_elf_select_section (decl, reloc, align);
10491
10492 if (decl && DECL_P (decl)
10493 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
10494 {
10495 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
10496
10497 /* __progmem__ goes in generic space but shall be allocated to
10498 .progmem.data */
10499
10500 if (ADDR_SPACE_GENERIC_P (as))
10501 as = ADDR_SPACE_FLASH;
10502
10503 if (sect->common.flags & SECTION_NAMED)
10504 {
10505 const char * name = sect->named.name;
10506 const char * old_prefix = ".rodata";
10507 const char * new_prefix = avr_addrspace[as].section_name;
10508
10509 if (STR_PREFIX_P (name, old_prefix))
10510 {
10511 const char *sname = ACONCAT ((new_prefix,
10512 name + strlen (old_prefix), NULL));
10513 return get_section (sname,
10514 sect->common.flags & ~SECTION_DECLARED,
10515 sect->named.decl);
10516 }
10517 }
10518
10519 if (!progmem_section[as])
10520 {
10521 progmem_section[as]
10522 = get_unnamed_section (0, avr_output_progmem_section_asm_op,
10523 avr_addrspace[as].section_name);
10524 }
10525
10526 return progmem_section[as];
10527 }
10528
10529 return sect;
10530 }
10531
10532 /* Implement `TARGET_ASM_FILE_START'. */
10533 /* Outputs some text at the start of each assembler file. */
10534
10535 static void
avr_file_start(void)10536 avr_file_start (void)
10537 {
10538 int sfr_offset = avr_arch->sfr_offset;
10539
10540 if (avr_arch->asm_only)
10541 error ("architecture %qs supported for assembler only", avr_mmcu);
10542
10543 default_file_start ();
10544
10545 /* Print I/O addresses of some SFRs used with IN and OUT. */
10546
10547 if (AVR_HAVE_SPH)
10548 fprintf (asm_out_file, "__SP_H__ = 0x%02x\n", avr_addr.sp_h - sfr_offset);
10549
10550 fprintf (asm_out_file, "__SP_L__ = 0x%02x\n", avr_addr.sp_l - sfr_offset);
10551 fprintf (asm_out_file, "__SREG__ = 0x%02x\n", avr_addr.sreg - sfr_offset);
10552 if (AVR_HAVE_RAMPZ)
10553 fprintf (asm_out_file, "__RAMPZ__ = 0x%02x\n", avr_addr.rampz - sfr_offset);
10554 if (AVR_HAVE_RAMPY)
10555 fprintf (asm_out_file, "__RAMPY__ = 0x%02x\n", avr_addr.rampy - sfr_offset);
10556 if (AVR_HAVE_RAMPX)
10557 fprintf (asm_out_file, "__RAMPX__ = 0x%02x\n", avr_addr.rampx - sfr_offset);
10558 if (AVR_HAVE_RAMPD)
10559 fprintf (asm_out_file, "__RAMPD__ = 0x%02x\n", avr_addr.rampd - sfr_offset);
10560 if (AVR_XMEGA || AVR_TINY)
10561 fprintf (asm_out_file, "__CCP__ = 0x%02x\n", avr_addr.ccp - sfr_offset);
10562 fprintf (asm_out_file, "__tmp_reg__ = %d\n", AVR_TMP_REGNO);
10563 fprintf (asm_out_file, "__zero_reg__ = %d\n", AVR_ZERO_REGNO);
10564 }
10565
10566
10567 /* Implement `TARGET_ASM_FILE_END'. */
10568 /* Outputs to the stdio stream FILE some
10569 appropriate text to go at the end of an assembler file. */
10570
10571 static void
avr_file_end(void)10572 avr_file_end (void)
10573 {
10574 /* Output these only if there is anything in the
10575 .data* / .rodata* / .gnu.linkonce.* resp. .bss* or COMMON
10576 input section(s) - some code size can be saved by not
10577 linking in the initialization code from libgcc if resp.
10578 sections are empty, see PR18145. */
10579
10580 if (avr_need_copy_data_p)
10581 fputs (".global __do_copy_data\n", asm_out_file);
10582
10583 if (avr_need_clear_bss_p)
10584 fputs (".global __do_clear_bss\n", asm_out_file);
10585 }
10586
10587
10588 /* Worker function for `ADJUST_REG_ALLOC_ORDER'. */
10589 /* Choose the order in which to allocate hard registers for
10590 pseudo-registers local to a basic block.
10591
10592 Store the desired register order in the array `reg_alloc_order'.
10593 Element 0 should be the register to allocate first; element 1, the
10594 next register; and so on. */
10595
10596 void
avr_adjust_reg_alloc_order(void)10597 avr_adjust_reg_alloc_order (void)
10598 {
10599 static const int order_0[] =
10600 {
10601 24, 25,
10602 18, 19, 20, 21, 22, 23,
10603 30, 31,
10604 26, 27, 28, 29,
10605 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
10606 0, 1,
10607 32, 33, 34, 35
10608 };
10609 static const int tiny_order_0[] = {
10610 20, 21,
10611 22, 23,
10612 24, 25,
10613 30, 31,
10614 26, 27,
10615 28, 29,
10616 19, 18,
10617 16, 17,
10618 32, 33, 34, 35,
10619 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
10620 };
10621 static const int order_1[] =
10622 {
10623 18, 19, 20, 21, 22, 23, 24, 25,
10624 30, 31,
10625 26, 27, 28, 29,
10626 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
10627 0, 1,
10628 32, 33, 34, 35
10629 };
10630 static const int tiny_order_1[] = {
10631 22, 23,
10632 24, 25,
10633 30, 31,
10634 26, 27,
10635 28, 29,
10636 21, 20, 19, 18,
10637 16, 17,
10638 32, 33, 34, 35,
10639 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
10640 };
10641 static const int order_2[] =
10642 {
10643 25, 24, 23, 22, 21, 20, 19, 18,
10644 30, 31,
10645 26, 27, 28, 29,
10646 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
10647 1, 0,
10648 32, 33, 34, 35
10649 };
10650
10651 /* Select specific register allocation order.
10652 Tiny Core (ATtiny4/5/9/10/20/40) devices have only 16 registers,
10653 so different allocation order should be used. */
10654
10655 const int *order = (TARGET_ORDER_1 ? (AVR_TINY ? tiny_order_1 : order_1)
10656 : TARGET_ORDER_2 ? (AVR_TINY ? tiny_order_0 : order_2)
10657 : (AVR_TINY ? tiny_order_0 : order_0));
10658
10659 for (size_t i = 0; i < ARRAY_SIZE (order_0); ++i)
10660 reg_alloc_order[i] = order[i];
10661 }
10662
10663
10664 /* Implement `TARGET_REGISTER_MOVE_COST' */
10665
10666 static int
avr_register_move_cost(machine_mode mode ATTRIBUTE_UNUSED,reg_class_t from,reg_class_t to)10667 avr_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
10668 reg_class_t from, reg_class_t to)
10669 {
10670 return (from == STACK_REG ? 6
10671 : to == STACK_REG ? 12
10672 : 2);
10673 }
10674
10675
10676 /* Implement `TARGET_MEMORY_MOVE_COST' */
10677
10678 static int
avr_memory_move_cost(machine_mode mode,reg_class_t rclass ATTRIBUTE_UNUSED,bool in ATTRIBUTE_UNUSED)10679 avr_memory_move_cost (machine_mode mode,
10680 reg_class_t rclass ATTRIBUTE_UNUSED,
10681 bool in ATTRIBUTE_UNUSED)
10682 {
10683 return (mode == QImode ? 2
10684 : mode == HImode ? 4
10685 : mode == SImode ? 8
10686 : mode == SFmode ? 8
10687 : 16);
10688 }
10689
10690
10691 /* Cost for mul highpart. X is a LSHIFTRT, i.e. the outer TRUNCATE is
10692 already stripped off. */
10693
10694 static int
avr_mul_highpart_cost(rtx x,int)10695 avr_mul_highpart_cost (rtx x, int)
10696 {
10697 if (AVR_HAVE_MUL
10698 && LSHIFTRT == GET_CODE (x)
10699 && MULT == GET_CODE (XEXP (x, 0))
10700 && CONST_INT_P (XEXP (x, 1)))
10701 {
10702 // This is the wider mode.
10703 machine_mode mode = GET_MODE (x);
10704
10705 // The middle-end might still have PR81444, i.e. it is calling the cost
10706 // functions with strange modes. Fix this now by also considering
10707 // PSImode (should actually be SImode instead).
10708 if (HImode == mode || PSImode == mode || SImode == mode)
10709 {
10710 return COSTS_N_INSNS (2);
10711 }
10712 }
10713
10714 return 10000;
10715 }
10716
10717
10718 /* Mutually recursive subroutine of avr_rtx_cost for calculating the
10719 cost of an RTX operand given its context. X is the rtx of the
10720 operand, MODE is its mode, and OUTER is the rtx_code of this
10721 operand's parent operator. */
10722
10723 static int
avr_operand_rtx_cost(rtx x,machine_mode mode,enum rtx_code outer,int opno,bool speed)10724 avr_operand_rtx_cost (rtx x, machine_mode mode, enum rtx_code outer,
10725 int opno, bool speed)
10726 {
10727 enum rtx_code code = GET_CODE (x);
10728 int total;
10729
10730 switch (code)
10731 {
10732 case REG:
10733 case SUBREG:
10734 return 0;
10735
10736 case CONST_INT:
10737 case CONST_FIXED:
10738 case CONST_DOUBLE:
10739 return COSTS_N_INSNS (GET_MODE_SIZE (mode));
10740
10741 default:
10742 break;
10743 }
10744
10745 total = 0;
10746 avr_rtx_costs (x, mode, outer, opno, &total, speed);
10747 return total;
10748 }
10749
10750 /* Worker function for AVR backend's rtx_cost function.
10751 X is rtx expression whose cost is to be calculated.
10752 Return true if the complete cost has been computed.
10753 Return false if subexpressions should be scanned.
10754 In either case, *TOTAL contains the cost result. */
10755
10756 static bool
avr_rtx_costs_1(rtx x,machine_mode mode,int outer_code,int opno ATTRIBUTE_UNUSED,int * total,bool speed)10757 avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
10758 int opno ATTRIBUTE_UNUSED, int *total, bool speed)
10759 {
10760 enum rtx_code code = GET_CODE (x);
10761 HOST_WIDE_INT val;
10762
10763 switch (code)
10764 {
10765 case CONST_INT:
10766 case CONST_FIXED:
10767 case CONST_DOUBLE:
10768 case SYMBOL_REF:
10769 case CONST:
10770 case LABEL_REF:
10771 /* Immediate constants are as cheap as registers. */
10772 *total = 0;
10773 return true;
10774
10775 case MEM:
10776 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10777 return true;
10778
10779 case NEG:
10780 switch (mode)
10781 {
10782 case E_QImode:
10783 case E_SFmode:
10784 *total = COSTS_N_INSNS (1);
10785 break;
10786
10787 case E_HImode:
10788 case E_PSImode:
10789 case E_SImode:
10790 *total = COSTS_N_INSNS (2 * GET_MODE_SIZE (mode) - 1);
10791 break;
10792
10793 default:
10794 return false;
10795 }
10796 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10797 return true;
10798
10799 case ABS:
10800 switch (mode)
10801 {
10802 case E_QImode:
10803 case E_SFmode:
10804 *total = COSTS_N_INSNS (1);
10805 break;
10806
10807 default:
10808 return false;
10809 }
10810 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10811 return true;
10812
10813 case NOT:
10814 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10815 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10816 return true;
10817
10818 case ZERO_EXTEND:
10819 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
10820 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
10821 *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
10822 code, 0, speed);
10823 return true;
10824
10825 case SIGN_EXTEND:
10826 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
10827 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
10828 *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
10829 code, 0, speed);
10830 return true;
10831
10832 case PLUS:
10833 switch (mode)
10834 {
10835 case E_QImode:
10836 if (AVR_HAVE_MUL
10837 && MULT == GET_CODE (XEXP (x, 0))
10838 && register_operand (XEXP (x, 1), QImode))
10839 {
10840 /* multiply-add */
10841 *total = COSTS_N_INSNS (speed ? 4 : 3);
10842 /* multiply-add with constant: will be split and load constant. */
10843 if (CONST_INT_P (XEXP (XEXP (x, 0), 1)))
10844 *total = COSTS_N_INSNS (1) + *total;
10845 return true;
10846 }
10847 *total = COSTS_N_INSNS (1);
10848 if (!CONST_INT_P (XEXP (x, 1)))
10849 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10850 break;
10851
10852 case E_HImode:
10853 if (AVR_HAVE_MUL
10854 && (MULT == GET_CODE (XEXP (x, 0))
10855 || ASHIFT == GET_CODE (XEXP (x, 0)))
10856 && register_operand (XEXP (x, 1), HImode)
10857 && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))
10858 || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))))
10859 {
10860 /* multiply-add */
10861 *total = COSTS_N_INSNS (speed ? 5 : 4);
10862 /* multiply-add with constant: will be split and load constant. */
10863 if (CONST_INT_P (XEXP (XEXP (x, 0), 1)))
10864 *total = COSTS_N_INSNS (1) + *total;
10865 return true;
10866 }
10867 if (!CONST_INT_P (XEXP (x, 1)))
10868 {
10869 *total = COSTS_N_INSNS (2);
10870 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10871 speed);
10872 }
10873 else if (IN_RANGE (INTVAL (XEXP (x, 1)), -63, 63))
10874 *total = COSTS_N_INSNS (1);
10875 else
10876 *total = COSTS_N_INSNS (2);
10877 break;
10878
10879 case E_PSImode:
10880 if (!CONST_INT_P (XEXP (x, 1)))
10881 {
10882 *total = COSTS_N_INSNS (3);
10883 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10884 speed);
10885 }
10886 else if (IN_RANGE (INTVAL (XEXP (x, 1)), -63, 63))
10887 *total = COSTS_N_INSNS (2);
10888 else
10889 *total = COSTS_N_INSNS (3);
10890 break;
10891
10892 case E_SImode:
10893 if (!CONST_INT_P (XEXP (x, 1)))
10894 {
10895 *total = COSTS_N_INSNS (4);
10896 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10897 speed);
10898 }
10899 else if (IN_RANGE (INTVAL (XEXP (x, 1)), -63, 63))
10900 *total = COSTS_N_INSNS (1);
10901 else
10902 *total = COSTS_N_INSNS (4);
10903 break;
10904
10905 default:
10906 return false;
10907 }
10908 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10909 return true;
10910
10911 case MINUS:
10912 if (AVR_HAVE_MUL
10913 && QImode == mode
10914 && register_operand (XEXP (x, 0), QImode)
10915 && MULT == GET_CODE (XEXP (x, 1)))
10916 {
10917 /* multiply-sub */
10918 *total = COSTS_N_INSNS (speed ? 4 : 3);
10919 /* multiply-sub with constant: will be split and load constant. */
10920 if (CONST_INT_P (XEXP (XEXP (x, 1), 1)))
10921 *total = COSTS_N_INSNS (1) + *total;
10922 return true;
10923 }
10924 if (AVR_HAVE_MUL
10925 && HImode == mode
10926 && register_operand (XEXP (x, 0), HImode)
10927 && (MULT == GET_CODE (XEXP (x, 1))
10928 || ASHIFT == GET_CODE (XEXP (x, 1)))
10929 && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))
10930 || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))))
10931 {
10932 /* multiply-sub */
10933 *total = COSTS_N_INSNS (speed ? 5 : 4);
10934 /* multiply-sub with constant: will be split and load constant. */
10935 if (CONST_INT_P (XEXP (XEXP (x, 1), 1)))
10936 *total = COSTS_N_INSNS (1) + *total;
10937 return true;
10938 }
10939 /* FALLTHRU */
10940 case AND:
10941 case IOR:
10942 if (IOR == code
10943 && HImode == mode
10944 && ASHIFT == GET_CODE (XEXP (x, 0)))
10945 {
10946 *total = COSTS_N_INSNS (2);
10947 // Just a rough estimate. If we see no sign- or zero-extend,
10948 // then increase the cost a little bit.
10949 if (REG_P (XEXP (XEXP (x, 0), 0)))
10950 *total += COSTS_N_INSNS (1);
10951 if (REG_P (XEXP (x, 1)))
10952 *total += COSTS_N_INSNS (1);
10953 return true;
10954 }
10955 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10956 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10957 if (!CONST_INT_P (XEXP (x, 1)))
10958 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10959 return true;
10960
10961 case XOR:
10962 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10963 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10964 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10965 return true;
10966
10967 case MULT:
10968 switch (mode)
10969 {
10970 case E_QImode:
10971 if (AVR_HAVE_MUL)
10972 *total = COSTS_N_INSNS (!speed ? 3 : 4);
10973 else if (!speed)
10974 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
10975 else
10976 return false;
10977 break;
10978
10979 case E_HImode:
10980 if (AVR_HAVE_MUL)
10981 {
10982 rtx op0 = XEXP (x, 0);
10983 rtx op1 = XEXP (x, 1);
10984 enum rtx_code code0 = GET_CODE (op0);
10985 enum rtx_code code1 = GET_CODE (op1);
10986 bool ex0 = SIGN_EXTEND == code0 || ZERO_EXTEND == code0;
10987 bool ex1 = SIGN_EXTEND == code1 || ZERO_EXTEND == code1;
10988
10989 if (ex0
10990 && (u8_operand (op1, HImode)
10991 || s8_operand (op1, HImode)))
10992 {
10993 *total = COSTS_N_INSNS (!speed ? 4 : 6);
10994 return true;
10995 }
10996 if (ex0
10997 && register_operand (op1, HImode))
10998 {
10999 *total = COSTS_N_INSNS (!speed ? 5 : 8);
11000 return true;
11001 }
11002 else if (ex0 || ex1)
11003 {
11004 *total = COSTS_N_INSNS (!speed ? 3 : 5);
11005 return true;
11006 }
11007 else if (register_operand (op0, HImode)
11008 && (u8_operand (op1, HImode)
11009 || s8_operand (op1, HImode)))
11010 {
11011 *total = COSTS_N_INSNS (!speed ? 6 : 9);
11012 return true;
11013 }
11014 else
11015 *total = COSTS_N_INSNS (!speed ? 7 : 10);
11016 }
11017 else if (!speed)
11018 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
11019 else
11020 return false;
11021 break;
11022
11023 case E_PSImode:
11024 if (!speed)
11025 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
11026 else
11027 *total = 10;
11028 break;
11029
11030 case E_SImode:
11031 case E_DImode:
11032 if (AVR_HAVE_MUL)
11033 {
11034 if (!speed)
11035 {
11036 /* Add some additional costs besides CALL like moves etc. */
11037
11038 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
11039 }
11040 else
11041 {
11042 /* Just a rough estimate. Even with -O2 we don't want bulky
11043 code expanded inline. */
11044
11045 *total = COSTS_N_INSNS (25);
11046 }
11047 }
11048 else
11049 {
11050 if (speed)
11051 *total = COSTS_N_INSNS (300);
11052 else
11053 /* Add some additional costs besides CALL like moves etc. */
11054 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
11055 }
11056
11057 if (mode == DImode)
11058 *total *= 2;
11059
11060 return true;
11061
11062 default:
11063 return false;
11064 }
11065 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11066 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
11067 return true;
11068
11069 case DIV:
11070 case MOD:
11071 case UDIV:
11072 case UMOD:
11073 if (!speed)
11074 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
11075 else
11076 *total = COSTS_N_INSNS (15 * GET_MODE_SIZE (mode));
11077 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11078 /* For div/mod with const-int divisor we have at least the cost of
11079 loading the divisor. */
11080 if (CONST_INT_P (XEXP (x, 1)))
11081 *total += COSTS_N_INSNS (GET_MODE_SIZE (mode));
11082 /* Add some overall penaly for clobbering and moving around registers */
11083 *total += COSTS_N_INSNS (2);
11084 return true;
11085
11086 case ROTATE:
11087 switch (mode)
11088 {
11089 case E_QImode:
11090 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 4)
11091 *total = COSTS_N_INSNS (1);
11092
11093 break;
11094
11095 case E_HImode:
11096 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 8)
11097 *total = COSTS_N_INSNS (3);
11098
11099 break;
11100
11101 case E_SImode:
11102 if (CONST_INT_P (XEXP (x, 1)))
11103 switch (INTVAL (XEXP (x, 1)))
11104 {
11105 case 8:
11106 case 24:
11107 *total = COSTS_N_INSNS (5);
11108 break;
11109 case 16:
11110 *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 6);
11111 break;
11112 }
11113 break;
11114
11115 default:
11116 return false;
11117 }
11118 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11119 return true;
11120
11121 case ASHIFT:
11122 switch (mode)
11123 {
11124 case E_QImode:
11125 if (!CONST_INT_P (XEXP (x, 1)))
11126 {
11127 *total = COSTS_N_INSNS (!speed ? 4 : 17);
11128 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11129 speed);
11130 }
11131 else
11132 {
11133 val = INTVAL (XEXP (x, 1));
11134 if (val == 7)
11135 *total = COSTS_N_INSNS (3);
11136 else if (val >= 0 && val <= 7)
11137 *total = COSTS_N_INSNS (val);
11138 else
11139 *total = COSTS_N_INSNS (1);
11140 }
11141 break;
11142
11143 case E_HImode:
11144 if (AVR_HAVE_MUL)
11145 {
11146 if (const_2_to_7_operand (XEXP (x, 1), HImode)
11147 && (SIGN_EXTEND == GET_CODE (XEXP (x, 0))
11148 || ZERO_EXTEND == GET_CODE (XEXP (x, 0))))
11149 {
11150 *total = COSTS_N_INSNS (!speed ? 4 : 6);
11151 return true;
11152 }
11153 }
11154
11155 if (const1_rtx == (XEXP (x, 1))
11156 && SIGN_EXTEND == GET_CODE (XEXP (x, 0)))
11157 {
11158 *total = COSTS_N_INSNS (2);
11159 return true;
11160 }
11161
11162 if (!CONST_INT_P (XEXP (x, 1)))
11163 {
11164 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11165 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11166 speed);
11167 }
11168 else
11169 switch (INTVAL (XEXP (x, 1)))
11170 {
11171 case 0:
11172 *total = 0;
11173 break;
11174 case 1:
11175 case 8:
11176 *total = COSTS_N_INSNS (2);
11177 break;
11178 case 9:
11179 *total = COSTS_N_INSNS (3);
11180 break;
11181 case 2:
11182 case 3:
11183 case 10:
11184 case 15:
11185 *total = COSTS_N_INSNS (4);
11186 break;
11187 case 7:
11188 case 11:
11189 case 12:
11190 *total = COSTS_N_INSNS (5);
11191 break;
11192 case 4:
11193 *total = COSTS_N_INSNS (!speed ? 5 : 8);
11194 break;
11195 case 6:
11196 *total = COSTS_N_INSNS (!speed ? 5 : 9);
11197 break;
11198 case 5:
11199 *total = COSTS_N_INSNS (!speed ? 5 : 10);
11200 break;
11201 default:
11202 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11203 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11204 speed);
11205 }
11206 break;
11207
11208 case E_PSImode:
11209 if (!CONST_INT_P (XEXP (x, 1)))
11210 {
11211 *total = COSTS_N_INSNS (!speed ? 6 : 73);
11212 }
11213 else
11214 switch (INTVAL (XEXP (x, 1)))
11215 {
11216 case 0:
11217 *total = 0;
11218 break;
11219 case 1:
11220 case 8:
11221 case 16:
11222 *total = COSTS_N_INSNS (3);
11223 break;
11224 case 23:
11225 *total = COSTS_N_INSNS (5);
11226 break;
11227 default:
11228 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
11229 break;
11230 }
11231 break;
11232
11233 case E_SImode:
11234 if (!CONST_INT_P (XEXP (x, 1)))
11235 {
11236 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11237 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11238 speed);
11239 }
11240 else
11241 switch (INTVAL (XEXP (x, 1)))
11242 {
11243 case 0:
11244 *total = 0;
11245 break;
11246 case 24:
11247 *total = COSTS_N_INSNS (3);
11248 break;
11249 case 1:
11250 case 8:
11251 case 16:
11252 *total = COSTS_N_INSNS (4);
11253 break;
11254 case 31:
11255 *total = COSTS_N_INSNS (6);
11256 break;
11257 case 2:
11258 *total = COSTS_N_INSNS (!speed ? 7 : 8);
11259 break;
11260 default:
11261 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11262 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11263 speed);
11264 }
11265 break;
11266
11267 default:
11268 return false;
11269 }
11270 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11271 return true;
11272
11273 case ASHIFTRT:
11274 switch (mode)
11275 {
11276 case E_QImode:
11277 if (!CONST_INT_P (XEXP (x, 1)))
11278 {
11279 *total = COSTS_N_INSNS (!speed ? 4 : 17);
11280 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11281 speed);
11282 }
11283 else
11284 {
11285 val = INTVAL (XEXP (x, 1));
11286 if (val == 6)
11287 *total = COSTS_N_INSNS (4);
11288 else if (val == 7)
11289 *total = COSTS_N_INSNS (2);
11290 else if (val >= 0 && val <= 7)
11291 *total = COSTS_N_INSNS (val);
11292 else
11293 *total = COSTS_N_INSNS (1);
11294 }
11295 break;
11296
11297 case E_HImode:
11298 if (!CONST_INT_P (XEXP (x, 1)))
11299 {
11300 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11301 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11302 speed);
11303 }
11304 else
11305 switch (INTVAL (XEXP (x, 1)))
11306 {
11307 case 0:
11308 *total = 0;
11309 break;
11310 case 1:
11311 *total = COSTS_N_INSNS (2);
11312 break;
11313 case 15:
11314 *total = COSTS_N_INSNS (3);
11315 break;
11316 case 2:
11317 case 7:
11318 case 8:
11319 case 9:
11320 *total = COSTS_N_INSNS (4);
11321 break;
11322 case 10:
11323 case 14:
11324 *total = COSTS_N_INSNS (5);
11325 break;
11326 case 11:
11327 *total = COSTS_N_INSNS (!speed ? 5 : 6);
11328 break;
11329 case 12:
11330 *total = COSTS_N_INSNS (!speed ? 5 : 7);
11331 break;
11332 case 6:
11333 case 13:
11334 *total = COSTS_N_INSNS (!speed ? 5 : 8);
11335 break;
11336 default:
11337 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11338 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11339 speed);
11340 }
11341 break;
11342
11343 case E_PSImode:
11344 if (!CONST_INT_P (XEXP (x, 1)))
11345 {
11346 *total = COSTS_N_INSNS (!speed ? 6 : 73);
11347 }
11348 else
11349 switch (INTVAL (XEXP (x, 1)))
11350 {
11351 case 0:
11352 *total = 0;
11353 break;
11354 case 1:
11355 *total = COSTS_N_INSNS (3);
11356 break;
11357 case 16:
11358 case 8:
11359 *total = COSTS_N_INSNS (5);
11360 break;
11361 case 23:
11362 *total = COSTS_N_INSNS (4);
11363 break;
11364 default:
11365 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
11366 break;
11367 }
11368 break;
11369
11370 case E_SImode:
11371 if (!CONST_INT_P (XEXP (x, 1)))
11372 {
11373 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11374 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11375 speed);
11376 }
11377 else
11378 switch (INTVAL (XEXP (x, 1)))
11379 {
11380 case 0:
11381 *total = 0;
11382 break;
11383 case 1:
11384 *total = COSTS_N_INSNS (4);
11385 break;
11386 case 8:
11387 case 16:
11388 case 24:
11389 *total = COSTS_N_INSNS (6);
11390 break;
11391 case 2:
11392 *total = COSTS_N_INSNS (!speed ? 7 : 8);
11393 break;
11394 case 31:
11395 *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 5);
11396 break;
11397 default:
11398 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11399 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11400 speed);
11401 }
11402 break;
11403
11404 default:
11405 return false;
11406 }
11407 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11408 return true;
11409
11410 case LSHIFTRT:
11411 if (outer_code == TRUNCATE)
11412 {
11413 *total = avr_mul_highpart_cost (x, speed);
11414 return true;
11415 }
11416
11417 switch (mode)
11418 {
11419 case E_QImode:
11420 if (!CONST_INT_P (XEXP (x, 1)))
11421 {
11422 *total = COSTS_N_INSNS (!speed ? 4 : 17);
11423 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11424 speed);
11425 }
11426 else
11427 {
11428 val = INTVAL (XEXP (x, 1));
11429 if (val == 7)
11430 *total = COSTS_N_INSNS (3);
11431 else if (val >= 0 && val <= 7)
11432 *total = COSTS_N_INSNS (val);
11433 else
11434 *total = COSTS_N_INSNS (1);
11435 }
11436 break;
11437
11438 case E_HImode:
11439 if (!CONST_INT_P (XEXP (x, 1)))
11440 {
11441 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11442 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11443 speed);
11444 }
11445 else
11446 switch (INTVAL (XEXP (x, 1)))
11447 {
11448 case 0:
11449 *total = 0;
11450 break;
11451 case 1:
11452 case 8:
11453 *total = COSTS_N_INSNS (2);
11454 break;
11455 case 9:
11456 *total = COSTS_N_INSNS (3);
11457 break;
11458 case 2:
11459 case 10:
11460 case 15:
11461 *total = COSTS_N_INSNS (4);
11462 break;
11463 case 7:
11464 case 11:
11465 *total = COSTS_N_INSNS (5);
11466 break;
11467 case 3:
11468 case 12:
11469 case 13:
11470 case 14:
11471 *total = COSTS_N_INSNS (!speed ? 5 : 6);
11472 break;
11473 case 4:
11474 *total = COSTS_N_INSNS (!speed ? 5 : 7);
11475 break;
11476 case 5:
11477 case 6:
11478 *total = COSTS_N_INSNS (!speed ? 5 : 9);
11479 break;
11480 default:
11481 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11482 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11483 speed);
11484 }
11485 break;
11486
11487 case E_PSImode:
11488 if (!CONST_INT_P (XEXP (x, 1)))
11489 {
11490 *total = COSTS_N_INSNS (!speed ? 6 : 73);
11491 }
11492 else
11493 switch (INTVAL (XEXP (x, 1)))
11494 {
11495 case 0:
11496 *total = 0;
11497 break;
11498 case 1:
11499 case 8:
11500 case 16:
11501 *total = COSTS_N_INSNS (3);
11502 break;
11503 case 23:
11504 *total = COSTS_N_INSNS (5);
11505 break;
11506 default:
11507 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
11508 break;
11509 }
11510 break;
11511
11512 case E_SImode:
11513 if (!CONST_INT_P (XEXP (x, 1)))
11514 {
11515 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11516 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11517 speed);
11518 }
11519 else
11520 switch (INTVAL (XEXP (x, 1)))
11521 {
11522 case 0:
11523 *total = 0;
11524 break;
11525 case 1:
11526 *total = COSTS_N_INSNS (4);
11527 break;
11528 case 2:
11529 *total = COSTS_N_INSNS (!speed ? 7 : 8);
11530 break;
11531 case 8:
11532 case 16:
11533 case 24:
11534 *total = COSTS_N_INSNS (4);
11535 break;
11536 case 31:
11537 *total = COSTS_N_INSNS (6);
11538 break;
11539 default:
11540 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11541 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11542 speed);
11543 }
11544 break;
11545
11546 default:
11547 return false;
11548 }
11549 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11550 return true;
11551
11552 case COMPARE:
11553 switch (GET_MODE (XEXP (x, 0)))
11554 {
11555 case E_QImode:
11556 *total = COSTS_N_INSNS (1);
11557 if (!CONST_INT_P (XEXP (x, 1)))
11558 *total += avr_operand_rtx_cost (XEXP (x, 1), QImode, code,
11559 1, speed);
11560 break;
11561
11562 case E_HImode:
11563 *total = COSTS_N_INSNS (2);
11564 if (!CONST_INT_P (XEXP (x, 1)))
11565 *total += avr_operand_rtx_cost (XEXP (x, 1), HImode, code,
11566 1, speed);
11567 else if (INTVAL (XEXP (x, 1)) != 0)
11568 *total += COSTS_N_INSNS (1);
11569 break;
11570
11571 case E_PSImode:
11572 *total = COSTS_N_INSNS (3);
11573 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) != 0)
11574 *total += COSTS_N_INSNS (2);
11575 break;
11576
11577 case E_SImode:
11578 *total = COSTS_N_INSNS (4);
11579 if (!CONST_INT_P (XEXP (x, 1)))
11580 *total += avr_operand_rtx_cost (XEXP (x, 1), SImode, code,
11581 1, speed);
11582 else if (INTVAL (XEXP (x, 1)) != 0)
11583 *total += COSTS_N_INSNS (3);
11584 break;
11585
11586 default:
11587 return false;
11588 }
11589 *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
11590 code, 0, speed);
11591 return true;
11592
11593 case TRUNCATE:
11594 if (LSHIFTRT == GET_CODE (XEXP (x, 0)))
11595 {
11596 *total = avr_mul_highpart_cost (XEXP (x, 0), speed);
11597 return true;
11598 }
11599 break;
11600
11601 default:
11602 break;
11603 }
11604 return false;
11605 }
11606
11607
11608 /* Implement `TARGET_RTX_COSTS'. */
11609
11610 static bool
avr_rtx_costs(rtx x,machine_mode mode,int outer_code,int opno,int * total,bool speed)11611 avr_rtx_costs (rtx x, machine_mode mode, int outer_code,
11612 int opno, int *total, bool speed)
11613 {
11614 bool done = avr_rtx_costs_1 (x, mode, outer_code, opno, total, speed);
11615
11616 if (avr_log.rtx_costs)
11617 {
11618 avr_edump ("\n%?=%b (%s) total=%d, outer=%C:\n%r\n",
11619 done, speed ? "speed" : "size", *total, outer_code, x);
11620 }
11621
11622 return done;
11623 }
11624
11625
11626 /* Implement `TARGET_ADDRESS_COST'. */
11627
11628 static int
avr_address_cost(rtx x,machine_mode mode ATTRIBUTE_UNUSED,addr_space_t as ATTRIBUTE_UNUSED,bool speed ATTRIBUTE_UNUSED)11629 avr_address_cost (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
11630 addr_space_t as ATTRIBUTE_UNUSED,
11631 bool speed ATTRIBUTE_UNUSED)
11632 {
11633 int cost = 4;
11634
11635 if (GET_CODE (x) == PLUS
11636 && CONST_INT_P (XEXP (x, 1))
11637 && (REG_P (XEXP (x, 0))
11638 || SUBREG_P (XEXP (x, 0))))
11639 {
11640 if (INTVAL (XEXP (x, 1)) > MAX_LD_OFFSET(mode))
11641 cost = 18;
11642 }
11643 else if (CONSTANT_ADDRESS_P (x))
11644 {
11645 if (io_address_operand (x, QImode))
11646 cost = 2;
11647
11648 if (AVR_TINY
11649 && avr_address_tiny_absdata_p (x, QImode))
11650 cost = 2;
11651 }
11652
11653 if (avr_log.address_cost)
11654 avr_edump ("\n%?: %d = %r\n", cost, x);
11655
11656 return cost;
11657 }
11658
11659 /* Test for extra memory constraint 'Q'.
11660 It's a memory address based on Y or Z pointer with valid displacement. */
11661
11662 int
extra_constraint_Q(rtx x)11663 extra_constraint_Q (rtx x)
11664 {
11665 int ok = 0;
11666 rtx plus = XEXP (x, 0);
11667
11668 if (GET_CODE (plus) == PLUS
11669 && REG_P (XEXP (plus, 0))
11670 && CONST_INT_P (XEXP (plus, 1))
11671 && (INTVAL (XEXP (plus, 1))
11672 <= MAX_LD_OFFSET (GET_MODE (x))))
11673 {
11674 rtx xx = XEXP (plus, 0);
11675 int regno = REGNO (xx);
11676
11677 ok = (/* allocate pseudos */
11678 regno >= FIRST_PSEUDO_REGISTER
11679 /* strictly check */
11680 || regno == REG_Z || regno == REG_Y
11681 /* XXX frame & arg pointer checks */
11682 || xx == frame_pointer_rtx
11683 || xx == arg_pointer_rtx);
11684
11685 if (avr_log.constraints)
11686 avr_edump ("\n%?=%d reload_completed=%d reload_in_progress=%d\n %r\n",
11687 ok, reload_completed, reload_in_progress, x);
11688 }
11689
11690 return ok;
11691 }
11692
11693 /* Convert condition code CONDITION to the valid AVR condition code. */
11694
11695 RTX_CODE
avr_normalize_condition(RTX_CODE condition)11696 avr_normalize_condition (RTX_CODE condition)
11697 {
11698 switch (condition)
11699 {
11700 case GT:
11701 return GE;
11702 case GTU:
11703 return GEU;
11704 case LE:
11705 return LT;
11706 case LEU:
11707 return LTU;
11708 default:
11709 gcc_unreachable ();
11710 }
11711 }
11712
11713 /* Helper function for `avr_reorg'. */
11714
11715 static rtx
avr_compare_pattern(rtx_insn * insn)11716 avr_compare_pattern (rtx_insn *insn)
11717 {
11718 rtx pattern = single_set (insn);
11719
11720 if (pattern
11721 && NONJUMP_INSN_P (insn)
11722 && SET_DEST (pattern) == cc0_rtx
11723 && GET_CODE (SET_SRC (pattern)) == COMPARE)
11724 {
11725 machine_mode mode0 = GET_MODE (XEXP (SET_SRC (pattern), 0));
11726 machine_mode mode1 = GET_MODE (XEXP (SET_SRC (pattern), 1));
11727
11728 /* The 64-bit comparisons have fixed operands ACC_A and ACC_B.
11729 They must not be swapped, thus skip them. */
11730
11731 if ((mode0 == VOIDmode || GET_MODE_SIZE (mode0) <= 4)
11732 && (mode1 == VOIDmode || GET_MODE_SIZE (mode1) <= 4))
11733 return pattern;
11734 }
11735
11736 return NULL_RTX;
11737 }
11738
11739 /* Helper function for `avr_reorg'. */
11740
11741 /* Expansion of switch/case decision trees leads to code like
11742
11743 cc0 = compare (Reg, Num)
11744 if (cc0 == 0)
11745 goto L1
11746
11747 cc0 = compare (Reg, Num)
11748 if (cc0 > 0)
11749 goto L2
11750
11751 The second comparison is superfluous and can be deleted.
11752 The second jump condition can be transformed from a
11753 "difficult" one to a "simple" one because "cc0 > 0" and
11754 "cc0 >= 0" will have the same effect here.
11755
11756 This function relies on the way switch/case is being expaned
11757 as binary decision tree. For example code see PR 49903.
11758
11759 Return TRUE if optimization performed.
11760 Return FALSE if nothing changed.
11761
11762 INSN1 is a comparison, i.e. avr_compare_pattern != 0.
11763
11764 We don't want to do this in text peephole because it is
11765 tedious to work out jump offsets there and the second comparison
11766 might have been transormed by `avr_reorg'.
11767
11768 RTL peephole won't do because peephole2 does not scan across
11769 basic blocks. */
11770
11771 static bool
avr_reorg_remove_redundant_compare(rtx_insn * insn1)11772 avr_reorg_remove_redundant_compare (rtx_insn *insn1)
11773 {
11774 rtx comp1, ifelse1, xcond1;
11775 rtx_insn *branch1;
11776 rtx comp2, ifelse2, xcond2;
11777 rtx_insn *branch2, *insn2;
11778 enum rtx_code code;
11779 rtx_insn *jump;
11780 rtx target, cond;
11781
11782 /* Look out for: compare1 - branch1 - compare2 - branch2 */
11783
11784 branch1 = next_nonnote_nondebug_insn (insn1);
11785 if (!branch1 || !JUMP_P (branch1))
11786 return false;
11787
11788 insn2 = next_nonnote_nondebug_insn (branch1);
11789 if (!insn2 || !avr_compare_pattern (insn2))
11790 return false;
11791
11792 branch2 = next_nonnote_nondebug_insn (insn2);
11793 if (!branch2 || !JUMP_P (branch2))
11794 return false;
11795
11796 comp1 = avr_compare_pattern (insn1);
11797 comp2 = avr_compare_pattern (insn2);
11798 xcond1 = single_set (branch1);
11799 xcond2 = single_set (branch2);
11800
11801 if (!comp1 || !comp2
11802 || !rtx_equal_p (comp1, comp2)
11803 || !xcond1 || SET_DEST (xcond1) != pc_rtx
11804 || !xcond2 || SET_DEST (xcond2) != pc_rtx
11805 || IF_THEN_ELSE != GET_CODE (SET_SRC (xcond1))
11806 || IF_THEN_ELSE != GET_CODE (SET_SRC (xcond2)))
11807 {
11808 return false;
11809 }
11810
11811 comp1 = SET_SRC (comp1);
11812 ifelse1 = SET_SRC (xcond1);
11813 ifelse2 = SET_SRC (xcond2);
11814
11815 /* comp<n> is COMPARE now and ifelse<n> is IF_THEN_ELSE. */
11816
11817 if (EQ != GET_CODE (XEXP (ifelse1, 0))
11818 || !REG_P (XEXP (comp1, 0))
11819 || !CONST_INT_P (XEXP (comp1, 1))
11820 || XEXP (ifelse1, 2) != pc_rtx
11821 || XEXP (ifelse2, 2) != pc_rtx
11822 || LABEL_REF != GET_CODE (XEXP (ifelse1, 1))
11823 || LABEL_REF != GET_CODE (XEXP (ifelse2, 1))
11824 || !COMPARISON_P (XEXP (ifelse2, 0))
11825 || cc0_rtx != XEXP (XEXP (ifelse1, 0), 0)
11826 || cc0_rtx != XEXP (XEXP (ifelse2, 0), 0)
11827 || const0_rtx != XEXP (XEXP (ifelse1, 0), 1)
11828 || const0_rtx != XEXP (XEXP (ifelse2, 0), 1))
11829 {
11830 return false;
11831 }
11832
11833 /* We filtered the insn sequence to look like
11834
11835 (set (cc0)
11836 (compare (reg:M N)
11837 (const_int VAL)))
11838 (set (pc)
11839 (if_then_else (eq (cc0)
11840 (const_int 0))
11841 (label_ref L1)
11842 (pc)))
11843
11844 (set (cc0)
11845 (compare (reg:M N)
11846 (const_int VAL)))
11847 (set (pc)
11848 (if_then_else (CODE (cc0)
11849 (const_int 0))
11850 (label_ref L2)
11851 (pc)))
11852 */
11853
11854 code = GET_CODE (XEXP (ifelse2, 0));
11855
11856 /* Map GT/GTU to GE/GEU which is easier for AVR.
11857 The first two instructions compare/branch on EQ
11858 so we may replace the difficult
11859
11860 if (x == VAL) goto L1;
11861 if (x > VAL) goto L2;
11862
11863 with easy
11864
11865 if (x == VAL) goto L1;
11866 if (x >= VAL) goto L2;
11867
11868 Similarly, replace LE/LEU by LT/LTU. */
11869
11870 switch (code)
11871 {
11872 case EQ:
11873 case LT: case LTU:
11874 case GE: case GEU:
11875 break;
11876
11877 case LE: case LEU:
11878 case GT: case GTU:
11879 code = avr_normalize_condition (code);
11880 break;
11881
11882 default:
11883 return false;
11884 }
11885
11886 /* Wrap the branches into UNSPECs so they won't be changed or
11887 optimized in the remainder. */
11888
11889 target = XEXP (XEXP (ifelse1, 1), 0);
11890 cond = XEXP (ifelse1, 0);
11891 jump = emit_jump_insn_after (gen_branch_unspec (target, cond), insn1);
11892
11893 JUMP_LABEL (jump) = JUMP_LABEL (branch1);
11894
11895 target = XEXP (XEXP (ifelse2, 1), 0);
11896 cond = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
11897 jump = emit_jump_insn_after (gen_branch_unspec (target, cond), insn2);
11898
11899 JUMP_LABEL (jump) = JUMP_LABEL (branch2);
11900
11901 /* The comparisons in insn1 and insn2 are exactly the same;
11902 insn2 is superfluous so delete it. */
11903
11904 delete_insn (insn2);
11905 delete_insn (branch1);
11906 delete_insn (branch2);
11907
11908 return true;
11909 }
11910
11911
11912 /* Implement `TARGET_MACHINE_DEPENDENT_REORG'. */
11913 /* Optimize conditional jumps. */
11914
11915 static void
avr_reorg(void)11916 avr_reorg (void)
11917 {
11918 rtx_insn *insn = get_insns();
11919
11920 for (insn = next_real_insn (insn); insn; insn = next_real_insn (insn))
11921 {
11922 rtx pattern = avr_compare_pattern (insn);
11923
11924 if (!pattern)
11925 continue;
11926
11927 if (optimize
11928 && avr_reorg_remove_redundant_compare (insn))
11929 {
11930 continue;
11931 }
11932
11933 if (compare_diff_p (insn))
11934 {
11935 /* Now we work under compare insn with difficult branch. */
11936
11937 rtx_insn *next = next_real_insn (insn);
11938 rtx pat = PATTERN (next);
11939
11940 pattern = SET_SRC (pattern);
11941
11942 if (true_regnum (XEXP (pattern, 0)) >= 0
11943 && true_regnum (XEXP (pattern, 1)) >= 0)
11944 {
11945 rtx x = XEXP (pattern, 0);
11946 rtx src = SET_SRC (pat);
11947 rtx t = XEXP (src, 0);
11948 PUT_CODE (t, swap_condition (GET_CODE (t)));
11949 XEXP (pattern, 0) = XEXP (pattern, 1);
11950 XEXP (pattern, 1) = x;
11951 INSN_CODE (next) = -1;
11952 }
11953 else if (true_regnum (XEXP (pattern, 0)) >= 0
11954 && XEXP (pattern, 1) == const0_rtx)
11955 {
11956 /* This is a tst insn, we can reverse it. */
11957 rtx src = SET_SRC (pat);
11958 rtx t = XEXP (src, 0);
11959
11960 PUT_CODE (t, swap_condition (GET_CODE (t)));
11961 XEXP (pattern, 1) = XEXP (pattern, 0);
11962 XEXP (pattern, 0) = const0_rtx;
11963 INSN_CODE (next) = -1;
11964 INSN_CODE (insn) = -1;
11965 }
11966 else if (true_regnum (XEXP (pattern, 0)) >= 0
11967 && CONST_INT_P (XEXP (pattern, 1)))
11968 {
11969 rtx x = XEXP (pattern, 1);
11970 rtx src = SET_SRC (pat);
11971 rtx t = XEXP (src, 0);
11972 machine_mode mode = GET_MODE (XEXP (pattern, 0));
11973
11974 if (avr_simplify_comparison_p (mode, GET_CODE (t), x))
11975 {
11976 XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
11977 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
11978 INSN_CODE (next) = -1;
11979 INSN_CODE (insn) = -1;
11980 }
11981 }
11982 }
11983 }
11984 }
11985
11986 /* Returns register number for function return value.*/
11987
11988 static inline unsigned int
avr_ret_register(void)11989 avr_ret_register (void)
11990 {
11991 return 24;
11992 }
11993
11994
11995 /* Implement `TARGET_FUNCTION_VALUE_REGNO_P'. */
11996
11997 static bool
avr_function_value_regno_p(const unsigned int regno)11998 avr_function_value_regno_p (const unsigned int regno)
11999 {
12000 return (regno == avr_ret_register ());
12001 }
12002
12003
12004 /* Implement `TARGET_LIBCALL_VALUE'. */
12005 /* Create an RTX representing the place where a
12006 library function returns a value of mode MODE. */
12007
12008 static rtx
avr_libcall_value(machine_mode mode,const_rtx func ATTRIBUTE_UNUSED)12009 avr_libcall_value (machine_mode mode,
12010 const_rtx func ATTRIBUTE_UNUSED)
12011 {
12012 int offs = GET_MODE_SIZE (mode);
12013
12014 if (offs <= 4)
12015 offs = (offs + 1) & ~1;
12016
12017 return gen_rtx_REG (mode, avr_ret_register () + 2 - offs);
12018 }
12019
12020
12021 /* Implement `TARGET_FUNCTION_VALUE'. */
12022 /* Create an RTX representing the place where a
12023 function returns a value of data type VALTYPE. */
12024
12025 static rtx
avr_function_value(const_tree type,const_tree fn_decl_or_type ATTRIBUTE_UNUSED,bool outgoing ATTRIBUTE_UNUSED)12026 avr_function_value (const_tree type,
12027 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
12028 bool outgoing ATTRIBUTE_UNUSED)
12029 {
12030 unsigned int offs;
12031
12032 if (TYPE_MODE (type) != BLKmode)
12033 return avr_libcall_value (TYPE_MODE (type), NULL_RTX);
12034
12035 offs = int_size_in_bytes (type);
12036 if (offs < 2)
12037 offs = 2;
12038 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
12039 offs = GET_MODE_SIZE (SImode);
12040 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
12041 offs = GET_MODE_SIZE (DImode);
12042
12043 return gen_rtx_REG (BLKmode, avr_ret_register () + 2 - offs);
12044 }
12045
12046 int
test_hard_reg_class(enum reg_class rclass,rtx x)12047 test_hard_reg_class (enum reg_class rclass, rtx x)
12048 {
12049 int regno = true_regnum (x);
12050 if (regno < 0)
12051 return 0;
12052
12053 if (TEST_HARD_REG_CLASS (rclass, regno))
12054 return 1;
12055
12056 return 0;
12057 }
12058
12059
12060 /* Helper for jump_over_one_insn_p: Test if INSN is a 2-word instruction
12061 and thus is suitable to be skipped by CPSE, SBRC, etc. */
12062
12063 static bool
avr_2word_insn_p(rtx_insn * insn)12064 avr_2word_insn_p (rtx_insn *insn)
12065 {
12066 if (TARGET_SKIP_BUG || !insn || get_attr_length (insn) != 2)
12067 {
12068 return false;
12069 }
12070
12071 switch (INSN_CODE (insn))
12072 {
12073 default:
12074 return false;
12075
12076 case CODE_FOR_movqi_insn:
12077 case CODE_FOR_movuqq_insn:
12078 case CODE_FOR_movqq_insn:
12079 {
12080 rtx set = single_set (insn);
12081 rtx src = SET_SRC (set);
12082 rtx dest = SET_DEST (set);
12083
12084 /* Factor out LDS and STS from movqi_insn. */
12085
12086 if (MEM_P (dest)
12087 && (REG_P (src) || src == CONST0_RTX (GET_MODE (dest))))
12088 {
12089 return CONSTANT_ADDRESS_P (XEXP (dest, 0));
12090 }
12091 else if (REG_P (dest)
12092 && MEM_P (src))
12093 {
12094 return CONSTANT_ADDRESS_P (XEXP (src, 0));
12095 }
12096
12097 return false;
12098 }
12099
12100 case CODE_FOR_call_insn:
12101 case CODE_FOR_call_value_insn:
12102 return true;
12103 }
12104 }
12105
12106
12107 int
jump_over_one_insn_p(rtx_insn * insn,rtx dest)12108 jump_over_one_insn_p (rtx_insn *insn, rtx dest)
12109 {
12110 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
12111 ? XEXP (dest, 0)
12112 : dest);
12113 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
12114 int dest_addr = INSN_ADDRESSES (uid);
12115 int jump_offset = dest_addr - jump_addr - get_attr_length (insn);
12116
12117 return (jump_offset == 1
12118 || (jump_offset == 2
12119 && avr_2word_insn_p (next_active_insn (insn))));
12120 }
12121
12122
12123 /* Implement TARGET_HARD_REGNO_MODE_OK. On the enhanced core, anything
12124 larger than 1 byte must start in even numbered register for "movw" to
12125 work (this way we don't have to check for odd registers everywhere). */
12126
12127 static bool
avr_hard_regno_mode_ok(unsigned int regno,machine_mode mode)12128 avr_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
12129 {
12130 /* NOTE: 8-bit values must not be disallowed for R28 or R29.
12131 Disallowing QI et al. in these regs might lead to code like
12132 (set (subreg:QI (reg:HI 28) n) ...)
12133 which will result in wrong code because reload does not
12134 handle SUBREGs of hard regsisters like this.
12135 This could be fixed in reload. However, it appears
12136 that fixing reload is not wanted by reload people. */
12137
12138 /* Any GENERAL_REGS register can hold 8-bit values. */
12139
12140 if (GET_MODE_SIZE (mode) == 1)
12141 return true;
12142
12143 /* FIXME: Ideally, the following test is not needed.
12144 However, it turned out that it can reduce the number
12145 of spill fails. AVR and it's poor endowment with
12146 address registers is extreme stress test for reload. */
12147
12148 if (GET_MODE_SIZE (mode) >= 4
12149 && regno >= REG_X)
12150 return false;
12151
12152 /* All modes larger than 8 bits should start in an even register. */
12153
12154 return !(regno & 1);
12155 }
12156
12157
12158 /* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED. */
12159
12160 static bool
avr_hard_regno_call_part_clobbered(unsigned,unsigned regno,machine_mode mode)12161 avr_hard_regno_call_part_clobbered (unsigned, unsigned regno,
12162 machine_mode mode)
12163 {
12164 /* FIXME: This hook gets called with MODE:REGNO combinations that don't
12165 represent valid hard registers like, e.g. HI:29. Returning TRUE
12166 for such registers can lead to performance degradation as mentioned
12167 in PR53595. Thus, report invalid hard registers as FALSE. */
12168
12169 if (!avr_hard_regno_mode_ok (regno, mode))
12170 return 0;
12171
12172 /* Return true if any of the following boundaries is crossed:
12173 17/18 or 19/20 (if AVR_TINY), 27/28 and 29/30. */
12174
12175 return ((regno <= LAST_CALLEE_SAVED_REG
12176 && regno + GET_MODE_SIZE (mode) > 1 + LAST_CALLEE_SAVED_REG)
12177 || (regno < REG_Y && regno + GET_MODE_SIZE (mode) > REG_Y)
12178 || (regno < REG_Z && regno + GET_MODE_SIZE (mode) > REG_Z));
12179 }
12180
12181
12182 /* Implement `MODE_CODE_BASE_REG_CLASS'. */
12183
12184 enum reg_class
avr_mode_code_base_reg_class(machine_mode mode ATTRIBUTE_UNUSED,addr_space_t as,RTX_CODE outer_code,RTX_CODE index_code ATTRIBUTE_UNUSED)12185 avr_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED,
12186 addr_space_t as, RTX_CODE outer_code,
12187 RTX_CODE index_code ATTRIBUTE_UNUSED)
12188 {
12189 if (!ADDR_SPACE_GENERIC_P (as))
12190 {
12191 return POINTER_Z_REGS;
12192 }
12193
12194 if (!avr_strict_X)
12195 return reload_completed ? BASE_POINTER_REGS : POINTER_REGS;
12196
12197 return PLUS == outer_code ? BASE_POINTER_REGS : POINTER_REGS;
12198 }
12199
12200
12201 /* Implement `REGNO_MODE_CODE_OK_FOR_BASE_P'. */
12202
12203 bool
avr_regno_mode_code_ok_for_base_p(int regno,machine_mode mode ATTRIBUTE_UNUSED,addr_space_t as ATTRIBUTE_UNUSED,RTX_CODE outer_code,RTX_CODE index_code ATTRIBUTE_UNUSED)12204 avr_regno_mode_code_ok_for_base_p (int regno,
12205 machine_mode mode ATTRIBUTE_UNUSED,
12206 addr_space_t as ATTRIBUTE_UNUSED,
12207 RTX_CODE outer_code,
12208 RTX_CODE index_code ATTRIBUTE_UNUSED)
12209 {
12210 bool ok = false;
12211
12212 if (!ADDR_SPACE_GENERIC_P (as))
12213 {
12214 if (regno < FIRST_PSEUDO_REGISTER
12215 && regno == REG_Z)
12216 {
12217 return true;
12218 }
12219
12220 if (reg_renumber)
12221 {
12222 regno = reg_renumber[regno];
12223
12224 if (regno == REG_Z)
12225 {
12226 return true;
12227 }
12228 }
12229
12230 return false;
12231 }
12232
12233 if (regno < FIRST_PSEUDO_REGISTER
12234 && (regno == REG_X
12235 || regno == REG_Y
12236 || regno == REG_Z
12237 || regno == ARG_POINTER_REGNUM))
12238 {
12239 ok = true;
12240 }
12241 else if (reg_renumber)
12242 {
12243 regno = reg_renumber[regno];
12244
12245 if (regno == REG_X
12246 || regno == REG_Y
12247 || regno == REG_Z
12248 || regno == ARG_POINTER_REGNUM)
12249 {
12250 ok = true;
12251 }
12252 }
12253
12254 if (avr_strict_X
12255 && PLUS == outer_code
12256 && regno == REG_X)
12257 {
12258 ok = false;
12259 }
12260
12261 return ok;
12262 }
12263
12264
12265 /* A helper for `output_reload_insisf' and `output_reload_inhi'. */
12266 /* Set 32-bit register OP[0] to compile-time constant OP[1].
12267 CLOBBER_REG is a QI clobber register or NULL_RTX.
12268 LEN == NULL: output instructions.
12269 LEN != NULL: set *LEN to the length of the instruction sequence
12270 (in words) printed with LEN = NULL.
12271 If CLEAR_P is true, OP[0] had been cleard to Zero already.
12272 If CLEAR_P is false, nothing is known about OP[0].
12273
12274 The effect on cc0 is as follows:
12275
12276 Load 0 to any register except ZERO_REG : NONE
12277 Load ld register with any value : NONE
12278 Anything else: : CLOBBER */
12279
12280 static void
output_reload_in_const(rtx * op,rtx clobber_reg,int * len,bool clear_p)12281 output_reload_in_const (rtx *op, rtx clobber_reg, int *len, bool clear_p)
12282 {
12283 rtx src = op[1];
12284 rtx dest = op[0];
12285 rtx xval, xdest[4];
12286 int ival[4];
12287 int clobber_val = 1234;
12288 bool cooked_clobber_p = false;
12289 bool set_p = false;
12290 machine_mode mode = GET_MODE (dest);
12291 int n_bytes = GET_MODE_SIZE (mode);
12292
12293 gcc_assert (REG_P (dest)
12294 && CONSTANT_P (src));
12295
12296 if (len)
12297 *len = 0;
12298
12299 /* (REG:SI 14) is special: It's neither in LD_REGS nor in NO_LD_REGS
12300 but has some subregs that are in LD_REGS. Use the MSB (REG:QI 17). */
12301
12302 if (REGNO (dest) < 16
12303 && REGNO (dest) + GET_MODE_SIZE (mode) > 16)
12304 {
12305 clobber_reg = all_regs_rtx[REGNO (dest) + n_bytes - 1];
12306 }
12307
12308 /* We might need a clobber reg but don't have one. Look at the value to
12309 be loaded more closely. A clobber is only needed if it is a symbol
12310 or contains a byte that is neither 0, -1 or a power of 2. */
12311
12312 if (NULL_RTX == clobber_reg
12313 && !test_hard_reg_class (LD_REGS, dest)
12314 && (! (CONST_INT_P (src) || CONST_FIXED_P (src) || CONST_DOUBLE_P (src))
12315 || !avr_popcount_each_byte (src, n_bytes,
12316 (1 << 0) | (1 << 1) | (1 << 8))))
12317 {
12318 /* We have no clobber register but need one. Cook one up.
12319 That's cheaper than loading from constant pool. */
12320
12321 cooked_clobber_p = true;
12322 clobber_reg = all_regs_rtx[REG_Z + 1];
12323 avr_asm_len ("mov __tmp_reg__,%0", &clobber_reg, len, 1);
12324 }
12325
12326 /* Now start filling DEST from LSB to MSB. */
12327
12328 for (int n = 0; n < n_bytes; n++)
12329 {
12330 int ldreg_p;
12331 bool done_byte = false;
12332 rtx xop[3];
12333
12334 /* Crop the n-th destination byte. */
12335
12336 xdest[n] = simplify_gen_subreg (QImode, dest, mode, n);
12337 ldreg_p = test_hard_reg_class (LD_REGS, xdest[n]);
12338
12339 if (!CONST_INT_P (src)
12340 && !CONST_FIXED_P (src)
12341 && !CONST_DOUBLE_P (src))
12342 {
12343 static const char* const asm_code[][2] =
12344 {
12345 { "ldi %2,lo8(%1)" CR_TAB "mov %0,%2", "ldi %0,lo8(%1)" },
12346 { "ldi %2,hi8(%1)" CR_TAB "mov %0,%2", "ldi %0,hi8(%1)" },
12347 { "ldi %2,hlo8(%1)" CR_TAB "mov %0,%2", "ldi %0,hlo8(%1)" },
12348 { "ldi %2,hhi8(%1)" CR_TAB "mov %0,%2", "ldi %0,hhi8(%1)" }
12349 };
12350
12351 xop[0] = xdest[n];
12352 xop[1] = src;
12353 xop[2] = clobber_reg;
12354
12355 avr_asm_len (asm_code[n][ldreg_p], xop, len, ldreg_p ? 1 : 2);
12356
12357 continue;
12358 }
12359
12360 /* Crop the n-th source byte. */
12361
12362 xval = simplify_gen_subreg (QImode, src, mode, n);
12363 ival[n] = INTVAL (xval);
12364
12365 /* Look if we can reuse the low word by means of MOVW. */
12366
12367 if (n == 2
12368 && n_bytes >= 4
12369 && AVR_HAVE_MOVW)
12370 {
12371 rtx lo16 = simplify_gen_subreg (HImode, src, mode, 0);
12372 rtx hi16 = simplify_gen_subreg (HImode, src, mode, 2);
12373
12374 if (INTVAL (lo16) == INTVAL (hi16))
12375 {
12376 if (INTVAL (lo16) != 0 || !clear_p)
12377 avr_asm_len ("movw %C0,%A0", &op[0], len, 1);
12378
12379 break;
12380 }
12381 }
12382
12383 /* Don't use CLR so that cc0 is set as expected. */
12384
12385 if (ival[n] == 0)
12386 {
12387 if (!clear_p)
12388 avr_asm_len (ldreg_p ? "ldi %0,0"
12389 : AVR_ZERO_REGNO == REGNO (xdest[n]) ? "clr %0"
12390 : "mov %0,__zero_reg__",
12391 &xdest[n], len, 1);
12392 continue;
12393 }
12394
12395 if (clobber_val == ival[n]
12396 && REGNO (clobber_reg) == REGNO (xdest[n]))
12397 {
12398 continue;
12399 }
12400
12401 /* LD_REGS can use LDI to move a constant value */
12402
12403 if (ldreg_p)
12404 {
12405 xop[0] = xdest[n];
12406 xop[1] = xval;
12407 avr_asm_len ("ldi %0,lo8(%1)", xop, len, 1);
12408 continue;
12409 }
12410
12411 /* Try to reuse value already loaded in some lower byte. */
12412
12413 for (int j = 0; j < n; j++)
12414 if (ival[j] == ival[n])
12415 {
12416 xop[0] = xdest[n];
12417 xop[1] = xdest[j];
12418
12419 avr_asm_len ("mov %0,%1", xop, len, 1);
12420 done_byte = true;
12421 break;
12422 }
12423
12424 if (done_byte)
12425 continue;
12426
12427 /* Need no clobber reg for -1: Use CLR/DEC */
12428
12429 if (ival[n] == -1)
12430 {
12431 if (!clear_p)
12432 avr_asm_len ("clr %0", &xdest[n], len, 1);
12433
12434 avr_asm_len ("dec %0", &xdest[n], len, 1);
12435 continue;
12436 }
12437 else if (ival[n] == 1)
12438 {
12439 if (!clear_p)
12440 avr_asm_len ("clr %0", &xdest[n], len, 1);
12441
12442 avr_asm_len ("inc %0", &xdest[n], len, 1);
12443 continue;
12444 }
12445
12446 /* Use T flag or INC to manage powers of 2 if we have
12447 no clobber reg. */
12448
12449 if (NULL_RTX == clobber_reg
12450 && single_one_operand (xval, QImode))
12451 {
12452 xop[0] = xdest[n];
12453 xop[1] = GEN_INT (exact_log2 (ival[n] & GET_MODE_MASK (QImode)));
12454
12455 gcc_assert (constm1_rtx != xop[1]);
12456
12457 if (!set_p)
12458 {
12459 set_p = true;
12460 avr_asm_len ("set", xop, len, 1);
12461 }
12462
12463 if (!clear_p)
12464 avr_asm_len ("clr %0", xop, len, 1);
12465
12466 avr_asm_len ("bld %0,%1", xop, len, 1);
12467 continue;
12468 }
12469
12470 /* We actually need the LD_REGS clobber reg. */
12471
12472 gcc_assert (NULL_RTX != clobber_reg);
12473
12474 xop[0] = xdest[n];
12475 xop[1] = xval;
12476 xop[2] = clobber_reg;
12477 clobber_val = ival[n];
12478
12479 avr_asm_len ("ldi %2,lo8(%1)" CR_TAB
12480 "mov %0,%2", xop, len, 2);
12481 }
12482
12483 /* If we cooked up a clobber reg above, restore it. */
12484
12485 if (cooked_clobber_p)
12486 {
12487 avr_asm_len ("mov %0,__tmp_reg__", &clobber_reg, len, 1);
12488 }
12489 }
12490
12491
12492 /* Reload the constant OP[1] into the HI register OP[0].
12493 CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
12494 into a NO_LD_REGS register. If CLOBBER_REG is NULL_RTX we either don't
12495 need a clobber reg or have to cook one up.
12496
12497 PLEN == NULL: Output instructions.
12498 PLEN != NULL: Output nothing. Set *PLEN to number of words occupied
12499 by the insns printed.
12500
12501 Return "". */
12502
12503 const char*
output_reload_inhi(rtx * op,rtx clobber_reg,int * plen)12504 output_reload_inhi (rtx *op, rtx clobber_reg, int *plen)
12505 {
12506 output_reload_in_const (op, clobber_reg, plen, false);
12507 return "";
12508 }
12509
12510
12511 /* Reload a SI or SF compile time constant OP[1] into the register OP[0].
12512 CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
12513 into a NO_LD_REGS register. If CLOBBER_REG is NULL_RTX we either don't
12514 need a clobber reg or have to cook one up.
12515
12516 LEN == NULL: Output instructions.
12517
12518 LEN != NULL: Output nothing. Set *LEN to number of words occupied
12519 by the insns printed.
12520
12521 Return "". */
12522
12523 const char *
output_reload_insisf(rtx * op,rtx clobber_reg,int * len)12524 output_reload_insisf (rtx *op, rtx clobber_reg, int *len)
12525 {
12526 if (AVR_HAVE_MOVW
12527 && !test_hard_reg_class (LD_REGS, op[0])
12528 && (CONST_INT_P (op[1])
12529 || CONST_FIXED_P (op[1])
12530 || CONST_DOUBLE_P (op[1])))
12531 {
12532 int len_clr, len_noclr;
12533
12534 /* In some cases it is better to clear the destination beforehand, e.g.
12535
12536 CLR R2 CLR R3 MOVW R4,R2 INC R2
12537
12538 is shorther than
12539
12540 CLR R2 INC R2 CLR R3 CLR R4 CLR R5
12541
12542 We find it too tedious to work that out in the print function.
12543 Instead, we call the print function twice to get the lengths of
12544 both methods and use the shortest one. */
12545
12546 output_reload_in_const (op, clobber_reg, &len_clr, true);
12547 output_reload_in_const (op, clobber_reg, &len_noclr, false);
12548
12549 if (len_noclr - len_clr == 4)
12550 {
12551 /* Default needs 4 CLR instructions: clear register beforehand. */
12552
12553 avr_asm_len ("mov %A0,__zero_reg__" CR_TAB
12554 "mov %B0,__zero_reg__" CR_TAB
12555 "movw %C0,%A0", &op[0], len, 3);
12556
12557 output_reload_in_const (op, clobber_reg, len, true);
12558
12559 if (len)
12560 *len += 3;
12561
12562 return "";
12563 }
12564 }
12565
12566 /* Default: destination not pre-cleared. */
12567
12568 output_reload_in_const (op, clobber_reg, len, false);
12569 return "";
12570 }
12571
12572 const char*
avr_out_reload_inpsi(rtx * op,rtx clobber_reg,int * len)12573 avr_out_reload_inpsi (rtx *op, rtx clobber_reg, int *len)
12574 {
12575 output_reload_in_const (op, clobber_reg, len, false);
12576 return "";
12577 }
12578
12579
12580 /* Worker function for `ASM_OUTPUT_ADDR_VEC'. */
12581 /* Emit jump tables out-of-line so that branches crossing the table
12582 get shorter offsets. If we have JUMP + CALL, then put the tables
12583 in a dedicated non-.text section so that CALLs get better chance to
12584 be relaxed to RCALLs.
12585
12586 We emit the tables by hand because `function_rodata_section' does not
12587 work as expected, cf. PR71151, and we do *NOT* want the table to be
12588 in .rodata, hence setting JUMP_TABLES_IN_TEXT_SECTION = 0 is of limited
12589 use; and setting it to 1 attributes table lengths to branch offsets...
12590 Moreover, fincal.c keeps switching section before each table entry
12591 which we find too fragile as to rely on section caching. */
12592
12593 void
avr_output_addr_vec(rtx_insn * labl,rtx table)12594 avr_output_addr_vec (rtx_insn *labl, rtx table)
12595 {
12596 FILE *stream = asm_out_file;
12597
12598 app_disable();
12599
12600 // Switch to appropriate (sub)section.
12601
12602 if (DECL_SECTION_NAME (current_function_decl)
12603 && symtab_node::get (current_function_decl)
12604 && ! symtab_node::get (current_function_decl)->implicit_section)
12605 {
12606 // .subsection will emit the code after the function and in the
12607 // section as chosen by the user.
12608
12609 switch_to_section (current_function_section ());
12610 fprintf (stream, "\t.subsection\t1\n");
12611 }
12612 else
12613 {
12614 // Since PR63223 there is no restriction where to put the table; it
12615 // may even reside above 128 KiB. We put it in a section as high as
12616 // possible and avoid progmem in order not to waste flash <= 64 KiB.
12617
12618 const char *sec_name = ".jumptables.gcc";
12619
12620 // The table belongs to its host function, therefore use fine
12621 // grained sections so that, if that function is removed by
12622 // --gc-sections, the child table(s) may also be removed. */
12623
12624 tree asm_name = DECL_ASSEMBLER_NAME (current_function_decl);
12625 const char *fname = IDENTIFIER_POINTER (asm_name);
12626 fname = targetm.strip_name_encoding (fname);
12627 sec_name = ACONCAT ((sec_name, ".", fname, NULL));
12628
12629 fprintf (stream, "\t.section\t%s,\"%s\",@progbits\n", sec_name,
12630 AVR_HAVE_JMP_CALL ? "a" : "ax");
12631 }
12632
12633 // Output the label that preceeds the table.
12634
12635 ASM_OUTPUT_ALIGN (stream, 1);
12636 targetm.asm_out.internal_label (stream, "L", CODE_LABEL_NUMBER (labl));
12637
12638 // Output the table's content.
12639
12640 int vlen = XVECLEN (table, 0);
12641
12642 for (int idx = 0; idx < vlen; idx++)
12643 {
12644 int value = CODE_LABEL_NUMBER (XEXP (XVECEXP (table, 0, idx), 0));
12645
12646 if (AVR_HAVE_JMP_CALL)
12647 fprintf (stream, "\t.word gs(.L%d)\n", value);
12648 else
12649 fprintf (stream, "\trjmp .L%d\n", value);
12650 }
12651
12652 // Switch back to original section. As we clobbered the section above,
12653 // forget the current section before switching back.
12654
12655 in_section = NULL;
12656 switch_to_section (current_function_section ());
12657 }
12658
12659
12660 /* Implement `TARGET_CONDITIONAL_REGISTER_USAGE'. */
12661
12662 static void
avr_conditional_register_usage(void)12663 avr_conditional_register_usage (void)
12664 {
12665 if (AVR_TINY)
12666 {
12667 const int tiny_reg_alloc_order[] = {
12668 24, 25,
12669 22, 23,
12670 30, 31,
12671 26, 27,
12672 28, 29,
12673 21, 20, 19, 18,
12674 16, 17,
12675 32, 33, 34, 35,
12676 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
12677 };
12678
12679 /* Set R0-R17 as fixed registers. Reset R0-R17 in call used register list
12680 - R0-R15 are not available in Tiny Core devices
12681 - R16 and R17 are fixed registers. */
12682
12683 for (size_t i = 0; i <= 17; i++)
12684 {
12685 fixed_regs[i] = 1;
12686 call_used_regs[i] = 1;
12687 }
12688
12689 /* Set R18 to R21 as callee saved registers
12690 - R18, R19, R20 and R21 are the callee saved registers in
12691 Tiny Core devices */
12692
12693 for (size_t i = 18; i <= LAST_CALLEE_SAVED_REG; i++)
12694 {
12695 call_used_regs[i] = 0;
12696 }
12697
12698 /* Update register allocation order for Tiny Core devices */
12699
12700 for (size_t i = 0; i < ARRAY_SIZE (tiny_reg_alloc_order); i++)
12701 {
12702 reg_alloc_order[i] = tiny_reg_alloc_order[i];
12703 }
12704
12705 CLEAR_HARD_REG_SET (reg_class_contents[(int) ADDW_REGS]);
12706 CLEAR_HARD_REG_SET (reg_class_contents[(int) NO_LD_REGS]);
12707 }
12708 }
12709
12710 /* Implement `TARGET_HARD_REGNO_SCRATCH_OK'. */
12711 /* Returns true if SCRATCH are safe to be allocated as a scratch
12712 registers (for a define_peephole2) in the current function. */
12713
12714 static bool
avr_hard_regno_scratch_ok(unsigned int regno)12715 avr_hard_regno_scratch_ok (unsigned int regno)
12716 {
12717 /* Interrupt functions can only use registers that have already been saved
12718 by the prologue, even if they would normally be call-clobbered. */
12719
12720 if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
12721 && !df_regs_ever_live_p (regno))
12722 return false;
12723
12724 /* Don't allow hard registers that might be part of the frame pointer.
12725 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
12726 and don't care for a frame pointer that spans more than one register. */
12727
12728 if ((!reload_completed || frame_pointer_needed)
12729 && (regno == REG_Y || regno == REG_Y + 1))
12730 {
12731 return false;
12732 }
12733
12734 return true;
12735 }
12736
12737
12738 /* Worker function for `HARD_REGNO_RENAME_OK'. */
12739 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
12740
12741 int
avr_hard_regno_rename_ok(unsigned int old_reg,unsigned int new_reg)12742 avr_hard_regno_rename_ok (unsigned int old_reg,
12743 unsigned int new_reg)
12744 {
12745 /* Interrupt functions can only use registers that have already been
12746 saved by the prologue, even if they would normally be
12747 call-clobbered. */
12748
12749 if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
12750 && !df_regs_ever_live_p (new_reg))
12751 return 0;
12752
12753 /* Don't allow hard registers that might be part of the frame pointer.
12754 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
12755 and don't care for a frame pointer that spans more than one register. */
12756
12757 if ((!reload_completed || frame_pointer_needed)
12758 && (old_reg == REG_Y || old_reg == REG_Y + 1
12759 || new_reg == REG_Y || new_reg == REG_Y + 1))
12760 {
12761 return 0;
12762 }
12763
12764 return 1;
12765 }
12766
12767 /* Output a branch that tests a single bit of a register (QI, HI, SI or DImode)
12768 or memory location in the I/O space (QImode only).
12769
12770 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
12771 Operand 1: register operand to test, or CONST_INT memory address.
12772 Operand 2: bit number.
12773 Operand 3: label to jump to if the test is true. */
12774
12775 const char*
avr_out_sbxx_branch(rtx_insn * insn,rtx operands[])12776 avr_out_sbxx_branch (rtx_insn *insn, rtx operands[])
12777 {
12778 enum rtx_code comp = GET_CODE (operands[0]);
12779 bool long_jump = get_attr_length (insn) >= 4;
12780 bool reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
12781
12782 if (comp == GE)
12783 comp = EQ;
12784 else if (comp == LT)
12785 comp = NE;
12786
12787 if (reverse)
12788 comp = reverse_condition (comp);
12789
12790 switch (GET_CODE (operands[1]))
12791 {
12792 default:
12793 gcc_unreachable();
12794
12795 case CONST_INT:
12796 case CONST:
12797 case SYMBOL_REF:
12798
12799 if (low_io_address_operand (operands[1], QImode))
12800 {
12801 if (comp == EQ)
12802 output_asm_insn ("sbis %i1,%2", operands);
12803 else
12804 output_asm_insn ("sbic %i1,%2", operands);
12805 }
12806 else
12807 {
12808 gcc_assert (io_address_operand (operands[1], QImode));
12809 output_asm_insn ("in __tmp_reg__,%i1", operands);
12810 if (comp == EQ)
12811 output_asm_insn ("sbrs __tmp_reg__,%2", operands);
12812 else
12813 output_asm_insn ("sbrc __tmp_reg__,%2", operands);
12814 }
12815
12816 break; /* CONST_INT */
12817
12818 case REG:
12819
12820 if (comp == EQ)
12821 output_asm_insn ("sbrs %T1%T2", operands);
12822 else
12823 output_asm_insn ("sbrc %T1%T2", operands);
12824
12825 break; /* REG */
12826 } /* switch */
12827
12828 if (long_jump)
12829 return ("rjmp .+4" CR_TAB
12830 "jmp %x3");
12831
12832 if (!reverse)
12833 return "rjmp %x3";
12834
12835 return "";
12836 }
12837
12838 /* Worker function for `TARGET_ASM_CONSTRUCTOR'. */
12839
12840 static void
avr_asm_out_ctor(rtx symbol,int priority)12841 avr_asm_out_ctor (rtx symbol, int priority)
12842 {
12843 fputs ("\t.global __do_global_ctors\n", asm_out_file);
12844 default_ctor_section_asm_out_constructor (symbol, priority);
12845 }
12846
12847
12848 /* Worker function for `TARGET_ASM_DESTRUCTOR'. */
12849
12850 static void
avr_asm_out_dtor(rtx symbol,int priority)12851 avr_asm_out_dtor (rtx symbol, int priority)
12852 {
12853 fputs ("\t.global __do_global_dtors\n", asm_out_file);
12854 default_dtor_section_asm_out_destructor (symbol, priority);
12855 }
12856
12857
12858 /* Worker function for `TARGET_RETURN_IN_MEMORY'. */
12859
12860 static bool
avr_return_in_memory(const_tree type,const_tree fntype ATTRIBUTE_UNUSED)12861 avr_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
12862 {
12863 HOST_WIDE_INT size = int_size_in_bytes (type);
12864 HOST_WIDE_INT ret_size_limit = AVR_TINY ? 4 : 8;
12865
12866 /* In avr, there are 8 return registers. But, for Tiny Core
12867 (ATtiny4/5/9/10/20/40) devices, only 4 registers are available.
12868 Return true if size is unknown or greater than the limit. */
12869
12870 if (size == -1 || size > ret_size_limit)
12871 {
12872 return true;
12873 }
12874 else
12875 {
12876 return false;
12877 }
12878 }
12879
12880
12881 /* Implement `CASE_VALUES_THRESHOLD'. */
12882 /* Supply the default for --param case-values-threshold=0 */
12883
12884 static unsigned int
avr_case_values_threshold(void)12885 avr_case_values_threshold (void)
12886 {
12887 /* The exact break-even point between a jump table and an if-else tree
12888 depends on several factors not available here like, e.g. if 8-bit
12889 comparisons can be used in the if-else tree or not, on the
12890 range of the case values, if the case value can be reused, on the
12891 register allocation, etc. '7' appears to be a good choice. */
12892
12893 return 7;
12894 }
12895
12896
12897 /* Implement `TARGET_ADDR_SPACE_ADDRESS_MODE'. */
12898
12899 static scalar_int_mode
avr_addr_space_address_mode(addr_space_t as)12900 avr_addr_space_address_mode (addr_space_t as)
12901 {
12902 return avr_addrspace[as].pointer_size == 3 ? PSImode : HImode;
12903 }
12904
12905
12906 /* Implement `TARGET_ADDR_SPACE_POINTER_MODE'. */
12907
12908 static scalar_int_mode
avr_addr_space_pointer_mode(addr_space_t as)12909 avr_addr_space_pointer_mode (addr_space_t as)
12910 {
12911 return avr_addr_space_address_mode (as);
12912 }
12913
12914
12915 /* Helper for following function. */
12916
12917 static bool
avr_reg_ok_for_pgm_addr(rtx reg,bool strict)12918 avr_reg_ok_for_pgm_addr (rtx reg, bool strict)
12919 {
12920 gcc_assert (REG_P (reg));
12921
12922 if (strict)
12923 {
12924 return REGNO (reg) == REG_Z;
12925 }
12926
12927 /* Avoid combine to propagate hard regs. */
12928
12929 if (can_create_pseudo_p()
12930 && REGNO (reg) < REG_Z)
12931 {
12932 return false;
12933 }
12934
12935 return true;
12936 }
12937
12938
12939 /* Implement `TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P'. */
12940
12941 static bool
avr_addr_space_legitimate_address_p(machine_mode mode,rtx x,bool strict,addr_space_t as)12942 avr_addr_space_legitimate_address_p (machine_mode mode, rtx x,
12943 bool strict, addr_space_t as)
12944 {
12945 bool ok = false;
12946
12947 switch (as)
12948 {
12949 default:
12950 gcc_unreachable();
12951
12952 case ADDR_SPACE_GENERIC:
12953 return avr_legitimate_address_p (mode, x, strict);
12954
12955 case ADDR_SPACE_FLASH:
12956 case ADDR_SPACE_FLASH1:
12957 case ADDR_SPACE_FLASH2:
12958 case ADDR_SPACE_FLASH3:
12959 case ADDR_SPACE_FLASH4:
12960 case ADDR_SPACE_FLASH5:
12961
12962 switch (GET_CODE (x))
12963 {
12964 case REG:
12965 ok = avr_reg_ok_for_pgm_addr (x, strict);
12966 break;
12967
12968 case POST_INC:
12969 ok = avr_reg_ok_for_pgm_addr (XEXP (x, 0), strict);
12970 break;
12971
12972 default:
12973 break;
12974 }
12975
12976 break; /* FLASH */
12977
12978 case ADDR_SPACE_MEMX:
12979 if (REG_P (x))
12980 ok = (!strict
12981 && can_create_pseudo_p());
12982
12983 if (LO_SUM == GET_CODE (x))
12984 {
12985 rtx hi = XEXP (x, 0);
12986 rtx lo = XEXP (x, 1);
12987
12988 ok = (REG_P (hi)
12989 && (!strict || REGNO (hi) < FIRST_PSEUDO_REGISTER)
12990 && REG_P (lo)
12991 && REGNO (lo) == REG_Z);
12992 }
12993
12994 break; /* MEMX */
12995 }
12996
12997 if (avr_log.legitimate_address_p)
12998 {
12999 avr_edump ("\n%?: ret=%b, mode=%m strict=%d "
13000 "reload_completed=%d reload_in_progress=%d %s:",
13001 ok, mode, strict, reload_completed, reload_in_progress,
13002 reg_renumber ? "(reg_renumber)" : "");
13003
13004 if (GET_CODE (x) == PLUS
13005 && REG_P (XEXP (x, 0))
13006 && CONST_INT_P (XEXP (x, 1))
13007 && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
13008 && reg_renumber)
13009 {
13010 avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
13011 true_regnum (XEXP (x, 0)));
13012 }
13013
13014 avr_edump ("\n%r\n", x);
13015 }
13016
13017 return ok;
13018 }
13019
13020
13021 /* Implement `TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS'. */
13022
13023 static rtx
avr_addr_space_legitimize_address(rtx x,rtx old_x,machine_mode mode,addr_space_t as)13024 avr_addr_space_legitimize_address (rtx x, rtx old_x,
13025 machine_mode mode, addr_space_t as)
13026 {
13027 if (ADDR_SPACE_GENERIC_P (as))
13028 return avr_legitimize_address (x, old_x, mode);
13029
13030 if (avr_log.legitimize_address)
13031 {
13032 avr_edump ("\n%?: mode=%m\n %r\n", mode, old_x);
13033 }
13034
13035 return old_x;
13036 }
13037
13038
13039 /* Implement `TARGET_ADDR_SPACE_CONVERT'. */
13040
13041 static rtx
avr_addr_space_convert(rtx src,tree type_from,tree type_to)13042 avr_addr_space_convert (rtx src, tree type_from, tree type_to)
13043 {
13044 addr_space_t as_from = TYPE_ADDR_SPACE (TREE_TYPE (type_from));
13045 addr_space_t as_to = TYPE_ADDR_SPACE (TREE_TYPE (type_to));
13046
13047 if (avr_log.progmem)
13048 avr_edump ("\n%!: op = %r\nfrom = %t\nto = %t\n",
13049 src, type_from, type_to);
13050
13051 /* Up-casting from 16-bit to 24-bit pointer. */
13052
13053 if (as_from != ADDR_SPACE_MEMX
13054 && as_to == ADDR_SPACE_MEMX)
13055 {
13056 int msb;
13057 rtx sym = src;
13058 rtx reg = gen_reg_rtx (PSImode);
13059
13060 while (CONST == GET_CODE (sym) || PLUS == GET_CODE (sym))
13061 sym = XEXP (sym, 0);
13062
13063 /* Look at symbol flags: avr_encode_section_info set the flags
13064 also if attribute progmem was seen so that we get the right
13065 promotion for, e.g. PSTR-like strings that reside in generic space
13066 but are located in flash. In that case we patch the incoming
13067 address space. */
13068
13069 if (SYMBOL_REF_P (sym)
13070 && ADDR_SPACE_FLASH == AVR_SYMBOL_GET_ADDR_SPACE (sym))
13071 {
13072 as_from = ADDR_SPACE_FLASH;
13073 }
13074
13075 /* Linearize memory: RAM has bit 23 set. */
13076
13077 msb = ADDR_SPACE_GENERIC_P (as_from)
13078 ? 0x80
13079 : avr_addrspace[as_from].segment;
13080
13081 src = force_reg (Pmode, src);
13082
13083 emit_insn (msb == 0
13084 ? gen_zero_extendhipsi2 (reg, src)
13085 : gen_n_extendhipsi2 (reg, gen_int_mode (msb, QImode), src));
13086
13087 return reg;
13088 }
13089
13090 /* Down-casting from 24-bit to 16-bit throws away the high byte. */
13091
13092 if (as_from == ADDR_SPACE_MEMX
13093 && as_to != ADDR_SPACE_MEMX)
13094 {
13095 rtx new_src = gen_reg_rtx (Pmode);
13096
13097 src = force_reg (PSImode, src);
13098
13099 emit_move_insn (new_src,
13100 simplify_gen_subreg (Pmode, src, PSImode, 0));
13101 return new_src;
13102 }
13103
13104 return src;
13105 }
13106
13107
13108 /* Implement `TARGET_ADDR_SPACE_SUBSET_P'. */
13109
13110 static bool
avr_addr_space_subset_p(addr_space_t subset ATTRIBUTE_UNUSED,addr_space_t superset ATTRIBUTE_UNUSED)13111 avr_addr_space_subset_p (addr_space_t subset ATTRIBUTE_UNUSED,
13112 addr_space_t superset ATTRIBUTE_UNUSED)
13113 {
13114 /* Allow any kind of pointer mess. */
13115
13116 return true;
13117 }
13118
13119
13120 /* Implement `TARGET_CONVERT_TO_TYPE'. */
13121
13122 static tree
avr_convert_to_type(tree type,tree expr)13123 avr_convert_to_type (tree type, tree expr)
13124 {
13125 /* Print a diagnose for pointer conversion that changes the address
13126 space of the pointer target to a non-enclosing address space,
13127 provided -Waddr-space-convert is on.
13128
13129 FIXME: Filter out cases where the target object is known to
13130 be located in the right memory, like in
13131
13132 (const __flash*) PSTR ("text")
13133
13134 Also try to distinguish between explicit casts requested by
13135 the user and implicit casts like
13136
13137 void f (const __flash char*);
13138
13139 void g (const char *p)
13140 {
13141 f ((const __flash*) p);
13142 }
13143
13144 under the assumption that an explicit casts means that the user
13145 knows what he is doing, e.g. interface with PSTR or old style
13146 code with progmem and pgm_read_xxx.
13147 */
13148
13149 if (avr_warn_addr_space_convert
13150 && expr != error_mark_node
13151 && POINTER_TYPE_P (type)
13152 && POINTER_TYPE_P (TREE_TYPE (expr)))
13153 {
13154 addr_space_t as_old = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (expr)));
13155 addr_space_t as_new = TYPE_ADDR_SPACE (TREE_TYPE (type));
13156
13157 if (avr_log.progmem)
13158 avr_edump ("%?: type = %t\nexpr = %t\n\n", type, expr);
13159
13160 if (as_new != ADDR_SPACE_MEMX
13161 && as_new != as_old)
13162 {
13163 location_t loc = EXPR_LOCATION (expr);
13164 const char *name_old = avr_addrspace[as_old].name;
13165 const char *name_new = avr_addrspace[as_new].name;
13166
13167 warning (OPT_Waddr_space_convert,
13168 "conversion from address space %qs to address space %qs",
13169 ADDR_SPACE_GENERIC_P (as_old) ? "generic" : name_old,
13170 ADDR_SPACE_GENERIC_P (as_new) ? "generic" : name_new);
13171
13172 return fold_build1_loc (loc, ADDR_SPACE_CONVERT_EXPR, type, expr);
13173 }
13174 }
13175
13176 return NULL_TREE;
13177 }
13178
13179
13180 /* Implement `TARGET_LEGITIMATE_COMBINED_INSN'. */
13181
13182 /* PR78883: Filter out paradoxical SUBREGs of MEM which are not handled
13183 properly by following passes. As INSN_SCHEDULING is off and hence
13184 general_operand accepts such expressions, ditch them now. */
13185
13186 static bool
avr_legitimate_combined_insn(rtx_insn * insn)13187 avr_legitimate_combined_insn (rtx_insn *insn)
13188 {
13189 subrtx_iterator::array_type array;
13190
13191 FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
13192 {
13193 const_rtx op = *iter;
13194
13195 if (SUBREG_P (op)
13196 && MEM_P (SUBREG_REG (op))
13197 && (GET_MODE_SIZE (GET_MODE (op))
13198 > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))))
13199 {
13200 return false;
13201 }
13202 }
13203
13204 return true;
13205 }
13206
13207
13208 /* PR63633: The middle-end might come up with hard regs as input operands.
13209
13210 RMASK is a bit mask representing a subset of hard registers R0...R31:
13211 Rn is an element of that set iff bit n of RMASK is set.
13212 OPMASK describes a subset of OP[]: If bit n of OPMASK is 1 then
13213 OP[n] has to be fixed; otherwise OP[n] is left alone.
13214
13215 For each element of OPMASK which is a hard register overlapping RMASK,
13216 replace OP[n] with a newly created pseudo register
13217
13218 HREG == 0: Also emit a move insn that copies the contents of that
13219 hard register into the new pseudo.
13220
13221 HREG != 0: Also set HREG[n] to the hard register. */
13222
13223 static void
avr_fix_operands(rtx * op,rtx * hreg,unsigned opmask,unsigned rmask)13224 avr_fix_operands (rtx *op, rtx *hreg, unsigned opmask, unsigned rmask)
13225 {
13226 for (; opmask; opmask >>= 1, op++)
13227 {
13228 rtx reg = *op;
13229
13230 if (hreg)
13231 *hreg = NULL_RTX;
13232
13233 if ((opmask & 1)
13234 && REG_P (reg)
13235 && REGNO (reg) < FIRST_PSEUDO_REGISTER
13236 // This hard-reg overlaps other prohibited hard regs?
13237 && (rmask & regmask (GET_MODE (reg), REGNO (reg))))
13238 {
13239 *op = gen_reg_rtx (GET_MODE (reg));
13240 if (hreg == NULL)
13241 emit_move_insn (*op, reg);
13242 else
13243 *hreg = reg;
13244 }
13245
13246 if (hreg)
13247 hreg++;
13248 }
13249 }
13250
13251
13252 void
avr_fix_inputs(rtx * op,unsigned opmask,unsigned rmask)13253 avr_fix_inputs (rtx *op, unsigned opmask, unsigned rmask)
13254 {
13255 avr_fix_operands (op, NULL, opmask, rmask);
13256 }
13257
13258
13259 /* Helper for the function below: If bit n of MASK is set and
13260 HREG[n] != NULL, then emit a move insn to copy OP[n] to HREG[n].
13261 Otherwise do nothing for that n. Return TRUE. */
13262
13263 static bool
avr_move_fixed_operands(rtx * op,rtx * hreg,unsigned mask)13264 avr_move_fixed_operands (rtx *op, rtx *hreg, unsigned mask)
13265 {
13266 for (; mask; mask >>= 1, op++, hreg++)
13267 if ((mask & 1)
13268 && *hreg)
13269 emit_move_insn (*hreg, *op);
13270
13271 return true;
13272 }
13273
13274
13275 /* PR63633: The middle-end might come up with hard regs as output operands.
13276
13277 GEN is a sequence generating function like gen_mulsi3 with 3 operands OP[].
13278 RMASK is a bit mask representing a subset of hard registers R0...R31:
13279 Rn is an element of that set iff bit n of RMASK is set.
13280 OPMASK describes a subset of OP[]: If bit n of OPMASK is 1 then
13281 OP[n] has to be fixed; otherwise OP[n] is left alone.
13282
13283 Emit the insn sequence as generated by GEN() with all elements of OPMASK
13284 which are hard registers overlapping RMASK replaced by newly created
13285 pseudo registers. After the sequence has been emitted, emit insns that
13286 move the contents of respective pseudos to their hard regs. */
13287
13288 bool
avr_emit3_fix_outputs(rtx (* gen)(rtx,rtx,rtx),rtx * op,unsigned opmask,unsigned rmask)13289 avr_emit3_fix_outputs (rtx (*gen)(rtx,rtx,rtx), rtx *op,
13290 unsigned opmask, unsigned rmask)
13291 {
13292 const int n = 3;
13293 rtx hreg[n];
13294
13295 /* It is letigimate for GEN to call this function, and in order not to
13296 get self-recursive we use the following static kludge. This is the
13297 only way not to duplicate all expanders and to avoid ugly and
13298 hard-to-maintain C-code instead of the much more appreciated RTL
13299 representation as supplied by define_expand. */
13300 static bool lock = false;
13301
13302 gcc_assert (opmask < (1u << n));
13303
13304 if (lock)
13305 return false;
13306
13307 avr_fix_operands (op, hreg, opmask, rmask);
13308
13309 lock = true;
13310 emit_insn (gen (op[0], op[1], op[2]));
13311 lock = false;
13312
13313 return avr_move_fixed_operands (op, hreg, opmask);
13314 }
13315
13316
13317 /* Worker function for cpymemhi expander.
13318 XOP[0] Destination as MEM:BLK
13319 XOP[1] Source " "
13320 XOP[2] # Bytes to copy
13321
13322 Return TRUE if the expansion is accomplished.
13323 Return FALSE if the operand compination is not supported. */
13324
13325 bool
avr_emit_cpymemhi(rtx * xop)13326 avr_emit_cpymemhi (rtx *xop)
13327 {
13328 HOST_WIDE_INT count;
13329 machine_mode loop_mode;
13330 addr_space_t as = MEM_ADDR_SPACE (xop[1]);
13331 rtx loop_reg, addr1, a_src, a_dest, insn, xas;
13332 rtx a_hi8 = NULL_RTX;
13333
13334 if (avr_mem_flash_p (xop[0]))
13335 return false;
13336
13337 if (!CONST_INT_P (xop[2]))
13338 return false;
13339
13340 count = INTVAL (xop[2]);
13341 if (count <= 0)
13342 return false;
13343
13344 a_src = XEXP (xop[1], 0);
13345 a_dest = XEXP (xop[0], 0);
13346
13347 if (PSImode == GET_MODE (a_src))
13348 {
13349 gcc_assert (as == ADDR_SPACE_MEMX);
13350
13351 loop_mode = (count < 0x100) ? QImode : HImode;
13352 loop_reg = gen_rtx_REG (loop_mode, 24);
13353 emit_move_insn (loop_reg, gen_int_mode (count, loop_mode));
13354
13355 addr1 = simplify_gen_subreg (HImode, a_src, PSImode, 0);
13356 a_hi8 = simplify_gen_subreg (QImode, a_src, PSImode, 2);
13357 }
13358 else
13359 {
13360 int segment = avr_addrspace[as].segment;
13361
13362 if (segment
13363 && avr_n_flash > 1)
13364 {
13365 a_hi8 = GEN_INT (segment);
13366 emit_move_insn (rampz_rtx, a_hi8 = copy_to_mode_reg (QImode, a_hi8));
13367 }
13368 else if (!ADDR_SPACE_GENERIC_P (as))
13369 {
13370 as = ADDR_SPACE_FLASH;
13371 }
13372
13373 addr1 = a_src;
13374
13375 loop_mode = (count <= 0x100) ? QImode : HImode;
13376 loop_reg = copy_to_mode_reg (loop_mode, gen_int_mode (count, loop_mode));
13377 }
13378
13379 xas = GEN_INT (as);
13380
13381 /* FIXME: Register allocator might come up with spill fails if it is left
13382 on its own. Thus, we allocate the pointer registers by hand:
13383 Z = source address
13384 X = destination address */
13385
13386 emit_move_insn (lpm_addr_reg_rtx, addr1);
13387 emit_move_insn (gen_rtx_REG (HImode, REG_X), a_dest);
13388
13389 /* FIXME: Register allocator does a bad job and might spill address
13390 register(s) inside the loop leading to additional move instruction
13391 to/from stack which could clobber tmp_reg. Thus, do *not* emit
13392 load and store as separate insns. Instead, we perform the copy
13393 by means of one monolithic insn. */
13394
13395 gcc_assert (TMP_REGNO == LPM_REGNO);
13396
13397 if (as != ADDR_SPACE_MEMX)
13398 {
13399 /* Load instruction ([E]LPM or LD) is known at compile time:
13400 Do the copy-loop inline. */
13401
13402 rtx (*fun) (rtx, rtx, rtx)
13403 = QImode == loop_mode ? gen_cpymem_qi : gen_cpymem_hi;
13404
13405 insn = fun (xas, loop_reg, loop_reg);
13406 }
13407 else
13408 {
13409 rtx (*fun) (rtx, rtx)
13410 = QImode == loop_mode ? gen_cpymemx_qi : gen_cpymemx_hi;
13411
13412 emit_move_insn (gen_rtx_REG (QImode, 23), a_hi8);
13413
13414 insn = fun (xas, GEN_INT (avr_addr.rampz));
13415 }
13416
13417 set_mem_addr_space (SET_SRC (XVECEXP (insn, 0, 0)), as);
13418 emit_insn (insn);
13419
13420 return true;
13421 }
13422
13423
13424 /* Print assembler for cpymem_qi, cpymem_hi insns...
13425 $0 : Address Space
13426 $1, $2 : Loop register
13427 Z : Source address
13428 X : Destination address
13429 */
13430
13431 const char*
avr_out_cpymem(rtx_insn * insn ATTRIBUTE_UNUSED,rtx * op,int * plen)13432 avr_out_cpymem (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
13433 {
13434 addr_space_t as = (addr_space_t) INTVAL (op[0]);
13435 machine_mode loop_mode = GET_MODE (op[1]);
13436 bool sbiw_p = test_hard_reg_class (ADDW_REGS, op[1]);
13437 rtx xop[3];
13438
13439 if (plen)
13440 *plen = 0;
13441
13442 xop[0] = op[0];
13443 xop[1] = op[1];
13444 xop[2] = tmp_reg_rtx;
13445
13446 /* Loop label */
13447
13448 avr_asm_len ("0:", xop, plen, 0);
13449
13450 /* Load with post-increment */
13451
13452 switch (as)
13453 {
13454 default:
13455 gcc_unreachable();
13456
13457 case ADDR_SPACE_GENERIC:
13458
13459 avr_asm_len ("ld %2,Z+", xop, plen, 1);
13460 break;
13461
13462 case ADDR_SPACE_FLASH:
13463
13464 if (AVR_HAVE_LPMX)
13465 avr_asm_len ("lpm %2,Z+", xop, plen, 1);
13466 else
13467 avr_asm_len ("lpm" CR_TAB
13468 "adiw r30,1", xop, plen, 2);
13469 break;
13470
13471 case ADDR_SPACE_FLASH1:
13472 case ADDR_SPACE_FLASH2:
13473 case ADDR_SPACE_FLASH3:
13474 case ADDR_SPACE_FLASH4:
13475 case ADDR_SPACE_FLASH5:
13476
13477 if (AVR_HAVE_ELPMX)
13478 avr_asm_len ("elpm %2,Z+", xop, plen, 1);
13479 else
13480 avr_asm_len ("elpm" CR_TAB
13481 "adiw r30,1", xop, plen, 2);
13482 break;
13483 }
13484
13485 /* Store with post-increment */
13486
13487 avr_asm_len ("st X+,%2", xop, plen, 1);
13488
13489 /* Decrement loop-counter and set Z-flag */
13490
13491 if (QImode == loop_mode)
13492 {
13493 avr_asm_len ("dec %1", xop, plen, 1);
13494 }
13495 else if (sbiw_p)
13496 {
13497 avr_asm_len ("sbiw %1,1", xop, plen, 1);
13498 }
13499 else
13500 {
13501 avr_asm_len ("subi %A1,1" CR_TAB
13502 "sbci %B1,0", xop, plen, 2);
13503 }
13504
13505 /* Loop until zero */
13506
13507 return avr_asm_len ("brne 0b", xop, plen, 1);
13508 }
13509
13510
13511
13512 /* Helper for __builtin_avr_delay_cycles */
13513
13514 static rtx
avr_mem_clobber(void)13515 avr_mem_clobber (void)
13516 {
13517 rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
13518 MEM_VOLATILE_P (mem) = 1;
13519 return mem;
13520 }
13521
13522 static void
avr_expand_delay_cycles(rtx operands0)13523 avr_expand_delay_cycles (rtx operands0)
13524 {
13525 unsigned HOST_WIDE_INT cycles = UINTVAL (operands0) & GET_MODE_MASK (SImode);
13526 unsigned HOST_WIDE_INT cycles_used;
13527 unsigned HOST_WIDE_INT loop_count;
13528
13529 if (IN_RANGE (cycles, 83886082, 0xFFFFFFFF))
13530 {
13531 loop_count = ((cycles - 9) / 6) + 1;
13532 cycles_used = ((loop_count - 1) * 6) + 9;
13533 emit_insn (gen_delay_cycles_4 (gen_int_mode (loop_count, SImode),
13534 avr_mem_clobber()));
13535 cycles -= cycles_used;
13536 }
13537
13538 if (IN_RANGE (cycles, 262145, 83886081))
13539 {
13540 loop_count = ((cycles - 7) / 5) + 1;
13541 if (loop_count > 0xFFFFFF)
13542 loop_count = 0xFFFFFF;
13543 cycles_used = ((loop_count - 1) * 5) + 7;
13544 emit_insn (gen_delay_cycles_3 (gen_int_mode (loop_count, SImode),
13545 avr_mem_clobber()));
13546 cycles -= cycles_used;
13547 }
13548
13549 if (IN_RANGE (cycles, 768, 262144))
13550 {
13551 loop_count = ((cycles - 5) / 4) + 1;
13552 if (loop_count > 0xFFFF)
13553 loop_count = 0xFFFF;
13554 cycles_used = ((loop_count - 1) * 4) + 5;
13555 emit_insn (gen_delay_cycles_2 (gen_int_mode (loop_count, HImode),
13556 avr_mem_clobber()));
13557 cycles -= cycles_used;
13558 }
13559
13560 if (IN_RANGE (cycles, 6, 767))
13561 {
13562 loop_count = cycles / 3;
13563 if (loop_count > 255)
13564 loop_count = 255;
13565 cycles_used = loop_count * 3;
13566 emit_insn (gen_delay_cycles_1 (gen_int_mode (loop_count, QImode),
13567 avr_mem_clobber()));
13568 cycles -= cycles_used;
13569 }
13570
13571 while (cycles >= 2)
13572 {
13573 emit_insn (gen_nopv (GEN_INT (2)));
13574 cycles -= 2;
13575 }
13576
13577 if (cycles == 1)
13578 {
13579 emit_insn (gen_nopv (GEN_INT (1)));
13580 cycles--;
13581 }
13582 }
13583
13584
13585 static void
avr_expand_nops(rtx operands0)13586 avr_expand_nops (rtx operands0)
13587 {
13588 unsigned HOST_WIDE_INT n_nops = UINTVAL (operands0) & GET_MODE_MASK (HImode);
13589
13590 while (n_nops--)
13591 {
13592 emit_insn (gen_nopv (const1_rtx));
13593 }
13594 }
13595
13596
13597 /* Compute the image of x under f, i.e. perform x --> f(x) */
13598
13599 static int
avr_map(unsigned int f,int x)13600 avr_map (unsigned int f, int x)
13601 {
13602 return x < 8 ? (f >> (4 * x)) & 0xf : 0;
13603 }
13604
13605
13606 /* Return some metrics of map A. */
13607
13608 enum
13609 {
13610 /* Number of fixed points in { 0 ... 7 } */
13611 MAP_FIXED_0_7,
13612
13613 /* Size of preimage of non-fixed points in { 0 ... 7 } */
13614 MAP_NONFIXED_0_7,
13615
13616 /* Mask representing the fixed points in { 0 ... 7 } */
13617 MAP_MASK_FIXED_0_7,
13618
13619 /* Size of the preimage of { 0 ... 7 } */
13620 MAP_PREIMAGE_0_7,
13621
13622 /* Mask that represents the preimage of { f } */
13623 MAP_MASK_PREIMAGE_F
13624 };
13625
13626 static unsigned
avr_map_metric(unsigned int a,int mode)13627 avr_map_metric (unsigned int a, int mode)
13628 {
13629 unsigned metric = 0;
13630
13631 for (unsigned i = 0; i < 8; i++)
13632 {
13633 unsigned ai = avr_map (a, i);
13634
13635 if (mode == MAP_FIXED_0_7)
13636 metric += ai == i;
13637 else if (mode == MAP_NONFIXED_0_7)
13638 metric += ai < 8 && ai != i;
13639 else if (mode == MAP_MASK_FIXED_0_7)
13640 metric |= ((unsigned) (ai == i)) << i;
13641 else if (mode == MAP_PREIMAGE_0_7)
13642 metric += ai < 8;
13643 else if (mode == MAP_MASK_PREIMAGE_F)
13644 metric |= ((unsigned) (ai == 0xf)) << i;
13645 else
13646 gcc_unreachable();
13647 }
13648
13649 return metric;
13650 }
13651
13652
13653 /* Return true if IVAL has a 0xf in its hexadecimal representation
13654 and false, otherwise. Only nibbles 0..7 are taken into account.
13655 Used as constraint helper for C0f and Cxf. */
13656
13657 bool
avr_has_nibble_0xf(rtx ival)13658 avr_has_nibble_0xf (rtx ival)
13659 {
13660 unsigned int map = UINTVAL (ival) & GET_MODE_MASK (SImode);
13661 return avr_map_metric (map, MAP_MASK_PREIMAGE_F) != 0;
13662 }
13663
13664
13665 /* We have a set of bits that are mapped by a function F.
13666 Try to decompose F by means of a second function G so that
13667
13668 F = F o G^-1 o G
13669
13670 and
13671
13672 cost (F o G^-1) + cost (G) < cost (F)
13673
13674 Example: Suppose builtin insert_bits supplies us with the map
13675 F = 0x3210ffff. Instead of doing 4 bit insertions to get the high
13676 nibble of the result, we can just as well rotate the bits before inserting
13677 them and use the map 0x7654ffff which is cheaper than the original map.
13678 For this example G = G^-1 = 0x32107654 and F o G^-1 = 0x7654ffff. */
13679
13680 typedef struct
13681 {
13682 /* tree code of binary function G */
13683 enum tree_code code;
13684
13685 /* The constant second argument of G */
13686 int arg;
13687
13688 /* G^-1, the inverse of G (*, arg) */
13689 unsigned ginv;
13690
13691 /* The cost of applying G (*, arg) */
13692 int cost;
13693
13694 /* The composition F o G^-1 (*, arg) for some function F */
13695 unsigned int map;
13696
13697 /* For debug purpose only */
13698 const char *str;
13699 } avr_map_op_t;
13700
13701 static const avr_map_op_t avr_map_op[] =
13702 {
13703 { LROTATE_EXPR, 0, 0x76543210, 0, 0, "id" },
13704 { LROTATE_EXPR, 1, 0x07654321, 2, 0, "<<<" },
13705 { LROTATE_EXPR, 2, 0x10765432, 4, 0, "<<<" },
13706 { LROTATE_EXPR, 3, 0x21076543, 4, 0, "<<<" },
13707 { LROTATE_EXPR, 4, 0x32107654, 1, 0, "<<<" },
13708 { LROTATE_EXPR, 5, 0x43210765, 3, 0, "<<<" },
13709 { LROTATE_EXPR, 6, 0x54321076, 5, 0, "<<<" },
13710 { LROTATE_EXPR, 7, 0x65432107, 3, 0, "<<<" },
13711 { RSHIFT_EXPR, 1, 0x6543210c, 1, 0, ">>" },
13712 { RSHIFT_EXPR, 1, 0x7543210c, 1, 0, ">>" },
13713 { RSHIFT_EXPR, 2, 0x543210cc, 2, 0, ">>" },
13714 { RSHIFT_EXPR, 2, 0x643210cc, 2, 0, ">>" },
13715 { RSHIFT_EXPR, 2, 0x743210cc, 2, 0, ">>" },
13716 { LSHIFT_EXPR, 1, 0xc7654321, 1, 0, "<<" },
13717 { LSHIFT_EXPR, 2, 0xcc765432, 2, 0, "<<" }
13718 };
13719
13720
13721 /* Try to decompose F as F = (F o G^-1) o G as described above.
13722 The result is a struct representing F o G^-1 and G.
13723 If result.cost < 0 then such a decomposition does not exist. */
13724
13725 static avr_map_op_t
avr_map_decompose(unsigned int f,const avr_map_op_t * g,bool val_const_p)13726 avr_map_decompose (unsigned int f, const avr_map_op_t *g, bool val_const_p)
13727 {
13728 bool val_used_p = avr_map_metric (f, MAP_MASK_PREIMAGE_F) != 0;
13729 avr_map_op_t f_ginv = *g;
13730 unsigned int ginv = g->ginv;
13731
13732 f_ginv.cost = -1;
13733
13734 /* Step 1: Computing F o G^-1 */
13735
13736 for (int i = 7; i >= 0; i--)
13737 {
13738 int x = avr_map (f, i);
13739
13740 if (x <= 7)
13741 {
13742 x = avr_map (ginv, x);
13743
13744 /* The bit is no element of the image of G: no avail (cost = -1) */
13745
13746 if (x > 7)
13747 return f_ginv;
13748 }
13749
13750 f_ginv.map = (f_ginv.map << 4) + x;
13751 }
13752
13753 /* Step 2: Compute the cost of the operations.
13754 The overall cost of doing an operation prior to the insertion is
13755 the cost of the insertion plus the cost of the operation. */
13756
13757 /* Step 2a: Compute cost of F o G^-1 */
13758
13759 if (avr_map_metric (f_ginv.map, MAP_NONFIXED_0_7) == 0)
13760 /* The mapping consists only of fixed points and can be folded
13761 to AND/OR logic in the remainder. Reasonable cost is 3. */
13762 f_ginv.cost = 2 + (val_used_p && !val_const_p);
13763 else
13764 {
13765 rtx xop[4];
13766
13767 /* Get the cost of the insn by calling the output worker with some
13768 fake values. Mimic effect of reloading xop[3]: Unused operands
13769 are mapped to 0 and used operands are reloaded to xop[0]. */
13770
13771 xop[0] = all_regs_rtx[24];
13772 xop[1] = gen_int_mode (f_ginv.map, SImode);
13773 xop[2] = all_regs_rtx[25];
13774 xop[3] = val_used_p ? xop[0] : const0_rtx;
13775
13776 avr_out_insert_bits (xop, &f_ginv.cost);
13777
13778 f_ginv.cost += val_const_p && val_used_p ? 1 : 0;
13779 }
13780
13781 /* Step 2b: Add cost of G */
13782
13783 f_ginv.cost += g->cost;
13784
13785 if (avr_log.builtin)
13786 avr_edump (" %s%d=%d", g->str, g->arg, f_ginv.cost);
13787
13788 return f_ginv;
13789 }
13790
13791
13792 /* Insert bits from XOP[1] into XOP[0] according to MAP.
13793 XOP[0] and XOP[1] don't overlap.
13794 If FIXP_P = true: Move all bits according to MAP using BLD/BST sequences.
13795 If FIXP_P = false: Just move the bit if its position in the destination
13796 is different to its source position. */
13797
13798 static void
avr_move_bits(rtx * xop,unsigned int map,bool fixp_p,int * plen)13799 avr_move_bits (rtx *xop, unsigned int map, bool fixp_p, int *plen)
13800 {
13801 /* T-flag contains this bit of the source, i.e. of XOP[1] */
13802 int t_bit_src = -1;
13803
13804 /* We order the operations according to the requested source bit b. */
13805
13806 for (int b = 0; b < 8; b++)
13807 for (int bit_dest = 0; bit_dest < 8; bit_dest++)
13808 {
13809 int bit_src = avr_map (map, bit_dest);
13810
13811 if (b != bit_src
13812 || bit_src >= 8
13813 /* Same position: No need to copy as requested by FIXP_P. */
13814 || (bit_dest == bit_src && !fixp_p))
13815 continue;
13816
13817 if (t_bit_src != bit_src)
13818 {
13819 /* Source bit is not yet in T: Store it to T. */
13820
13821 t_bit_src = bit_src;
13822
13823 xop[3] = GEN_INT (bit_src);
13824 avr_asm_len ("bst %T1%T3", xop, plen, 1);
13825 }
13826
13827 /* Load destination bit with T. */
13828
13829 xop[3] = GEN_INT (bit_dest);
13830 avr_asm_len ("bld %T0%T3", xop, plen, 1);
13831 }
13832 }
13833
13834
13835 /* PLEN == 0: Print assembler code for `insert_bits'.
13836 PLEN != 0: Compute code length in bytes.
13837
13838 OP[0]: Result
13839 OP[1]: The mapping composed of nibbles. If nibble no. N is
13840 0: Bit N of result is copied from bit OP[2].0
13841 ... ...
13842 7: Bit N of result is copied from bit OP[2].7
13843 0xf: Bit N of result is copied from bit OP[3].N
13844 OP[2]: Bits to be inserted
13845 OP[3]: Target value */
13846
13847 const char*
avr_out_insert_bits(rtx * op,int * plen)13848 avr_out_insert_bits (rtx *op, int *plen)
13849 {
13850 unsigned int map = UINTVAL (op[1]) & GET_MODE_MASK (SImode);
13851 unsigned mask_fixed;
13852 bool fixp_p = true;
13853 rtx xop[4];
13854
13855 xop[0] = op[0];
13856 xop[1] = op[2];
13857 xop[2] = op[3];
13858
13859 gcc_assert (REG_P (xop[2]) || CONST_INT_P (xop[2]));
13860
13861 if (plen)
13862 *plen = 0;
13863 else if (flag_print_asm_name)
13864 fprintf (asm_out_file, ASM_COMMENT_START "map = 0x%08x\n", map);
13865
13866 /* If MAP has fixed points it might be better to initialize the result
13867 with the bits to be inserted instead of moving all bits by hand. */
13868
13869 mask_fixed = avr_map_metric (map, MAP_MASK_FIXED_0_7);
13870
13871 if (REGNO (xop[0]) == REGNO (xop[1]))
13872 {
13873 /* Avoid early-clobber conflicts */
13874
13875 avr_asm_len ("mov __tmp_reg__,%1", xop, plen, 1);
13876 xop[1] = tmp_reg_rtx;
13877 fixp_p = false;
13878 }
13879
13880 if (avr_map_metric (map, MAP_MASK_PREIMAGE_F))
13881 {
13882 /* XOP[2] is used and reloaded to XOP[0] already */
13883
13884 int n_fix = 0, n_nofix = 0;
13885
13886 gcc_assert (REG_P (xop[2]));
13887
13888 /* Get the code size of the bit insertions; once with all bits
13889 moved and once with fixed points omitted. */
13890
13891 avr_move_bits (xop, map, true, &n_fix);
13892 avr_move_bits (xop, map, false, &n_nofix);
13893
13894 if (fixp_p && n_fix - n_nofix > 3)
13895 {
13896 xop[3] = gen_int_mode (~mask_fixed, QImode);
13897
13898 avr_asm_len ("eor %0,%1" CR_TAB
13899 "andi %0,%3" CR_TAB
13900 "eor %0,%1", xop, plen, 3);
13901 fixp_p = false;
13902 }
13903 }
13904 else
13905 {
13906 /* XOP[2] is unused */
13907
13908 if (fixp_p && mask_fixed)
13909 {
13910 avr_asm_len ("mov %0,%1", xop, plen, 1);
13911 fixp_p = false;
13912 }
13913 }
13914
13915 /* Move/insert remaining bits. */
13916
13917 avr_move_bits (xop, map, fixp_p, plen);
13918
13919 return "";
13920 }
13921
13922
13923 /* IDs for all the AVR builtins. */
13924
13925 enum avr_builtin_id
13926 {
13927 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
13928 AVR_BUILTIN_ ## NAME,
13929 #include "builtins.def"
13930 #undef DEF_BUILTIN
13931
13932 AVR_BUILTIN_COUNT
13933 };
13934
13935 struct GTY(()) avr_builtin_description
13936 {
13937 enum insn_code icode;
13938 int n_args;
13939 tree fndecl;
13940 };
13941
13942
13943 /* Notice that avr_bdesc[] and avr_builtin_id are initialized in such a way
13944 that a built-in's ID can be used to access the built-in by means of
13945 avr_bdesc[ID] */
13946
13947 static GTY(()) struct avr_builtin_description
13948 avr_bdesc[AVR_BUILTIN_COUNT] =
13949 {
13950 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE, LIBNAME) \
13951 { (enum insn_code) CODE_FOR_ ## ICODE, N_ARGS, NULL_TREE },
13952 #include "builtins.def"
13953 #undef DEF_BUILTIN
13954 };
13955
13956
13957 /* Implement `TARGET_BUILTIN_DECL'. */
13958
13959 static tree
avr_builtin_decl(unsigned id,bool initialize_p ATTRIBUTE_UNUSED)13960 avr_builtin_decl (unsigned id, bool initialize_p ATTRIBUTE_UNUSED)
13961 {
13962 if (id < AVR_BUILTIN_COUNT)
13963 return avr_bdesc[id].fndecl;
13964
13965 return error_mark_node;
13966 }
13967
13968
13969 static void
avr_init_builtin_int24(void)13970 avr_init_builtin_int24 (void)
13971 {
13972 tree int24_type = make_signed_type (GET_MODE_BITSIZE (PSImode));
13973 tree uint24_type = make_unsigned_type (GET_MODE_BITSIZE (PSImode));
13974
13975 lang_hooks.types.register_builtin_type (int24_type, "__int24");
13976 lang_hooks.types.register_builtin_type (uint24_type, "__uint24");
13977 }
13978
13979
13980 /* Implement `TARGET_INIT_BUILTINS' */
13981 /* Set up all builtin functions for this target. */
13982
13983 static void
avr_init_builtins(void)13984 avr_init_builtins (void)
13985 {
13986 tree void_ftype_void
13987 = build_function_type_list (void_type_node, NULL_TREE);
13988 tree uchar_ftype_uchar
13989 = build_function_type_list (unsigned_char_type_node,
13990 unsigned_char_type_node,
13991 NULL_TREE);
13992 tree uint_ftype_uchar_uchar
13993 = build_function_type_list (unsigned_type_node,
13994 unsigned_char_type_node,
13995 unsigned_char_type_node,
13996 NULL_TREE);
13997 tree int_ftype_char_char
13998 = build_function_type_list (integer_type_node,
13999 char_type_node,
14000 char_type_node,
14001 NULL_TREE);
14002 tree int_ftype_char_uchar
14003 = build_function_type_list (integer_type_node,
14004 char_type_node,
14005 unsigned_char_type_node,
14006 NULL_TREE);
14007 tree void_ftype_ulong
14008 = build_function_type_list (void_type_node,
14009 long_unsigned_type_node,
14010 NULL_TREE);
14011
14012 tree uchar_ftype_ulong_uchar_uchar
14013 = build_function_type_list (unsigned_char_type_node,
14014 long_unsigned_type_node,
14015 unsigned_char_type_node,
14016 unsigned_char_type_node,
14017 NULL_TREE);
14018
14019 tree const_memx_void_node
14020 = build_qualified_type (void_type_node,
14021 TYPE_QUAL_CONST
14022 | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_MEMX));
14023
14024 tree const_memx_ptr_type_node
14025 = build_pointer_type_for_mode (const_memx_void_node, PSImode, false);
14026
14027 tree char_ftype_const_memx_ptr
14028 = build_function_type_list (char_type_node,
14029 const_memx_ptr_type_node,
14030 NULL);
14031
14032 #define ITYP(T) \
14033 lang_hooks.types.type_for_size (TYPE_PRECISION (T), TYPE_UNSIGNED (T))
14034
14035 #define FX_FTYPE_FX(fx) \
14036 tree fx##r_ftype_##fx##r \
14037 = build_function_type_list (node_##fx##r, node_##fx##r, NULL); \
14038 tree fx##k_ftype_##fx##k \
14039 = build_function_type_list (node_##fx##k, node_##fx##k, NULL)
14040
14041 #define FX_FTYPE_FX_INT(fx) \
14042 tree fx##r_ftype_##fx##r_int \
14043 = build_function_type_list (node_##fx##r, node_##fx##r, \
14044 integer_type_node, NULL); \
14045 tree fx##k_ftype_##fx##k_int \
14046 = build_function_type_list (node_##fx##k, node_##fx##k, \
14047 integer_type_node, NULL)
14048
14049 #define INT_FTYPE_FX(fx) \
14050 tree int_ftype_##fx##r \
14051 = build_function_type_list (integer_type_node, node_##fx##r, NULL); \
14052 tree int_ftype_##fx##k \
14053 = build_function_type_list (integer_type_node, node_##fx##k, NULL)
14054
14055 #define INTX_FTYPE_FX(fx) \
14056 tree int##fx##r_ftype_##fx##r \
14057 = build_function_type_list (ITYP (node_##fx##r), node_##fx##r, NULL); \
14058 tree int##fx##k_ftype_##fx##k \
14059 = build_function_type_list (ITYP (node_##fx##k), node_##fx##k, NULL)
14060
14061 #define FX_FTYPE_INTX(fx) \
14062 tree fx##r_ftype_int##fx##r \
14063 = build_function_type_list (node_##fx##r, ITYP (node_##fx##r), NULL); \
14064 tree fx##k_ftype_int##fx##k \
14065 = build_function_type_list (node_##fx##k, ITYP (node_##fx##k), NULL)
14066
14067 tree node_hr = short_fract_type_node;
14068 tree node_nr = fract_type_node;
14069 tree node_lr = long_fract_type_node;
14070 tree node_llr = long_long_fract_type_node;
14071
14072 tree node_uhr = unsigned_short_fract_type_node;
14073 tree node_unr = unsigned_fract_type_node;
14074 tree node_ulr = unsigned_long_fract_type_node;
14075 tree node_ullr = unsigned_long_long_fract_type_node;
14076
14077 tree node_hk = short_accum_type_node;
14078 tree node_nk = accum_type_node;
14079 tree node_lk = long_accum_type_node;
14080 tree node_llk = long_long_accum_type_node;
14081
14082 tree node_uhk = unsigned_short_accum_type_node;
14083 tree node_unk = unsigned_accum_type_node;
14084 tree node_ulk = unsigned_long_accum_type_node;
14085 tree node_ullk = unsigned_long_long_accum_type_node;
14086
14087
14088 /* For absfx builtins. */
14089
14090 FX_FTYPE_FX (h);
14091 FX_FTYPE_FX (n);
14092 FX_FTYPE_FX (l);
14093 FX_FTYPE_FX (ll);
14094
14095 /* For roundfx builtins. */
14096
14097 FX_FTYPE_FX_INT (h);
14098 FX_FTYPE_FX_INT (n);
14099 FX_FTYPE_FX_INT (l);
14100 FX_FTYPE_FX_INT (ll);
14101
14102 FX_FTYPE_FX_INT (uh);
14103 FX_FTYPE_FX_INT (un);
14104 FX_FTYPE_FX_INT (ul);
14105 FX_FTYPE_FX_INT (ull);
14106
14107 /* For countlsfx builtins. */
14108
14109 INT_FTYPE_FX (h);
14110 INT_FTYPE_FX (n);
14111 INT_FTYPE_FX (l);
14112 INT_FTYPE_FX (ll);
14113
14114 INT_FTYPE_FX (uh);
14115 INT_FTYPE_FX (un);
14116 INT_FTYPE_FX (ul);
14117 INT_FTYPE_FX (ull);
14118
14119 /* For bitsfx builtins. */
14120
14121 INTX_FTYPE_FX (h);
14122 INTX_FTYPE_FX (n);
14123 INTX_FTYPE_FX (l);
14124 INTX_FTYPE_FX (ll);
14125
14126 INTX_FTYPE_FX (uh);
14127 INTX_FTYPE_FX (un);
14128 INTX_FTYPE_FX (ul);
14129 INTX_FTYPE_FX (ull);
14130
14131 /* For fxbits builtins. */
14132
14133 FX_FTYPE_INTX (h);
14134 FX_FTYPE_INTX (n);
14135 FX_FTYPE_INTX (l);
14136 FX_FTYPE_INTX (ll);
14137
14138 FX_FTYPE_INTX (uh);
14139 FX_FTYPE_INTX (un);
14140 FX_FTYPE_INTX (ul);
14141 FX_FTYPE_INTX (ull);
14142
14143
14144 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
14145 { \
14146 int id = AVR_BUILTIN_ ## NAME; \
14147 const char *Name = "__builtin_avr_" #NAME; \
14148 char *name = (char*) alloca (1 + strlen (Name)); \
14149 \
14150 gcc_assert (id < AVR_BUILTIN_COUNT); \
14151 avr_bdesc[id].fndecl \
14152 = add_builtin_function (avr_tolower (name, Name), TYPE, id, \
14153 BUILT_IN_MD, LIBNAME, NULL_TREE); \
14154 }
14155 #include "builtins.def"
14156 #undef DEF_BUILTIN
14157
14158 avr_init_builtin_int24 ();
14159 }
14160
14161
14162 /* Subroutine of avr_expand_builtin to expand vanilla builtins
14163 with non-void result and 1 ... 3 arguments. */
14164
14165 static rtx
avr_default_expand_builtin(enum insn_code icode,tree exp,rtx target)14166 avr_default_expand_builtin (enum insn_code icode, tree exp, rtx target)
14167 {
14168 rtx pat, xop[3];
14169 int n_args = call_expr_nargs (exp);
14170 machine_mode tmode = insn_data[icode].operand[0].mode;
14171
14172 gcc_assert (n_args >= 1 && n_args <= 3);
14173
14174 if (target == NULL_RTX
14175 || GET_MODE (target) != tmode
14176 || !insn_data[icode].operand[0].predicate (target, tmode))
14177 {
14178 target = gen_reg_rtx (tmode);
14179 }
14180
14181 for (int n = 0; n < n_args; n++)
14182 {
14183 tree arg = CALL_EXPR_ARG (exp, n);
14184 rtx op = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14185 machine_mode opmode = GET_MODE (op);
14186 machine_mode mode = insn_data[icode].operand[n + 1].mode;
14187
14188 if ((opmode == SImode || opmode == VOIDmode) && mode == HImode)
14189 {
14190 opmode = HImode;
14191 op = gen_lowpart (HImode, op);
14192 }
14193
14194 /* In case the insn wants input operands in modes different from
14195 the result, abort. */
14196
14197 gcc_assert (opmode == mode || opmode == VOIDmode);
14198
14199 if (!insn_data[icode].operand[n + 1].predicate (op, mode))
14200 op = copy_to_mode_reg (mode, op);
14201
14202 xop[n] = op;
14203 }
14204
14205 switch (n_args)
14206 {
14207 case 1: pat = GEN_FCN (icode) (target, xop[0]); break;
14208 case 2: pat = GEN_FCN (icode) (target, xop[0], xop[1]); break;
14209 case 3: pat = GEN_FCN (icode) (target, xop[0], xop[1], xop[2]); break;
14210
14211 default:
14212 gcc_unreachable();
14213 }
14214
14215 if (pat == NULL_RTX)
14216 return NULL_RTX;
14217
14218 emit_insn (pat);
14219
14220 return target;
14221 }
14222
14223
14224 /* Implement `TARGET_EXPAND_BUILTIN'. */
14225 /* Expand an expression EXP that calls a built-in function,
14226 with result going to TARGET if that's convenient
14227 (and in mode MODE if that's convenient).
14228 SUBTARGET may be used as the target for computing one of EXP's operands.
14229 IGNORE is nonzero if the value is to be ignored. */
14230
14231 static rtx
avr_expand_builtin(tree exp,rtx target,rtx subtarget ATTRIBUTE_UNUSED,machine_mode mode ATTRIBUTE_UNUSED,int ignore)14232 avr_expand_builtin (tree exp, rtx target,
14233 rtx subtarget ATTRIBUTE_UNUSED,
14234 machine_mode mode ATTRIBUTE_UNUSED,
14235 int ignore)
14236 {
14237 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
14238 const char *bname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
14239 unsigned int id = DECL_MD_FUNCTION_CODE (fndecl);
14240 const struct avr_builtin_description *d = &avr_bdesc[id];
14241 tree arg0;
14242 rtx op0;
14243
14244 gcc_assert (id < AVR_BUILTIN_COUNT);
14245
14246 switch (id)
14247 {
14248 case AVR_BUILTIN_NOP:
14249 emit_insn (gen_nopv (GEN_INT (1)));
14250 return 0;
14251
14252 case AVR_BUILTIN_DELAY_CYCLES:
14253 {
14254 arg0 = CALL_EXPR_ARG (exp, 0);
14255 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14256
14257 if (!CONST_INT_P (op0))
14258 error ("%s expects a compile time integer constant", bname);
14259 else
14260 avr_expand_delay_cycles (op0);
14261
14262 return NULL_RTX;
14263 }
14264
14265 case AVR_BUILTIN_NOPS:
14266 {
14267 arg0 = CALL_EXPR_ARG (exp, 0);
14268 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14269
14270 if (!CONST_INT_P (op0))
14271 error ("%s expects a compile time integer constant", bname);
14272 else
14273 avr_expand_nops (op0);
14274
14275 return NULL_RTX;
14276 }
14277
14278 case AVR_BUILTIN_INSERT_BITS:
14279 {
14280 arg0 = CALL_EXPR_ARG (exp, 0);
14281 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14282
14283 if (!CONST_INT_P (op0))
14284 {
14285 error ("%s expects a compile time long integer constant"
14286 " as first argument", bname);
14287 return target;
14288 }
14289
14290 break;
14291 }
14292
14293 case AVR_BUILTIN_ROUNDHR: case AVR_BUILTIN_ROUNDUHR:
14294 case AVR_BUILTIN_ROUNDR: case AVR_BUILTIN_ROUNDUR:
14295 case AVR_BUILTIN_ROUNDLR: case AVR_BUILTIN_ROUNDULR:
14296 case AVR_BUILTIN_ROUNDLLR: case AVR_BUILTIN_ROUNDULLR:
14297
14298 case AVR_BUILTIN_ROUNDHK: case AVR_BUILTIN_ROUNDUHK:
14299 case AVR_BUILTIN_ROUNDK: case AVR_BUILTIN_ROUNDUK:
14300 case AVR_BUILTIN_ROUNDLK: case AVR_BUILTIN_ROUNDULK:
14301 case AVR_BUILTIN_ROUNDLLK: case AVR_BUILTIN_ROUNDULLK:
14302
14303 /* Warn about odd rounding. Rounding points >= FBIT will have
14304 no effect. */
14305
14306 if (TREE_CODE (CALL_EXPR_ARG (exp, 1)) != INTEGER_CST)
14307 break;
14308
14309 int rbit = (int) TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1));
14310
14311 if (rbit >= (int) GET_MODE_FBIT (mode))
14312 {
14313 warning (OPT_Wextra, "rounding to %d bits has no effect for "
14314 "fixed-point value with %d fractional bits",
14315 rbit, GET_MODE_FBIT (mode));
14316
14317 return expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX, mode,
14318 EXPAND_NORMAL);
14319 }
14320 else if (rbit <= - (int) GET_MODE_IBIT (mode))
14321 {
14322 warning (0, "rounding result will always be 0");
14323 return CONST0_RTX (mode);
14324 }
14325
14326 /* The rounding points RP satisfies now: -IBIT < RP < FBIT.
14327
14328 TR 18037 only specifies results for RP > 0. However, the
14329 remaining cases of -IBIT < RP <= 0 can easily be supported
14330 without any additional overhead. */
14331
14332 break; /* round */
14333 }
14334
14335 /* No fold found and no insn: Call support function from libgcc. */
14336
14337 if (d->icode == CODE_FOR_nothing
14338 && DECL_ASSEMBLER_NAME (get_callee_fndecl (exp)) != NULL_TREE)
14339 {
14340 return expand_call (exp, target, ignore);
14341 }
14342
14343 /* No special treatment needed: vanilla expand. */
14344
14345 gcc_assert (d->icode != CODE_FOR_nothing);
14346 gcc_assert (d->n_args == call_expr_nargs (exp));
14347
14348 if (d->n_args == 0)
14349 {
14350 emit_insn ((GEN_FCN (d->icode)) (target));
14351 return NULL_RTX;
14352 }
14353
14354 return avr_default_expand_builtin (d->icode, exp, target);
14355 }
14356
14357
14358 /* Helper for `avr_fold_builtin' that folds absfx (FIXED_CST). */
14359
14360 static tree
avr_fold_absfx(tree tval)14361 avr_fold_absfx (tree tval)
14362 {
14363 if (FIXED_CST != TREE_CODE (tval))
14364 return NULL_TREE;
14365
14366 /* Our fixed-points have no padding: Use double_int payload directly. */
14367
14368 FIXED_VALUE_TYPE fval = TREE_FIXED_CST (tval);
14369 unsigned int bits = GET_MODE_BITSIZE (fval.mode);
14370 double_int ival = fval.data.sext (bits);
14371
14372 if (!ival.is_negative())
14373 return tval;
14374
14375 /* ISO/IEC TR 18037, 7.18a.6.2: The absfx functions are saturating. */
14376
14377 fval.data = (ival == double_int::min_value (bits, false).sext (bits))
14378 ? double_int::max_value (bits, false)
14379 : -ival;
14380
14381 return build_fixed (TREE_TYPE (tval), fval);
14382 }
14383
14384
14385 /* Implement `TARGET_FOLD_BUILTIN'. */
14386
14387 static tree
avr_fold_builtin(tree fndecl,int n_args ATTRIBUTE_UNUSED,tree * arg,bool ignore ATTRIBUTE_UNUSED)14388 avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg,
14389 bool ignore ATTRIBUTE_UNUSED)
14390 {
14391 unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
14392 tree val_type = TREE_TYPE (TREE_TYPE (fndecl));
14393
14394 if (!optimize)
14395 return NULL_TREE;
14396
14397 switch (fcode)
14398 {
14399 default:
14400 break;
14401
14402 case AVR_BUILTIN_SWAP:
14403 {
14404 return fold_build2 (LROTATE_EXPR, val_type, arg[0],
14405 build_int_cst (val_type, 4));
14406 }
14407
14408 case AVR_BUILTIN_ABSHR:
14409 case AVR_BUILTIN_ABSR:
14410 case AVR_BUILTIN_ABSLR:
14411 case AVR_BUILTIN_ABSLLR:
14412
14413 case AVR_BUILTIN_ABSHK:
14414 case AVR_BUILTIN_ABSK:
14415 case AVR_BUILTIN_ABSLK:
14416 case AVR_BUILTIN_ABSLLK:
14417 /* GCC is not good with folding ABS for fixed-point. Do it by hand. */
14418
14419 return avr_fold_absfx (arg[0]);
14420
14421 case AVR_BUILTIN_BITSHR: case AVR_BUILTIN_HRBITS:
14422 case AVR_BUILTIN_BITSHK: case AVR_BUILTIN_HKBITS:
14423 case AVR_BUILTIN_BITSUHR: case AVR_BUILTIN_UHRBITS:
14424 case AVR_BUILTIN_BITSUHK: case AVR_BUILTIN_UHKBITS:
14425
14426 case AVR_BUILTIN_BITSR: case AVR_BUILTIN_RBITS:
14427 case AVR_BUILTIN_BITSK: case AVR_BUILTIN_KBITS:
14428 case AVR_BUILTIN_BITSUR: case AVR_BUILTIN_URBITS:
14429 case AVR_BUILTIN_BITSUK: case AVR_BUILTIN_UKBITS:
14430
14431 case AVR_BUILTIN_BITSLR: case AVR_BUILTIN_LRBITS:
14432 case AVR_BUILTIN_BITSLK: case AVR_BUILTIN_LKBITS:
14433 case AVR_BUILTIN_BITSULR: case AVR_BUILTIN_ULRBITS:
14434 case AVR_BUILTIN_BITSULK: case AVR_BUILTIN_ULKBITS:
14435
14436 case AVR_BUILTIN_BITSLLR: case AVR_BUILTIN_LLRBITS:
14437 case AVR_BUILTIN_BITSLLK: case AVR_BUILTIN_LLKBITS:
14438 case AVR_BUILTIN_BITSULLR: case AVR_BUILTIN_ULLRBITS:
14439 case AVR_BUILTIN_BITSULLK: case AVR_BUILTIN_ULLKBITS:
14440
14441 gcc_assert (TYPE_PRECISION (val_type)
14442 == TYPE_PRECISION (TREE_TYPE (arg[0])));
14443
14444 return build1 (VIEW_CONVERT_EXPR, val_type, arg[0]);
14445
14446 case AVR_BUILTIN_INSERT_BITS:
14447 {
14448 tree tbits = arg[1];
14449 tree tval = arg[2];
14450 tree tmap;
14451 tree map_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
14452 unsigned int map;
14453 bool changed = false;
14454 avr_map_op_t best_g;
14455
14456 if (TREE_CODE (arg[0]) != INTEGER_CST)
14457 {
14458 /* No constant as first argument: Don't fold this and run into
14459 error in avr_expand_builtin. */
14460
14461 break;
14462 }
14463
14464 tmap = wide_int_to_tree (map_type, wi::to_wide (arg[0]));
14465 map = TREE_INT_CST_LOW (tmap);
14466
14467 if (TREE_CODE (tval) != INTEGER_CST
14468 && avr_map_metric (map, MAP_MASK_PREIMAGE_F) == 0)
14469 {
14470 /* There are no F in the map, i.e. 3rd operand is unused.
14471 Replace that argument with some constant to render
14472 respective input unused. */
14473
14474 tval = build_int_cst (val_type, 0);
14475 changed = true;
14476 }
14477
14478 if (TREE_CODE (tbits) != INTEGER_CST
14479 && avr_map_metric (map, MAP_PREIMAGE_0_7) == 0)
14480 {
14481 /* Similar for the bits to be inserted. If they are unused,
14482 we can just as well pass 0. */
14483
14484 tbits = build_int_cst (val_type, 0);
14485 }
14486
14487 if (TREE_CODE (tbits) == INTEGER_CST)
14488 {
14489 /* Inserting bits known at compile time is easy and can be
14490 performed by AND and OR with appropriate masks. */
14491
14492 int bits = TREE_INT_CST_LOW (tbits);
14493 int mask_ior = 0, mask_and = 0xff;
14494
14495 for (size_t i = 0; i < 8; i++)
14496 {
14497 int mi = avr_map (map, i);
14498
14499 if (mi < 8)
14500 {
14501 if (bits & (1 << mi)) mask_ior |= (1 << i);
14502 else mask_and &= ~(1 << i);
14503 }
14504 }
14505
14506 tval = fold_build2 (BIT_IOR_EXPR, val_type, tval,
14507 build_int_cst (val_type, mask_ior));
14508 return fold_build2 (BIT_AND_EXPR, val_type, tval,
14509 build_int_cst (val_type, mask_and));
14510 }
14511
14512 if (changed)
14513 return build_call_expr (fndecl, 3, tmap, tbits, tval);
14514
14515 /* If bits don't change their position we can use vanilla logic
14516 to merge the two arguments. */
14517
14518 if (avr_map_metric (map, MAP_NONFIXED_0_7) == 0)
14519 {
14520 int mask_f = avr_map_metric (map, MAP_MASK_PREIMAGE_F);
14521 tree tres, tmask = build_int_cst (val_type, mask_f ^ 0xff);
14522
14523 tres = fold_build2 (BIT_XOR_EXPR, val_type, tbits, tval);
14524 tres = fold_build2 (BIT_AND_EXPR, val_type, tres, tmask);
14525 return fold_build2 (BIT_XOR_EXPR, val_type, tres, tval);
14526 }
14527
14528 /* Try to decomposing map to reduce overall cost. */
14529
14530 if (avr_log.builtin)
14531 avr_edump ("\n%?: %x\n%?: ROL cost: ", map);
14532
14533 best_g = avr_map_op[0];
14534 best_g.cost = 1000;
14535
14536 for (size_t i = 0; i < ARRAY_SIZE (avr_map_op); i++)
14537 {
14538 avr_map_op_t g
14539 = avr_map_decompose (map, avr_map_op + i,
14540 TREE_CODE (tval) == INTEGER_CST);
14541
14542 if (g.cost >= 0 && g.cost < best_g.cost)
14543 best_g = g;
14544 }
14545
14546 if (avr_log.builtin)
14547 avr_edump ("\n");
14548
14549 if (best_g.arg == 0)
14550 /* No optimization found */
14551 break;
14552
14553 /* Apply operation G to the 2nd argument. */
14554
14555 if (avr_log.builtin)
14556 avr_edump ("%?: using OP(%s%d, %x) cost %d\n",
14557 best_g.str, best_g.arg, best_g.map, best_g.cost);
14558
14559 /* Do right-shifts arithmetically: They copy the MSB instead of
14560 shifting in a non-usable value (0) as with logic right-shift. */
14561
14562 tbits = fold_convert (signed_char_type_node, tbits);
14563 tbits = fold_build2 (best_g.code, signed_char_type_node, tbits,
14564 build_int_cst (val_type, best_g.arg));
14565 tbits = fold_convert (val_type, tbits);
14566
14567 /* Use map o G^-1 instead of original map to undo the effect of G. */
14568
14569 tmap = wide_int_to_tree (map_type, best_g.map);
14570
14571 return build_call_expr (fndecl, 3, tmap, tbits, tval);
14572 } /* AVR_BUILTIN_INSERT_BITS */
14573 }
14574
14575 return NULL_TREE;
14576 }
14577
14578
14579 /* Worker function for `FLOAT_LIB_COMPARE_RETURNS_BOOL'. */
14580
14581 bool
avr_float_lib_compare_returns_bool(machine_mode mode,enum rtx_code)14582 avr_float_lib_compare_returns_bool (machine_mode mode, enum rtx_code)
14583 {
14584 if (mode == DFmode)
14585 {
14586 #if WITH_DOUBLE_COMPARISON == 2
14587 return true;
14588 #endif
14589 }
14590
14591 // This is the GCC default and also what AVR-LibC implements.
14592 return false;
14593 }
14594
14595
14596
14597 /* Initialize the GCC target structure. */
14598
14599 #undef TARGET_ASM_ALIGNED_HI_OP
14600 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
14601 #undef TARGET_ASM_ALIGNED_SI_OP
14602 #define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
14603 #undef TARGET_ASM_UNALIGNED_HI_OP
14604 #define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
14605 #undef TARGET_ASM_UNALIGNED_SI_OP
14606 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
14607 #undef TARGET_ASM_INTEGER
14608 #define TARGET_ASM_INTEGER avr_assemble_integer
14609 #undef TARGET_ASM_FILE_START
14610 #define TARGET_ASM_FILE_START avr_file_start
14611 #undef TARGET_ASM_FILE_END
14612 #define TARGET_ASM_FILE_END avr_file_end
14613
14614 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
14615 #define TARGET_ASM_FUNCTION_END_PROLOGUE avr_asm_function_end_prologue
14616 #undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
14617 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE avr_asm_function_begin_epilogue
14618
14619 #undef TARGET_FUNCTION_VALUE
14620 #define TARGET_FUNCTION_VALUE avr_function_value
14621 #undef TARGET_LIBCALL_VALUE
14622 #define TARGET_LIBCALL_VALUE avr_libcall_value
14623 #undef TARGET_FUNCTION_VALUE_REGNO_P
14624 #define TARGET_FUNCTION_VALUE_REGNO_P avr_function_value_regno_p
14625
14626 #undef TARGET_ATTRIBUTE_TABLE
14627 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
14628 #undef TARGET_INSERT_ATTRIBUTES
14629 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
14630 #undef TARGET_SECTION_TYPE_FLAGS
14631 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
14632
14633 #undef TARGET_ASM_NAMED_SECTION
14634 #define TARGET_ASM_NAMED_SECTION avr_asm_named_section
14635 #undef TARGET_ASM_INIT_SECTIONS
14636 #define TARGET_ASM_INIT_SECTIONS avr_asm_init_sections
14637 #undef TARGET_ENCODE_SECTION_INFO
14638 #define TARGET_ENCODE_SECTION_INFO avr_encode_section_info
14639 #undef TARGET_ASM_SELECT_SECTION
14640 #define TARGET_ASM_SELECT_SECTION avr_asm_select_section
14641
14642 #undef TARGET_ASM_FINAL_POSTSCAN_INSN
14643 #define TARGET_ASM_FINAL_POSTSCAN_INSN avr_asm_final_postscan_insn
14644
14645 #undef TARGET_REGISTER_MOVE_COST
14646 #define TARGET_REGISTER_MOVE_COST avr_register_move_cost
14647 #undef TARGET_MEMORY_MOVE_COST
14648 #define TARGET_MEMORY_MOVE_COST avr_memory_move_cost
14649 #undef TARGET_RTX_COSTS
14650 #define TARGET_RTX_COSTS avr_rtx_costs
14651 #undef TARGET_ADDRESS_COST
14652 #define TARGET_ADDRESS_COST avr_address_cost
14653 #undef TARGET_MACHINE_DEPENDENT_REORG
14654 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
14655 #undef TARGET_FUNCTION_ARG
14656 #define TARGET_FUNCTION_ARG avr_function_arg
14657 #undef TARGET_FUNCTION_ARG_ADVANCE
14658 #define TARGET_FUNCTION_ARG_ADVANCE avr_function_arg_advance
14659
14660 #undef TARGET_SET_CURRENT_FUNCTION
14661 #define TARGET_SET_CURRENT_FUNCTION avr_set_current_function
14662
14663 #undef TARGET_RETURN_IN_MEMORY
14664 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
14665
14666 #undef TARGET_STRICT_ARGUMENT_NAMING
14667 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
14668
14669 #undef TARGET_CONDITIONAL_REGISTER_USAGE
14670 #define TARGET_CONDITIONAL_REGISTER_USAGE avr_conditional_register_usage
14671
14672 #undef TARGET_HARD_REGNO_MODE_OK
14673 #define TARGET_HARD_REGNO_MODE_OK avr_hard_regno_mode_ok
14674 #undef TARGET_HARD_REGNO_SCRATCH_OK
14675 #define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok
14676 #undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED
14677 #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
14678 avr_hard_regno_call_part_clobbered
14679
14680 #undef TARGET_CASE_VALUES_THRESHOLD
14681 #define TARGET_CASE_VALUES_THRESHOLD avr_case_values_threshold
14682
14683 #undef TARGET_FRAME_POINTER_REQUIRED
14684 #define TARGET_FRAME_POINTER_REQUIRED avr_frame_pointer_required_p
14685 #undef TARGET_CAN_ELIMINATE
14686 #define TARGET_CAN_ELIMINATE avr_can_eliminate
14687
14688 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
14689 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS avr_allocate_stack_slots_for_args
14690
14691 #undef TARGET_WARN_FUNC_RETURN
14692 #define TARGET_WARN_FUNC_RETURN avr_warn_func_return
14693
14694 #undef TARGET_CLASS_LIKELY_SPILLED_P
14695 #define TARGET_CLASS_LIKELY_SPILLED_P avr_class_likely_spilled_p
14696
14697 #undef TARGET_OPTION_OVERRIDE
14698 #define TARGET_OPTION_OVERRIDE avr_option_override
14699
14700 #undef TARGET_CANNOT_MODIFY_JUMPS_P
14701 #define TARGET_CANNOT_MODIFY_JUMPS_P avr_cannot_modify_jumps_p
14702
14703 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
14704 #define TARGET_FUNCTION_OK_FOR_SIBCALL avr_function_ok_for_sibcall
14705
14706 #undef TARGET_INIT_BUILTINS
14707 #define TARGET_INIT_BUILTINS avr_init_builtins
14708
14709 #undef TARGET_BUILTIN_DECL
14710 #define TARGET_BUILTIN_DECL avr_builtin_decl
14711
14712 #undef TARGET_EXPAND_BUILTIN
14713 #define TARGET_EXPAND_BUILTIN avr_expand_builtin
14714
14715 #undef TARGET_FOLD_BUILTIN
14716 #define TARGET_FOLD_BUILTIN avr_fold_builtin
14717
14718 #undef TARGET_SCALAR_MODE_SUPPORTED_P
14719 #define TARGET_SCALAR_MODE_SUPPORTED_P avr_scalar_mode_supported_p
14720
14721 #undef TARGET_BUILD_BUILTIN_VA_LIST
14722 #define TARGET_BUILD_BUILTIN_VA_LIST avr_build_builtin_va_list
14723
14724 #undef TARGET_FIXED_POINT_SUPPORTED_P
14725 #define TARGET_FIXED_POINT_SUPPORTED_P hook_bool_void_true
14726
14727 #undef TARGET_CONVERT_TO_TYPE
14728 #define TARGET_CONVERT_TO_TYPE avr_convert_to_type
14729
14730 #undef TARGET_LRA_P
14731 #define TARGET_LRA_P hook_bool_void_false
14732
14733 #undef TARGET_ADDR_SPACE_SUBSET_P
14734 #define TARGET_ADDR_SPACE_SUBSET_P avr_addr_space_subset_p
14735
14736 #undef TARGET_ADDR_SPACE_CONVERT
14737 #define TARGET_ADDR_SPACE_CONVERT avr_addr_space_convert
14738
14739 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
14740 #define TARGET_ADDR_SPACE_ADDRESS_MODE avr_addr_space_address_mode
14741
14742 #undef TARGET_ADDR_SPACE_POINTER_MODE
14743 #define TARGET_ADDR_SPACE_POINTER_MODE avr_addr_space_pointer_mode
14744
14745 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
14746 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
14747 avr_addr_space_legitimate_address_p
14748
14749 #undef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
14750 #define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS avr_addr_space_legitimize_address
14751
14752 #undef TARGET_ADDR_SPACE_DIAGNOSE_USAGE
14753 #define TARGET_ADDR_SPACE_DIAGNOSE_USAGE avr_addr_space_diagnose_usage
14754
14755 #undef TARGET_MODE_DEPENDENT_ADDRESS_P
14756 #define TARGET_MODE_DEPENDENT_ADDRESS_P avr_mode_dependent_address_p
14757
14758 #undef TARGET_PRINT_OPERAND
14759 #define TARGET_PRINT_OPERAND avr_print_operand
14760 #undef TARGET_PRINT_OPERAND_ADDRESS
14761 #define TARGET_PRINT_OPERAND_ADDRESS avr_print_operand_address
14762 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
14763 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P avr_print_operand_punct_valid_p
14764
14765 #undef TARGET_USE_BY_PIECES_INFRASTRUCTURE_P
14766 #define TARGET_USE_BY_PIECES_INFRASTRUCTURE_P \
14767 avr_use_by_pieces_infrastructure_p
14768
14769 #undef TARGET_LEGITIMATE_COMBINED_INSN
14770 #define TARGET_LEGITIMATE_COMBINED_INSN avr_legitimate_combined_insn
14771
14772 #undef TARGET_STARTING_FRAME_OFFSET
14773 #define TARGET_STARTING_FRAME_OFFSET avr_starting_frame_offset
14774
14775 struct gcc_target targetm = TARGET_INITIALIZER;
14776
14777
14778 #include "gt-avr.h"
14779