1 /* Subroutines for insn-output.c for ATMEL AVR micro controllers
2 Copyright (C) 1998-2016 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 #include "config.h"
22 #include "system.h"
23 #include "intl.h"
24 #include "coretypes.h"
25 #include "backend.h"
26 #include "target.h"
27 #include "rtl.h"
28 #include "tree.h"
29 #include "cgraph.h"
30 #include "c-family/c-common.h"
31 #include "cfghooks.h"
32 #include "df.h"
33 #include "tm_p.h"
34 #include "optabs.h"
35 #include "regs.h"
36 #include "emit-rtl.h"
37 #include "recog.h"
38 #include "conditions.h"
39 #include "insn-attr.h"
40 #include "reload.h"
41 #include "varasm.h"
42 #include "calls.h"
43 #include "stor-layout.h"
44 #include "output.h"
45 #include "explow.h"
46 #include "expr.h"
47 #include "langhooks.h"
48 #include "cfgrtl.h"
49 #include "params.h"
50 #include "builtins.h"
51 #include "context.h"
52 #include "tree-pass.h"
53
54 /* This file should be included last. */
55 #include "target-def.h"
56
57 /* Maximal allowed offset for an address in the LD command */
58 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
59
60 /* Return true if STR starts with PREFIX and false, otherwise. */
61 #define STR_PREFIX_P(STR,PREFIX) (0 == strncmp (STR, PREFIX, strlen (PREFIX)))
62
63 /* The 4 bits starting at SECTION_MACH_DEP are reserved to store the
64 address space where data is to be located.
65 As the only non-generic address spaces are all located in flash,
66 this can be used to test if data shall go into some .progmem* section.
67 This must be the rightmost field of machine dependent section flags. */
68 #define AVR_SECTION_PROGMEM (0xf * SECTION_MACH_DEP)
69
70 /* Similar 4-bit region for SYMBOL_REF_FLAGS. */
71 #define AVR_SYMBOL_FLAG_PROGMEM (0xf * SYMBOL_FLAG_MACH_DEP)
72
73 /* Similar 4-bit region in SYMBOL_REF_FLAGS:
74 Set address-space AS in SYMBOL_REF_FLAGS of SYM */
75 #define AVR_SYMBOL_SET_ADDR_SPACE(SYM,AS) \
76 do { \
77 SYMBOL_REF_FLAGS (sym) &= ~AVR_SYMBOL_FLAG_PROGMEM; \
78 SYMBOL_REF_FLAGS (sym) |= (AS) * SYMBOL_FLAG_MACH_DEP; \
79 } while (0)
80
81 /* Read address-space from SYMBOL_REF_FLAGS of SYM */
82 #define AVR_SYMBOL_GET_ADDR_SPACE(SYM) \
83 ((SYMBOL_REF_FLAGS (sym) & AVR_SYMBOL_FLAG_PROGMEM) \
84 / SYMBOL_FLAG_MACH_DEP)
85
86 #define TINY_ADIW(REG1, REG2, I) \
87 "subi " #REG1 ",lo8(-(" #I "))" CR_TAB \
88 "sbci " #REG2 ",hi8(-(" #I "))"
89
90 #define TINY_SBIW(REG1, REG2, I) \
91 "subi " #REG1 ",lo8((" #I "))" CR_TAB \
92 "sbci " #REG2 ",hi8((" #I "))"
93
94 #define AVR_TMP_REGNO (AVR_TINY ? TMP_REGNO_TINY : TMP_REGNO)
95 #define AVR_ZERO_REGNO (AVR_TINY ? ZERO_REGNO_TINY : ZERO_REGNO)
96
97 /* Known address spaces. The order must be the same as in the respective
98 enum from avr.h (or designated initialized must be used). */
99 const avr_addrspace_t avr_addrspace[ADDR_SPACE_COUNT] =
100 {
101 { ADDR_SPACE_RAM, 0, 2, "", 0, NULL },
102 { ADDR_SPACE_FLASH, 1, 2, "__flash", 0, ".progmem.data" },
103 { ADDR_SPACE_FLASH1, 1, 2, "__flash1", 1, ".progmem1.data" },
104 { ADDR_SPACE_FLASH2, 1, 2, "__flash2", 2, ".progmem2.data" },
105 { ADDR_SPACE_FLASH3, 1, 2, "__flash3", 3, ".progmem3.data" },
106 { ADDR_SPACE_FLASH4, 1, 2, "__flash4", 4, ".progmem4.data" },
107 { ADDR_SPACE_FLASH5, 1, 2, "__flash5", 5, ".progmem5.data" },
108 { ADDR_SPACE_MEMX, 1, 3, "__memx", 0, ".progmemx.data" },
109 };
110
111
112 /* Holding RAM addresses of some SFRs used by the compiler and that
113 are unique over all devices in an architecture like 'avr4'. */
114
115 typedef struct
116 {
117 /* SREG: The processor status */
118 int sreg;
119
120 /* RAMPX, RAMPY, RAMPD and CCP of XMEGA */
121 int ccp;
122 int rampd;
123 int rampx;
124 int rampy;
125
126 /* RAMPZ: The high byte of 24-bit address used with ELPM */
127 int rampz;
128
129 /* SP: The stack pointer and its low and high byte */
130 int sp_l;
131 int sp_h;
132 } avr_addr_t;
133
134 static avr_addr_t avr_addr;
135
136
137 /* Prototypes for local helper functions. */
138
139 static const char* out_movqi_r_mr (rtx_insn *, rtx[], int*);
140 static const char* out_movhi_r_mr (rtx_insn *, rtx[], int*);
141 static const char* out_movsi_r_mr (rtx_insn *, rtx[], int*);
142 static const char* out_movqi_mr_r (rtx_insn *, rtx[], int*);
143 static const char* out_movhi_mr_r (rtx_insn *, rtx[], int*);
144 static const char* out_movsi_mr_r (rtx_insn *, rtx[], int*);
145
146 static int get_sequence_length (rtx_insn *insns);
147 static int sequent_regs_live (void);
148 static const char *ptrreg_to_str (int);
149 static const char *cond_string (enum rtx_code);
150 static int avr_num_arg_regs (machine_mode, const_tree);
151 static int avr_operand_rtx_cost (rtx, machine_mode, enum rtx_code,
152 int, bool);
153 static void output_reload_in_const (rtx*, rtx, int*, bool);
154 static struct machine_function * avr_init_machine_status (void);
155
156
157 /* Prototypes for hook implementors if needed before their implementation. */
158
159 static bool avr_rtx_costs (rtx, machine_mode, int, int, int*, bool);
160
161
162 /* Allocate registers from r25 to r8 for parameters for function calls. */
163 #define FIRST_CUM_REG 26
164
165 /* Last call saved register */
166 #define LAST_CALLEE_SAVED_REG (AVR_TINY ? 19 : 17)
167
168 /* Implicit target register of LPM instruction (R0) */
169 extern GTY(()) rtx lpm_reg_rtx;
170 rtx lpm_reg_rtx;
171
172 /* (Implicit) address register of LPM instruction (R31:R30 = Z) */
173 extern GTY(()) rtx lpm_addr_reg_rtx;
174 rtx lpm_addr_reg_rtx;
175
176 /* Temporary register RTX (reg:QI TMP_REGNO) */
177 extern GTY(()) rtx tmp_reg_rtx;
178 rtx tmp_reg_rtx;
179
180 /* Zeroed register RTX (reg:QI ZERO_REGNO) */
181 extern GTY(()) rtx zero_reg_rtx;
182 rtx zero_reg_rtx;
183
184 /* RTXs for all general purpose registers as QImode */
185 extern GTY(()) rtx all_regs_rtx[32];
186 rtx all_regs_rtx[32];
187
188 /* SREG, the processor status */
189 extern GTY(()) rtx sreg_rtx;
190 rtx sreg_rtx;
191
192 /* RAMP* special function registers */
193 extern GTY(()) rtx rampd_rtx;
194 extern GTY(()) rtx rampx_rtx;
195 extern GTY(()) rtx rampy_rtx;
196 extern GTY(()) rtx rampz_rtx;
197 rtx rampd_rtx;
198 rtx rampx_rtx;
199 rtx rampy_rtx;
200 rtx rampz_rtx;
201
202 /* RTX containing the strings "" and "e", respectively */
203 static GTY(()) rtx xstring_empty;
204 static GTY(()) rtx xstring_e;
205
206 /* Current architecture. */
207 const avr_arch_t *avr_arch;
208
209 /* Unnamed sections associated to __attribute__((progmem)) aka. PROGMEM
210 or to address space __flash* or __memx. Only used as singletons inside
211 avr_asm_select_section, but it must not be local there because of GTY. */
212 static GTY(()) section *progmem_section[ADDR_SPACE_COUNT];
213
214 /* Condition for insns/expanders from avr-dimode.md. */
215 bool avr_have_dimode = true;
216
217 /* To track if code will use .bss and/or .data. */
218 bool avr_need_clear_bss_p = false;
219 bool avr_need_copy_data_p = false;
220
221
222 /* Transform UP into lowercase and write the result to LO.
223 You must provide enough space for LO. Return LO. */
224
225 static char*
avr_tolower(char * lo,const char * up)226 avr_tolower (char *lo, const char *up)
227 {
228 char *lo0 = lo;
229
230 for (; *up; up++, lo++)
231 *lo = TOLOWER (*up);
232
233 *lo = '\0';
234
235 return lo0;
236 }
237
238
239 /* Custom function to count number of set bits. */
240
241 static inline int
avr_popcount(unsigned int val)242 avr_popcount (unsigned int val)
243 {
244 int pop = 0;
245
246 while (val)
247 {
248 val &= val-1;
249 pop++;
250 }
251
252 return pop;
253 }
254
255
256 /* Constraint helper function. XVAL is a CONST_INT or a CONST_DOUBLE.
257 Return true if the least significant N_BYTES bytes of XVAL all have a
258 popcount in POP_MASK and false, otherwise. POP_MASK represents a subset
259 of integers which contains an integer N iff bit N of POP_MASK is set. */
260
261 bool
avr_popcount_each_byte(rtx xval,int n_bytes,int pop_mask)262 avr_popcount_each_byte (rtx xval, int n_bytes, int pop_mask)
263 {
264 int i;
265
266 machine_mode mode = GET_MODE (xval);
267
268 if (VOIDmode == mode)
269 mode = SImode;
270
271 for (i = 0; i < n_bytes; i++)
272 {
273 rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
274 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
275
276 if (0 == (pop_mask & (1 << avr_popcount (val8))))
277 return false;
278 }
279
280 return true;
281 }
282
283
284 /* Access some RTX as INT_MODE. If X is a CONST_FIXED we can get
285 the bit representation of X by "casting" it to CONST_INT. */
286
287 rtx
avr_to_int_mode(rtx x)288 avr_to_int_mode (rtx x)
289 {
290 machine_mode mode = GET_MODE (x);
291
292 return VOIDmode == mode
293 ? x
294 : simplify_gen_subreg (int_mode_for_mode (mode), x, mode, 0);
295 }
296
297
298 static const pass_data avr_pass_data_recompute_notes =
299 {
300 RTL_PASS, // type
301 "", // name (will be patched)
302 OPTGROUP_NONE, // optinfo_flags
303 TV_DF_SCAN, // tv_id
304 0, // properties_required
305 0, // properties_provided
306 0, // properties_destroyed
307 0, // todo_flags_start
308 TODO_df_finish | TODO_df_verify // todo_flags_finish
309 };
310
311
312 class avr_pass_recompute_notes : public rtl_opt_pass
313 {
314 public:
avr_pass_recompute_notes(gcc::context * ctxt,const char * name)315 avr_pass_recompute_notes (gcc::context *ctxt, const char *name)
316 : rtl_opt_pass (avr_pass_data_recompute_notes, ctxt)
317 {
318 this->name = name;
319 }
320
execute(function *)321 virtual unsigned int execute (function*)
322 {
323 df_note_add_problem ();
324 df_analyze ();
325
326 return 0;
327 }
328 }; // avr_pass_recompute_notes
329
330
331 static void
avr_register_passes(void)332 avr_register_passes (void)
333 {
334 /* This avr-specific pass (re)computes insn notes, in particular REG_DEAD
335 notes which are used by `avr.c::reg_unused_after' and branch offset
336 computations. These notes must be correct, i.e. there must be no
337 dangling REG_DEAD notes; otherwise wrong code might result, cf. PR64331.
338
339 DF needs (correct) CFG, hence right before free_cfg is the last
340 opportunity to rectify notes. */
341
342 register_pass (new avr_pass_recompute_notes (g, "avr-notes-free-cfg"),
343 PASS_POS_INSERT_BEFORE, "*free_cfg", 1);
344 }
345
346
347 /* Set `avr_arch' as specified by `-mmcu='.
348 Return true on success. */
349
350 static bool
avr_set_core_architecture(void)351 avr_set_core_architecture (void)
352 {
353 /* Search for mcu core architecture. */
354
355 if (!avr_mmcu)
356 avr_mmcu = AVR_MMCU_DEFAULT;
357
358 avr_arch = &avr_arch_types[0];
359
360 for (const avr_mcu_t *mcu = avr_mcu_types; ; mcu++)
361 {
362 if (NULL == mcu->name)
363 {
364 /* Reached the end of `avr_mcu_types'. This should actually never
365 happen as options are provided by device-specs. It could be a
366 typo in a device-specs or calling the compiler proper directly
367 with -mmcu=<device>. */
368
369 error ("unknown core architecture %qs specified with %qs",
370 avr_mmcu, "-mmcu=");
371 avr_inform_core_architectures ();
372 break;
373 }
374 else if (0 == strcmp (mcu->name, avr_mmcu)
375 // Is this a proper architecture ?
376 && NULL == mcu->macro)
377 {
378 avr_arch = &avr_arch_types[mcu->arch_id];
379 if (avr_n_flash < 0)
380 avr_n_flash = mcu->n_flash;
381
382 return true;
383 }
384 }
385
386 return false;
387 }
388
389
390 /* Implement `TARGET_OPTION_OVERRIDE'. */
391
392 static void
avr_option_override(void)393 avr_option_override (void)
394 {
395 /* Disable -fdelete-null-pointer-checks option for AVR target.
396 This option compiler assumes that dereferencing of a null pointer
397 would halt the program. For AVR this assumption is not true and
398 programs can safely dereference null pointers. Changes made by this
399 option may not work properly for AVR. So disable this option. */
400
401 flag_delete_null_pointer_checks = 0;
402
403 /* caller-save.c looks for call-clobbered hard registers that are assigned
404 to pseudos that cross calls and tries so save-restore them around calls
405 in order to reduce the number of stack slots needed.
406
407 This might lead to situations where reload is no more able to cope
408 with the challenge of AVR's very few address registers and fails to
409 perform the requested spills. */
410
411 if (avr_strict_X)
412 flag_caller_saves = 0;
413
414 /* Allow optimizer to introduce store data races. This used to be the
415 default - it was changed because bigger targets did not see any
416 performance decrease. For the AVR though, disallowing data races
417 introduces additional code in LIM and increases reg pressure. */
418
419 maybe_set_param_value (PARAM_ALLOW_STORE_DATA_RACES, 1,
420 global_options.x_param_values,
421 global_options_set.x_param_values);
422
423 /* Unwind tables currently require a frame pointer for correctness,
424 see toplev.c:process_options(). */
425
426 if ((flag_unwind_tables
427 || flag_non_call_exceptions
428 || flag_asynchronous_unwind_tables)
429 && !ACCUMULATE_OUTGOING_ARGS)
430 {
431 flag_omit_frame_pointer = 0;
432 }
433
434 if (flag_pic == 1)
435 warning (OPT_fpic, "-fpic is not supported");
436 if (flag_pic == 2)
437 warning (OPT_fPIC, "-fPIC is not supported");
438 if (flag_pie == 1)
439 warning (OPT_fpie, "-fpie is not supported");
440 if (flag_pie == 2)
441 warning (OPT_fPIE, "-fPIE is not supported");
442
443 if (!avr_set_core_architecture())
444 return;
445
446 /* RAM addresses of some SFRs common to all devices in respective arch. */
447
448 /* SREG: Status Register containing flags like I (global IRQ) */
449 avr_addr.sreg = 0x3F + avr_arch->sfr_offset;
450
451 /* RAMPZ: Address' high part when loading via ELPM */
452 avr_addr.rampz = 0x3B + avr_arch->sfr_offset;
453
454 avr_addr.rampy = 0x3A + avr_arch->sfr_offset;
455 avr_addr.rampx = 0x39 + avr_arch->sfr_offset;
456 avr_addr.rampd = 0x38 + avr_arch->sfr_offset;
457 avr_addr.ccp = (AVR_TINY ? 0x3C : 0x34) + avr_arch->sfr_offset;
458
459 /* SP: Stack Pointer (SP_H:SP_L) */
460 avr_addr.sp_l = 0x3D + avr_arch->sfr_offset;
461 avr_addr.sp_h = avr_addr.sp_l + 1;
462
463 init_machine_status = avr_init_machine_status;
464
465 avr_log_set_avr_log();
466
467 /* Register some avr-specific pass(es). There is no canonical place for
468 pass registration. This function is convenient. */
469
470 avr_register_passes ();
471 }
472
473 /* Function to set up the backend function structure. */
474
475 static struct machine_function *
avr_init_machine_status(void)476 avr_init_machine_status (void)
477 {
478 return ggc_cleared_alloc<machine_function> ();
479 }
480
481
482 /* Implement `INIT_EXPANDERS'. */
483 /* The function works like a singleton. */
484
485 void
avr_init_expanders(void)486 avr_init_expanders (void)
487 {
488 int regno;
489
490 for (regno = 0; regno < 32; regno ++)
491 all_regs_rtx[regno] = gen_rtx_REG (QImode, regno);
492
493 lpm_reg_rtx = all_regs_rtx[LPM_REGNO];
494 tmp_reg_rtx = all_regs_rtx[AVR_TMP_REGNO];
495 zero_reg_rtx = all_regs_rtx[AVR_ZERO_REGNO];
496
497 lpm_addr_reg_rtx = gen_rtx_REG (HImode, REG_Z);
498
499 sreg_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.sreg));
500 rampd_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampd));
501 rampx_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampx));
502 rampy_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampy));
503 rampz_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampz));
504
505 xstring_empty = gen_rtx_CONST_STRING (VOIDmode, "");
506 xstring_e = gen_rtx_CONST_STRING (VOIDmode, "e");
507
508 /* TINY core does not have regs r10-r16, but avr-dimode.md expects them
509 to be present */
510 if (AVR_TINY)
511 avr_have_dimode = false;
512 }
513
514
515 /* Implement `REGNO_REG_CLASS'. */
516 /* Return register class for register R. */
517
518 enum reg_class
avr_regno_reg_class(int r)519 avr_regno_reg_class (int r)
520 {
521 static const enum reg_class reg_class_tab[] =
522 {
523 R0_REG,
524 /* r1 - r15 */
525 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
526 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
527 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
528 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
529 /* r16 - r23 */
530 SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
531 SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
532 /* r24, r25 */
533 ADDW_REGS, ADDW_REGS,
534 /* X: r26, 27 */
535 POINTER_X_REGS, POINTER_X_REGS,
536 /* Y: r28, r29 */
537 POINTER_Y_REGS, POINTER_Y_REGS,
538 /* Z: r30, r31 */
539 POINTER_Z_REGS, POINTER_Z_REGS,
540 /* SP: SPL, SPH */
541 STACK_REG, STACK_REG
542 };
543
544 if (r <= 33)
545 return reg_class_tab[r];
546
547 return ALL_REGS;
548 }
549
550
551 /* Implement `TARGET_SCALAR_MODE_SUPPORTED_P'. */
552
553 static bool
avr_scalar_mode_supported_p(machine_mode mode)554 avr_scalar_mode_supported_p (machine_mode mode)
555 {
556 if (ALL_FIXED_POINT_MODE_P (mode))
557 return true;
558
559 if (PSImode == mode)
560 return true;
561
562 return default_scalar_mode_supported_p (mode);
563 }
564
565
566 /* Return TRUE if DECL is a VAR_DECL located in flash and FALSE, otherwise. */
567
568 static bool
avr_decl_flash_p(tree decl)569 avr_decl_flash_p (tree decl)
570 {
571 if (TREE_CODE (decl) != VAR_DECL
572 || TREE_TYPE (decl) == error_mark_node)
573 {
574 return false;
575 }
576
577 return !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (decl)));
578 }
579
580
581 /* Return TRUE if DECL is a VAR_DECL located in the 24-bit flash
582 address space and FALSE, otherwise. */
583
584 static bool
avr_decl_memx_p(tree decl)585 avr_decl_memx_p (tree decl)
586 {
587 if (TREE_CODE (decl) != VAR_DECL
588 || TREE_TYPE (decl) == error_mark_node)
589 {
590 return false;
591 }
592
593 return (ADDR_SPACE_MEMX == TYPE_ADDR_SPACE (TREE_TYPE (decl)));
594 }
595
596
597 /* Return TRUE if X is a MEM rtx located in flash and FALSE, otherwise. */
598
599 bool
avr_mem_flash_p(rtx x)600 avr_mem_flash_p (rtx x)
601 {
602 return (MEM_P (x)
603 && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x)));
604 }
605
606
607 /* Return TRUE if X is a MEM rtx located in the 24-bit flash
608 address space and FALSE, otherwise. */
609
610 bool
avr_mem_memx_p(rtx x)611 avr_mem_memx_p (rtx x)
612 {
613 return (MEM_P (x)
614 && ADDR_SPACE_MEMX == MEM_ADDR_SPACE (x));
615 }
616
617
618 /* A helper for the subsequent function attribute used to dig for
619 attribute 'name' in a FUNCTION_DECL or FUNCTION_TYPE */
620
621 static inline int
avr_lookup_function_attribute1(const_tree func,const char * name)622 avr_lookup_function_attribute1 (const_tree func, const char *name)
623 {
624 if (FUNCTION_DECL == TREE_CODE (func))
625 {
626 if (NULL_TREE != lookup_attribute (name, DECL_ATTRIBUTES (func)))
627 {
628 return true;
629 }
630
631 func = TREE_TYPE (func);
632 }
633
634 gcc_assert (TREE_CODE (func) == FUNCTION_TYPE
635 || TREE_CODE (func) == METHOD_TYPE);
636
637 return NULL_TREE != lookup_attribute (name, TYPE_ATTRIBUTES (func));
638 }
639
640 /* Return nonzero if FUNC is a naked function. */
641
642 static int
avr_naked_function_p(tree func)643 avr_naked_function_p (tree func)
644 {
645 return avr_lookup_function_attribute1 (func, "naked");
646 }
647
648 /* Return nonzero if FUNC is an interrupt function as specified
649 by the "interrupt" attribute. */
650
651 static int
avr_interrupt_function_p(tree func)652 avr_interrupt_function_p (tree func)
653 {
654 return avr_lookup_function_attribute1 (func, "interrupt");
655 }
656
657 /* Return nonzero if FUNC is a signal function as specified
658 by the "signal" attribute. */
659
660 static int
avr_signal_function_p(tree func)661 avr_signal_function_p (tree func)
662 {
663 return avr_lookup_function_attribute1 (func, "signal");
664 }
665
666 /* Return nonzero if FUNC is an OS_task function. */
667
668 static int
avr_OS_task_function_p(tree func)669 avr_OS_task_function_p (tree func)
670 {
671 return avr_lookup_function_attribute1 (func, "OS_task");
672 }
673
674 /* Return nonzero if FUNC is an OS_main function. */
675
676 static int
avr_OS_main_function_p(tree func)677 avr_OS_main_function_p (tree func)
678 {
679 return avr_lookup_function_attribute1 (func, "OS_main");
680 }
681
682
683 /* Implement `TARGET_SET_CURRENT_FUNCTION'. */
684 /* Sanity cheching for above function attributes. */
685
686 static void
avr_set_current_function(tree decl)687 avr_set_current_function (tree decl)
688 {
689 location_t loc;
690 const char *isr;
691
692 if (decl == NULL_TREE
693 || current_function_decl == NULL_TREE
694 || current_function_decl == error_mark_node
695 || ! cfun->machine
696 || cfun->machine->attributes_checked_p)
697 return;
698
699 loc = DECL_SOURCE_LOCATION (decl);
700
701 cfun->machine->is_naked = avr_naked_function_p (decl);
702 cfun->machine->is_signal = avr_signal_function_p (decl);
703 cfun->machine->is_interrupt = avr_interrupt_function_p (decl);
704 cfun->machine->is_OS_task = avr_OS_task_function_p (decl);
705 cfun->machine->is_OS_main = avr_OS_main_function_p (decl);
706
707 isr = cfun->machine->is_interrupt ? "interrupt" : "signal";
708
709 /* Too much attributes make no sense as they request conflicting features. */
710
711 if (cfun->machine->is_OS_task + cfun->machine->is_OS_main
712 + (cfun->machine->is_signal || cfun->machine->is_interrupt) > 1)
713 error_at (loc, "function attributes %qs, %qs and %qs are mutually"
714 " exclusive", "OS_task", "OS_main", isr);
715
716 /* 'naked' will hide effects of 'OS_task' and 'OS_main'. */
717
718 if (cfun->machine->is_naked
719 && (cfun->machine->is_OS_task || cfun->machine->is_OS_main))
720 warning_at (loc, OPT_Wattributes, "function attributes %qs and %qs have"
721 " no effect on %qs function", "OS_task", "OS_main", "naked");
722
723 if (cfun->machine->is_interrupt || cfun->machine->is_signal)
724 {
725 tree args = TYPE_ARG_TYPES (TREE_TYPE (decl));
726 tree ret = TREE_TYPE (TREE_TYPE (decl));
727 const char *name;
728
729 name = DECL_ASSEMBLER_NAME_SET_P (decl)
730 ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))
731 : IDENTIFIER_POINTER (DECL_NAME (decl));
732
733 /* Skip a leading '*' that might still prefix the assembler name,
734 e.g. in non-LTO runs. */
735
736 name = default_strip_name_encoding (name);
737
738 /* Interrupt handlers must be void __vector (void) functions. */
739
740 if (args && TREE_CODE (TREE_VALUE (args)) != VOID_TYPE)
741 error_at (loc, "%qs function cannot have arguments", isr);
742
743 if (TREE_CODE (ret) != VOID_TYPE)
744 error_at (loc, "%qs function cannot return a value", isr);
745
746 #if defined WITH_AVRLIBC
747 /* Silently ignore 'signal' if 'interrupt' is present. AVR-LibC startet
748 using this when it switched from SIGNAL and INTERRUPT to ISR. */
749
750 if (cfun->machine->is_interrupt)
751 cfun->machine->is_signal = 0;
752
753 /* If the function has the 'signal' or 'interrupt' attribute, ensure
754 that the name of the function is "__vector_NN" so as to catch
755 when the user misspells the vector name. */
756
757 if (!STR_PREFIX_P (name, "__vector"))
758 warning_at (loc, OPT_Wmisspelled_isr, "%qs appears to be a misspelled "
759 "%qs handler, missing %<__vector%> prefix", name, isr);
760 #endif // AVR-LibC naming conventions
761 }
762
763 #if defined WITH_AVRLIBC
764 // Common problem is using "ISR" without first including avr/interrupt.h.
765 const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
766 name = default_strip_name_encoding (name);
767 if (0 == strcmp ("ISR", name)
768 || 0 == strcmp ("INTERRUPT", name)
769 || 0 == strcmp ("SIGNAL", name))
770 {
771 warning_at (loc, OPT_Wmisspelled_isr, "%qs is a reserved identifier"
772 " in AVR-LibC. Consider %<#include <avr/interrupt.h>%>"
773 " before using the %qs macro", name, name);
774 }
775 #endif // AVR-LibC naming conventions
776
777 /* Don't print the above diagnostics more than once. */
778
779 cfun->machine->attributes_checked_p = 1;
780 }
781
782
783 /* Implement `ACCUMULATE_OUTGOING_ARGS'. */
784
785 int
avr_accumulate_outgoing_args(void)786 avr_accumulate_outgoing_args (void)
787 {
788 if (!cfun)
789 return TARGET_ACCUMULATE_OUTGOING_ARGS;
790
791 /* FIXME: For setjmp and in avr_builtin_setjmp_frame_value we don't know
792 what offset is correct. In some cases it is relative to
793 virtual_outgoing_args_rtx and in others it is relative to
794 virtual_stack_vars_rtx. For example code see
795 gcc.c-torture/execute/built-in-setjmp.c
796 gcc.c-torture/execute/builtins/sprintf-chk.c */
797
798 return (TARGET_ACCUMULATE_OUTGOING_ARGS
799 && !(cfun->calls_setjmp
800 || cfun->has_nonlocal_label));
801 }
802
803
804 /* Report contribution of accumulated outgoing arguments to stack size. */
805
806 static inline int
avr_outgoing_args_size(void)807 avr_outgoing_args_size (void)
808 {
809 return ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0;
810 }
811
812
813 /* Implement `STARTING_FRAME_OFFSET'. */
814 /* This is the offset from the frame pointer register to the first stack slot
815 that contains a variable living in the frame. */
816
817 int
avr_starting_frame_offset(void)818 avr_starting_frame_offset (void)
819 {
820 return 1 + avr_outgoing_args_size ();
821 }
822
823
824 /* Return the number of hard registers to push/pop in the prologue/epilogue
825 of the current function, and optionally store these registers in SET. */
826
827 static int
avr_regs_to_save(HARD_REG_SET * set)828 avr_regs_to_save (HARD_REG_SET *set)
829 {
830 int reg, count;
831 int int_or_sig_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
832
833 if (set)
834 CLEAR_HARD_REG_SET (*set);
835 count = 0;
836
837 /* No need to save any registers if the function never returns or
838 has the "OS_task" or "OS_main" attribute. */
839
840 if (TREE_THIS_VOLATILE (current_function_decl)
841 || cfun->machine->is_OS_task
842 || cfun->machine->is_OS_main)
843 return 0;
844
845 for (reg = 0; reg < 32; reg++)
846 {
847 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
848 any global register variables. */
849
850 if (fixed_regs[reg])
851 continue;
852
853 if ((int_or_sig_p && !crtl->is_leaf && call_used_regs[reg])
854 || (df_regs_ever_live_p (reg)
855 && (int_or_sig_p || !call_used_regs[reg])
856 /* Don't record frame pointer registers here. They are treated
857 indivitually in prologue. */
858 && !(frame_pointer_needed
859 && (reg == REG_Y || reg == (REG_Y+1)))))
860 {
861 if (set)
862 SET_HARD_REG_BIT (*set, reg);
863 count++;
864 }
865 }
866 return count;
867 }
868
869
870 /* Implement `TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS' */
871
872 static bool
avr_allocate_stack_slots_for_args(void)873 avr_allocate_stack_slots_for_args (void)
874 {
875 return !cfun->machine->is_naked;
876 }
877
878
879 /* Return true if register FROM can be eliminated via register TO. */
880
881 static bool
avr_can_eliminate(const int from ATTRIBUTE_UNUSED,const int to)882 avr_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
883 {
884 return ((frame_pointer_needed && to == FRAME_POINTER_REGNUM)
885 || !frame_pointer_needed);
886 }
887
888
889 /* Implement `TARGET_WARN_FUNC_RETURN'. */
890
891 static bool
avr_warn_func_return(tree decl)892 avr_warn_func_return (tree decl)
893 {
894 /* Naked functions are implemented entirely in assembly, including the
895 return sequence, so suppress warnings about this. */
896
897 return !avr_naked_function_p (decl);
898 }
899
900 /* Compute offset between arg_pointer and frame_pointer. */
901
902 int
avr_initial_elimination_offset(int from,int to)903 avr_initial_elimination_offset (int from, int to)
904 {
905 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
906 return 0;
907 else
908 {
909 int offset = frame_pointer_needed ? 2 : 0;
910 int avr_pc_size = AVR_HAVE_EIJMP_EICALL ? 3 : 2;
911
912 offset += avr_regs_to_save (NULL);
913 return (get_frame_size () + avr_outgoing_args_size()
914 + avr_pc_size + 1 + offset);
915 }
916 }
917
918
919 /* Helper for the function below. */
920
921 static void
avr_adjust_type_node(tree * node,machine_mode mode,int sat_p)922 avr_adjust_type_node (tree *node, machine_mode mode, int sat_p)
923 {
924 *node = make_node (FIXED_POINT_TYPE);
925 TYPE_SATURATING (*node) = sat_p;
926 TYPE_UNSIGNED (*node) = UNSIGNED_FIXED_POINT_MODE_P (mode);
927 TYPE_IBIT (*node) = GET_MODE_IBIT (mode);
928 TYPE_FBIT (*node) = GET_MODE_FBIT (mode);
929 TYPE_PRECISION (*node) = GET_MODE_BITSIZE (mode);
930 TYPE_ALIGN (*node) = 8;
931 SET_TYPE_MODE (*node, mode);
932
933 layout_type (*node);
934 }
935
936
937 /* Implement `TARGET_BUILD_BUILTIN_VA_LIST'. */
938
939 static tree
avr_build_builtin_va_list(void)940 avr_build_builtin_va_list (void)
941 {
942 /* avr-modes.def adjusts [U]TA to be 64-bit modes with 48 fractional bits.
943 This is more appropriate for the 8-bit machine AVR than 128-bit modes.
944 The ADJUST_IBIT/FBIT are handled in toplev:init_adjust_machine_modes()
945 which is auto-generated by genmodes, but the compiler assigns [U]DAmode
946 to the long long accum modes instead of the desired [U]TAmode.
947
948 Fix this now, right after node setup in tree.c:build_common_tree_nodes().
949 This must run before c-cppbuiltin.c:builtin_define_fixed_point_constants()
950 which built-in defines macros like __ULLACCUM_FBIT__ that are used by
951 libgcc to detect IBIT and FBIT. */
952
953 avr_adjust_type_node (&ta_type_node, TAmode, 0);
954 avr_adjust_type_node (&uta_type_node, UTAmode, 0);
955 avr_adjust_type_node (&sat_ta_type_node, TAmode, 1);
956 avr_adjust_type_node (&sat_uta_type_node, UTAmode, 1);
957
958 unsigned_long_long_accum_type_node = uta_type_node;
959 long_long_accum_type_node = ta_type_node;
960 sat_unsigned_long_long_accum_type_node = sat_uta_type_node;
961 sat_long_long_accum_type_node = sat_ta_type_node;
962
963 /* Dispatch to the default handler. */
964
965 return std_build_builtin_va_list ();
966 }
967
968
969 /* Implement `TARGET_BUILTIN_SETJMP_FRAME_VALUE'. */
970 /* Actual start of frame is virtual_stack_vars_rtx this is offset from
971 frame pointer by +STARTING_FRAME_OFFSET.
972 Using saved frame = virtual_stack_vars_rtx - STARTING_FRAME_OFFSET
973 avoids creating add/sub of offset in nonlocal goto and setjmp. */
974
975 static rtx
avr_builtin_setjmp_frame_value(void)976 avr_builtin_setjmp_frame_value (void)
977 {
978 rtx xval = gen_reg_rtx (Pmode);
979 emit_insn (gen_subhi3 (xval, virtual_stack_vars_rtx,
980 gen_int_mode (STARTING_FRAME_OFFSET, Pmode)));
981 return xval;
982 }
983
984
985 /* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3-byte PC).
986 This is return address of function. */
987
988 rtx
avr_return_addr_rtx(int count,rtx tem)989 avr_return_addr_rtx (int count, rtx tem)
990 {
991 rtx r;
992
993 /* Can only return this function's return address. Others not supported. */
994 if (count)
995 return NULL;
996
997 if (AVR_3_BYTE_PC)
998 {
999 r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+2");
1000 warning (0, "%<builtin_return_address%> contains only 2 bytes"
1001 " of address");
1002 }
1003 else
1004 r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+1");
1005
1006 r = gen_rtx_PLUS (Pmode, tem, r);
1007 r = gen_frame_mem (Pmode, memory_address (Pmode, r));
1008 r = gen_rtx_ROTATE (HImode, r, GEN_INT (8));
1009 return r;
1010 }
1011
1012 /* Return 1 if the function epilogue is just a single "ret". */
1013
1014 int
avr_simple_epilogue(void)1015 avr_simple_epilogue (void)
1016 {
1017 return (! frame_pointer_needed
1018 && get_frame_size () == 0
1019 && avr_outgoing_args_size() == 0
1020 && avr_regs_to_save (NULL) == 0
1021 && ! cfun->machine->is_interrupt
1022 && ! cfun->machine->is_signal
1023 && ! cfun->machine->is_naked
1024 && ! TREE_THIS_VOLATILE (current_function_decl));
1025 }
1026
1027 /* This function checks sequence of live registers. */
1028
1029 static int
sequent_regs_live(void)1030 sequent_regs_live (void)
1031 {
1032 int reg;
1033 int live_seq = 0;
1034 int cur_seq = 0;
1035
1036 for (reg = 0; reg <= LAST_CALLEE_SAVED_REG; ++reg)
1037 {
1038 if (fixed_regs[reg])
1039 {
1040 /* Don't recognize sequences that contain global register
1041 variables. */
1042
1043 if (live_seq != 0)
1044 return 0;
1045 else
1046 continue;
1047 }
1048
1049 if (!call_used_regs[reg])
1050 {
1051 if (df_regs_ever_live_p (reg))
1052 {
1053 ++live_seq;
1054 ++cur_seq;
1055 }
1056 else
1057 cur_seq = 0;
1058 }
1059 }
1060
1061 if (!frame_pointer_needed)
1062 {
1063 if (df_regs_ever_live_p (REG_Y))
1064 {
1065 ++live_seq;
1066 ++cur_seq;
1067 }
1068 else
1069 cur_seq = 0;
1070
1071 if (df_regs_ever_live_p (REG_Y+1))
1072 {
1073 ++live_seq;
1074 ++cur_seq;
1075 }
1076 else
1077 cur_seq = 0;
1078 }
1079 else
1080 {
1081 cur_seq += 2;
1082 live_seq += 2;
1083 }
1084 return (cur_seq == live_seq) ? live_seq : 0;
1085 }
1086
1087 /* Obtain the length sequence of insns. */
1088
1089 int
get_sequence_length(rtx_insn * insns)1090 get_sequence_length (rtx_insn *insns)
1091 {
1092 rtx_insn *insn;
1093 int length;
1094
1095 for (insn = insns, length = 0; insn; insn = NEXT_INSN (insn))
1096 length += get_attr_length (insn);
1097
1098 return length;
1099 }
1100
1101
1102 /* Implement `INCOMING_RETURN_ADDR_RTX'. */
1103
1104 rtx
avr_incoming_return_addr_rtx(void)1105 avr_incoming_return_addr_rtx (void)
1106 {
1107 /* The return address is at the top of the stack. Note that the push
1108 was via post-decrement, which means the actual address is off by one. */
1109 return gen_frame_mem (HImode, plus_constant (Pmode, stack_pointer_rtx, 1));
1110 }
1111
1112 /* Helper for expand_prologue. Emit a push of a byte register. */
1113
1114 static void
emit_push_byte(unsigned regno,bool frame_related_p)1115 emit_push_byte (unsigned regno, bool frame_related_p)
1116 {
1117 rtx mem, reg;
1118 rtx_insn *insn;
1119
1120 mem = gen_rtx_POST_DEC (HImode, stack_pointer_rtx);
1121 mem = gen_frame_mem (QImode, mem);
1122 reg = gen_rtx_REG (QImode, regno);
1123
1124 insn = emit_insn (gen_rtx_SET (mem, reg));
1125 if (frame_related_p)
1126 RTX_FRAME_RELATED_P (insn) = 1;
1127
1128 cfun->machine->stack_usage++;
1129 }
1130
1131
1132 /* Helper for expand_prologue. Emit a push of a SFR via tmp_reg.
1133 SFR is a MEM representing the memory location of the SFR.
1134 If CLR_P then clear the SFR after the push using zero_reg. */
1135
1136 static void
emit_push_sfr(rtx sfr,bool frame_related_p,bool clr_p)1137 emit_push_sfr (rtx sfr, bool frame_related_p, bool clr_p)
1138 {
1139 rtx_insn *insn;
1140
1141 gcc_assert (MEM_P (sfr));
1142
1143 /* IN __tmp_reg__, IO(SFR) */
1144 insn = emit_move_insn (tmp_reg_rtx, sfr);
1145 if (frame_related_p)
1146 RTX_FRAME_RELATED_P (insn) = 1;
1147
1148 /* PUSH __tmp_reg__ */
1149 emit_push_byte (AVR_TMP_REGNO, frame_related_p);
1150
1151 if (clr_p)
1152 {
1153 /* OUT IO(SFR), __zero_reg__ */
1154 insn = emit_move_insn (sfr, const0_rtx);
1155 if (frame_related_p)
1156 RTX_FRAME_RELATED_P (insn) = 1;
1157 }
1158 }
1159
1160 static void
avr_prologue_setup_frame(HOST_WIDE_INT size,HARD_REG_SET set)1161 avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
1162 {
1163 rtx_insn *insn;
1164 bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1165 int live_seq = sequent_regs_live ();
1166
1167 HOST_WIDE_INT size_max
1168 = (HOST_WIDE_INT) GET_MODE_MASK (AVR_HAVE_8BIT_SP ? QImode : Pmode);
1169
1170 bool minimize = (TARGET_CALL_PROLOGUES
1171 && size < size_max
1172 && live_seq
1173 && !isr_p
1174 && !cfun->machine->is_OS_task
1175 && !cfun->machine->is_OS_main
1176 && !AVR_TINY);
1177
1178 if (minimize
1179 && (frame_pointer_needed
1180 || avr_outgoing_args_size() > 8
1181 || (AVR_2_BYTE_PC && live_seq > 6)
1182 || live_seq > 7))
1183 {
1184 rtx pattern;
1185 int first_reg, reg, offset;
1186
1187 emit_move_insn (gen_rtx_REG (HImode, REG_X),
1188 gen_int_mode (size, HImode));
1189
1190 pattern = gen_call_prologue_saves (gen_int_mode (live_seq, HImode),
1191 gen_int_mode (live_seq+size, HImode));
1192 insn = emit_insn (pattern);
1193 RTX_FRAME_RELATED_P (insn) = 1;
1194
1195 /* Describe the effect of the unspec_volatile call to prologue_saves.
1196 Note that this formulation assumes that add_reg_note pushes the
1197 notes to the front. Thus we build them in the reverse order of
1198 how we want dwarf2out to process them. */
1199
1200 /* The function does always set frame_pointer_rtx, but whether that
1201 is going to be permanent in the function is frame_pointer_needed. */
1202
1203 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1204 gen_rtx_SET ((frame_pointer_needed
1205 ? frame_pointer_rtx
1206 : stack_pointer_rtx),
1207 plus_constant (Pmode, stack_pointer_rtx,
1208 -(size + live_seq))));
1209
1210 /* Note that live_seq always contains r28+r29, but the other
1211 registers to be saved are all below 18. */
1212
1213 first_reg = (LAST_CALLEE_SAVED_REG + 1) - (live_seq - 2);
1214
1215 for (reg = 29, offset = -live_seq + 1;
1216 reg >= first_reg;
1217 reg = (reg == 28 ? LAST_CALLEE_SAVED_REG : reg - 1), ++offset)
1218 {
1219 rtx m, r;
1220
1221 m = gen_rtx_MEM (QImode, plus_constant (Pmode, stack_pointer_rtx,
1222 offset));
1223 r = gen_rtx_REG (QImode, reg);
1224 add_reg_note (insn, REG_CFA_OFFSET, gen_rtx_SET (m, r));
1225 }
1226
1227 cfun->machine->stack_usage += size + live_seq;
1228 }
1229 else /* !minimize */
1230 {
1231 int reg;
1232
1233 for (reg = 0; reg < 32; ++reg)
1234 if (TEST_HARD_REG_BIT (set, reg))
1235 emit_push_byte (reg, true);
1236
1237 if (frame_pointer_needed
1238 && (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main)))
1239 {
1240 /* Push frame pointer. Always be consistent about the
1241 ordering of pushes -- epilogue_restores expects the
1242 register pair to be pushed low byte first. */
1243
1244 emit_push_byte (REG_Y, true);
1245 emit_push_byte (REG_Y + 1, true);
1246 }
1247
1248 if (frame_pointer_needed
1249 && size == 0)
1250 {
1251 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
1252 RTX_FRAME_RELATED_P (insn) = 1;
1253 }
1254
1255 if (size != 0)
1256 {
1257 /* Creating a frame can be done by direct manipulation of the
1258 stack or via the frame pointer. These two methods are:
1259 fp = sp
1260 fp -= size
1261 sp = fp
1262 or
1263 sp -= size
1264 fp = sp (*)
1265 the optimum method depends on function type, stack and
1266 frame size. To avoid a complex logic, both methods are
1267 tested and shortest is selected.
1268
1269 There is also the case where SIZE != 0 and no frame pointer is
1270 needed; this can occur if ACCUMULATE_OUTGOING_ARGS is on.
1271 In that case, insn (*) is not needed in that case.
1272 We use the X register as scratch. This is save because in X
1273 is call-clobbered.
1274 In an interrupt routine, the case of SIZE != 0 together with
1275 !frame_pointer_needed can only occur if the function is not a
1276 leaf function and thus X has already been saved. */
1277
1278 int irq_state = -1;
1279 HOST_WIDE_INT size_cfa = size, neg_size;
1280 rtx_insn *fp_plus_insns;
1281 rtx fp, my_fp;
1282
1283 gcc_assert (frame_pointer_needed
1284 || !isr_p
1285 || !crtl->is_leaf);
1286
1287 fp = my_fp = (frame_pointer_needed
1288 ? frame_pointer_rtx
1289 : gen_rtx_REG (Pmode, REG_X));
1290
1291 if (AVR_HAVE_8BIT_SP)
1292 {
1293 /* The high byte (r29) does not change:
1294 Prefer SUBI (1 cycle) over SBIW (2 cycles, same size). */
1295
1296 my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
1297 }
1298
1299 /* Cut down size and avoid size = 0 so that we don't run
1300 into ICE like PR52488 in the remainder. */
1301
1302 if (size > size_max)
1303 {
1304 /* Don't error so that insane code from newlib still compiles
1305 and does not break building newlib. As PR51345 is implemented
1306 now, there are multilib variants with -msp8.
1307
1308 If user wants sanity checks he can use -Wstack-usage=
1309 or similar options.
1310
1311 For CFA we emit the original, non-saturated size so that
1312 the generic machinery is aware of the real stack usage and
1313 will print the above diagnostic as expected. */
1314
1315 size = size_max;
1316 }
1317
1318 size = trunc_int_for_mode (size, GET_MODE (my_fp));
1319 neg_size = trunc_int_for_mode (-size, GET_MODE (my_fp));
1320
1321 /************ Method 1: Adjust frame pointer ************/
1322
1323 start_sequence ();
1324
1325 /* Normally, the dwarf2out frame-related-expr interpreter does
1326 not expect to have the CFA change once the frame pointer is
1327 set up. Thus, we avoid marking the move insn below and
1328 instead indicate that the entire operation is complete after
1329 the frame pointer subtraction is done. */
1330
1331 insn = emit_move_insn (fp, stack_pointer_rtx);
1332 if (frame_pointer_needed)
1333 {
1334 RTX_FRAME_RELATED_P (insn) = 1;
1335 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1336 gen_rtx_SET (fp, stack_pointer_rtx));
1337 }
1338
1339 insn = emit_move_insn (my_fp, plus_constant (GET_MODE (my_fp),
1340 my_fp, neg_size));
1341
1342 if (frame_pointer_needed)
1343 {
1344 RTX_FRAME_RELATED_P (insn) = 1;
1345 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1346 gen_rtx_SET (fp, plus_constant (Pmode, fp,
1347 -size_cfa)));
1348 }
1349
1350 /* Copy to stack pointer. Note that since we've already
1351 changed the CFA to the frame pointer this operation
1352 need not be annotated if frame pointer is needed.
1353 Always move through unspec, see PR50063.
1354 For meaning of irq_state see movhi_sp_r insn. */
1355
1356 if (cfun->machine->is_interrupt)
1357 irq_state = 1;
1358
1359 if (TARGET_NO_INTERRUPTS
1360 || cfun->machine->is_signal
1361 || cfun->machine->is_OS_main)
1362 irq_state = 0;
1363
1364 if (AVR_HAVE_8BIT_SP)
1365 irq_state = 2;
1366
1367 insn = emit_insn (gen_movhi_sp_r (stack_pointer_rtx,
1368 fp, GEN_INT (irq_state)));
1369 if (!frame_pointer_needed)
1370 {
1371 RTX_FRAME_RELATED_P (insn) = 1;
1372 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1373 gen_rtx_SET (stack_pointer_rtx,
1374 plus_constant (Pmode,
1375 stack_pointer_rtx,
1376 -size_cfa)));
1377 }
1378
1379 fp_plus_insns = get_insns ();
1380 end_sequence ();
1381
1382 /************ Method 2: Adjust Stack pointer ************/
1383
1384 /* Stack adjustment by means of RCALL . and/or PUSH __TMP_REG__
1385 can only handle specific offsets. */
1386
1387 if (avr_sp_immediate_operand (gen_int_mode (-size, HImode), HImode))
1388 {
1389 rtx_insn *sp_plus_insns;
1390
1391 start_sequence ();
1392
1393 insn = emit_move_insn (stack_pointer_rtx,
1394 plus_constant (Pmode, stack_pointer_rtx,
1395 -size));
1396 RTX_FRAME_RELATED_P (insn) = 1;
1397 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1398 gen_rtx_SET (stack_pointer_rtx,
1399 plus_constant (Pmode,
1400 stack_pointer_rtx,
1401 -size_cfa)));
1402 if (frame_pointer_needed)
1403 {
1404 insn = emit_move_insn (fp, stack_pointer_rtx);
1405 RTX_FRAME_RELATED_P (insn) = 1;
1406 }
1407
1408 sp_plus_insns = get_insns ();
1409 end_sequence ();
1410
1411 /************ Use shortest method ************/
1412
1413 emit_insn (get_sequence_length (sp_plus_insns)
1414 < get_sequence_length (fp_plus_insns)
1415 ? sp_plus_insns
1416 : fp_plus_insns);
1417 }
1418 else
1419 {
1420 emit_insn (fp_plus_insns);
1421 }
1422
1423 cfun->machine->stack_usage += size_cfa;
1424 } /* !minimize && size != 0 */
1425 } /* !minimize */
1426 }
1427
1428
1429 /* Output function prologue. */
1430
1431 void
avr_expand_prologue(void)1432 avr_expand_prologue (void)
1433 {
1434 HARD_REG_SET set;
1435 HOST_WIDE_INT size;
1436
1437 size = get_frame_size() + avr_outgoing_args_size();
1438
1439 cfun->machine->stack_usage = 0;
1440
1441 /* Prologue: naked. */
1442 if (cfun->machine->is_naked)
1443 {
1444 return;
1445 }
1446
1447 avr_regs_to_save (&set);
1448
1449 if (cfun->machine->is_interrupt || cfun->machine->is_signal)
1450 {
1451 /* Enable interrupts. */
1452 if (cfun->machine->is_interrupt)
1453 emit_insn (gen_enable_interrupt ());
1454
1455 /* Push zero reg. */
1456 emit_push_byte (AVR_ZERO_REGNO, true);
1457
1458 /* Push tmp reg. */
1459 emit_push_byte (AVR_TMP_REGNO, true);
1460
1461 /* Push SREG. */
1462 /* ??? There's no dwarf2 column reserved for SREG. */
1463 emit_push_sfr (sreg_rtx, false, false /* clr */);
1464
1465 /* Clear zero reg. */
1466 emit_move_insn (zero_reg_rtx, const0_rtx);
1467
1468 /* Prevent any attempt to delete the setting of ZERO_REG! */
1469 emit_use (zero_reg_rtx);
1470
1471 /* Push and clear RAMPD/X/Y/Z if present and low-part register is used.
1472 ??? There are no dwarf2 columns reserved for RAMPD/X/Y/Z. */
1473
1474 if (AVR_HAVE_RAMPD)
1475 emit_push_sfr (rampd_rtx, false /* frame-related */, true /* clr */);
1476
1477 if (AVR_HAVE_RAMPX
1478 && TEST_HARD_REG_BIT (set, REG_X)
1479 && TEST_HARD_REG_BIT (set, REG_X + 1))
1480 {
1481 emit_push_sfr (rampx_rtx, false /* frame-related */, true /* clr */);
1482 }
1483
1484 if (AVR_HAVE_RAMPY
1485 && (frame_pointer_needed
1486 || (TEST_HARD_REG_BIT (set, REG_Y)
1487 && TEST_HARD_REG_BIT (set, REG_Y + 1))))
1488 {
1489 emit_push_sfr (rampy_rtx, false /* frame-related */, true /* clr */);
1490 }
1491
1492 if (AVR_HAVE_RAMPZ
1493 && TEST_HARD_REG_BIT (set, REG_Z)
1494 && TEST_HARD_REG_BIT (set, REG_Z + 1))
1495 {
1496 emit_push_sfr (rampz_rtx, false /* frame-related */, AVR_HAVE_RAMPD);
1497 }
1498 } /* is_interrupt is_signal */
1499
1500 avr_prologue_setup_frame (size, set);
1501
1502 if (flag_stack_usage_info)
1503 current_function_static_stack_size = cfun->machine->stack_usage;
1504 }
1505
1506
1507 /* Implement `TARGET_ASM_FUNCTION_END_PROLOGUE'. */
1508 /* Output summary at end of function prologue. */
1509
1510 static void
avr_asm_function_end_prologue(FILE * file)1511 avr_asm_function_end_prologue (FILE *file)
1512 {
1513 if (cfun->machine->is_naked)
1514 {
1515 fputs ("/* prologue: naked */\n", file);
1516 }
1517 else
1518 {
1519 if (cfun->machine->is_interrupt)
1520 {
1521 fputs ("/* prologue: Interrupt */\n", file);
1522 }
1523 else if (cfun->machine->is_signal)
1524 {
1525 fputs ("/* prologue: Signal */\n", file);
1526 }
1527 else
1528 fputs ("/* prologue: function */\n", file);
1529 }
1530
1531 if (ACCUMULATE_OUTGOING_ARGS)
1532 fprintf (file, "/* outgoing args size = %d */\n",
1533 avr_outgoing_args_size());
1534
1535 fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n",
1536 get_frame_size());
1537 fprintf (file, "/* stack size = %d */\n",
1538 cfun->machine->stack_usage);
1539 /* Create symbol stack offset here so all functions have it. Add 1 to stack
1540 usage for offset so that SP + .L__stack_offset = return address. */
1541 fprintf (file, ".L__stack_usage = %d\n", cfun->machine->stack_usage);
1542 }
1543
1544
1545 /* Implement `EPILOGUE_USES'. */
1546
1547 int
avr_epilogue_uses(int regno ATTRIBUTE_UNUSED)1548 avr_epilogue_uses (int regno ATTRIBUTE_UNUSED)
1549 {
1550 if (reload_completed
1551 && cfun->machine
1552 && (cfun->machine->is_interrupt || cfun->machine->is_signal))
1553 return 1;
1554 return 0;
1555 }
1556
1557 /* Helper for avr_expand_epilogue. Emit a pop of a byte register. */
1558
1559 static void
emit_pop_byte(unsigned regno)1560 emit_pop_byte (unsigned regno)
1561 {
1562 rtx mem, reg;
1563
1564 mem = gen_rtx_PRE_INC (HImode, stack_pointer_rtx);
1565 mem = gen_frame_mem (QImode, mem);
1566 reg = gen_rtx_REG (QImode, regno);
1567
1568 emit_insn (gen_rtx_SET (reg, mem));
1569 }
1570
1571 /* Output RTL epilogue. */
1572
1573 void
avr_expand_epilogue(bool sibcall_p)1574 avr_expand_epilogue (bool sibcall_p)
1575 {
1576 int reg;
1577 int live_seq;
1578 HARD_REG_SET set;
1579 int minimize;
1580 HOST_WIDE_INT size;
1581 bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1582
1583 size = get_frame_size() + avr_outgoing_args_size();
1584
1585 /* epilogue: naked */
1586 if (cfun->machine->is_naked)
1587 {
1588 gcc_assert (!sibcall_p);
1589
1590 emit_jump_insn (gen_return ());
1591 return;
1592 }
1593
1594 avr_regs_to_save (&set);
1595 live_seq = sequent_regs_live ();
1596
1597 minimize = (TARGET_CALL_PROLOGUES
1598 && live_seq
1599 && !isr_p
1600 && !cfun->machine->is_OS_task
1601 && !cfun->machine->is_OS_main
1602 && !AVR_TINY);
1603
1604 if (minimize
1605 && (live_seq > 4
1606 || frame_pointer_needed
1607 || size))
1608 {
1609 /* Get rid of frame. */
1610
1611 if (!frame_pointer_needed)
1612 {
1613 emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
1614 }
1615
1616 if (size)
1617 {
1618 emit_move_insn (frame_pointer_rtx,
1619 plus_constant (Pmode, frame_pointer_rtx, size));
1620 }
1621
1622 emit_insn (gen_epilogue_restores (gen_int_mode (live_seq, HImode)));
1623 return;
1624 }
1625
1626 if (size)
1627 {
1628 /* Try two methods to adjust stack and select shortest. */
1629
1630 int irq_state = -1;
1631 rtx fp, my_fp;
1632 rtx_insn *fp_plus_insns;
1633 HOST_WIDE_INT size_max;
1634
1635 gcc_assert (frame_pointer_needed
1636 || !isr_p
1637 || !crtl->is_leaf);
1638
1639 fp = my_fp = (frame_pointer_needed
1640 ? frame_pointer_rtx
1641 : gen_rtx_REG (Pmode, REG_X));
1642
1643 if (AVR_HAVE_8BIT_SP)
1644 {
1645 /* The high byte (r29) does not change:
1646 Prefer SUBI (1 cycle) over SBIW (2 cycles). */
1647
1648 my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
1649 }
1650
1651 /* For rationale see comment in prologue generation. */
1652
1653 size_max = (HOST_WIDE_INT) GET_MODE_MASK (GET_MODE (my_fp));
1654 if (size > size_max)
1655 size = size_max;
1656 size = trunc_int_for_mode (size, GET_MODE (my_fp));
1657
1658 /********** Method 1: Adjust fp register **********/
1659
1660 start_sequence ();
1661
1662 if (!frame_pointer_needed)
1663 emit_move_insn (fp, stack_pointer_rtx);
1664
1665 emit_move_insn (my_fp, plus_constant (GET_MODE (my_fp), my_fp, size));
1666
1667 /* Copy to stack pointer. */
1668
1669 if (TARGET_NO_INTERRUPTS)
1670 irq_state = 0;
1671
1672 if (AVR_HAVE_8BIT_SP)
1673 irq_state = 2;
1674
1675 emit_insn (gen_movhi_sp_r (stack_pointer_rtx, fp,
1676 GEN_INT (irq_state)));
1677
1678 fp_plus_insns = get_insns ();
1679 end_sequence ();
1680
1681 /********** Method 2: Adjust Stack pointer **********/
1682
1683 if (avr_sp_immediate_operand (gen_int_mode (size, HImode), HImode))
1684 {
1685 rtx_insn *sp_plus_insns;
1686
1687 start_sequence ();
1688
1689 emit_move_insn (stack_pointer_rtx,
1690 plus_constant (Pmode, stack_pointer_rtx, size));
1691
1692 sp_plus_insns = get_insns ();
1693 end_sequence ();
1694
1695 /************ Use shortest method ************/
1696
1697 emit_insn (get_sequence_length (sp_plus_insns)
1698 < get_sequence_length (fp_plus_insns)
1699 ? sp_plus_insns
1700 : fp_plus_insns);
1701 }
1702 else
1703 emit_insn (fp_plus_insns);
1704 } /* size != 0 */
1705
1706 if (frame_pointer_needed
1707 && !(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
1708 {
1709 /* Restore previous frame_pointer. See avr_expand_prologue for
1710 rationale for not using pophi. */
1711
1712 emit_pop_byte (REG_Y + 1);
1713 emit_pop_byte (REG_Y);
1714 }
1715
1716 /* Restore used registers. */
1717
1718 for (reg = 31; reg >= 0; --reg)
1719 if (TEST_HARD_REG_BIT (set, reg))
1720 emit_pop_byte (reg);
1721
1722 if (isr_p)
1723 {
1724 /* Restore RAMPZ/Y/X/D using tmp_reg as scratch.
1725 The conditions to restore them must be tha same as in prologue. */
1726
1727 if (AVR_HAVE_RAMPZ
1728 && TEST_HARD_REG_BIT (set, REG_Z)
1729 && TEST_HARD_REG_BIT (set, REG_Z + 1))
1730 {
1731 emit_pop_byte (TMP_REGNO);
1732 emit_move_insn (rampz_rtx, tmp_reg_rtx);
1733 }
1734
1735 if (AVR_HAVE_RAMPY
1736 && (frame_pointer_needed
1737 || (TEST_HARD_REG_BIT (set, REG_Y)
1738 && TEST_HARD_REG_BIT (set, REG_Y + 1))))
1739 {
1740 emit_pop_byte (TMP_REGNO);
1741 emit_move_insn (rampy_rtx, tmp_reg_rtx);
1742 }
1743
1744 if (AVR_HAVE_RAMPX
1745 && TEST_HARD_REG_BIT (set, REG_X)
1746 && TEST_HARD_REG_BIT (set, REG_X + 1))
1747 {
1748 emit_pop_byte (TMP_REGNO);
1749 emit_move_insn (rampx_rtx, tmp_reg_rtx);
1750 }
1751
1752 if (AVR_HAVE_RAMPD)
1753 {
1754 emit_pop_byte (TMP_REGNO);
1755 emit_move_insn (rampd_rtx, tmp_reg_rtx);
1756 }
1757
1758 /* Restore SREG using tmp_reg as scratch. */
1759
1760 emit_pop_byte (AVR_TMP_REGNO);
1761 emit_move_insn (sreg_rtx, tmp_reg_rtx);
1762
1763 /* Restore tmp REG. */
1764 emit_pop_byte (AVR_TMP_REGNO);
1765
1766 /* Restore zero REG. */
1767 emit_pop_byte (AVR_ZERO_REGNO);
1768 }
1769
1770 if (!sibcall_p)
1771 emit_jump_insn (gen_return ());
1772 }
1773
1774
1775 /* Implement `TARGET_ASM_FUNCTION_BEGIN_EPILOGUE'. */
1776
1777 static void
avr_asm_function_begin_epilogue(FILE * file)1778 avr_asm_function_begin_epilogue (FILE *file)
1779 {
1780 fprintf (file, "/* epilogue start */\n");
1781 }
1782
1783
1784 /* Implement `TARGET_CANNOT_MODITY_JUMPS_P'. */
1785
1786 static bool
avr_cannot_modify_jumps_p(void)1787 avr_cannot_modify_jumps_p (void)
1788 {
1789
1790 /* Naked Functions must not have any instructions after
1791 their epilogue, see PR42240 */
1792
1793 if (reload_completed
1794 && cfun->machine
1795 && cfun->machine->is_naked)
1796 {
1797 return true;
1798 }
1799
1800 return false;
1801 }
1802
1803
1804 /* Implement `TARGET_MODE_DEPENDENT_ADDRESS_P'. */
1805
1806 static bool
avr_mode_dependent_address_p(const_rtx addr ATTRIBUTE_UNUSED,addr_space_t as)1807 avr_mode_dependent_address_p (const_rtx addr ATTRIBUTE_UNUSED, addr_space_t as)
1808 {
1809 /* FIXME: Non-generic addresses are not mode-dependent in themselves.
1810 This hook just serves to hack around PR rtl-optimization/52543 by
1811 claiming that non-generic addresses were mode-dependent so that
1812 lower-subreg.c will skip these addresses. lower-subreg.c sets up fake
1813 RTXes to probe SET and MEM costs and assumes that MEM is always in the
1814 generic address space which is not true. */
1815
1816 return !ADDR_SPACE_GENERIC_P (as);
1817 }
1818
1819
1820 /* Helper function for `avr_legitimate_address_p'. */
1821
1822 static inline bool
avr_reg_ok_for_addr_p(rtx reg,addr_space_t as,RTX_CODE outer_code,bool strict)1823 avr_reg_ok_for_addr_p (rtx reg, addr_space_t as,
1824 RTX_CODE outer_code, bool strict)
1825 {
1826 return (REG_P (reg)
1827 && (avr_regno_mode_code_ok_for_base_p (REGNO (reg), QImode,
1828 as, outer_code, UNKNOWN)
1829 || (!strict
1830 && REGNO (reg) >= FIRST_PSEUDO_REGISTER)));
1831 }
1832
1833
1834 /* Return nonzero if X (an RTX) is a legitimate memory address on the target
1835 machine for a memory operand of mode MODE. */
1836
1837 static bool
avr_legitimate_address_p(machine_mode mode,rtx x,bool strict)1838 avr_legitimate_address_p (machine_mode mode, rtx x, bool strict)
1839 {
1840 bool ok = CONSTANT_ADDRESS_P (x);
1841
1842 switch (GET_CODE (x))
1843 {
1844 case REG:
1845 ok = avr_reg_ok_for_addr_p (x, ADDR_SPACE_GENERIC,
1846 MEM, strict);
1847
1848 if (strict
1849 && GET_MODE_SIZE (mode) > 4
1850 && REG_X == REGNO (x))
1851 {
1852 ok = false;
1853 }
1854 break;
1855
1856 case POST_INC:
1857 case PRE_DEC:
1858 ok = avr_reg_ok_for_addr_p (XEXP (x, 0), ADDR_SPACE_GENERIC,
1859 GET_CODE (x), strict);
1860 break;
1861
1862 case PLUS:
1863 {
1864 rtx reg = XEXP (x, 0);
1865 rtx op1 = XEXP (x, 1);
1866
1867 if (REG_P (reg)
1868 && CONST_INT_P (op1)
1869 && INTVAL (op1) >= 0)
1870 {
1871 bool fit = IN_RANGE (INTVAL (op1), 0, MAX_LD_OFFSET (mode));
1872
1873 if (fit)
1874 {
1875 ok = (! strict
1876 || avr_reg_ok_for_addr_p (reg, ADDR_SPACE_GENERIC,
1877 PLUS, strict));
1878
1879 if (reg == frame_pointer_rtx
1880 || reg == arg_pointer_rtx)
1881 {
1882 ok = true;
1883 }
1884 }
1885 else if (frame_pointer_needed
1886 && reg == frame_pointer_rtx)
1887 {
1888 ok = true;
1889 }
1890 }
1891 }
1892 break;
1893
1894 default:
1895 break;
1896 }
1897
1898 if (AVR_TINY
1899 && CONSTANT_ADDRESS_P (x))
1900 {
1901 /* avrtiny's load / store instructions only cover addresses 0..0xbf:
1902 IN / OUT range is 0..0x3f and LDS / STS can access 0x40..0xbf. */
1903
1904 ok = (CONST_INT_P (x)
1905 && IN_RANGE (INTVAL (x), 0, 0xc0 - GET_MODE_SIZE (mode)));
1906 }
1907
1908 if (avr_log.legitimate_address_p)
1909 {
1910 avr_edump ("\n%?: ret=%d, mode=%m strict=%d "
1911 "reload_completed=%d reload_in_progress=%d %s:",
1912 ok, mode, strict, reload_completed, reload_in_progress,
1913 reg_renumber ? "(reg_renumber)" : "");
1914
1915 if (GET_CODE (x) == PLUS
1916 && REG_P (XEXP (x, 0))
1917 && CONST_INT_P (XEXP (x, 1))
1918 && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
1919 && reg_renumber)
1920 {
1921 avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
1922 true_regnum (XEXP (x, 0)));
1923 }
1924
1925 avr_edump ("\n%r\n", x);
1926 }
1927
1928 return ok;
1929 }
1930
1931
1932 /* Former implementation of TARGET_LEGITIMIZE_ADDRESS,
1933 now only a helper for avr_addr_space_legitimize_address. */
1934 /* Attempts to replace X with a valid
1935 memory address for an operand of mode MODE */
1936
1937 static rtx
avr_legitimize_address(rtx x,rtx oldx,machine_mode mode)1938 avr_legitimize_address (rtx x, rtx oldx, machine_mode mode)
1939 {
1940 bool big_offset_p = false;
1941
1942 x = oldx;
1943
1944 if (GET_CODE (oldx) == PLUS
1945 && REG_P (XEXP (oldx, 0)))
1946 {
1947 if (REG_P (XEXP (oldx, 1)))
1948 x = force_reg (GET_MODE (oldx), oldx);
1949 else if (CONST_INT_P (XEXP (oldx, 1)))
1950 {
1951 int offs = INTVAL (XEXP (oldx, 1));
1952 if (frame_pointer_rtx != XEXP (oldx, 0)
1953 && offs > MAX_LD_OFFSET (mode))
1954 {
1955 big_offset_p = true;
1956 x = force_reg (GET_MODE (oldx), oldx);
1957 }
1958 }
1959 }
1960
1961 if (avr_log.legitimize_address)
1962 {
1963 avr_edump ("\n%?: mode=%m\n %r\n", mode, oldx);
1964
1965 if (x != oldx)
1966 avr_edump (" %s --> %r\n", big_offset_p ? "(big offset)" : "", x);
1967 }
1968
1969 return x;
1970 }
1971
1972
1973 /* Implement `LEGITIMIZE_RELOAD_ADDRESS'. */
1974 /* This will allow register R26/27 to be used where it is no worse than normal
1975 base pointers R28/29 or R30/31. For example, if base offset is greater
1976 than 63 bytes or for R++ or --R addressing. */
1977
1978 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))1979 avr_legitimize_reload_address (rtx *px, machine_mode mode,
1980 int opnum, int type, int addr_type,
1981 int ind_levels ATTRIBUTE_UNUSED,
1982 rtx (*mk_memloc)(rtx,int))
1983 {
1984 rtx x = *px;
1985
1986 if (avr_log.legitimize_reload_address)
1987 avr_edump ("\n%?:%m %r\n", mode, x);
1988
1989 if (1 && (GET_CODE (x) == POST_INC
1990 || GET_CODE (x) == PRE_DEC))
1991 {
1992 push_reload (XEXP (x, 0), XEXP (x, 0), &XEXP (x, 0), &XEXP (x, 0),
1993 POINTER_REGS, GET_MODE (x), GET_MODE (x), 0, 0,
1994 opnum, RELOAD_OTHER);
1995
1996 if (avr_log.legitimize_reload_address)
1997 avr_edump (" RCLASS.1 = %R\n IN = %r\n OUT = %r\n",
1998 POINTER_REGS, XEXP (x, 0), XEXP (x, 0));
1999
2000 return x;
2001 }
2002
2003 if (GET_CODE (x) == PLUS
2004 && REG_P (XEXP (x, 0))
2005 && 0 == reg_equiv_constant (REGNO (XEXP (x, 0)))
2006 && CONST_INT_P (XEXP (x, 1))
2007 && INTVAL (XEXP (x, 1)) >= 1)
2008 {
2009 bool fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
2010
2011 if (fit)
2012 {
2013 if (reg_equiv_address (REGNO (XEXP (x, 0))) != 0)
2014 {
2015 int regno = REGNO (XEXP (x, 0));
2016 rtx mem = mk_memloc (x, regno);
2017
2018 push_reload (XEXP (mem, 0), NULL_RTX, &XEXP (mem, 0), NULL,
2019 POINTER_REGS, Pmode, VOIDmode, 0, 0,
2020 1, (enum reload_type) addr_type);
2021
2022 if (avr_log.legitimize_reload_address)
2023 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
2024 POINTER_REGS, XEXP (mem, 0), NULL_RTX);
2025
2026 push_reload (mem, NULL_RTX, &XEXP (x, 0), NULL,
2027 BASE_POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
2028 opnum, (enum reload_type) type);
2029
2030 if (avr_log.legitimize_reload_address)
2031 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
2032 BASE_POINTER_REGS, mem, NULL_RTX);
2033
2034 return x;
2035 }
2036 }
2037 else if (! (frame_pointer_needed
2038 && XEXP (x, 0) == frame_pointer_rtx))
2039 {
2040 push_reload (x, NULL_RTX, px, NULL,
2041 POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
2042 opnum, (enum reload_type) type);
2043
2044 if (avr_log.legitimize_reload_address)
2045 avr_edump (" RCLASS.3 = %R\n IN = %r\n OUT = %r\n",
2046 POINTER_REGS, x, NULL_RTX);
2047
2048 return x;
2049 }
2050 }
2051
2052 return NULL_RTX;
2053 }
2054
2055
2056 /* Implement `TARGET_SECONDARY_RELOAD' */
2057
2058 static reg_class_t
avr_secondary_reload(bool in_p,rtx x,reg_class_t reload_class ATTRIBUTE_UNUSED,machine_mode mode,secondary_reload_info * sri)2059 avr_secondary_reload (bool in_p, rtx x,
2060 reg_class_t reload_class ATTRIBUTE_UNUSED,
2061 machine_mode mode, secondary_reload_info *sri)
2062 {
2063 if (in_p
2064 && MEM_P (x)
2065 && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x))
2066 && ADDR_SPACE_MEMX != MEM_ADDR_SPACE (x))
2067 {
2068 /* For the non-generic 16-bit spaces we need a d-class scratch. */
2069
2070 switch (mode)
2071 {
2072 default:
2073 gcc_unreachable();
2074
2075 case QImode: sri->icode = CODE_FOR_reload_inqi; break;
2076 case QQmode: sri->icode = CODE_FOR_reload_inqq; break;
2077 case UQQmode: sri->icode = CODE_FOR_reload_inuqq; break;
2078
2079 case HImode: sri->icode = CODE_FOR_reload_inhi; break;
2080 case HQmode: sri->icode = CODE_FOR_reload_inhq; break;
2081 case HAmode: sri->icode = CODE_FOR_reload_inha; break;
2082 case UHQmode: sri->icode = CODE_FOR_reload_inuhq; break;
2083 case UHAmode: sri->icode = CODE_FOR_reload_inuha; break;
2084
2085 case PSImode: sri->icode = CODE_FOR_reload_inpsi; break;
2086
2087 case SImode: sri->icode = CODE_FOR_reload_insi; break;
2088 case SFmode: sri->icode = CODE_FOR_reload_insf; break;
2089 case SQmode: sri->icode = CODE_FOR_reload_insq; break;
2090 case SAmode: sri->icode = CODE_FOR_reload_insa; break;
2091 case USQmode: sri->icode = CODE_FOR_reload_inusq; break;
2092 case USAmode: sri->icode = CODE_FOR_reload_inusa; break;
2093 }
2094 }
2095
2096 return NO_REGS;
2097 }
2098
2099
2100 /* Helper function to print assembler resp. track instruction
2101 sequence lengths. Always return "".
2102
2103 If PLEN == NULL:
2104 Output assembler code from template TPL with operands supplied
2105 by OPERANDS. This is just forwarding to output_asm_insn.
2106
2107 If PLEN != NULL:
2108 If N_WORDS >= 0 Add N_WORDS to *PLEN.
2109 If N_WORDS < 0 Set *PLEN to -N_WORDS.
2110 Don't output anything.
2111 */
2112
2113 static const char*
avr_asm_len(const char * tpl,rtx * operands,int * plen,int n_words)2114 avr_asm_len (const char* tpl, rtx* operands, int* plen, int n_words)
2115 {
2116 if (NULL == plen)
2117 {
2118 output_asm_insn (tpl, operands);
2119 }
2120 else
2121 {
2122 if (n_words < 0)
2123 *plen = -n_words;
2124 else
2125 *plen += n_words;
2126 }
2127
2128 return "";
2129 }
2130
2131
2132 /* Return a pointer register name as a string. */
2133
2134 static const char*
ptrreg_to_str(int regno)2135 ptrreg_to_str (int regno)
2136 {
2137 switch (regno)
2138 {
2139 case REG_X: return "X";
2140 case REG_Y: return "Y";
2141 case REG_Z: return "Z";
2142 default:
2143 output_operand_lossage ("address operand requires constraint for"
2144 " X, Y, or Z register");
2145 }
2146 return NULL;
2147 }
2148
2149 /* Return the condition name as a string.
2150 Used in conditional jump constructing */
2151
2152 static const char*
cond_string(enum rtx_code code)2153 cond_string (enum rtx_code code)
2154 {
2155 switch (code)
2156 {
2157 case NE:
2158 return "ne";
2159 case EQ:
2160 return "eq";
2161 case GE:
2162 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
2163 return "pl";
2164 else
2165 return "ge";
2166 case LT:
2167 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
2168 return "mi";
2169 else
2170 return "lt";
2171 case GEU:
2172 return "sh";
2173 case LTU:
2174 return "lo";
2175 default:
2176 gcc_unreachable ();
2177 }
2178
2179 return "";
2180 }
2181
2182
2183 /* Implement `TARGET_PRINT_OPERAND_ADDRESS'. */
2184 /* Output ADDR to FILE as address. */
2185
2186 static void
avr_print_operand_address(FILE * file,machine_mode,rtx addr)2187 avr_print_operand_address (FILE *file, machine_mode /*mode*/, rtx addr)
2188 {
2189 switch (GET_CODE (addr))
2190 {
2191 case REG:
2192 fprintf (file, ptrreg_to_str (REGNO (addr)));
2193 break;
2194
2195 case PRE_DEC:
2196 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
2197 break;
2198
2199 case POST_INC:
2200 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
2201 break;
2202
2203 default:
2204 if (CONSTANT_ADDRESS_P (addr)
2205 && text_segment_operand (addr, VOIDmode))
2206 {
2207 rtx x = addr;
2208 if (GET_CODE (x) == CONST)
2209 x = XEXP (x, 0);
2210 if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x,1)) == CONST_INT)
2211 {
2212 /* Assembler gs() will implant word address. Make offset
2213 a byte offset inside gs() for assembler. This is
2214 needed because the more logical (constant+gs(sym)) is not
2215 accepted by gas. For 128K and smaller devices this is ok.
2216 For large devices it will create a trampoline to offset
2217 from symbol which may not be what the user really wanted. */
2218
2219 fprintf (file, "gs(");
2220 output_addr_const (file, XEXP (x,0));
2221 fprintf (file, "+" HOST_WIDE_INT_PRINT_DEC ")",
2222 2 * INTVAL (XEXP (x, 1)));
2223 if (AVR_3_BYTE_PC)
2224 if (warning (0, "pointer offset from symbol maybe incorrect"))
2225 {
2226 output_addr_const (stderr, addr);
2227 fprintf(stderr,"\n");
2228 }
2229 }
2230 else
2231 {
2232 fprintf (file, "gs(");
2233 output_addr_const (file, addr);
2234 fprintf (file, ")");
2235 }
2236 }
2237 else
2238 output_addr_const (file, addr);
2239 }
2240 }
2241
2242
2243 /* Implement `TARGET_PRINT_OPERAND_PUNCT_VALID_P'. */
2244
2245 static bool
avr_print_operand_punct_valid_p(unsigned char code)2246 avr_print_operand_punct_valid_p (unsigned char code)
2247 {
2248 return code == '~' || code == '!';
2249 }
2250
2251
2252 /* Implement `TARGET_PRINT_OPERAND'. */
2253 /* Output X as assembler operand to file FILE.
2254 For a description of supported %-codes, see top of avr.md. */
2255
2256 static void
avr_print_operand(FILE * file,rtx x,int code)2257 avr_print_operand (FILE *file, rtx x, int code)
2258 {
2259 int abcd = 0, ef = 0, ij = 0;
2260
2261 if (code >= 'A' && code <= 'D')
2262 abcd = code - 'A';
2263 else if (code == 'E' || code == 'F')
2264 ef = code - 'E';
2265 else if (code == 'I' || code == 'J')
2266 ij = code - 'I';
2267
2268 if (code == '~')
2269 {
2270 if (!AVR_HAVE_JMP_CALL)
2271 fputc ('r', file);
2272 }
2273 else if (code == '!')
2274 {
2275 if (AVR_HAVE_EIJMP_EICALL)
2276 fputc ('e', file);
2277 }
2278 else if (code == 't'
2279 || code == 'T')
2280 {
2281 static int t_regno = -1;
2282 static int t_nbits = -1;
2283
2284 if (REG_P (x) && t_regno < 0 && code == 'T')
2285 {
2286 t_regno = REGNO (x);
2287 t_nbits = GET_MODE_BITSIZE (GET_MODE (x));
2288 }
2289 else if (CONST_INT_P (x) && t_regno >= 0
2290 && IN_RANGE (INTVAL (x), 0, t_nbits - 1))
2291 {
2292 int bpos = INTVAL (x);
2293
2294 fprintf (file, "%s", reg_names[t_regno + bpos / 8]);
2295 if (code == 'T')
2296 fprintf (file, ",%d", bpos % 8);
2297
2298 t_regno = -1;
2299 }
2300 else
2301 fatal_insn ("operands to %T/%t must be reg + const_int:", x);
2302 }
2303 else if (code == 'E' || code == 'F')
2304 {
2305 rtx op = XEXP(x, 0);
2306 fprintf (file, reg_names[REGNO (op) + ef]);
2307 }
2308 else if (code == 'I' || code == 'J')
2309 {
2310 rtx op = XEXP(XEXP(x, 0), 0);
2311 fprintf (file, reg_names[REGNO (op) + ij]);
2312 }
2313 else if (REG_P (x))
2314 {
2315 if (x == zero_reg_rtx)
2316 fprintf (file, "__zero_reg__");
2317 else if (code == 'r' && REGNO (x) < 32)
2318 fprintf (file, "%d", (int) REGNO (x));
2319 else
2320 fprintf (file, reg_names[REGNO (x) + abcd]);
2321 }
2322 else if (CONST_INT_P (x))
2323 {
2324 HOST_WIDE_INT ival = INTVAL (x);
2325
2326 if ('i' != code)
2327 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival + abcd);
2328 else if (low_io_address_operand (x, VOIDmode)
2329 || high_io_address_operand (x, VOIDmode))
2330 {
2331 if (AVR_HAVE_RAMPZ && ival == avr_addr.rampz)
2332 fprintf (file, "__RAMPZ__");
2333 else if (AVR_HAVE_RAMPY && ival == avr_addr.rampy)
2334 fprintf (file, "__RAMPY__");
2335 else if (AVR_HAVE_RAMPX && ival == avr_addr.rampx)
2336 fprintf (file, "__RAMPX__");
2337 else if (AVR_HAVE_RAMPD && ival == avr_addr.rampd)
2338 fprintf (file, "__RAMPD__");
2339 else if ((AVR_XMEGA || AVR_TINY) && ival == avr_addr.ccp)
2340 fprintf (file, "__CCP__");
2341 else if (ival == avr_addr.sreg) fprintf (file, "__SREG__");
2342 else if (ival == avr_addr.sp_l) fprintf (file, "__SP_L__");
2343 else if (ival == avr_addr.sp_h) fprintf (file, "__SP_H__");
2344 else
2345 {
2346 fprintf (file, HOST_WIDE_INT_PRINT_HEX,
2347 ival - avr_arch->sfr_offset);
2348 }
2349 }
2350 else
2351 fatal_insn ("bad address, not an I/O address:", x);
2352 }
2353 else if (MEM_P (x))
2354 {
2355 rtx addr = XEXP (x, 0);
2356
2357 if (code == 'm')
2358 {
2359 if (!CONSTANT_P (addr))
2360 fatal_insn ("bad address, not a constant:", addr);
2361 /* Assembler template with m-code is data - not progmem section */
2362 if (text_segment_operand (addr, VOIDmode))
2363 if (warning (0, "accessing data memory with"
2364 " program memory address"))
2365 {
2366 output_addr_const (stderr, addr);
2367 fprintf(stderr,"\n");
2368 }
2369 output_addr_const (file, addr);
2370 }
2371 else if (code == 'i')
2372 {
2373 avr_print_operand (file, addr, 'i');
2374 }
2375 else if (code == 'o')
2376 {
2377 if (GET_CODE (addr) != PLUS)
2378 fatal_insn ("bad address, not (reg+disp):", addr);
2379
2380 avr_print_operand (file, XEXP (addr, 1), 0);
2381 }
2382 else if (code == 'b')
2383 {
2384 if (GET_CODE (addr) != PLUS)
2385 fatal_insn ("bad address, not (reg+disp):", addr);
2386
2387 avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
2388 }
2389 else if (code == 'p' || code == 'r')
2390 {
2391 if (GET_CODE (addr) != POST_INC && GET_CODE (addr) != PRE_DEC)
2392 fatal_insn ("bad address, not post_inc or pre_dec:", addr);
2393
2394 if (code == 'p')
2395 /* X, Y, Z */
2396 avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
2397 else
2398 avr_print_operand (file, XEXP (addr, 0), 0); /* r26, r28, r30 */
2399 }
2400 else if (GET_CODE (addr) == PLUS)
2401 {
2402 avr_print_operand_address (file, VOIDmode, XEXP (addr,0));
2403 if (REGNO (XEXP (addr, 0)) == REG_X)
2404 fatal_insn ("internal compiler error. Bad address:"
2405 ,addr);
2406 fputc ('+', file);
2407 avr_print_operand (file, XEXP (addr,1), code);
2408 }
2409 else
2410 avr_print_operand_address (file, VOIDmode, addr);
2411 }
2412 else if (code == 'i')
2413 {
2414 if (GET_CODE (x) == SYMBOL_REF && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO))
2415 avr_print_operand_address
2416 (file, VOIDmode, plus_constant (HImode, x, -avr_arch->sfr_offset));
2417 else
2418 fatal_insn ("bad address, not an I/O address:", x);
2419 }
2420 else if (code == 'x')
2421 {
2422 /* Constant progmem address - like used in jmp or call */
2423 if (0 == text_segment_operand (x, VOIDmode))
2424 if (warning (0, "accessing program memory"
2425 " with data memory address"))
2426 {
2427 output_addr_const (stderr, x);
2428 fprintf(stderr,"\n");
2429 }
2430 /* Use normal symbol for direct address no linker trampoline needed */
2431 output_addr_const (file, x);
2432 }
2433 else if (CONST_FIXED_P (x))
2434 {
2435 HOST_WIDE_INT ival = INTVAL (avr_to_int_mode (x));
2436 if (code != 0)
2437 output_operand_lossage ("Unsupported code '%c' for fixed-point:",
2438 code);
2439 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);
2440 }
2441 else if (GET_CODE (x) == CONST_DOUBLE)
2442 {
2443 long val;
2444 if (GET_MODE (x) != SFmode)
2445 fatal_insn ("internal compiler error. Unknown mode:", x);
2446 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), val);
2447 fprintf (file, "0x%lx", val);
2448 }
2449 else if (GET_CODE (x) == CONST_STRING)
2450 fputs (XSTR (x, 0), file);
2451 else if (code == 'j')
2452 fputs (cond_string (GET_CODE (x)), file);
2453 else if (code == 'k')
2454 fputs (cond_string (reverse_condition (GET_CODE (x))), file);
2455 else
2456 avr_print_operand_address (file, VOIDmode, x);
2457 }
2458
2459
2460 /* Implement TARGET_USE_BY_PIECES_INFRASTRUCTURE_P. */
2461
2462 /* Prefer sequence of loads/stores for moves of size upto
2463 two - two pairs of load/store instructions are always better
2464 than the 5 instruction sequence for a loop (1 instruction
2465 for loop counter setup, and 4 for the body of the loop). */
2466
2467 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)2468 avr_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size,
2469 unsigned int align ATTRIBUTE_UNUSED,
2470 enum by_pieces_operation op,
2471 bool speed_p)
2472 {
2473
2474 if (op != MOVE_BY_PIECES || (speed_p && (size > (MOVE_MAX_PIECES))))
2475 return default_use_by_pieces_infrastructure_p (size, align, op, speed_p);
2476
2477 return size <= (MOVE_MAX_PIECES);
2478 }
2479
2480
2481 /* Worker function for `NOTICE_UPDATE_CC'. */
2482 /* Update the condition code in the INSN. */
2483
2484 void
avr_notice_update_cc(rtx body ATTRIBUTE_UNUSED,rtx_insn * insn)2485 avr_notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx_insn *insn)
2486 {
2487 rtx set;
2488 enum attr_cc cc = get_attr_cc (insn);
2489
2490 switch (cc)
2491 {
2492 default:
2493 break;
2494
2495 case CC_PLUS:
2496 case CC_LDI:
2497 {
2498 rtx *op = recog_data.operand;
2499 int len_dummy, icc;
2500
2501 /* Extract insn's operands. */
2502 extract_constrain_insn_cached (insn);
2503
2504 switch (cc)
2505 {
2506 default:
2507 gcc_unreachable();
2508
2509 case CC_PLUS:
2510 avr_out_plus (insn, op, &len_dummy, &icc);
2511 cc = (enum attr_cc) icc;
2512 break;
2513
2514 case CC_LDI:
2515
2516 cc = (op[1] == CONST0_RTX (GET_MODE (op[0]))
2517 && reg_overlap_mentioned_p (op[0], zero_reg_rtx))
2518 /* Loading zero-reg with 0 uses CLR and thus clobbers cc0. */
2519 ? CC_CLOBBER
2520 /* Any other "r,rL" combination does not alter cc0. */
2521 : CC_NONE;
2522
2523 break;
2524 } /* inner switch */
2525
2526 break;
2527 }
2528 } /* outer swicth */
2529
2530 switch (cc)
2531 {
2532 default:
2533 /* Special values like CC_OUT_PLUS from above have been
2534 mapped to "standard" CC_* values so we never come here. */
2535
2536 gcc_unreachable();
2537 break;
2538
2539 case CC_NONE:
2540 /* Insn does not affect CC at all, but it might set some registers
2541 that are stored in cc_status. If such a register is affected by
2542 the current insn, for example by means of a SET or a CLOBBER,
2543 then we must reset cc_status; cf. PR77326.
2544
2545 Unfortunately, set_of cannot be used as reg_overlap_mentioned_p
2546 will abort on COMPARE (which might be found in cc_status.value1/2).
2547 Thus work out the registers set by the insn and regs mentioned
2548 in cc_status.value1/2. */
2549
2550 if (cc_status.value1
2551 || cc_status.value2)
2552 {
2553 HARD_REG_SET regs_used;
2554 HARD_REG_SET regs_set;
2555 CLEAR_HARD_REG_SET (regs_used);
2556
2557 if (cc_status.value1
2558 && !CONSTANT_P (cc_status.value1))
2559 {
2560 find_all_hard_regs (cc_status.value1, ®s_used);
2561 }
2562
2563 if (cc_status.value2
2564 && !CONSTANT_P (cc_status.value2))
2565 {
2566 find_all_hard_regs (cc_status.value2, ®s_used);
2567 }
2568
2569 find_all_hard_reg_sets (insn, ®s_set, false);
2570
2571 if (hard_reg_set_intersect_p (regs_used, regs_set))
2572 {
2573 CC_STATUS_INIT;
2574 }
2575 }
2576
2577 break; // CC_NONE
2578
2579 case CC_SET_N:
2580 CC_STATUS_INIT;
2581 break;
2582
2583 case CC_SET_ZN:
2584 set = single_set (insn);
2585 CC_STATUS_INIT;
2586 if (set)
2587 {
2588 cc_status.flags |= CC_NO_OVERFLOW;
2589 cc_status.value1 = SET_DEST (set);
2590 }
2591 break;
2592
2593 case CC_SET_VZN:
2594 /* Insn like INC, DEC, NEG that set Z,N,V. We currently don't make use
2595 of this combination, cf. also PR61055. */
2596 CC_STATUS_INIT;
2597 break;
2598
2599 case CC_SET_CZN:
2600 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
2601 The V flag may or may not be known but that's ok because
2602 alter_cond will change tests to use EQ/NE. */
2603 set = single_set (insn);
2604 CC_STATUS_INIT;
2605 if (set)
2606 {
2607 cc_status.value1 = SET_DEST (set);
2608 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
2609 }
2610 break;
2611
2612 case CC_COMPARE:
2613 set = single_set (insn);
2614 CC_STATUS_INIT;
2615 if (set)
2616 cc_status.value1 = SET_SRC (set);
2617 break;
2618
2619 case CC_CLOBBER:
2620 /* Insn doesn't leave CC in a usable state. */
2621 CC_STATUS_INIT;
2622 break;
2623 }
2624 }
2625
2626 /* Choose mode for jump insn:
2627 1 - relative jump in range -63 <= x <= 62 ;
2628 2 - relative jump in range -2046 <= x <= 2045 ;
2629 3 - absolute jump (only for ATmega[16]03). */
2630
2631 int
avr_jump_mode(rtx x,rtx_insn * insn)2632 avr_jump_mode (rtx x, rtx_insn *insn)
2633 {
2634 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_CODE (x) == LABEL_REF
2635 ? XEXP (x, 0) : x));
2636 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
2637 int jump_distance = cur_addr - dest_addr;
2638
2639 if (-63 <= jump_distance && jump_distance <= 62)
2640 return 1;
2641 else if (-2046 <= jump_distance && jump_distance <= 2045)
2642 return 2;
2643 else if (AVR_HAVE_JMP_CALL)
2644 return 3;
2645
2646 return 2;
2647 }
2648
2649 /* Return an AVR condition jump commands.
2650 X is a comparison RTX.
2651 LEN is a number returned by avr_jump_mode function.
2652 If REVERSE nonzero then condition code in X must be reversed. */
2653
2654 const char*
ret_cond_branch(rtx x,int len,int reverse)2655 ret_cond_branch (rtx x, int len, int reverse)
2656 {
2657 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
2658
2659 switch (cond)
2660 {
2661 case GT:
2662 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
2663 return (len == 1 ? ("breq .+2" CR_TAB
2664 "brpl %0") :
2665 len == 2 ? ("breq .+4" CR_TAB
2666 "brmi .+2" CR_TAB
2667 "rjmp %0") :
2668 ("breq .+6" CR_TAB
2669 "brmi .+4" CR_TAB
2670 "jmp %0"));
2671
2672 else
2673 return (len == 1 ? ("breq .+2" CR_TAB
2674 "brge %0") :
2675 len == 2 ? ("breq .+4" CR_TAB
2676 "brlt .+2" CR_TAB
2677 "rjmp %0") :
2678 ("breq .+6" CR_TAB
2679 "brlt .+4" CR_TAB
2680 "jmp %0"));
2681 case GTU:
2682 return (len == 1 ? ("breq .+2" CR_TAB
2683 "brsh %0") :
2684 len == 2 ? ("breq .+4" CR_TAB
2685 "brlo .+2" CR_TAB
2686 "rjmp %0") :
2687 ("breq .+6" CR_TAB
2688 "brlo .+4" CR_TAB
2689 "jmp %0"));
2690 case LE:
2691 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
2692 return (len == 1 ? ("breq %0" CR_TAB
2693 "brmi %0") :
2694 len == 2 ? ("breq .+2" CR_TAB
2695 "brpl .+2" CR_TAB
2696 "rjmp %0") :
2697 ("breq .+2" CR_TAB
2698 "brpl .+4" CR_TAB
2699 "jmp %0"));
2700 else
2701 return (len == 1 ? ("breq %0" CR_TAB
2702 "brlt %0") :
2703 len == 2 ? ("breq .+2" CR_TAB
2704 "brge .+2" CR_TAB
2705 "rjmp %0") :
2706 ("breq .+2" CR_TAB
2707 "brge .+4" CR_TAB
2708 "jmp %0"));
2709 case LEU:
2710 return (len == 1 ? ("breq %0" CR_TAB
2711 "brlo %0") :
2712 len == 2 ? ("breq .+2" CR_TAB
2713 "brsh .+2" CR_TAB
2714 "rjmp %0") :
2715 ("breq .+2" CR_TAB
2716 "brsh .+4" CR_TAB
2717 "jmp %0"));
2718 default:
2719 if (reverse)
2720 {
2721 switch (len)
2722 {
2723 case 1:
2724 return "br%k1 %0";
2725 case 2:
2726 return ("br%j1 .+2" CR_TAB
2727 "rjmp %0");
2728 default:
2729 return ("br%j1 .+4" CR_TAB
2730 "jmp %0");
2731 }
2732 }
2733 else
2734 {
2735 switch (len)
2736 {
2737 case 1:
2738 return "br%j1 %0";
2739 case 2:
2740 return ("br%k1 .+2" CR_TAB
2741 "rjmp %0");
2742 default:
2743 return ("br%k1 .+4" CR_TAB
2744 "jmp %0");
2745 }
2746 }
2747 }
2748 return "";
2749 }
2750
2751
2752 /* Worker function for `FINAL_PRESCAN_INSN'. */
2753 /* Output insn cost for next insn. */
2754
2755 void
avr_final_prescan_insn(rtx_insn * insn,rtx * operand ATTRIBUTE_UNUSED,int num_operands ATTRIBUTE_UNUSED)2756 avr_final_prescan_insn (rtx_insn *insn, rtx *operand ATTRIBUTE_UNUSED,
2757 int num_operands ATTRIBUTE_UNUSED)
2758 {
2759 if (avr_log.rtx_costs)
2760 {
2761 rtx set = single_set (insn);
2762
2763 if (set)
2764 fprintf (asm_out_file, "/* DEBUG: cost = %d. */\n",
2765 set_src_cost (SET_SRC (set), GET_MODE (SET_DEST (set)),
2766 optimize_insn_for_speed_p ()));
2767 else
2768 fprintf (asm_out_file, "/* DEBUG: pattern-cost = %d. */\n",
2769 rtx_cost (PATTERN (insn), VOIDmode, INSN, 0,
2770 optimize_insn_for_speed_p()));
2771 }
2772 }
2773
2774 /* Return 0 if undefined, 1 if always true or always false. */
2775
2776 int
avr_simplify_comparison_p(machine_mode mode,RTX_CODE op,rtx x)2777 avr_simplify_comparison_p (machine_mode mode, RTX_CODE op, rtx x)
2778 {
2779 unsigned int max = (mode == QImode ? 0xff :
2780 mode == HImode ? 0xffff :
2781 mode == PSImode ? 0xffffff :
2782 mode == SImode ? 0xffffffff : 0);
2783 if (max && op && CONST_INT_P (x))
2784 {
2785 if (unsigned_condition (op) != op)
2786 max >>= 1;
2787
2788 if (max != (INTVAL (x) & max)
2789 && INTVAL (x) != 0xff)
2790 return 1;
2791 }
2792 return 0;
2793 }
2794
2795
2796 /* Worker function for `FUNCTION_ARG_REGNO_P'. */
2797 /* Returns nonzero if REGNO is the number of a hard
2798 register in which function arguments are sometimes passed. */
2799
2800 int
avr_function_arg_regno_p(int r)2801 avr_function_arg_regno_p(int r)
2802 {
2803 return (AVR_TINY ? r >= 20 && r <= 25 : r >= 8 && r <= 25);
2804 }
2805
2806
2807 /* Worker function for `INIT_CUMULATIVE_ARGS'. */
2808 /* Initializing the variable cum for the state at the beginning
2809 of the argument list. */
2810
2811 void
avr_init_cumulative_args(CUMULATIVE_ARGS * cum,tree fntype,rtx libname,tree fndecl ATTRIBUTE_UNUSED)2812 avr_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
2813 tree fndecl ATTRIBUTE_UNUSED)
2814 {
2815 cum->nregs = AVR_TINY ? 6 : 18;
2816 cum->regno = FIRST_CUM_REG;
2817 if (!libname && stdarg_p (fntype))
2818 cum->nregs = 0;
2819
2820 /* Assume the calle may be tail called */
2821
2822 cfun->machine->sibcall_fails = 0;
2823 }
2824
2825 /* Returns the number of registers to allocate for a function argument. */
2826
2827 static int
avr_num_arg_regs(machine_mode mode,const_tree type)2828 avr_num_arg_regs (machine_mode mode, const_tree type)
2829 {
2830 int size;
2831
2832 if (mode == BLKmode)
2833 size = int_size_in_bytes (type);
2834 else
2835 size = GET_MODE_SIZE (mode);
2836
2837 /* Align all function arguments to start in even-numbered registers.
2838 Odd-sized arguments leave holes above them. */
2839
2840 return (size + 1) & ~1;
2841 }
2842
2843
2844 /* Implement `TARGET_FUNCTION_ARG'. */
2845 /* Controls whether a function argument is passed
2846 in a register, and which register. */
2847
2848 static rtx
avr_function_arg(cumulative_args_t cum_v,machine_mode mode,const_tree type,bool named ATTRIBUTE_UNUSED)2849 avr_function_arg (cumulative_args_t cum_v, machine_mode mode,
2850 const_tree type, bool named ATTRIBUTE_UNUSED)
2851 {
2852 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2853 int bytes = avr_num_arg_regs (mode, type);
2854
2855 if (cum->nregs && bytes <= cum->nregs)
2856 return gen_rtx_REG (mode, cum->regno - bytes);
2857
2858 return NULL_RTX;
2859 }
2860
2861
2862 /* Implement `TARGET_FUNCTION_ARG_ADVANCE'. */
2863 /* Update the summarizer variable CUM to advance past an argument
2864 in the argument list. */
2865
2866 static void
avr_function_arg_advance(cumulative_args_t cum_v,machine_mode mode,const_tree type,bool named ATTRIBUTE_UNUSED)2867 avr_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
2868 const_tree type, bool named ATTRIBUTE_UNUSED)
2869 {
2870 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
2871 int bytes = avr_num_arg_regs (mode, type);
2872
2873 cum->nregs -= bytes;
2874 cum->regno -= bytes;
2875
2876 /* A parameter is being passed in a call-saved register. As the original
2877 contents of these regs has to be restored before leaving the function,
2878 a function must not pass arguments in call-saved regs in order to get
2879 tail-called. */
2880
2881 if (cum->regno >= 8
2882 && cum->nregs >= 0
2883 && !call_used_regs[cum->regno])
2884 {
2885 /* FIXME: We ship info on failing tail-call in struct machine_function.
2886 This uses internals of calls.c:expand_call() and the way args_so_far
2887 is used. targetm.function_ok_for_sibcall() needs to be extended to
2888 pass &args_so_far, too. At present, CUMULATIVE_ARGS is target
2889 dependent so that such an extension is not wanted. */
2890
2891 cfun->machine->sibcall_fails = 1;
2892 }
2893
2894 /* Test if all registers needed by the ABI are actually available. If the
2895 user has fixed a GPR needed to pass an argument, an (implicit) function
2896 call will clobber that fixed register. See PR45099 for an example. */
2897
2898 if (cum->regno >= 8
2899 && cum->nregs >= 0)
2900 {
2901 int regno;
2902
2903 for (regno = cum->regno; regno < cum->regno + bytes; regno++)
2904 if (fixed_regs[regno])
2905 warning (0, "fixed register %s used to pass parameter to function",
2906 reg_names[regno]);
2907 }
2908
2909 if (cum->nregs <= 0)
2910 {
2911 cum->nregs = 0;
2912 cum->regno = FIRST_CUM_REG;
2913 }
2914 }
2915
2916 /* Implement `TARGET_FUNCTION_OK_FOR_SIBCALL' */
2917 /* Decide whether we can make a sibling call to a function. DECL is the
2918 declaration of the function being targeted by the call and EXP is the
2919 CALL_EXPR representing the call. */
2920
2921 static bool
avr_function_ok_for_sibcall(tree decl_callee,tree exp_callee)2922 avr_function_ok_for_sibcall (tree decl_callee, tree exp_callee)
2923 {
2924 tree fntype_callee;
2925
2926 /* Tail-calling must fail if callee-saved regs are used to pass
2927 function args. We must not tail-call when `epilogue_restores'
2928 is used. Unfortunately, we cannot tell at this point if that
2929 actually will happen or not, and we cannot step back from
2930 tail-calling. Thus, we inhibit tail-calling with -mcall-prologues. */
2931
2932 if (cfun->machine->sibcall_fails
2933 || TARGET_CALL_PROLOGUES)
2934 {
2935 return false;
2936 }
2937
2938 fntype_callee = TREE_TYPE (CALL_EXPR_FN (exp_callee));
2939
2940 if (decl_callee)
2941 {
2942 decl_callee = TREE_TYPE (decl_callee);
2943 }
2944 else
2945 {
2946 decl_callee = fntype_callee;
2947
2948 while (FUNCTION_TYPE != TREE_CODE (decl_callee)
2949 && METHOD_TYPE != TREE_CODE (decl_callee))
2950 {
2951 decl_callee = TREE_TYPE (decl_callee);
2952 }
2953 }
2954
2955 /* Ensure that caller and callee have compatible epilogues */
2956
2957 if (cfun->machine->is_interrupt
2958 || cfun->machine->is_signal
2959 || cfun->machine->is_naked
2960 || avr_naked_function_p (decl_callee)
2961 /* FIXME: For OS_task and OS_main, this might be over-conservative. */
2962 || (avr_OS_task_function_p (decl_callee)
2963 != cfun->machine->is_OS_task)
2964 || (avr_OS_main_function_p (decl_callee)
2965 != cfun->machine->is_OS_main))
2966 {
2967 return false;
2968 }
2969
2970 return true;
2971 }
2972
2973 /***********************************************************************
2974 Functions for outputting various mov's for a various modes
2975 ************************************************************************/
2976
2977 /* Return true if a value of mode MODE is read from flash by
2978 __load_* function from libgcc. */
2979
2980 bool
avr_load_libgcc_p(rtx op)2981 avr_load_libgcc_p (rtx op)
2982 {
2983 machine_mode mode = GET_MODE (op);
2984 int n_bytes = GET_MODE_SIZE (mode);
2985
2986 return (n_bytes > 2
2987 && !AVR_HAVE_LPMX
2988 && avr_mem_flash_p (op));
2989 }
2990
2991 /* Return true if a value of mode MODE is read by __xload_* function. */
2992
2993 bool
avr_xload_libgcc_p(machine_mode mode)2994 avr_xload_libgcc_p (machine_mode mode)
2995 {
2996 int n_bytes = GET_MODE_SIZE (mode);
2997
2998 return (n_bytes > 1
2999 || avr_n_flash > 1);
3000 }
3001
3002
3003 /* Fixme: This is a hack because secondary reloads don't works as expected.
3004
3005 Find an unused d-register to be used as scratch in INSN.
3006 EXCLUDE is either NULL_RTX or some register. In the case where EXCLUDE
3007 is a register, skip all possible return values that overlap EXCLUDE.
3008 The policy for the returned register is similar to that of
3009 `reg_unused_after', i.e. the returned register may overlap the SET_DEST
3010 of INSN.
3011
3012 Return a QImode d-register or NULL_RTX if nothing found. */
3013
3014 static rtx
avr_find_unused_d_reg(rtx_insn * insn,rtx exclude)3015 avr_find_unused_d_reg (rtx_insn *insn, rtx exclude)
3016 {
3017 int regno;
3018 bool isr_p = (avr_interrupt_function_p (current_function_decl)
3019 || avr_signal_function_p (current_function_decl));
3020
3021 for (regno = 16; regno < 32; regno++)
3022 {
3023 rtx reg = all_regs_rtx[regno];
3024
3025 if ((exclude
3026 && reg_overlap_mentioned_p (exclude, reg))
3027 || fixed_regs[regno])
3028 {
3029 continue;
3030 }
3031
3032 /* Try non-live register */
3033
3034 if (!df_regs_ever_live_p (regno)
3035 && (TREE_THIS_VOLATILE (current_function_decl)
3036 || cfun->machine->is_OS_task
3037 || cfun->machine->is_OS_main
3038 || (!isr_p && call_used_regs[regno])))
3039 {
3040 return reg;
3041 }
3042
3043 /* Any live register can be used if it is unused after.
3044 Prologue/epilogue will care for it as needed. */
3045
3046 if (df_regs_ever_live_p (regno)
3047 && reg_unused_after (insn, reg))
3048 {
3049 return reg;
3050 }
3051 }
3052
3053 return NULL_RTX;
3054 }
3055
3056
3057 /* Helper function for the next function in the case where only restricted
3058 version of LPM instruction is available. */
3059
3060 static const char*
avr_out_lpm_no_lpmx(rtx_insn * insn,rtx * xop,int * plen)3061 avr_out_lpm_no_lpmx (rtx_insn *insn, rtx *xop, int *plen)
3062 {
3063 rtx dest = xop[0];
3064 rtx addr = xop[1];
3065 int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
3066 int regno_dest;
3067
3068 regno_dest = REGNO (dest);
3069
3070 /* The implicit target register of LPM. */
3071 xop[3] = lpm_reg_rtx;
3072
3073 switch (GET_CODE (addr))
3074 {
3075 default:
3076 gcc_unreachable();
3077
3078 case REG:
3079
3080 gcc_assert (REG_Z == REGNO (addr));
3081
3082 switch (n_bytes)
3083 {
3084 default:
3085 gcc_unreachable();
3086
3087 case 1:
3088 avr_asm_len ("%4lpm", xop, plen, 1);
3089
3090 if (regno_dest != LPM_REGNO)
3091 avr_asm_len ("mov %0,%3", xop, plen, 1);
3092
3093 return "";
3094
3095 case 2:
3096 if (REGNO (dest) == REG_Z)
3097 return avr_asm_len ("%4lpm" CR_TAB
3098 "push %3" CR_TAB
3099 "adiw %2,1" CR_TAB
3100 "%4lpm" CR_TAB
3101 "mov %B0,%3" CR_TAB
3102 "pop %A0", xop, plen, 6);
3103
3104 avr_asm_len ("%4lpm" CR_TAB
3105 "mov %A0,%3" CR_TAB
3106 "adiw %2,1" CR_TAB
3107 "%4lpm" CR_TAB
3108 "mov %B0,%3", xop, plen, 5);
3109
3110 if (!reg_unused_after (insn, addr))
3111 avr_asm_len ("sbiw %2,1", xop, plen, 1);
3112
3113 break; /* 2 */
3114 }
3115
3116 break; /* REG */
3117
3118 case POST_INC:
3119
3120 gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
3121 && n_bytes <= 4);
3122
3123 if (regno_dest == LPM_REGNO)
3124 avr_asm_len ("%4lpm" CR_TAB
3125 "adiw %2,1", xop, plen, 2);
3126 else
3127 avr_asm_len ("%4lpm" CR_TAB
3128 "mov %A0,%3" CR_TAB
3129 "adiw %2,1", xop, plen, 3);
3130
3131 if (n_bytes >= 2)
3132 avr_asm_len ("%4lpm" CR_TAB
3133 "mov %B0,%3" CR_TAB
3134 "adiw %2,1", xop, plen, 3);
3135
3136 if (n_bytes >= 3)
3137 avr_asm_len ("%4lpm" CR_TAB
3138 "mov %C0,%3" CR_TAB
3139 "adiw %2,1", xop, plen, 3);
3140
3141 if (n_bytes >= 4)
3142 avr_asm_len ("%4lpm" CR_TAB
3143 "mov %D0,%3" CR_TAB
3144 "adiw %2,1", xop, plen, 3);
3145
3146 break; /* POST_INC */
3147
3148 } /* switch CODE (addr) */
3149
3150 return "";
3151 }
3152
3153
3154 /* If PLEN == NULL: Ouput instructions to load a value from a memory location
3155 OP[1] in AS1 to register OP[0].
3156 If PLEN != 0 set *PLEN to the length in words of the instruction sequence.
3157 Return "". */
3158
3159 const char*
avr_out_lpm(rtx_insn * insn,rtx * op,int * plen)3160 avr_out_lpm (rtx_insn *insn, rtx *op, int *plen)
3161 {
3162 rtx xop[7];
3163 rtx dest = op[0];
3164 rtx src = SET_SRC (single_set (insn));
3165 rtx addr;
3166 int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
3167 int segment;
3168 RTX_CODE code;
3169 addr_space_t as = MEM_ADDR_SPACE (src);
3170
3171 if (plen)
3172 *plen = 0;
3173
3174 if (MEM_P (dest))
3175 {
3176 warning (0, "writing to address space %qs not supported",
3177 avr_addrspace[MEM_ADDR_SPACE (dest)].name);
3178
3179 return "";
3180 }
3181
3182 addr = XEXP (src, 0);
3183 code = GET_CODE (addr);
3184
3185 gcc_assert (REG_P (dest));
3186 gcc_assert (REG == code || POST_INC == code);
3187
3188 xop[0] = dest;
3189 xop[1] = addr;
3190 xop[2] = lpm_addr_reg_rtx;
3191 xop[4] = xstring_empty;
3192 xop[5] = tmp_reg_rtx;
3193 xop[6] = XEXP (rampz_rtx, 0);
3194
3195 segment = avr_addrspace[as].segment;
3196
3197 /* Set RAMPZ as needed. */
3198
3199 if (segment)
3200 {
3201 xop[4] = GEN_INT (segment);
3202 xop[3] = avr_find_unused_d_reg (insn, lpm_addr_reg_rtx);
3203
3204 if (xop[3] != NULL_RTX)
3205 {
3206 avr_asm_len ("ldi %3,%4" CR_TAB
3207 "out %i6,%3", xop, plen, 2);
3208 }
3209 else if (segment == 1)
3210 {
3211 avr_asm_len ("clr %5" CR_TAB
3212 "inc %5" CR_TAB
3213 "out %i6,%5", xop, plen, 3);
3214 }
3215 else
3216 {
3217 avr_asm_len ("mov %5,%2" CR_TAB
3218 "ldi %2,%4" CR_TAB
3219 "out %i6,%2" CR_TAB
3220 "mov %2,%5", xop, plen, 4);
3221 }
3222
3223 xop[4] = xstring_e;
3224
3225 if (!AVR_HAVE_ELPMX)
3226 return avr_out_lpm_no_lpmx (insn, xop, plen);
3227 }
3228 else if (!AVR_HAVE_LPMX)
3229 {
3230 return avr_out_lpm_no_lpmx (insn, xop, plen);
3231 }
3232
3233 /* We have [E]LPMX: Output reading from Flash the comfortable way. */
3234
3235 switch (GET_CODE (addr))
3236 {
3237 default:
3238 gcc_unreachable();
3239
3240 case REG:
3241
3242 gcc_assert (REG_Z == REGNO (addr));
3243
3244 switch (n_bytes)
3245 {
3246 default:
3247 gcc_unreachable();
3248
3249 case 1:
3250 return avr_asm_len ("%4lpm %0,%a2", xop, plen, 1);
3251
3252 case 2:
3253 if (REGNO (dest) == REG_Z)
3254 return avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3255 "%4lpm %B0,%a2" CR_TAB
3256 "mov %A0,%5", xop, plen, 3);
3257 else
3258 {
3259 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3260 "%4lpm %B0,%a2", xop, plen, 2);
3261
3262 if (!reg_unused_after (insn, addr))
3263 avr_asm_len ("sbiw %2,1", xop, plen, 1);
3264 }
3265
3266 break; /* 2 */
3267
3268 case 3:
3269
3270 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3271 "%4lpm %B0,%a2+" CR_TAB
3272 "%4lpm %C0,%a2", xop, plen, 3);
3273
3274 if (!reg_unused_after (insn, addr))
3275 avr_asm_len ("sbiw %2,2", xop, plen, 1);
3276
3277 break; /* 3 */
3278
3279 case 4:
3280
3281 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3282 "%4lpm %B0,%a2+", xop, plen, 2);
3283
3284 if (REGNO (dest) == REG_Z - 2)
3285 return avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3286 "%4lpm %C0,%a2" CR_TAB
3287 "mov %D0,%5", xop, plen, 3);
3288 else
3289 {
3290 avr_asm_len ("%4lpm %C0,%a2+" CR_TAB
3291 "%4lpm %D0,%a2", xop, plen, 2);
3292
3293 if (!reg_unused_after (insn, addr))
3294 avr_asm_len ("sbiw %2,3", xop, plen, 1);
3295 }
3296
3297 break; /* 4 */
3298 } /* n_bytes */
3299
3300 break; /* REG */
3301
3302 case POST_INC:
3303
3304 gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
3305 && n_bytes <= 4);
3306
3307 avr_asm_len ("%4lpm %A0,%a2+", xop, plen, 1);
3308 if (n_bytes >= 2) avr_asm_len ("%4lpm %B0,%a2+", xop, plen, 1);
3309 if (n_bytes >= 3) avr_asm_len ("%4lpm %C0,%a2+", xop, plen, 1);
3310 if (n_bytes >= 4) avr_asm_len ("%4lpm %D0,%a2+", xop, plen, 1);
3311
3312 break; /* POST_INC */
3313
3314 } /* switch CODE (addr) */
3315
3316 if (xop[4] == xstring_e && AVR_HAVE_RAMPD)
3317 {
3318 /* Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM. */
3319
3320 xop[0] = zero_reg_rtx;
3321 avr_asm_len ("out %i6,%0", xop, plen, 1);
3322 }
3323
3324 return "";
3325 }
3326
3327
3328 /* Worker function for xload_8 insn. */
3329
3330 const char*
avr_out_xload(rtx_insn * insn ATTRIBUTE_UNUSED,rtx * op,int * plen)3331 avr_out_xload (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
3332 {
3333 rtx xop[4];
3334
3335 xop[0] = op[0];
3336 xop[1] = op[1];
3337 xop[2] = lpm_addr_reg_rtx;
3338 xop[3] = AVR_HAVE_LPMX ? op[0] : lpm_reg_rtx;
3339
3340 avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, -1);
3341
3342 avr_asm_len ("sbrc %1,7" CR_TAB
3343 "ld %3,%a2", xop, plen, 2);
3344
3345 if (REGNO (xop[0]) != REGNO (xop[3]))
3346 avr_asm_len ("mov %0,%3", xop, plen, 1);
3347
3348 return "";
3349 }
3350
3351
3352 const char*
output_movqi(rtx_insn * insn,rtx operands[],int * plen)3353 output_movqi (rtx_insn *insn, rtx operands[], int *plen)
3354 {
3355 rtx dest = operands[0];
3356 rtx src = operands[1];
3357
3358 if (avr_mem_flash_p (src)
3359 || avr_mem_flash_p (dest))
3360 {
3361 return avr_out_lpm (insn, operands, plen);
3362 }
3363
3364 gcc_assert (1 == GET_MODE_SIZE (GET_MODE (dest)));
3365
3366 if (REG_P (dest))
3367 {
3368 if (REG_P (src)) /* mov r,r */
3369 {
3370 if (test_hard_reg_class (STACK_REG, dest))
3371 return avr_asm_len ("out %0,%1", operands, plen, -1);
3372 else if (test_hard_reg_class (STACK_REG, src))
3373 return avr_asm_len ("in %0,%1", operands, plen, -1);
3374
3375 return avr_asm_len ("mov %0,%1", operands, plen, -1);
3376 }
3377 else if (CONSTANT_P (src))
3378 {
3379 output_reload_in_const (operands, NULL_RTX, plen, false);
3380 return "";
3381 }
3382 else if (MEM_P (src))
3383 return out_movqi_r_mr (insn, operands, plen); /* mov r,m */
3384 }
3385 else if (MEM_P (dest))
3386 {
3387 rtx xop[2];
3388
3389 xop[0] = dest;
3390 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
3391
3392 return out_movqi_mr_r (insn, xop, plen);
3393 }
3394
3395 return "";
3396 }
3397
3398
3399 const char *
output_movhi(rtx_insn * insn,rtx xop[],int * plen)3400 output_movhi (rtx_insn *insn, rtx xop[], int *plen)
3401 {
3402 rtx dest = xop[0];
3403 rtx src = xop[1];
3404
3405 gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 2);
3406
3407 if (avr_mem_flash_p (src)
3408 || avr_mem_flash_p (dest))
3409 {
3410 return avr_out_lpm (insn, xop, plen);
3411 }
3412
3413 gcc_assert (2 == GET_MODE_SIZE (GET_MODE (dest)));
3414
3415 if (REG_P (dest))
3416 {
3417 if (REG_P (src)) /* mov r,r */
3418 {
3419 if (test_hard_reg_class (STACK_REG, dest))
3420 {
3421 if (AVR_HAVE_8BIT_SP)
3422 return avr_asm_len ("out __SP_L__,%A1", xop, plen, -1);
3423
3424 if (AVR_XMEGA)
3425 return avr_asm_len ("out __SP_L__,%A1" CR_TAB
3426 "out __SP_H__,%B1", xop, plen, -2);
3427
3428 /* Use simple load of SP if no interrupts are used. */
3429
3430 return TARGET_NO_INTERRUPTS
3431 ? avr_asm_len ("out __SP_H__,%B1" CR_TAB
3432 "out __SP_L__,%A1", xop, plen, -2)
3433 : avr_asm_len ("in __tmp_reg__,__SREG__" CR_TAB
3434 "cli" CR_TAB
3435 "out __SP_H__,%B1" CR_TAB
3436 "out __SREG__,__tmp_reg__" CR_TAB
3437 "out __SP_L__,%A1", xop, plen, -5);
3438 }
3439 else if (test_hard_reg_class (STACK_REG, src))
3440 {
3441 return !AVR_HAVE_SPH
3442 ? avr_asm_len ("in %A0,__SP_L__" CR_TAB
3443 "clr %B0", xop, plen, -2)
3444
3445 : avr_asm_len ("in %A0,__SP_L__" CR_TAB
3446 "in %B0,__SP_H__", xop, plen, -2);
3447 }
3448
3449 return AVR_HAVE_MOVW
3450 ? avr_asm_len ("movw %0,%1", xop, plen, -1)
3451
3452 : avr_asm_len ("mov %A0,%A1" CR_TAB
3453 "mov %B0,%B1", xop, plen, -2);
3454 } /* REG_P (src) */
3455 else if (CONSTANT_P (src))
3456 {
3457 return output_reload_inhi (xop, NULL, plen);
3458 }
3459 else if (MEM_P (src))
3460 {
3461 return out_movhi_r_mr (insn, xop, plen); /* mov r,m */
3462 }
3463 }
3464 else if (MEM_P (dest))
3465 {
3466 rtx xop[2];
3467
3468 xop[0] = dest;
3469 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
3470
3471 return out_movhi_mr_r (insn, xop, plen);
3472 }
3473
3474 fatal_insn ("invalid insn:", insn);
3475
3476 return "";
3477 }
3478
3479
3480 /* Same as out_movqi_r_mr, but TINY does not have ADIW or SBIW */
3481
3482 static const char*
avr_out_movqi_r_mr_reg_disp_tiny(rtx_insn * insn,rtx op[],int * plen)3483 avr_out_movqi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
3484 {
3485 rtx dest = op[0];
3486 rtx src = op[1];
3487 rtx x = XEXP (src, 0);
3488
3489 avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
3490 "ld %0,%b1" , op, plen, -3);
3491
3492 if (!reg_overlap_mentioned_p (dest, XEXP (x,0))
3493 && !reg_unused_after (insn, XEXP (x,0)))
3494 avr_asm_len (TINY_SBIW (%I1, %J1, %o1), op, plen, 2);
3495
3496 return "";
3497 }
3498
3499 static const char*
out_movqi_r_mr(rtx_insn * insn,rtx op[],int * plen)3500 out_movqi_r_mr (rtx_insn *insn, rtx op[], int *plen)
3501 {
3502 rtx dest = op[0];
3503 rtx src = op[1];
3504 rtx x = XEXP (src, 0);
3505
3506 if (CONSTANT_ADDRESS_P (x))
3507 {
3508 int n_words = AVR_TINY ? 1 : 2;
3509 return io_address_operand (x, QImode)
3510 ? avr_asm_len ("in %0,%i1", op, plen, -1)
3511 : avr_asm_len ("lds %0,%m1", op, plen, -n_words);
3512 }
3513
3514 if (GET_CODE (x) == PLUS
3515 && REG_P (XEXP (x, 0))
3516 && CONST_INT_P (XEXP (x, 1)))
3517 {
3518 /* memory access by reg+disp */
3519
3520 int disp = INTVAL (XEXP (x, 1));
3521
3522 if (AVR_TINY)
3523 return avr_out_movqi_r_mr_reg_disp_tiny (insn, op, plen);
3524
3525 if (disp - GET_MODE_SIZE (GET_MODE (src)) >= 63)
3526 {
3527 if (REGNO (XEXP (x, 0)) != REG_Y)
3528 fatal_insn ("incorrect insn:",insn);
3529
3530 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
3531 return avr_asm_len ("adiw r28,%o1-63" CR_TAB
3532 "ldd %0,Y+63" CR_TAB
3533 "sbiw r28,%o1-63", op, plen, -3);
3534
3535 return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
3536 "sbci r29,hi8(-%o1)" CR_TAB
3537 "ld %0,Y" CR_TAB
3538 "subi r28,lo8(%o1)" CR_TAB
3539 "sbci r29,hi8(%o1)", op, plen, -5);
3540 }
3541 else if (REGNO (XEXP (x, 0)) == REG_X)
3542 {
3543 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
3544 it but I have this situation with extremal optimizing options. */
3545
3546 avr_asm_len ("adiw r26,%o1" CR_TAB
3547 "ld %0,X", op, plen, -2);
3548
3549 if (!reg_overlap_mentioned_p (dest, XEXP (x,0))
3550 && !reg_unused_after (insn, XEXP (x,0)))
3551 {
3552 avr_asm_len ("sbiw r26,%o1", op, plen, 1);
3553 }
3554
3555 return "";
3556 }
3557
3558 return avr_asm_len ("ldd %0,%1", op, plen, -1);
3559 }
3560
3561 return avr_asm_len ("ld %0,%1", op, plen, -1);
3562 }
3563
3564
3565 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
3566
3567 static const char*
avr_out_movhi_r_mr_reg_no_disp_tiny(rtx op[],int * plen)3568 avr_out_movhi_r_mr_reg_no_disp_tiny (rtx op[], int *plen)
3569 {
3570 rtx dest = op[0];
3571 rtx src = op[1];
3572 rtx base = XEXP (src, 0);
3573
3574 int reg_dest = true_regnum (dest);
3575 int reg_base = true_regnum (base);
3576
3577 if (reg_dest == reg_base) /* R = (R) */
3578 return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
3579 "ld %B0,%1" CR_TAB
3580 "mov %A0,__tmp_reg__", op, plen, -3);
3581
3582 return avr_asm_len ("ld %A0,%1" CR_TAB
3583 TINY_ADIW (%E1, %F1, 1) CR_TAB
3584 "ld %B0,%1" CR_TAB
3585 TINY_SBIW (%E1, %F1, 1), op, plen, -6);
3586 }
3587
3588
3589 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
3590
3591 static const char*
avr_out_movhi_r_mr_reg_disp_tiny(rtx op[],int * plen)3592 avr_out_movhi_r_mr_reg_disp_tiny (rtx op[], int *plen)
3593 {
3594 rtx dest = op[0];
3595 rtx src = op[1];
3596 rtx base = XEXP (src, 0);
3597
3598 int reg_dest = true_regnum (dest);
3599 int reg_base = true_regnum (XEXP (base, 0));
3600
3601 if (reg_base == reg_dest)
3602 {
3603 return avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
3604 "ld __tmp_reg__,%b1+" CR_TAB
3605 "ld %B0,%b1" CR_TAB
3606 "mov %A0,__tmp_reg__", op, plen, -5);
3607 }
3608 else
3609 {
3610 return avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
3611 "ld %A0,%b1+" CR_TAB
3612 "ld %B0,%b1" CR_TAB
3613 TINY_SBIW (%I1, %J1, %o1+1), op, plen, -6);
3614 }
3615 }
3616
3617
3618 /* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
3619
3620 static const char*
avr_out_movhi_r_mr_pre_dec_tiny(rtx_insn * insn,rtx op[],int * plen)3621 avr_out_movhi_r_mr_pre_dec_tiny (rtx_insn *insn, rtx op[], int *plen)
3622 {
3623 int mem_volatile_p = 0;
3624 rtx dest = op[0];
3625 rtx src = op[1];
3626 rtx base = XEXP (src, 0);
3627
3628 /* "volatile" forces reading low byte first, even if less efficient,
3629 for correct operation with 16-bit I/O registers. */
3630 mem_volatile_p = MEM_VOLATILE_P (src);
3631
3632 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
3633 fatal_insn ("incorrect insn:", insn);
3634
3635 if (!mem_volatile_p)
3636 return avr_asm_len ("ld %B0,%1" CR_TAB
3637 "ld %A0,%1", op, plen, -2);
3638
3639 return avr_asm_len (TINY_SBIW (%I1, %J1, 2) CR_TAB
3640 "ld %A0,%p1+" CR_TAB
3641 "ld %B0,%p1" CR_TAB
3642 TINY_SBIW (%I1, %J1, 1), op, plen, -6);
3643 }
3644
3645
3646 static const char*
out_movhi_r_mr(rtx_insn * insn,rtx op[],int * plen)3647 out_movhi_r_mr (rtx_insn *insn, rtx op[], int *plen)
3648 {
3649 rtx dest = op[0];
3650 rtx src = op[1];
3651 rtx base = XEXP (src, 0);
3652 int reg_dest = true_regnum (dest);
3653 int reg_base = true_regnum (base);
3654 /* "volatile" forces reading low byte first, even if less efficient,
3655 for correct operation with 16-bit I/O registers. */
3656 int mem_volatile_p = MEM_VOLATILE_P (src);
3657
3658 if (reg_base > 0)
3659 {
3660 if (AVR_TINY)
3661 return avr_out_movhi_r_mr_reg_no_disp_tiny (op, plen);
3662
3663 if (reg_dest == reg_base) /* R = (R) */
3664 return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
3665 "ld %B0,%1" CR_TAB
3666 "mov %A0,__tmp_reg__", op, plen, -3);
3667
3668 if (reg_base != REG_X)
3669 return avr_asm_len ("ld %A0,%1" CR_TAB
3670 "ldd %B0,%1+1", op, plen, -2);
3671
3672 avr_asm_len ("ld %A0,X+" CR_TAB
3673 "ld %B0,X", op, plen, -2);
3674
3675 if (!reg_unused_after (insn, base))
3676 avr_asm_len ("sbiw r26,1", op, plen, 1);
3677
3678 return "";
3679 }
3680 else if (GET_CODE (base) == PLUS) /* (R + i) */
3681 {
3682 int disp = INTVAL (XEXP (base, 1));
3683 int reg_base = true_regnum (XEXP (base, 0));
3684
3685 if (AVR_TINY)
3686 return avr_out_movhi_r_mr_reg_disp_tiny (op, plen);
3687
3688 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
3689 {
3690 if (REGNO (XEXP (base, 0)) != REG_Y)
3691 fatal_insn ("incorrect insn:",insn);
3692
3693 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (src))
3694 ? avr_asm_len ("adiw r28,%o1-62" CR_TAB
3695 "ldd %A0,Y+62" CR_TAB
3696 "ldd %B0,Y+63" CR_TAB
3697 "sbiw r28,%o1-62", op, plen, -4)
3698
3699 : avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
3700 "sbci r29,hi8(-%o1)" CR_TAB
3701 "ld %A0,Y" CR_TAB
3702 "ldd %B0,Y+1" CR_TAB
3703 "subi r28,lo8(%o1)" CR_TAB
3704 "sbci r29,hi8(%o1)", op, plen, -6);
3705 }
3706
3707 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
3708 it but I have this situation with extremal
3709 optimization options. */
3710
3711 if (reg_base == REG_X)
3712 return reg_base == reg_dest
3713 ? avr_asm_len ("adiw r26,%o1" CR_TAB
3714 "ld __tmp_reg__,X+" CR_TAB
3715 "ld %B0,X" CR_TAB
3716 "mov %A0,__tmp_reg__", op, plen, -4)
3717
3718 : avr_asm_len ("adiw r26,%o1" CR_TAB
3719 "ld %A0,X+" CR_TAB
3720 "ld %B0,X" CR_TAB
3721 "sbiw r26,%o1+1", op, plen, -4);
3722
3723 return reg_base == reg_dest
3724 ? avr_asm_len ("ldd __tmp_reg__,%A1" CR_TAB
3725 "ldd %B0,%B1" CR_TAB
3726 "mov %A0,__tmp_reg__", op, plen, -3)
3727
3728 : avr_asm_len ("ldd %A0,%A1" CR_TAB
3729 "ldd %B0,%B1", op, plen, -2);
3730 }
3731 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
3732 {
3733 if (AVR_TINY)
3734 return avr_out_movhi_r_mr_pre_dec_tiny (insn, op, plen);
3735
3736 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
3737 fatal_insn ("incorrect insn:", insn);
3738
3739 if (!mem_volatile_p)
3740 return avr_asm_len ("ld %B0,%1" CR_TAB
3741 "ld %A0,%1", op, plen, -2);
3742
3743 return REGNO (XEXP (base, 0)) == REG_X
3744 ? avr_asm_len ("sbiw r26,2" CR_TAB
3745 "ld %A0,X+" CR_TAB
3746 "ld %B0,X" CR_TAB
3747 "sbiw r26,1", op, plen, -4)
3748
3749 : avr_asm_len ("sbiw %r1,2" CR_TAB
3750 "ld %A0,%p1" CR_TAB
3751 "ldd %B0,%p1+1", op, plen, -3);
3752 }
3753 else if (GET_CODE (base) == POST_INC) /* (R++) */
3754 {
3755 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
3756 fatal_insn ("incorrect insn:", insn);
3757
3758 return avr_asm_len ("ld %A0,%1" CR_TAB
3759 "ld %B0,%1", op, plen, -2);
3760 }
3761 else if (CONSTANT_ADDRESS_P (base))
3762 {
3763 int n_words = AVR_TINY ? 2 : 4;
3764 return io_address_operand (base, HImode)
3765 ? avr_asm_len ("in %A0,%i1" CR_TAB
3766 "in %B0,%i1+1", op, plen, -2)
3767
3768 : avr_asm_len ("lds %A0,%m1" CR_TAB
3769 "lds %B0,%m1+1", op, plen, -n_words);
3770 }
3771
3772 fatal_insn ("unknown move insn:",insn);
3773 return "";
3774 }
3775
3776 static const char*
avr_out_movsi_r_mr_reg_no_disp_tiny(rtx_insn * insn,rtx op[],int * l)3777 avr_out_movsi_r_mr_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *l)
3778 {
3779 rtx dest = op[0];
3780 rtx src = op[1];
3781 rtx base = XEXP (src, 0);
3782 int reg_dest = true_regnum (dest);
3783 int reg_base = true_regnum (base);
3784
3785 if (reg_dest == reg_base)
3786 {
3787 /* "ld r26,-X" is undefined */
3788 return *l = 9, (TINY_ADIW (%E1, %F1, 3) CR_TAB
3789 "ld %D0,%1" CR_TAB
3790 "ld %C0,-%1" CR_TAB
3791 "ld __tmp_reg__,-%1" CR_TAB
3792 TINY_SBIW (%E1, %F1, 1) CR_TAB
3793 "ld %A0,%1" CR_TAB
3794 "mov %B0,__tmp_reg__");
3795 }
3796 else if (reg_dest == reg_base - 2)
3797 {
3798 return *l = 5, ("ld %A0,%1+" CR_TAB
3799 "ld %B0,%1+" CR_TAB
3800 "ld __tmp_reg__,%1+" CR_TAB
3801 "ld %D0,%1" CR_TAB
3802 "mov %C0,__tmp_reg__");
3803 }
3804 else if (reg_unused_after (insn, base))
3805 {
3806 return *l = 4, ("ld %A0,%1+" CR_TAB
3807 "ld %B0,%1+" CR_TAB
3808 "ld %C0,%1+" CR_TAB
3809 "ld %D0,%1");
3810 }
3811 else
3812 {
3813 return *l = 6, ("ld %A0,%1+" CR_TAB
3814 "ld %B0,%1+" CR_TAB
3815 "ld %C0,%1+" CR_TAB
3816 "ld %D0,%1" CR_TAB
3817 TINY_SBIW (%E1, %F1, 3));
3818 }
3819 }
3820
3821
3822 static const char*
avr_out_movsi_r_mr_reg_disp_tiny(rtx_insn * insn,rtx op[],int * l)3823 avr_out_movsi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *l)
3824 {
3825 rtx dest = op[0];
3826 rtx src = op[1];
3827 rtx base = XEXP (src, 0);
3828 int reg_dest = true_regnum (dest);
3829 int reg_base = true_regnum (XEXP (base, 0));
3830
3831 if (reg_dest == reg_base)
3832 {
3833 /* "ld r26,-X" is undefined */
3834 return *l = 9, (TINY_ADIW (%I1, %J1, %o1+3) CR_TAB
3835 "ld %D0,%b1" CR_TAB
3836 "ld %C0,-%b1" CR_TAB
3837 "ld __tmp_reg__,-%b1" CR_TAB
3838 TINY_SBIW (%I1, %J1, 1) CR_TAB
3839 "ld %A0,%b1" CR_TAB
3840 "mov %B0,__tmp_reg__");
3841 }
3842 else if (reg_dest == reg_base - 2)
3843 {
3844 return *l = 7, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
3845 "ld %A0,%b1+" CR_TAB
3846 "ld %B0,%b1+" CR_TAB
3847 "ld __tmp_reg__,%b1+" CR_TAB
3848 "ld %D0,%b1" CR_TAB
3849 "mov %C0,__tmp_reg__");
3850 }
3851 else if (reg_unused_after (insn, XEXP (base, 0)))
3852 {
3853 return *l = 6, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
3854 "ld %A0,%b1+" CR_TAB
3855 "ld %B0,%b1+" CR_TAB
3856 "ld %C0,%b1+" CR_TAB
3857 "ld %D0,%b1");
3858 }
3859 else
3860 {
3861 return *l = 8, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
3862 "ld %A0,%b1+" CR_TAB
3863 "ld %B0,%b1+" CR_TAB
3864 "ld %C0,%b1+" CR_TAB
3865 "ld %D0,%b1" CR_TAB
3866 TINY_SBIW (%I1, %J1, %o1+3));
3867 }
3868 }
3869
3870 static const char*
out_movsi_r_mr(rtx_insn * insn,rtx op[],int * l)3871 out_movsi_r_mr (rtx_insn *insn, rtx op[], int *l)
3872 {
3873 rtx dest = op[0];
3874 rtx src = op[1];
3875 rtx base = XEXP (src, 0);
3876 int reg_dest = true_regnum (dest);
3877 int reg_base = true_regnum (base);
3878 int tmp;
3879
3880 if (!l)
3881 l = &tmp;
3882
3883 if (reg_base > 0)
3884 {
3885 if (AVR_TINY)
3886 return avr_out_movsi_r_mr_reg_no_disp_tiny (insn, op, l);
3887
3888 if (reg_base == REG_X) /* (R26) */
3889 {
3890 if (reg_dest == REG_X)
3891 /* "ld r26,-X" is undefined */
3892 return *l=7, ("adiw r26,3" CR_TAB
3893 "ld r29,X" CR_TAB
3894 "ld r28,-X" CR_TAB
3895 "ld __tmp_reg__,-X" CR_TAB
3896 "sbiw r26,1" CR_TAB
3897 "ld r26,X" CR_TAB
3898 "mov r27,__tmp_reg__");
3899 else if (reg_dest == REG_X - 2)
3900 return *l=5, ("ld %A0,X+" CR_TAB
3901 "ld %B0,X+" CR_TAB
3902 "ld __tmp_reg__,X+" CR_TAB
3903 "ld %D0,X" CR_TAB
3904 "mov %C0,__tmp_reg__");
3905 else if (reg_unused_after (insn, base))
3906 return *l=4, ("ld %A0,X+" CR_TAB
3907 "ld %B0,X+" CR_TAB
3908 "ld %C0,X+" CR_TAB
3909 "ld %D0,X");
3910 else
3911 return *l=5, ("ld %A0,X+" CR_TAB
3912 "ld %B0,X+" CR_TAB
3913 "ld %C0,X+" CR_TAB
3914 "ld %D0,X" CR_TAB
3915 "sbiw r26,3");
3916 }
3917 else
3918 {
3919 if (reg_dest == reg_base)
3920 return *l=5, ("ldd %D0,%1+3" CR_TAB
3921 "ldd %C0,%1+2" CR_TAB
3922 "ldd __tmp_reg__,%1+1" CR_TAB
3923 "ld %A0,%1" CR_TAB
3924 "mov %B0,__tmp_reg__");
3925 else if (reg_base == reg_dest + 2)
3926 return *l=5, ("ld %A0,%1" CR_TAB
3927 "ldd %B0,%1+1" CR_TAB
3928 "ldd __tmp_reg__,%1+2" CR_TAB
3929 "ldd %D0,%1+3" CR_TAB
3930 "mov %C0,__tmp_reg__");
3931 else
3932 return *l=4, ("ld %A0,%1" CR_TAB
3933 "ldd %B0,%1+1" CR_TAB
3934 "ldd %C0,%1+2" CR_TAB
3935 "ldd %D0,%1+3");
3936 }
3937 }
3938 else if (GET_CODE (base) == PLUS) /* (R + i) */
3939 {
3940 int disp = INTVAL (XEXP (base, 1));
3941
3942 if (AVR_TINY)
3943 return avr_out_movsi_r_mr_reg_disp_tiny (insn, op, l);
3944
3945 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
3946 {
3947 if (REGNO (XEXP (base, 0)) != REG_Y)
3948 fatal_insn ("incorrect insn:",insn);
3949
3950 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
3951 return *l = 6, ("adiw r28,%o1-60" CR_TAB
3952 "ldd %A0,Y+60" CR_TAB
3953 "ldd %B0,Y+61" CR_TAB
3954 "ldd %C0,Y+62" CR_TAB
3955 "ldd %D0,Y+63" CR_TAB
3956 "sbiw r28,%o1-60");
3957
3958 return *l = 8, ("subi r28,lo8(-%o1)" CR_TAB
3959 "sbci r29,hi8(-%o1)" CR_TAB
3960 "ld %A0,Y" CR_TAB
3961 "ldd %B0,Y+1" CR_TAB
3962 "ldd %C0,Y+2" CR_TAB
3963 "ldd %D0,Y+3" CR_TAB
3964 "subi r28,lo8(%o1)" CR_TAB
3965 "sbci r29,hi8(%o1)");
3966 }
3967
3968 reg_base = true_regnum (XEXP (base, 0));
3969 if (reg_base == REG_X)
3970 {
3971 /* R = (X + d) */
3972 if (reg_dest == REG_X)
3973 {
3974 *l = 7;
3975 /* "ld r26,-X" is undefined */
3976 return ("adiw r26,%o1+3" CR_TAB
3977 "ld r29,X" CR_TAB
3978 "ld r28,-X" CR_TAB
3979 "ld __tmp_reg__,-X" CR_TAB
3980 "sbiw r26,1" CR_TAB
3981 "ld r26,X" CR_TAB
3982 "mov r27,__tmp_reg__");
3983 }
3984 *l = 6;
3985 if (reg_dest == REG_X - 2)
3986 return ("adiw r26,%o1" CR_TAB
3987 "ld r24,X+" CR_TAB
3988 "ld r25,X+" CR_TAB
3989 "ld __tmp_reg__,X+" CR_TAB
3990 "ld r27,X" CR_TAB
3991 "mov r26,__tmp_reg__");
3992
3993 return ("adiw r26,%o1" CR_TAB
3994 "ld %A0,X+" CR_TAB
3995 "ld %B0,X+" CR_TAB
3996 "ld %C0,X+" CR_TAB
3997 "ld %D0,X" CR_TAB
3998 "sbiw r26,%o1+3");
3999 }
4000 if (reg_dest == reg_base)
4001 return *l=5, ("ldd %D0,%D1" CR_TAB
4002 "ldd %C0,%C1" CR_TAB
4003 "ldd __tmp_reg__,%B1" CR_TAB
4004 "ldd %A0,%A1" CR_TAB
4005 "mov %B0,__tmp_reg__");
4006 else if (reg_dest == reg_base - 2)
4007 return *l=5, ("ldd %A0,%A1" CR_TAB
4008 "ldd %B0,%B1" CR_TAB
4009 "ldd __tmp_reg__,%C1" CR_TAB
4010 "ldd %D0,%D1" CR_TAB
4011 "mov %C0,__tmp_reg__");
4012 return *l=4, ("ldd %A0,%A1" CR_TAB
4013 "ldd %B0,%B1" CR_TAB
4014 "ldd %C0,%C1" CR_TAB
4015 "ldd %D0,%D1");
4016 }
4017 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4018 return *l=4, ("ld %D0,%1" CR_TAB
4019 "ld %C0,%1" CR_TAB
4020 "ld %B0,%1" CR_TAB
4021 "ld %A0,%1");
4022 else if (GET_CODE (base) == POST_INC) /* (R++) */
4023 return *l=4, ("ld %A0,%1" CR_TAB
4024 "ld %B0,%1" CR_TAB
4025 "ld %C0,%1" CR_TAB
4026 "ld %D0,%1");
4027 else if (CONSTANT_ADDRESS_P (base))
4028 {
4029 if (io_address_operand (base, SImode))
4030 {
4031 *l = 4;
4032 return ("in %A0,%i1" CR_TAB
4033 "in %B0,%i1+1" CR_TAB
4034 "in %C0,%i1+2" CR_TAB
4035 "in %D0,%i1+3");
4036 }
4037 else
4038 {
4039 *l = AVR_TINY ? 4 : 8;
4040 return ("lds %A0,%m1" CR_TAB
4041 "lds %B0,%m1+1" CR_TAB
4042 "lds %C0,%m1+2" CR_TAB
4043 "lds %D0,%m1+3");
4044 }
4045 }
4046
4047 fatal_insn ("unknown move insn:",insn);
4048 return "";
4049 }
4050
4051 static const char*
avr_out_movsi_mr_r_reg_no_disp_tiny(rtx_insn * insn,rtx op[],int * l)4052 avr_out_movsi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *l)
4053 {
4054 rtx dest = op[0];
4055 rtx src = op[1];
4056 rtx base = XEXP (dest, 0);
4057 int reg_base = true_regnum (base);
4058 int reg_src = true_regnum (src);
4059
4060 if (reg_base == reg_src)
4061 {
4062 /* "ld r26,-X" is undefined */
4063 if (reg_unused_after (insn, base))
4064 {
4065 return *l = 7, ("mov __tmp_reg__, %B1" CR_TAB
4066 "st %0,%A1" CR_TAB
4067 TINY_ADIW (%E0, %F0, 1) CR_TAB
4068 "st %0+,__tmp_reg__" CR_TAB
4069 "st %0+,%C1" CR_TAB
4070 "st %0+,%D1");
4071 }
4072 else
4073 {
4074 return *l = 9, ("mov __tmp_reg__, %B1" CR_TAB
4075 "st %0,%A1" CR_TAB
4076 TINY_ADIW (%E0, %F0, 1) CR_TAB
4077 "st %0+,__tmp_reg__" CR_TAB
4078 "st %0+,%C1" CR_TAB
4079 "st %0+,%D1" CR_TAB
4080 TINY_SBIW (%E0, %F0, 3));
4081 }
4082 }
4083 else if (reg_base == reg_src + 2)
4084 {
4085 if (reg_unused_after (insn, base))
4086 return *l = 7, ("mov __zero_reg__,%C1" CR_TAB
4087 "mov __tmp_reg__,%D1" CR_TAB
4088 "st %0+,%A1" CR_TAB
4089 "st %0+,%B1" CR_TAB
4090 "st %0+,__zero_reg__" CR_TAB
4091 "st %0,__tmp_reg__" CR_TAB
4092 "clr __zero_reg__");
4093 else
4094 return *l = 9, ("mov __zero_reg__,%C1" CR_TAB
4095 "mov __tmp_reg__,%D1" CR_TAB
4096 "st %0+,%A1" CR_TAB
4097 "st %0+,%B1" CR_TAB
4098 "st %0+,__zero_reg__" CR_TAB
4099 "st %0,__tmp_reg__" CR_TAB
4100 "clr __zero_reg__" CR_TAB
4101 TINY_SBIW (%E0, %F0, 3));
4102 }
4103
4104 return *l = 6, ("st %0+,%A1" CR_TAB
4105 "st %0+,%B1" CR_TAB
4106 "st %0+,%C1" CR_TAB
4107 "st %0,%D1" CR_TAB
4108 TINY_SBIW (%E0, %F0, 3));
4109 }
4110
4111 static const char*
avr_out_movsi_mr_r_reg_disp_tiny(rtx op[],int * l)4112 avr_out_movsi_mr_r_reg_disp_tiny (rtx op[], int *l)
4113 {
4114 rtx dest = op[0];
4115 rtx src = op[1];
4116 rtx base = XEXP (dest, 0);
4117 int reg_base = REGNO (XEXP (base, 0));
4118 int reg_src =true_regnum (src);
4119
4120 if (reg_base == reg_src)
4121 {
4122 *l = 11;
4123 return ("mov __tmp_reg__,%A2" CR_TAB
4124 "mov __zero_reg__,%B2" CR_TAB
4125 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4126 "st %b0+,__tmp_reg__" CR_TAB
4127 "st %b0+,__zero_reg__" CR_TAB
4128 "st %b0+,%C2" CR_TAB
4129 "st %b0,%D2" CR_TAB
4130 "clr __zero_reg__" CR_TAB
4131 TINY_SBIW (%I0, %J0, %o0+3));
4132 }
4133 else if (reg_src == reg_base - 2)
4134 {
4135 *l = 11;
4136 return ("mov __tmp_reg__,%C2" CR_TAB
4137 "mov __zero_reg__,%D2" CR_TAB
4138 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4139 "st %b0+,%A0" CR_TAB
4140 "st %b0+,%B0" CR_TAB
4141 "st %b0+,__tmp_reg__" CR_TAB
4142 "st %b0,__zero_reg__" CR_TAB
4143 "clr __zero_reg__" CR_TAB
4144 TINY_SBIW (%I0, %J0, %o0+3));
4145 }
4146 *l = 8;
4147 return (TINY_ADIW (%I0, %J0, %o0) CR_TAB
4148 "st %b0+,%A1" CR_TAB
4149 "st %b0+,%B1" CR_TAB
4150 "st %b0+,%C1" CR_TAB
4151 "st %b0,%D1" CR_TAB
4152 TINY_SBIW (%I0, %J0, %o0+3));
4153 }
4154
4155 static const char*
out_movsi_mr_r(rtx_insn * insn,rtx op[],int * l)4156 out_movsi_mr_r (rtx_insn *insn, rtx op[], int *l)
4157 {
4158 rtx dest = op[0];
4159 rtx src = op[1];
4160 rtx base = XEXP (dest, 0);
4161 int reg_base = true_regnum (base);
4162 int reg_src = true_regnum (src);
4163 int tmp;
4164
4165 if (!l)
4166 l = &tmp;
4167
4168 if (CONSTANT_ADDRESS_P (base))
4169 {
4170 if (io_address_operand (base, SImode))
4171 {
4172 return *l=4,("out %i0, %A1" CR_TAB
4173 "out %i0+1,%B1" CR_TAB
4174 "out %i0+2,%C1" CR_TAB
4175 "out %i0+3,%D1");
4176 }
4177 else
4178 {
4179 *l = AVR_TINY ? 4 : 8;
4180 return ("sts %m0,%A1" CR_TAB
4181 "sts %m0+1,%B1" CR_TAB
4182 "sts %m0+2,%C1" CR_TAB
4183 "sts %m0+3,%D1");
4184 }
4185 }
4186
4187 if (reg_base > 0) /* (r) */
4188 {
4189 if (AVR_TINY)
4190 return avr_out_movsi_mr_r_reg_no_disp_tiny (insn, op, l);
4191
4192 if (reg_base == REG_X) /* (R26) */
4193 {
4194 if (reg_src == REG_X)
4195 {
4196 /* "st X+,r26" is undefined */
4197 if (reg_unused_after (insn, base))
4198 return *l=6, ("mov __tmp_reg__,r27" CR_TAB
4199 "st X,r26" CR_TAB
4200 "adiw r26,1" CR_TAB
4201 "st X+,__tmp_reg__" CR_TAB
4202 "st X+,r28" CR_TAB
4203 "st X,r29");
4204 else
4205 return *l=7, ("mov __tmp_reg__,r27" CR_TAB
4206 "st X,r26" CR_TAB
4207 "adiw r26,1" CR_TAB
4208 "st X+,__tmp_reg__" CR_TAB
4209 "st X+,r28" CR_TAB
4210 "st X,r29" CR_TAB
4211 "sbiw r26,3");
4212 }
4213 else if (reg_base == reg_src + 2)
4214 {
4215 if (reg_unused_after (insn, base))
4216 return *l=7, ("mov __zero_reg__,%C1" CR_TAB
4217 "mov __tmp_reg__,%D1" CR_TAB
4218 "st %0+,%A1" CR_TAB
4219 "st %0+,%B1" CR_TAB
4220 "st %0+,__zero_reg__" CR_TAB
4221 "st %0,__tmp_reg__" CR_TAB
4222 "clr __zero_reg__");
4223 else
4224 return *l=8, ("mov __zero_reg__,%C1" CR_TAB
4225 "mov __tmp_reg__,%D1" CR_TAB
4226 "st %0+,%A1" CR_TAB
4227 "st %0+,%B1" CR_TAB
4228 "st %0+,__zero_reg__" CR_TAB
4229 "st %0,__tmp_reg__" CR_TAB
4230 "clr __zero_reg__" CR_TAB
4231 "sbiw r26,3");
4232 }
4233 return *l=5, ("st %0+,%A1" CR_TAB
4234 "st %0+,%B1" CR_TAB
4235 "st %0+,%C1" CR_TAB
4236 "st %0,%D1" CR_TAB
4237 "sbiw r26,3");
4238 }
4239 else
4240 return *l=4, ("st %0,%A1" CR_TAB
4241 "std %0+1,%B1" CR_TAB
4242 "std %0+2,%C1" CR_TAB
4243 "std %0+3,%D1");
4244 }
4245 else if (GET_CODE (base) == PLUS) /* (R + i) */
4246 {
4247 int disp = INTVAL (XEXP (base, 1));
4248
4249 if (AVR_TINY)
4250 return avr_out_movsi_mr_r_reg_disp_tiny (op, l);
4251
4252 reg_base = REGNO (XEXP (base, 0));
4253 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
4254 {
4255 if (reg_base != REG_Y)
4256 fatal_insn ("incorrect insn:",insn);
4257
4258 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
4259 return *l = 6, ("adiw r28,%o0-60" CR_TAB
4260 "std Y+60,%A1" CR_TAB
4261 "std Y+61,%B1" CR_TAB
4262 "std Y+62,%C1" CR_TAB
4263 "std Y+63,%D1" CR_TAB
4264 "sbiw r28,%o0-60");
4265
4266 return *l = 8, ("subi r28,lo8(-%o0)" CR_TAB
4267 "sbci r29,hi8(-%o0)" CR_TAB
4268 "st Y,%A1" CR_TAB
4269 "std Y+1,%B1" CR_TAB
4270 "std Y+2,%C1" CR_TAB
4271 "std Y+3,%D1" CR_TAB
4272 "subi r28,lo8(%o0)" CR_TAB
4273 "sbci r29,hi8(%o0)");
4274 }
4275 if (reg_base == REG_X)
4276 {
4277 /* (X + d) = R */
4278 if (reg_src == REG_X)
4279 {
4280 *l = 9;
4281 return ("mov __tmp_reg__,r26" CR_TAB
4282 "mov __zero_reg__,r27" CR_TAB
4283 "adiw r26,%o0" CR_TAB
4284 "st X+,__tmp_reg__" CR_TAB
4285 "st X+,__zero_reg__" CR_TAB
4286 "st X+,r28" CR_TAB
4287 "st X,r29" CR_TAB
4288 "clr __zero_reg__" CR_TAB
4289 "sbiw r26,%o0+3");
4290 }
4291 else if (reg_src == REG_X - 2)
4292 {
4293 *l = 9;
4294 return ("mov __tmp_reg__,r26" CR_TAB
4295 "mov __zero_reg__,r27" CR_TAB
4296 "adiw r26,%o0" CR_TAB
4297 "st X+,r24" CR_TAB
4298 "st X+,r25" CR_TAB
4299 "st X+,__tmp_reg__" CR_TAB
4300 "st X,__zero_reg__" CR_TAB
4301 "clr __zero_reg__" CR_TAB
4302 "sbiw r26,%o0+3");
4303 }
4304 *l = 6;
4305 return ("adiw r26,%o0" CR_TAB
4306 "st X+,%A1" CR_TAB
4307 "st X+,%B1" CR_TAB
4308 "st X+,%C1" CR_TAB
4309 "st X,%D1" CR_TAB
4310 "sbiw r26,%o0+3");
4311 }
4312 return *l=4, ("std %A0,%A1" CR_TAB
4313 "std %B0,%B1" CR_TAB
4314 "std %C0,%C1" CR_TAB
4315 "std %D0,%D1");
4316 }
4317 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4318 return *l=4, ("st %0,%D1" CR_TAB
4319 "st %0,%C1" CR_TAB
4320 "st %0,%B1" CR_TAB
4321 "st %0,%A1");
4322 else if (GET_CODE (base) == POST_INC) /* (R++) */
4323 return *l=4, ("st %0,%A1" CR_TAB
4324 "st %0,%B1" CR_TAB
4325 "st %0,%C1" CR_TAB
4326 "st %0,%D1");
4327 fatal_insn ("unknown move insn:",insn);
4328 return "";
4329 }
4330
4331 const char *
output_movsisf(rtx_insn * insn,rtx operands[],int * l)4332 output_movsisf (rtx_insn *insn, rtx operands[], int *l)
4333 {
4334 int dummy;
4335 rtx dest = operands[0];
4336 rtx src = operands[1];
4337 int *real_l = l;
4338
4339 if (avr_mem_flash_p (src)
4340 || avr_mem_flash_p (dest))
4341 {
4342 return avr_out_lpm (insn, operands, real_l);
4343 }
4344
4345 if (!l)
4346 l = &dummy;
4347
4348 gcc_assert (4 == GET_MODE_SIZE (GET_MODE (dest)));
4349 if (REG_P (dest))
4350 {
4351 if (REG_P (src)) /* mov r,r */
4352 {
4353 if (true_regnum (dest) > true_regnum (src))
4354 {
4355 if (AVR_HAVE_MOVW)
4356 {
4357 *l = 2;
4358 return ("movw %C0,%C1" CR_TAB
4359 "movw %A0,%A1");
4360 }
4361 *l = 4;
4362 return ("mov %D0,%D1" CR_TAB
4363 "mov %C0,%C1" CR_TAB
4364 "mov %B0,%B1" CR_TAB
4365 "mov %A0,%A1");
4366 }
4367 else
4368 {
4369 if (AVR_HAVE_MOVW)
4370 {
4371 *l = 2;
4372 return ("movw %A0,%A1" CR_TAB
4373 "movw %C0,%C1");
4374 }
4375 *l = 4;
4376 return ("mov %A0,%A1" CR_TAB
4377 "mov %B0,%B1" CR_TAB
4378 "mov %C0,%C1" CR_TAB
4379 "mov %D0,%D1");
4380 }
4381 }
4382 else if (CONSTANT_P (src))
4383 {
4384 return output_reload_insisf (operands, NULL_RTX, real_l);
4385 }
4386 else if (MEM_P (src))
4387 return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
4388 }
4389 else if (MEM_P (dest))
4390 {
4391 const char *templ;
4392
4393 if (src == CONST0_RTX (GET_MODE (dest)))
4394 operands[1] = zero_reg_rtx;
4395
4396 templ = out_movsi_mr_r (insn, operands, real_l);
4397
4398 if (!real_l)
4399 output_asm_insn (templ, operands);
4400
4401 operands[1] = src;
4402 return "";
4403 }
4404 fatal_insn ("invalid insn:", insn);
4405 return "";
4406 }
4407
4408
4409 /* Handle loads of 24-bit types from memory to register. */
4410
4411 static const char*
avr_out_load_psi_reg_no_disp_tiny(rtx_insn * insn,rtx * op,int * plen)4412 avr_out_load_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
4413 {
4414 rtx dest = op[0];
4415 rtx src = op[1];
4416 rtx base = XEXP (src, 0);
4417 int reg_dest = true_regnum (dest);
4418 int reg_base = true_regnum (base);
4419
4420 if (reg_base == reg_dest)
4421 {
4422 return avr_asm_len (TINY_ADIW (%E1, %F1, 2) CR_TAB
4423 "ld %C0,%1" CR_TAB
4424 "ld __tmp_reg__,-%1" CR_TAB
4425 TINY_SBIW (%E1, %F1, 1) CR_TAB
4426 "ld %A0,%1" CR_TAB
4427 "mov %B0,__tmp_reg__", op, plen, -8);
4428 }
4429 else
4430 {
4431 avr_asm_len ("ld %A0,%1+" CR_TAB
4432 "ld %B0,%1+" CR_TAB
4433 "ld %C0,%1", op, plen, -3);
4434
4435 if (reg_dest != reg_base - 2 &&
4436 !reg_unused_after (insn, base))
4437 {
4438 avr_asm_len (TINY_SBIW (%E1, %F1, 2), op, plen, 2);
4439 }
4440 return "";
4441 }
4442 }
4443
4444 static const char*
avr_out_load_psi_reg_disp_tiny(rtx_insn * insn,rtx * op,int * plen)4445 avr_out_load_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
4446 {
4447 rtx dest = op[0];
4448 rtx src = op[1];
4449 rtx base = XEXP (src, 0);
4450 int reg_dest = true_regnum (dest);
4451 int reg_base = true_regnum (base);
4452
4453 reg_base = true_regnum (XEXP (base, 0));
4454 if (reg_base == reg_dest)
4455 {
4456 return avr_asm_len (TINY_ADIW (%I1, %J1, %o1+2) CR_TAB
4457 "ld %C0,%b1" CR_TAB
4458 "ld __tmp_reg__,-%b1" CR_TAB
4459 TINY_SBIW (%I1, %J1, 1) CR_TAB
4460 "ld %A0,%b1" CR_TAB
4461 "mov %B0,__tmp_reg__", op, plen, -8);
4462 }
4463 else
4464 {
4465 avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4466 "ld %A0,%b1+" CR_TAB
4467 "ld %B0,%b1+" CR_TAB
4468 "ld %C0,%b1", op, plen, -5);
4469
4470 if (reg_dest != (reg_base - 2)
4471 && !reg_unused_after (insn, XEXP (base, 0)))
4472 avr_asm_len (TINY_SBIW (%I1, %J1, %o1+2), op, plen, 2);
4473
4474 return "";
4475 }
4476 }
4477
4478 static const char*
avr_out_load_psi(rtx_insn * insn,rtx * op,int * plen)4479 avr_out_load_psi (rtx_insn *insn, rtx *op, int *plen)
4480 {
4481 rtx dest = op[0];
4482 rtx src = op[1];
4483 rtx base = XEXP (src, 0);
4484 int reg_dest = true_regnum (dest);
4485 int reg_base = true_regnum (base);
4486
4487 if (reg_base > 0)
4488 {
4489 if (AVR_TINY)
4490 return avr_out_load_psi_reg_no_disp_tiny (insn, op, plen);
4491
4492 if (reg_base == REG_X) /* (R26) */
4493 {
4494 if (reg_dest == REG_X)
4495 /* "ld r26,-X" is undefined */
4496 return avr_asm_len ("adiw r26,2" CR_TAB
4497 "ld r28,X" CR_TAB
4498 "ld __tmp_reg__,-X" CR_TAB
4499 "sbiw r26,1" CR_TAB
4500 "ld r26,X" CR_TAB
4501 "mov r27,__tmp_reg__", op, plen, -6);
4502 else
4503 {
4504 avr_asm_len ("ld %A0,X+" CR_TAB
4505 "ld %B0,X+" CR_TAB
4506 "ld %C0,X", op, plen, -3);
4507
4508 if (reg_dest != REG_X - 2
4509 && !reg_unused_after (insn, base))
4510 {
4511 avr_asm_len ("sbiw r26,2", op, plen, 1);
4512 }
4513
4514 return "";
4515 }
4516 }
4517 else /* reg_base != REG_X */
4518 {
4519 if (reg_dest == reg_base)
4520 return avr_asm_len ("ldd %C0,%1+2" CR_TAB
4521 "ldd __tmp_reg__,%1+1" CR_TAB
4522 "ld %A0,%1" CR_TAB
4523 "mov %B0,__tmp_reg__", op, plen, -4);
4524 else
4525 return avr_asm_len ("ld %A0,%1" CR_TAB
4526 "ldd %B0,%1+1" CR_TAB
4527 "ldd %C0,%1+2", op, plen, -3);
4528 }
4529 }
4530 else if (GET_CODE (base) == PLUS) /* (R + i) */
4531 {
4532 int disp = INTVAL (XEXP (base, 1));
4533
4534 if (AVR_TINY)
4535 return avr_out_load_psi_reg_disp_tiny (insn, op, plen);
4536
4537 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
4538 {
4539 if (REGNO (XEXP (base, 0)) != REG_Y)
4540 fatal_insn ("incorrect insn:",insn);
4541
4542 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
4543 return avr_asm_len ("adiw r28,%o1-61" CR_TAB
4544 "ldd %A0,Y+61" CR_TAB
4545 "ldd %B0,Y+62" CR_TAB
4546 "ldd %C0,Y+63" CR_TAB
4547 "sbiw r28,%o1-61", op, plen, -5);
4548
4549 return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
4550 "sbci r29,hi8(-%o1)" CR_TAB
4551 "ld %A0,Y" CR_TAB
4552 "ldd %B0,Y+1" CR_TAB
4553 "ldd %C0,Y+2" CR_TAB
4554 "subi r28,lo8(%o1)" CR_TAB
4555 "sbci r29,hi8(%o1)", op, plen, -7);
4556 }
4557
4558 reg_base = true_regnum (XEXP (base, 0));
4559 if (reg_base == REG_X)
4560 {
4561 /* R = (X + d) */
4562 if (reg_dest == REG_X)
4563 {
4564 /* "ld r26,-X" is undefined */
4565 return avr_asm_len ("adiw r26,%o1+2" CR_TAB
4566 "ld r28,X" CR_TAB
4567 "ld __tmp_reg__,-X" CR_TAB
4568 "sbiw r26,1" CR_TAB
4569 "ld r26,X" CR_TAB
4570 "mov r27,__tmp_reg__", op, plen, -6);
4571 }
4572
4573 avr_asm_len ("adiw r26,%o1" CR_TAB
4574 "ld %A0,X+" CR_TAB
4575 "ld %B0,X+" CR_TAB
4576 "ld %C0,X", op, plen, -4);
4577
4578 if (reg_dest != REG_W
4579 && !reg_unused_after (insn, XEXP (base, 0)))
4580 avr_asm_len ("sbiw r26,%o1+2", op, plen, 1);
4581
4582 return "";
4583 }
4584
4585 if (reg_dest == reg_base)
4586 return avr_asm_len ("ldd %C0,%C1" CR_TAB
4587 "ldd __tmp_reg__,%B1" CR_TAB
4588 "ldd %A0,%A1" CR_TAB
4589 "mov %B0,__tmp_reg__", op, plen, -4);
4590
4591 return avr_asm_len ("ldd %A0,%A1" CR_TAB
4592 "ldd %B0,%B1" CR_TAB
4593 "ldd %C0,%C1", op, plen, -3);
4594 }
4595 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4596 return avr_asm_len ("ld %C0,%1" CR_TAB
4597 "ld %B0,%1" CR_TAB
4598 "ld %A0,%1", op, plen, -3);
4599 else if (GET_CODE (base) == POST_INC) /* (R++) */
4600 return avr_asm_len ("ld %A0,%1" CR_TAB
4601 "ld %B0,%1" CR_TAB
4602 "ld %C0,%1", op, plen, -3);
4603
4604 else if (CONSTANT_ADDRESS_P (base))
4605 {
4606 int n_words = AVR_TINY ? 3 : 6;
4607 return avr_asm_len ("lds %A0,%m1" CR_TAB
4608 "lds %B0,%m1+1" CR_TAB
4609 "lds %C0,%m1+2", op, plen , -n_words);
4610 }
4611
4612 fatal_insn ("unknown move insn:",insn);
4613 return "";
4614 }
4615
4616
4617 static const char*
avr_out_store_psi_reg_no_disp_tiny(rtx_insn * insn,rtx * op,int * plen)4618 avr_out_store_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
4619 {
4620 rtx dest = op[0];
4621 rtx src = op[1];
4622 rtx base = XEXP (dest, 0);
4623 int reg_base = true_regnum (base);
4624 int reg_src = true_regnum (src);
4625
4626 if (reg_base == reg_src)
4627 {
4628 avr_asm_len ("st %0,%A1" CR_TAB
4629 "mov __tmp_reg__,%B1" CR_TAB
4630 TINY_ADIW (%E0, %F0, 1) CR_TAB /* st X+, r27 is undefined */
4631 "st %0+,__tmp_reg__" CR_TAB
4632 "st %0,%C1", op, plen, -6);
4633
4634 }
4635 else if (reg_src == reg_base - 2)
4636 {
4637 avr_asm_len ("st %0,%A1" CR_TAB
4638 "mov __tmp_reg__,%C1" CR_TAB
4639 TINY_ADIW (%E0, %F0, 1) CR_TAB
4640 "st %0+,%B1" CR_TAB
4641 "st %0,__tmp_reg__", op, plen, 6);
4642 }
4643 else
4644 {
4645 avr_asm_len ("st %0+,%A1" CR_TAB
4646 "st %0+,%B1" CR_TAB
4647 "st %0,%C1", op, plen, -3);
4648 }
4649
4650 if (!reg_unused_after (insn, base))
4651 avr_asm_len (TINY_SBIW (%E0, %F0, 2), op, plen, 2);
4652
4653 return "";
4654 }
4655
4656 static const char*
avr_out_store_psi_reg_disp_tiny(rtx * op,int * plen)4657 avr_out_store_psi_reg_disp_tiny (rtx *op, int *plen)
4658 {
4659 rtx dest = op[0];
4660 rtx src = op[1];
4661 rtx base = XEXP (dest, 0);
4662 int reg_base = REGNO (XEXP (base, 0));
4663 int reg_src = true_regnum (src);
4664
4665 if (reg_src == reg_base)
4666 {
4667 return avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
4668 "mov __zero_reg__,%B1" CR_TAB
4669 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4670 "st %b0+,__tmp_reg__" CR_TAB
4671 "st %b0+,__zero_reg__" CR_TAB
4672 "st %b0,%C1" CR_TAB
4673 "clr __zero_reg__" CR_TAB
4674 TINY_SBIW (%I0, %J0, %o0+2), op, plen, -10);
4675 }
4676 else if (reg_src == reg_base - 2)
4677 {
4678 return avr_asm_len ("mov __tmp_reg__,%C1" CR_TAB
4679 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4680 "st %b0+,%A1" CR_TAB
4681 "st %b0+,%B1" CR_TAB
4682 "st %b0,__tmp_reg__" CR_TAB
4683 TINY_SBIW (%I0, %J0, %o0+2), op, plen, -8);
4684 }
4685
4686 return avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
4687 "st %b0+,%A1" CR_TAB
4688 "st %b0+,%B1" CR_TAB
4689 "st %b0,%C1" CR_TAB
4690 TINY_SBIW (%I0, %J0, %o0+2), op, plen, -7);
4691 }
4692
4693 /* Handle store of 24-bit type from register or zero to memory. */
4694
4695 static const char*
avr_out_store_psi(rtx_insn * insn,rtx * op,int * plen)4696 avr_out_store_psi (rtx_insn *insn, rtx *op, int *plen)
4697 {
4698 rtx dest = op[0];
4699 rtx src = op[1];
4700 rtx base = XEXP (dest, 0);
4701 int reg_base = true_regnum (base);
4702
4703 if (CONSTANT_ADDRESS_P (base))
4704 {
4705 int n_words = AVR_TINY ? 3 : 6;
4706 return avr_asm_len ("sts %m0,%A1" CR_TAB
4707 "sts %m0+1,%B1" CR_TAB
4708 "sts %m0+2,%C1", op, plen, -n_words);
4709 }
4710
4711 if (reg_base > 0) /* (r) */
4712 {
4713 if (AVR_TINY)
4714 return avr_out_store_psi_reg_no_disp_tiny (insn, op, plen);
4715
4716 if (reg_base == REG_X) /* (R26) */
4717 {
4718 gcc_assert (!reg_overlap_mentioned_p (base, src));
4719
4720 avr_asm_len ("st %0+,%A1" CR_TAB
4721 "st %0+,%B1" CR_TAB
4722 "st %0,%C1", op, plen, -3);
4723
4724 if (!reg_unused_after (insn, base))
4725 avr_asm_len ("sbiw r26,2", op, plen, 1);
4726
4727 return "";
4728 }
4729 else
4730 return avr_asm_len ("st %0,%A1" CR_TAB
4731 "std %0+1,%B1" CR_TAB
4732 "std %0+2,%C1", op, plen, -3);
4733 }
4734 else if (GET_CODE (base) == PLUS) /* (R + i) */
4735 {
4736 int disp = INTVAL (XEXP (base, 1));
4737
4738 if (AVR_TINY)
4739 return avr_out_store_psi_reg_disp_tiny (op, plen);
4740
4741 reg_base = REGNO (XEXP (base, 0));
4742
4743 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
4744 {
4745 if (reg_base != REG_Y)
4746 fatal_insn ("incorrect insn:",insn);
4747
4748 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
4749 return avr_asm_len ("adiw r28,%o0-61" CR_TAB
4750 "std Y+61,%A1" CR_TAB
4751 "std Y+62,%B1" CR_TAB
4752 "std Y+63,%C1" CR_TAB
4753 "sbiw r28,%o0-61", op, plen, -5);
4754
4755 return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
4756 "sbci r29,hi8(-%o0)" CR_TAB
4757 "st Y,%A1" CR_TAB
4758 "std Y+1,%B1" CR_TAB
4759 "std Y+2,%C1" CR_TAB
4760 "subi r28,lo8(%o0)" CR_TAB
4761 "sbci r29,hi8(%o0)", op, plen, -7);
4762 }
4763 if (reg_base == REG_X)
4764 {
4765 /* (X + d) = R */
4766 gcc_assert (!reg_overlap_mentioned_p (XEXP (base, 0), src));
4767
4768 avr_asm_len ("adiw r26,%o0" CR_TAB
4769 "st X+,%A1" CR_TAB
4770 "st X+,%B1" CR_TAB
4771 "st X,%C1", op, plen, -4);
4772
4773 if (!reg_unused_after (insn, XEXP (base, 0)))
4774 avr_asm_len ("sbiw r26,%o0+2", op, plen, 1);
4775
4776 return "";
4777 }
4778
4779 return avr_asm_len ("std %A0,%A1" CR_TAB
4780 "std %B0,%B1" CR_TAB
4781 "std %C0,%C1", op, plen, -3);
4782 }
4783 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4784 return avr_asm_len ("st %0,%C1" CR_TAB
4785 "st %0,%B1" CR_TAB
4786 "st %0,%A1", op, plen, -3);
4787 else if (GET_CODE (base) == POST_INC) /* (R++) */
4788 return avr_asm_len ("st %0,%A1" CR_TAB
4789 "st %0,%B1" CR_TAB
4790 "st %0,%C1", op, plen, -3);
4791
4792 fatal_insn ("unknown move insn:",insn);
4793 return "";
4794 }
4795
4796
4797 /* Move around 24-bit stuff. */
4798
4799 const char *
avr_out_movpsi(rtx_insn * insn,rtx * op,int * plen)4800 avr_out_movpsi (rtx_insn *insn, rtx *op, int *plen)
4801 {
4802 rtx dest = op[0];
4803 rtx src = op[1];
4804
4805 if (avr_mem_flash_p (src)
4806 || avr_mem_flash_p (dest))
4807 {
4808 return avr_out_lpm (insn, op, plen);
4809 }
4810
4811 if (register_operand (dest, VOIDmode))
4812 {
4813 if (register_operand (src, VOIDmode)) /* mov r,r */
4814 {
4815 if (true_regnum (dest) > true_regnum (src))
4816 {
4817 avr_asm_len ("mov %C0,%C1", op, plen, -1);
4818
4819 if (AVR_HAVE_MOVW)
4820 return avr_asm_len ("movw %A0,%A1", op, plen, 1);
4821 else
4822 return avr_asm_len ("mov %B0,%B1" CR_TAB
4823 "mov %A0,%A1", op, plen, 2);
4824 }
4825 else
4826 {
4827 if (AVR_HAVE_MOVW)
4828 avr_asm_len ("movw %A0,%A1", op, plen, -1);
4829 else
4830 avr_asm_len ("mov %A0,%A1" CR_TAB
4831 "mov %B0,%B1", op, plen, -2);
4832
4833 return avr_asm_len ("mov %C0,%C1", op, plen, 1);
4834 }
4835 }
4836 else if (CONSTANT_P (src))
4837 {
4838 return avr_out_reload_inpsi (op, NULL_RTX, plen);
4839 }
4840 else if (MEM_P (src))
4841 return avr_out_load_psi (insn, op, plen); /* mov r,m */
4842 }
4843 else if (MEM_P (dest))
4844 {
4845 rtx xop[2];
4846
4847 xop[0] = dest;
4848 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
4849
4850 return avr_out_store_psi (insn, xop, plen);
4851 }
4852
4853 fatal_insn ("invalid insn:", insn);
4854 return "";
4855 }
4856
4857 static const char*
avr_out_movqi_mr_r_reg_disp_tiny(rtx_insn * insn,rtx op[],int * plen)4858 avr_out_movqi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
4859 {
4860 rtx dest = op[0];
4861 rtx src = op[1];
4862 rtx x = XEXP (dest, 0);
4863
4864 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
4865 {
4866 avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
4867 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4868 "st %b0,__tmp_reg__", op, plen, -4);
4869 }
4870 else
4871 {
4872 avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
4873 "st %b0,%1" , op, plen, -3);
4874 }
4875
4876 if (!reg_unused_after (insn, XEXP (x,0)))
4877 avr_asm_len (TINY_SBIW (%I0, %J0, %o0), op, plen, 2);
4878
4879 return "";
4880 }
4881
4882 static const char*
out_movqi_mr_r(rtx_insn * insn,rtx op[],int * plen)4883 out_movqi_mr_r (rtx_insn *insn, rtx op[], int *plen)
4884 {
4885 rtx dest = op[0];
4886 rtx src = op[1];
4887 rtx x = XEXP (dest, 0);
4888
4889 if (CONSTANT_ADDRESS_P (x))
4890 {
4891 int n_words = AVR_TINY ? 1 : 2;
4892 return io_address_operand (x, QImode)
4893 ? avr_asm_len ("out %i0,%1", op, plen, -1)
4894 : avr_asm_len ("sts %m0,%1", op, plen, -n_words);
4895 }
4896 else if (GET_CODE (x) == PLUS
4897 && REG_P (XEXP (x, 0))
4898 && CONST_INT_P (XEXP (x, 1)))
4899 {
4900 /* memory access by reg+disp */
4901
4902 int disp = INTVAL (XEXP (x, 1));
4903
4904 if (AVR_TINY)
4905 return avr_out_movqi_mr_r_reg_disp_tiny (insn, op, plen);
4906
4907 if (disp - GET_MODE_SIZE (GET_MODE (dest)) >= 63)
4908 {
4909 if (REGNO (XEXP (x, 0)) != REG_Y)
4910 fatal_insn ("incorrect insn:",insn);
4911
4912 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
4913 return avr_asm_len ("adiw r28,%o0-63" CR_TAB
4914 "std Y+63,%1" CR_TAB
4915 "sbiw r28,%o0-63", op, plen, -3);
4916
4917 return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
4918 "sbci r29,hi8(-%o0)" CR_TAB
4919 "st Y,%1" CR_TAB
4920 "subi r28,lo8(%o0)" CR_TAB
4921 "sbci r29,hi8(%o0)", op, plen, -5);
4922 }
4923 else if (REGNO (XEXP (x,0)) == REG_X)
4924 {
4925 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
4926 {
4927 avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
4928 "adiw r26,%o0" CR_TAB
4929 "st X,__tmp_reg__", op, plen, -3);
4930 }
4931 else
4932 {
4933 avr_asm_len ("adiw r26,%o0" CR_TAB
4934 "st X,%1", op, plen, -2);
4935 }
4936
4937 if (!reg_unused_after (insn, XEXP (x,0)))
4938 avr_asm_len ("sbiw r26,%o0", op, plen, 1);
4939
4940 return "";
4941 }
4942
4943 return avr_asm_len ("std %0,%1", op, plen, -1);
4944 }
4945
4946 return avr_asm_len ("st %0,%1", op, plen, -1);
4947 }
4948
4949
4950 /* Helper for the next function for XMEGA. It does the same
4951 but with low byte first. */
4952
4953 static const char*
avr_out_movhi_mr_r_xmega(rtx_insn * insn,rtx op[],int * plen)4954 avr_out_movhi_mr_r_xmega (rtx_insn *insn, rtx op[], int *plen)
4955 {
4956 rtx dest = op[0];
4957 rtx src = op[1];
4958 rtx base = XEXP (dest, 0);
4959 int reg_base = true_regnum (base);
4960 int reg_src = true_regnum (src);
4961
4962 /* "volatile" forces writing low byte first, even if less efficient,
4963 for correct operation with 16-bit I/O registers like SP. */
4964 int mem_volatile_p = MEM_VOLATILE_P (dest);
4965
4966 if (CONSTANT_ADDRESS_P (base))
4967 {
4968 return io_address_operand (base, HImode)
4969 ? avr_asm_len ("out %i0,%A1" CR_TAB
4970 "out %i0+1,%B1", op, plen, -2)
4971
4972 : avr_asm_len ("sts %m0,%A1" CR_TAB
4973 "sts %m0+1,%B1", op, plen, -4);
4974 }
4975
4976 if (reg_base > 0)
4977 {
4978 if (reg_base != REG_X)
4979 return avr_asm_len ("st %0,%A1" CR_TAB
4980 "std %0+1,%B1", op, plen, -2);
4981
4982 if (reg_src == REG_X)
4983 /* "st X+,r26" and "st -X,r26" are undefined. */
4984 avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
4985 "st X,r26" CR_TAB
4986 "adiw r26,1" CR_TAB
4987 "st X,__tmp_reg__", op, plen, -4);
4988 else
4989 avr_asm_len ("st X+,%A1" CR_TAB
4990 "st X,%B1", op, plen, -2);
4991
4992 return reg_unused_after (insn, base)
4993 ? ""
4994 : avr_asm_len ("sbiw r26,1", op, plen, 1);
4995 }
4996 else if (GET_CODE (base) == PLUS)
4997 {
4998 int disp = INTVAL (XEXP (base, 1));
4999 reg_base = REGNO (XEXP (base, 0));
5000 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5001 {
5002 if (reg_base != REG_Y)
5003 fatal_insn ("incorrect insn:",insn);
5004
5005 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
5006 ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
5007 "std Y+62,%A1" CR_TAB
5008 "std Y+63,%B1" CR_TAB
5009 "sbiw r28,%o0-62", op, plen, -4)
5010
5011 : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5012 "sbci r29,hi8(-%o0)" CR_TAB
5013 "st Y,%A1" CR_TAB
5014 "std Y+1,%B1" CR_TAB
5015 "subi r28,lo8(%o0)" CR_TAB
5016 "sbci r29,hi8(%o0)", op, plen, -6);
5017 }
5018
5019 if (reg_base != REG_X)
5020 return avr_asm_len ("std %A0,%A1" CR_TAB
5021 "std %B0,%B1", op, plen, -2);
5022 /* (X + d) = R */
5023 return reg_src == REG_X
5024 ? avr_asm_len ("mov __tmp_reg__,r26" CR_TAB
5025 "mov __zero_reg__,r27" CR_TAB
5026 "adiw r26,%o0" CR_TAB
5027 "st X+,__tmp_reg__" CR_TAB
5028 "st X,__zero_reg__" CR_TAB
5029 "clr __zero_reg__" CR_TAB
5030 "sbiw r26,%o0+1", op, plen, -7)
5031
5032 : avr_asm_len ("adiw r26,%o0" CR_TAB
5033 "st X+,%A1" CR_TAB
5034 "st X,%B1" CR_TAB
5035 "sbiw r26,%o0+1", op, plen, -4);
5036 }
5037 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5038 {
5039 if (!mem_volatile_p)
5040 return avr_asm_len ("st %0,%B1" CR_TAB
5041 "st %0,%A1", op, plen, -2);
5042
5043 return REGNO (XEXP (base, 0)) == REG_X
5044 ? avr_asm_len ("sbiw r26,2" CR_TAB
5045 "st X+,%A1" CR_TAB
5046 "st X,%B1" CR_TAB
5047 "sbiw r26,1", op, plen, -4)
5048
5049 : avr_asm_len ("sbiw %r0,2" CR_TAB
5050 "st %p0,%A1" CR_TAB
5051 "std %p0+1,%B1", op, plen, -3);
5052 }
5053 else if (GET_CODE (base) == POST_INC) /* (R++) */
5054 {
5055 return avr_asm_len ("st %0,%A1" CR_TAB
5056 "st %0,%B1", op, plen, -2);
5057
5058 }
5059 fatal_insn ("unknown move insn:",insn);
5060 return "";
5061 }
5062
5063 static const char*
avr_out_movhi_mr_r_reg_no_disp_tiny(rtx_insn * insn,rtx op[],int * plen)5064 avr_out_movhi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5065 {
5066 rtx dest = op[0];
5067 rtx src = op[1];
5068 rtx base = XEXP (dest, 0);
5069 int reg_base = true_regnum (base);
5070 int reg_src = true_regnum (src);
5071 int mem_volatile_p = MEM_VOLATILE_P (dest);
5072
5073 if (reg_base == reg_src)
5074 {
5075 return !mem_volatile_p && reg_unused_after (insn, src)
5076 ? avr_asm_len ("mov __tmp_reg__,%B1" CR_TAB
5077 "st %0,%A1" CR_TAB
5078 TINY_ADIW (%E0, %F0, 1) CR_TAB
5079 "st %0,__tmp_reg__", op, plen, -5)
5080 : avr_asm_len ("mov __tmp_reg__,%B1" CR_TAB
5081 TINY_ADIW (%E0, %F0, 1) CR_TAB
5082 "st %0,__tmp_reg__" CR_TAB
5083 TINY_SBIW (%E0, %F0, 1) CR_TAB
5084 "st %0, %A1", op, plen, -7);
5085 }
5086
5087 return !mem_volatile_p && reg_unused_after (insn, base)
5088 ? avr_asm_len ("st %0+,%A1" CR_TAB
5089 "st %0,%B1", op, plen, -2)
5090 : avr_asm_len (TINY_ADIW (%E0, %F0, 1) CR_TAB
5091 "st %0,%B1" CR_TAB
5092 "st -%0,%A1", op, plen, -4);
5093 }
5094
5095 static const char*
avr_out_movhi_mr_r_reg_disp_tiny(rtx op[],int * plen)5096 avr_out_movhi_mr_r_reg_disp_tiny (rtx op[], int *plen)
5097 {
5098 rtx dest = op[0];
5099 rtx src = op[1];
5100 rtx base = XEXP (dest, 0);
5101 int reg_base = REGNO (XEXP (base, 0));
5102 int reg_src = true_regnum (src);
5103
5104 return reg_src == reg_base
5105 ? avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
5106 "mov __zero_reg__,%B1" CR_TAB
5107 TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
5108 "st %b0,__zero_reg__" CR_TAB
5109 "st -%b0,__tmp_reg__" CR_TAB
5110 "clr __zero_reg__" CR_TAB
5111 TINY_SBIW (%I0, %J0, %o0), op, plen, -9)
5112
5113 : avr_asm_len (TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
5114 "st %b0,%B1" CR_TAB
5115 "st -%b0,%A1" CR_TAB
5116 TINY_SBIW (%I0, %J0, %o0), op, plen, -6);
5117 }
5118
5119 static const char*
avr_out_movhi_mr_r_post_inc_tiny(rtx op[],int * plen)5120 avr_out_movhi_mr_r_post_inc_tiny (rtx op[], int *plen)
5121 {
5122 return avr_asm_len (TINY_ADIW (%I0, %J0, 1) CR_TAB
5123 "st %p0,%B1" CR_TAB
5124 "st -%p0,%A1" CR_TAB
5125 TINY_ADIW (%I0, %J0, 2), op, plen, -6);
5126 }
5127
5128 static const char*
out_movhi_mr_r(rtx_insn * insn,rtx op[],int * plen)5129 out_movhi_mr_r (rtx_insn *insn, rtx op[], int *plen)
5130 {
5131 rtx dest = op[0];
5132 rtx src = op[1];
5133 rtx base = XEXP (dest, 0);
5134 int reg_base = true_regnum (base);
5135 int reg_src = true_regnum (src);
5136 int mem_volatile_p;
5137
5138 /* "volatile" forces writing high-byte first (no-xmega) resp.
5139 low-byte first (xmega) even if less efficient, for correct
5140 operation with 16-bit I/O registers like. */
5141
5142 if (AVR_XMEGA)
5143 return avr_out_movhi_mr_r_xmega (insn, op, plen);
5144
5145 mem_volatile_p = MEM_VOLATILE_P (dest);
5146
5147 if (CONSTANT_ADDRESS_P (base))
5148 {
5149 int n_words = AVR_TINY ? 2 : 4;
5150 return io_address_operand (base, HImode)
5151 ? avr_asm_len ("out %i0+1,%B1" CR_TAB
5152 "out %i0,%A1", op, plen, -2)
5153
5154 : avr_asm_len ("sts %m0+1,%B1" CR_TAB
5155 "sts %m0,%A1", op, plen, -n_words);
5156 }
5157
5158 if (reg_base > 0)
5159 {
5160 if (AVR_TINY)
5161 return avr_out_movhi_mr_r_reg_no_disp_tiny (insn, op, plen);
5162
5163 if (reg_base != REG_X)
5164 return avr_asm_len ("std %0+1,%B1" CR_TAB
5165 "st %0,%A1", op, plen, -2);
5166
5167 if (reg_src == REG_X)
5168 /* "st X+,r26" and "st -X,r26" are undefined. */
5169 return !mem_volatile_p && reg_unused_after (insn, src)
5170 ? avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5171 "st X,r26" CR_TAB
5172 "adiw r26,1" CR_TAB
5173 "st X,__tmp_reg__", op, plen, -4)
5174
5175 : avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5176 "adiw r26,1" CR_TAB
5177 "st X,__tmp_reg__" CR_TAB
5178 "sbiw r26,1" CR_TAB
5179 "st X,r26", op, plen, -5);
5180
5181 return !mem_volatile_p && reg_unused_after (insn, base)
5182 ? avr_asm_len ("st X+,%A1" CR_TAB
5183 "st X,%B1", op, plen, -2)
5184 : avr_asm_len ("adiw r26,1" CR_TAB
5185 "st X,%B1" CR_TAB
5186 "st -X,%A1", op, plen, -3);
5187 }
5188 else if (GET_CODE (base) == PLUS)
5189 {
5190 int disp = INTVAL (XEXP (base, 1));
5191
5192 if (AVR_TINY)
5193 return avr_out_movhi_mr_r_reg_disp_tiny (op, plen);
5194
5195 reg_base = REGNO (XEXP (base, 0));
5196 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5197 {
5198 if (reg_base != REG_Y)
5199 fatal_insn ("incorrect insn:",insn);
5200
5201 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
5202 ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
5203 "std Y+63,%B1" CR_TAB
5204 "std Y+62,%A1" CR_TAB
5205 "sbiw r28,%o0-62", op, plen, -4)
5206
5207 : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5208 "sbci r29,hi8(-%o0)" CR_TAB
5209 "std Y+1,%B1" CR_TAB
5210 "st Y,%A1" CR_TAB
5211 "subi r28,lo8(%o0)" CR_TAB
5212 "sbci r29,hi8(%o0)", op, plen, -6);
5213 }
5214
5215 if (reg_base != REG_X)
5216 return avr_asm_len ("std %B0,%B1" CR_TAB
5217 "std %A0,%A1", op, plen, -2);
5218 /* (X + d) = R */
5219 return reg_src == REG_X
5220 ? avr_asm_len ("mov __tmp_reg__,r26" CR_TAB
5221 "mov __zero_reg__,r27" CR_TAB
5222 "adiw r26,%o0+1" CR_TAB
5223 "st X,__zero_reg__" CR_TAB
5224 "st -X,__tmp_reg__" CR_TAB
5225 "clr __zero_reg__" CR_TAB
5226 "sbiw r26,%o0", op, plen, -7)
5227
5228 : avr_asm_len ("adiw r26,%o0+1" CR_TAB
5229 "st X,%B1" CR_TAB
5230 "st -X,%A1" CR_TAB
5231 "sbiw r26,%o0", op, plen, -4);
5232 }
5233 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5234 {
5235 return avr_asm_len ("st %0,%B1" CR_TAB
5236 "st %0,%A1", op, plen, -2);
5237 }
5238 else if (GET_CODE (base) == POST_INC) /* (R++) */
5239 {
5240 if (!mem_volatile_p)
5241 return avr_asm_len ("st %0,%A1" CR_TAB
5242 "st %0,%B1", op, plen, -2);
5243
5244 if (AVR_TINY)
5245 return avr_out_movhi_mr_r_post_inc_tiny (op, plen);
5246
5247 return REGNO (XEXP (base, 0)) == REG_X
5248 ? avr_asm_len ("adiw r26,1" CR_TAB
5249 "st X,%B1" CR_TAB
5250 "st -X,%A1" CR_TAB
5251 "adiw r26,2", op, plen, -4)
5252
5253 : avr_asm_len ("std %p0+1,%B1" CR_TAB
5254 "st %p0,%A1" CR_TAB
5255 "adiw %r0,2", op, plen, -3);
5256 }
5257 fatal_insn ("unknown move insn:",insn);
5258 return "";
5259 }
5260
5261 /* Return 1 if frame pointer for current function required. */
5262
5263 static bool
avr_frame_pointer_required_p(void)5264 avr_frame_pointer_required_p (void)
5265 {
5266 return (cfun->calls_alloca
5267 || cfun->calls_setjmp
5268 || cfun->has_nonlocal_label
5269 || crtl->args.info.nregs == 0
5270 || get_frame_size () > 0);
5271 }
5272
5273 /* Returns the condition of compare insn INSN, or UNKNOWN. */
5274
5275 static RTX_CODE
compare_condition(rtx_insn * insn)5276 compare_condition (rtx_insn *insn)
5277 {
5278 rtx_insn *next = next_real_insn (insn);
5279
5280 if (next && JUMP_P (next))
5281 {
5282 rtx pat = PATTERN (next);
5283 rtx src = SET_SRC (pat);
5284
5285 if (IF_THEN_ELSE == GET_CODE (src))
5286 return GET_CODE (XEXP (src, 0));
5287 }
5288
5289 return UNKNOWN;
5290 }
5291
5292
5293 /* Returns true iff INSN is a tst insn that only tests the sign. */
5294
5295 static bool
compare_sign_p(rtx_insn * insn)5296 compare_sign_p (rtx_insn *insn)
5297 {
5298 RTX_CODE cond = compare_condition (insn);
5299 return (cond == GE || cond == LT);
5300 }
5301
5302
5303 /* Returns true iff the next insn is a JUMP_INSN with a condition
5304 that needs to be swapped (GT, GTU, LE, LEU). */
5305
5306 static bool
compare_diff_p(rtx_insn * insn)5307 compare_diff_p (rtx_insn *insn)
5308 {
5309 RTX_CODE cond = compare_condition (insn);
5310 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
5311 }
5312
5313 /* Returns true iff INSN is a compare insn with the EQ or NE condition. */
5314
5315 static bool
compare_eq_p(rtx_insn * insn)5316 compare_eq_p (rtx_insn *insn)
5317 {
5318 RTX_CODE cond = compare_condition (insn);
5319 return (cond == EQ || cond == NE);
5320 }
5321
5322
5323 /* Output compare instruction
5324
5325 compare (XOP[0], XOP[1])
5326
5327 for a register XOP[0] and a compile-time constant XOP[1]. Return "".
5328 XOP[2] is an 8-bit scratch register as needed.
5329
5330 PLEN == NULL: Output instructions.
5331 PLEN != NULL: Set *PLEN to the length (in words) of the sequence.
5332 Don't output anything. */
5333
5334 const char*
avr_out_compare(rtx_insn * insn,rtx * xop,int * plen)5335 avr_out_compare (rtx_insn *insn, rtx *xop, int *plen)
5336 {
5337 /* Register to compare and value to compare against. */
5338 rtx xreg = xop[0];
5339 rtx xval = xop[1];
5340
5341 /* MODE of the comparison. */
5342 machine_mode mode;
5343
5344 /* Number of bytes to operate on. */
5345 int i, n_bytes = GET_MODE_SIZE (GET_MODE (xreg));
5346
5347 /* Value (0..0xff) held in clobber register xop[2] or -1 if unknown. */
5348 int clobber_val = -1;
5349
5350 /* Map fixed mode operands to integer operands with the same binary
5351 representation. They are easier to handle in the remainder. */
5352
5353 if (CONST_FIXED_P (xval))
5354 {
5355 xreg = avr_to_int_mode (xop[0]);
5356 xval = avr_to_int_mode (xop[1]);
5357 }
5358
5359 mode = GET_MODE (xreg);
5360
5361 gcc_assert (REG_P (xreg));
5362 gcc_assert ((CONST_INT_P (xval) && n_bytes <= 4)
5363 || (const_double_operand (xval, VOIDmode) && n_bytes == 8));
5364
5365 if (plen)
5366 *plen = 0;
5367
5368 /* Comparisons == +/-1 and != +/-1 can be done similar to camparing
5369 against 0 by ORing the bytes. This is one instruction shorter.
5370 Notice that 64-bit comparisons are always against reg:ALL8 18 (ACC_A)
5371 and therefore don't use this. */
5372
5373 if (!test_hard_reg_class (LD_REGS, xreg)
5374 && compare_eq_p (insn)
5375 && reg_unused_after (insn, xreg))
5376 {
5377 if (xval == const1_rtx)
5378 {
5379 avr_asm_len ("dec %A0" CR_TAB
5380 "or %A0,%B0", xop, plen, 2);
5381
5382 if (n_bytes >= 3)
5383 avr_asm_len ("or %A0,%C0", xop, plen, 1);
5384
5385 if (n_bytes >= 4)
5386 avr_asm_len ("or %A0,%D0", xop, plen, 1);
5387
5388 return "";
5389 }
5390 else if (xval == constm1_rtx)
5391 {
5392 if (n_bytes >= 4)
5393 avr_asm_len ("and %A0,%D0", xop, plen, 1);
5394
5395 if (n_bytes >= 3)
5396 avr_asm_len ("and %A0,%C0", xop, plen, 1);
5397
5398 return avr_asm_len ("and %A0,%B0" CR_TAB
5399 "com %A0", xop, plen, 2);
5400 }
5401 }
5402
5403 for (i = 0; i < n_bytes; i++)
5404 {
5405 /* We compare byte-wise. */
5406 rtx reg8 = simplify_gen_subreg (QImode, xreg, mode, i);
5407 rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
5408
5409 /* 8-bit value to compare with this byte. */
5410 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
5411
5412 /* Registers R16..R31 can operate with immediate. */
5413 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
5414
5415 xop[0] = reg8;
5416 xop[1] = gen_int_mode (val8, QImode);
5417
5418 /* Word registers >= R24 can use SBIW/ADIW with 0..63. */
5419
5420 if (i == 0
5421 && test_hard_reg_class (ADDW_REGS, reg8))
5422 {
5423 int val16 = trunc_int_for_mode (INTVAL (xval), HImode);
5424
5425 if (IN_RANGE (val16, 0, 63)
5426 && (val8 == 0
5427 || reg_unused_after (insn, xreg)))
5428 {
5429 if (AVR_TINY)
5430 avr_asm_len (TINY_SBIW (%A0, %B0, %1), xop, plen, 2);
5431 else
5432 avr_asm_len ("sbiw %0,%1", xop, plen, 1);
5433
5434 i++;
5435 continue;
5436 }
5437
5438 if (n_bytes == 2
5439 && IN_RANGE (val16, -63, -1)
5440 && compare_eq_p (insn)
5441 && reg_unused_after (insn, xreg))
5442 {
5443 return AVR_TINY
5444 ? avr_asm_len (TINY_ADIW (%A0, %B0, %n1), xop, plen, 2)
5445 : avr_asm_len ("adiw %0,%n1", xop, plen, 1);
5446 }
5447 }
5448
5449 /* Comparing against 0 is easy. */
5450
5451 if (val8 == 0)
5452 {
5453 avr_asm_len (i == 0
5454 ? "cp %0,__zero_reg__"
5455 : "cpc %0,__zero_reg__", xop, plen, 1);
5456 continue;
5457 }
5458
5459 /* Upper registers can compare and subtract-with-carry immediates.
5460 Notice that compare instructions do the same as respective subtract
5461 instruction; the only difference is that comparisons don't write
5462 the result back to the target register. */
5463
5464 if (ld_reg_p)
5465 {
5466 if (i == 0)
5467 {
5468 avr_asm_len ("cpi %0,%1", xop, plen, 1);
5469 continue;
5470 }
5471 else if (reg_unused_after (insn, xreg))
5472 {
5473 avr_asm_len ("sbci %0,%1", xop, plen, 1);
5474 continue;
5475 }
5476 }
5477
5478 /* Must load the value into the scratch register. */
5479
5480 gcc_assert (REG_P (xop[2]));
5481
5482 if (clobber_val != (int) val8)
5483 avr_asm_len ("ldi %2,%1", xop, plen, 1);
5484 clobber_val = (int) val8;
5485
5486 avr_asm_len (i == 0
5487 ? "cp %0,%2"
5488 : "cpc %0,%2", xop, plen, 1);
5489 }
5490
5491 return "";
5492 }
5493
5494
5495 /* Prepare operands of compare_const_di2 to be used with avr_out_compare. */
5496
5497 const char*
avr_out_compare64(rtx_insn * insn,rtx * op,int * plen)5498 avr_out_compare64 (rtx_insn *insn, rtx *op, int *plen)
5499 {
5500 rtx xop[3];
5501
5502 xop[0] = gen_rtx_REG (DImode, 18);
5503 xop[1] = op[0];
5504 xop[2] = op[1];
5505
5506 return avr_out_compare (insn, xop, plen);
5507 }
5508
5509 /* Output test instruction for HImode. */
5510
5511 const char*
avr_out_tsthi(rtx_insn * insn,rtx * op,int * plen)5512 avr_out_tsthi (rtx_insn *insn, rtx *op, int *plen)
5513 {
5514 if (compare_sign_p (insn))
5515 {
5516 avr_asm_len ("tst %B0", op, plen, -1);
5517 }
5518 else if (reg_unused_after (insn, op[0])
5519 && compare_eq_p (insn))
5520 {
5521 /* Faster than sbiw if we can clobber the operand. */
5522 avr_asm_len ("or %A0,%B0", op, plen, -1);
5523 }
5524 else
5525 {
5526 avr_out_compare (insn, op, plen);
5527 }
5528
5529 return "";
5530 }
5531
5532
5533 /* Output test instruction for PSImode. */
5534
5535 const char*
avr_out_tstpsi(rtx_insn * insn,rtx * op,int * plen)5536 avr_out_tstpsi (rtx_insn *insn, rtx *op, int *plen)
5537 {
5538 if (compare_sign_p (insn))
5539 {
5540 avr_asm_len ("tst %C0", op, plen, -1);
5541 }
5542 else if (reg_unused_after (insn, op[0])
5543 && compare_eq_p (insn))
5544 {
5545 /* Faster than sbiw if we can clobber the operand. */
5546 avr_asm_len ("or %A0,%B0" CR_TAB
5547 "or %A0,%C0", op, plen, -2);
5548 }
5549 else
5550 {
5551 avr_out_compare (insn, op, plen);
5552 }
5553
5554 return "";
5555 }
5556
5557
5558 /* Output test instruction for SImode. */
5559
5560 const char*
avr_out_tstsi(rtx_insn * insn,rtx * op,int * plen)5561 avr_out_tstsi (rtx_insn *insn, rtx *op, int *plen)
5562 {
5563 if (compare_sign_p (insn))
5564 {
5565 avr_asm_len ("tst %D0", op, plen, -1);
5566 }
5567 else if (reg_unused_after (insn, op[0])
5568 && compare_eq_p (insn))
5569 {
5570 /* Faster than sbiw if we can clobber the operand. */
5571 avr_asm_len ("or %A0,%B0" CR_TAB
5572 "or %A0,%C0" CR_TAB
5573 "or %A0,%D0", op, plen, -3);
5574 }
5575 else
5576 {
5577 avr_out_compare (insn, op, plen);
5578 }
5579
5580 return "";
5581 }
5582
5583
5584 /* Generate asm equivalent for various shifts. This only handles cases
5585 that are not already carefully hand-optimized in ?sh??i3_out.
5586
5587 OPERANDS[0] resp. %0 in TEMPL is the operand to be shifted.
5588 OPERANDS[2] is the shift count as CONST_INT, MEM or REG.
5589 OPERANDS[3] is a QImode scratch register from LD regs if
5590 available and SCRATCH, otherwise (no scratch available)
5591
5592 TEMPL is an assembler template that shifts by one position.
5593 T_LEN is the length of this template. */
5594
5595 void
out_shift_with_cnt(const char * templ,rtx_insn * insn,rtx operands[],int * plen,int t_len)5596 out_shift_with_cnt (const char *templ, rtx_insn *insn, rtx operands[],
5597 int *plen, int t_len)
5598 {
5599 bool second_label = true;
5600 bool saved_in_tmp = false;
5601 bool use_zero_reg = false;
5602 rtx op[5];
5603
5604 op[0] = operands[0];
5605 op[1] = operands[1];
5606 op[2] = operands[2];
5607 op[3] = operands[3];
5608
5609 if (plen)
5610 *plen = 0;
5611
5612 if (CONST_INT_P (operands[2]))
5613 {
5614 bool scratch = (GET_CODE (PATTERN (insn)) == PARALLEL
5615 && REG_P (operands[3]));
5616 int count = INTVAL (operands[2]);
5617 int max_len = 10; /* If larger than this, always use a loop. */
5618
5619 if (count <= 0)
5620 return;
5621
5622 if (count < 8 && !scratch)
5623 use_zero_reg = true;
5624
5625 if (optimize_size)
5626 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
5627
5628 if (t_len * count <= max_len)
5629 {
5630 /* Output shifts inline with no loop - faster. */
5631
5632 while (count-- > 0)
5633 avr_asm_len (templ, op, plen, t_len);
5634
5635 return;
5636 }
5637
5638 if (scratch)
5639 {
5640 avr_asm_len ("ldi %3,%2", op, plen, 1);
5641 }
5642 else if (use_zero_reg)
5643 {
5644 /* Hack to save one word: use __zero_reg__ as loop counter.
5645 Set one bit, then shift in a loop until it is 0 again. */
5646
5647 op[3] = zero_reg_rtx;
5648
5649 avr_asm_len ("set" CR_TAB
5650 "bld %3,%2-1", op, plen, 2);
5651 }
5652 else
5653 {
5654 /* No scratch register available, use one from LD_REGS (saved in
5655 __tmp_reg__) that doesn't overlap with registers to shift. */
5656
5657 op[3] = all_regs_rtx[((REGNO (op[0]) - 1) & 15) + 16];
5658 op[4] = tmp_reg_rtx;
5659 saved_in_tmp = true;
5660
5661 avr_asm_len ("mov %4,%3" CR_TAB
5662 "ldi %3,%2", op, plen, 2);
5663 }
5664
5665 second_label = false;
5666 }
5667 else if (MEM_P (op[2]))
5668 {
5669 rtx op_mov[2];
5670
5671 op_mov[0] = op[3] = tmp_reg_rtx;
5672 op_mov[1] = op[2];
5673
5674 out_movqi_r_mr (insn, op_mov, plen);
5675 }
5676 else if (register_operand (op[2], QImode))
5677 {
5678 op[3] = op[2];
5679
5680 if (!reg_unused_after (insn, op[2])
5681 || reg_overlap_mentioned_p (op[0], op[2]))
5682 {
5683 op[3] = tmp_reg_rtx;
5684 avr_asm_len ("mov %3,%2", op, plen, 1);
5685 }
5686 }
5687 else
5688 fatal_insn ("bad shift insn:", insn);
5689
5690 if (second_label)
5691 avr_asm_len ("rjmp 2f", op, plen, 1);
5692
5693 avr_asm_len ("1:", op, plen, 0);
5694 avr_asm_len (templ, op, plen, t_len);
5695
5696 if (second_label)
5697 avr_asm_len ("2:", op, plen, 0);
5698
5699 avr_asm_len (use_zero_reg ? "lsr %3" : "dec %3", op, plen, 1);
5700 avr_asm_len (second_label ? "brpl 1b" : "brne 1b", op, plen, 1);
5701
5702 if (saved_in_tmp)
5703 avr_asm_len ("mov %3,%4", op, plen, 1);
5704 }
5705
5706
5707 /* 8bit shift left ((char)x << i) */
5708
5709 const char *
ashlqi3_out(rtx_insn * insn,rtx operands[],int * len)5710 ashlqi3_out (rtx_insn *insn, rtx operands[], int *len)
5711 {
5712 if (GET_CODE (operands[2]) == CONST_INT)
5713 {
5714 int k;
5715
5716 if (!len)
5717 len = &k;
5718
5719 switch (INTVAL (operands[2]))
5720 {
5721 default:
5722 if (INTVAL (operands[2]) < 8)
5723 break;
5724
5725 *len = 1;
5726 return "clr %0";
5727
5728 case 1:
5729 *len = 1;
5730 return "lsl %0";
5731
5732 case 2:
5733 *len = 2;
5734 return ("lsl %0" CR_TAB
5735 "lsl %0");
5736
5737 case 3:
5738 *len = 3;
5739 return ("lsl %0" CR_TAB
5740 "lsl %0" CR_TAB
5741 "lsl %0");
5742
5743 case 4:
5744 if (test_hard_reg_class (LD_REGS, operands[0]))
5745 {
5746 *len = 2;
5747 return ("swap %0" CR_TAB
5748 "andi %0,0xf0");
5749 }
5750 *len = 4;
5751 return ("lsl %0" CR_TAB
5752 "lsl %0" CR_TAB
5753 "lsl %0" CR_TAB
5754 "lsl %0");
5755
5756 case 5:
5757 if (test_hard_reg_class (LD_REGS, operands[0]))
5758 {
5759 *len = 3;
5760 return ("swap %0" CR_TAB
5761 "lsl %0" CR_TAB
5762 "andi %0,0xe0");
5763 }
5764 *len = 5;
5765 return ("lsl %0" CR_TAB
5766 "lsl %0" CR_TAB
5767 "lsl %0" CR_TAB
5768 "lsl %0" CR_TAB
5769 "lsl %0");
5770
5771 case 6:
5772 if (test_hard_reg_class (LD_REGS, operands[0]))
5773 {
5774 *len = 4;
5775 return ("swap %0" CR_TAB
5776 "lsl %0" CR_TAB
5777 "lsl %0" CR_TAB
5778 "andi %0,0xc0");
5779 }
5780 *len = 6;
5781 return ("lsl %0" CR_TAB
5782 "lsl %0" CR_TAB
5783 "lsl %0" CR_TAB
5784 "lsl %0" CR_TAB
5785 "lsl %0" CR_TAB
5786 "lsl %0");
5787
5788 case 7:
5789 *len = 3;
5790 return ("ror %0" CR_TAB
5791 "clr %0" CR_TAB
5792 "ror %0");
5793 }
5794 }
5795 else if (CONSTANT_P (operands[2]))
5796 fatal_insn ("internal compiler error. Incorrect shift:", insn);
5797
5798 out_shift_with_cnt ("lsl %0",
5799 insn, operands, len, 1);
5800 return "";
5801 }
5802
5803
5804 /* 16bit shift left ((short)x << i) */
5805
5806 const char *
ashlhi3_out(rtx_insn * insn,rtx operands[],int * len)5807 ashlhi3_out (rtx_insn *insn, rtx operands[], int *len)
5808 {
5809 if (GET_CODE (operands[2]) == CONST_INT)
5810 {
5811 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
5812 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
5813 int k;
5814 int *t = len;
5815
5816 if (!len)
5817 len = &k;
5818
5819 switch (INTVAL (operands[2]))
5820 {
5821 default:
5822 if (INTVAL (operands[2]) < 16)
5823 break;
5824
5825 *len = 2;
5826 return ("clr %B0" CR_TAB
5827 "clr %A0");
5828
5829 case 4:
5830 if (optimize_size && scratch)
5831 break; /* 5 */
5832 if (ldi_ok)
5833 {
5834 *len = 6;
5835 return ("swap %A0" CR_TAB
5836 "swap %B0" CR_TAB
5837 "andi %B0,0xf0" CR_TAB
5838 "eor %B0,%A0" CR_TAB
5839 "andi %A0,0xf0" CR_TAB
5840 "eor %B0,%A0");
5841 }
5842 if (scratch)
5843 {
5844 *len = 7;
5845 return ("swap %A0" CR_TAB
5846 "swap %B0" CR_TAB
5847 "ldi %3,0xf0" CR_TAB
5848 "and %B0,%3" CR_TAB
5849 "eor %B0,%A0" CR_TAB
5850 "and %A0,%3" CR_TAB
5851 "eor %B0,%A0");
5852 }
5853 break; /* optimize_size ? 6 : 8 */
5854
5855 case 5:
5856 if (optimize_size)
5857 break; /* scratch ? 5 : 6 */
5858 if (ldi_ok)
5859 {
5860 *len = 8;
5861 return ("lsl %A0" CR_TAB
5862 "rol %B0" CR_TAB
5863 "swap %A0" CR_TAB
5864 "swap %B0" CR_TAB
5865 "andi %B0,0xf0" CR_TAB
5866 "eor %B0,%A0" CR_TAB
5867 "andi %A0,0xf0" CR_TAB
5868 "eor %B0,%A0");
5869 }
5870 if (scratch)
5871 {
5872 *len = 9;
5873 return ("lsl %A0" CR_TAB
5874 "rol %B0" CR_TAB
5875 "swap %A0" CR_TAB
5876 "swap %B0" CR_TAB
5877 "ldi %3,0xf0" CR_TAB
5878 "and %B0,%3" CR_TAB
5879 "eor %B0,%A0" CR_TAB
5880 "and %A0,%3" CR_TAB
5881 "eor %B0,%A0");
5882 }
5883 break; /* 10 */
5884
5885 case 6:
5886 if (optimize_size)
5887 break; /* scratch ? 5 : 6 */
5888 *len = 9;
5889 return ("clr __tmp_reg__" CR_TAB
5890 "lsr %B0" CR_TAB
5891 "ror %A0" CR_TAB
5892 "ror __tmp_reg__" CR_TAB
5893 "lsr %B0" CR_TAB
5894 "ror %A0" CR_TAB
5895 "ror __tmp_reg__" CR_TAB
5896 "mov %B0,%A0" CR_TAB
5897 "mov %A0,__tmp_reg__");
5898
5899 case 7:
5900 *len = 5;
5901 return ("lsr %B0" CR_TAB
5902 "mov %B0,%A0" CR_TAB
5903 "clr %A0" CR_TAB
5904 "ror %B0" CR_TAB
5905 "ror %A0");
5906
5907 case 8:
5908 return *len = 2, ("mov %B0,%A1" CR_TAB
5909 "clr %A0");
5910
5911 case 9:
5912 *len = 3;
5913 return ("mov %B0,%A0" CR_TAB
5914 "clr %A0" CR_TAB
5915 "lsl %B0");
5916
5917 case 10:
5918 *len = 4;
5919 return ("mov %B0,%A0" CR_TAB
5920 "clr %A0" CR_TAB
5921 "lsl %B0" CR_TAB
5922 "lsl %B0");
5923
5924 case 11:
5925 *len = 5;
5926 return ("mov %B0,%A0" CR_TAB
5927 "clr %A0" CR_TAB
5928 "lsl %B0" CR_TAB
5929 "lsl %B0" CR_TAB
5930 "lsl %B0");
5931
5932 case 12:
5933 if (ldi_ok)
5934 {
5935 *len = 4;
5936 return ("mov %B0,%A0" CR_TAB
5937 "clr %A0" CR_TAB
5938 "swap %B0" CR_TAB
5939 "andi %B0,0xf0");
5940 }
5941 if (scratch)
5942 {
5943 *len = 5;
5944 return ("mov %B0,%A0" CR_TAB
5945 "clr %A0" CR_TAB
5946 "swap %B0" CR_TAB
5947 "ldi %3,0xf0" CR_TAB
5948 "and %B0,%3");
5949 }
5950 *len = 6;
5951 return ("mov %B0,%A0" CR_TAB
5952 "clr %A0" CR_TAB
5953 "lsl %B0" CR_TAB
5954 "lsl %B0" CR_TAB
5955 "lsl %B0" CR_TAB
5956 "lsl %B0");
5957
5958 case 13:
5959 if (ldi_ok)
5960 {
5961 *len = 5;
5962 return ("mov %B0,%A0" CR_TAB
5963 "clr %A0" CR_TAB
5964 "swap %B0" CR_TAB
5965 "lsl %B0" CR_TAB
5966 "andi %B0,0xe0");
5967 }
5968 if (AVR_HAVE_MUL && scratch)
5969 {
5970 *len = 5;
5971 return ("ldi %3,0x20" CR_TAB
5972 "mul %A0,%3" CR_TAB
5973 "mov %B0,r0" CR_TAB
5974 "clr %A0" CR_TAB
5975 "clr __zero_reg__");
5976 }
5977 if (optimize_size && scratch)
5978 break; /* 5 */
5979 if (scratch)
5980 {
5981 *len = 6;
5982 return ("mov %B0,%A0" CR_TAB
5983 "clr %A0" CR_TAB
5984 "swap %B0" CR_TAB
5985 "lsl %B0" CR_TAB
5986 "ldi %3,0xe0" CR_TAB
5987 "and %B0,%3");
5988 }
5989 if (AVR_HAVE_MUL)
5990 {
5991 *len = 6;
5992 return ("set" CR_TAB
5993 "bld r1,5" CR_TAB
5994 "mul %A0,r1" CR_TAB
5995 "mov %B0,r0" CR_TAB
5996 "clr %A0" CR_TAB
5997 "clr __zero_reg__");
5998 }
5999 *len = 7;
6000 return ("mov %B0,%A0" CR_TAB
6001 "clr %A0" CR_TAB
6002 "lsl %B0" CR_TAB
6003 "lsl %B0" CR_TAB
6004 "lsl %B0" CR_TAB
6005 "lsl %B0" CR_TAB
6006 "lsl %B0");
6007
6008 case 14:
6009 if (AVR_HAVE_MUL && ldi_ok)
6010 {
6011 *len = 5;
6012 return ("ldi %B0,0x40" CR_TAB
6013 "mul %A0,%B0" CR_TAB
6014 "mov %B0,r0" CR_TAB
6015 "clr %A0" CR_TAB
6016 "clr __zero_reg__");
6017 }
6018 if (AVR_HAVE_MUL && scratch)
6019 {
6020 *len = 5;
6021 return ("ldi %3,0x40" CR_TAB
6022 "mul %A0,%3" CR_TAB
6023 "mov %B0,r0" CR_TAB
6024 "clr %A0" CR_TAB
6025 "clr __zero_reg__");
6026 }
6027 if (optimize_size && ldi_ok)
6028 {
6029 *len = 5;
6030 return ("mov %B0,%A0" CR_TAB
6031 "ldi %A0,6" "\n1:\t"
6032 "lsl %B0" CR_TAB
6033 "dec %A0" CR_TAB
6034 "brne 1b");
6035 }
6036 if (optimize_size && scratch)
6037 break; /* 5 */
6038 *len = 6;
6039 return ("clr %B0" CR_TAB
6040 "lsr %A0" CR_TAB
6041 "ror %B0" CR_TAB
6042 "lsr %A0" CR_TAB
6043 "ror %B0" CR_TAB
6044 "clr %A0");
6045
6046 case 15:
6047 *len = 4;
6048 return ("clr %B0" CR_TAB
6049 "lsr %A0" CR_TAB
6050 "ror %B0" CR_TAB
6051 "clr %A0");
6052 }
6053 len = t;
6054 }
6055 out_shift_with_cnt ("lsl %A0" CR_TAB
6056 "rol %B0", insn, operands, len, 2);
6057 return "";
6058 }
6059
6060
6061 /* 24-bit shift left */
6062
6063 const char*
avr_out_ashlpsi3(rtx_insn * insn,rtx * op,int * plen)6064 avr_out_ashlpsi3 (rtx_insn *insn, rtx *op, int *plen)
6065 {
6066 if (plen)
6067 *plen = 0;
6068
6069 if (CONST_INT_P (op[2]))
6070 {
6071 switch (INTVAL (op[2]))
6072 {
6073 default:
6074 if (INTVAL (op[2]) < 24)
6075 break;
6076
6077 return avr_asm_len ("clr %A0" CR_TAB
6078 "clr %B0" CR_TAB
6079 "clr %C0", op, plen, 3);
6080
6081 case 8:
6082 {
6083 int reg0 = REGNO (op[0]);
6084 int reg1 = REGNO (op[1]);
6085
6086 if (reg0 >= reg1)
6087 return avr_asm_len ("mov %C0,%B1" CR_TAB
6088 "mov %B0,%A1" CR_TAB
6089 "clr %A0", op, plen, 3);
6090 else
6091 return avr_asm_len ("clr %A0" CR_TAB
6092 "mov %B0,%A1" CR_TAB
6093 "mov %C0,%B1", op, plen, 3);
6094 }
6095
6096 case 16:
6097 {
6098 int reg0 = REGNO (op[0]);
6099 int reg1 = REGNO (op[1]);
6100
6101 if (reg0 + 2 != reg1)
6102 avr_asm_len ("mov %C0,%A0", op, plen, 1);
6103
6104 return avr_asm_len ("clr %B0" CR_TAB
6105 "clr %A0", op, plen, 2);
6106 }
6107
6108 case 23:
6109 return avr_asm_len ("clr %C0" CR_TAB
6110 "lsr %A0" CR_TAB
6111 "ror %C0" CR_TAB
6112 "clr %B0" CR_TAB
6113 "clr %A0", op, plen, 5);
6114 }
6115 }
6116
6117 out_shift_with_cnt ("lsl %A0" CR_TAB
6118 "rol %B0" CR_TAB
6119 "rol %C0", insn, op, plen, 3);
6120 return "";
6121 }
6122
6123
6124 /* 32bit shift left ((long)x << i) */
6125
6126 const char *
ashlsi3_out(rtx_insn * insn,rtx operands[],int * len)6127 ashlsi3_out (rtx_insn *insn, rtx operands[], int *len)
6128 {
6129 if (GET_CODE (operands[2]) == CONST_INT)
6130 {
6131 int k;
6132 int *t = len;
6133
6134 if (!len)
6135 len = &k;
6136
6137 switch (INTVAL (operands[2]))
6138 {
6139 default:
6140 if (INTVAL (operands[2]) < 32)
6141 break;
6142
6143 if (AVR_HAVE_MOVW)
6144 return *len = 3, ("clr %D0" CR_TAB
6145 "clr %C0" CR_TAB
6146 "movw %A0,%C0");
6147 *len = 4;
6148 return ("clr %D0" CR_TAB
6149 "clr %C0" CR_TAB
6150 "clr %B0" CR_TAB
6151 "clr %A0");
6152
6153 case 8:
6154 {
6155 int reg0 = true_regnum (operands[0]);
6156 int reg1 = true_regnum (operands[1]);
6157 *len = 4;
6158 if (reg0 >= reg1)
6159 return ("mov %D0,%C1" CR_TAB
6160 "mov %C0,%B1" CR_TAB
6161 "mov %B0,%A1" CR_TAB
6162 "clr %A0");
6163 else
6164 return ("clr %A0" CR_TAB
6165 "mov %B0,%A1" CR_TAB
6166 "mov %C0,%B1" CR_TAB
6167 "mov %D0,%C1");
6168 }
6169
6170 case 16:
6171 {
6172 int reg0 = true_regnum (operands[0]);
6173 int reg1 = true_regnum (operands[1]);
6174 if (reg0 + 2 == reg1)
6175 return *len = 2, ("clr %B0" CR_TAB
6176 "clr %A0");
6177 if (AVR_HAVE_MOVW)
6178 return *len = 3, ("movw %C0,%A1" CR_TAB
6179 "clr %B0" CR_TAB
6180 "clr %A0");
6181 else
6182 return *len = 4, ("mov %C0,%A1" CR_TAB
6183 "mov %D0,%B1" CR_TAB
6184 "clr %B0" CR_TAB
6185 "clr %A0");
6186 }
6187
6188 case 24:
6189 *len = 4;
6190 return ("mov %D0,%A1" CR_TAB
6191 "clr %C0" CR_TAB
6192 "clr %B0" CR_TAB
6193 "clr %A0");
6194
6195 case 31:
6196 *len = 6;
6197 return ("clr %D0" CR_TAB
6198 "lsr %A0" CR_TAB
6199 "ror %D0" CR_TAB
6200 "clr %C0" CR_TAB
6201 "clr %B0" CR_TAB
6202 "clr %A0");
6203 }
6204 len = t;
6205 }
6206 out_shift_with_cnt ("lsl %A0" CR_TAB
6207 "rol %B0" CR_TAB
6208 "rol %C0" CR_TAB
6209 "rol %D0", insn, operands, len, 4);
6210 return "";
6211 }
6212
6213 /* 8bit arithmetic shift right ((signed char)x >> i) */
6214
6215 const char *
ashrqi3_out(rtx_insn * insn,rtx operands[],int * len)6216 ashrqi3_out (rtx_insn *insn, rtx operands[], int *len)
6217 {
6218 if (GET_CODE (operands[2]) == CONST_INT)
6219 {
6220 int k;
6221
6222 if (!len)
6223 len = &k;
6224
6225 switch (INTVAL (operands[2]))
6226 {
6227 case 1:
6228 *len = 1;
6229 return "asr %0";
6230
6231 case 2:
6232 *len = 2;
6233 return ("asr %0" CR_TAB
6234 "asr %0");
6235
6236 case 3:
6237 *len = 3;
6238 return ("asr %0" CR_TAB
6239 "asr %0" CR_TAB
6240 "asr %0");
6241
6242 case 4:
6243 *len = 4;
6244 return ("asr %0" CR_TAB
6245 "asr %0" CR_TAB
6246 "asr %0" CR_TAB
6247 "asr %0");
6248
6249 case 5:
6250 *len = 5;
6251 return ("asr %0" CR_TAB
6252 "asr %0" CR_TAB
6253 "asr %0" CR_TAB
6254 "asr %0" CR_TAB
6255 "asr %0");
6256
6257 case 6:
6258 *len = 4;
6259 return ("bst %0,6" CR_TAB
6260 "lsl %0" CR_TAB
6261 "sbc %0,%0" CR_TAB
6262 "bld %0,0");
6263
6264 default:
6265 if (INTVAL (operands[2]) < 8)
6266 break;
6267
6268 /* fall through */
6269
6270 case 7:
6271 *len = 2;
6272 return ("lsl %0" CR_TAB
6273 "sbc %0,%0");
6274 }
6275 }
6276 else if (CONSTANT_P (operands[2]))
6277 fatal_insn ("internal compiler error. Incorrect shift:", insn);
6278
6279 out_shift_with_cnt ("asr %0",
6280 insn, operands, len, 1);
6281 return "";
6282 }
6283
6284
6285 /* 16bit arithmetic shift right ((signed short)x >> i) */
6286
6287 const char *
ashrhi3_out(rtx_insn * insn,rtx operands[],int * len)6288 ashrhi3_out (rtx_insn *insn, rtx operands[], int *len)
6289 {
6290 if (GET_CODE (operands[2]) == CONST_INT)
6291 {
6292 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
6293 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
6294 int k;
6295 int *t = len;
6296
6297 if (!len)
6298 len = &k;
6299
6300 switch (INTVAL (operands[2]))
6301 {
6302 case 4:
6303 case 5:
6304 /* XXX try to optimize this too? */
6305 break;
6306
6307 case 6:
6308 if (optimize_size)
6309 break; /* scratch ? 5 : 6 */
6310 *len = 8;
6311 return ("mov __tmp_reg__,%A0" CR_TAB
6312 "mov %A0,%B0" CR_TAB
6313 "lsl __tmp_reg__" CR_TAB
6314 "rol %A0" CR_TAB
6315 "sbc %B0,%B0" CR_TAB
6316 "lsl __tmp_reg__" CR_TAB
6317 "rol %A0" CR_TAB
6318 "rol %B0");
6319
6320 case 7:
6321 *len = 4;
6322 return ("lsl %A0" CR_TAB
6323 "mov %A0,%B0" CR_TAB
6324 "rol %A0" CR_TAB
6325 "sbc %B0,%B0");
6326
6327 case 8:
6328 {
6329 int reg0 = true_regnum (operands[0]);
6330 int reg1 = true_regnum (operands[1]);
6331
6332 if (reg0 == reg1)
6333 return *len = 3, ("mov %A0,%B0" CR_TAB
6334 "lsl %B0" CR_TAB
6335 "sbc %B0,%B0");
6336 else
6337 return *len = 4, ("mov %A0,%B1" CR_TAB
6338 "clr %B0" CR_TAB
6339 "sbrc %A0,7" CR_TAB
6340 "dec %B0");
6341 }
6342
6343 case 9:
6344 *len = 4;
6345 return ("mov %A0,%B0" CR_TAB
6346 "lsl %B0" CR_TAB
6347 "sbc %B0,%B0" CR_TAB
6348 "asr %A0");
6349
6350 case 10:
6351 *len = 5;
6352 return ("mov %A0,%B0" CR_TAB
6353 "lsl %B0" CR_TAB
6354 "sbc %B0,%B0" CR_TAB
6355 "asr %A0" CR_TAB
6356 "asr %A0");
6357
6358 case 11:
6359 if (AVR_HAVE_MUL && ldi_ok)
6360 {
6361 *len = 5;
6362 return ("ldi %A0,0x20" CR_TAB
6363 "muls %B0,%A0" CR_TAB
6364 "mov %A0,r1" CR_TAB
6365 "sbc %B0,%B0" CR_TAB
6366 "clr __zero_reg__");
6367 }
6368 if (optimize_size && scratch)
6369 break; /* 5 */
6370 *len = 6;
6371 return ("mov %A0,%B0" CR_TAB
6372 "lsl %B0" CR_TAB
6373 "sbc %B0,%B0" CR_TAB
6374 "asr %A0" CR_TAB
6375 "asr %A0" CR_TAB
6376 "asr %A0");
6377
6378 case 12:
6379 if (AVR_HAVE_MUL && ldi_ok)
6380 {
6381 *len = 5;
6382 return ("ldi %A0,0x10" CR_TAB
6383 "muls %B0,%A0" CR_TAB
6384 "mov %A0,r1" CR_TAB
6385 "sbc %B0,%B0" CR_TAB
6386 "clr __zero_reg__");
6387 }
6388 if (optimize_size && scratch)
6389 break; /* 5 */
6390 *len = 7;
6391 return ("mov %A0,%B0" CR_TAB
6392 "lsl %B0" CR_TAB
6393 "sbc %B0,%B0" CR_TAB
6394 "asr %A0" CR_TAB
6395 "asr %A0" CR_TAB
6396 "asr %A0" CR_TAB
6397 "asr %A0");
6398
6399 case 13:
6400 if (AVR_HAVE_MUL && ldi_ok)
6401 {
6402 *len = 5;
6403 return ("ldi %A0,0x08" CR_TAB
6404 "muls %B0,%A0" CR_TAB
6405 "mov %A0,r1" CR_TAB
6406 "sbc %B0,%B0" CR_TAB
6407 "clr __zero_reg__");
6408 }
6409 if (optimize_size)
6410 break; /* scratch ? 5 : 7 */
6411 *len = 8;
6412 return ("mov %A0,%B0" CR_TAB
6413 "lsl %B0" CR_TAB
6414 "sbc %B0,%B0" CR_TAB
6415 "asr %A0" CR_TAB
6416 "asr %A0" CR_TAB
6417 "asr %A0" CR_TAB
6418 "asr %A0" CR_TAB
6419 "asr %A0");
6420
6421 case 14:
6422 *len = 5;
6423 return ("lsl %B0" CR_TAB
6424 "sbc %A0,%A0" CR_TAB
6425 "lsl %B0" CR_TAB
6426 "mov %B0,%A0" CR_TAB
6427 "rol %A0");
6428
6429 default:
6430 if (INTVAL (operands[2]) < 16)
6431 break;
6432
6433 /* fall through */
6434
6435 case 15:
6436 return *len = 3, ("lsl %B0" CR_TAB
6437 "sbc %A0,%A0" CR_TAB
6438 "mov %B0,%A0");
6439 }
6440 len = t;
6441 }
6442 out_shift_with_cnt ("asr %B0" CR_TAB
6443 "ror %A0", insn, operands, len, 2);
6444 return "";
6445 }
6446
6447
6448 /* 24-bit arithmetic shift right */
6449
6450 const char*
avr_out_ashrpsi3(rtx_insn * insn,rtx * op,int * plen)6451 avr_out_ashrpsi3 (rtx_insn *insn, rtx *op, int *plen)
6452 {
6453 int dest = REGNO (op[0]);
6454 int src = REGNO (op[1]);
6455
6456 if (CONST_INT_P (op[2]))
6457 {
6458 if (plen)
6459 *plen = 0;
6460
6461 switch (INTVAL (op[2]))
6462 {
6463 case 8:
6464 if (dest <= src)
6465 return avr_asm_len ("mov %A0,%B1" CR_TAB
6466 "mov %B0,%C1" CR_TAB
6467 "clr %C0" CR_TAB
6468 "sbrc %B0,7" CR_TAB
6469 "dec %C0", op, plen, 5);
6470 else
6471 return avr_asm_len ("clr %C0" CR_TAB
6472 "sbrc %C1,7" CR_TAB
6473 "dec %C0" CR_TAB
6474 "mov %B0,%C1" CR_TAB
6475 "mov %A0,%B1", op, plen, 5);
6476
6477 case 16:
6478 if (dest != src + 2)
6479 avr_asm_len ("mov %A0,%C1", op, plen, 1);
6480
6481 return avr_asm_len ("clr %B0" CR_TAB
6482 "sbrc %A0,7" CR_TAB
6483 "com %B0" CR_TAB
6484 "mov %C0,%B0", op, plen, 4);
6485
6486 default:
6487 if (INTVAL (op[2]) < 24)
6488 break;
6489
6490 /* fall through */
6491
6492 case 23:
6493 return avr_asm_len ("lsl %C0" CR_TAB
6494 "sbc %A0,%A0" CR_TAB
6495 "mov %B0,%A0" CR_TAB
6496 "mov %C0,%A0", op, plen, 4);
6497 } /* switch */
6498 }
6499
6500 out_shift_with_cnt ("asr %C0" CR_TAB
6501 "ror %B0" CR_TAB
6502 "ror %A0", insn, op, plen, 3);
6503 return "";
6504 }
6505
6506
6507 /* 32-bit arithmetic shift right ((signed long)x >> i) */
6508
6509 const char *
ashrsi3_out(rtx_insn * insn,rtx operands[],int * len)6510 ashrsi3_out (rtx_insn *insn, rtx operands[], int *len)
6511 {
6512 if (GET_CODE (operands[2]) == CONST_INT)
6513 {
6514 int k;
6515 int *t = len;
6516
6517 if (!len)
6518 len = &k;
6519
6520 switch (INTVAL (operands[2]))
6521 {
6522 case 8:
6523 {
6524 int reg0 = true_regnum (operands[0]);
6525 int reg1 = true_regnum (operands[1]);
6526 *len=6;
6527 if (reg0 <= reg1)
6528 return ("mov %A0,%B1" CR_TAB
6529 "mov %B0,%C1" CR_TAB
6530 "mov %C0,%D1" CR_TAB
6531 "clr %D0" CR_TAB
6532 "sbrc %C0,7" CR_TAB
6533 "dec %D0");
6534 else
6535 return ("clr %D0" CR_TAB
6536 "sbrc %D1,7" CR_TAB
6537 "dec %D0" CR_TAB
6538 "mov %C0,%D1" CR_TAB
6539 "mov %B0,%C1" CR_TAB
6540 "mov %A0,%B1");
6541 }
6542
6543 case 16:
6544 {
6545 int reg0 = true_regnum (operands[0]);
6546 int reg1 = true_regnum (operands[1]);
6547
6548 if (reg0 == reg1 + 2)
6549 return *len = 4, ("clr %D0" CR_TAB
6550 "sbrc %B0,7" CR_TAB
6551 "com %D0" CR_TAB
6552 "mov %C0,%D0");
6553 if (AVR_HAVE_MOVW)
6554 return *len = 5, ("movw %A0,%C1" CR_TAB
6555 "clr %D0" CR_TAB
6556 "sbrc %B0,7" CR_TAB
6557 "com %D0" CR_TAB
6558 "mov %C0,%D0");
6559 else
6560 return *len = 6, ("mov %B0,%D1" CR_TAB
6561 "mov %A0,%C1" CR_TAB
6562 "clr %D0" CR_TAB
6563 "sbrc %B0,7" CR_TAB
6564 "com %D0" CR_TAB
6565 "mov %C0,%D0");
6566 }
6567
6568 case 24:
6569 return *len = 6, ("mov %A0,%D1" CR_TAB
6570 "clr %D0" CR_TAB
6571 "sbrc %A0,7" CR_TAB
6572 "com %D0" CR_TAB
6573 "mov %B0,%D0" CR_TAB
6574 "mov %C0,%D0");
6575
6576 default:
6577 if (INTVAL (operands[2]) < 32)
6578 break;
6579
6580 /* fall through */
6581
6582 case 31:
6583 if (AVR_HAVE_MOVW)
6584 return *len = 4, ("lsl %D0" CR_TAB
6585 "sbc %A0,%A0" CR_TAB
6586 "mov %B0,%A0" CR_TAB
6587 "movw %C0,%A0");
6588 else
6589 return *len = 5, ("lsl %D0" CR_TAB
6590 "sbc %A0,%A0" CR_TAB
6591 "mov %B0,%A0" CR_TAB
6592 "mov %C0,%A0" CR_TAB
6593 "mov %D0,%A0");
6594 }
6595 len = t;
6596 }
6597 out_shift_with_cnt ("asr %D0" CR_TAB
6598 "ror %C0" CR_TAB
6599 "ror %B0" CR_TAB
6600 "ror %A0", insn, operands, len, 4);
6601 return "";
6602 }
6603
6604 /* 8-bit logic shift right ((unsigned char)x >> i) */
6605
6606 const char *
lshrqi3_out(rtx_insn * insn,rtx operands[],int * len)6607 lshrqi3_out (rtx_insn *insn, rtx operands[], int *len)
6608 {
6609 if (GET_CODE (operands[2]) == CONST_INT)
6610 {
6611 int k;
6612
6613 if (!len)
6614 len = &k;
6615
6616 switch (INTVAL (operands[2]))
6617 {
6618 default:
6619 if (INTVAL (operands[2]) < 8)
6620 break;
6621
6622 *len = 1;
6623 return "clr %0";
6624
6625 case 1:
6626 *len = 1;
6627 return "lsr %0";
6628
6629 case 2:
6630 *len = 2;
6631 return ("lsr %0" CR_TAB
6632 "lsr %0");
6633 case 3:
6634 *len = 3;
6635 return ("lsr %0" CR_TAB
6636 "lsr %0" CR_TAB
6637 "lsr %0");
6638
6639 case 4:
6640 if (test_hard_reg_class (LD_REGS, operands[0]))
6641 {
6642 *len=2;
6643 return ("swap %0" CR_TAB
6644 "andi %0,0x0f");
6645 }
6646 *len = 4;
6647 return ("lsr %0" CR_TAB
6648 "lsr %0" CR_TAB
6649 "lsr %0" CR_TAB
6650 "lsr %0");
6651
6652 case 5:
6653 if (test_hard_reg_class (LD_REGS, operands[0]))
6654 {
6655 *len = 3;
6656 return ("swap %0" CR_TAB
6657 "lsr %0" CR_TAB
6658 "andi %0,0x7");
6659 }
6660 *len = 5;
6661 return ("lsr %0" CR_TAB
6662 "lsr %0" CR_TAB
6663 "lsr %0" CR_TAB
6664 "lsr %0" CR_TAB
6665 "lsr %0");
6666
6667 case 6:
6668 if (test_hard_reg_class (LD_REGS, operands[0]))
6669 {
6670 *len = 4;
6671 return ("swap %0" CR_TAB
6672 "lsr %0" CR_TAB
6673 "lsr %0" CR_TAB
6674 "andi %0,0x3");
6675 }
6676 *len = 6;
6677 return ("lsr %0" CR_TAB
6678 "lsr %0" CR_TAB
6679 "lsr %0" CR_TAB
6680 "lsr %0" CR_TAB
6681 "lsr %0" CR_TAB
6682 "lsr %0");
6683
6684 case 7:
6685 *len = 3;
6686 return ("rol %0" CR_TAB
6687 "clr %0" CR_TAB
6688 "rol %0");
6689 }
6690 }
6691 else if (CONSTANT_P (operands[2]))
6692 fatal_insn ("internal compiler error. Incorrect shift:", insn);
6693
6694 out_shift_with_cnt ("lsr %0",
6695 insn, operands, len, 1);
6696 return "";
6697 }
6698
6699 /* 16-bit logic shift right ((unsigned short)x >> i) */
6700
6701 const char *
lshrhi3_out(rtx_insn * insn,rtx operands[],int * len)6702 lshrhi3_out (rtx_insn *insn, rtx operands[], int *len)
6703 {
6704 if (GET_CODE (operands[2]) == CONST_INT)
6705 {
6706 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
6707 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
6708 int k;
6709 int *t = len;
6710
6711 if (!len)
6712 len = &k;
6713
6714 switch (INTVAL (operands[2]))
6715 {
6716 default:
6717 if (INTVAL (operands[2]) < 16)
6718 break;
6719
6720 *len = 2;
6721 return ("clr %B0" CR_TAB
6722 "clr %A0");
6723
6724 case 4:
6725 if (optimize_size && scratch)
6726 break; /* 5 */
6727 if (ldi_ok)
6728 {
6729 *len = 6;
6730 return ("swap %B0" CR_TAB
6731 "swap %A0" CR_TAB
6732 "andi %A0,0x0f" CR_TAB
6733 "eor %A0,%B0" CR_TAB
6734 "andi %B0,0x0f" CR_TAB
6735 "eor %A0,%B0");
6736 }
6737 if (scratch)
6738 {
6739 *len = 7;
6740 return ("swap %B0" CR_TAB
6741 "swap %A0" CR_TAB
6742 "ldi %3,0x0f" CR_TAB
6743 "and %A0,%3" CR_TAB
6744 "eor %A0,%B0" CR_TAB
6745 "and %B0,%3" CR_TAB
6746 "eor %A0,%B0");
6747 }
6748 break; /* optimize_size ? 6 : 8 */
6749
6750 case 5:
6751 if (optimize_size)
6752 break; /* scratch ? 5 : 6 */
6753 if (ldi_ok)
6754 {
6755 *len = 8;
6756 return ("lsr %B0" CR_TAB
6757 "ror %A0" CR_TAB
6758 "swap %B0" CR_TAB
6759 "swap %A0" CR_TAB
6760 "andi %A0,0x0f" CR_TAB
6761 "eor %A0,%B0" CR_TAB
6762 "andi %B0,0x0f" CR_TAB
6763 "eor %A0,%B0");
6764 }
6765 if (scratch)
6766 {
6767 *len = 9;
6768 return ("lsr %B0" CR_TAB
6769 "ror %A0" CR_TAB
6770 "swap %B0" CR_TAB
6771 "swap %A0" CR_TAB
6772 "ldi %3,0x0f" CR_TAB
6773 "and %A0,%3" CR_TAB
6774 "eor %A0,%B0" CR_TAB
6775 "and %B0,%3" CR_TAB
6776 "eor %A0,%B0");
6777 }
6778 break; /* 10 */
6779
6780 case 6:
6781 if (optimize_size)
6782 break; /* scratch ? 5 : 6 */
6783 *len = 9;
6784 return ("clr __tmp_reg__" CR_TAB
6785 "lsl %A0" CR_TAB
6786 "rol %B0" CR_TAB
6787 "rol __tmp_reg__" CR_TAB
6788 "lsl %A0" CR_TAB
6789 "rol %B0" CR_TAB
6790 "rol __tmp_reg__" CR_TAB
6791 "mov %A0,%B0" CR_TAB
6792 "mov %B0,__tmp_reg__");
6793
6794 case 7:
6795 *len = 5;
6796 return ("lsl %A0" CR_TAB
6797 "mov %A0,%B0" CR_TAB
6798 "rol %A0" CR_TAB
6799 "sbc %B0,%B0" CR_TAB
6800 "neg %B0");
6801
6802 case 8:
6803 return *len = 2, ("mov %A0,%B1" CR_TAB
6804 "clr %B0");
6805
6806 case 9:
6807 *len = 3;
6808 return ("mov %A0,%B0" CR_TAB
6809 "clr %B0" CR_TAB
6810 "lsr %A0");
6811
6812 case 10:
6813 *len = 4;
6814 return ("mov %A0,%B0" CR_TAB
6815 "clr %B0" CR_TAB
6816 "lsr %A0" CR_TAB
6817 "lsr %A0");
6818
6819 case 11:
6820 *len = 5;
6821 return ("mov %A0,%B0" CR_TAB
6822 "clr %B0" CR_TAB
6823 "lsr %A0" CR_TAB
6824 "lsr %A0" CR_TAB
6825 "lsr %A0");
6826
6827 case 12:
6828 if (ldi_ok)
6829 {
6830 *len = 4;
6831 return ("mov %A0,%B0" CR_TAB
6832 "clr %B0" CR_TAB
6833 "swap %A0" CR_TAB
6834 "andi %A0,0x0f");
6835 }
6836 if (scratch)
6837 {
6838 *len = 5;
6839 return ("mov %A0,%B0" CR_TAB
6840 "clr %B0" CR_TAB
6841 "swap %A0" CR_TAB
6842 "ldi %3,0x0f" CR_TAB
6843 "and %A0,%3");
6844 }
6845 *len = 6;
6846 return ("mov %A0,%B0" CR_TAB
6847 "clr %B0" CR_TAB
6848 "lsr %A0" CR_TAB
6849 "lsr %A0" CR_TAB
6850 "lsr %A0" CR_TAB
6851 "lsr %A0");
6852
6853 case 13:
6854 if (ldi_ok)
6855 {
6856 *len = 5;
6857 return ("mov %A0,%B0" CR_TAB
6858 "clr %B0" CR_TAB
6859 "swap %A0" CR_TAB
6860 "lsr %A0" CR_TAB
6861 "andi %A0,0x07");
6862 }
6863 if (AVR_HAVE_MUL && scratch)
6864 {
6865 *len = 5;
6866 return ("ldi %3,0x08" CR_TAB
6867 "mul %B0,%3" CR_TAB
6868 "mov %A0,r1" CR_TAB
6869 "clr %B0" CR_TAB
6870 "clr __zero_reg__");
6871 }
6872 if (optimize_size && scratch)
6873 break; /* 5 */
6874 if (scratch)
6875 {
6876 *len = 6;
6877 return ("mov %A0,%B0" CR_TAB
6878 "clr %B0" CR_TAB
6879 "swap %A0" CR_TAB
6880 "lsr %A0" CR_TAB
6881 "ldi %3,0x07" CR_TAB
6882 "and %A0,%3");
6883 }
6884 if (AVR_HAVE_MUL)
6885 {
6886 *len = 6;
6887 return ("set" CR_TAB
6888 "bld r1,3" CR_TAB
6889 "mul %B0,r1" CR_TAB
6890 "mov %A0,r1" CR_TAB
6891 "clr %B0" CR_TAB
6892 "clr __zero_reg__");
6893 }
6894 *len = 7;
6895 return ("mov %A0,%B0" CR_TAB
6896 "clr %B0" CR_TAB
6897 "lsr %A0" CR_TAB
6898 "lsr %A0" CR_TAB
6899 "lsr %A0" CR_TAB
6900 "lsr %A0" CR_TAB
6901 "lsr %A0");
6902
6903 case 14:
6904 if (AVR_HAVE_MUL && ldi_ok)
6905 {
6906 *len = 5;
6907 return ("ldi %A0,0x04" CR_TAB
6908 "mul %B0,%A0" CR_TAB
6909 "mov %A0,r1" CR_TAB
6910 "clr %B0" CR_TAB
6911 "clr __zero_reg__");
6912 }
6913 if (AVR_HAVE_MUL && scratch)
6914 {
6915 *len = 5;
6916 return ("ldi %3,0x04" CR_TAB
6917 "mul %B0,%3" CR_TAB
6918 "mov %A0,r1" CR_TAB
6919 "clr %B0" CR_TAB
6920 "clr __zero_reg__");
6921 }
6922 if (optimize_size && ldi_ok)
6923 {
6924 *len = 5;
6925 return ("mov %A0,%B0" CR_TAB
6926 "ldi %B0,6" "\n1:\t"
6927 "lsr %A0" CR_TAB
6928 "dec %B0" CR_TAB
6929 "brne 1b");
6930 }
6931 if (optimize_size && scratch)
6932 break; /* 5 */
6933 *len = 6;
6934 return ("clr %A0" CR_TAB
6935 "lsl %B0" CR_TAB
6936 "rol %A0" CR_TAB
6937 "lsl %B0" CR_TAB
6938 "rol %A0" CR_TAB
6939 "clr %B0");
6940
6941 case 15:
6942 *len = 4;
6943 return ("clr %A0" CR_TAB
6944 "lsl %B0" CR_TAB
6945 "rol %A0" CR_TAB
6946 "clr %B0");
6947 }
6948 len = t;
6949 }
6950 out_shift_with_cnt ("lsr %B0" CR_TAB
6951 "ror %A0", insn, operands, len, 2);
6952 return "";
6953 }
6954
6955
6956 /* 24-bit logic shift right */
6957
6958 const char*
avr_out_lshrpsi3(rtx_insn * insn,rtx * op,int * plen)6959 avr_out_lshrpsi3 (rtx_insn *insn, rtx *op, int *plen)
6960 {
6961 int dest = REGNO (op[0]);
6962 int src = REGNO (op[1]);
6963
6964 if (CONST_INT_P (op[2]))
6965 {
6966 if (plen)
6967 *plen = 0;
6968
6969 switch (INTVAL (op[2]))
6970 {
6971 case 8:
6972 if (dest <= src)
6973 return avr_asm_len ("mov %A0,%B1" CR_TAB
6974 "mov %B0,%C1" CR_TAB
6975 "clr %C0", op, plen, 3);
6976 else
6977 return avr_asm_len ("clr %C0" CR_TAB
6978 "mov %B0,%C1" CR_TAB
6979 "mov %A0,%B1", op, plen, 3);
6980
6981 case 16:
6982 if (dest != src + 2)
6983 avr_asm_len ("mov %A0,%C1", op, plen, 1);
6984
6985 return avr_asm_len ("clr %B0" CR_TAB
6986 "clr %C0", op, plen, 2);
6987
6988 default:
6989 if (INTVAL (op[2]) < 24)
6990 break;
6991
6992 /* fall through */
6993
6994 case 23:
6995 return avr_asm_len ("clr %A0" CR_TAB
6996 "sbrc %C0,7" CR_TAB
6997 "inc %A0" CR_TAB
6998 "clr %B0" CR_TAB
6999 "clr %C0", op, plen, 5);
7000 } /* switch */
7001 }
7002
7003 out_shift_with_cnt ("lsr %C0" CR_TAB
7004 "ror %B0" CR_TAB
7005 "ror %A0", insn, op, plen, 3);
7006 return "";
7007 }
7008
7009
7010 /* 32-bit logic shift right ((unsigned int)x >> i) */
7011
7012 const char *
lshrsi3_out(rtx_insn * insn,rtx operands[],int * len)7013 lshrsi3_out (rtx_insn *insn, rtx operands[], int *len)
7014 {
7015 if (GET_CODE (operands[2]) == CONST_INT)
7016 {
7017 int k;
7018 int *t = len;
7019
7020 if (!len)
7021 len = &k;
7022
7023 switch (INTVAL (operands[2]))
7024 {
7025 default:
7026 if (INTVAL (operands[2]) < 32)
7027 break;
7028
7029 if (AVR_HAVE_MOVW)
7030 return *len = 3, ("clr %D0" CR_TAB
7031 "clr %C0" CR_TAB
7032 "movw %A0,%C0");
7033 *len = 4;
7034 return ("clr %D0" CR_TAB
7035 "clr %C0" CR_TAB
7036 "clr %B0" CR_TAB
7037 "clr %A0");
7038
7039 case 8:
7040 {
7041 int reg0 = true_regnum (operands[0]);
7042 int reg1 = true_regnum (operands[1]);
7043 *len = 4;
7044 if (reg0 <= reg1)
7045 return ("mov %A0,%B1" CR_TAB
7046 "mov %B0,%C1" CR_TAB
7047 "mov %C0,%D1" CR_TAB
7048 "clr %D0");
7049 else
7050 return ("clr %D0" CR_TAB
7051 "mov %C0,%D1" CR_TAB
7052 "mov %B0,%C1" CR_TAB
7053 "mov %A0,%B1");
7054 }
7055
7056 case 16:
7057 {
7058 int reg0 = true_regnum (operands[0]);
7059 int reg1 = true_regnum (operands[1]);
7060
7061 if (reg0 == reg1 + 2)
7062 return *len = 2, ("clr %C0" CR_TAB
7063 "clr %D0");
7064 if (AVR_HAVE_MOVW)
7065 return *len = 3, ("movw %A0,%C1" CR_TAB
7066 "clr %C0" CR_TAB
7067 "clr %D0");
7068 else
7069 return *len = 4, ("mov %B0,%D1" CR_TAB
7070 "mov %A0,%C1" CR_TAB
7071 "clr %C0" CR_TAB
7072 "clr %D0");
7073 }
7074
7075 case 24:
7076 return *len = 4, ("mov %A0,%D1" CR_TAB
7077 "clr %B0" CR_TAB
7078 "clr %C0" CR_TAB
7079 "clr %D0");
7080
7081 case 31:
7082 *len = 6;
7083 return ("clr %A0" CR_TAB
7084 "sbrc %D0,7" CR_TAB
7085 "inc %A0" CR_TAB
7086 "clr %B0" CR_TAB
7087 "clr %C0" CR_TAB
7088 "clr %D0");
7089 }
7090 len = t;
7091 }
7092 out_shift_with_cnt ("lsr %D0" CR_TAB
7093 "ror %C0" CR_TAB
7094 "ror %B0" CR_TAB
7095 "ror %A0", insn, operands, len, 4);
7096 return "";
7097 }
7098
7099
7100 /* Output addition of register XOP[0] and compile time constant XOP[2].
7101 CODE == PLUS: perform addition by using ADD instructions or
7102 CODE == MINUS: perform addition by using SUB instructions:
7103
7104 XOP[0] = XOP[0] + XOP[2]
7105
7106 Or perform addition/subtraction with register XOP[2] depending on CODE:
7107
7108 XOP[0] = XOP[0] +/- XOP[2]
7109
7110 If PLEN == NULL, print assembler instructions to perform the operation;
7111 otherwise, set *PLEN to the length of the instruction sequence (in words)
7112 printed with PLEN == NULL. XOP[3] is an 8-bit scratch register or NULL_RTX.
7113 Set *PCC to effect on cc0 according to respective CC_* insn attribute.
7114
7115 CODE_SAT == UNKNOWN: Perform ordinary, non-saturating operation.
7116 CODE_SAT != UNKNOWN: Perform operation and saturate according to CODE_SAT.
7117 If CODE_SAT != UNKNOWN then SIGN contains the sign of the summand resp.
7118 the subtrahend in the original insn, provided it is a compile time constant.
7119 In all other cases, SIGN is 0.
7120
7121 If OUT_LABEL is true, print the final 0: label which is needed for
7122 saturated addition / subtraction. The only case where OUT_LABEL = false
7123 is useful is for saturated addition / subtraction performed during
7124 fixed-point rounding, cf. `avr_out_round'. */
7125
7126 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)7127 avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc,
7128 enum rtx_code code_sat, int sign, bool out_label)
7129 {
7130 /* MODE of the operation. */
7131 machine_mode mode = GET_MODE (xop[0]);
7132
7133 /* INT_MODE of the same size. */
7134 machine_mode imode = int_mode_for_mode (mode);
7135
7136 /* Number of bytes to operate on. */
7137 int i, n_bytes = GET_MODE_SIZE (mode);
7138
7139 /* Value (0..0xff) held in clobber register op[3] or -1 if unknown. */
7140 int clobber_val = -1;
7141
7142 /* op[0]: 8-bit destination register
7143 op[1]: 8-bit const int
7144 op[2]: 8-bit scratch register */
7145 rtx op[3];
7146
7147 /* Started the operation? Before starting the operation we may skip
7148 adding 0. This is no more true after the operation started because
7149 carry must be taken into account. */
7150 bool started = false;
7151
7152 /* Value to add. There are two ways to add VAL: R += VAL and R -= -VAL. */
7153 rtx xval = xop[2];
7154
7155 /* Output a BRVC instruction. Only needed with saturation. */
7156 bool out_brvc = true;
7157
7158 if (plen)
7159 *plen = 0;
7160
7161 if (REG_P (xop[2]))
7162 {
7163 *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_CLOBBER;
7164
7165 for (i = 0; i < n_bytes; i++)
7166 {
7167 /* We operate byte-wise on the destination. */
7168 op[0] = simplify_gen_subreg (QImode, xop[0], mode, i);
7169 op[1] = simplify_gen_subreg (QImode, xop[2], mode, i);
7170
7171 if (i == 0)
7172 avr_asm_len (code == PLUS ? "add %0,%1" : "sub %0,%1",
7173 op, plen, 1);
7174 else
7175 avr_asm_len (code == PLUS ? "adc %0,%1" : "sbc %0,%1",
7176 op, plen, 1);
7177 }
7178
7179 if (reg_overlap_mentioned_p (xop[0], xop[2]))
7180 {
7181 gcc_assert (REGNO (xop[0]) == REGNO (xop[2]));
7182
7183 if (MINUS == code)
7184 return;
7185 }
7186
7187 goto saturate;
7188 }
7189
7190 /* Except in the case of ADIW with 16-bit register (see below)
7191 addition does not set cc0 in a usable way. */
7192
7193 *pcc = (MINUS == code) ? CC_SET_CZN : CC_CLOBBER;
7194
7195 if (CONST_FIXED_P (xval))
7196 xval = avr_to_int_mode (xval);
7197
7198 /* Adding/Subtracting zero is a no-op. */
7199
7200 if (xval == const0_rtx)
7201 {
7202 *pcc = CC_NONE;
7203 return;
7204 }
7205
7206 if (MINUS == code)
7207 xval = simplify_unary_operation (NEG, imode, xval, imode);
7208
7209 op[2] = xop[3];
7210
7211 if (SS_PLUS == code_sat && MINUS == code
7212 && sign < 0
7213 && 0x80 == (INTVAL (simplify_gen_subreg (QImode, xval, imode, n_bytes-1))
7214 & GET_MODE_MASK (QImode)))
7215 {
7216 /* We compute x + 0x80 by means of SUB instructions. We negated the
7217 constant subtrahend above and are left with x - (-128) so that we
7218 need something like SUBI r,128 which does not exist because SUBI sets
7219 V according to the sign of the subtrahend. Notice the only case
7220 where this must be done is when NEG overflowed in case [2s] because
7221 the V computation needs the right sign of the subtrahend. */
7222
7223 rtx msb = simplify_gen_subreg (QImode, xop[0], mode, n_bytes-1);
7224
7225 avr_asm_len ("subi %0,128" CR_TAB
7226 "brmi 0f", &msb, plen, 2);
7227 out_brvc = false;
7228
7229 goto saturate;
7230 }
7231
7232 for (i = 0; i < n_bytes; i++)
7233 {
7234 /* We operate byte-wise on the destination. */
7235 rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
7236 rtx xval8 = simplify_gen_subreg (QImode, xval, imode, i);
7237
7238 /* 8-bit value to operate with this byte. */
7239 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
7240
7241 /* Registers R16..R31 can operate with immediate. */
7242 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
7243
7244 op[0] = reg8;
7245 op[1] = gen_int_mode (val8, QImode);
7246
7247 /* To get usable cc0 no low-bytes must have been skipped. */
7248
7249 if (i && !started)
7250 *pcc = CC_CLOBBER;
7251
7252 if (!started
7253 && i % 2 == 0
7254 && i + 2 <= n_bytes
7255 && test_hard_reg_class (ADDW_REGS, reg8))
7256 {
7257 rtx xval16 = simplify_gen_subreg (HImode, xval, imode, i);
7258 unsigned int val16 = UINTVAL (xval16) & GET_MODE_MASK (HImode);
7259
7260 /* Registers R24, X, Y, Z can use ADIW/SBIW with constants < 64
7261 i.e. operate word-wise. */
7262
7263 if (val16 < 64)
7264 {
7265 if (val16 != 0)
7266 {
7267 started = true;
7268 avr_asm_len (code == PLUS ? "adiw %0,%1" : "sbiw %0,%1",
7269 op, plen, 1);
7270
7271 if (n_bytes == 2 && PLUS == code)
7272 *pcc = CC_SET_CZN;
7273 }
7274
7275 i++;
7276 continue;
7277 }
7278 }
7279
7280 if (val8 == 0)
7281 {
7282 if (started)
7283 avr_asm_len (code == PLUS
7284 ? "adc %0,__zero_reg__" : "sbc %0,__zero_reg__",
7285 op, plen, 1);
7286 continue;
7287 }
7288 else if ((val8 == 1 || val8 == 0xff)
7289 && UNKNOWN == code_sat
7290 && !started
7291 && i == n_bytes - 1)
7292 {
7293 avr_asm_len ((code == PLUS) ^ (val8 == 1) ? "dec %0" : "inc %0",
7294 op, plen, 1);
7295 *pcc = CC_CLOBBER;
7296 break;
7297 }
7298
7299 switch (code)
7300 {
7301 case PLUS:
7302
7303 gcc_assert (plen != NULL || (op[2] && REG_P (op[2])));
7304
7305 if (plen != NULL && UNKNOWN != code_sat)
7306 {
7307 /* This belongs to the x + 0x80 corner case. The code with
7308 ADD instruction is not smaller, thus make this case
7309 expensive so that the caller won't pick it. */
7310
7311 *plen += 10;
7312 break;
7313 }
7314
7315 if (clobber_val != (int) val8)
7316 avr_asm_len ("ldi %2,%1", op, plen, 1);
7317 clobber_val = (int) val8;
7318
7319 avr_asm_len (started ? "adc %0,%2" : "add %0,%2", op, plen, 1);
7320
7321 break; /* PLUS */
7322
7323 case MINUS:
7324
7325 if (ld_reg_p)
7326 avr_asm_len (started ? "sbci %0,%1" : "subi %0,%1", op, plen, 1);
7327 else
7328 {
7329 gcc_assert (plen != NULL || REG_P (op[2]));
7330
7331 if (clobber_val != (int) val8)
7332 avr_asm_len ("ldi %2,%1", op, plen, 1);
7333 clobber_val = (int) val8;
7334
7335 avr_asm_len (started ? "sbc %0,%2" : "sub %0,%2", op, plen, 1);
7336 }
7337
7338 break; /* MINUS */
7339
7340 default:
7341 /* Unknown code */
7342 gcc_unreachable();
7343 }
7344
7345 started = true;
7346
7347 } /* for all sub-bytes */
7348
7349 saturate:
7350
7351 if (UNKNOWN == code_sat)
7352 return;
7353
7354 *pcc = (int) CC_CLOBBER;
7355
7356 /* Vanilla addition/subtraction is done. We are left with saturation.
7357
7358 We have to compute A = A <op> B where A is a register and
7359 B is a register or a non-zero compile time constant CONST.
7360 A is register class "r" if unsigned && B is REG. Otherwise, A is in "d".
7361 B stands for the original operand $2 in INSN. In the case of B = CONST,
7362 SIGN in { -1, 1 } is the sign of B. Otherwise, SIGN is 0.
7363
7364 CODE is the instruction flavor we use in the asm sequence to perform <op>.
7365
7366
7367 unsigned
7368 operation | code | sat if | b is | sat value | case
7369 -----------------+-------+----------+--------------+-----------+-------
7370 + as a + b | add | C == 1 | const, reg | u+ = 0xff | [1u]
7371 + as a - (-b) | sub | C == 0 | const | u+ = 0xff | [2u]
7372 - as a - b | sub | C == 1 | const, reg | u- = 0 | [3u]
7373 - as a + (-b) | add | C == 0 | const | u- = 0 | [4u]
7374
7375
7376 signed
7377 operation | code | sat if | b is | sat value | case
7378 -----------------+-------+----------+--------------+-----------+-------
7379 + as a + b | add | V == 1 | const, reg | s+ | [1s]
7380 + as a - (-b) | sub | V == 1 | const | s+ | [2s]
7381 - as a - b | sub | V == 1 | const, reg | s- | [3s]
7382 - as a + (-b) | add | V == 1 | const | s- | [4s]
7383
7384 s+ = b < 0 ? -0x80 : 0x7f
7385 s- = b < 0 ? 0x7f : -0x80
7386
7387 The cases a - b actually perform a - (-(-b)) if B is CONST.
7388 */
7389
7390 op[0] = simplify_gen_subreg (QImode, xop[0], mode, n_bytes-1);
7391 op[1] = n_bytes > 1
7392 ? simplify_gen_subreg (QImode, xop[0], mode, n_bytes-2)
7393 : NULL_RTX;
7394
7395 bool need_copy = true;
7396 int len_call = 1 + AVR_HAVE_JMP_CALL;
7397
7398 switch (code_sat)
7399 {
7400 default:
7401 gcc_unreachable();
7402
7403 case SS_PLUS:
7404 case SS_MINUS:
7405
7406 if (out_brvc)
7407 avr_asm_len ("brvc 0f", op, plen, 1);
7408
7409 if (reg_overlap_mentioned_p (xop[0], xop[2]))
7410 {
7411 /* [1s,reg] */
7412
7413 if (n_bytes == 1)
7414 avr_asm_len ("ldi %0,0x7f" CR_TAB
7415 "adc %0,__zero_reg__", op, plen, 2);
7416 else
7417 avr_asm_len ("ldi %0,0x7f" CR_TAB
7418 "ldi %1,0xff" CR_TAB
7419 "adc %1,__zero_reg__" CR_TAB
7420 "adc %0,__zero_reg__", op, plen, 4);
7421 }
7422 else if (sign == 0 && PLUS == code)
7423 {
7424 /* [1s,reg] */
7425
7426 op[2] = simplify_gen_subreg (QImode, xop[2], mode, n_bytes-1);
7427
7428 if (n_bytes == 1)
7429 avr_asm_len ("ldi %0,0x80" CR_TAB
7430 "sbrs %2,7" CR_TAB
7431 "dec %0", op, plen, 3);
7432 else
7433 avr_asm_len ("ldi %0,0x80" CR_TAB
7434 "cp %2,%0" CR_TAB
7435 "sbc %1,%1" CR_TAB
7436 "sbci %0,0", op, plen, 4);
7437 }
7438 else if (sign == 0 && MINUS == code)
7439 {
7440 /* [3s,reg] */
7441
7442 op[2] = simplify_gen_subreg (QImode, xop[2], mode, n_bytes-1);
7443
7444 if (n_bytes == 1)
7445 avr_asm_len ("ldi %0,0x7f" CR_TAB
7446 "sbrs %2,7" CR_TAB
7447 "inc %0", op, plen, 3);
7448 else
7449 avr_asm_len ("ldi %0,0x7f" CR_TAB
7450 "cp %0,%2" CR_TAB
7451 "sbc %1,%1" CR_TAB
7452 "sbci %0,-1", op, plen, 4);
7453 }
7454 else if ((sign < 0) ^ (SS_MINUS == code_sat))
7455 {
7456 /* [1s,const,B < 0] [2s,B < 0] */
7457 /* [3s,const,B > 0] [4s,B > 0] */
7458
7459 if (n_bytes == 8)
7460 {
7461 avr_asm_len ("%~call __clr_8", op, plen, len_call);
7462 need_copy = false;
7463 }
7464
7465 avr_asm_len ("ldi %0,0x80", op, plen, 1);
7466 if (n_bytes > 1 && need_copy)
7467 avr_asm_len ("clr %1", op, plen, 1);
7468 }
7469 else if ((sign > 0) ^ (SS_MINUS == code_sat))
7470 {
7471 /* [1s,const,B > 0] [2s,B > 0] */
7472 /* [3s,const,B < 0] [4s,B < 0] */
7473
7474 if (n_bytes == 8)
7475 {
7476 avr_asm_len ("sec" CR_TAB
7477 "%~call __sbc_8", op, plen, 1 + len_call);
7478 need_copy = false;
7479 }
7480
7481 avr_asm_len ("ldi %0,0x7f", op, plen, 1);
7482 if (n_bytes > 1 && need_copy)
7483 avr_asm_len ("ldi %1,0xff", op, plen, 1);
7484 }
7485 else
7486 gcc_unreachable();
7487
7488 break;
7489
7490 case US_PLUS:
7491 /* [1u] : [2u] */
7492
7493 avr_asm_len (PLUS == code ? "brcc 0f" : "brcs 0f", op, plen, 1);
7494
7495 if (n_bytes == 8)
7496 {
7497 if (MINUS == code)
7498 avr_asm_len ("sec", op, plen, 1);
7499 avr_asm_len ("%~call __sbc_8", op, plen, len_call);
7500
7501 need_copy = false;
7502 }
7503 else
7504 {
7505 if (MINUS == code && !test_hard_reg_class (LD_REGS, op[0]))
7506 avr_asm_len ("sec" CR_TAB
7507 "sbc %0,%0", op, plen, 2);
7508 else
7509 avr_asm_len (PLUS == code ? "sbc %0,%0" : "ldi %0,0xff",
7510 op, plen, 1);
7511 }
7512 break; /* US_PLUS */
7513
7514 case US_MINUS:
7515 /* [4u] : [3u] */
7516
7517 avr_asm_len (PLUS == code ? "brcs 0f" : "brcc 0f", op, plen, 1);
7518
7519 if (n_bytes == 8)
7520 {
7521 avr_asm_len ("%~call __clr_8", op, plen, len_call);
7522 need_copy = false;
7523 }
7524 else
7525 avr_asm_len ("clr %0", op, plen, 1);
7526
7527 break;
7528 }
7529
7530 /* We set the MSB in the unsigned case and the 2 MSBs in the signed case.
7531 Now copy the right value to the LSBs. */
7532
7533 if (need_copy && n_bytes > 1)
7534 {
7535 if (US_MINUS == code_sat || US_PLUS == code_sat)
7536 {
7537 avr_asm_len ("mov %1,%0", op, plen, 1);
7538
7539 if (n_bytes > 2)
7540 {
7541 op[0] = xop[0];
7542 if (AVR_HAVE_MOVW)
7543 avr_asm_len ("movw %0,%1", op, plen, 1);
7544 else
7545 avr_asm_len ("mov %A0,%1" CR_TAB
7546 "mov %B0,%1", op, plen, 2);
7547 }
7548 }
7549 else if (n_bytes > 2)
7550 {
7551 op[0] = xop[0];
7552 avr_asm_len ("mov %A0,%1" CR_TAB
7553 "mov %B0,%1", op, plen, 2);
7554 }
7555 }
7556
7557 if (need_copy && n_bytes == 8)
7558 {
7559 if (AVR_HAVE_MOVW)
7560 avr_asm_len ("movw %r0+2,%0" CR_TAB
7561 "movw %r0+4,%0", xop, plen, 2);
7562 else
7563 avr_asm_len ("mov %r0+2,%0" CR_TAB
7564 "mov %r0+3,%0" CR_TAB
7565 "mov %r0+4,%0" CR_TAB
7566 "mov %r0+5,%0", xop, plen, 4);
7567 }
7568
7569 if (out_label)
7570 avr_asm_len ("0:", op, plen, 0);
7571 }
7572
7573
7574 /* Output addition/subtraction of register XOP[0] and a constant XOP[2] that
7575 is ont a compile-time constant:
7576
7577 XOP[0] = XOP[0] +/- XOP[2]
7578
7579 This is a helper for the function below. The only insns that need this
7580 are additions/subtraction for pointer modes, i.e. HImode and PSImode. */
7581
7582 static const char*
avr_out_plus_symbol(rtx * xop,enum rtx_code code,int * plen,int * pcc)7583 avr_out_plus_symbol (rtx *xop, enum rtx_code code, int *plen, int *pcc)
7584 {
7585 machine_mode mode = GET_MODE (xop[0]);
7586
7587 /* Only pointer modes want to add symbols. */
7588
7589 gcc_assert (mode == HImode || mode == PSImode);
7590
7591 *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_SET_N;
7592
7593 avr_asm_len (PLUS == code
7594 ? "subi %A0,lo8(-(%2))" CR_TAB "sbci %B0,hi8(-(%2))"
7595 : "subi %A0,lo8(%2)" CR_TAB "sbci %B0,hi8(%2)",
7596 xop, plen, -2);
7597
7598 if (PSImode == mode)
7599 avr_asm_len (PLUS == code
7600 ? "sbci %C0,hlo8(-(%2))"
7601 : "sbci %C0,hlo8(%2)", xop, plen, 1);
7602 return "";
7603 }
7604
7605
7606 /* Prepare operands of addition/subtraction to be used with avr_out_plus_1.
7607
7608 INSN is a single_set insn or an insn pattern with a binary operation as
7609 SET_SRC that is one of: PLUS, SS_PLUS, US_PLUS, MINUS, SS_MINUS, US_MINUS.
7610
7611 XOP are the operands of INSN. In the case of 64-bit operations with
7612 constant XOP[] has just one element: The summand/subtrahend in XOP[0].
7613 The non-saturating insns up to 32 bits may or may not supply a "d" class
7614 scratch as XOP[3].
7615
7616 If PLEN == NULL output the instructions.
7617 If PLEN != NULL set *PLEN to the length of the sequence in words.
7618
7619 PCC is a pointer to store the instructions' effect on cc0.
7620 PCC may be NULL.
7621
7622 PLEN and PCC default to NULL.
7623
7624 OUT_LABEL defaults to TRUE. For a description, see AVR_OUT_PLUS_1.
7625
7626 Return "" */
7627
7628 const char*
avr_out_plus(rtx insn,rtx * xop,int * plen,int * pcc,bool out_label)7629 avr_out_plus (rtx insn, rtx *xop, int *plen, int *pcc, bool out_label)
7630 {
7631 int cc_plus, cc_minus, cc_dummy;
7632 int len_plus, len_minus;
7633 rtx op[4];
7634 rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
7635 rtx xdest = SET_DEST (xpattern);
7636 machine_mode mode = GET_MODE (xdest);
7637 machine_mode imode = int_mode_for_mode (mode);
7638 int n_bytes = GET_MODE_SIZE (mode);
7639 enum rtx_code code_sat = GET_CODE (SET_SRC (xpattern));
7640 enum rtx_code code
7641 = (PLUS == code_sat || SS_PLUS == code_sat || US_PLUS == code_sat
7642 ? PLUS : MINUS);
7643
7644 if (!pcc)
7645 pcc = &cc_dummy;
7646
7647 /* PLUS and MINUS don't saturate: Use modular wrap-around. */
7648
7649 if (PLUS == code_sat || MINUS == code_sat)
7650 code_sat = UNKNOWN;
7651
7652 if (n_bytes <= 4 && REG_P (xop[2]))
7653 {
7654 avr_out_plus_1 (xop, plen, code, pcc, code_sat, 0, out_label);
7655 return "";
7656 }
7657
7658 if (8 == n_bytes)
7659 {
7660 op[0] = gen_rtx_REG (DImode, ACC_A);
7661 op[1] = gen_rtx_REG (DImode, ACC_A);
7662 op[2] = avr_to_int_mode (xop[0]);
7663 }
7664 else
7665 {
7666 if (!REG_P (xop[2])
7667 && !CONST_INT_P (xop[2])
7668 && !CONST_FIXED_P (xop[2]))
7669 {
7670 return avr_out_plus_symbol (xop, code, plen, pcc);
7671 }
7672
7673 op[0] = avr_to_int_mode (xop[0]);
7674 op[1] = avr_to_int_mode (xop[1]);
7675 op[2] = avr_to_int_mode (xop[2]);
7676 }
7677
7678 /* Saturations and 64-bit operations don't have a clobber operand.
7679 For the other cases, the caller will provide a proper XOP[3]. */
7680
7681 xpattern = INSN_P (insn) ? PATTERN (insn) : insn;
7682 op[3] = PARALLEL == GET_CODE (xpattern) ? xop[3] : NULL_RTX;
7683
7684 /* Saturation will need the sign of the original operand. */
7685
7686 rtx xmsb = simplify_gen_subreg (QImode, op[2], imode, n_bytes-1);
7687 int sign = INTVAL (xmsb) < 0 ? -1 : 1;
7688
7689 /* If we subtract and the subtrahend is a constant, then negate it
7690 so that avr_out_plus_1 can be used. */
7691
7692 if (MINUS == code)
7693 op[2] = simplify_unary_operation (NEG, imode, op[2], imode);
7694
7695 /* Work out the shortest sequence. */
7696
7697 avr_out_plus_1 (op, &len_minus, MINUS, &cc_minus, code_sat, sign, out_label);
7698 avr_out_plus_1 (op, &len_plus, PLUS, &cc_plus, code_sat, sign, out_label);
7699
7700 if (plen)
7701 {
7702 *plen = (len_minus <= len_plus) ? len_minus : len_plus;
7703 *pcc = (len_minus <= len_plus) ? cc_minus : cc_plus;
7704 }
7705 else if (len_minus <= len_plus)
7706 avr_out_plus_1 (op, NULL, MINUS, pcc, code_sat, sign, out_label);
7707 else
7708 avr_out_plus_1 (op, NULL, PLUS, pcc, code_sat, sign, out_label);
7709
7710 return "";
7711 }
7712
7713
7714 /* Output bit operation (IOR, AND, XOR) with register XOP[0] and compile
7715 time constant XOP[2]:
7716
7717 XOP[0] = XOP[0] <op> XOP[2]
7718
7719 and return "". If PLEN == NULL, print assembler instructions to perform the
7720 operation; otherwise, set *PLEN to the length of the instruction sequence
7721 (in words) printed with PLEN == NULL. XOP[3] is either an 8-bit clobber
7722 register or SCRATCH if no clobber register is needed for the operation.
7723 INSN is an INSN_P or a pattern of an insn. */
7724
7725 const char*
avr_out_bitop(rtx insn,rtx * xop,int * plen)7726 avr_out_bitop (rtx insn, rtx *xop, int *plen)
7727 {
7728 /* CODE and MODE of the operation. */
7729 rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
7730 enum rtx_code code = GET_CODE (SET_SRC (xpattern));
7731 machine_mode mode = GET_MODE (xop[0]);
7732
7733 /* Number of bytes to operate on. */
7734 int i, n_bytes = GET_MODE_SIZE (mode);
7735
7736 /* Value of T-flag (0 or 1) or -1 if unknow. */
7737 int set_t = -1;
7738
7739 /* Value (0..0xff) held in clobber register op[3] or -1 if unknown. */
7740 int clobber_val = -1;
7741
7742 /* op[0]: 8-bit destination register
7743 op[1]: 8-bit const int
7744 op[2]: 8-bit clobber register or SCRATCH
7745 op[3]: 8-bit register containing 0xff or NULL_RTX */
7746 rtx op[4];
7747
7748 op[2] = xop[3];
7749 op[3] = NULL_RTX;
7750
7751 if (plen)
7752 *plen = 0;
7753
7754 for (i = 0; i < n_bytes; i++)
7755 {
7756 /* We operate byte-wise on the destination. */
7757 rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
7758 rtx xval8 = simplify_gen_subreg (QImode, xop[2], mode, i);
7759
7760 /* 8-bit value to operate with this byte. */
7761 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
7762
7763 /* Number of bits set in the current byte of the constant. */
7764 int pop8 = avr_popcount (val8);
7765
7766 /* Registers R16..R31 can operate with immediate. */
7767 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
7768
7769 op[0] = reg8;
7770 op[1] = GEN_INT (val8);
7771
7772 switch (code)
7773 {
7774 case IOR:
7775
7776 if (0 == pop8)
7777 continue;
7778 else if (ld_reg_p)
7779 avr_asm_len ("ori %0,%1", op, plen, 1);
7780 else if (1 == pop8)
7781 {
7782 if (set_t != 1)
7783 avr_asm_len ("set", op, plen, 1);
7784 set_t = 1;
7785
7786 op[1] = GEN_INT (exact_log2 (val8));
7787 avr_asm_len ("bld %0,%1", op, plen, 1);
7788 }
7789 else if (8 == pop8)
7790 {
7791 if (op[3] != NULL_RTX)
7792 avr_asm_len ("mov %0,%3", op, plen, 1);
7793 else
7794 avr_asm_len ("clr %0" CR_TAB
7795 "dec %0", op, plen, 2);
7796
7797 op[3] = op[0];
7798 }
7799 else
7800 {
7801 if (clobber_val != (int) val8)
7802 avr_asm_len ("ldi %2,%1", op, plen, 1);
7803 clobber_val = (int) val8;
7804
7805 avr_asm_len ("or %0,%2", op, plen, 1);
7806 }
7807
7808 continue; /* IOR */
7809
7810 case AND:
7811
7812 if (8 == pop8)
7813 continue;
7814 else if (0 == pop8)
7815 avr_asm_len ("clr %0", op, plen, 1);
7816 else if (ld_reg_p)
7817 avr_asm_len ("andi %0,%1", op, plen, 1);
7818 else if (7 == pop8)
7819 {
7820 if (set_t != 0)
7821 avr_asm_len ("clt", op, plen, 1);
7822 set_t = 0;
7823
7824 op[1] = GEN_INT (exact_log2 (GET_MODE_MASK (QImode) & ~val8));
7825 avr_asm_len ("bld %0,%1", op, plen, 1);
7826 }
7827 else
7828 {
7829 if (clobber_val != (int) val8)
7830 avr_asm_len ("ldi %2,%1", op, plen, 1);
7831 clobber_val = (int) val8;
7832
7833 avr_asm_len ("and %0,%2", op, plen, 1);
7834 }
7835
7836 continue; /* AND */
7837
7838 case XOR:
7839
7840 if (0 == pop8)
7841 continue;
7842 else if (8 == pop8)
7843 avr_asm_len ("com %0", op, plen, 1);
7844 else if (ld_reg_p && val8 == (1 << 7))
7845 avr_asm_len ("subi %0,%1", op, plen, 1);
7846 else
7847 {
7848 if (clobber_val != (int) val8)
7849 avr_asm_len ("ldi %2,%1", op, plen, 1);
7850 clobber_val = (int) val8;
7851
7852 avr_asm_len ("eor %0,%2", op, plen, 1);
7853 }
7854
7855 continue; /* XOR */
7856
7857 default:
7858 /* Unknown rtx_code */
7859 gcc_unreachable();
7860 }
7861 } /* for all sub-bytes */
7862
7863 return "";
7864 }
7865
7866
7867 /* Output sign extension from XOP[1] to XOP[0] and return "".
7868 If PLEN == NULL, print assembler instructions to perform the operation;
7869 otherwise, set *PLEN to the length of the instruction sequence (in words)
7870 as printed with PLEN == NULL. */
7871
7872 const char*
avr_out_sign_extend(rtx_insn * insn,rtx * xop,int * plen)7873 avr_out_sign_extend (rtx_insn *insn, rtx *xop, int *plen)
7874 {
7875 // Size in bytes of source resp. destination operand.
7876 unsigned n_src = GET_MODE_SIZE (GET_MODE (xop[1]));
7877 unsigned n_dest = GET_MODE_SIZE (GET_MODE (xop[0]));
7878 rtx r_msb = all_regs_rtx[REGNO (xop[1]) + n_src - 1];
7879
7880 if (plen)
7881 *plen = 0;
7882
7883 // Copy destination to source
7884
7885 if (REGNO (xop[0]) != REGNO (xop[1]))
7886 {
7887 gcc_assert (n_src <= 2);
7888
7889 if (n_src == 2)
7890 avr_asm_len (AVR_HAVE_MOVW
7891 ? "movw %0,%1"
7892 : "mov %B0,%B1", xop, plen, 1);
7893 if (n_src == 1 || !AVR_HAVE_MOVW)
7894 avr_asm_len ("mov %A0,%A1", xop, plen, 1);
7895 }
7896
7897 // Set Carry to the sign bit MSB.7...
7898
7899 if (REGNO (xop[0]) == REGNO (xop[1])
7900 || !reg_unused_after (insn, r_msb))
7901 {
7902 avr_asm_len ("mov __tmp_reg__,%0", &r_msb, plen, 1);
7903 r_msb = tmp_reg_rtx;
7904 }
7905
7906 avr_asm_len ("lsl %0", &r_msb, plen, 1);
7907
7908 // ...and propagate it to all the new sign bits
7909
7910 for (unsigned n = n_src; n < n_dest; n++)
7911 avr_asm_len ("sbc %0,%0", &all_regs_rtx[REGNO (xop[0]) + n], plen, 1);
7912
7913 return "";
7914 }
7915
7916
7917 /* PLEN == NULL: Output code to add CONST_INT OP[0] to SP.
7918 PLEN != NULL: Set *PLEN to the length of that sequence.
7919 Return "". */
7920
7921 const char*
avr_out_addto_sp(rtx * op,int * plen)7922 avr_out_addto_sp (rtx *op, int *plen)
7923 {
7924 int pc_len = AVR_2_BYTE_PC ? 2 : 3;
7925 int addend = INTVAL (op[0]);
7926
7927 if (plen)
7928 *plen = 0;
7929
7930 if (addend < 0)
7931 {
7932 if (flag_verbose_asm || flag_print_asm_name)
7933 avr_asm_len (ASM_COMMENT_START "SP -= %n0", op, plen, 0);
7934
7935 while (addend <= -pc_len)
7936 {
7937 addend += pc_len;
7938 avr_asm_len ("rcall .", op, plen, 1);
7939 }
7940
7941 while (addend++ < 0)
7942 avr_asm_len ("push __zero_reg__", op, plen, 1);
7943 }
7944 else if (addend > 0)
7945 {
7946 if (flag_verbose_asm || flag_print_asm_name)
7947 avr_asm_len (ASM_COMMENT_START "SP += %0", op, plen, 0);
7948
7949 while (addend-- > 0)
7950 avr_asm_len ("pop __tmp_reg__", op, plen, 1);
7951 }
7952
7953 return "";
7954 }
7955
7956
7957 /* Outputs instructions needed for fixed point type conversion.
7958 This includes converting between any fixed point type, as well
7959 as converting to any integer type. Conversion between integer
7960 types is not supported.
7961
7962 Converting signed fractional types requires a bit shift if converting
7963 to or from any unsigned fractional type because the decimal place is
7964 shifted by 1 bit. When the destination is a signed fractional, the sign
7965 is stored in either the carry or T bit. */
7966
7967 const char*
avr_out_fract(rtx_insn * insn,rtx operands[],bool intsigned,int * plen)7968 avr_out_fract (rtx_insn *insn, rtx operands[], bool intsigned, int *plen)
7969 {
7970 size_t i;
7971 rtx xop[6];
7972 RTX_CODE shift = UNKNOWN;
7973 bool sign_in_carry = false;
7974 bool msb_in_carry = false;
7975 bool lsb_in_tmp_reg = false;
7976 bool lsb_in_carry = false;
7977 bool frac_rounded = false;
7978 const char *code_ashift = "lsl %0";
7979
7980
7981 #define MAY_CLOBBER(RR) \
7982 /* Shorthand used below. */ \
7983 ((sign_bytes \
7984 && IN_RANGE (RR, dest.regno_msb - sign_bytes + 1, dest.regno_msb)) \
7985 || (offset && IN_RANGE (RR, dest.regno, dest.regno_msb)) \
7986 || (reg_unused_after (insn, all_regs_rtx[RR]) \
7987 && !IN_RANGE (RR, dest.regno, dest.regno_msb)))
7988
7989 struct
7990 {
7991 /* bytes : Length of operand in bytes.
7992 ibyte : Length of integral part in bytes.
7993 fbyte, fbit : Length of fractional part in bytes, bits. */
7994
7995 bool sbit;
7996 unsigned fbit, bytes, ibyte, fbyte;
7997 unsigned regno, regno_msb;
7998 } dest, src, *val[2] = { &dest, &src };
7999
8000 if (plen)
8001 *plen = 0;
8002
8003 /* Step 0: Determine information on source and destination operand we
8004 ====== will need in the remainder. */
8005
8006 for (i = 0; i < sizeof (val) / sizeof (*val); i++)
8007 {
8008 machine_mode mode;
8009
8010 xop[i] = operands[i];
8011
8012 mode = GET_MODE (xop[i]);
8013
8014 val[i]->bytes = GET_MODE_SIZE (mode);
8015 val[i]->regno = REGNO (xop[i]);
8016 val[i]->regno_msb = REGNO (xop[i]) + val[i]->bytes - 1;
8017
8018 if (SCALAR_INT_MODE_P (mode))
8019 {
8020 val[i]->sbit = intsigned;
8021 val[i]->fbit = 0;
8022 }
8023 else if (ALL_SCALAR_FIXED_POINT_MODE_P (mode))
8024 {
8025 val[i]->sbit = SIGNED_SCALAR_FIXED_POINT_MODE_P (mode);
8026 val[i]->fbit = GET_MODE_FBIT (mode);
8027 }
8028 else
8029 fatal_insn ("unsupported fixed-point conversion", insn);
8030
8031 val[i]->fbyte = (1 + val[i]->fbit) / BITS_PER_UNIT;
8032 val[i]->ibyte = val[i]->bytes - val[i]->fbyte;
8033 }
8034
8035 // Byte offset of the decimal point taking into account different place
8036 // of the decimal point in input and output and different register numbers
8037 // of input and output.
8038 int offset = dest.regno - src.regno + dest.fbyte - src.fbyte;
8039
8040 // Number of destination bytes that will come from sign / zero extension.
8041 int sign_bytes = (dest.ibyte - src.ibyte) * (dest.ibyte > src.ibyte);
8042
8043 // Number of bytes at the low end to be filled with zeros.
8044 int zero_bytes = (dest.fbyte - src.fbyte) * (dest.fbyte > src.fbyte);
8045
8046 // Do we have a 16-Bit register that is cleared?
8047 rtx clrw = NULL_RTX;
8048
8049 bool sign_extend = src.sbit && sign_bytes;
8050
8051 if (0 == dest.fbit % 8 && 7 == src.fbit % 8)
8052 shift = ASHIFT;
8053 else if (7 == dest.fbit % 8 && 0 == src.fbit % 8)
8054 shift = ASHIFTRT;
8055 else if (dest.fbit % 8 == src.fbit % 8)
8056 shift = UNKNOWN;
8057 else
8058 gcc_unreachable();
8059
8060 /* If we need to round the fraction part, we might need to save/round it
8061 before clobbering any of it in Step 1. Also, we might want to do
8062 the rounding now to make use of LD_REGS. */
8063 if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8064 && SCALAR_ACCUM_MODE_P (GET_MODE (xop[1]))
8065 && !TARGET_FRACT_CONV_TRUNC)
8066 {
8067 bool overlap
8068 = (src.regno <=
8069 (offset ? dest.regno_msb - sign_bytes : dest.regno + zero_bytes - 1)
8070 && dest.regno - offset -1 >= dest.regno);
8071 unsigned s0 = dest.regno - offset -1;
8072 bool use_src = true;
8073 unsigned sn;
8074 unsigned copied_msb = src.regno_msb;
8075 bool have_carry = false;
8076
8077 if (src.ibyte > dest.ibyte)
8078 copied_msb -= src.ibyte - dest.ibyte;
8079
8080 for (sn = s0; sn <= copied_msb; sn++)
8081 if (!IN_RANGE (sn, dest.regno, dest.regno_msb)
8082 && !reg_unused_after (insn, all_regs_rtx[sn]))
8083 use_src = false;
8084 if (use_src && TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], s0))
8085 {
8086 avr_asm_len ("tst %0" CR_TAB "brpl 0f",
8087 &all_regs_rtx[src.regno_msb], plen, 2);
8088 sn = src.regno;
8089 if (sn < s0)
8090 {
8091 if (TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], sn))
8092 avr_asm_len ("cpi %0,1", &all_regs_rtx[sn], plen, 1);
8093 else
8094 avr_asm_len ("sec" CR_TAB
8095 "cpc %0,__zero_reg__",
8096 &all_regs_rtx[sn], plen, 2);
8097 have_carry = true;
8098 }
8099 while (++sn < s0)
8100 avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8101
8102 avr_asm_len (have_carry ? "sbci %0,128" : "subi %0,129",
8103 &all_regs_rtx[s0], plen, 1);
8104 for (sn = src.regno + src.fbyte; sn <= copied_msb; sn++)
8105 avr_asm_len ("sbci %0,255", &all_regs_rtx[sn], plen, 1);
8106 avr_asm_len ("\n0:", NULL, plen, 0);
8107 frac_rounded = true;
8108 }
8109 else if (use_src && overlap)
8110 {
8111 avr_asm_len ("clr __tmp_reg__" CR_TAB
8112 "sbrc %1,0" CR_TAB
8113 "dec __tmp_reg__", xop, plen, 1);
8114 sn = src.regno;
8115 if (sn < s0)
8116 {
8117 avr_asm_len ("add %0,__tmp_reg__", &all_regs_rtx[sn], plen, 1);
8118 have_carry = true;
8119 }
8120
8121 while (++sn < s0)
8122 avr_asm_len ("adc %0,__tmp_reg__", &all_regs_rtx[sn], plen, 1);
8123
8124 if (have_carry)
8125 avr_asm_len ("clt" CR_TAB
8126 "bld __tmp_reg__,7" CR_TAB
8127 "adc %0,__tmp_reg__",
8128 &all_regs_rtx[s0], plen, 1);
8129 else
8130 avr_asm_len ("lsr __tmp_reg" CR_TAB
8131 "add %0,__tmp_reg__",
8132 &all_regs_rtx[s0], plen, 2);
8133 for (sn = src.regno + src.fbyte; sn <= copied_msb; sn++)
8134 avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8135 frac_rounded = true;
8136 }
8137 else if (overlap)
8138 {
8139 bool use_src
8140 = (TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], s0)
8141 && (IN_RANGE (s0, dest.regno, dest.regno_msb)
8142 || reg_unused_after (insn, all_regs_rtx[s0])));
8143 xop[2] = all_regs_rtx[s0];
8144 unsigned sn = src.regno;
8145 if (!use_src || sn == s0)
8146 avr_asm_len ("mov __tmp_reg__,%2", xop, plen, 1);
8147 /* We need to consider to-be-discarded bits
8148 if the value is negative. */
8149 if (sn < s0)
8150 {
8151 avr_asm_len ("tst %0" CR_TAB
8152 "brpl 0f",
8153 &all_regs_rtx[src.regno_msb], plen, 2);
8154 /* Test to-be-discarded bytes for any nozero bits.
8155 ??? Could use OR or SBIW to test two registers at once. */
8156 if (sn < s0)
8157 avr_asm_len ("cp %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8158
8159 while (++sn < s0)
8160 avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8161 /* Set bit 0 in __tmp_reg__ if any of the lower bits was set. */
8162 if (use_src)
8163 avr_asm_len ("breq 0f" CR_TAB
8164 "ori %2,1"
8165 "\n0:\t" "mov __tmp_reg__,%2",
8166 xop, plen, 3);
8167 else
8168 avr_asm_len ("breq 0f" CR_TAB
8169 "set" CR_TAB
8170 "bld __tmp_reg__,0\n0:",
8171 xop, plen, 3);
8172 }
8173 lsb_in_tmp_reg = true;
8174 }
8175 }
8176
8177 /* Step 1: Clear bytes at the low end and copy payload bits from source
8178 ====== to destination. */
8179
8180 int step = offset < 0 ? 1 : -1;
8181 unsigned d0 = offset < 0 ? dest.regno : dest.regno_msb;
8182
8183 // We cleared at least that number of registers.
8184 int clr_n = 0;
8185
8186 for (; d0 >= dest.regno && d0 <= dest.regno_msb; d0 += step)
8187 {
8188 // Next regno of destination is needed for MOVW
8189 unsigned d1 = d0 + step;
8190
8191 // Current and next regno of source
8192 signed s0 = d0 - offset;
8193 signed s1 = s0 + step;
8194
8195 // Must current resp. next regno be CLRed? This applies to the low
8196 // bytes of the destination that have no associated source bytes.
8197 bool clr0 = s0 < (signed) src.regno;
8198 bool clr1 = s1 < (signed) src.regno && d1 >= dest.regno;
8199
8200 // First gather what code to emit (if any) and additional step to
8201 // apply if a MOVW is in use. xop[2] is destination rtx and xop[3]
8202 // is the source rtx for the current loop iteration.
8203 const char *code = NULL;
8204 int stepw = 0;
8205
8206 if (clr0)
8207 {
8208 if (AVR_HAVE_MOVW && clr1 && clrw)
8209 {
8210 xop[2] = all_regs_rtx[d0 & ~1];
8211 xop[3] = clrw;
8212 code = "movw %2,%3";
8213 stepw = step;
8214 }
8215 else
8216 {
8217 xop[2] = all_regs_rtx[d0];
8218 code = "clr %2";
8219
8220 if (++clr_n >= 2
8221 && !clrw
8222 && d0 % 2 == (step > 0))
8223 {
8224 clrw = all_regs_rtx[d0 & ~1];
8225 }
8226 }
8227 }
8228 else if (offset && s0 <= (signed) src.regno_msb)
8229 {
8230 int movw = AVR_HAVE_MOVW && offset % 2 == 0
8231 && d0 % 2 == (offset > 0)
8232 && d1 <= dest.regno_msb && d1 >= dest.regno
8233 && s1 <= (signed) src.regno_msb && s1 >= (signed) src.regno;
8234
8235 xop[2] = all_regs_rtx[d0 & ~movw];
8236 xop[3] = all_regs_rtx[s0 & ~movw];
8237 code = movw ? "movw %2,%3" : "mov %2,%3";
8238 stepw = step * movw;
8239 }
8240
8241 if (code)
8242 {
8243 if (sign_extend && shift != ASHIFT && !sign_in_carry
8244 && (d0 == src.regno_msb || d0 + stepw == src.regno_msb))
8245 {
8246 /* We are going to override the sign bit. If we sign-extend,
8247 store the sign in the Carry flag. This is not needed if
8248 the destination will be ASHIFT in the remainder because
8249 the ASHIFT will set Carry without extra instruction. */
8250
8251 avr_asm_len ("lsl %0", &all_regs_rtx[src.regno_msb], plen, 1);
8252 sign_in_carry = true;
8253 }
8254
8255 unsigned src_msb = dest.regno_msb - sign_bytes - offset + 1;
8256
8257 if (!sign_extend && shift == ASHIFTRT && !msb_in_carry
8258 && src.ibyte > dest.ibyte
8259 && (d0 == src_msb || d0 + stepw == src_msb))
8260 {
8261 /* We are going to override the MSB. If we shift right,
8262 store the MSB in the Carry flag. This is only needed if
8263 we don't sign-extend becaue with sign-extension the MSB
8264 (the sign) will be produced by the sign extension. */
8265
8266 avr_asm_len ("lsr %0", &all_regs_rtx[src_msb], plen, 1);
8267 msb_in_carry = true;
8268 }
8269
8270 unsigned src_lsb = dest.regno - offset -1;
8271
8272 if (shift == ASHIFT && src.fbyte > dest.fbyte && !lsb_in_carry
8273 && !lsb_in_tmp_reg
8274 && (d0 == src_lsb || d0 + stepw == src_lsb))
8275 {
8276 /* We are going to override the new LSB; store it into carry. */
8277
8278 avr_asm_len ("lsl %0", &all_regs_rtx[src_lsb], plen, 1);
8279 code_ashift = "rol %0";
8280 lsb_in_carry = true;
8281 }
8282
8283 avr_asm_len (code, xop, plen, 1);
8284 d0 += stepw;
8285 }
8286 }
8287
8288 /* Step 2: Shift destination left by 1 bit position. This might be needed
8289 ====== for signed input and unsigned output. */
8290
8291 if (shift == ASHIFT && src.fbyte > dest.fbyte && !lsb_in_carry)
8292 {
8293 unsigned s0 = dest.regno - offset -1;
8294
8295 /* n1169 4.1.4 says:
8296 "Conversions from a fixed-point to an integer type round toward zero."
8297 Hence, converting a fract type to integer only gives a non-zero result
8298 for -1. */
8299 if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8300 && SCALAR_FRACT_MODE_P (GET_MODE (xop[1]))
8301 && !TARGET_FRACT_CONV_TRUNC)
8302 {
8303 gcc_assert (s0 == src.regno_msb);
8304 /* Check if the input is -1. We do that by checking if negating
8305 the input causes an integer overflow. */
8306 unsigned sn = src.regno;
8307 avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx[sn++], plen, 1);
8308 while (sn <= s0)
8309 avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx[sn++], plen, 1);
8310
8311 /* Overflow goes with set carry. Clear carry otherwise. */
8312 avr_asm_len ("brvs 0f" CR_TAB
8313 "clc\n0:", NULL, plen, 2);
8314 }
8315 /* Likewise, when converting from accumulator types to integer, we
8316 need to round up negative values. */
8317 else if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8318 && SCALAR_ACCUM_MODE_P (GET_MODE (xop[1]))
8319 && !TARGET_FRACT_CONV_TRUNC
8320 && !frac_rounded)
8321 {
8322 bool have_carry = false;
8323
8324 xop[2] = all_regs_rtx[s0];
8325 if (!lsb_in_tmp_reg && !MAY_CLOBBER (s0))
8326 avr_asm_len ("mov __tmp_reg__,%2", xop, plen, 1);
8327 avr_asm_len ("tst %0" CR_TAB "brpl 0f",
8328 &all_regs_rtx[src.regno_msb], plen, 2);
8329 if (!lsb_in_tmp_reg)
8330 {
8331 unsigned sn = src.regno;
8332 if (sn < s0)
8333 {
8334 avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx[sn],
8335 plen, 1);
8336 have_carry = true;
8337 }
8338 while (++sn < s0)
8339 avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx[sn], plen, 1);
8340 lsb_in_tmp_reg = !MAY_CLOBBER (s0);
8341 }
8342 /* Add in C and the rounding value 127. */
8343 /* If the destination msb is a sign byte, and in LD_REGS,
8344 grab it as a temporary. */
8345 if (sign_bytes
8346 && TEST_HARD_REG_BIT (reg_class_contents[LD_REGS],
8347 dest.regno_msb))
8348 {
8349 xop[3] = all_regs_rtx[dest.regno_msb];
8350 avr_asm_len ("ldi %3,127", xop, plen, 1);
8351 avr_asm_len ((have_carry && lsb_in_tmp_reg ? "adc __tmp_reg__,%3"
8352 : have_carry ? "adc %2,%3"
8353 : lsb_in_tmp_reg ? "add __tmp_reg__,%3"
8354 : "add %2,%3"),
8355 xop, plen, 1);
8356 }
8357 else
8358 {
8359 /* Fall back to use __zero_reg__ as a temporary. */
8360 avr_asm_len ("dec __zero_reg__", NULL, plen, 1);
8361 if (have_carry)
8362 avr_asm_len ("clt" CR_TAB
8363 "bld __zero_reg__,7", NULL, plen, 2);
8364 else
8365 avr_asm_len ("lsr __zero_reg__", NULL, plen, 1);
8366 avr_asm_len (have_carry && lsb_in_tmp_reg
8367 ? "adc __tmp_reg__,__zero_reg__"
8368 : have_carry ? "adc %2,__zero_reg__"
8369 : lsb_in_tmp_reg ? "add __tmp_reg__,__zero_reg__"
8370 : "add %2,__zero_reg__",
8371 xop, plen, 1);
8372 avr_asm_len ("eor __zero_reg__,__zero_reg__", NULL, plen, 1);
8373 }
8374
8375 for (d0 = dest.regno + zero_bytes;
8376 d0 <= dest.regno_msb - sign_bytes; d0++)
8377 avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx[d0], plen, 1);
8378
8379 avr_asm_len (lsb_in_tmp_reg
8380 ? "\n0:\t" "lsl __tmp_reg__"
8381 : "\n0:\t" "lsl %2",
8382 xop, plen, 1);
8383 }
8384 else if (MAY_CLOBBER (s0))
8385 avr_asm_len ("lsl %0", &all_regs_rtx[s0], plen, 1);
8386 else
8387 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
8388 "lsl __tmp_reg__", &all_regs_rtx[s0], plen, 2);
8389
8390 code_ashift = "rol %0";
8391 lsb_in_carry = true;
8392 }
8393
8394 if (shift == ASHIFT)
8395 {
8396 for (d0 = dest.regno + zero_bytes;
8397 d0 <= dest.regno_msb - sign_bytes; d0++)
8398 {
8399 avr_asm_len (code_ashift, &all_regs_rtx[d0], plen, 1);
8400 code_ashift = "rol %0";
8401 }
8402
8403 lsb_in_carry = false;
8404 sign_in_carry = true;
8405 }
8406
8407 /* Step 4a: Store MSB in carry if we don't already have it or will produce
8408 ======= it in sign-extension below. */
8409
8410 if (!sign_extend && shift == ASHIFTRT && !msb_in_carry
8411 && src.ibyte > dest.ibyte)
8412 {
8413 unsigned s0 = dest.regno_msb - sign_bytes - offset + 1;
8414
8415 if (MAY_CLOBBER (s0))
8416 avr_asm_len ("lsr %0", &all_regs_rtx[s0], plen, 1);
8417 else
8418 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
8419 "lsr __tmp_reg__", &all_regs_rtx[s0], plen, 2);
8420
8421 msb_in_carry = true;
8422 }
8423
8424 /* Step 3: Sign-extend or zero-extend the destination as needed.
8425 ====== */
8426
8427 if (sign_extend && !sign_in_carry)
8428 {
8429 unsigned s0 = src.regno_msb;
8430
8431 if (MAY_CLOBBER (s0))
8432 avr_asm_len ("lsl %0", &all_regs_rtx[s0], plen, 1);
8433 else
8434 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
8435 "lsl __tmp_reg__", &all_regs_rtx[s0], plen, 2);
8436
8437 sign_in_carry = true;
8438 }
8439
8440 gcc_assert (sign_in_carry + msb_in_carry + lsb_in_carry <= 1);
8441
8442 unsigned copies = 0;
8443 rtx movw = sign_extend ? NULL_RTX : clrw;
8444
8445 for (d0 = dest.regno_msb - sign_bytes + 1; d0 <= dest.regno_msb; d0++)
8446 {
8447 if (AVR_HAVE_MOVW && movw
8448 && d0 % 2 == 0 && d0 + 1 <= dest.regno_msb)
8449 {
8450 xop[2] = all_regs_rtx[d0];
8451 xop[3] = movw;
8452 avr_asm_len ("movw %2,%3", xop, plen, 1);
8453 d0++;
8454 }
8455 else
8456 {
8457 avr_asm_len (sign_extend ? "sbc %0,%0" : "clr %0",
8458 &all_regs_rtx[d0], plen, 1);
8459
8460 if (++copies >= 2 && !movw && d0 % 2 == 1)
8461 movw = all_regs_rtx[d0-1];
8462 }
8463 } /* for */
8464
8465
8466 /* Step 4: Right shift the destination. This might be needed for
8467 ====== conversions from unsigned to signed. */
8468
8469 if (shift == ASHIFTRT)
8470 {
8471 const char *code_ashiftrt = "lsr %0";
8472
8473 if (sign_extend || msb_in_carry)
8474 code_ashiftrt = "ror %0";
8475
8476 if (src.sbit && src.ibyte == dest.ibyte)
8477 code_ashiftrt = "asr %0";
8478
8479 for (d0 = dest.regno_msb - sign_bytes;
8480 d0 >= dest.regno + zero_bytes - 1 && d0 >= dest.regno; d0--)
8481 {
8482 avr_asm_len (code_ashiftrt, &all_regs_rtx[d0], plen, 1);
8483 code_ashiftrt = "ror %0";
8484 }
8485 }
8486
8487 #undef MAY_CLOBBER
8488
8489 return "";
8490 }
8491
8492
8493 /* Output fixed-point rounding. XOP[0] = XOP[1] is the operand to round.
8494 XOP[2] is the rounding point, a CONST_INT. The function prints the
8495 instruction sequence if PLEN = NULL and computes the length in words
8496 of the sequence if PLEN != NULL. Most of this function deals with
8497 preparing operands for calls to `avr_out_plus' and `avr_out_bitop'. */
8498
8499 const char*
avr_out_round(rtx_insn * insn ATTRIBUTE_UNUSED,rtx * xop,int * plen)8500 avr_out_round (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *xop, int *plen)
8501 {
8502 machine_mode mode = GET_MODE (xop[0]);
8503 machine_mode imode = int_mode_for_mode (mode);
8504 // The smallest fractional bit not cleared by the rounding is 2^(-RP).
8505 int fbit = (int) GET_MODE_FBIT (mode);
8506 double_int i_add = double_int_zero.set_bit (fbit-1 - INTVAL (xop[2]));
8507 wide_int wi_add = wi::set_bit_in_zero (fbit-1 - INTVAL (xop[2]),
8508 GET_MODE_PRECISION (imode));
8509 // Lengths of PLUS and AND parts.
8510 int len_add = 0, *plen_add = plen ? &len_add : NULL;
8511 int len_and = 0, *plen_and = plen ? &len_and : NULL;
8512
8513 // Add-Saturate 1/2 * 2^(-RP). Don't print the label "0:" when printing
8514 // the saturated addition so that we can emit the "rjmp 1f" before the
8515 // "0:" below.
8516
8517 rtx xadd = const_fixed_from_double_int (i_add, mode);
8518 rtx xpattern, xsrc, op[4];
8519
8520 xsrc = SIGNED_FIXED_POINT_MODE_P (mode)
8521 ? gen_rtx_SS_PLUS (mode, xop[1], xadd)
8522 : gen_rtx_US_PLUS (mode, xop[1], xadd);
8523 xpattern = gen_rtx_SET (xop[0], xsrc);
8524
8525 op[0] = xop[0];
8526 op[1] = xop[1];
8527 op[2] = xadd;
8528 avr_out_plus (xpattern, op, plen_add, NULL, false /* Don't print "0:" */);
8529
8530 avr_asm_len ("rjmp 1f" CR_TAB
8531 "0:", NULL, plen_add, 1);
8532
8533 // Keep all bits from RP and higher: ... 2^(-RP)
8534 // Clear all bits from RP+1 and lower: 2^(-RP-1) ...
8535 // Rounding point ^^^^^^^
8536 // Added above ^^^^^^^^^
8537 rtx xreg = simplify_gen_subreg (imode, xop[0], mode, 0);
8538 rtx xmask = immed_wide_int_const (-wi_add - wi_add, imode);
8539
8540 xpattern = gen_rtx_SET (xreg, gen_rtx_AND (imode, xreg, xmask));
8541
8542 op[0] = xreg;
8543 op[1] = xreg;
8544 op[2] = xmask;
8545 op[3] = gen_rtx_SCRATCH (QImode);
8546 avr_out_bitop (xpattern, op, plen_and);
8547 avr_asm_len ("1:", NULL, plen, 0);
8548
8549 if (plen)
8550 *plen = len_add + len_and;
8551
8552 return "";
8553 }
8554
8555
8556 /* Create RTL split patterns for byte sized rotate expressions. This
8557 produces a series of move instructions and considers overlap situations.
8558 Overlapping non-HImode operands need a scratch register. */
8559
8560 bool
avr_rotate_bytes(rtx operands[])8561 avr_rotate_bytes (rtx operands[])
8562 {
8563 int i, j;
8564 machine_mode mode = GET_MODE (operands[0]);
8565 bool overlapped = reg_overlap_mentioned_p (operands[0], operands[1]);
8566 bool same_reg = rtx_equal_p (operands[0], operands[1]);
8567 int num = INTVAL (operands[2]);
8568 rtx scratch = operands[3];
8569 /* Work out if byte or word move is needed. Odd byte rotates need QImode.
8570 Word move if no scratch is needed, otherwise use size of scratch. */
8571 machine_mode move_mode = QImode;
8572 int move_size, offset, size;
8573
8574 if (num & 0xf)
8575 move_mode = QImode;
8576 else if ((mode == SImode && !same_reg) || !overlapped)
8577 move_mode = HImode;
8578 else
8579 move_mode = GET_MODE (scratch);
8580
8581 /* Force DI rotate to use QI moves since other DI moves are currently split
8582 into QI moves so forward propagation works better. */
8583 if (mode == DImode)
8584 move_mode = QImode;
8585 /* Make scratch smaller if needed. */
8586 if (SCRATCH != GET_CODE (scratch)
8587 && HImode == GET_MODE (scratch)
8588 && QImode == move_mode)
8589 scratch = simplify_gen_subreg (move_mode, scratch, HImode, 0);
8590
8591 move_size = GET_MODE_SIZE (move_mode);
8592 /* Number of bytes/words to rotate. */
8593 offset = (num >> 3) / move_size;
8594 /* Number of moves needed. */
8595 size = GET_MODE_SIZE (mode) / move_size;
8596 /* Himode byte swap is special case to avoid a scratch register. */
8597 if (mode == HImode && same_reg)
8598 {
8599 /* HImode byte swap, using xor. This is as quick as using scratch. */
8600 rtx src, dst;
8601 src = simplify_gen_subreg (move_mode, operands[1], mode, 0);
8602 dst = simplify_gen_subreg (move_mode, operands[0], mode, 1);
8603 if (!rtx_equal_p (dst, src))
8604 {
8605 emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
8606 emit_move_insn (src, gen_rtx_XOR (QImode, src, dst));
8607 emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
8608 }
8609 }
8610 else
8611 {
8612 #define MAX_SIZE 8 /* GET_MODE_SIZE (DImode) / GET_MODE_SIZE (QImode) */
8613 /* Create linked list of moves to determine move order. */
8614 struct {
8615 rtx src, dst;
8616 int links;
8617 } move[MAX_SIZE + 8];
8618 int blocked, moves;
8619
8620 gcc_assert (size <= MAX_SIZE);
8621 /* Generate list of subreg moves. */
8622 for (i = 0; i < size; i++)
8623 {
8624 int from = i;
8625 int to = (from + offset) % size;
8626 move[i].src = simplify_gen_subreg (move_mode, operands[1],
8627 mode, from * move_size);
8628 move[i].dst = simplify_gen_subreg (move_mode, operands[0],
8629 mode, to * move_size);
8630 move[i].links = -1;
8631 }
8632 /* Mark dependence where a dst of one move is the src of another move.
8633 The first move is a conflict as it must wait until second is
8634 performed. We ignore moves to self - we catch this later. */
8635 if (overlapped)
8636 for (i = 0; i < size; i++)
8637 if (reg_overlap_mentioned_p (move[i].dst, operands[1]))
8638 for (j = 0; j < size; j++)
8639 if (j != i && rtx_equal_p (move[j].src, move[i].dst))
8640 {
8641 /* The dst of move i is the src of move j. */
8642 move[i].links = j;
8643 break;
8644 }
8645
8646 blocked = -1;
8647 moves = 0;
8648 /* Go through move list and perform non-conflicting moves. As each
8649 non-overlapping move is made, it may remove other conflicts
8650 so the process is repeated until no conflicts remain. */
8651 do
8652 {
8653 blocked = -1;
8654 moves = 0;
8655 /* Emit move where dst is not also a src or we have used that
8656 src already. */
8657 for (i = 0; i < size; i++)
8658 if (move[i].src != NULL_RTX)
8659 {
8660 if (move[i].links == -1
8661 || move[move[i].links].src == NULL_RTX)
8662 {
8663 moves++;
8664 /* Ignore NOP moves to self. */
8665 if (!rtx_equal_p (move[i].dst, move[i].src))
8666 emit_move_insn (move[i].dst, move[i].src);
8667
8668 /* Remove conflict from list. */
8669 move[i].src = NULL_RTX;
8670 }
8671 else
8672 blocked = i;
8673 }
8674
8675 /* Check for deadlock. This is when no moves occurred and we have
8676 at least one blocked move. */
8677 if (moves == 0 && blocked != -1)
8678 {
8679 /* Need to use scratch register to break deadlock.
8680 Add move to put dst of blocked move into scratch.
8681 When this move occurs, it will break chain deadlock.
8682 The scratch register is substituted for real move. */
8683
8684 gcc_assert (SCRATCH != GET_CODE (scratch));
8685
8686 move[size].src = move[blocked].dst;
8687 move[size].dst = scratch;
8688 /* Scratch move is never blocked. */
8689 move[size].links = -1;
8690 /* Make sure we have valid link. */
8691 gcc_assert (move[blocked].links != -1);
8692 /* Replace src of blocking move with scratch reg. */
8693 move[move[blocked].links].src = scratch;
8694 /* Make dependent on scratch move occurring. */
8695 move[blocked].links = size;
8696 size=size+1;
8697 }
8698 }
8699 while (blocked != -1);
8700 }
8701 return true;
8702 }
8703
8704
8705 /* Worker function for `ADJUST_INSN_LENGTH'. */
8706 /* Modifies the length assigned to instruction INSN
8707 LEN is the initially computed length of the insn. */
8708
8709 int
avr_adjust_insn_length(rtx_insn * insn,int len)8710 avr_adjust_insn_length (rtx_insn *insn, int len)
8711 {
8712 rtx *op = recog_data.operand;
8713 enum attr_adjust_len adjust_len;
8714
8715 /* Some complex insns don't need length adjustment and therefore
8716 the length need not/must not be adjusted for these insns.
8717 It is easier to state this in an insn attribute "adjust_len" than
8718 to clutter up code here... */
8719
8720 if (!NONDEBUG_INSN_P (insn)
8721 || -1 == recog_memoized (insn))
8722 {
8723 return len;
8724 }
8725
8726 /* Read from insn attribute "adjust_len" if/how length is to be adjusted. */
8727
8728 adjust_len = get_attr_adjust_len (insn);
8729
8730 if (adjust_len == ADJUST_LEN_NO)
8731 {
8732 /* Nothing to adjust: The length from attribute "length" is fine.
8733 This is the default. */
8734
8735 return len;
8736 }
8737
8738 /* Extract insn's operands. */
8739
8740 extract_constrain_insn_cached (insn);
8741
8742 /* Dispatch to right function. */
8743
8744 switch (adjust_len)
8745 {
8746 case ADJUST_LEN_RELOAD_IN16: output_reload_inhi (op, op[2], &len); break;
8747 case ADJUST_LEN_RELOAD_IN24: avr_out_reload_inpsi (op, op[2], &len); break;
8748 case ADJUST_LEN_RELOAD_IN32: output_reload_insisf (op, op[2], &len); break;
8749
8750 case ADJUST_LEN_OUT_BITOP: avr_out_bitop (insn, op, &len); break;
8751
8752 case ADJUST_LEN_PLUS: avr_out_plus (insn, op, &len); break;
8753 case ADJUST_LEN_ADDTO_SP: avr_out_addto_sp (op, &len); break;
8754
8755 case ADJUST_LEN_MOV8: output_movqi (insn, op, &len); break;
8756 case ADJUST_LEN_MOV16: output_movhi (insn, op, &len); break;
8757 case ADJUST_LEN_MOV24: avr_out_movpsi (insn, op, &len); break;
8758 case ADJUST_LEN_MOV32: output_movsisf (insn, op, &len); break;
8759 case ADJUST_LEN_MOVMEM: avr_out_movmem (insn, op, &len); break;
8760 case ADJUST_LEN_XLOAD: avr_out_xload (insn, op, &len); break;
8761 case ADJUST_LEN_LPM: avr_out_lpm (insn, op, &len); break;
8762 case ADJUST_LEN_SEXT: avr_out_sign_extend (insn, op, &len); break;
8763
8764 case ADJUST_LEN_SFRACT: avr_out_fract (insn, op, true, &len); break;
8765 case ADJUST_LEN_UFRACT: avr_out_fract (insn, op, false, &len); break;
8766 case ADJUST_LEN_ROUND: avr_out_round (insn, op, &len); break;
8767
8768 case ADJUST_LEN_TSTHI: avr_out_tsthi (insn, op, &len); break;
8769 case ADJUST_LEN_TSTPSI: avr_out_tstpsi (insn, op, &len); break;
8770 case ADJUST_LEN_TSTSI: avr_out_tstsi (insn, op, &len); break;
8771 case ADJUST_LEN_COMPARE: avr_out_compare (insn, op, &len); break;
8772 case ADJUST_LEN_COMPARE64: avr_out_compare64 (insn, op, &len); break;
8773
8774 case ADJUST_LEN_LSHRQI: lshrqi3_out (insn, op, &len); break;
8775 case ADJUST_LEN_LSHRHI: lshrhi3_out (insn, op, &len); break;
8776 case ADJUST_LEN_LSHRSI: lshrsi3_out (insn, op, &len); break;
8777
8778 case ADJUST_LEN_ASHRQI: ashrqi3_out (insn, op, &len); break;
8779 case ADJUST_LEN_ASHRHI: ashrhi3_out (insn, op, &len); break;
8780 case ADJUST_LEN_ASHRSI: ashrsi3_out (insn, op, &len); break;
8781
8782 case ADJUST_LEN_ASHLQI: ashlqi3_out (insn, op, &len); break;
8783 case ADJUST_LEN_ASHLHI: ashlhi3_out (insn, op, &len); break;
8784 case ADJUST_LEN_ASHLSI: ashlsi3_out (insn, op, &len); break;
8785
8786 case ADJUST_LEN_ASHLPSI: avr_out_ashlpsi3 (insn, op, &len); break;
8787 case ADJUST_LEN_ASHRPSI: avr_out_ashrpsi3 (insn, op, &len); break;
8788 case ADJUST_LEN_LSHRPSI: avr_out_lshrpsi3 (insn, op, &len); break;
8789
8790 case ADJUST_LEN_CALL: len = AVR_HAVE_JMP_CALL ? 2 : 1; break;
8791
8792 case ADJUST_LEN_INSERT_BITS: avr_out_insert_bits (op, &len); break;
8793
8794 default:
8795 gcc_unreachable();
8796 }
8797
8798 return len;
8799 }
8800
8801 /* Return nonzero if register REG dead after INSN. */
8802
8803 int
reg_unused_after(rtx_insn * insn,rtx reg)8804 reg_unused_after (rtx_insn *insn, rtx reg)
8805 {
8806 return (dead_or_set_p (insn, reg)
8807 || (REG_P(reg) && _reg_unused_after (insn, reg)));
8808 }
8809
8810 /* Return nonzero if REG is not used after INSN.
8811 We assume REG is a reload reg, and therefore does
8812 not live past labels. It may live past calls or jumps though. */
8813
8814 int
_reg_unused_after(rtx_insn * insn,rtx reg)8815 _reg_unused_after (rtx_insn *insn, rtx reg)
8816 {
8817 enum rtx_code code;
8818 rtx set;
8819
8820 /* If the reg is set by this instruction, then it is safe for our
8821 case. Disregard the case where this is a store to memory, since
8822 we are checking a register used in the store address. */
8823 set = single_set (insn);
8824 if (set && GET_CODE (SET_DEST (set)) != MEM
8825 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
8826 return 1;
8827
8828 while ((insn = NEXT_INSN (insn)))
8829 {
8830 rtx set;
8831 code = GET_CODE (insn);
8832
8833 #if 0
8834 /* If this is a label that existed before reload, then the register
8835 if dead here. However, if this is a label added by reorg, then
8836 the register may still be live here. We can't tell the difference,
8837 so we just ignore labels completely. */
8838 if (code == CODE_LABEL)
8839 return 1;
8840 /* else */
8841 #endif
8842
8843 if (!INSN_P (insn))
8844 continue;
8845
8846 if (code == JUMP_INSN)
8847 return 0;
8848
8849 /* If this is a sequence, we must handle them all at once.
8850 We could have for instance a call that sets the target register,
8851 and an insn in a delay slot that uses the register. In this case,
8852 we must return 0. */
8853 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
8854 {
8855 rtx_sequence *seq = as_a <rtx_sequence *> (PATTERN (insn));
8856 int i;
8857 int retval = 0;
8858
8859 for (i = 0; i < seq->len (); i++)
8860 {
8861 rtx_insn *this_insn = seq->insn (i);
8862 rtx set = single_set (this_insn);
8863
8864 if (CALL_P (this_insn))
8865 code = CALL_INSN;
8866 else if (JUMP_P (this_insn))
8867 {
8868 if (INSN_ANNULLED_BRANCH_P (this_insn))
8869 return 0;
8870 code = JUMP_INSN;
8871 }
8872
8873 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
8874 return 0;
8875 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
8876 {
8877 if (GET_CODE (SET_DEST (set)) != MEM)
8878 retval = 1;
8879 else
8880 return 0;
8881 }
8882 if (set == 0
8883 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
8884 return 0;
8885 }
8886 if (retval == 1)
8887 return 1;
8888 else if (code == JUMP_INSN)
8889 return 0;
8890 }
8891
8892 if (code == CALL_INSN)
8893 {
8894 rtx tem;
8895 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
8896 if (GET_CODE (XEXP (tem, 0)) == USE
8897 && REG_P (XEXP (XEXP (tem, 0), 0))
8898 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
8899 return 0;
8900 if (call_used_regs[REGNO (reg)])
8901 return 1;
8902 }
8903
8904 set = single_set (insn);
8905
8906 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
8907 return 0;
8908 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
8909 return GET_CODE (SET_DEST (set)) != MEM;
8910 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
8911 return 0;
8912 }
8913 return 1;
8914 }
8915
8916
8917 /* Implement `TARGET_ASM_INTEGER'. */
8918 /* Target hook for assembling integer objects. The AVR version needs
8919 special handling for references to certain labels. */
8920
8921 static bool
avr_assemble_integer(rtx x,unsigned int size,int aligned_p)8922 avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
8923 {
8924 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
8925 && text_segment_operand (x, VOIDmode))
8926 {
8927 fputs ("\t.word\tgs(", asm_out_file);
8928 output_addr_const (asm_out_file, x);
8929 fputs (")\n", asm_out_file);
8930
8931 return true;
8932 }
8933 else if (GET_MODE (x) == PSImode)
8934 {
8935 /* This needs binutils 2.23+, see PR binutils/13503 */
8936
8937 fputs ("\t.byte\tlo8(", asm_out_file);
8938 output_addr_const (asm_out_file, x);
8939 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
8940
8941 fputs ("\t.byte\thi8(", asm_out_file);
8942 output_addr_const (asm_out_file, x);
8943 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
8944
8945 fputs ("\t.byte\thh8(", asm_out_file);
8946 output_addr_const (asm_out_file, x);
8947 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
8948
8949 return true;
8950 }
8951 else if (CONST_FIXED_P (x))
8952 {
8953 unsigned n;
8954
8955 /* varasm fails to handle big fixed modes that don't fit in hwi. */
8956
8957 for (n = 0; n < size; n++)
8958 {
8959 rtx xn = simplify_gen_subreg (QImode, x, GET_MODE (x), n);
8960 default_assemble_integer (xn, 1, aligned_p);
8961 }
8962
8963 return true;
8964 }
8965
8966 return default_assemble_integer (x, size, aligned_p);
8967 }
8968
8969
8970 /* Implement `TARGET_CLASS_LIKELY_SPILLED_P'. */
8971 /* Return value is nonzero if pseudos that have been
8972 assigned to registers of class CLASS would likely be spilled
8973 because registers of CLASS are needed for spill registers. */
8974
8975 static bool
avr_class_likely_spilled_p(reg_class_t c)8976 avr_class_likely_spilled_p (reg_class_t c)
8977 {
8978 return (c != ALL_REGS &&
8979 (AVR_TINY ? 1 : c != ADDW_REGS));
8980 }
8981
8982
8983 /* Valid attributes:
8984 progmem - Put data to program memory.
8985 signal - Make a function to be hardware interrupt.
8986 After function prologue interrupts remain disabled.
8987 interrupt - Make a function to be hardware interrupt. Before function
8988 prologue interrupts are enabled by means of SEI.
8989 naked - Don't generate function prologue/epilogue and RET
8990 instruction. */
8991
8992 /* Handle a "progmem" attribute; arguments as in
8993 struct attribute_spec.handler. */
8994
8995 static tree
avr_handle_progmem_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)8996 avr_handle_progmem_attribute (tree *node, tree name,
8997 tree args ATTRIBUTE_UNUSED,
8998 int flags ATTRIBUTE_UNUSED,
8999 bool *no_add_attrs)
9000 {
9001 if (DECL_P (*node))
9002 {
9003 if (TREE_CODE (*node) == TYPE_DECL)
9004 {
9005 /* This is really a decl attribute, not a type attribute,
9006 but try to handle it for GCC 3.0 backwards compatibility. */
9007
9008 tree type = TREE_TYPE (*node);
9009 tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
9010 tree newtype = build_type_attribute_variant (type, attr);
9011
9012 TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
9013 TREE_TYPE (*node) = newtype;
9014 *no_add_attrs = true;
9015 }
9016 else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
9017 {
9018 *no_add_attrs = false;
9019 }
9020 else
9021 {
9022 warning (OPT_Wattributes, "%qE attribute ignored",
9023 name);
9024 *no_add_attrs = true;
9025 }
9026 }
9027
9028 return NULL_TREE;
9029 }
9030
9031 /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
9032 struct attribute_spec.handler. */
9033
9034 static tree
avr_handle_fndecl_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)9035 avr_handle_fndecl_attribute (tree *node, tree name,
9036 tree args ATTRIBUTE_UNUSED,
9037 int flags ATTRIBUTE_UNUSED,
9038 bool *no_add_attrs)
9039 {
9040 if (TREE_CODE (*node) != FUNCTION_DECL)
9041 {
9042 warning (OPT_Wattributes, "%qE attribute only applies to functions",
9043 name);
9044 *no_add_attrs = true;
9045 }
9046
9047 return NULL_TREE;
9048 }
9049
9050 static tree
avr_handle_fntype_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)9051 avr_handle_fntype_attribute (tree *node, tree name,
9052 tree args ATTRIBUTE_UNUSED,
9053 int flags ATTRIBUTE_UNUSED,
9054 bool *no_add_attrs)
9055 {
9056 if (TREE_CODE (*node) != FUNCTION_TYPE)
9057 {
9058 warning (OPT_Wattributes, "%qE attribute only applies to functions",
9059 name);
9060 *no_add_attrs = true;
9061 }
9062
9063 return NULL_TREE;
9064 }
9065
9066 static tree
avr_handle_addr_attribute(tree * node,tree name,tree args,int flags ATTRIBUTE_UNUSED,bool * no_add)9067 avr_handle_addr_attribute (tree *node, tree name, tree args,
9068 int flags ATTRIBUTE_UNUSED, bool *no_add)
9069 {
9070 bool io_p = (strncmp (IDENTIFIER_POINTER (name), "io", 2) == 0);
9071 location_t loc = DECL_SOURCE_LOCATION (*node);
9072
9073 if (!VAR_P (*node))
9074 {
9075 warning_at (loc, OPT_Wattributes, "%qE attribute only applies to "
9076 "variables", name);
9077 *no_add = true;
9078 return NULL_TREE;
9079 }
9080
9081 if (args != NULL_TREE)
9082 {
9083 if (TREE_CODE (TREE_VALUE (args)) == NON_LVALUE_EXPR)
9084 TREE_VALUE (args) = TREE_OPERAND (TREE_VALUE (args), 0);
9085 tree arg = TREE_VALUE (args);
9086 if (TREE_CODE (arg) != INTEGER_CST)
9087 {
9088 warning_at (loc, OPT_Wattributes, "%qE attribute allows only an "
9089 "integer constant argument", name);
9090 *no_add = true;
9091 }
9092 else if (io_p
9093 && (!tree_fits_shwi_p (arg)
9094 || !(strcmp (IDENTIFIER_POINTER (name), "io_low") == 0
9095 ? low_io_address_operand : io_address_operand)
9096 (GEN_INT (TREE_INT_CST_LOW (arg)), QImode)))
9097 {
9098 warning_at (loc, OPT_Wattributes, "%qE attribute address "
9099 "out of range", name);
9100 *no_add = true;
9101 }
9102 else
9103 {
9104 tree attribs = DECL_ATTRIBUTES (*node);
9105 const char *names[] = { "io", "io_low", "address", NULL };
9106 for (const char **p = names; *p; p++)
9107 {
9108 tree other = lookup_attribute (*p, attribs);
9109 if (other && TREE_VALUE (other))
9110 {
9111 warning_at (loc, OPT_Wattributes,
9112 "both %s and %qE attribute provide address",
9113 *p, name);
9114 *no_add = true;
9115 break;
9116 }
9117 }
9118 }
9119 }
9120
9121 if (*no_add == false && io_p && !TREE_THIS_VOLATILE (*node))
9122 warning_at (loc, OPT_Wattributes, "%qE attribute on non-volatile variable",
9123 name);
9124
9125 return NULL_TREE;
9126 }
9127
9128 rtx
avr_eval_addr_attrib(rtx x)9129 avr_eval_addr_attrib (rtx x)
9130 {
9131 if (GET_CODE (x) == SYMBOL_REF
9132 && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_ADDRESS))
9133 {
9134 tree decl = SYMBOL_REF_DECL (x);
9135 tree attr = NULL_TREE;
9136
9137 if (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO)
9138 {
9139 attr = lookup_attribute ("io", DECL_ATTRIBUTES (decl));
9140 if (!attr || !TREE_VALUE (attr))
9141 attr = lookup_attribute ("io_low", DECL_ATTRIBUTES (decl));
9142 gcc_assert (attr);
9143 }
9144 if (!attr || !TREE_VALUE (attr))
9145 attr = lookup_attribute ("address", DECL_ATTRIBUTES (decl));
9146 gcc_assert (attr && TREE_VALUE (attr) && TREE_VALUE (TREE_VALUE (attr)));
9147 return GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))));
9148 }
9149 return x;
9150 }
9151
9152
9153 /* AVR attributes. */
9154 static const struct attribute_spec
9155 avr_attribute_table[] =
9156 {
9157 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
9158 affects_type_identity } */
9159 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute,
9160 false },
9161 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute,
9162 false },
9163 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute,
9164 false },
9165 { "naked", 0, 0, false, true, true, avr_handle_fntype_attribute,
9166 false },
9167 { "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute,
9168 false },
9169 { "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute,
9170 false },
9171 { "io", 0, 1, true, false, false, avr_handle_addr_attribute,
9172 false },
9173 { "io_low", 0, 1, true, false, false, avr_handle_addr_attribute,
9174 false },
9175 { "address", 1, 1, true, false, false, avr_handle_addr_attribute,
9176 false },
9177 { NULL, 0, 0, false, false, false, NULL, false }
9178 };
9179
9180
9181 /* Look if DECL shall be placed in program memory space by
9182 means of attribute `progmem' or some address-space qualifier.
9183 Return non-zero if DECL is data that must end up in Flash and
9184 zero if the data lives in RAM (.bss, .data, .rodata, ...).
9185
9186 Return 2 if DECL is located in 24-bit flash address-space
9187 Return 1 if DECL is located in 16-bit flash address-space
9188 Return -1 if attribute `progmem' occurs in DECL or ATTRIBUTES
9189 Return 0 otherwise */
9190
9191 int
avr_progmem_p(tree decl,tree attributes)9192 avr_progmem_p (tree decl, tree attributes)
9193 {
9194 tree a;
9195
9196 if (TREE_CODE (decl) != VAR_DECL)
9197 return 0;
9198
9199 if (avr_decl_memx_p (decl))
9200 return 2;
9201
9202 if (avr_decl_flash_p (decl))
9203 return 1;
9204
9205 if (NULL_TREE
9206 != lookup_attribute ("progmem", attributes))
9207 return -1;
9208
9209 a = decl;
9210
9211 do
9212 a = TREE_TYPE(a);
9213 while (TREE_CODE (a) == ARRAY_TYPE);
9214
9215 if (a == error_mark_node)
9216 return 0;
9217
9218 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
9219 return -1;
9220
9221 return 0;
9222 }
9223
9224
9225 /* Scan type TYP for pointer references to address space ASn.
9226 Return ADDR_SPACE_GENERIC (i.e. 0) if all pointers targeting
9227 the AS are also declared to be CONST.
9228 Otherwise, return the respective address space, i.e. a value != 0. */
9229
9230 static addr_space_t
avr_nonconst_pointer_addrspace(tree typ)9231 avr_nonconst_pointer_addrspace (tree typ)
9232 {
9233 while (ARRAY_TYPE == TREE_CODE (typ))
9234 typ = TREE_TYPE (typ);
9235
9236 if (POINTER_TYPE_P (typ))
9237 {
9238 addr_space_t as;
9239 tree target = TREE_TYPE (typ);
9240
9241 /* Pointer to function: Test the function's return type. */
9242
9243 if (FUNCTION_TYPE == TREE_CODE (target))
9244 return avr_nonconst_pointer_addrspace (TREE_TYPE (target));
9245
9246 /* "Ordinary" pointers... */
9247
9248 while (TREE_CODE (target) == ARRAY_TYPE)
9249 target = TREE_TYPE (target);
9250
9251 /* Pointers to non-generic address space must be const.
9252 Refuse address spaces outside the device's flash. */
9253
9254 as = TYPE_ADDR_SPACE (target);
9255
9256 if (!ADDR_SPACE_GENERIC_P (as)
9257 && (!TYPE_READONLY (target)
9258 || avr_addrspace[as].segment >= avr_n_flash
9259 /* Also refuse __memx address space if we can't support it. */
9260 || (!AVR_HAVE_LPM && avr_addrspace[as].pointer_size > 2)))
9261 {
9262 return as;
9263 }
9264
9265 /* Scan pointer's target type. */
9266
9267 return avr_nonconst_pointer_addrspace (target);
9268 }
9269
9270 return ADDR_SPACE_GENERIC;
9271 }
9272
9273
9274 /* Sanity check NODE so that all pointers targeting non-generic address spaces
9275 go along with CONST qualifier. Writing to these address spaces should
9276 be detected and complained about as early as possible. */
9277
9278 static bool
avr_pgm_check_var_decl(tree node)9279 avr_pgm_check_var_decl (tree node)
9280 {
9281 const char *reason = NULL;
9282
9283 addr_space_t as = ADDR_SPACE_GENERIC;
9284
9285 gcc_assert (as == 0);
9286
9287 if (avr_log.progmem)
9288 avr_edump ("%?: %t\n", node);
9289
9290 switch (TREE_CODE (node))
9291 {
9292 default:
9293 break;
9294
9295 case VAR_DECL:
9296 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
9297 reason = _("variable");
9298 break;
9299
9300 case PARM_DECL:
9301 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
9302 reason = _("function parameter");
9303 break;
9304
9305 case FIELD_DECL:
9306 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
9307 reason = _("structure field");
9308 break;
9309
9310 case FUNCTION_DECL:
9311 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (TREE_TYPE (node))),
9312 as)
9313 reason = _("return type of function");
9314 break;
9315
9316 case POINTER_TYPE:
9317 if (as = avr_nonconst_pointer_addrspace (node), as)
9318 reason = _("pointer");
9319 break;
9320 }
9321
9322 if (reason)
9323 {
9324 if (avr_addrspace[as].segment >= avr_n_flash)
9325 {
9326 if (TYPE_P (node))
9327 error ("%qT uses address space %qs beyond flash of %d KiB",
9328 node, avr_addrspace[as].name, 64 * avr_n_flash);
9329 else
9330 error ("%s %q+D uses address space %qs beyond flash of %d KiB",
9331 reason, node, avr_addrspace[as].name, 64 * avr_n_flash);
9332 }
9333 else
9334 {
9335 if (TYPE_P (node))
9336 error ("pointer targeting address space %qs must be const in %qT",
9337 avr_addrspace[as].name, node);
9338 else
9339 error ("pointer targeting address space %qs must be const"
9340 " in %s %q+D",
9341 avr_addrspace[as].name, reason, node);
9342 }
9343 }
9344
9345 return reason == NULL;
9346 }
9347
9348
9349 /* Add the section attribute if the variable is in progmem. */
9350
9351 static void
avr_insert_attributes(tree node,tree * attributes)9352 avr_insert_attributes (tree node, tree *attributes)
9353 {
9354 avr_pgm_check_var_decl (node);
9355
9356 if (TREE_CODE (node) == VAR_DECL
9357 && (TREE_STATIC (node) || DECL_EXTERNAL (node))
9358 && avr_progmem_p (node, *attributes))
9359 {
9360 addr_space_t as;
9361 tree node0 = node;
9362
9363 /* For C++, we have to peel arrays in order to get correct
9364 determination of readonlyness. */
9365
9366 do
9367 node0 = TREE_TYPE (node0);
9368 while (TREE_CODE (node0) == ARRAY_TYPE);
9369
9370 if (error_mark_node == node0)
9371 return;
9372
9373 as = TYPE_ADDR_SPACE (TREE_TYPE (node));
9374
9375 if (avr_addrspace[as].segment >= avr_n_flash)
9376 {
9377 error ("variable %q+D located in address space %qs beyond flash "
9378 "of %d KiB", node, avr_addrspace[as].name, 64 * avr_n_flash);
9379 }
9380 else if (!AVR_HAVE_LPM && avr_addrspace[as].pointer_size > 2)
9381 {
9382 error ("variable %q+D located in address space %qs"
9383 " which is not supported for architecture %qs",
9384 node, avr_addrspace[as].name, avr_arch->name);
9385 }
9386
9387 if (!TYPE_READONLY (node0)
9388 && !TREE_READONLY (node))
9389 {
9390 const char *reason = "__attribute__((progmem))";
9391
9392 if (!ADDR_SPACE_GENERIC_P (as))
9393 reason = avr_addrspace[as].name;
9394
9395 if (avr_log.progmem)
9396 avr_edump ("\n%?: %t\n%t\n", node, node0);
9397
9398 error ("variable %q+D must be const in order to be put into"
9399 " read-only section by means of %qs", node, reason);
9400 }
9401 }
9402 }
9403
9404
9405 /* Implement `ASM_OUTPUT_ALIGNED_DECL_LOCAL'. */
9406 /* Implement `ASM_OUTPUT_ALIGNED_DECL_COMMON'. */
9407 /* Track need of __do_clear_bss. */
9408
9409 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)9410 avr_asm_output_aligned_decl_common (FILE * stream,
9411 tree decl,
9412 const char *name,
9413 unsigned HOST_WIDE_INT size,
9414 unsigned int align, bool local_p)
9415 {
9416 rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
9417 rtx symbol;
9418
9419 if (mem != NULL_RTX && MEM_P (mem)
9420 && GET_CODE ((symbol = XEXP (mem, 0))) == SYMBOL_REF
9421 && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
9422 {
9423
9424 if (!local_p)
9425 {
9426 fprintf (stream, "\t.globl\t");
9427 assemble_name (stream, name);
9428 fprintf (stream, "\n");
9429 }
9430 if (SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS)
9431 {
9432 assemble_name (stream, name);
9433 fprintf (stream, " = %ld\n",
9434 (long) INTVAL (avr_eval_addr_attrib (symbol)));
9435 }
9436 else if (local_p)
9437 error_at (DECL_SOURCE_LOCATION (decl),
9438 "static IO declaration for %q+D needs an address", decl);
9439 return;
9440 }
9441
9442 /* __gnu_lto_v1 etc. are just markers for the linker injected by toplev.c.
9443 There is no need to trigger __do_clear_bss code for them. */
9444
9445 if (!STR_PREFIX_P (name, "__gnu_lto"))
9446 avr_need_clear_bss_p = true;
9447
9448 if (local_p)
9449 ASM_OUTPUT_ALIGNED_LOCAL (stream, name, size, align);
9450 else
9451 ASM_OUTPUT_ALIGNED_COMMON (stream, name, size, align);
9452 }
9453
9454 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))9455 avr_asm_asm_output_aligned_bss (FILE *file, tree decl, const char *name,
9456 unsigned HOST_WIDE_INT size, int align,
9457 void (*default_func)
9458 (FILE *, tree, const char *,
9459 unsigned HOST_WIDE_INT, int))
9460 {
9461 rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
9462 rtx symbol;
9463
9464 if (mem != NULL_RTX && MEM_P (mem)
9465 && GET_CODE ((symbol = XEXP (mem, 0))) == SYMBOL_REF
9466 && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
9467 {
9468 if (!(SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS))
9469 error_at (DECL_SOURCE_LOCATION (decl),
9470 "IO definition for %q+D needs an address", decl);
9471 avr_asm_output_aligned_decl_common (file, decl, name, size, align, false);
9472 }
9473 else
9474 default_func (file, decl, name, size, align);
9475 }
9476
9477
9478 /* Unnamed section callback for data_section
9479 to track need of __do_copy_data. */
9480
9481 static void
avr_output_data_section_asm_op(const void * data)9482 avr_output_data_section_asm_op (const void *data)
9483 {
9484 avr_need_copy_data_p = true;
9485
9486 /* Dispatch to default. */
9487 output_section_asm_op (data);
9488 }
9489
9490
9491 /* Unnamed section callback for bss_section
9492 to track need of __do_clear_bss. */
9493
9494 static void
avr_output_bss_section_asm_op(const void * data)9495 avr_output_bss_section_asm_op (const void *data)
9496 {
9497 avr_need_clear_bss_p = true;
9498
9499 /* Dispatch to default. */
9500 output_section_asm_op (data);
9501 }
9502
9503
9504 /* Unnamed section callback for progmem*.data sections. */
9505
9506 static void
avr_output_progmem_section_asm_op(const void * data)9507 avr_output_progmem_section_asm_op (const void *data)
9508 {
9509 fprintf (asm_out_file, "\t.section\t%s,\"a\",@progbits\n",
9510 (const char*) data);
9511 }
9512
9513
9514 /* Implement `TARGET_ASM_INIT_SECTIONS'. */
9515
9516 static void
avr_asm_init_sections(void)9517 avr_asm_init_sections (void)
9518 {
9519 /* Override section callbacks to keep track of `avr_need_clear_bss_p'
9520 resp. `avr_need_copy_data_p'. */
9521
9522 readonly_data_section->unnamed.callback = avr_output_data_section_asm_op;
9523 data_section->unnamed.callback = avr_output_data_section_asm_op;
9524 bss_section->unnamed.callback = avr_output_bss_section_asm_op;
9525 }
9526
9527
9528 /* Implement `TARGET_ASM_NAMED_SECTION'. */
9529 /* Track need of __do_clear_bss, __do_copy_data for named sections. */
9530
9531 static void
avr_asm_named_section(const char * name,unsigned int flags,tree decl)9532 avr_asm_named_section (const char *name, unsigned int flags, tree decl)
9533 {
9534 if (flags & AVR_SECTION_PROGMEM)
9535 {
9536 addr_space_t as = (flags & AVR_SECTION_PROGMEM) / SECTION_MACH_DEP;
9537 const char *old_prefix = ".rodata";
9538 const char *new_prefix = avr_addrspace[as].section_name;
9539
9540 if (STR_PREFIX_P (name, old_prefix))
9541 {
9542 const char *sname = ACONCAT ((new_prefix,
9543 name + strlen (old_prefix), NULL));
9544 default_elf_asm_named_section (sname, flags, decl);
9545 return;
9546 }
9547
9548 default_elf_asm_named_section (new_prefix, flags, decl);
9549 return;
9550 }
9551
9552 if (!avr_need_copy_data_p)
9553 avr_need_copy_data_p = (STR_PREFIX_P (name, ".data")
9554 || STR_PREFIX_P (name, ".rodata")
9555 || STR_PREFIX_P (name, ".gnu.linkonce.d"));
9556
9557 if (!avr_need_clear_bss_p)
9558 avr_need_clear_bss_p = STR_PREFIX_P (name, ".bss");
9559
9560 default_elf_asm_named_section (name, flags, decl);
9561 }
9562
9563
9564 /* Implement `TARGET_SECTION_TYPE_FLAGS'. */
9565
9566 static unsigned int
avr_section_type_flags(tree decl,const char * name,int reloc)9567 avr_section_type_flags (tree decl, const char *name, int reloc)
9568 {
9569 unsigned int flags = default_section_type_flags (decl, name, reloc);
9570
9571 if (STR_PREFIX_P (name, ".noinit"))
9572 {
9573 if (decl && TREE_CODE (decl) == VAR_DECL
9574 && DECL_INITIAL (decl) == NULL_TREE)
9575 flags |= SECTION_BSS; /* @nobits */
9576 else
9577 warning (0, "only uninitialized variables can be placed in the "
9578 ".noinit section");
9579 }
9580
9581 if (decl && DECL_P (decl)
9582 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
9583 {
9584 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
9585
9586 /* Attribute progmem puts data in generic address space.
9587 Set section flags as if it was in __flash to get the right
9588 section prefix in the remainder. */
9589
9590 if (ADDR_SPACE_GENERIC_P (as))
9591 as = ADDR_SPACE_FLASH;
9592
9593 flags |= as * SECTION_MACH_DEP;
9594 flags &= ~SECTION_WRITE;
9595 flags &= ~SECTION_BSS;
9596 }
9597
9598 return flags;
9599 }
9600
9601
9602 /* Implement `TARGET_ENCODE_SECTION_INFO'. */
9603
9604 static void
avr_encode_section_info(tree decl,rtx rtl,int new_decl_p)9605 avr_encode_section_info (tree decl, rtx rtl, int new_decl_p)
9606 {
9607 /* In avr_handle_progmem_attribute, DECL_INITIAL is not yet
9608 readily available, see PR34734. So we postpone the warning
9609 about uninitialized data in program memory section until here. */
9610
9611 if (new_decl_p
9612 && decl && DECL_P (decl)
9613 && !DECL_EXTERNAL (decl)
9614 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
9615 {
9616 if (!TREE_READONLY (decl))
9617 {
9618 // This might happen with C++ if stuff needs constructing.
9619 error ("variable %q+D with dynamic initialization put "
9620 "into program memory area", decl);
9621 }
9622 else if (NULL_TREE == DECL_INITIAL (decl))
9623 {
9624 // Don't warn for (implicit) aliases like in PR80462.
9625 tree asmname = DECL_ASSEMBLER_NAME (decl);
9626 varpool_node *node = varpool_node::get_for_asmname (asmname);
9627 bool alias_p = node && node->alias;
9628
9629 if (!alias_p)
9630 warning (OPT_Wuninitialized, "uninitialized variable %q+D put "
9631 "into program memory area", decl);
9632 }
9633 }
9634
9635 default_encode_section_info (decl, rtl, new_decl_p);
9636
9637 if (decl && DECL_P (decl)
9638 && TREE_CODE (decl) != FUNCTION_DECL
9639 && MEM_P (rtl)
9640 && SYMBOL_REF == GET_CODE (XEXP (rtl, 0)))
9641 {
9642 rtx sym = XEXP (rtl, 0);
9643 tree type = TREE_TYPE (decl);
9644 tree attr = DECL_ATTRIBUTES (decl);
9645 if (type == error_mark_node)
9646 return;
9647
9648 addr_space_t as = TYPE_ADDR_SPACE (type);
9649
9650 /* PSTR strings are in generic space but located in flash:
9651 patch address space. */
9652
9653 if (-1 == avr_progmem_p (decl, attr))
9654 as = ADDR_SPACE_FLASH;
9655
9656 AVR_SYMBOL_SET_ADDR_SPACE (sym, as);
9657
9658 tree io_low_attr = lookup_attribute ("io_low", attr);
9659 tree io_attr = lookup_attribute ("io", attr);
9660 tree addr_attr;
9661 if (io_low_attr
9662 && TREE_VALUE (io_low_attr) && TREE_VALUE (TREE_VALUE (io_low_attr)))
9663 addr_attr = io_attr;
9664 else if (io_attr
9665 && TREE_VALUE (io_attr) && TREE_VALUE (TREE_VALUE (io_attr)))
9666 addr_attr = io_attr;
9667 else
9668 addr_attr = lookup_attribute ("address", attr);
9669 if (io_low_attr
9670 || (io_attr && addr_attr
9671 && low_io_address_operand
9672 (GEN_INT (TREE_INT_CST_LOW
9673 (TREE_VALUE (TREE_VALUE (addr_attr)))), QImode)))
9674 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO_LOW;
9675 if (io_attr || io_low_attr)
9676 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO;
9677 /* If we have an (io) address attribute specification, but the variable
9678 is external, treat the address as only a tentative definition
9679 to be used to determine if an io port is in the lower range, but
9680 don't use the exact value for constant propagation. */
9681 if (addr_attr && !DECL_EXTERNAL (decl))
9682 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_ADDRESS;
9683 }
9684 }
9685
9686
9687 /* Implement `TARGET_ASM_SELECT_SECTION' */
9688
9689 static section *
avr_asm_select_section(tree decl,int reloc,unsigned HOST_WIDE_INT align)9690 avr_asm_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
9691 {
9692 section * sect = default_elf_select_section (decl, reloc, align);
9693
9694 if (decl && DECL_P (decl)
9695 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
9696 {
9697 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
9698
9699 /* __progmem__ goes in generic space but shall be allocated to
9700 .progmem.data */
9701
9702 if (ADDR_SPACE_GENERIC_P (as))
9703 as = ADDR_SPACE_FLASH;
9704
9705 if (sect->common.flags & SECTION_NAMED)
9706 {
9707 const char * name = sect->named.name;
9708 const char * old_prefix = ".rodata";
9709 const char * new_prefix = avr_addrspace[as].section_name;
9710
9711 if (STR_PREFIX_P (name, old_prefix))
9712 {
9713 const char *sname = ACONCAT ((new_prefix,
9714 name + strlen (old_prefix), NULL));
9715 return get_section (sname,
9716 sect->common.flags & ~SECTION_DECLARED,
9717 sect->named.decl);
9718 }
9719 }
9720
9721 if (!progmem_section[as])
9722 {
9723 progmem_section[as]
9724 = get_unnamed_section (0, avr_output_progmem_section_asm_op,
9725 avr_addrspace[as].section_name);
9726 }
9727
9728 return progmem_section[as];
9729 }
9730
9731 return sect;
9732 }
9733
9734 /* Implement `TARGET_ASM_FILE_START'. */
9735 /* Outputs some text at the start of each assembler file. */
9736
9737 static void
avr_file_start(void)9738 avr_file_start (void)
9739 {
9740 int sfr_offset = avr_arch->sfr_offset;
9741
9742 if (avr_arch->asm_only)
9743 error ("architecture %qs supported for assembler only", avr_mmcu);
9744
9745 default_file_start ();
9746
9747 /* Print I/O addresses of some SFRs used with IN and OUT. */
9748
9749 if (AVR_HAVE_SPH)
9750 fprintf (asm_out_file, "__SP_H__ = 0x%02x\n", avr_addr.sp_h - sfr_offset);
9751
9752 fprintf (asm_out_file, "__SP_L__ = 0x%02x\n", avr_addr.sp_l - sfr_offset);
9753 fprintf (asm_out_file, "__SREG__ = 0x%02x\n", avr_addr.sreg - sfr_offset);
9754 if (AVR_HAVE_RAMPZ)
9755 fprintf (asm_out_file, "__RAMPZ__ = 0x%02x\n", avr_addr.rampz - sfr_offset);
9756 if (AVR_HAVE_RAMPY)
9757 fprintf (asm_out_file, "__RAMPY__ = 0x%02x\n", avr_addr.rampy - sfr_offset);
9758 if (AVR_HAVE_RAMPX)
9759 fprintf (asm_out_file, "__RAMPX__ = 0x%02x\n", avr_addr.rampx - sfr_offset);
9760 if (AVR_HAVE_RAMPD)
9761 fprintf (asm_out_file, "__RAMPD__ = 0x%02x\n", avr_addr.rampd - sfr_offset);
9762 if (AVR_XMEGA || AVR_TINY)
9763 fprintf (asm_out_file, "__CCP__ = 0x%02x\n", avr_addr.ccp - sfr_offset);
9764 fprintf (asm_out_file, "__tmp_reg__ = %d\n", AVR_TMP_REGNO);
9765 fprintf (asm_out_file, "__zero_reg__ = %d\n", AVR_ZERO_REGNO);
9766 }
9767
9768
9769 /* Implement `TARGET_ASM_FILE_END'. */
9770 /* Outputs to the stdio stream FILE some
9771 appropriate text to go at the end of an assembler file. */
9772
9773 static void
avr_file_end(void)9774 avr_file_end (void)
9775 {
9776 /* Output these only if there is anything in the
9777 .data* / .rodata* / .gnu.linkonce.* resp. .bss* or COMMON
9778 input section(s) - some code size can be saved by not
9779 linking in the initialization code from libgcc if resp.
9780 sections are empty, see PR18145. */
9781
9782 if (avr_need_copy_data_p)
9783 fputs (".global __do_copy_data\n", asm_out_file);
9784
9785 if (avr_need_clear_bss_p)
9786 fputs (".global __do_clear_bss\n", asm_out_file);
9787 }
9788
9789
9790 /* Worker function for `ADJUST_REG_ALLOC_ORDER'. */
9791 /* Choose the order in which to allocate hard registers for
9792 pseudo-registers local to a basic block.
9793
9794 Store the desired register order in the array `reg_alloc_order'.
9795 Element 0 should be the register to allocate first; element 1, the
9796 next register; and so on. */
9797
9798 void
avr_adjust_reg_alloc_order(void)9799 avr_adjust_reg_alloc_order (void)
9800 {
9801 unsigned int i;
9802 static const int order_0[] =
9803 {
9804 24, 25,
9805 18, 19, 20, 21, 22, 23,
9806 30, 31,
9807 26, 27, 28, 29,
9808 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
9809 0, 1,
9810 32, 33, 34, 35
9811 };
9812 static const int tiny_order_0[] = {
9813 20, 21,
9814 22, 23,
9815 24, 25,
9816 30, 31,
9817 26, 27,
9818 28, 29,
9819 19, 18,
9820 16, 17,
9821 32, 33, 34, 35,
9822 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
9823 };
9824 static const int order_1[] =
9825 {
9826 18, 19, 20, 21, 22, 23, 24, 25,
9827 30, 31,
9828 26, 27, 28, 29,
9829 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
9830 0, 1,
9831 32, 33, 34, 35
9832 };
9833 static const int tiny_order_1[] = {
9834 22, 23,
9835 24, 25,
9836 30, 31,
9837 26, 27,
9838 28, 29,
9839 21, 20, 19, 18,
9840 16, 17,
9841 32, 33, 34, 35,
9842 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
9843 };
9844 static const int order_2[] =
9845 {
9846 25, 24, 23, 22, 21, 20, 19, 18,
9847 30, 31,
9848 26, 27, 28, 29,
9849 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
9850 1, 0,
9851 32, 33, 34, 35
9852 };
9853
9854 /* Select specific register allocation order.
9855 Tiny Core (ATtiny4/5/9/10/20/40) devices have only 16 registers,
9856 so different allocation order should be used. */
9857
9858 const int *order = (TARGET_ORDER_1 ? (AVR_TINY ? tiny_order_1 : order_1)
9859 : TARGET_ORDER_2 ? (AVR_TINY ? tiny_order_0 : order_2)
9860 : (AVR_TINY ? tiny_order_0 : order_0));
9861
9862 for (i = 0; i < ARRAY_SIZE (order_0); ++i)
9863 reg_alloc_order[i] = order[i];
9864 }
9865
9866
9867 /* Implement `TARGET_REGISTER_MOVE_COST' */
9868
9869 static int
avr_register_move_cost(machine_mode mode ATTRIBUTE_UNUSED,reg_class_t from,reg_class_t to)9870 avr_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
9871 reg_class_t from, reg_class_t to)
9872 {
9873 return (from == STACK_REG ? 6
9874 : to == STACK_REG ? 12
9875 : 2);
9876 }
9877
9878
9879 /* Implement `TARGET_MEMORY_MOVE_COST' */
9880
9881 static int
avr_memory_move_cost(machine_mode mode,reg_class_t rclass ATTRIBUTE_UNUSED,bool in ATTRIBUTE_UNUSED)9882 avr_memory_move_cost (machine_mode mode,
9883 reg_class_t rclass ATTRIBUTE_UNUSED,
9884 bool in ATTRIBUTE_UNUSED)
9885 {
9886 return (mode == QImode ? 2
9887 : mode == HImode ? 4
9888 : mode == SImode ? 8
9889 : mode == SFmode ? 8
9890 : 16);
9891 }
9892
9893
9894 /* Cost for mul highpart. X is a LSHIFTRT, i.e. the outer TRUNCATE is
9895 already stripped off. */
9896
9897 static int
avr_mul_highpart_cost(rtx x,int)9898 avr_mul_highpart_cost (rtx x, int)
9899 {
9900 if (AVR_HAVE_MUL
9901 && LSHIFTRT == GET_CODE (x)
9902 && MULT == GET_CODE (XEXP (x, 0))
9903 && CONST_INT_P (XEXP (x, 1)))
9904 {
9905 // This is the wider mode.
9906 machine_mode mode = GET_MODE (x);
9907
9908 // The middle-end might still have PR81444, i.e. it is calling the cost
9909 // functions with strange modes. Fix this now by also considering
9910 // PSImode (should actually be SImode instead).
9911 if (HImode == mode || PSImode == mode || SImode == mode)
9912 {
9913 return COSTS_N_INSNS (2);
9914 }
9915 }
9916
9917 return 10000;
9918 }
9919
9920
9921 /* Mutually recursive subroutine of avr_rtx_cost for calculating the
9922 cost of an RTX operand given its context. X is the rtx of the
9923 operand, MODE is its mode, and OUTER is the rtx_code of this
9924 operand's parent operator. */
9925
9926 static int
avr_operand_rtx_cost(rtx x,machine_mode mode,enum rtx_code outer,int opno,bool speed)9927 avr_operand_rtx_cost (rtx x, machine_mode mode, enum rtx_code outer,
9928 int opno, bool speed)
9929 {
9930 enum rtx_code code = GET_CODE (x);
9931 int total;
9932
9933 switch (code)
9934 {
9935 case REG:
9936 case SUBREG:
9937 return 0;
9938
9939 case CONST_INT:
9940 case CONST_FIXED:
9941 case CONST_DOUBLE:
9942 return COSTS_N_INSNS (GET_MODE_SIZE (mode));
9943
9944 default:
9945 break;
9946 }
9947
9948 total = 0;
9949 avr_rtx_costs (x, mode, outer, opno, &total, speed);
9950 return total;
9951 }
9952
9953 /* Worker function for AVR backend's rtx_cost function.
9954 X is rtx expression whose cost is to be calculated.
9955 Return true if the complete cost has been computed.
9956 Return false if subexpressions should be scanned.
9957 In either case, *TOTAL contains the cost result. */
9958
9959 static bool
avr_rtx_costs_1(rtx x,machine_mode mode,int outer_code,int opno ATTRIBUTE_UNUSED,int * total,bool speed)9960 avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code,
9961 int opno ATTRIBUTE_UNUSED, int *total, bool speed)
9962 {
9963 enum rtx_code code = GET_CODE (x);
9964 HOST_WIDE_INT val;
9965
9966 switch (code)
9967 {
9968 case CONST_INT:
9969 case CONST_FIXED:
9970 case CONST_DOUBLE:
9971 case SYMBOL_REF:
9972 case CONST:
9973 case LABEL_REF:
9974 /* Immediate constants are as cheap as registers. */
9975 *total = 0;
9976 return true;
9977
9978 case MEM:
9979 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
9980 return true;
9981
9982 case NEG:
9983 switch (mode)
9984 {
9985 case QImode:
9986 case SFmode:
9987 *total = COSTS_N_INSNS (1);
9988 break;
9989
9990 case HImode:
9991 case PSImode:
9992 case SImode:
9993 *total = COSTS_N_INSNS (2 * GET_MODE_SIZE (mode) - 1);
9994 break;
9995
9996 default:
9997 return false;
9998 }
9999 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10000 return true;
10001
10002 case ABS:
10003 switch (mode)
10004 {
10005 case QImode:
10006 case SFmode:
10007 *total = COSTS_N_INSNS (1);
10008 break;
10009
10010 default:
10011 return false;
10012 }
10013 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10014 return true;
10015
10016 case NOT:
10017 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10018 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10019 return true;
10020
10021 case ZERO_EXTEND:
10022 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
10023 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
10024 *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
10025 code, 0, speed);
10026 return true;
10027
10028 case SIGN_EXTEND:
10029 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
10030 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
10031 *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
10032 code, 0, speed);
10033 return true;
10034
10035 case PLUS:
10036 switch (mode)
10037 {
10038 case QImode:
10039 if (AVR_HAVE_MUL
10040 && MULT == GET_CODE (XEXP (x, 0))
10041 && register_operand (XEXP (x, 1), QImode))
10042 {
10043 /* multiply-add */
10044 *total = COSTS_N_INSNS (speed ? 4 : 3);
10045 /* multiply-add with constant: will be split and load constant. */
10046 if (CONST_INT_P (XEXP (XEXP (x, 0), 1)))
10047 *total = COSTS_N_INSNS (1) + *total;
10048 return true;
10049 }
10050 *total = COSTS_N_INSNS (1);
10051 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10052 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10053 break;
10054
10055 case HImode:
10056 if (AVR_HAVE_MUL
10057 && (MULT == GET_CODE (XEXP (x, 0))
10058 || ASHIFT == GET_CODE (XEXP (x, 0)))
10059 && register_operand (XEXP (x, 1), HImode)
10060 && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))
10061 || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))))
10062 {
10063 /* multiply-add */
10064 *total = COSTS_N_INSNS (speed ? 5 : 4);
10065 /* multiply-add with constant: will be split and load constant. */
10066 if (CONST_INT_P (XEXP (XEXP (x, 0), 1)))
10067 *total = COSTS_N_INSNS (1) + *total;
10068 return true;
10069 }
10070 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10071 {
10072 *total = COSTS_N_INSNS (2);
10073 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10074 speed);
10075 }
10076 else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
10077 *total = COSTS_N_INSNS (1);
10078 else
10079 *total = COSTS_N_INSNS (2);
10080 break;
10081
10082 case PSImode:
10083 if (!CONST_INT_P (XEXP (x, 1)))
10084 {
10085 *total = COSTS_N_INSNS (3);
10086 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10087 speed);
10088 }
10089 else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
10090 *total = COSTS_N_INSNS (2);
10091 else
10092 *total = COSTS_N_INSNS (3);
10093 break;
10094
10095 case SImode:
10096 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10097 {
10098 *total = COSTS_N_INSNS (4);
10099 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10100 speed);
10101 }
10102 else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
10103 *total = COSTS_N_INSNS (1);
10104 else
10105 *total = COSTS_N_INSNS (4);
10106 break;
10107
10108 default:
10109 return false;
10110 }
10111 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10112 return true;
10113
10114 case MINUS:
10115 if (AVR_HAVE_MUL
10116 && QImode == mode
10117 && register_operand (XEXP (x, 0), QImode)
10118 && MULT == GET_CODE (XEXP (x, 1)))
10119 {
10120 /* multiply-sub */
10121 *total = COSTS_N_INSNS (speed ? 4 : 3);
10122 /* multiply-sub with constant: will be split and load constant. */
10123 if (CONST_INT_P (XEXP (XEXP (x, 1), 1)))
10124 *total = COSTS_N_INSNS (1) + *total;
10125 return true;
10126 }
10127 if (AVR_HAVE_MUL
10128 && HImode == mode
10129 && register_operand (XEXP (x, 0), HImode)
10130 && (MULT == GET_CODE (XEXP (x, 1))
10131 || ASHIFT == GET_CODE (XEXP (x, 1)))
10132 && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))
10133 || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))))
10134 {
10135 /* multiply-sub */
10136 *total = COSTS_N_INSNS (speed ? 5 : 4);
10137 /* multiply-sub with constant: will be split and load constant. */
10138 if (CONST_INT_P (XEXP (XEXP (x, 1), 1)))
10139 *total = COSTS_N_INSNS (1) + *total;
10140 return true;
10141 }
10142 /* FALLTHRU */
10143 case AND:
10144 case IOR:
10145 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10146 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10147 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10148 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10149 return true;
10150
10151 case XOR:
10152 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10153 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10154 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10155 return true;
10156
10157 case MULT:
10158 switch (mode)
10159 {
10160 case QImode:
10161 if (AVR_HAVE_MUL)
10162 *total = COSTS_N_INSNS (!speed ? 3 : 4);
10163 else if (!speed)
10164 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
10165 else
10166 return false;
10167 break;
10168
10169 case HImode:
10170 if (AVR_HAVE_MUL)
10171 {
10172 rtx op0 = XEXP (x, 0);
10173 rtx op1 = XEXP (x, 1);
10174 enum rtx_code code0 = GET_CODE (op0);
10175 enum rtx_code code1 = GET_CODE (op1);
10176 bool ex0 = SIGN_EXTEND == code0 || ZERO_EXTEND == code0;
10177 bool ex1 = SIGN_EXTEND == code1 || ZERO_EXTEND == code1;
10178
10179 if (ex0
10180 && (u8_operand (op1, HImode)
10181 || s8_operand (op1, HImode)))
10182 {
10183 *total = COSTS_N_INSNS (!speed ? 4 : 6);
10184 return true;
10185 }
10186 if (ex0
10187 && register_operand (op1, HImode))
10188 {
10189 *total = COSTS_N_INSNS (!speed ? 5 : 8);
10190 return true;
10191 }
10192 else if (ex0 || ex1)
10193 {
10194 *total = COSTS_N_INSNS (!speed ? 3 : 5);
10195 return true;
10196 }
10197 else if (register_operand (op0, HImode)
10198 && (u8_operand (op1, HImode)
10199 || s8_operand (op1, HImode)))
10200 {
10201 *total = COSTS_N_INSNS (!speed ? 6 : 9);
10202 return true;
10203 }
10204 else
10205 *total = COSTS_N_INSNS (!speed ? 7 : 10);
10206 }
10207 else if (!speed)
10208 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
10209 else
10210 return false;
10211 break;
10212
10213 case PSImode:
10214 if (!speed)
10215 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
10216 else
10217 *total = 10;
10218 break;
10219
10220 case SImode:
10221 case DImode:
10222 if (AVR_HAVE_MUL)
10223 {
10224 if (!speed)
10225 {
10226 /* Add some additional costs besides CALL like moves etc. */
10227
10228 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
10229 }
10230 else
10231 {
10232 /* Just a rough estimate. Even with -O2 we don't want bulky
10233 code expanded inline. */
10234
10235 *total = COSTS_N_INSNS (25);
10236 }
10237 }
10238 else
10239 {
10240 if (speed)
10241 *total = COSTS_N_INSNS (300);
10242 else
10243 /* Add some additional costs besides CALL like moves etc. */
10244 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
10245 }
10246
10247 if (mode == DImode)
10248 *total *= 2;
10249
10250 return true;
10251
10252 default:
10253 return false;
10254 }
10255 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10256 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
10257 return true;
10258
10259 case DIV:
10260 case MOD:
10261 case UDIV:
10262 case UMOD:
10263 if (!speed)
10264 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
10265 else
10266 *total = COSTS_N_INSNS (15 * GET_MODE_SIZE (mode));
10267 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10268 /* For div/mod with const-int divisor we have at least the cost of
10269 loading the divisor. */
10270 if (CONST_INT_P (XEXP (x, 1)))
10271 *total += COSTS_N_INSNS (GET_MODE_SIZE (mode));
10272 /* Add some overall penaly for clobbering and moving around registers */
10273 *total += COSTS_N_INSNS (2);
10274 return true;
10275
10276 case ROTATE:
10277 switch (mode)
10278 {
10279 case QImode:
10280 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 4)
10281 *total = COSTS_N_INSNS (1);
10282
10283 break;
10284
10285 case HImode:
10286 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 8)
10287 *total = COSTS_N_INSNS (3);
10288
10289 break;
10290
10291 case SImode:
10292 if (CONST_INT_P (XEXP (x, 1)))
10293 switch (INTVAL (XEXP (x, 1)))
10294 {
10295 case 8:
10296 case 24:
10297 *total = COSTS_N_INSNS (5);
10298 break;
10299 case 16:
10300 *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 6);
10301 break;
10302 }
10303 break;
10304
10305 default:
10306 return false;
10307 }
10308 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10309 return true;
10310
10311 case ASHIFT:
10312 switch (mode)
10313 {
10314 case QImode:
10315 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10316 {
10317 *total = COSTS_N_INSNS (!speed ? 4 : 17);
10318 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10319 speed);
10320 }
10321 else
10322 {
10323 val = INTVAL (XEXP (x, 1));
10324 if (val == 7)
10325 *total = COSTS_N_INSNS (3);
10326 else if (val >= 0 && val <= 7)
10327 *total = COSTS_N_INSNS (val);
10328 else
10329 *total = COSTS_N_INSNS (1);
10330 }
10331 break;
10332
10333 case HImode:
10334 if (AVR_HAVE_MUL)
10335 {
10336 if (const_2_to_7_operand (XEXP (x, 1), HImode)
10337 && (SIGN_EXTEND == GET_CODE (XEXP (x, 0))
10338 || ZERO_EXTEND == GET_CODE (XEXP (x, 0))))
10339 {
10340 *total = COSTS_N_INSNS (!speed ? 4 : 6);
10341 return true;
10342 }
10343 }
10344
10345 if (const1_rtx == (XEXP (x, 1))
10346 && SIGN_EXTEND == GET_CODE (XEXP (x, 0)))
10347 {
10348 *total = COSTS_N_INSNS (2);
10349 return true;
10350 }
10351
10352 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10353 {
10354 *total = COSTS_N_INSNS (!speed ? 5 : 41);
10355 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10356 speed);
10357 }
10358 else
10359 switch (INTVAL (XEXP (x, 1)))
10360 {
10361 case 0:
10362 *total = 0;
10363 break;
10364 case 1:
10365 case 8:
10366 *total = COSTS_N_INSNS (2);
10367 break;
10368 case 9:
10369 *total = COSTS_N_INSNS (3);
10370 break;
10371 case 2:
10372 case 3:
10373 case 10:
10374 case 15:
10375 *total = COSTS_N_INSNS (4);
10376 break;
10377 case 7:
10378 case 11:
10379 case 12:
10380 *total = COSTS_N_INSNS (5);
10381 break;
10382 case 4:
10383 *total = COSTS_N_INSNS (!speed ? 5 : 8);
10384 break;
10385 case 6:
10386 *total = COSTS_N_INSNS (!speed ? 5 : 9);
10387 break;
10388 case 5:
10389 *total = COSTS_N_INSNS (!speed ? 5 : 10);
10390 break;
10391 default:
10392 *total = COSTS_N_INSNS (!speed ? 5 : 41);
10393 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10394 speed);
10395 }
10396 break;
10397
10398 case PSImode:
10399 if (!CONST_INT_P (XEXP (x, 1)))
10400 {
10401 *total = COSTS_N_INSNS (!speed ? 6 : 73);
10402 }
10403 else
10404 switch (INTVAL (XEXP (x, 1)))
10405 {
10406 case 0:
10407 *total = 0;
10408 break;
10409 case 1:
10410 case 8:
10411 case 16:
10412 *total = COSTS_N_INSNS (3);
10413 break;
10414 case 23:
10415 *total = COSTS_N_INSNS (5);
10416 break;
10417 default:
10418 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
10419 break;
10420 }
10421 break;
10422
10423 case SImode:
10424 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10425 {
10426 *total = COSTS_N_INSNS (!speed ? 7 : 113);
10427 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10428 speed);
10429 }
10430 else
10431 switch (INTVAL (XEXP (x, 1)))
10432 {
10433 case 0:
10434 *total = 0;
10435 break;
10436 case 24:
10437 *total = COSTS_N_INSNS (3);
10438 break;
10439 case 1:
10440 case 8:
10441 case 16:
10442 *total = COSTS_N_INSNS (4);
10443 break;
10444 case 31:
10445 *total = COSTS_N_INSNS (6);
10446 break;
10447 case 2:
10448 *total = COSTS_N_INSNS (!speed ? 7 : 8);
10449 break;
10450 default:
10451 *total = COSTS_N_INSNS (!speed ? 7 : 113);
10452 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10453 speed);
10454 }
10455 break;
10456
10457 default:
10458 return false;
10459 }
10460 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10461 return true;
10462
10463 case ASHIFTRT:
10464 switch (mode)
10465 {
10466 case QImode:
10467 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10468 {
10469 *total = COSTS_N_INSNS (!speed ? 4 : 17);
10470 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10471 speed);
10472 }
10473 else
10474 {
10475 val = INTVAL (XEXP (x, 1));
10476 if (val == 6)
10477 *total = COSTS_N_INSNS (4);
10478 else if (val == 7)
10479 *total = COSTS_N_INSNS (2);
10480 else if (val >= 0 && val <= 7)
10481 *total = COSTS_N_INSNS (val);
10482 else
10483 *total = COSTS_N_INSNS (1);
10484 }
10485 break;
10486
10487 case HImode:
10488 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10489 {
10490 *total = COSTS_N_INSNS (!speed ? 5 : 41);
10491 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10492 speed);
10493 }
10494 else
10495 switch (INTVAL (XEXP (x, 1)))
10496 {
10497 case 0:
10498 *total = 0;
10499 break;
10500 case 1:
10501 *total = COSTS_N_INSNS (2);
10502 break;
10503 case 15:
10504 *total = COSTS_N_INSNS (3);
10505 break;
10506 case 2:
10507 case 7:
10508 case 8:
10509 case 9:
10510 *total = COSTS_N_INSNS (4);
10511 break;
10512 case 10:
10513 case 14:
10514 *total = COSTS_N_INSNS (5);
10515 break;
10516 case 11:
10517 *total = COSTS_N_INSNS (!speed ? 5 : 6);
10518 break;
10519 case 12:
10520 *total = COSTS_N_INSNS (!speed ? 5 : 7);
10521 break;
10522 case 6:
10523 case 13:
10524 *total = COSTS_N_INSNS (!speed ? 5 : 8);
10525 break;
10526 default:
10527 *total = COSTS_N_INSNS (!speed ? 5 : 41);
10528 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10529 speed);
10530 }
10531 break;
10532
10533 case PSImode:
10534 if (!CONST_INT_P (XEXP (x, 1)))
10535 {
10536 *total = COSTS_N_INSNS (!speed ? 6 : 73);
10537 }
10538 else
10539 switch (INTVAL (XEXP (x, 1)))
10540 {
10541 case 0:
10542 *total = 0;
10543 break;
10544 case 1:
10545 *total = COSTS_N_INSNS (3);
10546 break;
10547 case 16:
10548 case 8:
10549 *total = COSTS_N_INSNS (5);
10550 break;
10551 case 23:
10552 *total = COSTS_N_INSNS (4);
10553 break;
10554 default:
10555 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
10556 break;
10557 }
10558 break;
10559
10560 case SImode:
10561 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10562 {
10563 *total = COSTS_N_INSNS (!speed ? 7 : 113);
10564 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10565 speed);
10566 }
10567 else
10568 switch (INTVAL (XEXP (x, 1)))
10569 {
10570 case 0:
10571 *total = 0;
10572 break;
10573 case 1:
10574 *total = COSTS_N_INSNS (4);
10575 break;
10576 case 8:
10577 case 16:
10578 case 24:
10579 *total = COSTS_N_INSNS (6);
10580 break;
10581 case 2:
10582 *total = COSTS_N_INSNS (!speed ? 7 : 8);
10583 break;
10584 case 31:
10585 *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 5);
10586 break;
10587 default:
10588 *total = COSTS_N_INSNS (!speed ? 7 : 113);
10589 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10590 speed);
10591 }
10592 break;
10593
10594 default:
10595 return false;
10596 }
10597 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10598 return true;
10599
10600 case LSHIFTRT:
10601 if (outer_code == TRUNCATE)
10602 {
10603 *total = avr_mul_highpart_cost (x, speed);
10604 return true;
10605 }
10606
10607 switch (mode)
10608 {
10609 case QImode:
10610 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10611 {
10612 *total = COSTS_N_INSNS (!speed ? 4 : 17);
10613 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10614 speed);
10615 }
10616 else
10617 {
10618 val = INTVAL (XEXP (x, 1));
10619 if (val == 7)
10620 *total = COSTS_N_INSNS (3);
10621 else if (val >= 0 && val <= 7)
10622 *total = COSTS_N_INSNS (val);
10623 else
10624 *total = COSTS_N_INSNS (1);
10625 }
10626 break;
10627
10628 case HImode:
10629 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10630 {
10631 *total = COSTS_N_INSNS (!speed ? 5 : 41);
10632 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10633 speed);
10634 }
10635 else
10636 switch (INTVAL (XEXP (x, 1)))
10637 {
10638 case 0:
10639 *total = 0;
10640 break;
10641 case 1:
10642 case 8:
10643 *total = COSTS_N_INSNS (2);
10644 break;
10645 case 9:
10646 *total = COSTS_N_INSNS (3);
10647 break;
10648 case 2:
10649 case 10:
10650 case 15:
10651 *total = COSTS_N_INSNS (4);
10652 break;
10653 case 7:
10654 case 11:
10655 *total = COSTS_N_INSNS (5);
10656 break;
10657 case 3:
10658 case 12:
10659 case 13:
10660 case 14:
10661 *total = COSTS_N_INSNS (!speed ? 5 : 6);
10662 break;
10663 case 4:
10664 *total = COSTS_N_INSNS (!speed ? 5 : 7);
10665 break;
10666 case 5:
10667 case 6:
10668 *total = COSTS_N_INSNS (!speed ? 5 : 9);
10669 break;
10670 default:
10671 *total = COSTS_N_INSNS (!speed ? 5 : 41);
10672 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10673 speed);
10674 }
10675 break;
10676
10677 case PSImode:
10678 if (!CONST_INT_P (XEXP (x, 1)))
10679 {
10680 *total = COSTS_N_INSNS (!speed ? 6 : 73);
10681 }
10682 else
10683 switch (INTVAL (XEXP (x, 1)))
10684 {
10685 case 0:
10686 *total = 0;
10687 break;
10688 case 1:
10689 case 8:
10690 case 16:
10691 *total = COSTS_N_INSNS (3);
10692 break;
10693 case 23:
10694 *total = COSTS_N_INSNS (5);
10695 break;
10696 default:
10697 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
10698 break;
10699 }
10700 break;
10701
10702 case SImode:
10703 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10704 {
10705 *total = COSTS_N_INSNS (!speed ? 7 : 113);
10706 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10707 speed);
10708 }
10709 else
10710 switch (INTVAL (XEXP (x, 1)))
10711 {
10712 case 0:
10713 *total = 0;
10714 break;
10715 case 1:
10716 *total = COSTS_N_INSNS (4);
10717 break;
10718 case 2:
10719 *total = COSTS_N_INSNS (!speed ? 7 : 8);
10720 break;
10721 case 8:
10722 case 16:
10723 case 24:
10724 *total = COSTS_N_INSNS (4);
10725 break;
10726 case 31:
10727 *total = COSTS_N_INSNS (6);
10728 break;
10729 default:
10730 *total = COSTS_N_INSNS (!speed ? 7 : 113);
10731 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10732 speed);
10733 }
10734 break;
10735
10736 default:
10737 return false;
10738 }
10739 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10740 return true;
10741
10742 case COMPARE:
10743 switch (GET_MODE (XEXP (x, 0)))
10744 {
10745 case QImode:
10746 *total = COSTS_N_INSNS (1);
10747 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10748 *total += avr_operand_rtx_cost (XEXP (x, 1), QImode, code,
10749 1, speed);
10750 break;
10751
10752 case HImode:
10753 *total = COSTS_N_INSNS (2);
10754 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10755 *total += avr_operand_rtx_cost (XEXP (x, 1), HImode, code,
10756 1, speed);
10757 else if (INTVAL (XEXP (x, 1)) != 0)
10758 *total += COSTS_N_INSNS (1);
10759 break;
10760
10761 case PSImode:
10762 *total = COSTS_N_INSNS (3);
10763 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) != 0)
10764 *total += COSTS_N_INSNS (2);
10765 break;
10766
10767 case SImode:
10768 *total = COSTS_N_INSNS (4);
10769 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10770 *total += avr_operand_rtx_cost (XEXP (x, 1), SImode, code,
10771 1, speed);
10772 else if (INTVAL (XEXP (x, 1)) != 0)
10773 *total += COSTS_N_INSNS (3);
10774 break;
10775
10776 default:
10777 return false;
10778 }
10779 *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
10780 code, 0, speed);
10781 return true;
10782
10783 case TRUNCATE:
10784 if (LSHIFTRT == GET_CODE (XEXP (x, 0)))
10785 {
10786 *total = avr_mul_highpart_cost (XEXP (x, 0), speed);
10787 return true;
10788 }
10789 break;
10790
10791 default:
10792 break;
10793 }
10794 return false;
10795 }
10796
10797
10798 /* Implement `TARGET_RTX_COSTS'. */
10799
10800 static bool
avr_rtx_costs(rtx x,machine_mode mode,int outer_code,int opno,int * total,bool speed)10801 avr_rtx_costs (rtx x, machine_mode mode, int outer_code,
10802 int opno, int *total, bool speed)
10803 {
10804 bool done = avr_rtx_costs_1 (x, mode, outer_code,
10805 opno, total, speed);
10806
10807 if (avr_log.rtx_costs)
10808 {
10809 avr_edump ("\n%?=%b (%s) total=%d, outer=%C:\n%r\n",
10810 done, speed ? "speed" : "size", *total, outer_code, x);
10811 }
10812
10813 return done;
10814 }
10815
10816
10817 /* Implement `TARGET_ADDRESS_COST'. */
10818
10819 static int
avr_address_cost(rtx x,machine_mode mode ATTRIBUTE_UNUSED,addr_space_t as ATTRIBUTE_UNUSED,bool speed ATTRIBUTE_UNUSED)10820 avr_address_cost (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
10821 addr_space_t as ATTRIBUTE_UNUSED,
10822 bool speed ATTRIBUTE_UNUSED)
10823 {
10824 int cost = 4;
10825
10826 if (GET_CODE (x) == PLUS
10827 && CONST_INT_P (XEXP (x, 1))
10828 && (REG_P (XEXP (x, 0))
10829 || GET_CODE (XEXP (x, 0)) == SUBREG))
10830 {
10831 if (INTVAL (XEXP (x, 1)) > MAX_LD_OFFSET(mode))
10832 cost = 18;
10833 }
10834 else if (CONSTANT_ADDRESS_P (x))
10835 {
10836 if (io_address_operand (x, QImode))
10837 cost = 2;
10838 }
10839
10840 if (avr_log.address_cost)
10841 avr_edump ("\n%?: %d = %r\n", cost, x);
10842
10843 return cost;
10844 }
10845
10846 /* Test for extra memory constraint 'Q'.
10847 It's a memory address based on Y or Z pointer with valid displacement. */
10848
10849 int
extra_constraint_Q(rtx x)10850 extra_constraint_Q (rtx x)
10851 {
10852 int ok = 0;
10853
10854 if (GET_CODE (XEXP (x,0)) == PLUS
10855 && REG_P (XEXP (XEXP (x,0), 0))
10856 && GET_CODE (XEXP (XEXP (x,0), 1)) == CONST_INT
10857 && (INTVAL (XEXP (XEXP (x,0), 1))
10858 <= MAX_LD_OFFSET (GET_MODE (x))))
10859 {
10860 rtx xx = XEXP (XEXP (x,0), 0);
10861 int regno = REGNO (xx);
10862
10863 ok = (/* allocate pseudos */
10864 regno >= FIRST_PSEUDO_REGISTER
10865 /* strictly check */
10866 || regno == REG_Z || regno == REG_Y
10867 /* XXX frame & arg pointer checks */
10868 || xx == frame_pointer_rtx
10869 || xx == arg_pointer_rtx);
10870
10871 if (avr_log.constraints)
10872 avr_edump ("\n%?=%d reload_completed=%d reload_in_progress=%d\n %r\n",
10873 ok, reload_completed, reload_in_progress, x);
10874 }
10875
10876 return ok;
10877 }
10878
10879 /* Convert condition code CONDITION to the valid AVR condition code. */
10880
10881 RTX_CODE
avr_normalize_condition(RTX_CODE condition)10882 avr_normalize_condition (RTX_CODE condition)
10883 {
10884 switch (condition)
10885 {
10886 case GT:
10887 return GE;
10888 case GTU:
10889 return GEU;
10890 case LE:
10891 return LT;
10892 case LEU:
10893 return LTU;
10894 default:
10895 gcc_unreachable ();
10896 }
10897 }
10898
10899 /* Helper function for `avr_reorg'. */
10900
10901 static rtx
avr_compare_pattern(rtx_insn * insn)10902 avr_compare_pattern (rtx_insn *insn)
10903 {
10904 rtx pattern = single_set (insn);
10905
10906 if (pattern
10907 && NONJUMP_INSN_P (insn)
10908 && SET_DEST (pattern) == cc0_rtx
10909 && GET_CODE (SET_SRC (pattern)) == COMPARE)
10910 {
10911 machine_mode mode0 = GET_MODE (XEXP (SET_SRC (pattern), 0));
10912 machine_mode mode1 = GET_MODE (XEXP (SET_SRC (pattern), 1));
10913
10914 /* The 64-bit comparisons have fixed operands ACC_A and ACC_B.
10915 They must not be swapped, thus skip them. */
10916
10917 if ((mode0 == VOIDmode || GET_MODE_SIZE (mode0) <= 4)
10918 && (mode1 == VOIDmode || GET_MODE_SIZE (mode1) <= 4))
10919 return pattern;
10920 }
10921
10922 return NULL_RTX;
10923 }
10924
10925 /* Helper function for `avr_reorg'. */
10926
10927 /* Expansion of switch/case decision trees leads to code like
10928
10929 cc0 = compare (Reg, Num)
10930 if (cc0 == 0)
10931 goto L1
10932
10933 cc0 = compare (Reg, Num)
10934 if (cc0 > 0)
10935 goto L2
10936
10937 The second comparison is superfluous and can be deleted.
10938 The second jump condition can be transformed from a
10939 "difficult" one to a "simple" one because "cc0 > 0" and
10940 "cc0 >= 0" will have the same effect here.
10941
10942 This function relies on the way switch/case is being expaned
10943 as binary decision tree. For example code see PR 49903.
10944
10945 Return TRUE if optimization performed.
10946 Return FALSE if nothing changed.
10947
10948 INSN1 is a comparison, i.e. avr_compare_pattern != 0.
10949
10950 We don't want to do this in text peephole because it is
10951 tedious to work out jump offsets there and the second comparison
10952 might have been transormed by `avr_reorg'.
10953
10954 RTL peephole won't do because peephole2 does not scan across
10955 basic blocks. */
10956
10957 static bool
avr_reorg_remove_redundant_compare(rtx_insn * insn1)10958 avr_reorg_remove_redundant_compare (rtx_insn *insn1)
10959 {
10960 rtx comp1, ifelse1, xcond1;
10961 rtx_insn *branch1;
10962 rtx comp2, ifelse2, xcond2;
10963 rtx_insn *branch2, *insn2;
10964 enum rtx_code code;
10965 rtx_insn *jump;
10966 rtx target, cond;
10967
10968 /* Look out for: compare1 - branch1 - compare2 - branch2 */
10969
10970 branch1 = next_nonnote_nondebug_insn (insn1);
10971 if (!branch1 || !JUMP_P (branch1))
10972 return false;
10973
10974 insn2 = next_nonnote_nondebug_insn (branch1);
10975 if (!insn2 || !avr_compare_pattern (insn2))
10976 return false;
10977
10978 branch2 = next_nonnote_nondebug_insn (insn2);
10979 if (!branch2 || !JUMP_P (branch2))
10980 return false;
10981
10982 comp1 = avr_compare_pattern (insn1);
10983 comp2 = avr_compare_pattern (insn2);
10984 xcond1 = single_set (branch1);
10985 xcond2 = single_set (branch2);
10986
10987 if (!comp1 || !comp2
10988 || !rtx_equal_p (comp1, comp2)
10989 || !xcond1 || SET_DEST (xcond1) != pc_rtx
10990 || !xcond2 || SET_DEST (xcond2) != pc_rtx
10991 || IF_THEN_ELSE != GET_CODE (SET_SRC (xcond1))
10992 || IF_THEN_ELSE != GET_CODE (SET_SRC (xcond2)))
10993 {
10994 return false;
10995 }
10996
10997 comp1 = SET_SRC (comp1);
10998 ifelse1 = SET_SRC (xcond1);
10999 ifelse2 = SET_SRC (xcond2);
11000
11001 /* comp<n> is COMPARE now and ifelse<n> is IF_THEN_ELSE. */
11002
11003 if (EQ != GET_CODE (XEXP (ifelse1, 0))
11004 || !REG_P (XEXP (comp1, 0))
11005 || !CONST_INT_P (XEXP (comp1, 1))
11006 || XEXP (ifelse1, 2) != pc_rtx
11007 || XEXP (ifelse2, 2) != pc_rtx
11008 || LABEL_REF != GET_CODE (XEXP (ifelse1, 1))
11009 || LABEL_REF != GET_CODE (XEXP (ifelse2, 1))
11010 || !COMPARISON_P (XEXP (ifelse2, 0))
11011 || cc0_rtx != XEXP (XEXP (ifelse1, 0), 0)
11012 || cc0_rtx != XEXP (XEXP (ifelse2, 0), 0)
11013 || const0_rtx != XEXP (XEXP (ifelse1, 0), 1)
11014 || const0_rtx != XEXP (XEXP (ifelse2, 0), 1))
11015 {
11016 return false;
11017 }
11018
11019 /* We filtered the insn sequence to look like
11020
11021 (set (cc0)
11022 (compare (reg:M N)
11023 (const_int VAL)))
11024 (set (pc)
11025 (if_then_else (eq (cc0)
11026 (const_int 0))
11027 (label_ref L1)
11028 (pc)))
11029
11030 (set (cc0)
11031 (compare (reg:M N)
11032 (const_int VAL)))
11033 (set (pc)
11034 (if_then_else (CODE (cc0)
11035 (const_int 0))
11036 (label_ref L2)
11037 (pc)))
11038 */
11039
11040 code = GET_CODE (XEXP (ifelse2, 0));
11041
11042 /* Map GT/GTU to GE/GEU which is easier for AVR.
11043 The first two instructions compare/branch on EQ
11044 so we may replace the difficult
11045
11046 if (x == VAL) goto L1;
11047 if (x > VAL) goto L2;
11048
11049 with easy
11050
11051 if (x == VAL) goto L1;
11052 if (x >= VAL) goto L2;
11053
11054 Similarly, replace LE/LEU by LT/LTU. */
11055
11056 switch (code)
11057 {
11058 case EQ:
11059 case LT: case LTU:
11060 case GE: case GEU:
11061 break;
11062
11063 case LE: case LEU:
11064 case GT: case GTU:
11065 code = avr_normalize_condition (code);
11066 break;
11067
11068 default:
11069 return false;
11070 }
11071
11072 /* Wrap the branches into UNSPECs so they won't be changed or
11073 optimized in the remainder. */
11074
11075 target = XEXP (XEXP (ifelse1, 1), 0);
11076 cond = XEXP (ifelse1, 0);
11077 jump = emit_jump_insn_after (gen_branch_unspec (target, cond), insn1);
11078
11079 JUMP_LABEL (jump) = JUMP_LABEL (branch1);
11080
11081 target = XEXP (XEXP (ifelse2, 1), 0);
11082 cond = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
11083 jump = emit_jump_insn_after (gen_branch_unspec (target, cond), insn2);
11084
11085 JUMP_LABEL (jump) = JUMP_LABEL (branch2);
11086
11087 /* The comparisons in insn1 and insn2 are exactly the same;
11088 insn2 is superfluous so delete it. */
11089
11090 delete_insn (insn2);
11091 delete_insn (branch1);
11092 delete_insn (branch2);
11093
11094 return true;
11095 }
11096
11097
11098 /* Implement `TARGET_MACHINE_DEPENDENT_REORG'. */
11099 /* Optimize conditional jumps. */
11100
11101 static void
avr_reorg(void)11102 avr_reorg (void)
11103 {
11104 rtx_insn *insn = get_insns();
11105
11106 for (insn = next_real_insn (insn); insn; insn = next_real_insn (insn))
11107 {
11108 rtx pattern = avr_compare_pattern (insn);
11109
11110 if (!pattern)
11111 continue;
11112
11113 if (optimize
11114 && avr_reorg_remove_redundant_compare (insn))
11115 {
11116 continue;
11117 }
11118
11119 if (compare_diff_p (insn))
11120 {
11121 /* Now we work under compare insn with difficult branch. */
11122
11123 rtx_insn *next = next_real_insn (insn);
11124 rtx pat = PATTERN (next);
11125
11126 pattern = SET_SRC (pattern);
11127
11128 if (true_regnum (XEXP (pattern, 0)) >= 0
11129 && true_regnum (XEXP (pattern, 1)) >= 0)
11130 {
11131 rtx x = XEXP (pattern, 0);
11132 rtx src = SET_SRC (pat);
11133 rtx t = XEXP (src,0);
11134 PUT_CODE (t, swap_condition (GET_CODE (t)));
11135 XEXP (pattern, 0) = XEXP (pattern, 1);
11136 XEXP (pattern, 1) = x;
11137 INSN_CODE (next) = -1;
11138 }
11139 else if (true_regnum (XEXP (pattern, 0)) >= 0
11140 && XEXP (pattern, 1) == const0_rtx)
11141 {
11142 /* This is a tst insn, we can reverse it. */
11143 rtx src = SET_SRC (pat);
11144 rtx t = XEXP (src,0);
11145
11146 PUT_CODE (t, swap_condition (GET_CODE (t)));
11147 XEXP (pattern, 1) = XEXP (pattern, 0);
11148 XEXP (pattern, 0) = const0_rtx;
11149 INSN_CODE (next) = -1;
11150 INSN_CODE (insn) = -1;
11151 }
11152 else if (true_regnum (XEXP (pattern, 0)) >= 0
11153 && CONST_INT_P (XEXP (pattern, 1)))
11154 {
11155 rtx x = XEXP (pattern, 1);
11156 rtx src = SET_SRC (pat);
11157 rtx t = XEXP (src,0);
11158 machine_mode mode = GET_MODE (XEXP (pattern, 0));
11159
11160 if (avr_simplify_comparison_p (mode, GET_CODE (t), x))
11161 {
11162 XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
11163 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
11164 INSN_CODE (next) = -1;
11165 INSN_CODE (insn) = -1;
11166 }
11167 }
11168 }
11169 }
11170 }
11171
11172 /* Returns register number for function return value.*/
11173
11174 static inline unsigned int
avr_ret_register(void)11175 avr_ret_register (void)
11176 {
11177 return 24;
11178 }
11179
11180
11181 /* Implement `TARGET_FUNCTION_VALUE_REGNO_P'. */
11182
11183 static bool
avr_function_value_regno_p(const unsigned int regno)11184 avr_function_value_regno_p (const unsigned int regno)
11185 {
11186 return (regno == avr_ret_register ());
11187 }
11188
11189
11190 /* Implement `TARGET_LIBCALL_VALUE'. */
11191 /* Create an RTX representing the place where a
11192 library function returns a value of mode MODE. */
11193
11194 static rtx
avr_libcall_value(machine_mode mode,const_rtx func ATTRIBUTE_UNUSED)11195 avr_libcall_value (machine_mode mode,
11196 const_rtx func ATTRIBUTE_UNUSED)
11197 {
11198 int offs = GET_MODE_SIZE (mode);
11199
11200 if (offs <= 4)
11201 offs = (offs + 1) & ~1;
11202
11203 return gen_rtx_REG (mode, avr_ret_register () + 2 - offs);
11204 }
11205
11206
11207 /* Implement `TARGET_FUNCTION_VALUE'. */
11208 /* Create an RTX representing the place where a
11209 function returns a value of data type VALTYPE. */
11210
11211 static rtx
avr_function_value(const_tree type,const_tree fn_decl_or_type ATTRIBUTE_UNUSED,bool outgoing ATTRIBUTE_UNUSED)11212 avr_function_value (const_tree type,
11213 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
11214 bool outgoing ATTRIBUTE_UNUSED)
11215 {
11216 unsigned int offs;
11217
11218 if (TYPE_MODE (type) != BLKmode)
11219 return avr_libcall_value (TYPE_MODE (type), NULL_RTX);
11220
11221 offs = int_size_in_bytes (type);
11222 if (offs < 2)
11223 offs = 2;
11224 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
11225 offs = GET_MODE_SIZE (SImode);
11226 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
11227 offs = GET_MODE_SIZE (DImode);
11228
11229 return gen_rtx_REG (BLKmode, avr_ret_register () + 2 - offs);
11230 }
11231
11232 int
test_hard_reg_class(enum reg_class rclass,rtx x)11233 test_hard_reg_class (enum reg_class rclass, rtx x)
11234 {
11235 int regno = true_regnum (x);
11236 if (regno < 0)
11237 return 0;
11238
11239 if (TEST_HARD_REG_CLASS (rclass, regno))
11240 return 1;
11241
11242 return 0;
11243 }
11244
11245
11246 /* Helper for jump_over_one_insn_p: Test if INSN is a 2-word instruction
11247 and thus is suitable to be skipped by CPSE, SBRC, etc. */
11248
11249 static bool
avr_2word_insn_p(rtx_insn * insn)11250 avr_2word_insn_p (rtx_insn *insn)
11251 {
11252 if (TARGET_SKIP_BUG
11253 || !insn
11254 || 2 != get_attr_length (insn))
11255 {
11256 return false;
11257 }
11258
11259 switch (INSN_CODE (insn))
11260 {
11261 default:
11262 return false;
11263
11264 case CODE_FOR_movqi_insn:
11265 case CODE_FOR_movuqq_insn:
11266 case CODE_FOR_movqq_insn:
11267 {
11268 rtx set = single_set (insn);
11269 rtx src = SET_SRC (set);
11270 rtx dest = SET_DEST (set);
11271
11272 /* Factor out LDS and STS from movqi_insn. */
11273
11274 if (MEM_P (dest)
11275 && (REG_P (src) || src == CONST0_RTX (GET_MODE (dest))))
11276 {
11277 return CONSTANT_ADDRESS_P (XEXP (dest, 0));
11278 }
11279 else if (REG_P (dest)
11280 && MEM_P (src))
11281 {
11282 return CONSTANT_ADDRESS_P (XEXP (src, 0));
11283 }
11284
11285 return false;
11286 }
11287
11288 case CODE_FOR_call_insn:
11289 case CODE_FOR_call_value_insn:
11290 return true;
11291 }
11292 }
11293
11294
11295 int
jump_over_one_insn_p(rtx_insn * insn,rtx dest)11296 jump_over_one_insn_p (rtx_insn *insn, rtx dest)
11297 {
11298 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
11299 ? XEXP (dest, 0)
11300 : dest);
11301 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
11302 int dest_addr = INSN_ADDRESSES (uid);
11303 int jump_offset = dest_addr - jump_addr - get_attr_length (insn);
11304
11305 return (jump_offset == 1
11306 || (jump_offset == 2
11307 && avr_2word_insn_p (next_active_insn (insn))));
11308 }
11309
11310
11311 /* Worker function for `HARD_REGNO_MODE_OK'. */
11312 /* Returns 1 if a value of mode MODE can be stored starting with hard
11313 register number REGNO. On the enhanced core, anything larger than
11314 1 byte must start in even numbered register for "movw" to work
11315 (this way we don't have to check for odd registers everywhere). */
11316
11317 int
avr_hard_regno_mode_ok(int regno,machine_mode mode)11318 avr_hard_regno_mode_ok (int regno, machine_mode mode)
11319 {
11320 /* NOTE: 8-bit values must not be disallowed for R28 or R29.
11321 Disallowing QI et al. in these regs might lead to code like
11322 (set (subreg:QI (reg:HI 28) n) ...)
11323 which will result in wrong code because reload does not
11324 handle SUBREGs of hard regsisters like this.
11325 This could be fixed in reload. However, it appears
11326 that fixing reload is not wanted by reload people. */
11327
11328 /* Any GENERAL_REGS register can hold 8-bit values. */
11329
11330 if (GET_MODE_SIZE (mode) == 1)
11331 return 1;
11332
11333 /* FIXME: Ideally, the following test is not needed.
11334 However, it turned out that it can reduce the number
11335 of spill fails. AVR and it's poor endowment with
11336 address registers is extreme stress test for reload. */
11337
11338 if (GET_MODE_SIZE (mode) >= 4
11339 && regno >= REG_X)
11340 return 0;
11341
11342 /* All modes larger than 8 bits should start in an even register. */
11343
11344 return !(regno & 1);
11345 }
11346
11347
11348 /* Implement `HARD_REGNO_CALL_PART_CLOBBERED'. */
11349
11350 int
avr_hard_regno_call_part_clobbered(unsigned regno,machine_mode mode)11351 avr_hard_regno_call_part_clobbered (unsigned regno, machine_mode mode)
11352 {
11353 /* FIXME: This hook gets called with MODE:REGNO combinations that don't
11354 represent valid hard registers like, e.g. HI:29. Returning TRUE
11355 for such registers can lead to performance degradation as mentioned
11356 in PR53595. Thus, report invalid hard registers as FALSE. */
11357
11358 if (!avr_hard_regno_mode_ok (regno, mode))
11359 return 0;
11360
11361 /* Return true if any of the following boundaries is crossed:
11362 17/18 or 19/20 (if AVR_TINY), 27/28 and 29/30. */
11363
11364 return ((regno <= LAST_CALLEE_SAVED_REG &&
11365 regno + GET_MODE_SIZE (mode) > (LAST_CALLEE_SAVED_REG + 1))
11366 || (regno < REG_Y && regno + GET_MODE_SIZE (mode) > REG_Y)
11367 || (regno < REG_Z && regno + GET_MODE_SIZE (mode) > REG_Z));
11368 }
11369
11370
11371 /* Implement `MODE_CODE_BASE_REG_CLASS'. */
11372
11373 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)11374 avr_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED,
11375 addr_space_t as, RTX_CODE outer_code,
11376 RTX_CODE index_code ATTRIBUTE_UNUSED)
11377 {
11378 if (!ADDR_SPACE_GENERIC_P (as))
11379 {
11380 return POINTER_Z_REGS;
11381 }
11382
11383 if (!avr_strict_X)
11384 return reload_completed ? BASE_POINTER_REGS : POINTER_REGS;
11385
11386 return PLUS == outer_code ? BASE_POINTER_REGS : POINTER_REGS;
11387 }
11388
11389
11390 /* Implement `REGNO_MODE_CODE_OK_FOR_BASE_P'. */
11391
11392 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)11393 avr_regno_mode_code_ok_for_base_p (int regno,
11394 machine_mode mode ATTRIBUTE_UNUSED,
11395 addr_space_t as ATTRIBUTE_UNUSED,
11396 RTX_CODE outer_code,
11397 RTX_CODE index_code ATTRIBUTE_UNUSED)
11398 {
11399 bool ok = false;
11400
11401 if (!ADDR_SPACE_GENERIC_P (as))
11402 {
11403 if (regno < FIRST_PSEUDO_REGISTER
11404 && regno == REG_Z)
11405 {
11406 return true;
11407 }
11408
11409 if (reg_renumber)
11410 {
11411 regno = reg_renumber[regno];
11412
11413 if (regno == REG_Z)
11414 {
11415 return true;
11416 }
11417 }
11418
11419 return false;
11420 }
11421
11422 if (regno < FIRST_PSEUDO_REGISTER
11423 && (regno == REG_X
11424 || regno == REG_Y
11425 || regno == REG_Z
11426 || regno == ARG_POINTER_REGNUM))
11427 {
11428 ok = true;
11429 }
11430 else if (reg_renumber)
11431 {
11432 regno = reg_renumber[regno];
11433
11434 if (regno == REG_X
11435 || regno == REG_Y
11436 || regno == REG_Z
11437 || regno == ARG_POINTER_REGNUM)
11438 {
11439 ok = true;
11440 }
11441 }
11442
11443 if (avr_strict_X
11444 && PLUS == outer_code
11445 && regno == REG_X)
11446 {
11447 ok = false;
11448 }
11449
11450 return ok;
11451 }
11452
11453
11454 /* A helper for `output_reload_insisf' and `output_reload_inhi'. */
11455 /* Set 32-bit register OP[0] to compile-time constant OP[1].
11456 CLOBBER_REG is a QI clobber register or NULL_RTX.
11457 LEN == NULL: output instructions.
11458 LEN != NULL: set *LEN to the length of the instruction sequence
11459 (in words) printed with LEN = NULL.
11460 If CLEAR_P is true, OP[0] had been cleard to Zero already.
11461 If CLEAR_P is false, nothing is known about OP[0].
11462
11463 The effect on cc0 is as follows:
11464
11465 Load 0 to any register except ZERO_REG : NONE
11466 Load ld register with any value : NONE
11467 Anything else: : CLOBBER */
11468
11469 static void
output_reload_in_const(rtx * op,rtx clobber_reg,int * len,bool clear_p)11470 output_reload_in_const (rtx *op, rtx clobber_reg, int *len, bool clear_p)
11471 {
11472 rtx src = op[1];
11473 rtx dest = op[0];
11474 rtx xval, xdest[4];
11475 int ival[4];
11476 int clobber_val = 1234;
11477 bool cooked_clobber_p = false;
11478 bool set_p = false;
11479 machine_mode mode = GET_MODE (dest);
11480 int n, n_bytes = GET_MODE_SIZE (mode);
11481
11482 gcc_assert (REG_P (dest)
11483 && CONSTANT_P (src));
11484
11485 if (len)
11486 *len = 0;
11487
11488 /* (REG:SI 14) is special: It's neither in LD_REGS nor in NO_LD_REGS
11489 but has some subregs that are in LD_REGS. Use the MSB (REG:QI 17). */
11490
11491 if (REGNO (dest) < 16
11492 && REGNO (dest) + GET_MODE_SIZE (mode) > 16)
11493 {
11494 clobber_reg = all_regs_rtx[REGNO (dest) + n_bytes - 1];
11495 }
11496
11497 /* We might need a clobber reg but don't have one. Look at the value to
11498 be loaded more closely. A clobber is only needed if it is a symbol
11499 or contains a byte that is neither 0, -1 or a power of 2. */
11500
11501 if (NULL_RTX == clobber_reg
11502 && !test_hard_reg_class (LD_REGS, dest)
11503 && (! (CONST_INT_P (src) || CONST_FIXED_P (src) || CONST_DOUBLE_P (src))
11504 || !avr_popcount_each_byte (src, n_bytes,
11505 (1 << 0) | (1 << 1) | (1 << 8))))
11506 {
11507 /* We have no clobber register but need one. Cook one up.
11508 That's cheaper than loading from constant pool. */
11509
11510 cooked_clobber_p = true;
11511 clobber_reg = all_regs_rtx[REG_Z + 1];
11512 avr_asm_len ("mov __tmp_reg__,%0", &clobber_reg, len, 1);
11513 }
11514
11515 /* Now start filling DEST from LSB to MSB. */
11516
11517 for (n = 0; n < n_bytes; n++)
11518 {
11519 int ldreg_p;
11520 bool done_byte = false;
11521 int j;
11522 rtx xop[3];
11523
11524 /* Crop the n-th destination byte. */
11525
11526 xdest[n] = simplify_gen_subreg (QImode, dest, mode, n);
11527 ldreg_p = test_hard_reg_class (LD_REGS, xdest[n]);
11528
11529 if (!CONST_INT_P (src)
11530 && !CONST_FIXED_P (src)
11531 && !CONST_DOUBLE_P (src))
11532 {
11533 static const char* const asm_code[][2] =
11534 {
11535 { "ldi %2,lo8(%1)" CR_TAB "mov %0,%2", "ldi %0,lo8(%1)" },
11536 { "ldi %2,hi8(%1)" CR_TAB "mov %0,%2", "ldi %0,hi8(%1)" },
11537 { "ldi %2,hlo8(%1)" CR_TAB "mov %0,%2", "ldi %0,hlo8(%1)" },
11538 { "ldi %2,hhi8(%1)" CR_TAB "mov %0,%2", "ldi %0,hhi8(%1)" }
11539 };
11540
11541 xop[0] = xdest[n];
11542 xop[1] = src;
11543 xop[2] = clobber_reg;
11544
11545 avr_asm_len (asm_code[n][ldreg_p], xop, len, ldreg_p ? 1 : 2);
11546
11547 continue;
11548 }
11549
11550 /* Crop the n-th source byte. */
11551
11552 xval = simplify_gen_subreg (QImode, src, mode, n);
11553 ival[n] = INTVAL (xval);
11554
11555 /* Look if we can reuse the low word by means of MOVW. */
11556
11557 if (n == 2
11558 && n_bytes >= 4
11559 && AVR_HAVE_MOVW)
11560 {
11561 rtx lo16 = simplify_gen_subreg (HImode, src, mode, 0);
11562 rtx hi16 = simplify_gen_subreg (HImode, src, mode, 2);
11563
11564 if (INTVAL (lo16) == INTVAL (hi16))
11565 {
11566 if (0 != INTVAL (lo16)
11567 || !clear_p)
11568 {
11569 avr_asm_len ("movw %C0,%A0", &op[0], len, 1);
11570 }
11571
11572 break;
11573 }
11574 }
11575
11576 /* Don't use CLR so that cc0 is set as expected. */
11577
11578 if (ival[n] == 0)
11579 {
11580 if (!clear_p)
11581 avr_asm_len (ldreg_p ? "ldi %0,0"
11582 : AVR_ZERO_REGNO == REGNO (xdest[n]) ? "clr %0"
11583 : "mov %0,__zero_reg__",
11584 &xdest[n], len, 1);
11585 continue;
11586 }
11587
11588 if (clobber_val == ival[n]
11589 && REGNO (clobber_reg) == REGNO (xdest[n]))
11590 {
11591 continue;
11592 }
11593
11594 /* LD_REGS can use LDI to move a constant value */
11595
11596 if (ldreg_p)
11597 {
11598 xop[0] = xdest[n];
11599 xop[1] = xval;
11600 avr_asm_len ("ldi %0,lo8(%1)", xop, len, 1);
11601 continue;
11602 }
11603
11604 /* Try to reuse value already loaded in some lower byte. */
11605
11606 for (j = 0; j < n; j++)
11607 if (ival[j] == ival[n])
11608 {
11609 xop[0] = xdest[n];
11610 xop[1] = xdest[j];
11611
11612 avr_asm_len ("mov %0,%1", xop, len, 1);
11613 done_byte = true;
11614 break;
11615 }
11616
11617 if (done_byte)
11618 continue;
11619
11620 /* Need no clobber reg for -1: Use CLR/DEC */
11621
11622 if (-1 == ival[n])
11623 {
11624 if (!clear_p)
11625 avr_asm_len ("clr %0", &xdest[n], len, 1);
11626
11627 avr_asm_len ("dec %0", &xdest[n], len, 1);
11628 continue;
11629 }
11630 else if (1 == ival[n])
11631 {
11632 if (!clear_p)
11633 avr_asm_len ("clr %0", &xdest[n], len, 1);
11634
11635 avr_asm_len ("inc %0", &xdest[n], len, 1);
11636 continue;
11637 }
11638
11639 /* Use T flag or INC to manage powers of 2 if we have
11640 no clobber reg. */
11641
11642 if (NULL_RTX == clobber_reg
11643 && single_one_operand (xval, QImode))
11644 {
11645 xop[0] = xdest[n];
11646 xop[1] = GEN_INT (exact_log2 (ival[n] & GET_MODE_MASK (QImode)));
11647
11648 gcc_assert (constm1_rtx != xop[1]);
11649
11650 if (!set_p)
11651 {
11652 set_p = true;
11653 avr_asm_len ("set", xop, len, 1);
11654 }
11655
11656 if (!clear_p)
11657 avr_asm_len ("clr %0", xop, len, 1);
11658
11659 avr_asm_len ("bld %0,%1", xop, len, 1);
11660 continue;
11661 }
11662
11663 /* We actually need the LD_REGS clobber reg. */
11664
11665 gcc_assert (NULL_RTX != clobber_reg);
11666
11667 xop[0] = xdest[n];
11668 xop[1] = xval;
11669 xop[2] = clobber_reg;
11670 clobber_val = ival[n];
11671
11672 avr_asm_len ("ldi %2,lo8(%1)" CR_TAB
11673 "mov %0,%2", xop, len, 2);
11674 }
11675
11676 /* If we cooked up a clobber reg above, restore it. */
11677
11678 if (cooked_clobber_p)
11679 {
11680 avr_asm_len ("mov %0,__tmp_reg__", &clobber_reg, len, 1);
11681 }
11682 }
11683
11684
11685 /* Reload the constant OP[1] into the HI register OP[0].
11686 CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
11687 into a NO_LD_REGS register. If CLOBBER_REG is NULL_RTX we either don't
11688 need a clobber reg or have to cook one up.
11689
11690 PLEN == NULL: Output instructions.
11691 PLEN != NULL: Output nothing. Set *PLEN to number of words occupied
11692 by the insns printed.
11693
11694 Return "". */
11695
11696 const char*
output_reload_inhi(rtx * op,rtx clobber_reg,int * plen)11697 output_reload_inhi (rtx *op, rtx clobber_reg, int *plen)
11698 {
11699 output_reload_in_const (op, clobber_reg, plen, false);
11700 return "";
11701 }
11702
11703
11704 /* Reload a SI or SF compile time constant OP[1] into the register OP[0].
11705 CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
11706 into a NO_LD_REGS register. If CLOBBER_REG is NULL_RTX we either don't
11707 need a clobber reg or have to cook one up.
11708
11709 LEN == NULL: Output instructions.
11710
11711 LEN != NULL: Output nothing. Set *LEN to number of words occupied
11712 by the insns printed.
11713
11714 Return "". */
11715
11716 const char *
output_reload_insisf(rtx * op,rtx clobber_reg,int * len)11717 output_reload_insisf (rtx *op, rtx clobber_reg, int *len)
11718 {
11719 if (AVR_HAVE_MOVW
11720 && !test_hard_reg_class (LD_REGS, op[0])
11721 && (CONST_INT_P (op[1])
11722 || CONST_FIXED_P (op[1])
11723 || CONST_DOUBLE_P (op[1])))
11724 {
11725 int len_clr, len_noclr;
11726
11727 /* In some cases it is better to clear the destination beforehand, e.g.
11728
11729 CLR R2 CLR R3 MOVW R4,R2 INC R2
11730
11731 is shorther than
11732
11733 CLR R2 INC R2 CLR R3 CLR R4 CLR R5
11734
11735 We find it too tedious to work that out in the print function.
11736 Instead, we call the print function twice to get the lengths of
11737 both methods and use the shortest one. */
11738
11739 output_reload_in_const (op, clobber_reg, &len_clr, true);
11740 output_reload_in_const (op, clobber_reg, &len_noclr, false);
11741
11742 if (len_noclr - len_clr == 4)
11743 {
11744 /* Default needs 4 CLR instructions: clear register beforehand. */
11745
11746 avr_asm_len ("mov %A0,__zero_reg__" CR_TAB
11747 "mov %B0,__zero_reg__" CR_TAB
11748 "movw %C0,%A0", &op[0], len, 3);
11749
11750 output_reload_in_const (op, clobber_reg, len, true);
11751
11752 if (len)
11753 *len += 3;
11754
11755 return "";
11756 }
11757 }
11758
11759 /* Default: destination not pre-cleared. */
11760
11761 output_reload_in_const (op, clobber_reg, len, false);
11762 return "";
11763 }
11764
11765 const char*
avr_out_reload_inpsi(rtx * op,rtx clobber_reg,int * len)11766 avr_out_reload_inpsi (rtx *op, rtx clobber_reg, int *len)
11767 {
11768 output_reload_in_const (op, clobber_reg, len, false);
11769 return "";
11770 }
11771
11772
11773 /* Worker function for `ASM_OUTPUT_ADDR_VEC_ELT'. */
11774
11775 void
avr_output_addr_vec_elt(FILE * stream,int value)11776 avr_output_addr_vec_elt (FILE *stream, int value)
11777 {
11778 if (AVR_HAVE_JMP_CALL)
11779 fprintf (stream, "\t.word gs(.L%d)\n", value);
11780 else
11781 fprintf (stream, "\trjmp .L%d\n", value);
11782 }
11783
11784 static void
avr_conditional_register_usage(void)11785 avr_conditional_register_usage(void)
11786 {
11787 if (AVR_TINY)
11788 {
11789 unsigned int i;
11790
11791 const int tiny_reg_alloc_order[] = {
11792 24, 25,
11793 22, 23,
11794 30, 31,
11795 26, 27,
11796 28, 29,
11797 21, 20, 19, 18,
11798 16, 17,
11799 32, 33, 34, 35,
11800 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
11801 };
11802
11803 /* Set R0-R17 as fixed registers. Reset R0-R17 in call used register list
11804 - R0-R15 are not available in Tiny Core devices
11805 - R16 and R17 are fixed registers. */
11806
11807 for (i = 0; i <= 17; i++)
11808 {
11809 fixed_regs[i] = 1;
11810 call_used_regs[i] = 1;
11811 }
11812
11813 /* Set R18 to R21 as callee saved registers
11814 - R18, R19, R20 and R21 are the callee saved registers in
11815 Tiny Core devices */
11816
11817 for (i = 18; i <= LAST_CALLEE_SAVED_REG; i++)
11818 {
11819 call_used_regs[i] = 0;
11820 }
11821
11822 /* Update register allocation order for Tiny Core devices */
11823
11824 for (i = 0; i < ARRAY_SIZE (tiny_reg_alloc_order); i++)
11825 {
11826 reg_alloc_order[i] = tiny_reg_alloc_order[i];
11827 }
11828
11829 CLEAR_HARD_REG_SET (reg_class_contents[(int) ADDW_REGS]);
11830 CLEAR_HARD_REG_SET (reg_class_contents[(int) NO_LD_REGS]);
11831 }
11832 }
11833
11834 /* Implement `TARGET_HARD_REGNO_SCRATCH_OK'. */
11835 /* Returns true if SCRATCH are safe to be allocated as a scratch
11836 registers (for a define_peephole2) in the current function. */
11837
11838 static bool
avr_hard_regno_scratch_ok(unsigned int regno)11839 avr_hard_regno_scratch_ok (unsigned int regno)
11840 {
11841 /* Interrupt functions can only use registers that have already been saved
11842 by the prologue, even if they would normally be call-clobbered. */
11843
11844 if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
11845 && !df_regs_ever_live_p (regno))
11846 return false;
11847
11848 /* Don't allow hard registers that might be part of the frame pointer.
11849 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
11850 and don't care for a frame pointer that spans more than one register. */
11851
11852 if ((!reload_completed || frame_pointer_needed)
11853 && (regno == REG_Y || regno == REG_Y + 1))
11854 {
11855 return false;
11856 }
11857
11858 return true;
11859 }
11860
11861
11862 /* Worker function for `HARD_REGNO_RENAME_OK'. */
11863 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
11864
11865 int
avr_hard_regno_rename_ok(unsigned int old_reg,unsigned int new_reg)11866 avr_hard_regno_rename_ok (unsigned int old_reg,
11867 unsigned int new_reg)
11868 {
11869 /* Interrupt functions can only use registers that have already been
11870 saved by the prologue, even if they would normally be
11871 call-clobbered. */
11872
11873 if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
11874 && !df_regs_ever_live_p (new_reg))
11875 return 0;
11876
11877 /* Don't allow hard registers that might be part of the frame pointer.
11878 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
11879 and don't care for a frame pointer that spans more than one register. */
11880
11881 if ((!reload_completed || frame_pointer_needed)
11882 && (old_reg == REG_Y || old_reg == REG_Y + 1
11883 || new_reg == REG_Y || new_reg == REG_Y + 1))
11884 {
11885 return 0;
11886 }
11887
11888 return 1;
11889 }
11890
11891 /* Output a branch that tests a single bit of a register (QI, HI, SI or DImode)
11892 or memory location in the I/O space (QImode only).
11893
11894 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
11895 Operand 1: register operand to test, or CONST_INT memory address.
11896 Operand 2: bit number.
11897 Operand 3: label to jump to if the test is true. */
11898
11899 const char*
avr_out_sbxx_branch(rtx_insn * insn,rtx operands[])11900 avr_out_sbxx_branch (rtx_insn *insn, rtx operands[])
11901 {
11902 enum rtx_code comp = GET_CODE (operands[0]);
11903 bool long_jump = get_attr_length (insn) >= 4;
11904 bool reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
11905
11906 if (comp == GE)
11907 comp = EQ;
11908 else if (comp == LT)
11909 comp = NE;
11910
11911 if (reverse)
11912 comp = reverse_condition (comp);
11913
11914 switch (GET_CODE (operands[1]))
11915 {
11916 default:
11917 gcc_unreachable();
11918
11919 case CONST_INT:
11920 case CONST:
11921 case SYMBOL_REF:
11922
11923 if (low_io_address_operand (operands[1], QImode))
11924 {
11925 if (comp == EQ)
11926 output_asm_insn ("sbis %i1,%2", operands);
11927 else
11928 output_asm_insn ("sbic %i1,%2", operands);
11929 }
11930 else
11931 {
11932 gcc_assert (io_address_operand (operands[1], QImode));
11933 output_asm_insn ("in __tmp_reg__,%i1", operands);
11934 if (comp == EQ)
11935 output_asm_insn ("sbrs __tmp_reg__,%2", operands);
11936 else
11937 output_asm_insn ("sbrc __tmp_reg__,%2", operands);
11938 }
11939
11940 break; /* CONST_INT */
11941
11942 case REG:
11943
11944 if (comp == EQ)
11945 output_asm_insn ("sbrs %T1%T2", operands);
11946 else
11947 output_asm_insn ("sbrc %T1%T2", operands);
11948
11949 break; /* REG */
11950 } /* switch */
11951
11952 if (long_jump)
11953 return ("rjmp .+4" CR_TAB
11954 "jmp %x3");
11955
11956 if (!reverse)
11957 return "rjmp %x3";
11958
11959 return "";
11960 }
11961
11962 /* Worker function for `TARGET_ASM_CONSTRUCTOR'. */
11963
11964 static void
avr_asm_out_ctor(rtx symbol,int priority)11965 avr_asm_out_ctor (rtx symbol, int priority)
11966 {
11967 fputs ("\t.global __do_global_ctors\n", asm_out_file);
11968 default_ctor_section_asm_out_constructor (symbol, priority);
11969 }
11970
11971
11972 /* Worker function for `TARGET_ASM_DESTRUCTOR'. */
11973
11974 static void
avr_asm_out_dtor(rtx symbol,int priority)11975 avr_asm_out_dtor (rtx symbol, int priority)
11976 {
11977 fputs ("\t.global __do_global_dtors\n", asm_out_file);
11978 default_dtor_section_asm_out_destructor (symbol, priority);
11979 }
11980
11981
11982 /* Worker function for `TARGET_RETURN_IN_MEMORY'. */
11983
11984 static bool
avr_return_in_memory(const_tree type,const_tree fntype ATTRIBUTE_UNUSED)11985 avr_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
11986 {
11987 HOST_WIDE_INT size = int_size_in_bytes (type);
11988 HOST_WIDE_INT ret_size_limit = AVR_TINY ? 4 : 8;
11989
11990 /* In avr, there are 8 return registers. But, for Tiny Core
11991 (ATtiny4/5/9/10/20/40) devices, only 4 registers are available.
11992 Return true if size is unknown or greater than the limit. */
11993
11994 if (size == -1 || size > ret_size_limit)
11995 {
11996 return true;
11997 }
11998 else
11999 {
12000 return false;
12001 }
12002 }
12003
12004
12005 /* Implement `CASE_VALUES_THRESHOLD'. */
12006 /* Supply the default for --param case-values-threshold=0 */
12007
12008 static unsigned int
avr_case_values_threshold(void)12009 avr_case_values_threshold (void)
12010 {
12011 /* The exact break-even point between a jump table and an if-else tree
12012 depends on several factors not available here like, e.g. if 8-bit
12013 comparisons can be used in the if-else tree or not, on the
12014 range of the case values, if the case value can be reused, on the
12015 register allocation, etc. '7' appears to be a good choice. */
12016
12017 return 7;
12018 }
12019
12020
12021 /* Implement `TARGET_ADDR_SPACE_ADDRESS_MODE'. */
12022
12023 static machine_mode
avr_addr_space_address_mode(addr_space_t as)12024 avr_addr_space_address_mode (addr_space_t as)
12025 {
12026 return avr_addrspace[as].pointer_size == 3 ? PSImode : HImode;
12027 }
12028
12029
12030 /* Implement `TARGET_ADDR_SPACE_POINTER_MODE'. */
12031
12032 static machine_mode
avr_addr_space_pointer_mode(addr_space_t as)12033 avr_addr_space_pointer_mode (addr_space_t as)
12034 {
12035 return avr_addr_space_address_mode (as);
12036 }
12037
12038
12039 /* Helper for following function. */
12040
12041 static bool
avr_reg_ok_for_pgm_addr(rtx reg,bool strict)12042 avr_reg_ok_for_pgm_addr (rtx reg, bool strict)
12043 {
12044 gcc_assert (REG_P (reg));
12045
12046 if (strict)
12047 {
12048 return REGNO (reg) == REG_Z;
12049 }
12050
12051 /* Avoid combine to propagate hard regs. */
12052
12053 if (can_create_pseudo_p()
12054 && REGNO (reg) < REG_Z)
12055 {
12056 return false;
12057 }
12058
12059 return true;
12060 }
12061
12062
12063 /* Implement `TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P'. */
12064
12065 static bool
avr_addr_space_legitimate_address_p(machine_mode mode,rtx x,bool strict,addr_space_t as)12066 avr_addr_space_legitimate_address_p (machine_mode mode, rtx x,
12067 bool strict, addr_space_t as)
12068 {
12069 bool ok = false;
12070
12071 switch (as)
12072 {
12073 default:
12074 gcc_unreachable();
12075
12076 case ADDR_SPACE_GENERIC:
12077 return avr_legitimate_address_p (mode, x, strict);
12078
12079 case ADDR_SPACE_FLASH:
12080 case ADDR_SPACE_FLASH1:
12081 case ADDR_SPACE_FLASH2:
12082 case ADDR_SPACE_FLASH3:
12083 case ADDR_SPACE_FLASH4:
12084 case ADDR_SPACE_FLASH5:
12085
12086 switch (GET_CODE (x))
12087 {
12088 case REG:
12089 ok = avr_reg_ok_for_pgm_addr (x, strict);
12090 break;
12091
12092 case POST_INC:
12093 ok = avr_reg_ok_for_pgm_addr (XEXP (x, 0), strict);
12094 break;
12095
12096 default:
12097 break;
12098 }
12099
12100 break; /* FLASH */
12101
12102 case ADDR_SPACE_MEMX:
12103 if (REG_P (x))
12104 ok = (!strict
12105 && can_create_pseudo_p());
12106
12107 if (LO_SUM == GET_CODE (x))
12108 {
12109 rtx hi = XEXP (x, 0);
12110 rtx lo = XEXP (x, 1);
12111
12112 ok = (REG_P (hi)
12113 && (!strict || REGNO (hi) < FIRST_PSEUDO_REGISTER)
12114 && REG_P (lo)
12115 && REGNO (lo) == REG_Z);
12116 }
12117
12118 break; /* MEMX */
12119 }
12120
12121 if (avr_log.legitimate_address_p)
12122 {
12123 avr_edump ("\n%?: ret=%b, mode=%m strict=%d "
12124 "reload_completed=%d reload_in_progress=%d %s:",
12125 ok, mode, strict, reload_completed, reload_in_progress,
12126 reg_renumber ? "(reg_renumber)" : "");
12127
12128 if (GET_CODE (x) == PLUS
12129 && REG_P (XEXP (x, 0))
12130 && CONST_INT_P (XEXP (x, 1))
12131 && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
12132 && reg_renumber)
12133 {
12134 avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
12135 true_regnum (XEXP (x, 0)));
12136 }
12137
12138 avr_edump ("\n%r\n", x);
12139 }
12140
12141 return ok;
12142 }
12143
12144
12145 /* Implement `TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS'. */
12146
12147 static rtx
avr_addr_space_legitimize_address(rtx x,rtx old_x,machine_mode mode,addr_space_t as)12148 avr_addr_space_legitimize_address (rtx x, rtx old_x,
12149 machine_mode mode, addr_space_t as)
12150 {
12151 if (ADDR_SPACE_GENERIC_P (as))
12152 return avr_legitimize_address (x, old_x, mode);
12153
12154 if (avr_log.legitimize_address)
12155 {
12156 avr_edump ("\n%?: mode=%m\n %r\n", mode, old_x);
12157 }
12158
12159 return old_x;
12160 }
12161
12162
12163 /* Implement `TARGET_ADDR_SPACE_CONVERT'. */
12164
12165 static rtx
avr_addr_space_convert(rtx src,tree type_from,tree type_to)12166 avr_addr_space_convert (rtx src, tree type_from, tree type_to)
12167 {
12168 addr_space_t as_from = TYPE_ADDR_SPACE (TREE_TYPE (type_from));
12169 addr_space_t as_to = TYPE_ADDR_SPACE (TREE_TYPE (type_to));
12170
12171 if (avr_log.progmem)
12172 avr_edump ("\n%!: op = %r\nfrom = %t\nto = %t\n",
12173 src, type_from, type_to);
12174
12175 /* Up-casting from 16-bit to 24-bit pointer. */
12176
12177 if (as_from != ADDR_SPACE_MEMX
12178 && as_to == ADDR_SPACE_MEMX)
12179 {
12180 int msb;
12181 rtx sym = src;
12182 rtx reg = gen_reg_rtx (PSImode);
12183
12184 while (CONST == GET_CODE (sym) || PLUS == GET_CODE (sym))
12185 sym = XEXP (sym, 0);
12186
12187 /* Look at symbol flags: avr_encode_section_info set the flags
12188 also if attribute progmem was seen so that we get the right
12189 promotion for, e.g. PSTR-like strings that reside in generic space
12190 but are located in flash. In that case we patch the incoming
12191 address space. */
12192
12193 if (SYMBOL_REF == GET_CODE (sym)
12194 && ADDR_SPACE_FLASH == AVR_SYMBOL_GET_ADDR_SPACE (sym))
12195 {
12196 as_from = ADDR_SPACE_FLASH;
12197 }
12198
12199 /* Linearize memory: RAM has bit 23 set. */
12200
12201 msb = ADDR_SPACE_GENERIC_P (as_from)
12202 ? 0x80
12203 : avr_addrspace[as_from].segment;
12204
12205 src = force_reg (Pmode, src);
12206
12207 emit_insn (msb == 0
12208 ? gen_zero_extendhipsi2 (reg, src)
12209 : gen_n_extendhipsi2 (reg, gen_int_mode (msb, QImode), src));
12210
12211 return reg;
12212 }
12213
12214 /* Down-casting from 24-bit to 16-bit throws away the high byte. */
12215
12216 if (as_from == ADDR_SPACE_MEMX
12217 && as_to != ADDR_SPACE_MEMX)
12218 {
12219 rtx new_src = gen_reg_rtx (Pmode);
12220
12221 src = force_reg (PSImode, src);
12222
12223 emit_move_insn (new_src,
12224 simplify_gen_subreg (Pmode, src, PSImode, 0));
12225 return new_src;
12226 }
12227
12228 return src;
12229 }
12230
12231
12232 /* Implement `TARGET_ADDR_SPACE_SUBSET_P'. */
12233
12234 static bool
avr_addr_space_subset_p(addr_space_t subset ATTRIBUTE_UNUSED,addr_space_t superset ATTRIBUTE_UNUSED)12235 avr_addr_space_subset_p (addr_space_t subset ATTRIBUTE_UNUSED,
12236 addr_space_t superset ATTRIBUTE_UNUSED)
12237 {
12238 /* Allow any kind of pointer mess. */
12239
12240 return true;
12241 }
12242
12243
12244 /* Implement `TARGET_CONVERT_TO_TYPE'. */
12245
12246 static tree
avr_convert_to_type(tree type,tree expr)12247 avr_convert_to_type (tree type, tree expr)
12248 {
12249 /* Print a diagnose for pointer conversion that changes the address
12250 space of the pointer target to a non-enclosing address space,
12251 provided -Waddr-space-convert is on.
12252
12253 FIXME: Filter out cases where the target object is known to
12254 be located in the right memory, like in
12255
12256 (const __flash*) PSTR ("text")
12257
12258 Also try to distinguish between explicit casts requested by
12259 the user and implicit casts like
12260
12261 void f (const __flash char*);
12262
12263 void g (const char *p)
12264 {
12265 f ((const __flash*) p);
12266 }
12267
12268 under the assumption that an explicit casts means that the user
12269 knows what he is doing, e.g. interface with PSTR or old style
12270 code with progmem and pgm_read_xxx.
12271 */
12272
12273 if (avr_warn_addr_space_convert
12274 && expr != error_mark_node
12275 && POINTER_TYPE_P (type)
12276 && POINTER_TYPE_P (TREE_TYPE (expr)))
12277 {
12278 addr_space_t as_old = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (expr)));
12279 addr_space_t as_new = TYPE_ADDR_SPACE (TREE_TYPE (type));
12280
12281 if (avr_log.progmem)
12282 avr_edump ("%?: type = %t\nexpr = %t\n\n", type, expr);
12283
12284 if (as_new != ADDR_SPACE_MEMX
12285 && as_new != as_old)
12286 {
12287 location_t loc = EXPR_LOCATION (expr);
12288 const char *name_old = avr_addrspace[as_old].name;
12289 const char *name_new = avr_addrspace[as_new].name;
12290
12291 warning (OPT_Waddr_space_convert,
12292 "conversion from address space %qs to address space %qs",
12293 ADDR_SPACE_GENERIC_P (as_old) ? "generic" : name_old,
12294 ADDR_SPACE_GENERIC_P (as_new) ? "generic" : name_new);
12295
12296 return fold_build1_loc (loc, ADDR_SPACE_CONVERT_EXPR, type, expr);
12297 }
12298 }
12299
12300 return NULL_TREE;
12301 }
12302
12303
12304 /* PR63633: The middle-end might come up with hard regs as input operands.
12305
12306 RMASK is a bit mask representing a subset of hard registers R0...R31:
12307 Rn is an element of that set iff bit n of RMASK is set.
12308 OPMASK describes a subset of OP[]: If bit n of OPMASK is 1 then
12309 OP[n] has to be fixed; otherwise OP[n] is left alone.
12310
12311 For each element of OPMASK which is a hard register overlapping RMASK,
12312 replace OP[n] with a newly created pseudo register
12313
12314 HREG == 0: Also emit a move insn that copies the contents of that
12315 hard register into the new pseudo.
12316
12317 HREG != 0: Also set HREG[n] to the hard register. */
12318
12319 static void
avr_fix_operands(rtx * op,rtx * hreg,unsigned opmask,unsigned rmask)12320 avr_fix_operands (rtx *op, rtx *hreg, unsigned opmask, unsigned rmask)
12321 {
12322 for (; opmask; opmask >>= 1, op++)
12323 {
12324 rtx reg = *op;
12325
12326 if (hreg)
12327 *hreg = NULL_RTX;
12328
12329 if ((opmask & 1)
12330 && REG_P (reg)
12331 && REGNO (reg) < FIRST_PSEUDO_REGISTER
12332 // This hard-reg overlaps other prohibited hard regs?
12333 && (rmask & regmask (GET_MODE (reg), REGNO (reg))))
12334 {
12335 *op = gen_reg_rtx (GET_MODE (reg));
12336 if (hreg == NULL)
12337 emit_move_insn (*op, reg);
12338 else
12339 *hreg = reg;
12340 }
12341
12342 if (hreg)
12343 hreg++;
12344 }
12345 }
12346
12347
12348 void
avr_fix_inputs(rtx * op,unsigned opmask,unsigned rmask)12349 avr_fix_inputs (rtx *op, unsigned opmask, unsigned rmask)
12350 {
12351 avr_fix_operands (op, NULL, opmask, rmask);
12352 }
12353
12354
12355 /* Helper for the function below: If bit n of MASK is set and
12356 HREG[n] != NULL, then emit a move insn to copy OP[n] to HREG[n].
12357 Otherwise do nothing for that n. Return TRUE. */
12358
12359 static bool
avr_move_fixed_operands(rtx * op,rtx * hreg,unsigned mask)12360 avr_move_fixed_operands (rtx *op, rtx *hreg, unsigned mask)
12361 {
12362 for (; mask; mask >>= 1, op++, hreg++)
12363 if ((mask & 1)
12364 && *hreg)
12365 emit_move_insn (*hreg, *op);
12366
12367 return true;
12368 }
12369
12370
12371 /* PR63633: The middle-end might come up with hard regs as output operands.
12372
12373 GEN is a sequence generating function like gen_mulsi3 with 3 operands OP[].
12374 RMASK is a bit mask representing a subset of hard registers R0...R31:
12375 Rn is an element of that set iff bit n of RMASK is set.
12376 OPMASK describes a subset of OP[]: If bit n of OPMASK is 1 then
12377 OP[n] has to be fixed; otherwise OP[n] is left alone.
12378
12379 Emit the insn sequence as generated by GEN() with all elements of OPMASK
12380 which are hard registers overlapping RMASK replaced by newly created
12381 pseudo registers. After the sequence has been emitted, emit insns that
12382 move the contents of respective pseudos to their hard regs. */
12383
12384 bool
avr_emit3_fix_outputs(rtx (* gen)(rtx,rtx,rtx),rtx * op,unsigned opmask,unsigned rmask)12385 avr_emit3_fix_outputs (rtx (*gen)(rtx,rtx,rtx), rtx *op,
12386 unsigned opmask, unsigned rmask)
12387 {
12388 const int n = 3;
12389 rtx hreg[n];
12390
12391 /* It is letigimate for GEN to call this function, and in order not to
12392 get self-recursive we use the following static kludge. This is the
12393 only way not to duplicate all expanders and to avoid ugly and
12394 hard-to-maintain C-code instead of the much more appreciated RTL
12395 representation as supplied by define_expand. */
12396 static bool lock = false;
12397
12398 gcc_assert (opmask < (1u << n));
12399
12400 if (lock)
12401 return false;
12402
12403 avr_fix_operands (op, hreg, opmask, rmask);
12404
12405 lock = true;
12406 emit_insn (gen (op[0], op[1], op[2]));
12407 lock = false;
12408
12409 return avr_move_fixed_operands (op, hreg, opmask);
12410 }
12411
12412
12413 /* Worker function for movmemhi expander.
12414 XOP[0] Destination as MEM:BLK
12415 XOP[1] Source " "
12416 XOP[2] # Bytes to copy
12417
12418 Return TRUE if the expansion is accomplished.
12419 Return FALSE if the operand compination is not supported. */
12420
12421 bool
avr_emit_movmemhi(rtx * xop)12422 avr_emit_movmemhi (rtx *xop)
12423 {
12424 HOST_WIDE_INT count;
12425 machine_mode loop_mode;
12426 addr_space_t as = MEM_ADDR_SPACE (xop[1]);
12427 rtx loop_reg, addr1, a_src, a_dest, insn, xas;
12428 rtx a_hi8 = NULL_RTX;
12429
12430 if (avr_mem_flash_p (xop[0]))
12431 return false;
12432
12433 if (!CONST_INT_P (xop[2]))
12434 return false;
12435
12436 count = INTVAL (xop[2]);
12437 if (count <= 0)
12438 return false;
12439
12440 a_src = XEXP (xop[1], 0);
12441 a_dest = XEXP (xop[0], 0);
12442
12443 if (PSImode == GET_MODE (a_src))
12444 {
12445 gcc_assert (as == ADDR_SPACE_MEMX);
12446
12447 loop_mode = (count < 0x100) ? QImode : HImode;
12448 loop_reg = gen_rtx_REG (loop_mode, 24);
12449 emit_move_insn (loop_reg, gen_int_mode (count, loop_mode));
12450
12451 addr1 = simplify_gen_subreg (HImode, a_src, PSImode, 0);
12452 a_hi8 = simplify_gen_subreg (QImode, a_src, PSImode, 2);
12453 }
12454 else
12455 {
12456 int segment = avr_addrspace[as].segment;
12457
12458 if (segment
12459 && avr_n_flash > 1)
12460 {
12461 a_hi8 = GEN_INT (segment);
12462 emit_move_insn (rampz_rtx, a_hi8 = copy_to_mode_reg (QImode, a_hi8));
12463 }
12464 else if (!ADDR_SPACE_GENERIC_P (as))
12465 {
12466 as = ADDR_SPACE_FLASH;
12467 }
12468
12469 addr1 = a_src;
12470
12471 loop_mode = (count <= 0x100) ? QImode : HImode;
12472 loop_reg = copy_to_mode_reg (loop_mode, gen_int_mode (count, loop_mode));
12473 }
12474
12475 xas = GEN_INT (as);
12476
12477 /* FIXME: Register allocator might come up with spill fails if it is left
12478 on its own. Thus, we allocate the pointer registers by hand:
12479 Z = source address
12480 X = destination address */
12481
12482 emit_move_insn (lpm_addr_reg_rtx, addr1);
12483 emit_move_insn (gen_rtx_REG (HImode, REG_X), a_dest);
12484
12485 /* FIXME: Register allocator does a bad job and might spill address
12486 register(s) inside the loop leading to additional move instruction
12487 to/from stack which could clobber tmp_reg. Thus, do *not* emit
12488 load and store as separate insns. Instead, we perform the copy
12489 by means of one monolithic insn. */
12490
12491 gcc_assert (TMP_REGNO == LPM_REGNO);
12492
12493 if (as != ADDR_SPACE_MEMX)
12494 {
12495 /* Load instruction ([E]LPM or LD) is known at compile time:
12496 Do the copy-loop inline. */
12497
12498 rtx (*fun) (rtx, rtx, rtx)
12499 = QImode == loop_mode ? gen_movmem_qi : gen_movmem_hi;
12500
12501 insn = fun (xas, loop_reg, loop_reg);
12502 }
12503 else
12504 {
12505 rtx (*fun) (rtx, rtx)
12506 = QImode == loop_mode ? gen_movmemx_qi : gen_movmemx_hi;
12507
12508 emit_move_insn (gen_rtx_REG (QImode, 23), a_hi8);
12509
12510 insn = fun (xas, GEN_INT (avr_addr.rampz));
12511 }
12512
12513 set_mem_addr_space (SET_SRC (XVECEXP (insn, 0, 0)), as);
12514 emit_insn (insn);
12515
12516 return true;
12517 }
12518
12519
12520 /* Print assembler for movmem_qi, movmem_hi insns...
12521 $0 : Address Space
12522 $1, $2 : Loop register
12523 Z : Source address
12524 X : Destination address
12525 */
12526
12527 const char*
avr_out_movmem(rtx_insn * insn ATTRIBUTE_UNUSED,rtx * op,int * plen)12528 avr_out_movmem (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
12529 {
12530 addr_space_t as = (addr_space_t) INTVAL (op[0]);
12531 machine_mode loop_mode = GET_MODE (op[1]);
12532 bool sbiw_p = test_hard_reg_class (ADDW_REGS, op[1]);
12533 rtx xop[3];
12534
12535 if (plen)
12536 *plen = 0;
12537
12538 xop[0] = op[0];
12539 xop[1] = op[1];
12540 xop[2] = tmp_reg_rtx;
12541
12542 /* Loop label */
12543
12544 avr_asm_len ("0:", xop, plen, 0);
12545
12546 /* Load with post-increment */
12547
12548 switch (as)
12549 {
12550 default:
12551 gcc_unreachable();
12552
12553 case ADDR_SPACE_GENERIC:
12554
12555 avr_asm_len ("ld %2,Z+", xop, plen, 1);
12556 break;
12557
12558 case ADDR_SPACE_FLASH:
12559
12560 if (AVR_HAVE_LPMX)
12561 avr_asm_len ("lpm %2,Z+", xop, plen, 1);
12562 else
12563 avr_asm_len ("lpm" CR_TAB
12564 "adiw r30,1", xop, plen, 2);
12565 break;
12566
12567 case ADDR_SPACE_FLASH1:
12568 case ADDR_SPACE_FLASH2:
12569 case ADDR_SPACE_FLASH3:
12570 case ADDR_SPACE_FLASH4:
12571 case ADDR_SPACE_FLASH5:
12572
12573 if (AVR_HAVE_ELPMX)
12574 avr_asm_len ("elpm %2,Z+", xop, plen, 1);
12575 else
12576 avr_asm_len ("elpm" CR_TAB
12577 "adiw r30,1", xop, plen, 2);
12578 break;
12579 }
12580
12581 /* Store with post-increment */
12582
12583 avr_asm_len ("st X+,%2", xop, plen, 1);
12584
12585 /* Decrement loop-counter and set Z-flag */
12586
12587 if (QImode == loop_mode)
12588 {
12589 avr_asm_len ("dec %1", xop, plen, 1);
12590 }
12591 else if (sbiw_p)
12592 {
12593 avr_asm_len ("sbiw %1,1", xop, plen, 1);
12594 }
12595 else
12596 {
12597 avr_asm_len ("subi %A1,1" CR_TAB
12598 "sbci %B1,0", xop, plen, 2);
12599 }
12600
12601 /* Loop until zero */
12602
12603 return avr_asm_len ("brne 0b", xop, plen, 1);
12604 }
12605
12606
12607
12608 /* Helper for __builtin_avr_delay_cycles */
12609
12610 static rtx
avr_mem_clobber(void)12611 avr_mem_clobber (void)
12612 {
12613 rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
12614 MEM_VOLATILE_P (mem) = 1;
12615 return mem;
12616 }
12617
12618 static void
avr_expand_delay_cycles(rtx operands0)12619 avr_expand_delay_cycles (rtx operands0)
12620 {
12621 unsigned HOST_WIDE_INT cycles = UINTVAL (operands0) & GET_MODE_MASK (SImode);
12622 unsigned HOST_WIDE_INT cycles_used;
12623 unsigned HOST_WIDE_INT loop_count;
12624
12625 if (IN_RANGE (cycles, 83886082, 0xFFFFFFFF))
12626 {
12627 loop_count = ((cycles - 9) / 6) + 1;
12628 cycles_used = ((loop_count - 1) * 6) + 9;
12629 emit_insn (gen_delay_cycles_4 (gen_int_mode (loop_count, SImode),
12630 avr_mem_clobber()));
12631 cycles -= cycles_used;
12632 }
12633
12634 if (IN_RANGE (cycles, 262145, 83886081))
12635 {
12636 loop_count = ((cycles - 7) / 5) + 1;
12637 if (loop_count > 0xFFFFFF)
12638 loop_count = 0xFFFFFF;
12639 cycles_used = ((loop_count - 1) * 5) + 7;
12640 emit_insn (gen_delay_cycles_3 (gen_int_mode (loop_count, SImode),
12641 avr_mem_clobber()));
12642 cycles -= cycles_used;
12643 }
12644
12645 if (IN_RANGE (cycles, 768, 262144))
12646 {
12647 loop_count = ((cycles - 5) / 4) + 1;
12648 if (loop_count > 0xFFFF)
12649 loop_count = 0xFFFF;
12650 cycles_used = ((loop_count - 1) * 4) + 5;
12651 emit_insn (gen_delay_cycles_2 (gen_int_mode (loop_count, HImode),
12652 avr_mem_clobber()));
12653 cycles -= cycles_used;
12654 }
12655
12656 if (IN_RANGE (cycles, 6, 767))
12657 {
12658 loop_count = cycles / 3;
12659 if (loop_count > 255)
12660 loop_count = 255;
12661 cycles_used = loop_count * 3;
12662 emit_insn (gen_delay_cycles_1 (gen_int_mode (loop_count, QImode),
12663 avr_mem_clobber()));
12664 cycles -= cycles_used;
12665 }
12666
12667 while (cycles >= 2)
12668 {
12669 emit_insn (gen_nopv (GEN_INT(2)));
12670 cycles -= 2;
12671 }
12672
12673 if (cycles == 1)
12674 {
12675 emit_insn (gen_nopv (GEN_INT(1)));
12676 cycles--;
12677 }
12678 }
12679
12680
12681 /* Compute the image of x under f, i.e. perform x --> f(x) */
12682
12683 static int
avr_map(unsigned int f,int x)12684 avr_map (unsigned int f, int x)
12685 {
12686 return x < 8 ? (f >> (4 * x)) & 0xf : 0;
12687 }
12688
12689
12690 /* Return some metrics of map A. */
12691
12692 enum
12693 {
12694 /* Number of fixed points in { 0 ... 7 } */
12695 MAP_FIXED_0_7,
12696
12697 /* Size of preimage of non-fixed points in { 0 ... 7 } */
12698 MAP_NONFIXED_0_7,
12699
12700 /* Mask representing the fixed points in { 0 ... 7 } */
12701 MAP_MASK_FIXED_0_7,
12702
12703 /* Size of the preimage of { 0 ... 7 } */
12704 MAP_PREIMAGE_0_7,
12705
12706 /* Mask that represents the preimage of { f } */
12707 MAP_MASK_PREIMAGE_F
12708 };
12709
12710 static unsigned
avr_map_metric(unsigned int a,int mode)12711 avr_map_metric (unsigned int a, int mode)
12712 {
12713 unsigned i, metric = 0;
12714
12715 for (i = 0; i < 8; i++)
12716 {
12717 unsigned ai = avr_map (a, i);
12718
12719 if (mode == MAP_FIXED_0_7)
12720 metric += ai == i;
12721 else if (mode == MAP_NONFIXED_0_7)
12722 metric += ai < 8 && ai != i;
12723 else if (mode == MAP_MASK_FIXED_0_7)
12724 metric |= ((unsigned) (ai == i)) << i;
12725 else if (mode == MAP_PREIMAGE_0_7)
12726 metric += ai < 8;
12727 else if (mode == MAP_MASK_PREIMAGE_F)
12728 metric |= ((unsigned) (ai == 0xf)) << i;
12729 else
12730 gcc_unreachable();
12731 }
12732
12733 return metric;
12734 }
12735
12736
12737 /* Return true if IVAL has a 0xf in its hexadecimal representation
12738 and false, otherwise. Only nibbles 0..7 are taken into account.
12739 Used as constraint helper for C0f and Cxf. */
12740
12741 bool
avr_has_nibble_0xf(rtx ival)12742 avr_has_nibble_0xf (rtx ival)
12743 {
12744 unsigned int map = UINTVAL (ival) & GET_MODE_MASK (SImode);
12745 return 0 != avr_map_metric (map, MAP_MASK_PREIMAGE_F);
12746 }
12747
12748
12749 /* We have a set of bits that are mapped by a function F.
12750 Try to decompose F by means of a second function G so that
12751
12752 F = F o G^-1 o G
12753
12754 and
12755
12756 cost (F o G^-1) + cost (G) < cost (F)
12757
12758 Example: Suppose builtin insert_bits supplies us with the map
12759 F = 0x3210ffff. Instead of doing 4 bit insertions to get the high
12760 nibble of the result, we can just as well rotate the bits before inserting
12761 them and use the map 0x7654ffff which is cheaper than the original map.
12762 For this example G = G^-1 = 0x32107654 and F o G^-1 = 0x7654ffff. */
12763
12764 typedef struct
12765 {
12766 /* tree code of binary function G */
12767 enum tree_code code;
12768
12769 /* The constant second argument of G */
12770 int arg;
12771
12772 /* G^-1, the inverse of G (*, arg) */
12773 unsigned ginv;
12774
12775 /* The cost of appplying G (*, arg) */
12776 int cost;
12777
12778 /* The composition F o G^-1 (*, arg) for some function F */
12779 unsigned int map;
12780
12781 /* For debug purpose only */
12782 const char *str;
12783 } avr_map_op_t;
12784
12785 static const avr_map_op_t avr_map_op[] =
12786 {
12787 { LROTATE_EXPR, 0, 0x76543210, 0, 0, "id" },
12788 { LROTATE_EXPR, 1, 0x07654321, 2, 0, "<<<" },
12789 { LROTATE_EXPR, 2, 0x10765432, 4, 0, "<<<" },
12790 { LROTATE_EXPR, 3, 0x21076543, 4, 0, "<<<" },
12791 { LROTATE_EXPR, 4, 0x32107654, 1, 0, "<<<" },
12792 { LROTATE_EXPR, 5, 0x43210765, 3, 0, "<<<" },
12793 { LROTATE_EXPR, 6, 0x54321076, 5, 0, "<<<" },
12794 { LROTATE_EXPR, 7, 0x65432107, 3, 0, "<<<" },
12795 { RSHIFT_EXPR, 1, 0x6543210c, 1, 0, ">>" },
12796 { RSHIFT_EXPR, 1, 0x7543210c, 1, 0, ">>" },
12797 { RSHIFT_EXPR, 2, 0x543210cc, 2, 0, ">>" },
12798 { RSHIFT_EXPR, 2, 0x643210cc, 2, 0, ">>" },
12799 { RSHIFT_EXPR, 2, 0x743210cc, 2, 0, ">>" },
12800 { LSHIFT_EXPR, 1, 0xc7654321, 1, 0, "<<" },
12801 { LSHIFT_EXPR, 2, 0xcc765432, 2, 0, "<<" }
12802 };
12803
12804
12805 /* Try to decompose F as F = (F o G^-1) o G as described above.
12806 The result is a struct representing F o G^-1 and G.
12807 If result.cost < 0 then such a decomposition does not exist. */
12808
12809 static avr_map_op_t
avr_map_decompose(unsigned int f,const avr_map_op_t * g,bool val_const_p)12810 avr_map_decompose (unsigned int f, const avr_map_op_t *g, bool val_const_p)
12811 {
12812 int i;
12813 bool val_used_p = 0 != avr_map_metric (f, MAP_MASK_PREIMAGE_F);
12814 avr_map_op_t f_ginv = *g;
12815 unsigned int ginv = g->ginv;
12816
12817 f_ginv.cost = -1;
12818
12819 /* Step 1: Computing F o G^-1 */
12820
12821 for (i = 7; i >= 0; i--)
12822 {
12823 int x = avr_map (f, i);
12824
12825 if (x <= 7)
12826 {
12827 x = avr_map (ginv, x);
12828
12829 /* The bit is no element of the image of G: no avail (cost = -1) */
12830
12831 if (x > 7)
12832 return f_ginv;
12833 }
12834
12835 f_ginv.map = (f_ginv.map << 4) + x;
12836 }
12837
12838 /* Step 2: Compute the cost of the operations.
12839 The overall cost of doing an operation prior to the insertion is
12840 the cost of the insertion plus the cost of the operation. */
12841
12842 /* Step 2a: Compute cost of F o G^-1 */
12843
12844 if (0 == avr_map_metric (f_ginv.map, MAP_NONFIXED_0_7))
12845 {
12846 /* The mapping consists only of fixed points and can be folded
12847 to AND/OR logic in the remainder. Reasonable cost is 3. */
12848
12849 f_ginv.cost = 2 + (val_used_p && !val_const_p);
12850 }
12851 else
12852 {
12853 rtx xop[4];
12854
12855 /* Get the cost of the insn by calling the output worker with some
12856 fake values. Mimic effect of reloading xop[3]: Unused operands
12857 are mapped to 0 and used operands are reloaded to xop[0]. */
12858
12859 xop[0] = all_regs_rtx[24];
12860 xop[1] = gen_int_mode (f_ginv.map, SImode);
12861 xop[2] = all_regs_rtx[25];
12862 xop[3] = val_used_p ? xop[0] : const0_rtx;
12863
12864 avr_out_insert_bits (xop, &f_ginv.cost);
12865
12866 f_ginv.cost += val_const_p && val_used_p ? 1 : 0;
12867 }
12868
12869 /* Step 2b: Add cost of G */
12870
12871 f_ginv.cost += g->cost;
12872
12873 if (avr_log.builtin)
12874 avr_edump (" %s%d=%d", g->str, g->arg, f_ginv.cost);
12875
12876 return f_ginv;
12877 }
12878
12879
12880 /* Insert bits from XOP[1] into XOP[0] according to MAP.
12881 XOP[0] and XOP[1] don't overlap.
12882 If FIXP_P = true: Move all bits according to MAP using BLD/BST sequences.
12883 If FIXP_P = false: Just move the bit if its position in the destination
12884 is different to its source position. */
12885
12886 static void
avr_move_bits(rtx * xop,unsigned int map,bool fixp_p,int * plen)12887 avr_move_bits (rtx *xop, unsigned int map, bool fixp_p, int *plen)
12888 {
12889 int bit_dest, b;
12890
12891 /* T-flag contains this bit of the source, i.e. of XOP[1] */
12892 int t_bit_src = -1;
12893
12894 /* We order the operations according to the requested source bit b. */
12895
12896 for (b = 0; b < 8; b++)
12897 for (bit_dest = 0; bit_dest < 8; bit_dest++)
12898 {
12899 int bit_src = avr_map (map, bit_dest);
12900
12901 if (b != bit_src
12902 || bit_src >= 8
12903 /* Same position: No need to copy as requested by FIXP_P. */
12904 || (bit_dest == bit_src && !fixp_p))
12905 continue;
12906
12907 if (t_bit_src != bit_src)
12908 {
12909 /* Source bit is not yet in T: Store it to T. */
12910
12911 t_bit_src = bit_src;
12912
12913 xop[3] = GEN_INT (bit_src);
12914 avr_asm_len ("bst %T1%T3", xop, plen, 1);
12915 }
12916
12917 /* Load destination bit with T. */
12918
12919 xop[3] = GEN_INT (bit_dest);
12920 avr_asm_len ("bld %T0%T3", xop, plen, 1);
12921 }
12922 }
12923
12924
12925 /* PLEN == 0: Print assembler code for `insert_bits'.
12926 PLEN != 0: Compute code length in bytes.
12927
12928 OP[0]: Result
12929 OP[1]: The mapping composed of nibbles. If nibble no. N is
12930 0: Bit N of result is copied from bit OP[2].0
12931 ... ...
12932 7: Bit N of result is copied from bit OP[2].7
12933 0xf: Bit N of result is copied from bit OP[3].N
12934 OP[2]: Bits to be inserted
12935 OP[3]: Target value */
12936
12937 const char*
avr_out_insert_bits(rtx * op,int * plen)12938 avr_out_insert_bits (rtx *op, int *plen)
12939 {
12940 unsigned int map = UINTVAL (op[1]) & GET_MODE_MASK (SImode);
12941 unsigned mask_fixed;
12942 bool fixp_p = true;
12943 rtx xop[4];
12944
12945 xop[0] = op[0];
12946 xop[1] = op[2];
12947 xop[2] = op[3];
12948
12949 gcc_assert (REG_P (xop[2]) || CONST_INT_P (xop[2]));
12950
12951 if (plen)
12952 *plen = 0;
12953 else if (flag_print_asm_name)
12954 fprintf (asm_out_file, ASM_COMMENT_START "map = 0x%08x\n", map);
12955
12956 /* If MAP has fixed points it might be better to initialize the result
12957 with the bits to be inserted instead of moving all bits by hand. */
12958
12959 mask_fixed = avr_map_metric (map, MAP_MASK_FIXED_0_7);
12960
12961 if (REGNO (xop[0]) == REGNO (xop[1]))
12962 {
12963 /* Avoid early-clobber conflicts */
12964
12965 avr_asm_len ("mov __tmp_reg__,%1", xop, plen, 1);
12966 xop[1] = tmp_reg_rtx;
12967 fixp_p = false;
12968 }
12969
12970 if (avr_map_metric (map, MAP_MASK_PREIMAGE_F))
12971 {
12972 /* XOP[2] is used and reloaded to XOP[0] already */
12973
12974 int n_fix = 0, n_nofix = 0;
12975
12976 gcc_assert (REG_P (xop[2]));
12977
12978 /* Get the code size of the bit insertions; once with all bits
12979 moved and once with fixed points omitted. */
12980
12981 avr_move_bits (xop, map, true, &n_fix);
12982 avr_move_bits (xop, map, false, &n_nofix);
12983
12984 if (fixp_p && n_fix - n_nofix > 3)
12985 {
12986 xop[3] = gen_int_mode (~mask_fixed, QImode);
12987
12988 avr_asm_len ("eor %0,%1" CR_TAB
12989 "andi %0,%3" CR_TAB
12990 "eor %0,%1", xop, plen, 3);
12991 fixp_p = false;
12992 }
12993 }
12994 else
12995 {
12996 /* XOP[2] is unused */
12997
12998 if (fixp_p && mask_fixed)
12999 {
13000 avr_asm_len ("mov %0,%1", xop, plen, 1);
13001 fixp_p = false;
13002 }
13003 }
13004
13005 /* Move/insert remaining bits. */
13006
13007 avr_move_bits (xop, map, fixp_p, plen);
13008
13009 return "";
13010 }
13011
13012
13013 /* IDs for all the AVR builtins. */
13014
13015 enum avr_builtin_id
13016 {
13017 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
13018 AVR_BUILTIN_ ## NAME,
13019 #include "builtins.def"
13020 #undef DEF_BUILTIN
13021
13022 AVR_BUILTIN_COUNT
13023 };
13024
13025 struct GTY(()) avr_builtin_description
13026 {
13027 enum insn_code icode;
13028 int n_args;
13029 tree fndecl;
13030 };
13031
13032
13033 /* Notice that avr_bdesc[] and avr_builtin_id are initialized in such a way
13034 that a built-in's ID can be used to access the built-in by means of
13035 avr_bdesc[ID] */
13036
13037 static GTY(()) struct avr_builtin_description
13038 avr_bdesc[AVR_BUILTIN_COUNT] =
13039 {
13040 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE, LIBNAME) \
13041 { (enum insn_code) CODE_FOR_ ## ICODE, N_ARGS, NULL_TREE },
13042 #include "builtins.def"
13043 #undef DEF_BUILTIN
13044 };
13045
13046
13047 /* Implement `TARGET_BUILTIN_DECL'. */
13048
13049 static tree
avr_builtin_decl(unsigned id,bool initialize_p ATTRIBUTE_UNUSED)13050 avr_builtin_decl (unsigned id, bool initialize_p ATTRIBUTE_UNUSED)
13051 {
13052 if (id < AVR_BUILTIN_COUNT)
13053 return avr_bdesc[id].fndecl;
13054
13055 return error_mark_node;
13056 }
13057
13058
13059 static void
avr_init_builtin_int24(void)13060 avr_init_builtin_int24 (void)
13061 {
13062 tree int24_type = make_signed_type (GET_MODE_BITSIZE (PSImode));
13063 tree uint24_type = make_unsigned_type (GET_MODE_BITSIZE (PSImode));
13064
13065 lang_hooks.types.register_builtin_type (int24_type, "__int24");
13066 lang_hooks.types.register_builtin_type (uint24_type, "__uint24");
13067 }
13068
13069
13070 /* Implement `TARGET_INIT_BUILTINS' */
13071 /* Set up all builtin functions for this target. */
13072
13073 static void
avr_init_builtins(void)13074 avr_init_builtins (void)
13075 {
13076 tree void_ftype_void
13077 = build_function_type_list (void_type_node, NULL_TREE);
13078 tree uchar_ftype_uchar
13079 = build_function_type_list (unsigned_char_type_node,
13080 unsigned_char_type_node,
13081 NULL_TREE);
13082 tree uint_ftype_uchar_uchar
13083 = build_function_type_list (unsigned_type_node,
13084 unsigned_char_type_node,
13085 unsigned_char_type_node,
13086 NULL_TREE);
13087 tree int_ftype_char_char
13088 = build_function_type_list (integer_type_node,
13089 char_type_node,
13090 char_type_node,
13091 NULL_TREE);
13092 tree int_ftype_char_uchar
13093 = build_function_type_list (integer_type_node,
13094 char_type_node,
13095 unsigned_char_type_node,
13096 NULL_TREE);
13097 tree void_ftype_ulong
13098 = build_function_type_list (void_type_node,
13099 long_unsigned_type_node,
13100 NULL_TREE);
13101
13102 tree uchar_ftype_ulong_uchar_uchar
13103 = build_function_type_list (unsigned_char_type_node,
13104 long_unsigned_type_node,
13105 unsigned_char_type_node,
13106 unsigned_char_type_node,
13107 NULL_TREE);
13108
13109 tree const_memx_void_node
13110 = build_qualified_type (void_type_node,
13111 TYPE_QUAL_CONST
13112 | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_MEMX));
13113
13114 tree const_memx_ptr_type_node
13115 = build_pointer_type_for_mode (const_memx_void_node, PSImode, false);
13116
13117 tree char_ftype_const_memx_ptr
13118 = build_function_type_list (char_type_node,
13119 const_memx_ptr_type_node,
13120 NULL);
13121
13122 #define ITYP(T) \
13123 lang_hooks.types.type_for_size (TYPE_PRECISION (T), TYPE_UNSIGNED (T))
13124
13125 #define FX_FTYPE_FX(fx) \
13126 tree fx##r_ftype_##fx##r \
13127 = build_function_type_list (node_##fx##r, node_##fx##r, NULL); \
13128 tree fx##k_ftype_##fx##k \
13129 = build_function_type_list (node_##fx##k, node_##fx##k, NULL)
13130
13131 #define FX_FTYPE_FX_INT(fx) \
13132 tree fx##r_ftype_##fx##r_int \
13133 = build_function_type_list (node_##fx##r, node_##fx##r, \
13134 integer_type_node, NULL); \
13135 tree fx##k_ftype_##fx##k_int \
13136 = build_function_type_list (node_##fx##k, node_##fx##k, \
13137 integer_type_node, NULL)
13138
13139 #define INT_FTYPE_FX(fx) \
13140 tree int_ftype_##fx##r \
13141 = build_function_type_list (integer_type_node, node_##fx##r, NULL); \
13142 tree int_ftype_##fx##k \
13143 = build_function_type_list (integer_type_node, node_##fx##k, NULL)
13144
13145 #define INTX_FTYPE_FX(fx) \
13146 tree int##fx##r_ftype_##fx##r \
13147 = build_function_type_list (ITYP (node_##fx##r), node_##fx##r, NULL); \
13148 tree int##fx##k_ftype_##fx##k \
13149 = build_function_type_list (ITYP (node_##fx##k), node_##fx##k, NULL)
13150
13151 #define FX_FTYPE_INTX(fx) \
13152 tree fx##r_ftype_int##fx##r \
13153 = build_function_type_list (node_##fx##r, ITYP (node_##fx##r), NULL); \
13154 tree fx##k_ftype_int##fx##k \
13155 = build_function_type_list (node_##fx##k, ITYP (node_##fx##k), NULL)
13156
13157 tree node_hr = short_fract_type_node;
13158 tree node_nr = fract_type_node;
13159 tree node_lr = long_fract_type_node;
13160 tree node_llr = long_long_fract_type_node;
13161
13162 tree node_uhr = unsigned_short_fract_type_node;
13163 tree node_unr = unsigned_fract_type_node;
13164 tree node_ulr = unsigned_long_fract_type_node;
13165 tree node_ullr = unsigned_long_long_fract_type_node;
13166
13167 tree node_hk = short_accum_type_node;
13168 tree node_nk = accum_type_node;
13169 tree node_lk = long_accum_type_node;
13170 tree node_llk = long_long_accum_type_node;
13171
13172 tree node_uhk = unsigned_short_accum_type_node;
13173 tree node_unk = unsigned_accum_type_node;
13174 tree node_ulk = unsigned_long_accum_type_node;
13175 tree node_ullk = unsigned_long_long_accum_type_node;
13176
13177
13178 /* For absfx builtins. */
13179
13180 FX_FTYPE_FX (h);
13181 FX_FTYPE_FX (n);
13182 FX_FTYPE_FX (l);
13183 FX_FTYPE_FX (ll);
13184
13185 /* For roundfx builtins. */
13186
13187 FX_FTYPE_FX_INT (h);
13188 FX_FTYPE_FX_INT (n);
13189 FX_FTYPE_FX_INT (l);
13190 FX_FTYPE_FX_INT (ll);
13191
13192 FX_FTYPE_FX_INT (uh);
13193 FX_FTYPE_FX_INT (un);
13194 FX_FTYPE_FX_INT (ul);
13195 FX_FTYPE_FX_INT (ull);
13196
13197 /* For countlsfx builtins. */
13198
13199 INT_FTYPE_FX (h);
13200 INT_FTYPE_FX (n);
13201 INT_FTYPE_FX (l);
13202 INT_FTYPE_FX (ll);
13203
13204 INT_FTYPE_FX (uh);
13205 INT_FTYPE_FX (un);
13206 INT_FTYPE_FX (ul);
13207 INT_FTYPE_FX (ull);
13208
13209 /* For bitsfx builtins. */
13210
13211 INTX_FTYPE_FX (h);
13212 INTX_FTYPE_FX (n);
13213 INTX_FTYPE_FX (l);
13214 INTX_FTYPE_FX (ll);
13215
13216 INTX_FTYPE_FX (uh);
13217 INTX_FTYPE_FX (un);
13218 INTX_FTYPE_FX (ul);
13219 INTX_FTYPE_FX (ull);
13220
13221 /* For fxbits builtins. */
13222
13223 FX_FTYPE_INTX (h);
13224 FX_FTYPE_INTX (n);
13225 FX_FTYPE_INTX (l);
13226 FX_FTYPE_INTX (ll);
13227
13228 FX_FTYPE_INTX (uh);
13229 FX_FTYPE_INTX (un);
13230 FX_FTYPE_INTX (ul);
13231 FX_FTYPE_INTX (ull);
13232
13233
13234 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
13235 { \
13236 int id = AVR_BUILTIN_ ## NAME; \
13237 const char *Name = "__builtin_avr_" #NAME; \
13238 char *name = (char*) alloca (1 + strlen (Name)); \
13239 \
13240 gcc_assert (id < AVR_BUILTIN_COUNT); \
13241 avr_bdesc[id].fndecl \
13242 = add_builtin_function (avr_tolower (name, Name), TYPE, id, \
13243 BUILT_IN_MD, LIBNAME, NULL_TREE); \
13244 }
13245 #include "builtins.def"
13246 #undef DEF_BUILTIN
13247
13248 avr_init_builtin_int24 ();
13249 }
13250
13251
13252 /* Subroutine of avr_expand_builtin to expand vanilla builtins
13253 with non-void result and 1 ... 3 arguments. */
13254
13255 static rtx
avr_default_expand_builtin(enum insn_code icode,tree exp,rtx target)13256 avr_default_expand_builtin (enum insn_code icode, tree exp, rtx target)
13257 {
13258 rtx pat, xop[3];
13259 int n, n_args = call_expr_nargs (exp);
13260 machine_mode tmode = insn_data[icode].operand[0].mode;
13261
13262 gcc_assert (n_args >= 1 && n_args <= 3);
13263
13264 if (target == NULL_RTX
13265 || GET_MODE (target) != tmode
13266 || !insn_data[icode].operand[0].predicate (target, tmode))
13267 {
13268 target = gen_reg_rtx (tmode);
13269 }
13270
13271 for (n = 0; n < n_args; n++)
13272 {
13273 tree arg = CALL_EXPR_ARG (exp, n);
13274 rtx op = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
13275 machine_mode opmode = GET_MODE (op);
13276 machine_mode mode = insn_data[icode].operand[n+1].mode;
13277
13278 if ((opmode == SImode || opmode == VOIDmode) && mode == HImode)
13279 {
13280 opmode = HImode;
13281 op = gen_lowpart (HImode, op);
13282 }
13283
13284 /* In case the insn wants input operands in modes different from
13285 the result, abort. */
13286
13287 gcc_assert (opmode == mode || opmode == VOIDmode);
13288
13289 if (!insn_data[icode].operand[n+1].predicate (op, mode))
13290 op = copy_to_mode_reg (mode, op);
13291
13292 xop[n] = op;
13293 }
13294
13295 switch (n_args)
13296 {
13297 case 1: pat = GEN_FCN (icode) (target, xop[0]); break;
13298 case 2: pat = GEN_FCN (icode) (target, xop[0], xop[1]); break;
13299 case 3: pat = GEN_FCN (icode) (target, xop[0], xop[1], xop[2]); break;
13300
13301 default:
13302 gcc_unreachable();
13303 }
13304
13305 if (pat == NULL_RTX)
13306 return NULL_RTX;
13307
13308 emit_insn (pat);
13309
13310 return target;
13311 }
13312
13313
13314 /* Implement `TARGET_EXPAND_BUILTIN'. */
13315 /* Expand an expression EXP that calls a built-in function,
13316 with result going to TARGET if that's convenient
13317 (and in mode MODE if that's convenient).
13318 SUBTARGET may be used as the target for computing one of EXP's operands.
13319 IGNORE is nonzero if the value is to be ignored. */
13320
13321 static rtx
avr_expand_builtin(tree exp,rtx target,rtx subtarget ATTRIBUTE_UNUSED,machine_mode mode ATTRIBUTE_UNUSED,int ignore)13322 avr_expand_builtin (tree exp, rtx target,
13323 rtx subtarget ATTRIBUTE_UNUSED,
13324 machine_mode mode ATTRIBUTE_UNUSED,
13325 int ignore)
13326 {
13327 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
13328 const char *bname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
13329 unsigned int id = DECL_FUNCTION_CODE (fndecl);
13330 const struct avr_builtin_description *d = &avr_bdesc[id];
13331 tree arg0;
13332 rtx op0;
13333
13334 gcc_assert (id < AVR_BUILTIN_COUNT);
13335
13336 switch (id)
13337 {
13338 case AVR_BUILTIN_NOP:
13339 emit_insn (gen_nopv (GEN_INT(1)));
13340 return 0;
13341
13342 case AVR_BUILTIN_DELAY_CYCLES:
13343 {
13344 arg0 = CALL_EXPR_ARG (exp, 0);
13345 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
13346
13347 if (!CONST_INT_P (op0))
13348 error ("%s expects a compile time integer constant", bname);
13349 else
13350 avr_expand_delay_cycles (op0);
13351
13352 return NULL_RTX;
13353 }
13354
13355 case AVR_BUILTIN_INSERT_BITS:
13356 {
13357 arg0 = CALL_EXPR_ARG (exp, 0);
13358 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
13359
13360 if (!CONST_INT_P (op0))
13361 {
13362 error ("%s expects a compile time long integer constant"
13363 " as first argument", bname);
13364 return target;
13365 }
13366
13367 break;
13368 }
13369
13370 case AVR_BUILTIN_ROUNDHR: case AVR_BUILTIN_ROUNDUHR:
13371 case AVR_BUILTIN_ROUNDR: case AVR_BUILTIN_ROUNDUR:
13372 case AVR_BUILTIN_ROUNDLR: case AVR_BUILTIN_ROUNDULR:
13373 case AVR_BUILTIN_ROUNDLLR: case AVR_BUILTIN_ROUNDULLR:
13374
13375 case AVR_BUILTIN_ROUNDHK: case AVR_BUILTIN_ROUNDUHK:
13376 case AVR_BUILTIN_ROUNDK: case AVR_BUILTIN_ROUNDUK:
13377 case AVR_BUILTIN_ROUNDLK: case AVR_BUILTIN_ROUNDULK:
13378 case AVR_BUILTIN_ROUNDLLK: case AVR_BUILTIN_ROUNDULLK:
13379
13380 /* Warn about odd rounding. Rounding points >= FBIT will have
13381 no effect. */
13382
13383 if (TREE_CODE (CALL_EXPR_ARG (exp, 1)) != INTEGER_CST)
13384 break;
13385
13386 int rbit = (int) TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1));
13387
13388 if (rbit >= (int) GET_MODE_FBIT (mode))
13389 {
13390 warning (OPT_Wextra, "rounding to %d bits has no effect for "
13391 "fixed-point value with %d fractional bits",
13392 rbit, GET_MODE_FBIT (mode));
13393
13394 return expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX, mode,
13395 EXPAND_NORMAL);
13396 }
13397 else if (rbit <= - (int) GET_MODE_IBIT (mode))
13398 {
13399 warning (0, "rounding result will always be 0");
13400 return CONST0_RTX (mode);
13401 }
13402
13403 /* The rounding points RP satisfies now: -IBIT < RP < FBIT.
13404
13405 TR 18037 only specifies results for RP > 0. However, the
13406 remaining cases of -IBIT < RP <= 0 can easily be supported
13407 without any additional overhead. */
13408
13409 break; /* round */
13410 }
13411
13412 /* No fold found and no insn: Call support function from libgcc. */
13413
13414 if (d->icode == CODE_FOR_nothing
13415 && DECL_ASSEMBLER_NAME (get_callee_fndecl (exp)) != NULL_TREE)
13416 {
13417 return expand_call (exp, target, ignore);
13418 }
13419
13420 /* No special treatment needed: vanilla expand. */
13421
13422 gcc_assert (d->icode != CODE_FOR_nothing);
13423 gcc_assert (d->n_args == call_expr_nargs (exp));
13424
13425 if (d->n_args == 0)
13426 {
13427 emit_insn ((GEN_FCN (d->icode)) (target));
13428 return NULL_RTX;
13429 }
13430
13431 return avr_default_expand_builtin (d->icode, exp, target);
13432 }
13433
13434
13435 /* Helper for `avr_fold_builtin' that folds absfx (FIXED_CST). */
13436
13437 static tree
avr_fold_absfx(tree tval)13438 avr_fold_absfx (tree tval)
13439 {
13440 if (FIXED_CST != TREE_CODE (tval))
13441 return NULL_TREE;
13442
13443 /* Our fixed-points have no padding: Use double_int payload directly. */
13444
13445 FIXED_VALUE_TYPE fval = TREE_FIXED_CST (tval);
13446 unsigned int bits = GET_MODE_BITSIZE (fval.mode);
13447 double_int ival = fval.data.sext (bits);
13448
13449 if (!ival.is_negative())
13450 return tval;
13451
13452 /* ISO/IEC TR 18037, 7.18a.6.2: The absfx functions are saturating. */
13453
13454 fval.data = (ival == double_int::min_value (bits, false).sext (bits))
13455 ? double_int::max_value (bits, false)
13456 : -ival;
13457
13458 return build_fixed (TREE_TYPE (tval), fval);
13459 }
13460
13461
13462 /* Implement `TARGET_FOLD_BUILTIN'. */
13463
13464 static tree
avr_fold_builtin(tree fndecl,int n_args ATTRIBUTE_UNUSED,tree * arg,bool ignore ATTRIBUTE_UNUSED)13465 avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg,
13466 bool ignore ATTRIBUTE_UNUSED)
13467 {
13468 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
13469 tree val_type = TREE_TYPE (TREE_TYPE (fndecl));
13470
13471 if (!optimize)
13472 return NULL_TREE;
13473
13474 switch (fcode)
13475 {
13476 default:
13477 break;
13478
13479 case AVR_BUILTIN_SWAP:
13480 {
13481 return fold_build2 (LROTATE_EXPR, val_type, arg[0],
13482 build_int_cst (val_type, 4));
13483 }
13484
13485 case AVR_BUILTIN_ABSHR:
13486 case AVR_BUILTIN_ABSR:
13487 case AVR_BUILTIN_ABSLR:
13488 case AVR_BUILTIN_ABSLLR:
13489
13490 case AVR_BUILTIN_ABSHK:
13491 case AVR_BUILTIN_ABSK:
13492 case AVR_BUILTIN_ABSLK:
13493 case AVR_BUILTIN_ABSLLK:
13494 /* GCC is not good with folding ABS for fixed-point. Do it by hand. */
13495
13496 return avr_fold_absfx (arg[0]);
13497
13498 case AVR_BUILTIN_BITSHR: case AVR_BUILTIN_HRBITS:
13499 case AVR_BUILTIN_BITSHK: case AVR_BUILTIN_HKBITS:
13500 case AVR_BUILTIN_BITSUHR: case AVR_BUILTIN_UHRBITS:
13501 case AVR_BUILTIN_BITSUHK: case AVR_BUILTIN_UHKBITS:
13502
13503 case AVR_BUILTIN_BITSR: case AVR_BUILTIN_RBITS:
13504 case AVR_BUILTIN_BITSK: case AVR_BUILTIN_KBITS:
13505 case AVR_BUILTIN_BITSUR: case AVR_BUILTIN_URBITS:
13506 case AVR_BUILTIN_BITSUK: case AVR_BUILTIN_UKBITS:
13507
13508 case AVR_BUILTIN_BITSLR: case AVR_BUILTIN_LRBITS:
13509 case AVR_BUILTIN_BITSLK: case AVR_BUILTIN_LKBITS:
13510 case AVR_BUILTIN_BITSULR: case AVR_BUILTIN_ULRBITS:
13511 case AVR_BUILTIN_BITSULK: case AVR_BUILTIN_ULKBITS:
13512
13513 case AVR_BUILTIN_BITSLLR: case AVR_BUILTIN_LLRBITS:
13514 case AVR_BUILTIN_BITSLLK: case AVR_BUILTIN_LLKBITS:
13515 case AVR_BUILTIN_BITSULLR: case AVR_BUILTIN_ULLRBITS:
13516 case AVR_BUILTIN_BITSULLK: case AVR_BUILTIN_ULLKBITS:
13517
13518 gcc_assert (TYPE_PRECISION (val_type)
13519 == TYPE_PRECISION (TREE_TYPE (arg[0])));
13520
13521 return build1 (VIEW_CONVERT_EXPR, val_type, arg[0]);
13522
13523 case AVR_BUILTIN_INSERT_BITS:
13524 {
13525 tree tbits = arg[1];
13526 tree tval = arg[2];
13527 tree tmap;
13528 tree map_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
13529 unsigned int map;
13530 bool changed = false;
13531 unsigned i;
13532 avr_map_op_t best_g;
13533
13534 if (TREE_CODE (arg[0]) != INTEGER_CST)
13535 {
13536 /* No constant as first argument: Don't fold this and run into
13537 error in avr_expand_builtin. */
13538
13539 break;
13540 }
13541
13542 tmap = wide_int_to_tree (map_type, arg[0]);
13543 map = TREE_INT_CST_LOW (tmap);
13544
13545 if (TREE_CODE (tval) != INTEGER_CST
13546 && 0 == avr_map_metric (map, MAP_MASK_PREIMAGE_F))
13547 {
13548 /* There are no F in the map, i.e. 3rd operand is unused.
13549 Replace that argument with some constant to render
13550 respective input unused. */
13551
13552 tval = build_int_cst (val_type, 0);
13553 changed = true;
13554 }
13555
13556 if (TREE_CODE (tbits) != INTEGER_CST
13557 && 0 == avr_map_metric (map, MAP_PREIMAGE_0_7))
13558 {
13559 /* Similar for the bits to be inserted. If they are unused,
13560 we can just as well pass 0. */
13561
13562 tbits = build_int_cst (val_type, 0);
13563 }
13564
13565 if (TREE_CODE (tbits) == INTEGER_CST)
13566 {
13567 /* Inserting bits known at compile time is easy and can be
13568 performed by AND and OR with appropriate masks. */
13569
13570 int bits = TREE_INT_CST_LOW (tbits);
13571 int mask_ior = 0, mask_and = 0xff;
13572
13573 for (i = 0; i < 8; i++)
13574 {
13575 int mi = avr_map (map, i);
13576
13577 if (mi < 8)
13578 {
13579 if (bits & (1 << mi)) mask_ior |= (1 << i);
13580 else mask_and &= ~(1 << i);
13581 }
13582 }
13583
13584 tval = fold_build2 (BIT_IOR_EXPR, val_type, tval,
13585 build_int_cst (val_type, mask_ior));
13586 return fold_build2 (BIT_AND_EXPR, val_type, tval,
13587 build_int_cst (val_type, mask_and));
13588 }
13589
13590 if (changed)
13591 return build_call_expr (fndecl, 3, tmap, tbits, tval);
13592
13593 /* If bits don't change their position we can use vanilla logic
13594 to merge the two arguments. */
13595
13596 if (0 == avr_map_metric (map, MAP_NONFIXED_0_7))
13597 {
13598 int mask_f = avr_map_metric (map, MAP_MASK_PREIMAGE_F);
13599 tree tres, tmask = build_int_cst (val_type, mask_f ^ 0xff);
13600
13601 tres = fold_build2 (BIT_XOR_EXPR, val_type, tbits, tval);
13602 tres = fold_build2 (BIT_AND_EXPR, val_type, tres, tmask);
13603 return fold_build2 (BIT_XOR_EXPR, val_type, tres, tval);
13604 }
13605
13606 /* Try to decomposing map to reduce overall cost. */
13607
13608 if (avr_log.builtin)
13609 avr_edump ("\n%?: %x\n%?: ROL cost: ", map);
13610
13611 best_g = avr_map_op[0];
13612 best_g.cost = 1000;
13613
13614 for (i = 0; i < sizeof (avr_map_op) / sizeof (*avr_map_op); i++)
13615 {
13616 avr_map_op_t g
13617 = avr_map_decompose (map, avr_map_op + i,
13618 TREE_CODE (tval) == INTEGER_CST);
13619
13620 if (g.cost >= 0 && g.cost < best_g.cost)
13621 best_g = g;
13622 }
13623
13624 if (avr_log.builtin)
13625 avr_edump ("\n");
13626
13627 if (best_g.arg == 0)
13628 /* No optimization found */
13629 break;
13630
13631 /* Apply operation G to the 2nd argument. */
13632
13633 if (avr_log.builtin)
13634 avr_edump ("%?: using OP(%s%d, %x) cost %d\n",
13635 best_g.str, best_g.arg, best_g.map, best_g.cost);
13636
13637 /* Do right-shifts arithmetically: They copy the MSB instead of
13638 shifting in a non-usable value (0) as with logic right-shift. */
13639
13640 tbits = fold_convert (signed_char_type_node, tbits);
13641 tbits = fold_build2 (best_g.code, signed_char_type_node, tbits,
13642 build_int_cst (val_type, best_g.arg));
13643 tbits = fold_convert (val_type, tbits);
13644
13645 /* Use map o G^-1 instead of original map to undo the effect of G. */
13646
13647 tmap = wide_int_to_tree (map_type, best_g.map);
13648
13649 return build_call_expr (fndecl, 3, tmap, tbits, tval);
13650 } /* AVR_BUILTIN_INSERT_BITS */
13651 }
13652
13653 return NULL_TREE;
13654 }
13655
13656
13657
13658 /* Initialize the GCC target structure. */
13659
13660 #undef TARGET_ASM_ALIGNED_HI_OP
13661 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
13662 #undef TARGET_ASM_ALIGNED_SI_OP
13663 #define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
13664 #undef TARGET_ASM_UNALIGNED_HI_OP
13665 #define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
13666 #undef TARGET_ASM_UNALIGNED_SI_OP
13667 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
13668 #undef TARGET_ASM_INTEGER
13669 #define TARGET_ASM_INTEGER avr_assemble_integer
13670 #undef TARGET_ASM_FILE_START
13671 #define TARGET_ASM_FILE_START avr_file_start
13672 #undef TARGET_ASM_FILE_END
13673 #define TARGET_ASM_FILE_END avr_file_end
13674
13675 #undef TARGET_ASM_FUNCTION_END_PROLOGUE
13676 #define TARGET_ASM_FUNCTION_END_PROLOGUE avr_asm_function_end_prologue
13677 #undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
13678 #define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE avr_asm_function_begin_epilogue
13679
13680 #undef TARGET_FUNCTION_VALUE
13681 #define TARGET_FUNCTION_VALUE avr_function_value
13682 #undef TARGET_LIBCALL_VALUE
13683 #define TARGET_LIBCALL_VALUE avr_libcall_value
13684 #undef TARGET_FUNCTION_VALUE_REGNO_P
13685 #define TARGET_FUNCTION_VALUE_REGNO_P avr_function_value_regno_p
13686
13687 #undef TARGET_ATTRIBUTE_TABLE
13688 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
13689 #undef TARGET_INSERT_ATTRIBUTES
13690 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
13691 #undef TARGET_SECTION_TYPE_FLAGS
13692 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
13693
13694 #undef TARGET_ASM_NAMED_SECTION
13695 #define TARGET_ASM_NAMED_SECTION avr_asm_named_section
13696 #undef TARGET_ASM_INIT_SECTIONS
13697 #define TARGET_ASM_INIT_SECTIONS avr_asm_init_sections
13698 #undef TARGET_ENCODE_SECTION_INFO
13699 #define TARGET_ENCODE_SECTION_INFO avr_encode_section_info
13700 #undef TARGET_ASM_SELECT_SECTION
13701 #define TARGET_ASM_SELECT_SECTION avr_asm_select_section
13702
13703 #undef TARGET_REGISTER_MOVE_COST
13704 #define TARGET_REGISTER_MOVE_COST avr_register_move_cost
13705 #undef TARGET_MEMORY_MOVE_COST
13706 #define TARGET_MEMORY_MOVE_COST avr_memory_move_cost
13707 #undef TARGET_RTX_COSTS
13708 #define TARGET_RTX_COSTS avr_rtx_costs
13709 #undef TARGET_ADDRESS_COST
13710 #define TARGET_ADDRESS_COST avr_address_cost
13711 #undef TARGET_MACHINE_DEPENDENT_REORG
13712 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
13713 #undef TARGET_FUNCTION_ARG
13714 #define TARGET_FUNCTION_ARG avr_function_arg
13715 #undef TARGET_FUNCTION_ARG_ADVANCE
13716 #define TARGET_FUNCTION_ARG_ADVANCE avr_function_arg_advance
13717
13718 #undef TARGET_SET_CURRENT_FUNCTION
13719 #define TARGET_SET_CURRENT_FUNCTION avr_set_current_function
13720
13721 #undef TARGET_RETURN_IN_MEMORY
13722 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
13723
13724 #undef TARGET_STRICT_ARGUMENT_NAMING
13725 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
13726
13727 #undef TARGET_BUILTIN_SETJMP_FRAME_VALUE
13728 #define TARGET_BUILTIN_SETJMP_FRAME_VALUE avr_builtin_setjmp_frame_value
13729
13730 #undef TARGET_CONDITIONAL_REGISTER_USAGE
13731 #define TARGET_CONDITIONAL_REGISTER_USAGE avr_conditional_register_usage
13732
13733 #undef TARGET_HARD_REGNO_SCRATCH_OK
13734 #define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok
13735 #undef TARGET_CASE_VALUES_THRESHOLD
13736 #define TARGET_CASE_VALUES_THRESHOLD avr_case_values_threshold
13737
13738 #undef TARGET_FRAME_POINTER_REQUIRED
13739 #define TARGET_FRAME_POINTER_REQUIRED avr_frame_pointer_required_p
13740 #undef TARGET_CAN_ELIMINATE
13741 #define TARGET_CAN_ELIMINATE avr_can_eliminate
13742
13743 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
13744 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS avr_allocate_stack_slots_for_args
13745
13746 #undef TARGET_WARN_FUNC_RETURN
13747 #define TARGET_WARN_FUNC_RETURN avr_warn_func_return
13748
13749 #undef TARGET_CLASS_LIKELY_SPILLED_P
13750 #define TARGET_CLASS_LIKELY_SPILLED_P avr_class_likely_spilled_p
13751
13752 #undef TARGET_OPTION_OVERRIDE
13753 #define TARGET_OPTION_OVERRIDE avr_option_override
13754
13755 #undef TARGET_CANNOT_MODIFY_JUMPS_P
13756 #define TARGET_CANNOT_MODIFY_JUMPS_P avr_cannot_modify_jumps_p
13757
13758 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
13759 #define TARGET_FUNCTION_OK_FOR_SIBCALL avr_function_ok_for_sibcall
13760
13761 #undef TARGET_INIT_BUILTINS
13762 #define TARGET_INIT_BUILTINS avr_init_builtins
13763
13764 #undef TARGET_BUILTIN_DECL
13765 #define TARGET_BUILTIN_DECL avr_builtin_decl
13766
13767 #undef TARGET_EXPAND_BUILTIN
13768 #define TARGET_EXPAND_BUILTIN avr_expand_builtin
13769
13770 #undef TARGET_FOLD_BUILTIN
13771 #define TARGET_FOLD_BUILTIN avr_fold_builtin
13772
13773 #undef TARGET_SCALAR_MODE_SUPPORTED_P
13774 #define TARGET_SCALAR_MODE_SUPPORTED_P avr_scalar_mode_supported_p
13775
13776 #undef TARGET_BUILD_BUILTIN_VA_LIST
13777 #define TARGET_BUILD_BUILTIN_VA_LIST avr_build_builtin_va_list
13778
13779 #undef TARGET_FIXED_POINT_SUPPORTED_P
13780 #define TARGET_FIXED_POINT_SUPPORTED_P hook_bool_void_true
13781
13782 #undef TARGET_CONVERT_TO_TYPE
13783 #define TARGET_CONVERT_TO_TYPE avr_convert_to_type
13784
13785 #undef TARGET_ADDR_SPACE_SUBSET_P
13786 #define TARGET_ADDR_SPACE_SUBSET_P avr_addr_space_subset_p
13787
13788 #undef TARGET_ADDR_SPACE_CONVERT
13789 #define TARGET_ADDR_SPACE_CONVERT avr_addr_space_convert
13790
13791 #undef TARGET_ADDR_SPACE_ADDRESS_MODE
13792 #define TARGET_ADDR_SPACE_ADDRESS_MODE avr_addr_space_address_mode
13793
13794 #undef TARGET_ADDR_SPACE_POINTER_MODE
13795 #define TARGET_ADDR_SPACE_POINTER_MODE avr_addr_space_pointer_mode
13796
13797 #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
13798 #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
13799 avr_addr_space_legitimate_address_p
13800
13801 #undef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
13802 #define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS avr_addr_space_legitimize_address
13803
13804 #undef TARGET_MODE_DEPENDENT_ADDRESS_P
13805 #define TARGET_MODE_DEPENDENT_ADDRESS_P avr_mode_dependent_address_p
13806
13807 #undef TARGET_SECONDARY_RELOAD
13808 #define TARGET_SECONDARY_RELOAD avr_secondary_reload
13809
13810 #undef TARGET_PRINT_OPERAND
13811 #define TARGET_PRINT_OPERAND avr_print_operand
13812 #undef TARGET_PRINT_OPERAND_ADDRESS
13813 #define TARGET_PRINT_OPERAND_ADDRESS avr_print_operand_address
13814 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
13815 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P avr_print_operand_punct_valid_p
13816
13817 #undef TARGET_USE_BY_PIECES_INFRASTRUCTURE_P
13818 #define TARGET_USE_BY_PIECES_INFRASTRUCTURE_P \
13819 avr_use_by_pieces_infrastructure_p
13820
13821 struct gcc_target targetm = TARGET_INITIALIZER;
13822
13823
13824 #include "gt-avr.h"
13825