1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2 Copyright (C) 1998-2021 Free Software Foundation, Inc.
3 Contributed by Denis Chertykov (chertykov@gmail.com)
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
20
21 #define IN_TARGET_CODE 1
22
23 #include "config.h"
24 #include "system.h"
25 #include "intl.h"
26 #include "coretypes.h"
27 #include "backend.h"
28 #include "target.h"
29 #include "rtl.h"
30 #include "tree.h"
31 #include "stringpool.h"
32 #include "attribs.h"
33 #include "cgraph.h"
34 #include "c-family/c-common.h"
35 #include "cfghooks.h"
36 #include "df.h"
37 #include "memmodel.h"
38 #include "tm_p.h"
39 #include "optabs.h"
40 #include "regs.h"
41 #include "emit-rtl.h"
42 #include "recog.h"
43 #include "conditions.h"
44 #include "insn-attr.h"
45 #include "reload.h"
46 #include "varasm.h"
47 #include "calls.h"
48 #include "stor-layout.h"
49 #include "output.h"
50 #include "explow.h"
51 #include "expr.h"
52 #include "langhooks.h"
53 #include "cfgrtl.h"
54 #include "builtins.h"
55 #include "context.h"
56 #include "tree-pass.h"
57 #include "print-rtl.h"
58 #include "rtl-iter.h"
59
60 /* This file should be included last. */
61 #include "target-def.h"
62
63 /* Maximal allowed offset for an address in the LD command */
64 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
65
66 /* The 4 bits starting at SECTION_MACH_DEP are reserved to store the
67 address space where data is to be located.
68 As the only non-generic address spaces are all located in flash,
69 this can be used to test if data shall go into some .progmem* section.
70 This must be the rightmost field of machine dependent section flags. */
71 #define AVR_SECTION_PROGMEM (0xf * SECTION_MACH_DEP)
72
73 /* Similar 4-bit region for SYMBOL_REF_FLAGS. */
74 #define AVR_SYMBOL_FLAG_PROGMEM (0xf * SYMBOL_FLAG_MACH_DEP)
75
76 /* Similar 4-bit region in SYMBOL_REF_FLAGS:
77 Set address-space AS in SYMBOL_REF_FLAGS of SYM */
78 #define AVR_SYMBOL_SET_ADDR_SPACE(SYM,AS) \
79 do { \
80 SYMBOL_REF_FLAGS (sym) &= ~AVR_SYMBOL_FLAG_PROGMEM; \
81 SYMBOL_REF_FLAGS (sym) |= (AS) * SYMBOL_FLAG_MACH_DEP; \
82 } while (0)
83
84 /* Read address-space from SYMBOL_REF_FLAGS of SYM */
85 #define AVR_SYMBOL_GET_ADDR_SPACE(SYM) \
86 ((SYMBOL_REF_FLAGS (sym) & AVR_SYMBOL_FLAG_PROGMEM) \
87 / SYMBOL_FLAG_MACH_DEP)
88
89 /* (AVR_TINY only): Symbol has attribute progmem */
90 #define AVR_SYMBOL_FLAG_TINY_PM \
91 (SYMBOL_FLAG_MACH_DEP << 7)
92
93 /* (AVR_TINY only): Symbol has attribute absdata */
94 #define AVR_SYMBOL_FLAG_TINY_ABSDATA \
95 (SYMBOL_FLAG_MACH_DEP << 8)
96
97 #define TINY_ADIW(REG1, REG2, I) \
98 "subi " #REG1 ",lo8(-(" #I "))" CR_TAB \
99 "sbci " #REG2 ",hi8(-(" #I "))"
100
101 #define TINY_SBIW(REG1, REG2, I) \
102 "subi " #REG1 ",lo8((" #I "))" CR_TAB \
103 "sbci " #REG2 ",hi8((" #I "))"
104
105 #define AVR_TMP_REGNO (AVR_TINY ? TMP_REGNO_TINY : TMP_REGNO)
106 #define AVR_ZERO_REGNO (AVR_TINY ? ZERO_REGNO_TINY : ZERO_REGNO)
107
108 /* Known address spaces. The order must be the same as in the respective
109 enum from avr.h (or designated initialized must be used). */
110 const avr_addrspace_t avr_addrspace[ADDR_SPACE_COUNT] =
111 {
112 { ADDR_SPACE_RAM, 0, 2, "", 0, NULL },
113 { ADDR_SPACE_FLASH, 1, 2, "__flash", 0, ".progmem.data" },
114 { ADDR_SPACE_FLASH1, 1, 2, "__flash1", 1, ".progmem1.data" },
115 { ADDR_SPACE_FLASH2, 1, 2, "__flash2", 2, ".progmem2.data" },
116 { ADDR_SPACE_FLASH3, 1, 2, "__flash3", 3, ".progmem3.data" },
117 { ADDR_SPACE_FLASH4, 1, 2, "__flash4", 4, ".progmem4.data" },
118 { ADDR_SPACE_FLASH5, 1, 2, "__flash5", 5, ".progmem5.data" },
119 { ADDR_SPACE_MEMX, 1, 3, "__memx", 0, ".progmemx.data" },
120 };
121
122
123 /* Holding RAM addresses of some SFRs used by the compiler and that
124 are unique over all devices in an architecture like 'avr4'. */
125
126 typedef struct
127 {
128 /* SREG: The processor status */
129 int sreg;
130
131 /* RAMPX, RAMPY, RAMPD and CCP of XMEGA */
132 int ccp;
133 int rampd;
134 int rampx;
135 int rampy;
136
137 /* RAMPZ: The high byte of 24-bit address used with ELPM */
138 int rampz;
139
140 /* SP: The stack pointer and its low and high byte */
141 int sp_l;
142 int sp_h;
143 } avr_addr_t;
144
145 static avr_addr_t avr_addr;
146
147
148 /* Prototypes for local helper functions. */
149
150 static const char* out_movqi_r_mr (rtx_insn *, rtx[], int*);
151 static const char* out_movhi_r_mr (rtx_insn *, rtx[], int*);
152 static const char* out_movsi_r_mr (rtx_insn *, rtx[], int*);
153 static const char* out_movqi_mr_r (rtx_insn *, rtx[], int*);
154 static const char* out_movhi_mr_r (rtx_insn *, rtx[], int*);
155 static const char* out_movsi_mr_r (rtx_insn *, rtx[], int*);
156
157 static int get_sequence_length (rtx_insn *insns);
158 static int sequent_regs_live (void);
159 static const char *ptrreg_to_str (int);
160 static const char *cond_string (enum rtx_code);
161 static int avr_num_arg_regs (machine_mode, const_tree);
162 static int avr_operand_rtx_cost (rtx, machine_mode, enum rtx_code,
163 int, bool);
164 static void output_reload_in_const (rtx*, rtx, int*, bool);
165 static struct machine_function * avr_init_machine_status (void);
166
167
168 /* Prototypes for hook implementors if needed before their implementation. */
169
170 static bool avr_rtx_costs (rtx, machine_mode, int, int, int*, bool);
171
172
173 /* Allocate registers from r25 to r8 for parameters for function calls. */
174 #define FIRST_CUM_REG 26
175
176 /* Last call saved register */
177 #define LAST_CALLEE_SAVED_REG (AVR_TINY ? 19 : 17)
178
179 /* Implicit target register of LPM instruction (R0) */
180 extern GTY(()) rtx lpm_reg_rtx;
181 rtx lpm_reg_rtx;
182
183 /* (Implicit) address register of LPM instruction (R31:R30 = Z) */
184 extern GTY(()) rtx lpm_addr_reg_rtx;
185 rtx lpm_addr_reg_rtx;
186
187 /* Temporary register RTX (reg:QI TMP_REGNO) */
188 extern GTY(()) rtx tmp_reg_rtx;
189 rtx tmp_reg_rtx;
190
191 /* Zeroed register RTX (reg:QI ZERO_REGNO) */
192 extern GTY(()) rtx zero_reg_rtx;
193 rtx zero_reg_rtx;
194
195 /* Condition Code register RTX (reg:CC REG_CC) */
196 extern GTY(()) rtx cc_reg_rtx;
197 rtx cc_reg_rtx;
198
199 /* RTXs for all general purpose registers as QImode */
200 extern GTY(()) rtx all_regs_rtx[32];
201 rtx all_regs_rtx[32];
202
203 /* SREG, the processor status */
204 extern GTY(()) rtx sreg_rtx;
205 rtx sreg_rtx;
206
207 /* RAMP* special function registers */
208 extern GTY(()) rtx rampd_rtx;
209 extern GTY(()) rtx rampx_rtx;
210 extern GTY(()) rtx rampy_rtx;
211 extern GTY(()) rtx rampz_rtx;
212 rtx rampd_rtx;
213 rtx rampx_rtx;
214 rtx rampy_rtx;
215 rtx rampz_rtx;
216
217 /* RTX containing the strings "" and "e", respectively */
218 static GTY(()) rtx xstring_empty;
219 static GTY(()) rtx xstring_e;
220
221 /* Current architecture. */
222 const avr_arch_t *avr_arch;
223
224 /* Unnamed sections associated to __attribute__((progmem)) aka. PROGMEM
225 or to address space __flash* or __memx. Only used as singletons inside
226 avr_asm_select_section, but it must not be local there because of GTY. */
227 static GTY(()) section *progmem_section[ADDR_SPACE_COUNT];
228
229 /* Condition for insns/expanders from avr-dimode.md. */
230 bool avr_have_dimode = true;
231
232 /* To track if code will use .bss and/or .data. */
233 bool avr_need_clear_bss_p = false;
234 bool avr_need_copy_data_p = false;
235
236
237 /* Transform UP into lowercase and write the result to LO.
238 You must provide enough space for LO. Return LO. */
239
240 static char*
avr_tolower(char * lo,const char * up)241 avr_tolower (char *lo, const char *up)
242 {
243 char *lo0 = lo;
244
245 for (; *up; up++, lo++)
246 *lo = TOLOWER (*up);
247
248 *lo = '\0';
249
250 return lo0;
251 }
252
253
254 /* Constraint helper function. XVAL is a CONST_INT or a CONST_DOUBLE.
255 Return true if the least significant N_BYTES bytes of XVAL all have a
256 popcount in POP_MASK and false, otherwise. POP_MASK represents a subset
257 of integers which contains an integer N iff bit N of POP_MASK is set. */
258
259 bool
avr_popcount_each_byte(rtx xval,int n_bytes,int pop_mask)260 avr_popcount_each_byte (rtx xval, int n_bytes, int pop_mask)
261 {
262 machine_mode mode = GET_MODE (xval);
263
264 if (VOIDmode == mode)
265 mode = SImode;
266
267 for (int i = 0; i < n_bytes; i++)
268 {
269 rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
270 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
271
272 if ((pop_mask & (1 << popcount_hwi (val8))) == 0)
273 return false;
274 }
275
276 return true;
277 }
278
279
280 /* Access some RTX as INT_MODE. If X is a CONST_FIXED we can get
281 the bit representation of X by "casting" it to CONST_INT. */
282
283 rtx
avr_to_int_mode(rtx x)284 avr_to_int_mode (rtx x)
285 {
286 machine_mode mode = GET_MODE (x);
287
288 return VOIDmode == mode
289 ? x
290 : simplify_gen_subreg (int_mode_for_mode (mode).require (), x, mode, 0);
291 }
292
293 namespace {
294
295 static const pass_data avr_pass_data_recompute_notes =
296 {
297 RTL_PASS, // type
298 "", // name (will be patched)
299 OPTGROUP_NONE, // optinfo_flags
300 TV_DF_SCAN, // tv_id
301 0, // properties_required
302 0, // properties_provided
303 0, // properties_destroyed
304 0, // todo_flags_start
305 TODO_df_finish | TODO_df_verify // todo_flags_finish
306 };
307
308
309 class avr_pass_recompute_notes : public rtl_opt_pass
310 {
311 public:
avr_pass_recompute_notes(gcc::context * ctxt,const char * name)312 avr_pass_recompute_notes (gcc::context *ctxt, const char *name)
313 : rtl_opt_pass (avr_pass_data_recompute_notes, ctxt)
314 {
315 this->name = name;
316 }
317
execute(function *)318 virtual unsigned int execute (function*)
319 {
320 df_note_add_problem ();
321 df_analyze ();
322
323 return 0;
324 }
325 }; // avr_pass_recompute_notes
326
327 static const pass_data avr_pass_data_casesi =
328 {
329 RTL_PASS, // type
330 "", // name (will be patched)
331 OPTGROUP_NONE, // optinfo_flags
332 TV_DF_SCAN, // tv_id
333 0, // properties_required
334 0, // properties_provided
335 0, // properties_destroyed
336 0, // todo_flags_start
337 0 // todo_flags_finish
338 };
339
340
341 class avr_pass_casesi : public rtl_opt_pass
342 {
343 public:
avr_pass_casesi(gcc::context * ctxt,const char * name)344 avr_pass_casesi (gcc::context *ctxt, const char *name)
345 : rtl_opt_pass (avr_pass_data_casesi, ctxt)
346 {
347 this->name = name;
348 }
349
350 void avr_rest_of_handle_casesi (function*);
351
gate(function *)352 virtual bool gate (function*) { return optimize > 0; }
353
execute(function * func)354 virtual unsigned int execute (function *func)
355 {
356 avr_rest_of_handle_casesi (func);
357
358 return 0;
359 }
360 }; // avr_pass_casesi
361
362 } // anon namespace
363
364 rtl_opt_pass*
make_avr_pass_recompute_notes(gcc::context * ctxt)365 make_avr_pass_recompute_notes (gcc::context *ctxt)
366 {
367 return new avr_pass_recompute_notes (ctxt, "avr-notes-free-cfg");
368 }
369
370 rtl_opt_pass*
make_avr_pass_casesi(gcc::context * ctxt)371 make_avr_pass_casesi (gcc::context *ctxt)
372 {
373 return new avr_pass_casesi (ctxt, "avr-casesi");
374 }
375
376
377 /* Make one parallel insn with all the patterns from insns i[0]..i[5]. */
378
379 static rtx_insn*
avr_parallel_insn_from_insns(rtx_insn * i[5])380 avr_parallel_insn_from_insns (rtx_insn *i[5])
381 {
382 rtvec vec = gen_rtvec (5, PATTERN (i[0]), PATTERN (i[1]), PATTERN (i[2]),
383 PATTERN (i[3]), PATTERN (i[4]));
384 start_sequence();
385 emit (gen_rtx_PARALLEL (VOIDmode, vec));
386 rtx_insn *insn = get_insns();
387 end_sequence();
388
389 return insn;
390 }
391
392
393 /* Return true if we see an insn stream generated by casesi expander together
394 with an extension to SImode of the switch value.
395
396 If this is the case, fill in the insns from casesi to INSNS[1..5] and
397 the SImode extension to INSNS[0]. Moreover, extract the operands of
398 pattern casesi_<mode>_sequence forged from the sequence to recog_data. */
399
400 static bool
avr_is_casesi_sequence(basic_block bb,rtx_insn * insn,rtx_insn * insns[5])401 avr_is_casesi_sequence (basic_block bb, rtx_insn *insn, rtx_insn *insns[5])
402 {
403 rtx set_4, set_0;
404
405 /* A first and quick test for a casesi sequences. As a side effect of
406 the test, harvest respective insns to INSNS[0..4]. */
407
408 if (!(JUMP_P (insns[4] = insn)
409 // casesi is the only insn that comes up with UNSPEC_INDEX_JMP,
410 // hence the following test ensures that we are actually dealing
411 // with code from casesi.
412 && (set_4 = single_set (insns[4]))
413 && UNSPEC == GET_CODE (SET_SRC (set_4))
414 && UNSPEC_INDEX_JMP == XINT (SET_SRC (set_4), 1)
415
416 && (insns[3] = prev_real_insn (insns[4]))
417 && (insns[2] = prev_real_insn (insns[3]))
418 && (insns[1] = prev_real_insn (insns[2]))
419
420 // Insn prior to casesi.
421 && (insns[0] = prev_real_insn (insns[1]))
422 && (set_0 = single_set (insns[0]))
423 && extend_operator (SET_SRC (set_0), SImode)))
424 {
425 return false;
426 }
427
428 if (dump_file)
429 {
430 fprintf (dump_file, ";; Sequence from casesi in "
431 "[bb %d]:\n\n", bb->index);
432 for (int i = 0; i < 5; i++)
433 print_rtl_single (dump_file, insns[i]);
434 }
435
436 /* We have to deal with quite some operands. Extracting them by hand
437 would be tedious, therefore wrap the insn patterns into a parallel,
438 run recog against it and then use insn extract to get the operands. */
439
440 rtx_insn *xinsn = avr_parallel_insn_from_insns (insns);
441
442 INSN_CODE (xinsn) = recog (PATTERN (xinsn), xinsn, NULL /* num_clobbers */);
443
444 /* Failing to recognize means that someone changed the casesi expander or
445 that some passes prior to this one performed some unexpected changes.
446 Gracefully drop such situations instead of aborting. */
447
448 if (INSN_CODE (xinsn) < 0)
449 {
450 if (dump_file)
451 fprintf (dump_file, ";; Sequence not recognized, giving up.\n\n");
452
453 return false;
454 }
455
456 gcc_assert (CODE_FOR_casesi_qi_sequence == INSN_CODE (xinsn)
457 || CODE_FOR_casesi_hi_sequence == INSN_CODE (xinsn));
458
459 extract_insn (xinsn);
460
461 // Assert on the anatomy of xinsn's operands we are going to work with.
462
463 gcc_assert (recog_data.n_operands == 11);
464 gcc_assert (recog_data.n_dups == 4);
465
466 if (dump_file)
467 {
468 fprintf (dump_file, ";; Operands extracted:\n");
469 for (int i = 0; i < recog_data.n_operands; i++)
470 avr_fdump (dump_file, ";; $%d = %r\n", i, recog_data.operand[i]);
471 fprintf (dump_file, "\n");
472 }
473
474 return true;
475 }
476
477
478 /* Perform some extra checks on operands of casesi_<mode>_sequence.
479 Not all operand dependencies can be described by means of predicates.
480 This function performs left over checks and should always return true.
481 Returning false means that someone changed the casesi expander but did
482 not adjust casesi_<mode>_sequence. */
483
484 bool
avr_casei_sequence_check_operands(rtx * xop)485 avr_casei_sequence_check_operands (rtx *xop)
486 {
487 rtx sub_5 = NULL_RTX;
488
489 if (AVR_HAVE_EIJMP_EICALL
490 // The last clobber op of the tablejump.
491 && xop[8] == all_regs_rtx[24])
492 {
493 // $6 is: (subreg:SI ($5) 0)
494 sub_5 = xop[6];
495 }
496
497 if (!AVR_HAVE_EIJMP_EICALL
498 // $6 is: (plus:HI (subreg:SI ($5) 0)
499 // (label_ref ($3)))
500 && PLUS == GET_CODE (xop[6])
501 && LABEL_REF == GET_CODE (XEXP (xop[6], 1))
502 && rtx_equal_p (xop[3], XEXP (XEXP (xop[6], 1), 0))
503 // The last clobber op of the tablejump.
504 && xop[8] == const0_rtx)
505 {
506 sub_5 = XEXP (xop[6], 0);
507 }
508
509 if (sub_5
510 && SUBREG_P (sub_5)
511 && SUBREG_BYTE (sub_5) == 0
512 && rtx_equal_p (xop[5], SUBREG_REG (sub_5)))
513 return true;
514
515 if (dump_file)
516 fprintf (dump_file, "\n;; Failed condition for casesi_<mode>_sequence\n\n");
517
518 return false;
519 }
520
521
522 /* INSNS[1..4] is a sequence as generated by casesi and INSNS[0] is an
523 extension of an 8-bit or 16-bit integer to SImode. XOP contains the
524 operands of INSNS as extracted by insn_extract from pattern
525 casesi_<mode>_sequence:
526
527 $0: SImode reg switch value as result of $9.
528 $1: Negative of smallest index in switch.
529 $2: Number of entries in switch.
530 $3: Label to table.
531 $4: Label if out-of-bounds.
532 $5: $0 + $1.
533 $6: 3-byte PC: subreg:HI ($5) + label_ref ($3)
534 2-byte PC: subreg:HI ($5)
535 $7: HI reg index into table (Z or pseudo)
536 $8: R24 or const0_rtx (to be clobbered)
537 $9: Extension to SImode of an 8-bit or 16-bit integer register $10.
538 $10: QImode or HImode register input of $9.
539
540 Try to optimize this sequence, i.e. use the original HImode / QImode
541 switch value instead of SImode. */
542
543 static void
avr_optimize_casesi(rtx_insn * insns[5],rtx * xop)544 avr_optimize_casesi (rtx_insn *insns[5], rtx *xop)
545 {
546 // Original mode of the switch value; this is QImode or HImode.
547 machine_mode mode = GET_MODE (xop[10]);
548
549 // How the original switch value was extended to SImode; this is
550 // SIGN_EXTEND or ZERO_EXTEND.
551 enum rtx_code code = GET_CODE (xop[9]);
552
553 // Lower index, upper index (plus one) and range of case calues.
554 HOST_WIDE_INT low_idx = -INTVAL (xop[1]);
555 HOST_WIDE_INT num_idx = INTVAL (xop[2]);
556 HOST_WIDE_INT hig_idx = low_idx + num_idx;
557
558 // Maximum ranges of (un)signed QImode resp. HImode.
559 unsigned umax = QImode == mode ? 0xff : 0xffff;
560 int imax = QImode == mode ? 0x7f : 0x7fff;
561 int imin = -imax - 1;
562
563 // Testing the case range and whether it fits into the range of the
564 // (un)signed mode. This test should actually always pass because it
565 // makes no sense to have case values outside the mode range. Notice
566 // that case labels which are unreachable because they are outside the
567 // mode of the switch value (e.g. "case -1" for uint8_t) have already
568 // been thrown away by the middle-end.
569
570 if (SIGN_EXTEND == code
571 && low_idx >= imin
572 && hig_idx <= imax)
573 {
574 // ok
575 }
576 else if (ZERO_EXTEND == code
577 && low_idx >= 0
578 && (unsigned) hig_idx <= umax)
579 {
580 // ok
581 }
582 else
583 {
584 if (dump_file)
585 fprintf (dump_file, ";; Case ranges too big, giving up.\n\n");
586 return;
587 }
588
589 // Do normalization of switch value $10 and out-of-bound check in its
590 // original mode instead of in SImode. Use a newly created pseudo.
591 // This will replace insns[1..2].
592
593 start_sequence();
594
595 rtx_insn *seq1, *seq2, *last1, *last2;
596
597 rtx reg = copy_to_mode_reg (mode, xop[10]);
598
599 rtx (*gen_add)(rtx,rtx,rtx) = QImode == mode ? gen_addqi3 : gen_addhi3;
600 rtx (*gen_cbranch)(rtx,rtx,rtx,rtx)
601 = QImode == mode ? gen_cbranchqi4 : gen_cbranchhi4;
602
603 emit_insn (gen_add (reg, reg, gen_int_mode (-low_idx, mode)));
604 rtx op0 = reg; rtx op1 = gen_int_mode (num_idx, mode);
605 rtx labelref = copy_rtx (xop[4]);
606 emit_jump_insn (gen_cbranch (gen_rtx_fmt_ee (GTU, VOIDmode, op0, op1),
607 op0, op1,
608 labelref));
609
610 seq1 = get_insns();
611 last1 = get_last_insn();
612 end_sequence();
613
614 emit_insn_after (seq1, insns[2]);
615
616 // After the out-of-bounds test and corresponding branch, use a
617 // 16-bit index. If QImode is used, extend it to HImode first.
618 // This will replace insns[4].
619
620 start_sequence();
621
622 if (QImode == mode)
623 reg = force_reg (HImode, gen_rtx_fmt_e (code, HImode, reg));
624
625 rtx pat_4 = AVR_3_BYTE_PC
626 ? gen_movhi (xop[7], reg)
627 : gen_addhi3 (xop[7], reg, gen_rtx_LABEL_REF (VOIDmode, xop[3]));
628
629 emit_insn (pat_4);
630
631 seq2 = get_insns();
632 last2 = get_last_insn();
633 end_sequence();
634
635 emit_insn_after (seq2, insns[3]);
636
637 if (dump_file)
638 {
639 fprintf (dump_file, ";; New insns: ");
640
641 for (rtx_insn *insn = seq1; ; insn = NEXT_INSN (insn))
642 {
643 fprintf (dump_file, "%d, ", INSN_UID (insn));
644 if (insn == last1)
645 break;
646 }
647 for (rtx_insn *insn = seq2; ; insn = NEXT_INSN (insn))
648 {
649 fprintf (dump_file, "%d%s", INSN_UID (insn),
650 insn == last2 ? ".\n\n" : ", ");
651 if (insn == last2)
652 break;
653 }
654
655 fprintf (dump_file, ";; Deleting insns: %d, %d, %d.\n\n",
656 INSN_UID (insns[1]), INSN_UID (insns[2]), INSN_UID (insns[3]));
657 }
658
659 // Pseudodelete the SImode and subreg of SImode insns. We don't care
660 // about the extension insns[0]: Its result is now unused and other
661 // passes will clean it up.
662
663 SET_INSN_DELETED (insns[1]);
664 SET_INSN_DELETED (insns[2]);
665 SET_INSN_DELETED (insns[3]);
666 }
667
668
669 void
avr_rest_of_handle_casesi(function * func)670 avr_pass_casesi::avr_rest_of_handle_casesi (function *func)
671 {
672 basic_block bb;
673
674 FOR_EACH_BB_FN (bb, func)
675 {
676 rtx_insn *insn, *insns[5];
677
678 FOR_BB_INSNS (bb, insn)
679 {
680 if (avr_is_casesi_sequence (bb, insn, insns))
681 {
682 avr_optimize_casesi (insns, recog_data.operand);
683 }
684 }
685 }
686 }
687
688
689 /* Set `avr_arch' as specified by `-mmcu='.
690 Return true on success. */
691
692 static bool
avr_set_core_architecture(void)693 avr_set_core_architecture (void)
694 {
695 /* Search for mcu core architecture. */
696
697 if (!avr_mmcu)
698 avr_mmcu = AVR_MMCU_DEFAULT;
699
700 avr_arch = &avr_arch_types[0];
701
702 for (const avr_mcu_t *mcu = avr_mcu_types; ; mcu++)
703 {
704 if (mcu->name == NULL)
705 {
706 /* Reached the end of `avr_mcu_types'. This should actually never
707 happen as options are provided by device-specs. It could be a
708 typo in a device-specs or calling the compiler proper directly
709 with -mmcu=<device>. */
710
711 error ("unknown core architecture %qs specified with %qs",
712 avr_mmcu, "-mmcu=");
713 avr_inform_core_architectures ();
714 break;
715 }
716 else if (strcmp (mcu->name, avr_mmcu) == 0
717 // Is this a proper architecture ?
718 && mcu->macro == NULL)
719 {
720 avr_arch = &avr_arch_types[mcu->arch_id];
721 if (avr_n_flash < 0)
722 avr_n_flash = 1 + (mcu->flash_size - 1) / 0x10000;
723
724 return true;
725 }
726 }
727
728 return false;
729 }
730
731
732 /* Implement `TARGET_OPTION_OVERRIDE'. */
733
734 static void
avr_option_override(void)735 avr_option_override (void)
736 {
737 /* caller-save.c looks for call-clobbered hard registers that are assigned
738 to pseudos that cross calls and tries so save-restore them around calls
739 in order to reduce the number of stack slots needed.
740
741 This might lead to situations where reload is no more able to cope
742 with the challenge of AVR's very few address registers and fails to
743 perform the requested spills. */
744
745 if (avr_strict_X)
746 flag_caller_saves = 0;
747
748 /* Unwind tables currently require a frame pointer for correctness,
749 see toplev.c:process_options(). */
750
751 if ((flag_unwind_tables
752 || flag_non_call_exceptions
753 || flag_asynchronous_unwind_tables)
754 && !ACCUMULATE_OUTGOING_ARGS)
755 {
756 flag_omit_frame_pointer = 0;
757 }
758
759 if (flag_pic == 1)
760 warning (OPT_fpic, "%<-fpic%> is not supported");
761 if (flag_pic == 2)
762 warning (OPT_fPIC, "%<-fPIC%> is not supported");
763 if (flag_pie == 1)
764 warning (OPT_fpie, "%<-fpie%> is not supported");
765 if (flag_pie == 2)
766 warning (OPT_fPIE, "%<-fPIE%> is not supported");
767
768 #if !defined (HAVE_AS_AVR_MGCCISR_OPTION)
769 avr_gasisr_prologues = 0;
770 #endif
771
772 if (!avr_set_core_architecture())
773 return;
774
775 /* Sould be set by avr-common.c */
776 gcc_assert (avr_long_double >= avr_double && avr_double >= 32);
777
778 /* RAM addresses of some SFRs common to all devices in respective arch. */
779
780 /* SREG: Status Register containing flags like I (global IRQ) */
781 avr_addr.sreg = 0x3F + avr_arch->sfr_offset;
782
783 /* RAMPZ: Address' high part when loading via ELPM */
784 avr_addr.rampz = 0x3B + avr_arch->sfr_offset;
785
786 avr_addr.rampy = 0x3A + avr_arch->sfr_offset;
787 avr_addr.rampx = 0x39 + avr_arch->sfr_offset;
788 avr_addr.rampd = 0x38 + avr_arch->sfr_offset;
789 avr_addr.ccp = (AVR_TINY ? 0x3C : 0x34) + avr_arch->sfr_offset;
790
791 /* SP: Stack Pointer (SP_H:SP_L) */
792 avr_addr.sp_l = 0x3D + avr_arch->sfr_offset;
793 avr_addr.sp_h = avr_addr.sp_l + 1;
794
795 init_machine_status = avr_init_machine_status;
796
797 avr_log_set_avr_log();
798 }
799
800 /* Function to set up the backend function structure. */
801
802 static struct machine_function *
avr_init_machine_status(void)803 avr_init_machine_status (void)
804 {
805 return ggc_cleared_alloc<machine_function> ();
806 }
807
808
809 /* Implement `INIT_EXPANDERS'. */
810 /* The function works like a singleton. */
811
812 void
avr_init_expanders(void)813 avr_init_expanders (void)
814 {
815 for (int regno = 0; regno < 32; regno ++)
816 all_regs_rtx[regno] = gen_rtx_REG (QImode, regno);
817
818 lpm_reg_rtx = all_regs_rtx[LPM_REGNO];
819 tmp_reg_rtx = all_regs_rtx[AVR_TMP_REGNO];
820 zero_reg_rtx = all_regs_rtx[AVR_ZERO_REGNO];
821
822 cc_reg_rtx = gen_rtx_REG (CCmode, REG_CC);
823
824 lpm_addr_reg_rtx = gen_rtx_REG (HImode, REG_Z);
825
826 sreg_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.sreg));
827 rampd_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampd));
828 rampx_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampx));
829 rampy_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampy));
830 rampz_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampz));
831
832 xstring_empty = gen_rtx_CONST_STRING (VOIDmode, "");
833 xstring_e = gen_rtx_CONST_STRING (VOIDmode, "e");
834
835 /* TINY core does not have regs r10-r16, but avr-dimode.md expects them
836 to be present */
837 if (AVR_TINY)
838 avr_have_dimode = false;
839 }
840
841
842 /* Implement `REGNO_REG_CLASS'. */
843 /* Return register class for register R. */
844
845 enum reg_class
avr_regno_reg_class(int r)846 avr_regno_reg_class (int r)
847 {
848 static const enum reg_class reg_class_tab[] =
849 {
850 R0_REG,
851 /* r1 - r15 */
852 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
853 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
854 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
855 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
856 /* r16 - r23 */
857 SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
858 SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
859 /* r24, r25 */
860 ADDW_REGS, ADDW_REGS,
861 /* X: r26, 27 */
862 POINTER_X_REGS, POINTER_X_REGS,
863 /* Y: r28, r29 */
864 POINTER_Y_REGS, POINTER_Y_REGS,
865 /* Z: r30, r31 */
866 POINTER_Z_REGS, POINTER_Z_REGS,
867 /* SP: SPL, SPH */
868 STACK_REG, STACK_REG
869 };
870
871 if (r <= 33)
872 return reg_class_tab[r];
873
874 if (r == REG_CC)
875 return CC_REG;
876
877 return ALL_REGS;
878 }
879
880
881 /* Implement `TARGET_SCALAR_MODE_SUPPORTED_P'. */
882
883 static bool
avr_scalar_mode_supported_p(scalar_mode mode)884 avr_scalar_mode_supported_p (scalar_mode mode)
885 {
886 if (ALL_FIXED_POINT_MODE_P (mode))
887 return true;
888
889 if (PSImode == mode)
890 return true;
891
892 return default_scalar_mode_supported_p (mode);
893 }
894
895
896 /* Return TRUE if DECL is a VAR_DECL located in flash and FALSE, otherwise. */
897
898 static bool
avr_decl_flash_p(tree decl)899 avr_decl_flash_p (tree decl)
900 {
901 if (TREE_CODE (decl) != VAR_DECL
902 || TREE_TYPE (decl) == error_mark_node)
903 {
904 return false;
905 }
906
907 return !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (decl)));
908 }
909
910
911 /* Return TRUE if DECL is a VAR_DECL located in the 24-bit flash
912 address space and FALSE, otherwise. */
913
914 static bool
avr_decl_memx_p(tree decl)915 avr_decl_memx_p (tree decl)
916 {
917 if (TREE_CODE (decl) != VAR_DECL
918 || TREE_TYPE (decl) == error_mark_node)
919 {
920 return false;
921 }
922
923 return (ADDR_SPACE_MEMX == TYPE_ADDR_SPACE (TREE_TYPE (decl)));
924 }
925
926
927 /* Return TRUE if X is a MEM rtx located in flash and FALSE, otherwise. */
928
929 bool
avr_mem_flash_p(rtx x)930 avr_mem_flash_p (rtx x)
931 {
932 return (MEM_P (x)
933 && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x)));
934 }
935
936
937 /* Return TRUE if X is a MEM rtx located in the 24-bit flash
938 address space and FALSE, otherwise. */
939
940 bool
avr_mem_memx_p(rtx x)941 avr_mem_memx_p (rtx x)
942 {
943 return (MEM_P (x)
944 && ADDR_SPACE_MEMX == MEM_ADDR_SPACE (x));
945 }
946
947
948 /* A helper for the subsequent function attribute used to dig for
949 attribute 'name' in a FUNCTION_DECL or FUNCTION_TYPE */
950
951 static inline int
avr_lookup_function_attribute1(const_tree func,const char * name)952 avr_lookup_function_attribute1 (const_tree func, const char *name)
953 {
954 if (FUNCTION_DECL == TREE_CODE (func))
955 {
956 if (NULL_TREE != lookup_attribute (name, DECL_ATTRIBUTES (func)))
957 {
958 return true;
959 }
960
961 func = TREE_TYPE (func);
962 }
963
964 gcc_assert (TREE_CODE (func) == FUNCTION_TYPE
965 || TREE_CODE (func) == METHOD_TYPE);
966
967 return NULL_TREE != lookup_attribute (name, TYPE_ATTRIBUTES (func));
968 }
969
970 /* Return nonzero if FUNC is a naked function. */
971
972 static int
avr_naked_function_p(tree func)973 avr_naked_function_p (tree func)
974 {
975 return avr_lookup_function_attribute1 (func, "naked");
976 }
977
978 /* Return nonzero if FUNC is an interrupt function as specified
979 by the "interrupt" attribute. */
980
981 static int
avr_interrupt_function_p(tree func)982 avr_interrupt_function_p (tree func)
983 {
984 return avr_lookup_function_attribute1 (func, "interrupt");
985 }
986
987 /* Return nonzero if FUNC is a signal function as specified
988 by the "signal" attribute. */
989
990 static int
avr_signal_function_p(tree func)991 avr_signal_function_p (tree func)
992 {
993 return avr_lookup_function_attribute1 (func, "signal");
994 }
995
996 /* Return nonzero if FUNC is an OS_task function. */
997
998 static int
avr_OS_task_function_p(tree func)999 avr_OS_task_function_p (tree func)
1000 {
1001 return avr_lookup_function_attribute1 (func, "OS_task");
1002 }
1003
1004 /* Return nonzero if FUNC is an OS_main function. */
1005
1006 static int
avr_OS_main_function_p(tree func)1007 avr_OS_main_function_p (tree func)
1008 {
1009 return avr_lookup_function_attribute1 (func, "OS_main");
1010 }
1011
1012
1013 /* Return nonzero if FUNC is a no_gccisr function as specified
1014 by the "no_gccisr" attribute. */
1015
1016 static int
avr_no_gccisr_function_p(tree func)1017 avr_no_gccisr_function_p (tree func)
1018 {
1019 return avr_lookup_function_attribute1 (func, "no_gccisr");
1020 }
1021
1022 /* Implement `TARGET_SET_CURRENT_FUNCTION'. */
1023 /* Sanity cheching for above function attributes. */
1024
1025 static void
avr_set_current_function(tree decl)1026 avr_set_current_function (tree decl)
1027 {
1028 if (decl == NULL_TREE
1029 || current_function_decl == NULL_TREE
1030 || current_function_decl == error_mark_node
1031 || ! cfun->machine
1032 || cfun->machine->attributes_checked_p)
1033 return;
1034
1035 location_t loc = DECL_SOURCE_LOCATION (decl);
1036
1037 cfun->machine->is_naked = avr_naked_function_p (decl);
1038 cfun->machine->is_signal = avr_signal_function_p (decl);
1039 cfun->machine->is_interrupt = avr_interrupt_function_p (decl);
1040 cfun->machine->is_OS_task = avr_OS_task_function_p (decl);
1041 cfun->machine->is_OS_main = avr_OS_main_function_p (decl);
1042 cfun->machine->is_no_gccisr = avr_no_gccisr_function_p (decl);
1043
1044 const char *isr = cfun->machine->is_interrupt ? "interrupt" : "signal";
1045
1046 /* Too much attributes make no sense as they request conflicting features. */
1047
1048 if (cfun->machine->is_OS_task
1049 && (cfun->machine->is_signal || cfun->machine->is_interrupt))
1050 error_at (loc, "function attributes %qs and %qs are mutually exclusive",
1051 "OS_task", isr);
1052
1053 if (cfun->machine->is_OS_main
1054 && (cfun->machine->is_signal || cfun->machine->is_interrupt))
1055 error_at (loc, "function attributes %qs and %qs are mutually exclusive",
1056 "OS_main", isr);
1057
1058 if (cfun->machine->is_interrupt || cfun->machine->is_signal)
1059 {
1060 tree args = TYPE_ARG_TYPES (TREE_TYPE (decl));
1061 tree ret = TREE_TYPE (TREE_TYPE (decl));
1062 const char *name;
1063
1064 name = DECL_ASSEMBLER_NAME_SET_P (decl)
1065 ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))
1066 : IDENTIFIER_POINTER (DECL_NAME (decl));
1067
1068 /* Skip a leading '*' that might still prefix the assembler name,
1069 e.g. in non-LTO runs. */
1070
1071 name = default_strip_name_encoding (name);
1072
1073 /* Interrupt handlers must be void __vector (void) functions. */
1074
1075 if (args && TREE_CODE (TREE_VALUE (args)) != VOID_TYPE)
1076 error_at (loc, "%qs function cannot have arguments", isr);
1077
1078 if (TREE_CODE (ret) != VOID_TYPE)
1079 error_at (loc, "%qs function cannot return a value", isr);
1080
1081 #if defined WITH_AVRLIBC
1082 /* Silently ignore 'signal' if 'interrupt' is present. AVR-LibC startet
1083 using this when it switched from SIGNAL and INTERRUPT to ISR. */
1084
1085 if (cfun->machine->is_interrupt)
1086 cfun->machine->is_signal = 0;
1087
1088 /* If the function has the 'signal' or 'interrupt' attribute, ensure
1089 that the name of the function is "__vector_NN" so as to catch
1090 when the user misspells the vector name. */
1091
1092 if (!startswith (name, "__vector"))
1093 warning_at (loc, OPT_Wmisspelled_isr, "%qs appears to be a misspelled "
1094 "%qs handler, missing %<__vector%> prefix", name, isr);
1095 #endif // AVR-LibC naming conventions
1096 }
1097
1098 #if defined WITH_AVRLIBC
1099 // Common problem is using "ISR" without first including avr/interrupt.h.
1100 const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
1101 name = default_strip_name_encoding (name);
1102 if (strcmp ("ISR", name) == 0
1103 || strcmp ("INTERRUPT", name) == 0
1104 || strcmp ("SIGNAL", name) == 0)
1105 {
1106 warning_at (loc, OPT_Wmisspelled_isr, "%qs is a reserved identifier"
1107 " in AVR-LibC. Consider %<#include <avr/interrupt.h>%>"
1108 " before using the %qs macro", name, name);
1109 }
1110 #endif // AVR-LibC naming conventions
1111
1112 /* Don't print the above diagnostics more than once. */
1113
1114 cfun->machine->attributes_checked_p = 1;
1115 }
1116
1117
1118 /* Implement `ACCUMULATE_OUTGOING_ARGS'. */
1119
1120 int
avr_accumulate_outgoing_args(void)1121 avr_accumulate_outgoing_args (void)
1122 {
1123 if (!cfun)
1124 return TARGET_ACCUMULATE_OUTGOING_ARGS;
1125
1126 /* FIXME: For setjmp and in avr_builtin_setjmp_frame_value we don't know
1127 what offset is correct. In some cases it is relative to
1128 virtual_outgoing_args_rtx and in others it is relative to
1129 virtual_stack_vars_rtx. For example code see
1130 gcc.c-torture/execute/built-in-setjmp.c
1131 gcc.c-torture/execute/builtins/sprintf-chk.c */
1132
1133 return (TARGET_ACCUMULATE_OUTGOING_ARGS
1134 && !(cfun->calls_setjmp
1135 || cfun->has_nonlocal_label));
1136 }
1137
1138
1139 /* Report contribution of accumulated outgoing arguments to stack size. */
1140
1141 static inline int
avr_outgoing_args_size(void)1142 avr_outgoing_args_size (void)
1143 {
1144 return (ACCUMULATE_OUTGOING_ARGS
1145 ? (HOST_WIDE_INT) crtl->outgoing_args_size : 0);
1146 }
1147
1148
1149 /* Implement TARGET_STARTING_FRAME_OFFSET. */
1150 /* This is the offset from the frame pointer register to the first stack slot
1151 that contains a variable living in the frame. */
1152
1153 static HOST_WIDE_INT
avr_starting_frame_offset(void)1154 avr_starting_frame_offset (void)
1155 {
1156 return 1 + avr_outgoing_args_size ();
1157 }
1158
1159
1160 /* Return the number of hard registers to push/pop in the prologue/epilogue
1161 of the current function, and optionally store these registers in SET. */
1162
1163 static int
avr_regs_to_save(HARD_REG_SET * set)1164 avr_regs_to_save (HARD_REG_SET *set)
1165 {
1166 int count;
1167 int int_or_sig_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1168
1169 if (set)
1170 CLEAR_HARD_REG_SET (*set);
1171 count = 0;
1172
1173 /* No need to save any registers if the function never returns or
1174 has the "OS_task" or "OS_main" attribute. */
1175
1176 if (TREE_THIS_VOLATILE (current_function_decl)
1177 || cfun->machine->is_OS_task
1178 || cfun->machine->is_OS_main)
1179 return 0;
1180
1181 for (int reg = 0; reg < 32; reg++)
1182 {
1183 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
1184 any global register variables. */
1185
1186 if (fixed_regs[reg])
1187 continue;
1188
1189 if ((int_or_sig_p && !crtl->is_leaf && call_used_or_fixed_reg_p (reg))
1190 || (df_regs_ever_live_p (reg)
1191 && (int_or_sig_p || !call_used_or_fixed_reg_p (reg))
1192 /* Don't record frame pointer registers here. They are treated
1193 indivitually in prologue. */
1194 && !(frame_pointer_needed
1195 && (reg == REG_Y || reg == REG_Y + 1))))
1196 {
1197 if (set)
1198 SET_HARD_REG_BIT (*set, reg);
1199 count++;
1200 }
1201 }
1202 return count;
1203 }
1204
1205
1206 /* Implement `TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS' */
1207
1208 static bool
avr_allocate_stack_slots_for_args(void)1209 avr_allocate_stack_slots_for_args (void)
1210 {
1211 return !cfun->machine->is_naked;
1212 }
1213
1214
1215 /* Return true if register FROM can be eliminated via register TO. */
1216
1217 static bool
avr_can_eliminate(const int from ATTRIBUTE_UNUSED,const int to)1218 avr_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
1219 {
1220 return ((frame_pointer_needed && to == FRAME_POINTER_REGNUM)
1221 || !frame_pointer_needed);
1222 }
1223
1224
1225 /* Implement `TARGET_WARN_FUNC_RETURN'. */
1226
1227 static bool
avr_warn_func_return(tree decl)1228 avr_warn_func_return (tree decl)
1229 {
1230 /* Naked functions are implemented entirely in assembly, including the
1231 return sequence, so suppress warnings about this. */
1232
1233 return !avr_naked_function_p (decl);
1234 }
1235
1236 /* Compute offset between arg_pointer and frame_pointer. */
1237
1238 int
avr_initial_elimination_offset(int from,int to)1239 avr_initial_elimination_offset (int from, int to)
1240 {
1241 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
1242 return 0;
1243 else
1244 {
1245 int offset = frame_pointer_needed ? 2 : 0;
1246 int avr_pc_size = AVR_HAVE_EIJMP_EICALL ? 3 : 2;
1247
1248 // If FROM is ARG_POINTER_REGNUM, we are not in an ISR as ISRs
1249 // might not have arguments. Hence the following is not affected
1250 // by gasisr prologues.
1251 offset += avr_regs_to_save (NULL);
1252 return (get_frame_size () + avr_outgoing_args_size()
1253 + avr_pc_size + 1 + offset);
1254 }
1255 }
1256
1257
1258 /* Helper for the function below. */
1259
1260 static void
avr_adjust_type_node(tree * node,machine_mode mode,int sat_p)1261 avr_adjust_type_node (tree *node, machine_mode mode, int sat_p)
1262 {
1263 *node = make_node (FIXED_POINT_TYPE);
1264 TYPE_SATURATING (*node) = sat_p;
1265 TYPE_UNSIGNED (*node) = UNSIGNED_FIXED_POINT_MODE_P (mode);
1266 TYPE_IBIT (*node) = GET_MODE_IBIT (mode);
1267 TYPE_FBIT (*node) = GET_MODE_FBIT (mode);
1268 TYPE_PRECISION (*node) = GET_MODE_BITSIZE (mode);
1269 SET_TYPE_ALIGN (*node, 8);
1270 SET_TYPE_MODE (*node, mode);
1271
1272 layout_type (*node);
1273 }
1274
1275
1276 /* Implement `TARGET_BUILD_BUILTIN_VA_LIST'. */
1277
1278 static tree
avr_build_builtin_va_list(void)1279 avr_build_builtin_va_list (void)
1280 {
1281 /* avr-modes.def adjusts [U]TA to be 64-bit modes with 48 fractional bits.
1282 This is more appropriate for the 8-bit machine AVR than 128-bit modes.
1283 The ADJUST_IBIT/FBIT are handled in toplev:init_adjust_machine_modes()
1284 which is auto-generated by genmodes, but the compiler assigns [U]DAmode
1285 to the long long accum modes instead of the desired [U]TAmode.
1286
1287 Fix this now, right after node setup in tree.c:build_common_tree_nodes().
1288 This must run before c-cppbuiltin.c:builtin_define_fixed_point_constants()
1289 which built-in defines macros like __ULLACCUM_FBIT__ that are used by
1290 libgcc to detect IBIT and FBIT. */
1291
1292 avr_adjust_type_node (&ta_type_node, TAmode, 0);
1293 avr_adjust_type_node (&uta_type_node, UTAmode, 0);
1294 avr_adjust_type_node (&sat_ta_type_node, TAmode, 1);
1295 avr_adjust_type_node (&sat_uta_type_node, UTAmode, 1);
1296
1297 unsigned_long_long_accum_type_node = uta_type_node;
1298 long_long_accum_type_node = ta_type_node;
1299 sat_unsigned_long_long_accum_type_node = sat_uta_type_node;
1300 sat_long_long_accum_type_node = sat_ta_type_node;
1301
1302 /* Dispatch to the default handler. */
1303
1304 return std_build_builtin_va_list ();
1305 }
1306
1307
1308 /* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3-byte PC).
1309 This is return address of function. */
1310
1311 rtx
avr_return_addr_rtx(int count,rtx tem)1312 avr_return_addr_rtx (int count, rtx tem)
1313 {
1314 rtx r;
1315
1316 /* Can only return this function's return address. Others not supported. */
1317 if (count)
1318 return NULL;
1319
1320 if (AVR_3_BYTE_PC)
1321 {
1322 r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+2");
1323 warning (0, "%<builtin_return_address%> contains only 2 bytes"
1324 " of address");
1325 }
1326 else
1327 r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+1");
1328
1329 cfun->machine->use_L__stack_usage = 1;
1330
1331 r = gen_rtx_PLUS (Pmode, tem, r);
1332 r = gen_frame_mem (Pmode, memory_address (Pmode, r));
1333 r = gen_rtx_ROTATE (HImode, r, GEN_INT (8));
1334 return r;
1335 }
1336
1337 /* Return 1 if the function epilogue is just a single "ret". */
1338
1339 int
avr_simple_epilogue(void)1340 avr_simple_epilogue (void)
1341 {
1342 return (! frame_pointer_needed
1343 && get_frame_size () == 0
1344 && avr_outgoing_args_size() == 0
1345 && avr_regs_to_save (NULL) == 0
1346 && ! cfun->machine->is_interrupt
1347 && ! cfun->machine->is_signal
1348 && ! cfun->machine->is_naked
1349 && ! TREE_THIS_VOLATILE (current_function_decl));
1350 }
1351
1352 /* This function checks sequence of live registers. */
1353
1354 static int
sequent_regs_live(void)1355 sequent_regs_live (void)
1356 {
1357 int live_seq = 0;
1358 int cur_seq = 0;
1359
1360 for (int reg = 0; reg <= LAST_CALLEE_SAVED_REG; ++reg)
1361 {
1362 if (fixed_regs[reg])
1363 {
1364 /* Don't recognize sequences that contain global register
1365 variables. */
1366
1367 if (live_seq != 0)
1368 return 0;
1369 else
1370 continue;
1371 }
1372
1373 if (!call_used_or_fixed_reg_p (reg))
1374 {
1375 if (df_regs_ever_live_p (reg))
1376 {
1377 ++live_seq;
1378 ++cur_seq;
1379 }
1380 else
1381 cur_seq = 0;
1382 }
1383 }
1384
1385 if (!frame_pointer_needed)
1386 {
1387 if (df_regs_ever_live_p (REG_Y))
1388 {
1389 ++live_seq;
1390 ++cur_seq;
1391 }
1392 else
1393 cur_seq = 0;
1394
1395 if (df_regs_ever_live_p (REG_Y + 1))
1396 {
1397 ++live_seq;
1398 ++cur_seq;
1399 }
1400 else
1401 cur_seq = 0;
1402 }
1403 else
1404 {
1405 cur_seq += 2;
1406 live_seq += 2;
1407 }
1408 return (cur_seq == live_seq) ? live_seq : 0;
1409 }
1410
1411 namespace {
1412 static const pass_data avr_pass_data_pre_proep =
1413 {
1414 RTL_PASS, // type
1415 "", // name (will be patched)
1416 OPTGROUP_NONE, // optinfo_flags
1417 TV_DF_SCAN, // tv_id
1418 0, // properties_required
1419 0, // properties_provided
1420 0, // properties_destroyed
1421 0, // todo_flags_start
1422 0 // todo_flags_finish
1423 };
1424
1425
1426 class avr_pass_pre_proep : public rtl_opt_pass
1427 {
1428 public:
avr_pass_pre_proep(gcc::context * ctxt,const char * name)1429 avr_pass_pre_proep (gcc::context *ctxt, const char *name)
1430 : rtl_opt_pass (avr_pass_data_pre_proep, ctxt)
1431 {
1432 this->name = name;
1433 }
1434
1435 void compute_maybe_gasisr (function*);
1436
execute(function * fun)1437 virtual unsigned int execute (function *fun)
1438 {
1439 if (avr_gasisr_prologues
1440 // Whether this function is an ISR worth scanning at all.
1441 && !fun->machine->is_no_gccisr
1442 && (fun->machine->is_interrupt
1443 || fun->machine->is_signal)
1444 && !cfun->machine->is_naked
1445 // Paranoia: Non-local gotos and labels that might escape.
1446 && !cfun->calls_setjmp
1447 && !cfun->has_nonlocal_label
1448 && !cfun->has_forced_label_in_static)
1449 {
1450 compute_maybe_gasisr (fun);
1451 }
1452
1453 return 0;
1454 }
1455
1456 }; // avr_pass_pre_proep
1457
1458 } // anon namespace
1459
1460 rtl_opt_pass*
make_avr_pass_pre_proep(gcc::context * ctxt)1461 make_avr_pass_pre_proep (gcc::context *ctxt)
1462 {
1463 return new avr_pass_pre_proep (ctxt, "avr-pre-proep");
1464 }
1465
1466
1467 /* Set fun->machine->gasisr.maybe provided we don't find anything that
1468 prohibits GAS generating parts of ISR prologues / epilogues for us. */
1469
1470 void
compute_maybe_gasisr(function * fun)1471 avr_pass_pre_proep::compute_maybe_gasisr (function *fun)
1472 {
1473 // Don't use BB iterators so that we see JUMP_TABLE_DATA.
1474
1475 for (rtx_insn *insn = get_insns (); insn; insn = NEXT_INSN (insn))
1476 {
1477 // Transparent calls always use [R]CALL and are filtered out by GAS.
1478 // ISRs don't use -mcall-prologues, hence what remains to be filtered
1479 // out are open coded (tail) calls.
1480
1481 if (CALL_P (insn))
1482 return;
1483
1484 // __tablejump2__ clobbers something and is targeted by JMP so
1485 // that GAS won't see its usage.
1486
1487 if (AVR_HAVE_JMP_CALL
1488 && JUMP_TABLE_DATA_P (insn))
1489 return;
1490
1491 // Non-local gotos not seen in *FUN.
1492
1493 if (JUMP_P (insn)
1494 && find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
1495 return;
1496 }
1497
1498 fun->machine->gasisr.maybe = 1;
1499 }
1500
1501
1502 /* Obtain the length sequence of insns. */
1503
1504 int
get_sequence_length(rtx_insn * insns)1505 get_sequence_length (rtx_insn *insns)
1506 {
1507 int length = 0;
1508
1509 for (rtx_insn *insn = insns; insn; insn = NEXT_INSN (insn))
1510 length += get_attr_length (insn);
1511
1512 return length;
1513 }
1514
1515
1516 /* Implement `INCOMING_RETURN_ADDR_RTX'. */
1517
1518 rtx
avr_incoming_return_addr_rtx(void)1519 avr_incoming_return_addr_rtx (void)
1520 {
1521 /* The return address is at the top of the stack. Note that the push
1522 was via post-decrement, which means the actual address is off by one. */
1523 return gen_frame_mem (HImode, plus_constant (Pmode, stack_pointer_rtx, 1));
1524 }
1525
1526
1527 /* Unset a bit in *SET. If successful, return the respective bit number.
1528 Otherwise, return -1 and *SET is unaltered. */
1529
1530 static int
avr_hregs_split_reg(HARD_REG_SET * set)1531 avr_hregs_split_reg (HARD_REG_SET *set)
1532 {
1533 for (int regno = 0; regno < 32; regno++)
1534 if (TEST_HARD_REG_BIT (*set, regno))
1535 {
1536 // Don't remove a register from *SET which might indicate that
1537 // some RAMP* register might need ISR prologue / epilogue treatment.
1538
1539 if (AVR_HAVE_RAMPX
1540 && (REG_X == regno || REG_X + 1 == regno)
1541 && TEST_HARD_REG_BIT (*set, REG_X)
1542 && TEST_HARD_REG_BIT (*set, REG_X + 1))
1543 continue;
1544
1545 if (AVR_HAVE_RAMPY
1546 && !frame_pointer_needed
1547 && (REG_Y == regno || REG_Y + 1 == regno)
1548 && TEST_HARD_REG_BIT (*set, REG_Y)
1549 && TEST_HARD_REG_BIT (*set, REG_Y + 1))
1550 continue;
1551
1552 if (AVR_HAVE_RAMPZ
1553 && (REG_Z == regno || REG_Z + 1 == regno)
1554 && TEST_HARD_REG_BIT (*set, REG_Z)
1555 && TEST_HARD_REG_BIT (*set, REG_Z + 1))
1556 continue;
1557
1558 CLEAR_HARD_REG_BIT (*set, regno);
1559 return regno;
1560 }
1561
1562 return -1;
1563 }
1564
1565
1566 /* Helper for expand_prologue. Emit a push of a byte register. */
1567
1568 static void
emit_push_byte(unsigned regno,bool frame_related_p)1569 emit_push_byte (unsigned regno, bool frame_related_p)
1570 {
1571 rtx mem, reg;
1572 rtx_insn *insn;
1573
1574 mem = gen_rtx_POST_DEC (HImode, stack_pointer_rtx);
1575 mem = gen_frame_mem (QImode, mem);
1576 reg = gen_rtx_REG (QImode, regno);
1577
1578 insn = emit_insn (gen_rtx_SET (mem, reg));
1579 if (frame_related_p)
1580 RTX_FRAME_RELATED_P (insn) = 1;
1581
1582 cfun->machine->stack_usage++;
1583 }
1584
1585
1586 /* Helper for expand_prologue. Emit a push of a SFR via register TREG.
1587 SFR is a MEM representing the memory location of the SFR.
1588 If CLR_P then clear the SFR after the push using zero_reg. */
1589
1590 static void
emit_push_sfr(rtx sfr,bool frame_related_p,bool clr_p,int treg)1591 emit_push_sfr (rtx sfr, bool frame_related_p, bool clr_p, int treg)
1592 {
1593 rtx_insn *insn;
1594
1595 gcc_assert (MEM_P (sfr));
1596
1597 /* IN treg, IO(SFR) */
1598 insn = emit_move_insn (all_regs_rtx[treg], sfr);
1599 if (frame_related_p)
1600 RTX_FRAME_RELATED_P (insn) = 1;
1601
1602 /* PUSH treg */
1603 emit_push_byte (treg, frame_related_p);
1604
1605 if (clr_p)
1606 {
1607 /* OUT IO(SFR), __zero_reg__ */
1608 insn = emit_move_insn (sfr, const0_rtx);
1609 if (frame_related_p)
1610 RTX_FRAME_RELATED_P (insn) = 1;
1611 }
1612 }
1613
1614 static void
avr_prologue_setup_frame(HOST_WIDE_INT size,HARD_REG_SET set)1615 avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
1616 {
1617 rtx_insn *insn;
1618 bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1619 int live_seq = sequent_regs_live ();
1620
1621 HOST_WIDE_INT size_max
1622 = (HOST_WIDE_INT) GET_MODE_MASK (AVR_HAVE_8BIT_SP ? QImode : Pmode);
1623
1624 bool minimize = (TARGET_CALL_PROLOGUES
1625 && size < size_max
1626 && live_seq
1627 && !isr_p
1628 && !cfun->machine->is_OS_task
1629 && !cfun->machine->is_OS_main
1630 && !AVR_TINY);
1631
1632 if (minimize
1633 && (frame_pointer_needed
1634 || avr_outgoing_args_size() > 8
1635 || (AVR_2_BYTE_PC && live_seq > 6)
1636 || live_seq > 7))
1637 {
1638 rtx pattern;
1639 int first_reg, reg, offset;
1640
1641 emit_move_insn (gen_rtx_REG (HImode, REG_X),
1642 gen_int_mode (size, HImode));
1643
1644 pattern = gen_call_prologue_saves (gen_int_mode (live_seq, HImode),
1645 gen_int_mode (live_seq+size, HImode));
1646 insn = emit_insn (pattern);
1647 RTX_FRAME_RELATED_P (insn) = 1;
1648
1649 /* Describe the effect of the unspec_volatile call to prologue_saves.
1650 Note that this formulation assumes that add_reg_note pushes the
1651 notes to the front. Thus we build them in the reverse order of
1652 how we want dwarf2out to process them. */
1653
1654 /* The function does always set frame_pointer_rtx, but whether that
1655 is going to be permanent in the function is frame_pointer_needed. */
1656
1657 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1658 gen_rtx_SET ((frame_pointer_needed
1659 ? frame_pointer_rtx
1660 : stack_pointer_rtx),
1661 plus_constant (Pmode, stack_pointer_rtx,
1662 -(size + live_seq))));
1663
1664 /* Note that live_seq always contains r28+r29, but the other
1665 registers to be saved are all below 18. */
1666
1667 first_reg = (LAST_CALLEE_SAVED_REG + 1) - (live_seq - 2);
1668
1669 for (reg = 29, offset = -live_seq + 1;
1670 reg >= first_reg;
1671 reg = (reg == 28 ? LAST_CALLEE_SAVED_REG : reg - 1), ++offset)
1672 {
1673 rtx m, r;
1674
1675 m = gen_rtx_MEM (QImode, plus_constant (Pmode, stack_pointer_rtx,
1676 offset));
1677 r = gen_rtx_REG (QImode, reg);
1678 add_reg_note (insn, REG_CFA_OFFSET, gen_rtx_SET (m, r));
1679 }
1680
1681 cfun->machine->stack_usage += size + live_seq;
1682 }
1683 else /* !minimize */
1684 {
1685 for (int reg = 0; reg < 32; ++reg)
1686 if (TEST_HARD_REG_BIT (set, reg))
1687 emit_push_byte (reg, true);
1688
1689 if (frame_pointer_needed
1690 && (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main)))
1691 {
1692 /* Push frame pointer. Always be consistent about the
1693 ordering of pushes -- epilogue_restores expects the
1694 register pair to be pushed low byte first. */
1695
1696 emit_push_byte (REG_Y, true);
1697 emit_push_byte (REG_Y + 1, true);
1698 }
1699
1700 if (frame_pointer_needed
1701 && size == 0)
1702 {
1703 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
1704 RTX_FRAME_RELATED_P (insn) = 1;
1705 }
1706
1707 if (size != 0)
1708 {
1709 /* Creating a frame can be done by direct manipulation of the
1710 stack or via the frame pointer. These two methods are:
1711 fp = sp
1712 fp -= size
1713 sp = fp
1714 or
1715 sp -= size
1716 fp = sp (*)
1717 the optimum method depends on function type, stack and
1718 frame size. To avoid a complex logic, both methods are
1719 tested and shortest is selected.
1720
1721 There is also the case where SIZE != 0 and no frame pointer is
1722 needed; this can occur if ACCUMULATE_OUTGOING_ARGS is on.
1723 In that case, insn (*) is not needed in that case.
1724 We use the X register as scratch. This is save because in X
1725 is call-clobbered.
1726 In an interrupt routine, the case of SIZE != 0 together with
1727 !frame_pointer_needed can only occur if the function is not a
1728 leaf function and thus X has already been saved. */
1729
1730 int irq_state = -1;
1731 HOST_WIDE_INT size_cfa = size, neg_size;
1732 rtx_insn *fp_plus_insns;
1733 rtx fp, my_fp;
1734
1735 gcc_assert (frame_pointer_needed
1736 || !isr_p
1737 || !crtl->is_leaf);
1738
1739 fp = my_fp = (frame_pointer_needed
1740 ? frame_pointer_rtx
1741 : gen_rtx_REG (Pmode, REG_X));
1742
1743 if (AVR_HAVE_8BIT_SP)
1744 {
1745 /* The high byte (r29) does not change:
1746 Prefer SUBI (1 cycle) over SBIW (2 cycles, same size). */
1747
1748 my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
1749 }
1750
1751 /* Cut down size and avoid size = 0 so that we don't run
1752 into ICE like PR52488 in the remainder. */
1753
1754 if (size > size_max)
1755 {
1756 /* Don't error so that insane code from newlib still compiles
1757 and does not break building newlib. As PR51345 is implemented
1758 now, there are multilib variants with -msp8.
1759
1760 If user wants sanity checks he can use -Wstack-usage=
1761 or similar options.
1762
1763 For CFA we emit the original, non-saturated size so that
1764 the generic machinery is aware of the real stack usage and
1765 will print the above diagnostic as expected. */
1766
1767 size = size_max;
1768 }
1769
1770 size = trunc_int_for_mode (size, GET_MODE (my_fp));
1771 neg_size = trunc_int_for_mode (-size, GET_MODE (my_fp));
1772
1773 /************ Method 1: Adjust frame pointer ************/
1774
1775 start_sequence ();
1776
1777 /* Normally, the dwarf2out frame-related-expr interpreter does
1778 not expect to have the CFA change once the frame pointer is
1779 set up. Thus, we avoid marking the move insn below and
1780 instead indicate that the entire operation is complete after
1781 the frame pointer subtraction is done. */
1782
1783 insn = emit_move_insn (fp, stack_pointer_rtx);
1784 if (frame_pointer_needed)
1785 {
1786 RTX_FRAME_RELATED_P (insn) = 1;
1787 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1788 gen_rtx_SET (fp, stack_pointer_rtx));
1789 }
1790
1791 insn = emit_move_insn (my_fp, plus_constant (GET_MODE (my_fp),
1792 my_fp, neg_size));
1793
1794 if (frame_pointer_needed)
1795 {
1796 RTX_FRAME_RELATED_P (insn) = 1;
1797 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1798 gen_rtx_SET (fp, plus_constant (Pmode, fp,
1799 -size_cfa)));
1800 }
1801
1802 /* Copy to stack pointer. Note that since we've already
1803 changed the CFA to the frame pointer this operation
1804 need not be annotated if frame pointer is needed.
1805 Always move through unspec, see PR50063.
1806 For meaning of irq_state see movhi_sp_r insn. */
1807
1808 if (cfun->machine->is_interrupt)
1809 irq_state = 1;
1810
1811 if (TARGET_NO_INTERRUPTS
1812 || cfun->machine->is_signal
1813 || cfun->machine->is_OS_main)
1814 irq_state = 0;
1815
1816 if (AVR_HAVE_8BIT_SP)
1817 irq_state = 2;
1818
1819 insn = emit_insn (gen_movhi_sp_r (stack_pointer_rtx,
1820 fp, GEN_INT (irq_state)));
1821 if (!frame_pointer_needed)
1822 {
1823 RTX_FRAME_RELATED_P (insn) = 1;
1824 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1825 gen_rtx_SET (stack_pointer_rtx,
1826 plus_constant (Pmode,
1827 stack_pointer_rtx,
1828 -size_cfa)));
1829 }
1830
1831 fp_plus_insns = get_insns ();
1832 end_sequence ();
1833
1834 /************ Method 2: Adjust Stack pointer ************/
1835
1836 /* Stack adjustment by means of RCALL . and/or PUSH __TMP_REG__
1837 can only handle specific offsets. */
1838
1839 int n_rcall = size / (AVR_3_BYTE_PC ? 3 : 2);
1840
1841 if (avr_sp_immediate_operand (gen_int_mode (-size, HImode), HImode)
1842 // Don't use more than 3 RCALLs.
1843 && n_rcall <= 3)
1844 {
1845 rtx_insn *sp_plus_insns;
1846
1847 start_sequence ();
1848
1849 insn = emit_move_insn (stack_pointer_rtx,
1850 plus_constant (Pmode, stack_pointer_rtx,
1851 -size));
1852 RTX_FRAME_RELATED_P (insn) = 1;
1853 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1854 gen_rtx_SET (stack_pointer_rtx,
1855 plus_constant (Pmode,
1856 stack_pointer_rtx,
1857 -size_cfa)));
1858 if (frame_pointer_needed)
1859 {
1860 insn = emit_move_insn (fp, stack_pointer_rtx);
1861 RTX_FRAME_RELATED_P (insn) = 1;
1862 }
1863
1864 sp_plus_insns = get_insns ();
1865 end_sequence ();
1866
1867 /************ Use shortest method ************/
1868
1869 emit_insn (get_sequence_length (sp_plus_insns)
1870 < get_sequence_length (fp_plus_insns)
1871 ? sp_plus_insns
1872 : fp_plus_insns);
1873 }
1874 else
1875 {
1876 emit_insn (fp_plus_insns);
1877 }
1878
1879 cfun->machine->stack_usage += size_cfa;
1880 } /* !minimize && size != 0 */
1881 } /* !minimize */
1882 }
1883
1884
1885 /* Output function prologue. */
1886
1887 void
avr_expand_prologue(void)1888 avr_expand_prologue (void)
1889 {
1890 HARD_REG_SET set;
1891 HOST_WIDE_INT size;
1892
1893 size = get_frame_size() + avr_outgoing_args_size();
1894
1895 cfun->machine->stack_usage = 0;
1896
1897 /* Prologue: naked. */
1898 if (cfun->machine->is_naked)
1899 {
1900 return;
1901 }
1902
1903 avr_regs_to_save (&set);
1904
1905 if (cfun->machine->is_interrupt || cfun->machine->is_signal)
1906 {
1907 int treg = AVR_TMP_REGNO;
1908 /* Enable interrupts. */
1909 if (cfun->machine->is_interrupt)
1910 emit_insn (gen_enable_interrupt ());
1911
1912 if (cfun->machine->gasisr.maybe)
1913 {
1914 /* Let GAS PR21472 emit prologue preamble for us which handles SREG,
1915 ZERO_REG and TMP_REG and one additional, optional register for
1916 us in an optimal way. This even scans through inline asm. */
1917
1918 cfun->machine->gasisr.yes = 1;
1919
1920 // The optional reg or TMP_REG if we don't need one. If we need one,
1921 // remove that reg from SET so that it's not puhed / popped twice.
1922 // We also use it below instead of TMP_REG in some places.
1923
1924 treg = avr_hregs_split_reg (&set);
1925 if (treg < 0)
1926 treg = AVR_TMP_REGNO;
1927 cfun->machine->gasisr.regno = treg;
1928
1929 // The worst case of pushes. The exact number can be inferred
1930 // at assembly time by magic expression __gcc_isr.n_pushed.
1931 cfun->machine->stack_usage += 3 + (treg != AVR_TMP_REGNO);
1932
1933 // Emit a Prologue chunk. Epilogue chunk(s) might follow.
1934 // The final Done chunk is emit by final postscan.
1935 emit_insn (gen_gasisr (GEN_INT (GASISR_Prologue), GEN_INT (treg)));
1936 }
1937 else // !TARGET_GASISR_PROLOGUES: Classic, dumb prologue preamble.
1938 {
1939 /* Push zero reg. */
1940 emit_push_byte (AVR_ZERO_REGNO, true);
1941
1942 /* Push tmp reg. */
1943 emit_push_byte (AVR_TMP_REGNO, true);
1944
1945 /* Push SREG. */
1946 /* ??? There's no dwarf2 column reserved for SREG. */
1947 emit_push_sfr (sreg_rtx, false, false /* clr */, AVR_TMP_REGNO);
1948
1949 /* Clear zero reg. */
1950 emit_move_insn (zero_reg_rtx, const0_rtx);
1951
1952 /* Prevent any attempt to delete the setting of ZERO_REG! */
1953 emit_use (zero_reg_rtx);
1954 }
1955
1956 /* Push and clear RAMPD/X/Y/Z if present and low-part register is used.
1957 ??? There are no dwarf2 columns reserved for RAMPD/X/Y/Z. */
1958
1959 if (AVR_HAVE_RAMPD)
1960 emit_push_sfr (rampd_rtx, false /* frame */, true /* clr */, treg);
1961
1962 if (AVR_HAVE_RAMPX
1963 && TEST_HARD_REG_BIT (set, REG_X)
1964 && TEST_HARD_REG_BIT (set, REG_X + 1))
1965 {
1966 emit_push_sfr (rampx_rtx, false /* frame */, true /* clr */, treg);
1967 }
1968
1969 if (AVR_HAVE_RAMPY
1970 && (frame_pointer_needed
1971 || (TEST_HARD_REG_BIT (set, REG_Y)
1972 && TEST_HARD_REG_BIT (set, REG_Y + 1))))
1973 {
1974 emit_push_sfr (rampy_rtx, false /* frame */, true /* clr */, treg);
1975 }
1976
1977 if (AVR_HAVE_RAMPZ
1978 && TEST_HARD_REG_BIT (set, REG_Z)
1979 && TEST_HARD_REG_BIT (set, REG_Z + 1))
1980 {
1981 emit_push_sfr (rampz_rtx, false /* frame */, AVR_HAVE_RAMPD, treg);
1982 }
1983 } /* is_interrupt is_signal */
1984
1985 avr_prologue_setup_frame (size, set);
1986
1987 if (flag_stack_usage_info)
1988 current_function_static_stack_size
1989 = cfun->machine->stack_usage + INCOMING_FRAME_SP_OFFSET;
1990 }
1991
1992
1993 /* Implement `TARGET_ASM_FUNCTION_END_PROLOGUE'. */
1994 /* Output summary at end of function prologue. */
1995
1996 static void
avr_asm_function_end_prologue(FILE * file)1997 avr_asm_function_end_prologue (FILE *file)
1998 {
1999 if (cfun->machine->is_naked)
2000 {
2001 fputs ("/* prologue: naked */\n", file);
2002 }
2003 else
2004 {
2005 if (cfun->machine->is_interrupt)
2006 {
2007 fputs ("/* prologue: Interrupt */\n", file);
2008 }
2009 else if (cfun->machine->is_signal)
2010 {
2011 fputs ("/* prologue: Signal */\n", file);
2012 }
2013 else
2014 fputs ("/* prologue: function */\n", file);
2015 }
2016
2017 if (ACCUMULATE_OUTGOING_ARGS)
2018 fprintf (file, "/* outgoing args size = %d */\n",
2019 avr_outgoing_args_size());
2020
2021 fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n",
2022 (HOST_WIDE_INT) get_frame_size());
2023
2024 if (!cfun->machine->gasisr.yes)
2025 {
2026 fprintf (file, "/* stack size = %d */\n", cfun->machine->stack_usage);
2027 // Create symbol stack offset so all functions have it. Add 1 to stack
2028 // usage for offset so that SP + .L__stack_offset = return address.
2029 fprintf (file, ".L__stack_usage = %d\n", cfun->machine->stack_usage);
2030 }
2031 else
2032 {
2033 int used_by_gasisr = 3 + (cfun->machine->gasisr.regno != AVR_TMP_REGNO);
2034 int to = cfun->machine->stack_usage;
2035 int from = to - used_by_gasisr;
2036 // Number of pushed regs is only known at assembly-time.
2037 fprintf (file, "/* stack size = %d...%d */\n", from , to);
2038 fprintf (file, ".L__stack_usage = %d + __gcc_isr.n_pushed\n", from);
2039 }
2040 }
2041
2042
2043 /* Implement `EPILOGUE_USES'. */
2044
2045 int
avr_epilogue_uses(int regno ATTRIBUTE_UNUSED)2046 avr_epilogue_uses (int regno ATTRIBUTE_UNUSED)
2047 {
2048 if (reload_completed
2049 && cfun->machine
2050 && (cfun->machine->is_interrupt || cfun->machine->is_signal))
2051 return 1;
2052 return 0;
2053 }
2054
2055 /* Helper for avr_expand_epilogue. Emit a pop of a byte register. */
2056
2057 static void
emit_pop_byte(unsigned regno)2058 emit_pop_byte (unsigned regno)
2059 {
2060 rtx mem, reg;
2061
2062 mem = gen_rtx_PRE_INC (HImode, stack_pointer_rtx);
2063 mem = gen_frame_mem (QImode, mem);
2064 reg = gen_rtx_REG (QImode, regno);
2065
2066 emit_insn (gen_rtx_SET (reg, mem));
2067 }
2068
2069 /* Output RTL epilogue. */
2070
2071 void
avr_expand_epilogue(bool sibcall_p)2072 avr_expand_epilogue (bool sibcall_p)
2073 {
2074 int live_seq;
2075 HARD_REG_SET set;
2076 int minimize;
2077 HOST_WIDE_INT size;
2078 bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
2079
2080 size = get_frame_size() + avr_outgoing_args_size();
2081
2082 /* epilogue: naked */
2083 if (cfun->machine->is_naked)
2084 {
2085 gcc_assert (!sibcall_p);
2086
2087 emit_jump_insn (gen_return ());
2088 return;
2089 }
2090
2091 avr_regs_to_save (&set);
2092 live_seq = sequent_regs_live ();
2093
2094 minimize = (TARGET_CALL_PROLOGUES
2095 && live_seq
2096 && !isr_p
2097 && !cfun->machine->is_OS_task
2098 && !cfun->machine->is_OS_main
2099 && !AVR_TINY);
2100
2101 if (minimize
2102 && (live_seq > 4
2103 || frame_pointer_needed
2104 || size))
2105 {
2106 /* Get rid of frame. */
2107
2108 if (!frame_pointer_needed)
2109 {
2110 emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
2111 }
2112
2113 if (size)
2114 {
2115 emit_move_insn (frame_pointer_rtx,
2116 plus_constant (Pmode, frame_pointer_rtx, size));
2117 }
2118
2119 emit_insn (gen_epilogue_restores (gen_int_mode (live_seq, HImode)));
2120 return;
2121 }
2122
2123 if (size)
2124 {
2125 /* Try two methods to adjust stack and select shortest. */
2126
2127 int irq_state = -1;
2128 rtx fp, my_fp;
2129 rtx_insn *fp_plus_insns;
2130 HOST_WIDE_INT size_max;
2131
2132 gcc_assert (frame_pointer_needed
2133 || !isr_p
2134 || !crtl->is_leaf);
2135
2136 fp = my_fp = (frame_pointer_needed
2137 ? frame_pointer_rtx
2138 : gen_rtx_REG (Pmode, REG_X));
2139
2140 if (AVR_HAVE_8BIT_SP)
2141 {
2142 /* The high byte (r29) does not change:
2143 Prefer SUBI (1 cycle) over SBIW (2 cycles). */
2144
2145 my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
2146 }
2147
2148 /* For rationale see comment in prologue generation. */
2149
2150 size_max = (HOST_WIDE_INT) GET_MODE_MASK (GET_MODE (my_fp));
2151 if (size > size_max)
2152 size = size_max;
2153 size = trunc_int_for_mode (size, GET_MODE (my_fp));
2154
2155 /********** Method 1: Adjust fp register **********/
2156
2157 start_sequence ();
2158
2159 if (!frame_pointer_needed)
2160 emit_move_insn (fp, stack_pointer_rtx);
2161
2162 emit_move_insn (my_fp, plus_constant (GET_MODE (my_fp), my_fp, size));
2163
2164 /* Copy to stack pointer. */
2165
2166 if (TARGET_NO_INTERRUPTS)
2167 irq_state = 0;
2168
2169 if (AVR_HAVE_8BIT_SP)
2170 irq_state = 2;
2171
2172 emit_insn (gen_movhi_sp_r (stack_pointer_rtx, fp,
2173 GEN_INT (irq_state)));
2174
2175 fp_plus_insns = get_insns ();
2176 end_sequence ();
2177
2178 /********** Method 2: Adjust Stack pointer **********/
2179
2180 if (avr_sp_immediate_operand (gen_int_mode (size, HImode), HImode))
2181 {
2182 rtx_insn *sp_plus_insns;
2183
2184 start_sequence ();
2185
2186 emit_move_insn (stack_pointer_rtx,
2187 plus_constant (Pmode, stack_pointer_rtx, size));
2188
2189 sp_plus_insns = get_insns ();
2190 end_sequence ();
2191
2192 /************ Use shortest method ************/
2193
2194 emit_insn (get_sequence_length (sp_plus_insns)
2195 < get_sequence_length (fp_plus_insns)
2196 ? sp_plus_insns
2197 : fp_plus_insns);
2198 }
2199 else
2200 emit_insn (fp_plus_insns);
2201 } /* size != 0 */
2202
2203 if (frame_pointer_needed
2204 && !(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
2205 {
2206 /* Restore previous frame_pointer. See avr_expand_prologue for
2207 rationale for not using pophi. */
2208
2209 emit_pop_byte (REG_Y + 1);
2210 emit_pop_byte (REG_Y);
2211 }
2212
2213 /* Restore used registers. */
2214
2215 int treg = AVR_TMP_REGNO;
2216
2217 if (isr_p
2218 && cfun->machine->gasisr.yes)
2219 {
2220 treg = cfun->machine->gasisr.regno;
2221 CLEAR_HARD_REG_BIT (set, treg);
2222 }
2223
2224 for (int reg = 31; reg >= 0; --reg)
2225 if (TEST_HARD_REG_BIT (set, reg))
2226 emit_pop_byte (reg);
2227
2228 if (isr_p)
2229 {
2230 /* Restore RAMPZ/Y/X/D using tmp_reg as scratch.
2231 The conditions to restore them must be tha same as in prologue. */
2232
2233 if (AVR_HAVE_RAMPZ
2234 && TEST_HARD_REG_BIT (set, REG_Z)
2235 && TEST_HARD_REG_BIT (set, REG_Z + 1))
2236 {
2237 emit_pop_byte (treg);
2238 emit_move_insn (rampz_rtx, all_regs_rtx[treg]);
2239 }
2240
2241 if (AVR_HAVE_RAMPY
2242 && (frame_pointer_needed
2243 || (TEST_HARD_REG_BIT (set, REG_Y)
2244 && TEST_HARD_REG_BIT (set, REG_Y + 1))))
2245 {
2246 emit_pop_byte (treg);
2247 emit_move_insn (rampy_rtx, all_regs_rtx[treg]);
2248 }
2249
2250 if (AVR_HAVE_RAMPX
2251 && TEST_HARD_REG_BIT (set, REG_X)
2252 && TEST_HARD_REG_BIT (set, REG_X + 1))
2253 {
2254 emit_pop_byte (treg);
2255 emit_move_insn (rampx_rtx, all_regs_rtx[treg]);
2256 }
2257
2258 if (AVR_HAVE_RAMPD)
2259 {
2260 emit_pop_byte (treg);
2261 emit_move_insn (rampd_rtx, all_regs_rtx[treg]);
2262 }
2263
2264 if (cfun->machine->gasisr.yes)
2265 {
2266 // Emit an Epilogue chunk.
2267 emit_insn (gen_gasisr (GEN_INT (GASISR_Epilogue),
2268 GEN_INT (cfun->machine->gasisr.regno)));
2269 }
2270 else // !TARGET_GASISR_PROLOGUES
2271 {
2272 /* Restore SREG using tmp_reg as scratch. */
2273
2274 emit_pop_byte (AVR_TMP_REGNO);
2275 emit_move_insn (sreg_rtx, tmp_reg_rtx);
2276
2277 /* Restore tmp REG. */
2278 emit_pop_byte (AVR_TMP_REGNO);
2279
2280 /* Restore zero REG. */
2281 emit_pop_byte (AVR_ZERO_REGNO);
2282 }
2283 }
2284
2285 if (!sibcall_p)
2286 emit_jump_insn (gen_return ());
2287 }
2288
2289
2290 /* Implement `TARGET_ASM_FUNCTION_BEGIN_EPILOGUE'. */
2291
2292 static void
avr_asm_function_begin_epilogue(FILE * file)2293 avr_asm_function_begin_epilogue (FILE *file)
2294 {
2295 app_disable();
2296 fprintf (file, "/* epilogue start */\n");
2297 }
2298
2299
2300 /* Implement `TARGET_CANNOT_MODITY_JUMPS_P'. */
2301
2302 static bool
avr_cannot_modify_jumps_p(void)2303 avr_cannot_modify_jumps_p (void)
2304 {
2305 /* Naked Functions must not have any instructions after
2306 their epilogue, see PR42240 */
2307
2308 if (reload_completed
2309 && cfun->machine
2310 && cfun->machine->is_naked)
2311 {
2312 return true;
2313 }
2314
2315 return false;
2316 }
2317
2318
2319 /* Implement `TARGET_MODE_DEPENDENT_ADDRESS_P'. */
2320
2321 static bool
avr_mode_dependent_address_p(const_rtx addr ATTRIBUTE_UNUSED,addr_space_t as)2322 avr_mode_dependent_address_p (const_rtx addr ATTRIBUTE_UNUSED, addr_space_t as)
2323 {
2324 /* FIXME: Non-generic addresses are not mode-dependent in themselves.
2325 This hook just serves to hack around PR rtl-optimization/52543 by
2326 claiming that non-generic addresses were mode-dependent so that
2327 lower-subreg.c will skip these addresses. lower-subreg.c sets up fake
2328 RTXes to probe SET and MEM costs and assumes that MEM is always in the
2329 generic address space which is not true. */
2330
2331 return !ADDR_SPACE_GENERIC_P (as);
2332 }
2333
2334
2335 /* Return true if rtx X is a CONST_INT, CONST or SYMBOL_REF
2336 address with the `absdata' variable attribute, i.e. respective
2337 data can be read / written by LDS / STS instruction.
2338 This is used only for AVR_TINY. */
2339
2340 static bool
avr_address_tiny_absdata_p(rtx x,machine_mode mode)2341 avr_address_tiny_absdata_p (rtx x, machine_mode mode)
2342 {
2343 if (CONST == GET_CODE (x))
2344 x = XEXP (XEXP (x, 0), 0);
2345
2346 if (SYMBOL_REF_P (x))
2347 return SYMBOL_REF_FLAGS (x) & AVR_SYMBOL_FLAG_TINY_ABSDATA;
2348
2349 if (CONST_INT_P (x)
2350 && IN_RANGE (INTVAL (x), 0, 0xc0 - GET_MODE_SIZE (mode)))
2351 return true;
2352
2353 return false;
2354 }
2355
2356
2357 /* Helper function for `avr_legitimate_address_p'. */
2358
2359 static inline bool
avr_reg_ok_for_addr_p(rtx reg,addr_space_t as,RTX_CODE outer_code,bool strict)2360 avr_reg_ok_for_addr_p (rtx reg, addr_space_t as,
2361 RTX_CODE outer_code, bool strict)
2362 {
2363 return (REG_P (reg)
2364 && (avr_regno_mode_code_ok_for_base_p (REGNO (reg), QImode,
2365 as, outer_code, UNKNOWN)
2366 || (!strict
2367 && REGNO (reg) >= FIRST_PSEUDO_REGISTER)));
2368 }
2369
2370
2371 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
2372 machine for a memory operand of mode MODE. */
2373
2374 static bool
avr_legitimate_address_p(machine_mode mode,rtx x,bool strict)2375 avr_legitimate_address_p (machine_mode mode, rtx x, bool strict)
2376 {
2377 bool ok = CONSTANT_ADDRESS_P (x);
2378
2379 switch (GET_CODE (x))
2380 {
2381 case REG:
2382 ok = avr_reg_ok_for_addr_p (x, ADDR_SPACE_GENERIC,
2383 MEM, strict);
2384
2385 if (strict
2386 && GET_MODE_SIZE (mode) > 4
2387 && REG_X == REGNO (x))
2388 {
2389 ok = false;
2390 }
2391 break;
2392
2393 case POST_INC:
2394 case PRE_DEC:
2395 ok = avr_reg_ok_for_addr_p (XEXP (x, 0), ADDR_SPACE_GENERIC,
2396 GET_CODE (x), strict);
2397 break;
2398
2399 case PLUS:
2400 {
2401 rtx reg = XEXP (x, 0);
2402 rtx op1 = XEXP (x, 1);
2403
2404 if (REG_P (reg)
2405 && CONST_INT_P (op1)
2406 && INTVAL (op1) >= 0)
2407 {
2408 bool fit = IN_RANGE (INTVAL (op1), 0, MAX_LD_OFFSET (mode));
2409
2410 if (fit)
2411 {
2412 ok = (! strict
2413 || avr_reg_ok_for_addr_p (reg, ADDR_SPACE_GENERIC,
2414 PLUS, strict));
2415
2416 if (reg == frame_pointer_rtx
2417 || reg == arg_pointer_rtx)
2418 {
2419 ok = true;
2420 }
2421 }
2422 else if (frame_pointer_needed
2423 && reg == frame_pointer_rtx)
2424 {
2425 ok = true;
2426 }
2427 }
2428 }
2429 break;
2430
2431 default:
2432 break;
2433 }
2434
2435 if (AVR_TINY
2436 && CONSTANT_ADDRESS_P (x))
2437 {
2438 /* avrtiny's load / store instructions only cover addresses 0..0xbf:
2439 IN / OUT range is 0..0x3f and LDS / STS can access 0x40..0xbf. */
2440
2441 ok = avr_address_tiny_absdata_p (x, mode);
2442 }
2443
2444 if (avr_log.legitimate_address_p)
2445 {
2446 avr_edump ("\n%?: ret=%d, mode=%m strict=%d "
2447 "reload_completed=%d reload_in_progress=%d %s:",
2448 ok, mode, strict, reload_completed, reload_in_progress,
2449 reg_renumber ? "(reg_renumber)" : "");
2450
2451 if (GET_CODE (x) == PLUS
2452 && REG_P (XEXP (x, 0))
2453 && CONST_INT_P (XEXP (x, 1))
2454 && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
2455 && reg_renumber)
2456 {
2457 avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
2458 true_regnum (XEXP (x, 0)));
2459 }
2460
2461 avr_edump ("\n%r\n", x);
2462 }
2463
2464 return ok;
2465 }
2466
2467
2468 /* Former implementation of TARGET_LEGITIMIZE_ADDRESS,
2469 now only a helper for avr_addr_space_legitimize_address. */
2470 /* Attempts to replace X with a valid
2471 memory address for an operand of mode MODE */
2472
2473 static rtx
avr_legitimize_address(rtx x,rtx oldx,machine_mode mode)2474 avr_legitimize_address (rtx x, rtx oldx, machine_mode mode)
2475 {
2476 bool big_offset_p = false;
2477
2478 x = oldx;
2479
2480 if (AVR_TINY)
2481 {
2482 if (CONSTANT_ADDRESS_P (x)
2483 && ! avr_address_tiny_absdata_p (x, mode))
2484 {
2485 x = force_reg (Pmode, x);
2486 }
2487 }
2488
2489 if (GET_CODE (oldx) == PLUS
2490 && REG_P (XEXP (oldx, 0)))
2491 {
2492 if (REG_P (XEXP (oldx, 1)))
2493 x = force_reg (GET_MODE (oldx), oldx);
2494 else if (CONST_INT_P (XEXP (oldx, 1)))
2495 {
2496 int offs = INTVAL (XEXP (oldx, 1));
2497 if (frame_pointer_rtx != XEXP (oldx, 0)
2498 && offs > MAX_LD_OFFSET (mode))
2499 {
2500 big_offset_p = true;
2501 x = force_reg (GET_MODE (oldx), oldx);
2502 }
2503 }
2504 }
2505
2506 if (avr_log.legitimize_address)
2507 {
2508 avr_edump ("\n%?: mode=%m\n %r\n", mode, oldx);
2509
2510 if (x != oldx)
2511 avr_edump (" %s --> %r\n", big_offset_p ? "(big offset)" : "", x);
2512 }
2513
2514 return x;
2515 }
2516
2517
2518 /* Implement `LEGITIMIZE_RELOAD_ADDRESS'. */
2519 /* This will allow register R26/27 to be used where it is no worse than normal
2520 base pointers R28/29 or R30/31. For example, if base offset is greater
2521 than 63 bytes or for R++ or --R addressing. */
2522
2523 rtx
avr_legitimize_reload_address(rtx * px,machine_mode mode,int opnum,int type,int addr_type,int ind_levels ATTRIBUTE_UNUSED,rtx (* mk_memloc)(rtx,int))2524 avr_legitimize_reload_address (rtx *px, machine_mode mode,
2525 int opnum, int type, int addr_type,
2526 int ind_levels ATTRIBUTE_UNUSED,
2527 rtx (*mk_memloc)(rtx,int))
2528 {
2529 rtx x = *px;
2530
2531 if (avr_log.legitimize_reload_address)
2532 avr_edump ("\n%?:%m %r\n", mode, x);
2533
2534 if (1 && (GET_CODE (x) == POST_INC
2535 || GET_CODE (x) == PRE_DEC))
2536 {
2537 push_reload (XEXP (x, 0), XEXP (x, 0), &XEXP (x, 0), &XEXP (x, 0),
2538 POINTER_REGS, GET_MODE (x), GET_MODE (x), 0, 0,
2539 opnum, RELOAD_OTHER);
2540
2541 if (avr_log.legitimize_reload_address)
2542 avr_edump (" RCLASS.1 = %R\n IN = %r\n OUT = %r\n",
2543 POINTER_REGS, XEXP (x, 0), XEXP (x, 0));
2544
2545 return x;
2546 }
2547
2548 if (GET_CODE (x) == PLUS
2549 && REG_P (XEXP (x, 0))
2550 && reg_equiv_constant (REGNO (XEXP (x, 0))) == 0
2551 && CONST_INT_P (XEXP (x, 1))
2552 && INTVAL (XEXP (x, 1)) >= 1)
2553 {
2554 bool fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
2555
2556 if (fit)
2557 {
2558 if (reg_equiv_address (REGNO (XEXP (x, 0))) != 0)
2559 {
2560 int regno = REGNO (XEXP (x, 0));
2561 rtx mem = mk_memloc (x, regno);
2562
2563 push_reload (XEXP (mem, 0), NULL_RTX, &XEXP (mem, 0), NULL,
2564 POINTER_REGS, Pmode, VOIDmode, 0, 0,
2565 1, (enum reload_type) addr_type);
2566
2567 if (avr_log.legitimize_reload_address)
2568 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
2569 POINTER_REGS, XEXP (mem, 0), NULL_RTX);
2570
2571 push_reload (mem, NULL_RTX, &XEXP (x, 0), NULL,
2572 BASE_POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
2573 opnum, (enum reload_type) type);
2574
2575 if (avr_log.legitimize_reload_address)
2576 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
2577 BASE_POINTER_REGS, mem, NULL_RTX);
2578
2579 return x;
2580 }
2581 }
2582 else if (! (frame_pointer_needed
2583 && XEXP (x, 0) == frame_pointer_rtx))
2584 {
2585 push_reload (x, NULL_RTX, px, NULL,
2586 POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
2587 opnum, (enum reload_type) type);
2588
2589 if (avr_log.legitimize_reload_address)
2590 avr_edump (" RCLASS.3 = %R\n IN = %r\n OUT = %r\n",
2591 POINTER_REGS, x, NULL_RTX);
2592
2593 return x;
2594 }
2595 }
2596
2597 return NULL_RTX;
2598 }
2599
2600
2601 /* Helper function to print assembler resp. track instruction
2602 sequence lengths. Always return "".
2603
2604 If PLEN == NULL:
2605 Output assembler code from template TPL with operands supplied
2606 by OPERANDS. This is just forwarding to output_asm_insn.
2607
2608 If PLEN != NULL:
2609 If N_WORDS >= 0 Add N_WORDS to *PLEN.
2610 If N_WORDS < 0 Set *PLEN to -N_WORDS.
2611 Don't output anything.
2612 */
2613
2614 static const char*
avr_asm_len(const char * tpl,rtx * operands,int * plen,int n_words)2615 avr_asm_len (const char* tpl, rtx* operands, int* plen, int n_words)
2616 {
2617 if (plen == NULL)
2618 output_asm_insn (tpl, operands);
2619 else
2620 {
2621 if (n_words < 0)
2622 *plen = -n_words;
2623 else
2624 *plen += n_words;
2625 }
2626
2627 return "";
2628 }
2629
2630
2631 /* Return a pointer register name as a string. */
2632
2633 static const char*
ptrreg_to_str(int regno)2634 ptrreg_to_str (int regno)
2635 {
2636 switch (regno)
2637 {
2638 case REG_X: return "X";
2639 case REG_Y: return "Y";
2640 case REG_Z: return "Z";
2641 default:
2642 output_operand_lossage ("address operand requires constraint for"
2643 " X, Y, or Z register");
2644 }
2645 return NULL;
2646 }
2647
2648 /* Return the condition name as a string.
2649 Used in conditional jump constructing */
2650
2651 static const char*
cond_string(enum rtx_code code)2652 cond_string (enum rtx_code code)
2653 {
2654 bool cc_overflow_unusable = false;
2655
2656 switch (code)
2657 {
2658 case NE:
2659 return "ne";
2660 case EQ:
2661 return "eq";
2662 case GE:
2663 if (cc_overflow_unusable)
2664 return "pl";
2665 else
2666 return "ge";
2667 case LT:
2668 if (cc_overflow_unusable)
2669 return "mi";
2670 else
2671 return "lt";
2672 case GEU:
2673 return "sh";
2674 case LTU:
2675 return "lo";
2676 default:
2677 gcc_unreachable ();
2678 }
2679
2680 return "";
2681 }
2682
2683
2684 /* Return true if rtx X is a CONST or SYMBOL_REF with progmem.
2685 This must be used for AVR_TINY only because on other cores
2686 the flash memory is not visible in the RAM address range and
2687 cannot be read by, say, LD instruction. */
2688
2689 static bool
avr_address_tiny_pm_p(rtx x)2690 avr_address_tiny_pm_p (rtx x)
2691 {
2692 if (CONST == GET_CODE (x))
2693 x = XEXP (XEXP (x, 0), 0);
2694
2695 if (SYMBOL_REF_P (x))
2696 return SYMBOL_REF_FLAGS (x) & AVR_SYMBOL_FLAG_TINY_PM;
2697
2698 return false;
2699 }
2700
2701 /* Implement `TARGET_PRINT_OPERAND_ADDRESS'. */
2702 /* Output ADDR to FILE as address. */
2703
2704 static void
avr_print_operand_address(FILE * file,machine_mode,rtx addr)2705 avr_print_operand_address (FILE *file, machine_mode /*mode*/, rtx addr)
2706 {
2707 if (AVR_TINY
2708 && avr_address_tiny_pm_p (addr))
2709 {
2710 addr = plus_constant (Pmode, addr, avr_arch->flash_pm_offset);
2711 }
2712
2713 switch (GET_CODE (addr))
2714 {
2715 case REG:
2716 fprintf (file, "%s", ptrreg_to_str (REGNO (addr)));
2717 break;
2718
2719 case PRE_DEC:
2720 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
2721 break;
2722
2723 case POST_INC:
2724 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
2725 break;
2726
2727 default:
2728 if (CONSTANT_ADDRESS_P (addr)
2729 && text_segment_operand (addr, VOIDmode))
2730 {
2731 rtx x = addr;
2732 if (GET_CODE (x) == CONST)
2733 x = XEXP (x, 0);
2734 if (GET_CODE (x) == PLUS && CONST_INT_P (XEXP (x, 1)))
2735 {
2736 /* Assembler gs() will implant word address. Make offset
2737 a byte offset inside gs() for assembler. This is
2738 needed because the more logical (constant+gs(sym)) is not
2739 accepted by gas. For 128K and smaller devices this is ok.
2740 For large devices it will create a trampoline to offset
2741 from symbol which may not be what the user really wanted. */
2742
2743 fprintf (file, "gs(");
2744 output_addr_const (file, XEXP (x, 0));
2745 fprintf (file, "+" HOST_WIDE_INT_PRINT_DEC ")",
2746 2 * INTVAL (XEXP (x, 1)));
2747 if (AVR_3_BYTE_PC)
2748 if (warning (0, "pointer offset from symbol maybe incorrect"))
2749 {
2750 output_addr_const (stderr, addr);
2751 fprintf (stderr, "\n");
2752 }
2753 }
2754 else
2755 {
2756 fprintf (file, "gs(");
2757 output_addr_const (file, addr);
2758 fprintf (file, ")");
2759 }
2760 }
2761 else
2762 output_addr_const (file, addr);
2763 }
2764 }
2765
2766
2767 /* Implement `TARGET_PRINT_OPERAND_PUNCT_VALID_P'. */
2768
2769 static bool
avr_print_operand_punct_valid_p(unsigned char code)2770 avr_print_operand_punct_valid_p (unsigned char code)
2771 {
2772 return code == '~' || code == '!';
2773 }
2774
2775
2776 /* Implement `TARGET_PRINT_OPERAND'. */
2777 /* Output X as assembler operand to file FILE.
2778 For a description of supported %-codes, see top of avr.md. */
2779
2780 static void
avr_print_operand(FILE * file,rtx x,int code)2781 avr_print_operand (FILE *file, rtx x, int code)
2782 {
2783 int abcd = 0, ef = 0, ij = 0;
2784
2785 if (code >= 'A' && code <= 'D')
2786 abcd = code - 'A';
2787 else if (code == 'E' || code == 'F')
2788 ef = code - 'E';
2789 else if (code == 'I' || code == 'J')
2790 ij = code - 'I';
2791
2792 if (code == '~')
2793 {
2794 if (!AVR_HAVE_JMP_CALL)
2795 fputc ('r', file);
2796 }
2797 else if (code == '!')
2798 {
2799 if (AVR_HAVE_EIJMP_EICALL)
2800 fputc ('e', file);
2801 }
2802 else if (code == 't'
2803 || code == 'T')
2804 {
2805 static int t_regno = -1;
2806 static int t_nbits = -1;
2807
2808 if (REG_P (x) && t_regno < 0 && code == 'T')
2809 {
2810 t_regno = REGNO (x);
2811 t_nbits = GET_MODE_BITSIZE (GET_MODE (x));
2812 }
2813 else if (CONST_INT_P (x) && t_regno >= 0
2814 && IN_RANGE (INTVAL (x), 0, t_nbits - 1))
2815 {
2816 int bpos = INTVAL (x);
2817
2818 fprintf (file, "%s", reg_names[t_regno + bpos / 8]);
2819 if (code == 'T')
2820 fprintf (file, ",%d", bpos % 8);
2821
2822 t_regno = -1;
2823 }
2824 else
2825 fatal_insn ("operands to %T/%t must be reg + const_int:", x);
2826 }
2827 else if (code == 'E' || code == 'F')
2828 {
2829 rtx op = XEXP (x, 0);
2830 fprintf (file, "%s", reg_names[REGNO (op) + ef]);
2831 }
2832 else if (code == 'I' || code == 'J')
2833 {
2834 rtx op = XEXP (XEXP (x, 0), 0);
2835 fprintf (file, "%s", reg_names[REGNO (op) + ij]);
2836 }
2837 else if (REG_P (x))
2838 {
2839 if (x == zero_reg_rtx)
2840 fprintf (file, "__zero_reg__");
2841 else if (code == 'r' && REGNO (x) < 32)
2842 fprintf (file, "%d", (int) REGNO (x));
2843 else
2844 fprintf (file, "%s", reg_names[REGNO (x) + abcd]);
2845 }
2846 else if (CONST_INT_P (x))
2847 {
2848 HOST_WIDE_INT ival = INTVAL (x);
2849
2850 if ('i' != code)
2851 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival + abcd);
2852 else if (low_io_address_operand (x, VOIDmode)
2853 || high_io_address_operand (x, VOIDmode))
2854 {
2855 if (AVR_HAVE_RAMPZ && ival == avr_addr.rampz)
2856 fprintf (file, "__RAMPZ__");
2857 else if (AVR_HAVE_RAMPY && ival == avr_addr.rampy)
2858 fprintf (file, "__RAMPY__");
2859 else if (AVR_HAVE_RAMPX && ival == avr_addr.rampx)
2860 fprintf (file, "__RAMPX__");
2861 else if (AVR_HAVE_RAMPD && ival == avr_addr.rampd)
2862 fprintf (file, "__RAMPD__");
2863 else if ((AVR_XMEGA || AVR_TINY) && ival == avr_addr.ccp)
2864 fprintf (file, "__CCP__");
2865 else if (ival == avr_addr.sreg) fprintf (file, "__SREG__");
2866 else if (ival == avr_addr.sp_l) fprintf (file, "__SP_L__");
2867 else if (ival == avr_addr.sp_h) fprintf (file, "__SP_H__");
2868 else
2869 {
2870 fprintf (file, HOST_WIDE_INT_PRINT_HEX,
2871 ival - avr_arch->sfr_offset);
2872 }
2873 }
2874 else
2875 fatal_insn ("bad address, not an I/O address:", x);
2876 }
2877 else if (MEM_P (x))
2878 {
2879 rtx addr = XEXP (x, 0);
2880
2881 if (code == 'm')
2882 {
2883 if (!CONSTANT_P (addr))
2884 fatal_insn ("bad address, not a constant:", addr);
2885 /* Assembler template with m-code is data - not progmem section */
2886 if (text_segment_operand (addr, VOIDmode))
2887 if (warning (0, "accessing data memory with"
2888 " program memory address"))
2889 {
2890 output_addr_const (stderr, addr);
2891 fprintf(stderr,"\n");
2892 }
2893 output_addr_const (file, addr);
2894 }
2895 else if (code == 'i')
2896 {
2897 avr_print_operand (file, addr, 'i');
2898 }
2899 else if (code == 'o')
2900 {
2901 if (GET_CODE (addr) != PLUS)
2902 fatal_insn ("bad address, not (reg+disp):", addr);
2903
2904 avr_print_operand (file, XEXP (addr, 1), 0);
2905 }
2906 else if (code == 'b')
2907 {
2908 if (GET_CODE (addr) != PLUS)
2909 fatal_insn ("bad address, not (reg+disp):", addr);
2910
2911 avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
2912 }
2913 else if (code == 'p' || code == 'r')
2914 {
2915 if (GET_CODE (addr) != POST_INC && GET_CODE (addr) != PRE_DEC)
2916 fatal_insn ("bad address, not post_inc or pre_dec:", addr);
2917
2918 if (code == 'p')
2919 /* X, Y, Z */
2920 avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
2921 else
2922 avr_print_operand (file, XEXP (addr, 0), 0); /* r26, r28, r30 */
2923 }
2924 else if (GET_CODE (addr) == PLUS)
2925 {
2926 avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
2927 if (REGNO (XEXP (addr, 0)) == REG_X)
2928 fatal_insn ("internal compiler error. Bad address:"
2929 ,addr);
2930 fputc ('+', file);
2931 avr_print_operand (file, XEXP (addr, 1), code);
2932 }
2933 else
2934 avr_print_operand_address (file, VOIDmode, addr);
2935 }
2936 else if (code == 'i')
2937 {
2938 if (SYMBOL_REF_P (x) && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO))
2939 avr_print_operand_address
2940 (file, VOIDmode, plus_constant (HImode, x, -avr_arch->sfr_offset));
2941 else
2942 fatal_insn ("bad address, not an I/O address:", x);
2943 }
2944 else if (code == 'x')
2945 {
2946 /* Constant progmem address - like used in jmp or call */
2947 if (text_segment_operand (x, VOIDmode) == 0)
2948 if (warning (0, "accessing program memory"
2949 " with data memory address"))
2950 {
2951 output_addr_const (stderr, x);
2952 fprintf(stderr,"\n");
2953 }
2954 /* Use normal symbol for direct address no linker trampoline needed */
2955 output_addr_const (file, x);
2956 }
2957 else if (CONST_FIXED_P (x))
2958 {
2959 HOST_WIDE_INT ival = INTVAL (avr_to_int_mode (x));
2960 if (code != 0)
2961 output_operand_lossage ("Unsupported code '%c' for fixed-point:",
2962 code);
2963 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);
2964 }
2965 else if (CONST_DOUBLE_P (x))
2966 {
2967 long val;
2968 if (GET_MODE (x) != SFmode)
2969 fatal_insn ("internal compiler error. Unknown mode:", x);
2970 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), val);
2971 fprintf (file, "0x%lx", val);
2972 }
2973 else if (GET_CODE (x) == CONST_STRING)
2974 fputs (XSTR (x, 0), file);
2975 else if (code == 'j')
2976 fputs (cond_string (GET_CODE (x)), file);
2977 else if (code == 'k')
2978 fputs (cond_string (reverse_condition (GET_CODE (x))), file);
2979 else
2980 avr_print_operand_address (file, VOIDmode, x);
2981 }
2982
2983
2984 /* Implement TARGET_USE_BY_PIECES_INFRASTRUCTURE_P. */
2985
2986 /* Prefer sequence of loads/stores for moves of size upto
2987 two - two pairs of load/store instructions are always better
2988 than the 5 instruction sequence for a loop (1 instruction
2989 for loop counter setup, and 4 for the body of the loop). */
2990
2991 static bool
avr_use_by_pieces_infrastructure_p(unsigned HOST_WIDE_INT size,unsigned int align ATTRIBUTE_UNUSED,enum by_pieces_operation op,bool speed_p)2992 avr_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size,
2993 unsigned int align ATTRIBUTE_UNUSED,
2994 enum by_pieces_operation op,
2995 bool speed_p)
2996 {
2997 if (op != MOVE_BY_PIECES
2998 || (speed_p && size > MOVE_MAX_PIECES))
2999 return default_use_by_pieces_infrastructure_p (size, align, op, speed_p);
3000
3001 return size <= MOVE_MAX_PIECES;
3002 }
3003
3004 /* Choose mode for jump insn:
3005 1 - relative jump in range -63 <= x <= 62 ;
3006 2 - relative jump in range -2046 <= x <= 2045 ;
3007 3 - absolute jump (only for ATmega[16]03). */
3008
3009 int
avr_jump_mode(rtx x,rtx_insn * insn)3010 avr_jump_mode (rtx x, rtx_insn *insn)
3011 {
3012 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_CODE (x) == LABEL_REF
3013 ? XEXP (x, 0) : x));
3014 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
3015 int jump_distance = cur_addr - dest_addr;
3016
3017 if (IN_RANGE (jump_distance, -63, 62))
3018 return 1;
3019 else if (IN_RANGE (jump_distance, -2046, 2045))
3020 return 2;
3021 else if (AVR_HAVE_JMP_CALL)
3022 return 3;
3023
3024 return 2;
3025 }
3026
3027 /* Return an AVR condition jump commands.
3028 X is a comparison RTX.
3029 LEN is a number returned by avr_jump_mode function.
3030 If REVERSE nonzero then condition code in X must be reversed. */
3031
3032 const char*
ret_cond_branch(rtx x,int len,int reverse)3033 ret_cond_branch (rtx x, int len, int reverse)
3034 {
3035 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
3036 bool cc_overflow_unusable = false;
3037
3038 switch (cond)
3039 {
3040 case GT:
3041 if (cc_overflow_unusable)
3042 return (len == 1 ? ("breq .+2" CR_TAB
3043 "brpl %0") :
3044 len == 2 ? ("breq .+4" CR_TAB
3045 "brmi .+2" CR_TAB
3046 "rjmp %0") :
3047 ("breq .+6" CR_TAB
3048 "brmi .+4" CR_TAB
3049 "jmp %0"));
3050
3051 else
3052 return (len == 1 ? ("breq .+2" CR_TAB
3053 "brge %0") :
3054 len == 2 ? ("breq .+4" CR_TAB
3055 "brlt .+2" CR_TAB
3056 "rjmp %0") :
3057 ("breq .+6" CR_TAB
3058 "brlt .+4" CR_TAB
3059 "jmp %0"));
3060 case GTU:
3061 return (len == 1 ? ("breq .+2" CR_TAB
3062 "brsh %0") :
3063 len == 2 ? ("breq .+4" CR_TAB
3064 "brlo .+2" CR_TAB
3065 "rjmp %0") :
3066 ("breq .+6" CR_TAB
3067 "brlo .+4" CR_TAB
3068 "jmp %0"));
3069 case LE:
3070 if (cc_overflow_unusable)
3071 return (len == 1 ? ("breq %0" CR_TAB
3072 "brmi %0") :
3073 len == 2 ? ("breq .+2" CR_TAB
3074 "brpl .+2" CR_TAB
3075 "rjmp %0") :
3076 ("breq .+2" CR_TAB
3077 "brpl .+4" CR_TAB
3078 "jmp %0"));
3079 else
3080 return (len == 1 ? ("breq %0" CR_TAB
3081 "brlt %0") :
3082 len == 2 ? ("breq .+2" CR_TAB
3083 "brge .+2" CR_TAB
3084 "rjmp %0") :
3085 ("breq .+2" CR_TAB
3086 "brge .+4" CR_TAB
3087 "jmp %0"));
3088 case LEU:
3089 return (len == 1 ? ("breq %0" CR_TAB
3090 "brlo %0") :
3091 len == 2 ? ("breq .+2" CR_TAB
3092 "brsh .+2" CR_TAB
3093 "rjmp %0") :
3094 ("breq .+2" CR_TAB
3095 "brsh .+4" CR_TAB
3096 "jmp %0"));
3097 default:
3098 if (reverse)
3099 {
3100 switch (len)
3101 {
3102 case 1:
3103 return "br%k1 %0";
3104 case 2:
3105 return ("br%j1 .+2" CR_TAB
3106 "rjmp %0");
3107 default:
3108 return ("br%j1 .+4" CR_TAB
3109 "jmp %0");
3110 }
3111 }
3112 else
3113 {
3114 switch (len)
3115 {
3116 case 1:
3117 return "br%j1 %0";
3118 case 2:
3119 return ("br%k1 .+2" CR_TAB
3120 "rjmp %0");
3121 default:
3122 return ("br%k1 .+4" CR_TAB
3123 "jmp %0");
3124 }
3125 }
3126 }
3127 return "";
3128 }
3129
3130
3131 /* Worker function for `FINAL_PRESCAN_INSN'. */
3132 /* Output insn cost for next insn. */
3133
3134 void
avr_final_prescan_insn(rtx_insn * insn,rtx * operand ATTRIBUTE_UNUSED,int num_operands ATTRIBUTE_UNUSED)3135 avr_final_prescan_insn (rtx_insn *insn, rtx *operand ATTRIBUTE_UNUSED,
3136 int num_operands ATTRIBUTE_UNUSED)
3137 {
3138 if (avr_log.rtx_costs)
3139 {
3140 rtx set = single_set (insn);
3141
3142 if (set)
3143 fprintf (asm_out_file, "/* DEBUG: cost = %d. */\n",
3144 set_src_cost (SET_SRC (set), GET_MODE (SET_DEST (set)),
3145 optimize_insn_for_speed_p ()));
3146 else
3147 fprintf (asm_out_file, "/* DEBUG: pattern-cost = %d. */\n",
3148 rtx_cost (PATTERN (insn), VOIDmode, INSN, 0,
3149 optimize_insn_for_speed_p()));
3150 }
3151
3152 if (avr_log.insn_addresses)
3153 fprintf (asm_out_file, ";; ADDR = %d\n",
3154 (int) INSN_ADDRESSES (INSN_UID (insn)));
3155 }
3156
3157
3158 /* Implement `TARGET_ASM_FINAL_POSTSCAN_INSN'. */
3159 /* When GAS generates (parts of) ISR prologue / epilogue for us, we must
3160 hint GAS about the end of the code to scan. There migh be code located
3161 after the last epilogue. */
3162
3163 static void
avr_asm_final_postscan_insn(FILE * stream,rtx_insn * insn,rtx *,int)3164 avr_asm_final_postscan_insn (FILE *stream, rtx_insn *insn, rtx*, int)
3165 {
3166 if (cfun->machine->gasisr.yes
3167 && !next_real_insn (insn))
3168 {
3169 app_disable();
3170 fprintf (stream, "\t__gcc_isr %d,r%d\n", GASISR_Done,
3171 cfun->machine->gasisr.regno);
3172 }
3173 }
3174
3175
3176 /* Return 0 if undefined, 1 if always true or always false. */
3177
3178 int
avr_simplify_comparison_p(machine_mode mode,RTX_CODE op,rtx x)3179 avr_simplify_comparison_p (machine_mode mode, RTX_CODE op, rtx x)
3180 {
3181 unsigned int max = (mode == QImode ? 0xff :
3182 mode == HImode ? 0xffff :
3183 mode == PSImode ? 0xffffff :
3184 mode == SImode ? 0xffffffff : 0);
3185 if (max && op && CONST_INT_P (x))
3186 {
3187 if (unsigned_condition (op) != op)
3188 max >>= 1;
3189
3190 if (max != (INTVAL (x) & max)
3191 && INTVAL (x) != 0xff)
3192 return 1;
3193 }
3194 return 0;
3195 }
3196
3197
3198 /* Worker function for `FUNCTION_ARG_REGNO_P'. */
3199 /* Returns nonzero if REGNO is the number of a hard
3200 register in which function arguments are sometimes passed. */
3201
3202 int
avr_function_arg_regno_p(int r)3203 avr_function_arg_regno_p (int r)
3204 {
3205 return AVR_TINY ? IN_RANGE (r, 20, 25) : IN_RANGE (r, 8, 25);
3206 }
3207
3208
3209 /* Worker function for `INIT_CUMULATIVE_ARGS'. */
3210 /* Initializing the variable cum for the state at the beginning
3211 of the argument list. */
3212
3213 void
avr_init_cumulative_args(CUMULATIVE_ARGS * cum,tree fntype,rtx libname,tree fndecl ATTRIBUTE_UNUSED)3214 avr_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
3215 tree fndecl ATTRIBUTE_UNUSED)
3216 {
3217 cum->nregs = AVR_TINY ? 6 : 18;
3218 cum->regno = FIRST_CUM_REG;
3219 if (!libname && stdarg_p (fntype))
3220 cum->nregs = 0;
3221
3222 /* Assume the calle may be tail called */
3223
3224 cfun->machine->sibcall_fails = 0;
3225 }
3226
3227 /* Returns the number of registers to allocate for a function argument. */
3228
3229 static int
avr_num_arg_regs(machine_mode mode,const_tree type)3230 avr_num_arg_regs (machine_mode mode, const_tree type)
3231 {
3232 int size;
3233
3234 if (mode == BLKmode)
3235 size = int_size_in_bytes (type);
3236 else
3237 size = GET_MODE_SIZE (mode);
3238
3239 /* Align all function arguments to start in even-numbered registers.
3240 Odd-sized arguments leave holes above them. */
3241
3242 return (size + 1) & ~1;
3243 }
3244
3245
3246 /* Implement `TARGET_FUNCTION_ARG'. */
3247 /* Controls whether a function argument is passed
3248 in a register, and which register. */
3249
3250 static rtx
avr_function_arg(cumulative_args_t cum_v,const function_arg_info & arg)3251 avr_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
3252 {
3253 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
3254 int bytes = avr_num_arg_regs (arg.mode, arg.type);
3255
3256 if (cum->nregs && bytes <= cum->nregs)
3257 return gen_rtx_REG (arg.mode, cum->regno - bytes);
3258
3259 return NULL_RTX;
3260 }
3261
3262
3263 /* Implement `TARGET_FUNCTION_ARG_ADVANCE'. */
3264 /* Update the summarizer variable CUM to advance past an argument
3265 in the argument list. */
3266
3267 static void
avr_function_arg_advance(cumulative_args_t cum_v,const function_arg_info & arg)3268 avr_function_arg_advance (cumulative_args_t cum_v,
3269 const function_arg_info &arg)
3270 {
3271 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
3272 int bytes = avr_num_arg_regs (arg.mode, arg.type);
3273
3274 cum->nregs -= bytes;
3275 cum->regno -= bytes;
3276
3277 /* A parameter is being passed in a call-saved register. As the original
3278 contents of these regs has to be restored before leaving the function,
3279 a function must not pass arguments in call-saved regs in order to get
3280 tail-called. */
3281
3282 if (cum->regno >= 8
3283 && cum->nregs >= 0
3284 && !call_used_or_fixed_reg_p (cum->regno))
3285 {
3286 /* FIXME: We ship info on failing tail-call in struct machine_function.
3287 This uses internals of calls.c:expand_call() and the way args_so_far
3288 is used. targetm.function_ok_for_sibcall() needs to be extended to
3289 pass &args_so_far, too. At present, CUMULATIVE_ARGS is target
3290 dependent so that such an extension is not wanted. */
3291
3292 cfun->machine->sibcall_fails = 1;
3293 }
3294
3295 /* Test if all registers needed by the ABI are actually available. If the
3296 user has fixed a GPR needed to pass an argument, an (implicit) function
3297 call will clobber that fixed register. See PR45099 for an example. */
3298
3299 if (cum->regno >= 8
3300 && cum->nregs >= 0)
3301 {
3302 for (int regno = cum->regno; regno < cum->regno + bytes; regno++)
3303 if (fixed_regs[regno])
3304 warning (0, "fixed register %s used to pass parameter to function",
3305 reg_names[regno]);
3306 }
3307
3308 if (cum->nregs <= 0)
3309 {
3310 cum->nregs = 0;
3311 cum->regno = FIRST_CUM_REG;
3312 }
3313 }
3314
3315 /* Implement `TARGET_FUNCTION_OK_FOR_SIBCALL' */
3316 /* Decide whether we can make a sibling call to a function. DECL is the
3317 declaration of the function being targeted by the call and EXP is the
3318 CALL_EXPR representing the call. */
3319
3320 static bool
avr_function_ok_for_sibcall(tree decl_callee,tree exp_callee)3321 avr_function_ok_for_sibcall (tree decl_callee, tree exp_callee)
3322 {
3323 tree fntype_callee;
3324
3325 /* Tail-calling must fail if callee-saved regs are used to pass
3326 function args. We must not tail-call when `epilogue_restores'
3327 is used. Unfortunately, we cannot tell at this point if that
3328 actually will happen or not, and we cannot step back from
3329 tail-calling. Thus, we inhibit tail-calling with -mcall-prologues. */
3330
3331 if (cfun->machine->sibcall_fails
3332 || TARGET_CALL_PROLOGUES)
3333 {
3334 return false;
3335 }
3336
3337 fntype_callee = TREE_TYPE (CALL_EXPR_FN (exp_callee));
3338
3339 if (decl_callee)
3340 {
3341 decl_callee = TREE_TYPE (decl_callee);
3342 }
3343 else
3344 {
3345 decl_callee = fntype_callee;
3346
3347 while (FUNCTION_TYPE != TREE_CODE (decl_callee)
3348 && METHOD_TYPE != TREE_CODE (decl_callee))
3349 {
3350 decl_callee = TREE_TYPE (decl_callee);
3351 }
3352 }
3353
3354 /* Ensure that caller and callee have compatible epilogues */
3355
3356 if (cfun->machine->is_interrupt
3357 || cfun->machine->is_signal
3358 || cfun->machine->is_naked
3359 || avr_naked_function_p (decl_callee))
3360 {
3361 return false;
3362 }
3363
3364 return true;
3365 }
3366
3367 /***********************************************************************
3368 Functions for outputting various mov's for a various modes
3369 ************************************************************************/
3370
3371 /* Return true if a value of mode MODE is read from flash by
3372 __load_* function from libgcc. */
3373
3374 bool
avr_load_libgcc_p(rtx op)3375 avr_load_libgcc_p (rtx op)
3376 {
3377 machine_mode mode = GET_MODE (op);
3378 int n_bytes = GET_MODE_SIZE (mode);
3379
3380 return (n_bytes > 2
3381 && !AVR_HAVE_LPMX
3382 && avr_mem_flash_p (op));
3383 }
3384
3385 /* Return true if a value of mode MODE is read by __xload_* function. */
3386
3387 bool
avr_xload_libgcc_p(machine_mode mode)3388 avr_xload_libgcc_p (machine_mode mode)
3389 {
3390 int n_bytes = GET_MODE_SIZE (mode);
3391
3392 return (n_bytes > 1
3393 || avr_n_flash > 1);
3394 }
3395
3396
3397 /* Fixme: This is a hack because secondary reloads don't works as expected.
3398
3399 Find an unused d-register to be used as scratch in INSN.
3400 EXCLUDE is either NULL_RTX or some register. In the case where EXCLUDE
3401 is a register, skip all possible return values that overlap EXCLUDE.
3402 The policy for the returned register is similar to that of
3403 `reg_unused_after', i.e. the returned register may overlap the SET_DEST
3404 of INSN.
3405
3406 Return a QImode d-register or NULL_RTX if nothing found. */
3407
3408 static rtx
avr_find_unused_d_reg(rtx_insn * insn,rtx exclude)3409 avr_find_unused_d_reg (rtx_insn *insn, rtx exclude)
3410 {
3411 bool isr_p = (avr_interrupt_function_p (current_function_decl)
3412 || avr_signal_function_p (current_function_decl));
3413
3414 for (int regno = 16; regno < 32; regno++)
3415 {
3416 rtx reg = all_regs_rtx[regno];
3417
3418 if ((exclude
3419 && reg_overlap_mentioned_p (exclude, reg))
3420 || fixed_regs[regno])
3421 {
3422 continue;
3423 }
3424
3425 /* Try non-live register */
3426
3427 if (!df_regs_ever_live_p (regno)
3428 && (TREE_THIS_VOLATILE (current_function_decl)
3429 || cfun->machine->is_OS_task
3430 || cfun->machine->is_OS_main
3431 || (!isr_p && call_used_or_fixed_reg_p (regno))))
3432 {
3433 return reg;
3434 }
3435
3436 /* Any live register can be used if it is unused after.
3437 Prologue/epilogue will care for it as needed. */
3438
3439 if (df_regs_ever_live_p (regno)
3440 && reg_unused_after (insn, reg))
3441 {
3442 return reg;
3443 }
3444 }
3445
3446 return NULL_RTX;
3447 }
3448
3449
3450 /* Helper function for the next function in the case where only restricted
3451 version of LPM instruction is available. */
3452
3453 static const char*
avr_out_lpm_no_lpmx(rtx_insn * insn,rtx * xop,int * plen)3454 avr_out_lpm_no_lpmx (rtx_insn *insn, rtx *xop, int *plen)
3455 {
3456 rtx dest = xop[0];
3457 rtx addr = xop[1];
3458 int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
3459 int regno_dest;
3460
3461 regno_dest = REGNO (dest);
3462
3463 /* The implicit target register of LPM. */
3464 xop[3] = lpm_reg_rtx;
3465
3466 switch (GET_CODE (addr))
3467 {
3468 default:
3469 gcc_unreachable();
3470
3471 case REG:
3472
3473 gcc_assert (REG_Z == REGNO (addr));
3474
3475 switch (n_bytes)
3476 {
3477 default:
3478 gcc_unreachable();
3479
3480 case 1:
3481 avr_asm_len ("%4lpm", xop, plen, 1);
3482
3483 if (regno_dest != LPM_REGNO)
3484 avr_asm_len ("mov %0,%3", xop, plen, 1);
3485
3486 return "";
3487
3488 case 2:
3489 if (REGNO (dest) == REG_Z)
3490 return avr_asm_len ("%4lpm" CR_TAB
3491 "push %3" CR_TAB
3492 "adiw %2,1" CR_TAB
3493 "%4lpm" CR_TAB
3494 "mov %B0,%3" CR_TAB
3495 "pop %A0", xop, plen, 6);
3496
3497 avr_asm_len ("%4lpm" CR_TAB
3498 "mov %A0,%3" CR_TAB
3499 "adiw %2,1" CR_TAB
3500 "%4lpm" CR_TAB
3501 "mov %B0,%3", xop, plen, 5);
3502
3503 if (!reg_unused_after (insn, addr))
3504 avr_asm_len ("sbiw %2,1", xop, plen, 1);
3505
3506 break; /* 2 */
3507 }
3508
3509 break; /* REG */
3510
3511 case POST_INC:
3512
3513 gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
3514 && n_bytes <= 4);
3515
3516 if (regno_dest == LPM_REGNO)
3517 avr_asm_len ("%4lpm" CR_TAB
3518 "adiw %2,1", xop, plen, 2);
3519 else
3520 avr_asm_len ("%4lpm" CR_TAB
3521 "mov %A0,%3" CR_TAB
3522 "adiw %2,1", xop, plen, 3);
3523
3524 if (n_bytes >= 2)
3525 avr_asm_len ("%4lpm" CR_TAB
3526 "mov %B0,%3" CR_TAB
3527 "adiw %2,1", xop, plen, 3);
3528
3529 if (n_bytes >= 3)
3530 avr_asm_len ("%4lpm" CR_TAB
3531 "mov %C0,%3" CR_TAB
3532 "adiw %2,1", xop, plen, 3);
3533
3534 if (n_bytes >= 4)
3535 avr_asm_len ("%4lpm" CR_TAB
3536 "mov %D0,%3" CR_TAB
3537 "adiw %2,1", xop, plen, 3);
3538
3539 break; /* POST_INC */
3540
3541 } /* switch CODE (addr) */
3542
3543 return "";
3544 }
3545
3546
3547 /* If PLEN == NULL: Ouput instructions to load a value from a memory location
3548 OP[1] in AS1 to register OP[0].
3549 If PLEN != 0 set *PLEN to the length in words of the instruction sequence.
3550 Return "". */
3551
3552 const char*
avr_out_lpm(rtx_insn * insn,rtx * op,int * plen)3553 avr_out_lpm (rtx_insn *insn, rtx *op, int *plen)
3554 {
3555 rtx xop[7];
3556 rtx dest = op[0];
3557 rtx src = SET_SRC (single_set (insn));
3558 rtx addr;
3559 int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
3560 int segment;
3561 RTX_CODE code;
3562 addr_space_t as = MEM_ADDR_SPACE (src);
3563
3564 if (plen)
3565 *plen = 0;
3566
3567 if (MEM_P (dest))
3568 {
3569 warning (0, "writing to address space %qs not supported",
3570 avr_addrspace[MEM_ADDR_SPACE (dest)].name);
3571
3572 return "";
3573 }
3574
3575 addr = XEXP (src, 0);
3576 code = GET_CODE (addr);
3577
3578 gcc_assert (REG_P (dest));
3579 gcc_assert (REG == code || POST_INC == code);
3580
3581 xop[0] = dest;
3582 xop[1] = addr;
3583 xop[2] = lpm_addr_reg_rtx;
3584 xop[4] = xstring_empty;
3585 xop[5] = tmp_reg_rtx;
3586 xop[6] = XEXP (rampz_rtx, 0);
3587
3588 segment = avr_addrspace[as].segment;
3589
3590 /* Set RAMPZ as needed. */
3591
3592 if (segment)
3593 {
3594 xop[4] = GEN_INT (segment);
3595 xop[3] = avr_find_unused_d_reg (insn, lpm_addr_reg_rtx);
3596
3597 if (xop[3] != NULL_RTX)
3598 {
3599 avr_asm_len ("ldi %3,%4" CR_TAB
3600 "out %i6,%3", xop, plen, 2);
3601 }
3602 else if (segment == 1)
3603 {
3604 avr_asm_len ("clr %5" CR_TAB
3605 "inc %5" CR_TAB
3606 "out %i6,%5", xop, plen, 3);
3607 }
3608 else
3609 {
3610 avr_asm_len ("mov %5,%2" CR_TAB
3611 "ldi %2,%4" CR_TAB
3612 "out %i6,%2" CR_TAB
3613 "mov %2,%5", xop, plen, 4);
3614 }
3615
3616 xop[4] = xstring_e;
3617
3618 if (!AVR_HAVE_ELPMX)
3619 return avr_out_lpm_no_lpmx (insn, xop, plen);
3620 }
3621 else if (!AVR_HAVE_LPMX)
3622 {
3623 return avr_out_lpm_no_lpmx (insn, xop, plen);
3624 }
3625
3626 /* We have [E]LPMX: Output reading from Flash the comfortable way. */
3627
3628 switch (GET_CODE (addr))
3629 {
3630 default:
3631 gcc_unreachable();
3632
3633 case REG:
3634
3635 gcc_assert (REG_Z == REGNO (addr));
3636
3637 switch (n_bytes)
3638 {
3639 default:
3640 gcc_unreachable();
3641
3642 case 1:
3643 avr_asm_len ("%4lpm %0,%a2", xop, plen, 1);
3644 break;
3645
3646 case 2:
3647 if (REGNO (dest) == REG_Z)
3648 avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3649 "%4lpm %B0,%a2" CR_TAB
3650 "mov %A0,%5", xop, plen, 3);
3651 else
3652 {
3653 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3654 "%4lpm %B0,%a2", xop, plen, 2);
3655
3656 if (!reg_unused_after (insn, addr))
3657 avr_asm_len ("sbiw %2,1", xop, plen, 1);
3658 }
3659
3660 break; /* 2 */
3661
3662 case 3:
3663
3664 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3665 "%4lpm %B0,%a2+" CR_TAB
3666 "%4lpm %C0,%a2", xop, plen, 3);
3667
3668 if (!reg_unused_after (insn, addr))
3669 avr_asm_len ("sbiw %2,2", xop, plen, 1);
3670
3671 break; /* 3 */
3672
3673 case 4:
3674
3675 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3676 "%4lpm %B0,%a2+", xop, plen, 2);
3677
3678 if (REGNO (dest) == REG_Z - 2)
3679 avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3680 "%4lpm %C0,%a2" CR_TAB
3681 "mov %D0,%5", xop, plen, 3);
3682 else
3683 {
3684 avr_asm_len ("%4lpm %C0,%a2+" CR_TAB
3685 "%4lpm %D0,%a2", xop, plen, 2);
3686
3687 if (!reg_unused_after (insn, addr))
3688 avr_asm_len ("sbiw %2,3", xop, plen, 1);
3689 }
3690
3691 break; /* 4 */
3692 } /* n_bytes */
3693
3694 break; /* REG */
3695
3696 case POST_INC:
3697
3698 gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
3699 && n_bytes <= 4);
3700
3701 avr_asm_len ("%4lpm %A0,%a2+", xop, plen, 1);
3702 if (n_bytes >= 2) avr_asm_len ("%4lpm %B0,%a2+", xop, plen, 1);
3703 if (n_bytes >= 3) avr_asm_len ("%4lpm %C0,%a2+", xop, plen, 1);
3704 if (n_bytes >= 4) avr_asm_len ("%4lpm %D0,%a2+", xop, plen, 1);
3705
3706 break; /* POST_INC */
3707
3708 } /* switch CODE (addr) */
3709
3710 if (xop[4] == xstring_e && AVR_HAVE_RAMPD)
3711 {
3712 /* Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM. */
3713
3714 xop[0] = zero_reg_rtx;
3715 avr_asm_len ("out %i6,%0", xop, plen, 1);
3716 }
3717
3718 return "";
3719 }
3720
3721
3722 /* Worker function for xload_8 insn. */
3723
3724 const char*
avr_out_xload(rtx_insn * insn ATTRIBUTE_UNUSED,rtx * op,int * plen)3725 avr_out_xload (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
3726 {
3727 rtx xop[4];
3728
3729 xop[0] = op[0];
3730 xop[1] = op[1];
3731 xop[2] = lpm_addr_reg_rtx;
3732 xop[3] = AVR_HAVE_LPMX ? op[0] : lpm_reg_rtx;
3733
3734 avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, -1);
3735
3736 avr_asm_len ("sbrc %1,7" CR_TAB
3737 "ld %3,%a2", xop, plen, 2);
3738
3739 if (REGNO (xop[0]) != REGNO (xop[3]))
3740 avr_asm_len ("mov %0,%3", xop, plen, 1);
3741
3742 return "";
3743 }
3744
3745
3746 const char*
output_movqi(rtx_insn * insn,rtx operands[],int * plen)3747 output_movqi (rtx_insn *insn, rtx operands[], int *plen)
3748 {
3749 rtx dest = operands[0];
3750 rtx src = operands[1];
3751
3752 if (avr_mem_flash_p (src)
3753 || avr_mem_flash_p (dest))
3754 {
3755 return avr_out_lpm (insn, operands, plen);
3756 }
3757
3758 gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 1);
3759
3760 if (REG_P (dest))
3761 {
3762 if (REG_P (src)) /* mov r,r */
3763 {
3764 if (test_hard_reg_class (STACK_REG, dest))
3765 return avr_asm_len ("out %0,%1", operands, plen, -1);
3766 else if (test_hard_reg_class (STACK_REG, src))
3767 return avr_asm_len ("in %0,%1", operands, plen, -1);
3768
3769 return avr_asm_len ("mov %0,%1", operands, plen, -1);
3770 }
3771 else if (CONSTANT_P (src))
3772 {
3773 output_reload_in_const (operands, NULL_RTX, plen, false);
3774 return "";
3775 }
3776 else if (MEM_P (src))
3777 return out_movqi_r_mr (insn, operands, plen); /* mov r,m */
3778 }
3779 else if (MEM_P (dest))
3780 {
3781 rtx xop[2];
3782
3783 xop[0] = dest;
3784 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
3785
3786 return out_movqi_mr_r (insn, xop, plen);
3787 }
3788
3789 return "";
3790 }
3791
3792
3793 const char *
output_movhi(rtx_insn * insn,rtx xop[],int * plen)3794 output_movhi (rtx_insn *insn, rtx xop[], int *plen)
3795 {
3796 rtx dest = xop[0];
3797 rtx src = xop[1];
3798
3799 gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 2);
3800
3801 if (avr_mem_flash_p (src)
3802 || avr_mem_flash_p (dest))
3803 {
3804 return avr_out_lpm (insn, xop, plen);
3805 }
3806
3807 if (REG_P (dest))
3808 {
3809 if (REG_P (src)) /* mov r,r */
3810 {
3811 if (test_hard_reg_class (STACK_REG, dest))
3812 {
3813 if (AVR_HAVE_8BIT_SP)
3814 return avr_asm_len ("out __SP_L__,%A1", xop, plen, -1);
3815
3816 if (AVR_XMEGA)
3817 return avr_asm_len ("out __SP_L__,%A1" CR_TAB
3818 "out __SP_H__,%B1", xop, plen, -2);
3819
3820 /* Use simple load of SP if no interrupts are used. */
3821
3822 return TARGET_NO_INTERRUPTS
3823 ? avr_asm_len ("out __SP_H__,%B1" CR_TAB
3824 "out __SP_L__,%A1", xop, plen, -2)
3825 : avr_asm_len ("in __tmp_reg__,__SREG__" CR_TAB
3826 "cli" CR_TAB
3827 "out __SP_H__,%B1" CR_TAB
3828 "out __SREG__,__tmp_reg__" CR_TAB
3829 "out __SP_L__,%A1", xop, plen, -5);
3830 }
3831 else if (test_hard_reg_class (STACK_REG, src))
3832 {
3833 return !AVR_HAVE_SPH
3834 ? avr_asm_len ("in %A0,__SP_L__" CR_TAB
3835 "clr %B0", xop, plen, -2)
3836
3837 : avr_asm_len ("in %A0,__SP_L__" CR_TAB
3838 "in %B0,__SP_H__", xop, plen, -2);
3839 }
3840
3841 return AVR_HAVE_MOVW
3842 ? avr_asm_len ("movw %0,%1", xop, plen, -1)
3843
3844 : avr_asm_len ("mov %A0,%A1" CR_TAB
3845 "mov %B0,%B1", xop, plen, -2);
3846 } /* REG_P (src) */
3847 else if (CONSTANT_P (src))
3848 {
3849 return output_reload_inhi (xop, NULL, plen);
3850 }
3851 else if (MEM_P (src))
3852 {
3853 return out_movhi_r_mr (insn, xop, plen); /* mov r,m */
3854 }
3855 }
3856 else if (MEM_P (dest))
3857 {
3858 rtx xop[2];
3859
3860 xop[0] = dest;
3861 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
3862
3863 return out_movhi_mr_r (insn, xop, plen);
3864 }
3865
3866 fatal_insn ("invalid insn:", insn);
3867
3868 return "";
3869 }
3870
3871
3872 /* Same as out_movqi_r_mr, but TINY does not have ADIW or SBIW */
3873
3874 static const char*
avr_out_movqi_r_mr_reg_disp_tiny(rtx_insn * insn,rtx op[],int * plen)3875 avr_out_movqi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
3876 {
3877 rtx dest = op[0];
3878 rtx src = op[1];
3879 rtx x = XEXP (src, 0);
3880
3881 avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
3882 "ld %0,%b1" , op, plen, -3);
3883
3884 if (!reg_overlap_mentioned_p (dest, XEXP (x, 0))
3885 && !reg_unused_after (insn, XEXP (x, 0)))
3886 avr_asm_len (TINY_SBIW (%I1, %J1, %o1), op, plen, 2);
3887
3888 return "";
3889 }
3890
3891 static const char*
out_movqi_r_mr(rtx_insn * insn,rtx op[],int * plen)3892 out_movqi_r_mr (rtx_insn *insn, rtx op[], int *plen)
3893 {
3894 rtx dest = op[0];
3895 rtx src = op[1];
3896 rtx x = XEXP (src, 0);
3897
3898 if (CONSTANT_ADDRESS_P (x))
3899 {
3900 int n_words = AVR_TINY ? 1 : 2;
3901 return io_address_operand (x, QImode)
3902 ? avr_asm_len ("in %0,%i1", op, plen, -1)
3903 : avr_asm_len ("lds %0,%m1", op, plen, -n_words);
3904 }
3905
3906 if (GET_CODE (x) == PLUS
3907 && REG_P (XEXP (x, 0))
3908 && CONST_INT_P (XEXP (x, 1)))
3909 {
3910 /* memory access by reg+disp */
3911
3912 int disp = INTVAL (XEXP (x, 1));
3913
3914 if (AVR_TINY)
3915 return avr_out_movqi_r_mr_reg_disp_tiny (insn, op, plen);
3916
3917 if (disp - GET_MODE_SIZE (GET_MODE (src)) >= 63)
3918 {
3919 if (REGNO (XEXP (x, 0)) != REG_Y)
3920 fatal_insn ("incorrect insn:",insn);
3921
3922 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
3923 return avr_asm_len ("adiw r28,%o1-63" CR_TAB
3924 "ldd %0,Y+63" CR_TAB
3925 "sbiw r28,%o1-63", op, plen, -3);
3926
3927 return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
3928 "sbci r29,hi8(-%o1)" CR_TAB
3929 "ld %0,Y" CR_TAB
3930 "subi r28,lo8(%o1)" CR_TAB
3931 "sbci r29,hi8(%o1)", op, plen, -5);
3932 }
3933 else if (REGNO (XEXP (x, 0)) == REG_X)
3934 {
3935 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
3936 it but I have this situation with extremal optimizing options. */
3937
3938 avr_asm_len ("adiw r26,%o1" CR_TAB
3939 "ld %0,X", op, plen, -2);
3940
3941 if (!reg_overlap_mentioned_p (dest, XEXP (x, 0))
3942 && !reg_unused_after (insn, XEXP (x, 0)))
3943 {
3944 avr_asm_len ("sbiw r26,%o1", op, plen, 1);
3945 }
3946
3947 return "";
3948 }
3949
3950 return avr_asm_len ("ldd %0,%1", op, plen, -1);
3951 }
3952
3953 return avr_asm_len ("ld %0,%1", op, plen, -1);
3954 }
3955
3956
3957 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
3958
3959 static const char*
avr_out_movhi_r_mr_reg_no_disp_tiny(rtx_insn * insn,rtx op[],int * plen)3960 avr_out_movhi_r_mr_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
3961 {
3962 rtx dest = op[0];
3963 rtx src = op[1];
3964 rtx base = XEXP (src, 0);
3965
3966 int reg_dest = true_regnum (dest);
3967 int reg_base = true_regnum (base);
3968
3969 if (reg_dest == reg_base) /* R = (R) */
3970 return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
3971 "ld %B0,%1" CR_TAB
3972 "mov %A0,__tmp_reg__", op, plen, -3);
3973
3974 avr_asm_len ("ld %A0,%1+" CR_TAB
3975 "ld %B0,%1", op, plen, -2);
3976
3977 if (!reg_unused_after (insn, base))
3978 avr_asm_len (TINY_SBIW (%E1, %F1, 1), op, plen, 2);
3979
3980 return "";
3981 }
3982
3983
3984 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
3985
3986 static const char*
avr_out_movhi_r_mr_reg_disp_tiny(rtx_insn * insn,rtx op[],int * plen)3987 avr_out_movhi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
3988 {
3989 rtx dest = op[0];
3990 rtx src = op[1];
3991 rtx base = XEXP (src, 0);
3992
3993 int reg_dest = true_regnum (dest);
3994 int reg_base = true_regnum (XEXP (base, 0));
3995
3996 if (reg_base == reg_dest)
3997 {
3998 return avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
3999 "ld __tmp_reg__,%b1+" CR_TAB
4000 "ld %B0,%b1" CR_TAB
4001 "mov %A0,__tmp_reg__", op, plen, -5);
4002 }
4003 else
4004 {
4005 avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4006 "ld %A0,%b1+" CR_TAB
4007 "ld %B0,%b1", op, plen, -4);
4008
4009 if (!reg_unused_after (insn, XEXP (base, 0)))
4010 avr_asm_len (TINY_SBIW (%I1, %J1, %o1+1), op, plen, 2);
4011
4012 return "";
4013 }
4014 }
4015
4016
4017 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
4018
4019 static const char*
avr_out_movhi_r_mr_pre_dec_tiny(rtx_insn * insn,rtx op[],int * plen)4020 avr_out_movhi_r_mr_pre_dec_tiny (rtx_insn *insn, rtx op[], int *plen)
4021 {
4022 int mem_volatile_p = 0;
4023 rtx dest = op[0];
4024 rtx src = op[1];
4025 rtx base = XEXP (src, 0);
4026
4027 /* "volatile" forces reading low byte first, even if less efficient,
4028 for correct operation with 16-bit I/O registers. */
4029 mem_volatile_p = MEM_VOLATILE_P (src);
4030
4031 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
4032 fatal_insn ("incorrect insn:", insn);
4033
4034 if (!mem_volatile_p)
4035 return avr_asm_len ("ld %B0,%1" CR_TAB
4036 "ld %A0,%1", op, plen, -2);
4037
4038 return avr_asm_len (TINY_SBIW (%I1, %J1, 2) CR_TAB
4039 "ld %A0,%p1+" CR_TAB
4040 "ld %B0,%p1" CR_TAB
4041 TINY_SBIW (%I1, %J1, 1), op, plen, -6);
4042 }
4043
4044
4045 static const char*
out_movhi_r_mr(rtx_insn * insn,rtx op[],int * plen)4046 out_movhi_r_mr (rtx_insn *insn, rtx op[], int *plen)
4047 {
4048 rtx dest = op[0];
4049 rtx src = op[1];
4050 rtx base = XEXP (src, 0);
4051 int reg_dest = true_regnum (dest);
4052 int reg_base = true_regnum (base);
4053 /* "volatile" forces reading low byte first, even if less efficient,
4054 for correct operation with 16-bit I/O registers. */
4055 int mem_volatile_p = MEM_VOLATILE_P (src);
4056
4057 if (reg_base > 0)
4058 {
4059 if (AVR_TINY)
4060 return avr_out_movhi_r_mr_reg_no_disp_tiny (insn, op, plen);
4061
4062 if (reg_dest == reg_base) /* R = (R) */
4063 return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
4064 "ld %B0,%1" CR_TAB
4065 "mov %A0,__tmp_reg__", op, plen, -3);
4066
4067 if (reg_base != REG_X)
4068 return avr_asm_len ("ld %A0,%1" CR_TAB
4069 "ldd %B0,%1+1", op, plen, -2);
4070
4071 avr_asm_len ("ld %A0,X+" CR_TAB
4072 "ld %B0,X", op, plen, -2);
4073
4074 if (!reg_unused_after (insn, base))
4075 avr_asm_len ("sbiw r26,1", op, plen, 1);
4076
4077 return "";
4078 }
4079 else if (GET_CODE (base) == PLUS) /* (R + i) */
4080 {
4081 int disp = INTVAL (XEXP (base, 1));
4082 int reg_base = true_regnum (XEXP (base, 0));
4083
4084 if (AVR_TINY)
4085 return avr_out_movhi_r_mr_reg_disp_tiny (insn, op, plen);
4086
4087 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
4088 {
4089 if (REGNO (XEXP (base, 0)) != REG_Y)
4090 fatal_insn ("incorrect insn:",insn);
4091
4092 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (src))
4093 ? avr_asm_len ("adiw r28,%o1-62" CR_TAB
4094 "ldd %A0,Y+62" CR_TAB
4095 "ldd %B0,Y+63" CR_TAB
4096 "sbiw r28,%o1-62", op, plen, -4)
4097
4098 : avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
4099 "sbci r29,hi8(-%o1)" CR_TAB
4100 "ld %A0,Y" CR_TAB
4101 "ldd %B0,Y+1" CR_TAB
4102 "subi r28,lo8(%o1)" CR_TAB
4103 "sbci r29,hi8(%o1)", op, plen, -6);
4104 }
4105
4106 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
4107 it but I have this situation with extremal
4108 optimization options. */
4109
4110 if (reg_base == REG_X)
4111 {
4112 if (reg_base == reg_dest)
4113 return avr_asm_len ("adiw r26,%o1" CR_TAB
4114 "ld __tmp_reg__,X+" CR_TAB
4115 "ld %B0,X" CR_TAB
4116 "mov %A0,__tmp_reg__", op, plen, -4);
4117
4118 avr_asm_len ("adiw r26,%o1" CR_TAB
4119 "ld %A0,X+" CR_TAB
4120 "ld %B0,X", op, plen, -3);
4121
4122 if (!reg_unused_after (insn, XEXP (base, 0)))
4123 avr_asm_len ("sbiw r26,%o1+1", op, plen, 1);
4124
4125 return "";
4126 }
4127
4128 return reg_base == reg_dest
4129 ? avr_asm_len ("ldd __tmp_reg__,%A1" CR_TAB
4130 "ldd %B0,%B1" CR_TAB
4131 "mov %A0,__tmp_reg__", op, plen, -3)
4132
4133 : avr_asm_len ("ldd %A0,%A1" CR_TAB
4134 "ldd %B0,%B1", op, plen, -2);
4135 }
4136 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4137 {
4138 if (AVR_TINY)
4139 return avr_out_movhi_r_mr_pre_dec_tiny (insn, op, plen);
4140
4141 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
4142 fatal_insn ("incorrect insn:", insn);
4143
4144 if (!mem_volatile_p)
4145 return avr_asm_len ("ld %B0,%1" CR_TAB
4146 "ld %A0,%1", op, plen, -2);
4147
4148 return REGNO (XEXP (base, 0)) == REG_X
4149 ? avr_asm_len ("sbiw r26,2" CR_TAB
4150 "ld %A0,X+" CR_TAB
4151 "ld %B0,X" CR_TAB
4152 "sbiw r26,1", op, plen, -4)
4153
4154 : avr_asm_len ("sbiw %r1,2" CR_TAB
4155 "ld %A0,%p1" CR_TAB
4156 "ldd %B0,%p1+1", op, plen, -3);
4157 }
4158 else if (GET_CODE (base) == POST_INC) /* (R++) */
4159 {
4160 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
4161 fatal_insn ("incorrect insn:", insn);
4162
4163 return avr_asm_len ("ld %A0,%1" CR_TAB
4164 "ld %B0,%1", op, plen, -2);
4165 }
4166 else if (CONSTANT_ADDRESS_P (base))
4167 {
4168 int n_words = AVR_TINY ? 2 : 4;
4169 return io_address_operand (base, HImode)
4170 ? avr_asm_len ("in %A0,%i1" CR_TAB
4171 "in %B0,%i1+1", op, plen, -2)
4172
4173 : avr_asm_len ("lds %A0,%m1" CR_TAB
4174 "lds %B0,%m1+1", op, plen, -n_words);
4175 }
4176
4177 fatal_insn ("unknown move insn:",insn);
4178 return "";
4179 }
4180
4181 static const char*
avr_out_movsi_r_mr_reg_no_disp_tiny(rtx_insn * insn,rtx op[],int * l)4182 avr_out_movsi_r_mr_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *l)
4183 {
4184 rtx dest = op[0];
4185 rtx src = op[1];
4186 rtx base = XEXP (src, 0);
4187 int reg_dest = true_regnum (dest);
4188 int reg_base = true_regnum (base);
4189
4190 if (reg_dest == reg_base)
4191 {
4192 /* "ld r26,-X" is undefined */
4193 return *l = 9, (TINY_ADIW (%E1, %F1, 3) CR_TAB
4194 "ld %D0,%1" CR_TAB
4195 "ld %C0,-%1" CR_TAB
4196 "ld __tmp_reg__,-%1" CR_TAB
4197 TINY_SBIW (%E1, %F1, 1) CR_TAB
4198 "ld %A0,%1" CR_TAB
4199 "mov %B0,__tmp_reg__");
4200 }
4201 else if (reg_dest == reg_base - 2)
4202 {
4203 return *l = 5, ("ld %A0,%1+" CR_TAB
4204 "ld %B0,%1+" CR_TAB
4205 "ld __tmp_reg__,%1+" CR_TAB
4206 "ld %D0,%1" CR_TAB
4207 "mov %C0,__tmp_reg__");
4208 }
4209 else if (reg_unused_after (insn, base))
4210 {
4211 return *l = 4, ("ld %A0,%1+" CR_TAB
4212 "ld %B0,%1+" CR_TAB
4213 "ld %C0,%1+" CR_TAB
4214 "ld %D0,%1");
4215 }
4216 else
4217 {
4218 return *l = 6, ("ld %A0,%1+" CR_TAB
4219 "ld %B0,%1+" CR_TAB
4220 "ld %C0,%1+" CR_TAB
4221 "ld %D0,%1" CR_TAB
4222 TINY_SBIW (%E1, %F1, 3));
4223 }
4224 }
4225
4226
4227 static const char*
avr_out_movsi_r_mr_reg_disp_tiny(rtx_insn * insn,rtx op[],int * l)4228 avr_out_movsi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *l)
4229 {
4230 rtx dest = op[0];
4231 rtx src = op[1];
4232 rtx base = XEXP (src, 0);
4233 int reg_dest = true_regnum (dest);
4234 int reg_base = true_regnum (XEXP (base, 0));
4235
4236 if (reg_dest == reg_base)
4237 {
4238 /* "ld r26,-X" is undefined */
4239 return *l = 9, (TINY_ADIW (%I1, %J1, %o1+3) CR_TAB
4240 "ld %D0,%b1" CR_TAB
4241 "ld %C0,-%b1" CR_TAB
4242 "ld __tmp_reg__,-%b1" CR_TAB
4243 TINY_SBIW (%I1, %J1, 1) CR_TAB
4244 "ld %A0,%b1" CR_TAB
4245 "mov %B0,__tmp_reg__");
4246 }
4247 else if (reg_dest == reg_base - 2)
4248 {
4249 return *l = 7, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4250 "ld %A0,%b1+" CR_TAB
4251 "ld %B0,%b1+" CR_TAB
4252 "ld __tmp_reg__,%b1+" CR_TAB
4253 "ld %D0,%b1" CR_TAB
4254 "mov %C0,__tmp_reg__");
4255 }
4256 else if (reg_unused_after (insn, XEXP (base, 0)))
4257 {
4258 return *l = 6, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4259 "ld %A0,%b1+" CR_TAB
4260 "ld %B0,%b1+" CR_TAB
4261 "ld %C0,%b1+" CR_TAB
4262 "ld %D0,%b1");
4263 }
4264 else
4265 {
4266 return *l = 8, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4267 "ld %A0,%b1+" CR_TAB
4268 "ld %B0,%b1+" CR_TAB
4269 "ld %C0,%b1+" CR_TAB
4270 "ld %D0,%b1" CR_TAB
4271 TINY_SBIW (%I1, %J1, %o1+3));
4272 }
4273 }
4274
4275 static const char*
out_movsi_r_mr(rtx_insn * insn,rtx op[],int * l)4276 out_movsi_r_mr (rtx_insn *insn, rtx op[], int *l)
4277 {
4278 rtx dest = op[0];
4279 rtx src = op[1];
4280 rtx base = XEXP (src, 0);
4281 int reg_dest = true_regnum (dest);
4282 int reg_base = true_regnum (base);
4283 int tmp;
4284
4285 if (!l)
4286 l = &tmp;
4287
4288 if (reg_base > 0)
4289 {
4290 if (AVR_TINY)
4291 return avr_out_movsi_r_mr_reg_no_disp_tiny (insn, op, l);
4292
4293 if (reg_base == REG_X) /* (R26) */
4294 {
4295 if (reg_dest == REG_X)
4296 /* "ld r26,-X" is undefined */
4297 return *l=7, ("adiw r26,3" CR_TAB
4298 "ld r29,X" CR_TAB
4299 "ld r28,-X" CR_TAB
4300 "ld __tmp_reg__,-X" CR_TAB
4301 "sbiw r26,1" CR_TAB
4302 "ld r26,X" CR_TAB
4303 "mov r27,__tmp_reg__");
4304 else if (reg_dest == REG_X - 2)
4305 return *l=5, ("ld %A0,X+" CR_TAB
4306 "ld %B0,X+" CR_TAB
4307 "ld __tmp_reg__,X+" CR_TAB
4308 "ld %D0,X" CR_TAB
4309 "mov %C0,__tmp_reg__");
4310 else if (reg_unused_after (insn, base))
4311 return *l=4, ("ld %A0,X+" CR_TAB
4312 "ld %B0,X+" CR_TAB
4313 "ld %C0,X+" CR_TAB
4314 "ld %D0,X");
4315 else
4316 return *l=5, ("ld %A0,X+" CR_TAB
4317 "ld %B0,X+" CR_TAB
4318 "ld %C0,X+" CR_TAB
4319 "ld %D0,X" CR_TAB
4320 "sbiw r26,3");
4321 }
4322 else
4323 {
4324 if (reg_dest == reg_base)
4325 return *l=5, ("ldd %D0,%1+3" CR_TAB
4326 "ldd %C0,%1+2" CR_TAB
4327 "ldd __tmp_reg__,%1+1" CR_TAB
4328 "ld %A0,%1" CR_TAB
4329 "mov %B0,__tmp_reg__");
4330 else if (reg_base == reg_dest + 2)
4331 return *l=5, ("ld %A0,%1" CR_TAB
4332 "ldd %B0,%1+1" CR_TAB
4333 "ldd __tmp_reg__,%1+2" CR_TAB
4334 "ldd %D0,%1+3" CR_TAB
4335 "mov %C0,__tmp_reg__");
4336 else
4337 return *l=4, ("ld %A0,%1" CR_TAB
4338 "ldd %B0,%1+1" CR_TAB
4339 "ldd %C0,%1+2" CR_TAB
4340 "ldd %D0,%1+3");
4341 }
4342 }
4343 else if (GET_CODE (base) == PLUS) /* (R + i) */
4344 {
4345 int disp = INTVAL (XEXP (base, 1));
4346
4347 if (AVR_TINY)
4348 return avr_out_movsi_r_mr_reg_disp_tiny (insn, op, l);
4349
4350 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
4351 {
4352 if (REGNO (XEXP (base, 0)) != REG_Y)
4353 fatal_insn ("incorrect insn:",insn);
4354
4355 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
4356 return *l = 6, ("adiw r28,%o1-60" CR_TAB
4357 "ldd %A0,Y+60" CR_TAB
4358 "ldd %B0,Y+61" CR_TAB
4359 "ldd %C0,Y+62" CR_TAB
4360 "ldd %D0,Y+63" CR_TAB
4361 "sbiw r28,%o1-60");
4362
4363 return *l = 8, ("subi r28,lo8(-%o1)" CR_TAB
4364 "sbci r29,hi8(-%o1)" CR_TAB
4365 "ld %A0,Y" CR_TAB
4366 "ldd %B0,Y+1" CR_TAB
4367 "ldd %C0,Y+2" CR_TAB
4368 "ldd %D0,Y+3" CR_TAB
4369 "subi r28,lo8(%o1)" CR_TAB
4370 "sbci r29,hi8(%o1)");
4371 }
4372
4373 reg_base = true_regnum (XEXP (base, 0));
4374 if (reg_base == REG_X)
4375 {
4376 /* R = (X + d) */
4377 if (reg_dest == REG_X)
4378 {
4379 *l = 7;
4380 /* "ld r26,-X" is undefined */
4381 return ("adiw r26,%o1+3" CR_TAB
4382 "ld r29,X" CR_TAB
4383 "ld r28,-X" CR_TAB
4384 "ld __tmp_reg__,-X" CR_TAB
4385 "sbiw r26,1" CR_TAB
4386 "ld r26,X" CR_TAB
4387 "mov r27,__tmp_reg__");
4388 }
4389 *l = 6;
4390 if (reg_dest == REG_X - 2)
4391 return ("adiw r26,%o1" CR_TAB
4392 "ld r24,X+" CR_TAB
4393 "ld r25,X+" CR_TAB
4394 "ld __tmp_reg__,X+" CR_TAB
4395 "ld r27,X" CR_TAB
4396 "mov r26,__tmp_reg__");
4397
4398 return ("adiw r26,%o1" CR_TAB
4399 "ld %A0,X+" CR_TAB
4400 "ld %B0,X+" CR_TAB
4401 "ld %C0,X+" CR_TAB
4402 "ld %D0,X" CR_TAB
4403 "sbiw r26,%o1+3");
4404 }
4405 if (reg_dest == reg_base)
4406 return *l=5, ("ldd %D0,%D1" CR_TAB
4407 "ldd %C0,%C1" CR_TAB
4408 "ldd __tmp_reg__,%B1" CR_TAB
4409 "ldd %A0,%A1" CR_TAB
4410 "mov %B0,__tmp_reg__");
4411 else if (reg_dest == reg_base - 2)
4412 return *l=5, ("ldd %A0,%A1" CR_TAB
4413 "ldd %B0,%B1" CR_TAB
4414 "ldd __tmp_reg__,%C1" CR_TAB
4415 "ldd %D0,%D1" CR_TAB
4416 "mov %C0,__tmp_reg__");
4417 return *l=4, ("ldd %A0,%A1" CR_TAB
4418 "ldd %B0,%B1" CR_TAB
4419 "ldd %C0,%C1" CR_TAB
4420 "ldd %D0,%D1");
4421 }
4422 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4423 return *l=4, ("ld %D0,%1" CR_TAB
4424 "ld %C0,%1" CR_TAB
4425 "ld %B0,%1" CR_TAB
4426 "ld %A0,%1");
4427 else if (GET_CODE (base) == POST_INC) /* (R++) */
4428 return *l=4, ("ld %A0,%1" CR_TAB
4429 "ld %B0,%1" CR_TAB
4430 "ld %C0,%1" CR_TAB
4431 "ld %D0,%1");
4432 else if (CONSTANT_ADDRESS_P (base))
4433 {
4434 if (io_address_operand (base, SImode))
4435 {
4436 *l = 4;
4437 return ("in %A0,%i1" CR_TAB
4438 "in %B0,%i1+1" CR_TAB
4439 "in %C0,%i1+2" CR_TAB
4440 "in %D0,%i1+3");
4441 }
4442 else
4443 {
4444 *l = AVR_TINY ? 4 : 8;
4445 return ("lds %A0,%m1" CR_TAB
4446 "lds %B0,%m1+1" CR_TAB
4447 "lds %C0,%m1+2" CR_TAB
4448 "lds %D0,%m1+3");
4449 }
4450 }
4451
4452 fatal_insn ("unknown move insn:",insn);
4453 return "";
4454 }
4455
4456 static const char*
avr_out_movsi_mr_r_reg_no_disp_tiny(rtx_insn * insn,rtx op[],int * l)4457 avr_out_movsi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *l)
4458 {
4459 rtx dest = op[0];
4460 rtx src = op[1];
4461 rtx base = XEXP (dest, 0);
4462 int reg_base = true_regnum (base);
4463 int reg_src = true_regnum (src);
4464
4465 if (reg_base == reg_src)
4466 {
4467 /* "ld r26,-X" is undefined */
4468 if (reg_unused_after (insn, base))
4469 {
4470 return *l = 7, ("mov __tmp_reg__, %B1" CR_TAB
4471 "st %0,%A1" CR_TAB
4472 TINY_ADIW (%E0, %F0, 1) CR_TAB
4473 "st %0+,__tmp_reg__" CR_TAB
4474 "st %0+,%C1" CR_TAB
4475 "st %0+,%D1");
4476 }
4477 else
4478 {
4479 return *l = 9, ("mov __tmp_reg__, %B1" CR_TAB
4480 "st %0,%A1" CR_TAB
4481 TINY_ADIW (%E0, %F0, 1) CR_TAB
4482 "st %0+,__tmp_reg__" CR_TAB
4483 "st %0+,%C1" CR_TAB
4484 "st %0+,%D1" CR_TAB
4485 TINY_SBIW (%E0, %F0, 3));
4486 }
4487 }
4488 else if (reg_base == reg_src + 2)
4489 {
4490 if (reg_unused_after (insn, base))
4491 return *l = 7, ("mov __zero_reg__,%C1" CR_TAB
4492 "mov __tmp_reg__,%D1" CR_TAB
4493 "st %0+,%A1" CR_TAB
4494 "st %0+,%B1" CR_TAB
4495 "st %0+,__zero_reg__" CR_TAB
4496 "st %0,__tmp_reg__" CR_TAB
4497 "clr __zero_reg__");
4498 else
4499 return *l = 9, ("mov __zero_reg__,%C1" CR_TAB
4500 "mov __tmp_reg__,%D1" CR_TAB
4501 "st %0+,%A1" CR_TAB
4502 "st %0+,%B1" CR_TAB
4503 "st %0+,__zero_reg__" CR_TAB
4504 "st %0,__tmp_reg__" CR_TAB
4505 "clr __zero_reg__" CR_TAB
4506 TINY_SBIW (%E0, %F0, 3));
4507 }
4508
4509 return *l = 6, ("st %0+,%A1" CR_TAB
4510 "st %0+,%B1" CR_TAB
4511 "st %0+,%C1" CR_TAB
4512 "st %0,%D1" CR_TAB
4513 TINY_SBIW (%E0, %F0, 3));
4514 }
4515
4516 static const char*
avr_out_movsi_mr_r_reg_disp_tiny(rtx op[],int * l)4517 avr_out_movsi_mr_r_reg_disp_tiny (rtx op[], int *l)
4518 {
4519 rtx dest = op[0];
4520 rtx src = op[1];
4521 rtx base = XEXP (dest, 0);
4522 int reg_base = REGNO (XEXP (base, 0));
4523 int reg_src =true_regnum (src);
4524
4525 if (reg_base == reg_src)
4526 {
4527 *l = 11;
4528 return ("mov __tmp_reg__,%A2" CR_TAB
4529 "mov __zero_reg__,%B2" CR_TAB
4530 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4531 "st %b0+,__tmp_reg__" CR_TAB
4532 "st %b0+,__zero_reg__" CR_TAB
4533 "st %b0+,%C2" CR_TAB
4534 "st %b0,%D2" CR_TAB
4535 "clr __zero_reg__" CR_TAB
4536 TINY_SBIW (%I0, %J0, %o0+3));
4537 }
4538 else if (reg_src == reg_base - 2)
4539 {
4540 *l = 11;
4541 return ("mov __tmp_reg__,%C2" CR_TAB
4542 "mov __zero_reg__,%D2" CR_TAB
4543 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4544 "st %b0+,%A0" CR_TAB
4545 "st %b0+,%B0" CR_TAB
4546 "st %b0+,__tmp_reg__" CR_TAB
4547 "st %b0,__zero_reg__" CR_TAB
4548 "clr __zero_reg__" CR_TAB
4549 TINY_SBIW (%I0, %J0, %o0+3));
4550 }
4551 *l = 8;
4552 return (TINY_ADIW (%I0, %J0, %o0) CR_TAB
4553 "st %b0+,%A1" CR_TAB
4554 "st %b0+,%B1" CR_TAB
4555 "st %b0+,%C1" CR_TAB
4556 "st %b0,%D1" CR_TAB
4557 TINY_SBIW (%I0, %J0, %o0+3));
4558 }
4559
4560 static const char*
out_movsi_mr_r(rtx_insn * insn,rtx op[],int * l)4561 out_movsi_mr_r (rtx_insn *insn, rtx op[], int *l)
4562 {
4563 rtx dest = op[0];
4564 rtx src = op[1];
4565 rtx base = XEXP (dest, 0);
4566 int reg_base = true_regnum (base);
4567 int reg_src = true_regnum (src);
4568 int tmp;
4569
4570 if (!l)
4571 l = &tmp;
4572
4573 if (CONSTANT_ADDRESS_P (base))
4574 {
4575 if (io_address_operand (base, SImode))
4576 {
4577 return *l=4,("out %i0, %A1" CR_TAB
4578 "out %i0+1,%B1" CR_TAB
4579 "out %i0+2,%C1" CR_TAB
4580 "out %i0+3,%D1");
4581 }
4582 else
4583 {
4584 *l = AVR_TINY ? 4 : 8;
4585 return ("sts %m0,%A1" CR_TAB
4586 "sts %m0+1,%B1" CR_TAB
4587 "sts %m0+2,%C1" CR_TAB
4588 "sts %m0+3,%D1");
4589 }
4590 }
4591
4592 if (reg_base > 0) /* (r) */
4593 {
4594 if (AVR_TINY)
4595 return avr_out_movsi_mr_r_reg_no_disp_tiny (insn, op, l);
4596
4597 if (reg_base == REG_X) /* (R26) */
4598 {
4599 if (reg_src == REG_X)
4600 {
4601 /* "st X+,r26" is undefined */
4602 if (reg_unused_after (insn, base))
4603 return *l=6, ("mov __tmp_reg__,r27" CR_TAB
4604 "st X,r26" CR_TAB
4605 "adiw r26,1" CR_TAB
4606 "st X+,__tmp_reg__" CR_TAB
4607 "st X+,r28" CR_TAB
4608 "st X,r29");
4609 else
4610 return *l=7, ("mov __tmp_reg__,r27" CR_TAB
4611 "st X,r26" CR_TAB
4612 "adiw r26,1" CR_TAB
4613 "st X+,__tmp_reg__" CR_TAB
4614 "st X+,r28" CR_TAB
4615 "st X,r29" CR_TAB
4616 "sbiw r26,3");
4617 }
4618 else if (reg_base == reg_src + 2)
4619 {
4620 if (reg_unused_after (insn, base))
4621 return *l=7, ("mov __zero_reg__,%C1" CR_TAB
4622 "mov __tmp_reg__,%D1" CR_TAB
4623 "st %0+,%A1" CR_TAB
4624 "st %0+,%B1" CR_TAB
4625 "st %0+,__zero_reg__" CR_TAB
4626 "st %0,__tmp_reg__" CR_TAB
4627 "clr __zero_reg__");
4628 else
4629 return *l=8, ("mov __zero_reg__,%C1" CR_TAB
4630 "mov __tmp_reg__,%D1" CR_TAB
4631 "st %0+,%A1" CR_TAB
4632 "st %0+,%B1" CR_TAB
4633 "st %0+,__zero_reg__" CR_TAB
4634 "st %0,__tmp_reg__" CR_TAB
4635 "clr __zero_reg__" CR_TAB
4636 "sbiw r26,3");
4637 }
4638 return *l=5, ("st %0+,%A1" CR_TAB
4639 "st %0+,%B1" CR_TAB
4640 "st %0+,%C1" CR_TAB
4641 "st %0,%D1" CR_TAB
4642 "sbiw r26,3");
4643 }
4644 else
4645 return *l=4, ("st %0,%A1" CR_TAB
4646 "std %0+1,%B1" CR_TAB
4647 "std %0+2,%C1" CR_TAB
4648 "std %0+3,%D1");
4649 }
4650 else if (GET_CODE (base) == PLUS) /* (R + i) */
4651 {
4652 int disp = INTVAL (XEXP (base, 1));
4653
4654 if (AVR_TINY)
4655 return avr_out_movsi_mr_r_reg_disp_tiny (op, l);
4656
4657 reg_base = REGNO (XEXP (base, 0));
4658 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
4659 {
4660 if (reg_base != REG_Y)
4661 fatal_insn ("incorrect insn:",insn);
4662
4663 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
4664 return *l = 6, ("adiw r28,%o0-60" CR_TAB
4665 "std Y+60,%A1" CR_TAB
4666 "std Y+61,%B1" CR_TAB
4667 "std Y+62,%C1" CR_TAB
4668 "std Y+63,%D1" CR_TAB
4669 "sbiw r28,%o0-60");
4670
4671 return *l = 8, ("subi r28,lo8(-%o0)" CR_TAB
4672 "sbci r29,hi8(-%o0)" CR_TAB
4673 "st Y,%A1" CR_TAB
4674 "std Y+1,%B1" CR_TAB
4675 "std Y+2,%C1" CR_TAB
4676 "std Y+3,%D1" CR_TAB
4677 "subi r28,lo8(%o0)" CR_TAB
4678 "sbci r29,hi8(%o0)");
4679 }
4680 if (reg_base == REG_X)
4681 {
4682 /* (X + d) = R */
4683 if (reg_src == REG_X)
4684 {
4685 *l = 9;
4686 return ("mov __tmp_reg__,r26" CR_TAB
4687 "mov __zero_reg__,r27" CR_TAB
4688 "adiw r26,%o0" CR_TAB
4689 "st X+,__tmp_reg__" CR_TAB
4690 "st X+,__zero_reg__" CR_TAB
4691 "st X+,r28" CR_TAB
4692 "st X,r29" CR_TAB
4693 "clr __zero_reg__" CR_TAB
4694 "sbiw r26,%o0+3");
4695 }
4696 else if (reg_src == REG_X - 2)
4697 {
4698 *l = 9;
4699 return ("mov __tmp_reg__,r26" CR_TAB
4700 "mov __zero_reg__,r27" CR_TAB
4701 "adiw r26,%o0" CR_TAB
4702 "st X+,r24" CR_TAB
4703 "st X+,r25" CR_TAB
4704 "st X+,__tmp_reg__" CR_TAB
4705 "st X,__zero_reg__" CR_TAB
4706 "clr __zero_reg__" CR_TAB
4707 "sbiw r26,%o0+3");
4708 }
4709 *l = 6;
4710 return ("adiw r26,%o0" CR_TAB
4711 "st X+,%A1" CR_TAB
4712 "st X+,%B1" CR_TAB
4713 "st X+,%C1" CR_TAB
4714 "st X,%D1" CR_TAB
4715 "sbiw r26,%o0+3");
4716 }
4717 return *l=4, ("std %A0,%A1" CR_TAB
4718 "std %B0,%B1" CR_TAB
4719 "std %C0,%C1" CR_TAB
4720 "std %D0,%D1");
4721 }
4722 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4723 return *l=4, ("st %0,%D1" CR_TAB
4724 "st %0,%C1" CR_TAB
4725 "st %0,%B1" CR_TAB
4726 "st %0,%A1");
4727 else if (GET_CODE (base) == POST_INC) /* (R++) */
4728 return *l=4, ("st %0,%A1" CR_TAB
4729 "st %0,%B1" CR_TAB
4730 "st %0,%C1" CR_TAB
4731 "st %0,%D1");
4732 fatal_insn ("unknown move insn:",insn);
4733 return "";
4734 }
4735
4736 const char *
output_movsisf(rtx_insn * insn,rtx operands[],int * l)4737 output_movsisf (rtx_insn *insn, rtx operands[], int *l)
4738 {
4739 int dummy;
4740 rtx dest = operands[0];
4741 rtx src = operands[1];
4742 int *real_l = l;
4743
4744 if (avr_mem_flash_p (src)
4745 || avr_mem_flash_p (dest))
4746 {
4747 return avr_out_lpm (insn, operands, real_l);
4748 }
4749
4750 if (!l)
4751 l = &dummy;
4752
4753 gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 4);
4754
4755 if (REG_P (dest))
4756 {
4757 if (REG_P (src)) /* mov r,r */
4758 {
4759 if (true_regnum (dest) > true_regnum (src))
4760 {
4761 if (AVR_HAVE_MOVW)
4762 {
4763 *l = 2;
4764 return ("movw %C0,%C1" CR_TAB
4765 "movw %A0,%A1");
4766 }
4767 *l = 4;
4768 return ("mov %D0,%D1" CR_TAB
4769 "mov %C0,%C1" CR_TAB
4770 "mov %B0,%B1" CR_TAB
4771 "mov %A0,%A1");
4772 }
4773 else
4774 {
4775 if (AVR_HAVE_MOVW)
4776 {
4777 *l = 2;
4778 return ("movw %A0,%A1" CR_TAB
4779 "movw %C0,%C1");
4780 }
4781 *l = 4;
4782 return ("mov %A0,%A1" CR_TAB
4783 "mov %B0,%B1" CR_TAB
4784 "mov %C0,%C1" CR_TAB
4785 "mov %D0,%D1");
4786 }
4787 }
4788 else if (CONSTANT_P (src))
4789 {
4790 return output_reload_insisf (operands, NULL_RTX, real_l);
4791 }
4792 else if (MEM_P (src))
4793 return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
4794 }
4795 else if (MEM_P (dest))
4796 {
4797 const char *templ;
4798
4799 if (src == CONST0_RTX (GET_MODE (dest)))
4800 operands[1] = zero_reg_rtx;
4801
4802 templ = out_movsi_mr_r (insn, operands, real_l);
4803
4804 if (!real_l)
4805 output_asm_insn (templ, operands);
4806
4807 operands[1] = src;
4808 return "";
4809 }
4810 fatal_insn ("invalid insn:", insn);
4811 return "";
4812 }
4813
4814
4815 /* Handle loads of 24-bit types from memory to register. */
4816
4817 static const char*
avr_out_load_psi_reg_no_disp_tiny(rtx_insn * insn,rtx * op,int * plen)4818 avr_out_load_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
4819 {
4820 rtx dest = op[0];
4821 rtx src = op[1];
4822 rtx base = XEXP (src, 0);
4823 int reg_dest = true_regnum (dest);
4824 int reg_base = true_regnum (base);
4825
4826 if (reg_base == reg_dest)
4827 {
4828 return avr_asm_len (TINY_ADIW (%E1, %F1, 2) CR_TAB
4829 "ld %C0,%1" CR_TAB
4830 "ld __tmp_reg__,-%1" CR_TAB
4831 TINY_SBIW (%E1, %F1, 1) CR_TAB
4832 "ld %A0,%1" CR_TAB
4833 "mov %B0,__tmp_reg__", op, plen, -8);
4834 }
4835 else
4836 {
4837 avr_asm_len ("ld %A0,%1+" CR_TAB
4838 "ld %B0,%1+" CR_TAB
4839 "ld %C0,%1", op, plen, -3);
4840
4841 if (reg_dest != reg_base - 2
4842 && !reg_unused_after (insn, base))
4843 {
4844 avr_asm_len (TINY_SBIW (%E1, %F1, 2), op, plen, 2);
4845 }
4846 return "";
4847 }
4848 }
4849
4850 static const char*
avr_out_load_psi_reg_disp_tiny(rtx_insn * insn,rtx * op,int * plen)4851 avr_out_load_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
4852 {
4853 rtx dest = op[0];
4854 rtx src = op[1];
4855 rtx base = XEXP (src, 0);
4856 int reg_dest = true_regnum (dest);
4857 int reg_base = true_regnum (base);
4858
4859 reg_base = true_regnum (XEXP (base, 0));
4860 if (reg_base == reg_dest)
4861 {
4862 return avr_asm_len (TINY_ADIW (%I1, %J1, %o1+2) CR_TAB
4863 "ld %C0,%b1" CR_TAB
4864 "ld __tmp_reg__,-%b1" CR_TAB
4865 TINY_SBIW (%I1, %J1, 1) CR_TAB
4866 "ld %A0,%b1" CR_TAB
4867 "mov %B0,__tmp_reg__", op, plen, -8);
4868 }
4869 else
4870 {
4871 avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4872 "ld %A0,%b1+" CR_TAB
4873 "ld %B0,%b1+" CR_TAB
4874 "ld %C0,%b1", op, plen, -5);
4875
4876 if (reg_dest != reg_base - 2
4877 && !reg_unused_after (insn, XEXP (base, 0)))
4878 avr_asm_len (TINY_SBIW (%I1, %J1, %o1+2), op, plen, 2);
4879
4880 return "";
4881 }
4882 }
4883
4884 static const char*
avr_out_load_psi(rtx_insn * insn,rtx * op,int * plen)4885 avr_out_load_psi (rtx_insn *insn, rtx *op, int *plen)
4886 {
4887 rtx dest = op[0];
4888 rtx src = op[1];
4889 rtx base = XEXP (src, 0);
4890 int reg_dest = true_regnum (dest);
4891 int reg_base = true_regnum (base);
4892
4893 if (reg_base > 0)
4894 {
4895 if (AVR_TINY)
4896 return avr_out_load_psi_reg_no_disp_tiny (insn, op, plen);
4897
4898 if (reg_base == REG_X) /* (R26) */
4899 {
4900 if (reg_dest == REG_X)
4901 /* "ld r26,-X" is undefined */
4902 return avr_asm_len ("adiw r26,2" CR_TAB
4903 "ld r28,X" CR_TAB
4904 "ld __tmp_reg__,-X" CR_TAB
4905 "sbiw r26,1" CR_TAB
4906 "ld r26,X" CR_TAB
4907 "mov r27,__tmp_reg__", op, plen, -6);
4908 else
4909 {
4910 avr_asm_len ("ld %A0,X+" CR_TAB
4911 "ld %B0,X+" CR_TAB
4912 "ld %C0,X", op, plen, -3);
4913
4914 if (reg_dest != REG_X - 2
4915 && !reg_unused_after (insn, base))
4916 {
4917 avr_asm_len ("sbiw r26,2", op, plen, 1);
4918 }
4919
4920 return "";
4921 }
4922 }
4923 else /* reg_base != REG_X */
4924 {
4925 if (reg_dest == reg_base)
4926 return avr_asm_len ("ldd %C0,%1+2" CR_TAB
4927 "ldd __tmp_reg__,%1+1" CR_TAB
4928 "ld %A0,%1" CR_TAB
4929 "mov %B0,__tmp_reg__", op, plen, -4);
4930 else
4931 return avr_asm_len ("ld %A0,%1" CR_TAB
4932 "ldd %B0,%1+1" CR_TAB
4933 "ldd %C0,%1+2", op, plen, -3);
4934 }
4935 }
4936 else if (GET_CODE (base) == PLUS) /* (R + i) */
4937 {
4938 int disp = INTVAL (XEXP (base, 1));
4939
4940 if (AVR_TINY)
4941 return avr_out_load_psi_reg_disp_tiny (insn, op, plen);
4942
4943 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
4944 {
4945 if (REGNO (XEXP (base, 0)) != REG_Y)
4946 fatal_insn ("incorrect insn:",insn);
4947
4948 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
4949 return avr_asm_len ("adiw r28,%o1-61" CR_TAB
4950 "ldd %A0,Y+61" CR_TAB
4951 "ldd %B0,Y+62" CR_TAB
4952 "ldd %C0,Y+63" CR_TAB
4953 "sbiw r28,%o1-61", op, plen, -5);
4954
4955 return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
4956 "sbci r29,hi8(-%o1)" CR_TAB
4957 "ld %A0,Y" CR_TAB
4958 "ldd %B0,Y+1" CR_TAB
4959 "ldd %C0,Y+2" CR_TAB
4960 "subi r28,lo8(%o1)" CR_TAB
4961 "sbci r29,hi8(%o1)", op, plen, -7);
4962 }
4963
4964 reg_base = true_regnum (XEXP (base, 0));
4965 if (reg_base == REG_X)
4966 {
4967 /* R = (X + d) */
4968 if (reg_dest == REG_X)
4969 {
4970 /* "ld r26,-X" is undefined */
4971 return avr_asm_len ("adiw r26,%o1+2" CR_TAB
4972 "ld r28,X" CR_TAB
4973 "ld __tmp_reg__,-X" CR_TAB
4974 "sbiw r26,1" CR_TAB
4975 "ld r26,X" CR_TAB
4976 "mov r27,__tmp_reg__", op, plen, -6);
4977 }
4978
4979 avr_asm_len ("adiw r26,%o1" CR_TAB
4980 "ld %A0,X+" CR_TAB
4981 "ld %B0,X+" CR_TAB
4982 "ld %C0,X", op, plen, -4);
4983
4984 if (reg_dest != REG_W
4985 && !reg_unused_after (insn, XEXP (base, 0)))
4986 avr_asm_len ("sbiw r26,%o1+2", op, plen, 1);
4987
4988 return "";
4989 }
4990
4991 if (reg_dest == reg_base)
4992 return avr_asm_len ("ldd %C0,%C1" CR_TAB
4993 "ldd __tmp_reg__,%B1" CR_TAB
4994 "ldd %A0,%A1" CR_TAB
4995 "mov %B0,__tmp_reg__", op, plen, -4);
4996
4997 return avr_asm_len ("ldd %A0,%A1" CR_TAB
4998 "ldd %B0,%B1" CR_TAB
4999 "ldd %C0,%C1", op, plen, -3);
5000 }
5001 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5002 return avr_asm_len ("ld %C0,%1" CR_TAB
5003 "ld %B0,%1" CR_TAB
5004 "ld %A0,%1", op, plen, -3);
5005 else if (GET_CODE (base) == POST_INC) /* (R++) */
5006 return avr_asm_len ("ld %A0,%1" CR_TAB
5007 "ld %B0,%1" CR_TAB
5008 "ld %C0,%1", op, plen, -3);
5009
5010 else if (CONSTANT_ADDRESS_P (base))
5011 {
5012 int n_words = AVR_TINY ? 3 : 6;
5013 return avr_asm_len ("lds %A0,%m1" CR_TAB
5014 "lds %B0,%m1+1" CR_TAB
5015 "lds %C0,%m1+2", op, plen , -n_words);
5016 }
5017
5018 fatal_insn ("unknown move insn:",insn);
5019 return "";
5020 }
5021
5022
5023 static const char*
avr_out_store_psi_reg_no_disp_tiny(rtx_insn * insn,rtx * op,int * plen)5024 avr_out_store_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
5025 {
5026 rtx dest = op[0];
5027 rtx src = op[1];
5028 rtx base = XEXP (dest, 0);
5029 int reg_base = true_regnum (base);
5030 int reg_src = true_regnum (src);
5031
5032 if (reg_base == reg_src)
5033 {
5034 avr_asm_len ("st %0,%A1" CR_TAB
5035 "mov __tmp_reg__,%B1" CR_TAB
5036 TINY_ADIW (%E0, %F0, 1) CR_TAB /* st X+, r27 is undefined */
5037 "st %0+,__tmp_reg__" CR_TAB
5038 "st %0,%C1", op, plen, -6);
5039
5040 }
5041 else if (reg_src == reg_base - 2)
5042 {
5043 avr_asm_len ("st %0,%A1" CR_TAB
5044 "mov __tmp_reg__,%C1" CR_TAB
5045 TINY_ADIW (%E0, %F0, 1) CR_TAB
5046 "st %0+,%B1" CR_TAB
5047 "st %0,__tmp_reg__", op, plen, 6);
5048 }
5049 else
5050 {
5051 avr_asm_len ("st %0+,%A1" CR_TAB
5052 "st %0+,%B1" CR_TAB
5053 "st %0,%C1", op, plen, -3);
5054 }
5055
5056 if (!reg_unused_after (insn, base))
5057 avr_asm_len (TINY_SBIW (%E0, %F0, 2), op, plen, 2);
5058
5059 return "";
5060 }
5061
5062 static const char*
avr_out_store_psi_reg_disp_tiny(rtx_insn * insn,rtx * op,int * plen)5063 avr_out_store_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
5064 {
5065 rtx dest = op[0];
5066 rtx src = op[1];
5067 rtx base = XEXP (dest, 0);
5068 int reg_base = REGNO (XEXP (base, 0));
5069 int reg_src = true_regnum (src);
5070
5071 if (reg_src == reg_base)
5072 avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
5073 "mov __zero_reg__,%B1" CR_TAB
5074 TINY_ADIW (%I0, %J0, %o0) CR_TAB
5075 "st %b0+,__tmp_reg__" CR_TAB
5076 "st %b0+,__zero_reg__" CR_TAB
5077 "st %b0,%C1" CR_TAB
5078 "clr __zero_reg__", op, plen, -8);
5079 else if (reg_src == reg_base - 2)
5080 avr_asm_len ("mov __tmp_reg__,%C1" CR_TAB
5081 TINY_ADIW (%I0, %J0, %o0) CR_TAB
5082 "st %b0+,%A1" CR_TAB
5083 "st %b0+,%B1" CR_TAB
5084 "st %b0,__tmp_reg__", op, plen, -6);
5085 else
5086 avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
5087 "st %b0+,%A1" CR_TAB
5088 "st %b0+,%B1" CR_TAB
5089 "st %b0,%C1", op, plen, -5);
5090
5091 if (!reg_unused_after (insn, XEXP (base, 0)))
5092 avr_asm_len (TINY_SBIW (%I0, %J0, %o0+2), op, plen, 2);
5093
5094 return "";
5095 }
5096
5097 /* Handle store of 24-bit type from register or zero to memory. */
5098
5099 static const char*
avr_out_store_psi(rtx_insn * insn,rtx * op,int * plen)5100 avr_out_store_psi (rtx_insn *insn, rtx *op, int *plen)
5101 {
5102 rtx dest = op[0];
5103 rtx src = op[1];
5104 rtx base = XEXP (dest, 0);
5105 int reg_base = true_regnum (base);
5106
5107 if (CONSTANT_ADDRESS_P (base))
5108 {
5109 int n_words = AVR_TINY ? 3 : 6;
5110 return avr_asm_len ("sts %m0,%A1" CR_TAB
5111 "sts %m0+1,%B1" CR_TAB
5112 "sts %m0+2,%C1", op, plen, -n_words);
5113 }
5114
5115 if (reg_base > 0) /* (r) */
5116 {
5117 if (AVR_TINY)
5118 return avr_out_store_psi_reg_no_disp_tiny (insn, op, plen);
5119
5120 if (reg_base == REG_X) /* (R26) */
5121 {
5122 gcc_assert (!reg_overlap_mentioned_p (base, src));
5123
5124 avr_asm_len ("st %0+,%A1" CR_TAB
5125 "st %0+,%B1" CR_TAB
5126 "st %0,%C1", op, plen, -3);
5127
5128 if (!reg_unused_after (insn, base))
5129 avr_asm_len ("sbiw r26,2", op, plen, 1);
5130
5131 return "";
5132 }
5133 else
5134 return avr_asm_len ("st %0,%A1" CR_TAB
5135 "std %0+1,%B1" CR_TAB
5136 "std %0+2,%C1", op, plen, -3);
5137 }
5138 else if (GET_CODE (base) == PLUS) /* (R + i) */
5139 {
5140 int disp = INTVAL (XEXP (base, 1));
5141
5142 if (AVR_TINY)
5143 return avr_out_store_psi_reg_disp_tiny (insn, op, plen);
5144
5145 reg_base = REGNO (XEXP (base, 0));
5146
5147 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5148 {
5149 if (reg_base != REG_Y)
5150 fatal_insn ("incorrect insn:",insn);
5151
5152 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
5153 return avr_asm_len ("adiw r28,%o0-61" CR_TAB
5154 "std Y+61,%A1" CR_TAB
5155 "std Y+62,%B1" CR_TAB
5156 "std Y+63,%C1" CR_TAB
5157 "sbiw r28,%o0-61", op, plen, -5);
5158
5159 return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5160 "sbci r29,hi8(-%o0)" CR_TAB
5161 "st Y,%A1" CR_TAB
5162 "std Y+1,%B1" CR_TAB
5163 "std Y+2,%C1" CR_TAB
5164 "subi r28,lo8(%o0)" CR_TAB
5165 "sbci r29,hi8(%o0)", op, plen, -7);
5166 }
5167 if (reg_base == REG_X)
5168 {
5169 /* (X + d) = R */
5170 gcc_assert (!reg_overlap_mentioned_p (XEXP (base, 0), src));
5171
5172 avr_asm_len ("adiw r26,%o0" CR_TAB
5173 "st X+,%A1" CR_TAB
5174 "st X+,%B1" CR_TAB
5175 "st X,%C1", op, plen, -4);
5176
5177 if (!reg_unused_after (insn, XEXP (base, 0)))
5178 avr_asm_len ("sbiw r26,%o0+2", op, plen, 1);
5179
5180 return "";
5181 }
5182
5183 return avr_asm_len ("std %A0,%A1" CR_TAB
5184 "std %B0,%B1" CR_TAB
5185 "std %C0,%C1", op, plen, -3);
5186 }
5187 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5188 return avr_asm_len ("st %0,%C1" CR_TAB
5189 "st %0,%B1" CR_TAB
5190 "st %0,%A1", op, plen, -3);
5191 else if (GET_CODE (base) == POST_INC) /* (R++) */
5192 return avr_asm_len ("st %0,%A1" CR_TAB
5193 "st %0,%B1" CR_TAB
5194 "st %0,%C1", op, plen, -3);
5195
5196 fatal_insn ("unknown move insn:",insn);
5197 return "";
5198 }
5199
5200
5201 /* Move around 24-bit stuff. */
5202
5203 const char *
avr_out_movpsi(rtx_insn * insn,rtx * op,int * plen)5204 avr_out_movpsi (rtx_insn *insn, rtx *op, int *plen)
5205 {
5206 rtx dest = op[0];
5207 rtx src = op[1];
5208
5209 if (avr_mem_flash_p (src)
5210 || avr_mem_flash_p (dest))
5211 {
5212 return avr_out_lpm (insn, op, plen);
5213 }
5214
5215 if (register_operand (dest, VOIDmode))
5216 {
5217 if (register_operand (src, VOIDmode)) /* mov r,r */
5218 {
5219 if (true_regnum (dest) > true_regnum (src))
5220 {
5221 avr_asm_len ("mov %C0,%C1", op, plen, -1);
5222
5223 if (AVR_HAVE_MOVW)
5224 return avr_asm_len ("movw %A0,%A1", op, plen, 1);
5225 else
5226 return avr_asm_len ("mov %B0,%B1" CR_TAB
5227 "mov %A0,%A1", op, plen, 2);
5228 }
5229 else
5230 {
5231 if (AVR_HAVE_MOVW)
5232 avr_asm_len ("movw %A0,%A1", op, plen, -1);
5233 else
5234 avr_asm_len ("mov %A0,%A1" CR_TAB
5235 "mov %B0,%B1", op, plen, -2);
5236
5237 return avr_asm_len ("mov %C0,%C1", op, plen, 1);
5238 }
5239 }
5240 else if (CONSTANT_P (src))
5241 {
5242 return avr_out_reload_inpsi (op, NULL_RTX, plen);
5243 }
5244 else if (MEM_P (src))
5245 return avr_out_load_psi (insn, op, plen); /* mov r,m */
5246 }
5247 else if (MEM_P (dest))
5248 {
5249 rtx xop[2];
5250
5251 xop[0] = dest;
5252 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
5253
5254 return avr_out_store_psi (insn, xop, plen);
5255 }
5256
5257 fatal_insn ("invalid insn:", insn);
5258 return "";
5259 }
5260
5261 static const char*
avr_out_movqi_mr_r_reg_disp_tiny(rtx_insn * insn,rtx op[],int * plen)5262 avr_out_movqi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5263 {
5264 rtx dest = op[0];
5265 rtx src = op[1];
5266 rtx x = XEXP (dest, 0);
5267
5268 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
5269 {
5270 avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
5271 TINY_ADIW (%I0, %J0, %o0) CR_TAB
5272 "st %b0,__tmp_reg__", op, plen, -4);
5273 }
5274 else
5275 {
5276 avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
5277 "st %b0,%1", op, plen, -3);
5278 }
5279
5280 if (!reg_unused_after (insn, XEXP (x, 0)))
5281 avr_asm_len (TINY_SBIW (%I0, %J0, %o0), op, plen, 2);
5282
5283 return "";
5284 }
5285
5286 static const char*
out_movqi_mr_r(rtx_insn * insn,rtx op[],int * plen)5287 out_movqi_mr_r (rtx_insn *insn, rtx op[], int *plen)
5288 {
5289 rtx dest = op[0];
5290 rtx src = op[1];
5291 rtx x = XEXP (dest, 0);
5292
5293 if (CONSTANT_ADDRESS_P (x))
5294 {
5295 int n_words = AVR_TINY ? 1 : 2;
5296 return io_address_operand (x, QImode)
5297 ? avr_asm_len ("out %i0,%1", op, plen, -1)
5298 : avr_asm_len ("sts %m0,%1", op, plen, -n_words);
5299 }
5300 else if (GET_CODE (x) == PLUS
5301 && REG_P (XEXP (x, 0))
5302 && CONST_INT_P (XEXP (x, 1)))
5303 {
5304 /* memory access by reg+disp */
5305
5306 int disp = INTVAL (XEXP (x, 1));
5307
5308 if (AVR_TINY)
5309 return avr_out_movqi_mr_r_reg_disp_tiny (insn, op, plen);
5310
5311 if (disp - GET_MODE_SIZE (GET_MODE (dest)) >= 63)
5312 {
5313 if (REGNO (XEXP (x, 0)) != REG_Y)
5314 fatal_insn ("incorrect insn:",insn);
5315
5316 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
5317 return avr_asm_len ("adiw r28,%o0-63" CR_TAB
5318 "std Y+63,%1" CR_TAB
5319 "sbiw r28,%o0-63", op, plen, -3);
5320
5321 return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5322 "sbci r29,hi8(-%o0)" CR_TAB
5323 "st Y,%1" CR_TAB
5324 "subi r28,lo8(%o0)" CR_TAB
5325 "sbci r29,hi8(%o0)", op, plen, -5);
5326 }
5327 else if (REGNO (XEXP (x, 0)) == REG_X)
5328 {
5329 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
5330 {
5331 avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
5332 "adiw r26,%o0" CR_TAB
5333 "st X,__tmp_reg__", op, plen, -3);
5334 }
5335 else
5336 {
5337 avr_asm_len ("adiw r26,%o0" CR_TAB
5338 "st X,%1", op, plen, -2);
5339 }
5340
5341 if (!reg_unused_after (insn, XEXP (x, 0)))
5342 avr_asm_len ("sbiw r26,%o0", op, plen, 1);
5343
5344 return "";
5345 }
5346
5347 return avr_asm_len ("std %0,%1", op, plen, -1);
5348 }
5349
5350 return avr_asm_len ("st %0,%1", op, plen, -1);
5351 }
5352
5353
5354 /* Helper for the next function for XMEGA. It does the same
5355 but with low byte first. */
5356
5357 static const char*
avr_out_movhi_mr_r_xmega(rtx_insn * insn,rtx op[],int * plen)5358 avr_out_movhi_mr_r_xmega (rtx_insn *insn, rtx op[], int *plen)
5359 {
5360 rtx dest = op[0];
5361 rtx src = op[1];
5362 rtx base = XEXP (dest, 0);
5363 int reg_base = true_regnum (base);
5364 int reg_src = true_regnum (src);
5365
5366 /* "volatile" forces writing low byte first, even if less efficient,
5367 for correct operation with 16-bit I/O registers like SP. */
5368 int mem_volatile_p = MEM_VOLATILE_P (dest);
5369
5370 if (CONSTANT_ADDRESS_P (base))
5371 {
5372 return io_address_operand (base, HImode)
5373 ? avr_asm_len ("out %i0,%A1" CR_TAB
5374 "out %i0+1,%B1", op, plen, -2)
5375
5376 : avr_asm_len ("sts %m0,%A1" CR_TAB
5377 "sts %m0+1,%B1", op, plen, -4);
5378 }
5379
5380 if (reg_base > 0)
5381 {
5382 if (reg_base != REG_X)
5383 return avr_asm_len ("st %0,%A1" CR_TAB
5384 "std %0+1,%B1", op, plen, -2);
5385
5386 if (reg_src == REG_X)
5387 /* "st X+,r26" and "st -X,r26" are undefined. */
5388 avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5389 "st X,r26" CR_TAB
5390 "adiw r26,1" CR_TAB
5391 "st X,__tmp_reg__", op, plen, -4);
5392 else
5393 avr_asm_len ("st X+,%A1" CR_TAB
5394 "st X,%B1", op, plen, -2);
5395
5396 return reg_unused_after (insn, base)
5397 ? ""
5398 : avr_asm_len ("sbiw r26,1", op, plen, 1);
5399 }
5400 else if (GET_CODE (base) == PLUS)
5401 {
5402 int disp = INTVAL (XEXP (base, 1));
5403 reg_base = REGNO (XEXP (base, 0));
5404 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5405 {
5406 if (reg_base != REG_Y)
5407 fatal_insn ("incorrect insn:",insn);
5408
5409 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
5410 ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
5411 "std Y+62,%A1" CR_TAB
5412 "std Y+63,%B1" CR_TAB
5413 "sbiw r28,%o0-62", op, plen, -4)
5414
5415 : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5416 "sbci r29,hi8(-%o0)" CR_TAB
5417 "st Y,%A1" CR_TAB
5418 "std Y+1,%B1" CR_TAB
5419 "subi r28,lo8(%o0)" CR_TAB
5420 "sbci r29,hi8(%o0)", op, plen, -6);
5421 }
5422
5423 if (reg_base != REG_X)
5424 return avr_asm_len ("std %A0,%A1" CR_TAB
5425 "std %B0,%B1", op, plen, -2);
5426 /* (X + d) = R */
5427 return reg_src == REG_X
5428 ? avr_asm_len ("mov __tmp_reg__,r26" CR_TAB
5429 "mov __zero_reg__,r27" CR_TAB
5430 "adiw r26,%o0" CR_TAB
5431 "st X+,__tmp_reg__" CR_TAB
5432 "st X,__zero_reg__" CR_TAB
5433 "clr __zero_reg__" CR_TAB
5434 "sbiw r26,%o0+1", op, plen, -7)
5435
5436 : avr_asm_len ("adiw r26,%o0" CR_TAB
5437 "st X+,%A1" CR_TAB
5438 "st X,%B1" CR_TAB
5439 "sbiw r26,%o0+1", op, plen, -4);
5440 }
5441 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5442 {
5443 if (!mem_volatile_p)
5444 return avr_asm_len ("st %0,%B1" CR_TAB
5445 "st %0,%A1", op, plen, -2);
5446
5447 return REGNO (XEXP (base, 0)) == REG_X
5448 ? avr_asm_len ("sbiw r26,2" CR_TAB
5449 "st X+,%A1" CR_TAB
5450 "st X,%B1" CR_TAB
5451 "sbiw r26,1", op, plen, -4)
5452
5453 : avr_asm_len ("sbiw %r0,2" CR_TAB
5454 "st %p0,%A1" CR_TAB
5455 "std %p0+1,%B1", op, plen, -3);
5456 }
5457 else if (GET_CODE (base) == POST_INC) /* (R++) */
5458 {
5459 return avr_asm_len ("st %0,%A1" CR_TAB
5460 "st %0,%B1", op, plen, -2);
5461
5462 }
5463 fatal_insn ("unknown move insn:",insn);
5464 return "";
5465 }
5466
5467 static const char*
avr_out_movhi_mr_r_reg_no_disp_tiny(rtx_insn * insn,rtx op[],int * plen)5468 avr_out_movhi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5469 {
5470 rtx dest = op[0];
5471 rtx src = op[1];
5472 rtx base = XEXP (dest, 0);
5473 int reg_base = true_regnum (base);
5474 int reg_src = true_regnum (src);
5475 int mem_volatile_p = MEM_VOLATILE_P (dest);
5476
5477 if (reg_base == reg_src)
5478 {
5479 return !mem_volatile_p && reg_unused_after (insn, src)
5480 ? avr_asm_len ("mov __tmp_reg__,%B1" CR_TAB
5481 "st %0,%A1" CR_TAB
5482 TINY_ADIW (%E0, %F0, 1) CR_TAB
5483 "st %0,__tmp_reg__", op, plen, -5)
5484 : avr_asm_len ("mov __tmp_reg__,%B1" CR_TAB
5485 TINY_ADIW (%E0, %F0, 1) CR_TAB
5486 "st %0,__tmp_reg__" CR_TAB
5487 TINY_SBIW (%E0, %F0, 1) CR_TAB
5488 "st %0, %A1", op, plen, -7);
5489 }
5490
5491 return !mem_volatile_p && reg_unused_after (insn, base)
5492 ? avr_asm_len ("st %0+,%A1" CR_TAB
5493 "st %0,%B1", op, plen, -2)
5494 : avr_asm_len (TINY_ADIW (%E0, %F0, 1) CR_TAB
5495 "st %0,%B1" CR_TAB
5496 "st -%0,%A1", op, plen, -4);
5497 }
5498
5499 static const char*
avr_out_movhi_mr_r_reg_disp_tiny(rtx_insn * insn,rtx op[],int * plen)5500 avr_out_movhi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5501 {
5502 rtx dest = op[0];
5503 rtx src = op[1];
5504 rtx base = XEXP (dest, 0);
5505 int reg_base = REGNO (XEXP (base, 0));
5506 int reg_src = true_regnum (src);
5507
5508 if (reg_src == reg_base)
5509 avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
5510 "mov __zero_reg__,%B1" CR_TAB
5511 TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
5512 "st %b0,__zero_reg__" CR_TAB
5513 "st -%b0,__tmp_reg__" CR_TAB
5514 "clr __zero_reg__", op, plen, -7);
5515 else
5516 avr_asm_len (TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
5517 "st %b0,%B1" CR_TAB
5518 "st -%b0,%A1", op, plen, -4);
5519
5520 if (!reg_unused_after (insn, XEXP (base, 0)))
5521 avr_asm_len (TINY_SBIW (%I0, %J0, %o0), op, plen, 2);
5522
5523 return "";
5524 }
5525
5526 static const char*
avr_out_movhi_mr_r_post_inc_tiny(rtx op[],int * plen)5527 avr_out_movhi_mr_r_post_inc_tiny (rtx op[], int *plen)
5528 {
5529 return avr_asm_len (TINY_ADIW (%I0, %J0, 1) CR_TAB
5530 "st %p0,%B1" CR_TAB
5531 "st -%p0,%A1" CR_TAB
5532 TINY_ADIW (%I0, %J0, 2), op, plen, -6);
5533 }
5534
5535 static const char*
out_movhi_mr_r(rtx_insn * insn,rtx op[],int * plen)5536 out_movhi_mr_r (rtx_insn *insn, rtx op[], int *plen)
5537 {
5538 rtx dest = op[0];
5539 rtx src = op[1];
5540 rtx base = XEXP (dest, 0);
5541 int reg_base = true_regnum (base);
5542 int reg_src = true_regnum (src);
5543 int mem_volatile_p;
5544
5545 /* "volatile" forces writing high-byte first (no-xmega) resp.
5546 low-byte first (xmega) even if less efficient, for correct
5547 operation with 16-bit I/O registers like. */
5548
5549 if (AVR_XMEGA)
5550 return avr_out_movhi_mr_r_xmega (insn, op, plen);
5551
5552 mem_volatile_p = MEM_VOLATILE_P (dest);
5553
5554 if (CONSTANT_ADDRESS_P (base))
5555 {
5556 int n_words = AVR_TINY ? 2 : 4;
5557 return io_address_operand (base, HImode)
5558 ? avr_asm_len ("out %i0+1,%B1" CR_TAB
5559 "out %i0,%A1", op, plen, -2)
5560
5561 : avr_asm_len ("sts %m0+1,%B1" CR_TAB
5562 "sts %m0,%A1", op, plen, -n_words);
5563 }
5564
5565 if (reg_base > 0)
5566 {
5567 if (AVR_TINY)
5568 return avr_out_movhi_mr_r_reg_no_disp_tiny (insn, op, plen);
5569
5570 if (reg_base != REG_X)
5571 return avr_asm_len ("std %0+1,%B1" CR_TAB
5572 "st %0,%A1", op, plen, -2);
5573
5574 if (reg_src == REG_X)
5575 /* "st X+,r26" and "st -X,r26" are undefined. */
5576 return !mem_volatile_p && reg_unused_after (insn, src)
5577 ? avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5578 "st X,r26" CR_TAB
5579 "adiw r26,1" CR_TAB
5580 "st X,__tmp_reg__", op, plen, -4)
5581
5582 : avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5583 "adiw r26,1" CR_TAB
5584 "st X,__tmp_reg__" CR_TAB
5585 "sbiw r26,1" CR_TAB
5586 "st X,r26", op, plen, -5);
5587
5588 return !mem_volatile_p && reg_unused_after (insn, base)
5589 ? avr_asm_len ("st X+,%A1" CR_TAB
5590 "st X,%B1", op, plen, -2)
5591 : avr_asm_len ("adiw r26,1" CR_TAB
5592 "st X,%B1" CR_TAB
5593 "st -X,%A1", op, plen, -3);
5594 }
5595 else if (GET_CODE (base) == PLUS)
5596 {
5597 int disp = INTVAL (XEXP (base, 1));
5598
5599 if (AVR_TINY)
5600 return avr_out_movhi_mr_r_reg_disp_tiny (insn, op, plen);
5601
5602 reg_base = REGNO (XEXP (base, 0));
5603 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5604 {
5605 if (reg_base != REG_Y)
5606 fatal_insn ("incorrect insn:",insn);
5607
5608 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
5609 ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
5610 "std Y+63,%B1" CR_TAB
5611 "std Y+62,%A1" CR_TAB
5612 "sbiw r28,%o0-62", op, plen, -4)
5613
5614 : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5615 "sbci r29,hi8(-%o0)" CR_TAB
5616 "std Y+1,%B1" CR_TAB
5617 "st Y,%A1" CR_TAB
5618 "subi r28,lo8(%o0)" CR_TAB
5619 "sbci r29,hi8(%o0)", op, plen, -6);
5620 }
5621
5622 if (reg_base != REG_X)
5623 return avr_asm_len ("std %B0,%B1" CR_TAB
5624 "std %A0,%A1", op, plen, -2);
5625 /* (X + d) = R */
5626 return reg_src == REG_X
5627 ? avr_asm_len ("mov __tmp_reg__,r26" CR_TAB
5628 "mov __zero_reg__,r27" CR_TAB
5629 "adiw r26,%o0+1" CR_TAB
5630 "st X,__zero_reg__" CR_TAB
5631 "st -X,__tmp_reg__" CR_TAB
5632 "clr __zero_reg__" CR_TAB
5633 "sbiw r26,%o0", op, plen, -7)
5634
5635 : avr_asm_len ("adiw r26,%o0+1" CR_TAB
5636 "st X,%B1" CR_TAB
5637 "st -X,%A1" CR_TAB
5638 "sbiw r26,%o0", op, plen, -4);
5639 }
5640 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5641 {
5642 return avr_asm_len ("st %0,%B1" CR_TAB
5643 "st %0,%A1", op, plen, -2);
5644 }
5645 else if (GET_CODE (base) == POST_INC) /* (R++) */
5646 {
5647 if (!mem_volatile_p)
5648 return avr_asm_len ("st %0,%A1" CR_TAB
5649 "st %0,%B1", op, plen, -2);
5650
5651 if (AVR_TINY)
5652 return avr_out_movhi_mr_r_post_inc_tiny (op, plen);
5653
5654 return REGNO (XEXP (base, 0)) == REG_X
5655 ? avr_asm_len ("adiw r26,1" CR_TAB
5656 "st X,%B1" CR_TAB
5657 "st -X,%A1" CR_TAB
5658 "adiw r26,2", op, plen, -4)
5659
5660 : avr_asm_len ("std %p0+1,%B1" CR_TAB
5661 "st %p0,%A1" CR_TAB
5662 "adiw %r0,2", op, plen, -3);
5663 }
5664 fatal_insn ("unknown move insn:",insn);
5665 return "";
5666 }
5667
5668 /* Return 1 if frame pointer for current function required. */
5669
5670 static bool
avr_frame_pointer_required_p(void)5671 avr_frame_pointer_required_p (void)
5672 {
5673 return (cfun->calls_alloca
5674 || cfun->calls_setjmp
5675 || cfun->has_nonlocal_label
5676 || crtl->args.info.nregs == 0
5677 || get_frame_size () > 0);
5678 }
5679
5680 /* Returns the condition of compare insn INSN, or UNKNOWN. */
5681
5682 static RTX_CODE
compare_condition(rtx_insn * insn)5683 compare_condition (rtx_insn *insn)
5684 {
5685 rtx_insn *next = next_real_insn (insn);
5686
5687 if (next && JUMP_P (next))
5688 {
5689 rtx pat = PATTERN (next);
5690 if (GET_CODE (pat) == PARALLEL)
5691 pat = XVECEXP (pat, 0, 0);
5692 rtx src = SET_SRC (pat);
5693
5694 if (IF_THEN_ELSE == GET_CODE (src))
5695 return GET_CODE (XEXP (src, 0));
5696 }
5697
5698 return UNKNOWN;
5699 }
5700
5701
5702 /* Returns true iff INSN is a tst insn that only tests the sign. */
5703
5704 static bool
compare_sign_p(rtx_insn * insn)5705 compare_sign_p (rtx_insn *insn)
5706 {
5707 RTX_CODE cond = compare_condition (insn);
5708 return (cond == GE || cond == LT);
5709 }
5710
5711
5712 /* Returns true iff the next insn is a JUMP_INSN with a condition
5713 that needs to be swapped (GT, GTU, LE, LEU). */
5714
5715 static bool
compare_diff_p(rtx_insn * insn)5716 compare_diff_p (rtx_insn *insn)
5717 {
5718 RTX_CODE cond = compare_condition (insn);
5719 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
5720 }
5721
5722 /* Returns true iff INSN is a compare insn with the EQ or NE condition. */
5723
5724 static bool
compare_eq_p(rtx_insn * insn)5725 compare_eq_p (rtx_insn *insn)
5726 {
5727 RTX_CODE cond = compare_condition (insn);
5728 return (cond == EQ || cond == NE);
5729 }
5730
5731
5732 /* Output compare instruction
5733
5734 compare (XOP[0], XOP[1])
5735
5736 for a register XOP[0] and a compile-time constant XOP[1]. Return "".
5737 XOP[2] is an 8-bit scratch register as needed.
5738
5739 PLEN == NULL: Output instructions.
5740 PLEN != NULL: Set *PLEN to the length (in words) of the sequence.
5741 Don't output anything. */
5742
5743 const char*
avr_out_compare(rtx_insn * insn,rtx * xop,int * plen)5744 avr_out_compare (rtx_insn *insn, rtx *xop, int *plen)
5745 {
5746 /* Register to compare and value to compare against. */
5747 rtx xreg = xop[0];
5748 rtx xval = xop[1];
5749
5750 /* MODE of the comparison. */
5751 machine_mode mode;
5752
5753 /* Number of bytes to operate on. */
5754 int n_bytes = GET_MODE_SIZE (GET_MODE (xreg));
5755
5756 /* Value (0..0xff) held in clobber register xop[2] or -1 if unknown. */
5757 int clobber_val = -1;
5758
5759 /* Map fixed mode operands to integer operands with the same binary
5760 representation. They are easier to handle in the remainder. */
5761
5762 if (CONST_FIXED_P (xval))
5763 {
5764 xreg = avr_to_int_mode (xop[0]);
5765 xval = avr_to_int_mode (xop[1]);
5766 }
5767
5768 mode = GET_MODE (xreg);
5769
5770 gcc_assert (REG_P (xreg));
5771 gcc_assert ((CONST_INT_P (xval) && n_bytes <= 4)
5772 || (const_double_operand (xval, VOIDmode) && n_bytes == 8));
5773
5774 if (plen)
5775 *plen = 0;
5776
5777 /* Comparisons == +/-1 and != +/-1 can be done similar to camparing
5778 against 0 by ORing the bytes. This is one instruction shorter.
5779 Notice that 64-bit comparisons are always against reg:ALL8 18 (ACC_A)
5780 and therefore don't use this. */
5781
5782 if (!test_hard_reg_class (LD_REGS, xreg)
5783 && compare_eq_p (insn)
5784 && reg_unused_after (insn, xreg))
5785 {
5786 if (xval == const1_rtx)
5787 {
5788 avr_asm_len ("dec %A0" CR_TAB
5789 "or %A0,%B0", xop, plen, 2);
5790
5791 if (n_bytes >= 3)
5792 avr_asm_len ("or %A0,%C0", xop, plen, 1);
5793
5794 if (n_bytes >= 4)
5795 avr_asm_len ("or %A0,%D0", xop, plen, 1);
5796
5797 return "";
5798 }
5799 else if (xval == constm1_rtx)
5800 {
5801 if (n_bytes >= 4)
5802 avr_asm_len ("and %A0,%D0", xop, plen, 1);
5803
5804 if (n_bytes >= 3)
5805 avr_asm_len ("and %A0,%C0", xop, plen, 1);
5806
5807 return avr_asm_len ("and %A0,%B0" CR_TAB
5808 "com %A0", xop, plen, 2);
5809 }
5810 }
5811
5812 /* Comparisons == -1 and != -1 of a d-register that's used after the
5813 comparison. (If it's unused after we use CPI / SBCI or ADIW sequence
5814 from below.) Instead of CPI Rlo,-1 / LDI Rx,-1 / CPC Rhi,Rx we can
5815 use CPI Rlo,-1 / CPC Rhi,Rlo which is 1 instruction shorter:
5816 If CPI is true then Rlo contains -1 and we can use Rlo instead of Rx
5817 when CPC'ing the high part. If CPI is false then CPC cannot render
5818 the result to true. This also works for the more generic case where
5819 the constant is of the form 0xabab. */
5820
5821 if (n_bytes == 2
5822 && xval != const0_rtx
5823 && test_hard_reg_class (LD_REGS, xreg)
5824 && compare_eq_p (insn)
5825 && !reg_unused_after (insn, xreg))
5826 {
5827 rtx xlo8 = simplify_gen_subreg (QImode, xval, mode, 0);
5828 rtx xhi8 = simplify_gen_subreg (QImode, xval, mode, 1);
5829
5830 if (INTVAL (xlo8) == INTVAL (xhi8))
5831 {
5832 xop[0] = xreg;
5833 xop[1] = xlo8;
5834
5835 return avr_asm_len ("cpi %A0,%1" CR_TAB
5836 "cpc %B0,%A0", xop, plen, 2);
5837 }
5838 }
5839
5840 for (int i = 0; i < n_bytes; i++)
5841 {
5842 /* We compare byte-wise. */
5843 rtx reg8 = simplify_gen_subreg (QImode, xreg, mode, i);
5844 rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
5845
5846 /* 8-bit value to compare with this byte. */
5847 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
5848
5849 /* Registers R16..R31 can operate with immediate. */
5850 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
5851
5852 xop[0] = reg8;
5853 xop[1] = gen_int_mode (val8, QImode);
5854
5855 /* Word registers >= R24 can use SBIW/ADIW with 0..63. */
5856
5857 if (i == 0
5858 && test_hard_reg_class (ADDW_REGS, reg8))
5859 {
5860 int val16 = trunc_int_for_mode (INTVAL (xval), HImode);
5861
5862 if (IN_RANGE (val16, 0, 63)
5863 && (val8 == 0
5864 || reg_unused_after (insn, xreg)))
5865 {
5866 if (AVR_TINY)
5867 avr_asm_len (TINY_SBIW (%A0, %B0, %1), xop, plen, 2);
5868 else
5869 avr_asm_len ("sbiw %0,%1", xop, plen, 1);
5870
5871 i++;
5872 continue;
5873 }
5874
5875 if (n_bytes == 2
5876 && IN_RANGE (val16, -63, -1)
5877 && compare_eq_p (insn)
5878 && reg_unused_after (insn, xreg))
5879 {
5880 return AVR_TINY
5881 ? avr_asm_len (TINY_ADIW (%A0, %B0, %n1), xop, plen, 2)
5882 : avr_asm_len ("adiw %0,%n1", xop, plen, 1);
5883 }
5884 }
5885
5886 /* Comparing against 0 is easy. */
5887
5888 if (val8 == 0)
5889 {
5890 avr_asm_len (i == 0
5891 ? "cp %0,__zero_reg__"
5892 : "cpc %0,__zero_reg__", xop, plen, 1);
5893 continue;
5894 }
5895
5896 /* Upper registers can compare and subtract-with-carry immediates.
5897 Notice that compare instructions do the same as respective subtract
5898 instruction; the only difference is that comparisons don't write
5899 the result back to the target register. */
5900
5901 if (ld_reg_p)
5902 {
5903 if (i == 0)
5904 {
5905 avr_asm_len ("cpi %0,%1", xop, plen, 1);
5906 continue;
5907 }
5908 else if (reg_unused_after (insn, xreg))
5909 {
5910 avr_asm_len ("sbci %0,%1", xop, plen, 1);
5911 continue;
5912 }
5913 }
5914
5915 /* Must load the value into the scratch register. */
5916
5917 gcc_assert (REG_P (xop[2]));
5918
5919 if (clobber_val != (int) val8)
5920 avr_asm_len ("ldi %2,%1", xop, plen, 1);
5921 clobber_val = (int) val8;
5922
5923 avr_asm_len (i == 0
5924 ? "cp %0,%2"
5925 : "cpc %0,%2", xop, plen, 1);
5926 }
5927
5928 return "";
5929 }
5930
5931
5932 /* Prepare operands of compare_const_di2 to be used with avr_out_compare. */
5933
5934 const char*
avr_out_compare64(rtx_insn * insn,rtx * op,int * plen)5935 avr_out_compare64 (rtx_insn *insn, rtx *op, int *plen)
5936 {
5937 rtx xop[3];
5938
5939 xop[0] = gen_rtx_REG (DImode, 18);
5940 xop[1] = op[0];
5941 xop[2] = op[1];
5942
5943 return avr_out_compare (insn, xop, plen);
5944 }
5945
5946 /* Output test instruction for HImode. */
5947
5948 const char*
avr_out_tsthi(rtx_insn * insn,rtx * op,int * plen)5949 avr_out_tsthi (rtx_insn *insn, rtx *op, int *plen)
5950 {
5951 if (compare_sign_p (insn))
5952 {
5953 avr_asm_len ("tst %B0", op, plen, -1);
5954 }
5955 else if (reg_unused_after (insn, op[0])
5956 && compare_eq_p (insn))
5957 {
5958 /* Faster than sbiw if we can clobber the operand. */
5959 avr_asm_len ("or %A0,%B0", op, plen, -1);
5960 }
5961 else
5962 {
5963 avr_out_compare (insn, op, plen);
5964 }
5965
5966 return "";
5967 }
5968
5969
5970 /* Output test instruction for PSImode. */
5971
5972 const char*
avr_out_tstpsi(rtx_insn * insn,rtx * op,int * plen)5973 avr_out_tstpsi (rtx_insn *insn, rtx *op, int *plen)
5974 {
5975 if (compare_sign_p (insn))
5976 {
5977 avr_asm_len ("tst %C0", op, plen, -1);
5978 }
5979 else if (reg_unused_after (insn, op[0])
5980 && compare_eq_p (insn))
5981 {
5982 /* Faster than sbiw if we can clobber the operand. */
5983 avr_asm_len ("or %A0,%B0" CR_TAB
5984 "or %A0,%C0", op, plen, -2);
5985 }
5986 else
5987 {
5988 avr_out_compare (insn, op, plen);
5989 }
5990
5991 return "";
5992 }
5993
5994
5995 /* Output test instruction for SImode. */
5996
5997 const char*
avr_out_tstsi(rtx_insn * insn,rtx * op,int * plen)5998 avr_out_tstsi (rtx_insn *insn, rtx *op, int *plen)
5999 {
6000 if (compare_sign_p (insn))
6001 {
6002 avr_asm_len ("tst %D0", op, plen, -1);
6003 }
6004 else if (reg_unused_after (insn, op[0])
6005 && compare_eq_p (insn))
6006 {
6007 /* Faster than sbiw if we can clobber the operand. */
6008 avr_asm_len ("or %A0,%B0" CR_TAB
6009 "or %A0,%C0" CR_TAB
6010 "or %A0,%D0", op, plen, -3);
6011 }
6012 else
6013 {
6014 avr_out_compare (insn, op, plen);
6015 }
6016
6017 return "";
6018 }
6019
6020
6021 /* Generate asm equivalent for various shifts. This only handles cases
6022 that are not already carefully hand-optimized in ?sh??i3_out.
6023
6024 OPERANDS[0] resp. %0 in TEMPL is the operand to be shifted.
6025 OPERANDS[2] is the shift count as CONST_INT, MEM or REG.
6026 OPERANDS[3] is a QImode scratch register from LD regs if
6027 available and SCRATCH, otherwise (no scratch available)
6028
6029 TEMPL is an assembler template that shifts by one position.
6030 T_LEN is the length of this template. */
6031
6032 void
out_shift_with_cnt(const char * templ,rtx_insn * insn,rtx operands[],int * plen,int t_len)6033 out_shift_with_cnt (const char *templ, rtx_insn *insn, rtx operands[],
6034 int *plen, int t_len)
6035 {
6036 bool second_label = true;
6037 bool saved_in_tmp = false;
6038 bool use_zero_reg = false;
6039 rtx op[5];
6040
6041 op[0] = operands[0];
6042 op[1] = operands[1];
6043 op[2] = operands[2];
6044 op[3] = operands[3];
6045
6046 if (plen)
6047 *plen = 0;
6048
6049 if (CONST_INT_P (operands[2]))
6050 {
6051 /* Operand 3 is a scratch register if this is a
6052 parallel with three elements i.e. a set,
6053 a clobber of a scratch, and clobber of REG_CC.
6054 If a scratch reg is not available, then the parallel
6055 will contain only a set and clobber of REG_CC. */
6056 bool scratch = (GET_CODE (PATTERN (insn)) == PARALLEL
6057 && XVECLEN (PATTERN (insn), 0) == 3
6058 && REG_P (operands[3]));
6059 int count = INTVAL (operands[2]);
6060 int max_len = 10; /* If larger than this, always use a loop. */
6061
6062 if (count <= 0)
6063 return;
6064
6065 if (count < 8 && !scratch)
6066 use_zero_reg = true;
6067
6068 if (optimize_size)
6069 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
6070
6071 if (t_len * count <= max_len)
6072 {
6073 /* Output shifts inline with no loop - faster. */
6074
6075 while (count-- > 0)
6076 avr_asm_len (templ, op, plen, t_len);
6077
6078 return;
6079 }
6080
6081 if (scratch)
6082 {
6083 avr_asm_len ("ldi %3,%2", op, plen, 1);
6084 }
6085 else if (use_zero_reg)
6086 {
6087 /* Hack to save one word: use __zero_reg__ as loop counter.
6088 Set one bit, then shift in a loop until it is 0 again. */
6089
6090 op[3] = zero_reg_rtx;
6091
6092 avr_asm_len ("set" CR_TAB
6093 "bld %3,%2-1", op, plen, 2);
6094 }
6095 else
6096 {
6097 /* No scratch register available, use one from LD_REGS (saved in
6098 __tmp_reg__) that doesn't overlap with registers to shift. */
6099
6100 op[3] = all_regs_rtx[((REGNO (op[0]) - 1) & 15) + 16];
6101 op[4] = tmp_reg_rtx;
6102 saved_in_tmp = true;
6103
6104 avr_asm_len ("mov %4,%3" CR_TAB
6105 "ldi %3,%2", op, plen, 2);
6106 }
6107
6108 second_label = false;
6109 }
6110 else if (MEM_P (op[2]))
6111 {
6112 rtx op_mov[2];
6113
6114 op_mov[0] = op[3] = tmp_reg_rtx;
6115 op_mov[1] = op[2];
6116
6117 out_movqi_r_mr (insn, op_mov, plen);
6118 }
6119 else if (register_operand (op[2], QImode))
6120 {
6121 op[3] = op[2];
6122
6123 if (!reg_unused_after (insn, op[2])
6124 || reg_overlap_mentioned_p (op[0], op[2]))
6125 {
6126 op[3] = tmp_reg_rtx;
6127 avr_asm_len ("mov %3,%2", op, plen, 1);
6128 }
6129 }
6130 else
6131 fatal_insn ("bad shift insn:", insn);
6132
6133 if (second_label)
6134 avr_asm_len ("rjmp 2f", op, plen, 1);
6135
6136 avr_asm_len ("1:", op, plen, 0);
6137 avr_asm_len (templ, op, plen, t_len);
6138
6139 if (second_label)
6140 avr_asm_len ("2:", op, plen, 0);
6141
6142 avr_asm_len (use_zero_reg ? "lsr %3" : "dec %3", op, plen, 1);
6143 avr_asm_len (second_label ? "brpl 1b" : "brne 1b", op, plen, 1);
6144
6145 if (saved_in_tmp)
6146 avr_asm_len ("mov %3,%4", op, plen, 1);
6147 }
6148
6149
6150 /* 8bit shift left ((char)x << i) */
6151
6152 const char *
ashlqi3_out(rtx_insn * insn,rtx operands[],int * len)6153 ashlqi3_out (rtx_insn *insn, rtx operands[], int *len)
6154 {
6155 if (CONST_INT_P (operands[2]))
6156 {
6157 int k;
6158
6159 if (!len)
6160 len = &k;
6161
6162 switch (INTVAL (operands[2]))
6163 {
6164 default:
6165 if (INTVAL (operands[2]) < 8)
6166 break;
6167
6168 *len = 1;
6169 return "clr %0";
6170
6171 case 1:
6172 *len = 1;
6173 return "lsl %0";
6174
6175 case 2:
6176 *len = 2;
6177 return ("lsl %0" CR_TAB
6178 "lsl %0");
6179
6180 case 3:
6181 *len = 3;
6182 return ("lsl %0" CR_TAB
6183 "lsl %0" CR_TAB
6184 "lsl %0");
6185
6186 case 4:
6187 if (test_hard_reg_class (LD_REGS, operands[0]))
6188 {
6189 *len = 2;
6190 return ("swap %0" CR_TAB
6191 "andi %0,0xf0");
6192 }
6193 *len = 4;
6194 return ("lsl %0" CR_TAB
6195 "lsl %0" CR_TAB
6196 "lsl %0" CR_TAB
6197 "lsl %0");
6198
6199 case 5:
6200 if (test_hard_reg_class (LD_REGS, operands[0]))
6201 {
6202 *len = 3;
6203 return ("swap %0" CR_TAB
6204 "lsl %0" CR_TAB
6205 "andi %0,0xe0");
6206 }
6207 *len = 5;
6208 return ("lsl %0" CR_TAB
6209 "lsl %0" CR_TAB
6210 "lsl %0" CR_TAB
6211 "lsl %0" CR_TAB
6212 "lsl %0");
6213
6214 case 6:
6215 if (test_hard_reg_class (LD_REGS, operands[0]))
6216 {
6217 *len = 4;
6218 return ("swap %0" CR_TAB
6219 "lsl %0" CR_TAB
6220 "lsl %0" CR_TAB
6221 "andi %0,0xc0");
6222 }
6223 *len = 6;
6224 return ("lsl %0" CR_TAB
6225 "lsl %0" CR_TAB
6226 "lsl %0" CR_TAB
6227 "lsl %0" CR_TAB
6228 "lsl %0" CR_TAB
6229 "lsl %0");
6230
6231 case 7:
6232 *len = 3;
6233 return ("ror %0" CR_TAB
6234 "clr %0" CR_TAB
6235 "ror %0");
6236 }
6237 }
6238 else if (CONSTANT_P (operands[2]))
6239 fatal_insn ("internal compiler error. Incorrect shift:", insn);
6240
6241 out_shift_with_cnt ("lsl %0",
6242 insn, operands, len, 1);
6243 return "";
6244 }
6245
6246
6247 /* 16bit shift left ((short)x << i) */
6248
6249 const char *
ashlhi3_out(rtx_insn * insn,rtx operands[],int * len)6250 ashlhi3_out (rtx_insn *insn, rtx operands[], int *len)
6251 {
6252 if (CONST_INT_P (operands[2]))
6253 {
6254 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL
6255 && XVECLEN (PATTERN (insn), 0) == 3
6256 && REG_P (operands[3]));
6257 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
6258 int k;
6259 int *t = len;
6260
6261 if (!len)
6262 len = &k;
6263
6264 switch (INTVAL (operands[2]))
6265 {
6266 default:
6267 if (INTVAL (operands[2]) < 16)
6268 break;
6269
6270 *len = 2;
6271 return ("clr %B0" CR_TAB
6272 "clr %A0");
6273
6274 case 4:
6275 if (optimize_size && scratch)
6276 break; /* 5 */
6277 if (ldi_ok)
6278 {
6279 *len = 6;
6280 return ("swap %A0" CR_TAB
6281 "swap %B0" CR_TAB
6282 "andi %B0,0xf0" CR_TAB
6283 "eor %B0,%A0" CR_TAB
6284 "andi %A0,0xf0" CR_TAB
6285 "eor %B0,%A0");
6286 }
6287 if (scratch)
6288 {
6289 *len = 7;
6290 return ("swap %A0" CR_TAB
6291 "swap %B0" CR_TAB
6292 "ldi %3,0xf0" CR_TAB
6293 "and %B0,%3" CR_TAB
6294 "eor %B0,%A0" CR_TAB
6295 "and %A0,%3" CR_TAB
6296 "eor %B0,%A0");
6297 }
6298 break; /* optimize_size ? 6 : 8 */
6299
6300 case 5:
6301 if (optimize_size)
6302 break; /* scratch ? 5 : 6 */
6303 if (ldi_ok)
6304 {
6305 *len = 8;
6306 return ("lsl %A0" CR_TAB
6307 "rol %B0" CR_TAB
6308 "swap %A0" CR_TAB
6309 "swap %B0" CR_TAB
6310 "andi %B0,0xf0" CR_TAB
6311 "eor %B0,%A0" CR_TAB
6312 "andi %A0,0xf0" CR_TAB
6313 "eor %B0,%A0");
6314 }
6315 if (scratch)
6316 {
6317 *len = 9;
6318 return ("lsl %A0" CR_TAB
6319 "rol %B0" CR_TAB
6320 "swap %A0" CR_TAB
6321 "swap %B0" CR_TAB
6322 "ldi %3,0xf0" CR_TAB
6323 "and %B0,%3" CR_TAB
6324 "eor %B0,%A0" CR_TAB
6325 "and %A0,%3" CR_TAB
6326 "eor %B0,%A0");
6327 }
6328 break; /* 10 */
6329
6330 case 6:
6331 if (optimize_size)
6332 break; /* scratch ? 5 : 6 */
6333 *len = 9;
6334 return ("clr __tmp_reg__" CR_TAB
6335 "lsr %B0" CR_TAB
6336 "ror %A0" CR_TAB
6337 "ror __tmp_reg__" CR_TAB
6338 "lsr %B0" CR_TAB
6339 "ror %A0" CR_TAB
6340 "ror __tmp_reg__" CR_TAB
6341 "mov %B0,%A0" CR_TAB
6342 "mov %A0,__tmp_reg__");
6343
6344 case 7:
6345 *len = 5;
6346 return ("lsr %B0" CR_TAB
6347 "mov %B0,%A0" CR_TAB
6348 "clr %A0" CR_TAB
6349 "ror %B0" CR_TAB
6350 "ror %A0");
6351
6352 case 8:
6353 return *len = 2, ("mov %B0,%A1" CR_TAB
6354 "clr %A0");
6355
6356 case 9:
6357 *len = 3;
6358 return ("mov %B0,%A0" CR_TAB
6359 "clr %A0" CR_TAB
6360 "lsl %B0");
6361
6362 case 10:
6363 *len = 4;
6364 return ("mov %B0,%A0" CR_TAB
6365 "clr %A0" CR_TAB
6366 "lsl %B0" CR_TAB
6367 "lsl %B0");
6368
6369 case 11:
6370 *len = 5;
6371 return ("mov %B0,%A0" CR_TAB
6372 "clr %A0" CR_TAB
6373 "lsl %B0" CR_TAB
6374 "lsl %B0" CR_TAB
6375 "lsl %B0");
6376
6377 case 12:
6378 if (ldi_ok)
6379 {
6380 *len = 4;
6381 return ("mov %B0,%A0" CR_TAB
6382 "clr %A0" CR_TAB
6383 "swap %B0" CR_TAB
6384 "andi %B0,0xf0");
6385 }
6386 if (scratch)
6387 {
6388 *len = 5;
6389 return ("mov %B0,%A0" CR_TAB
6390 "clr %A0" CR_TAB
6391 "swap %B0" CR_TAB
6392 "ldi %3,0xf0" CR_TAB
6393 "and %B0,%3");
6394 }
6395 *len = 6;
6396 return ("mov %B0,%A0" CR_TAB
6397 "clr %A0" CR_TAB
6398 "lsl %B0" CR_TAB
6399 "lsl %B0" CR_TAB
6400 "lsl %B0" CR_TAB
6401 "lsl %B0");
6402
6403 case 13:
6404 if (ldi_ok)
6405 {
6406 *len = 5;
6407 return ("mov %B0,%A0" CR_TAB
6408 "clr %A0" CR_TAB
6409 "swap %B0" CR_TAB
6410 "lsl %B0" CR_TAB
6411 "andi %B0,0xe0");
6412 }
6413 if (AVR_HAVE_MUL && scratch)
6414 {
6415 *len = 5;
6416 return ("ldi %3,0x20" CR_TAB
6417 "mul %A0,%3" CR_TAB
6418 "mov %B0,r0" CR_TAB
6419 "clr %A0" CR_TAB
6420 "clr __zero_reg__");
6421 }
6422 if (optimize_size && scratch)
6423 break; /* 5 */
6424 if (scratch)
6425 {
6426 *len = 6;
6427 return ("mov %B0,%A0" CR_TAB
6428 "clr %A0" CR_TAB
6429 "swap %B0" CR_TAB
6430 "lsl %B0" CR_TAB
6431 "ldi %3,0xe0" CR_TAB
6432 "and %B0,%3");
6433 }
6434 if (AVR_HAVE_MUL)
6435 {
6436 *len = 6;
6437 return ("set" CR_TAB
6438 "bld r1,5" CR_TAB
6439 "mul %A0,r1" CR_TAB
6440 "mov %B0,r0" CR_TAB
6441 "clr %A0" CR_TAB
6442 "clr __zero_reg__");
6443 }
6444 *len = 7;
6445 return ("mov %B0,%A0" CR_TAB
6446 "clr %A0" CR_TAB
6447 "lsl %B0" CR_TAB
6448 "lsl %B0" CR_TAB
6449 "lsl %B0" CR_TAB
6450 "lsl %B0" CR_TAB
6451 "lsl %B0");
6452
6453 case 14:
6454 if (AVR_HAVE_MUL && ldi_ok)
6455 {
6456 *len = 5;
6457 return ("ldi %B0,0x40" CR_TAB
6458 "mul %A0,%B0" CR_TAB
6459 "mov %B0,r0" CR_TAB
6460 "clr %A0" CR_TAB
6461 "clr __zero_reg__");
6462 }
6463 if (AVR_HAVE_MUL && scratch)
6464 {
6465 *len = 5;
6466 return ("ldi %3,0x40" CR_TAB
6467 "mul %A0,%3" CR_TAB
6468 "mov %B0,r0" CR_TAB
6469 "clr %A0" CR_TAB
6470 "clr __zero_reg__");
6471 }
6472 if (optimize_size && ldi_ok)
6473 {
6474 *len = 5;
6475 return ("mov %B0,%A0" CR_TAB
6476 "ldi %A0,6" "\n1:\t"
6477 "lsl %B0" CR_TAB
6478 "dec %A0" CR_TAB
6479 "brne 1b");
6480 }
6481 if (optimize_size && scratch)
6482 break; /* 5 */
6483 *len = 6;
6484 return ("clr %B0" CR_TAB
6485 "lsr %A0" CR_TAB
6486 "ror %B0" CR_TAB
6487 "lsr %A0" CR_TAB
6488 "ror %B0" CR_TAB
6489 "clr %A0");
6490
6491 case 15:
6492 *len = 4;
6493 return ("clr %B0" CR_TAB
6494 "lsr %A0" CR_TAB
6495 "ror %B0" CR_TAB
6496 "clr %A0");
6497 }
6498 len = t;
6499 }
6500 out_shift_with_cnt ("lsl %A0" CR_TAB
6501 "rol %B0", insn, operands, len, 2);
6502 return "";
6503 }
6504
6505
6506 /* 24-bit shift left */
6507
6508 const char*
avr_out_ashlpsi3(rtx_insn * insn,rtx * op,int * plen)6509 avr_out_ashlpsi3 (rtx_insn *insn, rtx *op, int *plen)
6510 {
6511 if (plen)
6512 *plen = 0;
6513
6514 if (CONST_INT_P (op[2]))
6515 {
6516 switch (INTVAL (op[2]))
6517 {
6518 default:
6519 if (INTVAL (op[2]) < 24)
6520 break;
6521
6522 return avr_asm_len ("clr %A0" CR_TAB
6523 "clr %B0" CR_TAB
6524 "clr %C0", op, plen, 3);
6525
6526 case 8:
6527 {
6528 int reg0 = REGNO (op[0]);
6529 int reg1 = REGNO (op[1]);
6530
6531 if (reg0 >= reg1)
6532 return avr_asm_len ("mov %C0,%B1" CR_TAB
6533 "mov %B0,%A1" CR_TAB
6534 "clr %A0", op, plen, 3);
6535 else
6536 return avr_asm_len ("clr %A0" CR_TAB
6537 "mov %B0,%A1" CR_TAB
6538 "mov %C0,%B1", op, plen, 3);
6539 }
6540
6541 case 16:
6542 {
6543 int reg0 = REGNO (op[0]);
6544 int reg1 = REGNO (op[1]);
6545
6546 if (reg0 + 2 != reg1)
6547 avr_asm_len ("mov %C0,%A0", op, plen, 1);
6548
6549 return avr_asm_len ("clr %B0" CR_TAB
6550 "clr %A0", op, plen, 2);
6551 }
6552
6553 case 23:
6554 return avr_asm_len ("clr %C0" CR_TAB
6555 "lsr %A0" CR_TAB
6556 "ror %C0" CR_TAB
6557 "clr %B0" CR_TAB
6558 "clr %A0", op, plen, 5);
6559 }
6560 }
6561
6562 out_shift_with_cnt ("lsl %A0" CR_TAB
6563 "rol %B0" CR_TAB
6564 "rol %C0", insn, op, plen, 3);
6565 return "";
6566 }
6567
6568
6569 /* 32bit shift left ((long)x << i) */
6570
6571 const char *
ashlsi3_out(rtx_insn * insn,rtx operands[],int * len)6572 ashlsi3_out (rtx_insn *insn, rtx operands[], int *len)
6573 {
6574 if (CONST_INT_P (operands[2]))
6575 {
6576 int k;
6577 int *t = len;
6578
6579 if (!len)
6580 len = &k;
6581
6582 switch (INTVAL (operands[2]))
6583 {
6584 default:
6585 if (INTVAL (operands[2]) < 32)
6586 break;
6587
6588 if (AVR_HAVE_MOVW)
6589 return *len = 3, ("clr %D0" CR_TAB
6590 "clr %C0" CR_TAB
6591 "movw %A0,%C0");
6592 *len = 4;
6593 return ("clr %D0" CR_TAB
6594 "clr %C0" CR_TAB
6595 "clr %B0" CR_TAB
6596 "clr %A0");
6597
6598 case 8:
6599 {
6600 int reg0 = true_regnum (operands[0]);
6601 int reg1 = true_regnum (operands[1]);
6602 *len = 4;
6603 if (reg0 >= reg1)
6604 return ("mov %D0,%C1" CR_TAB
6605 "mov %C0,%B1" CR_TAB
6606 "mov %B0,%A1" CR_TAB
6607 "clr %A0");
6608 else
6609 return ("clr %A0" CR_TAB
6610 "mov %B0,%A1" CR_TAB
6611 "mov %C0,%B1" CR_TAB
6612 "mov %D0,%C1");
6613 }
6614
6615 case 16:
6616 {
6617 int reg0 = true_regnum (operands[0]);
6618 int reg1 = true_regnum (operands[1]);
6619 if (reg0 + 2 == reg1)
6620 return *len = 2, ("clr %B0" CR_TAB
6621 "clr %A0");
6622 if (AVR_HAVE_MOVW)
6623 return *len = 3, ("movw %C0,%A1" CR_TAB
6624 "clr %B0" CR_TAB
6625 "clr %A0");
6626 else
6627 return *len = 4, ("mov %C0,%A1" CR_TAB
6628 "mov %D0,%B1" CR_TAB
6629 "clr %B0" CR_TAB
6630 "clr %A0");
6631 }
6632
6633 case 24:
6634 *len = 4;
6635 return ("mov %D0,%A1" CR_TAB
6636 "clr %C0" CR_TAB
6637 "clr %B0" CR_TAB
6638 "clr %A0");
6639
6640 case 31:
6641 *len = 6;
6642 return ("clr %D0" CR_TAB
6643 "lsr %A0" CR_TAB
6644 "ror %D0" CR_TAB
6645 "clr %C0" CR_TAB
6646 "clr %B0" CR_TAB
6647 "clr %A0");
6648 }
6649 len = t;
6650 }
6651 out_shift_with_cnt ("lsl %A0" CR_TAB
6652 "rol %B0" CR_TAB
6653 "rol %C0" CR_TAB
6654 "rol %D0", insn, operands, len, 4);
6655 return "";
6656 }
6657
6658 /* 8bit arithmetic shift right ((signed char)x >> i) */
6659
6660 const char *
ashrqi3_out(rtx_insn * insn,rtx operands[],int * len)6661 ashrqi3_out (rtx_insn *insn, rtx operands[], int *len)
6662 {
6663 if (CONST_INT_P (operands[2]))
6664 {
6665 int k;
6666
6667 if (!len)
6668 len = &k;
6669
6670 switch (INTVAL (operands[2]))
6671 {
6672 case 1:
6673 *len = 1;
6674 return "asr %0";
6675
6676 case 2:
6677 *len = 2;
6678 return ("asr %0" CR_TAB
6679 "asr %0");
6680
6681 case 3:
6682 *len = 3;
6683 return ("asr %0" CR_TAB
6684 "asr %0" CR_TAB
6685 "asr %0");
6686
6687 case 4:
6688 *len = 4;
6689 return ("asr %0" CR_TAB
6690 "asr %0" CR_TAB
6691 "asr %0" CR_TAB
6692 "asr %0");
6693
6694 case 5:
6695 *len = 5;
6696 return ("asr %0" CR_TAB
6697 "asr %0" CR_TAB
6698 "asr %0" CR_TAB
6699 "asr %0" CR_TAB
6700 "asr %0");
6701
6702 case 6:
6703 *len = 4;
6704 return ("bst %0,6" CR_TAB
6705 "lsl %0" CR_TAB
6706 "sbc %0,%0" CR_TAB
6707 "bld %0,0");
6708
6709 default:
6710 if (INTVAL (operands[2]) < 8)
6711 break;
6712
6713 /* fall through */
6714
6715 case 7:
6716 *len = 2;
6717 return ("lsl %0" CR_TAB
6718 "sbc %0,%0");
6719 }
6720 }
6721 else if (CONSTANT_P (operands[2]))
6722 fatal_insn ("internal compiler error. Incorrect shift:", insn);
6723
6724 out_shift_with_cnt ("asr %0",
6725 insn, operands, len, 1);
6726 return "";
6727 }
6728
6729
6730 /* 16bit arithmetic shift right ((signed short)x >> i) */
6731
6732 const char *
ashrhi3_out(rtx_insn * insn,rtx operands[],int * len)6733 ashrhi3_out (rtx_insn *insn, rtx operands[], int *len)
6734 {
6735 if (CONST_INT_P (operands[2]))
6736 {
6737 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL
6738 && XVECLEN (PATTERN (insn), 0) == 3
6739 && REG_P (operands[3]));
6740 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
6741 int k;
6742 int *t = len;
6743
6744 if (!len)
6745 len = &k;
6746
6747 switch (INTVAL (operands[2]))
6748 {
6749 case 4:
6750 case 5:
6751 /* XXX try to optimize this too? */
6752 break;
6753
6754 case 6:
6755 if (optimize_size)
6756 break; /* scratch ? 5 : 6 */
6757 *len = 8;
6758 return ("mov __tmp_reg__,%A0" CR_TAB
6759 "mov %A0,%B0" CR_TAB
6760 "lsl __tmp_reg__" CR_TAB
6761 "rol %A0" CR_TAB
6762 "sbc %B0,%B0" CR_TAB
6763 "lsl __tmp_reg__" CR_TAB
6764 "rol %A0" CR_TAB
6765 "rol %B0");
6766
6767 case 7:
6768 *len = 4;
6769 return ("lsl %A0" CR_TAB
6770 "mov %A0,%B0" CR_TAB
6771 "rol %A0" CR_TAB
6772 "sbc %B0,%B0");
6773
6774 case 8:
6775 {
6776 int reg0 = true_regnum (operands[0]);
6777 int reg1 = true_regnum (operands[1]);
6778
6779 if (reg0 == reg1)
6780 return *len = 3, ("mov %A0,%B0" CR_TAB
6781 "lsl %B0" CR_TAB
6782 "sbc %B0,%B0");
6783 else
6784 return *len = 4, ("mov %A0,%B1" CR_TAB
6785 "clr %B0" CR_TAB
6786 "sbrc %A0,7" CR_TAB
6787 "dec %B0");
6788 }
6789
6790 case 9:
6791 *len = 4;
6792 return ("mov %A0,%B0" CR_TAB
6793 "lsl %B0" CR_TAB
6794 "sbc %B0,%B0" CR_TAB
6795 "asr %A0");
6796
6797 case 10:
6798 *len = 5;
6799 return ("mov %A0,%B0" CR_TAB
6800 "lsl %B0" CR_TAB
6801 "sbc %B0,%B0" CR_TAB
6802 "asr %A0" CR_TAB
6803 "asr %A0");
6804
6805 case 11:
6806 if (AVR_HAVE_MUL && ldi_ok)
6807 {
6808 *len = 5;
6809 return ("ldi %A0,0x20" CR_TAB
6810 "muls %B0,%A0" CR_TAB
6811 "mov %A0,r1" CR_TAB
6812 "sbc %B0,%B0" CR_TAB
6813 "clr __zero_reg__");
6814 }
6815 if (optimize_size && scratch)
6816 break; /* 5 */
6817 *len = 6;
6818 return ("mov %A0,%B0" CR_TAB
6819 "lsl %B0" CR_TAB
6820 "sbc %B0,%B0" CR_TAB
6821 "asr %A0" CR_TAB
6822 "asr %A0" CR_TAB
6823 "asr %A0");
6824
6825 case 12:
6826 if (AVR_HAVE_MUL && ldi_ok)
6827 {
6828 *len = 5;
6829 return ("ldi %A0,0x10" CR_TAB
6830 "muls %B0,%A0" CR_TAB
6831 "mov %A0,r1" CR_TAB
6832 "sbc %B0,%B0" CR_TAB
6833 "clr __zero_reg__");
6834 }
6835 if (optimize_size && scratch)
6836 break; /* 5 */
6837 *len = 7;
6838 return ("mov %A0,%B0" CR_TAB
6839 "lsl %B0" CR_TAB
6840 "sbc %B0,%B0" CR_TAB
6841 "asr %A0" CR_TAB
6842 "asr %A0" CR_TAB
6843 "asr %A0" CR_TAB
6844 "asr %A0");
6845
6846 case 13:
6847 if (AVR_HAVE_MUL && ldi_ok)
6848 {
6849 *len = 5;
6850 return ("ldi %A0,0x08" CR_TAB
6851 "muls %B0,%A0" CR_TAB
6852 "mov %A0,r1" CR_TAB
6853 "sbc %B0,%B0" CR_TAB
6854 "clr __zero_reg__");
6855 }
6856 if (optimize_size)
6857 break; /* scratch ? 5 : 7 */
6858 *len = 8;
6859 return ("mov %A0,%B0" CR_TAB
6860 "lsl %B0" CR_TAB
6861 "sbc %B0,%B0" CR_TAB
6862 "asr %A0" CR_TAB
6863 "asr %A0" CR_TAB
6864 "asr %A0" CR_TAB
6865 "asr %A0" CR_TAB
6866 "asr %A0");
6867
6868 case 14:
6869 *len = 5;
6870 return ("lsl %B0" CR_TAB
6871 "sbc %A0,%A0" CR_TAB
6872 "lsl %B0" CR_TAB
6873 "mov %B0,%A0" CR_TAB
6874 "rol %A0");
6875
6876 default:
6877 if (INTVAL (operands[2]) < 16)
6878 break;
6879
6880 /* fall through */
6881
6882 case 15:
6883 return *len = 3, ("lsl %B0" CR_TAB
6884 "sbc %A0,%A0" CR_TAB
6885 "mov %B0,%A0");
6886 }
6887 len = t;
6888 }
6889 out_shift_with_cnt ("asr %B0" CR_TAB
6890 "ror %A0", insn, operands, len, 2);
6891 return "";
6892 }
6893
6894
6895 /* 24-bit arithmetic shift right */
6896
6897 const char*
avr_out_ashrpsi3(rtx_insn * insn,rtx * op,int * plen)6898 avr_out_ashrpsi3 (rtx_insn *insn, rtx *op, int *plen)
6899 {
6900 int dest = REGNO (op[0]);
6901 int src = REGNO (op[1]);
6902
6903 if (CONST_INT_P (op[2]))
6904 {
6905 if (plen)
6906 *plen = 0;
6907
6908 switch (INTVAL (op[2]))
6909 {
6910 case 8:
6911 if (dest <= src)
6912 return avr_asm_len ("mov %A0,%B1" CR_TAB
6913 "mov %B0,%C1" CR_TAB
6914 "clr %C0" CR_TAB
6915 "sbrc %B0,7" CR_TAB
6916 "dec %C0", op, plen, 5);
6917 else
6918 return avr_asm_len ("clr %C0" CR_TAB
6919 "sbrc %C1,7" CR_TAB
6920 "dec %C0" CR_TAB
6921 "mov %B0,%C1" CR_TAB
6922 "mov %A0,%B1", op, plen, 5);
6923
6924 case 16:
6925 if (dest != src + 2)
6926 avr_asm_len ("mov %A0,%C1", op, plen, 1);
6927
6928 return avr_asm_len ("clr %B0" CR_TAB
6929 "sbrc %A0,7" CR_TAB
6930 "com %B0" CR_TAB
6931 "mov %C0,%B0", op, plen, 4);
6932
6933 default:
6934 if (INTVAL (op[2]) < 24)
6935 break;
6936
6937 /* fall through */
6938
6939 case 23:
6940 return avr_asm_len ("lsl %C0" CR_TAB
6941 "sbc %A0,%A0" CR_TAB
6942 "mov %B0,%A0" CR_TAB
6943 "mov %C0,%A0", op, plen, 4);
6944 } /* switch */
6945 }
6946
6947 out_shift_with_cnt ("asr %C0" CR_TAB
6948 "ror %B0" CR_TAB
6949 "ror %A0", insn, op, plen, 3);
6950 return "";
6951 }
6952
6953
6954 /* 32-bit arithmetic shift right ((signed long)x >> i) */
6955
6956 const char *
ashrsi3_out(rtx_insn * insn,rtx operands[],int * len)6957 ashrsi3_out (rtx_insn *insn, rtx operands[], int *len)
6958 {
6959 if (CONST_INT_P (operands[2]))
6960 {
6961 int k;
6962 int *t = len;
6963
6964 if (!len)
6965 len = &k;
6966
6967 switch (INTVAL (operands[2]))
6968 {
6969 case 8:
6970 {
6971 int reg0 = true_regnum (operands[0]);
6972 int reg1 = true_regnum (operands[1]);
6973 *len=6;
6974 if (reg0 <= reg1)
6975 return ("mov %A0,%B1" CR_TAB
6976 "mov %B0,%C1" CR_TAB
6977 "mov %C0,%D1" CR_TAB
6978 "clr %D0" CR_TAB
6979 "sbrc %C0,7" CR_TAB
6980 "dec %D0");
6981 else
6982 return ("clr %D0" CR_TAB
6983 "sbrc %D1,7" CR_TAB
6984 "dec %D0" CR_TAB
6985 "mov %C0,%D1" CR_TAB
6986 "mov %B0,%C1" CR_TAB
6987 "mov %A0,%B1");
6988 }
6989
6990 case 16:
6991 {
6992 int reg0 = true_regnum (operands[0]);
6993 int reg1 = true_regnum (operands[1]);
6994
6995 if (reg0 == reg1 + 2)
6996 return *len = 4, ("clr %D0" CR_TAB
6997 "sbrc %B0,7" CR_TAB
6998 "com %D0" CR_TAB
6999 "mov %C0,%D0");
7000 if (AVR_HAVE_MOVW)
7001 return *len = 5, ("movw %A0,%C1" CR_TAB
7002 "clr %D0" CR_TAB
7003 "sbrc %B0,7" CR_TAB
7004 "com %D0" CR_TAB
7005 "mov %C0,%D0");
7006 else
7007 return *len = 6, ("mov %B0,%D1" CR_TAB
7008 "mov %A0,%C1" CR_TAB
7009 "clr %D0" CR_TAB
7010 "sbrc %B0,7" CR_TAB
7011 "com %D0" CR_TAB
7012 "mov %C0,%D0");
7013 }
7014
7015 case 24:
7016 return *len = 6, ("mov %A0,%D1" CR_TAB
7017 "clr %D0" CR_TAB
7018 "sbrc %A0,7" CR_TAB
7019 "com %D0" CR_TAB
7020 "mov %B0,%D0" CR_TAB
7021 "mov %C0,%D0");
7022
7023 default:
7024 if (INTVAL (operands[2]) < 32)
7025 break;
7026
7027 /* fall through */
7028
7029 case 31:
7030 if (AVR_HAVE_MOVW)
7031 return *len = 4, ("lsl %D0" CR_TAB
7032 "sbc %A0,%A0" CR_TAB
7033 "mov %B0,%A0" CR_TAB
7034 "movw %C0,%A0");
7035 else
7036 return *len = 5, ("lsl %D0" CR_TAB
7037 "sbc %A0,%A0" CR_TAB
7038 "mov %B0,%A0" CR_TAB
7039 "mov %C0,%A0" CR_TAB
7040 "mov %D0,%A0");
7041 }
7042 len = t;
7043 }
7044 out_shift_with_cnt ("asr %D0" CR_TAB
7045 "ror %C0" CR_TAB
7046 "ror %B0" CR_TAB
7047 "ror %A0", insn, operands, len, 4);
7048 return "";
7049 }
7050
7051 /* 8-bit logic shift right ((unsigned char)x >> i) */
7052
7053 const char *
lshrqi3_out(rtx_insn * insn,rtx operands[],int * len)7054 lshrqi3_out (rtx_insn *insn, rtx operands[], int *len)
7055 {
7056 if (CONST_INT_P (operands[2]))
7057 {
7058 int k;
7059
7060 if (!len)
7061 len = &k;
7062
7063 switch (INTVAL (operands[2]))
7064 {
7065 default:
7066 if (INTVAL (operands[2]) < 8)
7067 break;
7068
7069 *len = 1;
7070 return "clr %0";
7071
7072 case 1:
7073 *len = 1;
7074 return "lsr %0";
7075
7076 case 2:
7077 *len = 2;
7078 return ("lsr %0" CR_TAB
7079 "lsr %0");
7080 case 3:
7081 *len = 3;
7082 return ("lsr %0" CR_TAB
7083 "lsr %0" CR_TAB
7084 "lsr %0");
7085
7086 case 4:
7087 if (test_hard_reg_class (LD_REGS, operands[0]))
7088 {
7089 *len=2;
7090 return ("swap %0" CR_TAB
7091 "andi %0,0x0f");
7092 }
7093 *len = 4;
7094 return ("lsr %0" CR_TAB
7095 "lsr %0" CR_TAB
7096 "lsr %0" CR_TAB
7097 "lsr %0");
7098
7099 case 5:
7100 if (test_hard_reg_class (LD_REGS, operands[0]))
7101 {
7102 *len = 3;
7103 return ("swap %0" CR_TAB
7104 "lsr %0" CR_TAB
7105 "andi %0,0x7");
7106 }
7107 *len = 5;
7108 return ("lsr %0" CR_TAB
7109 "lsr %0" CR_TAB
7110 "lsr %0" CR_TAB
7111 "lsr %0" CR_TAB
7112 "lsr %0");
7113
7114 case 6:
7115 if (test_hard_reg_class (LD_REGS, operands[0]))
7116 {
7117 *len = 4;
7118 return ("swap %0" CR_TAB
7119 "lsr %0" CR_TAB
7120 "lsr %0" CR_TAB
7121 "andi %0,0x3");
7122 }
7123 *len = 6;
7124 return ("lsr %0" CR_TAB
7125 "lsr %0" CR_TAB
7126 "lsr %0" CR_TAB
7127 "lsr %0" CR_TAB
7128 "lsr %0" CR_TAB
7129 "lsr %0");
7130
7131 case 7:
7132 *len = 3;
7133 return ("rol %0" CR_TAB
7134 "clr %0" CR_TAB
7135 "rol %0");
7136 }
7137 }
7138 else if (CONSTANT_P (operands[2]))
7139 fatal_insn ("internal compiler error. Incorrect shift:", insn);
7140
7141 out_shift_with_cnt ("lsr %0",
7142 insn, operands, len, 1);
7143 return "";
7144 }
7145
7146 /* 16-bit logic shift right ((unsigned short)x >> i) */
7147
7148 const char *
lshrhi3_out(rtx_insn * insn,rtx operands[],int * len)7149 lshrhi3_out (rtx_insn *insn, rtx operands[], int *len)
7150 {
7151 if (CONST_INT_P (operands[2]))
7152 {
7153 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL
7154 && XVECLEN (PATTERN (insn), 0) == 3
7155 && REG_P (operands[3]));
7156 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
7157 int k;
7158 int *t = len;
7159
7160 if (!len)
7161 len = &k;
7162
7163 switch (INTVAL (operands[2]))
7164 {
7165 default:
7166 if (INTVAL (operands[2]) < 16)
7167 break;
7168
7169 *len = 2;
7170 return ("clr %B0" CR_TAB
7171 "clr %A0");
7172
7173 case 4:
7174 if (optimize_size && scratch)
7175 break; /* 5 */
7176 if (ldi_ok)
7177 {
7178 *len = 6;
7179 return ("swap %B0" CR_TAB
7180 "swap %A0" CR_TAB
7181 "andi %A0,0x0f" CR_TAB
7182 "eor %A0,%B0" CR_TAB
7183 "andi %B0,0x0f" CR_TAB
7184 "eor %A0,%B0");
7185 }
7186 if (scratch)
7187 {
7188 *len = 7;
7189 return ("swap %B0" CR_TAB
7190 "swap %A0" CR_TAB
7191 "ldi %3,0x0f" CR_TAB
7192 "and %A0,%3" CR_TAB
7193 "eor %A0,%B0" CR_TAB
7194 "and %B0,%3" CR_TAB
7195 "eor %A0,%B0");
7196 }
7197 break; /* optimize_size ? 6 : 8 */
7198
7199 case 5:
7200 if (optimize_size)
7201 break; /* scratch ? 5 : 6 */
7202 if (ldi_ok)
7203 {
7204 *len = 8;
7205 return ("lsr %B0" CR_TAB
7206 "ror %A0" CR_TAB
7207 "swap %B0" CR_TAB
7208 "swap %A0" CR_TAB
7209 "andi %A0,0x0f" CR_TAB
7210 "eor %A0,%B0" CR_TAB
7211 "andi %B0,0x0f" CR_TAB
7212 "eor %A0,%B0");
7213 }
7214 if (scratch)
7215 {
7216 *len = 9;
7217 return ("lsr %B0" CR_TAB
7218 "ror %A0" CR_TAB
7219 "swap %B0" CR_TAB
7220 "swap %A0" CR_TAB
7221 "ldi %3,0x0f" CR_TAB
7222 "and %A0,%3" CR_TAB
7223 "eor %A0,%B0" CR_TAB
7224 "and %B0,%3" CR_TAB
7225 "eor %A0,%B0");
7226 }
7227 break; /* 10 */
7228
7229 case 6:
7230 if (optimize_size)
7231 break; /* scratch ? 5 : 6 */
7232 *len = 9;
7233 return ("clr __tmp_reg__" CR_TAB
7234 "lsl %A0" CR_TAB
7235 "rol %B0" CR_TAB
7236 "rol __tmp_reg__" CR_TAB
7237 "lsl %A0" CR_TAB
7238 "rol %B0" CR_TAB
7239 "rol __tmp_reg__" CR_TAB
7240 "mov %A0,%B0" CR_TAB
7241 "mov %B0,__tmp_reg__");
7242
7243 case 7:
7244 *len = 5;
7245 return ("lsl %A0" CR_TAB
7246 "mov %A0,%B0" CR_TAB
7247 "rol %A0" CR_TAB
7248 "sbc %B0,%B0" CR_TAB
7249 "neg %B0");
7250
7251 case 8:
7252 return *len = 2, ("mov %A0,%B1" CR_TAB
7253 "clr %B0");
7254
7255 case 9:
7256 *len = 3;
7257 return ("mov %A0,%B0" CR_TAB
7258 "clr %B0" CR_TAB
7259 "lsr %A0");
7260
7261 case 10:
7262 *len = 4;
7263 return ("mov %A0,%B0" CR_TAB
7264 "clr %B0" CR_TAB
7265 "lsr %A0" CR_TAB
7266 "lsr %A0");
7267
7268 case 11:
7269 *len = 5;
7270 return ("mov %A0,%B0" CR_TAB
7271 "clr %B0" CR_TAB
7272 "lsr %A0" CR_TAB
7273 "lsr %A0" CR_TAB
7274 "lsr %A0");
7275
7276 case 12:
7277 if (ldi_ok)
7278 {
7279 *len = 4;
7280 return ("mov %A0,%B0" CR_TAB
7281 "clr %B0" CR_TAB
7282 "swap %A0" CR_TAB
7283 "andi %A0,0x0f");
7284 }
7285 if (scratch)
7286 {
7287 *len = 5;
7288 return ("mov %A0,%B0" CR_TAB
7289 "clr %B0" CR_TAB
7290 "swap %A0" CR_TAB
7291 "ldi %3,0x0f" CR_TAB
7292 "and %A0,%3");
7293 }
7294 *len = 6;
7295 return ("mov %A0,%B0" CR_TAB
7296 "clr %B0" CR_TAB
7297 "lsr %A0" CR_TAB
7298 "lsr %A0" CR_TAB
7299 "lsr %A0" CR_TAB
7300 "lsr %A0");
7301
7302 case 13:
7303 if (ldi_ok)
7304 {
7305 *len = 5;
7306 return ("mov %A0,%B0" CR_TAB
7307 "clr %B0" CR_TAB
7308 "swap %A0" CR_TAB
7309 "lsr %A0" CR_TAB
7310 "andi %A0,0x07");
7311 }
7312 if (AVR_HAVE_MUL && scratch)
7313 {
7314 *len = 5;
7315 return ("ldi %3,0x08" CR_TAB
7316 "mul %B0,%3" CR_TAB
7317 "mov %A0,r1" CR_TAB
7318 "clr %B0" CR_TAB
7319 "clr __zero_reg__");
7320 }
7321 if (optimize_size && scratch)
7322 break; /* 5 */
7323 if (scratch)
7324 {
7325 *len = 6;
7326 return ("mov %A0,%B0" CR_TAB
7327 "clr %B0" CR_TAB
7328 "swap %A0" CR_TAB
7329 "lsr %A0" CR_TAB
7330 "ldi %3,0x07" CR_TAB
7331 "and %A0,%3");
7332 }
7333 if (AVR_HAVE_MUL)
7334 {
7335 *len = 6;
7336 return ("set" CR_TAB
7337 "bld r1,3" CR_TAB
7338 "mul %B0,r1" CR_TAB
7339 "mov %A0,r1" CR_TAB
7340 "clr %B0" CR_TAB
7341 "clr __zero_reg__");
7342 }
7343 *len = 7;
7344 return ("mov %A0,%B0" CR_TAB
7345 "clr %B0" CR_TAB
7346 "lsr %A0" CR_TAB
7347 "lsr %A0" CR_TAB
7348 "lsr %A0" CR_TAB
7349 "lsr %A0" CR_TAB
7350 "lsr %A0");
7351
7352 case 14:
7353 if (AVR_HAVE_MUL && ldi_ok)
7354 {
7355 *len = 5;
7356 return ("ldi %A0,0x04" CR_TAB
7357 "mul %B0,%A0" CR_TAB
7358 "mov %A0,r1" CR_TAB
7359 "clr %B0" CR_TAB
7360 "clr __zero_reg__");
7361 }
7362 if (AVR_HAVE_MUL && scratch)
7363 {
7364 *len = 5;
7365 return ("ldi %3,0x04" CR_TAB
7366 "mul %B0,%3" CR_TAB
7367 "mov %A0,r1" CR_TAB
7368 "clr %B0" CR_TAB
7369 "clr __zero_reg__");
7370 }
7371 if (optimize_size && ldi_ok)
7372 {
7373 *len = 5;
7374 return ("mov %A0,%B0" CR_TAB
7375 "ldi %B0,6" "\n1:\t"
7376 "lsr %A0" CR_TAB
7377 "dec %B0" CR_TAB
7378 "brne 1b");
7379 }
7380 if (optimize_size && scratch)
7381 break; /* 5 */
7382 *len = 6;
7383 return ("clr %A0" CR_TAB
7384 "lsl %B0" CR_TAB
7385 "rol %A0" CR_TAB
7386 "lsl %B0" CR_TAB
7387 "rol %A0" CR_TAB
7388 "clr %B0");
7389
7390 case 15:
7391 *len = 4;
7392 return ("clr %A0" CR_TAB
7393 "lsl %B0" CR_TAB
7394 "rol %A0" CR_TAB
7395 "clr %B0");
7396 }
7397 len = t;
7398 }
7399 out_shift_with_cnt ("lsr %B0" CR_TAB
7400 "ror %A0", insn, operands, len, 2);
7401 return "";
7402 }
7403
7404
7405 /* 24-bit logic shift right */
7406
7407 const char*
avr_out_lshrpsi3(rtx_insn * insn,rtx * op,int * plen)7408 avr_out_lshrpsi3 (rtx_insn *insn, rtx *op, int *plen)
7409 {
7410 int dest = REGNO (op[0]);
7411 int src = REGNO (op[1]);
7412
7413 if (CONST_INT_P (op[2]))
7414 {
7415 if (plen)
7416 *plen = 0;
7417
7418 switch (INTVAL (op[2]))
7419 {
7420 case 8:
7421 if (dest <= src)
7422 return avr_asm_len ("mov %A0,%B1" CR_TAB
7423 "mov %B0,%C1" CR_TAB
7424 "clr %C0", op, plen, 3);
7425 else
7426 return avr_asm_len ("clr %C0" CR_TAB
7427 "mov %B0,%C1" CR_TAB
7428 "mov %A0,%B1", op, plen, 3);
7429
7430 case 16:
7431 if (dest != src + 2)
7432 avr_asm_len ("mov %A0,%C1", op, plen, 1);
7433
7434 return avr_asm_len ("clr %B0" CR_TAB
7435 "clr %C0", op, plen, 2);
7436
7437 default:
7438 if (INTVAL (op[2]) < 24)
7439 break;
7440
7441 /* fall through */
7442
7443 case 23:
7444 return avr_asm_len ("clr %A0" CR_TAB
7445 "sbrc %C0,7" CR_TAB
7446 "inc %A0" CR_TAB
7447 "clr %B0" CR_TAB
7448 "clr %C0", op, plen, 5);
7449 } /* switch */
7450 }
7451
7452 out_shift_with_cnt ("lsr %C0" CR_TAB
7453 "ror %B0" CR_TAB
7454 "ror %A0", insn, op, plen, 3);
7455 return "";
7456 }
7457
7458
7459 /* 32-bit logic shift right ((unsigned int)x >> i) */
7460
7461 const char *
lshrsi3_out(rtx_insn * insn,rtx operands[],int * len)7462 lshrsi3_out (rtx_insn *insn, rtx operands[], int *len)
7463 {
7464 if (CONST_INT_P (operands[2]))
7465 {
7466 int k;
7467 int *t = len;
7468
7469 if (!len)
7470 len = &k;
7471
7472 switch (INTVAL (operands[2]))
7473 {
7474 default:
7475 if (INTVAL (operands[2]) < 32)
7476 break;
7477
7478 if (AVR_HAVE_MOVW)
7479 return *len = 3, ("clr %D0" CR_TAB
7480 "clr %C0" CR_TAB
7481 "movw %A0,%C0");
7482 *len = 4;
7483 return ("clr %D0" CR_TAB
7484 "clr %C0" CR_TAB
7485 "clr %B0" CR_TAB
7486 "clr %A0");
7487
7488 case 8:
7489 {
7490 int reg0 = true_regnum (operands[0]);
7491 int reg1 = true_regnum (operands[1]);
7492 *len = 4;
7493 if (reg0 <= reg1)
7494 return ("mov %A0,%B1" CR_TAB
7495 "mov %B0,%C1" CR_TAB
7496 "mov %C0,%D1" CR_TAB
7497 "clr %D0");
7498 else
7499 return ("clr %D0" CR_TAB
7500 "mov %C0,%D1" CR_TAB
7501 "mov %B0,%C1" CR_TAB
7502 "mov %A0,%B1");
7503 }
7504
7505 case 16:
7506 {
7507 int reg0 = true_regnum (operands[0]);
7508 int reg1 = true_regnum (operands[1]);
7509
7510 if (reg0 == reg1 + 2)
7511 return *len = 2, ("clr %C0" CR_TAB
7512 "clr %D0");
7513 if (AVR_HAVE_MOVW)
7514 return *len = 3, ("movw %A0,%C1" CR_TAB
7515 "clr %C0" CR_TAB
7516 "clr %D0");
7517 else
7518 return *len = 4, ("mov %B0,%D1" CR_TAB
7519 "mov %A0,%C1" CR_TAB
7520 "clr %C0" CR_TAB
7521 "clr %D0");
7522 }
7523
7524 case 24:
7525 return *len = 4, ("mov %A0,%D1" CR_TAB
7526 "clr %B0" CR_TAB
7527 "clr %C0" CR_TAB
7528 "clr %D0");
7529
7530 case 31:
7531 *len = 6;
7532 return ("clr %A0" CR_TAB
7533 "sbrc %D0,7" CR_TAB
7534 "inc %A0" CR_TAB
7535 "clr %B0" CR_TAB
7536 "clr %C0" CR_TAB
7537 "clr %D0");
7538 }
7539 len = t;
7540 }
7541 out_shift_with_cnt ("lsr %D0" CR_TAB
7542 "ror %C0" CR_TAB
7543 "ror %B0" CR_TAB
7544 "ror %A0", insn, operands, len, 4);
7545 return "";
7546 }
7547
7548
7549 /* Output addition of register XOP[0] and compile time constant XOP[2].
7550 CODE == PLUS: perform addition by using ADD instructions or
7551 CODE == MINUS: perform addition by using SUB instructions:
7552
7553 XOP[0] = XOP[0] + XOP[2]
7554
7555 Or perform addition/subtraction with register XOP[2] depending on CODE:
7556
7557 XOP[0] = XOP[0] +/- XOP[2]
7558
7559 If PLEN == NULL, print assembler instructions to perform the operation;
7560 otherwise, set *PLEN to the length of the instruction sequence (in words)
7561 printed with PLEN == NULL. XOP[3] is an 8-bit scratch register or NULL_RTX.
7562 Set *PCC to effect on cc0 according to respective CC_* insn attribute.
7563
7564 CODE_SAT == UNKNOWN: Perform ordinary, non-saturating operation.
7565 CODE_SAT != UNKNOWN: Perform operation and saturate according to CODE_SAT.
7566 If CODE_SAT != UNKNOWN then SIGN contains the sign of the summand resp.
7567 the subtrahend in the original insn, provided it is a compile time constant.
7568 In all other cases, SIGN is 0.
7569
7570 If OUT_LABEL is true, print the final 0: label which is needed for
7571 saturated addition / subtraction. The only case where OUT_LABEL = false
7572 is useful is for saturated addition / subtraction performed during
7573 fixed-point rounding, cf. `avr_out_round'. */
7574
7575 static void
avr_out_plus_1(rtx * xop,int * plen,enum rtx_code code,int * pcc,enum rtx_code code_sat,int sign,bool out_label)7576 avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc,
7577 enum rtx_code code_sat, int sign, bool out_label)
7578 {
7579 /* MODE of the operation. */
7580 machine_mode mode = GET_MODE (xop[0]);
7581
7582 /* INT_MODE of the same size. */
7583 scalar_int_mode imode = int_mode_for_mode (mode).require ();
7584
7585 /* Number of bytes to operate on. */
7586 int n_bytes = GET_MODE_SIZE (mode);
7587
7588 /* Value (0..0xff) held in clobber register op[3] or -1 if unknown. */
7589 int clobber_val = -1;
7590
7591 /* op[0]: 8-bit destination register
7592 op[1]: 8-bit const int
7593 op[2]: 8-bit scratch register */
7594 rtx op[3];
7595
7596 /* Started the operation? Before starting the operation we may skip
7597 adding 0. This is no more true after the operation started because
7598 carry must be taken into account. */
7599 bool started = false;
7600
7601 /* Value to add. There are two ways to add VAL: R += VAL and R -= -VAL. */
7602 rtx xval = xop[2];
7603
7604 /* Output a BRVC instruction. Only needed with saturation. */
7605 bool out_brvc = true;
7606
7607 if (plen)
7608 *plen = 0;
7609
7610 if (REG_P (xop[2]))
7611 {
7612 *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_CLOBBER;
7613
7614 for (int i = 0; i < n_bytes; i++)
7615 {
7616 /* We operate byte-wise on the destination. */
7617 op[0] = simplify_gen_subreg (QImode, xop[0], mode, i);
7618 op[1] = simplify_gen_subreg (QImode, xop[2], mode, i);
7619
7620 if (i == 0)
7621 avr_asm_len (code == PLUS ? "add %0,%1" : "sub %0,%1",
7622 op, plen, 1);
7623 else
7624 avr_asm_len (code == PLUS ? "adc %0,%1" : "sbc %0,%1",
7625 op, plen, 1);
7626 }
7627
7628 if (reg_overlap_mentioned_p (xop[0], xop[2]))
7629 {
7630 gcc_assert (REGNO (xop[0]) == REGNO (xop[2]));
7631
7632 if (MINUS == code)
7633 return;
7634 }
7635
7636 goto saturate;
7637 }
7638
7639 /* Except in the case of ADIW with 16-bit register (see below)
7640 addition does not set cc0 in a usable way. */
7641
7642 *pcc = (MINUS == code) ? CC_SET_CZN : CC_CLOBBER;
7643
7644 if (CONST_FIXED_P (xval))
7645 xval = avr_to_int_mode (xval);
7646
7647 /* Adding/Subtracting zero is a no-op. */
7648
7649 if (xval == const0_rtx)
7650 {
7651 *pcc = CC_NONE;
7652 return;
7653 }
7654
7655 if (MINUS == code)
7656 xval = simplify_unary_operation (NEG, imode, xval, imode);
7657
7658 op[2] = xop[3];
7659
7660 if (SS_PLUS == code_sat && MINUS == code
7661 && sign < 0
7662 && 0x80 == (INTVAL (simplify_gen_subreg (QImode, xval, imode, n_bytes-1))
7663 & GET_MODE_MASK (QImode)))
7664 {
7665 /* We compute x + 0x80 by means of SUB instructions. We negated the
7666 constant subtrahend above and are left with x - (-128) so that we
7667 need something like SUBI r,128 which does not exist because SUBI sets
7668 V according to the sign of the subtrahend. Notice the only case
7669 where this must be done is when NEG overflowed in case [2s] because
7670 the V computation needs the right sign of the subtrahend. */
7671
7672 rtx msb = simplify_gen_subreg (QImode, xop[0], mode, n_bytes - 1);
7673
7674 avr_asm_len ("subi %0,128" CR_TAB
7675 "brmi 0f", &msb, plen, 2);
7676 out_brvc = false;
7677
7678 goto saturate;
7679 }
7680
7681 for (int i = 0; i < n_bytes; i++)
7682 {
7683 /* We operate byte-wise on the destination. */
7684 rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
7685 rtx xval8 = simplify_gen_subreg (QImode, xval, imode, i);
7686
7687 /* 8-bit value to operate with this byte. */
7688 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
7689
7690 /* Registers R16..R31 can operate with immediate. */
7691 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
7692
7693 op[0] = reg8;
7694 op[1] = gen_int_mode (val8, QImode);
7695
7696 /* To get usable cc0 no low-bytes must have been skipped. */
7697
7698 if (i && !started)
7699 *pcc = CC_CLOBBER;
7700
7701 if (!started
7702 && i % 2 == 0
7703 && i + 2 <= n_bytes
7704 && test_hard_reg_class (ADDW_REGS, reg8))
7705 {
7706 rtx xval16 = simplify_gen_subreg (HImode, xval, imode, i);
7707 unsigned int val16 = UINTVAL (xval16) & GET_MODE_MASK (HImode);
7708
7709 /* Registers R24, X, Y, Z can use ADIW/SBIW with constants < 64
7710 i.e. operate word-wise. */
7711
7712 if (val16 < 64)
7713 {
7714 if (val16 != 0)
7715 {
7716 started = true;
7717 avr_asm_len (code == PLUS ? "adiw %0,%1" : "sbiw %0,%1",
7718 op, plen, 1);
7719
7720 if (n_bytes == 2 && PLUS == code)
7721 *pcc = CC_SET_CZN;
7722 }
7723
7724 i++;
7725 continue;
7726 }
7727 }
7728
7729 if (val8 == 0)
7730 {
7731 if (started)
7732 avr_asm_len (code == PLUS
7733 ? "adc %0,__zero_reg__" : "sbc %0,__zero_reg__",
7734 op, plen, 1);
7735 continue;
7736 }
7737 else if ((val8 == 1 || val8 == 0xff)
7738 && UNKNOWN == code_sat
7739 && !started
7740 && i == n_bytes - 1)
7741 {
7742 avr_asm_len ((code == PLUS) ^ (val8 == 1) ? "dec %0" : "inc %0",
7743 op, plen, 1);
7744 *pcc = CC_CLOBBER;
7745 break;
7746 }
7747
7748 switch (code)
7749 {
7750 case PLUS:
7751
7752 gcc_assert (plen != NULL || (op[2] && REG_P (op[2])));
7753
7754 if (plen != NULL && UNKNOWN != code_sat)
7755 {
7756 /* This belongs to the x + 0x80 corner case. The code with
7757 ADD instruction is not smaller, thus make this case
7758 expensive so that the caller won't pick it. */
7759
7760 *plen += 10;
7761 break;
7762 }
7763
7764 if (clobber_val != (int) val8)
7765 avr_asm_len ("ldi %2,%1", op, plen, 1);
7766 clobber_val = (int) val8;
7767
7768 avr_asm_len (started ? "adc %0,%2" : "add %0,%2", op, plen, 1);
7769
7770 break; /* PLUS */
7771
7772 case MINUS:
7773
7774 if (ld_reg_p)
7775 avr_asm_len (started ? "sbci %0,%1" : "subi %0,%1", op, plen, 1);
7776 else
7777 {
7778 gcc_assert (plen != NULL || REG_P (op[2]));
7779
7780 if (clobber_val != (int) val8)
7781 avr_asm_len ("ldi %2,%1", op, plen, 1);
7782 clobber_val = (int) val8;
7783
7784 avr_asm_len (started ? "sbc %0,%2" : "sub %0,%2", op, plen, 1);
7785 }
7786
7787 break; /* MINUS */
7788
7789 default:
7790 /* Unknown code */
7791 gcc_unreachable();
7792 }
7793
7794 started = true;
7795
7796 } /* for all sub-bytes */
7797
7798 saturate:
7799
7800 if (UNKNOWN == code_sat)
7801 return;
7802
7803 *pcc = (int) CC_CLOBBER;
7804
7805 /* Vanilla addition/subtraction is done. We are left with saturation.
7806
7807 We have to compute A = A <op> B where A is a register and
7808 B is a register or a non-zero compile time constant CONST.
7809 A is register class "r" if unsigned && B is REG. Otherwise, A is in "d".
7810 B stands for the original operand $2 in INSN. In the case of B = CONST,
7811 SIGN in { -1, 1 } is the sign of B. Otherwise, SIGN is 0.
7812
7813 CODE is the instruction flavor we use in the asm sequence to perform <op>.
7814
7815
7816 unsigned
7817 operation | code | sat if | b is | sat value | case
7818 -----------------+-------+----------+--------------+-----------+-------
7819 + as a + b | add | C == 1 | const, reg | u+ = 0xff | [1u]
7820 + as a - (-b) | sub | C == 0 | const | u+ = 0xff | [2u]
7821 - as a - b | sub | C == 1 | const, reg | u- = 0 | [3u]
7822 - as a + (-b) | add | C == 0 | const | u- = 0 | [4u]
7823
7824
7825 signed
7826 operation | code | sat if | b is | sat value | case
7827 -----------------+-------+----------+--------------+-----------+-------
7828 + as a + b | add | V == 1 | const, reg | s+ | [1s]
7829 + as a - (-b) | sub | V == 1 | const | s+ | [2s]
7830 - as a - b | sub | V == 1 | const, reg | s- | [3s]
7831 - as a + (-b) | add | V == 1 | const | s- | [4s]
7832
7833 s+ = b < 0 ? -0x80 : 0x7f
7834 s- = b < 0 ? 0x7f : -0x80
7835
7836 The cases a - b actually perform a - (-(-b)) if B is CONST.
7837 */
7838
7839 op[0] = simplify_gen_subreg (QImode, xop[0], mode, n_bytes-1);
7840 op[1] = n_bytes > 1
7841 ? simplify_gen_subreg (QImode, xop[0], mode, n_bytes-2)
7842 : NULL_RTX;
7843
7844 bool need_copy = true;
7845 int len_call = 1 + AVR_HAVE_JMP_CALL;
7846
7847 switch (code_sat)
7848 {
7849 default:
7850 gcc_unreachable();
7851
7852 case SS_PLUS:
7853 case SS_MINUS:
7854
7855 if (out_brvc)
7856 avr_asm_len ("brvc 0f", op, plen, 1);
7857
7858 if (reg_overlap_mentioned_p (xop[0], xop[2]))
7859 {
7860 /* [1s,reg] */
7861
7862 if (n_bytes == 1)
7863 avr_asm_len ("ldi %0,0x7f" CR_TAB
7864 "adc %0,__zero_reg__", op, plen, 2);
7865 else
7866 avr_asm_len ("ldi %0,0x7f" CR_TAB
7867 "ldi %1,0xff" CR_TAB
7868 "adc %1,__zero_reg__" CR_TAB
7869 "adc %0,__zero_reg__", op, plen, 4);
7870 }
7871 else if (sign == 0 && PLUS == code)
7872 {
7873 /* [1s,reg] */
7874
7875 op[2] = simplify_gen_subreg (QImode, xop[2], mode, n_bytes-1);
7876
7877 if (n_bytes == 1)
7878 avr_asm_len ("ldi %0,0x80" CR_TAB
7879 "sbrs %2,7" CR_TAB
7880 "dec %0", op, plen, 3);
7881 else
7882 avr_asm_len ("ldi %0,0x80" CR_TAB
7883 "cp %2,%0" CR_TAB
7884 "sbc %1,%1" CR_TAB
7885 "sbci %0,0", op, plen, 4);
7886 }
7887 else if (sign == 0 && MINUS == code)
7888 {
7889 /* [3s,reg] */
7890
7891 op[2] = simplify_gen_subreg (QImode, xop[2], mode, n_bytes-1);
7892
7893 if (n_bytes == 1)
7894 avr_asm_len ("ldi %0,0x7f" CR_TAB
7895 "sbrs %2,7" CR_TAB
7896 "inc %0", op, plen, 3);
7897 else
7898 avr_asm_len ("ldi %0,0x7f" CR_TAB
7899 "cp %0,%2" CR_TAB
7900 "sbc %1,%1" CR_TAB
7901 "sbci %0,-1", op, plen, 4);
7902 }
7903 else if ((sign < 0) ^ (SS_MINUS == code_sat))
7904 {
7905 /* [1s,const,B < 0] [2s,B < 0] */
7906 /* [3s,const,B > 0] [4s,B > 0] */
7907
7908 if (n_bytes == 8)
7909 {
7910 avr_asm_len ("%~call __clr_8", op, plen, len_call);
7911 need_copy = false;
7912 }
7913
7914 avr_asm_len ("ldi %0,0x80", op, plen, 1);
7915 if (n_bytes > 1 && need_copy)
7916 avr_asm_len ("clr %1", op, plen, 1);
7917 }
7918 else if ((sign > 0) ^ (SS_MINUS == code_sat))
7919 {
7920 /* [1s,const,B > 0] [2s,B > 0] */
7921 /* [3s,const,B < 0] [4s,B < 0] */
7922
7923 if (n_bytes == 8)
7924 {
7925 avr_asm_len ("sec" CR_TAB
7926 "%~call __sbc_8", op, plen, 1 + len_call);
7927 need_copy = false;
7928 }
7929
7930 avr_asm_len ("ldi %0,0x7f", op, plen, 1);
7931 if (n_bytes > 1 && need_copy)
7932 avr_asm_len ("ldi %1,0xff", op, plen, 1);
7933 }
7934 else
7935 gcc_unreachable();
7936
7937 break;
7938
7939 case US_PLUS:
7940 /* [1u] : [2u] */
7941
7942 avr_asm_len (PLUS == code ? "brcc 0f" : "brcs 0f", op, plen, 1);
7943
7944 if (n_bytes == 8)
7945 {
7946 if (MINUS == code)
7947 avr_asm_len ("sec", op, plen, 1);
7948 avr_asm_len ("%~call __sbc_8", op, plen, len_call);
7949
7950 need_copy = false;
7951 }
7952 else
7953 {
7954 if (MINUS == code && !test_hard_reg_class (LD_REGS, op[0]))
7955 avr_asm_len ("sec" CR_TAB
7956 "sbc %0,%0", op, plen, 2);
7957 else
7958 avr_asm_len (PLUS == code ? "sbc %0,%0" : "ldi %0,0xff",
7959 op, plen, 1);
7960 }
7961 break; /* US_PLUS */
7962
7963 case US_MINUS:
7964 /* [4u] : [3u] */
7965
7966 avr_asm_len (PLUS == code ? "brcs 0f" : "brcc 0f", op, plen, 1);
7967
7968 if (n_bytes == 8)
7969 {
7970 avr_asm_len ("%~call __clr_8", op, plen, len_call);
7971 need_copy = false;
7972 }
7973 else
7974 avr_asm_len ("clr %0", op, plen, 1);
7975
7976 break;
7977 }
7978
7979 /* We set the MSB in the unsigned case and the 2 MSBs in the signed case.
7980 Now copy the right value to the LSBs. */
7981
7982 if (need_copy && n_bytes > 1)
7983 {
7984 if (US_MINUS == code_sat || US_PLUS == code_sat)
7985 {
7986 avr_asm_len ("mov %1,%0", op, plen, 1);
7987
7988 if (n_bytes > 2)
7989 {
7990 op[0] = xop[0];
7991 if (AVR_HAVE_MOVW)
7992 avr_asm_len ("movw %0,%1", op, plen, 1);
7993 else
7994 avr_asm_len ("mov %A0,%1" CR_TAB
7995 "mov %B0,%1", op, plen, 2);
7996 }
7997 }
7998 else if (n_bytes > 2)
7999 {
8000 op[0] = xop[0];
8001 avr_asm_len ("mov %A0,%1" CR_TAB
8002 "mov %B0,%1", op, plen, 2);
8003 }
8004 }
8005
8006 if (need_copy && n_bytes == 8)
8007 {
8008 if (AVR_HAVE_MOVW)
8009 avr_asm_len ("movw %r0+2,%0" CR_TAB
8010 "movw %r0+4,%0", xop, plen, 2);
8011 else
8012 avr_asm_len ("mov %r0+2,%0" CR_TAB
8013 "mov %r0+3,%0" CR_TAB
8014 "mov %r0+4,%0" CR_TAB
8015 "mov %r0+5,%0", xop, plen, 4);
8016 }
8017
8018 if (out_label)
8019 avr_asm_len ("0:", op, plen, 0);
8020 }
8021
8022
8023 /* Output addition/subtraction of register XOP[0] and a constant XOP[2] that
8024 is ont a compile-time constant:
8025
8026 XOP[0] = XOP[0] +/- XOP[2]
8027
8028 This is a helper for the function below. The only insns that need this
8029 are additions/subtraction for pointer modes, i.e. HImode and PSImode. */
8030
8031 static const char*
avr_out_plus_symbol(rtx * xop,enum rtx_code code,int * plen,int * pcc)8032 avr_out_plus_symbol (rtx *xop, enum rtx_code code, int *plen, int *pcc)
8033 {
8034 machine_mode mode = GET_MODE (xop[0]);
8035
8036 /* Only pointer modes want to add symbols. */
8037
8038 gcc_assert (mode == HImode || mode == PSImode);
8039
8040 *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_SET_N;
8041
8042 avr_asm_len (PLUS == code
8043 ? "subi %A0,lo8(-(%2))" CR_TAB "sbci %B0,hi8(-(%2))"
8044 : "subi %A0,lo8(%2)" CR_TAB "sbci %B0,hi8(%2)",
8045 xop, plen, -2);
8046
8047 if (PSImode == mode)
8048 avr_asm_len (PLUS == code
8049 ? "sbci %C0,hlo8(-(%2))"
8050 : "sbci %C0,hlo8(%2)", xop, plen, 1);
8051 return "";
8052 }
8053
8054
8055 /* Prepare operands of addition/subtraction to be used with avr_out_plus_1.
8056
8057 INSN is a single_set insn or an insn pattern with a binary operation as
8058 SET_SRC that is one of: PLUS, SS_PLUS, US_PLUS, MINUS, SS_MINUS, US_MINUS.
8059
8060 XOP are the operands of INSN. In the case of 64-bit operations with
8061 constant XOP[] has just one element: The summand/subtrahend in XOP[0].
8062 The non-saturating insns up to 32 bits may or may not supply a "d" class
8063 scratch as XOP[3].
8064
8065 If PLEN == NULL output the instructions.
8066 If PLEN != NULL set *PLEN to the length of the sequence in words.
8067
8068 PCC is a pointer to store the instructions' effect on cc0.
8069 PCC may be NULL.
8070
8071 PLEN and PCC default to NULL.
8072
8073 OUT_LABEL defaults to TRUE. For a description, see AVR_OUT_PLUS_1.
8074
8075 Return "" */
8076
8077 const char*
avr_out_plus(rtx insn,rtx * xop,int * plen,int * pcc,bool out_label)8078 avr_out_plus (rtx insn, rtx *xop, int *plen, int *pcc, bool out_label)
8079 {
8080 int cc_plus, cc_minus, cc_dummy;
8081 int len_plus, len_minus;
8082 rtx op[4];
8083 rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
8084 rtx xdest = SET_DEST (xpattern);
8085 machine_mode mode = GET_MODE (xdest);
8086 scalar_int_mode imode = int_mode_for_mode (mode).require ();
8087 int n_bytes = GET_MODE_SIZE (mode);
8088 enum rtx_code code_sat = GET_CODE (SET_SRC (xpattern));
8089 enum rtx_code code
8090 = (PLUS == code_sat || SS_PLUS == code_sat || US_PLUS == code_sat
8091 ? PLUS : MINUS);
8092
8093 if (!pcc)
8094 pcc = &cc_dummy;
8095
8096 /* PLUS and MINUS don't saturate: Use modular wrap-around. */
8097
8098 if (PLUS == code_sat || MINUS == code_sat)
8099 code_sat = UNKNOWN;
8100
8101 if (n_bytes <= 4 && REG_P (xop[2]))
8102 {
8103 avr_out_plus_1 (xop, plen, code, pcc, code_sat, 0, out_label);
8104 return "";
8105 }
8106
8107 if (n_bytes == 8)
8108 {
8109 op[0] = gen_rtx_REG (DImode, ACC_A);
8110 op[1] = gen_rtx_REG (DImode, ACC_A);
8111 op[2] = avr_to_int_mode (xop[0]);
8112 }
8113 else
8114 {
8115 if (!REG_P (xop[2])
8116 && !CONST_INT_P (xop[2])
8117 && !CONST_FIXED_P (xop[2]))
8118 {
8119 return avr_out_plus_symbol (xop, code, plen, pcc);
8120 }
8121
8122 op[0] = avr_to_int_mode (xop[0]);
8123 op[1] = avr_to_int_mode (xop[1]);
8124 op[2] = avr_to_int_mode (xop[2]);
8125 }
8126
8127 /* Saturations and 64-bit operations don't have a clobber operand.
8128 For the other cases, the caller will provide a proper XOP[3]. */
8129
8130 xpattern = INSN_P (insn) ? PATTERN (insn) : insn;
8131 op[3] = PARALLEL == GET_CODE (xpattern) ? xop[3] : NULL_RTX;
8132
8133 /* Saturation will need the sign of the original operand. */
8134
8135 rtx xmsb = simplify_gen_subreg (QImode, op[2], imode, n_bytes-1);
8136 int sign = INTVAL (xmsb) < 0 ? -1 : 1;
8137
8138 /* If we subtract and the subtrahend is a constant, then negate it
8139 so that avr_out_plus_1 can be used. */
8140
8141 if (MINUS == code)
8142 op[2] = simplify_unary_operation (NEG, imode, op[2], imode);
8143
8144 /* Work out the shortest sequence. */
8145
8146 avr_out_plus_1 (op, &len_minus, MINUS, &cc_minus, code_sat, sign, out_label);
8147 avr_out_plus_1 (op, &len_plus, PLUS, &cc_plus, code_sat, sign, out_label);
8148
8149 if (plen)
8150 {
8151 *plen = (len_minus <= len_plus) ? len_minus : len_plus;
8152 *pcc = (len_minus <= len_plus) ? cc_minus : cc_plus;
8153 }
8154 else if (len_minus <= len_plus)
8155 avr_out_plus_1 (op, NULL, MINUS, pcc, code_sat, sign, out_label);
8156 else
8157 avr_out_plus_1 (op, NULL, PLUS, pcc, code_sat, sign, out_label);
8158
8159 return "";
8160 }
8161
8162
8163 /* Output bit operation (IOR, AND, XOR) with register XOP[0] and compile
8164 time constant XOP[2]:
8165
8166 XOP[0] = XOP[0] <op> XOP[2]
8167
8168 and return "". If PLEN == NULL, print assembler instructions to perform the
8169 operation; otherwise, set *PLEN to the length of the instruction sequence
8170 (in words) printed with PLEN == NULL. XOP[3] is either an 8-bit clobber
8171 register or SCRATCH if no clobber register is needed for the operation.
8172 INSN is an INSN_P or a pattern of an insn. */
8173
8174 const char*
avr_out_bitop(rtx insn,rtx * xop,int * plen)8175 avr_out_bitop (rtx insn, rtx *xop, int *plen)
8176 {
8177 /* CODE and MODE of the operation. */
8178 rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
8179 enum rtx_code code = GET_CODE (SET_SRC (xpattern));
8180 machine_mode mode = GET_MODE (xop[0]);
8181
8182 /* Number of bytes to operate on. */
8183 int n_bytes = GET_MODE_SIZE (mode);
8184
8185 /* Value of T-flag (0 or 1) or -1 if unknow. */
8186 int set_t = -1;
8187
8188 /* Value (0..0xff) held in clobber register op[3] or -1 if unknown. */
8189 int clobber_val = -1;
8190
8191 /* op[0]: 8-bit destination register
8192 op[1]: 8-bit const int
8193 op[2]: 8-bit clobber register, SCRATCH or NULL_RTX.
8194 op[3]: 8-bit register containing 0xff or NULL_RTX */
8195 rtx op[4];
8196
8197 op[2] = QImode == mode ? NULL_RTX : xop[3];
8198 op[3] = NULL_RTX;
8199
8200 if (plen)
8201 *plen = 0;
8202
8203 for (int i = 0; i < n_bytes; i++)
8204 {
8205 /* We operate byte-wise on the destination. */
8206 rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
8207 rtx xval8 = simplify_gen_subreg (QImode, xop[2], mode, i);
8208
8209 /* 8-bit value to operate with this byte. */
8210 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
8211
8212 /* Number of bits set in the current byte of the constant. */
8213 int pop8 = popcount_hwi (val8);
8214
8215 /* Registers R16..R31 can operate with immediate. */
8216 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
8217
8218 op[0] = reg8;
8219 op[1] = GEN_INT (val8);
8220
8221 switch (code)
8222 {
8223 case IOR:
8224
8225 if (pop8 == 0)
8226 continue;
8227 else if (ld_reg_p)
8228 avr_asm_len ("ori %0,%1", op, plen, 1);
8229 else if (pop8 == 1)
8230 {
8231 if (set_t != 1)
8232 avr_asm_len ("set", op, plen, 1);
8233 set_t = 1;
8234
8235 op[1] = GEN_INT (exact_log2 (val8));
8236 avr_asm_len ("bld %0,%1", op, plen, 1);
8237 }
8238 else if (pop8 == 8)
8239 {
8240 if (op[3] != NULL_RTX)
8241 avr_asm_len ("mov %0,%3", op, plen, 1);
8242 else
8243 avr_asm_len ("clr %0" CR_TAB
8244 "dec %0", op, plen, 2);
8245
8246 op[3] = op[0];
8247 }
8248 else
8249 {
8250 if (clobber_val != (int) val8)
8251 avr_asm_len ("ldi %2,%1", op, plen, 1);
8252 clobber_val = (int) val8;
8253
8254 avr_asm_len ("or %0,%2", op, plen, 1);
8255 }
8256
8257 continue; /* IOR */
8258
8259 case AND:
8260
8261 if (pop8 == 8)
8262 continue;
8263 else if (pop8 == 0)
8264 avr_asm_len ("clr %0", op, plen, 1);
8265 else if (ld_reg_p)
8266 avr_asm_len ("andi %0,%1", op, plen, 1);
8267 else if (pop8 == 7)
8268 {
8269 if (set_t != 0)
8270 avr_asm_len ("clt", op, plen, 1);
8271 set_t = 0;
8272
8273 op[1] = GEN_INT (exact_log2 (GET_MODE_MASK (QImode) & ~val8));
8274 avr_asm_len ("bld %0,%1", op, plen, 1);
8275 }
8276 else
8277 {
8278 if (clobber_val != (int) val8)
8279 avr_asm_len ("ldi %2,%1", op, plen, 1);
8280 clobber_val = (int) val8;
8281
8282 avr_asm_len ("and %0,%2", op, plen, 1);
8283 }
8284
8285 continue; /* AND */
8286
8287 case XOR:
8288
8289 if (pop8 == 0)
8290 continue;
8291 else if (pop8 == 8)
8292 avr_asm_len ("com %0", op, plen, 1);
8293 else if (ld_reg_p && val8 == (1 << 7))
8294 avr_asm_len ("subi %0,%1", op, plen, 1);
8295 else
8296 {
8297 if (clobber_val != (int) val8)
8298 avr_asm_len ("ldi %2,%1", op, plen, 1);
8299 clobber_val = (int) val8;
8300
8301 avr_asm_len ("eor %0,%2", op, plen, 1);
8302 }
8303
8304 continue; /* XOR */
8305
8306 default:
8307 /* Unknown rtx_code */
8308 gcc_unreachable();
8309 }
8310 } /* for all sub-bytes */
8311
8312 return "";
8313 }
8314
8315
8316 /* Output sign extension from XOP[1] to XOP[0] and return "".
8317 If PLEN == NULL, print assembler instructions to perform the operation;
8318 otherwise, set *PLEN to the length of the instruction sequence (in words)
8319 as printed with PLEN == NULL. */
8320
8321 const char*
avr_out_sign_extend(rtx_insn * insn,rtx * xop,int * plen)8322 avr_out_sign_extend (rtx_insn *insn, rtx *xop, int *plen)
8323 {
8324 // Size in bytes of source resp. destination operand.
8325 unsigned n_src = GET_MODE_SIZE (GET_MODE (xop[1]));
8326 unsigned n_dest = GET_MODE_SIZE (GET_MODE (xop[0]));
8327 rtx r_msb = all_regs_rtx[REGNO (xop[1]) + n_src - 1];
8328
8329 if (plen)
8330 *plen = 0;
8331
8332 // Copy destination to source
8333
8334 if (REGNO (xop[0]) != REGNO (xop[1]))
8335 {
8336 gcc_assert (n_src <= 2);
8337
8338 if (n_src == 2)
8339 avr_asm_len (AVR_HAVE_MOVW
8340 ? "movw %0,%1"
8341 : "mov %B0,%B1", xop, plen, 1);
8342 if (n_src == 1 || !AVR_HAVE_MOVW)
8343 avr_asm_len ("mov %A0,%A1", xop, plen, 1);
8344 }
8345
8346 // Set Carry to the sign bit MSB.7...
8347
8348 if (REGNO (xop[0]) == REGNO (xop[1])
8349 || !reg_unused_after (insn, r_msb))
8350 {
8351 avr_asm_len ("mov __tmp_reg__,%0", &r_msb, plen, 1);
8352 r_msb = tmp_reg_rtx;
8353 }
8354
8355 avr_asm_len ("lsl %0", &r_msb, plen, 1);
8356
8357 // ...and propagate it to all the new sign bits
8358
8359 for (unsigned n = n_src; n < n_dest; n++)
8360 avr_asm_len ("sbc %0,%0", &all_regs_rtx[REGNO (xop[0]) + n], plen, 1);
8361
8362 return "";
8363 }
8364
8365
8366 /* PLEN == NULL: Output code to add CONST_INT OP[0] to SP.
8367 PLEN != NULL: Set *PLEN to the length of that sequence.
8368 Return "". */
8369
8370 const char*
avr_out_addto_sp(rtx * op,int * plen)8371 avr_out_addto_sp (rtx *op, int *plen)
8372 {
8373 int pc_len = AVR_2_BYTE_PC ? 2 : 3;
8374 int addend = INTVAL (op[0]);
8375
8376 if (plen)
8377 *plen = 0;
8378
8379 if (addend < 0)
8380 {
8381 if (flag_verbose_asm || flag_print_asm_name)
8382 avr_asm_len (ASM_COMMENT_START "SP -= %n0", op, plen, 0);
8383
8384 while (addend <= -pc_len)
8385 {
8386 addend += pc_len;
8387 avr_asm_len ("rcall .", op, plen, 1);
8388 }
8389
8390 while (addend++ < 0)
8391 avr_asm_len ("push __tmp_reg__", op, plen, 1);
8392 }
8393 else if (addend > 0)
8394 {
8395 if (flag_verbose_asm || flag_print_asm_name)
8396 avr_asm_len (ASM_COMMENT_START "SP += %0", op, plen, 0);
8397
8398 while (addend-- > 0)
8399 avr_asm_len ("pop __tmp_reg__", op, plen, 1);
8400 }
8401
8402 return "";
8403 }
8404
8405
8406 /* Output instructions to insert an inverted bit into OPERANDS[0]:
8407 $0.$1 = ~$2.$3 if XBITNO = NULL
8408 $0.$1 = ~$2.XBITNO if XBITNO != NULL.
8409 If PLEN = NULL then output the respective instruction sequence which
8410 is a combination of BST / BLD and some instruction(s) to invert the bit.
8411 If PLEN != NULL then store the length of the sequence (in words) in *PLEN.
8412 Return "". */
8413
8414 const char*
avr_out_insert_notbit(rtx_insn * insn,rtx operands[],rtx xbitno,int * plen)8415 avr_out_insert_notbit (rtx_insn *insn, rtx operands[], rtx xbitno, int *plen)
8416 {
8417 rtx op[4] = { operands[0], operands[1], operands[2],
8418 xbitno == NULL_RTX ? operands [3] : xbitno };
8419
8420 if (INTVAL (op[1]) == 7
8421 && test_hard_reg_class (LD_REGS, op[0]))
8422 {
8423 /* If the inserted bit number is 7 and we have a d-reg, then invert
8424 the bit after the insertion by means of SUBI *,0x80. */
8425
8426 if (INTVAL (op[3]) == 7
8427 && REGNO (op[0]) == REGNO (op[2]))
8428 {
8429 avr_asm_len ("subi %0,0x80", op, plen, -1);
8430 }
8431 else
8432 {
8433 avr_asm_len ("bst %2,%3" CR_TAB
8434 "bld %0,%1" CR_TAB
8435 "subi %0,0x80", op, plen, -3);
8436 }
8437 }
8438 else if (test_hard_reg_class (LD_REGS, op[0])
8439 && (INTVAL (op[1]) != INTVAL (op[3])
8440 || !reg_overlap_mentioned_p (op[0], op[2])))
8441 {
8442 /* If the destination bit is in a d-reg we can jump depending
8443 on the source bit and use ANDI / ORI. This just applies if we
8444 have not an early-clobber situation with the bit. */
8445
8446 avr_asm_len ("andi %0,~(1<<%1)" CR_TAB
8447 "sbrs %2,%3" CR_TAB
8448 "ori %0,1<<%1", op, plen, -3);
8449 }
8450 else
8451 {
8452 /* Otherwise, invert the bit by means of COM before we store it with
8453 BST and then undo the COM if needed. */
8454
8455 avr_asm_len ("com %2" CR_TAB
8456 "bst %2,%3", op, plen, -2);
8457
8458 if (!reg_unused_after (insn, op[2])
8459 // A simple 'reg_unused_after' is not enough because that function
8460 // assumes that the destination register is overwritten completely
8461 // and hence is in order for our purpose. This is not the case
8462 // with BLD which just changes one bit of the destination.
8463 || reg_overlap_mentioned_p (op[0], op[2]))
8464 {
8465 /* Undo the COM from above. */
8466 avr_asm_len ("com %2", op, plen, 1);
8467 }
8468
8469 avr_asm_len ("bld %0,%1", op, plen, 1);
8470 }
8471
8472 return "";
8473 }
8474
8475
8476 /* Outputs instructions needed for fixed point type conversion.
8477 This includes converting between any fixed point type, as well
8478 as converting to any integer type. Conversion between integer
8479 types is not supported.
8480
8481 Converting signed fractional types requires a bit shift if converting
8482 to or from any unsigned fractional type because the decimal place is
8483 shifted by 1 bit. When the destination is a signed fractional, the sign
8484 is stored in either the carry or T bit. */
8485
8486 const char*
avr_out_fract(rtx_insn * insn,rtx operands[],bool intsigned,int * plen)8487 avr_out_fract (rtx_insn *insn, rtx operands[], bool intsigned, int *plen)
8488 {
8489 rtx xop[6];
8490 RTX_CODE shift = UNKNOWN;
8491 bool sign_in_carry = false;
8492 bool msb_in_carry = false;
8493 bool lsb_in_tmp_reg = false;
8494 bool lsb_in_carry = false;
8495 bool frac_rounded = false;
8496 const char *code_ashift = "lsl %0";
8497
8498
8499 #define MAY_CLOBBER(RR) \
8500 /* Shorthand used below. */ \
8501 ((sign_bytes \
8502 && IN_RANGE (RR, dest.regno_msb - sign_bytes + 1, dest.regno_msb)) \
8503 || (offset && IN_RANGE (RR, dest.regno, dest.regno_msb)) \
8504 || (reg_unused_after (insn, all_regs_rtx[RR]) \
8505 && !IN_RANGE (RR, dest.regno, dest.regno_msb)))
8506
8507 struct
8508 {
8509 /* bytes : Length of operand in bytes.
8510 ibyte : Length of integral part in bytes.
8511 fbyte, fbit : Length of fractional part in bytes, bits. */
8512
8513 bool sbit;
8514 unsigned fbit, bytes, ibyte, fbyte;
8515 unsigned regno, regno_msb;
8516 } dest, src, *val[2] = { &dest, &src };
8517
8518 if (plen)
8519 *plen = 0;
8520
8521 /* Step 0: Determine information on source and destination operand we
8522 ====== will need in the remainder. */
8523
8524 for (size_t i = 0; i < ARRAY_SIZE (val); i++)
8525 {
8526 machine_mode mode;
8527
8528 xop[i] = operands[i];
8529
8530 mode = GET_MODE (xop[i]);
8531
8532 val[i]->bytes = GET_MODE_SIZE (mode);
8533 val[i]->regno = REGNO (xop[i]);
8534 val[i]->regno_msb = REGNO (xop[i]) + val[i]->bytes - 1;
8535
8536 if (SCALAR_INT_MODE_P (mode))
8537 {
8538 val[i]->sbit = intsigned;
8539 val[i]->fbit = 0;
8540 }
8541 else if (ALL_SCALAR_FIXED_POINT_MODE_P (mode))
8542 {
8543 val[i]->sbit = SIGNED_SCALAR_FIXED_POINT_MODE_P (mode);
8544 val[i]->fbit = GET_MODE_FBIT (mode);
8545 }
8546 else
8547 fatal_insn ("unsupported fixed-point conversion", insn);
8548
8549 val[i]->fbyte = (1 + val[i]->fbit) / BITS_PER_UNIT;
8550 val[i]->ibyte = val[i]->bytes - val[i]->fbyte;
8551 }
8552
8553 // Byte offset of the decimal point taking into account different place
8554 // of the decimal point in input and output and different register numbers
8555 // of input and output.
8556 int offset = dest.regno - src.regno + dest.fbyte - src.fbyte;
8557
8558 // Number of destination bytes that will come from sign / zero extension.
8559 int sign_bytes = (dest.ibyte - src.ibyte) * (dest.ibyte > src.ibyte);
8560
8561 // Number of bytes at the low end to be filled with zeros.
8562 int zero_bytes = (dest.fbyte - src.fbyte) * (dest.fbyte > src.fbyte);
8563
8564 // Do we have a 16-Bit register that is cleared?
8565 rtx clrw = NULL_RTX;
8566
8567 bool sign_extend = src.sbit && sign_bytes;
8568
8569 if (dest.fbit % 8 == 0 && src.fbit % 8 == 7)
8570 shift = ASHIFT;
8571 else if (dest.fbit % 8 == 7 && src.fbit % 8 == 0)
8572 shift = ASHIFTRT;
8573 else if (dest.fbit % 8 == src.fbit % 8)
8574 shift = UNKNOWN;
8575 else
8576 gcc_unreachable();
8577
8578 /* If we need to round the fraction part, we might need to save/round it
8579 before clobbering any of it in Step 1. Also, we might want to do
8580 the rounding now to make use of LD_REGS. */
8581 if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8582 && SCALAR_ACCUM_MODE_P (GET_MODE (xop[1]))
8583 && !TARGET_FRACT_CONV_TRUNC)
8584 {
8585 bool overlap
8586 = (src.regno <=
8587 (offset ? dest.regno_msb - sign_bytes : dest.regno + zero_bytes - 1)
8588 && dest.regno - offset -1 >= dest.regno);
8589 unsigned s0 = dest.regno - offset -1;
8590 bool use_src = true;
8591 unsigned sn;
8592 unsigned copied_msb = src.regno_msb;
8593 bool have_carry = false;
8594
8595 if (src.ibyte > dest.ibyte)
8596 copied_msb -= src.ibyte - dest.ibyte;
8597
8598 for (sn = s0; sn <= copied_msb; sn++)
8599 if (!IN_RANGE (sn, dest.regno, dest.regno_msb)
8600 && !reg_unused_after (insn, all_regs_rtx[sn]))
8601 use_src = false;
8602 if (use_src && TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], s0))
8603 {
8604 avr_asm_len ("tst %0" CR_TAB "brpl 0f",
8605 &all_regs_rtx[src.regno_msb], plen, 2);
8606 sn = src.regno;
8607 if (sn < s0)
8608 {
8609 if (TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], sn))
8610 avr_asm_len ("cpi %0,1", &all_regs_rtx[sn], plen, 1);
8611 else
8612 avr_asm_len ("sec" CR_TAB
8613 "cpc %0,__zero_reg__",
8614 &all_regs_rtx[sn], plen, 2);
8615 have_carry = true;
8616 }
8617 while (++sn < s0)
8618 avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8619
8620 avr_asm_len (have_carry ? "sbci %0,128" : "subi %0,129",
8621 &all_regs_rtx[s0], plen, 1);
8622 for (sn = src.regno + src.fbyte; sn <= copied_msb; sn++)
8623 avr_asm_len ("sbci %0,255", &all_regs_rtx[sn], plen, 1);
8624 avr_asm_len ("\n0:", NULL, plen, 0);
8625 frac_rounded = true;
8626 }
8627 else if (use_src && overlap)
8628 {
8629 avr_asm_len ("clr __tmp_reg__" CR_TAB
8630 "sbrc %1,0" CR_TAB
8631 "dec __tmp_reg__", xop, plen, 1);
8632 sn = src.regno;
8633 if (sn < s0)
8634 {
8635 avr_asm_len ("add %0,__tmp_reg__", &all_regs_rtx[sn], plen, 1);
8636 have_carry = true;
8637 }
8638
8639 while (++sn < s0)
8640 avr_asm_len ("adc %0,__tmp_reg__", &all_regs_rtx[sn], plen, 1);
8641
8642 if (have_carry)
8643 avr_asm_len ("clt" CR_TAB
8644 "bld __tmp_reg__,7" CR_TAB
8645 "adc %0,__tmp_reg__",
8646 &all_regs_rtx[s0], plen, 1);
8647 else
8648 avr_asm_len ("lsr __tmp_reg" CR_TAB
8649 "add %0,__tmp_reg__",
8650 &all_regs_rtx[s0], plen, 2);
8651 for (sn = src.regno + src.fbyte; sn <= copied_msb; sn++)
8652 avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8653 frac_rounded = true;
8654 }
8655 else if (overlap)
8656 {
8657 bool use_src
8658 = (TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], s0)
8659 && (IN_RANGE (s0, dest.regno, dest.regno_msb)
8660 || reg_unused_after (insn, all_regs_rtx[s0])));
8661 xop[2] = all_regs_rtx[s0];
8662 unsigned sn = src.regno;
8663 if (!use_src || sn == s0)
8664 avr_asm_len ("mov __tmp_reg__,%2", xop, plen, 1);
8665 /* We need to consider to-be-discarded bits
8666 if the value is negative. */
8667 if (sn < s0)
8668 {
8669 avr_asm_len ("tst %0" CR_TAB
8670 "brpl 0f",
8671 &all_regs_rtx[src.regno_msb], plen, 2);
8672 /* Test to-be-discarded bytes for any nozero bits.
8673 ??? Could use OR or SBIW to test two registers at once. */
8674 if (sn < s0)
8675 avr_asm_len ("cp %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8676
8677 while (++sn < s0)
8678 avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8679 /* Set bit 0 in __tmp_reg__ if any of the lower bits was set. */
8680 if (use_src)
8681 avr_asm_len ("breq 0f" CR_TAB
8682 "ori %2,1"
8683 "\n0:\t" "mov __tmp_reg__,%2",
8684 xop, plen, 3);
8685 else
8686 avr_asm_len ("breq 0f" CR_TAB
8687 "set" CR_TAB
8688 "bld __tmp_reg__,0\n0:",
8689 xop, plen, 3);
8690 }
8691 lsb_in_tmp_reg = true;
8692 }
8693 }
8694
8695 /* Step 1: Clear bytes at the low end and copy payload bits from source
8696 ====== to destination. */
8697
8698 int step = offset < 0 ? 1 : -1;
8699 unsigned d0 = offset < 0 ? dest.regno : dest.regno_msb;
8700
8701 // We cleared at least that number of registers.
8702 int clr_n = 0;
8703
8704 for (; d0 >= dest.regno && d0 <= dest.regno_msb; d0 += step)
8705 {
8706 // Next regno of destination is needed for MOVW
8707 unsigned d1 = d0 + step;
8708
8709 // Current and next regno of source
8710 signed s0 = d0 - offset;
8711 signed s1 = s0 + step;
8712
8713 // Must current resp. next regno be CLRed? This applies to the low
8714 // bytes of the destination that have no associated source bytes.
8715 bool clr0 = s0 < (signed) src.regno;
8716 bool clr1 = s1 < (signed) src.regno && d1 >= dest.regno;
8717
8718 // First gather what code to emit (if any) and additional step to
8719 // apply if a MOVW is in use. xop[2] is destination rtx and xop[3]
8720 // is the source rtx for the current loop iteration.
8721 const char *code = NULL;
8722 int stepw = 0;
8723
8724 if (clr0)
8725 {
8726 if (AVR_HAVE_MOVW && clr1 && clrw)
8727 {
8728 xop[2] = all_regs_rtx[d0 & ~1];
8729 xop[3] = clrw;
8730 code = "movw %2,%3";
8731 stepw = step;
8732 }
8733 else
8734 {
8735 xop[2] = all_regs_rtx[d0];
8736 code = "clr %2";
8737
8738 if (++clr_n >= 2
8739 && !clrw
8740 && d0 % 2 == (step > 0))
8741 {
8742 clrw = all_regs_rtx[d0 & ~1];
8743 }
8744 }
8745 }
8746 else if (offset && s0 <= (signed) src.regno_msb)
8747 {
8748 int movw = AVR_HAVE_MOVW && offset % 2 == 0
8749 && d0 % 2 == (offset > 0)
8750 && d1 <= dest.regno_msb && d1 >= dest.regno
8751 && s1 <= (signed) src.regno_msb && s1 >= (signed) src.regno;
8752
8753 xop[2] = all_regs_rtx[d0 & ~movw];
8754 xop[3] = all_regs_rtx[s0 & ~movw];
8755 code = movw ? "movw %2,%3" : "mov %2,%3";
8756 stepw = step * movw;
8757 }
8758
8759 if (code)
8760 {
8761 if (sign_extend && shift != ASHIFT && !sign_in_carry
8762 && (d0 == src.regno_msb || d0 + stepw == src.regno_msb))
8763 {
8764 /* We are going to override the sign bit. If we sign-extend,
8765 store the sign in the Carry flag. This is not needed if
8766 the destination will be ASHIFT in the remainder because
8767 the ASHIFT will set Carry without extra instruction. */
8768
8769 avr_asm_len ("lsl %0", &all_regs_rtx[src.regno_msb], plen, 1);
8770 sign_in_carry = true;
8771 }
8772
8773 unsigned src_msb = dest.regno_msb - sign_bytes - offset + 1;
8774
8775 if (!sign_extend && shift == ASHIFTRT && !msb_in_carry
8776 && src.ibyte > dest.ibyte
8777 && (d0 == src_msb || d0 + stepw == src_msb))
8778 {
8779 /* We are going to override the MSB. If we shift right,
8780 store the MSB in the Carry flag. This is only needed if
8781 we don't sign-extend becaue with sign-extension the MSB
8782 (the sign) will be produced by the sign extension. */
8783
8784 avr_asm_len ("lsr %0", &all_regs_rtx[src_msb], plen, 1);
8785 msb_in_carry = true;
8786 }
8787
8788 unsigned src_lsb = dest.regno - offset -1;
8789
8790 if (shift == ASHIFT && src.fbyte > dest.fbyte && !lsb_in_carry
8791 && !lsb_in_tmp_reg
8792 && (d0 == src_lsb || d0 + stepw == src_lsb))
8793 {
8794 /* We are going to override the new LSB; store it into carry. */
8795
8796 avr_asm_len ("lsl %0", &all_regs_rtx[src_lsb], plen, 1);
8797 code_ashift = "rol %0";
8798 lsb_in_carry = true;
8799 }
8800
8801 avr_asm_len (code, xop, plen, 1);
8802 d0 += stepw;
8803 }
8804 }
8805
8806 /* Step 2: Shift destination left by 1 bit position. This might be needed
8807 ====== for signed input and unsigned output. */
8808
8809 if (shift == ASHIFT && src.fbyte > dest.fbyte && !lsb_in_carry)
8810 {
8811 unsigned s0 = dest.regno - offset -1;
8812
8813 /* n1169 4.1.4 says:
8814 "Conversions from a fixed-point to an integer type round toward zero."
8815 Hence, converting a fract type to integer only gives a non-zero result
8816 for -1. */
8817 if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8818 && SCALAR_FRACT_MODE_P (GET_MODE (xop[1]))
8819 && !TARGET_FRACT_CONV_TRUNC)
8820 {
8821 gcc_assert (s0 == src.regno_msb);
8822 /* Check if the input is -1. We do that by checking if negating
8823 the input causes an integer overflow. */
8824 unsigned sn = src.regno;
8825 avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx[sn++], plen, 1);
8826 while (sn <= s0)
8827 avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx[sn++], plen, 1);
8828
8829 /* Overflow goes with set carry. Clear carry otherwise. */
8830 avr_asm_len ("brvs 0f" CR_TAB
8831 "clc\n0:", NULL, plen, 2);
8832 }
8833 /* Likewise, when converting from accumulator types to integer, we
8834 need to round up negative values. */
8835 else if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8836 && SCALAR_ACCUM_MODE_P (GET_MODE (xop[1]))
8837 && !TARGET_FRACT_CONV_TRUNC
8838 && !frac_rounded)
8839 {
8840 bool have_carry = false;
8841
8842 xop[2] = all_regs_rtx[s0];
8843 if (!lsb_in_tmp_reg && !MAY_CLOBBER (s0))
8844 avr_asm_len ("mov __tmp_reg__,%2", xop, plen, 1);
8845 avr_asm_len ("tst %0" CR_TAB "brpl 0f",
8846 &all_regs_rtx[src.regno_msb], plen, 2);
8847 if (!lsb_in_tmp_reg)
8848 {
8849 unsigned sn = src.regno;
8850 if (sn < s0)
8851 {
8852 avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx[sn],
8853 plen, 1);
8854 have_carry = true;
8855 }
8856 while (++sn < s0)
8857 avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx[sn], plen, 1);
8858 lsb_in_tmp_reg = !MAY_CLOBBER (s0);
8859 }
8860 /* Add in C and the rounding value 127. */
8861 /* If the destination msb is a sign byte, and in LD_REGS,
8862 grab it as a temporary. */
8863 if (sign_bytes
8864 && TEST_HARD_REG_BIT (reg_class_contents[LD_REGS],
8865 dest.regno_msb))
8866 {
8867 xop[3] = all_regs_rtx[dest.regno_msb];
8868 avr_asm_len ("ldi %3,127", xop, plen, 1);
8869 avr_asm_len ((have_carry && lsb_in_tmp_reg ? "adc __tmp_reg__,%3"
8870 : have_carry ? "adc %2,%3"
8871 : lsb_in_tmp_reg ? "add __tmp_reg__,%3"
8872 : "add %2,%3"),
8873 xop, plen, 1);
8874 }
8875 else
8876 {
8877 /* Fall back to use __zero_reg__ as a temporary. */
8878 avr_asm_len ("dec __zero_reg__", NULL, plen, 1);
8879 if (have_carry)
8880 avr_asm_len ("clt" CR_TAB
8881 "bld __zero_reg__,7", NULL, plen, 2);
8882 else
8883 avr_asm_len ("lsr __zero_reg__", NULL, plen, 1);
8884 avr_asm_len (have_carry && lsb_in_tmp_reg
8885 ? "adc __tmp_reg__,__zero_reg__"
8886 : have_carry ? "adc %2,__zero_reg__"
8887 : lsb_in_tmp_reg ? "add __tmp_reg__,__zero_reg__"
8888 : "add %2,__zero_reg__",
8889 xop, plen, 1);
8890 avr_asm_len ("eor __zero_reg__,__zero_reg__", NULL, plen, 1);
8891 }
8892
8893 for (d0 = dest.regno + zero_bytes;
8894 d0 <= dest.regno_msb - sign_bytes; d0++)
8895 avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx[d0], plen, 1);
8896
8897 avr_asm_len (lsb_in_tmp_reg
8898 ? "\n0:\t" "lsl __tmp_reg__"
8899 : "\n0:\t" "lsl %2",
8900 xop, plen, 1);
8901 }
8902 else if (MAY_CLOBBER (s0))
8903 avr_asm_len ("lsl %0", &all_regs_rtx[s0], plen, 1);
8904 else
8905 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
8906 "lsl __tmp_reg__", &all_regs_rtx[s0], plen, 2);
8907
8908 code_ashift = "rol %0";
8909 lsb_in_carry = true;
8910 }
8911
8912 if (shift == ASHIFT)
8913 {
8914 for (d0 = dest.regno + zero_bytes;
8915 d0 <= dest.regno_msb - sign_bytes; d0++)
8916 {
8917 avr_asm_len (code_ashift, &all_regs_rtx[d0], plen, 1);
8918 code_ashift = "rol %0";
8919 }
8920
8921 lsb_in_carry = false;
8922 sign_in_carry = true;
8923 }
8924
8925 /* Step 4a: Store MSB in carry if we don't already have it or will produce
8926 ======= it in sign-extension below. */
8927
8928 if (!sign_extend && shift == ASHIFTRT && !msb_in_carry
8929 && src.ibyte > dest.ibyte)
8930 {
8931 unsigned s0 = dest.regno_msb - sign_bytes - offset + 1;
8932
8933 if (MAY_CLOBBER (s0))
8934 avr_asm_len ("lsr %0", &all_regs_rtx[s0], plen, 1);
8935 else
8936 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
8937 "lsr __tmp_reg__", &all_regs_rtx[s0], plen, 2);
8938
8939 msb_in_carry = true;
8940 }
8941
8942 /* Step 3: Sign-extend or zero-extend the destination as needed.
8943 ====== */
8944
8945 if (sign_extend && !sign_in_carry)
8946 {
8947 unsigned s0 = src.regno_msb;
8948
8949 if (MAY_CLOBBER (s0))
8950 avr_asm_len ("lsl %0", &all_regs_rtx[s0], plen, 1);
8951 else
8952 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
8953 "lsl __tmp_reg__", &all_regs_rtx[s0], plen, 2);
8954
8955 sign_in_carry = true;
8956 }
8957
8958 gcc_assert (sign_in_carry + msb_in_carry + lsb_in_carry <= 1);
8959
8960 unsigned copies = 0;
8961 rtx movw = sign_extend ? NULL_RTX : clrw;
8962
8963 for (d0 = dest.regno_msb - sign_bytes + 1; d0 <= dest.regno_msb; d0++)
8964 {
8965 if (AVR_HAVE_MOVW && movw
8966 && d0 % 2 == 0 && d0 + 1 <= dest.regno_msb)
8967 {
8968 xop[2] = all_regs_rtx[d0];
8969 xop[3] = movw;
8970 avr_asm_len ("movw %2,%3", xop, plen, 1);
8971 d0++;
8972 }
8973 else
8974 {
8975 avr_asm_len (sign_extend ? "sbc %0,%0" : "clr %0",
8976 &all_regs_rtx[d0], plen, 1);
8977
8978 if (++copies >= 2 && !movw && d0 % 2 == 1)
8979 movw = all_regs_rtx[d0-1];
8980 }
8981 } /* for */
8982
8983
8984 /* Step 4: Right shift the destination. This might be needed for
8985 ====== conversions from unsigned to signed. */
8986
8987 if (shift == ASHIFTRT)
8988 {
8989 const char *code_ashiftrt = "lsr %0";
8990
8991 if (sign_extend || msb_in_carry)
8992 code_ashiftrt = "ror %0";
8993
8994 if (src.sbit && src.ibyte == dest.ibyte)
8995 code_ashiftrt = "asr %0";
8996
8997 for (d0 = dest.regno_msb - sign_bytes;
8998 d0 >= dest.regno + zero_bytes - 1 && d0 >= dest.regno; d0--)
8999 {
9000 avr_asm_len (code_ashiftrt, &all_regs_rtx[d0], plen, 1);
9001 code_ashiftrt = "ror %0";
9002 }
9003 }
9004
9005 #undef MAY_CLOBBER
9006
9007 return "";
9008 }
9009
9010
9011 /* Output fixed-point rounding. XOP[0] = XOP[1] is the operand to round.
9012 XOP[2] is the rounding point, a CONST_INT. The function prints the
9013 instruction sequence if PLEN = NULL and computes the length in words
9014 of the sequence if PLEN != NULL. Most of this function deals with
9015 preparing operands for calls to `avr_out_plus' and `avr_out_bitop'. */
9016
9017 const char*
avr_out_round(rtx_insn * insn ATTRIBUTE_UNUSED,rtx * xop,int * plen)9018 avr_out_round (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *xop, int *plen)
9019 {
9020 scalar_mode mode = as_a <scalar_mode> (GET_MODE (xop[0]));
9021 scalar_int_mode imode = int_mode_for_mode (mode).require ();
9022 // The smallest fractional bit not cleared by the rounding is 2^(-RP).
9023 int fbit = (int) GET_MODE_FBIT (mode);
9024 double_int i_add = double_int_zero.set_bit (fbit-1 - INTVAL (xop[2]));
9025 wide_int wi_add = wi::set_bit_in_zero (fbit-1 - INTVAL (xop[2]),
9026 GET_MODE_PRECISION (imode));
9027 // Lengths of PLUS and AND parts.
9028 int len_add = 0, *plen_add = plen ? &len_add : NULL;
9029 int len_and = 0, *plen_and = plen ? &len_and : NULL;
9030
9031 // Add-Saturate 1/2 * 2^(-RP). Don't print the label "0:" when printing
9032 // the saturated addition so that we can emit the "rjmp 1f" before the
9033 // "0:" below.
9034
9035 rtx xadd = const_fixed_from_double_int (i_add, mode);
9036 rtx xpattern, xsrc, op[4];
9037
9038 xsrc = SIGNED_FIXED_POINT_MODE_P (mode)
9039 ? gen_rtx_SS_PLUS (mode, xop[1], xadd)
9040 : gen_rtx_US_PLUS (mode, xop[1], xadd);
9041 xpattern = gen_rtx_SET (xop[0], xsrc);
9042
9043 op[0] = xop[0];
9044 op[1] = xop[1];
9045 op[2] = xadd;
9046 avr_out_plus (xpattern, op, plen_add, NULL, false /* Don't print "0:" */);
9047
9048 avr_asm_len ("rjmp 1f" CR_TAB
9049 "0:", NULL, plen_add, 1);
9050
9051 // Keep all bits from RP and higher: ... 2^(-RP)
9052 // Clear all bits from RP+1 and lower: 2^(-RP-1) ...
9053 // Rounding point ^^^^^^^
9054 // Added above ^^^^^^^^^
9055 rtx xreg = simplify_gen_subreg (imode, xop[0], mode, 0);
9056 rtx xmask = immed_wide_int_const (-wi_add - wi_add, imode);
9057
9058 xpattern = gen_rtx_SET (xreg, gen_rtx_AND (imode, xreg, xmask));
9059
9060 op[0] = xreg;
9061 op[1] = xreg;
9062 op[2] = xmask;
9063 op[3] = gen_rtx_SCRATCH (QImode);
9064 avr_out_bitop (xpattern, op, plen_and);
9065 avr_asm_len ("1:", NULL, plen, 0);
9066
9067 if (plen)
9068 *plen = len_add + len_and;
9069
9070 return "";
9071 }
9072
9073
9074 /* Create RTL split patterns for byte sized rotate expressions. This
9075 produces a series of move instructions and considers overlap situations.
9076 Overlapping non-HImode operands need a scratch register. */
9077
9078 bool
avr_rotate_bytes(rtx operands[])9079 avr_rotate_bytes (rtx operands[])
9080 {
9081 machine_mode mode = GET_MODE (operands[0]);
9082 bool overlapped = reg_overlap_mentioned_p (operands[0], operands[1]);
9083 bool same_reg = rtx_equal_p (operands[0], operands[1]);
9084 int num = INTVAL (operands[2]);
9085 rtx scratch = operands[3];
9086 /* Work out if byte or word move is needed. Odd byte rotates need QImode.
9087 Word move if no scratch is needed, otherwise use size of scratch. */
9088 machine_mode move_mode = QImode;
9089 int move_size, offset, size;
9090
9091 if (num & 0xf)
9092 move_mode = QImode;
9093 else if ((mode == SImode && !same_reg) || !overlapped)
9094 move_mode = HImode;
9095 else
9096 move_mode = GET_MODE (scratch);
9097
9098 /* Force DI rotate to use QI moves since other DI moves are currently split
9099 into QI moves so forward propagation works better. */
9100 if (mode == DImode)
9101 move_mode = QImode;
9102 /* Make scratch smaller if needed. */
9103 if (SCRATCH != GET_CODE (scratch)
9104 && HImode == GET_MODE (scratch)
9105 && QImode == move_mode)
9106 scratch = simplify_gen_subreg (move_mode, scratch, HImode, 0);
9107
9108 move_size = GET_MODE_SIZE (move_mode);
9109 /* Number of bytes/words to rotate. */
9110 offset = (num >> 3) / move_size;
9111 /* Number of moves needed. */
9112 size = GET_MODE_SIZE (mode) / move_size;
9113 /* Himode byte swap is special case to avoid a scratch register. */
9114 if (mode == HImode && same_reg)
9115 {
9116 /* HImode byte swap, using xor. This is as quick as using scratch. */
9117 rtx src, dst;
9118 src = simplify_gen_subreg (move_mode, operands[1], mode, 0);
9119 dst = simplify_gen_subreg (move_mode, operands[0], mode, 1);
9120 if (!rtx_equal_p (dst, src))
9121 {
9122 emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
9123 emit_move_insn (src, gen_rtx_XOR (QImode, src, dst));
9124 emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
9125 }
9126 }
9127 else
9128 {
9129 #define MAX_SIZE 8 /* GET_MODE_SIZE (DImode) / GET_MODE_SIZE (QImode) */
9130 /* Create linked list of moves to determine move order. */
9131 struct {
9132 rtx src, dst;
9133 int links;
9134 } move[MAX_SIZE + 8];
9135 int blocked, moves;
9136
9137 gcc_assert (size <= MAX_SIZE);
9138 /* Generate list of subreg moves. */
9139 for (int i = 0; i < size; i++)
9140 {
9141 int from = i;
9142 int to = (from + offset) % size;
9143 move[i].src = simplify_gen_subreg (move_mode, operands[1],
9144 mode, from * move_size);
9145 move[i].dst = simplify_gen_subreg (move_mode, operands[0],
9146 mode, to * move_size);
9147 move[i].links = -1;
9148 }
9149 /* Mark dependence where a dst of one move is the src of another move.
9150 The first move is a conflict as it must wait until second is
9151 performed. We ignore moves to self - we catch this later. */
9152 if (overlapped)
9153 for (int i = 0; i < size; i++)
9154 if (reg_overlap_mentioned_p (move[i].dst, operands[1]))
9155 for (int j = 0; j < size; j++)
9156 if (j != i && rtx_equal_p (move[j].src, move[i].dst))
9157 {
9158 /* The dst of move i is the src of move j. */
9159 move[i].links = j;
9160 break;
9161 }
9162
9163 blocked = -1;
9164 moves = 0;
9165 /* Go through move list and perform non-conflicting moves. As each
9166 non-overlapping move is made, it may remove other conflicts
9167 so the process is repeated until no conflicts remain. */
9168 do
9169 {
9170 blocked = -1;
9171 moves = 0;
9172 /* Emit move where dst is not also a src or we have used that
9173 src already. */
9174 for (int i = 0; i < size; i++)
9175 if (move[i].src != NULL_RTX)
9176 {
9177 if (move[i].links == -1
9178 || move[move[i].links].src == NULL_RTX)
9179 {
9180 moves++;
9181 /* Ignore NOP moves to self. */
9182 if (!rtx_equal_p (move[i].dst, move[i].src))
9183 emit_move_insn (move[i].dst, move[i].src);
9184
9185 /* Remove conflict from list. */
9186 move[i].src = NULL_RTX;
9187 }
9188 else
9189 blocked = i;
9190 }
9191
9192 /* Check for deadlock. This is when no moves occurred and we have
9193 at least one blocked move. */
9194 if (moves == 0 && blocked != -1)
9195 {
9196 /* Need to use scratch register to break deadlock.
9197 Add move to put dst of blocked move into scratch.
9198 When this move occurs, it will break chain deadlock.
9199 The scratch register is substituted for real move. */
9200
9201 gcc_assert (SCRATCH != GET_CODE (scratch));
9202
9203 move[size].src = move[blocked].dst;
9204 move[size].dst = scratch;
9205 /* Scratch move is never blocked. */
9206 move[size].links = -1;
9207 /* Make sure we have valid link. */
9208 gcc_assert (move[blocked].links != -1);
9209 /* Replace src of blocking move with scratch reg. */
9210 move[move[blocked].links].src = scratch;
9211 /* Make dependent on scratch move occurring. */
9212 move[blocked].links = size;
9213 size=size+1;
9214 }
9215 }
9216 while (blocked != -1);
9217 }
9218 return true;
9219 }
9220
9221
9222 /* Worker function for `ADJUST_INSN_LENGTH'. */
9223 /* Modifies the length assigned to instruction INSN
9224 LEN is the initially computed length of the insn. */
9225
9226 int
avr_adjust_insn_length(rtx_insn * insn,int len)9227 avr_adjust_insn_length (rtx_insn *insn, int len)
9228 {
9229 rtx *op = recog_data.operand;
9230 enum attr_adjust_len adjust_len;
9231
9232 /* As we pretend jump tables in .text, fix branch offsets crossing jump
9233 tables now. */
9234
9235 if (JUMP_TABLE_DATA_P (insn))
9236 return 0;
9237
9238 /* Some complex insns don't need length adjustment and therefore
9239 the length need not/must not be adjusted for these insns.
9240 It is easier to state this in an insn attribute "adjust_len" than
9241 to clutter up code here... */
9242
9243 if (!NONDEBUG_INSN_P (insn) || recog_memoized (insn) == -1)
9244 {
9245 return len;
9246 }
9247
9248 /* Read from insn attribute "adjust_len" if/how length is to be adjusted. */
9249
9250 adjust_len = get_attr_adjust_len (insn);
9251
9252 if (adjust_len == ADJUST_LEN_NO)
9253 {
9254 /* Nothing to adjust: The length from attribute "length" is fine.
9255 This is the default. */
9256
9257 return len;
9258 }
9259
9260 /* Extract insn's operands. */
9261
9262 extract_constrain_insn_cached (insn);
9263
9264 /* Dispatch to right function. */
9265
9266 switch (adjust_len)
9267 {
9268 case ADJUST_LEN_RELOAD_IN16: output_reload_inhi (op, op[2], &len); break;
9269 case ADJUST_LEN_RELOAD_IN24: avr_out_reload_inpsi (op, op[2], &len); break;
9270 case ADJUST_LEN_RELOAD_IN32: output_reload_insisf (op, op[2], &len); break;
9271
9272 case ADJUST_LEN_OUT_BITOP: avr_out_bitop (insn, op, &len); break;
9273
9274 case ADJUST_LEN_PLUS: avr_out_plus (insn, op, &len); break;
9275 case ADJUST_LEN_ADDTO_SP: avr_out_addto_sp (op, &len); break;
9276
9277 case ADJUST_LEN_MOV8: output_movqi (insn, op, &len); break;
9278 case ADJUST_LEN_MOV16: output_movhi (insn, op, &len); break;
9279 case ADJUST_LEN_MOV24: avr_out_movpsi (insn, op, &len); break;
9280 case ADJUST_LEN_MOV32: output_movsisf (insn, op, &len); break;
9281 case ADJUST_LEN_CPYMEM: avr_out_cpymem (insn, op, &len); break;
9282 case ADJUST_LEN_XLOAD: avr_out_xload (insn, op, &len); break;
9283 case ADJUST_LEN_SEXT: avr_out_sign_extend (insn, op, &len); break;
9284
9285 case ADJUST_LEN_SFRACT: avr_out_fract (insn, op, true, &len); break;
9286 case ADJUST_LEN_UFRACT: avr_out_fract (insn, op, false, &len); break;
9287 case ADJUST_LEN_ROUND: avr_out_round (insn, op, &len); break;
9288
9289 case ADJUST_LEN_TSTHI: avr_out_tsthi (insn, op, &len); break;
9290 case ADJUST_LEN_TSTPSI: avr_out_tstpsi (insn, op, &len); break;
9291 case ADJUST_LEN_TSTSI: avr_out_tstsi (insn, op, &len); break;
9292 case ADJUST_LEN_COMPARE: avr_out_compare (insn, op, &len); break;
9293 case ADJUST_LEN_COMPARE64: avr_out_compare64 (insn, op, &len); break;
9294
9295 case ADJUST_LEN_LSHRQI: lshrqi3_out (insn, op, &len); break;
9296 case ADJUST_LEN_LSHRHI: lshrhi3_out (insn, op, &len); break;
9297 case ADJUST_LEN_LSHRSI: lshrsi3_out (insn, op, &len); break;
9298
9299 case ADJUST_LEN_ASHRQI: ashrqi3_out (insn, op, &len); break;
9300 case ADJUST_LEN_ASHRHI: ashrhi3_out (insn, op, &len); break;
9301 case ADJUST_LEN_ASHRSI: ashrsi3_out (insn, op, &len); break;
9302
9303 case ADJUST_LEN_ASHLQI: ashlqi3_out (insn, op, &len); break;
9304 case ADJUST_LEN_ASHLHI: ashlhi3_out (insn, op, &len); break;
9305 case ADJUST_LEN_ASHLSI: ashlsi3_out (insn, op, &len); break;
9306
9307 case ADJUST_LEN_ASHLPSI: avr_out_ashlpsi3 (insn, op, &len); break;
9308 case ADJUST_LEN_ASHRPSI: avr_out_ashrpsi3 (insn, op, &len); break;
9309 case ADJUST_LEN_LSHRPSI: avr_out_lshrpsi3 (insn, op, &len); break;
9310
9311 case ADJUST_LEN_CALL: len = AVR_HAVE_JMP_CALL ? 2 : 1; break;
9312
9313 case ADJUST_LEN_INSERT_BITS: avr_out_insert_bits (op, &len); break;
9314
9315 case ADJUST_LEN_INSV_NOTBIT:
9316 avr_out_insert_notbit (insn, op, NULL_RTX, &len);
9317 break;
9318 case ADJUST_LEN_INSV_NOTBIT_0:
9319 avr_out_insert_notbit (insn, op, const0_rtx, &len);
9320 break;
9321 case ADJUST_LEN_INSV_NOTBIT_7:
9322 avr_out_insert_notbit (insn, op, GEN_INT (7), &len);
9323 break;
9324
9325 default:
9326 gcc_unreachable();
9327 }
9328
9329 return len;
9330 }
9331
9332 /* Return nonzero if register REG dead after INSN. */
9333
9334 int
reg_unused_after(rtx_insn * insn,rtx reg)9335 reg_unused_after (rtx_insn *insn, rtx reg)
9336 {
9337 return (dead_or_set_p (insn, reg)
9338 || (REG_P (reg) && _reg_unused_after (insn, reg)));
9339 }
9340
9341 /* Return nonzero if REG is not used after INSN.
9342 We assume REG is a reload reg, and therefore does
9343 not live past labels. It may live past calls or jumps though. */
9344
9345 int
_reg_unused_after(rtx_insn * insn,rtx reg)9346 _reg_unused_after (rtx_insn *insn, rtx reg)
9347 {
9348 enum rtx_code code;
9349 rtx set;
9350
9351 /* If the reg is set by this instruction, then it is safe for our
9352 case. Disregard the case where this is a store to memory, since
9353 we are checking a register used in the store address. */
9354 set = single_set (insn);
9355 if (set && !MEM_P (SET_DEST (set))
9356 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
9357 return 1;
9358
9359 while ((insn = NEXT_INSN (insn)))
9360 {
9361 rtx set;
9362 code = GET_CODE (insn);
9363
9364 #if 0
9365 /* If this is a label that existed before reload, then the register
9366 if dead here. However, if this is a label added by reorg, then
9367 the register may still be live here. We can't tell the difference,
9368 so we just ignore labels completely. */
9369 if (code == CODE_LABEL)
9370 return 1;
9371 /* else */
9372 #endif
9373
9374 if (!INSN_P (insn))
9375 continue;
9376
9377 if (code == JUMP_INSN)
9378 return 0;
9379
9380 /* If this is a sequence, we must handle them all at once.
9381 We could have for instance a call that sets the target register,
9382 and an insn in a delay slot that uses the register. In this case,
9383 we must return 0. */
9384 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
9385 {
9386 rtx_sequence *seq = as_a <rtx_sequence *> (PATTERN (insn));
9387 int retval = 0;
9388
9389 for (int i = 0; i < seq->len (); i++)
9390 {
9391 rtx_insn *this_insn = seq->insn (i);
9392 rtx set = single_set (this_insn);
9393
9394 if (CALL_P (this_insn))
9395 code = CALL_INSN;
9396 else if (JUMP_P (this_insn))
9397 {
9398 if (INSN_ANNULLED_BRANCH_P (this_insn))
9399 return 0;
9400 code = JUMP_INSN;
9401 }
9402
9403 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
9404 return 0;
9405 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
9406 {
9407 if (!MEM_P (SET_DEST (set)))
9408 retval = 1;
9409 else
9410 return 0;
9411 }
9412 if (set == 0
9413 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
9414 return 0;
9415 }
9416 if (retval == 1)
9417 return 1;
9418 else if (code == JUMP_INSN)
9419 return 0;
9420 }
9421
9422 if (code == CALL_INSN)
9423 {
9424 rtx tem;
9425 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
9426 if (GET_CODE (XEXP (tem, 0)) == USE
9427 && REG_P (XEXP (XEXP (tem, 0), 0))
9428 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
9429 return 0;
9430 if (call_used_or_fixed_reg_p (REGNO (reg)))
9431 return 1;
9432 }
9433
9434 set = single_set (insn);
9435
9436 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
9437 return 0;
9438 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
9439 return !MEM_P (SET_DEST (set));
9440 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
9441 return 0;
9442 }
9443 return 1;
9444 }
9445
9446
9447 /* Implement `TARGET_ASM_INTEGER'. */
9448 /* Target hook for assembling integer objects. The AVR version needs
9449 special handling for references to certain labels. */
9450
9451 static bool
avr_assemble_integer(rtx x,unsigned int size,int aligned_p)9452 avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
9453 {
9454 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
9455 && text_segment_operand (x, VOIDmode))
9456 {
9457 fputs ("\t.word\tgs(", asm_out_file);
9458 output_addr_const (asm_out_file, x);
9459 fputs (")\n", asm_out_file);
9460
9461 return true;
9462 }
9463 else if (GET_MODE (x) == PSImode)
9464 {
9465 /* This needs binutils 2.23+, see PR binutils/13503 */
9466
9467 fputs ("\t.byte\tlo8(", asm_out_file);
9468 output_addr_const (asm_out_file, x);
9469 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
9470
9471 fputs ("\t.byte\thi8(", asm_out_file);
9472 output_addr_const (asm_out_file, x);
9473 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
9474
9475 fputs ("\t.byte\thh8(", asm_out_file);
9476 output_addr_const (asm_out_file, x);
9477 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
9478
9479 return true;
9480 }
9481 else if (CONST_FIXED_P (x))
9482 {
9483 /* varasm fails to handle big fixed modes that don't fit in hwi. */
9484
9485 for (unsigned n = 0; n < size; n++)
9486 {
9487 rtx xn = simplify_gen_subreg (QImode, x, GET_MODE (x), n);
9488 default_assemble_integer (xn, 1, aligned_p);
9489 }
9490
9491 return true;
9492 }
9493
9494 if (AVR_TINY
9495 && avr_address_tiny_pm_p (x))
9496 {
9497 x = plus_constant (Pmode, x, avr_arch->flash_pm_offset);
9498 }
9499
9500 return default_assemble_integer (x, size, aligned_p);
9501 }
9502
9503 /* Implement TARGET_CLASS_MAX_NREGS. Reasons described in comments for
9504 avr_hard_regno_nregs. */
9505
9506 static unsigned char
avr_class_max_nregs(reg_class_t rclass,machine_mode mode)9507 avr_class_max_nregs (reg_class_t rclass, machine_mode mode)
9508 {
9509 if (rclass == CC_REG && mode == CCmode)
9510 return 1;
9511
9512 return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
9513 }
9514
9515
9516 /* Implement `TARGET_CLASS_LIKELY_SPILLED_P'. */
9517 /* Return value is nonzero if pseudos that have been
9518 assigned to registers of class CLASS would likely be spilled
9519 because registers of CLASS are needed for spill registers. */
9520
9521 static bool
avr_class_likely_spilled_p(reg_class_t c)9522 avr_class_likely_spilled_p (reg_class_t c)
9523 {
9524 return (c != ALL_REGS &&
9525 (AVR_TINY ? 1 : c != ADDW_REGS));
9526 }
9527
9528
9529 /* Valid attributes:
9530 progmem - Put data to program memory.
9531 signal - Make a function to be hardware interrupt.
9532 After function prologue interrupts remain disabled.
9533 interrupt - Make a function to be hardware interrupt. Before function
9534 prologue interrupts are enabled by means of SEI.
9535 naked - Don't generate function prologue/epilogue and RET
9536 instruction. */
9537
9538 /* Handle a "progmem" attribute; arguments as in
9539 struct attribute_spec.handler. */
9540
9541 static tree
avr_handle_progmem_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)9542 avr_handle_progmem_attribute (tree *node, tree name,
9543 tree args ATTRIBUTE_UNUSED,
9544 int flags ATTRIBUTE_UNUSED,
9545 bool *no_add_attrs)
9546 {
9547 if (DECL_P (*node))
9548 {
9549 if (TREE_CODE (*node) == TYPE_DECL)
9550 {
9551 /* This is really a decl attribute, not a type attribute,
9552 but try to handle it for GCC 3.0 backwards compatibility. */
9553
9554 tree type = TREE_TYPE (*node);
9555 tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
9556 tree newtype = build_type_attribute_variant (type, attr);
9557
9558 TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
9559 TREE_TYPE (*node) = newtype;
9560 *no_add_attrs = true;
9561 }
9562 else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
9563 {
9564 *no_add_attrs = false;
9565 }
9566 else
9567 {
9568 warning (OPT_Wattributes, "%qE attribute ignored",
9569 name);
9570 *no_add_attrs = true;
9571 }
9572 }
9573
9574 return NULL_TREE;
9575 }
9576
9577 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
9578 struct attribute_spec.handler. */
9579
9580 static tree
avr_handle_fndecl_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)9581 avr_handle_fndecl_attribute (tree *node, tree name,
9582 tree args ATTRIBUTE_UNUSED,
9583 int flags ATTRIBUTE_UNUSED,
9584 bool *no_add_attrs)
9585 {
9586 if (TREE_CODE (*node) != FUNCTION_DECL)
9587 {
9588 warning (OPT_Wattributes, "%qE attribute only applies to functions",
9589 name);
9590 *no_add_attrs = true;
9591 }
9592
9593 return NULL_TREE;
9594 }
9595
9596 static tree
avr_handle_fntype_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)9597 avr_handle_fntype_attribute (tree *node, tree name,
9598 tree args ATTRIBUTE_UNUSED,
9599 int flags ATTRIBUTE_UNUSED,
9600 bool *no_add_attrs)
9601 {
9602 if (TREE_CODE (*node) != FUNCTION_TYPE)
9603 {
9604 warning (OPT_Wattributes, "%qE attribute only applies to functions",
9605 name);
9606 *no_add_attrs = true;
9607 }
9608
9609 return NULL_TREE;
9610 }
9611
9612 static tree
avr_handle_absdata_attribute(tree * node,tree name,tree,int,bool * no_add)9613 avr_handle_absdata_attribute (tree *node, tree name, tree /* args */,
9614 int /* flags */, bool *no_add)
9615 {
9616 location_t loc = DECL_SOURCE_LOCATION (*node);
9617
9618 if (AVR_TINY)
9619 {
9620 if (TREE_CODE (*node) != VAR_DECL
9621 || (!TREE_STATIC (*node) && !DECL_EXTERNAL (*node)))
9622 {
9623 warning_at (loc, OPT_Wattributes, "%qE attribute only applies to"
9624 " variables in static storage", name);
9625 *no_add = true;
9626 }
9627 }
9628 else
9629 {
9630 warning_at (loc, OPT_Wattributes, "%qE attribute only supported"
9631 " for reduced Tiny cores", name);
9632 *no_add = true;
9633 }
9634
9635 return NULL_TREE;
9636 }
9637
9638 static tree
avr_handle_addr_attribute(tree * node,tree name,tree args,int flags ATTRIBUTE_UNUSED,bool * no_add)9639 avr_handle_addr_attribute (tree *node, tree name, tree args,
9640 int flags ATTRIBUTE_UNUSED, bool *no_add)
9641 {
9642 bool io_p = startswith (IDENTIFIER_POINTER (name), "io");
9643 location_t loc = DECL_SOURCE_LOCATION (*node);
9644
9645 if (!VAR_P (*node))
9646 {
9647 warning_at (loc, OPT_Wattributes, "%qE attribute only applies to "
9648 "variables", name);
9649 *no_add = true;
9650 return NULL_TREE;
9651 }
9652
9653 if (args != NULL_TREE)
9654 {
9655 if (TREE_CODE (TREE_VALUE (args)) == NON_LVALUE_EXPR)
9656 TREE_VALUE (args) = TREE_OPERAND (TREE_VALUE (args), 0);
9657 tree arg = TREE_VALUE (args);
9658 if (TREE_CODE (arg) != INTEGER_CST)
9659 {
9660 warning_at (loc, OPT_Wattributes, "%qE attribute allows only an "
9661 "integer constant argument", name);
9662 *no_add = true;
9663 }
9664 else if (io_p
9665 && (!tree_fits_shwi_p (arg)
9666 || !(strcmp (IDENTIFIER_POINTER (name), "io_low") == 0
9667 ? low_io_address_operand : io_address_operand)
9668 (GEN_INT (TREE_INT_CST_LOW (arg)), QImode)))
9669 {
9670 warning_at (loc, OPT_Wattributes, "%qE attribute address "
9671 "out of range", name);
9672 *no_add = true;
9673 }
9674 else
9675 {
9676 tree attribs = DECL_ATTRIBUTES (*node);
9677 const char *names[] = { "io", "io_low", "address", NULL };
9678 for (const char **p = names; *p; p++)
9679 {
9680 tree other = lookup_attribute (*p, attribs);
9681 if (other && TREE_VALUE (other))
9682 {
9683 warning_at (loc, OPT_Wattributes,
9684 "both %s and %qE attribute provide address",
9685 *p, name);
9686 *no_add = true;
9687 break;
9688 }
9689 }
9690 }
9691 }
9692
9693 if (*no_add == false && io_p && !TREE_THIS_VOLATILE (*node))
9694 warning_at (loc, OPT_Wattributes, "%qE attribute on non-volatile variable",
9695 name);
9696
9697 return NULL_TREE;
9698 }
9699
9700 rtx
avr_eval_addr_attrib(rtx x)9701 avr_eval_addr_attrib (rtx x)
9702 {
9703 if (SYMBOL_REF_P (x)
9704 && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_ADDRESS))
9705 {
9706 tree decl = SYMBOL_REF_DECL (x);
9707 tree attr = NULL_TREE;
9708
9709 if (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO)
9710 {
9711 attr = lookup_attribute ("io", DECL_ATTRIBUTES (decl));
9712 if (!attr || !TREE_VALUE (attr))
9713 attr = lookup_attribute ("io_low", DECL_ATTRIBUTES (decl));
9714 gcc_assert (attr);
9715 }
9716 if (!attr || !TREE_VALUE (attr))
9717 attr = lookup_attribute ("address", DECL_ATTRIBUTES (decl));
9718 gcc_assert (attr && TREE_VALUE (attr) && TREE_VALUE (TREE_VALUE (attr)));
9719 return GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))));
9720 }
9721 return x;
9722 }
9723
9724
9725 /* AVR attributes. */
9726 static const struct attribute_spec avr_attribute_table[] =
9727 {
9728 /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
9729 affects_type_identity, handler, exclude } */
9730 { "progmem", 0, 0, false, false, false, false,
9731 avr_handle_progmem_attribute, NULL },
9732 { "signal", 0, 0, true, false, false, false,
9733 avr_handle_fndecl_attribute, NULL },
9734 { "interrupt", 0, 0, true, false, false, false,
9735 avr_handle_fndecl_attribute, NULL },
9736 { "no_gccisr", 0, 0, true, false, false, false,
9737 avr_handle_fndecl_attribute, NULL },
9738 { "naked", 0, 0, false, true, true, false,
9739 avr_handle_fntype_attribute, NULL },
9740 { "OS_task", 0, 0, false, true, true, false,
9741 avr_handle_fntype_attribute, NULL },
9742 { "OS_main", 0, 0, false, true, true, false,
9743 avr_handle_fntype_attribute, NULL },
9744 { "io", 0, 1, true, false, false, false,
9745 avr_handle_addr_attribute, NULL },
9746 { "io_low", 0, 1, true, false, false, false,
9747 avr_handle_addr_attribute, NULL },
9748 { "address", 1, 1, true, false, false, false,
9749 avr_handle_addr_attribute, NULL },
9750 { "absdata", 0, 0, true, false, false, false,
9751 avr_handle_absdata_attribute, NULL },
9752 { NULL, 0, 0, false, false, false, false, NULL, NULL }
9753 };
9754
9755
9756 /* Return true if we support address space AS for the architecture in effect
9757 and false, otherwise. If LOC is not UNKNOWN_LOCATION then also issue
9758 a respective error. */
9759
9760 bool
avr_addr_space_supported_p(addr_space_t as,location_t loc)9761 avr_addr_space_supported_p (addr_space_t as, location_t loc)
9762 {
9763 if (AVR_TINY)
9764 {
9765 if (loc != UNKNOWN_LOCATION)
9766 error_at (loc, "address spaces are not supported for reduced "
9767 "Tiny devices");
9768 return false;
9769 }
9770 else if (avr_addrspace[as].segment >= avr_n_flash)
9771 {
9772 if (loc != UNKNOWN_LOCATION)
9773 error_at (loc, "address space %qs not supported for devices with "
9774 "flash size up to %d KiB", avr_addrspace[as].name,
9775 64 * avr_n_flash);
9776 return false;
9777 }
9778
9779 return true;
9780 }
9781
9782
9783 /* Implement `TARGET_ADDR_SPACE_DIAGNOSE_USAGE'. */
9784
9785 static void
avr_addr_space_diagnose_usage(addr_space_t as,location_t loc)9786 avr_addr_space_diagnose_usage (addr_space_t as, location_t loc)
9787 {
9788 (void) avr_addr_space_supported_p (as, loc);
9789 }
9790
9791
9792 /* Look if DECL shall be placed in program memory space by
9793 means of attribute `progmem' or some address-space qualifier.
9794 Return non-zero if DECL is data that must end up in Flash and
9795 zero if the data lives in RAM (.bss, .data, .rodata, ...).
9796
9797 Return 2 if DECL is located in 24-bit flash address-space
9798 Return 1 if DECL is located in 16-bit flash address-space
9799 Return -1 if attribute `progmem' occurs in DECL or ATTRIBUTES
9800 Return 0 otherwise */
9801
9802 int
avr_progmem_p(tree decl,tree attributes)9803 avr_progmem_p (tree decl, tree attributes)
9804 {
9805 tree a;
9806
9807 if (TREE_CODE (decl) != VAR_DECL)
9808 return 0;
9809
9810 if (avr_decl_memx_p (decl))
9811 return 2;
9812
9813 if (avr_decl_flash_p (decl))
9814 return 1;
9815
9816 if (NULL_TREE
9817 != lookup_attribute ("progmem", attributes))
9818 return -1;
9819
9820 a = decl;
9821
9822 do
9823 a = TREE_TYPE(a);
9824 while (TREE_CODE (a) == ARRAY_TYPE);
9825
9826 if (a == error_mark_node)
9827 return 0;
9828
9829 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
9830 return -1;
9831
9832 return 0;
9833 }
9834
9835
9836 /* Return true if DECL has attribute `absdata' set. This function should
9837 only be used for AVR_TINY. */
9838
9839 static bool
avr_decl_absdata_p(tree decl,tree attributes)9840 avr_decl_absdata_p (tree decl, tree attributes)
9841 {
9842 return (TREE_CODE (decl) == VAR_DECL
9843 && NULL_TREE != lookup_attribute ("absdata", attributes));
9844 }
9845
9846
9847 /* Scan type TYP for pointer references to address space ASn.
9848 Return ADDR_SPACE_GENERIC (i.e. 0) if all pointers targeting
9849 the AS are also declared to be CONST.
9850 Otherwise, return the respective address space, i.e. a value != 0. */
9851
9852 static addr_space_t
avr_nonconst_pointer_addrspace(tree typ)9853 avr_nonconst_pointer_addrspace (tree typ)
9854 {
9855 while (ARRAY_TYPE == TREE_CODE (typ))
9856 typ = TREE_TYPE (typ);
9857
9858 if (POINTER_TYPE_P (typ))
9859 {
9860 addr_space_t as;
9861 tree target = TREE_TYPE (typ);
9862
9863 /* Pointer to function: Test the function's return type. */
9864
9865 if (FUNCTION_TYPE == TREE_CODE (target))
9866 return avr_nonconst_pointer_addrspace (TREE_TYPE (target));
9867
9868 /* "Ordinary" pointers... */
9869
9870 while (TREE_CODE (target) == ARRAY_TYPE)
9871 target = TREE_TYPE (target);
9872
9873 /* Pointers to non-generic address space must be const. */
9874
9875 as = TYPE_ADDR_SPACE (target);
9876
9877 if (!ADDR_SPACE_GENERIC_P (as)
9878 && !TYPE_READONLY (target)
9879 && avr_addr_space_supported_p (as))
9880 {
9881 return as;
9882 }
9883
9884 /* Scan pointer's target type. */
9885
9886 return avr_nonconst_pointer_addrspace (target);
9887 }
9888
9889 return ADDR_SPACE_GENERIC;
9890 }
9891
9892
9893 /* Sanity check NODE so that all pointers targeting non-generic address spaces
9894 go along with CONST qualifier. Writing to these address spaces should
9895 be detected and complained about as early as possible. */
9896
9897 static bool
avr_pgm_check_var_decl(tree node)9898 avr_pgm_check_var_decl (tree node)
9899 {
9900 const char *reason = NULL;
9901
9902 addr_space_t as = ADDR_SPACE_GENERIC;
9903
9904 gcc_assert (as == 0);
9905
9906 if (avr_log.progmem)
9907 avr_edump ("%?: %t\n", node);
9908
9909 switch (TREE_CODE (node))
9910 {
9911 default:
9912 break;
9913
9914 case VAR_DECL:
9915 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
9916 reason = _("variable");
9917 break;
9918
9919 case PARM_DECL:
9920 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
9921 reason = _("function parameter");
9922 break;
9923
9924 case FIELD_DECL:
9925 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
9926 reason = _("structure field");
9927 break;
9928
9929 case FUNCTION_DECL:
9930 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (TREE_TYPE (node))),
9931 as)
9932 reason = _("return type of function");
9933 break;
9934
9935 case POINTER_TYPE:
9936 if (as = avr_nonconst_pointer_addrspace (node), as)
9937 reason = _("pointer");
9938 break;
9939 }
9940
9941 if (reason)
9942 {
9943 if (TYPE_P (node))
9944 error ("pointer targeting address space %qs must be const in %qT",
9945 avr_addrspace[as].name, node);
9946 else
9947 error ("pointer targeting address space %qs must be const"
9948 " in %s %q+D",
9949 avr_addrspace[as].name, reason, node);
9950 }
9951
9952 return reason == NULL;
9953 }
9954
9955
9956 /* Implement `TARGET_INSERT_ATTRIBUTES'. */
9957
9958 static void
avr_insert_attributes(tree node,tree * attributes)9959 avr_insert_attributes (tree node, tree *attributes)
9960 {
9961 avr_pgm_check_var_decl (node);
9962
9963 if (TARGET_MAIN_IS_OS_TASK
9964 && TREE_CODE (node) == FUNCTION_DECL
9965 && MAIN_NAME_P (DECL_NAME (node))
9966 // FIXME: We'd like to also test `flag_hosted' which is only
9967 // available in the C-ish fronts, hence no such test for now.
9968 // Instead, we test the return type of "main" which is not exactly
9969 // the same but good enough.
9970 && INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (node)))
9971 && NULL == lookup_attribute ("OS_task", *attributes))
9972 {
9973 *attributes = tree_cons (get_identifier ("OS_task"),
9974 NULL, *attributes);
9975 }
9976
9977 /* Add the section attribute if the variable is in progmem. */
9978
9979 if (TREE_CODE (node) == VAR_DECL
9980 && (TREE_STATIC (node) || DECL_EXTERNAL (node))
9981 && avr_progmem_p (node, *attributes))
9982 {
9983 addr_space_t as;
9984 tree node0 = node;
9985
9986 /* For C++, we have to peel arrays in order to get correct
9987 determination of readonlyness. */
9988
9989 do
9990 node0 = TREE_TYPE (node0);
9991 while (TREE_CODE (node0) == ARRAY_TYPE);
9992
9993 if (error_mark_node == node0)
9994 return;
9995
9996 as = TYPE_ADDR_SPACE (TREE_TYPE (node));
9997
9998 if (!TYPE_READONLY (node0)
9999 && !TREE_READONLY (node))
10000 {
10001 const char *reason = "__attribute__((progmem))";
10002
10003 if (!ADDR_SPACE_GENERIC_P (as))
10004 reason = avr_addrspace[as].name;
10005
10006 if (avr_log.progmem)
10007 avr_edump ("\n%?: %t\n%t\n", node, node0);
10008
10009 error ("variable %q+D must be const in order to be put into"
10010 " read-only section by means of %qs", node, reason);
10011 }
10012 }
10013 }
10014
10015
10016 /* Implement `ASM_OUTPUT_ALIGNED_DECL_LOCAL'. */
10017 /* Implement `ASM_OUTPUT_ALIGNED_DECL_COMMON'. */
10018 /* Track need of __do_clear_bss. */
10019
10020 void
avr_asm_output_aligned_decl_common(FILE * stream,tree decl,const char * name,unsigned HOST_WIDE_INT size,unsigned int align,bool local_p)10021 avr_asm_output_aligned_decl_common (FILE * stream,
10022 tree decl,
10023 const char *name,
10024 unsigned HOST_WIDE_INT size,
10025 unsigned int align, bool local_p)
10026 {
10027 rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
10028 rtx symbol;
10029
10030 if (mem != NULL_RTX && MEM_P (mem)
10031 && SYMBOL_REF_P ((symbol = XEXP (mem, 0)))
10032 && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
10033 {
10034 if (!local_p)
10035 {
10036 fprintf (stream, "\t.globl\t");
10037 assemble_name (stream, name);
10038 fprintf (stream, "\n");
10039 }
10040 if (SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS)
10041 {
10042 assemble_name (stream, name);
10043 fprintf (stream, " = %ld\n",
10044 (long) INTVAL (avr_eval_addr_attrib (symbol)));
10045 }
10046 else if (local_p)
10047 error_at (DECL_SOURCE_LOCATION (decl),
10048 "static IO declaration for %q+D needs an address", decl);
10049 return;
10050 }
10051
10052 /* __gnu_lto_slim is just a marker for the linker injected by toplev.c.
10053 There is no need to trigger __do_clear_bss code for them. */
10054
10055 if (!startswith (name, "__gnu_lto"))
10056 avr_need_clear_bss_p = true;
10057
10058 if (local_p)
10059 ASM_OUTPUT_ALIGNED_LOCAL (stream, name, size, align);
10060 else
10061 ASM_OUTPUT_ALIGNED_COMMON (stream, name, size, align);
10062 }
10063
10064 void
avr_asm_asm_output_aligned_bss(FILE * file,tree decl,const char * name,unsigned HOST_WIDE_INT size,int align,void (* default_func)(FILE *,tree,const char *,unsigned HOST_WIDE_INT,int))10065 avr_asm_asm_output_aligned_bss (FILE *file, tree decl, const char *name,
10066 unsigned HOST_WIDE_INT size, int align,
10067 void (*default_func)
10068 (FILE *, tree, const char *,
10069 unsigned HOST_WIDE_INT, int))
10070 {
10071 rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
10072 rtx symbol;
10073
10074 if (mem != NULL_RTX && MEM_P (mem)
10075 && SYMBOL_REF_P ((symbol = XEXP (mem, 0)))
10076 && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
10077 {
10078 if (!(SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS))
10079 error_at (DECL_SOURCE_LOCATION (decl),
10080 "IO definition for %q+D needs an address", decl);
10081 avr_asm_output_aligned_decl_common (file, decl, name, size, align, false);
10082 }
10083 else
10084 default_func (file, decl, name, size, align);
10085 }
10086
10087
10088 /* Unnamed section callback for data_section
10089 to track need of __do_copy_data. */
10090
10091 static void
avr_output_data_section_asm_op(const void * data)10092 avr_output_data_section_asm_op (const void *data)
10093 {
10094 avr_need_copy_data_p = true;
10095
10096 /* Dispatch to default. */
10097 output_section_asm_op (data);
10098 }
10099
10100
10101 /* Unnamed section callback for bss_section
10102 to track need of __do_clear_bss. */
10103
10104 static void
avr_output_bss_section_asm_op(const void * data)10105 avr_output_bss_section_asm_op (const void *data)
10106 {
10107 avr_need_clear_bss_p = true;
10108
10109 /* Dispatch to default. */
10110 output_section_asm_op (data);
10111 }
10112
10113
10114 /* Unnamed section callback for progmem*.data sections. */
10115
10116 static void
avr_output_progmem_section_asm_op(const char * data)10117 avr_output_progmem_section_asm_op (const char *data)
10118 {
10119 fprintf (asm_out_file, "\t.section\t%s,\"a\",@progbits\n", data);
10120 }
10121
10122
10123 /* Implement `TARGET_ASM_INIT_SECTIONS'. */
10124
10125 static void
avr_asm_init_sections(void)10126 avr_asm_init_sections (void)
10127 {
10128 /* Override section callbacks to keep track of `avr_need_clear_bss_p'
10129 resp. `avr_need_copy_data_p'. If flash is not mapped to RAM then
10130 we have also to track .rodata because it is located in RAM then. */
10131
10132 #if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
10133 if (avr_arch->flash_pm_offset == 0)
10134 #endif
10135 readonly_data_section->unnamed.callback = avr_output_data_section_asm_op;
10136 data_section->unnamed.callback = avr_output_data_section_asm_op;
10137 bss_section->unnamed.callback = avr_output_bss_section_asm_op;
10138 }
10139
10140
10141 /* Implement `TARGET_ASM_NAMED_SECTION'. */
10142 /* Track need of __do_clear_bss, __do_copy_data for named sections. */
10143
10144 static void
avr_asm_named_section(const char * name,unsigned int flags,tree decl)10145 avr_asm_named_section (const char *name, unsigned int flags, tree decl)
10146 {
10147 if (flags & AVR_SECTION_PROGMEM)
10148 {
10149 addr_space_t as = (flags & AVR_SECTION_PROGMEM) / SECTION_MACH_DEP;
10150 const char *old_prefix = ".rodata";
10151 const char *new_prefix = avr_addrspace[as].section_name;
10152
10153 if (startswith (name, old_prefix))
10154 {
10155 const char *sname = ACONCAT ((new_prefix,
10156 name + strlen (old_prefix), NULL));
10157 default_elf_asm_named_section (sname, flags, decl);
10158 return;
10159 }
10160
10161 default_elf_asm_named_section (new_prefix, flags, decl);
10162 return;
10163 }
10164
10165 if (!avr_need_copy_data_p)
10166 avr_need_copy_data_p = (startswith (name, ".data")
10167 || startswith (name, ".gnu.linkonce.d"));
10168
10169 if (!avr_need_copy_data_p
10170 #if defined HAVE_LD_AVR_AVRXMEGA3_RODATA_IN_FLASH
10171 && avr_arch->flash_pm_offset == 0
10172 #endif
10173 )
10174 avr_need_copy_data_p = (startswith (name, ".rodata")
10175 || startswith (name, ".gnu.linkonce.r"));
10176
10177 if (!avr_need_clear_bss_p)
10178 avr_need_clear_bss_p = startswith (name, ".bss");
10179
10180 default_elf_asm_named_section (name, flags, decl);
10181 }
10182
10183
10184 /* Implement `TARGET_SECTION_TYPE_FLAGS'. */
10185
10186 static unsigned int
avr_section_type_flags(tree decl,const char * name,int reloc)10187 avr_section_type_flags (tree decl, const char *name, int reloc)
10188 {
10189 unsigned int flags = default_section_type_flags (decl, name, reloc);
10190
10191 if (startswith (name, ".noinit"))
10192 {
10193 if (decl && TREE_CODE (decl) == VAR_DECL
10194 && DECL_INITIAL (decl) == NULL_TREE)
10195 flags |= SECTION_BSS; /* @nobits */
10196 else
10197 warning (0, "only uninitialized variables can be placed in the "
10198 ".noinit section");
10199 }
10200
10201 if (decl && DECL_P (decl)
10202 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
10203 {
10204 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
10205
10206 /* Attribute progmem puts data in generic address space.
10207 Set section flags as if it was in __flash to get the right
10208 section prefix in the remainder. */
10209
10210 if (ADDR_SPACE_GENERIC_P (as))
10211 as = ADDR_SPACE_FLASH;
10212
10213 flags |= as * SECTION_MACH_DEP;
10214 flags &= ~SECTION_WRITE;
10215 flags &= ~SECTION_BSS;
10216 }
10217
10218 return flags;
10219 }
10220
10221
10222 /* A helper for the next function. NODE is a decl that is associated with
10223 a symbol. Return TRUE if the respective object may be accessed by LDS.
10224 There might still be other reasons for why LDS is not appropriate.
10225 This function is only appropriate for AVR_TINY. */
10226
10227 static bool
avr_decl_maybe_lds_p(tree node)10228 avr_decl_maybe_lds_p (tree node)
10229 {
10230 if (!node
10231 || TREE_CODE (node) != VAR_DECL
10232 || DECL_SECTION_NAME (node) != NULL)
10233 return false;
10234
10235 /* Don't use LDS for objects that go to .rodata. The current default
10236 linker description file still locates .rodata in RAM, but this is not
10237 a must. A better linker script would just keep .rodata in flash and
10238 add an offset of 0x4000 to the VMA. Hence avoid LDS for such data. */
10239
10240 if (TREE_READONLY (node))
10241 return false;
10242
10243 // C++ requires peeling arrays.
10244
10245 do
10246 node = TREE_TYPE (node);
10247 while (ARRAY_TYPE == TREE_CODE (node));
10248
10249 return (node != error_mark_node
10250 && !TYPE_READONLY (node));
10251 }
10252
10253
10254 /* Implement `TARGET_ENCODE_SECTION_INFO'. */
10255
10256 static void
avr_encode_section_info(tree decl,rtx rtl,int new_decl_p)10257 avr_encode_section_info (tree decl, rtx rtl, int new_decl_p)
10258 {
10259 tree addr_attr = NULL_TREE;
10260
10261 /* In avr_handle_progmem_attribute, DECL_INITIAL is not yet
10262 readily available, see PR34734. So we postpone the warning
10263 about uninitialized data in program memory section until here. */
10264
10265 if (new_decl_p
10266 && decl && DECL_P (decl)
10267 && !DECL_EXTERNAL (decl)
10268 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
10269 {
10270 if (!TREE_READONLY (decl))
10271 {
10272 // This might happen with C++ if stuff needs constructing.
10273 error ("variable %q+D with dynamic initialization put "
10274 "into program memory area", decl);
10275 }
10276 else if (NULL_TREE == DECL_INITIAL (decl))
10277 {
10278 // Don't warn for (implicit) aliases like in PR80462.
10279 tree asmname = DECL_ASSEMBLER_NAME (decl);
10280 varpool_node *node = varpool_node::get_for_asmname (asmname);
10281 bool alias_p = node && node->alias;
10282
10283 if (!alias_p)
10284 warning (OPT_Wuninitialized, "uninitialized variable %q+D put "
10285 "into program memory area", decl);
10286 }
10287 }
10288
10289 default_encode_section_info (decl, rtl, new_decl_p);
10290
10291 if (decl && DECL_P (decl)
10292 && TREE_CODE (decl) != FUNCTION_DECL
10293 && MEM_P (rtl)
10294 && SYMBOL_REF_P (XEXP (rtl, 0)))
10295 {
10296 rtx sym = XEXP (rtl, 0);
10297 tree type = TREE_TYPE (decl);
10298 tree attr = DECL_ATTRIBUTES (decl);
10299 if (type == error_mark_node)
10300 return;
10301
10302 addr_space_t as = TYPE_ADDR_SPACE (type);
10303
10304 /* PSTR strings are in generic space but located in flash:
10305 patch address space. */
10306
10307 if (!AVR_TINY && avr_progmem_p (decl, attr) == -1)
10308 as = ADDR_SPACE_FLASH;
10309
10310 AVR_SYMBOL_SET_ADDR_SPACE (sym, as);
10311
10312 tree io_low_attr = lookup_attribute ("io_low", attr);
10313 tree io_attr = lookup_attribute ("io", attr);
10314
10315 if (io_low_attr
10316 && TREE_VALUE (io_low_attr) && TREE_VALUE (TREE_VALUE (io_low_attr)))
10317 addr_attr = io_attr;
10318 else if (io_attr
10319 && TREE_VALUE (io_attr) && TREE_VALUE (TREE_VALUE (io_attr)))
10320 addr_attr = io_attr;
10321 else
10322 addr_attr = lookup_attribute ("address", attr);
10323 if (io_low_attr
10324 || (io_attr && addr_attr
10325 && low_io_address_operand
10326 (GEN_INT (TREE_INT_CST_LOW
10327 (TREE_VALUE (TREE_VALUE (addr_attr)))), QImode)))
10328 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO_LOW;
10329 if (io_attr || io_low_attr)
10330 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO;
10331 /* If we have an (io) address attribute specification, but the variable
10332 is external, treat the address as only a tentative definition
10333 to be used to determine if an io port is in the lower range, but
10334 don't use the exact value for constant propagation. */
10335 if (addr_attr && !DECL_EXTERNAL (decl))
10336 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_ADDRESS;
10337 }
10338
10339 if (AVR_TINY
10340 && decl
10341 && VAR_DECL == TREE_CODE (decl)
10342 && MEM_P (rtl)
10343 && SYMBOL_REF_P (XEXP (rtl, 0)))
10344 {
10345 rtx sym = XEXP (rtl, 0);
10346 bool progmem_p = avr_progmem_p (decl, DECL_ATTRIBUTES (decl)) == -1;
10347
10348 if (progmem_p)
10349 {
10350 // Tag symbols for addition of 0x4000 (avr_arch->flash_pm_offset).
10351 SYMBOL_REF_FLAGS (sym) |= AVR_SYMBOL_FLAG_TINY_PM;
10352 }
10353
10354 if (avr_decl_absdata_p (decl, DECL_ATTRIBUTES (decl))
10355 || (TARGET_ABSDATA
10356 && !progmem_p
10357 && !addr_attr
10358 && avr_decl_maybe_lds_p (decl))
10359 || (addr_attr
10360 // If addr_attr is non-null, it has an argument. Peek into it.
10361 && TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (addr_attr))) < 0xc0))
10362 {
10363 // May be accessed by LDS / STS.
10364 SYMBOL_REF_FLAGS (sym) |= AVR_SYMBOL_FLAG_TINY_ABSDATA;
10365 }
10366
10367 if (progmem_p
10368 && avr_decl_absdata_p (decl, DECL_ATTRIBUTES (decl)))
10369 {
10370 error ("%q+D has incompatible attributes %qs and %qs",
10371 decl, "progmem", "absdata");
10372 }
10373 }
10374 }
10375
10376
10377 /* Implement `TARGET_ASM_SELECT_SECTION' */
10378
10379 static section *
avr_asm_select_section(tree decl,int reloc,unsigned HOST_WIDE_INT align)10380 avr_asm_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
10381 {
10382 section * sect = default_elf_select_section (decl, reloc, align);
10383
10384 if (decl && DECL_P (decl)
10385 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
10386 {
10387 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
10388
10389 /* __progmem__ goes in generic space but shall be allocated to
10390 .progmem.data */
10391
10392 if (ADDR_SPACE_GENERIC_P (as))
10393 as = ADDR_SPACE_FLASH;
10394
10395 if (sect->common.flags & SECTION_NAMED)
10396 {
10397 const char * name = sect->named.name;
10398 const char * old_prefix = ".rodata";
10399 const char * new_prefix = avr_addrspace[as].section_name;
10400
10401 if (startswith (name, old_prefix))
10402 {
10403 const char *sname = ACONCAT ((new_prefix,
10404 name + strlen (old_prefix), NULL));
10405 return get_section (sname,
10406 sect->common.flags & ~SECTION_DECLARED,
10407 sect->named.decl);
10408 }
10409 }
10410
10411 if (!progmem_section[as])
10412 {
10413 progmem_section[as]
10414 = get_unnamed_section (0, avr_output_progmem_section_asm_op,
10415 avr_addrspace[as].section_name);
10416 }
10417
10418 return progmem_section[as];
10419 }
10420
10421 return sect;
10422 }
10423
10424 /* Implement `TARGET_ASM_FILE_START'. */
10425 /* Outputs some text at the start of each assembler file. */
10426
10427 static void
avr_file_start(void)10428 avr_file_start (void)
10429 {
10430 int sfr_offset = avr_arch->sfr_offset;
10431
10432 if (avr_arch->asm_only)
10433 error ("architecture %qs supported for assembler only", avr_mmcu);
10434
10435 default_file_start ();
10436
10437 /* Print I/O addresses of some SFRs used with IN and OUT. */
10438
10439 if (AVR_HAVE_SPH)
10440 fprintf (asm_out_file, "__SP_H__ = 0x%02x\n", avr_addr.sp_h - sfr_offset);
10441
10442 fprintf (asm_out_file, "__SP_L__ = 0x%02x\n", avr_addr.sp_l - sfr_offset);
10443 fprintf (asm_out_file, "__SREG__ = 0x%02x\n", avr_addr.sreg - sfr_offset);
10444 if (AVR_HAVE_RAMPZ)
10445 fprintf (asm_out_file, "__RAMPZ__ = 0x%02x\n", avr_addr.rampz - sfr_offset);
10446 if (AVR_HAVE_RAMPY)
10447 fprintf (asm_out_file, "__RAMPY__ = 0x%02x\n", avr_addr.rampy - sfr_offset);
10448 if (AVR_HAVE_RAMPX)
10449 fprintf (asm_out_file, "__RAMPX__ = 0x%02x\n", avr_addr.rampx - sfr_offset);
10450 if (AVR_HAVE_RAMPD)
10451 fprintf (asm_out_file, "__RAMPD__ = 0x%02x\n", avr_addr.rampd - sfr_offset);
10452 if (AVR_XMEGA || AVR_TINY)
10453 fprintf (asm_out_file, "__CCP__ = 0x%02x\n", avr_addr.ccp - sfr_offset);
10454 fprintf (asm_out_file, "__tmp_reg__ = %d\n", AVR_TMP_REGNO);
10455 fprintf (asm_out_file, "__zero_reg__ = %d\n", AVR_ZERO_REGNO);
10456 }
10457
10458
10459 /* Implement `TARGET_ASM_FILE_END'. */
10460 /* Outputs to the stdio stream FILE some
10461 appropriate text to go at the end of an assembler file. */
10462
10463 static void
avr_file_end(void)10464 avr_file_end (void)
10465 {
10466 /* Output these only if there is anything in the
10467 .data* / .rodata* / .gnu.linkonce.* resp. .bss* or COMMON
10468 input section(s) - some code size can be saved by not
10469 linking in the initialization code from libgcc if resp.
10470 sections are empty, see PR18145. */
10471
10472 if (avr_need_copy_data_p)
10473 fputs (".global __do_copy_data\n", asm_out_file);
10474
10475 if (avr_need_clear_bss_p)
10476 fputs (".global __do_clear_bss\n", asm_out_file);
10477 }
10478
10479
10480 /* Worker function for `ADJUST_REG_ALLOC_ORDER'. */
10481 /* Choose the order in which to allocate hard registers for
10482 pseudo-registers local to a basic block.
10483
10484 Store the desired register order in the array `reg_alloc_order'.
10485 Element 0 should be the register to allocate first; element 1, the
10486 next register; and so on. */
10487
10488 void
avr_adjust_reg_alloc_order(void)10489 avr_adjust_reg_alloc_order (void)
10490 {
10491 static const int order_0[] =
10492 {
10493 24, 25,
10494 18, 19, 20, 21, 22, 23,
10495 30, 31,
10496 26, 27, 28, 29,
10497 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
10498 0, 1,
10499 32, 33, 34, 35
10500 };
10501 static const int tiny_order_0[] = {
10502 20, 21,
10503 22, 23,
10504 24, 25,
10505 30, 31,
10506 26, 27,
10507 28, 29,
10508 19, 18,
10509 16, 17,
10510 32, 33, 34, 35,
10511 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
10512 };
10513 static const int order_1[] =
10514 {
10515 18, 19, 20, 21, 22, 23, 24, 25,
10516 30, 31,
10517 26, 27, 28, 29,
10518 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
10519 0, 1,
10520 32, 33, 34, 35
10521 };
10522 static const int tiny_order_1[] = {
10523 22, 23,
10524 24, 25,
10525 30, 31,
10526 26, 27,
10527 28, 29,
10528 21, 20, 19, 18,
10529 16, 17,
10530 32, 33, 34, 35,
10531 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
10532 };
10533 static const int order_2[] =
10534 {
10535 25, 24, 23, 22, 21, 20, 19, 18,
10536 30, 31,
10537 26, 27, 28, 29,
10538 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
10539 1, 0,
10540 32, 33, 34, 35
10541 };
10542
10543 /* Select specific register allocation order.
10544 Tiny Core (ATtiny4/5/9/10/20/40) devices have only 16 registers,
10545 so different allocation order should be used. */
10546
10547 const int *order = (TARGET_ORDER_1 ? (AVR_TINY ? tiny_order_1 : order_1)
10548 : TARGET_ORDER_2 ? (AVR_TINY ? tiny_order_0 : order_2)
10549 : (AVR_TINY ? tiny_order_0 : order_0));
10550
10551 for (size_t i = 0; i < ARRAY_SIZE (order_0); ++i)
10552 reg_alloc_order[i] = order[i];
10553 }
10554
10555
10556 /* Implement `TARGET_REGISTER_MOVE_COST' */
10557
10558 static int
avr_register_move_cost(machine_mode mode ATTRIBUTE_UNUSED,reg_class_t from,reg_class_t to)10559 avr_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
10560 reg_class_t from, reg_class_t to)
10561 {
10562 return (from == STACK_REG ? 6
10563 : to == STACK_REG ? 12
10564 : 2);
10565 }
10566
10567
10568 /* Implement `TARGET_MEMORY_MOVE_COST' */
10569
10570 static int
avr_memory_move_cost(machine_mode mode,reg_class_t rclass ATTRIBUTE_UNUSED,bool in ATTRIBUTE_UNUSED)10571 avr_memory_move_cost (machine_mode mode,
10572 reg_class_t rclass ATTRIBUTE_UNUSED,
10573 bool in ATTRIBUTE_UNUSED)
10574 {
10575 return (mode == QImode ? 2
10576 : mode == HImode ? 4
10577 : mode == SImode ? 8
10578 : mode == SFmode ? 8
10579 : 16);
10580 }
10581
10582
10583 /* Cost for mul highpart. X is a LSHIFTRT, i.e. the outer TRUNCATE is
10584 already stripped off. */
10585
10586 static int
avr_mul_highpart_cost(rtx x,int)10587 avr_mul_highpart_cost (rtx x, int)
10588 {
10589 if (AVR_HAVE_MUL
10590 && LSHIFTRT == GET_CODE (x)
10591 && MULT == GET_CODE (XEXP (x, 0))
10592 && CONST_INT_P (XEXP (x, 1)))
10593 {
10594 // This is the wider mode.
10595 machine_mode mode = GET_MODE (x);
10596
10597 // The middle-end might still have PR81444, i.e. it is calling the cost
10598 // functions with strange modes. Fix this now by also considering
10599 // PSImode (should actually be SImode instead).
10600 if (HImode == mode || PSImode == mode || SImode == mode)
10601 {
10602 return COSTS_N_INSNS (2);
10603 }
10604 }
10605
10606 return 10000;
10607 }
10608
10609
10610 /* Mutually recursive subroutine of avr_rtx_cost for calculating the
10611 cost of an RTX operand given its context. X is the rtx of the
10612 operand, MODE is its mode, and OUTER is the rtx_code of this
10613 operand's parent operator. */
10614
10615 static int
avr_operand_rtx_cost(rtx x,machine_mode mode,enum rtx_code outer,int opno,bool speed)10616 avr_operand_rtx_cost (rtx x, machine_mode mode, enum rtx_code outer,
10617 int opno, bool speed)
10618 {
10619 enum rtx_code code = GET_CODE (x);
10620 int total;
10621
10622 switch (code)
10623 {
10624 case REG:
10625 case SUBREG:
10626 return 0;
10627
10628 case CONST_INT:
10629 case CONST_FIXED:
10630 case CONST_DOUBLE:
10631 return COSTS_N_INSNS (GET_MODE_SIZE (mode));
10632
10633 default:
10634 break;
10635 }
10636
10637 total = 0;
10638 avr_rtx_costs (x, mode, outer, opno, &total, speed);
10639 return total;
10640 }
10641
10642 /* Worker function for AVR backend's rtx_cost function.
10643 X is rtx expression whose cost is to be calculated.
10644 Return true if the complete cost has been computed.
10645 Return false if subexpressions should be scanned.
10646 In either case, *TOTAL contains the cost result. */
10647
10648 static bool
avr_rtx_costs_1(rtx x,machine_mode mode,int outer_code,int opno ATTRIBUTE_UNUSED,int * total,bool speed)10649 avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
10650 int opno ATTRIBUTE_UNUSED, int *total, bool speed)
10651 {
10652 enum rtx_code code = GET_CODE (x);
10653 HOST_WIDE_INT val;
10654
10655 switch (code)
10656 {
10657 case CONST_INT:
10658 case CONST_FIXED:
10659 case CONST_DOUBLE:
10660 case SYMBOL_REF:
10661 case CONST:
10662 case LABEL_REF:
10663 /* Immediate constants are as cheap as registers. */
10664 *total = 0;
10665 return true;
10666
10667 case MEM:
10668 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10669 return true;
10670
10671 case NEG:
10672 switch (mode)
10673 {
10674 case E_QImode:
10675 case E_SFmode:
10676 *total = COSTS_N_INSNS (1);
10677 break;
10678
10679 case E_HImode:
10680 case E_PSImode:
10681 case E_SImode:
10682 *total = COSTS_N_INSNS (2 * GET_MODE_SIZE (mode) - 1);
10683 break;
10684
10685 default:
10686 return false;
10687 }
10688 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10689 return true;
10690
10691 case ABS:
10692 switch (mode)
10693 {
10694 case E_QImode:
10695 case E_SFmode:
10696 *total = COSTS_N_INSNS (1);
10697 break;
10698
10699 default:
10700 return false;
10701 }
10702 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10703 return true;
10704
10705 case NOT:
10706 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10707 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10708 return true;
10709
10710 case ZERO_EXTEND:
10711 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
10712 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
10713 *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
10714 code, 0, speed);
10715 return true;
10716
10717 case SIGN_EXTEND:
10718 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
10719 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
10720 *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
10721 code, 0, speed);
10722 return true;
10723
10724 case PLUS:
10725 switch (mode)
10726 {
10727 case E_QImode:
10728 if (AVR_HAVE_MUL
10729 && MULT == GET_CODE (XEXP (x, 0))
10730 && register_operand (XEXP (x, 1), QImode))
10731 {
10732 /* multiply-add */
10733 *total = COSTS_N_INSNS (speed ? 4 : 3);
10734 /* multiply-add with constant: will be split and load constant. */
10735 if (CONST_INT_P (XEXP (XEXP (x, 0), 1)))
10736 *total = COSTS_N_INSNS (1) + *total;
10737 return true;
10738 }
10739 *total = COSTS_N_INSNS (1);
10740 if (!CONST_INT_P (XEXP (x, 1)))
10741 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10742 break;
10743
10744 case E_HImode:
10745 if (AVR_HAVE_MUL
10746 && (MULT == GET_CODE (XEXP (x, 0))
10747 || ASHIFT == GET_CODE (XEXP (x, 0)))
10748 && register_operand (XEXP (x, 1), HImode)
10749 && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))
10750 || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))))
10751 {
10752 /* multiply-add */
10753 *total = COSTS_N_INSNS (speed ? 5 : 4);
10754 /* multiply-add with constant: will be split and load constant. */
10755 if (CONST_INT_P (XEXP (XEXP (x, 0), 1)))
10756 *total = COSTS_N_INSNS (1) + *total;
10757 return true;
10758 }
10759 if (!CONST_INT_P (XEXP (x, 1)))
10760 {
10761 *total = COSTS_N_INSNS (2);
10762 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10763 speed);
10764 }
10765 else if (IN_RANGE (INTVAL (XEXP (x, 1)), -63, 63))
10766 *total = COSTS_N_INSNS (1);
10767 else
10768 *total = COSTS_N_INSNS (2);
10769 break;
10770
10771 case E_PSImode:
10772 if (!CONST_INT_P (XEXP (x, 1)))
10773 {
10774 *total = COSTS_N_INSNS (3);
10775 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10776 speed);
10777 }
10778 else if (IN_RANGE (INTVAL (XEXP (x, 1)), -63, 63))
10779 *total = COSTS_N_INSNS (2);
10780 else
10781 *total = COSTS_N_INSNS (3);
10782 break;
10783
10784 case E_SImode:
10785 if (!CONST_INT_P (XEXP (x, 1)))
10786 {
10787 *total = COSTS_N_INSNS (4);
10788 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10789 speed);
10790 }
10791 else if (IN_RANGE (INTVAL (XEXP (x, 1)), -63, 63))
10792 *total = COSTS_N_INSNS (1);
10793 else
10794 *total = COSTS_N_INSNS (4);
10795 break;
10796
10797 default:
10798 return false;
10799 }
10800 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10801 return true;
10802
10803 case MINUS:
10804 if (AVR_HAVE_MUL
10805 && QImode == mode
10806 && register_operand (XEXP (x, 0), QImode)
10807 && MULT == GET_CODE (XEXP (x, 1)))
10808 {
10809 /* multiply-sub */
10810 *total = COSTS_N_INSNS (speed ? 4 : 3);
10811 /* multiply-sub with constant: will be split and load constant. */
10812 if (CONST_INT_P (XEXP (XEXP (x, 1), 1)))
10813 *total = COSTS_N_INSNS (1) + *total;
10814 return true;
10815 }
10816 if (AVR_HAVE_MUL
10817 && HImode == mode
10818 && register_operand (XEXP (x, 0), HImode)
10819 && (MULT == GET_CODE (XEXP (x, 1))
10820 || ASHIFT == GET_CODE (XEXP (x, 1)))
10821 && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))
10822 || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))))
10823 {
10824 /* multiply-sub */
10825 *total = COSTS_N_INSNS (speed ? 5 : 4);
10826 /* multiply-sub with constant: will be split and load constant. */
10827 if (CONST_INT_P (XEXP (XEXP (x, 1), 1)))
10828 *total = COSTS_N_INSNS (1) + *total;
10829 return true;
10830 }
10831 /* FALLTHRU */
10832 case AND:
10833 case IOR:
10834 if (IOR == code
10835 && HImode == mode
10836 && ASHIFT == GET_CODE (XEXP (x, 0)))
10837 {
10838 *total = COSTS_N_INSNS (2);
10839 // Just a rough estimate. If we see no sign- or zero-extend,
10840 // then increase the cost a little bit.
10841 if (REG_P (XEXP (XEXP (x, 0), 0)))
10842 *total += COSTS_N_INSNS (1);
10843 if (REG_P (XEXP (x, 1)))
10844 *total += COSTS_N_INSNS (1);
10845 return true;
10846 }
10847 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10848 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10849 if (!CONST_INT_P (XEXP (x, 1)))
10850 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10851 return true;
10852
10853 case XOR:
10854 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10855 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10856 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10857 return true;
10858
10859 case MULT:
10860 switch (mode)
10861 {
10862 case E_QImode:
10863 if (AVR_HAVE_MUL)
10864 *total = COSTS_N_INSNS (!speed ? 3 : 4);
10865 else if (!speed)
10866 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
10867 else
10868 return false;
10869 break;
10870
10871 case E_HImode:
10872 if (AVR_HAVE_MUL)
10873 {
10874 rtx op0 = XEXP (x, 0);
10875 rtx op1 = XEXP (x, 1);
10876 enum rtx_code code0 = GET_CODE (op0);
10877 enum rtx_code code1 = GET_CODE (op1);
10878 bool ex0 = SIGN_EXTEND == code0 || ZERO_EXTEND == code0;
10879 bool ex1 = SIGN_EXTEND == code1 || ZERO_EXTEND == code1;
10880
10881 if (ex0
10882 && (u8_operand (op1, HImode)
10883 || s8_operand (op1, HImode)))
10884 {
10885 *total = COSTS_N_INSNS (!speed ? 4 : 6);
10886 return true;
10887 }
10888 if (ex0
10889 && register_operand (op1, HImode))
10890 {
10891 *total = COSTS_N_INSNS (!speed ? 5 : 8);
10892 return true;
10893 }
10894 else if (ex0 || ex1)
10895 {
10896 *total = COSTS_N_INSNS (!speed ? 3 : 5);
10897 return true;
10898 }
10899 else if (register_operand (op0, HImode)
10900 && (u8_operand (op1, HImode)
10901 || s8_operand (op1, HImode)))
10902 {
10903 *total = COSTS_N_INSNS (!speed ? 6 : 9);
10904 return true;
10905 }
10906 else
10907 *total = COSTS_N_INSNS (!speed ? 7 : 10);
10908 }
10909 else if (!speed)
10910 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
10911 else
10912 return false;
10913 break;
10914
10915 case E_PSImode:
10916 if (!speed)
10917 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
10918 else
10919 *total = 10;
10920 break;
10921
10922 case E_SImode:
10923 case E_DImode:
10924 if (AVR_HAVE_MUL)
10925 {
10926 if (!speed)
10927 {
10928 /* Add some additional costs besides CALL like moves etc. */
10929
10930 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
10931 }
10932 else
10933 {
10934 /* Just a rough estimate. Even with -O2 we don't want bulky
10935 code expanded inline. */
10936
10937 *total = COSTS_N_INSNS (25);
10938 }
10939 }
10940 else
10941 {
10942 if (speed)
10943 *total = COSTS_N_INSNS (300);
10944 else
10945 /* Add some additional costs besides CALL like moves etc. */
10946 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
10947 }
10948
10949 if (mode == DImode)
10950 *total *= 2;
10951
10952 return true;
10953
10954 default:
10955 return false;
10956 }
10957 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10958 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10959 return true;
10960
10961 case DIV:
10962 case MOD:
10963 case UDIV:
10964 case UMOD:
10965 if (!speed)
10966 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
10967 else
10968 *total = COSTS_N_INSNS (15 * GET_MODE_SIZE (mode));
10969 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10970 /* For div/mod with const-int divisor we have at least the cost of
10971 loading the divisor. */
10972 if (CONST_INT_P (XEXP (x, 1)))
10973 *total += COSTS_N_INSNS (GET_MODE_SIZE (mode));
10974 /* Add some overall penaly for clobbering and moving around registers */
10975 *total += COSTS_N_INSNS (2);
10976 return true;
10977
10978 case ROTATE:
10979 switch (mode)
10980 {
10981 case E_QImode:
10982 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 4)
10983 *total = COSTS_N_INSNS (1);
10984
10985 break;
10986
10987 case E_HImode:
10988 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 8)
10989 *total = COSTS_N_INSNS (3);
10990
10991 break;
10992
10993 case E_SImode:
10994 if (CONST_INT_P (XEXP (x, 1)))
10995 switch (INTVAL (XEXP (x, 1)))
10996 {
10997 case 8:
10998 case 24:
10999 *total = COSTS_N_INSNS (5);
11000 break;
11001 case 16:
11002 *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 6);
11003 break;
11004 }
11005 break;
11006
11007 default:
11008 return false;
11009 }
11010 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11011 return true;
11012
11013 case ASHIFT:
11014 switch (mode)
11015 {
11016 case E_QImode:
11017 if (!CONST_INT_P (XEXP (x, 1)))
11018 {
11019 *total = COSTS_N_INSNS (!speed ? 4 : 17);
11020 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11021 speed);
11022 }
11023 else
11024 {
11025 val = INTVAL (XEXP (x, 1));
11026 if (val == 7)
11027 *total = COSTS_N_INSNS (3);
11028 else if (val >= 0 && val <= 7)
11029 *total = COSTS_N_INSNS (val);
11030 else
11031 *total = COSTS_N_INSNS (1);
11032 }
11033 break;
11034
11035 case E_HImode:
11036 if (AVR_HAVE_MUL)
11037 {
11038 if (const_2_to_7_operand (XEXP (x, 1), HImode)
11039 && (SIGN_EXTEND == GET_CODE (XEXP (x, 0))
11040 || ZERO_EXTEND == GET_CODE (XEXP (x, 0))))
11041 {
11042 *total = COSTS_N_INSNS (!speed ? 4 : 6);
11043 return true;
11044 }
11045 }
11046
11047 if (const1_rtx == (XEXP (x, 1))
11048 && SIGN_EXTEND == GET_CODE (XEXP (x, 0)))
11049 {
11050 *total = COSTS_N_INSNS (2);
11051 return true;
11052 }
11053
11054 if (!CONST_INT_P (XEXP (x, 1)))
11055 {
11056 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11057 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11058 speed);
11059 }
11060 else
11061 switch (INTVAL (XEXP (x, 1)))
11062 {
11063 case 0:
11064 *total = 0;
11065 break;
11066 case 1:
11067 case 8:
11068 *total = COSTS_N_INSNS (2);
11069 break;
11070 case 9:
11071 *total = COSTS_N_INSNS (3);
11072 break;
11073 case 2:
11074 case 3:
11075 case 10:
11076 case 15:
11077 *total = COSTS_N_INSNS (4);
11078 break;
11079 case 7:
11080 case 11:
11081 case 12:
11082 *total = COSTS_N_INSNS (5);
11083 break;
11084 case 4:
11085 *total = COSTS_N_INSNS (!speed ? 5 : 8);
11086 break;
11087 case 6:
11088 *total = COSTS_N_INSNS (!speed ? 5 : 9);
11089 break;
11090 case 5:
11091 *total = COSTS_N_INSNS (!speed ? 5 : 10);
11092 break;
11093 default:
11094 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11095 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11096 speed);
11097 }
11098 break;
11099
11100 case E_PSImode:
11101 if (!CONST_INT_P (XEXP (x, 1)))
11102 {
11103 *total = COSTS_N_INSNS (!speed ? 6 : 73);
11104 }
11105 else
11106 switch (INTVAL (XEXP (x, 1)))
11107 {
11108 case 0:
11109 *total = 0;
11110 break;
11111 case 1:
11112 case 8:
11113 case 16:
11114 *total = COSTS_N_INSNS (3);
11115 break;
11116 case 23:
11117 *total = COSTS_N_INSNS (5);
11118 break;
11119 default:
11120 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
11121 break;
11122 }
11123 break;
11124
11125 case E_SImode:
11126 if (!CONST_INT_P (XEXP (x, 1)))
11127 {
11128 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11129 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11130 speed);
11131 }
11132 else
11133 switch (INTVAL (XEXP (x, 1)))
11134 {
11135 case 0:
11136 *total = 0;
11137 break;
11138 case 24:
11139 *total = COSTS_N_INSNS (3);
11140 break;
11141 case 1:
11142 case 8:
11143 case 16:
11144 *total = COSTS_N_INSNS (4);
11145 break;
11146 case 31:
11147 *total = COSTS_N_INSNS (6);
11148 break;
11149 case 2:
11150 *total = COSTS_N_INSNS (!speed ? 7 : 8);
11151 break;
11152 default:
11153 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11154 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11155 speed);
11156 }
11157 break;
11158
11159 default:
11160 return false;
11161 }
11162 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11163 return true;
11164
11165 case ASHIFTRT:
11166 switch (mode)
11167 {
11168 case E_QImode:
11169 if (!CONST_INT_P (XEXP (x, 1)))
11170 {
11171 *total = COSTS_N_INSNS (!speed ? 4 : 17);
11172 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11173 speed);
11174 }
11175 else
11176 {
11177 val = INTVAL (XEXP (x, 1));
11178 if (val == 6)
11179 *total = COSTS_N_INSNS (4);
11180 else if (val == 7)
11181 *total = COSTS_N_INSNS (2);
11182 else if (val >= 0 && val <= 7)
11183 *total = COSTS_N_INSNS (val);
11184 else
11185 *total = COSTS_N_INSNS (1);
11186 }
11187 break;
11188
11189 case E_HImode:
11190 if (!CONST_INT_P (XEXP (x, 1)))
11191 {
11192 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11193 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11194 speed);
11195 }
11196 else
11197 switch (INTVAL (XEXP (x, 1)))
11198 {
11199 case 0:
11200 *total = 0;
11201 break;
11202 case 1:
11203 *total = COSTS_N_INSNS (2);
11204 break;
11205 case 15:
11206 *total = COSTS_N_INSNS (3);
11207 break;
11208 case 2:
11209 case 7:
11210 case 8:
11211 case 9:
11212 *total = COSTS_N_INSNS (4);
11213 break;
11214 case 10:
11215 case 14:
11216 *total = COSTS_N_INSNS (5);
11217 break;
11218 case 11:
11219 *total = COSTS_N_INSNS (!speed ? 5 : 6);
11220 break;
11221 case 12:
11222 *total = COSTS_N_INSNS (!speed ? 5 : 7);
11223 break;
11224 case 6:
11225 case 13:
11226 *total = COSTS_N_INSNS (!speed ? 5 : 8);
11227 break;
11228 default:
11229 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11230 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11231 speed);
11232 }
11233 break;
11234
11235 case E_PSImode:
11236 if (!CONST_INT_P (XEXP (x, 1)))
11237 {
11238 *total = COSTS_N_INSNS (!speed ? 6 : 73);
11239 }
11240 else
11241 switch (INTVAL (XEXP (x, 1)))
11242 {
11243 case 0:
11244 *total = 0;
11245 break;
11246 case 1:
11247 *total = COSTS_N_INSNS (3);
11248 break;
11249 case 16:
11250 case 8:
11251 *total = COSTS_N_INSNS (5);
11252 break;
11253 case 23:
11254 *total = COSTS_N_INSNS (4);
11255 break;
11256 default:
11257 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
11258 break;
11259 }
11260 break;
11261
11262 case E_SImode:
11263 if (!CONST_INT_P (XEXP (x, 1)))
11264 {
11265 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11266 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11267 speed);
11268 }
11269 else
11270 switch (INTVAL (XEXP (x, 1)))
11271 {
11272 case 0:
11273 *total = 0;
11274 break;
11275 case 1:
11276 *total = COSTS_N_INSNS (4);
11277 break;
11278 case 8:
11279 case 16:
11280 case 24:
11281 *total = COSTS_N_INSNS (6);
11282 break;
11283 case 2:
11284 *total = COSTS_N_INSNS (!speed ? 7 : 8);
11285 break;
11286 case 31:
11287 *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 5);
11288 break;
11289 default:
11290 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11291 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11292 speed);
11293 }
11294 break;
11295
11296 default:
11297 return false;
11298 }
11299 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11300 return true;
11301
11302 case LSHIFTRT:
11303 if (outer_code == TRUNCATE)
11304 {
11305 *total = avr_mul_highpart_cost (x, speed);
11306 return true;
11307 }
11308
11309 switch (mode)
11310 {
11311 case E_QImode:
11312 if (!CONST_INT_P (XEXP (x, 1)))
11313 {
11314 *total = COSTS_N_INSNS (!speed ? 4 : 17);
11315 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11316 speed);
11317 }
11318 else
11319 {
11320 val = INTVAL (XEXP (x, 1));
11321 if (val == 7)
11322 *total = COSTS_N_INSNS (3);
11323 else if (val >= 0 && val <= 7)
11324 *total = COSTS_N_INSNS (val);
11325 else
11326 *total = COSTS_N_INSNS (1);
11327 }
11328 break;
11329
11330 case E_HImode:
11331 if (!CONST_INT_P (XEXP (x, 1)))
11332 {
11333 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11334 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11335 speed);
11336 }
11337 else
11338 switch (INTVAL (XEXP (x, 1)))
11339 {
11340 case 0:
11341 *total = 0;
11342 break;
11343 case 1:
11344 case 8:
11345 *total = COSTS_N_INSNS (2);
11346 break;
11347 case 9:
11348 *total = COSTS_N_INSNS (3);
11349 break;
11350 case 2:
11351 case 10:
11352 case 15:
11353 *total = COSTS_N_INSNS (4);
11354 break;
11355 case 7:
11356 case 11:
11357 *total = COSTS_N_INSNS (5);
11358 break;
11359 case 3:
11360 case 12:
11361 case 13:
11362 case 14:
11363 *total = COSTS_N_INSNS (!speed ? 5 : 6);
11364 break;
11365 case 4:
11366 *total = COSTS_N_INSNS (!speed ? 5 : 7);
11367 break;
11368 case 5:
11369 case 6:
11370 *total = COSTS_N_INSNS (!speed ? 5 : 9);
11371 break;
11372 default:
11373 *total = COSTS_N_INSNS (!speed ? 5 : 41);
11374 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11375 speed);
11376 }
11377 break;
11378
11379 case E_PSImode:
11380 if (!CONST_INT_P (XEXP (x, 1)))
11381 {
11382 *total = COSTS_N_INSNS (!speed ? 6 : 73);
11383 }
11384 else
11385 switch (INTVAL (XEXP (x, 1)))
11386 {
11387 case 0:
11388 *total = 0;
11389 break;
11390 case 1:
11391 case 8:
11392 case 16:
11393 *total = COSTS_N_INSNS (3);
11394 break;
11395 case 23:
11396 *total = COSTS_N_INSNS (5);
11397 break;
11398 default:
11399 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
11400 break;
11401 }
11402 break;
11403
11404 case E_SImode:
11405 if (!CONST_INT_P (XEXP (x, 1)))
11406 {
11407 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11408 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11409 speed);
11410 }
11411 else
11412 switch (INTVAL (XEXP (x, 1)))
11413 {
11414 case 0:
11415 *total = 0;
11416 break;
11417 case 1:
11418 *total = COSTS_N_INSNS (4);
11419 break;
11420 case 2:
11421 *total = COSTS_N_INSNS (!speed ? 7 : 8);
11422 break;
11423 case 8:
11424 case 16:
11425 case 24:
11426 *total = COSTS_N_INSNS (4);
11427 break;
11428 case 31:
11429 *total = COSTS_N_INSNS (6);
11430 break;
11431 default:
11432 *total = COSTS_N_INSNS (!speed ? 7 : 113);
11433 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
11434 speed);
11435 }
11436 break;
11437
11438 default:
11439 return false;
11440 }
11441 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
11442 return true;
11443
11444 case COMPARE:
11445 switch (GET_MODE (XEXP (x, 0)))
11446 {
11447 case E_QImode:
11448 *total = COSTS_N_INSNS (1);
11449 if (!CONST_INT_P (XEXP (x, 1)))
11450 *total += avr_operand_rtx_cost (XEXP (x, 1), QImode, code,
11451 1, speed);
11452 break;
11453
11454 case E_HImode:
11455 *total = COSTS_N_INSNS (2);
11456 if (!CONST_INT_P (XEXP (x, 1)))
11457 *total += avr_operand_rtx_cost (XEXP (x, 1), HImode, code,
11458 1, speed);
11459 else if (INTVAL (XEXP (x, 1)) != 0)
11460 *total += COSTS_N_INSNS (1);
11461 break;
11462
11463 case E_PSImode:
11464 *total = COSTS_N_INSNS (3);
11465 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) != 0)
11466 *total += COSTS_N_INSNS (2);
11467 break;
11468
11469 case E_SImode:
11470 *total = COSTS_N_INSNS (4);
11471 if (!CONST_INT_P (XEXP (x, 1)))
11472 *total += avr_operand_rtx_cost (XEXP (x, 1), SImode, code,
11473 1, speed);
11474 else if (INTVAL (XEXP (x, 1)) != 0)
11475 *total += COSTS_N_INSNS (3);
11476 break;
11477
11478 default:
11479 return false;
11480 }
11481 *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
11482 code, 0, speed);
11483 return true;
11484
11485 case TRUNCATE:
11486 if (LSHIFTRT == GET_CODE (XEXP (x, 0)))
11487 {
11488 *total = avr_mul_highpart_cost (XEXP (x, 0), speed);
11489 return true;
11490 }
11491 break;
11492
11493 default:
11494 break;
11495 }
11496 return false;
11497 }
11498
11499
11500 /* Implement `TARGET_RTX_COSTS'. */
11501
11502 static bool
avr_rtx_costs(rtx x,machine_mode mode,int outer_code,int opno,int * total,bool speed)11503 avr_rtx_costs (rtx x, machine_mode mode, int outer_code,
11504 int opno, int *total, bool speed)
11505 {
11506 bool done = avr_rtx_costs_1 (x, mode, outer_code, opno, total, speed);
11507
11508 if (avr_log.rtx_costs)
11509 {
11510 avr_edump ("\n%?=%b (%s) total=%d, outer=%C:\n%r\n",
11511 done, speed ? "speed" : "size", *total, outer_code, x);
11512 }
11513
11514 return done;
11515 }
11516
11517
11518 /* Implement `TARGET_ADDRESS_COST'. */
11519
11520 static int
avr_address_cost(rtx x,machine_mode mode ATTRIBUTE_UNUSED,addr_space_t as ATTRIBUTE_UNUSED,bool speed ATTRIBUTE_UNUSED)11521 avr_address_cost (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
11522 addr_space_t as ATTRIBUTE_UNUSED,
11523 bool speed ATTRIBUTE_UNUSED)
11524 {
11525 int cost = 4;
11526
11527 if (GET_CODE (x) == PLUS
11528 && CONST_INT_P (XEXP (x, 1))
11529 && (REG_P (XEXP (x, 0))
11530 || SUBREG_P (XEXP (x, 0))))
11531 {
11532 if (INTVAL (XEXP (x, 1)) > MAX_LD_OFFSET(mode))
11533 cost = 18;
11534 }
11535 else if (CONSTANT_ADDRESS_P (x))
11536 {
11537 if (io_address_operand (x, QImode))
11538 cost = 2;
11539
11540 if (AVR_TINY
11541 && avr_address_tiny_absdata_p (x, QImode))
11542 cost = 2;
11543 }
11544
11545 if (avr_log.address_cost)
11546 avr_edump ("\n%?: %d = %r\n", cost, x);
11547
11548 return cost;
11549 }
11550
11551 /* Test for extra memory constraint 'Q'.
11552 It's a memory address based on Y or Z pointer with valid displacement. */
11553
11554 int
extra_constraint_Q(rtx x)11555 extra_constraint_Q (rtx x)
11556 {
11557 int ok = 0;
11558 rtx plus = XEXP (x, 0);
11559
11560 if (GET_CODE (plus) == PLUS
11561 && REG_P (XEXP (plus, 0))
11562 && CONST_INT_P (XEXP (plus, 1))
11563 && (INTVAL (XEXP (plus, 1))
11564 <= MAX_LD_OFFSET (GET_MODE (x))))
11565 {
11566 rtx xx = XEXP (plus, 0);
11567 int regno = REGNO (xx);
11568
11569 ok = (/* allocate pseudos */
11570 regno >= FIRST_PSEUDO_REGISTER
11571 /* strictly check */
11572 || regno == REG_Z || regno == REG_Y
11573 /* XXX frame & arg pointer checks */
11574 || xx == frame_pointer_rtx
11575 || xx == arg_pointer_rtx);
11576
11577 if (avr_log.constraints)
11578 avr_edump ("\n%?=%d reload_completed=%d reload_in_progress=%d\n %r\n",
11579 ok, reload_completed, reload_in_progress, x);
11580 }
11581
11582 return ok;
11583 }
11584
11585 /* Convert condition code CONDITION to the valid AVR condition code. */
11586
11587 RTX_CODE
avr_normalize_condition(RTX_CODE condition)11588 avr_normalize_condition (RTX_CODE condition)
11589 {
11590 switch (condition)
11591 {
11592 case GT:
11593 return GE;
11594 case GTU:
11595 return GEU;
11596 case LE:
11597 return LT;
11598 case LEU:
11599 return LTU;
11600 default:
11601 gcc_unreachable ();
11602 }
11603 }
11604
11605 /* Helper function for `avr_reorg'. */
11606
11607 static rtx
avr_compare_pattern(rtx_insn * insn)11608 avr_compare_pattern (rtx_insn *insn)
11609 {
11610 rtx pattern = single_set (insn);
11611
11612 if (pattern
11613 && NONJUMP_INSN_P (insn)
11614 && REG_P (SET_DEST (pattern))
11615 && REGNO (SET_DEST (pattern)) == REG_CC
11616 && GET_CODE (SET_SRC (pattern)) == COMPARE)
11617 {
11618 machine_mode mode0 = GET_MODE (XEXP (SET_SRC (pattern), 0));
11619 machine_mode mode1 = GET_MODE (XEXP (SET_SRC (pattern), 1));
11620
11621 /* The 64-bit comparisons have fixed operands ACC_A and ACC_B.
11622 They must not be swapped, thus skip them. */
11623
11624 if ((mode0 == VOIDmode || GET_MODE_SIZE (mode0) <= 4)
11625 && (mode1 == VOIDmode || GET_MODE_SIZE (mode1) <= 4))
11626 return pattern;
11627 }
11628
11629 return NULL_RTX;
11630 }
11631
11632 /* Helper function for `avr_reorg'. */
11633
11634 /* Expansion of switch/case decision trees leads to code like
11635
11636 REG_CC = compare (Reg, Num)
11637 if (REG_CC == 0)
11638 goto L1
11639
11640 REG_CC = compare (Reg, Num)
11641 if (REG_CC > 0)
11642 goto L2
11643
11644 The second comparison is superfluous and can be deleted.
11645 The second jump condition can be transformed from a
11646 "difficult" one to a "simple" one because "REG_CC > 0" and
11647 "REG_CC >= 0" will have the same effect here.
11648
11649 This function relies on the way switch/case is being expaned
11650 as binary decision tree. For example code see PR 49903.
11651
11652 Return TRUE if optimization performed.
11653 Return FALSE if nothing changed.
11654
11655 INSN1 is a comparison, i.e. avr_compare_pattern != 0.
11656
11657 We don't want to do this in text peephole because it is
11658 tedious to work out jump offsets there and the second comparison
11659 might have been transormed by `avr_reorg'.
11660
11661 RTL peephole won't do because peephole2 does not scan across
11662 basic blocks. */
11663
11664 static bool
avr_reorg_remove_redundant_compare(rtx_insn * insn1)11665 avr_reorg_remove_redundant_compare (rtx_insn *insn1)
11666 {
11667 rtx comp1, ifelse1, xcond1;
11668 rtx_insn *branch1;
11669 rtx comp2, ifelse2, xcond2;
11670 rtx_insn *branch2, *insn2;
11671 enum rtx_code code;
11672 rtx_insn *jump;
11673 rtx target, cond;
11674
11675 /* Look out for: compare1 - branch1 - compare2 - branch2 */
11676
11677 branch1 = next_nonnote_nondebug_insn (insn1);
11678 if (!branch1 || !JUMP_P (branch1))
11679 return false;
11680
11681 insn2 = next_nonnote_nondebug_insn (branch1);
11682 if (!insn2 || !avr_compare_pattern (insn2))
11683 return false;
11684
11685 branch2 = next_nonnote_nondebug_insn (insn2);
11686 if (!branch2 || !JUMP_P (branch2))
11687 return false;
11688
11689 comp1 = avr_compare_pattern (insn1);
11690 comp2 = avr_compare_pattern (insn2);
11691 xcond1 = single_set (branch1);
11692 xcond2 = single_set (branch2);
11693
11694 if (!comp1 || !comp2
11695 || !rtx_equal_p (comp1, comp2)
11696 || !xcond1 || SET_DEST (xcond1) != pc_rtx
11697 || !xcond2 || SET_DEST (xcond2) != pc_rtx
11698 || IF_THEN_ELSE != GET_CODE (SET_SRC (xcond1))
11699 || IF_THEN_ELSE != GET_CODE (SET_SRC (xcond2)))
11700 {
11701 return false;
11702 }
11703
11704 comp1 = SET_SRC (comp1);
11705 ifelse1 = SET_SRC (xcond1);
11706 ifelse2 = SET_SRC (xcond2);
11707
11708 /* comp<n> is COMPARE now and ifelse<n> is IF_THEN_ELSE. */
11709
11710 if (EQ != GET_CODE (XEXP (ifelse1, 0))
11711 || !REG_P (XEXP (comp1, 0))
11712 || !CONST_INT_P (XEXP (comp1, 1))
11713 || XEXP (ifelse1, 2) != pc_rtx
11714 || XEXP (ifelse2, 2) != pc_rtx
11715 || LABEL_REF != GET_CODE (XEXP (ifelse1, 1))
11716 || LABEL_REF != GET_CODE (XEXP (ifelse2, 1))
11717 || !COMPARISON_P (XEXP (ifelse2, 0))
11718 || REG_CC != REGNO (XEXP (XEXP (ifelse1, 0), 0))
11719 || REG_CC != REGNO (XEXP (XEXP (ifelse2, 0), 0))
11720 || const0_rtx != XEXP (XEXP (ifelse1, 0), 1)
11721 || const0_rtx != XEXP (XEXP (ifelse2, 0), 1))
11722 {
11723 return false;
11724 }
11725
11726 /* We filtered the insn sequence to look like
11727
11728 (set (reg:CC cc)
11729 (compare (reg:M N)
11730 (const_int VAL)))
11731 (set (pc)
11732 (if_then_else (eq (reg:CC cc)
11733 (const_int 0))
11734 (label_ref L1)
11735 (pc)))
11736
11737 (set (reg:CC cc)
11738 (compare (reg:M N)
11739 (const_int VAL)))
11740 (set (pc)
11741 (if_then_else (CODE (reg:CC cc)
11742 (const_int 0))
11743 (label_ref L2)
11744 (pc)))
11745 */
11746
11747 code = GET_CODE (XEXP (ifelse2, 0));
11748
11749 /* Map GT/GTU to GE/GEU which is easier for AVR.
11750 The first two instructions compare/branch on EQ
11751 so we may replace the difficult
11752
11753 if (x == VAL) goto L1;
11754 if (x > VAL) goto L2;
11755
11756 with easy
11757
11758 if (x == VAL) goto L1;
11759 if (x >= VAL) goto L2;
11760
11761 Similarly, replace LE/LEU by LT/LTU. */
11762
11763 switch (code)
11764 {
11765 case EQ:
11766 case LT: case LTU:
11767 case GE: case GEU:
11768 break;
11769
11770 case LE: case LEU:
11771 case GT: case GTU:
11772 code = avr_normalize_condition (code);
11773 break;
11774
11775 default:
11776 return false;
11777 }
11778
11779 /* Wrap the branches into UNSPECs so they won't be changed or
11780 optimized in the remainder. */
11781
11782 target = XEXP (XEXP (ifelse1, 1), 0);
11783 cond = XEXP (ifelse1, 0);
11784 jump = emit_jump_insn_after (gen_branch_unspec (target, cond), insn1);
11785
11786 JUMP_LABEL (jump) = JUMP_LABEL (branch1);
11787
11788 target = XEXP (XEXP (ifelse2, 1), 0);
11789 cond = gen_rtx_fmt_ee (code, VOIDmode, cc_reg_rtx, const0_rtx);
11790 jump = emit_jump_insn_after (gen_branch_unspec (target, cond), insn2);
11791
11792 JUMP_LABEL (jump) = JUMP_LABEL (branch2);
11793
11794 /* The comparisons in insn1 and insn2 are exactly the same;
11795 insn2 is superfluous so delete it. */
11796
11797 delete_insn (insn2);
11798 delete_insn (branch1);
11799 delete_insn (branch2);
11800
11801 return true;
11802 }
11803
11804
11805 /* Implement `TARGET_MACHINE_DEPENDENT_REORG'. */
11806 /* Optimize conditional jumps. */
11807
11808 static void
avr_reorg(void)11809 avr_reorg (void)
11810 {
11811 rtx_insn *insn = get_insns();
11812
11813 for (insn = next_real_insn (insn); insn; insn = next_real_insn (insn))
11814 {
11815 rtx pattern = avr_compare_pattern (insn);
11816
11817 if (!pattern)
11818 continue;
11819
11820 if (optimize
11821 && avr_reorg_remove_redundant_compare (insn))
11822 {
11823 continue;
11824 }
11825
11826 if (compare_diff_p (insn))
11827 {
11828 /* Now we work under compare insn with difficult branch. */
11829
11830 rtx_insn *next = next_real_insn (insn);
11831 rtx pat = PATTERN (next);
11832 if (GET_CODE (pat) == PARALLEL)
11833 pat = XVECEXP (pat, 0, 0);
11834
11835 pattern = SET_SRC (pattern);
11836
11837 if (true_regnum (XEXP (pattern, 0)) >= 0
11838 && true_regnum (XEXP (pattern, 1)) >= 0)
11839 {
11840 rtx x = XEXP (pattern, 0);
11841 rtx src = SET_SRC (pat);
11842 rtx t = XEXP (src, 0);
11843 PUT_CODE (t, swap_condition (GET_CODE (t)));
11844 XEXP (pattern, 0) = XEXP (pattern, 1);
11845 XEXP (pattern, 1) = x;
11846 INSN_CODE (next) = -1;
11847 }
11848 else if (true_regnum (XEXP (pattern, 0)) >= 0
11849 && XEXP (pattern, 1) == const0_rtx)
11850 {
11851 /* This is a tst insn, we can reverse it. */
11852 rtx src = SET_SRC (pat);
11853 rtx t = XEXP (src, 0);
11854
11855 PUT_CODE (t, swap_condition (GET_CODE (t)));
11856 XEXP (pattern, 1) = XEXP (pattern, 0);
11857 XEXP (pattern, 0) = const0_rtx;
11858 INSN_CODE (next) = -1;
11859 INSN_CODE (insn) = -1;
11860 }
11861 else if (true_regnum (XEXP (pattern, 0)) >= 0
11862 && CONST_INT_P (XEXP (pattern, 1)))
11863 {
11864 rtx x = XEXP (pattern, 1);
11865 rtx src = SET_SRC (pat);
11866 rtx t = XEXP (src, 0);
11867 machine_mode mode = GET_MODE (XEXP (pattern, 0));
11868
11869 if (avr_simplify_comparison_p (mode, GET_CODE (t), x))
11870 {
11871 XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
11872 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
11873 INSN_CODE (next) = -1;
11874 INSN_CODE (insn) = -1;
11875 }
11876 }
11877 }
11878 }
11879 }
11880
11881 /* Returns register number for function return value.*/
11882
11883 static inline unsigned int
avr_ret_register(void)11884 avr_ret_register (void)
11885 {
11886 return 24;
11887 }
11888
11889
11890 /* Implement `TARGET_FUNCTION_VALUE_REGNO_P'. */
11891
11892 static bool
avr_function_value_regno_p(const unsigned int regno)11893 avr_function_value_regno_p (const unsigned int regno)
11894 {
11895 return (regno == avr_ret_register ());
11896 }
11897
11898
11899 /* Implement `TARGET_LIBCALL_VALUE'. */
11900 /* Create an RTX representing the place where a
11901 library function returns a value of mode MODE. */
11902
11903 static rtx
avr_libcall_value(machine_mode mode,const_rtx func ATTRIBUTE_UNUSED)11904 avr_libcall_value (machine_mode mode,
11905 const_rtx func ATTRIBUTE_UNUSED)
11906 {
11907 int offs = GET_MODE_SIZE (mode);
11908
11909 if (offs <= 4)
11910 offs = (offs + 1) & ~1;
11911
11912 return gen_rtx_REG (mode, avr_ret_register () + 2 - offs);
11913 }
11914
11915
11916 /* Implement `TARGET_FUNCTION_VALUE'. */
11917 /* Create an RTX representing the place where a
11918 function returns a value of data type VALTYPE. */
11919
11920 static rtx
avr_function_value(const_tree type,const_tree fn_decl_or_type ATTRIBUTE_UNUSED,bool outgoing ATTRIBUTE_UNUSED)11921 avr_function_value (const_tree type,
11922 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
11923 bool outgoing ATTRIBUTE_UNUSED)
11924 {
11925 unsigned int offs;
11926
11927 if (TYPE_MODE (type) != BLKmode)
11928 return avr_libcall_value (TYPE_MODE (type), NULL_RTX);
11929
11930 offs = int_size_in_bytes (type);
11931 if (offs < 2)
11932 offs = 2;
11933 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
11934 offs = GET_MODE_SIZE (SImode);
11935 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
11936 offs = GET_MODE_SIZE (DImode);
11937
11938 return gen_rtx_REG (BLKmode, avr_ret_register () + 2 - offs);
11939 }
11940
11941 int
test_hard_reg_class(enum reg_class rclass,rtx x)11942 test_hard_reg_class (enum reg_class rclass, rtx x)
11943 {
11944 int regno = true_regnum (x);
11945 if (regno < 0)
11946 return 0;
11947
11948 if (TEST_HARD_REG_CLASS (rclass, regno))
11949 return 1;
11950
11951 return 0;
11952 }
11953
11954
11955 /* Helper for jump_over_one_insn_p: Test if INSN is a 2-word instruction
11956 and thus is suitable to be skipped by CPSE, SBRC, etc. */
11957
11958 static bool
avr_2word_insn_p(rtx_insn * insn)11959 avr_2word_insn_p (rtx_insn *insn)
11960 {
11961 if (TARGET_SKIP_BUG || !insn || get_attr_length (insn) != 2)
11962 {
11963 return false;
11964 }
11965
11966 switch (INSN_CODE (insn))
11967 {
11968 default:
11969 return false;
11970
11971 case CODE_FOR_movqi_insn:
11972 case CODE_FOR_movuqq_insn:
11973 case CODE_FOR_movqq_insn:
11974 {
11975 rtx set = single_set (insn);
11976 rtx src = SET_SRC (set);
11977 rtx dest = SET_DEST (set);
11978
11979 /* Factor out LDS and STS from movqi_insn. */
11980
11981 if (MEM_P (dest)
11982 && (REG_P (src) || src == CONST0_RTX (GET_MODE (dest))))
11983 {
11984 return CONSTANT_ADDRESS_P (XEXP (dest, 0));
11985 }
11986 else if (REG_P (dest)
11987 && MEM_P (src))
11988 {
11989 return CONSTANT_ADDRESS_P (XEXP (src, 0));
11990 }
11991
11992 return false;
11993 }
11994
11995 case CODE_FOR_call_insn:
11996 case CODE_FOR_call_value_insn:
11997 return true;
11998 }
11999 }
12000
12001
12002 int
jump_over_one_insn_p(rtx_insn * insn,rtx dest)12003 jump_over_one_insn_p (rtx_insn *insn, rtx dest)
12004 {
12005 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
12006 ? XEXP (dest, 0)
12007 : dest);
12008 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
12009 int dest_addr = INSN_ADDRESSES (uid);
12010 int jump_offset = dest_addr - jump_addr - get_attr_length (insn);
12011
12012 return (jump_offset == 1
12013 || (jump_offset == 2
12014 && avr_2word_insn_p (next_active_insn (insn))));
12015 }
12016
12017 /* Implement TARGET_HARD_REGNO_NREGS. CCmode is four units for historical
12018 reasons. If this hook is not defined, TARGET_HARD_REGNO_NREGS
12019 reports that CCmode requires four registers.
12020 Define this hook to allow CCmode to fit in a single REG_CC. For
12021 other modes and regs, return the number of words in mode (i.e whatever
12022 the default implementation of the hook returned). */
12023
12024 static unsigned int
avr_hard_regno_nregs(unsigned int regno,machine_mode mode)12025 avr_hard_regno_nregs (unsigned int regno, machine_mode mode)
12026 {
12027 if (regno == REG_CC && mode == CCmode)
12028 return 1;
12029
12030 return CEIL (GET_MODE_SIZE (mode), UNITS_PER_WORD);
12031 }
12032
12033
12034 /* Implement TARGET_HARD_REGNO_MODE_OK. On the enhanced core, anything
12035 larger than 1 byte must start in even numbered register for "movw" to
12036 work (this way we don't have to check for odd registers everywhere). */
12037
12038 static bool
avr_hard_regno_mode_ok(unsigned int regno,machine_mode mode)12039 avr_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
12040 {
12041 if (regno == REG_CC)
12042 return mode == CCmode;
12043
12044 /* NOTE: 8-bit values must not be disallowed for R28 or R29.
12045 Disallowing QI et al. in these regs might lead to code like
12046 (set (subreg:QI (reg:HI 28) n) ...)
12047 which will result in wrong code because reload does not
12048 handle SUBREGs of hard regsisters like this.
12049 This could be fixed in reload. However, it appears
12050 that fixing reload is not wanted by reload people. */
12051
12052 /* Any GENERAL_REGS register can hold 8-bit values. */
12053
12054 if (GET_MODE_SIZE (mode) == 1)
12055 return true;
12056
12057 /* FIXME: Ideally, the following test is not needed.
12058 However, it turned out that it can reduce the number
12059 of spill fails. AVR and it's poor endowment with
12060 address registers is extreme stress test for reload. */
12061
12062 if (GET_MODE_SIZE (mode) >= 4
12063 && regno >= REG_X)
12064 return false;
12065
12066 /* All modes larger than 8 bits should start in an even register. */
12067
12068 return !(regno & 1);
12069 }
12070
12071
12072 /* Implement TARGET_HARD_REGNO_CALL_PART_CLOBBERED. */
12073
12074 static bool
avr_hard_regno_call_part_clobbered(unsigned,unsigned regno,machine_mode mode)12075 avr_hard_regno_call_part_clobbered (unsigned, unsigned regno,
12076 machine_mode mode)
12077 {
12078 /* FIXME: This hook gets called with MODE:REGNO combinations that don't
12079 represent valid hard registers like, e.g. HI:29. Returning TRUE
12080 for such registers can lead to performance degradation as mentioned
12081 in PR53595. Thus, report invalid hard registers as FALSE. */
12082
12083 if (!avr_hard_regno_mode_ok (regno, mode))
12084 return 0;
12085
12086 /* Return true if any of the following boundaries is crossed:
12087 17/18 or 19/20 (if AVR_TINY), 27/28 and 29/30. */
12088
12089 return ((regno <= LAST_CALLEE_SAVED_REG
12090 && regno + GET_MODE_SIZE (mode) > 1 + LAST_CALLEE_SAVED_REG)
12091 || (regno < REG_Y && regno + GET_MODE_SIZE (mode) > REG_Y)
12092 || (regno < REG_Z && regno + GET_MODE_SIZE (mode) > REG_Z));
12093 }
12094
12095
12096 /* Implement `MODE_CODE_BASE_REG_CLASS'. */
12097
12098 enum reg_class
avr_mode_code_base_reg_class(machine_mode mode ATTRIBUTE_UNUSED,addr_space_t as,RTX_CODE outer_code,RTX_CODE index_code ATTRIBUTE_UNUSED)12099 avr_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED,
12100 addr_space_t as, RTX_CODE outer_code,
12101 RTX_CODE index_code ATTRIBUTE_UNUSED)
12102 {
12103 if (!ADDR_SPACE_GENERIC_P (as))
12104 {
12105 return POINTER_Z_REGS;
12106 }
12107
12108 if (!avr_strict_X)
12109 return reload_completed ? BASE_POINTER_REGS : POINTER_REGS;
12110
12111 return PLUS == outer_code ? BASE_POINTER_REGS : POINTER_REGS;
12112 }
12113
12114
12115 /* Implement `REGNO_MODE_CODE_OK_FOR_BASE_P'. */
12116
12117 bool
avr_regno_mode_code_ok_for_base_p(int regno,machine_mode mode ATTRIBUTE_UNUSED,addr_space_t as ATTRIBUTE_UNUSED,RTX_CODE outer_code,RTX_CODE index_code ATTRIBUTE_UNUSED)12118 avr_regno_mode_code_ok_for_base_p (int regno,
12119 machine_mode mode ATTRIBUTE_UNUSED,
12120 addr_space_t as ATTRIBUTE_UNUSED,
12121 RTX_CODE outer_code,
12122 RTX_CODE index_code ATTRIBUTE_UNUSED)
12123 {
12124 bool ok = false;
12125
12126 if (!ADDR_SPACE_GENERIC_P (as))
12127 {
12128 if (regno < FIRST_PSEUDO_REGISTER
12129 && regno == REG_Z)
12130 {
12131 return true;
12132 }
12133
12134 if (reg_renumber)
12135 {
12136 regno = reg_renumber[regno];
12137
12138 if (regno == REG_Z)
12139 {
12140 return true;
12141 }
12142 }
12143
12144 return false;
12145 }
12146
12147 if (regno < FIRST_PSEUDO_REGISTER
12148 && (regno == REG_X
12149 || regno == REG_Y
12150 || regno == REG_Z
12151 || regno == ARG_POINTER_REGNUM))
12152 {
12153 ok = true;
12154 }
12155 else if (reg_renumber)
12156 {
12157 regno = reg_renumber[regno];
12158
12159 if (regno == REG_X
12160 || regno == REG_Y
12161 || regno == REG_Z
12162 || regno == ARG_POINTER_REGNUM)
12163 {
12164 ok = true;
12165 }
12166 }
12167
12168 if (avr_strict_X
12169 && PLUS == outer_code
12170 && regno == REG_X)
12171 {
12172 ok = false;
12173 }
12174
12175 return ok;
12176 }
12177
12178
12179 /* A helper for `output_reload_insisf' and `output_reload_inhi'. */
12180 /* Set 32-bit register OP[0] to compile-time constant OP[1].
12181 CLOBBER_REG is a QI clobber register or NULL_RTX.
12182 LEN == NULL: output instructions.
12183 LEN != NULL: set *LEN to the length of the instruction sequence
12184 (in words) printed with LEN = NULL.
12185 If CLEAR_P is true, OP[0] had been cleard to Zero already.
12186 If CLEAR_P is false, nothing is known about OP[0].
12187
12188 The effect on cc0 is as follows:
12189
12190 Load 0 to any register except ZERO_REG : NONE
12191 Load ld register with any value : NONE
12192 Anything else: : CLOBBER */
12193
12194 static void
output_reload_in_const(rtx * op,rtx clobber_reg,int * len,bool clear_p)12195 output_reload_in_const (rtx *op, rtx clobber_reg, int *len, bool clear_p)
12196 {
12197 rtx src = op[1];
12198 rtx dest = op[0];
12199 rtx xval, xdest[4];
12200 int ival[4];
12201 int clobber_val = 1234;
12202 bool cooked_clobber_p = false;
12203 bool set_p = false;
12204 machine_mode mode = GET_MODE (dest);
12205 int n_bytes = GET_MODE_SIZE (mode);
12206
12207 gcc_assert (REG_P (dest)
12208 && CONSTANT_P (src));
12209
12210 if (len)
12211 *len = 0;
12212
12213 /* (REG:SI 14) is special: It's neither in LD_REGS nor in NO_LD_REGS
12214 but has some subregs that are in LD_REGS. Use the MSB (REG:QI 17). */
12215
12216 if (REGNO (dest) < 16
12217 && REGNO (dest) + GET_MODE_SIZE (mode) > 16)
12218 {
12219 clobber_reg = all_regs_rtx[REGNO (dest) + n_bytes - 1];
12220 }
12221
12222 /* We might need a clobber reg but don't have one. Look at the value to
12223 be loaded more closely. A clobber is only needed if it is a symbol
12224 or contains a byte that is neither 0, -1 or a power of 2. */
12225
12226 if (NULL_RTX == clobber_reg
12227 && !test_hard_reg_class (LD_REGS, dest)
12228 && (! (CONST_INT_P (src) || CONST_FIXED_P (src) || CONST_DOUBLE_P (src))
12229 || !avr_popcount_each_byte (src, n_bytes,
12230 (1 << 0) | (1 << 1) | (1 << 8))))
12231 {
12232 /* We have no clobber register but need one. Cook one up.
12233 That's cheaper than loading from constant pool. */
12234
12235 cooked_clobber_p = true;
12236 clobber_reg = all_regs_rtx[REG_Z + 1];
12237 avr_asm_len ("mov __tmp_reg__,%0", &clobber_reg, len, 1);
12238 }
12239
12240 /* Now start filling DEST from LSB to MSB. */
12241
12242 for (int n = 0; n < n_bytes; n++)
12243 {
12244 int ldreg_p;
12245 bool done_byte = false;
12246 rtx xop[3];
12247
12248 /* Crop the n-th destination byte. */
12249
12250 xdest[n] = simplify_gen_subreg (QImode, dest, mode, n);
12251 ldreg_p = test_hard_reg_class (LD_REGS, xdest[n]);
12252
12253 if (!CONST_INT_P (src)
12254 && !CONST_FIXED_P (src)
12255 && !CONST_DOUBLE_P (src))
12256 {
12257 static const char* const asm_code[][2] =
12258 {
12259 { "ldi %2,lo8(%1)" CR_TAB "mov %0,%2", "ldi %0,lo8(%1)" },
12260 { "ldi %2,hi8(%1)" CR_TAB "mov %0,%2", "ldi %0,hi8(%1)" },
12261 { "ldi %2,hlo8(%1)" CR_TAB "mov %0,%2", "ldi %0,hlo8(%1)" },
12262 { "ldi %2,hhi8(%1)" CR_TAB "mov %0,%2", "ldi %0,hhi8(%1)" }
12263 };
12264
12265 xop[0] = xdest[n];
12266 xop[1] = src;
12267 xop[2] = clobber_reg;
12268
12269 avr_asm_len (asm_code[n][ldreg_p], xop, len, ldreg_p ? 1 : 2);
12270
12271 continue;
12272 }
12273
12274 /* Crop the n-th source byte. */
12275
12276 xval = simplify_gen_subreg (QImode, src, mode, n);
12277 ival[n] = INTVAL (xval);
12278
12279 /* Look if we can reuse the low word by means of MOVW. */
12280
12281 if (n == 2
12282 && n_bytes >= 4
12283 && AVR_HAVE_MOVW)
12284 {
12285 rtx lo16 = simplify_gen_subreg (HImode, src, mode, 0);
12286 rtx hi16 = simplify_gen_subreg (HImode, src, mode, 2);
12287
12288 if (INTVAL (lo16) == INTVAL (hi16))
12289 {
12290 if (INTVAL (lo16) != 0 || !clear_p)
12291 avr_asm_len ("movw %C0,%A0", &op[0], len, 1);
12292
12293 break;
12294 }
12295 }
12296
12297 /* Don't use CLR so that cc0 is set as expected. */
12298
12299 if (ival[n] == 0)
12300 {
12301 if (!clear_p)
12302 avr_asm_len (ldreg_p ? "ldi %0,0"
12303 : AVR_ZERO_REGNO == REGNO (xdest[n]) ? "clr %0"
12304 : "mov %0,__zero_reg__",
12305 &xdest[n], len, 1);
12306 continue;
12307 }
12308
12309 if (clobber_val == ival[n]
12310 && REGNO (clobber_reg) == REGNO (xdest[n]))
12311 {
12312 continue;
12313 }
12314
12315 /* LD_REGS can use LDI to move a constant value */
12316
12317 if (ldreg_p)
12318 {
12319 xop[0] = xdest[n];
12320 xop[1] = xval;
12321 avr_asm_len ("ldi %0,lo8(%1)", xop, len, 1);
12322 continue;
12323 }
12324
12325 /* Try to reuse value already loaded in some lower byte. */
12326
12327 for (int j = 0; j < n; j++)
12328 if (ival[j] == ival[n])
12329 {
12330 xop[0] = xdest[n];
12331 xop[1] = xdest[j];
12332
12333 avr_asm_len ("mov %0,%1", xop, len, 1);
12334 done_byte = true;
12335 break;
12336 }
12337
12338 if (done_byte)
12339 continue;
12340
12341 /* Need no clobber reg for -1: Use CLR/DEC */
12342
12343 if (ival[n] == -1)
12344 {
12345 if (!clear_p)
12346 avr_asm_len ("clr %0", &xdest[n], len, 1);
12347
12348 avr_asm_len ("dec %0", &xdest[n], len, 1);
12349 continue;
12350 }
12351 else if (ival[n] == 1)
12352 {
12353 if (!clear_p)
12354 avr_asm_len ("clr %0", &xdest[n], len, 1);
12355
12356 avr_asm_len ("inc %0", &xdest[n], len, 1);
12357 continue;
12358 }
12359
12360 /* Use T flag or INC to manage powers of 2 if we have
12361 no clobber reg. */
12362
12363 if (NULL_RTX == clobber_reg
12364 && single_one_operand (xval, QImode))
12365 {
12366 xop[0] = xdest[n];
12367 xop[1] = GEN_INT (exact_log2 (ival[n] & GET_MODE_MASK (QImode)));
12368
12369 gcc_assert (constm1_rtx != xop[1]);
12370
12371 if (!set_p)
12372 {
12373 set_p = true;
12374 avr_asm_len ("set", xop, len, 1);
12375 }
12376
12377 if (!clear_p)
12378 avr_asm_len ("clr %0", xop, len, 1);
12379
12380 avr_asm_len ("bld %0,%1", xop, len, 1);
12381 continue;
12382 }
12383
12384 /* We actually need the LD_REGS clobber reg. */
12385
12386 gcc_assert (NULL_RTX != clobber_reg);
12387
12388 xop[0] = xdest[n];
12389 xop[1] = xval;
12390 xop[2] = clobber_reg;
12391 clobber_val = ival[n];
12392
12393 avr_asm_len ("ldi %2,lo8(%1)" CR_TAB
12394 "mov %0,%2", xop, len, 2);
12395 }
12396
12397 /* If we cooked up a clobber reg above, restore it. */
12398
12399 if (cooked_clobber_p)
12400 {
12401 avr_asm_len ("mov %0,__tmp_reg__", &clobber_reg, len, 1);
12402 }
12403 }
12404
12405
12406 /* Reload the constant OP[1] into the HI register OP[0].
12407 CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
12408 into a NO_LD_REGS register. If CLOBBER_REG is NULL_RTX we either don't
12409 need a clobber reg or have to cook one up.
12410
12411 PLEN == NULL: Output instructions.
12412 PLEN != NULL: Output nothing. Set *PLEN to number of words occupied
12413 by the insns printed.
12414
12415 Return "". */
12416
12417 const char*
output_reload_inhi(rtx * op,rtx clobber_reg,int * plen)12418 output_reload_inhi (rtx *op, rtx clobber_reg, int *plen)
12419 {
12420 output_reload_in_const (op, clobber_reg, plen, false);
12421 return "";
12422 }
12423
12424
12425 /* Reload a SI or SF compile time constant OP[1] into the register OP[0].
12426 CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
12427 into a NO_LD_REGS register. If CLOBBER_REG is NULL_RTX we either don't
12428 need a clobber reg or have to cook one up.
12429
12430 LEN == NULL: Output instructions.
12431
12432 LEN != NULL: Output nothing. Set *LEN to number of words occupied
12433 by the insns printed.
12434
12435 Return "". */
12436
12437 const char *
output_reload_insisf(rtx * op,rtx clobber_reg,int * len)12438 output_reload_insisf (rtx *op, rtx clobber_reg, int *len)
12439 {
12440 if (AVR_HAVE_MOVW
12441 && !test_hard_reg_class (LD_REGS, op[0])
12442 && (CONST_INT_P (op[1])
12443 || CONST_FIXED_P (op[1])
12444 || CONST_DOUBLE_P (op[1])))
12445 {
12446 int len_clr, len_noclr;
12447
12448 /* In some cases it is better to clear the destination beforehand, e.g.
12449
12450 CLR R2 CLR R3 MOVW R4,R2 INC R2
12451
12452 is shorther than
12453
12454 CLR R2 INC R2 CLR R3 CLR R4 CLR R5
12455
12456 We find it too tedious to work that out in the print function.
12457 Instead, we call the print function twice to get the lengths of
12458 both methods and use the shortest one. */
12459
12460 output_reload_in_const (op, clobber_reg, &len_clr, true);
12461 output_reload_in_const (op, clobber_reg, &len_noclr, false);
12462
12463 if (len_noclr - len_clr == 4)
12464 {
12465 /* Default needs 4 CLR instructions: clear register beforehand. */
12466
12467 avr_asm_len ("mov %A0,__zero_reg__" CR_TAB
12468 "mov %B0,__zero_reg__" CR_TAB
12469 "movw %C0,%A0", &op[0], len, 3);
12470
12471 output_reload_in_const (op, clobber_reg, len, true);
12472
12473 if (len)
12474 *len += 3;
12475
12476 return "";
12477 }
12478 }
12479
12480 /* Default: destination not pre-cleared. */
12481
12482 output_reload_in_const (op, clobber_reg, len, false);
12483 return "";
12484 }
12485
12486 const char*
avr_out_reload_inpsi(rtx * op,rtx clobber_reg,int * len)12487 avr_out_reload_inpsi (rtx *op, rtx clobber_reg, int *len)
12488 {
12489 output_reload_in_const (op, clobber_reg, len, false);
12490 return "";
12491 }
12492
12493
12494 /* Worker function for `ASM_OUTPUT_ADDR_VEC'. */
12495 /* Emit jump tables out-of-line so that branches crossing the table
12496 get shorter offsets. If we have JUMP + CALL, then put the tables
12497 in a dedicated non-.text section so that CALLs get better chance to
12498 be relaxed to RCALLs.
12499
12500 We emit the tables by hand because `function_rodata_section' does not
12501 work as expected, cf. PR71151, and we do *NOT* want the table to be
12502 in .rodata, hence setting JUMP_TABLES_IN_TEXT_SECTION = 0 is of limited
12503 use; and setting it to 1 attributes table lengths to branch offsets...
12504 Moreover, fincal.c keeps switching section before each table entry
12505 which we find too fragile as to rely on section caching. */
12506
12507 void
avr_output_addr_vec(rtx_insn * labl,rtx table)12508 avr_output_addr_vec (rtx_insn *labl, rtx table)
12509 {
12510 FILE *stream = asm_out_file;
12511
12512 app_disable();
12513
12514 // Switch to appropriate (sub)section.
12515
12516 if (DECL_SECTION_NAME (current_function_decl)
12517 && symtab_node::get (current_function_decl)
12518 && ! symtab_node::get (current_function_decl)->implicit_section)
12519 {
12520 // .subsection will emit the code after the function and in the
12521 // section as chosen by the user.
12522
12523 switch_to_section (current_function_section ());
12524 fprintf (stream, "\t.subsection\t1\n");
12525 }
12526 else
12527 {
12528 // Since PR63223 there is no restriction where to put the table; it
12529 // may even reside above 128 KiB. We put it in a section as high as
12530 // possible and avoid progmem in order not to waste flash <= 64 KiB.
12531
12532 const char *sec_name = ".jumptables.gcc";
12533
12534 // The table belongs to its host function, therefore use fine
12535 // grained sections so that, if that function is removed by
12536 // --gc-sections, the child table(s) may also be removed. */
12537
12538 tree asm_name = DECL_ASSEMBLER_NAME (current_function_decl);
12539 const char *fname = IDENTIFIER_POINTER (asm_name);
12540 fname = targetm.strip_name_encoding (fname);
12541 sec_name = ACONCAT ((sec_name, ".", fname, NULL));
12542
12543 fprintf (stream, "\t.section\t%s,\"%s\",@progbits\n", sec_name,
12544 AVR_HAVE_JMP_CALL ? "a" : "ax");
12545 }
12546
12547 // Output the label that preceeds the table.
12548
12549 ASM_OUTPUT_ALIGN (stream, 1);
12550 targetm.asm_out.internal_label (stream, "L", CODE_LABEL_NUMBER (labl));
12551
12552 // Output the table's content.
12553
12554 int vlen = XVECLEN (table, 0);
12555
12556 for (int idx = 0; idx < vlen; idx++)
12557 {
12558 int value = CODE_LABEL_NUMBER (XEXP (XVECEXP (table, 0, idx), 0));
12559
12560 if (AVR_HAVE_JMP_CALL)
12561 fprintf (stream, "\t.word gs(.L%d)\n", value);
12562 else
12563 fprintf (stream, "\trjmp .L%d\n", value);
12564 }
12565
12566 // Switch back to original section. As we clobbered the section above,
12567 // forget the current section before switching back.
12568
12569 in_section = NULL;
12570 switch_to_section (current_function_section ());
12571 }
12572
12573
12574 /* Implement `TARGET_CONDITIONAL_REGISTER_USAGE'. */
12575
12576 static void
avr_conditional_register_usage(void)12577 avr_conditional_register_usage (void)
12578 {
12579 if (AVR_TINY)
12580 {
12581 const int tiny_reg_alloc_order[] = {
12582 24, 25,
12583 22, 23,
12584 30, 31,
12585 26, 27,
12586 28, 29,
12587 21, 20, 19, 18,
12588 16, 17,
12589 32, 33, 34, 35,
12590 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
12591 };
12592
12593 /* Set R0-R17 as fixed registers. Reset R0-R17 in call used register list
12594 - R0-R15 are not available in Tiny Core devices
12595 - R16 and R17 are fixed registers. */
12596
12597 for (size_t i = 0; i <= 17; i++)
12598 {
12599 fixed_regs[i] = 1;
12600 call_used_regs[i] = 1;
12601 }
12602
12603 /* Set R18 to R21 as callee saved registers
12604 - R18, R19, R20 and R21 are the callee saved registers in
12605 Tiny Core devices */
12606
12607 for (size_t i = 18; i <= LAST_CALLEE_SAVED_REG; i++)
12608 {
12609 call_used_regs[i] = 0;
12610 }
12611
12612 /* Update register allocation order for Tiny Core devices */
12613
12614 for (size_t i = 0; i < ARRAY_SIZE (tiny_reg_alloc_order); i++)
12615 {
12616 reg_alloc_order[i] = tiny_reg_alloc_order[i];
12617 }
12618
12619 CLEAR_HARD_REG_SET (reg_class_contents[(int) ADDW_REGS]);
12620 CLEAR_HARD_REG_SET (reg_class_contents[(int) NO_LD_REGS]);
12621 }
12622 }
12623
12624 /* Implement `TARGET_HARD_REGNO_SCRATCH_OK'. */
12625 /* Returns true if SCRATCH are safe to be allocated as a scratch
12626 registers (for a define_peephole2) in the current function. */
12627
12628 static bool
avr_hard_regno_scratch_ok(unsigned int regno)12629 avr_hard_regno_scratch_ok (unsigned int regno)
12630 {
12631 /* Interrupt functions can only use registers that have already been saved
12632 by the prologue, even if they would normally be call-clobbered. */
12633
12634 if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
12635 && !df_regs_ever_live_p (regno))
12636 return false;
12637
12638 /* Don't allow hard registers that might be part of the frame pointer.
12639 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
12640 and don't care for a frame pointer that spans more than one register. */
12641
12642 if ((!reload_completed || frame_pointer_needed)
12643 && (regno == REG_Y || regno == REG_Y + 1))
12644 {
12645 return false;
12646 }
12647
12648 return true;
12649 }
12650
12651
12652 /* Worker function for `HARD_REGNO_RENAME_OK'. */
12653 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
12654
12655 int
avr_hard_regno_rename_ok(unsigned int old_reg,unsigned int new_reg)12656 avr_hard_regno_rename_ok (unsigned int old_reg,
12657 unsigned int new_reg)
12658 {
12659 /* Interrupt functions can only use registers that have already been
12660 saved by the prologue, even if they would normally be
12661 call-clobbered. */
12662
12663 if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
12664 && !df_regs_ever_live_p (new_reg))
12665 return 0;
12666
12667 /* Don't allow hard registers that might be part of the frame pointer.
12668 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
12669 and don't care for a frame pointer that spans more than one register. */
12670
12671 if ((!reload_completed || frame_pointer_needed)
12672 && (old_reg == REG_Y || old_reg == REG_Y + 1
12673 || new_reg == REG_Y || new_reg == REG_Y + 1))
12674 {
12675 return 0;
12676 }
12677
12678 return 1;
12679 }
12680
12681 /* Output a branch that tests a single bit of a register (QI, HI, SI or DImode)
12682 or memory location in the I/O space (QImode only).
12683
12684 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
12685 Operand 1: register operand to test, or CONST_INT memory address.
12686 Operand 2: bit number.
12687 Operand 3: label to jump to if the test is true. */
12688
12689 const char*
avr_out_sbxx_branch(rtx_insn * insn,rtx operands[])12690 avr_out_sbxx_branch (rtx_insn *insn, rtx operands[])
12691 {
12692 enum rtx_code comp = GET_CODE (operands[0]);
12693 bool long_jump = get_attr_length (insn) >= 4;
12694 bool reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
12695
12696 if (comp == GE)
12697 comp = EQ;
12698 else if (comp == LT)
12699 comp = NE;
12700
12701 if (reverse)
12702 comp = reverse_condition (comp);
12703
12704 switch (GET_CODE (operands[1]))
12705 {
12706 default:
12707 gcc_unreachable();
12708
12709 case CONST_INT:
12710 case CONST:
12711 case SYMBOL_REF:
12712
12713 if (low_io_address_operand (operands[1], QImode))
12714 {
12715 if (comp == EQ)
12716 output_asm_insn ("sbis %i1,%2", operands);
12717 else
12718 output_asm_insn ("sbic %i1,%2", operands);
12719 }
12720 else
12721 {
12722 gcc_assert (io_address_operand (operands[1], QImode));
12723 output_asm_insn ("in __tmp_reg__,%i1", operands);
12724 if (comp == EQ)
12725 output_asm_insn ("sbrs __tmp_reg__,%2", operands);
12726 else
12727 output_asm_insn ("sbrc __tmp_reg__,%2", operands);
12728 }
12729
12730 break; /* CONST_INT */
12731
12732 case REG:
12733
12734 if (comp == EQ)
12735 output_asm_insn ("sbrs %T1%T2", operands);
12736 else
12737 output_asm_insn ("sbrc %T1%T2", operands);
12738
12739 break; /* REG */
12740 } /* switch */
12741
12742 if (long_jump)
12743 return ("rjmp .+4" CR_TAB
12744 "jmp %x3");
12745
12746 if (!reverse)
12747 return "rjmp %x3";
12748
12749 return "";
12750 }
12751
12752 /* Worker function for `TARGET_ASM_CONSTRUCTOR'. */
12753
12754 static void
avr_asm_out_ctor(rtx symbol,int priority)12755 avr_asm_out_ctor (rtx symbol, int priority)
12756 {
12757 fputs ("\t.global __do_global_ctors\n", asm_out_file);
12758 default_ctor_section_asm_out_constructor (symbol, priority);
12759 }
12760
12761
12762 /* Worker function for `TARGET_ASM_DESTRUCTOR'. */
12763
12764 static void
avr_asm_out_dtor(rtx symbol,int priority)12765 avr_asm_out_dtor (rtx symbol, int priority)
12766 {
12767 fputs ("\t.global __do_global_dtors\n", asm_out_file);
12768 default_dtor_section_asm_out_destructor (symbol, priority);
12769 }
12770
12771
12772 /* Worker function for `TARGET_RETURN_IN_MEMORY'. */
12773
12774 static bool
avr_return_in_memory(const_tree type,const_tree fntype ATTRIBUTE_UNUSED)12775 avr_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
12776 {
12777 HOST_WIDE_INT size = int_size_in_bytes (type);
12778 HOST_WIDE_INT ret_size_limit = AVR_TINY ? 4 : 8;
12779
12780 /* In avr, there are 8 return registers. But, for Tiny Core
12781 (ATtiny4/5/9/10/20/40) devices, only 4 registers are available.
12782 Return true if size is unknown or greater than the limit. */
12783
12784 if (size == -1 || size > ret_size_limit)
12785 {
12786 return true;
12787 }
12788 else
12789 {
12790 return false;
12791 }
12792 }
12793
12794
12795 /* Implement `CASE_VALUES_THRESHOLD'. */
12796 /* Supply the default for --param case-values-threshold=0 */
12797
12798 static unsigned int
avr_case_values_threshold(void)12799 avr_case_values_threshold (void)
12800 {
12801 /* The exact break-even point between a jump table and an if-else tree
12802 depends on several factors not available here like, e.g. if 8-bit
12803 comparisons can be used in the if-else tree or not, on the
12804 range of the case values, if the case value can be reused, on the
12805 register allocation, etc. '7' appears to be a good choice. */
12806
12807 return 7;
12808 }
12809
12810
12811 /* Implement `TARGET_ADDR_SPACE_ADDRESS_MODE'. */
12812
12813 static scalar_int_mode
avr_addr_space_address_mode(addr_space_t as)12814 avr_addr_space_address_mode (addr_space_t as)
12815 {
12816 return avr_addrspace[as].pointer_size == 3 ? PSImode : HImode;
12817 }
12818
12819
12820 /* Implement `TARGET_ADDR_SPACE_POINTER_MODE'. */
12821
12822 static scalar_int_mode
avr_addr_space_pointer_mode(addr_space_t as)12823 avr_addr_space_pointer_mode (addr_space_t as)
12824 {
12825 return avr_addr_space_address_mode (as);
12826 }
12827
12828
12829 /* Helper for following function. */
12830
12831 static bool
avr_reg_ok_for_pgm_addr(rtx reg,bool strict)12832 avr_reg_ok_for_pgm_addr (rtx reg, bool strict)
12833 {
12834 gcc_assert (REG_P (reg));
12835
12836 if (strict)
12837 {
12838 return REGNO (reg) == REG_Z;
12839 }
12840
12841 /* Avoid combine to propagate hard regs. */
12842
12843 if (can_create_pseudo_p()
12844 && REGNO (reg) < REG_Z)
12845 {
12846 return false;
12847 }
12848
12849 return true;
12850 }
12851
12852
12853 /* Implement `TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P'. */
12854
12855 static bool
avr_addr_space_legitimate_address_p(machine_mode mode,rtx x,bool strict,addr_space_t as)12856 avr_addr_space_legitimate_address_p (machine_mode mode, rtx x,
12857 bool strict, addr_space_t as)
12858 {
12859 bool ok = false;
12860
12861 switch (as)
12862 {
12863 default:
12864 gcc_unreachable();
12865
12866 case ADDR_SPACE_GENERIC:
12867 return avr_legitimate_address_p (mode, x, strict);
12868
12869 case ADDR_SPACE_FLASH:
12870 case ADDR_SPACE_FLASH1:
12871 case ADDR_SPACE_FLASH2:
12872 case ADDR_SPACE_FLASH3:
12873 case ADDR_SPACE_FLASH4:
12874 case ADDR_SPACE_FLASH5:
12875
12876 switch (GET_CODE (x))
12877 {
12878 case REG:
12879 ok = avr_reg_ok_for_pgm_addr (x, strict);
12880 break;
12881
12882 case POST_INC:
12883 ok = avr_reg_ok_for_pgm_addr (XEXP (x, 0), strict);
12884 break;
12885
12886 default:
12887 break;
12888 }
12889
12890 break; /* FLASH */
12891
12892 case ADDR_SPACE_MEMX:
12893 if (REG_P (x))
12894 ok = (!strict
12895 && can_create_pseudo_p());
12896
12897 if (LO_SUM == GET_CODE (x))
12898 {
12899 rtx hi = XEXP (x, 0);
12900 rtx lo = XEXP (x, 1);
12901
12902 ok = (REG_P (hi)
12903 && (!strict || REGNO (hi) < FIRST_PSEUDO_REGISTER)
12904 && REG_P (lo)
12905 && REGNO (lo) == REG_Z);
12906 }
12907
12908 break; /* MEMX */
12909 }
12910
12911 if (avr_log.legitimate_address_p)
12912 {
12913 avr_edump ("\n%?: ret=%b, mode=%m strict=%d "
12914 "reload_completed=%d reload_in_progress=%d %s:",
12915 ok, mode, strict, reload_completed, reload_in_progress,
12916 reg_renumber ? "(reg_renumber)" : "");
12917
12918 if (GET_CODE (x) == PLUS
12919 && REG_P (XEXP (x, 0))
12920 && CONST_INT_P (XEXP (x, 1))
12921 && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
12922 && reg_renumber)
12923 {
12924 avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
12925 true_regnum (XEXP (x, 0)));
12926 }
12927
12928 avr_edump ("\n%r\n", x);
12929 }
12930
12931 return ok;
12932 }
12933
12934
12935 /* Implement `TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS'. */
12936
12937 static rtx
avr_addr_space_legitimize_address(rtx x,rtx old_x,machine_mode mode,addr_space_t as)12938 avr_addr_space_legitimize_address (rtx x, rtx old_x,
12939 machine_mode mode, addr_space_t as)
12940 {
12941 if (ADDR_SPACE_GENERIC_P (as))
12942 return avr_legitimize_address (x, old_x, mode);
12943
12944 if (avr_log.legitimize_address)
12945 {
12946 avr_edump ("\n%?: mode=%m\n %r\n", mode, old_x);
12947 }
12948
12949 return old_x;
12950 }
12951
12952
12953 /* Implement `TARGET_ADDR_SPACE_CONVERT'. */
12954
12955 static rtx
avr_addr_space_convert(rtx src,tree type_from,tree type_to)12956 avr_addr_space_convert (rtx src, tree type_from, tree type_to)
12957 {
12958 addr_space_t as_from = TYPE_ADDR_SPACE (TREE_TYPE (type_from));
12959 addr_space_t as_to = TYPE_ADDR_SPACE (TREE_TYPE (type_to));
12960
12961 if (avr_log.progmem)
12962 avr_edump ("\n%!: op = %r\nfrom = %t\nto = %t\n",
12963 src, type_from, type_to);
12964
12965 /* Up-casting from 16-bit to 24-bit pointer. */
12966
12967 if (as_from != ADDR_SPACE_MEMX
12968 && as_to == ADDR_SPACE_MEMX)
12969 {
12970 int msb;
12971 rtx sym = src;
12972 rtx reg = gen_reg_rtx (PSImode);
12973
12974 while (CONST == GET_CODE (sym) || PLUS == GET_CODE (sym))
12975 sym = XEXP (sym, 0);
12976
12977 /* Look at symbol flags: avr_encode_section_info set the flags
12978 also if attribute progmem was seen so that we get the right
12979 promotion for, e.g. PSTR-like strings that reside in generic space
12980 but are located in flash. In that case we patch the incoming
12981 address space. */
12982
12983 if (SYMBOL_REF_P (sym)
12984 && ADDR_SPACE_FLASH == AVR_SYMBOL_GET_ADDR_SPACE (sym))
12985 {
12986 as_from = ADDR_SPACE_FLASH;
12987 }
12988
12989 /* Linearize memory: RAM has bit 23 set. */
12990
12991 msb = ADDR_SPACE_GENERIC_P (as_from)
12992 ? 0x80
12993 : avr_addrspace[as_from].segment;
12994
12995 src = force_reg (Pmode, src);
12996
12997 emit_insn (msb == 0
12998 ? gen_zero_extendhipsi2 (reg, src)
12999 : gen_n_extendhipsi2 (reg, gen_int_mode (msb, QImode), src));
13000
13001 return reg;
13002 }
13003
13004 /* Down-casting from 24-bit to 16-bit throws away the high byte. */
13005
13006 if (as_from == ADDR_SPACE_MEMX
13007 && as_to != ADDR_SPACE_MEMX)
13008 {
13009 rtx new_src = gen_reg_rtx (Pmode);
13010
13011 src = force_reg (PSImode, src);
13012
13013 emit_move_insn (new_src,
13014 simplify_gen_subreg (Pmode, src, PSImode, 0));
13015 return new_src;
13016 }
13017
13018 return src;
13019 }
13020
13021
13022 /* Implement `TARGET_ADDR_SPACE_SUBSET_P'. */
13023
13024 static bool
avr_addr_space_subset_p(addr_space_t subset ATTRIBUTE_UNUSED,addr_space_t superset ATTRIBUTE_UNUSED)13025 avr_addr_space_subset_p (addr_space_t subset ATTRIBUTE_UNUSED,
13026 addr_space_t superset ATTRIBUTE_UNUSED)
13027 {
13028 /* Allow any kind of pointer mess. */
13029
13030 return true;
13031 }
13032
13033
13034 /* Implement `TARGET_CONVERT_TO_TYPE'. */
13035
13036 static tree
avr_convert_to_type(tree type,tree expr)13037 avr_convert_to_type (tree type, tree expr)
13038 {
13039 /* Print a diagnose for pointer conversion that changes the address
13040 space of the pointer target to a non-enclosing address space,
13041 provided -Waddr-space-convert is on.
13042
13043 FIXME: Filter out cases where the target object is known to
13044 be located in the right memory, like in
13045
13046 (const __flash*) PSTR ("text")
13047
13048 Also try to distinguish between explicit casts requested by
13049 the user and implicit casts like
13050
13051 void f (const __flash char*);
13052
13053 void g (const char *p)
13054 {
13055 f ((const __flash*) p);
13056 }
13057
13058 under the assumption that an explicit casts means that the user
13059 knows what he is doing, e.g. interface with PSTR or old style
13060 code with progmem and pgm_read_xxx.
13061 */
13062
13063 if (avr_warn_addr_space_convert
13064 && expr != error_mark_node
13065 && POINTER_TYPE_P (type)
13066 && POINTER_TYPE_P (TREE_TYPE (expr)))
13067 {
13068 addr_space_t as_old = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (expr)));
13069 addr_space_t as_new = TYPE_ADDR_SPACE (TREE_TYPE (type));
13070
13071 if (avr_log.progmem)
13072 avr_edump ("%?: type = %t\nexpr = %t\n\n", type, expr);
13073
13074 if (as_new != ADDR_SPACE_MEMX
13075 && as_new != as_old)
13076 {
13077 location_t loc = EXPR_LOCATION (expr);
13078 const char *name_old = avr_addrspace[as_old].name;
13079 const char *name_new = avr_addrspace[as_new].name;
13080
13081 warning (OPT_Waddr_space_convert,
13082 "conversion from address space %qs to address space %qs",
13083 ADDR_SPACE_GENERIC_P (as_old) ? "generic" : name_old,
13084 ADDR_SPACE_GENERIC_P (as_new) ? "generic" : name_new);
13085
13086 return fold_build1_loc (loc, ADDR_SPACE_CONVERT_EXPR, type, expr);
13087 }
13088 }
13089
13090 return NULL_TREE;
13091 }
13092
13093
13094 /* Implement `TARGET_LEGITIMATE_COMBINED_INSN'. */
13095
13096 /* PR78883: Filter out paradoxical SUBREGs of MEM which are not handled
13097 properly by following passes. As INSN_SCHEDULING is off and hence
13098 general_operand accepts such expressions, ditch them now. */
13099
13100 static bool
avr_legitimate_combined_insn(rtx_insn * insn)13101 avr_legitimate_combined_insn (rtx_insn *insn)
13102 {
13103 subrtx_iterator::array_type array;
13104
13105 FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
13106 {
13107 const_rtx op = *iter;
13108
13109 if (SUBREG_P (op)
13110 && MEM_P (SUBREG_REG (op))
13111 && (GET_MODE_SIZE (GET_MODE (op))
13112 > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))))
13113 {
13114 return false;
13115 }
13116 }
13117
13118 return true;
13119 }
13120
13121
13122 /* PR63633: The middle-end might come up with hard regs as input operands.
13123
13124 RMASK is a bit mask representing a subset of hard registers R0...R31:
13125 Rn is an element of that set iff bit n of RMASK is set.
13126 OPMASK describes a subset of OP[]: If bit n of OPMASK is 1 then
13127 OP[n] has to be fixed; otherwise OP[n] is left alone.
13128
13129 For each element of OPMASK which is a hard register overlapping RMASK,
13130 replace OP[n] with a newly created pseudo register
13131
13132 HREG == 0: Also emit a move insn that copies the contents of that
13133 hard register into the new pseudo.
13134
13135 HREG != 0: Also set HREG[n] to the hard register. */
13136
13137 static void
avr_fix_operands(rtx * op,rtx * hreg,unsigned opmask,unsigned rmask)13138 avr_fix_operands (rtx *op, rtx *hreg, unsigned opmask, unsigned rmask)
13139 {
13140 for (; opmask; opmask >>= 1, op++)
13141 {
13142 rtx reg = *op;
13143
13144 if (hreg)
13145 *hreg = NULL_RTX;
13146
13147 if ((opmask & 1)
13148 && REG_P (reg)
13149 && REGNO (reg) < FIRST_PSEUDO_REGISTER
13150 // This hard-reg overlaps other prohibited hard regs?
13151 && (rmask & regmask (GET_MODE (reg), REGNO (reg))))
13152 {
13153 *op = gen_reg_rtx (GET_MODE (reg));
13154 if (hreg == NULL)
13155 emit_move_insn (*op, reg);
13156 else
13157 *hreg = reg;
13158 }
13159
13160 if (hreg)
13161 hreg++;
13162 }
13163 }
13164
13165
13166 void
avr_fix_inputs(rtx * op,unsigned opmask,unsigned rmask)13167 avr_fix_inputs (rtx *op, unsigned opmask, unsigned rmask)
13168 {
13169 avr_fix_operands (op, NULL, opmask, rmask);
13170 }
13171
13172
13173 /* Helper for the function below: If bit n of MASK is set and
13174 HREG[n] != NULL, then emit a move insn to copy OP[n] to HREG[n].
13175 Otherwise do nothing for that n. Return TRUE. */
13176
13177 static bool
avr_move_fixed_operands(rtx * op,rtx * hreg,unsigned mask)13178 avr_move_fixed_operands (rtx *op, rtx *hreg, unsigned mask)
13179 {
13180 for (; mask; mask >>= 1, op++, hreg++)
13181 if ((mask & 1)
13182 && *hreg)
13183 emit_move_insn (*hreg, *op);
13184
13185 return true;
13186 }
13187
13188
13189 /* PR63633: The middle-end might come up with hard regs as output operands.
13190
13191 GEN is a sequence generating function like gen_mulsi3 with 3 operands OP[].
13192 RMASK is a bit mask representing a subset of hard registers R0...R31:
13193 Rn is an element of that set iff bit n of RMASK is set.
13194 OPMASK describes a subset of OP[]: If bit n of OPMASK is 1 then
13195 OP[n] has to be fixed; otherwise OP[n] is left alone.
13196
13197 Emit the insn sequence as generated by GEN() with all elements of OPMASK
13198 which are hard registers overlapping RMASK replaced by newly created
13199 pseudo registers. After the sequence has been emitted, emit insns that
13200 move the contents of respective pseudos to their hard regs. */
13201
13202 bool
avr_emit3_fix_outputs(rtx (* gen)(rtx,rtx,rtx),rtx * op,unsigned opmask,unsigned rmask)13203 avr_emit3_fix_outputs (rtx (*gen)(rtx,rtx,rtx), rtx *op,
13204 unsigned opmask, unsigned rmask)
13205 {
13206 const int n = 3;
13207 rtx hreg[n];
13208
13209 /* It is letigimate for GEN to call this function, and in order not to
13210 get self-recursive we use the following static kludge. This is the
13211 only way not to duplicate all expanders and to avoid ugly and
13212 hard-to-maintain C-code instead of the much more appreciated RTL
13213 representation as supplied by define_expand. */
13214 static bool lock = false;
13215
13216 gcc_assert (opmask < (1u << n));
13217
13218 if (lock)
13219 return false;
13220
13221 avr_fix_operands (op, hreg, opmask, rmask);
13222
13223 lock = true;
13224 emit_insn (gen (op[0], op[1], op[2]));
13225 lock = false;
13226
13227 return avr_move_fixed_operands (op, hreg, opmask);
13228 }
13229
13230
13231 /* Worker function for cpymemhi expander.
13232 XOP[0] Destination as MEM:BLK
13233 XOP[1] Source " "
13234 XOP[2] # Bytes to copy
13235
13236 Return TRUE if the expansion is accomplished.
13237 Return FALSE if the operand compination is not supported. */
13238
13239 bool
avr_emit_cpymemhi(rtx * xop)13240 avr_emit_cpymemhi (rtx *xop)
13241 {
13242 HOST_WIDE_INT count;
13243 machine_mode loop_mode;
13244 addr_space_t as = MEM_ADDR_SPACE (xop[1]);
13245 rtx loop_reg, addr1, a_src, a_dest, insn, xas;
13246 rtx a_hi8 = NULL_RTX;
13247
13248 if (avr_mem_flash_p (xop[0]))
13249 return false;
13250
13251 if (!CONST_INT_P (xop[2]))
13252 return false;
13253
13254 count = INTVAL (xop[2]);
13255 if (count <= 0)
13256 return false;
13257
13258 a_src = XEXP (xop[1], 0);
13259 a_dest = XEXP (xop[0], 0);
13260
13261 if (PSImode == GET_MODE (a_src))
13262 {
13263 gcc_assert (as == ADDR_SPACE_MEMX);
13264
13265 loop_mode = (count < 0x100) ? QImode : HImode;
13266 loop_reg = gen_rtx_REG (loop_mode, 24);
13267 emit_move_insn (loop_reg, gen_int_mode (count, loop_mode));
13268
13269 addr1 = simplify_gen_subreg (HImode, a_src, PSImode, 0);
13270 a_hi8 = simplify_gen_subreg (QImode, a_src, PSImode, 2);
13271 }
13272 else
13273 {
13274 int segment = avr_addrspace[as].segment;
13275
13276 if (segment
13277 && avr_n_flash > 1)
13278 {
13279 a_hi8 = GEN_INT (segment);
13280 emit_move_insn (rampz_rtx, a_hi8 = copy_to_mode_reg (QImode, a_hi8));
13281 }
13282 else if (!ADDR_SPACE_GENERIC_P (as))
13283 {
13284 as = ADDR_SPACE_FLASH;
13285 }
13286
13287 addr1 = a_src;
13288
13289 loop_mode = (count <= 0x100) ? QImode : HImode;
13290 loop_reg = copy_to_mode_reg (loop_mode, gen_int_mode (count, loop_mode));
13291 }
13292
13293 xas = GEN_INT (as);
13294
13295 /* FIXME: Register allocator might come up with spill fails if it is left
13296 on its own. Thus, we allocate the pointer registers by hand:
13297 Z = source address
13298 X = destination address */
13299
13300 emit_move_insn (lpm_addr_reg_rtx, addr1);
13301 emit_move_insn (gen_rtx_REG (HImode, REG_X), a_dest);
13302
13303 /* FIXME: Register allocator does a bad job and might spill address
13304 register(s) inside the loop leading to additional move instruction
13305 to/from stack which could clobber tmp_reg. Thus, do *not* emit
13306 load and store as separate insns. Instead, we perform the copy
13307 by means of one monolithic insn. */
13308
13309 gcc_assert (TMP_REGNO == LPM_REGNO);
13310
13311 if (as != ADDR_SPACE_MEMX)
13312 {
13313 /* Load instruction ([E]LPM or LD) is known at compile time:
13314 Do the copy-loop inline. */
13315
13316 rtx (*fun) (rtx, rtx, rtx)
13317 = QImode == loop_mode ? gen_cpymem_qi : gen_cpymem_hi;
13318
13319 insn = fun (xas, loop_reg, loop_reg);
13320 }
13321 else
13322 {
13323 rtx (*fun) (rtx, rtx)
13324 = QImode == loop_mode ? gen_cpymemx_qi : gen_cpymemx_hi;
13325
13326 emit_move_insn (gen_rtx_REG (QImode, 23), a_hi8);
13327
13328 insn = fun (xas, GEN_INT (avr_addr.rampz));
13329 }
13330
13331 set_mem_addr_space (SET_SRC (XVECEXP (insn, 0, 0)), as);
13332 emit_insn (insn);
13333
13334 return true;
13335 }
13336
13337
13338 /* Print assembler for cpymem_qi, cpymem_hi insns...
13339 $0 : Address Space
13340 $1, $2 : Loop register
13341 Z : Source address
13342 X : Destination address
13343 */
13344
13345 const char*
avr_out_cpymem(rtx_insn * insn ATTRIBUTE_UNUSED,rtx * op,int * plen)13346 avr_out_cpymem (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
13347 {
13348 addr_space_t as = (addr_space_t) INTVAL (op[0]);
13349 machine_mode loop_mode = GET_MODE (op[1]);
13350 bool sbiw_p = test_hard_reg_class (ADDW_REGS, op[1]);
13351 rtx xop[3];
13352
13353 if (plen)
13354 *plen = 0;
13355
13356 xop[0] = op[0];
13357 xop[1] = op[1];
13358 xop[2] = tmp_reg_rtx;
13359
13360 /* Loop label */
13361
13362 avr_asm_len ("0:", xop, plen, 0);
13363
13364 /* Load with post-increment */
13365
13366 switch (as)
13367 {
13368 default:
13369 gcc_unreachable();
13370
13371 case ADDR_SPACE_GENERIC:
13372
13373 avr_asm_len ("ld %2,Z+", xop, plen, 1);
13374 break;
13375
13376 case ADDR_SPACE_FLASH:
13377
13378 if (AVR_HAVE_LPMX)
13379 avr_asm_len ("lpm %2,Z+", xop, plen, 1);
13380 else
13381 avr_asm_len ("lpm" CR_TAB
13382 "adiw r30,1", xop, plen, 2);
13383 break;
13384
13385 case ADDR_SPACE_FLASH1:
13386 case ADDR_SPACE_FLASH2:
13387 case ADDR_SPACE_FLASH3:
13388 case ADDR_SPACE_FLASH4:
13389 case ADDR_SPACE_FLASH5:
13390
13391 if (AVR_HAVE_ELPMX)
13392 avr_asm_len ("elpm %2,Z+", xop, plen, 1);
13393 else
13394 avr_asm_len ("elpm" CR_TAB
13395 "adiw r30,1", xop, plen, 2);
13396 break;
13397 }
13398
13399 /* Store with post-increment */
13400
13401 avr_asm_len ("st X+,%2", xop, plen, 1);
13402
13403 /* Decrement loop-counter and set Z-flag */
13404
13405 if (QImode == loop_mode)
13406 {
13407 avr_asm_len ("dec %1", xop, plen, 1);
13408 }
13409 else if (sbiw_p)
13410 {
13411 avr_asm_len ("sbiw %1,1", xop, plen, 1);
13412 }
13413 else
13414 {
13415 avr_asm_len ("subi %A1,1" CR_TAB
13416 "sbci %B1,0", xop, plen, 2);
13417 }
13418
13419 /* Loop until zero */
13420
13421 return avr_asm_len ("brne 0b", xop, plen, 1);
13422 }
13423
13424
13425
13426 /* Helper for __builtin_avr_delay_cycles */
13427
13428 static rtx
avr_mem_clobber(void)13429 avr_mem_clobber (void)
13430 {
13431 rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
13432 MEM_VOLATILE_P (mem) = 1;
13433 return mem;
13434 }
13435
13436 static void
avr_expand_delay_cycles(rtx operands0)13437 avr_expand_delay_cycles (rtx operands0)
13438 {
13439 unsigned HOST_WIDE_INT cycles = UINTVAL (operands0) & GET_MODE_MASK (SImode);
13440 unsigned HOST_WIDE_INT cycles_used;
13441 unsigned HOST_WIDE_INT loop_count;
13442
13443 if (IN_RANGE (cycles, 83886082, 0xFFFFFFFF))
13444 {
13445 loop_count = ((cycles - 9) / 6) + 1;
13446 cycles_used = ((loop_count - 1) * 6) + 9;
13447 emit_insn (gen_delay_cycles_4 (gen_int_mode (loop_count, SImode),
13448 avr_mem_clobber()));
13449 cycles -= cycles_used;
13450 }
13451
13452 if (IN_RANGE (cycles, 262145, 83886081))
13453 {
13454 loop_count = ((cycles - 7) / 5) + 1;
13455 if (loop_count > 0xFFFFFF)
13456 loop_count = 0xFFFFFF;
13457 cycles_used = ((loop_count - 1) * 5) + 7;
13458 emit_insn (gen_delay_cycles_3 (gen_int_mode (loop_count, SImode),
13459 avr_mem_clobber()));
13460 cycles -= cycles_used;
13461 }
13462
13463 if (IN_RANGE (cycles, 768, 262144))
13464 {
13465 loop_count = ((cycles - 5) / 4) + 1;
13466 if (loop_count > 0xFFFF)
13467 loop_count = 0xFFFF;
13468 cycles_used = ((loop_count - 1) * 4) + 5;
13469 emit_insn (gen_delay_cycles_2 (gen_int_mode (loop_count, HImode),
13470 avr_mem_clobber()));
13471 cycles -= cycles_used;
13472 }
13473
13474 if (IN_RANGE (cycles, 6, 767))
13475 {
13476 loop_count = cycles / 3;
13477 if (loop_count > 255)
13478 loop_count = 255;
13479 cycles_used = loop_count * 3;
13480 emit_insn (gen_delay_cycles_1 (gen_int_mode (loop_count, QImode),
13481 avr_mem_clobber()));
13482 cycles -= cycles_used;
13483 }
13484
13485 while (cycles >= 2)
13486 {
13487 emit_insn (gen_nopv (GEN_INT (2)));
13488 cycles -= 2;
13489 }
13490
13491 if (cycles == 1)
13492 {
13493 emit_insn (gen_nopv (GEN_INT (1)));
13494 cycles--;
13495 }
13496 }
13497
13498
13499 static void
avr_expand_nops(rtx operands0)13500 avr_expand_nops (rtx operands0)
13501 {
13502 unsigned HOST_WIDE_INT n_nops = UINTVAL (operands0) & GET_MODE_MASK (HImode);
13503
13504 while (n_nops--)
13505 {
13506 emit_insn (gen_nopv (const1_rtx));
13507 }
13508 }
13509
13510
13511 /* Compute the image of x under f, i.e. perform x --> f(x) */
13512
13513 static int
avr_map(unsigned int f,int x)13514 avr_map (unsigned int f, int x)
13515 {
13516 return x < 8 ? (f >> (4 * x)) & 0xf : 0;
13517 }
13518
13519
13520 /* Return some metrics of map A. */
13521
13522 enum
13523 {
13524 /* Number of fixed points in { 0 ... 7 } */
13525 MAP_FIXED_0_7,
13526
13527 /* Size of preimage of non-fixed points in { 0 ... 7 } */
13528 MAP_NONFIXED_0_7,
13529
13530 /* Mask representing the fixed points in { 0 ... 7 } */
13531 MAP_MASK_FIXED_0_7,
13532
13533 /* Size of the preimage of { 0 ... 7 } */
13534 MAP_PREIMAGE_0_7,
13535
13536 /* Mask that represents the preimage of { f } */
13537 MAP_MASK_PREIMAGE_F
13538 };
13539
13540 static unsigned
avr_map_metric(unsigned int a,int mode)13541 avr_map_metric (unsigned int a, int mode)
13542 {
13543 unsigned metric = 0;
13544
13545 for (unsigned i = 0; i < 8; i++)
13546 {
13547 unsigned ai = avr_map (a, i);
13548
13549 if (mode == MAP_FIXED_0_7)
13550 metric += ai == i;
13551 else if (mode == MAP_NONFIXED_0_7)
13552 metric += ai < 8 && ai != i;
13553 else if (mode == MAP_MASK_FIXED_0_7)
13554 metric |= ((unsigned) (ai == i)) << i;
13555 else if (mode == MAP_PREIMAGE_0_7)
13556 metric += ai < 8;
13557 else if (mode == MAP_MASK_PREIMAGE_F)
13558 metric |= ((unsigned) (ai == 0xf)) << i;
13559 else
13560 gcc_unreachable();
13561 }
13562
13563 return metric;
13564 }
13565
13566
13567 /* Return true if IVAL has a 0xf in its hexadecimal representation
13568 and false, otherwise. Only nibbles 0..7 are taken into account.
13569 Used as constraint helper for C0f and Cxf. */
13570
13571 bool
avr_has_nibble_0xf(rtx ival)13572 avr_has_nibble_0xf (rtx ival)
13573 {
13574 unsigned int map = UINTVAL (ival) & GET_MODE_MASK (SImode);
13575 return avr_map_metric (map, MAP_MASK_PREIMAGE_F) != 0;
13576 }
13577
13578
13579 /* We have a set of bits that are mapped by a function F.
13580 Try to decompose F by means of a second function G so that
13581
13582 F = F o G^-1 o G
13583
13584 and
13585
13586 cost (F o G^-1) + cost (G) < cost (F)
13587
13588 Example: Suppose builtin insert_bits supplies us with the map
13589 F = 0x3210ffff. Instead of doing 4 bit insertions to get the high
13590 nibble of the result, we can just as well rotate the bits before inserting
13591 them and use the map 0x7654ffff which is cheaper than the original map.
13592 For this example G = G^-1 = 0x32107654 and F o G^-1 = 0x7654ffff. */
13593
13594 typedef struct
13595 {
13596 /* tree code of binary function G */
13597 enum tree_code code;
13598
13599 /* The constant second argument of G */
13600 int arg;
13601
13602 /* G^-1, the inverse of G (*, arg) */
13603 unsigned ginv;
13604
13605 /* The cost of applying G (*, arg) */
13606 int cost;
13607
13608 /* The composition F o G^-1 (*, arg) for some function F */
13609 unsigned int map;
13610
13611 /* For debug purpose only */
13612 const char *str;
13613 } avr_map_op_t;
13614
13615 static const avr_map_op_t avr_map_op[] =
13616 {
13617 { LROTATE_EXPR, 0, 0x76543210, 0, 0, "id" },
13618 { LROTATE_EXPR, 1, 0x07654321, 2, 0, "<<<" },
13619 { LROTATE_EXPR, 2, 0x10765432, 4, 0, "<<<" },
13620 { LROTATE_EXPR, 3, 0x21076543, 4, 0, "<<<" },
13621 { LROTATE_EXPR, 4, 0x32107654, 1, 0, "<<<" },
13622 { LROTATE_EXPR, 5, 0x43210765, 3, 0, "<<<" },
13623 { LROTATE_EXPR, 6, 0x54321076, 5, 0, "<<<" },
13624 { LROTATE_EXPR, 7, 0x65432107, 3, 0, "<<<" },
13625 { RSHIFT_EXPR, 1, 0x6543210c, 1, 0, ">>" },
13626 { RSHIFT_EXPR, 1, 0x7543210c, 1, 0, ">>" },
13627 { RSHIFT_EXPR, 2, 0x543210cc, 2, 0, ">>" },
13628 { RSHIFT_EXPR, 2, 0x643210cc, 2, 0, ">>" },
13629 { RSHIFT_EXPR, 2, 0x743210cc, 2, 0, ">>" },
13630 { LSHIFT_EXPR, 1, 0xc7654321, 1, 0, "<<" },
13631 { LSHIFT_EXPR, 2, 0xcc765432, 2, 0, "<<" }
13632 };
13633
13634
13635 /* Try to decompose F as F = (F o G^-1) o G as described above.
13636 The result is a struct representing F o G^-1 and G.
13637 If result.cost < 0 then such a decomposition does not exist. */
13638
13639 static avr_map_op_t
avr_map_decompose(unsigned int f,const avr_map_op_t * g,bool val_const_p)13640 avr_map_decompose (unsigned int f, const avr_map_op_t *g, bool val_const_p)
13641 {
13642 bool val_used_p = avr_map_metric (f, MAP_MASK_PREIMAGE_F) != 0;
13643 avr_map_op_t f_ginv = *g;
13644 unsigned int ginv = g->ginv;
13645
13646 f_ginv.cost = -1;
13647
13648 /* Step 1: Computing F o G^-1 */
13649
13650 for (int i = 7; i >= 0; i--)
13651 {
13652 int x = avr_map (f, i);
13653
13654 if (x <= 7)
13655 {
13656 x = avr_map (ginv, x);
13657
13658 /* The bit is no element of the image of G: no avail (cost = -1) */
13659
13660 if (x > 7)
13661 return f_ginv;
13662 }
13663
13664 f_ginv.map = (f_ginv.map << 4) + x;
13665 }
13666
13667 /* Step 2: Compute the cost of the operations.
13668 The overall cost of doing an operation prior to the insertion is
13669 the cost of the insertion plus the cost of the operation. */
13670
13671 /* Step 2a: Compute cost of F o G^-1 */
13672
13673 if (avr_map_metric (f_ginv.map, MAP_NONFIXED_0_7) == 0)
13674 /* The mapping consists only of fixed points and can be folded
13675 to AND/OR logic in the remainder. Reasonable cost is 3. */
13676 f_ginv.cost = 2 + (val_used_p && !val_const_p);
13677 else
13678 {
13679 rtx xop[4];
13680
13681 /* Get the cost of the insn by calling the output worker with some
13682 fake values. Mimic effect of reloading xop[3]: Unused operands
13683 are mapped to 0 and used operands are reloaded to xop[0]. */
13684
13685 xop[0] = all_regs_rtx[24];
13686 xop[1] = gen_int_mode (f_ginv.map, SImode);
13687 xop[2] = all_regs_rtx[25];
13688 xop[3] = val_used_p ? xop[0] : const0_rtx;
13689
13690 avr_out_insert_bits (xop, &f_ginv.cost);
13691
13692 f_ginv.cost += val_const_p && val_used_p ? 1 : 0;
13693 }
13694
13695 /* Step 2b: Add cost of G */
13696
13697 f_ginv.cost += g->cost;
13698
13699 if (avr_log.builtin)
13700 avr_edump (" %s%d=%d", g->str, g->arg, f_ginv.cost);
13701
13702 return f_ginv;
13703 }
13704
13705
13706 /* Insert bits from XOP[1] into XOP[0] according to MAP.
13707 XOP[0] and XOP[1] don't overlap.
13708 If FIXP_P = true: Move all bits according to MAP using BLD/BST sequences.
13709 If FIXP_P = false: Just move the bit if its position in the destination
13710 is different to its source position. */
13711
13712 static void
avr_move_bits(rtx * xop,unsigned int map,bool fixp_p,int * plen)13713 avr_move_bits (rtx *xop, unsigned int map, bool fixp_p, int *plen)
13714 {
13715 /* T-flag contains this bit of the source, i.e. of XOP[1] */
13716 int t_bit_src = -1;
13717
13718 /* We order the operations according to the requested source bit b. */
13719
13720 for (int b = 0; b < 8; b++)
13721 for (int bit_dest = 0; bit_dest < 8; bit_dest++)
13722 {
13723 int bit_src = avr_map (map, bit_dest);
13724
13725 if (b != bit_src
13726 || bit_src >= 8
13727 /* Same position: No need to copy as requested by FIXP_P. */
13728 || (bit_dest == bit_src && !fixp_p))
13729 continue;
13730
13731 if (t_bit_src != bit_src)
13732 {
13733 /* Source bit is not yet in T: Store it to T. */
13734
13735 t_bit_src = bit_src;
13736
13737 xop[3] = GEN_INT (bit_src);
13738 avr_asm_len ("bst %T1%T3", xop, plen, 1);
13739 }
13740
13741 /* Load destination bit with T. */
13742
13743 xop[3] = GEN_INT (bit_dest);
13744 avr_asm_len ("bld %T0%T3", xop, plen, 1);
13745 }
13746 }
13747
13748
13749 /* PLEN == 0: Print assembler code for `insert_bits'.
13750 PLEN != 0: Compute code length in bytes.
13751
13752 OP[0]: Result
13753 OP[1]: The mapping composed of nibbles. If nibble no. N is
13754 0: Bit N of result is copied from bit OP[2].0
13755 ... ...
13756 7: Bit N of result is copied from bit OP[2].7
13757 0xf: Bit N of result is copied from bit OP[3].N
13758 OP[2]: Bits to be inserted
13759 OP[3]: Target value */
13760
13761 const char*
avr_out_insert_bits(rtx * op,int * plen)13762 avr_out_insert_bits (rtx *op, int *plen)
13763 {
13764 unsigned int map = UINTVAL (op[1]) & GET_MODE_MASK (SImode);
13765 unsigned mask_fixed;
13766 bool fixp_p = true;
13767 rtx xop[4];
13768
13769 xop[0] = op[0];
13770 xop[1] = op[2];
13771 xop[2] = op[3];
13772
13773 gcc_assert (REG_P (xop[2]) || CONST_INT_P (xop[2]));
13774
13775 if (plen)
13776 *plen = 0;
13777 else if (flag_print_asm_name)
13778 fprintf (asm_out_file, ASM_COMMENT_START "map = 0x%08x\n", map);
13779
13780 /* If MAP has fixed points it might be better to initialize the result
13781 with the bits to be inserted instead of moving all bits by hand. */
13782
13783 mask_fixed = avr_map_metric (map, MAP_MASK_FIXED_0_7);
13784
13785 if (REGNO (xop[0]) == REGNO (xop[1]))
13786 {
13787 /* Avoid early-clobber conflicts */
13788
13789 avr_asm_len ("mov __tmp_reg__,%1", xop, plen, 1);
13790 xop[1] = tmp_reg_rtx;
13791 fixp_p = false;
13792 }
13793
13794 if (avr_map_metric (map, MAP_MASK_PREIMAGE_F))
13795 {
13796 /* XOP[2] is used and reloaded to XOP[0] already */
13797
13798 int n_fix = 0, n_nofix = 0;
13799
13800 gcc_assert (REG_P (xop[2]));
13801
13802 /* Get the code size of the bit insertions; once with all bits
13803 moved and once with fixed points omitted. */
13804
13805 avr_move_bits (xop, map, true, &n_fix);
13806 avr_move_bits (xop, map, false, &n_nofix);
13807
13808 if (fixp_p && n_fix - n_nofix > 3)
13809 {
13810 xop[3] = gen_int_mode (~mask_fixed, QImode);
13811
13812 avr_asm_len ("eor %0,%1" CR_TAB
13813 "andi %0,%3" CR_TAB
13814 "eor %0,%1", xop, plen, 3);
13815 fixp_p = false;
13816 }
13817 }
13818 else
13819 {
13820 /* XOP[2] is unused */
13821
13822 if (fixp_p && mask_fixed)
13823 {
13824 avr_asm_len ("mov %0,%1", xop, plen, 1);
13825 fixp_p = false;
13826 }
13827 }
13828
13829 /* Move/insert remaining bits. */
13830
13831 avr_move_bits (xop, map, fixp_p, plen);
13832
13833 return "";
13834 }
13835
13836
13837 /* IDs for all the AVR builtins. */
13838
13839 enum avr_builtin_id
13840 {
13841 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
13842 AVR_BUILTIN_ ## NAME,
13843 #include "builtins.def"
13844 #undef DEF_BUILTIN
13845
13846 AVR_BUILTIN_COUNT
13847 };
13848
13849 struct GTY(()) avr_builtin_description
13850 {
13851 enum insn_code icode;
13852 int n_args;
13853 tree fndecl;
13854 };
13855
13856
13857 /* Notice that avr_bdesc[] and avr_builtin_id are initialized in such a way
13858 that a built-in's ID can be used to access the built-in by means of
13859 avr_bdesc[ID] */
13860
13861 static GTY(()) struct avr_builtin_description
13862 avr_bdesc[AVR_BUILTIN_COUNT] =
13863 {
13864 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE, LIBNAME) \
13865 { (enum insn_code) CODE_FOR_ ## ICODE, N_ARGS, NULL_TREE },
13866 #include "builtins.def"
13867 #undef DEF_BUILTIN
13868 };
13869
13870
13871 /* Implement `TARGET_BUILTIN_DECL'. */
13872
13873 static tree
avr_builtin_decl(unsigned id,bool initialize_p ATTRIBUTE_UNUSED)13874 avr_builtin_decl (unsigned id, bool initialize_p ATTRIBUTE_UNUSED)
13875 {
13876 if (id < AVR_BUILTIN_COUNT)
13877 return avr_bdesc[id].fndecl;
13878
13879 return error_mark_node;
13880 }
13881
13882
13883 static void
avr_init_builtin_int24(void)13884 avr_init_builtin_int24 (void)
13885 {
13886 tree int24_type = make_signed_type (GET_MODE_BITSIZE (PSImode));
13887 tree uint24_type = make_unsigned_type (GET_MODE_BITSIZE (PSImode));
13888
13889 lang_hooks.types.register_builtin_type (int24_type, "__int24");
13890 lang_hooks.types.register_builtin_type (uint24_type, "__uint24");
13891 }
13892
13893
13894 /* Implement `TARGET_INIT_BUILTINS' */
13895 /* Set up all builtin functions for this target. */
13896
13897 static void
avr_init_builtins(void)13898 avr_init_builtins (void)
13899 {
13900 tree void_ftype_void
13901 = build_function_type_list (void_type_node, NULL_TREE);
13902 tree uchar_ftype_uchar
13903 = build_function_type_list (unsigned_char_type_node,
13904 unsigned_char_type_node,
13905 NULL_TREE);
13906 tree uint_ftype_uchar_uchar
13907 = build_function_type_list (unsigned_type_node,
13908 unsigned_char_type_node,
13909 unsigned_char_type_node,
13910 NULL_TREE);
13911 tree int_ftype_char_char
13912 = build_function_type_list (integer_type_node,
13913 char_type_node,
13914 char_type_node,
13915 NULL_TREE);
13916 tree int_ftype_char_uchar
13917 = build_function_type_list (integer_type_node,
13918 char_type_node,
13919 unsigned_char_type_node,
13920 NULL_TREE);
13921 tree void_ftype_ulong
13922 = build_function_type_list (void_type_node,
13923 long_unsigned_type_node,
13924 NULL_TREE);
13925
13926 tree uchar_ftype_ulong_uchar_uchar
13927 = build_function_type_list (unsigned_char_type_node,
13928 long_unsigned_type_node,
13929 unsigned_char_type_node,
13930 unsigned_char_type_node,
13931 NULL_TREE);
13932
13933 tree const_memx_void_node
13934 = build_qualified_type (void_type_node,
13935 TYPE_QUAL_CONST
13936 | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_MEMX));
13937
13938 tree const_memx_ptr_type_node
13939 = build_pointer_type_for_mode (const_memx_void_node, PSImode, false);
13940
13941 tree char_ftype_const_memx_ptr
13942 = build_function_type_list (char_type_node,
13943 const_memx_ptr_type_node,
13944 NULL);
13945
13946 #define ITYP(T) \
13947 lang_hooks.types.type_for_size (TYPE_PRECISION (T), TYPE_UNSIGNED (T))
13948
13949 #define FX_FTYPE_FX(fx) \
13950 tree fx##r_ftype_##fx##r \
13951 = build_function_type_list (node_##fx##r, node_##fx##r, NULL); \
13952 tree fx##k_ftype_##fx##k \
13953 = build_function_type_list (node_##fx##k, node_##fx##k, NULL)
13954
13955 #define FX_FTYPE_FX_INT(fx) \
13956 tree fx##r_ftype_##fx##r_int \
13957 = build_function_type_list (node_##fx##r, node_##fx##r, \
13958 integer_type_node, NULL); \
13959 tree fx##k_ftype_##fx##k_int \
13960 = build_function_type_list (node_##fx##k, node_##fx##k, \
13961 integer_type_node, NULL)
13962
13963 #define INT_FTYPE_FX(fx) \
13964 tree int_ftype_##fx##r \
13965 = build_function_type_list (integer_type_node, node_##fx##r, NULL); \
13966 tree int_ftype_##fx##k \
13967 = build_function_type_list (integer_type_node, node_##fx##k, NULL)
13968
13969 #define INTX_FTYPE_FX(fx) \
13970 tree int##fx##r_ftype_##fx##r \
13971 = build_function_type_list (ITYP (node_##fx##r), node_##fx##r, NULL); \
13972 tree int##fx##k_ftype_##fx##k \
13973 = build_function_type_list (ITYP (node_##fx##k), node_##fx##k, NULL)
13974
13975 #define FX_FTYPE_INTX(fx) \
13976 tree fx##r_ftype_int##fx##r \
13977 = build_function_type_list (node_##fx##r, ITYP (node_##fx##r), NULL); \
13978 tree fx##k_ftype_int##fx##k \
13979 = build_function_type_list (node_##fx##k, ITYP (node_##fx##k), NULL)
13980
13981 tree node_hr = short_fract_type_node;
13982 tree node_nr = fract_type_node;
13983 tree node_lr = long_fract_type_node;
13984 tree node_llr = long_long_fract_type_node;
13985
13986 tree node_uhr = unsigned_short_fract_type_node;
13987 tree node_unr = unsigned_fract_type_node;
13988 tree node_ulr = unsigned_long_fract_type_node;
13989 tree node_ullr = unsigned_long_long_fract_type_node;
13990
13991 tree node_hk = short_accum_type_node;
13992 tree node_nk = accum_type_node;
13993 tree node_lk = long_accum_type_node;
13994 tree node_llk = long_long_accum_type_node;
13995
13996 tree node_uhk = unsigned_short_accum_type_node;
13997 tree node_unk = unsigned_accum_type_node;
13998 tree node_ulk = unsigned_long_accum_type_node;
13999 tree node_ullk = unsigned_long_long_accum_type_node;
14000
14001
14002 /* For absfx builtins. */
14003
14004 FX_FTYPE_FX (h);
14005 FX_FTYPE_FX (n);
14006 FX_FTYPE_FX (l);
14007 FX_FTYPE_FX (ll);
14008
14009 /* For roundfx builtins. */
14010
14011 FX_FTYPE_FX_INT (h);
14012 FX_FTYPE_FX_INT (n);
14013 FX_FTYPE_FX_INT (l);
14014 FX_FTYPE_FX_INT (ll);
14015
14016 FX_FTYPE_FX_INT (uh);
14017 FX_FTYPE_FX_INT (un);
14018 FX_FTYPE_FX_INT (ul);
14019 FX_FTYPE_FX_INT (ull);
14020
14021 /* For countlsfx builtins. */
14022
14023 INT_FTYPE_FX (h);
14024 INT_FTYPE_FX (n);
14025 INT_FTYPE_FX (l);
14026 INT_FTYPE_FX (ll);
14027
14028 INT_FTYPE_FX (uh);
14029 INT_FTYPE_FX (un);
14030 INT_FTYPE_FX (ul);
14031 INT_FTYPE_FX (ull);
14032
14033 /* For bitsfx builtins. */
14034
14035 INTX_FTYPE_FX (h);
14036 INTX_FTYPE_FX (n);
14037 INTX_FTYPE_FX (l);
14038 INTX_FTYPE_FX (ll);
14039
14040 INTX_FTYPE_FX (uh);
14041 INTX_FTYPE_FX (un);
14042 INTX_FTYPE_FX (ul);
14043 INTX_FTYPE_FX (ull);
14044
14045 /* For fxbits builtins. */
14046
14047 FX_FTYPE_INTX (h);
14048 FX_FTYPE_INTX (n);
14049 FX_FTYPE_INTX (l);
14050 FX_FTYPE_INTX (ll);
14051
14052 FX_FTYPE_INTX (uh);
14053 FX_FTYPE_INTX (un);
14054 FX_FTYPE_INTX (ul);
14055 FX_FTYPE_INTX (ull);
14056
14057
14058 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
14059 { \
14060 int id = AVR_BUILTIN_ ## NAME; \
14061 const char *Name = "__builtin_avr_" #NAME; \
14062 char *name = (char*) alloca (1 + strlen (Name)); \
14063 \
14064 gcc_assert (id < AVR_BUILTIN_COUNT); \
14065 avr_bdesc[id].fndecl \
14066 = add_builtin_function (avr_tolower (name, Name), TYPE, id, \
14067 BUILT_IN_MD, LIBNAME, NULL_TREE); \
14068 }
14069 #include "builtins.def"
14070 #undef DEF_BUILTIN
14071
14072 avr_init_builtin_int24 ();
14073 }
14074
14075
14076 /* Subroutine of avr_expand_builtin to expand vanilla builtins
14077 with non-void result and 1 ... 3 arguments. */
14078
14079 static rtx
avr_default_expand_builtin(enum insn_code icode,tree exp,rtx target)14080 avr_default_expand_builtin (enum insn_code icode, tree exp, rtx target)
14081 {
14082 rtx pat, xop[3];
14083 int n_args = call_expr_nargs (exp);
14084 machine_mode tmode = insn_data[icode].operand[0].mode;
14085
14086 gcc_assert (n_args >= 1 && n_args <= 3);
14087
14088 if (target == NULL_RTX
14089 || GET_MODE (target) != tmode
14090 || !insn_data[icode].operand[0].predicate (target, tmode))
14091 {
14092 target = gen_reg_rtx (tmode);
14093 }
14094
14095 for (int n = 0; n < n_args; n++)
14096 {
14097 tree arg = CALL_EXPR_ARG (exp, n);
14098 rtx op = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14099 machine_mode opmode = GET_MODE (op);
14100 machine_mode mode = insn_data[icode].operand[n + 1].mode;
14101
14102 if ((opmode == SImode || opmode == VOIDmode) && mode == HImode)
14103 {
14104 opmode = HImode;
14105 op = gen_lowpart (HImode, op);
14106 }
14107
14108 /* In case the insn wants input operands in modes different from
14109 the result, abort. */
14110
14111 gcc_assert (opmode == mode || opmode == VOIDmode);
14112
14113 if (!insn_data[icode].operand[n + 1].predicate (op, mode))
14114 op = copy_to_mode_reg (mode, op);
14115
14116 xop[n] = op;
14117 }
14118
14119 switch (n_args)
14120 {
14121 case 1: pat = GEN_FCN (icode) (target, xop[0]); break;
14122 case 2: pat = GEN_FCN (icode) (target, xop[0], xop[1]); break;
14123 case 3: pat = GEN_FCN (icode) (target, xop[0], xop[1], xop[2]); break;
14124
14125 default:
14126 gcc_unreachable();
14127 }
14128
14129 if (pat == NULL_RTX)
14130 return NULL_RTX;
14131
14132 emit_insn (pat);
14133
14134 return target;
14135 }
14136
14137
14138 /* Implement `TARGET_EXPAND_BUILTIN'. */
14139 /* Expand an expression EXP that calls a built-in function,
14140 with result going to TARGET if that's convenient
14141 (and in mode MODE if that's convenient).
14142 SUBTARGET may be used as the target for computing one of EXP's operands.
14143 IGNORE is nonzero if the value is to be ignored. */
14144
14145 static rtx
avr_expand_builtin(tree exp,rtx target,rtx subtarget ATTRIBUTE_UNUSED,machine_mode mode ATTRIBUTE_UNUSED,int ignore)14146 avr_expand_builtin (tree exp, rtx target,
14147 rtx subtarget ATTRIBUTE_UNUSED,
14148 machine_mode mode ATTRIBUTE_UNUSED,
14149 int ignore)
14150 {
14151 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
14152 const char *bname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
14153 unsigned int id = DECL_MD_FUNCTION_CODE (fndecl);
14154 const struct avr_builtin_description *d = &avr_bdesc[id];
14155 tree arg0;
14156 rtx op0;
14157
14158 gcc_assert (id < AVR_BUILTIN_COUNT);
14159
14160 switch (id)
14161 {
14162 case AVR_BUILTIN_NOP:
14163 emit_insn (gen_nopv (GEN_INT (1)));
14164 return 0;
14165
14166 case AVR_BUILTIN_DELAY_CYCLES:
14167 {
14168 arg0 = CALL_EXPR_ARG (exp, 0);
14169 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14170
14171 if (!CONST_INT_P (op0))
14172 error ("%s expects a compile time integer constant", bname);
14173 else
14174 avr_expand_delay_cycles (op0);
14175
14176 return NULL_RTX;
14177 }
14178
14179 case AVR_BUILTIN_NOPS:
14180 {
14181 arg0 = CALL_EXPR_ARG (exp, 0);
14182 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14183
14184 if (!CONST_INT_P (op0))
14185 error ("%s expects a compile time integer constant", bname);
14186 else
14187 avr_expand_nops (op0);
14188
14189 return NULL_RTX;
14190 }
14191
14192 case AVR_BUILTIN_INSERT_BITS:
14193 {
14194 arg0 = CALL_EXPR_ARG (exp, 0);
14195 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
14196
14197 if (!CONST_INT_P (op0))
14198 {
14199 error ("%s expects a compile time long integer constant"
14200 " as first argument", bname);
14201 return target;
14202 }
14203
14204 break;
14205 }
14206
14207 case AVR_BUILTIN_ROUNDHR: case AVR_BUILTIN_ROUNDUHR:
14208 case AVR_BUILTIN_ROUNDR: case AVR_BUILTIN_ROUNDUR:
14209 case AVR_BUILTIN_ROUNDLR: case AVR_BUILTIN_ROUNDULR:
14210 case AVR_BUILTIN_ROUNDLLR: case AVR_BUILTIN_ROUNDULLR:
14211
14212 case AVR_BUILTIN_ROUNDHK: case AVR_BUILTIN_ROUNDUHK:
14213 case AVR_BUILTIN_ROUNDK: case AVR_BUILTIN_ROUNDUK:
14214 case AVR_BUILTIN_ROUNDLK: case AVR_BUILTIN_ROUNDULK:
14215 case AVR_BUILTIN_ROUNDLLK: case AVR_BUILTIN_ROUNDULLK:
14216
14217 /* Warn about odd rounding. Rounding points >= FBIT will have
14218 no effect. */
14219
14220 if (TREE_CODE (CALL_EXPR_ARG (exp, 1)) != INTEGER_CST)
14221 break;
14222
14223 int rbit = (int) TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1));
14224
14225 if (rbit >= (int) GET_MODE_FBIT (mode))
14226 {
14227 warning (OPT_Wextra, "rounding to %d bits has no effect for "
14228 "fixed-point value with %d fractional bits",
14229 rbit, GET_MODE_FBIT (mode));
14230
14231 return expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX, mode,
14232 EXPAND_NORMAL);
14233 }
14234 else if (rbit <= - (int) GET_MODE_IBIT (mode))
14235 {
14236 warning (0, "rounding result will always be 0");
14237 return CONST0_RTX (mode);
14238 }
14239
14240 /* The rounding points RP satisfies now: -IBIT < RP < FBIT.
14241
14242 TR 18037 only specifies results for RP > 0. However, the
14243 remaining cases of -IBIT < RP <= 0 can easily be supported
14244 without any additional overhead. */
14245
14246 break; /* round */
14247 }
14248
14249 /* No fold found and no insn: Call support function from libgcc. */
14250
14251 if (d->icode == CODE_FOR_nothing
14252 && DECL_ASSEMBLER_NAME (get_callee_fndecl (exp)) != NULL_TREE)
14253 {
14254 return expand_call (exp, target, ignore);
14255 }
14256
14257 /* No special treatment needed: vanilla expand. */
14258
14259 gcc_assert (d->icode != CODE_FOR_nothing);
14260 gcc_assert (d->n_args == call_expr_nargs (exp));
14261
14262 if (d->n_args == 0)
14263 {
14264 emit_insn ((GEN_FCN (d->icode)) (target));
14265 return NULL_RTX;
14266 }
14267
14268 return avr_default_expand_builtin (d->icode, exp, target);
14269 }
14270
14271
14272 /* Helper for `avr_fold_builtin' that folds absfx (FIXED_CST). */
14273
14274 static tree
avr_fold_absfx(tree tval)14275 avr_fold_absfx (tree tval)
14276 {
14277 if (FIXED_CST != TREE_CODE (tval))
14278 return NULL_TREE;
14279
14280 /* Our fixed-points have no padding: Use double_int payload directly. */
14281
14282 FIXED_VALUE_TYPE fval = TREE_FIXED_CST (tval);
14283 unsigned int bits = GET_MODE_BITSIZE (fval.mode);
14284 double_int ival = fval.data.sext (bits);
14285
14286 if (!ival.is_negative())
14287 return tval;
14288
14289 /* ISO/IEC TR 18037, 7.18a.6.2: The absfx functions are saturating. */
14290
14291 fval.data = (ival == double_int::min_value (bits, false).sext (bits))
14292 ? double_int::max_value (bits, false)
14293 : -ival;
14294
14295 return build_fixed (TREE_TYPE (tval), fval);
14296 }
14297
14298
14299 /* Implement `TARGET_FOLD_BUILTIN'. */
14300
14301 static tree
avr_fold_builtin(tree fndecl,int n_args ATTRIBUTE_UNUSED,tree * arg,bool ignore ATTRIBUTE_UNUSED)14302 avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg,
14303 bool ignore ATTRIBUTE_UNUSED)
14304 {
14305 unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
14306 tree val_type = TREE_TYPE (TREE_TYPE (fndecl));
14307
14308 if (!optimize)
14309 return NULL_TREE;
14310
14311 switch (fcode)
14312 {
14313 default:
14314 break;
14315
14316 case AVR_BUILTIN_SWAP:
14317 {
14318 return fold_build2 (LROTATE_EXPR, val_type, arg[0],
14319 build_int_cst (val_type, 4));
14320 }
14321
14322 case AVR_BUILTIN_ABSHR:
14323 case AVR_BUILTIN_ABSR:
14324 case AVR_BUILTIN_ABSLR:
14325 case AVR_BUILTIN_ABSLLR:
14326
14327 case AVR_BUILTIN_ABSHK:
14328 case AVR_BUILTIN_ABSK:
14329 case AVR_BUILTIN_ABSLK:
14330 case AVR_BUILTIN_ABSLLK:
14331 /* GCC is not good with folding ABS for fixed-point. Do it by hand. */
14332
14333 return avr_fold_absfx (arg[0]);
14334
14335 case AVR_BUILTIN_BITSHR: case AVR_BUILTIN_HRBITS:
14336 case AVR_BUILTIN_BITSHK: case AVR_BUILTIN_HKBITS:
14337 case AVR_BUILTIN_BITSUHR: case AVR_BUILTIN_UHRBITS:
14338 case AVR_BUILTIN_BITSUHK: case AVR_BUILTIN_UHKBITS:
14339
14340 case AVR_BUILTIN_BITSR: case AVR_BUILTIN_RBITS:
14341 case AVR_BUILTIN_BITSK: case AVR_BUILTIN_KBITS:
14342 case AVR_BUILTIN_BITSUR: case AVR_BUILTIN_URBITS:
14343 case AVR_BUILTIN_BITSUK: case AVR_BUILTIN_UKBITS:
14344
14345 case AVR_BUILTIN_BITSLR: case AVR_BUILTIN_LRBITS:
14346 case AVR_BUILTIN_BITSLK: case AVR_BUILTIN_LKBITS:
14347 case AVR_BUILTIN_BITSULR: case AVR_BUILTIN_ULRBITS:
14348 case AVR_BUILTIN_BITSULK: case AVR_BUILTIN_ULKBITS:
14349
14350 case AVR_BUILTIN_BITSLLR: case AVR_BUILTIN_LLRBITS:
14351 case AVR_BUILTIN_BITSLLK: case AVR_BUILTIN_LLKBITS:
14352 case AVR_BUILTIN_BITSULLR: case AVR_BUILTIN_ULLRBITS:
14353 case AVR_BUILTIN_BITSULLK: case AVR_BUILTIN_ULLKBITS:
14354
14355 gcc_assert (TYPE_PRECISION (val_type)
14356 == TYPE_PRECISION (TREE_TYPE (arg[0])));
14357
14358 return build1 (VIEW_CONVERT_EXPR, val_type, arg[0]);
14359
14360 case AVR_BUILTIN_INSERT_BITS:
14361 {
14362 tree tbits = arg[1];
14363 tree tval = arg[2];
14364 tree tmap;
14365 tree map_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
14366 unsigned int map;
14367 bool changed = false;
14368 avr_map_op_t best_g;
14369
14370 if (TREE_CODE (arg[0]) != INTEGER_CST)
14371 {
14372 /* No constant as first argument: Don't fold this and run into
14373 error in avr_expand_builtin. */
14374
14375 break;
14376 }
14377
14378 tmap = wide_int_to_tree (map_type, wi::to_wide (arg[0]));
14379 map = TREE_INT_CST_LOW (tmap);
14380
14381 if (TREE_CODE (tval) != INTEGER_CST
14382 && avr_map_metric (map, MAP_MASK_PREIMAGE_F) == 0)
14383 {
14384 /* There are no F in the map, i.e. 3rd operand is unused.
14385 Replace that argument with some constant to render
14386 respective input unused. */
14387
14388 tval = build_int_cst (val_type, 0);
14389 changed = true;
14390 }
14391
14392 if (TREE_CODE (tbits) != INTEGER_CST
14393 && avr_map_metric (map, MAP_PREIMAGE_0_7) == 0)
14394 {
14395 /* Similar for the bits to be inserted. If they are unused,
14396 we can just as well pass 0. */
14397
14398 tbits = build_int_cst (val_type, 0);
14399 }
14400
14401 if (TREE_CODE (tbits) == INTEGER_CST)
14402 {
14403 /* Inserting bits known at compile time is easy and can be
14404 performed by AND and OR with appropriate masks. */
14405
14406 int bits = TREE_INT_CST_LOW (tbits);
14407 int mask_ior = 0, mask_and = 0xff;
14408
14409 for (size_t i = 0; i < 8; i++)
14410 {
14411 int mi = avr_map (map, i);
14412
14413 if (mi < 8)
14414 {
14415 if (bits & (1 << mi)) mask_ior |= (1 << i);
14416 else mask_and &= ~(1 << i);
14417 }
14418 }
14419
14420 tval = fold_build2 (BIT_IOR_EXPR, val_type, tval,
14421 build_int_cst (val_type, mask_ior));
14422 return fold_build2 (BIT_AND_EXPR, val_type, tval,
14423 build_int_cst (val_type, mask_and));
14424 }
14425
14426 if (changed)
14427 return build_call_expr (fndecl, 3, tmap, tbits, tval);
14428
14429 /* If bits don't change their position we can use vanilla logic
14430 to merge the two arguments. */
14431
14432 if (avr_map_metric (map, MAP_NONFIXED_0_7) == 0)
14433 {
14434 int mask_f = avr_map_metric (map, MAP_MASK_PREIMAGE_F);
14435 tree tres, tmask = build_int_cst (val_type, mask_f ^ 0xff);
14436
14437 tres = fold_build2 (BIT_XOR_EXPR, val_type, tbits, tval);
14438 tres = fold_build2 (BIT_AND_EXPR, val_type, tres, tmask);
14439 return fold_build2 (BIT_XOR_EXPR, val_type, tres, tval);
14440 }
14441
14442 /* Try to decomposing map to reduce overall cost. */
14443
14444 if (avr_log.builtin)
14445 avr_edump ("\n%?: %x\n%?: ROL cost: ", map);
14446
14447 best_g = avr_map_op[0];
14448 best_g.cost = 1000;
14449
14450 for (size_t i = 0; i < ARRAY_SIZE (avr_map_op); i++)
14451 {
14452 avr_map_op_t g
14453 = avr_map_decompose (map, avr_map_op + i,
14454 TREE_CODE (tval) == INTEGER_CST);
14455
14456 if (g.cost >= 0 && g.cost < best_g.cost)
14457 best_g = g;
14458 }
14459
14460 if (avr_log.builtin)
14461 avr_edump ("\n");
14462
14463 if (best_g.arg == 0)
14464 /* No optimization found */
14465 break;
14466
14467 /* Apply operation G to the 2nd argument. */
14468
14469 if (avr_log.builtin)
14470 avr_edump ("%?: using OP(%s%d, %x) cost %d\n",
14471 best_g.str, best_g.arg, best_g.map, best_g.cost);
14472
14473 /* Do right-shifts arithmetically: They copy the MSB instead of
14474 shifting in a non-usable value (0) as with logic right-shift. */
14475
14476 tbits = fold_convert (signed_char_type_node, tbits);
14477 tbits = fold_build2 (best_g.code, signed_char_type_node, tbits,
14478 build_int_cst (val_type, best_g.arg));
14479 tbits = fold_convert (val_type, tbits);
14480
14481 /* Use map o G^-1 instead of original map to undo the effect of G. */
14482
14483 tmap = wide_int_to_tree (map_type, best_g.map);
14484
14485 return build_call_expr (fndecl, 3, tmap, tbits, tval);
14486 } /* AVR_BUILTIN_INSERT_BITS */
14487 }
14488
14489 return NULL_TREE;
14490 }
14491
14492 /* Prepend to CLOBBERS hard registers that are automatically clobbered
14493 for an asm. We do this for CC_REGNUM to maintain source compatibility
14494 with the original cc0-based compiler. */
14495
14496 static rtx_insn *
avr_md_asm_adjust(vec<rtx> &,vec<rtx> &,vec<machine_mode> &,vec<const char * > &,vec<rtx> & clobbers,HARD_REG_SET & clobbered_regs,location_t)14497 avr_md_asm_adjust (vec<rtx> &/*outputs*/, vec<rtx> &/*inputs*/,
14498 vec<machine_mode> & /*input_modes*/,
14499 vec<const char *> &/*constraints*/,
14500 vec<rtx> &clobbers, HARD_REG_SET &clobbered_regs,
14501 location_t /*loc*/)
14502 {
14503 clobbers.safe_push (cc_reg_rtx);
14504 SET_HARD_REG_BIT (clobbered_regs, REG_CC);
14505 return NULL;
14506 }
14507
14508
14509 /* Worker function for `FLOAT_LIB_COMPARE_RETURNS_BOOL'. */
14510
14511 bool
avr_float_lib_compare_returns_bool(machine_mode mode,enum rtx_code)14512 avr_float_lib_compare_returns_bool (machine_mode mode, enum rtx_code)
14513 {
14514 if (mode == DFmode)
14515 {
14516 #if WITH_DOUBLE_COMPARISON == 2
14517 return true;
14518 #endif
14519 }
14520
14521 // This is the GCC default and also what AVR-LibC implements.
14522 return false;
14523 }
14524
14525
14526
14527 /* Initialize the GCC target structure. */
14528
14529 #undef TARGET_ASM_ALIGNED_HI_OP
14530 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
14531 #undef TARGET_ASM_ALIGNED_SI_OP
14532 #define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
14533 #undef TARGET_ASM_UNALIGNED_HI_OP
14534 #define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
14535 #undef TARGET_ASM_UNALIGNED_SI_OP
14536 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
14537 #undef TARGET_ASM_INTEGER
14538 #define TARGET_ASM_INTEGER avr_assemble_integer
14539 #undef TARGET_ASM_FILE_START
14540 #define TARGET_ASM_FILE_START avr_file_start
14541 #undef TARGET_ASM_FILE_END
14542 #define TARGET_ASM_FILE_END avr_file_end
14543
14544 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
14545 #define TARGET_ASM_FUNCTION_END_PROLOGUE avr_asm_function_end_prologue
14546 #undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
14547 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE avr_asm_function_begin_epilogue
14548
14549 #undef TARGET_FUNCTION_VALUE
14550 #define TARGET_FUNCTION_VALUE avr_function_value
14551 #undef TARGET_LIBCALL_VALUE
14552 #define TARGET_LIBCALL_VALUE avr_libcall_value
14553 #undef TARGET_FUNCTION_VALUE_REGNO_P
14554 #define TARGET_FUNCTION_VALUE_REGNO_P avr_function_value_regno_p
14555
14556 #undef TARGET_ATTRIBUTE_TABLE
14557 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
14558 #undef TARGET_INSERT_ATTRIBUTES
14559 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
14560 #undef TARGET_SECTION_TYPE_FLAGS
14561 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
14562
14563 #undef TARGET_ASM_NAMED_SECTION
14564 #define TARGET_ASM_NAMED_SECTION avr_asm_named_section
14565 #undef TARGET_ASM_INIT_SECTIONS
14566 #define TARGET_ASM_INIT_SECTIONS avr_asm_init_sections
14567 #undef TARGET_ENCODE_SECTION_INFO
14568 #define TARGET_ENCODE_SECTION_INFO avr_encode_section_info
14569 #undef TARGET_ASM_SELECT_SECTION
14570 #define TARGET_ASM_SELECT_SECTION avr_asm_select_section
14571
14572 #undef TARGET_ASM_FINAL_POSTSCAN_INSN
14573 #define TARGET_ASM_FINAL_POSTSCAN_INSN avr_asm_final_postscan_insn
14574
14575 #undef TARGET_REGISTER_MOVE_COST
14576 #define TARGET_REGISTER_MOVE_COST avr_register_move_cost
14577 #undef TARGET_MEMORY_MOVE_COST
14578 #define TARGET_MEMORY_MOVE_COST avr_memory_move_cost
14579 #undef TARGET_RTX_COSTS
14580 #define TARGET_RTX_COSTS avr_rtx_costs
14581 #undef TARGET_ADDRESS_COST
14582 #define TARGET_ADDRESS_COST avr_address_cost
14583 #undef TARGET_MACHINE_DEPENDENT_REORG
14584 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
14585 #undef TARGET_FUNCTION_ARG
14586 #define TARGET_FUNCTION_ARG avr_function_arg
14587 #undef TARGET_FUNCTION_ARG_ADVANCE
14588 #define TARGET_FUNCTION_ARG_ADVANCE avr_function_arg_advance
14589
14590 #undef TARGET_SET_CURRENT_FUNCTION
14591 #define TARGET_SET_CURRENT_FUNCTION avr_set_current_function
14592
14593 #undef TARGET_RETURN_IN_MEMORY
14594 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
14595
14596 #undef TARGET_STRICT_ARGUMENT_NAMING
14597 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
14598
14599 #undef TARGET_CONDITIONAL_REGISTER_USAGE
14600 #define TARGET_CONDITIONAL_REGISTER_USAGE avr_conditional_register_usage
14601
14602 #undef TARGET_HARD_REGNO_NREGS
14603 #define TARGET_HARD_REGNO_NREGS avr_hard_regno_nregs
14604
14605 #undef TARGET_HARD_REGNO_MODE_OK
14606 #define TARGET_HARD_REGNO_MODE_OK avr_hard_regno_mode_ok
14607 #undef TARGET_HARD_REGNO_SCRATCH_OK
14608 #define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok
14609 #undef TARGET_HARD_REGNO_CALL_PART_CLOBBERED
14610 #define TARGET_HARD_REGNO_CALL_PART_CLOBBERED \
14611 avr_hard_regno_call_part_clobbered
14612
14613 #undef TARGET_CASE_VALUES_THRESHOLD
14614 #define TARGET_CASE_VALUES_THRESHOLD avr_case_values_threshold
14615
14616 #undef TARGET_FRAME_POINTER_REQUIRED
14617 #define TARGET_FRAME_POINTER_REQUIRED avr_frame_pointer_required_p
14618 #undef TARGET_CAN_ELIMINATE
14619 #define TARGET_CAN_ELIMINATE avr_can_eliminate
14620
14621 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
14622 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS avr_allocate_stack_slots_for_args
14623
14624 #undef TARGET_WARN_FUNC_RETURN
14625 #define TARGET_WARN_FUNC_RETURN avr_warn_func_return
14626
14627 #undef TARGET_CLASS_LIKELY_SPILLED_P
14628 #define TARGET_CLASS_LIKELY_SPILLED_P avr_class_likely_spilled_p
14629
14630 #undef TARGET_CLASS_MAX_NREGS
14631 #define TARGET_CLASS_MAX_NREGS avr_class_max_nregs
14632
14633 #undef TARGET_OPTION_OVERRIDE
14634 #define TARGET_OPTION_OVERRIDE avr_option_override
14635
14636 #undef TARGET_CANNOT_MODIFY_JUMPS_P
14637 #define TARGET_CANNOT_MODIFY_JUMPS_P avr_cannot_modify_jumps_p
14638
14639 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
14640 #define TARGET_FUNCTION_OK_FOR_SIBCALL avr_function_ok_for_sibcall
14641
14642 #undef TARGET_INIT_BUILTINS
14643 #define TARGET_INIT_BUILTINS avr_init_builtins
14644
14645 #undef TARGET_BUILTIN_DECL
14646 #define TARGET_BUILTIN_DECL avr_builtin_decl
14647
14648 #undef TARGET_EXPAND_BUILTIN
14649 #define TARGET_EXPAND_BUILTIN avr_expand_builtin
14650
14651 #undef TARGET_FOLD_BUILTIN
14652 #define TARGET_FOLD_BUILTIN avr_fold_builtin
14653
14654 #undef TARGET_SCALAR_MODE_SUPPORTED_P
14655 #define TARGET_SCALAR_MODE_SUPPORTED_P avr_scalar_mode_supported_p
14656
14657 #undef TARGET_BUILD_BUILTIN_VA_LIST
14658 #define TARGET_BUILD_BUILTIN_VA_LIST avr_build_builtin_va_list
14659
14660 #undef TARGET_FIXED_POINT_SUPPORTED_P
14661 #define TARGET_FIXED_POINT_SUPPORTED_P hook_bool_void_true
14662
14663 #undef TARGET_CONVERT_TO_TYPE
14664 #define TARGET_CONVERT_TO_TYPE avr_convert_to_type
14665
14666 #undef TARGET_LRA_P
14667 #define TARGET_LRA_P hook_bool_void_false
14668
14669 #undef TARGET_ADDR_SPACE_SUBSET_P
14670 #define TARGET_ADDR_SPACE_SUBSET_P avr_addr_space_subset_p
14671
14672 #undef TARGET_ADDR_SPACE_CONVERT
14673 #define TARGET_ADDR_SPACE_CONVERT avr_addr_space_convert
14674
14675 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
14676 #define TARGET_ADDR_SPACE_ADDRESS_MODE avr_addr_space_address_mode
14677
14678 #undef TARGET_ADDR_SPACE_POINTER_MODE
14679 #define TARGET_ADDR_SPACE_POINTER_MODE avr_addr_space_pointer_mode
14680
14681 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
14682 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
14683 avr_addr_space_legitimate_address_p
14684
14685 #undef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
14686 #define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS avr_addr_space_legitimize_address
14687
14688 #undef TARGET_ADDR_SPACE_DIAGNOSE_USAGE
14689 #define TARGET_ADDR_SPACE_DIAGNOSE_USAGE avr_addr_space_diagnose_usage
14690
14691 #undef TARGET_MODE_DEPENDENT_ADDRESS_P
14692 #define TARGET_MODE_DEPENDENT_ADDRESS_P avr_mode_dependent_address_p
14693
14694 #undef TARGET_PRINT_OPERAND
14695 #define TARGET_PRINT_OPERAND avr_print_operand
14696 #undef TARGET_PRINT_OPERAND_ADDRESS
14697 #define TARGET_PRINT_OPERAND_ADDRESS avr_print_operand_address
14698 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
14699 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P avr_print_operand_punct_valid_p
14700
14701 #undef TARGET_USE_BY_PIECES_INFRASTRUCTURE_P
14702 #define TARGET_USE_BY_PIECES_INFRASTRUCTURE_P \
14703 avr_use_by_pieces_infrastructure_p
14704
14705 #undef TARGET_LEGITIMATE_COMBINED_INSN
14706 #define TARGET_LEGITIMATE_COMBINED_INSN avr_legitimate_combined_insn
14707
14708 #undef TARGET_STARTING_FRAME_OFFSET
14709 #define TARGET_STARTING_FRAME_OFFSET avr_starting_frame_offset
14710
14711 #undef TARGET_MD_ASM_ADJUST
14712 #define TARGET_MD_ASM_ADJUST avr_md_asm_adjust
14713
14714 struct gcc_target targetm = TARGET_INITIALIZER;
14715
14716
14717 #include "gt-avr.h"
14718