]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/avr/avr.c
gcc/ada/
[thirdparty/gcc.git] / gcc / config / avr / avr.c
CommitLineData
a28e4651 1/* Subroutines for insn-output.c for ATMEL AVR micro controllers
3aea1f79 2 Copyright (C) 1998-2014 Free Software Foundation, Inc.
947dd720 3 Contributed by Denis Chertykov (chertykov@gmail.com)
a28e4651 4
187b36cf 5 This file is part of GCC.
a28e4651 6
187b36cf 7 GCC is free software; you can redistribute it and/or modify
a28e4651 8 it under the terms of the GNU General Public License as published by
038d1e19 9 the Free Software Foundation; either version 3, or (at your option)
a28e4651 10 any later version.
11
187b36cf 12 GCC is distributed in the hope that it will be useful,
a28e4651 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
038d1e19 18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
a28e4651 20
21#include "config.h"
3337ec92 22#include "system.h"
805e22b2 23#include "coretypes.h"
24#include "tm.h"
a28e4651 25#include "rtl.h"
26#include "regs.h"
27#include "hard-reg-set.h"
a28e4651 28#include "insn-config.h"
29#include "conditions.h"
a28e4651 30#include "insn-attr.h"
c5be380e 31#include "insn-codes.h"
a28e4651 32#include "flags.h"
33#include "reload.h"
34#include "tree.h"
c0d7a1d0 35#include "varasm.h"
9ed99284 36#include "print-tree.h"
37#include "calls.h"
38#include "stor-layout.h"
39#include "stringpool.h"
9bfdb494 40#include "output.h"
a28e4651 41#include "expr.h"
4202ef11 42#include "c-family/c-common.h"
0b205f4c 43#include "diagnostic-core.h"
a28e4651 44#include "obstack.h"
a3020f2f 45#include "hashtab.h"
46#include "hash-set.h"
47#include "vec.h"
48#include "machmode.h"
49#include "input.h"
a28e4651 50#include "function.h"
51#include "recog.h"
c5be380e 52#include "optabs.h"
c84f2269 53#include "ggc.h"
c5be380e 54#include "langhooks.h"
a28e4651 55#include "tm_p.h"
a767736d 56#include "target.h"
57#include "target-def.h"
9c12cc94 58#include "params.h"
94ea8568 59#include "dominance.h"
60#include "cfg.h"
61#include "cfgrtl.h"
62#include "cfganal.h"
63#include "lcm.h"
64#include "cfgbuild.h"
65#include "cfgcleanup.h"
66#include "predict.h"
67#include "basic-block.h"
a4c6e6a2 68#include "df.h"
f7715905 69#include "builtins.h"
a28e4651 70
1cb39658 71/* Maximal allowed offset for an address in the LD command */
72#define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
a28e4651 73
53026b2c 74/* Return true if STR starts with PREFIX and false, otherwise. */
75#define STR_PREFIX_P(STR,PREFIX) (0 == strncmp (STR, PREFIX, strlen (PREFIX)))
76
9d734fa8 77/* The 4 bits starting at SECTION_MACH_DEP are reserved to store the
78 address space where data is to be located.
0dff9558 79 As the only non-generic address spaces are all located in flash,
9d734fa8 80 this can be used to test if data shall go into some .progmem* section.
81 This must be the rightmost field of machine dependent section flags. */
5bd39e93 82#define AVR_SECTION_PROGMEM (0xf * SECTION_MACH_DEP)
bf412f98 83
ed2541ea 84/* Similar 4-bit region for SYMBOL_REF_FLAGS. */
85#define AVR_SYMBOL_FLAG_PROGMEM (0xf * SYMBOL_FLAG_MACH_DEP)
86
87/* Similar 4-bit region in SYMBOL_REF_FLAGS:
88 Set address-space AS in SYMBOL_REF_FLAGS of SYM */
89#define AVR_SYMBOL_SET_ADDR_SPACE(SYM,AS) \
90 do { \
91 SYMBOL_REF_FLAGS (sym) &= ~AVR_SYMBOL_FLAG_PROGMEM; \
92 SYMBOL_REF_FLAGS (sym) |= (AS) * SYMBOL_FLAG_MACH_DEP; \
93 } while (0)
94
95/* Read address-space from SYMBOL_REF_FLAGS of SYM */
96#define AVR_SYMBOL_GET_ADDR_SPACE(SYM) \
97 ((SYMBOL_REF_FLAGS (sym) & AVR_SYMBOL_FLAG_PROGMEM) \
98 / SYMBOL_FLAG_MACH_DEP)
99
b4e6d2e2 100#define TINY_ADIW(REG1, REG2, I) \
1a96adb9 101 "subi " #REG1 ",lo8(-(" #I "))" CR_TAB \
102 "sbci " #REG2 ",hi8(-(" #I "))"
b4e6d2e2 103
104#define TINY_SBIW(REG1, REG2, I) \
1a96adb9 105 "subi " #REG1 ",lo8((" #I "))" CR_TAB \
106 "sbci " #REG2 ",hi8((" #I "))"
b4e6d2e2 107
108#define AVR_TMP_REGNO (AVR_TINY ? TMP_REGNO_TINY : TMP_REGNO)
109#define AVR_ZERO_REGNO (AVR_TINY ? ZERO_REGNO_TINY : ZERO_REGNO)
110
9d734fa8 111/* Known address spaces. The order must be the same as in the respective
112 enum from avr.h (or designated initialized must be used). */
0558f5da 113const avr_addrspace_t avr_addrspace[ADDR_SPACE_COUNT] =
114{
115 { ADDR_SPACE_RAM, 0, 2, "", 0, NULL },
116 { ADDR_SPACE_FLASH, 1, 2, "__flash", 0, ".progmem.data" },
117 { ADDR_SPACE_FLASH1, 1, 2, "__flash1", 1, ".progmem1.data" },
118 { ADDR_SPACE_FLASH2, 1, 2, "__flash2", 2, ".progmem2.data" },
119 { ADDR_SPACE_FLASH3, 1, 2, "__flash3", 3, ".progmem3.data" },
120 { ADDR_SPACE_FLASH4, 1, 2, "__flash4", 4, ".progmem4.data" },
121 { ADDR_SPACE_FLASH5, 1, 2, "__flash5", 5, ".progmem5.data" },
122 { ADDR_SPACE_MEMX, 1, 3, "__memx", 0, ".progmemx.data" },
9d734fa8 123};
124
9d734fa8 125
72851b68 126/* Holding RAM addresses of some SFRs used by the compiler and that
127 are unique over all devices in an architecture like 'avr4'. */
0dff9558 128
72851b68 129typedef struct
130{
0dff9558 131 /* SREG: The processor status */
72851b68 132 int sreg;
133
0b6cf66f 134 /* RAMPX, RAMPY, RAMPD and CCP of XMEGA */
135 int ccp;
136 int rampd;
137 int rampx;
138 int rampy;
139
0dff9558 140 /* RAMPZ: The high byte of 24-bit address used with ELPM */
72851b68 141 int rampz;
142
143 /* SP: The stack pointer and its low and high byte */
144 int sp_l;
145 int sp_h;
146} avr_addr_t;
147
148static avr_addr_t avr_addr;
149
a45076aa 150
151/* Prototypes for local helper functions. */
152
375204de 153static const char* out_movqi_r_mr (rtx_insn *, rtx[], int*);
154static const char* out_movhi_r_mr (rtx_insn *, rtx[], int*);
155static const char* out_movsi_r_mr (rtx_insn *, rtx[], int*);
156static const char* out_movqi_mr_r (rtx_insn *, rtx[], int*);
157static const char* out_movhi_mr_r (rtx_insn *, rtx[], int*);
158static const char* out_movsi_mr_r (rtx_insn *, rtx[], int*);
159
160static int get_sequence_length (rtx_insn *insns);
206a5129 161static int sequent_regs_live (void);
162static const char *ptrreg_to_str (int);
163static const char *cond_string (enum rtx_code);
3754d046 164static int avr_num_arg_regs (machine_mode, const_tree);
165static int avr_operand_rtx_cost (rtx, machine_mode, enum rtx_code,
a49907f9 166 int, bool);
167static void output_reload_in_const (rtx*, rtx, int*, bool);
df3d6232 168static struct machine_function * avr_init_machine_status (void);
a45076aa 169
170
171/* Prototypes for hook implementors if needed before their implementation. */
172
0dff9558 173static bool avr_rtx_costs (rtx, int, int, int, int*, bool);
a45076aa 174
b1665fa2 175
20c71901 176/* Allocate registers from r25 to r8 for parameters for function calls. */
a28e4651 177#define FIRST_CUM_REG 26
178
b4e6d2e2 179/* Last call saved register */
180#define LAST_CALLEE_SAVED_REG (AVR_TINY ? 19 : 17)
181
4202ef11 182/* Implicit target register of LPM instruction (R0) */
2d86450c 183extern GTY(()) rtx lpm_reg_rtx;
184rtx lpm_reg_rtx;
4202ef11 185
186/* (Implicit) address register of LPM instruction (R31:R30 = Z) */
2d86450c 187extern GTY(()) rtx lpm_addr_reg_rtx;
188rtx lpm_addr_reg_rtx;
4202ef11 189
2d86450c 190/* Temporary register RTX (reg:QI TMP_REGNO) */
191extern GTY(()) rtx tmp_reg_rtx;
192rtx tmp_reg_rtx;
a28e4651 193
2d86450c 194/* Zeroed register RTX (reg:QI ZERO_REGNO) */
195extern GTY(()) rtx zero_reg_rtx;
196rtx zero_reg_rtx;
197
198/* RTXs for all general purpose registers as QImode */
199extern GTY(()) rtx all_regs_rtx[32];
200rtx all_regs_rtx[32];
e511e253 201
0b6cf66f 202/* SREG, the processor status */
203extern GTY(()) rtx sreg_rtx;
204rtx sreg_rtx;
205
206/* RAMP* special function registers */
207extern GTY(()) rtx rampd_rtx;
208extern GTY(()) rtx rampx_rtx;
209extern GTY(()) rtx rampy_rtx;
2d86450c 210extern GTY(()) rtx rampz_rtx;
0b6cf66f 211rtx rampd_rtx;
212rtx rampx_rtx;
213rtx rampy_rtx;
2d86450c 214rtx rampz_rtx;
5bd39e93 215
216/* RTX containing the strings "" and "e", respectively */
217static GTY(()) rtx xstring_empty;
218static GTY(()) rtx xstring_e;
219
b1eb5c83 220/* Current architecture. */
ce544647 221const avr_arch_t *avr_current_arch;
b1eb5c83 222
795cff42 223/* Current device. */
ce544647 224const avr_mcu_t *avr_current_device;
e511e253 225
c3f18f18 226/* Section to put switch tables in. */
227static GTY(()) section *progmem_swtable_section;
a28e4651 228
9d734fa8 229/* Unnamed sections associated to __attribute__((progmem)) aka. PROGMEM
0558f5da 230 or to address space __flash* or __memx. Only used as singletons inside
231 avr_asm_select_section, but it must not be local there because of GTY. */
232static GTY(()) section *progmem_section[ADDR_SPACE_COUNT];
5bd39e93 233
83921eda 234/* Condition for insns/expanders from avr-dimode.md. */
235bool avr_have_dimode = true;
236
7c2339f8 237/* To track if code will use .bss and/or .data. */
238bool avr_need_clear_bss_p = false;
239bool avr_need_copy_data_p = false;
240
a767736d 241\f
73263209 242/* Transform UP into lowercase and write the result to LO.
243 You must provide enough space for LO. Return LO. */
244
245static char*
246avr_tolower (char *lo, const char *up)
247{
248 char *lo0 = lo;
249
250 for (; *up; up++, lo++)
251 *lo = TOLOWER (*up);
252
253 *lo = '\0';
254
255 return lo0;
256}
257
bf412f98 258
6be828c1 259/* Custom function to count number of set bits. */
260
261static inline int
262avr_popcount (unsigned int val)
263{
264 int pop = 0;
265
266 while (val)
267 {
268 val &= val-1;
269 pop++;
270 }
271
272 return pop;
273}
274
275
2f2d376f 276/* Constraint helper function. XVAL is a CONST_INT or a CONST_DOUBLE.
277 Return true if the least significant N_BYTES bytes of XVAL all have a
278 popcount in POP_MASK and false, otherwise. POP_MASK represents a subset
279 of integers which contains an integer N iff bit N of POP_MASK is set. */
0dff9558 280
6be828c1 281bool
282avr_popcount_each_byte (rtx xval, int n_bytes, int pop_mask)
283{
284 int i;
285
3754d046 286 machine_mode mode = GET_MODE (xval);
2f2d376f 287
288 if (VOIDmode == mode)
289 mode = SImode;
290
6be828c1 291 for (i = 0; i < n_bytes; i++)
292 {
2f2d376f 293 rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
6be828c1 294 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
295
296 if (0 == (pop_mask & (1 << avr_popcount (val8))))
297 return false;
298 }
299
300 return true;
301}
302
017c5b98 303
304/* Access some RTX as INT_MODE. If X is a CONST_FIXED we can get
305 the bit representation of X by "casting" it to CONST_INT. */
306
307rtx
308avr_to_int_mode (rtx x)
309{
3754d046 310 machine_mode mode = GET_MODE (x);
017c5b98 311
312 return VOIDmode == mode
313 ? x
314 : simplify_gen_subreg (int_mode_for_mode (mode), x, mode, 0);
315}
316
317
318/* Implement `TARGET_OPTION_OVERRIDE'. */
319
4c834714 320static void
321avr_option_override (void)
a28e4651 322{
dbf10c97 323 /* Disable -fdelete-null-pointer-checks option for AVR target.
324 This option compiler assumes that dereferencing of a null pointer
325 would halt the program. For AVR this assumption is not true and
326 programs can safely dereference null pointers. Changes made by this
327 option may not work properly for AVR. So disable this option. */
328
6e9e3dbe 329 flag_delete_null_pointer_checks = 0;
330
f9efb148 331 /* caller-save.c looks for call-clobbered hard registers that are assigned
332 to pseudos that cross calls and tries so save-restore them around calls
333 in order to reduce the number of stack slots needed.
334
0dff9558 335 This might lead to situations where reload is no more able to cope
f9efb148 336 with the challenge of AVR's very few address registers and fails to
337 perform the requested spills. */
0dff9558 338
f9efb148 339 if (avr_strict_X)
340 flag_caller_saves = 0;
341
344ae919 342 /* Unwind tables currently require a frame pointer for correctness,
343 see toplev.c:process_options(). */
344
345 if ((flag_unwind_tables
346 || flag_non_call_exceptions
347 || flag_asynchronous_unwind_tables)
348 && !ACCUMULATE_OUTGOING_ARGS)
349 {
350 flag_omit_frame_pointer = 0;
351 }
344ae919 352
13fde1a0 353 if (flag_pic == 1)
354 warning (OPT_fpic, "-fpic is not supported");
355 if (flag_pic == 2)
356 warning (OPT_fPIC, "-fPIC is not supported");
357 if (flag_pie == 1)
358 warning (OPT_fpie, "-fpie is not supported");
359 if (flag_pie == 2)
360 warning (OPT_fPIE, "-fPIE is not supported");
361
c0d7a1d0 362 /* Search for mcu arch.
363 ??? We should probably just put the architecture-default device
364 settings in the architecture struct and remove any notion of a current
365 device from gcc. */
366
367 for (avr_current_device = avr_mcu_types; ; avr_current_device++)
368 {
369 if (!avr_current_device->name)
1a96adb9 370 fatal_error ("mcu not found");
c0d7a1d0 371 if (!avr_current_device->macro
1a96adb9 372 && avr_current_device->arch == avr_arch_index)
373 break;
c0d7a1d0 374 }
375
376 avr_current_arch = &avr_arch_types[avr_arch_index];
377 if (avr_n_flash < 0)
378 avr_n_flash = avr_current_device->n_flash;
0dff9558 379
380 /* RAM addresses of some SFRs common to all devices in respective arch. */
72851b68 381
382 /* SREG: Status Register containing flags like I (global IRQ) */
383 avr_addr.sreg = 0x3F + avr_current_arch->sfr_offset;
384
385 /* RAMPZ: Address' high part when loading via ELPM */
386 avr_addr.rampz = 0x3B + avr_current_arch->sfr_offset;
387
0b6cf66f 388 avr_addr.rampy = 0x3A + avr_current_arch->sfr_offset;
389 avr_addr.rampx = 0x39 + avr_current_arch->sfr_offset;
390 avr_addr.rampd = 0x38 + avr_current_arch->sfr_offset;
b4e6d2e2 391 avr_addr.ccp = (AVR_TINY ? 0x3C : 0x34) + avr_current_arch->sfr_offset;
0b6cf66f 392
72851b68 393 /* SP: Stack Pointer (SP_H:SP_L) */
394 avr_addr.sp_l = 0x3D + avr_current_arch->sfr_offset;
395 avr_addr.sp_h = avr_addr.sp_l + 1;
21167a30 396
df3d6232 397 init_machine_status = avr_init_machine_status;
47fe598e 398
399 avr_log_set_avr_log();
a28e4651 400}
401
df3d6232 402/* Function to set up the backend function structure. */
403
404static struct machine_function *
405avr_init_machine_status (void)
406{
25a27413 407 return ggc_cleared_alloc<machine_function> ();
df3d6232 408}
409
5bd39e93 410
411/* Implement `INIT_EXPANDERS'. */
412/* The function works like a singleton. */
413
414void
415avr_init_expanders (void)
416{
417 int regno;
418
5bd39e93 419 for (regno = 0; regno < 32; regno ++)
420 all_regs_rtx[regno] = gen_rtx_REG (QImode, regno);
421
422 lpm_reg_rtx = all_regs_rtx[LPM_REGNO];
b4e6d2e2 423 tmp_reg_rtx = all_regs_rtx[AVR_TMP_REGNO];
424 zero_reg_rtx = all_regs_rtx[AVR_ZERO_REGNO];
5bd39e93 425
426 lpm_addr_reg_rtx = gen_rtx_REG (HImode, REG_Z);
427
0b6cf66f 428 sreg_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.sreg));
429 rampd_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampd));
430 rampx_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampx));
431 rampy_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampy));
72851b68 432 rampz_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampz));
5bd39e93 433
434 xstring_empty = gen_rtx_CONST_STRING (VOIDmode, "");
435 xstring_e = gen_rtx_CONST_STRING (VOIDmode, "e");
b4e6d2e2 436
437 /* TINY core does not have regs r10-r16, but avr-dimode.md expects them
438 to be present */
439 if (AVR_TINY)
1a96adb9 440 avr_have_dimode = false;
5bd39e93 441}
442
443
0dff9558 444/* Implement `REGNO_REG_CLASS'. */
20c71901 445/* Return register class for register R. */
a28e4651 446
447enum reg_class
206a5129 448avr_regno_reg_class (int r)
a28e4651 449{
7104fbe4 450 static const enum reg_class reg_class_tab[] =
451 {
452 R0_REG,
453 /* r1 - r15 */
454 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
455 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
456 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
457 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
458 /* r16 - r23 */
459 SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
460 SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
461 /* r24, r25 */
462 ADDW_REGS, ADDW_REGS,
463 /* X: r26, 27 */
464 POINTER_X_REGS, POINTER_X_REGS,
465 /* Y: r28, r29 */
466 POINTER_Y_REGS, POINTER_Y_REGS,
467 /* Z: r30, r31 */
468 POINTER_Z_REGS, POINTER_Z_REGS,
469 /* SP: SPL, SPH */
470 STACK_REG, STACK_REG
471 };
472
a28e4651 473 if (r <= 33)
474 return reg_class_tab[r];
0dff9558 475
a28e4651 476 return ALL_REGS;
477}
478
02d9a2c3 479
017c5b98 480/* Implement `TARGET_SCALAR_MODE_SUPPORTED_P'. */
481
02d9a2c3 482static bool
3754d046 483avr_scalar_mode_supported_p (machine_mode mode)
02d9a2c3 484{
017c5b98 485 if (ALL_FIXED_POINT_MODE_P (mode))
486 return true;
487
02d9a2c3 488 if (PSImode == mode)
489 return true;
490
491 return default_scalar_mode_supported_p (mode);
492}
493
494
0dff9558 495/* Return TRUE if DECL is a VAR_DECL located in flash and FALSE, otherwise. */
4202ef11 496
497static bool
590da9f2 498avr_decl_flash_p (tree decl)
4202ef11 499{
5bd39e93 500 if (TREE_CODE (decl) != VAR_DECL
501 || TREE_TYPE (decl) == error_mark_node)
502 {
503 return false;
504 }
4202ef11 505
506 return !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (decl)));
507}
508
509
0dff9558 510/* Return TRUE if DECL is a VAR_DECL located in the 24-bit flash
5bd39e93 511 address space and FALSE, otherwise. */
0dff9558 512
5bd39e93 513static bool
590da9f2 514avr_decl_memx_p (tree decl)
5bd39e93 515{
516 if (TREE_CODE (decl) != VAR_DECL
517 || TREE_TYPE (decl) == error_mark_node)
518 {
519 return false;
520 }
521
590da9f2 522 return (ADDR_SPACE_MEMX == TYPE_ADDR_SPACE (TREE_TYPE (decl)));
5bd39e93 523}
524
525
0dff9558 526/* Return TRUE if X is a MEM rtx located in flash and FALSE, otherwise. */
4202ef11 527
528bool
590da9f2 529avr_mem_flash_p (rtx x)
4202ef11 530{
531 return (MEM_P (x)
532 && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x)));
533}
534
535
0dff9558 536/* Return TRUE if X is a MEM rtx located in the 24-bit flash
5bd39e93 537 address space and FALSE, otherwise. */
538
539bool
590da9f2 540avr_mem_memx_p (rtx x)
5bd39e93 541{
542 return (MEM_P (x)
590da9f2 543 && ADDR_SPACE_MEMX == MEM_ADDR_SPACE (x));
5bd39e93 544}
545
546
32969c63 547/* A helper for the subsequent function attribute used to dig for
548 attribute 'name' in a FUNCTION_DECL or FUNCTION_TYPE */
549
550static inline int
551avr_lookup_function_attribute1 (const_tree func, const char *name)
552{
553 if (FUNCTION_DECL == TREE_CODE (func))
554 {
555 if (NULL_TREE != lookup_attribute (name, DECL_ATTRIBUTES (func)))
556 {
557 return true;
558 }
0dff9558 559
32969c63 560 func = TREE_TYPE (func);
561 }
562
563 gcc_assert (TREE_CODE (func) == FUNCTION_TYPE
564 || TREE_CODE (func) == METHOD_TYPE);
0dff9558 565
32969c63 566 return NULL_TREE != lookup_attribute (name, TYPE_ATTRIBUTES (func));
567}
568
e3e08e7f 569/* Return nonzero if FUNC is a naked function. */
a28e4651 570
571static int
206a5129 572avr_naked_function_p (tree func)
a28e4651 573{
32969c63 574 return avr_lookup_function_attribute1 (func, "naked");
a28e4651 575}
576
577/* Return nonzero if FUNC is an interrupt function as specified
578 by the "interrupt" attribute. */
579
580static int
ea679361 581avr_interrupt_function_p (tree func)
a28e4651 582{
32969c63 583 return avr_lookup_function_attribute1 (func, "interrupt");
a28e4651 584}
585
1cb39658 586/* Return nonzero if FUNC is a signal function as specified
a28e4651 587 by the "signal" attribute. */
588
589static int
ea679361 590avr_signal_function_p (tree func)
a28e4651 591{
32969c63 592 return avr_lookup_function_attribute1 (func, "signal");
a28e4651 593}
594
b0e2b973 595/* Return nonzero if FUNC is an OS_task function. */
ba8273a8 596
597static int
598avr_OS_task_function_p (tree func)
599{
32969c63 600 return avr_lookup_function_attribute1 (func, "OS_task");
ba8273a8 601}
602
b0e2b973 603/* Return nonzero if FUNC is an OS_main function. */
a6e595be 604
605static int
606avr_OS_main_function_p (tree func)
607{
32969c63 608 return avr_lookup_function_attribute1 (func, "OS_main");
a6e595be 609}
610
a12b9b80 611
ea679361 612/* Implement `TARGET_SET_CURRENT_FUNCTION'. */
613/* Sanity cheching for above function attributes. */
614
615static void
616avr_set_current_function (tree decl)
617{
618 location_t loc;
619 const char *isr;
620
621 if (decl == NULL_TREE
622 || current_function_decl == NULL_TREE
623 || current_function_decl == error_mark_node
23184a0e 624 || ! cfun->machine
ea679361 625 || cfun->machine->attributes_checked_p)
626 return;
627
628 loc = DECL_SOURCE_LOCATION (decl);
629
630 cfun->machine->is_naked = avr_naked_function_p (decl);
631 cfun->machine->is_signal = avr_signal_function_p (decl);
632 cfun->machine->is_interrupt = avr_interrupt_function_p (decl);
633 cfun->machine->is_OS_task = avr_OS_task_function_p (decl);
634 cfun->machine->is_OS_main = avr_OS_main_function_p (decl);
635
636 isr = cfun->machine->is_interrupt ? "interrupt" : "signal";
637
638 /* Too much attributes make no sense as they request conflicting features. */
639
640 if (cfun->machine->is_OS_task + cfun->machine->is_OS_main
641 + (cfun->machine->is_signal || cfun->machine->is_interrupt) > 1)
642 error_at (loc, "function attributes %qs, %qs and %qs are mutually"
643 " exclusive", "OS_task", "OS_main", isr);
644
645 /* 'naked' will hide effects of 'OS_task' and 'OS_main'. */
646
647 if (cfun->machine->is_naked
648 && (cfun->machine->is_OS_task || cfun->machine->is_OS_main))
649 warning_at (loc, OPT_Wattributes, "function attributes %qs and %qs have"
650 " no effect on %qs function", "OS_task", "OS_main", "naked");
651
652 if (cfun->machine->is_interrupt || cfun->machine->is_signal)
653 {
654 tree args = TYPE_ARG_TYPES (TREE_TYPE (decl));
655 tree ret = TREE_TYPE (TREE_TYPE (decl));
248c10bf 656 const char *name;
657
658 name = DECL_ASSEMBLER_NAME_SET_P (decl)
a11b2cf9 659 ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))
248c10bf 660 : IDENTIFIER_POINTER (DECL_NAME (decl));
0dff9558 661
a11b2cf9 662 /* Skip a leading '*' that might still prefix the assembler name,
663 e.g. in non-LTO runs. */
664
665 name = default_strip_name_encoding (name);
666
ea679361 667 /* Silently ignore 'signal' if 'interrupt' is present. AVR-LibC startet
668 using this when it switched from SIGNAL and INTERRUPT to ISR. */
669
670 if (cfun->machine->is_interrupt)
671 cfun->machine->is_signal = 0;
672
673 /* Interrupt handlers must be void __vector (void) functions. */
674
675 if (args && TREE_CODE (TREE_VALUE (args)) != VOID_TYPE)
676 error_at (loc, "%qs function cannot have arguments", isr);
677
678 if (TREE_CODE (ret) != VOID_TYPE)
679 error_at (loc, "%qs function cannot return a value", isr);
680
681 /* If the function has the 'signal' or 'interrupt' attribute, ensure
682 that the name of the function is "__vector_NN" so as to catch
683 when the user misspells the vector name. */
684
685 if (!STR_PREFIX_P (name, "__vector"))
686 warning_at (loc, 0, "%qs appears to be a misspelled %s handler",
687 name, isr);
688 }
689
0dff9558 690 /* Don't print the above diagnostics more than once. */
691
ea679361 692 cfun->machine->attributes_checked_p = 1;
693}
694
695
a12b9b80 696/* Implement `ACCUMULATE_OUTGOING_ARGS'. */
c529cd37 697
698int
a12b9b80 699avr_accumulate_outgoing_args (void)
700{
701 if (!cfun)
702 return TARGET_ACCUMULATE_OUTGOING_ARGS;
703
704 /* FIXME: For setjmp and in avr_builtin_setjmp_frame_value we don't know
705 what offset is correct. In some cases it is relative to
706 virtual_outgoing_args_rtx and in others it is relative to
707 virtual_stack_vars_rtx. For example code see
708 gcc.c-torture/execute/built-in-setjmp.c
709 gcc.c-torture/execute/builtins/sprintf-chk.c */
0dff9558 710
a12b9b80 711 return (TARGET_ACCUMULATE_OUTGOING_ARGS
712 && !(cfun->calls_setjmp
713 || cfun->has_nonlocal_label));
714}
715
716
717/* Report contribution of accumulated outgoing arguments to stack size. */
718
719static inline int
720avr_outgoing_args_size (void)
721{
722 return ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0;
723}
724
725
726/* Implement `STARTING_FRAME_OFFSET'. */
727/* This is the offset from the frame pointer register to the first stack slot
728 that contains a variable living in the frame. */
729
730int
731avr_starting_frame_offset (void)
732{
733 return 1 + avr_outgoing_args_size ();
734}
735
736
f0973368 737/* Return the number of hard registers to push/pop in the prologue/epilogue
738 of the current function, and optionally store these registers in SET. */
739
740static int
206a5129 741avr_regs_to_save (HARD_REG_SET *set)
f0973368 742{
743 int reg, count;
ea679361 744 int int_or_sig_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
f2323747 745
f0973368 746 if (set)
747 CLEAR_HARD_REG_SET (*set);
748 count = 0;
c3bcd5a9 749
0dff9558 750 /* No need to save any registers if the function never returns or
b0e2b973 751 has the "OS_task" or "OS_main" attribute. */
0dff9558 752
ba8273a8 753 if (TREE_THIS_VOLATILE (current_function_decl)
a6e595be 754 || cfun->machine->is_OS_task
755 || cfun->machine->is_OS_main)
c3bcd5a9 756 return 0;
757
f0973368 758 for (reg = 0; reg < 32; reg++)
759 {
760 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
a12b9b80 761 any global register variables. */
0dff9558 762
f0973368 763 if (fixed_regs[reg])
a12b9b80 764 continue;
f0973368 765
d5bf7b64 766 if ((int_or_sig_p && !crtl->is_leaf && call_used_regs[reg])
a12b9b80 767 || (df_regs_ever_live_p (reg)
768 && (int_or_sig_p || !call_used_regs[reg])
769 /* Don't record frame pointer registers here. They are treated
770 indivitually in prologue. */
771 && !(frame_pointer_needed
772 && (reg == REG_Y || reg == (REG_Y+1)))))
773 {
774 if (set)
775 SET_HARD_REG_BIT (*set, reg);
776 count++;
777 }
f0973368 778 }
779 return count;
780}
781
a28e3283 782
783/* Implement `TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS' */
784
785static bool
786avr_allocate_stack_slots_for_args (void)
787{
788 return !cfun->machine->is_naked;
789}
790
791
ebdd0478 792/* Return true if register FROM can be eliminated via register TO. */
793
a45076aa 794static bool
50f39f78 795avr_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
ebdd0478 796{
1cffa4f0 797 return ((frame_pointer_needed && to == FRAME_POINTER_REGNUM)
798 || !frame_pointer_needed);
ebdd0478 799}
800
08c6cbd2 801
0dff9558 802/* Implement `TARGET_WARN_FUNC_RETURN'. */
08c6cbd2 803
804static bool
805avr_warn_func_return (tree decl)
806{
807 /* Naked functions are implemented entirely in assembly, including the
808 return sequence, so suppress warnings about this. */
0dff9558 809
08c6cbd2 810 return !avr_naked_function_p (decl);
811}
812
20c71901 813/* Compute offset between arg_pointer and frame_pointer. */
a28e4651 814
815int
9f42c829 816avr_initial_elimination_offset (int from, int to)
a28e4651 817{
9f42c829 818 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
819 return 0;
820 else
1cb39658 821 {
9f42c829 822 int offset = frame_pointer_needed ? 2 : 0;
823 int avr_pc_size = AVR_HAVE_EIJMP_EICALL ? 3 : 2;
0dff9558 824
f0973368 825 offset += avr_regs_to_save (NULL);
9f42c829 826 return (get_frame_size () + avr_outgoing_args_size()
827 + avr_pc_size + 1 + offset);
a28e4651 828 }
a28e4651 829}
830
017c5b98 831
832/* Helper for the function below. */
833
834static void
3754d046 835avr_adjust_type_node (tree *node, machine_mode mode, int sat_p)
017c5b98 836{
837 *node = make_node (FIXED_POINT_TYPE);
838 TYPE_SATURATING (*node) = sat_p;
839 TYPE_UNSIGNED (*node) = UNSIGNED_FIXED_POINT_MODE_P (mode);
840 TYPE_IBIT (*node) = GET_MODE_IBIT (mode);
841 TYPE_FBIT (*node) = GET_MODE_FBIT (mode);
842 TYPE_PRECISION (*node) = GET_MODE_BITSIZE (mode);
843 TYPE_ALIGN (*node) = 8;
844 SET_TYPE_MODE (*node, mode);
845
846 layout_type (*node);
847}
848
849
850/* Implement `TARGET_BUILD_BUILTIN_VA_LIST'. */
851
852static tree
853avr_build_builtin_va_list (void)
854{
855 /* avr-modes.def adjusts [U]TA to be 64-bit modes with 48 fractional bits.
856 This is more appropriate for the 8-bit machine AVR than 128-bit modes.
857 The ADJUST_IBIT/FBIT are handled in toplev:init_adjust_machine_modes()
858 which is auto-generated by genmodes, but the compiler assigns [U]DAmode
859 to the long long accum modes instead of the desired [U]TAmode.
860
861 Fix this now, right after node setup in tree.c:build_common_tree_nodes().
862 This must run before c-cppbuiltin.c:builtin_define_fixed_point_constants()
863 which built-in defines macros like __ULLACCUM_FBIT__ that are used by
864 libgcc to detect IBIT and FBIT. */
865
866 avr_adjust_type_node (&ta_type_node, TAmode, 0);
867 avr_adjust_type_node (&uta_type_node, UTAmode, 0);
868 avr_adjust_type_node (&sat_ta_type_node, TAmode, 1);
869 avr_adjust_type_node (&sat_uta_type_node, UTAmode, 1);
870
871 unsigned_long_long_accum_type_node = uta_type_node;
872 long_long_accum_type_node = ta_type_node;
873 sat_unsigned_long_long_accum_type_node = sat_uta_type_node;
874 sat_long_long_accum_type_node = sat_ta_type_node;
875
876 /* Dispatch to the default handler. */
0dff9558 877
017c5b98 878 return std_build_builtin_va_list ();
879}
880
881
882/* Implement `TARGET_BUILTIN_SETJMP_FRAME_VALUE'. */
0dff9558 883/* Actual start of frame is virtual_stack_vars_rtx this is offset from
b1665fa2 884 frame pointer by +STARTING_FRAME_OFFSET.
885 Using saved frame = virtual_stack_vars_rtx - STARTING_FRAME_OFFSET
886 avoids creating add/sub of offset in nonlocal goto and setjmp. */
887
a45076aa 888static rtx
889avr_builtin_setjmp_frame_value (void)
b1665fa2 890{
017c5b98 891 rtx xval = gen_reg_rtx (Pmode);
892 emit_insn (gen_subhi3 (xval, virtual_stack_vars_rtx,
893 gen_int_mode (STARTING_FRAME_OFFSET, Pmode)));
894 return xval;
b1665fa2 895}
896
017c5b98 897
0dff9558 898/* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3-byte PC).
34413b10 899 This is return address of function. */
0dff9558 900
901rtx
36f949a2 902avr_return_addr_rtx (int count, rtx tem)
34413b10 903{
904 rtx r;
0dff9558 905
b0e2b973 906 /* Can only return this function's return address. Others not supported. */
34413b10 907 if (count)
908 return NULL;
909
910 if (AVR_3_BYTE_PC)
911 {
912 r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+2");
0dff9558 913 warning (0, "%<builtin_return_address%> contains only 2 bytes"
914 " of address");
34413b10 915 }
916 else
917 r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+1");
918
919 r = gen_rtx_PLUS (Pmode, tem, r);
920 r = gen_frame_mem (Pmode, memory_address (Pmode, r));
921 r = gen_rtx_ROTATE (HImode, r, GEN_INT (8));
922 return r;
923}
924
bf522d86 925/* Return 1 if the function epilogue is just a single "ret". */
926
927int
206a5129 928avr_simple_epilogue (void)
bf522d86 929{
930 return (! frame_pointer_needed
a12b9b80 931 && get_frame_size () == 0
932 && avr_outgoing_args_size() == 0
933 && avr_regs_to_save (NULL) == 0
ea679361 934 && ! cfun->machine->is_interrupt
935 && ! cfun->machine->is_signal
936 && ! cfun->machine->is_naked
a12b9b80 937 && ! TREE_THIS_VOLATILE (current_function_decl));
bf522d86 938}
939
20c71901 940/* This function checks sequence of live registers. */
a28e4651 941
942static int
206a5129 943sequent_regs_live (void)
a28e4651 944{
945 int reg;
0dff9558 946 int live_seq = 0;
947 int cur_seq = 0;
a28e4651 948
b4e6d2e2 949 for (reg = 0; reg <= LAST_CALLEE_SAVED_REG; ++reg)
a28e4651 950 {
3d83581f 951 if (fixed_regs[reg])
952 {
953 /* Don't recognize sequences that contain global register
954 variables. */
0dff9558 955
3d83581f 956 if (live_seq != 0)
957 return 0;
958 else
959 continue;
960 }
0dff9558 961
a28e4651 962 if (!call_used_regs[reg])
0dff9558 963 {
964 if (df_regs_ever_live_p (reg))
965 {
966 ++live_seq;
967 ++cur_seq;
968 }
969 else
970 cur_seq = 0;
971 }
a28e4651 972 }
973
974 if (!frame_pointer_needed)
975 {
3072d30e 976 if (df_regs_ever_live_p (REG_Y))
0dff9558 977 {
978 ++live_seq;
979 ++cur_seq;
980 }
a28e4651 981 else
0dff9558 982 cur_seq = 0;
a28e4651 983
3072d30e 984 if (df_regs_ever_live_p (REG_Y+1))
0dff9558 985 {
986 ++live_seq;
987 ++cur_seq;
988 }
a28e4651 989 else
0dff9558 990 cur_seq = 0;
a28e4651 991 }
992 else
993 {
994 cur_seq += 2;
995 live_seq += 2;
996 }
997 return (cur_seq == live_seq) ? live_seq : 0;
998}
999
58f62c92 1000/* Obtain the length sequence of insns. */
1001
1002int
375204de 1003get_sequence_length (rtx_insn *insns)
58f62c92 1004{
375204de 1005 rtx_insn *insn;
58f62c92 1006 int length;
0dff9558 1007
58f62c92 1008 for (insn = insns, length = 0; insn; insn = NEXT_INSN (insn))
1009 length += get_attr_length (insn);
0dff9558 1010
58f62c92 1011 return length;
1012}
1013
0dff9558 1014
1015/* Implement `INCOMING_RETURN_ADDR_RTX'. */
e484266f 1016
1017rtx
1018avr_incoming_return_addr_rtx (void)
1019{
1020 /* The return address is at the top of the stack. Note that the push
1021 was via post-decrement, which means the actual address is off by one. */
29c05e22 1022 return gen_frame_mem (HImode, plus_constant (Pmode, stack_pointer_rtx, 1));
e484266f 1023}
1024
1025/* Helper for expand_prologue. Emit a push of a byte register. */
1026
1027static void
1028emit_push_byte (unsigned regno, bool frame_related_p)
1029{
375204de 1030 rtx mem, reg;
1031 rtx_insn *insn;
e484266f 1032
1033 mem = gen_rtx_POST_DEC (HImode, stack_pointer_rtx);
1034 mem = gen_frame_mem (QImode, mem);
1035 reg = gen_rtx_REG (QImode, regno);
1036
1037 insn = emit_insn (gen_rtx_SET (VOIDmode, mem, reg));
1038 if (frame_related_p)
1039 RTX_FRAME_RELATED_P (insn) = 1;
1040
1041 cfun->machine->stack_usage++;
1042}
1043
0b6cf66f 1044
1045/* Helper for expand_prologue. Emit a push of a SFR via tmp_reg.
1046 SFR is a MEM representing the memory location of the SFR.
1047 If CLR_P then clear the SFR after the push using zero_reg. */
1048
1049static void
1050emit_push_sfr (rtx sfr, bool frame_related_p, bool clr_p)
1051{
375204de 1052 rtx_insn *insn;
0dff9558 1053
0b6cf66f 1054 gcc_assert (MEM_P (sfr));
1055
1056 /* IN __tmp_reg__, IO(SFR) */
1057 insn = emit_move_insn (tmp_reg_rtx, sfr);
1058 if (frame_related_p)
1059 RTX_FRAME_RELATED_P (insn) = 1;
0dff9558 1060
0b6cf66f 1061 /* PUSH __tmp_reg__ */
b4e6d2e2 1062 emit_push_byte (AVR_TMP_REGNO, frame_related_p);
0b6cf66f 1063
1064 if (clr_p)
1065 {
1066 /* OUT IO(SFR), __zero_reg__ */
1067 insn = emit_move_insn (sfr, const0_rtx);
1068 if (frame_related_p)
1069 RTX_FRAME_RELATED_P (insn) = 1;
1070 }
1071}
1072
a12b9b80 1073static void
1074avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
1075{
375204de 1076 rtx_insn *insn;
a12b9b80 1077 bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1078 int live_seq = sequent_regs_live ();
1079
21467ee6 1080 HOST_WIDE_INT size_max
1081 = (HOST_WIDE_INT) GET_MODE_MASK (AVR_HAVE_8BIT_SP ? QImode : Pmode);
1082
a12b9b80 1083 bool minimize = (TARGET_CALL_PROLOGUES
21467ee6 1084 && size < size_max
a12b9b80 1085 && live_seq
1086 && !isr_p
1087 && !cfun->machine->is_OS_task
b4e6d2e2 1088 && !cfun->machine->is_OS_main
1089 && !AVR_TINY);
0dff9558 1090
a12b9b80 1091 if (minimize
1092 && (frame_pointer_needed
1093 || avr_outgoing_args_size() > 8
1094 || (AVR_2_BYTE_PC && live_seq > 6)
0dff9558 1095 || live_seq > 7))
a12b9b80 1096 {
1097 rtx pattern;
1098 int first_reg, reg, offset;
1099
0dff9558 1100 emit_move_insn (gen_rtx_REG (HImode, REG_X),
a12b9b80 1101 gen_int_mode (size, HImode));
1102
1103 pattern = gen_call_prologue_saves (gen_int_mode (live_seq, HImode),
1104 gen_int_mode (live_seq+size, HImode));
1105 insn = emit_insn (pattern);
1106 RTX_FRAME_RELATED_P (insn) = 1;
1107
1108 /* Describe the effect of the unspec_volatile call to prologue_saves.
1109 Note that this formulation assumes that add_reg_note pushes the
1110 notes to the front. Thus we build them in the reverse order of
1111 how we want dwarf2out to process them. */
1112
9f42c829 1113 /* The function does always set frame_pointer_rtx, but whether that
a12b9b80 1114 is going to be permanent in the function is frame_pointer_needed. */
1115
1116 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1117 gen_rtx_SET (VOIDmode, (frame_pointer_needed
9f42c829 1118 ? frame_pointer_rtx
a12b9b80 1119 : stack_pointer_rtx),
29c05e22 1120 plus_constant (Pmode, stack_pointer_rtx,
68c8bdc6 1121 -(size + live_seq))));
a12b9b80 1122
1123 /* Note that live_seq always contains r28+r29, but the other
1124 registers to be saved are all below 18. */
1125
b4e6d2e2 1126 first_reg = (LAST_CALLEE_SAVED_REG + 1) - (live_seq - 2);
a12b9b80 1127
1128 for (reg = 29, offset = -live_seq + 1;
1129 reg >= first_reg;
b4e6d2e2 1130 reg = (reg == 28 ? LAST_CALLEE_SAVED_REG : reg - 1), ++offset)
a12b9b80 1131 {
1132 rtx m, r;
1133
29c05e22 1134 m = gen_rtx_MEM (QImode, plus_constant (Pmode, stack_pointer_rtx,
68c8bdc6 1135 offset));
a12b9b80 1136 r = gen_rtx_REG (QImode, reg);
1137 add_reg_note (insn, REG_CFA_OFFSET, gen_rtx_SET (VOIDmode, m, r));
1138 }
1139
1140 cfun->machine->stack_usage += size + live_seq;
1141 }
1142 else /* !minimize */
1143 {
1144 int reg;
0dff9558 1145
a12b9b80 1146 for (reg = 0; reg < 32; ++reg)
1147 if (TEST_HARD_REG_BIT (set, reg))
1148 emit_push_byte (reg, true);
1149
1150 if (frame_pointer_needed
1151 && (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main)))
1152 {
1153 /* Push frame pointer. Always be consistent about the
1154 ordering of pushes -- epilogue_restores expects the
1155 register pair to be pushed low byte first. */
0dff9558 1156
a12b9b80 1157 emit_push_byte (REG_Y, true);
1158 emit_push_byte (REG_Y + 1, true);
1159 }
0dff9558 1160
a12b9b80 1161 if (frame_pointer_needed
1162 && size == 0)
1163 {
9f42c829 1164 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
a12b9b80 1165 RTX_FRAME_RELATED_P (insn) = 1;
1166 }
0dff9558 1167
a12b9b80 1168 if (size != 0)
1169 {
1170 /* Creating a frame can be done by direct manipulation of the
1171 stack or via the frame pointer. These two methods are:
1172 fp = sp
1173 fp -= size
1174 sp = fp
1175 or
1176 sp -= size
1177 fp = sp (*)
1178 the optimum method depends on function type, stack and
1179 frame size. To avoid a complex logic, both methods are
1180 tested and shortest is selected.
1181
1182 There is also the case where SIZE != 0 and no frame pointer is
1183 needed; this can occur if ACCUMULATE_OUTGOING_ARGS is on.
1184 In that case, insn (*) is not needed in that case.
1185 We use the X register as scratch. This is save because in X
1186 is call-clobbered.
1187 In an interrupt routine, the case of SIZE != 0 together with
1188 !frame_pointer_needed can only occur if the function is not a
1189 leaf function and thus X has already been saved. */
0dff9558 1190
b5b90b5a 1191 int irq_state = -1;
cde06e71 1192 HOST_WIDE_INT size_cfa = size, neg_size;
375204de 1193 rtx_insn *fp_plus_insns;
1194 rtx fp, my_fp;
a12b9b80 1195
1196 gcc_assert (frame_pointer_needed
1197 || !isr_p
d5bf7b64 1198 || !crtl->is_leaf);
0dff9558 1199
a12b9b80 1200 fp = my_fp = (frame_pointer_needed
9f42c829 1201 ? frame_pointer_rtx
a12b9b80 1202 : gen_rtx_REG (Pmode, REG_X));
0dff9558 1203
a12b9b80 1204 if (AVR_HAVE_8BIT_SP)
1205 {
1206 /* The high byte (r29) does not change:
b5b90b5a 1207 Prefer SUBI (1 cycle) over SBIW (2 cycles, same size). */
a12b9b80 1208
9f42c829 1209 my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
a12b9b80 1210 }
1211
21467ee6 1212 /* Cut down size and avoid size = 0 so that we don't run
1213 into ICE like PR52488 in the remainder. */
1214
1215 if (size > size_max)
1216 {
1217 /* Don't error so that insane code from newlib still compiles
1218 and does not break building newlib. As PR51345 is implemented
d32d7e3a 1219 now, there are multilib variants with -msp8.
0dff9558 1220
21467ee6 1221 If user wants sanity checks he can use -Wstack-usage=
1222 or similar options.
1223
1224 For CFA we emit the original, non-saturated size so that
1225 the generic machinery is aware of the real stack usage and
1226 will print the above diagnostic as expected. */
0dff9558 1227
21467ee6 1228 size = size_max;
1229 }
1230
1231 size = trunc_int_for_mode (size, GET_MODE (my_fp));
cde06e71 1232 neg_size = trunc_int_for_mode (-size, GET_MODE (my_fp));
0dff9558 1233
a12b9b80 1234 /************ Method 1: Adjust frame pointer ************/
0dff9558 1235
a12b9b80 1236 start_sequence ();
1237
1238 /* Normally, the dwarf2out frame-related-expr interpreter does
1239 not expect to have the CFA change once the frame pointer is
1240 set up. Thus, we avoid marking the move insn below and
1241 instead indicate that the entire operation is complete after
1242 the frame pointer subtraction is done. */
0dff9558 1243
a12b9b80 1244 insn = emit_move_insn (fp, stack_pointer_rtx);
b5b90b5a 1245 if (frame_pointer_needed)
1246 {
1247 RTX_FRAME_RELATED_P (insn) = 1;
1248 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1249 gen_rtx_SET (VOIDmode, fp, stack_pointer_rtx));
1250 }
a12b9b80 1251
b51b04ad 1252 insn = emit_move_insn (my_fp, plus_constant (GET_MODE (my_fp),
cde06e71 1253 my_fp, neg_size));
1254
a12b9b80 1255 if (frame_pointer_needed)
1256 {
b5b90b5a 1257 RTX_FRAME_RELATED_P (insn) = 1;
a12b9b80 1258 add_reg_note (insn, REG_CFA_ADJUST_CFA,
b5b90b5a 1259 gen_rtx_SET (VOIDmode, fp,
29c05e22 1260 plus_constant (Pmode, fp,
68c8bdc6 1261 -size_cfa)));
a12b9b80 1262 }
0dff9558 1263
a12b9b80 1264 /* Copy to stack pointer. Note that since we've already
1265 changed the CFA to the frame pointer this operation
b5b90b5a 1266 need not be annotated if frame pointer is needed.
1267 Always move through unspec, see PR50063.
1268 For meaning of irq_state see movhi_sp_r insn. */
a12b9b80 1269
b5b90b5a 1270 if (cfun->machine->is_interrupt)
1271 irq_state = 1;
1272
1273 if (TARGET_NO_INTERRUPTS
1274 || cfun->machine->is_signal
1275 || cfun->machine->is_OS_main)
1276 irq_state = 0;
a12b9b80 1277
b5b90b5a 1278 if (AVR_HAVE_8BIT_SP)
1279 irq_state = 2;
1280
1281 insn = emit_insn (gen_movhi_sp_r (stack_pointer_rtx,
1282 fp, GEN_INT (irq_state)));
1283 if (!frame_pointer_needed)
1284 {
1285 RTX_FRAME_RELATED_P (insn) = 1;
1286 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1287 gen_rtx_SET (VOIDmode, stack_pointer_rtx,
29c05e22 1288 plus_constant (Pmode,
68c8bdc6 1289 stack_pointer_rtx,
1290 -size_cfa)));
b5b90b5a 1291 }
0dff9558 1292
a12b9b80 1293 fp_plus_insns = get_insns ();
1294 end_sequence ();
0dff9558 1295
a12b9b80 1296 /************ Method 2: Adjust Stack pointer ************/
1297
1298 /* Stack adjustment by means of RCALL . and/or PUSH __TMP_REG__
1299 can only handle specific offsets. */
0dff9558 1300
a12b9b80 1301 if (avr_sp_immediate_operand (gen_int_mode (-size, HImode), HImode))
1302 {
375204de 1303 rtx_insn *sp_plus_insns;
0dff9558 1304
a12b9b80 1305 start_sequence ();
1306
b5b90b5a 1307 insn = emit_move_insn (stack_pointer_rtx,
29c05e22 1308 plus_constant (Pmode, stack_pointer_rtx,
68c8bdc6 1309 -size));
a12b9b80 1310 RTX_FRAME_RELATED_P (insn) = 1;
b5b90b5a 1311 add_reg_note (insn, REG_CFA_ADJUST_CFA,
1312 gen_rtx_SET (VOIDmode, stack_pointer_rtx,
29c05e22 1313 plus_constant (Pmode,
0dff9558 1314 stack_pointer_rtx,
68c8bdc6 1315 -size_cfa)));
a12b9b80 1316 if (frame_pointer_needed)
1317 {
1318 insn = emit_move_insn (fp, stack_pointer_rtx);
1319 RTX_FRAME_RELATED_P (insn) = 1;
1320 }
1321
1322 sp_plus_insns = get_insns ();
1323 end_sequence ();
1324
1325 /************ Use shortest method ************/
0dff9558 1326
a12b9b80 1327 emit_insn (get_sequence_length (sp_plus_insns)
1328 < get_sequence_length (fp_plus_insns)
1329 ? sp_plus_insns
1330 : fp_plus_insns);
1331 }
1332 else
1333 {
1334 emit_insn (fp_plus_insns);
1335 }
1336
21467ee6 1337 cfun->machine->stack_usage += size_cfa;
a12b9b80 1338 } /* !minimize && size != 0 */
1339 } /* !minimize */
1340}
1341
e484266f 1342
df3d6232 1343/* Output function prologue. */
a28e4651 1344
df3d6232 1345void
0dff9558 1346avr_expand_prologue (void)
a7690ba9 1347{
637dc5b6 1348 HARD_REG_SET set;
a12b9b80 1349 HOST_WIDE_INT size;
1350
1351 size = get_frame_size() + avr_outgoing_args_size();
0dff9558 1352
34413b10 1353 cfun->machine->stack_usage = 0;
0dff9558 1354
df3d6232 1355 /* Prologue: naked. */
1356 if (cfun->machine->is_naked)
a7690ba9 1357 {
df3d6232 1358 return;
a7690ba9 1359 }
a7690ba9 1360
637dc5b6 1361 avr_regs_to_save (&set);
a7690ba9 1362
df3d6232 1363 if (cfun->machine->is_interrupt || cfun->machine->is_signal)
a7690ba9 1364 {
e484266f 1365 /* Enable interrupts. */
df3d6232 1366 if (cfun->machine->is_interrupt)
a12b9b80 1367 emit_insn (gen_enable_interrupt ());
0dff9558 1368
df3d6232 1369 /* Push zero reg. */
b4e6d2e2 1370 emit_push_byte (AVR_ZERO_REGNO, true);
df3d6232 1371
1372 /* Push tmp reg. */
b4e6d2e2 1373 emit_push_byte (AVR_TMP_REGNO, true);
df3d6232 1374
1375 /* Push SREG. */
e484266f 1376 /* ??? There's no dwarf2 column reserved for SREG. */
0b6cf66f 1377 emit_push_sfr (sreg_rtx, false, false /* clr */);
637dc5b6 1378
df3d6232 1379 /* Clear zero reg. */
e484266f 1380 emit_move_insn (zero_reg_rtx, const0_rtx);
a7690ba9 1381
df3d6232 1382 /* Prevent any attempt to delete the setting of ZERO_REG! */
18b42941 1383 emit_use (zero_reg_rtx);
0b6cf66f 1384
1385 /* Push and clear RAMPD/X/Y/Z if present and low-part register is used.
1386 ??? There are no dwarf2 columns reserved for RAMPD/X/Y/Z. */
0dff9558 1387
0b6cf66f 1388 if (AVR_HAVE_RAMPD)
1389 emit_push_sfr (rampd_rtx, false /* frame-related */, true /* clr */);
1390
1391 if (AVR_HAVE_RAMPX
1392 && TEST_HARD_REG_BIT (set, REG_X)
1393 && TEST_HARD_REG_BIT (set, REG_X + 1))
1394 {
1395 emit_push_sfr (rampx_rtx, false /* frame-related */, true /* clr */);
1396 }
1397
1398 if (AVR_HAVE_RAMPY
1399 && (frame_pointer_needed
1400 || (TEST_HARD_REG_BIT (set, REG_Y)
1401 && TEST_HARD_REG_BIT (set, REG_Y + 1))))
1402 {
1403 emit_push_sfr (rampy_rtx, false /* frame-related */, true /* clr */);
1404 }
1405
69a2907c 1406 if (AVR_HAVE_RAMPZ
0b6cf66f 1407 && TEST_HARD_REG_BIT (set, REG_Z)
1408 && TEST_HARD_REG_BIT (set, REG_Z + 1))
1409 {
69a2907c 1410 emit_push_sfr (rampz_rtx, false /* frame-related */, AVR_HAVE_RAMPD);
0b6cf66f 1411 }
1412 } /* is_interrupt is_signal */
200b5210 1413
a12b9b80 1414 avr_prologue_setup_frame (size, set);
0dff9558 1415
8c0dd614 1416 if (flag_stack_usage_info)
200b5210 1417 current_function_static_stack_size = cfun->machine->stack_usage;
a7690ba9 1418}
1419
0dff9558 1420
1421/* Implement `TARGET_ASM_FUNCTION_END_PROLOGUE'. */
df3d6232 1422/* Output summary at end of function prologue. */
a28e4651 1423
17d9b0c3 1424static void
df3d6232 1425avr_asm_function_end_prologue (FILE *file)
a28e4651 1426{
df3d6232 1427 if (cfun->machine->is_naked)
a28e4651 1428 {
c3bcd5a9 1429 fputs ("/* prologue: naked */\n", file);
a28e4651 1430 }
df3d6232 1431 else
a28e4651 1432 {
df3d6232 1433 if (cfun->machine->is_interrupt)
1434 {
1435 fputs ("/* prologue: Interrupt */\n", file);
1436 }
1437 else if (cfun->machine->is_signal)
1438 {
1439 fputs ("/* prologue: Signal */\n", file);
1440 }
a28e4651 1441 else
df3d6232 1442 fputs ("/* prologue: function */\n", file);
a28e4651 1443 }
a12b9b80 1444
1445 if (ACCUMULATE_OUTGOING_ARGS)
1446 fprintf (file, "/* outgoing args size = %d */\n",
1447 avr_outgoing_args_size());
1448
df3d6232 1449 fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n",
1450 get_frame_size());
34413b10 1451 fprintf (file, "/* stack size = %d */\n",
1452 cfun->machine->stack_usage);
1453 /* Create symbol stack offset here so all functions have it. Add 1 to stack
1454 usage for offset so that SP + .L__stack_offset = return address. */
1455 fprintf (file, ".L__stack_usage = %d\n", cfun->machine->stack_usage);
df3d6232 1456}
f0973368 1457
e067eab2 1458
0dff9558 1459/* Implement `EPILOGUE_USES'. */
c3bcd5a9 1460
df3d6232 1461int
1462avr_epilogue_uses (int regno ATTRIBUTE_UNUSED)
1463{
0dff9558 1464 if (reload_completed
df3d6232 1465 && cfun->machine
1466 && (cfun->machine->is_interrupt || cfun->machine->is_signal))
1467 return 1;
1468 return 0;
a28e4651 1469}
1470
0dff9558 1471/* Helper for avr_expand_epilogue. Emit a pop of a byte register. */
e484266f 1472
1473static void
1474emit_pop_byte (unsigned regno)
1475{
1476 rtx mem, reg;
1477
1478 mem = gen_rtx_PRE_INC (HImode, stack_pointer_rtx);
1479 mem = gen_frame_mem (QImode, mem);
1480 reg = gen_rtx_REG (QImode, regno);
1481
1482 emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
1483}
1484
df3d6232 1485/* Output RTL epilogue. */
a28e4651 1486
df3d6232 1487void
0dff9558 1488avr_expand_epilogue (bool sibcall_p)
a28e4651 1489{
1490 int reg;
a28e4651 1491 int live_seq;
0dff9558 1492 HARD_REG_SET set;
a28e4651 1493 int minimize;
a12b9b80 1494 HOST_WIDE_INT size;
1495 bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1496
1497 size = get_frame_size() + avr_outgoing_args_size();
0dff9558 1498
df3d6232 1499 /* epilogue: naked */
1500 if (cfun->machine->is_naked)
c3bcd5a9 1501 {
32969c63 1502 gcc_assert (!sibcall_p);
0dff9558 1503
f7b38f2d 1504 emit_jump_insn (gen_return ());
df3d6232 1505 return;
a28e4651 1506 }
1507
637dc5b6 1508 avr_regs_to_save (&set);
a28e4651 1509 live_seq = sequent_regs_live ();
0dff9558 1510
a28e4651 1511 minimize = (TARGET_CALL_PROLOGUES
a12b9b80 1512 && live_seq
1513 && !isr_p
1514 && !cfun->machine->is_OS_task
b4e6d2e2 1515 && !cfun->machine->is_OS_main
1516 && !AVR_TINY);
0dff9558 1517
a12b9b80 1518 if (minimize
1519 && (live_seq > 4
1520 || frame_pointer_needed
1521 || size))
a28e4651 1522 {
a12b9b80 1523 /* Get rid of frame. */
0dff9558 1524
a12b9b80 1525 if (!frame_pointer_needed)
1526 {
9f42c829 1527 emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
a12b9b80 1528 }
1529
1530 if (size)
1531 {
9f42c829 1532 emit_move_insn (frame_pointer_rtx,
29c05e22 1533 plus_constant (Pmode, frame_pointer_rtx, size));
a12b9b80 1534 }
0dff9558 1535
f7b38f2d 1536 emit_insn (gen_epilogue_restores (gen_int_mode (live_seq, HImode)));
a12b9b80 1537 return;
a28e4651 1538 }
0dff9558 1539
a12b9b80 1540 if (size)
a28e4651 1541 {
a12b9b80 1542 /* Try two methods to adjust stack and select shortest. */
b5b90b5a 1543
1544 int irq_state = -1;
a12b9b80 1545 rtx fp, my_fp;
375204de 1546 rtx_insn *fp_plus_insns;
21467ee6 1547 HOST_WIDE_INT size_max;
e484266f 1548
a12b9b80 1549 gcc_assert (frame_pointer_needed
1550 || !isr_p
d5bf7b64 1551 || !crtl->is_leaf);
0dff9558 1552
a12b9b80 1553 fp = my_fp = (frame_pointer_needed
9f42c829 1554 ? frame_pointer_rtx
a12b9b80 1555 : gen_rtx_REG (Pmode, REG_X));
58f62c92 1556
a12b9b80 1557 if (AVR_HAVE_8BIT_SP)
1558 {
1559 /* The high byte (r29) does not change:
1560 Prefer SUBI (1 cycle) over SBIW (2 cycles). */
0dff9558 1561
9f42c829 1562 my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
a12b9b80 1563 }
21467ee6 1564
1565 /* For rationale see comment in prologue generation. */
1566
1567 size_max = (HOST_WIDE_INT) GET_MODE_MASK (GET_MODE (my_fp));
1568 if (size > size_max)
1569 size = size_max;
1570 size = trunc_int_for_mode (size, GET_MODE (my_fp));
0dff9558 1571
a12b9b80 1572 /********** Method 1: Adjust fp register **********/
0dff9558 1573
a12b9b80 1574 start_sequence ();
58f62c92 1575
a12b9b80 1576 if (!frame_pointer_needed)
1577 emit_move_insn (fp, stack_pointer_rtx);
58f62c92 1578
b51b04ad 1579 emit_move_insn (my_fp, plus_constant (GET_MODE (my_fp), my_fp, size));
58f62c92 1580
a12b9b80 1581 /* Copy to stack pointer. */
b5b90b5a 1582
1583 if (TARGET_NO_INTERRUPTS)
1584 irq_state = 0;
1585
1586 if (AVR_HAVE_8BIT_SP)
1587 irq_state = 2;
1588
1589 emit_insn (gen_movhi_sp_r (stack_pointer_rtx, fp,
1590 GEN_INT (irq_state)));
e484266f 1591
a12b9b80 1592 fp_plus_insns = get_insns ();
0dff9558 1593 end_sequence ();
58f62c92 1594
a12b9b80 1595 /********** Method 2: Adjust Stack pointer **********/
0dff9558 1596
a12b9b80 1597 if (avr_sp_immediate_operand (gen_int_mode (size, HImode), HImode))
1598 {
375204de 1599 rtx_insn *sp_plus_insns;
58f62c92 1600
a12b9b80 1601 start_sequence ();
58f62c92 1602
a12b9b80 1603 emit_move_insn (stack_pointer_rtx,
29c05e22 1604 plus_constant (Pmode, stack_pointer_rtx, size));
e484266f 1605
a12b9b80 1606 sp_plus_insns = get_insns ();
1607 end_sequence ();
e484266f 1608
a12b9b80 1609 /************ Use shortest method ************/
0dff9558 1610
a12b9b80 1611 emit_insn (get_sequence_length (sp_plus_insns)
1612 < get_sequence_length (fp_plus_insns)
1613 ? sp_plus_insns
1614 : fp_plus_insns);
1615 }
1616 else
1617 emit_insn (fp_plus_insns);
1618 } /* size != 0 */
0dff9558 1619
a12b9b80 1620 if (frame_pointer_needed
1621 && !(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
1622 {
0dff9558 1623 /* Restore previous frame_pointer. See avr_expand_prologue for
a12b9b80 1624 rationale for not using pophi. */
0dff9558 1625
a12b9b80 1626 emit_pop_byte (REG_Y + 1);
1627 emit_pop_byte (REG_Y);
1628 }
f0973368 1629
a12b9b80 1630 /* Restore used registers. */
0dff9558 1631
a12b9b80 1632 for (reg = 31; reg >= 0; --reg)
1633 if (TEST_HARD_REG_BIT (set, reg))
1634 emit_pop_byte (reg);
df3d6232 1635
a12b9b80 1636 if (isr_p)
1637 {
0b6cf66f 1638 /* Restore RAMPZ/Y/X/D using tmp_reg as scratch.
1639 The conditions to restore them must be tha same as in prologue. */
0dff9558 1640
69a2907c 1641 if (AVR_HAVE_RAMPZ
1642 && TEST_HARD_REG_BIT (set, REG_Z)
1643 && TEST_HARD_REG_BIT (set, REG_Z + 1))
0b6cf66f 1644 {
1645 emit_pop_byte (TMP_REGNO);
69a2907c 1646 emit_move_insn (rampz_rtx, tmp_reg_rtx);
0b6cf66f 1647 }
1648
1649 if (AVR_HAVE_RAMPY
1650 && (frame_pointer_needed
1651 || (TEST_HARD_REG_BIT (set, REG_Y)
1652 && TEST_HARD_REG_BIT (set, REG_Y + 1))))
1653 {
1654 emit_pop_byte (TMP_REGNO);
1655 emit_move_insn (rampy_rtx, tmp_reg_rtx);
1656 }
1657
69a2907c 1658 if (AVR_HAVE_RAMPX
1659 && TEST_HARD_REG_BIT (set, REG_X)
1660 && TEST_HARD_REG_BIT (set, REG_X + 1))
a12b9b80 1661 {
e484266f 1662 emit_pop_byte (TMP_REGNO);
69a2907c 1663 emit_move_insn (rampx_rtx, tmp_reg_rtx);
df3d6232 1664 }
c3bcd5a9 1665
0b6cf66f 1666 if (AVR_HAVE_RAMPD)
1667 {
1668 emit_pop_byte (TMP_REGNO);
1669 emit_move_insn (rampd_rtx, tmp_reg_rtx);
1670 }
1671
1672 /* Restore SREG using tmp_reg as scratch. */
0dff9558 1673
b4e6d2e2 1674 emit_pop_byte (AVR_TMP_REGNO);
0b6cf66f 1675 emit_move_insn (sreg_rtx, tmp_reg_rtx);
a12b9b80 1676
1677 /* Restore tmp REG. */
b4e6d2e2 1678 emit_pop_byte (AVR_TMP_REGNO);
a12b9b80 1679
1680 /* Restore zero REG. */
b4e6d2e2 1681 emit_pop_byte (AVR_ZERO_REGNO);
df3d6232 1682 }
a12b9b80 1683
1684 if (!sibcall_p)
1685 emit_jump_insn (gen_return ());
a28e4651 1686}
1687
0dff9558 1688
1689/* Implement `TARGET_ASM_FUNCTION_BEGIN_EPILOGUE'. */
df3d6232 1690
1691static void
1692avr_asm_function_begin_epilogue (FILE *file)
1693{
1694 fprintf (file, "/* epilogue start */\n");
1695}
a28e4651 1696
1f959902 1697
0dff9558 1698/* Implement `TARGET_CANNOT_MODITY_JUMPS_P'. */
1f959902 1699
1700static bool
1701avr_cannot_modify_jumps_p (void)
1702{
1703
1704 /* Naked Functions must not have any instructions after
1705 their epilogue, see PR42240 */
0dff9558 1706
1f959902 1707 if (reload_completed
1708 && cfun->machine
1709 && cfun->machine->is_naked)
1710 {
1711 return true;
1712 }
1713
1714 return false;
1715}
1716
1717
002565f0 1718/* Implement `TARGET_MODE_DEPENDENT_ADDRESS_P'. */
1719
002565f0 1720static bool
be6d8823 1721avr_mode_dependent_address_p (const_rtx addr ATTRIBUTE_UNUSED, addr_space_t as)
002565f0 1722{
be6d8823 1723 /* FIXME: Non-generic addresses are not mode-dependent in themselves.
1724 This hook just serves to hack around PR rtl-optimization/52543 by
1725 claiming that non-generic addresses were mode-dependent so that
1726 lower-subreg.c will skip these addresses. lower-subreg.c sets up fake
1727 RTXes to probe SET and MEM costs and assumes that MEM is always in the
1728 generic address space which is not true. */
1729
1730 return !ADDR_SPACE_GENERIC_P (as);
002565f0 1731}
1732
1733
8b0ecac5 1734/* Helper function for `avr_legitimate_address_p'. */
1735
1736static inline bool
f8a8fc7b 1737avr_reg_ok_for_addr_p (rtx reg, addr_space_t as,
f9efb148 1738 RTX_CODE outer_code, bool strict)
8b0ecac5 1739{
1740 return (REG_P (reg)
f8a8fc7b 1741 && (avr_regno_mode_code_ok_for_base_p (REGNO (reg), QImode,
1742 as, outer_code, UNKNOWN)
8b0ecac5 1743 || (!strict
1744 && REGNO (reg) >= FIRST_PSEUDO_REGISTER)));
1745}
1746
1747
a28e4651 1748/* Return nonzero if X (an RTX) is a legitimate memory address on the target
1749 machine for a memory operand of mode MODE. */
1750
8b0ecac5 1751static bool
3754d046 1752avr_legitimate_address_p (machine_mode mode, rtx x, bool strict)
a28e4651 1753{
f9efb148 1754 bool ok = CONSTANT_ADDRESS_P (x);
0dff9558 1755
f9efb148 1756 switch (GET_CODE (x))
a28e4651 1757 {
f9efb148 1758 case REG:
1759 ok = avr_reg_ok_for_addr_p (x, ADDR_SPACE_GENERIC,
1760 MEM, strict);
1761
1762 if (strict
017c5b98 1763 && GET_MODE_SIZE (mode) > 4
f9efb148 1764 && REG_X == REGNO (x))
8b0ecac5 1765 {
f9efb148 1766 ok = false;
8b0ecac5 1767 }
f9efb148 1768 break;
1769
1770 case POST_INC:
1771 case PRE_DEC:
1772 ok = avr_reg_ok_for_addr_p (XEXP (x, 0), ADDR_SPACE_GENERIC,
1773 GET_CODE (x), strict);
1774 break;
ae86bb47 1775
f9efb148 1776 case PLUS:
1777 {
1778 rtx reg = XEXP (x, 0);
1779 rtx op1 = XEXP (x, 1);
0dff9558 1780
f9efb148 1781 if (REG_P (reg)
1782 && CONST_INT_P (op1)
1783 && INTVAL (op1) >= 0)
1784 {
1785 bool fit = IN_RANGE (INTVAL (op1), 0, MAX_LD_OFFSET (mode));
1786
1787 if (fit)
1788 {
1789 ok = (! strict
1790 || avr_reg_ok_for_addr_p (reg, ADDR_SPACE_GENERIC,
1791 PLUS, strict));
0dff9558 1792
f9efb148 1793 if (reg == frame_pointer_rtx
1794 || reg == arg_pointer_rtx)
1795 {
1796 ok = true;
1797 }
1798 }
1799 else if (frame_pointer_needed
1800 && reg == frame_pointer_rtx)
1801 {
1802 ok = true;
1803 }
1804 }
1805 }
1806 break;
0dff9558 1807
f9efb148 1808 default:
1809 break;
1810 }
0dff9558 1811
ae86bb47 1812 if (avr_log.legitimate_address_p)
a28e4651 1813 {
f9efb148 1814 avr_edump ("\n%?: ret=%d, mode=%m strict=%d "
ae86bb47 1815 "reload_completed=%d reload_in_progress=%d %s:",
f9efb148 1816 ok, mode, strict, reload_completed, reload_in_progress,
ae86bb47 1817 reg_renumber ? "(reg_renumber)" : "");
0dff9558 1818
ae86bb47 1819 if (GET_CODE (x) == PLUS
1820 && REG_P (XEXP (x, 0))
1821 && CONST_INT_P (XEXP (x, 1))
1822 && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
1823 && reg_renumber)
1824 {
1825 avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
1826 true_regnum (XEXP (x, 0)));
1827 }
0dff9558 1828
ae86bb47 1829 avr_edump ("\n%r\n", x);
a28e4651 1830 }
0dff9558 1831
f9efb148 1832 return ok;
a28e4651 1833}
1834
4202ef11 1835
1836/* Former implementation of TARGET_LEGITIMIZE_ADDRESS,
1837 now only a helper for avr_addr_space_legitimize_address. */
a28e4651 1838/* Attempts to replace X with a valid
1839 memory address for an operand of mode MODE */
1840
8b0ecac5 1841static rtx
3754d046 1842avr_legitimize_address (rtx x, rtx oldx, machine_mode mode)
a28e4651 1843{
9f42c829 1844 bool big_offset_p = false;
0dff9558 1845
9f42c829 1846 x = oldx;
0dff9558 1847
9f42c829 1848 if (GET_CODE (oldx) == PLUS
1849 && REG_P (XEXP (oldx, 0)))
1850 {
1851 if (REG_P (XEXP (oldx, 1)))
1852 x = force_reg (GET_MODE (oldx), oldx);
1853 else if (CONST_INT_P (XEXP (oldx, 1)))
1854 {
0dff9558 1855 int offs = INTVAL (XEXP (oldx, 1));
9f42c829 1856 if (frame_pointer_rtx != XEXP (oldx, 0)
1857 && offs > MAX_LD_OFFSET (mode))
1858 {
1859 big_offset_p = true;
1860 x = force_reg (GET_MODE (oldx), oldx);
1861 }
1862 }
1863 }
0dff9558 1864
9f42c829 1865 if (avr_log.legitimize_address)
1866 {
1867 avr_edump ("\n%?: mode=%m\n %r\n", mode, oldx);
1868
1869 if (x != oldx)
1870 avr_edump (" %s --> %r\n", big_offset_p ? "(big offset)" : "", x);
1871 }
1872
a28e4651 1873 return x;
1874}
1875
1876
68a79dfc 1877/* Implement `LEGITIMIZE_RELOAD_ADDRESS'. */
1878/* This will allow register R26/27 to be used where it is no worse than normal
1879 base pointers R28/29 or R30/31. For example, if base offset is greater
1880 than 63 bytes or for R++ or --R addressing. */
1881
1882rtx
3754d046 1883avr_legitimize_reload_address (rtx *px, machine_mode mode,
68a79dfc 1884 int opnum, int type, int addr_type,
1885 int ind_levels ATTRIBUTE_UNUSED,
1886 rtx (*mk_memloc)(rtx,int))
1887{
1f46ee39 1888 rtx x = *px;
0dff9558 1889
68a79dfc 1890 if (avr_log.legitimize_reload_address)
1891 avr_edump ("\n%?:%m %r\n", mode, x);
0dff9558 1892
68a79dfc 1893 if (1 && (GET_CODE (x) == POST_INC
1894 || GET_CODE (x) == PRE_DEC))
1895 {
1896 push_reload (XEXP (x, 0), XEXP (x, 0), &XEXP (x, 0), &XEXP (x, 0),
1897 POINTER_REGS, GET_MODE (x), GET_MODE (x), 0, 0,
1898 opnum, RELOAD_OTHER);
0dff9558 1899
68a79dfc 1900 if (avr_log.legitimize_reload_address)
1f46ee39 1901 avr_edump (" RCLASS.1 = %R\n IN = %r\n OUT = %r\n",
68a79dfc 1902 POINTER_REGS, XEXP (x, 0), XEXP (x, 0));
0dff9558 1903
68a79dfc 1904 return x;
1905 }
0dff9558 1906
68a79dfc 1907 if (GET_CODE (x) == PLUS
1908 && REG_P (XEXP (x, 0))
1909 && 0 == reg_equiv_constant (REGNO (XEXP (x, 0)))
1910 && CONST_INT_P (XEXP (x, 1))
1911 && INTVAL (XEXP (x, 1)) >= 1)
1912 {
1913 bool fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
0dff9558 1914
68a79dfc 1915 if (fit)
1916 {
1917 if (reg_equiv_address (REGNO (XEXP (x, 0))) != 0)
1918 {
1919 int regno = REGNO (XEXP (x, 0));
1920 rtx mem = mk_memloc (x, regno);
0dff9558 1921
68a79dfc 1922 push_reload (XEXP (mem, 0), NULL_RTX, &XEXP (mem, 0), NULL,
1923 POINTER_REGS, Pmode, VOIDmode, 0, 0,
95dcc8ad 1924 1, (enum reload_type) addr_type);
0dff9558 1925
68a79dfc 1926 if (avr_log.legitimize_reload_address)
1f46ee39 1927 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
68a79dfc 1928 POINTER_REGS, XEXP (mem, 0), NULL_RTX);
0dff9558 1929
68a79dfc 1930 push_reload (mem, NULL_RTX, &XEXP (x, 0), NULL,
1931 BASE_POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
95dcc8ad 1932 opnum, (enum reload_type) type);
0dff9558 1933
68a79dfc 1934 if (avr_log.legitimize_reload_address)
1f46ee39 1935 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
68a79dfc 1936 BASE_POINTER_REGS, mem, NULL_RTX);
0dff9558 1937
68a79dfc 1938 return x;
1939 }
1940 }
1941 else if (! (frame_pointer_needed
9f42c829 1942 && XEXP (x, 0) == frame_pointer_rtx))
68a79dfc 1943 {
1f46ee39 1944 push_reload (x, NULL_RTX, px, NULL,
68a79dfc 1945 POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
95dcc8ad 1946 opnum, (enum reload_type) type);
0dff9558 1947
68a79dfc 1948 if (avr_log.legitimize_reload_address)
1f46ee39 1949 avr_edump (" RCLASS.3 = %R\n IN = %r\n OUT = %r\n",
68a79dfc 1950 POINTER_REGS, x, NULL_RTX);
0dff9558 1951
68a79dfc 1952 return x;
1953 }
1954 }
0dff9558 1955
68a79dfc 1956 return NULL_RTX;
1957}
1958
1959
be6d8823 1960/* Implement `TARGET_SECONDARY_RELOAD' */
1961
1962static reg_class_t
1963avr_secondary_reload (bool in_p, rtx x,
1964 reg_class_t reload_class ATTRIBUTE_UNUSED,
3754d046 1965 machine_mode mode, secondary_reload_info *sri)
be6d8823 1966{
1967 if (in_p
1968 && MEM_P (x)
1969 && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x))
1970 && ADDR_SPACE_MEMX != MEM_ADDR_SPACE (x))
1971 {
1972 /* For the non-generic 16-bit spaces we need a d-class scratch. */
1973
1974 switch (mode)
1975 {
1976 default:
1977 gcc_unreachable();
1978
1979 case QImode: sri->icode = CODE_FOR_reload_inqi; break;
1980 case QQmode: sri->icode = CODE_FOR_reload_inqq; break;
1981 case UQQmode: sri->icode = CODE_FOR_reload_inuqq; break;
1982
1983 case HImode: sri->icode = CODE_FOR_reload_inhi; break;
1984 case HQmode: sri->icode = CODE_FOR_reload_inhq; break;
1985 case HAmode: sri->icode = CODE_FOR_reload_inha; break;
1986 case UHQmode: sri->icode = CODE_FOR_reload_inuhq; break;
1987 case UHAmode: sri->icode = CODE_FOR_reload_inuha; break;
1988
1989 case PSImode: sri->icode = CODE_FOR_reload_inpsi; break;
1990
1991 case SImode: sri->icode = CODE_FOR_reload_insi; break;
1992 case SFmode: sri->icode = CODE_FOR_reload_insf; break;
1993 case SQmode: sri->icode = CODE_FOR_reload_insq; break;
1994 case SAmode: sri->icode = CODE_FOR_reload_insa; break;
1995 case USQmode: sri->icode = CODE_FOR_reload_inusq; break;
1996 case USAmode: sri->icode = CODE_FOR_reload_inusa; break;
1997 }
1998 }
1999
2000 return NO_REGS;
2001}
2002
2003
9ce2d202 2004/* Helper function to print assembler resp. track instruction
02d9a2c3 2005 sequence lengths. Always return "".
0dff9558 2006
9ce2d202 2007 If PLEN == NULL:
2008 Output assembler code from template TPL with operands supplied
2009 by OPERANDS. This is just forwarding to output_asm_insn.
0dff9558 2010
9ce2d202 2011 If PLEN != NULL:
dfd52f2b 2012 If N_WORDS >= 0 Add N_WORDS to *PLEN.
2013 If N_WORDS < 0 Set *PLEN to -N_WORDS.
9ce2d202 2014 Don't output anything.
2015*/
2016
02d9a2c3 2017static const char*
9ce2d202 2018avr_asm_len (const char* tpl, rtx* operands, int* plen, int n_words)
2019{
2020 if (NULL == plen)
2021 {
2022 output_asm_insn (tpl, operands);
2023 }
2024 else
2025 {
dfd52f2b 2026 if (n_words < 0)
2027 *plen = -n_words;
2028 else
2029 *plen += n_words;
9ce2d202 2030 }
02d9a2c3 2031
2032 return "";
9ce2d202 2033}
2034
2035
20c71901 2036/* Return a pointer register name as a string. */
a28e4651 2037
0dff9558 2038static const char*
206a5129 2039ptrreg_to_str (int regno)
a28e4651 2040{
2041 switch (regno)
2042 {
2043 case REG_X: return "X";
2044 case REG_Y: return "Y";
2045 case REG_Z: return "Z";
2046 default:
a45076aa 2047 output_operand_lossage ("address operand requires constraint for"
2048 " X, Y, or Z register");
a28e4651 2049 }
2050 return NULL;
2051}
2052
2053/* Return the condition name as a string.
2054 Used in conditional jump constructing */
2055
0dff9558 2056static const char*
206a5129 2057cond_string (enum rtx_code code)
a28e4651 2058{
2059 switch (code)
2060 {
2061 case NE:
2062 return "ne";
2063 case EQ:
2064 return "eq";
2065 case GE:
2066 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
0dff9558 2067 return "pl";
a28e4651 2068 else
0dff9558 2069 return "ge";
a28e4651 2070 case LT:
2071 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
0dff9558 2072 return "mi";
a28e4651 2073 else
0dff9558 2074 return "lt";
a28e4651 2075 case GEU:
2076 return "sh";
a28e4651 2077 case LTU:
2078 return "lo";
2079 default:
8ef66241 2080 gcc_unreachable ();
a28e4651 2081 }
02d9a2c3 2082
2083 return "";
a28e4651 2084}
2085
62a6a7ee 2086
2087/* Implement `TARGET_PRINT_OPERAND_ADDRESS'. */
20c71901 2088/* Output ADDR to FILE as address. */
a28e4651 2089
62a6a7ee 2090static void
2091avr_print_operand_address (FILE *file, rtx addr)
a28e4651 2092{
2093 switch (GET_CODE (addr))
2094 {
2095 case REG:
2096 fprintf (file, ptrreg_to_str (REGNO (addr)));
2097 break;
2098
2099 case PRE_DEC:
2100 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
2101 break;
2102
2103 case POST_INC:
2104 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
2105 break;
2106
2107 default:
2108 if (CONSTANT_ADDRESS_P (addr)
0dff9558 2109 && text_segment_operand (addr, VOIDmode))
2110 {
2111 rtx x = addr;
2112 if (GET_CODE (x) == CONST)
2113 x = XEXP (x, 0);
2114 if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x,1)) == CONST_INT)
2115 {
2116 /* Assembler gs() will implant word address. Make offset
2117 a byte offset inside gs() for assembler. This is
2118 needed because the more logical (constant+gs(sym)) is not
2119 accepted by gas. For 128K and smaller devices this is ok.
2120 For large devices it will create a trampoline to offset
a45076aa 2121 from symbol which may not be what the user really wanted. */
0dff9558 2122
2123 fprintf (file, "gs(");
2124 output_addr_const (file, XEXP (x,0));
a45076aa 2125 fprintf (file, "+" HOST_WIDE_INT_PRINT_DEC ")",
2126 2 * INTVAL (XEXP (x, 1)));
0dff9558 2127 if (AVR_3_BYTE_PC)
2128 if (warning (0, "pointer offset from symbol maybe incorrect"))
2129 {
2130 output_addr_const (stderr, addr);
2131 fprintf(stderr,"\n");
2132 }
2133 }
2134 else
2135 {
2136 fprintf (file, "gs(");
2137 output_addr_const (file, addr);
2138 fprintf (file, ")");
2139 }
2140 }
a28e4651 2141 else
0dff9558 2142 output_addr_const (file, addr);
a28e4651 2143 }
2144}
2145
2146
62a6a7ee 2147/* Implement `TARGET_PRINT_OPERAND_PUNCT_VALID_P'. */
2148
2149static bool
2150avr_print_operand_punct_valid_p (unsigned char code)
2151{
2152 return code == '~' || code == '!';
2153}
2154
2155
2156/* Implement `TARGET_PRINT_OPERAND'. */
384f6361 2157/* Output X as assembler operand to file FILE.
2158 For a description of supported %-codes, see top of avr.md. */
2159
62a6a7ee 2160static void
2161avr_print_operand (FILE *file, rtx x, int code)
a28e4651 2162{
b4e6d2e2 2163 int abcd = 0, ef = 0, ij = 0;
a28e4651 2164
2165 if (code >= 'A' && code <= 'D')
2166 abcd = code - 'A';
b4e6d2e2 2167 else if (code == 'E' || code == 'F')
2168 ef = code - 'E';
2169 else if (code == 'I' || code == 'J')
2170 ij = code - 'I';
a28e4651 2171
3b351734 2172 if (code == '~')
2173 {
4f0e2214 2174 if (!AVR_HAVE_JMP_CALL)
0dff9558 2175 fputc ('r', file);
3b351734 2176 }
90ef7269 2177 else if (code == '!')
2178 {
2179 if (AVR_HAVE_EIJMP_EICALL)
0dff9558 2180 fputc ('e', file);
90ef7269 2181 }
384f6361 2182 else if (code == 't'
2183 || code == 'T')
2184 {
2185 static int t_regno = -1;
2186 static int t_nbits = -1;
2187
2188 if (REG_P (x) && t_regno < 0 && code == 'T')
2189 {
2190 t_regno = REGNO (x);
2191 t_nbits = GET_MODE_BITSIZE (GET_MODE (x));
2192 }
2193 else if (CONST_INT_P (x) && t_regno >= 0
2194 && IN_RANGE (INTVAL (x), 0, t_nbits - 1))
2195 {
2196 int bpos = INTVAL (x);
2197
2198 fprintf (file, "%s", reg_names[t_regno + bpos / 8]);
2199 if (code == 'T')
2200 fprintf (file, ",%d", bpos % 8);
2201
2202 t_regno = -1;
2203 }
2204 else
2205 fatal_insn ("operands to %T/%t must be reg + const_int:", x);
2206 }
b4e6d2e2 2207 else if (code == 'E' || code == 'F')
2208 {
2209 rtx op = XEXP(x, 0);
2210 fprintf (file, reg_names[REGNO (op) + ef]);
2211 }
2212 else if (code == 'I' || code == 'J')
2213 {
2214 rtx op = XEXP(XEXP(x, 0), 0);
2215 fprintf (file, reg_names[REGNO (op) + ij]);
2216 }
3b351734 2217 else if (REG_P (x))
a28e4651 2218 {
2219 if (x == zero_reg_rtx)
b4ebb666 2220 fprintf (file, "__zero_reg__");
2221 else if (code == 'r' && REGNO (x) < 32)
2222 fprintf (file, "%d", (int) REGNO (x));
a28e4651 2223 else
b4ebb666 2224 fprintf (file, reg_names[REGNO (x) + abcd]);
a28e4651 2225 }
96871982 2226 else if (CONST_INT_P (x))
2227 {
2228 HOST_WIDE_INT ival = INTVAL (x);
0dff9558 2229
96871982 2230 if ('i' != code)
2231 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival + abcd);
2232 else if (low_io_address_operand (x, VOIDmode)
2233 || high_io_address_operand (x, VOIDmode))
2234 {
0b6cf66f 2235 if (AVR_HAVE_RAMPZ && ival == avr_addr.rampz)
2236 fprintf (file, "__RAMPZ__");
2237 else if (AVR_HAVE_RAMPY && ival == avr_addr.rampy)
2238 fprintf (file, "__RAMPY__");
2239 else if (AVR_HAVE_RAMPX && ival == avr_addr.rampx)
2240 fprintf (file, "__RAMPX__");
2241 else if (AVR_HAVE_RAMPD && ival == avr_addr.rampd)
2242 fprintf (file, "__RAMPD__");
b4e6d2e2 2243 else if ((AVR_XMEGA || AVR_TINY) && ival == avr_addr.ccp)
0b6cf66f 2244 fprintf (file, "__CCP__");
72851b68 2245 else if (ival == avr_addr.sreg) fprintf (file, "__SREG__");
2246 else if (ival == avr_addr.sp_l) fprintf (file, "__SP_L__");
2247 else if (ival == avr_addr.sp_h) fprintf (file, "__SP_H__");
2248 else
96871982 2249 {
96871982 2250 fprintf (file, HOST_WIDE_INT_PRINT_HEX,
2251 ival - avr_current_arch->sfr_offset);
96871982 2252 }
2253 }
2254 else
2255 fatal_insn ("bad address, not an I/O address:", x);
2256 }
2257 else if (MEM_P (x))
a28e4651 2258 {
a45076aa 2259 rtx addr = XEXP (x, 0);
0dff9558 2260
310f64db 2261 if (code == 'm')
0dff9558 2262 {
a45076aa 2263 if (!CONSTANT_P (addr))
644ac9c5 2264 fatal_insn ("bad address, not a constant:", addr);
a45076aa 2265 /* Assembler template with m-code is data - not progmem section */
2266 if (text_segment_operand (addr, VOIDmode))
2267 if (warning (0, "accessing data memory with"
2268 " program memory address"))
2269 {
2270 output_addr_const (stderr, addr);
2271 fprintf(stderr,"\n");
2272 }
2273 output_addr_const (file, addr);
0dff9558 2274 }
644ac9c5 2275 else if (code == 'i')
2276 {
62a6a7ee 2277 avr_print_operand (file, addr, 'i');
644ac9c5 2278 }
3b351734 2279 else if (code == 'o')
0dff9558 2280 {
2281 if (GET_CODE (addr) != PLUS)
2282 fatal_insn ("bad address, not (reg+disp):", addr);
3b351734 2283
0dff9558 2284 avr_print_operand (file, XEXP (addr, 1), 0);
2285 }
b4e6d2e2 2286 else if (code == 'b')
2287 {
2288 if (GET_CODE (addr) != PLUS)
2289 fatal_insn ("bad address, not (reg+disp):", addr);
2290
2291 avr_print_operand_address (file, XEXP (addr, 0));
2292 }
f43bae99 2293 else if (code == 'p' || code == 'r')
2294 {
2295 if (GET_CODE (addr) != POST_INC && GET_CODE (addr) != PRE_DEC)
2296 fatal_insn ("bad address, not post_inc or pre_dec:", addr);
0dff9558 2297
f43bae99 2298 if (code == 'p')
62a6a7ee 2299 avr_print_operand_address (file, XEXP (addr, 0)); /* X, Y, Z */
f43bae99 2300 else
62a6a7ee 2301 avr_print_operand (file, XEXP (addr, 0), 0); /* r26, r28, r30 */
f43bae99 2302 }
a28e4651 2303 else if (GET_CODE (addr) == PLUS)
0dff9558 2304 {
2305 avr_print_operand_address (file, XEXP (addr,0));
2306 if (REGNO (XEXP (addr, 0)) == REG_X)
2307 fatal_insn ("internal compiler error. Bad address:"
2308 ,addr);
2309 fputc ('+', file);
2310 avr_print_operand (file, XEXP (addr,1), code);
2311 }
a28e4651 2312 else
0dff9558 2313 avr_print_operand_address (file, addr);
a28e4651 2314 }
96871982 2315 else if (code == 'i')
2316 {
c0d7a1d0 2317 if (GET_CODE (x) == SYMBOL_REF && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO))
2318 avr_print_operand_address
2319 (file, plus_constant (HImode, x, -avr_current_arch->sfr_offset));
2320 else
2321 fatal_insn ("bad address, not an I/O address:", x);
96871982 2322 }
310f64db 2323 else if (code == 'x')
2324 {
2325 /* Constant progmem address - like used in jmp or call */
2326 if (0 == text_segment_operand (x, VOIDmode))
a45076aa 2327 if (warning (0, "accessing program memory"
2328 " with data memory address"))
0dff9558 2329 {
2330 output_addr_const (stderr, x);
2331 fprintf(stderr,"\n");
2332 }
310f64db 2333 /* Use normal symbol for direct address no linker trampoline needed */
2334 output_addr_const (file, x);
2335 }
b4ebb666 2336 else if (CONST_FIXED_P (x))
017c5b98 2337 {
2338 HOST_WIDE_INT ival = INTVAL (avr_to_int_mode (x));
2339 if (code != 0)
803e7ca1 2340 output_operand_lossage ("Unsupported code '%c' for fixed-point:",
017c5b98 2341 code);
2342 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);
2343 }
a28e4651 2344 else if (GET_CODE (x) == CONST_DOUBLE)
2345 {
2346 long val;
2347 REAL_VALUE_TYPE rv;
2348 if (GET_MODE (x) != SFmode)
0dff9558 2349 fatal_insn ("internal compiler error. Unknown mode:", x);
a28e4651 2350 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
2351 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
7fe1d31c 2352 fprintf (file, "0x%lx", val);
a28e4651 2353 }
5bd39e93 2354 else if (GET_CODE (x) == CONST_STRING)
2355 fputs (XSTR (x, 0), file);
a28e4651 2356 else if (code == 'j')
7fe1d31c 2357 fputs (cond_string (GET_CODE (x)), file);
a28e4651 2358 else if (code == 'k')
7fe1d31c 2359 fputs (cond_string (reverse_condition (GET_CODE (x))), file);
a28e4651 2360 else
62a6a7ee 2361 avr_print_operand_address (file, x);
a28e4651 2362}
2363
0dff9558 2364
2365/* Worker function for `NOTICE_UPDATE_CC'. */
a28e4651 2366/* Update the condition code in the INSN. */
2367
2368void
ed3e6e5d 2369avr_notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx_insn *insn)
a28e4651 2370{
1cb39658 2371 rtx set;
bcad9375 2372 enum attr_cc cc = get_attr_cc (insn);
0dff9558 2373
bcad9375 2374 switch (cc)
a28e4651 2375 {
bcad9375 2376 default:
2377 break;
2378
b4ebb666 2379 case CC_PLUS:
f4806884 2380 case CC_LDI:
bcad9375 2381 {
2382 rtx *op = recog_data.operand;
2383 int len_dummy, icc;
0dff9558 2384
bcad9375 2385 /* Extract insn's operands. */
2386 extract_constrain_insn_cached (insn);
eac146f2 2387
f4806884 2388 switch (cc)
2389 {
2390 default:
2391 gcc_unreachable();
0dff9558 2392
b4ebb666 2393 case CC_PLUS:
2394 avr_out_plus (insn, op, &len_dummy, &icc);
017c5b98 2395 cc = (enum attr_cc) icc;
2396 break;
2397
f4806884 2398 case CC_LDI:
2399
2400 cc = (op[1] == CONST0_RTX (GET_MODE (op[0]))
2401 && reg_overlap_mentioned_p (op[0], zero_reg_rtx))
0dff9558 2402 /* Loading zero-reg with 0 uses CLR and thus clobbers cc0. */
f4806884 2403 ? CC_CLOBBER
2404 /* Any other "r,rL" combination does not alter cc0. */
2405 : CC_NONE;
0dff9558 2406
f4806884 2407 break;
2408 } /* inner switch */
2409
bcad9375 2410 break;
2411 }
f4806884 2412 } /* outer swicth */
bcad9375 2413
2414 switch (cc)
2415 {
2416 default:
2417 /* Special values like CC_OUT_PLUS from above have been
2418 mapped to "standard" CC_* values so we never come here. */
0dff9558 2419
bcad9375 2420 gcc_unreachable();
2421 break;
0dff9558 2422
a28e4651 2423 case CC_NONE:
2424 /* Insn does not affect CC at all. */
2425 break;
2426
2427 case CC_SET_N:
2428 CC_STATUS_INIT;
2429 break;
2430
2431 case CC_SET_ZN:
1cb39658 2432 set = single_set (insn);
2433 CC_STATUS_INIT;
2434 if (set)
0dff9558 2435 {
2436 cc_status.flags |= CC_NO_OVERFLOW;
2437 cc_status.value1 = SET_DEST (set);
2438 }
a28e4651 2439 break;
2440
c455e5d3 2441 case CC_SET_VZN:
2442 /* Insn like INC, DEC, NEG that set Z,N,V. We currently don't make use
2443 of this combination, cf. also PR61055. */
2444 CC_STATUS_INIT;
2445 break;
2446
a28e4651 2447 case CC_SET_CZN:
2448 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
2449 The V flag may or may not be known but that's ok because
2450 alter_cond will change tests to use EQ/NE. */
1cb39658 2451 set = single_set (insn);
2452 CC_STATUS_INIT;
2453 if (set)
0dff9558 2454 {
2455 cc_status.value1 = SET_DEST (set);
2456 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
2457 }
a28e4651 2458 break;
2459
2460 case CC_COMPARE:
1cb39658 2461 set = single_set (insn);
2462 CC_STATUS_INIT;
2463 if (set)
0dff9558 2464 cc_status.value1 = SET_SRC (set);
a28e4651 2465 break;
0dff9558 2466
a28e4651 2467 case CC_CLOBBER:
2468 /* Insn doesn't leave CC in a usable state. */
2469 CC_STATUS_INIT;
2470 break;
2471 }
2472}
2473
a28e4651 2474/* Choose mode for jump insn:
2475 1 - relative jump in range -63 <= x <= 62 ;
2476 2 - relative jump in range -2046 <= x <= 2045 ;
2477 3 - absolute jump (only for ATmega[16]03). */
2478
2479int
375204de 2480avr_jump_mode (rtx x, rtx_insn *insn)
a28e4651 2481{
ef51d1e3 2482 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_CODE (x) == LABEL_REF
0dff9558 2483 ? XEXP (x, 0) : x));
47fc0706 2484 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
a28e4651 2485 int jump_distance = cur_addr - dest_addr;
0dff9558 2486
a28e4651 2487 if (-63 <= jump_distance && jump_distance <= 62)
2488 return 1;
2489 else if (-2046 <= jump_distance && jump_distance <= 2045)
2490 return 2;
4f0e2214 2491 else if (AVR_HAVE_JMP_CALL)
a28e4651 2492 return 3;
0dff9558 2493
a28e4651 2494 return 2;
2495}
2496
0dff9558 2497/* Return an AVR condition jump commands.
e7d17bf3 2498 X is a comparison RTX.
2499 LEN is a number returned by avr_jump_mode function.
0dff9558 2500 If REVERSE nonzero then condition code in X must be reversed. */
a28e4651 2501
0dff9558 2502const char*
206a5129 2503ret_cond_branch (rtx x, int len, int reverse)
a28e4651 2504{
e7d17bf3 2505 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
0dff9558 2506
a28e4651 2507 switch (cond)
2508 {
2509 case GT:
2510 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
02a011e9 2511 return (len == 1 ? ("breq .+2" CR_TAB
2512 "brpl %0") :
2513 len == 2 ? ("breq .+4" CR_TAB
2514 "brmi .+2" CR_TAB
2515 "rjmp %0") :
2516 ("breq .+6" CR_TAB
2517 "brmi .+4" CR_TAB
2518 "jmp %0"));
0dff9558 2519
a28e4651 2520 else
02a011e9 2521 return (len == 1 ? ("breq .+2" CR_TAB
2522 "brge %0") :
2523 len == 2 ? ("breq .+4" CR_TAB
2524 "brlt .+2" CR_TAB
2525 "rjmp %0") :
2526 ("breq .+6" CR_TAB
2527 "brlt .+4" CR_TAB
2528 "jmp %0"));
a28e4651 2529 case GTU:
02a011e9 2530 return (len == 1 ? ("breq .+2" CR_TAB
2531 "brsh %0") :
2532 len == 2 ? ("breq .+4" CR_TAB
2533 "brlo .+2" CR_TAB
2534 "rjmp %0") :
2535 ("breq .+6" CR_TAB
2536 "brlo .+4" CR_TAB
2537 "jmp %0"));
a28e4651 2538 case LE:
2539 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
02a011e9 2540 return (len == 1 ? ("breq %0" CR_TAB
2541 "brmi %0") :
2542 len == 2 ? ("breq .+2" CR_TAB
2543 "brpl .+2" CR_TAB
2544 "rjmp %0") :
2545 ("breq .+2" CR_TAB
2546 "brpl .+4" CR_TAB
2547 "jmp %0"));
a28e4651 2548 else
02a011e9 2549 return (len == 1 ? ("breq %0" CR_TAB
2550 "brlt %0") :
2551 len == 2 ? ("breq .+2" CR_TAB
2552 "brge .+2" CR_TAB
2553 "rjmp %0") :
2554 ("breq .+2" CR_TAB
2555 "brge .+4" CR_TAB
2556 "jmp %0"));
a28e4651 2557 case LEU:
02a011e9 2558 return (len == 1 ? ("breq %0" CR_TAB
2559 "brlo %0") :
2560 len == 2 ? ("breq .+2" CR_TAB
2561 "brsh .+2" CR_TAB
2562 "rjmp %0") :
2563 ("breq .+2" CR_TAB
2564 "brsh .+4" CR_TAB
2565 "jmp %0"));
a28e4651 2566 default:
e7d17bf3 2567 if (reverse)
2568 {
2569 switch (len)
2570 {
2571 case 1:
02a011e9 2572 return "br%k1 %0";
e7d17bf3 2573 case 2:
02a011e9 2574 return ("br%j1 .+2" CR_TAB
2575 "rjmp %0");
e7d17bf3 2576 default:
02a011e9 2577 return ("br%j1 .+4" CR_TAB
2578 "jmp %0");
e7d17bf3 2579 }
2580 }
02a011e9 2581 else
2582 {
2583 switch (len)
2584 {
2585 case 1:
2586 return "br%j1 %0";
2587 case 2:
2588 return ("br%k1 .+2" CR_TAB
2589 "rjmp %0");
2590 default:
2591 return ("br%k1 .+4" CR_TAB
2592 "jmp %0");
2593 }
2594 }
a28e4651 2595 }
2596 return "";
2597}
2598
0dff9558 2599
2600/* Worker function for `FINAL_PRESCAN_INSN'. */
fe74bc77 2601/* Output insn cost for next insn. */
a28e4651 2602
2603void
375204de 2604avr_final_prescan_insn (rtx_insn *insn, rtx *operand ATTRIBUTE_UNUSED,
0dff9558 2605 int num_operands ATTRIBUTE_UNUSED)
a28e4651 2606{
ae86bb47 2607 if (avr_log.rtx_costs)
a28e4651 2608 {
114786e6 2609 rtx set = single_set (insn);
2610
2611 if (set)
2612 fprintf (asm_out_file, "/* DEBUG: cost = %d. */\n",
7013e87c 2613 set_src_cost (SET_SRC (set), optimize_insn_for_speed_p ()));
114786e6 2614 else
2615 fprintf (asm_out_file, "/* DEBUG: pattern-cost = %d. */\n",
20d892d1 2616 rtx_cost (PATTERN (insn), INSN, 0,
0dff9558 2617 optimize_insn_for_speed_p()));
a28e4651 2618 }
a28e4651 2619}
2620
37ac04dc 2621/* Return 0 if undefined, 1 if always true or always false. */
a28e4651 2622
2623int
3754d046 2624avr_simplify_comparison_p (machine_mode mode, RTX_CODE op, rtx x)
a28e4651 2625{
2626 unsigned int max = (mode == QImode ? 0xff :
2627 mode == HImode ? 0xffff :
02d9a2c3 2628 mode == PSImode ? 0xffffff :
30435bf8 2629 mode == SImode ? 0xffffffff : 0);
0dff9558 2630 if (max && op && CONST_INT_P (x))
a28e4651 2631 {
8deb3959 2632 if (unsigned_condition (op) != op)
0dff9558 2633 max >>= 1;
a28e4651 2634
2635 if (max != (INTVAL (x) & max)
0dff9558 2636 && INTVAL (x) != 0xff)
2637 return 1;
a28e4651 2638 }
2639 return 0;
2640}
2641
2642
0dff9558 2643/* Worker function for `FUNCTION_ARG_REGNO_P'. */
a28e4651 2644/* Returns nonzero if REGNO is the number of a hard
2645 register in which function arguments are sometimes passed. */
2646
2647int
0dff9558 2648avr_function_arg_regno_p(int r)
a28e4651 2649{
b4e6d2e2 2650 return (AVR_TINY ? r >= 20 && r <= 25 : r >= 8 && r <= 25);
a28e4651 2651}
2652
0dff9558 2653
2654/* Worker function for `INIT_CUMULATIVE_ARGS'. */
a28e4651 2655/* Initializing the variable cum for the state at the beginning
2656 of the argument list. */
2657
2658void
0dff9558 2659avr_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
2660 tree fndecl ATTRIBUTE_UNUSED)
a28e4651 2661{
b4e6d2e2 2662 cum->nregs = AVR_TINY ? 6 : 18;
a28e4651 2663 cum->regno = FIRST_CUM_REG;
257d99c3 2664 if (!libname && stdarg_p (fntype))
2665 cum->nregs = 0;
32969c63 2666
2667 /* Assume the calle may be tail called */
0dff9558 2668
32969c63 2669 cfun->machine->sibcall_fails = 0;
a28e4651 2670}
2671
0af74aa0 2672/* Returns the number of registers to allocate for a function argument. */
2673
2674static int
3754d046 2675avr_num_arg_regs (machine_mode mode, const_tree type)
0af74aa0 2676{
2677 int size;
2678
2679 if (mode == BLKmode)
2680 size = int_size_in_bytes (type);
2681 else
2682 size = GET_MODE_SIZE (mode);
2683
b681d971 2684 /* Align all function arguments to start in even-numbered registers.
2685 Odd-sized arguments leave holes above them. */
0af74aa0 2686
b681d971 2687 return (size + 1) & ~1;
0af74aa0 2688}
2689
0dff9558 2690
2691/* Implement `TARGET_FUNCTION_ARG'. */
a28e4651 2692/* Controls whether a function argument is passed
20c71901 2693 in a register, and which register. */
a28e4651 2694
e8509bef 2695static rtx
3754d046 2696avr_function_arg (cumulative_args_t cum_v, machine_mode mode,
0dff9558 2697 const_tree type, bool named ATTRIBUTE_UNUSED)
a28e4651 2698{
39cba157 2699 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
0af74aa0 2700 int bytes = avr_num_arg_regs (mode, type);
a28e4651 2701
2702 if (cum->nregs && bytes <= cum->nregs)
1a83b3ff 2703 return gen_rtx_REG (mode, cum->regno - bytes);
0af74aa0 2704
a28e4651 2705 return NULL_RTX;
2706}
2707
0dff9558 2708
2709/* Implement `TARGET_FUNCTION_ARG_ADVANCE'. */
a28e4651 2710/* Update the summarizer variable CUM to advance past an argument
2711 in the argument list. */
0dff9558 2712
e8509bef 2713static void
3754d046 2714avr_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
0dff9558 2715 const_tree type, bool named ATTRIBUTE_UNUSED)
a28e4651 2716{
39cba157 2717 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
0af74aa0 2718 int bytes = avr_num_arg_regs (mode, type);
a28e4651 2719
a28e4651 2720 cum->nregs -= bytes;
2721 cum->regno -= bytes;
2722
0dff9558 2723 /* A parameter is being passed in a call-saved register. As the original
32969c63 2724 contents of these regs has to be restored before leaving the function,
2725 a function must not pass arguments in call-saved regs in order to get
0dff9558 2726 tail-called. */
2727
e46ab6d3 2728 if (cum->regno >= 8
2729 && cum->nregs >= 0
32969c63 2730 && !call_used_regs[cum->regno])
2731 {
2732 /* FIXME: We ship info on failing tail-call in struct machine_function.
2733 This uses internals of calls.c:expand_call() and the way args_so_far
0dff9558 2734 is used. targetm.function_ok_for_sibcall() needs to be extended to
2735 pass &args_so_far, too. At present, CUMULATIVE_ARGS is target
2736 dependent so that such an extension is not wanted. */
2737
32969c63 2738 cfun->machine->sibcall_fails = 1;
2739 }
2740
04f600bb 2741 /* Test if all registers needed by the ABI are actually available. If the
2742 user has fixed a GPR needed to pass an argument, an (implicit) function
363cd51e 2743 call will clobber that fixed register. See PR45099 for an example. */
0dff9558 2744
e46ab6d3 2745 if (cum->regno >= 8
2746 && cum->nregs >= 0)
04f600bb 2747 {
2748 int regno;
2749
2750 for (regno = cum->regno; regno < cum->regno + bytes; regno++)
2751 if (fixed_regs[regno])
363cd51e 2752 warning (0, "fixed register %s used to pass parameter to function",
2753 reg_names[regno]);
04f600bb 2754 }
0dff9558 2755
a28e4651 2756 if (cum->nregs <= 0)
2757 {
2758 cum->nregs = 0;
2759 cum->regno = FIRST_CUM_REG;
2760 }
a28e4651 2761}
2762
32969c63 2763/* Implement `TARGET_FUNCTION_OK_FOR_SIBCALL' */
2764/* Decide whether we can make a sibling call to a function. DECL is the
2765 declaration of the function being targeted by the call and EXP is the
0dff9558 2766 CALL_EXPR representing the call. */
32969c63 2767
2768static bool
2769avr_function_ok_for_sibcall (tree decl_callee, tree exp_callee)
2770{
2771 tree fntype_callee;
2772
2773 /* Tail-calling must fail if callee-saved regs are used to pass
2774 function args. We must not tail-call when `epilogue_restores'
2775 is used. Unfortunately, we cannot tell at this point if that
2776 actually will happen or not, and we cannot step back from
0dff9558 2777 tail-calling. Thus, we inhibit tail-calling with -mcall-prologues. */
2778
32969c63 2779 if (cfun->machine->sibcall_fails
2780 || TARGET_CALL_PROLOGUES)
2781 {
2782 return false;
2783 }
0dff9558 2784
32969c63 2785 fntype_callee = TREE_TYPE (CALL_EXPR_FN (exp_callee));
2786
2787 if (decl_callee)
2788 {
2789 decl_callee = TREE_TYPE (decl_callee);
2790 }
2791 else
2792 {
2793 decl_callee = fntype_callee;
0dff9558 2794
32969c63 2795 while (FUNCTION_TYPE != TREE_CODE (decl_callee)
2796 && METHOD_TYPE != TREE_CODE (decl_callee))
2797 {
2798 decl_callee = TREE_TYPE (decl_callee);
2799 }
2800 }
2801
2802 /* Ensure that caller and callee have compatible epilogues */
0dff9558 2803
ea679361 2804 if (cfun->machine->is_interrupt
2805 || cfun->machine->is_signal
2806 || cfun->machine->is_naked
32969c63 2807 || avr_naked_function_p (decl_callee)
0dff9558 2808 /* FIXME: For OS_task and OS_main, this might be over-conservative. */
32969c63 2809 || (avr_OS_task_function_p (decl_callee)
ea679361 2810 != cfun->machine->is_OS_task)
32969c63 2811 || (avr_OS_main_function_p (decl_callee)
ea679361 2812 != cfun->machine->is_OS_main))
32969c63 2813 {
2814 return false;
2815 }
0dff9558 2816
32969c63 2817 return true;
2818}
2819
a28e4651 2820/***********************************************************************
2821 Functions for outputting various mov's for a various modes
2822************************************************************************/
4202ef11 2823
2824/* Return true if a value of mode MODE is read from flash by
2825 __load_* function from libgcc. */
2826
2827bool
2828avr_load_libgcc_p (rtx op)
2829{
3754d046 2830 machine_mode mode = GET_MODE (op);
4202ef11 2831 int n_bytes = GET_MODE_SIZE (mode);
0dff9558 2832
4202ef11 2833 return (n_bytes > 2
2834 && !AVR_HAVE_LPMX
be6d8823 2835 && avr_mem_flash_p (op));
4202ef11 2836}
2837
5bd39e93 2838/* Return true if a value of mode MODE is read by __xload_* function. */
2839
2840bool
3754d046 2841avr_xload_libgcc_p (machine_mode mode)
5bd39e93 2842{
2843 int n_bytes = GET_MODE_SIZE (mode);
0dff9558 2844
5bd39e93 2845 return (n_bytes > 1
c0d7a1d0 2846 || avr_n_flash > 1);
5bd39e93 2847}
2848
2849
be6d8823 2850/* Fixme: This is a hack because secondary reloads don't works as expected.
2851
2852 Find an unused d-register to be used as scratch in INSN.
2853 EXCLUDE is either NULL_RTX or some register. In the case where EXCLUDE
2854 is a register, skip all possible return values that overlap EXCLUDE.
2855 The policy for the returned register is similar to that of
2856 `reg_unused_after', i.e. the returned register may overlap the SET_DEST
2857 of INSN.
2858
2859 Return a QImode d-register or NULL_RTX if nothing found. */
2860
2861static rtx
375204de 2862avr_find_unused_d_reg (rtx_insn *insn, rtx exclude)
be6d8823 2863{
2864 int regno;
2865 bool isr_p = (avr_interrupt_function_p (current_function_decl)
2866 || avr_signal_function_p (current_function_decl));
2867
2868 for (regno = 16; regno < 32; regno++)
2869 {
2870 rtx reg = all_regs_rtx[regno];
0dff9558 2871
be6d8823 2872 if ((exclude
2873 && reg_overlap_mentioned_p (exclude, reg))
2874 || fixed_regs[regno])
2875 {
2876 continue;
2877 }
2878
2879 /* Try non-live register */
2880
2881 if (!df_regs_ever_live_p (regno)
2882 && (TREE_THIS_VOLATILE (current_function_decl)
2883 || cfun->machine->is_OS_task
2884 || cfun->machine->is_OS_main
2885 || (!isr_p && call_used_regs[regno])))
2886 {
2887 return reg;
2888 }
2889
2890 /* Any live register can be used if it is unused after.
2891 Prologue/epilogue will care for it as needed. */
0dff9558 2892
be6d8823 2893 if (df_regs_ever_live_p (regno)
2894 && reg_unused_after (insn, reg))
2895 {
2896 return reg;
2897 }
2898 }
2899
2900 return NULL_RTX;
2901}
2902
2903
2904/* Helper function for the next function in the case where only restricted
2905 version of LPM instruction is available. */
2906
2907static const char*
375204de 2908avr_out_lpm_no_lpmx (rtx_insn *insn, rtx *xop, int *plen)
be6d8823 2909{
2910 rtx dest = xop[0];
2911 rtx addr = xop[1];
2912 int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
2913 int regno_dest;
2914
2915 regno_dest = REGNO (dest);
2916
2917 /* The implicit target register of LPM. */
2918 xop[3] = lpm_reg_rtx;
2919
2920 switch (GET_CODE (addr))
2921 {
2922 default:
2923 gcc_unreachable();
2924
2925 case REG:
2926
2927 gcc_assert (REG_Z == REGNO (addr));
2928
2929 switch (n_bytes)
2930 {
2931 default:
2932 gcc_unreachable();
2933
2934 case 1:
2935 avr_asm_len ("%4lpm", xop, plen, 1);
2936
2937 if (regno_dest != LPM_REGNO)
2938 avr_asm_len ("mov %0,%3", xop, plen, 1);
2939
2940 return "";
2941
2942 case 2:
2943 if (REGNO (dest) == REG_Z)
2944 return avr_asm_len ("%4lpm" CR_TAB
2945 "push %3" CR_TAB
2946 "adiw %2,1" CR_TAB
2947 "%4lpm" CR_TAB
2948 "mov %B0,%3" CR_TAB
2949 "pop %A0", xop, plen, 6);
0dff9558 2950
be6d8823 2951 avr_asm_len ("%4lpm" CR_TAB
2952 "mov %A0,%3" CR_TAB
2953 "adiw %2,1" CR_TAB
2954 "%4lpm" CR_TAB
2955 "mov %B0,%3", xop, plen, 5);
0dff9558 2956
be6d8823 2957 if (!reg_unused_after (insn, addr))
2958 avr_asm_len ("sbiw %2,1", xop, plen, 1);
0dff9558 2959
be6d8823 2960 break; /* 2 */
2961 }
0dff9558 2962
be6d8823 2963 break; /* REG */
2964
2965 case POST_INC:
2966
2967 gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
2968 && n_bytes <= 4);
2969
2970 if (regno_dest == LPM_REGNO)
2971 avr_asm_len ("%4lpm" CR_TAB
2972 "adiw %2,1", xop, plen, 2);
2973 else
2974 avr_asm_len ("%4lpm" CR_TAB
2975 "mov %A0,%3" CR_TAB
2976 "adiw %2,1", xop, plen, 3);
2977
2978 if (n_bytes >= 2)
2979 avr_asm_len ("%4lpm" CR_TAB
2980 "mov %B0,%3" CR_TAB
2981 "adiw %2,1", xop, plen, 3);
2982
2983 if (n_bytes >= 3)
2984 avr_asm_len ("%4lpm" CR_TAB
2985 "mov %C0,%3" CR_TAB
2986 "adiw %2,1", xop, plen, 3);
2987
2988 if (n_bytes >= 4)
2989 avr_asm_len ("%4lpm" CR_TAB
2990 "mov %D0,%3" CR_TAB
2991 "adiw %2,1", xop, plen, 3);
2992
2993 break; /* POST_INC */
0dff9558 2994
be6d8823 2995 } /* switch CODE (addr) */
0dff9558 2996
be6d8823 2997 return "";
2998}
2999
3000
4202ef11 3001/* If PLEN == NULL: Ouput instructions to load a value from a memory location
3002 OP[1] in AS1 to register OP[0].
3003 If PLEN != 0 set *PLEN to the length in words of the instruction sequence.
3004 Return "". */
3005
4b72e680 3006const char*
375204de 3007avr_out_lpm (rtx_insn *insn, rtx *op, int *plen)
4202ef11 3008{
be6d8823 3009 rtx xop[7];
4202ef11 3010 rtx dest = op[0];
3011 rtx src = SET_SRC (single_set (insn));
3012 rtx addr;
3013 int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
be6d8823 3014 int segment;
9d734fa8 3015 RTX_CODE code;
ed2541ea 3016 addr_space_t as = MEM_ADDR_SPACE (src);
4202ef11 3017
3018 if (plen)
3019 *plen = 0;
0dff9558 3020
4202ef11 3021 if (MEM_P (dest))
3022 {
3023 warning (0, "writing to address space %qs not supported",
9d734fa8 3024 avr_addrspace[MEM_ADDR_SPACE (dest)].name);
0dff9558 3025
4202ef11 3026 return "";
3027 }
3028
9d734fa8 3029 addr = XEXP (src, 0);
3030 code = GET_CODE (addr);
5bd39e93 3031
9d734fa8 3032 gcc_assert (REG_P (dest));
ed2541ea 3033 gcc_assert (REG == code || POST_INC == code);
4202ef11 3034
002565f0 3035 xop[0] = dest;
be6d8823 3036 xop[1] = addr;
3037 xop[2] = lpm_addr_reg_rtx;
3038 xop[4] = xstring_empty;
3039 xop[5] = tmp_reg_rtx;
3040 xop[6] = XEXP (rampz_rtx, 0);
9d734fa8 3041
be6d8823 3042 segment = avr_addrspace[as].segment;
3043
3044 /* Set RAMPZ as needed. */
3045
3046 if (segment)
3047 {
3048 xop[4] = GEN_INT (segment);
3049 xop[3] = avr_find_unused_d_reg (insn, lpm_addr_reg_rtx);
3050
3051 if (xop[3] != NULL_RTX)
3052 {
3053 avr_asm_len ("ldi %3,%4" CR_TAB
3054 "out %i6,%3", xop, plen, 2);
3055 }
3056 else if (segment == 1)
3057 {
3058 avr_asm_len ("clr %5" CR_TAB
3059 "inc %5" CR_TAB
3060 "out %i6,%5", xop, plen, 3);
3061 }
3062 else
3063 {
3064 avr_asm_len ("mov %5,%2" CR_TAB
3065 "ldi %2,%4" CR_TAB
3066 "out %i6,%2" CR_TAB
3067 "mov %2,%5", xop, plen, 4);
3068 }
0dff9558 3069
be6d8823 3070 xop[4] = xstring_e;
3071
3072 if (!AVR_HAVE_ELPMX)
3073 return avr_out_lpm_no_lpmx (insn, xop, plen);
3074 }
3075 else if (!AVR_HAVE_LPMX)
3076 {
3077 return avr_out_lpm_no_lpmx (insn, xop, plen);
3078 }
3079
3080 /* We have [E]LPMX: Output reading from Flash the comfortable way. */
3081
3082 switch (GET_CODE (addr))
4202ef11 3083 {
3084 default:
3085 gcc_unreachable();
3086
3087 case REG:
3088
3089 gcc_assert (REG_Z == REGNO (addr));
3090
be6d8823 3091 switch (n_bytes)
3092 {
3093 default:
3094 gcc_unreachable();
4202ef11 3095
be6d8823 3096 case 1:
3097 return avr_asm_len ("%4lpm %0,%a2", xop, plen, 1);
4202ef11 3098
be6d8823 3099 case 2:
3100 if (REGNO (dest) == REG_Z)
3101 return avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3102 "%4lpm %B0,%a2" CR_TAB
3103 "mov %A0,%5", xop, plen, 3);
3104 else
3105 {
3106 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3107 "%4lpm %B0,%a2", xop, plen, 2);
0dff9558 3108
be6d8823 3109 if (!reg_unused_after (insn, addr))
3110 avr_asm_len ("sbiw %2,1", xop, plen, 1);
3111 }
0dff9558 3112
be6d8823 3113 break; /* 2 */
4202ef11 3114
be6d8823 3115 case 3:
4202ef11 3116
be6d8823 3117 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3118 "%4lpm %B0,%a2+" CR_TAB
3119 "%4lpm %C0,%a2", xop, plen, 3);
0dff9558 3120
be6d8823 3121 if (!reg_unused_after (insn, addr))
3122 avr_asm_len ("sbiw %2,2", xop, plen, 1);
3123
3124 break; /* 3 */
0dff9558 3125
be6d8823 3126 case 4:
3127
3128 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3129 "%4lpm %B0,%a2+", xop, plen, 2);
0dff9558 3130
be6d8823 3131 if (REGNO (dest) == REG_Z - 2)
3132 return avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3133 "%4lpm %C0,%a2" CR_TAB
3134 "mov %D0,%5", xop, plen, 3);
3135 else
4202ef11 3136 {
be6d8823 3137 avr_asm_len ("%4lpm %C0,%a2+" CR_TAB
3138 "%4lpm %D0,%a2", xop, plen, 2);
0dff9558 3139
be6d8823 3140 if (!reg_unused_after (insn, addr))
3141 avr_asm_len ("sbiw %2,3", xop, plen, 1);
4202ef11 3142 }
3143
be6d8823 3144 break; /* 4 */
3145 } /* n_bytes */
0dff9558 3146
be6d8823 3147 break; /* REG */
3148
3149 case POST_INC:
3150
3151 gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
3152 && n_bytes <= 4);
3153
3154 avr_asm_len ("%4lpm %A0,%a2+", xop, plen, 1);
3155 if (n_bytes >= 2) avr_asm_len ("%4lpm %B0,%a2+", xop, plen, 1);
3156 if (n_bytes >= 3) avr_asm_len ("%4lpm %C0,%a2+", xop, plen, 1);
3157 if (n_bytes >= 4) avr_asm_len ("%4lpm %D0,%a2+", xop, plen, 1);
3158
3159 break; /* POST_INC */
3160
3161 } /* switch CODE (addr) */
3162
3163 if (xop[4] == xstring_e && AVR_HAVE_RAMPD)
be20cbdd 3164 {
0dff9558 3165 /* Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM. */
be6d8823 3166
3167 xop[0] = zero_reg_rtx;
3168 avr_asm_len ("out %i6,%0", xop, plen, 1);
be20cbdd 3169 }
3170
4202ef11 3171 return "";
3172}
3173
3174
ed2541ea 3175/* Worker function for xload_8 insn. */
5bd39e93 3176
3177const char*
375204de 3178avr_out_xload (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
5bd39e93 3179{
ed2541ea 3180 rtx xop[4];
5bd39e93 3181
ed2541ea 3182 xop[0] = op[0];
5bd39e93 3183 xop[1] = op[1];
3184 xop[2] = lpm_addr_reg_rtx;
ed2541ea 3185 xop[3] = AVR_HAVE_LPMX ? op[0] : lpm_reg_rtx;
5bd39e93 3186
4f3c1595 3187 avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, -1);
5bd39e93 3188
ee3ce577 3189 avr_asm_len ("sbrc %1,7" CR_TAB
4f3c1595 3190 "ld %3,%a2", xop, plen, 2);
5bd39e93 3191
ed2541ea 3192 if (REGNO (xop[0]) != REGNO (xop[3]))
3193 avr_asm_len ("mov %0,%3", xop, plen, 1);
0dff9558 3194
5bd39e93 3195 return "";
3196}
3197
1a96adb9 3198
3199/* AVRTC-579
3200 If OP is a symbol or a constant expression with value > 0xbf
3201 return FALSE, otherwise TRUE.
3202 This check is used to avoid LDS / STS instruction with invalid memory
3203 access range (valid range 0x40..0xbf). For I/O operand range 0x0..0x3f,
3204 IN / OUT instruction will be generated. */
3205
3206bool
3754d046 3207tiny_valid_direct_memory_access_range (rtx op, machine_mode mode)
b4e6d2e2 3208{
3209 rtx x;
3210
3211 if (!AVR_TINY)
3212 return true;
3213
1a96adb9 3214 x = XEXP (op,0);
b4e6d2e2 3215
1a96adb9 3216 if (MEM_P (op) && x && GET_CODE (x) == SYMBOL_REF)
3217 {
3218 return false;
3219 }
3220
3221 if (MEM_P (op) && x && (CONSTANT_ADDRESS_P (x))
3222 && !(IN_RANGE (INTVAL (x), 0, 0xC0 - GET_MODE_SIZE (mode))))
3223 {
3224 return false;
3225 }
b4e6d2e2 3226
3227 return true;
3228}
5bd39e93 3229
002565f0 3230const char*
375204de 3231output_movqi (rtx_insn *insn, rtx operands[], int *plen)
a28e4651 3232{
e511e253 3233 rtx dest = operands[0];
3234 rtx src = operands[1];
0dff9558 3235
590da9f2 3236 if (avr_mem_flash_p (src)
3237 || avr_mem_flash_p (dest))
4202ef11 3238 {
be6d8823 3239 return avr_out_lpm (insn, operands, plen);
4202ef11 3240 }
3241
017c5b98 3242 gcc_assert (1 == GET_MODE_SIZE (GET_MODE (dest)));
3243
3244 if (REG_P (dest))
a28e4651 3245 {
017c5b98 3246 if (REG_P (src)) /* mov r,r */
be6d8823 3247 {
3248 if (test_hard_reg_class (STACK_REG, dest))
3249 return avr_asm_len ("out %0,%1", operands, plen, -1);
3250 else if (test_hard_reg_class (STACK_REG, src))
3251 return avr_asm_len ("in %0,%1", operands, plen, -1);
0dff9558 3252
be6d8823 3253 return avr_asm_len ("mov %0,%1", operands, plen, -1);
3254 }
e511e253 3255 else if (CONSTANT_P (src))
a49907f9 3256 {
be6d8823 3257 output_reload_in_const (operands, NULL_RTX, plen, false);
a49907f9 3258 return "";
3259 }
002565f0 3260 else if (MEM_P (src))
be6d8823 3261 return out_movqi_r_mr (insn, operands, plen); /* mov r,m */
e511e253 3262 }
002565f0 3263 else if (MEM_P (dest))
e511e253 3264 {
644ac9c5 3265 rtx xop[2];
37ac04dc 3266
644ac9c5 3267 xop[0] = dest;
017c5b98 3268 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
e511e253 3269
be6d8823 3270 return out_movqi_mr_r (insn, xop, plen);
e511e253 3271 }
be6d8823 3272
e511e253 3273 return "";
3274}
3275
3276
37ac04dc 3277const char *
375204de 3278output_movhi (rtx_insn *insn, rtx xop[], int *plen)
e511e253 3279{
8c8193e1 3280 rtx dest = xop[0];
3281 rtx src = xop[1];
3282
3283 gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 2);
0dff9558 3284
590da9f2 3285 if (avr_mem_flash_p (src)
3286 || avr_mem_flash_p (dest))
4202ef11 3287 {
8c8193e1 3288 return avr_out_lpm (insn, xop, plen);
4202ef11 3289 }
3290
017c5b98 3291 gcc_assert (2 == GET_MODE_SIZE (GET_MODE (dest)));
3292
8c8193e1 3293 if (REG_P (dest))
e511e253 3294 {
8c8193e1 3295 if (REG_P (src)) /* mov r,r */
3296 {
3297 if (test_hard_reg_class (STACK_REG, dest))
3298 {
3299 if (AVR_HAVE_8BIT_SP)
3300 return avr_asm_len ("out __SP_L__,%A1", xop, plen, -1);
0b6cf66f 3301
3302 if (AVR_XMEGA)
3303 return avr_asm_len ("out __SP_L__,%A1" CR_TAB
3304 "out __SP_H__,%B1", xop, plen, -2);
0dff9558 3305
8c8193e1 3306 /* Use simple load of SP if no interrupts are used. */
0dff9558 3307
8c8193e1 3308 return TARGET_NO_INTERRUPTS
3309 ? avr_asm_len ("out __SP_H__,%B1" CR_TAB
3310 "out __SP_L__,%A1", xop, plen, -2)
8c8193e1 3311 : avr_asm_len ("in __tmp_reg__,__SREG__" CR_TAB
3312 "cli" CR_TAB
3313 "out __SP_H__,%B1" CR_TAB
3314 "out __SREG__,__tmp_reg__" CR_TAB
3315 "out __SP_L__,%A1", xop, plen, -5);
3316 }
3317 else if (test_hard_reg_class (STACK_REG, src))
3318 {
d32d7e3a 3319 return !AVR_HAVE_SPH
8c8193e1 3320 ? avr_asm_len ("in %A0,__SP_L__" CR_TAB
3321 "clr %B0", xop, plen, -2)
0dff9558 3322
8c8193e1 3323 : avr_asm_len ("in %A0,__SP_L__" CR_TAB
3324 "in %B0,__SP_H__", xop, plen, -2);
3325 }
e511e253 3326
8c8193e1 3327 return AVR_HAVE_MOVW
3328 ? avr_asm_len ("movw %0,%1", xop, plen, -1)
3329
3330 : avr_asm_len ("mov %A0,%A1" CR_TAB
3331 "mov %B0,%B1", xop, plen, -2);
3332 } /* REG_P (src) */
e511e253 3333 else if (CONSTANT_P (src))
2f2d376f 3334 {
8c8193e1 3335 return output_reload_inhi (xop, NULL, plen);
3336 }
3337 else if (MEM_P (src))
3338 {
3339 return out_movhi_r_mr (insn, xop, plen); /* mov r,m */
2f2d376f 3340 }
e511e253 3341 }
8c8193e1 3342 else if (MEM_P (dest))
e511e253 3343 {
644ac9c5 3344 rtx xop[2];
37ac04dc 3345
644ac9c5 3346 xop[0] = dest;
017c5b98 3347 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
37ac04dc 3348
8c8193e1 3349 return out_movhi_mr_r (insn, xop, plen);
a28e4651 3350 }
0dff9558 3351
68435912 3352 fatal_insn ("invalid insn:", insn);
0dff9558 3353
e511e253 3354 return "";
3355}
3356
1a96adb9 3357
b4e6d2e2 3358/* Same as out_movqi_r_mr, but TINY does not have ADIW or SBIW */
1a96adb9 3359
b4e6d2e2 3360static const char*
3361avr_out_movqi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
3362{
3363 rtx dest = op[0];
3364 rtx src = op[1];
3365 rtx x = XEXP (src, 0);
3366
3367 avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
1a96adb9 3368 "ld %0,%b1" , op, plen, -3);
b4e6d2e2 3369
3370 if (!reg_overlap_mentioned_p (dest, XEXP (x,0))
1a96adb9 3371 && !reg_unused_after (insn, XEXP (x,0)))
3372 avr_asm_len (TINY_SBIW (%I1, %J1, %o1), op, plen, 2);
b4e6d2e2 3373
3374 return "";
3375}
3376
644ac9c5 3377static const char*
375204de 3378out_movqi_r_mr (rtx_insn *insn, rtx op[], int *plen)
e511e253 3379{
37ac04dc 3380 rtx dest = op[0];
3381 rtx src = op[1];
3382 rtx x = XEXP (src, 0);
0dff9558 3383
e511e253 3384 if (CONSTANT_ADDRESS_P (x))
3385 {
b4e6d2e2 3386 int n_words = AVR_TINY ? 1 : 2;
644ac9c5 3387 return optimize > 0 && io_address_operand (x, QImode)
3388 ? avr_asm_len ("in %0,%i1", op, plen, -1)
b4e6d2e2 3389 : avr_asm_len ("lds %0,%m1", op, plen, -n_words);
e511e253 3390 }
b4e6d2e2 3391
3392 if (GET_CODE (x) == PLUS
5bd39e93 3393 && REG_P (XEXP (x, 0))
3394 && CONST_INT_P (XEXP (x, 1)))
e511e253 3395 {
5bd39e93 3396 /* memory access by reg+disp */
db45d3ed 3397
5bd39e93 3398 int disp = INTVAL (XEXP (x, 1));
0dff9558 3399
b4e6d2e2 3400 if (AVR_TINY)
3401 return avr_out_movqi_r_mr_reg_disp_tiny (insn, op, plen);
3402
5bd39e93 3403 if (disp - GET_MODE_SIZE (GET_MODE (src)) >= 63)
3404 {
3405 if (REGNO (XEXP (x, 0)) != REG_Y)
3406 fatal_insn ("incorrect insn:",insn);
db45d3ed 3407
5bd39e93 3408 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
3409 return avr_asm_len ("adiw r28,%o1-63" CR_TAB
3410 "ldd %0,Y+63" CR_TAB
3411 "sbiw r28,%o1-63", op, plen, -3);
3412
3413 return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
3414 "sbci r29,hi8(-%o1)" CR_TAB
3415 "ld %0,Y" CR_TAB
3416 "subi r28,lo8(%o1)" CR_TAB
3417 "sbci r29,hi8(%o1)", op, plen, -5);
3418 }
3419 else if (REGNO (XEXP (x, 0)) == REG_X)
3420 {
3421 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
3422 it but I have this situation with extremal optimizing options. */
0dff9558 3423
5bd39e93 3424 avr_asm_len ("adiw r26,%o1" CR_TAB
3425 "ld %0,X", op, plen, -2);
0dff9558 3426
5bd39e93 3427 if (!reg_overlap_mentioned_p (dest, XEXP (x,0))
3428 && !reg_unused_after (insn, XEXP (x,0)))
3429 {
3430 avr_asm_len ("sbiw r26,%o1", op, plen, 1);
3431 }
3432
3433 return "";
3434 }
3435
3436 return avr_asm_len ("ldd %0,%1", op, plen, -1);
e511e253 3437 }
0dff9558 3438
5bd39e93 3439 return avr_asm_len ("ld %0,%1", op, plen, -1);
a28e4651 3440}
3441
1a96adb9 3442
b4e6d2e2 3443/* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
1a96adb9 3444
b4e6d2e2 3445static const char*
3446avr_out_movhi_r_mr_reg_no_disp_tiny (rtx op[], int *plen)
3447{
3448 rtx dest = op[0];
3449 rtx src = op[1];
3450 rtx base = XEXP (src, 0);
3451
3452 int reg_dest = true_regnum (dest);
3453 int reg_base = true_regnum (base);
3454
3455 if (reg_dest == reg_base) /* R = (R) */
1a96adb9 3456 return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
3457 "ld %B0,%1" CR_TAB
3458 "mov %A0,__tmp_reg__", op, plen, -3);
b4e6d2e2 3459
1a96adb9 3460 return avr_asm_len ("ld %A0,%1" CR_TAB
3461 TINY_ADIW (%E1, %F1, 1) CR_TAB
3462 "ld %B0,%1" CR_TAB
3463 TINY_SBIW (%E1, %F1, 1), op, plen, -6);
b4e6d2e2 3464}
3465
1a96adb9 3466
b4e6d2e2 3467/* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
1a96adb9 3468
b4e6d2e2 3469static const char*
3470avr_out_movhi_r_mr_reg_disp_tiny (rtx op[], int *plen)
3471{
3472 rtx dest = op[0];
3473 rtx src = op[1];
3474 rtx base = XEXP (src, 0);
3475
3476 int reg_dest = true_regnum (dest);
3477 int reg_base = true_regnum (XEXP (base, 0));
3478
3479 if (reg_base == reg_dest)
1a96adb9 3480 {
b4e6d2e2 3481 return avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
1a96adb9 3482 "ld __tmp_reg__,%b1+" CR_TAB
3483 "ld %B0,%b1" CR_TAB
3484 "mov %A0,__tmp_reg__", op, plen, -5);
3485 }
b4e6d2e2 3486 else
1a96adb9 3487 {
b4e6d2e2 3488 return avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
1a96adb9 3489 "ld %A0,%b1+" CR_TAB
3490 "ld %B0,%b1" CR_TAB
3491 TINY_SBIW (%I1, %J1, %o1+1), op, plen, -6);
3492 }
3493}
3494
b4e6d2e2 3495
3496/* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
1a96adb9 3497
b4e6d2e2 3498static const char*
3499avr_out_movhi_r_mr_pre_dec_tiny (rtx_insn *insn, rtx op[], int *plen)
3500{
3501 int mem_volatile_p = 0;
3502 rtx dest = op[0];
3503 rtx src = op[1];
3504 rtx base = XEXP (src, 0);
3505
3506 /* "volatile" forces reading low byte first, even if less efficient,
3507 for correct operation with 16-bit I/O registers. */
3508 mem_volatile_p = MEM_VOLATILE_P (src);
3509
3510 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
1a96adb9 3511 fatal_insn ("incorrect insn:", insn);
b4e6d2e2 3512
3513 if (!mem_volatile_p)
1a96adb9 3514 return avr_asm_len ("ld %B0,%1" CR_TAB
3515 "ld %A0,%1", op, plen, -2);
b4e6d2e2 3516
3517 return avr_asm_len (TINY_SBIW (%I1, %J1, 2) CR_TAB
1a96adb9 3518 "ld %A0,%p1+" CR_TAB
3519 "ld %B0,%p1" CR_TAB
3520 TINY_SBIW (%I1, %J1, 1), op, plen, -6);
b4e6d2e2 3521}
3522
1a96adb9 3523
644ac9c5 3524static const char*
375204de 3525out_movhi_r_mr (rtx_insn *insn, rtx op[], int *plen)
a28e4651 3526{
37ac04dc 3527 rtx dest = op[0];
3528 rtx src = op[1];
3529 rtx base = XEXP (src, 0);
3530 int reg_dest = true_regnum (dest);
3531 int reg_base = true_regnum (base);
f43bae99 3532 /* "volatile" forces reading low byte first, even if less efficient,
3533 for correct operation with 16-bit I/O registers. */
3534 int mem_volatile_p = MEM_VOLATILE_P (src);
a28e4651 3535
3536 if (reg_base > 0)
3537 {
b4e6d2e2 3538 if (AVR_TINY)
3539 return avr_out_movhi_r_mr_reg_no_disp_tiny (op, plen);
3540
a28e4651 3541 if (reg_dest == reg_base) /* R = (R) */
644ac9c5 3542 return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
3543 "ld %B0,%1" CR_TAB
3544 "mov %A0,__tmp_reg__", op, plen, -3);
3545
3546 if (reg_base != REG_X)
3547 return avr_asm_len ("ld %A0,%1" CR_TAB
3548 "ldd %B0,%1+1", op, plen, -2);
0dff9558 3549
644ac9c5 3550 avr_asm_len ("ld %A0,X+" CR_TAB
3551 "ld %B0,X", op, plen, -2);
0dff9558 3552
644ac9c5 3553 if (!reg_unused_after (insn, base))
3554 avr_asm_len ("sbiw r26,1", op, plen, 1);
3555
3556 return "";
a28e4651 3557 }
37ac04dc 3558 else if (GET_CODE (base) == PLUS) /* (R + i) */
a28e4651 3559 {
37ac04dc 3560 int disp = INTVAL (XEXP (base, 1));
3561 int reg_base = true_regnum (XEXP (base, 0));
0dff9558 3562
b4e6d2e2 3563 if (AVR_TINY)
3564 return avr_out_movhi_r_mr_reg_disp_tiny (op, plen);
3565
37ac04dc 3566 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
644ac9c5 3567 {
3568 if (REGNO (XEXP (base, 0)) != REG_Y)
3569 fatal_insn ("incorrect insn:",insn);
0dff9558 3570
644ac9c5 3571 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (src))
3572 ? avr_asm_len ("adiw r28,%o1-62" CR_TAB
3573 "ldd %A0,Y+62" CR_TAB
3574 "ldd %B0,Y+63" CR_TAB
3575 "sbiw r28,%o1-62", op, plen, -4)
3576
b4e6d2e2 3577 : avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
644ac9c5 3578 "sbci r29,hi8(-%o1)" CR_TAB
3579 "ld %A0,Y" CR_TAB
3580 "ldd %B0,Y+1" CR_TAB
3581 "subi r28,lo8(%o1)" CR_TAB
3582 "sbci r29,hi8(%o1)", op, plen, -6);
3583 }
3584
3585 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
3586 it but I have this situation with extremal
3587 optimization options. */
db45d3ed 3588
a28e4651 3589 if (reg_base == REG_X)
644ac9c5 3590 return reg_base == reg_dest
3591 ? avr_asm_len ("adiw r26,%o1" CR_TAB
3592 "ld __tmp_reg__,X+" CR_TAB
3593 "ld %B0,X" CR_TAB
3594 "mov %A0,__tmp_reg__", op, plen, -4)
e511e253 3595
644ac9c5 3596 : avr_asm_len ("adiw r26,%o1" CR_TAB
3597 "ld %A0,X+" CR_TAB
3598 "ld %B0,X" CR_TAB
3599 "sbiw r26,%o1+1", op, plen, -4);
e511e253 3600
644ac9c5 3601 return reg_base == reg_dest
3602 ? avr_asm_len ("ldd __tmp_reg__,%A1" CR_TAB
3603 "ldd %B0,%B1" CR_TAB
3604 "mov %A0,__tmp_reg__", op, plen, -3)
3605
3606 : avr_asm_len ("ldd %A0,%A1" CR_TAB
3607 "ldd %B0,%B1", op, plen, -2);
a28e4651 3608 }
37ac04dc 3609 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
a28e4651 3610 {
b4e6d2e2 3611 if (AVR_TINY)
1a96adb9 3612 return avr_out_movhi_r_mr_pre_dec_tiny (insn, op, plen);
b4e6d2e2 3613
37ac04dc 3614 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
644ac9c5 3615 fatal_insn ("incorrect insn:", insn);
e511e253 3616
644ac9c5 3617 if (!mem_volatile_p)
3618 return avr_asm_len ("ld %B0,%1" CR_TAB
3619 "ld %A0,%1", op, plen, -2);
0dff9558 3620
644ac9c5 3621 return REGNO (XEXP (base, 0)) == REG_X
3622 ? avr_asm_len ("sbiw r26,2" CR_TAB
3623 "ld %A0,X+" CR_TAB
3624 "ld %B0,X" CR_TAB
3625 "sbiw r26,1", op, plen, -4)
0dff9558 3626
644ac9c5 3627 : avr_asm_len ("sbiw %r1,2" CR_TAB
3628 "ld %A0,%p1" CR_TAB
3629 "ldd %B0,%p1+1", op, plen, -3);
a28e4651 3630 }
37ac04dc 3631 else if (GET_CODE (base) == POST_INC) /* (R++) */
a28e4651 3632 {
37ac04dc 3633 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
644ac9c5 3634 fatal_insn ("incorrect insn:", insn);
e511e253 3635
644ac9c5 3636 return avr_asm_len ("ld %A0,%1" CR_TAB
3637 "ld %B0,%1", op, plen, -2);
a28e4651 3638 }
37ac04dc 3639 else if (CONSTANT_ADDRESS_P (base))
e511e253 3640 {
b4e6d2e2 3641 int n_words = AVR_TINY ? 2 : 4;
644ac9c5 3642 return optimize > 0 && io_address_operand (base, HImode)
3643 ? avr_asm_len ("in %A0,%i1" CR_TAB
3644 "in %B0,%i1+1", op, plen, -2)
3645
3646 : avr_asm_len ("lds %A0,%m1" CR_TAB
b4e6d2e2 3647 "lds %B0,%m1+1", op, plen, -n_words);
e511e253 3648 }
0dff9558 3649
68435912 3650 fatal_insn ("unknown move insn:",insn);
a28e4651 3651 return "";
3652}
3653
b4e6d2e2 3654static const char*
3655avr_out_movsi_r_mr_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *l)
3656{
3657 rtx dest = op[0];
3658 rtx src = op[1];
3659 rtx base = XEXP (src, 0);
3660 int reg_dest = true_regnum (dest);
3661 int reg_base = true_regnum (base);
3662
3663 if (reg_dest == reg_base)
3664 {
1a96adb9 3665 /* "ld r26,-X" is undefined */
3666 return *l = 9, (TINY_ADIW (%E1, %F1, 3) CR_TAB
3667 "ld %D0,%1" CR_TAB
3668 "ld %C0,-%1" CR_TAB
3669 "ld __tmp_reg__,-%1" CR_TAB
3670 TINY_SBIW (%E1, %F1, 1) CR_TAB
3671 "ld %A0,%1" CR_TAB
3672 "mov %B0,__tmp_reg__");
b4e6d2e2 3673 }
3674 else if (reg_dest == reg_base - 2)
3675 {
1a96adb9 3676 return *l = 5, ("ld %A0,%1+" CR_TAB
3677 "ld %B0,%1+" CR_TAB
3678 "ld __tmp_reg__,%1+" CR_TAB
3679 "ld %D0,%1" CR_TAB
3680 "mov %C0,__tmp_reg__");
b4e6d2e2 3681 }
3682 else if (reg_unused_after (insn, base))
3683 {
1a96adb9 3684 return *l = 4, ("ld %A0,%1+" CR_TAB
3685 "ld %B0,%1+" CR_TAB
3686 "ld %C0,%1+" CR_TAB
3687 "ld %D0,%1");
b4e6d2e2 3688 }
3689 else
3690 {
1a96adb9 3691 return *l = 6, ("ld %A0,%1+" CR_TAB
3692 "ld %B0,%1+" CR_TAB
3693 "ld %C0,%1+" CR_TAB
3694 "ld %D0,%1" CR_TAB
3695 TINY_SBIW (%E1, %F1, 3));
b4e6d2e2 3696 }
3697}
3698
1a96adb9 3699
b4e6d2e2 3700static const char*
3701avr_out_movsi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *l)
3702{
3703 rtx dest = op[0];
3704 rtx src = op[1];
3705 rtx base = XEXP (src, 0);
3706 int reg_dest = true_regnum (dest);
3707 int reg_base = true_regnum (XEXP (base, 0));
3708
3709 if (reg_dest == reg_base)
3710 {
1a96adb9 3711 /* "ld r26,-X" is undefined */
3712 return *l = 9, (TINY_ADIW (%I1, %J1, %o1+3) CR_TAB
3713 "ld %D0,%b1" CR_TAB
3714 "ld %C0,-%b1" CR_TAB
3715 "ld __tmp_reg__,-%b1" CR_TAB
3716 TINY_SBIW (%I1, %J1, 1) CR_TAB
3717 "ld %A0,%b1" CR_TAB
3718 "mov %B0,__tmp_reg__");
b4e6d2e2 3719 }
3720 else if (reg_dest == reg_base - 2)
3721 {
1a96adb9 3722 return *l = 7, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
3723 "ld %A0,%b1+" CR_TAB
3724 "ld %B0,%b1+" CR_TAB
3725 "ld __tmp_reg__,%b1+" CR_TAB
3726 "ld %D0,%b1" CR_TAB
3727 "mov %C0,__tmp_reg__");
b4e6d2e2 3728 }
3729 else if (reg_unused_after (insn, XEXP (base, 0)))
3730 {
1a96adb9 3731 return *l = 6, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
3732 "ld %A0,%b1+" CR_TAB
3733 "ld %B0,%b1+" CR_TAB
3734 "ld %C0,%b1+" CR_TAB
3735 "ld %D0,%b1");
b4e6d2e2 3736 }
3737 else
3738 {
1a96adb9 3739 return *l = 8, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
3740 "ld %A0,%b1+" CR_TAB
3741 "ld %B0,%b1+" CR_TAB
3742 "ld %C0,%b1+" CR_TAB
3743 "ld %D0,%b1" CR_TAB
3744 TINY_SBIW (%I1, %J1, %o1+3));
b4e6d2e2 3745 }
3746}
3747
644ac9c5 3748static const char*
375204de 3749out_movsi_r_mr (rtx_insn *insn, rtx op[], int *l)
a28e4651 3750{
37ac04dc 3751 rtx dest = op[0];
3752 rtx src = op[1];
3753 rtx base = XEXP (src, 0);
3754 int reg_dest = true_regnum (dest);
3755 int reg_base = true_regnum (base);
a28e4651 3756 int tmp;
e511e253 3757
a28e4651 3758 if (!l)
e511e253 3759 l = &tmp;
0dff9558 3760
a28e4651 3761 if (reg_base > 0)
3762 {
b4e6d2e2 3763 if (AVR_TINY)
3764 return avr_out_movsi_r_mr_reg_no_disp_tiny (insn, op, l);
3765
a28e4651 3766 if (reg_base == REG_X) /* (R26) */
3767 {
3768 if (reg_dest == REG_X)
66ad0834 3769 /* "ld r26,-X" is undefined */
02a011e9 3770 return *l=7, ("adiw r26,3" CR_TAB
3771 "ld r29,X" CR_TAB
3772 "ld r28,-X" CR_TAB
3773 "ld __tmp_reg__,-X" CR_TAB
3774 "sbiw r26,1" CR_TAB
3775 "ld r26,X" CR_TAB
3776 "mov r27,__tmp_reg__");
a28e4651 3777 else if (reg_dest == REG_X - 2)
02a011e9 3778 return *l=5, ("ld %A0,X+" CR_TAB
3779 "ld %B0,X+" CR_TAB
3780 "ld __tmp_reg__,X+" CR_TAB
3781 "ld %D0,X" CR_TAB
3782 "mov %C0,__tmp_reg__");
37ac04dc 3783 else if (reg_unused_after (insn, base))
02a011e9 3784 return *l=4, ("ld %A0,X+" CR_TAB
3785 "ld %B0,X+" CR_TAB
3786 "ld %C0,X+" CR_TAB
3787 "ld %D0,X");
a28e4651 3788 else
02a011e9 3789 return *l=5, ("ld %A0,X+" CR_TAB
3790 "ld %B0,X+" CR_TAB
3791 "ld %C0,X+" CR_TAB
3792 "ld %D0,X" CR_TAB
3793 "sbiw r26,3");
a28e4651 3794 }
3795 else
3796 {
3797 if (reg_dest == reg_base)
02a011e9 3798 return *l=5, ("ldd %D0,%1+3" CR_TAB
3799 "ldd %C0,%1+2" CR_TAB
3800 "ldd __tmp_reg__,%1+1" CR_TAB
3801 "ld %A0,%1" CR_TAB
3802 "mov %B0,__tmp_reg__");
a28e4651 3803 else if (reg_base == reg_dest + 2)
02a011e9 3804 return *l=5, ("ld %A0,%1" CR_TAB
3805 "ldd %B0,%1+1" CR_TAB
3806 "ldd __tmp_reg__,%1+2" CR_TAB
3807 "ldd %D0,%1+3" CR_TAB
3808 "mov %C0,__tmp_reg__");
a28e4651 3809 else
02a011e9 3810 return *l=4, ("ld %A0,%1" CR_TAB
3811 "ldd %B0,%1+1" CR_TAB
3812 "ldd %C0,%1+2" CR_TAB
3813 "ldd %D0,%1+3");
a28e4651 3814 }
3815 }
37ac04dc 3816 else if (GET_CODE (base) == PLUS) /* (R + i) */
a28e4651 3817 {
37ac04dc 3818 int disp = INTVAL (XEXP (base, 1));
0dff9558 3819
b4e6d2e2 3820 if (AVR_TINY)
3821 return avr_out_movsi_r_mr_reg_disp_tiny (insn, op, l);
3822
37ac04dc 3823 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
a28e4651 3824 {
37ac04dc 3825 if (REGNO (XEXP (base, 0)) != REG_Y)
68435912 3826 fatal_insn ("incorrect insn:",insn);
db45d3ed 3827
37ac04dc 3828 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
02a011e9 3829 return *l = 6, ("adiw r28,%o1-60" CR_TAB
3830 "ldd %A0,Y+60" CR_TAB
3831 "ldd %B0,Y+61" CR_TAB
3832 "ldd %C0,Y+62" CR_TAB
3833 "ldd %D0,Y+63" CR_TAB
3834 "sbiw r28,%o1-60");
3835
3836 return *l = 8, ("subi r28,lo8(-%o1)" CR_TAB
3837 "sbci r29,hi8(-%o1)" CR_TAB
3838 "ld %A0,Y" CR_TAB
3839 "ldd %B0,Y+1" CR_TAB
3840 "ldd %C0,Y+2" CR_TAB
3841 "ldd %D0,Y+3" CR_TAB
3842 "subi r28,lo8(%o1)" CR_TAB
3843 "sbci r29,hi8(%o1)");
a28e4651 3844 }
3845
37ac04dc 3846 reg_base = true_regnum (XEXP (base, 0));
66ad0834 3847 if (reg_base == REG_X)
3848 {
3849 /* R = (X + d) */
3850 if (reg_dest == REG_X)
3851 {
3852 *l = 7;
3853 /* "ld r26,-X" is undefined */
02a011e9 3854 return ("adiw r26,%o1+3" CR_TAB
3855 "ld r29,X" CR_TAB
3856 "ld r28,-X" CR_TAB
3857 "ld __tmp_reg__,-X" CR_TAB
3858 "sbiw r26,1" CR_TAB
3859 "ld r26,X" CR_TAB
3860 "mov r27,__tmp_reg__");
66ad0834 3861 }
3862 *l = 6;
3863 if (reg_dest == REG_X - 2)
02a011e9 3864 return ("adiw r26,%o1" CR_TAB
3865 "ld r24,X+" CR_TAB
3866 "ld r25,X+" CR_TAB
3867 "ld __tmp_reg__,X+" CR_TAB
3868 "ld r27,X" CR_TAB
3869 "mov r26,__tmp_reg__");
3870
3871 return ("adiw r26,%o1" CR_TAB
3872 "ld %A0,X+" CR_TAB
3873 "ld %B0,X+" CR_TAB
3874 "ld %C0,X+" CR_TAB
3875 "ld %D0,X" CR_TAB
3876 "sbiw r26,%o1+3");
66ad0834 3877 }
a28e4651 3878 if (reg_dest == reg_base)
02a011e9 3879 return *l=5, ("ldd %D0,%D1" CR_TAB
3880 "ldd %C0,%C1" CR_TAB
3881 "ldd __tmp_reg__,%B1" CR_TAB
3882 "ldd %A0,%A1" CR_TAB
3883 "mov %B0,__tmp_reg__");
a28e4651 3884 else if (reg_dest == reg_base - 2)
02a011e9 3885 return *l=5, ("ldd %A0,%A1" CR_TAB
3886 "ldd %B0,%B1" CR_TAB
3887 "ldd __tmp_reg__,%C1" CR_TAB
3888 "ldd %D0,%D1" CR_TAB
3889 "mov %C0,__tmp_reg__");
3890 return *l=4, ("ldd %A0,%A1" CR_TAB
3891 "ldd %B0,%B1" CR_TAB
3892 "ldd %C0,%C1" CR_TAB
3893 "ldd %D0,%D1");
a28e4651 3894 }
37ac04dc 3895 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
02a011e9 3896 return *l=4, ("ld %D0,%1" CR_TAB
3897 "ld %C0,%1" CR_TAB
3898 "ld %B0,%1" CR_TAB
3899 "ld %A0,%1");
37ac04dc 3900 else if (GET_CODE (base) == POST_INC) /* (R++) */
02a011e9 3901 return *l=4, ("ld %A0,%1" CR_TAB
3902 "ld %B0,%1" CR_TAB
3903 "ld %C0,%1" CR_TAB
3904 "ld %D0,%1");
37ac04dc 3905 else if (CONSTANT_ADDRESS_P (base))
b4e6d2e2 3906 {
3907 if (io_address_operand (base, SImode))
3908 {
3909 *l = 4;
3910 return ("in %A0,%i1" CR_TAB
3911 "in %B0,%i1+1" CR_TAB
3912 "in %C0,%i1+2" CR_TAB
3913 "in %D0,%i1+3");
3914 }
3915 else
3916 {
3917 *l = AVR_TINY ? 4 : 8;
3918 return ("lds %A0,%m1" CR_TAB
02a011e9 3919 "lds %B0,%m1+1" CR_TAB
3920 "lds %C0,%m1+2" CR_TAB
3921 "lds %D0,%m1+3");
b4e6d2e2 3922 }
3923 }
0dff9558 3924
68435912 3925 fatal_insn ("unknown move insn:",insn);
a28e4651 3926 return "";
3927}
3928
b4e6d2e2 3929static const char*
3930avr_out_movsi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *l)
3931{
3932 rtx dest = op[0];
3933 rtx src = op[1];
3934 rtx base = XEXP (dest, 0);
3935 int reg_base = true_regnum (base);
3936 int reg_src = true_regnum (src);
1a96adb9 3937
b4e6d2e2 3938 if (reg_base == reg_src)
3939 {
3940 /* "ld r26,-X" is undefined */
3941 if (reg_unused_after (insn, base))
1a96adb9 3942 {
3943 return *l = 7, ("mov __tmp_reg__, %B1" CR_TAB
3944 "st %0,%A1" CR_TAB
3945 TINY_ADIW (%E0, %F0, 1) CR_TAB
3946 "st %0+,__tmp_reg__" CR_TAB
3947 "st %0+,%C1" CR_TAB
3948 "st %0+,%D1");
b4e6d2e2 3949 }
3950 else
3951 {
1a96adb9 3952 return *l = 9, ("mov __tmp_reg__, %B1" CR_TAB
3953 "st %0,%A1" CR_TAB
3954 TINY_ADIW (%E0, %F0, 1) CR_TAB
3955 "st %0+,__tmp_reg__" CR_TAB
3956 "st %0+,%C1" CR_TAB
3957 "st %0+,%D1" CR_TAB
3958 TINY_SBIW (%E0, %F0, 3));
b4e6d2e2 3959 }
3960 }
1a96adb9 3961 else if (reg_base == reg_src + 2)
3962 {
3963 if (reg_unused_after (insn, base))
3964 return *l = 7, ("mov __zero_reg__,%C1" CR_TAB
b4e6d2e2 3965 "mov __tmp_reg__,%D1" CR_TAB
3966 "st %0+,%A1" CR_TAB
3967 "st %0+,%B1" CR_TAB
3968 "st %0+,__zero_reg__" CR_TAB
3969 "st %0,__tmp_reg__" CR_TAB
3970 "clr __zero_reg__");
1a96adb9 3971 else
3972 return *l = 9, ("mov __zero_reg__,%C1" CR_TAB
3973 "mov __tmp_reg__,%D1" CR_TAB
3974 "st %0+,%A1" CR_TAB
3975 "st %0+,%B1" CR_TAB
3976 "st %0+,__zero_reg__" CR_TAB
3977 "st %0,__tmp_reg__" CR_TAB
3978 "clr __zero_reg__" CR_TAB
3979 TINY_SBIW (%E0, %F0, 3));
3980 }
b4e6d2e2 3981
1a96adb9 3982 return *l = 6, ("st %0+,%A1" CR_TAB
3983 "st %0+,%B1" CR_TAB
3984 "st %0+,%C1" CR_TAB
3985 "st %0,%D1" CR_TAB
3986 TINY_SBIW (%E0, %F0, 3));
b4e6d2e2 3987}
3988
3989static const char*
3990avr_out_movsi_mr_r_reg_disp_tiny (rtx op[], int *l)
3991{
3992 rtx dest = op[0];
3993 rtx src = op[1];
3994 rtx base = XEXP (dest, 0);
3995 int reg_base = REGNO (XEXP (base, 0));
3996 int reg_src =true_regnum (src);
3997
3998 if (reg_base == reg_src)
3999 {
1a96adb9 4000 *l = 11;
4001 return ("mov __tmp_reg__,%A2" CR_TAB
4002 "mov __zero_reg__,%B2" CR_TAB
b4e6d2e2 4003 TINY_ADIW (%I0, %J0, %o0) CR_TAB
1a96adb9 4004 "st %b0+,__tmp_reg__" CR_TAB
4005 "st %b0+,__zero_reg__" CR_TAB
4006 "st %b0+,%C2" CR_TAB
4007 "st %b0,%D2" CR_TAB
4008 "clr __zero_reg__" CR_TAB
4009 TINY_SBIW (%I0, %J0, %o0+3));
4010 }
b4e6d2e2 4011 else if (reg_src == reg_base - 2)
4012 {
1a96adb9 4013 *l = 11;
4014 return ("mov __tmp_reg__,%C2" CR_TAB
4015 "mov __zero_reg__,%D2" CR_TAB
4016 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4017 "st %b0+,%A0" CR_TAB
4018 "st %b0+,%B0" CR_TAB
4019 "st %b0+,__tmp_reg__" CR_TAB
4020 "st %b0,__zero_reg__" CR_TAB
4021 "clr __zero_reg__" CR_TAB
4022 TINY_SBIW (%I0, %J0, %o0+3));
4023 }
b4e6d2e2 4024 *l = 8;
4025 return (TINY_ADIW (%I0, %J0, %o0) CR_TAB
1a96adb9 4026 "st %b0+,%A1" CR_TAB
4027 "st %b0+,%B1" CR_TAB
4028 "st %b0+,%C1" CR_TAB
4029 "st %b0,%D1" CR_TAB
4030 TINY_SBIW (%I0, %J0, %o0+3));
b4e6d2e2 4031}
4032
644ac9c5 4033static const char*
375204de 4034out_movsi_mr_r (rtx_insn *insn, rtx op[], int *l)
a28e4651 4035{
37ac04dc 4036 rtx dest = op[0];
4037 rtx src = op[1];
4038 rtx base = XEXP (dest, 0);
4039 int reg_base = true_regnum (base);
4040 int reg_src = true_regnum (src);
a28e4651 4041 int tmp;
0dff9558 4042
a28e4651 4043 if (!l)
4044 l = &tmp;
0dff9558 4045
37ac04dc 4046 if (CONSTANT_ADDRESS_P (base))
b4e6d2e2 4047 {
4048 if (io_address_operand (base, SImode))
4049 {
4050 return *l=4,("out %i0, %A1" CR_TAB
4051 "out %i0+1,%B1" CR_TAB
4052 "out %i0+2,%C1" CR_TAB
4053 "out %i0+3,%D1");
4054 }
4055 else
4056 {
4057 *l = AVR_TINY ? 4 : 8;
4058 return ("sts %m0,%A1" CR_TAB
4059 "sts %m0+1,%B1" CR_TAB
4060 "sts %m0+2,%C1" CR_TAB
4061 "sts %m0+3,%D1");
4062 }
4063 }
4064
a28e4651 4065 if (reg_base > 0) /* (r) */
4066 {
b4e6d2e2 4067 if (AVR_TINY)
4068 return avr_out_movsi_mr_r_reg_no_disp_tiny (insn, op, l);
4069
a28e4651 4070 if (reg_base == REG_X) /* (R26) */
4071 {
37ac04dc 4072 if (reg_src == REG_X)
a28e4651 4073 {
66ad0834 4074 /* "st X+,r26" is undefined */
37ac04dc 4075 if (reg_unused_after (insn, base))
02a011e9 4076 return *l=6, ("mov __tmp_reg__,r27" CR_TAB
4077 "st X,r26" CR_TAB
4078 "adiw r26,1" CR_TAB
4079 "st X+,__tmp_reg__" CR_TAB
4080 "st X+,r28" CR_TAB
4081 "st X,r29");
a28e4651 4082 else
02a011e9 4083 return *l=7, ("mov __tmp_reg__,r27" CR_TAB
4084 "st X,r26" CR_TAB
4085 "adiw r26,1" CR_TAB
4086 "st X+,__tmp_reg__" CR_TAB
4087 "st X+,r28" CR_TAB
4088 "st X,r29" CR_TAB
4089 "sbiw r26,3");
a28e4651 4090 }
37ac04dc 4091 else if (reg_base == reg_src + 2)
a28e4651 4092 {
37ac04dc 4093 if (reg_unused_after (insn, base))
02a011e9 4094 return *l=7, ("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__");
a28e4651 4101 else
02a011e9 4102 return *l=8, ("mov __zero_reg__,%C1" CR_TAB
4103 "mov __tmp_reg__,%D1" CR_TAB
4104 "st %0+,%A1" CR_TAB
4105 "st %0+,%B1" CR_TAB
4106 "st %0+,__zero_reg__" CR_TAB
4107 "st %0,__tmp_reg__" CR_TAB
4108 "clr __zero_reg__" CR_TAB
4109 "sbiw r26,3");
a28e4651 4110 }
02a011e9 4111 return *l=5, ("st %0+,%A1" CR_TAB
4112 "st %0+,%B1" CR_TAB
4113 "st %0+,%C1" CR_TAB
4114 "st %0,%D1" CR_TAB
4115 "sbiw r26,3");
a28e4651 4116 }
4117 else
02a011e9 4118 return *l=4, ("st %0,%A1" CR_TAB
4119 "std %0+1,%B1" CR_TAB
4120 "std %0+2,%C1" CR_TAB
4121 "std %0+3,%D1");
a28e4651 4122 }
37ac04dc 4123 else if (GET_CODE (base) == PLUS) /* (R + i) */
a28e4651 4124 {
37ac04dc 4125 int disp = INTVAL (XEXP (base, 1));
b4e6d2e2 4126
4127 if (AVR_TINY)
4128 return avr_out_movsi_mr_r_reg_disp_tiny (op, l);
4129
66ad0834 4130 reg_base = REGNO (XEXP (base, 0));
37ac04dc 4131 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
a28e4651 4132 {
66ad0834 4133 if (reg_base != REG_Y)
68435912 4134 fatal_insn ("incorrect insn:",insn);
db45d3ed 4135
37ac04dc 4136 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
02a011e9 4137 return *l = 6, ("adiw r28,%o0-60" CR_TAB
4138 "std Y+60,%A1" CR_TAB
4139 "std Y+61,%B1" CR_TAB
4140 "std Y+62,%C1" CR_TAB
4141 "std Y+63,%D1" CR_TAB
4142 "sbiw r28,%o0-60");
4143
4144 return *l = 8, ("subi r28,lo8(-%o0)" CR_TAB
4145 "sbci r29,hi8(-%o0)" CR_TAB
4146 "st Y,%A1" CR_TAB
4147 "std Y+1,%B1" CR_TAB
4148 "std Y+2,%C1" CR_TAB
4149 "std Y+3,%D1" CR_TAB
4150 "subi r28,lo8(%o0)" CR_TAB
4151 "sbci r29,hi8(%o0)");
a28e4651 4152 }
66ad0834 4153 if (reg_base == REG_X)
4154 {
4155 /* (X + d) = R */
4156 if (reg_src == REG_X)
4157 {
4158 *l = 9;
02a011e9 4159 return ("mov __tmp_reg__,r26" CR_TAB
4160 "mov __zero_reg__,r27" CR_TAB
4161 "adiw r26,%o0" CR_TAB
4162 "st X+,__tmp_reg__" CR_TAB
4163 "st X+,__zero_reg__" CR_TAB
4164 "st X+,r28" CR_TAB
4165 "st X,r29" CR_TAB
4166 "clr __zero_reg__" CR_TAB
4167 "sbiw r26,%o0+3");
66ad0834 4168 }
4169 else if (reg_src == REG_X - 2)
4170 {
4171 *l = 9;
02a011e9 4172 return ("mov __tmp_reg__,r26" CR_TAB
4173 "mov __zero_reg__,r27" CR_TAB
4174 "adiw r26,%o0" CR_TAB
4175 "st X+,r24" CR_TAB
4176 "st X+,r25" CR_TAB
4177 "st X+,__tmp_reg__" CR_TAB
4178 "st X,__zero_reg__" CR_TAB
4179 "clr __zero_reg__" CR_TAB
4180 "sbiw r26,%o0+3");
66ad0834 4181 }
4182 *l = 6;
02a011e9 4183 return ("adiw r26,%o0" CR_TAB
4184 "st X+,%A1" CR_TAB
4185 "st X+,%B1" CR_TAB
4186 "st X+,%C1" CR_TAB
4187 "st X,%D1" CR_TAB
4188 "sbiw r26,%o0+3");
66ad0834 4189 }
02a011e9 4190 return *l=4, ("std %A0,%A1" CR_TAB
4191 "std %B0,%B1" CR_TAB
4192 "std %C0,%C1" CR_TAB
4193 "std %D0,%D1");
a28e4651 4194 }
37ac04dc 4195 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
02a011e9 4196 return *l=4, ("st %0,%D1" CR_TAB
4197 "st %0,%C1" CR_TAB
4198 "st %0,%B1" CR_TAB
4199 "st %0,%A1");
37ac04dc 4200 else if (GET_CODE (base) == POST_INC) /* (R++) */
02a011e9 4201 return *l=4, ("st %0,%A1" CR_TAB
4202 "st %0,%B1" CR_TAB
4203 "st %0,%C1" CR_TAB
4204 "st %0,%D1");
68435912 4205 fatal_insn ("unknown move insn:",insn);
a28e4651 4206 return "";
4207}
4208
37ac04dc 4209const char *
375204de 4210output_movsisf (rtx_insn *insn, rtx operands[], int *l)
a28e4651 4211{
e511e253 4212 int dummy;
4213 rtx dest = operands[0];
4214 rtx src = operands[1];
4215 int *real_l = l;
0dff9558 4216
590da9f2 4217 if (avr_mem_flash_p (src)
4218 || avr_mem_flash_p (dest))
4202ef11 4219 {
4220 return avr_out_lpm (insn, operands, real_l);
4221 }
4222
e511e253 4223 if (!l)
4224 l = &dummy;
0dff9558 4225
017c5b98 4226 gcc_assert (4 == GET_MODE_SIZE (GET_MODE (dest)));
4227 if (REG_P (dest))
a28e4651 4228 {
017c5b98 4229 if (REG_P (src)) /* mov r,r */
0af74aa0 4230 {
e511e253 4231 if (true_regnum (dest) > true_regnum (src))
4232 {
0aab73c2 4233 if (AVR_HAVE_MOVW)
e511e253 4234 {
4235 *l = 2;
02a011e9 4236 return ("movw %C0,%C1" CR_TAB
4237 "movw %A0,%A1");
e511e253 4238 }
4239 *l = 4;
02a011e9 4240 return ("mov %D0,%D1" CR_TAB
4241 "mov %C0,%C1" CR_TAB
4242 "mov %B0,%B1" CR_TAB
4243 "mov %A0,%A1");
e511e253 4244 }
0af74aa0 4245 else
e511e253 4246 {
0aab73c2 4247 if (AVR_HAVE_MOVW)
e511e253 4248 {
4249 *l = 2;
02a011e9 4250 return ("movw %A0,%A1" CR_TAB
4251 "movw %C0,%C1");
e511e253 4252 }
4253 *l = 4;
02a011e9 4254 return ("mov %A0,%A1" CR_TAB
4255 "mov %B0,%B1" CR_TAB
4256 "mov %C0,%C1" CR_TAB
4257 "mov %D0,%D1");
e511e253 4258 }
0af74aa0 4259 }
e511e253 4260 else if (CONSTANT_P (src))
0af74aa0 4261 {
644ac9c5 4262 return output_reload_insisf (operands, NULL_RTX, real_l);
4263 }
017c5b98 4264 else if (MEM_P (src))
e511e253 4265 return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
4266 }
017c5b98 4267 else if (MEM_P (dest))
e511e253 4268 {
8deb3959 4269 const char *templ;
37ac04dc 4270
9ce2d202 4271 if (src == CONST0_RTX (GET_MODE (dest)))
e511e253 4272 operands[1] = zero_reg_rtx;
37ac04dc 4273
8deb3959 4274 templ = out_movsi_mr_r (insn, operands, real_l);
e511e253 4275
4276 if (!real_l)
8deb3959 4277 output_asm_insn (templ, operands);
37ac04dc 4278
4279 operands[1] = src;
e511e253 4280 return "";
a28e4651 4281 }
68435912 4282 fatal_insn ("invalid insn:", insn);
a28e4651 4283 return "";
4284}
4285
02d9a2c3 4286
4287/* Handle loads of 24-bit types from memory to register. */
4288
b4e6d2e2 4289static const char*
4290avr_out_load_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
4291{
4292 rtx dest = op[0];
4293 rtx src = op[1];
4294 rtx base = XEXP (src, 0);
4295 int reg_dest = true_regnum (dest);
4296 int reg_base = true_regnum (base);
4297
4298 if (reg_base == reg_dest)
4299 {
4300 return avr_asm_len (TINY_ADIW (%E1, %F1, 2) CR_TAB
4301 "ld %C0,%1" CR_TAB
1a96adb9 4302 "ld __tmp_reg__,-%1" CR_TAB
b4e6d2e2 4303 TINY_SBIW (%E1, %F1, 1) CR_TAB
1a96adb9 4304 "ld %A0,%1" CR_TAB
b4e6d2e2 4305 "mov %B0,__tmp_reg__", op, plen, -8);
4306 }
4307 else
4308 {
4309 return avr_asm_len ("ld %A0,%1+" CR_TAB
4310 "ld %B0,%1+" CR_TAB
4311 "ld %C0,%1", op, plen, -3);
4312
4313 if (reg_dest != reg_base - 2 &&
4314 !reg_unused_after (insn, base))
4315 {
4316 avr_asm_len (TINY_SBIW (%E1, %F1, 2), op, plen, 2);
4317 }
4318 return "";
4319 }
4320}
4321
4322static const char*
4323avr_out_load_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
4324{
4325 rtx dest = op[0];
4326 rtx src = op[1];
4327 rtx base = XEXP (src, 0);
4328 int reg_dest = true_regnum (dest);
4329 int reg_base = true_regnum (base);
4330
4331 reg_base = true_regnum (XEXP (base, 0));
4332 if (reg_base == reg_dest)
4333 {
4334 return avr_asm_len (TINY_ADIW (%I1, %J1, %o1+2) CR_TAB
4335 "ld %C0,%b1" CR_TAB
4336 "ld __tmp_reg__,-%b1" CR_TAB
4337 TINY_SBIW (%I1, %J1, 1) CR_TAB
4338 "ld %A0,%b1" CR_TAB
4339 "mov %B0,__tmp_reg__", op, plen, -8);
4340 }
4341 else
4342 {
4343 avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
4344 "ld %A0,%b1+" CR_TAB
1a96adb9 4345 "ld %B0,%b1+" CR_TAB
b4e6d2e2 4346 "ld %C0,%b1", op, plen, -5);
4347
4348 if (reg_dest != (reg_base - 2)
4349 && !reg_unused_after (insn, XEXP (base, 0)))
4350 avr_asm_len (TINY_SBIW (%I1, %J1, %o1+2), op, plen, 2);
1a96adb9 4351
b4e6d2e2 4352 return "";
4353 }
4354}
4355
02d9a2c3 4356static const char*
375204de 4357avr_out_load_psi (rtx_insn *insn, rtx *op, int *plen)
02d9a2c3 4358{
4359 rtx dest = op[0];
4360 rtx src = op[1];
4361 rtx base = XEXP (src, 0);
4362 int reg_dest = true_regnum (dest);
4363 int reg_base = true_regnum (base);
0dff9558 4364
02d9a2c3 4365 if (reg_base > 0)
4366 {
b4e6d2e2 4367 if (AVR_TINY)
4368 return avr_out_load_psi_reg_no_disp_tiny (insn, op, plen);
4369
02d9a2c3 4370 if (reg_base == REG_X) /* (R26) */
4371 {
4372 if (reg_dest == REG_X)
4373 /* "ld r26,-X" is undefined */
4374 return avr_asm_len ("adiw r26,2" CR_TAB
4375 "ld r28,X" CR_TAB
4376 "ld __tmp_reg__,-X" CR_TAB
4377 "sbiw r26,1" CR_TAB
4378 "ld r26,X" CR_TAB
4379 "mov r27,__tmp_reg__", op, plen, -6);
4380 else
4381 {
4382 avr_asm_len ("ld %A0,X+" CR_TAB
4383 "ld %B0,X+" CR_TAB
4384 "ld %C0,X", op, plen, -3);
4385
4386 if (reg_dest != REG_X - 2
4387 && !reg_unused_after (insn, base))
4388 {
4389 avr_asm_len ("sbiw r26,2", op, plen, 1);
4390 }
4391
4392 return "";
4393 }
4394 }
4395 else /* reg_base != REG_X */
4396 {
4397 if (reg_dest == reg_base)
4398 return avr_asm_len ("ldd %C0,%1+2" CR_TAB
4399 "ldd __tmp_reg__,%1+1" CR_TAB
4400 "ld %A0,%1" CR_TAB
4401 "mov %B0,__tmp_reg__", op, plen, -4);
4402 else
4403 return avr_asm_len ("ld %A0,%1" CR_TAB
4404 "ldd %B0,%1+1" CR_TAB
4405 "ldd %C0,%1+2", op, plen, -3);
4406 }
4407 }
4408 else if (GET_CODE (base) == PLUS) /* (R + i) */
4409 {
4410 int disp = INTVAL (XEXP (base, 1));
0dff9558 4411
b4e6d2e2 4412 if (AVR_TINY)
4413 return avr_out_load_psi_reg_disp_tiny (insn, op, plen);
4414
02d9a2c3 4415 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
4416 {
4417 if (REGNO (XEXP (base, 0)) != REG_Y)
4418 fatal_insn ("incorrect insn:",insn);
4419
4420 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
4421 return avr_asm_len ("adiw r28,%o1-61" CR_TAB
4422 "ldd %A0,Y+61" CR_TAB
4423 "ldd %B0,Y+62" CR_TAB
4424 "ldd %C0,Y+63" CR_TAB
4425 "sbiw r28,%o1-61", op, plen, -5);
4426
4427 return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
4428 "sbci r29,hi8(-%o1)" CR_TAB
4429 "ld %A0,Y" CR_TAB
4430 "ldd %B0,Y+1" CR_TAB
4431 "ldd %C0,Y+2" CR_TAB
4432 "subi r28,lo8(%o1)" CR_TAB
4433 "sbci r29,hi8(%o1)", op, plen, -7);
4434 }
4435
4436 reg_base = true_regnum (XEXP (base, 0));
4437 if (reg_base == REG_X)
4438 {
4439 /* R = (X + d) */
4440 if (reg_dest == REG_X)
4441 {
4442 /* "ld r26,-X" is undefined */
4443 return avr_asm_len ("adiw r26,%o1+2" CR_TAB
4444 "ld r28,X" CR_TAB
4445 "ld __tmp_reg__,-X" CR_TAB
4446 "sbiw r26,1" CR_TAB
4447 "ld r26,X" CR_TAB
4448 "mov r27,__tmp_reg__", op, plen, -6);
4449 }
0dff9558 4450
27b3429e 4451 avr_asm_len ("adiw r26,%o1" CR_TAB
4452 "ld %A0,X+" CR_TAB
4453 "ld %B0,X+" CR_TAB
4454 "ld %C0,X", op, plen, -4);
02d9a2c3 4455
27b3429e 4456 if (reg_dest != REG_W
4457 && !reg_unused_after (insn, XEXP (base, 0)))
4458 avr_asm_len ("sbiw r26,%o1+2", op, plen, 1);
02d9a2c3 4459
27b3429e 4460 return "";
02d9a2c3 4461 }
0dff9558 4462
02d9a2c3 4463 if (reg_dest == reg_base)
4464 return avr_asm_len ("ldd %C0,%C1" CR_TAB
4465 "ldd __tmp_reg__,%B1" CR_TAB
4466 "ldd %A0,%A1" CR_TAB
4467 "mov %B0,__tmp_reg__", op, plen, -4);
4468
4469 return avr_asm_len ("ldd %A0,%A1" CR_TAB
4470 "ldd %B0,%B1" CR_TAB
4471 "ldd %C0,%C1", op, plen, -3);
4472 }
4473 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4474 return avr_asm_len ("ld %C0,%1" CR_TAB
4475 "ld %B0,%1" CR_TAB
4476 "ld %A0,%1", op, plen, -3);
4477 else if (GET_CODE (base) == POST_INC) /* (R++) */
4478 return avr_asm_len ("ld %A0,%1" CR_TAB
4479 "ld %B0,%1" CR_TAB
4480 "ld %C0,%1", op, plen, -3);
4481
4482 else if (CONSTANT_ADDRESS_P (base))
b4e6d2e2 4483 {
4484 int n_words = AVR_TINY ? 3 : 6;
4485 return avr_asm_len ("lds %A0,%m1" CR_TAB
4486 "lds %B0,%m1+1" CR_TAB
4487 "lds %C0,%m1+2", op, plen , -n_words);
4488 }
0dff9558 4489
02d9a2c3 4490 fatal_insn ("unknown move insn:",insn);
4491 return "";
4492}
4493
b4e6d2e2 4494
4495static const char*
4496avr_out_store_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
4497{
4498 rtx dest = op[0];
4499 rtx src = op[1];
4500 rtx base = XEXP (dest, 0);
4501 int reg_base = true_regnum (base);
4502 int reg_src = true_regnum (src);
4503
4504 if (reg_base == reg_src)
4505 {
4506 avr_asm_len ("st %0,%A1" CR_TAB
4507 "mov __tmp_reg__,%B1" CR_TAB
4508 TINY_ADIW (%E0, %F0, 1) CR_TAB /* st X+, r27 is undefined */
4509 "st %0+,__tmp_reg__" CR_TAB
4510 "st %0,%C1", op, plen, -6);
4511
4512 }
4513 else if (reg_src == reg_base - 2)
4514 {
4515 avr_asm_len ("st %0,%A1" CR_TAB
4516 "mov __tmp_reg__,%C1" CR_TAB
4517 TINY_ADIW (%E0, %F0, 1) CR_TAB
4518 "st %0+,%B1" CR_TAB
4519 "st %0,__tmp_reg__", op, plen, 6);
4520 }
4521 else
4522 {
4523 avr_asm_len ("st %0+,%A1" CR_TAB
4524 "st %0+,%B1" CR_TAB
4525 "st %0,%C1", op, plen, -3);
4526 }
4527
4528 if (!reg_unused_after (insn, base))
4529 avr_asm_len (TINY_SBIW (%E0, %F0, 2), op, plen, 2);
4530
4531 return "";
4532}
4533
4534static const char*
4535avr_out_store_psi_reg_disp_tiny (rtx *op, int *plen)
4536{
4537 rtx dest = op[0];
4538 rtx src = op[1];
4539 rtx base = XEXP (dest, 0);
4540 int reg_base = REGNO (XEXP (base, 0));
4541 int reg_src = true_regnum (src);
4542
4543 if (reg_src == reg_base)
4544 {
4545 return avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
4546 "mov __zero_reg__,%B1" CR_TAB
4547 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4548 "st %b0+,__tmp_reg__" CR_TAB
4549 "st %b0+,__zero_reg__" CR_TAB
4550 "st %b0,%C1" CR_TAB
4551 "clr __zero_reg__" CR_TAB
4552 TINY_SBIW (%I0, %J0, %o0+2), op, plen, -10);
4553 }
4554 else if (reg_src == reg_base - 2)
4555 {
1a96adb9 4556 return avr_asm_len ("mov __tmp_reg__,%C1" CR_TAB
b4e6d2e2 4557 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4558 "st %b0+,%A1" CR_TAB
4559 "st %b0+,%B1" CR_TAB
4560 "st %b0,__tmp_reg__" CR_TAB
4561 TINY_SBIW (%I0, %J0, %o0+2), op, plen, -8);
4562 }
4563
4564 return avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
4565 "st %b0+,%A1" CR_TAB
4566 "st %b0+,%B1" CR_TAB
4567 "st %b0,%C1" CR_TAB
4568 TINY_SBIW (%I0, %J0, %o0+2), op, plen, -7);
4569}
4570
02d9a2c3 4571/* Handle store of 24-bit type from register or zero to memory. */
4572
4573static const char*
375204de 4574avr_out_store_psi (rtx_insn *insn, rtx *op, int *plen)
02d9a2c3 4575{
4576 rtx dest = op[0];
4577 rtx src = op[1];
4578 rtx base = XEXP (dest, 0);
4579 int reg_base = true_regnum (base);
0dff9558 4580
02d9a2c3 4581 if (CONSTANT_ADDRESS_P (base))
b4e6d2e2 4582 {
4583 int n_words = AVR_TINY ? 3 : 6;
4584 return avr_asm_len ("sts %m0,%A1" CR_TAB
4585 "sts %m0+1,%B1" CR_TAB
4586 "sts %m0+2,%C1", op, plen, -n_words);
4587 }
0dff9558 4588
02d9a2c3 4589 if (reg_base > 0) /* (r) */
4590 {
b4e6d2e2 4591 if (AVR_TINY)
4592 return avr_out_store_psi_reg_no_disp_tiny (insn, op, plen);
4593
02d9a2c3 4594 if (reg_base == REG_X) /* (R26) */
4595 {
4596 gcc_assert (!reg_overlap_mentioned_p (base, src));
0dff9558 4597
02d9a2c3 4598 avr_asm_len ("st %0+,%A1" CR_TAB
4599 "st %0+,%B1" CR_TAB
4600 "st %0,%C1", op, plen, -3);
4601
4602 if (!reg_unused_after (insn, base))
4603 avr_asm_len ("sbiw r26,2", op, plen, 1);
4604
4605 return "";
4606 }
4607 else
4608 return avr_asm_len ("st %0,%A1" CR_TAB
4609 "std %0+1,%B1" CR_TAB
4610 "std %0+2,%C1", op, plen, -3);
4611 }
4612 else if (GET_CODE (base) == PLUS) /* (R + i) */
4613 {
4614 int disp = INTVAL (XEXP (base, 1));
b4e6d2e2 4615
4616 if (AVR_TINY)
4617 return avr_out_store_psi_reg_disp_tiny (op, plen);
4618
02d9a2c3 4619 reg_base = REGNO (XEXP (base, 0));
4620
4621 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
4622 {
4623 if (reg_base != REG_Y)
4624 fatal_insn ("incorrect insn:",insn);
4625
4626 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
4627 return avr_asm_len ("adiw r28,%o0-61" CR_TAB
4628 "std Y+61,%A1" CR_TAB
4629 "std Y+62,%B1" CR_TAB
4630 "std Y+63,%C1" CR_TAB
467dcd24 4631 "sbiw r28,%o0-61", op, plen, -5);
02d9a2c3 4632
4633 return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
4634 "sbci r29,hi8(-%o0)" CR_TAB
4635 "st Y,%A1" CR_TAB
4636 "std Y+1,%B1" CR_TAB
4637 "std Y+2,%C1" CR_TAB
4638 "subi r28,lo8(%o0)" CR_TAB
4639 "sbci r29,hi8(%o0)", op, plen, -7);
4640 }
4641 if (reg_base == REG_X)
4642 {
4643 /* (X + d) = R */
4644 gcc_assert (!reg_overlap_mentioned_p (XEXP (base, 0), src));
0dff9558 4645
02d9a2c3 4646 avr_asm_len ("adiw r26,%o0" CR_TAB
4647 "st X+,%A1" CR_TAB
4648 "st X+,%B1" CR_TAB
4649 "st X,%C1", op, plen, -4);
4650
4651 if (!reg_unused_after (insn, XEXP (base, 0)))
4652 avr_asm_len ("sbiw r26,%o0+2", op, plen, 1);
4653
4654 return "";
4655 }
0dff9558 4656
02d9a2c3 4657 return avr_asm_len ("std %A0,%A1" CR_TAB
4658 "std %B0,%B1" CR_TAB
4659 "std %C0,%C1", op, plen, -3);
4660 }
4661 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4662 return avr_asm_len ("st %0,%C1" CR_TAB
4663 "st %0,%B1" CR_TAB
4664 "st %0,%A1", op, plen, -3);
4665 else if (GET_CODE (base) == POST_INC) /* (R++) */
4666 return avr_asm_len ("st %0,%A1" CR_TAB
4667 "st %0,%B1" CR_TAB
4668 "st %0,%C1", op, plen, -3);
4669
4670 fatal_insn ("unknown move insn:",insn);
4671 return "";
4672}
4673
4674
4675/* Move around 24-bit stuff. */
4676
4677const char *
375204de 4678avr_out_movpsi (rtx_insn *insn, rtx *op, int *plen)
02d9a2c3 4679{
4680 rtx dest = op[0];
4681 rtx src = op[1];
0dff9558 4682
590da9f2 4683 if (avr_mem_flash_p (src)
4684 || avr_mem_flash_p (dest))
4202ef11 4685 {
4686 return avr_out_lpm (insn, op, plen);
4687 }
0dff9558 4688
02d9a2c3 4689 if (register_operand (dest, VOIDmode))
4690 {
4691 if (register_operand (src, VOIDmode)) /* mov r,r */
4692 {
4693 if (true_regnum (dest) > true_regnum (src))
4694 {
4695 avr_asm_len ("mov %C0,%C1", op, plen, -1);
4696
4697 if (AVR_HAVE_MOVW)
4698 return avr_asm_len ("movw %A0,%A1", op, plen, 1);
4699 else
4700 return avr_asm_len ("mov %B0,%B1" CR_TAB
4701 "mov %A0,%A1", op, plen, 2);
4702 }
4703 else
4704 {
4705 if (AVR_HAVE_MOVW)
4706 avr_asm_len ("movw %A0,%A1", op, plen, -1);
4707 else
4708 avr_asm_len ("mov %A0,%A1" CR_TAB
4709 "mov %B0,%B1", op, plen, -2);
0dff9558 4710
02d9a2c3 4711 return avr_asm_len ("mov %C0,%C1", op, plen, 1);
4712 }
4713 }
02d9a2c3 4714 else if (CONSTANT_P (src))
4715 {
644ac9c5 4716 return avr_out_reload_inpsi (op, NULL_RTX, plen);
02d9a2c3 4717 }
4718 else if (MEM_P (src))
4719 return avr_out_load_psi (insn, op, plen); /* mov r,m */
4720 }
4721 else if (MEM_P (dest))
4722 {
644ac9c5 4723 rtx xop[2];
4724
4725 xop[0] = dest;
4726 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
0dff9558 4727
644ac9c5 4728 return avr_out_store_psi (insn, xop, plen);
02d9a2c3 4729 }
0dff9558 4730
02d9a2c3 4731 fatal_insn ("invalid insn:", insn);
4732 return "";
4733}
4734
b4e6d2e2 4735static const char*
4736avr_out_movqi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
4737{
4738 rtx dest = op[0];
4739 rtx src = op[1];
4740 rtx x = XEXP (dest, 0);
4741
4742 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
4743 {
4744 avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
4745 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4746 "st %b0,__tmp_reg__", op, plen, -4);
4747 }
4748 else
4749 {
4750 avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
4751 "st %b0,%1" , op, plen, -3);
4752 }
4753
4754 if (!reg_unused_after (insn, XEXP (x,0)))
4755 avr_asm_len (TINY_SBIW (%I0, %J0, %o0), op, plen, 2);
4756
4757 return "";
4758}
02d9a2c3 4759
644ac9c5 4760static const char*
375204de 4761out_movqi_mr_r (rtx_insn *insn, rtx op[], int *plen)
a28e4651 4762{
37ac04dc 4763 rtx dest = op[0];
4764 rtx src = op[1];
4765 rtx x = XEXP (dest, 0);
0dff9558 4766
e511e253 4767 if (CONSTANT_ADDRESS_P (x))
a28e4651 4768 {
b4e6d2e2 4769 int n_words = AVR_TINY ? 1 : 2;
644ac9c5 4770 return optimize > 0 && io_address_operand (x, QImode)
4771 ? avr_asm_len ("out %i0,%1", op, plen, -1)
b4e6d2e2 4772 : avr_asm_len ("sts %m0,%1", op, plen, -n_words);
e511e253 4773 }
5bd39e93 4774 else if (GET_CODE (x) == PLUS
4775 && REG_P (XEXP (x, 0))
4776 && CONST_INT_P (XEXP (x, 1)))
e511e253 4777 {
5bd39e93 4778 /* memory access by reg+disp */
db45d3ed 4779
5bd39e93 4780 int disp = INTVAL (XEXP (x, 1));
db45d3ed 4781
b4e6d2e2 4782 if (AVR_TINY)
4783 return avr_out_movqi_mr_r_reg_disp_tiny (insn, op, plen);
4784
5bd39e93 4785 if (disp - GET_MODE_SIZE (GET_MODE (dest)) >= 63)
4786 {
4787 if (REGNO (XEXP (x, 0)) != REG_Y)
4788 fatal_insn ("incorrect insn:",insn);
4789
4790 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
4791 return avr_asm_len ("adiw r28,%o0-63" CR_TAB
4792 "std Y+63,%1" CR_TAB
4793 "sbiw r28,%o0-63", op, plen, -3);
4794
4795 return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
4796 "sbci r29,hi8(-%o0)" CR_TAB
4797 "st Y,%1" CR_TAB
4798 "subi r28,lo8(%o0)" CR_TAB
4799 "sbci r29,hi8(%o0)", op, plen, -5);
4800 }
e511e253 4801 else if (REGNO (XEXP (x,0)) == REG_X)
5bd39e93 4802 {
4803 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
4804 {
4805 avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
4806 "adiw r26,%o0" CR_TAB
4807 "st X,__tmp_reg__", op, plen, -3);
4808 }
4809 else
4810 {
4811 avr_asm_len ("adiw r26,%o0" CR_TAB
4812 "st X,%1", op, plen, -2);
4813 }
0dff9558 4814
5bd39e93 4815 if (!reg_unused_after (insn, XEXP (x,0)))
4816 avr_asm_len ("sbiw r26,%o0", op, plen, 1);
db45d3ed 4817
5bd39e93 4818 return "";
4819 }
0dff9558 4820
578c09ca 4821 return avr_asm_len ("std %0,%1", op, plen, -1);
a28e4651 4822 }
0dff9558 4823
7e7baeb5 4824 return avr_asm_len ("st %0,%1", op, plen, -1);
a28e4651 4825}
4826
0b6cf66f 4827
4828/* Helper for the next function for XMEGA. It does the same
4829 but with low byte first. */
4830
644ac9c5 4831static const char*
375204de 4832avr_out_movhi_mr_r_xmega (rtx_insn *insn, rtx op[], int *plen)
a28e4651 4833{
37ac04dc 4834 rtx dest = op[0];
4835 rtx src = op[1];
4836 rtx base = XEXP (dest, 0);
4837 int reg_base = true_regnum (base);
4838 int reg_src = true_regnum (src);
0b6cf66f 4839
4840 /* "volatile" forces writing low byte first, even if less efficient,
4841 for correct operation with 16-bit I/O registers like SP. */
f43bae99 4842 int mem_volatile_p = MEM_VOLATILE_P (dest);
f43bae99 4843
0b6cf66f 4844 if (CONSTANT_ADDRESS_P (base))
b4e6d2e2 4845 {
4846 int n_words = AVR_TINY ? 2 : 4;
4847 return optimize > 0 && io_address_operand (base, HImode)
4848 ? avr_asm_len ("out %i0,%A1" CR_TAB
4849 "out %i0+1,%B1", op, plen, -2)
0b6cf66f 4850
b4e6d2e2 4851 : avr_asm_len ("sts %m0,%A1" CR_TAB
4852 "sts %m0+1,%B1", op, plen, -n_words);
4853 }
0dff9558 4854
0b6cf66f 4855 if (reg_base > 0)
4856 {
4857 if (reg_base != REG_X)
4858 return avr_asm_len ("st %0,%A1" CR_TAB
4859 "std %0+1,%B1", op, plen, -2);
0dff9558 4860
0b6cf66f 4861 if (reg_src == REG_X)
4862 /* "st X+,r26" and "st -X,r26" are undefined. */
4863 avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
4864 "st X,r26" CR_TAB
4865 "adiw r26,1" CR_TAB
4866 "st X,__tmp_reg__", op, plen, -4);
4867 else
4868 avr_asm_len ("st X+,%A1" CR_TAB
4869 "st X,%B1", op, plen, -2);
00c52bc9 4870
4871 return reg_unused_after (insn, base)
0b6cf66f 4872 ? ""
4873 : avr_asm_len ("sbiw r26,1", op, plen, 1);
4874 }
4875 else if (GET_CODE (base) == PLUS)
4876 {
4877 int disp = INTVAL (XEXP (base, 1));
4878 reg_base = REGNO (XEXP (base, 0));
4879 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
4880 {
4881 if (reg_base != REG_Y)
4882 fatal_insn ("incorrect insn:",insn);
0dff9558 4883
0b6cf66f 4884 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
4885 ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
4886 "std Y+62,%A1" CR_TAB
4887 "std Y+63,%B1" CR_TAB
4888 "sbiw r28,%o0-62", op, plen, -4)
4889
4890 : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
4891 "sbci r29,hi8(-%o0)" CR_TAB
4892 "st Y,%A1" CR_TAB
4893 "std Y+1,%B1" CR_TAB
4894 "subi r28,lo8(%o0)" CR_TAB
4895 "sbci r29,hi8(%o0)", op, plen, -6);
4896 }
0dff9558 4897
0b6cf66f 4898 if (reg_base != REG_X)
4899 return avr_asm_len ("std %A0,%A1" CR_TAB
4900 "std %B0,%B1", op, plen, -2);
4901 /* (X + d) = R */
4902 return reg_src == REG_X
4903 ? avr_asm_len ("mov __tmp_reg__,r26" CR_TAB
4904 "mov __zero_reg__,r27" CR_TAB
4905 "adiw r26,%o0" CR_TAB
4906 "st X+,__tmp_reg__" CR_TAB
4907 "st X,__zero_reg__" CR_TAB
4908 "clr __zero_reg__" CR_TAB
4909 "sbiw r26,%o0+1", op, plen, -7)
4910
4911 : avr_asm_len ("adiw r26,%o0" CR_TAB
4912 "st X+,%A1" CR_TAB
4913 "st X,%B1" CR_TAB
4914 "sbiw r26,%o0+1", op, plen, -4);
4915 }
4916 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4917 {
4918 if (!mem_volatile_p)
4919 return avr_asm_len ("st %0,%B1" CR_TAB
4920 "st %0,%A1", op, plen, -2);
4921
4922 return REGNO (XEXP (base, 0)) == REG_X
4923 ? avr_asm_len ("sbiw r26,2" CR_TAB
4924 "st X+,%A1" CR_TAB
4925 "st X,%B1" CR_TAB
4926 "sbiw r26,1", op, plen, -4)
4927
4928 : avr_asm_len ("sbiw %r0,2" CR_TAB
4929 "st %p0,%A1" CR_TAB
4930 "std %p0+1,%B1", op, plen, -3);
4931 }
4932 else if (GET_CODE (base) == POST_INC) /* (R++) */
4933 {
4934 return avr_asm_len ("st %0,%A1" CR_TAB
4935 "st %0,%B1", op, plen, -2);
0dff9558 4936
0b6cf66f 4937 }
4938 fatal_insn ("unknown move insn:",insn);
4939 return "";
4940}
4941
b4e6d2e2 4942static const char*
4943avr_out_movhi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
4944{
4945 rtx dest = op[0];
4946 rtx src = op[1];
4947 rtx base = XEXP (dest, 0);
4948 int reg_base = true_regnum (base);
4949 int reg_src = true_regnum (src);
4950 int mem_volatile_p = MEM_VOLATILE_P (dest);
4951
4952 if (reg_base == reg_src)
4953 {
4954 return !mem_volatile_p && reg_unused_after (insn, src)
4955 ? avr_asm_len ("mov __tmp_reg__,%B1" CR_TAB
4956 "st %0,%A1" CR_TAB
4957 TINY_ADIW (%E0, %F0, 1) CR_TAB
4958 "st %0,__tmp_reg__", op, plen, -5)
4959 : avr_asm_len ("mov __tmp_reg__,%B1" CR_TAB
4960 TINY_ADIW (%E0, %F0, 1) CR_TAB
4961 "st %0,__tmp_reg__" CR_TAB
4962 TINY_SBIW (%E0, %F0, 1) CR_TAB
4963 "st %0, %A1", op, plen, -7);
4964 }
4965
4966 return !mem_volatile_p && reg_unused_after (insn, base)
4967 ? avr_asm_len ("st %0+,%A1" CR_TAB
4968 "st %0,%B1", op, plen, -2)
4969 : avr_asm_len (TINY_ADIW (%E0, %F0, 1) CR_TAB
4970 "st %0,%B1" CR_TAB
4971 "st -%0,%A1", op, plen, -4);
4972}
4973
4974static const char*
4975avr_out_movhi_mr_r_reg_disp_tiny (rtx op[], int *plen)
4976{
4977 rtx dest = op[0];
4978 rtx src = op[1];
4979 rtx base = XEXP (dest, 0);
4980 int reg_base = REGNO (XEXP (base, 0));
4981 int reg_src = true_regnum (src);
4982
4983 return reg_src == reg_base
4984 ? avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
4985 "mov __zero_reg__,%B1" CR_TAB
4986 TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
4987 "st %b0,__zero_reg__" CR_TAB
4988 "st -%b0,__tmp_reg__" CR_TAB
4989 "clr __zero_reg__" CR_TAB
1a96adb9 4990 TINY_SBIW (%I0, %J0, %o0), op, plen, -9)
b4e6d2e2 4991
4992 : avr_asm_len (TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
4993 "st %b0,%B1" CR_TAB
4994 "st -%b0,%A1" CR_TAB
4995 TINY_SBIW (%I0, %J0, %o0), op, plen, -6);
4996}
4997
4998static const char*
4999avr_out_movhi_mr_r_post_inc_tiny (rtx op[], int *plen)
5000{
5001 return avr_asm_len (TINY_ADIW (%I0, %J0, 1) CR_TAB
5002 "st %p0,%B1" CR_TAB
5003 "st -%p0,%A1" CR_TAB
5004 TINY_ADIW (%I0, %J0, 2), op, plen, -6);
5005}
0b6cf66f 5006
5007static const char*
375204de 5008out_movhi_mr_r (rtx_insn *insn, rtx op[], int *plen)
0b6cf66f 5009{
5010 rtx dest = op[0];
5011 rtx src = op[1];
5012 rtx base = XEXP (dest, 0);
5013 int reg_base = true_regnum (base);
5014 int reg_src = true_regnum (src);
5015 int mem_volatile_p;
5016
5017 /* "volatile" forces writing high-byte first (no-xmega) resp.
5018 low-byte first (xmega) even if less efficient, for correct
5019 operation with 16-bit I/O registers like. */
5020
5021 if (AVR_XMEGA)
5022 return avr_out_movhi_mr_r_xmega (insn, op, plen);
5023
5024 mem_volatile_p = MEM_VOLATILE_P (dest);
5025
37ac04dc 5026 if (CONSTANT_ADDRESS_P (base))
b4e6d2e2 5027 {
5028 int n_words = AVR_TINY ? 2 : 4;
5029 return optimize > 0 && io_address_operand (base, HImode)
5030 ? avr_asm_len ("out %i0+1,%B1" CR_TAB
5031 "out %i0,%A1", op, plen, -2)
644ac9c5 5032
b4e6d2e2 5033 : avr_asm_len ("sts %m0+1,%B1" CR_TAB
5034 "sts %m0,%A1", op, plen, -n_words);
5035 }
0dff9558 5036
a28e4651 5037 if (reg_base > 0)
5038 {
b4e6d2e2 5039 if (AVR_TINY)
5040 return avr_out_movhi_mr_r_reg_no_disp_tiny (insn, op, plen);
5041
644ac9c5 5042 if (reg_base != REG_X)
5043 return avr_asm_len ("std %0+1,%B1" CR_TAB
5044 "st %0,%A1", op, plen, -2);
0dff9558 5045
644ac9c5 5046 if (reg_src == REG_X)
5047 /* "st X+,r26" and "st -X,r26" are undefined. */
5048 return !mem_volatile_p && reg_unused_after (insn, src)
5049 ? avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5050 "st X,r26" CR_TAB
5051 "adiw r26,1" CR_TAB
5052 "st X,__tmp_reg__", op, plen, -4)
5053
5054 : avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5055 "adiw r26,1" CR_TAB
5056 "st X,__tmp_reg__" CR_TAB
5057 "sbiw r26,1" CR_TAB
5058 "st X,r26", op, plen, -5);
0dff9558 5059
644ac9c5 5060 return !mem_volatile_p && reg_unused_after (insn, base)
5061 ? avr_asm_len ("st X+,%A1" CR_TAB
5062 "st X,%B1", op, plen, -2)
5063 : avr_asm_len ("adiw r26,1" CR_TAB
5064 "st X,%B1" CR_TAB
5065 "st -X,%A1", op, plen, -3);
a28e4651 5066 }
37ac04dc 5067 else if (GET_CODE (base) == PLUS)
a28e4651 5068 {
37ac04dc 5069 int disp = INTVAL (XEXP (base, 1));
b4e6d2e2 5070
5071 if (AVR_TINY)
5072 return avr_out_movhi_mr_r_reg_disp_tiny (op, plen);
5073
66ad0834 5074 reg_base = REGNO (XEXP (base, 0));
37ac04dc 5075 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
644ac9c5 5076 {
5077 if (reg_base != REG_Y)
5078 fatal_insn ("incorrect insn:",insn);
0dff9558 5079
644ac9c5 5080 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
5081 ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
5082 "std Y+63,%B1" CR_TAB
5083 "std Y+62,%A1" CR_TAB
5084 "sbiw r28,%o0-62", op, plen, -4)
5085
5086 : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5087 "sbci r29,hi8(-%o0)" CR_TAB
5088 "std Y+1,%B1" CR_TAB
5089 "st Y,%A1" CR_TAB
5090 "subi r28,lo8(%o0)" CR_TAB
5091 "sbci r29,hi8(%o0)", op, plen, -6);
5092 }
0dff9558 5093
644ac9c5 5094 if (reg_base != REG_X)
5095 return avr_asm_len ("std %B0,%B1" CR_TAB
5096 "std %A0,%A1", op, plen, -2);
5097 /* (X + d) = R */
5098 return reg_src == REG_X
5099 ? avr_asm_len ("mov __tmp_reg__,r26" CR_TAB
5100 "mov __zero_reg__,r27" CR_TAB
5101 "adiw r26,%o0+1" CR_TAB
5102 "st X,__zero_reg__" CR_TAB
5103 "st -X,__tmp_reg__" CR_TAB
5104 "clr __zero_reg__" CR_TAB
5105 "sbiw r26,%o0", op, plen, -7)
5106
5107 : avr_asm_len ("adiw r26,%o0+1" CR_TAB
5108 "st X,%B1" CR_TAB
5109 "st -X,%A1" CR_TAB
5110 "sbiw r26,%o0", op, plen, -4);
e511e253 5111 }
37ac04dc 5112 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
644ac9c5 5113 {
5114 return avr_asm_len ("st %0,%B1" CR_TAB
5115 "st %0,%A1", op, plen, -2);
5116 }
37ac04dc 5117 else if (GET_CODE (base) == POST_INC) /* (R++) */
f43bae99 5118 {
644ac9c5 5119 if (!mem_volatile_p)
5120 return avr_asm_len ("st %0,%A1" CR_TAB
5121 "st %0,%B1", op, plen, -2);
0dff9558 5122
b4e6d2e2 5123 if (AVR_TINY)
5124 return avr_out_movhi_mr_r_post_inc_tiny (op, plen);
5125
644ac9c5 5126 return REGNO (XEXP (base, 0)) == REG_X
5127 ? avr_asm_len ("adiw r26,1" CR_TAB
5128 "st X,%B1" CR_TAB
5129 "st -X,%A1" CR_TAB
5130 "adiw r26,2", op, plen, -4)
f43bae99 5131
644ac9c5 5132 : avr_asm_len ("std %p0+1,%B1" CR_TAB
5133 "st %p0,%A1" CR_TAB
5134 "adiw %r0,2", op, plen, -3);
f43bae99 5135 }
68435912 5136 fatal_insn ("unknown move insn:",insn);
a28e4651 5137 return "";
5138}
5139
20c71901 5140/* Return 1 if frame pointer for current function required. */
a28e4651 5141
a45076aa 5142static bool
ebdd0478 5143avr_frame_pointer_required_p (void)
a28e4651 5144{
18d50ae6 5145 return (cfun->calls_alloca
a12b9b80 5146 || cfun->calls_setjmp
5147 || cfun->has_nonlocal_label
5148 || crtl->args.info.nregs == 0
5149 || get_frame_size () > 0);
a28e4651 5150}
5151
faf8f400 5152/* Returns the condition of compare insn INSN, or UNKNOWN. */
a28e4651 5153
faf8f400 5154static RTX_CODE
375204de 5155compare_condition (rtx_insn *insn)
a28e4651 5156{
375204de 5157 rtx_insn *next = next_real_insn (insn);
cffa155c 5158
5159 if (next && JUMP_P (next))
a28e4651 5160 {
5161 rtx pat = PATTERN (next);
5162 rtx src = SET_SRC (pat);
0dff9558 5163
cffa155c 5164 if (IF_THEN_ELSE == GET_CODE (src))
5165 return GET_CODE (XEXP (src, 0));
a28e4651 5166 }
0dff9558 5167
cffa155c 5168 return UNKNOWN;
faf8f400 5169}
5170
faf8f400 5171
dfd52f2b 5172/* Returns true iff INSN is a tst insn that only tests the sign. */
5173
5174static bool
375204de 5175compare_sign_p (rtx_insn *insn)
faf8f400 5176{
5177 RTX_CODE cond = compare_condition (insn);
5178 return (cond == GE || cond == LT);
5179}
5180
dfd52f2b 5181
5182/* Returns true iff the next insn is a JUMP_INSN with a condition
faf8f400 5183 that needs to be swapped (GT, GTU, LE, LEU). */
5184
dfd52f2b 5185static bool
375204de 5186compare_diff_p (rtx_insn *insn)
faf8f400 5187{
5188 RTX_CODE cond = compare_condition (insn);
a28e4651 5189 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
5190}
5191
dfd52f2b 5192/* Returns true iff INSN is a compare insn with the EQ or NE condition. */
a28e4651 5193
dfd52f2b 5194static bool
375204de 5195compare_eq_p (rtx_insn *insn)
a28e4651 5196{
faf8f400 5197 RTX_CODE cond = compare_condition (insn);
a28e4651 5198 return (cond == EQ || cond == NE);
5199}
5200
5201
dfd52f2b 5202/* Output compare instruction
5203
5204 compare (XOP[0], XOP[1])
5205
0dff9558 5206 for a register XOP[0] and a compile-time constant XOP[1]. Return "".
dfd52f2b 5207 XOP[2] is an 8-bit scratch register as needed.
5208
5209 PLEN == NULL: Output instructions.
5210 PLEN != NULL: Set *PLEN to the length (in words) of the sequence.
5211 Don't output anything. */
5212
5213const char*
375204de 5214avr_out_compare (rtx_insn *insn, rtx *xop, int *plen)
dfd52f2b 5215{
5216 /* Register to compare and value to compare against. */
5217 rtx xreg = xop[0];
5218 rtx xval = xop[1];
0dff9558 5219
dfd52f2b 5220 /* MODE of the comparison. */
3754d046 5221 machine_mode mode;
dfd52f2b 5222
5223 /* Number of bytes to operate on. */
017c5b98 5224 int i, n_bytes = GET_MODE_SIZE (GET_MODE (xreg));
dfd52f2b 5225
5226 /* Value (0..0xff) held in clobber register xop[2] or -1 if unknown. */
5227 int clobber_val = -1;
5228
017c5b98 5229 /* Map fixed mode operands to integer operands with the same binary
5230 representation. They are easier to handle in the remainder. */
5231
b4ebb666 5232 if (CONST_FIXED_P (xval))
017c5b98 5233 {
5234 xreg = avr_to_int_mode (xop[0]);
5235 xval = avr_to_int_mode (xop[1]);
5236 }
0dff9558 5237
017c5b98 5238 mode = GET_MODE (xreg);
5239
83921eda 5240 gcc_assert (REG_P (xreg));
5241 gcc_assert ((CONST_INT_P (xval) && n_bytes <= 4)
5242 || (const_double_operand (xval, VOIDmode) && n_bytes == 8));
0dff9558 5243
dfd52f2b 5244 if (plen)
5245 *plen = 0;
5246
7f94020e 5247 /* Comparisons == +/-1 and != +/-1 can be done similar to camparing
83921eda 5248 against 0 by ORing the bytes. This is one instruction shorter.
017c5b98 5249 Notice that 64-bit comparisons are always against reg:ALL8 18 (ACC_A)
83921eda 5250 and therefore don't use this. */
7f94020e 5251
5252 if (!test_hard_reg_class (LD_REGS, xreg)
5253 && compare_eq_p (insn)
5254 && reg_unused_after (insn, xreg))
5255 {
5256 if (xval == const1_rtx)
5257 {
5258 avr_asm_len ("dec %A0" CR_TAB
5259 "or %A0,%B0", xop, plen, 2);
0dff9558 5260
02d9a2c3 5261 if (n_bytes >= 3)
5262 avr_asm_len ("or %A0,%C0", xop, plen, 1);
5263
5264 if (n_bytes >= 4)
5265 avr_asm_len ("or %A0,%D0", xop, plen, 1);
7f94020e 5266
5267 return "";
5268 }
5269 else if (xval == constm1_rtx)
5270 {
02d9a2c3 5271 if (n_bytes >= 4)
5272 avr_asm_len ("and %A0,%D0", xop, plen, 1);
0dff9558 5273
02d9a2c3 5274 if (n_bytes >= 3)
5275 avr_asm_len ("and %A0,%C0", xop, plen, 1);
0dff9558 5276
02d9a2c3 5277 return avr_asm_len ("and %A0,%B0" CR_TAB
5278 "com %A0", xop, plen, 2);
7f94020e 5279 }
5280 }
5281
dfd52f2b 5282 for (i = 0; i < n_bytes; i++)
5283 {
5284 /* We compare byte-wise. */
5285 rtx reg8 = simplify_gen_subreg (QImode, xreg, mode, i);
5286 rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
5287
5288 /* 8-bit value to compare with this byte. */
5289 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
5290
5291 /* Registers R16..R31 can operate with immediate. */
5292 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
5293
5294 xop[0] = reg8;
5295 xop[1] = gen_int_mode (val8, QImode);
5296
5297 /* Word registers >= R24 can use SBIW/ADIW with 0..63. */
5298
5299 if (i == 0
5300 && test_hard_reg_class (ADDW_REGS, reg8))
5301 {
5302 int val16 = trunc_int_for_mode (INTVAL (xval), HImode);
0dff9558 5303
dfd52f2b 5304 if (IN_RANGE (val16, 0, 63)
5305 && (val8 == 0
5306 || reg_unused_after (insn, xreg)))
5307 {
b4e6d2e2 5308 if (AVR_TINY)
5309 avr_asm_len (TINY_SBIW (%A0, %B0, %1), xop, plen, 2);
5310 else
5311 avr_asm_len ("sbiw %0,%1", xop, plen, 1);
5312
dfd52f2b 5313 i++;
5314 continue;
5315 }
5316
5317 if (n_bytes == 2
5318 && IN_RANGE (val16, -63, -1)
5319 && compare_eq_p (insn)
5320 && reg_unused_after (insn, xreg))
5321 {
b4e6d2e2 5322 return AVR_TINY
5323 ? avr_asm_len (TINY_ADIW (%A0, %B0, %n1), xop, plen, 2)
5324 : avr_asm_len ("adiw %0,%n1", xop, plen, 1);
dfd52f2b 5325 }
5326 }
5327
5328 /* Comparing against 0 is easy. */
0dff9558 5329
dfd52f2b 5330 if (val8 == 0)
5331 {
5332 avr_asm_len (i == 0
5333 ? "cp %0,__zero_reg__"
5334 : "cpc %0,__zero_reg__", xop, plen, 1);
5335 continue;
5336 }
5337
5338 /* Upper registers can compare and subtract-with-carry immediates.
5339 Notice that compare instructions do the same as respective subtract
5340 instruction; the only difference is that comparisons don't write
5341 the result back to the target register. */
5342
5343 if (ld_reg_p)
5344 {
5345 if (i == 0)
5346 {
5347 avr_asm_len ("cpi %0,%1", xop, plen, 1);
5348 continue;
5349 }
5350 else if (reg_unused_after (insn, xreg))
5351 {
5352 avr_asm_len ("sbci %0,%1", xop, plen, 1);
5353 continue;
5354 }
5355 }
5356
5357 /* Must load the value into the scratch register. */
5358
5359 gcc_assert (REG_P (xop[2]));
0dff9558 5360
dfd52f2b 5361 if (clobber_val != (int) val8)
5362 avr_asm_len ("ldi %2,%1", xop, plen, 1);
5363 clobber_val = (int) val8;
0dff9558 5364
dfd52f2b 5365 avr_asm_len (i == 0
5366 ? "cp %0,%2"
5367 : "cpc %0,%2", xop, plen, 1);
5368 }
5369
5370 return "";
5371}
5372
5373
83921eda 5374/* Prepare operands of compare_const_di2 to be used with avr_out_compare. */
5375
5376const char*
375204de 5377avr_out_compare64 (rtx_insn *insn, rtx *op, int *plen)
83921eda 5378{
5379 rtx xop[3];
5380
5381 xop[0] = gen_rtx_REG (DImode, 18);
5382 xop[1] = op[0];
5383 xop[2] = op[1];
5384
5385 return avr_out_compare (insn, xop, plen);
5386}
5387
20c71901 5388/* Output test instruction for HImode. */
a28e4651 5389
dfd52f2b 5390const char*
375204de 5391avr_out_tsthi (rtx_insn *insn, rtx *op, int *plen)
a28e4651 5392{
faf8f400 5393 if (compare_sign_p (insn))
a28e4651 5394 {
dfd52f2b 5395 avr_asm_len ("tst %B0", op, plen, -1);
a28e4651 5396 }
dfd52f2b 5397 else if (reg_unused_after (insn, op[0])
5398 && compare_eq_p (insn))
a28e4651 5399 {
20c71901 5400 /* Faster than sbiw if we can clobber the operand. */
dfd52f2b 5401 avr_asm_len ("or %A0,%B0", op, plen, -1);
a28e4651 5402 }
dfd52f2b 5403 else
a28e4651 5404 {
dfd52f2b 5405 avr_out_compare (insn, op, plen);
a28e4651 5406 }
dfd52f2b 5407
5408 return "";
a28e4651 5409}
5410
5411
02d9a2c3 5412/* Output test instruction for PSImode. */
5413
5414const char*
375204de 5415avr_out_tstpsi (rtx_insn *insn, rtx *op, int *plen)
02d9a2c3 5416{
5417 if (compare_sign_p (insn))
5418 {
5419 avr_asm_len ("tst %C0", op, plen, -1);
5420 }
5421 else if (reg_unused_after (insn, op[0])
5422 && compare_eq_p (insn))
5423 {
5424 /* Faster than sbiw if we can clobber the operand. */
5425 avr_asm_len ("or %A0,%B0" CR_TAB
5426 "or %A0,%C0", op, plen, -2);
5427 }
5428 else
5429 {
5430 avr_out_compare (insn, op, plen);
5431 }
5432
5433 return "";
5434}
5435
5436
20c71901 5437/* Output test instruction for SImode. */
a28e4651 5438
dfd52f2b 5439const char*
375204de 5440avr_out_tstsi (rtx_insn *insn, rtx *op, int *plen)
a28e4651 5441{
faf8f400 5442 if (compare_sign_p (insn))
a28e4651 5443 {
dfd52f2b 5444 avr_asm_len ("tst %D0", op, plen, -1);
a28e4651 5445 }
dfd52f2b 5446 else if (reg_unused_after (insn, op[0])
5447 && compare_eq_p (insn))
a28e4651 5448 {
dfd52f2b 5449 /* Faster than sbiw if we can clobber the operand. */
5450 avr_asm_len ("or %A0,%B0" CR_TAB
5451 "or %A0,%C0" CR_TAB
5452 "or %A0,%D0", op, plen, -3);
5453 }
5454 else
5455 {
5456 avr_out_compare (insn, op, plen);
a28e4651 5457 }
dfd52f2b 5458
5459 return "";
a28e4651 5460}
5461
5462
644ac9c5 5463/* Generate asm equivalent for various shifts. This only handles cases
5464 that are not already carefully hand-optimized in ?sh??i3_out.
5465
5466 OPERANDS[0] resp. %0 in TEMPL is the operand to be shifted.
5467 OPERANDS[2] is the shift count as CONST_INT, MEM or REG.
5468 OPERANDS[3] is a QImode scratch register from LD regs if
5469 available and SCRATCH, otherwise (no scratch available)
5470
5471 TEMPL is an assembler template that shifts by one position.
5472 T_LEN is the length of this template. */
a28e4651 5473
5474void
375204de 5475out_shift_with_cnt (const char *templ, rtx_insn *insn, rtx operands[],
644ac9c5 5476 int *plen, int t_len)
a28e4651 5477{
644ac9c5 5478 bool second_label = true;
5479 bool saved_in_tmp = false;
5480 bool use_zero_reg = false;
5481 rtx op[5];
b681d971 5482
a28e4651 5483 op[0] = operands[0];
5484 op[1] = operands[1];
5485 op[2] = operands[2];
5486 op[3] = operands[3];
b681d971 5487
644ac9c5 5488 if (plen)
5489 *plen = 0;
b681d971 5490
4202ef11 5491 if (CONST_INT_P (operands[2]))
a28e4651 5492 {
4202ef11 5493 bool scratch = (GET_CODE (PATTERN (insn)) == PARALLEL
5494 && REG_P (operands[3]));
b681d971 5495 int count = INTVAL (operands[2]);
5496 int max_len = 10; /* If larger than this, always use a loop. */
5497
5667001b 5498 if (count <= 0)
644ac9c5 5499 return;
5667001b 5500
b681d971 5501 if (count < 8 && !scratch)
644ac9c5 5502 use_zero_reg = true;
b681d971 5503
5504 if (optimize_size)
644ac9c5 5505 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
b681d971 5506
5507 if (t_len * count <= max_len)
644ac9c5 5508 {
5509 /* Output shifts inline with no loop - faster. */
0dff9558 5510
644ac9c5 5511 while (count-- > 0)
5512 avr_asm_len (templ, op, plen, t_len);
b681d971 5513
644ac9c5 5514 return;
5515 }
b681d971 5516
5517 if (scratch)
644ac9c5 5518 {
5519 avr_asm_len ("ldi %3,%2", op, plen, 1);
5520 }
b681d971 5521 else if (use_zero_reg)
644ac9c5 5522 {
5523 /* Hack to save one word: use __zero_reg__ as loop counter.
5524 Set one bit, then shift in a loop until it is 0 again. */
b681d971 5525
644ac9c5 5526 op[3] = zero_reg_rtx;
5527
5528 avr_asm_len ("set" CR_TAB
5529 "bld %3,%2-1", op, plen, 2);
5530 }
a28e4651 5531 else
644ac9c5 5532 {
5533 /* No scratch register available, use one from LD_REGS (saved in
5534 __tmp_reg__) that doesn't overlap with registers to shift. */
b681d971 5535
644ac9c5 5536 op[3] = all_regs_rtx[((REGNO (op[0]) - 1) & 15) + 16];
5537 op[4] = tmp_reg_rtx;
5538 saved_in_tmp = true;
b681d971 5539
644ac9c5 5540 avr_asm_len ("mov %4,%3" CR_TAB
5541 "ldi %3,%2", op, plen, 2);
5542 }
b681d971 5543
644ac9c5 5544 second_label = false;
a28e4651 5545 }
644ac9c5 5546 else if (MEM_P (op[2]))
a28e4651 5547 {
644ac9c5 5548 rtx op_mov[2];
0dff9558 5549
644ac9c5 5550 op_mov[0] = op[3] = tmp_reg_rtx;
a28e4651 5551 op_mov[1] = op[2];
b681d971 5552
644ac9c5 5553 out_movqi_r_mr (insn, op_mov, plen);
a28e4651 5554 }
644ac9c5 5555 else if (register_operand (op[2], QImode))
a28e4651 5556 {
644ac9c5 5557 op[3] = op[2];
0dff9558 5558
644ac9c5 5559 if (!reg_unused_after (insn, op[2])
5560 || reg_overlap_mentioned_p (op[0], op[2]))
959d6369 5561 {
644ac9c5 5562 op[3] = tmp_reg_rtx;
5563 avr_asm_len ("mov %3,%2", op, plen, 1);
959d6369 5564 }
b681d971 5565 }
5566 else
68435912 5567 fatal_insn ("bad shift insn:", insn);
b681d971 5568
5569 if (second_label)
644ac9c5 5570 avr_asm_len ("rjmp 2f", op, plen, 1);
b681d971 5571
644ac9c5 5572 avr_asm_len ("1:", op, plen, 0);
5573 avr_asm_len (templ, op, plen, t_len);
5574
5575 if (second_label)
5576 avr_asm_len ("2:", op, plen, 0);
5577
5578 avr_asm_len (use_zero_reg ? "lsr %3" : "dec %3", op, plen, 1);
5579 avr_asm_len (second_label ? "brpl 1b" : "brne 1b", op, plen, 1);
5580
5581 if (saved_in_tmp)
5582 avr_asm_len ("mov %3,%4", op, plen, 1);
a28e4651 5583}
5584
5585
5586/* 8bit shift left ((char)x << i) */
5587
37ac04dc 5588const char *
375204de 5589ashlqi3_out (rtx_insn *insn, rtx operands[], int *len)
a28e4651 5590{
5591 if (GET_CODE (operands[2]) == CONST_INT)
5592 {
5593 int k;
1cb39658 5594
a28e4651 5595 if (!len)
5596 len = &k;
1cb39658 5597
a28e4651 5598 switch (INTVAL (operands[2]))
5599 {
1cb39658 5600 default:
5667001b 5601 if (INTVAL (operands[2]) < 8)
5602 break;
5603
1cb39658 5604 *len = 1;
02a011e9 5605 return "clr %0";
0dff9558 5606
a28e4651 5607 case 1:
1cb39658 5608 *len = 1;
02a011e9 5609 return "lsl %0";
0dff9558 5610
a28e4651 5611 case 2:
1cb39658 5612 *len = 2;
02a011e9 5613 return ("lsl %0" CR_TAB
5614 "lsl %0");
1cb39658 5615
a28e4651 5616 case 3:
1cb39658 5617 *len = 3;
02a011e9 5618 return ("lsl %0" CR_TAB
5619 "lsl %0" CR_TAB
5620 "lsl %0");
1cb39658 5621
a28e4651 5622 case 4:
0af74aa0 5623 if (test_hard_reg_class (LD_REGS, operands[0]))
a28e4651 5624 {
1cb39658 5625 *len = 2;
02a011e9 5626 return ("swap %0" CR_TAB
5627 "andi %0,0xf0");
a28e4651 5628 }
1cb39658 5629 *len = 4;
02a011e9 5630 return ("lsl %0" CR_TAB
5631 "lsl %0" CR_TAB
5632 "lsl %0" CR_TAB
5633 "lsl %0");
1cb39658 5634
a28e4651 5635 case 5:
0af74aa0 5636 if (test_hard_reg_class (LD_REGS, operands[0]))
a28e4651 5637 {
1cb39658 5638 *len = 3;
02a011e9 5639 return ("swap %0" CR_TAB
5640 "lsl %0" CR_TAB
5641 "andi %0,0xe0");
a28e4651 5642 }
1cb39658 5643 *len = 5;
02a011e9 5644 return ("lsl %0" CR_TAB
5645 "lsl %0" CR_TAB
5646 "lsl %0" CR_TAB
5647 "lsl %0" CR_TAB
5648 "lsl %0");
1cb39658 5649
a28e4651 5650 case 6:
0af74aa0 5651 if (test_hard_reg_class (LD_REGS, operands[0]))
a28e4651 5652 {
1cb39658 5653 *len = 4;
02a011e9 5654 return ("swap %0" CR_TAB
5655 "lsl %0" CR_TAB
5656 "lsl %0" CR_TAB
5657 "andi %0,0xc0");
a28e4651 5658 }
1cb39658 5659 *len = 6;
02a011e9 5660 return ("lsl %0" CR_TAB
5661 "lsl %0" CR_TAB
5662 "lsl %0" CR_TAB
5663 "lsl %0" CR_TAB
5664 "lsl %0" CR_TAB
5665 "lsl %0");
1cb39658 5666
a28e4651 5667 case 7:
1cb39658 5668 *len = 3;
02a011e9 5669 return ("ror %0" CR_TAB
5670 "clr %0" CR_TAB
5671 "ror %0");
a28e4651 5672 }
5673 }
1cb39658 5674 else if (CONSTANT_P (operands[2]))
68435912 5675 fatal_insn ("internal compiler error. Incorrect shift:", insn);
1cb39658 5676
02a011e9 5677 out_shift_with_cnt ("lsl %0",
5678 insn, operands, len, 1);
a28e4651 5679 return "";
5680}
5681
5682
5683/* 16bit shift left ((short)x << i) */
5684
37ac04dc 5685const char *
375204de 5686ashlhi3_out (rtx_insn *insn, rtx operands[], int *len)
a28e4651 5687{
5688 if (GET_CODE (operands[2]) == CONST_INT)
5689 {
b681d971 5690 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
5691 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
a28e4651 5692 int k;
b681d971 5693 int *t = len;
1cb39658 5694
a28e4651 5695 if (!len)
5696 len = &k;
0dff9558 5697
a28e4651 5698 switch (INTVAL (operands[2]))
5699 {
5667001b 5700 default:
5701 if (INTVAL (operands[2]) < 16)
5702 break;
5703
5704 *len = 2;
02a011e9 5705 return ("clr %B0" CR_TAB
5706 "clr %A0");
5667001b 5707
b681d971 5708 case 4:
5709 if (optimize_size && scratch)
5710 break; /* 5 */
5711 if (ldi_ok)
5712 {
5713 *len = 6;
02a011e9 5714 return ("swap %A0" CR_TAB
5715 "swap %B0" CR_TAB
5716 "andi %B0,0xf0" CR_TAB
5717 "eor %B0,%A0" CR_TAB
5718 "andi %A0,0xf0" CR_TAB
5719 "eor %B0,%A0");
b681d971 5720 }
5721 if (scratch)
5722 {
5723 *len = 7;
02a011e9 5724 return ("swap %A0" CR_TAB
5725 "swap %B0" CR_TAB
5726 "ldi %3,0xf0" CR_TAB
ef51d1e3 5727 "and %B0,%3" CR_TAB
02a011e9 5728 "eor %B0,%A0" CR_TAB
ef51d1e3 5729 "and %A0,%3" CR_TAB
02a011e9 5730 "eor %B0,%A0");
b681d971 5731 }
5732 break; /* optimize_size ? 6 : 8 */
1cb39658 5733
b681d971 5734 case 5:
5735 if (optimize_size)
5736 break; /* scratch ? 5 : 6 */
5737 if (ldi_ok)
5738 {
5739 *len = 8;
02a011e9 5740 return ("lsl %A0" CR_TAB
5741 "rol %B0" CR_TAB
5742 "swap %A0" CR_TAB
5743 "swap %B0" CR_TAB
5744 "andi %B0,0xf0" CR_TAB
5745 "eor %B0,%A0" CR_TAB
5746 "andi %A0,0xf0" CR_TAB
5747 "eor %B0,%A0");
b681d971 5748 }
5749 if (scratch)
5750 {
5751 *len = 9;
02a011e9 5752 return ("lsl %A0" CR_TAB
5753 "rol %B0" CR_TAB
5754 "swap %A0" CR_TAB
5755 "swap %B0" CR_TAB
5756 "ldi %3,0xf0" CR_TAB
ef51d1e3 5757 "and %B0,%3" CR_TAB
02a011e9 5758 "eor %B0,%A0" CR_TAB
ef51d1e3 5759 "and %A0,%3" CR_TAB
02a011e9 5760 "eor %B0,%A0");
b681d971 5761 }
5762 break; /* 10 */
5763
5764 case 6:
5765 if (optimize_size)
5766 break; /* scratch ? 5 : 6 */
5767 *len = 9;
02a011e9 5768 return ("clr __tmp_reg__" CR_TAB
5769 "lsr %B0" CR_TAB
5770 "ror %A0" CR_TAB
5771 "ror __tmp_reg__" CR_TAB
5772 "lsr %B0" CR_TAB
5773 "ror %A0" CR_TAB
5774 "ror __tmp_reg__" CR_TAB
5775 "mov %B0,%A0" CR_TAB
5776 "mov %A0,__tmp_reg__");
1cb39658 5777
28f5cc4d 5778 case 7:
5779 *len = 5;
02a011e9 5780 return ("lsr %B0" CR_TAB
5781 "mov %B0,%A0" CR_TAB
5782 "clr %A0" CR_TAB
5783 "ror %B0" CR_TAB
5784 "ror %A0");
28f5cc4d 5785
a28e4651 5786 case 8:
02a011e9 5787 return *len = 2, ("mov %B0,%A1" CR_TAB
5788 "clr %A0");
28f5cc4d 5789
5790 case 9:
5791 *len = 3;
02a011e9 5792 return ("mov %B0,%A0" CR_TAB
5793 "clr %A0" CR_TAB
5794 "lsl %B0");
28f5cc4d 5795
5796 case 10:
5797 *len = 4;
02a011e9 5798 return ("mov %B0,%A0" CR_TAB
5799 "clr %A0" CR_TAB
5800 "lsl %B0" CR_TAB
5801 "lsl %B0");
28f5cc4d 5802
5803 case 11:
5804 *len = 5;
02a011e9 5805 return ("mov %B0,%A0" CR_TAB
5806 "clr %A0" CR_TAB
5807 "lsl %B0" CR_TAB
5808 "lsl %B0" CR_TAB
5809 "lsl %B0");
28f5cc4d 5810
5811 case 12:
b681d971 5812 if (ldi_ok)
28f5cc4d 5813 {
5814 *len = 4;
02a011e9 5815 return ("mov %B0,%A0" CR_TAB
5816 "clr %A0" CR_TAB
5817 "swap %B0" CR_TAB
5818 "andi %B0,0xf0");
28f5cc4d 5819 }
b681d971 5820 if (scratch)
5821 {
5822 *len = 5;
02a011e9 5823 return ("mov %B0,%A0" CR_TAB
5824 "clr %A0" CR_TAB
5825 "swap %B0" CR_TAB
5826 "ldi %3,0xf0" CR_TAB
ef51d1e3 5827 "and %B0,%3");
b681d971 5828 }
5829 *len = 6;
02a011e9 5830 return ("mov %B0,%A0" CR_TAB
5831 "clr %A0" CR_TAB
5832 "lsl %B0" CR_TAB
5833 "lsl %B0" CR_TAB
5834 "lsl %B0" CR_TAB
5835 "lsl %B0");
28f5cc4d 5836
5837 case 13:
b681d971 5838 if (ldi_ok)
28f5cc4d 5839 {
5840 *len = 5;
02a011e9 5841 return ("mov %B0,%A0" CR_TAB
5842 "clr %A0" CR_TAB
5843 "swap %B0" CR_TAB
5844 "lsl %B0" CR_TAB
5845 "andi %B0,0xe0");
28f5cc4d 5846 }
8cc5a1af 5847 if (AVR_HAVE_MUL && scratch)
28f5cc4d 5848 {
5849 *len = 5;
02a011e9 5850 return ("ldi %3,0x20" CR_TAB
5851 "mul %A0,%3" CR_TAB
5852 "mov %B0,r0" CR_TAB
5853 "clr %A0" CR_TAB
5854 "clr __zero_reg__");
28f5cc4d 5855 }
b681d971 5856 if (optimize_size && scratch)
5857 break; /* 5 */
5858 if (scratch)
5859 {
5860 *len = 6;
02a011e9 5861 return ("mov %B0,%A0" CR_TAB
5862 "clr %A0" CR_TAB
5863 "swap %B0" CR_TAB
5864 "lsl %B0" CR_TAB
5865 "ldi %3,0xe0" CR_TAB
ef51d1e3 5866 "and %B0,%3");
b681d971 5867 }
8cc5a1af 5868 if (AVR_HAVE_MUL)
b681d971 5869 {
5870 *len = 6;
5871 return ("set" CR_TAB
02a011e9 5872 "bld r1,5" CR_TAB
5873 "mul %A0,r1" CR_TAB
5874 "mov %B0,r0" CR_TAB
5875 "clr %A0" CR_TAB
5876 "clr __zero_reg__");
b681d971 5877 }
5878 *len = 7;
02a011e9 5879 return ("mov %B0,%A0" CR_TAB
5880 "clr %A0" CR_TAB
5881 "lsl %B0" CR_TAB
5882 "lsl %B0" CR_TAB
5883 "lsl %B0" CR_TAB
5884 "lsl %B0" CR_TAB
5885 "lsl %B0");
28f5cc4d 5886
5887 case 14:
8cc5a1af 5888 if (AVR_HAVE_MUL && ldi_ok)
b681d971 5889 {
5890 *len = 5;
02a011e9 5891 return ("ldi %B0,0x40" CR_TAB
5892 "mul %A0,%B0" CR_TAB
5893 "mov %B0,r0" CR_TAB
5894 "clr %A0" CR_TAB
5895 "clr __zero_reg__");
b681d971 5896 }
8cc5a1af 5897 if (AVR_HAVE_MUL && scratch)
28f5cc4d 5898 {
5899 *len = 5;
02a011e9 5900 return ("ldi %3,0x40" CR_TAB
5901 "mul %A0,%3" CR_TAB
5902 "mov %B0,r0" CR_TAB
5903 "clr %A0" CR_TAB
5904 "clr __zero_reg__");
28f5cc4d 5905 }
b681d971 5906 if (optimize_size && ldi_ok)
5907 {
5908 *len = 5;
02a011e9 5909 return ("mov %B0,%A0" CR_TAB
5910 "ldi %A0,6" "\n1:\t"
5911 "lsl %B0" CR_TAB
5912 "dec %A0" CR_TAB
5913 "brne 1b");
b681d971 5914 }
5915 if (optimize_size && scratch)
5916 break; /* 5 */
5917 *len = 6;
02a011e9 5918 return ("clr %B0" CR_TAB
5919 "lsr %A0" CR_TAB
5920 "ror %B0" CR_TAB
5921 "lsr %A0" CR_TAB
5922 "ror %B0" CR_TAB
5923 "clr %A0");
28f5cc4d 5924
5925 case 15:
5926 *len = 4;
02a011e9 5927 return ("clr %B0" CR_TAB
5928 "lsr %A0" CR_TAB
5929 "ror %B0" CR_TAB
5930 "clr %A0");
a28e4651 5931 }
28f5cc4d 5932 len = t;
a28e4651 5933 }
02a011e9 5934 out_shift_with_cnt ("lsl %A0" CR_TAB
5935 "rol %B0", insn, operands, len, 2);
a28e4651 5936 return "";
5937}
5938
5939
02d9a2c3 5940/* 24-bit shift left */
5941
5942const char*
375204de 5943avr_out_ashlpsi3 (rtx_insn *insn, rtx *op, int *plen)
02d9a2c3 5944{
5945 if (plen)
5946 *plen = 0;
0dff9558 5947
02d9a2c3 5948 if (CONST_INT_P (op[2]))
5949 {
5950 switch (INTVAL (op[2]))
5951 {
5952 default:
5953 if (INTVAL (op[2]) < 24)
5954 break;
5955
5956 return avr_asm_len ("clr %A0" CR_TAB
5957 "clr %B0" CR_TAB
5958 "clr %C0", op, plen, 3);
5959
5960 case 8:
5961 {
5962 int reg0 = REGNO (op[0]);
5963 int reg1 = REGNO (op[1]);
0dff9558 5964
02d9a2c3 5965 if (reg0 >= reg1)
5966 return avr_asm_len ("mov %C0,%B1" CR_TAB
5967 "mov %B0,%A1" CR_TAB
5968 "clr %A0", op, plen, 3);
5969 else
5970 return avr_asm_len ("clr %A0" CR_TAB
5971 "mov %B0,%A1" CR_TAB
5972 "mov %C0,%B1", op, plen, 3);
5973 }
5974
5975 case 16:
5976 {
5977 int reg0 = REGNO (op[0]);
5978 int reg1 = REGNO (op[1]);
5979
5980 if (reg0 + 2 != reg1)
5981 avr_asm_len ("mov %C0,%A0", op, plen, 1);
0dff9558 5982
02d9a2c3 5983 return avr_asm_len ("clr %B0" CR_TAB
5984 "clr %A0", op, plen, 2);
5985 }
5986
5987 case 23:
5988 return avr_asm_len ("clr %C0" CR_TAB
5989 "lsr %A0" CR_TAB
5990 "ror %C0" CR_TAB
5991 "clr %B0" CR_TAB
5992 "clr %A0", op, plen, 5);
5993 }
5994 }
0dff9558 5995
02d9a2c3 5996 out_shift_with_cnt ("lsl %A0" CR_TAB
5997 "rol %B0" CR_TAB
5998 "rol %C0", insn, op, plen, 3);
5999 return "";
6000}
6001
6002
a28e4651 6003/* 32bit shift left ((long)x << i) */
6004
37ac04dc 6005const char *
375204de 6006ashlsi3_out (rtx_insn *insn, rtx operands[], int *len)
a28e4651 6007{
6008 if (GET_CODE (operands[2]) == CONST_INT)
6009 {
6010 int k;
b681d971 6011 int *t = len;
0dff9558 6012
a28e4651 6013 if (!len)
6014 len = &k;
0dff9558 6015
a28e4651 6016 switch (INTVAL (operands[2]))
6017 {
5667001b 6018 default:
6019 if (INTVAL (operands[2]) < 32)
6020 break;
6021
0aab73c2 6022 if (AVR_HAVE_MOVW)
02a011e9 6023 return *len = 3, ("clr %D0" CR_TAB
6024 "clr %C0" CR_TAB
6025 "movw %A0,%C0");
5667001b 6026 *len = 4;
02a011e9 6027 return ("clr %D0" CR_TAB
6028 "clr %C0" CR_TAB
6029 "clr %B0" CR_TAB
6030 "clr %A0");
5667001b 6031
a28e4651 6032 case 8:
6033 {
6034 int reg0 = true_regnum (operands[0]);
6035 int reg1 = true_regnum (operands[1]);
1cb39658 6036 *len = 4;
a28e4651 6037 if (reg0 >= reg1)
02a011e9 6038 return ("mov %D0,%C1" CR_TAB
6039 "mov %C0,%B1" CR_TAB
6040 "mov %B0,%A1" CR_TAB
6041 "clr %A0");
a28e4651 6042 else
02a011e9 6043 return ("clr %A0" CR_TAB
6044 "mov %B0,%A1" CR_TAB
6045 "mov %C0,%B1" CR_TAB
6046 "mov %D0,%C1");
a28e4651 6047 }
1cb39658 6048
a28e4651 6049 case 16:
6050 {
6051 int reg0 = true_regnum (operands[0]);
6052 int reg1 = true_regnum (operands[1]);
a28e4651 6053 if (reg0 + 2 == reg1)
02a011e9 6054 return *len = 2, ("clr %B0" CR_TAB
6055 "clr %A0");
ab3a6ef8 6056 if (AVR_HAVE_MOVW)
02a011e9 6057 return *len = 3, ("movw %C0,%A1" CR_TAB
6058 "clr %B0" CR_TAB
6059 "clr %A0");
a28e4651 6060 else
02a011e9 6061 return *len = 4, ("mov %C0,%A1" CR_TAB
6062 "mov %D0,%B1" CR_TAB
6063 "clr %B0" CR_TAB
6064 "clr %A0");
a28e4651 6065 }
1cb39658 6066
a28e4651 6067 case 24:
1cb39658 6068 *len = 4;
02a011e9 6069 return ("mov %D0,%A1" CR_TAB
6070 "clr %C0" CR_TAB
6071 "clr %B0" CR_TAB
6072 "clr %A0");
28f5cc4d 6073
6074 case 31:
6075 *len = 6;
02a011e9 6076 return ("clr %D0" CR_TAB
6077 "lsr %A0" CR_TAB
6078 "ror %D0" CR_TAB
6079 "clr %C0" CR_TAB
6080 "clr %B0" CR_TAB
6081 "clr %A0");
a28e4651 6082 }
28f5cc4d 6083 len = t;
a28e4651 6084 }
02a011e9 6085 out_shift_with_cnt ("lsl %A0" CR_TAB
6086 "rol %B0" CR_TAB
6087 "rol %C0" CR_TAB
6088 "rol %D0", insn, operands, len, 4);
a28e4651 6089 return "";
6090}
6091
6092/* 8bit arithmetic shift right ((signed char)x >> i) */
6093
37ac04dc 6094const char *
375204de 6095ashrqi3_out (rtx_insn *insn, rtx operands[], int *len)
a28e4651 6096{
6097 if (GET_CODE (operands[2]) == CONST_INT)
6098 {
a28e4651 6099 int k;
1cb39658 6100
a28e4651 6101 if (!len)
6102 len = &k;
1cb39658 6103
a28e4651 6104 switch (INTVAL (operands[2]))
6105 {
a28e4651 6106 case 1:
1cb39658 6107 *len = 1;
02a011e9 6108 return "asr %0";
1cb39658 6109
a28e4651 6110 case 2:
1cb39658 6111 *len = 2;
02a011e9 6112 return ("asr %0" CR_TAB
6113 "asr %0");
1cb39658 6114
a28e4651 6115 case 3:
1cb39658 6116 *len = 3;
02a011e9 6117 return ("asr %0" CR_TAB
6118 "asr %0" CR_TAB
6119 "asr %0");
1cb39658 6120
a28e4651 6121 case 4:
1cb39658 6122 *len = 4;
02a011e9 6123 return ("asr %0" CR_TAB
6124 "asr %0" CR_TAB
6125 "asr %0" CR_TAB
6126 "asr %0");
1cb39658 6127
6128 case 5:
6129 *len = 5;
02a011e9 6130 return ("asr %0" CR_TAB
6131 "asr %0" CR_TAB
6132 "asr %0" CR_TAB
6133 "asr %0" CR_TAB
6134 "asr %0");
1cb39658 6135
6136 case 6:
6137 *len = 4;
02a011e9 6138 return ("bst %0,6" CR_TAB
6139 "lsl %0" CR_TAB
6140 "sbc %0,%0" CR_TAB
6141 "bld %0,0");
1cb39658 6142
6143 default:
5667001b 6144 if (INTVAL (operands[2]) < 8)
6145 break;
6146
6147 /* fall through */
6148
1cb39658 6149 case 7:
6150 *len = 2;
02a011e9 6151 return ("lsl %0" CR_TAB
6152 "sbc %0,%0");
a28e4651 6153 }
6154 }
1cb39658 6155 else if (CONSTANT_P (operands[2]))
68435912 6156 fatal_insn ("internal compiler error. Incorrect shift:", insn);
1cb39658 6157
02a011e9 6158 out_shift_with_cnt ("asr %0",
6159 insn, operands, len, 1);
a28e4651 6160 return "";
6161}
6162
6163
6164/* 16bit arithmetic shift right ((signed short)x >> i) */
6165
37ac04dc 6166const char *
375204de 6167ashrhi3_out (rtx_insn *insn, rtx operands[], int *len)
a28e4651 6168{
6169 if (GET_CODE (operands[2]) == CONST_INT)
6170 {
b681d971 6171 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
6172 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
a28e4651 6173 int k;
1cb39658 6174 int *t = len;
0dff9558 6175
a28e4651 6176 if (!len)
6177 len = &k;
1cb39658 6178
a28e4651 6179 switch (INTVAL (operands[2]))
6180 {
b681d971 6181 case 4:
6182 case 5:
6183 /* XXX try to optimize this too? */
6184 break;
1cb39658 6185
b681d971 6186 case 6:
6187 if (optimize_size)
6188 break; /* scratch ? 5 : 6 */
6189 *len = 8;
02a011e9 6190 return ("mov __tmp_reg__,%A0" CR_TAB
6191 "mov %A0,%B0" CR_TAB
6192 "lsl __tmp_reg__" CR_TAB
6193 "rol %A0" CR_TAB
6194 "sbc %B0,%B0" CR_TAB
6195 "lsl __tmp_reg__" CR_TAB
6196 "rol %A0" CR_TAB
6197 "rol %B0");
1cb39658 6198
28f5cc4d 6199 case 7:
6200 *len = 4;
02a011e9 6201 return ("lsl %A0" CR_TAB
6202 "mov %A0,%B0" CR_TAB
6203 "rol %A0" CR_TAB
6204 "sbc %B0,%B0");
28f5cc4d 6205
a28e4651 6206 case 8:
b681d971 6207 {
6208 int reg0 = true_regnum (operands[0]);
6209 int reg1 = true_regnum (operands[1]);
6210
6211 if (reg0 == reg1)
02a011e9 6212 return *len = 3, ("mov %A0,%B0" CR_TAB
6213 "lsl %B0" CR_TAB
6214 "sbc %B0,%B0");
0dff9558 6215 else
02a011e9 6216 return *len = 4, ("mov %A0,%B1" CR_TAB
6217 "clr %B0" CR_TAB
6218 "sbrc %A0,7" CR_TAB
6219 "dec %B0");
b681d971 6220 }
1cb39658 6221
28f5cc4d 6222 case 9:
6223 *len = 4;
02a011e9 6224 return ("mov %A0,%B0" CR_TAB
6225 "lsl %B0" CR_TAB
6226 "sbc %B0,%B0" CR_TAB
6227 "asr %A0");
28f5cc4d 6228
6229 case 10:
6230 *len = 5;
02a011e9 6231 return ("mov %A0,%B0" CR_TAB
6232 "lsl %B0" CR_TAB
6233 "sbc %B0,%B0" CR_TAB
6234 "asr %A0" CR_TAB
6235 "asr %A0");
28f5cc4d 6236
6237 case 11:
8cc5a1af 6238 if (AVR_HAVE_MUL && ldi_ok)
28f5cc4d 6239 {
6240 *len = 5;
02a011e9 6241 return ("ldi %A0,0x20" CR_TAB
6242 "muls %B0,%A0" CR_TAB
6243 "mov %A0,r1" CR_TAB
6244 "sbc %B0,%B0" CR_TAB
6245 "clr __zero_reg__");
28f5cc4d 6246 }
b681d971 6247 if (optimize_size && scratch)
6248 break; /* 5 */
6249 *len = 6;
02a011e9 6250 return ("mov %A0,%B0" CR_TAB
6251 "lsl %B0" CR_TAB
6252 "sbc %B0,%B0" CR_TAB
6253 "asr %A0" CR_TAB
6254 "asr %A0" CR_TAB
6255 "asr %A0");
28f5cc4d 6256
6257 case 12:
8cc5a1af 6258 if (AVR_HAVE_MUL && ldi_ok)
28f5cc4d 6259 {
6260 *len = 5;
02a011e9 6261 return ("ldi %A0,0x10" CR_TAB
6262 "muls %B0,%A0" CR_TAB
6263 "mov %A0,r1" CR_TAB
6264 "sbc %B0,%B0" CR_TAB
6265 "clr __zero_reg__");
28f5cc4d 6266 }
b681d971 6267 if (optimize_size && scratch)
6268 break; /* 5 */
6269 *len = 7;
02a011e9 6270 return ("mov %A0,%B0" CR_TAB
6271 "lsl %B0" CR_TAB
6272 "sbc %B0,%B0" CR_TAB
6273 "asr %A0" CR_TAB
6274 "asr %A0" CR_TAB
6275 "asr %A0" CR_TAB
6276 "asr %A0");
28f5cc4d 6277
6278 case 13:
8cc5a1af 6279 if (AVR_HAVE_MUL && ldi_ok)
28f5cc4d 6280 {
6281 *len = 5;
02a011e9 6282 return ("ldi %A0,0x08" CR_TAB
6283 "muls %B0,%A0" CR_TAB
6284 "mov %A0,r1" CR_TAB
6285 "sbc %B0,%B0" CR_TAB
6286 "clr __zero_reg__");
28f5cc4d 6287 }
b681d971 6288 if (optimize_size)
6289 break; /* scratch ? 5 : 7 */
6290 *len = 8;
02a011e9 6291 return ("mov %A0,%B0" CR_TAB
6292 "lsl %B0" CR_TAB
6293 "sbc %B0,%B0" CR_TAB
6294 "asr %A0" CR_TAB
6295 "asr %A0" CR_TAB
6296 "asr %A0" CR_TAB
6297 "asr %A0" CR_TAB
6298 "asr %A0");
28f5cc4d 6299
6300 case 14:
6301 *len = 5;
02a011e9 6302 return ("lsl %B0" CR_TAB
6303 "sbc %A0,%A0" CR_TAB
6304 "lsl %B0" CR_TAB
6305 "mov %B0,%A0" CR_TAB
6306 "rol %A0");
28f5cc4d 6307
5667001b 6308 default:
6309 if (INTVAL (operands[2]) < 16)
6310 break;
6311
6312 /* fall through */
6313
8a2a7305 6314 case 15:
02a011e9 6315 return *len = 3, ("lsl %B0" CR_TAB
6316 "sbc %A0,%A0" CR_TAB
6317 "mov %B0,%A0");
a28e4651 6318 }
28f5cc4d 6319 len = t;
a28e4651 6320 }
02a011e9 6321 out_shift_with_cnt ("asr %B0" CR_TAB
6322 "ror %A0", insn, operands, len, 2);
a28e4651 6323 return "";
6324}
6325
6326
02d9a2c3 6327/* 24-bit arithmetic shift right */
6328
6329const char*
375204de 6330avr_out_ashrpsi3 (rtx_insn *insn, rtx *op, int *plen)
02d9a2c3 6331{
6332 int dest = REGNO (op[0]);
6333 int src = REGNO (op[1]);
6334
6335 if (CONST_INT_P (op[2]))
6336 {
6337 if (plen)
6338 *plen = 0;
0dff9558 6339
02d9a2c3 6340 switch (INTVAL (op[2]))
6341 {
6342 case 8:
6343 if (dest <= src)
6344 return avr_asm_len ("mov %A0,%B1" CR_TAB
6345 "mov %B0,%C1" CR_TAB
6346 "clr %C0" CR_TAB
6347 "sbrc %B0,7" CR_TAB
6348 "dec %C0", op, plen, 5);
6349 else
6350 return avr_asm_len ("clr %C0" CR_TAB
6351 "sbrc %C1,7" CR_TAB
6352 "dec %C0" CR_TAB
6353 "mov %B0,%C1" CR_TAB
6354 "mov %A0,%B1", op, plen, 5);
0dff9558 6355
02d9a2c3 6356 case 16:
6357 if (dest != src + 2)
6358 avr_asm_len ("mov %A0,%C1", op, plen, 1);
0dff9558 6359
02d9a2c3 6360 return avr_asm_len ("clr %B0" CR_TAB
6361 "sbrc %A0,7" CR_TAB
6362 "com %B0" CR_TAB
6363 "mov %C0,%B0", op, plen, 4);
6364
6365 default:
6366 if (INTVAL (op[2]) < 24)
6367 break;
6368
6369 /* fall through */
6370
8e8ae8d4 6371 case 23:
02d9a2c3 6372 return avr_asm_len ("lsl %C0" CR_TAB
6373 "sbc %A0,%A0" CR_TAB
6374 "mov %B0,%A0" CR_TAB
6375 "mov %C0,%A0", op, plen, 4);
6376 } /* switch */
6377 }
0dff9558 6378
02d9a2c3 6379 out_shift_with_cnt ("asr %C0" CR_TAB
6380 "ror %B0" CR_TAB
6381 "ror %A0", insn, op, plen, 3);
6382 return "";
6383}
6384
6385
0dff9558 6386/* 32-bit arithmetic shift right ((signed long)x >> i) */
a28e4651 6387
37ac04dc 6388const char *
375204de 6389ashrsi3_out (rtx_insn *insn, rtx operands[], int *len)
a28e4651 6390{
6391 if (GET_CODE (operands[2]) == CONST_INT)
6392 {
6393 int k;
6394 int *t = len;
0dff9558 6395
a28e4651 6396 if (!len)
6397 len = &k;
0dff9558 6398
a28e4651 6399 switch (INTVAL (operands[2]))
6400 {
a28e4651 6401 case 8:
6402 {
6403 int reg0 = true_regnum (operands[0]);
6404 int reg1 = true_regnum (operands[1]);
6405 *len=6;
6406 if (reg0 <= reg1)
02a011e9 6407 return ("mov %A0,%B1" CR_TAB
6408 "mov %B0,%C1" CR_TAB
6409 "mov %C0,%D1" CR_TAB
6410 "clr %D0" CR_TAB
6411 "sbrc %C0,7" CR_TAB
6412 "dec %D0");
a28e4651 6413 else
02a011e9 6414 return ("clr %D0" CR_TAB
6415 "sbrc %D1,7" CR_TAB
6416 "dec %D0" CR_TAB
6417 "mov %C0,%D1" CR_TAB
6418 "mov %B0,%C1" CR_TAB
6419 "mov %A0,%B1");
a28e4651 6420 }
0dff9558 6421
a28e4651 6422 case 16:
6423 {
6424 int reg0 = true_regnum (operands[0]);
6425 int reg1 = true_regnum (operands[1]);
0dff9558 6426
ab3a6ef8 6427 if (reg0 == reg1 + 2)
02a011e9 6428 return *len = 4, ("clr %D0" CR_TAB
6429 "sbrc %B0,7" CR_TAB
6430 "com %D0" CR_TAB
6431 "mov %C0,%D0");
ab3a6ef8 6432 if (AVR_HAVE_MOVW)
02a011e9 6433 return *len = 5, ("movw %A0,%C1" CR_TAB
6434 "clr %D0" CR_TAB
6435 "sbrc %B0,7" CR_TAB
6436 "com %D0" CR_TAB
6437 "mov %C0,%D0");
0dff9558 6438 else
02a011e9 6439 return *len = 6, ("mov %B0,%D1" CR_TAB
6440 "mov %A0,%C1" CR_TAB
6441 "clr %D0" CR_TAB
6442 "sbrc %B0,7" CR_TAB
6443 "com %D0" CR_TAB
6444 "mov %C0,%D0");
a28e4651 6445 }
1cb39658 6446
a28e4651 6447 case 24:
02a011e9 6448 return *len = 6, ("mov %A0,%D1" CR_TAB
6449 "clr %D0" CR_TAB
6450 "sbrc %A0,7" CR_TAB
6451 "com %D0" CR_TAB
6452 "mov %B0,%D0" CR_TAB
6453 "mov %C0,%D0");
28f5cc4d 6454
5667001b 6455 default:
6456 if (INTVAL (operands[2]) < 32)
6457 break;
6458
6459 /* fall through */
6460
28f5cc4d 6461 case 31:
0aab73c2 6462 if (AVR_HAVE_MOVW)
02a011e9 6463 return *len = 4, ("lsl %D0" CR_TAB
6464 "sbc %A0,%A0" CR_TAB
6465 "mov %B0,%A0" CR_TAB
6466 "movw %C0,%A0");
28f5cc4d 6467 else
02a011e9 6468 return *len = 5, ("lsl %D0" CR_TAB
6469 "sbc %A0,%A0" CR_TAB
6470 "mov %B0,%A0" CR_TAB
6471 "mov %C0,%A0" CR_TAB
6472 "mov %D0,%A0");
a28e4651 6473 }
28f5cc4d 6474 len = t;
a28e4651 6475 }
02a011e9 6476 out_shift_with_cnt ("asr %D0" CR_TAB
6477 "ror %C0" CR_TAB
6478 "ror %B0" CR_TAB
6479 "ror %A0", insn, operands, len, 4);
a28e4651 6480 return "";
6481}
6482
0dff9558 6483/* 8-bit logic shift right ((unsigned char)x >> i) */
a28e4651 6484
37ac04dc 6485const char *
375204de 6486lshrqi3_out (rtx_insn *insn, rtx operands[], int *len)
a28e4651 6487{
6488 if (GET_CODE (operands[2]) == CONST_INT)
6489 {
6490 int k;
1cb39658 6491
a28e4651 6492 if (!len)
6493 len = &k;
0dff9558 6494
a28e4651 6495 switch (INTVAL (operands[2]))
6496 {
1cb39658 6497 default:
5667001b 6498 if (INTVAL (operands[2]) < 8)
6499 break;
6500
1cb39658 6501 *len = 1;
02a011e9 6502 return "clr %0";
1cb39658 6503
a28e4651 6504 case 1:
1cb39658 6505 *len = 1;
02a011e9 6506 return "lsr %0";
1cb39658 6507
a28e4651 6508 case 2:
1cb39658 6509 *len = 2;
02a011e9 6510 return ("lsr %0" CR_TAB
6511 "lsr %0");
a28e4651 6512 case 3:
1cb39658 6513 *len = 3;
02a011e9 6514 return ("lsr %0" CR_TAB
6515 "lsr %0" CR_TAB
6516 "lsr %0");
0dff9558 6517
a28e4651 6518 case 4:
0af74aa0 6519 if (test_hard_reg_class (LD_REGS, operands[0]))
a28e4651 6520 {
6521 *len=2;
02a011e9 6522 return ("swap %0" CR_TAB
6523 "andi %0,0x0f");
a28e4651 6524 }
1cb39658 6525 *len = 4;
02a011e9 6526 return ("lsr %0" CR_TAB
6527 "lsr %0" CR_TAB
6528 "lsr %0" CR_TAB
6529 "lsr %0");
0dff9558 6530
a28e4651 6531 case 5:
0af74aa0 6532 if (test_hard_reg_class (LD_REGS, operands[0]))
a28e4651 6533 {
1cb39658 6534 *len = 3;
02a011e9 6535 return ("swap %0" CR_TAB
6536 "lsr %0" CR_TAB
6537 "andi %0,0x7");
a28e4651 6538 }
1cb39658 6539 *len = 5;
02a011e9 6540 return ("lsr %0" CR_TAB
6541 "lsr %0" CR_TAB
6542 "lsr %0" CR_TAB
6543 "lsr %0" CR_TAB
6544 "lsr %0");
0dff9558 6545
a28e4651 6546 case 6:
0af74aa0 6547 if (test_hard_reg_class (LD_REGS, operands[0]))
a28e4651 6548 {
1cb39658 6549 *len = 4;
02a011e9 6550 return ("swap %0" CR_TAB
6551 "lsr %0" CR_TAB
6552 "lsr %0" CR_TAB
6553 "andi %0,0x3");
a28e4651 6554 }
1cb39658 6555 *len = 6;
02a011e9 6556 return ("lsr %0" CR_TAB
6557 "lsr %0" CR_TAB
6558 "lsr %0" CR_TAB
6559 "lsr %0" CR_TAB
6560 "lsr %0" CR_TAB
6561 "lsr %0");
0dff9558 6562
a28e4651 6563 case 7:
1cb39658 6564 *len = 3;
02a011e9 6565 return ("rol %0" CR_TAB
6566 "clr %0" CR_TAB
6567 "rol %0");
a28e4651 6568 }
6569 }
1cb39658 6570 else if (CONSTANT_P (operands[2]))
68435912 6571 fatal_insn ("internal compiler error. Incorrect shift:", insn);
0dff9558 6572
02a011e9 6573 out_shift_with_cnt ("lsr %0",
6574 insn, operands, len, 1);
a28e4651 6575 return "";
6576}
6577
0dff9558 6578/* 16-bit logic shift right ((unsigned short)x >> i) */
a28e4651 6579
37ac04dc 6580const char *
375204de 6581lshrhi3_out (rtx_insn *insn, rtx operands[], int *len)
a28e4651 6582{
6583 if (GET_CODE (operands[2]) == CONST_INT)
6584 {
b681d971 6585 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
6586 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
a28e4651 6587 int k;
1cb39658 6588 int *t = len;
b681d971 6589
a28e4651 6590 if (!len)
6591 len = &k;
0dff9558 6592
a28e4651 6593 switch (INTVAL (operands[2]))
6594 {
5667001b 6595 default:
6596 if (INTVAL (operands[2]) < 16)
6597 break;
6598
6599 *len = 2;
02a011e9 6600 return ("clr %B0" CR_TAB
6601 "clr %A0");
5667001b 6602
b681d971 6603 case 4:
6604 if (optimize_size && scratch)
6605 break; /* 5 */
6606 if (ldi_ok)
6607 {
6608 *len = 6;
02a011e9 6609 return ("swap %B0" CR_TAB
6610 "swap %A0" CR_TAB
6611 "andi %A0,0x0f" CR_TAB
6612 "eor %A0,%B0" CR_TAB
6613 "andi %B0,0x0f" CR_TAB
6614 "eor %A0,%B0");
b681d971 6615 }
6616 if (scratch)
6617 {
6618 *len = 7;
02a011e9 6619 return ("swap %B0" CR_TAB
6620 "swap %A0" CR_TAB
6621 "ldi %3,0x0f" CR_TAB
ef51d1e3 6622 "and %A0,%3" CR_TAB
02a011e9 6623 "eor %A0,%B0" CR_TAB
ef51d1e3 6624 "and %B0,%3" CR_TAB
02a011e9 6625 "eor %A0,%B0");
b681d971 6626 }
6627 break; /* optimize_size ? 6 : 8 */
6628
6629 case 5:
6630 if (optimize_size)
6631 break; /* scratch ? 5 : 6 */
6632 if (ldi_ok)
6633 {
6634 *len = 8;
02a011e9 6635 return ("lsr %B0" CR_TAB
6636 "ror %A0" CR_TAB
6637 "swap %B0" CR_TAB
6638 "swap %A0" CR_TAB
6639 "andi %A0,0x0f" CR_TAB
6640 "eor %A0,%B0" CR_TAB
6641 "andi %B0,0x0f" CR_TAB
6642 "eor %A0,%B0");
b681d971 6643 }
6644 if (scratch)
6645 {
6646 *len = 9;
02a011e9 6647 return ("lsr %B0" CR_TAB
6648 "ror %A0" CR_TAB
6649 "swap %B0" CR_TAB
6650 "swap %A0" CR_TAB
6651 "ldi %3,0x0f" CR_TAB
ef51d1e3 6652 "and %A0,%3" CR_TAB
02a011e9 6653 "eor %A0,%B0" CR_TAB
ef51d1e3 6654 "and %B0,%3" CR_TAB
02a011e9 6655 "eor %A0,%B0");
b681d971 6656 }
6657 break; /* 10 */
6658
6659 case 6:
6660 if (optimize_size)
6661 break; /* scratch ? 5 : 6 */
6662 *len = 9;
02a011e9 6663 return ("clr __tmp_reg__" CR_TAB
6664 "lsl %A0" CR_TAB
6665 "rol %B0" CR_TAB
6666 "rol __tmp_reg__" CR_TAB
6667 "lsl %A0" CR_TAB
6668 "rol %B0" CR_TAB
6669 "rol __tmp_reg__" CR_TAB
6670 "mov %A0,%B0" CR_TAB
6671 "mov %B0,__tmp_reg__");
28f5cc4d 6672
6673 case 7:
6674 *len = 5;
02a011e9 6675 return ("lsl %A0" CR_TAB
6676 "mov %A0,%B0" CR_TAB
6677 "rol %A0" CR_TAB
6678 "sbc %B0,%B0" CR_TAB
6679 "neg %B0");
28f5cc4d 6680
a28e4651 6681 case 8:
02a011e9 6682 return *len = 2, ("mov %A0,%B1" CR_TAB
6683 "clr %B0");
28f5cc4d 6684
6685 case 9:
6686 *len = 3;
02a011e9 6687 return ("mov %A0,%B0" CR_TAB
6688 "clr %B0" CR_TAB
6689 "lsr %A0");
28f5cc4d 6690
6691 case 10:
6692 *len = 4;
02a011e9 6693 return ("mov %A0,%B0" CR_TAB
6694 "clr %B0" CR_TAB
6695 "lsr %A0" CR_TAB
6696 "lsr %A0");
28f5cc4d 6697
6698 case 11:
6699 *len = 5;
02a011e9 6700 return ("mov %A0,%B0" CR_TAB
6701 "clr %B0" CR_TAB
6702 "lsr %A0" CR_TAB
6703 "lsr %A0" CR_TAB
6704 "lsr %A0");
28f5cc4d 6705
6706 case 12:
b681d971 6707 if (ldi_ok)
28f5cc4d 6708 {
6709 *len = 4;
02a011e9 6710 return ("mov %A0,%B0" CR_TAB
6711 "clr %B0" CR_TAB
6712 "swap %A0" CR_TAB
6713 "andi %A0,0x0f");
28f5cc4d 6714 }
b681d971 6715 if (scratch)
6716 {
6717 *len = 5;
02a011e9 6718 return ("mov %A0,%B0" CR_TAB
6719 "clr %B0" CR_TAB
6720 "swap %A0" CR_TAB
6721 "ldi %3,0x0f" CR_TAB
ef51d1e3 6722 "and %A0,%3");
b681d971 6723 }
6724 *len = 6;
02a011e9 6725 return ("mov %A0,%B0" CR_TAB
6726 "clr %B0" CR_TAB
6727 "lsr %A0" CR_TAB
6728 "lsr %A0" CR_TAB
6729 "lsr %A0" CR_TAB
6730 "lsr %A0");
28f5cc4d 6731
6732 case 13:
b681d971 6733 if (ldi_ok)
28f5cc4d 6734 {
6735 *len = 5;
02a011e9 6736 return ("mov %A0,%B0" CR_TAB
6737 "clr %B0" CR_TAB
6738 "swap %A0" CR_TAB
6739 "lsr %A0" CR_TAB
6740 "andi %A0,0x07");
28f5cc4d 6741 }
8cc5a1af 6742 if (AVR_HAVE_MUL && scratch)
28f5cc4d 6743 {
6744 *len = 5;
02a011e9 6745 return ("ldi %3,0x08" CR_TAB
6746 "mul %B0,%3" CR_TAB
6747 "mov %A0,r1" CR_TAB
6748 "clr %B0" CR_TAB
6749 "clr __zero_reg__");
28f5cc4d 6750 }
b681d971 6751 if (optimize_size && scratch)
6752 break; /* 5 */
6753 if (scratch)
6754 {
6755 *len = 6;
02a011e9 6756 return ("mov %A0,%B0" CR_TAB
6757 "clr %B0" CR_TAB
6758 "swap %A0" CR_TAB
6759 "lsr %A0" CR_TAB
6760 "ldi %3,0x07" CR_TAB
ef51d1e3 6761 "and %A0,%3");
b681d971 6762 }
8cc5a1af 6763 if (AVR_HAVE_MUL)
b681d971 6764 {
6765 *len = 6;
6766 return ("set" CR_TAB
02a011e9 6767 "bld r1,3" CR_TAB
6768 "mul %B0,r1" CR_TAB
6769 "mov %A0,r1" CR_TAB
6770 "clr %B0" CR_TAB
6771 "clr __zero_reg__");
b681d971 6772 }
6773 *len = 7;
02a011e9 6774 return ("mov %A0,%B0" CR_TAB
6775 "clr %B0" CR_TAB
6776 "lsr %A0" CR_TAB
6777 "lsr %A0" CR_TAB
6778 "lsr %A0" CR_TAB
6779 "lsr %A0" CR_TAB
6780 "lsr %A0");
28f5cc4d 6781
6782 case 14:
8cc5a1af 6783 if (AVR_HAVE_MUL && ldi_ok)
b681d971 6784 {
6785 *len = 5;
02a011e9 6786 return ("ldi %A0,0x04" CR_TAB
6787 "mul %B0,%A0" CR_TAB
6788 "mov %A0,r1" CR_TAB
6789 "clr %B0" CR_TAB
6790 "clr __zero_reg__");
b681d971 6791 }
8cc5a1af 6792 if (AVR_HAVE_MUL && scratch)
28f5cc4d 6793 {
6794 *len = 5;
02a011e9 6795 return ("ldi %3,0x04" CR_TAB
6796 "mul %B0,%3" CR_TAB
6797 "mov %A0,r1" CR_TAB
6798 "clr %B0" CR_TAB
6799 "clr __zero_reg__");
28f5cc4d 6800 }
b681d971 6801 if (optimize_size && ldi_ok)
6802 {
6803 *len = 5;
02a011e9 6804 return ("mov %A0,%B0" CR_TAB
6805 "ldi %B0,6" "\n1:\t"
6806 "lsr %A0" CR_TAB
6807 "dec %B0" CR_TAB
6808 "brne 1b");
b681d971 6809 }
6810 if (optimize_size && scratch)
6811 break; /* 5 */
6812 *len = 6;
02a011e9 6813 return ("clr %A0" CR_TAB
6814 "lsl %B0" CR_TAB
6815 "rol %A0" CR_TAB
6816 "lsl %B0" CR_TAB
6817 "rol %A0" CR_TAB
6818 "clr %B0");
28f5cc4d 6819
8a2a7305 6820 case 15:
1cb39658 6821 *len = 4;
02a011e9 6822 return ("clr %A0" CR_TAB
6823 "lsl %B0" CR_TAB
6824 "rol %A0" CR_TAB
6825 "clr %B0");
a28e4651 6826 }
28f5cc4d 6827 len = t;
a28e4651 6828 }
02a011e9 6829 out_shift_with_cnt ("lsr %B0" CR_TAB
6830 "ror %A0", insn, operands, len, 2);
a28e4651 6831 return "";
6832}
6833
02d9a2c3 6834
6835/* 24-bit logic shift right */
6836
6837const char*
375204de 6838avr_out_lshrpsi3 (rtx_insn *insn, rtx *op, int *plen)
02d9a2c3 6839{
6840 int dest = REGNO (op[0]);
6841 int src = REGNO (op[1]);
6842
6843 if (CONST_INT_P (op[2]))
6844 {
6845 if (plen)
6846 *plen = 0;
0dff9558 6847
02d9a2c3 6848 switch (INTVAL (op[2]))
6849 {
6850 case 8:
6851 if (dest <= src)
6852 return avr_asm_len ("mov %A0,%B1" CR_TAB
6853 "mov %B0,%C1" CR_TAB
6854 "clr %C0", op, plen, 3);
6855 else
6856 return avr_asm_len ("clr %C0" CR_TAB
6857 "mov %B0,%C1" CR_TAB
6858 "mov %A0,%B1", op, plen, 3);
0dff9558 6859
02d9a2c3 6860 case 16:
6861 if (dest != src + 2)
6862 avr_asm_len ("mov %A0,%C1", op, plen, 1);
0dff9558 6863
02d9a2c3 6864 return avr_asm_len ("clr %B0" CR_TAB
6865 "clr %C0", op, plen, 2);
6866
6867 default:
6868 if (INTVAL (op[2]) < 24)
6869 break;
6870
6871 /* fall through */
6872
6873 case 23:
6874 return avr_asm_len ("clr %A0" CR_TAB
6875 "sbrc %C0,7" CR_TAB
6876 "inc %A0" CR_TAB
6877 "clr %B0" CR_TAB
6878 "clr %C0", op, plen, 5);
6879 } /* switch */
6880 }
0dff9558 6881
02d9a2c3 6882 out_shift_with_cnt ("lsr %C0" CR_TAB
6883 "ror %B0" CR_TAB
6884 "ror %A0", insn, op, plen, 3);
6885 return "";
6886}
6887
6888
0dff9558 6889/* 32-bit logic shift right ((unsigned int)x >> i) */
a28e4651 6890
37ac04dc 6891const char *
375204de 6892lshrsi3_out (rtx_insn *insn, rtx operands[], int *len)
a28e4651 6893{
6894 if (GET_CODE (operands[2]) == CONST_INT)
6895 {
6896 int k;
1cb39658 6897 int *t = len;
0dff9558 6898
a28e4651 6899 if (!len)
6900 len = &k;
0dff9558 6901
a28e4651 6902 switch (INTVAL (operands[2]))
6903 {
5667001b 6904 default:
6905 if (INTVAL (operands[2]) < 32)
6906 break;
6907
0aab73c2 6908 if (AVR_HAVE_MOVW)
02a011e9 6909 return *len = 3, ("clr %D0" CR_TAB
6910 "clr %C0" CR_TAB
6911 "movw %A0,%C0");
5667001b 6912 *len = 4;
02a011e9 6913 return ("clr %D0" CR_TAB
6914 "clr %C0" CR_TAB
6915 "clr %B0" CR_TAB
6916 "clr %A0");
5667001b 6917
a28e4651 6918 case 8:
6919 {
6920 int reg0 = true_regnum (operands[0]);
6921 int reg1 = true_regnum (operands[1]);
1cb39658 6922 *len = 4;
a28e4651 6923 if (reg0 <= reg1)
02a011e9 6924 return ("mov %A0,%B1" CR_TAB
6925 "mov %B0,%C1" CR_TAB
6926 "mov %C0,%D1" CR_TAB
6927 "clr %D0");
a28e4651 6928 else
02a011e9 6929 return ("clr %D0" CR_TAB
6930 "mov %C0,%D1" CR_TAB
6931 "mov %B0,%C1" CR_TAB
0dff9558 6932 "mov %A0,%B1");
a28e4651 6933 }
0dff9558 6934
a28e4651 6935 case 16:
6936 {
6937 int reg0 = true_regnum (operands[0]);
6938 int reg1 = true_regnum (operands[1]);
ab3a6ef8 6939
6940 if (reg0 == reg1 + 2)
02a011e9 6941 return *len = 2, ("clr %C0" CR_TAB
6942 "clr %D0");
ab3a6ef8 6943 if (AVR_HAVE_MOVW)
02a011e9 6944 return *len = 3, ("movw %A0,%C1" CR_TAB
6945 "clr %C0" CR_TAB
6946 "clr %D0");
a28e4651 6947 else
02a011e9 6948 return *len = 4, ("mov %B0,%D1" CR_TAB
6949 "mov %A0,%C1" CR_TAB
6950 "clr %C0" CR_TAB
6951 "clr %D0");
a28e4651 6952 }
0dff9558 6953
a28e4651 6954 case 24:
02a011e9 6955 return *len = 4, ("mov %A0,%D1" CR_TAB
6956 "clr %B0" CR_TAB
6957 "clr %C0" CR_TAB
6958 "clr %D0");
28f5cc4d 6959
6960 case 31:
6961 *len = 6;
02a011e9 6962 return ("clr %A0" CR_TAB
6963 "sbrc %D0,7" CR_TAB
6964 "inc %A0" CR_TAB
6965 "clr %B0" CR_TAB
6966 "clr %C0" CR_TAB
6967 "clr %D0");
a28e4651 6968 }
28f5cc4d 6969 len = t;
a28e4651 6970 }
02a011e9 6971 out_shift_with_cnt ("lsr %D0" CR_TAB
6972 "ror %C0" CR_TAB
6973 "ror %B0" CR_TAB
6974 "ror %A0", insn, operands, len, 4);
a28e4651 6975 return "";
6976}
6977
6be828c1 6978
b4ebb666 6979/* Output addition of register XOP[0] and compile time constant XOP[2].
6980 CODE == PLUS: perform addition by using ADD instructions or
6981 CODE == MINUS: perform addition by using SUB instructions:
0dff9558 6982
37bcc7b9 6983 XOP[0] = XOP[0] + XOP[2]
0dff9558 6984
b4ebb666 6985 Or perform addition/subtraction with register XOP[2] depending on CODE:
0dff9558 6986
b4ebb666 6987 XOP[0] = XOP[0] +/- XOP[2]
37bcc7b9 6988
b4ebb666 6989 If PLEN == NULL, print assembler instructions to perform the operation;
6990 otherwise, set *PLEN to the length of the instruction sequence (in words)
6991 printed with PLEN == NULL. XOP[3] is an 8-bit scratch register or NULL_RTX.
6992 Set *PCC to effect on cc0 according to respective CC_* insn attribute.
6993
6994 CODE_SAT == UNKNOWN: Perform ordinary, non-saturating operation.
6995 CODE_SAT != UNKNOWN: Perform operation and saturate according to CODE_SAT.
6996 If CODE_SAT != UNKNOWN then SIGN contains the sign of the summand resp.
6997 the subtrahend in the original insn, provided it is a compile time constant.
6998 In all other cases, SIGN is 0.
6999
fdbf5b19 7000 If OUT_LABEL is true, print the final 0: label which is needed for
7001 saturated addition / subtraction. The only case where OUT_LABEL = false
7002 is useful is for saturated addition / subtraction performed during
7003 fixed-point rounding, cf. `avr_out_round'. */
37bcc7b9 7004
7005static void
b4ebb666 7006avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc,
fdbf5b19 7007 enum rtx_code code_sat, int sign, bool out_label)
37bcc7b9 7008{
7009 /* MODE of the operation. */
3754d046 7010 machine_mode mode = GET_MODE (xop[0]);
37bcc7b9 7011
017c5b98 7012 /* INT_MODE of the same size. */
3754d046 7013 machine_mode imode = int_mode_for_mode (mode);
017c5b98 7014
37bcc7b9 7015 /* Number of bytes to operate on. */
7016 int i, n_bytes = GET_MODE_SIZE (mode);
7017
7018 /* Value (0..0xff) held in clobber register op[3] or -1 if unknown. */
7019 int clobber_val = -1;
7020
7021 /* op[0]: 8-bit destination register
7022 op[1]: 8-bit const int
7023 op[2]: 8-bit scratch register */
7024 rtx op[3];
7025
7026 /* Started the operation? Before starting the operation we may skip
7027 adding 0. This is no more true after the operation started because
7028 carry must be taken into account. */
7029 bool started = false;
7030
7031 /* Value to add. There are two ways to add VAL: R += VAL and R -= -VAL. */
7032 rtx xval = xop[2];
7033
b4ebb666 7034 /* Output a BRVC instruction. Only needed with saturation. */
7035 bool out_brvc = true;
7036
7037 if (plen)
7038 *plen = 0;
7039
7040 if (REG_P (xop[2]))
7041 {
c455e5d3 7042 *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_CLOBBER;
b4ebb666 7043
7044 for (i = 0; i < n_bytes; i++)
7045 {
7046 /* We operate byte-wise on the destination. */
7047 op[0] = simplify_gen_subreg (QImode, xop[0], mode, i);
7048 op[1] = simplify_gen_subreg (QImode, xop[2], mode, i);
7049
7050 if (i == 0)
7051 avr_asm_len (code == PLUS ? "add %0,%1" : "sub %0,%1",
7052 op, plen, 1);
7053 else
7054 avr_asm_len (code == PLUS ? "adc %0,%1" : "sbc %0,%1",
7055 op, plen, 1);
7056 }
7057
7058 if (reg_overlap_mentioned_p (xop[0], xop[2]))
7059 {
7060 gcc_assert (REGNO (xop[0]) == REGNO (xop[2]));
0dff9558 7061
b4ebb666 7062 if (MINUS == code)
7063 return;
7064 }
7065
7066 goto saturate;
7067 }
7068
eac146f2 7069 /* Except in the case of ADIW with 16-bit register (see below)
7070 addition does not set cc0 in a usable way. */
0dff9558 7071
bcad9375 7072 *pcc = (MINUS == code) ? CC_SET_CZN : CC_CLOBBER;
7073
017c5b98 7074 if (CONST_FIXED_P (xval))
7075 xval = avr_to_int_mode (xval);
7076
b4ebb666 7077 /* Adding/Subtracting zero is a no-op. */
0dff9558 7078
b4ebb666 7079 if (xval == const0_rtx)
7080 {
7081 *pcc = CC_NONE;
7082 return;
7083 }
7084
37bcc7b9 7085 if (MINUS == code)
017c5b98 7086 xval = simplify_unary_operation (NEG, imode, xval, imode);
37bcc7b9 7087
7088 op[2] = xop[3];
7089
b4ebb666 7090 if (SS_PLUS == code_sat && MINUS == code
7091 && sign < 0
7092 && 0x80 == (INTVAL (simplify_gen_subreg (QImode, xval, imode, n_bytes-1))
7093 & GET_MODE_MASK (QImode)))
7094 {
7095 /* We compute x + 0x80 by means of SUB instructions. We negated the
7096 constant subtrahend above and are left with x - (-128) so that we
7097 need something like SUBI r,128 which does not exist because SUBI sets
7098 V according to the sign of the subtrahend. Notice the only case
7099 where this must be done is when NEG overflowed in case [2s] because
7100 the V computation needs the right sign of the subtrahend. */
0dff9558 7101
b4ebb666 7102 rtx msb = simplify_gen_subreg (QImode, xop[0], mode, n_bytes-1);
7103
7104 avr_asm_len ("subi %0,128" CR_TAB
7105 "brmi 0f", &msb, plen, 2);
7106 out_brvc = false;
7107
7108 goto saturate;
7109 }
37bcc7b9 7110
7111 for (i = 0; i < n_bytes; i++)
7112 {
7113 /* We operate byte-wise on the destination. */
7114 rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
017c5b98 7115 rtx xval8 = simplify_gen_subreg (QImode, xval, imode, i);
37bcc7b9 7116
7117 /* 8-bit value to operate with this byte. */
7118 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
7119
7120 /* Registers R16..R31 can operate with immediate. */
7121 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
7122
7123 op[0] = reg8;
644ac9c5 7124 op[1] = gen_int_mode (val8, QImode);
bcad9375 7125
7126 /* To get usable cc0 no low-bytes must have been skipped. */
0dff9558 7127
bcad9375 7128 if (i && !started)
7129 *pcc = CC_CLOBBER;
0dff9558 7130
02d9a2c3 7131 if (!started
7132 && i % 2 == 0
7133 && i + 2 <= n_bytes
37bcc7b9 7134 && test_hard_reg_class (ADDW_REGS, reg8))
7135 {
017c5b98 7136 rtx xval16 = simplify_gen_subreg (HImode, xval, imode, i);
37bcc7b9 7137 unsigned int val16 = UINTVAL (xval16) & GET_MODE_MASK (HImode);
7138
7139 /* Registers R24, X, Y, Z can use ADIW/SBIW with constants < 64
7140 i.e. operate word-wise. */
7141
7142 if (val16 < 64)
7143 {
7144 if (val16 != 0)
7145 {
7146 started = true;
7147 avr_asm_len (code == PLUS ? "adiw %0,%1" : "sbiw %0,%1",
7148 op, plen, 1);
eac146f2 7149
7150 if (n_bytes == 2 && PLUS == code)
c455e5d3 7151 *pcc = CC_SET_CZN;
37bcc7b9 7152 }
7153
7154 i++;
7155 continue;
7156 }
7157 }
7158
7159 if (val8 == 0)
7160 {
7161 if (started)
7162 avr_asm_len (code == PLUS
7163 ? "adc %0,__zero_reg__" : "sbc %0,__zero_reg__",
7164 op, plen, 1);
7165 continue;
7166 }
eac146f2 7167 else if ((val8 == 1 || val8 == 0xff)
b4ebb666 7168 && UNKNOWN == code_sat
eac146f2 7169 && !started
7170 && i == n_bytes - 1)
02d9a2c3 7171 {
eac146f2 7172 avr_asm_len ((code == PLUS) ^ (val8 == 1) ? "dec %0" : "inc %0",
7173 op, plen, 1);
c455e5d3 7174 *pcc = CC_CLOBBER;
eac146f2 7175 break;
02d9a2c3 7176 }
37bcc7b9 7177
7178 switch (code)
7179 {
7180 case PLUS:
7181
b4ebb666 7182 gcc_assert (plen != NULL || (op[2] && REG_P (op[2])));
7183
7184 if (plen != NULL && UNKNOWN != code_sat)
7185 {
7186 /* This belongs to the x + 0x80 corner case. The code with
7187 ADD instruction is not smaller, thus make this case
7188 expensive so that the caller won't pick it. */
7189
7190 *plen += 10;
7191 break;
7192 }
37bcc7b9 7193
7194 if (clobber_val != (int) val8)
7195 avr_asm_len ("ldi %2,%1", op, plen, 1);
7196 clobber_val = (int) val8;
0dff9558 7197
37bcc7b9 7198 avr_asm_len (started ? "adc %0,%2" : "add %0,%2", op, plen, 1);
7199
7200 break; /* PLUS */
7201
7202 case MINUS:
7203
7204 if (ld_reg_p)
7205 avr_asm_len (started ? "sbci %0,%1" : "subi %0,%1", op, plen, 1);
7206 else
7207 {
7208 gcc_assert (plen != NULL || REG_P (op[2]));
7209
7210 if (clobber_val != (int) val8)
7211 avr_asm_len ("ldi %2,%1", op, plen, 1);
7212 clobber_val = (int) val8;
0dff9558 7213
37bcc7b9 7214 avr_asm_len (started ? "sbc %0,%2" : "sub %0,%2", op, plen, 1);
7215 }
7216
7217 break; /* MINUS */
0dff9558 7218
37bcc7b9 7219 default:
7220 /* Unknown code */
7221 gcc_unreachable();
7222 }
7223
7224 started = true;
7225
7226 } /* for all sub-bytes */
bcad9375 7227
b4ebb666 7228 saturate:
37bcc7b9 7229
b4ebb666 7230 if (UNKNOWN == code_sat)
7231 return;
37bcc7b9 7232
b4ebb666 7233 *pcc = (int) CC_CLOBBER;
37bcc7b9 7234
b4ebb666 7235 /* Vanilla addition/subtraction is done. We are left with saturation.
0dff9558 7236
b4ebb666 7237 We have to compute A = A <op> B where A is a register and
7238 B is a register or a non-zero compile time constant CONST.
7239 A is register class "r" if unsigned && B is REG. Otherwise, A is in "d".
0dff9558 7240 B stands for the original operand $2 in INSN. In the case of B = CONST,
b4ebb666 7241 SIGN in { -1, 1 } is the sign of B. Otherwise, SIGN is 0.
0dff9558 7242
b4ebb666 7243 CODE is the instruction flavor we use in the asm sequence to perform <op>.
0dff9558 7244
7245
b4ebb666 7246 unsigned
7247 operation | code | sat if | b is | sat value | case
7248 -----------------+-------+----------+--------------+-----------+-------
7249 + as a + b | add | C == 1 | const, reg | u+ = 0xff | [1u]
7250 + as a - (-b) | sub | C == 0 | const | u+ = 0xff | [2u]
7251 - as a - b | sub | C == 1 | const, reg | u- = 0 | [3u]
7252 - as a + (-b) | add | C == 0 | const | u- = 0 | [4u]
0dff9558 7253
7254
b4ebb666 7255 signed
7256 operation | code | sat if | b is | sat value | case
7257 -----------------+-------+----------+--------------+-----------+-------
7258 + as a + b | add | V == 1 | const, reg | s+ | [1s]
7259 + as a - (-b) | sub | V == 1 | const | s+ | [2s]
7260 - as a - b | sub | V == 1 | const, reg | s- | [3s]
7261 - as a + (-b) | add | V == 1 | const | s- | [4s]
0dff9558 7262
b4ebb666 7263 s+ = b < 0 ? -0x80 : 0x7f
7264 s- = b < 0 ? 0x7f : -0x80
0dff9558 7265
b4ebb666 7266 The cases a - b actually perform a - (-(-b)) if B is CONST.
7267 */
37bcc7b9 7268
b4ebb666 7269 op[0] = simplify_gen_subreg (QImode, xop[0], mode, n_bytes-1);
7270 op[1] = n_bytes > 1
7271 ? simplify_gen_subreg (QImode, xop[0], mode, n_bytes-2)
7272 : NULL_RTX;
37bcc7b9 7273
b4ebb666 7274 bool need_copy = true;
7275 int len_call = 1 + AVR_HAVE_JMP_CALL;
0dff9558 7276
b4ebb666 7277 switch (code_sat)
7278 {
7279 default:
7280 gcc_unreachable();
7281
7282 case SS_PLUS:
7283 case SS_MINUS:
b4ebb666 7284
7285 if (out_brvc)
7286 avr_asm_len ("brvc 0f", op, plen, 1);
7287
7288 if (reg_overlap_mentioned_p (xop[0], xop[2]))
7289 {
7290 /* [1s,reg] */
7291
7292 if (n_bytes == 1)
7293 avr_asm_len ("ldi %0,0x7f" CR_TAB
7294 "adc %0,__zero_reg__", op, plen, 2);
7295 else
7296 avr_asm_len ("ldi %0,0x7f" CR_TAB
7297 "ldi %1,0xff" CR_TAB
7298 "adc %1,__zero_reg__" CR_TAB
7299 "adc %0,__zero_reg__", op, plen, 4);
7300 }
7301 else if (sign == 0 && PLUS == code)
7302 {
7303 /* [1s,reg] */
7304
7305 op[2] = simplify_gen_subreg (QImode, xop[2], mode, n_bytes-1);
7306
7307 if (n_bytes == 1)
7308 avr_asm_len ("ldi %0,0x80" CR_TAB
7309 "sbrs %2,7" CR_TAB
7310 "dec %0", op, plen, 3);
7311 else
7312 avr_asm_len ("ldi %0,0x80" CR_TAB
7313 "cp %2,%0" CR_TAB
7314 "sbc %1,%1" CR_TAB
7315 "sbci %0,0", op, plen, 4);
7316 }
7317 else if (sign == 0 && MINUS == code)
7318 {
7319 /* [3s,reg] */
7320
7321 op[2] = simplify_gen_subreg (QImode, xop[2], mode, n_bytes-1);
7322
7323 if (n_bytes == 1)
7324 avr_asm_len ("ldi %0,0x7f" CR_TAB
7325 "sbrs %2,7" CR_TAB
7326 "inc %0", op, plen, 3);
7327 else
7328 avr_asm_len ("ldi %0,0x7f" CR_TAB
7329 "cp %0,%2" CR_TAB
7330 "sbc %1,%1" CR_TAB
7331 "sbci %0,-1", op, plen, 4);
7332 }
7333 else if ((sign < 0) ^ (SS_MINUS == code_sat))
7334 {
7335 /* [1s,const,B < 0] [2s,B < 0] */
7336 /* [3s,const,B > 0] [4s,B > 0] */
7337
7338 if (n_bytes == 8)
7339 {
7340 avr_asm_len ("%~call __clr_8", op, plen, len_call);
7341 need_copy = false;
7342 }
7343
7344 avr_asm_len ("ldi %0,0x80", op, plen, 1);
7345 if (n_bytes > 1 && need_copy)
7346 avr_asm_len ("clr %1", op, plen, 1);
7347 }
7348 else if ((sign > 0) ^ (SS_MINUS == code_sat))
7349 {
7350 /* [1s,const,B > 0] [2s,B > 0] */
7351 /* [3s,const,B < 0] [4s,B < 0] */
7352
7353 if (n_bytes == 8)
7354 {
7355 avr_asm_len ("sec" CR_TAB
7356 "%~call __sbc_8", op, plen, 1 + len_call);
7357 need_copy = false;
7358 }
7359
7360 avr_asm_len ("ldi %0,0x7f", op, plen, 1);
7361 if (n_bytes > 1 && need_copy)
7362 avr_asm_len ("ldi %1,0xff", op, plen, 1);
7363 }
7364 else
7365 gcc_unreachable();
0dff9558 7366
b4ebb666 7367 break;
7368
7369 case US_PLUS:
7370 /* [1u] : [2u] */
0dff9558 7371
b4ebb666 7372 avr_asm_len (PLUS == code ? "brcc 0f" : "brcs 0f", op, plen, 1);
0dff9558 7373
b4ebb666 7374 if (n_bytes == 8)
7375 {
7376 if (MINUS == code)
7377 avr_asm_len ("sec", op, plen, 1);
7378 avr_asm_len ("%~call __sbc_8", op, plen, len_call);
7379
7380 need_copy = false;
7381 }
7382 else
7383 {
7384 if (MINUS == code && !test_hard_reg_class (LD_REGS, op[0]))
1a96adb9 7385 avr_asm_len ("sec" CR_TAB
7386 "sbc %0,%0", op, plen, 2);
b4ebb666 7387 else
7388 avr_asm_len (PLUS == code ? "sbc %0,%0" : "ldi %0,0xff",
7389 op, plen, 1);
7390 }
7391 break; /* US_PLUS */
0dff9558 7392
b4ebb666 7393 case US_MINUS:
7394 /* [4u] : [3u] */
7395
7396 avr_asm_len (PLUS == code ? "brcs 0f" : "brcc 0f", op, plen, 1);
7397
7398 if (n_bytes == 8)
7399 {
7400 avr_asm_len ("%~call __clr_8", op, plen, len_call);
7401 need_copy = false;
7402 }
7403 else
7404 avr_asm_len ("clr %0", op, plen, 1);
0dff9558 7405
b4ebb666 7406 break;
7407 }
37bcc7b9 7408
b4ebb666 7409 /* We set the MSB in the unsigned case and the 2 MSBs in the signed case.
7410 Now copy the right value to the LSBs. */
0dff9558 7411
b4ebb666 7412 if (need_copy && n_bytes > 1)
bcad9375 7413 {
b4ebb666 7414 if (US_MINUS == code_sat || US_PLUS == code_sat)
7415 {
7416 avr_asm_len ("mov %1,%0", op, plen, 1);
7417
7418 if (n_bytes > 2)
7419 {
7420 op[0] = xop[0];
7421 if (AVR_HAVE_MOVW)
7422 avr_asm_len ("movw %0,%1", op, plen, 1);
7423 else
7424 avr_asm_len ("mov %A0,%1" CR_TAB
7425 "mov %B0,%1", op, plen, 2);
7426 }
7427 }
7428 else if (n_bytes > 2)
7429 {
7430 op[0] = xop[0];
7431 avr_asm_len ("mov %A0,%1" CR_TAB
7432 "mov %B0,%1", op, plen, 2);
7433 }
bcad9375 7434 }
37bcc7b9 7435
b4ebb666 7436 if (need_copy && n_bytes == 8)
7437 {
7438 if (AVR_HAVE_MOVW)
7439 avr_asm_len ("movw %r0+2,%0" CR_TAB
7440 "movw %r0+4,%0", xop, plen, 2);
7441 else
7442 avr_asm_len ("mov %r0+2,%0" CR_TAB
7443 "mov %r0+3,%0" CR_TAB
7444 "mov %r0+4,%0" CR_TAB
7445 "mov %r0+5,%0", xop, plen, 4);
7446 }
7447
fdbf5b19 7448 if (out_label)
7449 avr_asm_len ("0:", op, plen, 0);
37bcc7b9 7450}
7451
7452
b4ebb666 7453/* Output addition/subtraction of register XOP[0] and a constant XOP[2] that
7454 is ont a compile-time constant:
eac146f2 7455
b4ebb666 7456 XOP[0] = XOP[0] +/- XOP[2]
7457
7458 This is a helper for the function below. The only insns that need this
7459 are additions/subtraction for pointer modes, i.e. HImode and PSImode. */
7460
7461static const char*
7462avr_out_plus_symbol (rtx *xop, enum rtx_code code, int *plen, int *pcc)
eac146f2 7463{
3754d046 7464 machine_mode mode = GET_MODE (xop[0]);
eac146f2 7465
b4ebb666 7466 /* Only pointer modes want to add symbols. */
0dff9558 7467
b4ebb666 7468 gcc_assert (mode == HImode || mode == PSImode);
eac146f2 7469
b4ebb666 7470 *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_SET_N;
7471
7472 avr_asm_len (PLUS == code
7473 ? "subi %A0,lo8(-(%2))" CR_TAB "sbci %B0,hi8(-(%2))"
7474 : "subi %A0,lo8(%2)" CR_TAB "sbci %B0,hi8(%2)",
7475 xop, plen, -2);
7476
4e07e83e 7477 if (PSImode == mode)
b4ebb666 7478 avr_asm_len (PLUS == code
4e07e83e 7479 ? "sbci %C0,hlo8(-(%2))"
b4ebb666 7480 : "sbci %C0,hlo8(%2)", xop, plen, 1);
7481 return "";
eac146f2 7482}
7483
83921eda 7484
b4ebb666 7485/* Prepare operands of addition/subtraction to be used with avr_out_plus_1.
0dff9558 7486
fdbf5b19 7487 INSN is a single_set insn or an insn pattern with a binary operation as
7488 SET_SRC that is one of: PLUS, SS_PLUS, US_PLUS, MINUS, SS_MINUS, US_MINUS.
b4ebb666 7489
7490 XOP are the operands of INSN. In the case of 64-bit operations with
7491 constant XOP[] has just one element: The summand/subtrahend in XOP[0].
7492 The non-saturating insns up to 32 bits may or may not supply a "d" class
7493 scratch as XOP[3].
7494
7495 If PLEN == NULL output the instructions.
7496 If PLEN != NULL set *PLEN to the length of the sequence in words.
017c5b98 7497
b4ebb666 7498 PCC is a pointer to store the instructions' effect on cc0.
7499 PCC may be NULL.
017c5b98 7500
b4ebb666 7501 PLEN and PCC default to NULL.
7502
fdbf5b19 7503 OUT_LABEL defaults to TRUE. For a description, see AVR_OUT_PLUS_1.
7504
b4ebb666 7505 Return "" */
017c5b98 7506
7507const char*
fdbf5b19 7508avr_out_plus (rtx insn, rtx *xop, int *plen, int *pcc, bool out_label)
017c5b98 7509{
b4ebb666 7510 int cc_plus, cc_minus, cc_dummy;
7511 int len_plus, len_minus;
017c5b98 7512 rtx op[4];
50fc2d35 7513 rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
fdbf5b19 7514 rtx xdest = SET_DEST (xpattern);
3754d046 7515 machine_mode mode = GET_MODE (xdest);
7516 machine_mode imode = int_mode_for_mode (mode);
b4ebb666 7517 int n_bytes = GET_MODE_SIZE (mode);
fdbf5b19 7518 enum rtx_code code_sat = GET_CODE (SET_SRC (xpattern));
b4ebb666 7519 enum rtx_code code
7520 = (PLUS == code_sat || SS_PLUS == code_sat || US_PLUS == code_sat
7521 ? PLUS : MINUS);
017c5b98 7522
b4ebb666 7523 if (!pcc)
7524 pcc = &cc_dummy;
017c5b98 7525
b4ebb666 7526 /* PLUS and MINUS don't saturate: Use modular wrap-around. */
0dff9558 7527
b4ebb666 7528 if (PLUS == code_sat || MINUS == code_sat)
7529 code_sat = UNKNOWN;
017c5b98 7530
b4ebb666 7531 if (n_bytes <= 4 && REG_P (xop[2]))
7532 {
fdbf5b19 7533 avr_out_plus_1 (xop, plen, code, pcc, code_sat, 0, out_label);
b4ebb666 7534 return "";
7535 }
017c5b98 7536
b4ebb666 7537 if (8 == n_bytes)
7538 {
7539 op[0] = gen_rtx_REG (DImode, ACC_A);
7540 op[1] = gen_rtx_REG (DImode, ACC_A);
7541 op[2] = avr_to_int_mode (xop[0]);
7542 }
7543 else
7544 {
7545 if (!REG_P (xop[2])
7546 && !CONST_INT_P (xop[2])
7547 && !CONST_FIXED_P (xop[2]))
7548 {
7549 return avr_out_plus_symbol (xop, code, plen, pcc);
7550 }
0dff9558 7551
b4ebb666 7552 op[0] = avr_to_int_mode (xop[0]);
7553 op[1] = avr_to_int_mode (xop[1]);
7554 op[2] = avr_to_int_mode (xop[2]);
7555 }
017c5b98 7556
b4ebb666 7557 /* Saturations and 64-bit operations don't have a clobber operand.
7558 For the other cases, the caller will provide a proper XOP[3]. */
0dff9558 7559
fdbf5b19 7560 xpattern = INSN_P (insn) ? PATTERN (insn) : insn;
7561 op[3] = PARALLEL == GET_CODE (xpattern) ? xop[3] : NULL_RTX;
83921eda 7562
b4ebb666 7563 /* Saturation will need the sign of the original operand. */
83921eda 7564
b4ebb666 7565 rtx xmsb = simplify_gen_subreg (QImode, op[2], imode, n_bytes-1);
7566 int sign = INTVAL (xmsb) < 0 ? -1 : 1;
83921eda 7567
b4ebb666 7568 /* If we subtract and the subtrahend is a constant, then negate it
7569 so that avr_out_plus_1 can be used. */
83921eda 7570
b4ebb666 7571 if (MINUS == code)
7572 op[2] = simplify_unary_operation (NEG, imode, op[2], imode);
83921eda 7573
b4ebb666 7574 /* Work out the shortest sequence. */
017c5b98 7575
3269fce4 7576 avr_out_plus_1 (op, &len_minus, MINUS, &cc_minus, code_sat, sign, out_label);
7577 avr_out_plus_1 (op, &len_plus, PLUS, &cc_plus, code_sat, sign, out_label);
017c5b98 7578
b4ebb666 7579 if (plen)
7580 {
7581 *plen = (len_minus <= len_plus) ? len_minus : len_plus;
7582 *pcc = (len_minus <= len_plus) ? cc_minus : cc_plus;
7583 }
7584 else if (len_minus <= len_plus)
fdbf5b19 7585 avr_out_plus_1 (op, NULL, MINUS, pcc, code_sat, sign, out_label);
b4ebb666 7586 else
fdbf5b19 7587 avr_out_plus_1 (op, NULL, PLUS, pcc, code_sat, sign, out_label);
017c5b98 7588
b4ebb666 7589 return "";
017c5b98 7590}
7591
7592
6be828c1 7593/* Output bit operation (IOR, AND, XOR) with register XOP[0] and compile
7594 time constant XOP[2]:
7595
7596 XOP[0] = XOP[0] <op> XOP[2]
7597
7598 and return "". If PLEN == NULL, print assembler instructions to perform the
7599 operation; otherwise, set *PLEN to the length of the instruction sequence
7600 (in words) printed with PLEN == NULL. XOP[3] is either an 8-bit clobber
fdbf5b19 7601 register or SCRATCH if no clobber register is needed for the operation.
7602 INSN is an INSN_P or a pattern of an insn. */
6be828c1 7603
7604const char*
7605avr_out_bitop (rtx insn, rtx *xop, int *plen)
7606{
7607 /* CODE and MODE of the operation. */
50fc2d35 7608 rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
fdbf5b19 7609 enum rtx_code code = GET_CODE (SET_SRC (xpattern));
3754d046 7610 machine_mode mode = GET_MODE (xop[0]);
6be828c1 7611
7612 /* Number of bytes to operate on. */
7613 int i, n_bytes = GET_MODE_SIZE (mode);
7614
7615 /* Value of T-flag (0 or 1) or -1 if unknow. */
7616 int set_t = -1;
7617
7618 /* Value (0..0xff) held in clobber register op[3] or -1 if unknown. */
7619 int clobber_val = -1;
7620
7621 /* op[0]: 8-bit destination register
7622 op[1]: 8-bit const int
7623 op[2]: 8-bit clobber register or SCRATCH
7624 op[3]: 8-bit register containing 0xff or NULL_RTX */
7625 rtx op[4];
7626
7627 op[2] = xop[3];
7628 op[3] = NULL_RTX;
7629
7630 if (plen)
7631 *plen = 0;
7632
7633 for (i = 0; i < n_bytes; i++)
7634 {
7635 /* We operate byte-wise on the destination. */
7636 rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
7637 rtx xval8 = simplify_gen_subreg (QImode, xop[2], mode, i);
7638
7639 /* 8-bit value to operate with this byte. */
7640 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
7641
7642 /* Number of bits set in the current byte of the constant. */
7643 int pop8 = avr_popcount (val8);
7644
7645 /* Registers R16..R31 can operate with immediate. */
7646 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
7647
7648 op[0] = reg8;
7649 op[1] = GEN_INT (val8);
0dff9558 7650
6be828c1 7651 switch (code)
7652 {
7653 case IOR:
7654
7655 if (0 == pop8)
7656 continue;
7657 else if (ld_reg_p)
7658 avr_asm_len ("ori %0,%1", op, plen, 1);
7659 else if (1 == pop8)
7660 {
7661 if (set_t != 1)
7662 avr_asm_len ("set", op, plen, 1);
7663 set_t = 1;
0dff9558 7664
6be828c1 7665 op[1] = GEN_INT (exact_log2 (val8));
7666 avr_asm_len ("bld %0,%1", op, plen, 1);
7667 }
7668 else if (8 == pop8)
7669 {
7670 if (op[3] != NULL_RTX)
7671 avr_asm_len ("mov %0,%3", op, plen, 1);
7672 else
7673 avr_asm_len ("clr %0" CR_TAB
7674 "dec %0", op, plen, 2);
7675
7676 op[3] = op[0];
7677 }
7678 else
7679 {
7680 if (clobber_val != (int) val8)
7681 avr_asm_len ("ldi %2,%1", op, plen, 1);
7682 clobber_val = (int) val8;
0dff9558 7683
6be828c1 7684 avr_asm_len ("or %0,%2", op, plen, 1);
7685 }
7686
7687 continue; /* IOR */
7688
7689 case AND:
7690
7691 if (8 == pop8)
7692 continue;
7693 else if (0 == pop8)
7694 avr_asm_len ("clr %0", op, plen, 1);
7695 else if (ld_reg_p)
7696 avr_asm_len ("andi %0,%1", op, plen, 1);
7697 else if (7 == pop8)
7698 {
7699 if (set_t != 0)
7700 avr_asm_len ("clt", op, plen, 1);
7701 set_t = 0;
0dff9558 7702
6be828c1 7703 op[1] = GEN_INT (exact_log2 (GET_MODE_MASK (QImode) & ~val8));
7704 avr_asm_len ("bld %0,%1", op, plen, 1);
7705 }
7706 else
7707 {
7708 if (clobber_val != (int) val8)
7709 avr_asm_len ("ldi %2,%1", op, plen, 1);
7710 clobber_val = (int) val8;
0dff9558 7711
6be828c1 7712 avr_asm_len ("and %0,%2", op, plen, 1);
7713 }
7714
7715 continue; /* AND */
0dff9558 7716
6be828c1 7717 case XOR:
7718
7719 if (0 == pop8)
7720 continue;
7721 else if (8 == pop8)
7722 avr_asm_len ("com %0", op, plen, 1);
7723 else if (ld_reg_p && val8 == (1 << 7))
7724 avr_asm_len ("subi %0,%1", op, plen, 1);
7725 else
7726 {
7727 if (clobber_val != (int) val8)
7728 avr_asm_len ("ldi %2,%1", op, plen, 1);
7729 clobber_val = (int) val8;
0dff9558 7730
6be828c1 7731 avr_asm_len ("eor %0,%2", op, plen, 1);
7732 }
7733
7734 continue; /* XOR */
0dff9558 7735
6be828c1 7736 default:
7737 /* Unknown rtx_code */
7738 gcc_unreachable();
7739 }
7740 } /* for all sub-bytes */
7741
7742 return "";
7743}
7744
915f904b 7745
5766e83c 7746/* Output sign extension from XOP[1] to XOP[0] and return "".
7747 If PLEN == NULL, print assembler instructions to perform the operation;
7748 otherwise, set *PLEN to the length of the instruction sequence (in words)
7749 as printed with PLEN == NULL. */
7750
7751const char*
7752avr_out_sign_extend (rtx_insn *insn, rtx *xop, int *plen)
7753{
7754 // Size in bytes of source resp. destination operand.
7755 unsigned n_src = GET_MODE_SIZE (GET_MODE (xop[1]));
7756 unsigned n_dest = GET_MODE_SIZE (GET_MODE (xop[0]));
7757 rtx r_msb = all_regs_rtx[REGNO (xop[1]) + n_src - 1];
7758
7759 if (plen)
7760 *plen = 0;
7761
7762 // Copy destination to source
7763
7764 if (REGNO (xop[0]) != REGNO (xop[1]))
7765 {
7766 gcc_assert (n_src <= 2);
7767
7768 if (n_src == 2)
7769 avr_asm_len (AVR_HAVE_MOVW
7770 ? "movw %0,%1"
7771 : "mov %B0,%B1", xop, plen, 1);
7772 if (n_src == 1 || !AVR_HAVE_MOVW)
7773 avr_asm_len ("mov %A0,%A1", xop, plen, 1);
7774 }
7775
7776 // Set Carry to the sign bit MSB.7...
7777
7778 if (REGNO (xop[0]) == REGNO (xop[1])
7779 || !reg_unused_after (insn, r_msb))
7780 {
7781 avr_asm_len ("mov __tmp_reg__,%0", &r_msb, plen, 1);
7782 r_msb = tmp_reg_rtx;
7783 }
7784
7785 avr_asm_len ("lsl %0", &r_msb, plen, 1);
7786
7787 // ...and propagate it to all the new sign bits
7788
7789 for (unsigned n = n_src; n < n_dest; n++)
7790 avr_asm_len ("sbc %0,%0", &all_regs_rtx[REGNO (xop[0]) + n], plen, 1);
7791
7792 return "";
7793}
7794
7795
915f904b 7796/* PLEN == NULL: Output code to add CONST_INT OP[0] to SP.
7797 PLEN != NULL: Set *PLEN to the length of that sequence.
7798 Return "". */
7799
7800const char*
7801avr_out_addto_sp (rtx *op, int *plen)
7802{
7803 int pc_len = AVR_2_BYTE_PC ? 2 : 3;
7804 int addend = INTVAL (op[0]);
7805
7806 if (plen)
7807 *plen = 0;
7808
7809 if (addend < 0)
7810 {
7811 if (flag_verbose_asm || flag_print_asm_name)
7812 avr_asm_len (ASM_COMMENT_START "SP -= %n0", op, plen, 0);
0dff9558 7813
915f904b 7814 while (addend <= -pc_len)
7815 {
7816 addend += pc_len;
7817 avr_asm_len ("rcall .", op, plen, 1);
7818 }
7819
7820 while (addend++ < 0)
7821 avr_asm_len ("push __zero_reg__", op, plen, 1);
7822 }
7823 else if (addend > 0)
7824 {
7825 if (flag_verbose_asm || flag_print_asm_name)
7826 avr_asm_len (ASM_COMMENT_START "SP += %0", op, plen, 0);
7827
7828 while (addend-- > 0)
7829 avr_asm_len ("pop __tmp_reg__", op, plen, 1);
7830 }
7831
7832 return "";
7833}
7834
7835
c8ec4eb6 7836/* Outputs instructions needed for fixed point type conversion.
7837 This includes converting between any fixed point type, as well
7838 as converting to any integer type. Conversion between integer
7839 types is not supported.
7840
7841 Converting signed fractional types requires a bit shift if converting
7842 to or from any unsigned fractional type because the decimal place is
7843 shifted by 1 bit. When the destination is a signed fractional, the sign
7844 is stored in either the carry or T bit. */
7845
7846const char*
375204de 7847avr_out_fract (rtx_insn *insn, rtx operands[], bool intsigned, int *plen)
c8ec4eb6 7848{
7849 size_t i;
7850 rtx xop[6];
7851 RTX_CODE shift = UNKNOWN;
7852 bool sign_in_carry = false;
7853 bool msb_in_carry = false;
226d57b0 7854 bool lsb_in_tmp_reg = false;
c8ec4eb6 7855 bool lsb_in_carry = false;
226d57b0 7856 bool frac_rounded = false;
c8ec4eb6 7857 const char *code_ashift = "lsl %0";
7858
0dff9558 7859
c8ec4eb6 7860#define MAY_CLOBBER(RR) \
7861 /* Shorthand used below. */ \
7862 ((sign_bytes \
7863 && IN_RANGE (RR, dest.regno_msb - sign_bytes + 1, dest.regno_msb)) \
226d57b0 7864 || (offset && IN_RANGE (RR, dest.regno, dest.regno_msb)) \
c8ec4eb6 7865 || (reg_unused_after (insn, all_regs_rtx[RR]) \
7866 && !IN_RANGE (RR, dest.regno, dest.regno_msb)))
7867
7868 struct
7869 {
7870 /* bytes : Length of operand in bytes.
7871 ibyte : Length of integral part in bytes.
7872 fbyte, fbit : Length of fractional part in bytes, bits. */
7873
7874 bool sbit;
7875 unsigned fbit, bytes, ibyte, fbyte;
7876 unsigned regno, regno_msb;
7877 } dest, src, *val[2] = { &dest, &src };
7878
7879 if (plen)
7880 *plen = 0;
7881
7882 /* Step 0: Determine information on source and destination operand we
7883 ====== will need in the remainder. */
7884
7885 for (i = 0; i < sizeof (val) / sizeof (*val); i++)
7886 {
3754d046 7887 machine_mode mode;
c8ec4eb6 7888
7889 xop[i] = operands[i];
7890
7891 mode = GET_MODE (xop[i]);
7892
7893 val[i]->bytes = GET_MODE_SIZE (mode);
7894 val[i]->regno = REGNO (xop[i]);
7895 val[i]->regno_msb = REGNO (xop[i]) + val[i]->bytes - 1;
7896
7897 if (SCALAR_INT_MODE_P (mode))
7898 {
7899 val[i]->sbit = intsigned;
7900 val[i]->fbit = 0;
7901 }
7902 else if (ALL_SCALAR_FIXED_POINT_MODE_P (mode))
7903 {
7904 val[i]->sbit = SIGNED_SCALAR_FIXED_POINT_MODE_P (mode);
7905 val[i]->fbit = GET_MODE_FBIT (mode);
7906 }
7907 else
7908 fatal_insn ("unsupported fixed-point conversion", insn);
7909
7910 val[i]->fbyte = (1 + val[i]->fbit) / BITS_PER_UNIT;
7911 val[i]->ibyte = val[i]->bytes - val[i]->fbyte;
7912 }
7913
7914 // Byte offset of the decimal point taking into account different place
7915 // of the decimal point in input and output and different register numbers
7916 // of input and output.
7917 int offset = dest.regno - src.regno + dest.fbyte - src.fbyte;
7918
7919 // Number of destination bytes that will come from sign / zero extension.
7920 int sign_bytes = (dest.ibyte - src.ibyte) * (dest.ibyte > src.ibyte);
7921
7922 // Number of bytes at the low end to be filled with zeros.
7923 int zero_bytes = (dest.fbyte - src.fbyte) * (dest.fbyte > src.fbyte);
7924
7925 // Do we have a 16-Bit register that is cleared?
7926 rtx clrw = NULL_RTX;
0dff9558 7927
c8ec4eb6 7928 bool sign_extend = src.sbit && sign_bytes;
7929
7930 if (0 == dest.fbit % 8 && 7 == src.fbit % 8)
7931 shift = ASHIFT;
7932 else if (7 == dest.fbit % 8 && 0 == src.fbit % 8)
7933 shift = ASHIFTRT;
7934 else if (dest.fbit % 8 == src.fbit % 8)
7935 shift = UNKNOWN;
7936 else
7937 gcc_unreachable();
7938
226d57b0 7939 /* If we need to round the fraction part, we might need to save/round it
1a96adb9 7940 before clobbering any of it in Step 1. Also, we might want to do
226d57b0 7941 the rounding now to make use of LD_REGS. */
7942 if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
7943 && SCALAR_ACCUM_MODE_P (GET_MODE (xop[1]))
7944 && !TARGET_FRACT_CONV_TRUNC)
7945 {
7946 bool overlap
1a96adb9 7947 = (src.regno <=
7948 (offset ? dest.regno_msb - sign_bytes : dest.regno + zero_bytes - 1)
7949 && dest.regno - offset -1 >= dest.regno);
226d57b0 7950 unsigned s0 = dest.regno - offset -1;
7951 bool use_src = true;
7952 unsigned sn;
7953 unsigned copied_msb = src.regno_msb;
7954 bool have_carry = false;
7955
7956 if (src.ibyte > dest.ibyte)
1a96adb9 7957 copied_msb -= src.ibyte - dest.ibyte;
226d57b0 7958
7959 for (sn = s0; sn <= copied_msb; sn++)
1a96adb9 7960 if (!IN_RANGE (sn, dest.regno, dest.regno_msb)
7961 && !reg_unused_after (insn, all_regs_rtx[sn]))
7962 use_src = false;
226d57b0 7963 if (use_src && TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], s0))
1a96adb9 7964 {
7965 avr_asm_len ("tst %0" CR_TAB "brpl 0f",
7966 &all_regs_rtx[src.regno_msb], plen, 2);
7967 sn = src.regno;
7968 if (sn < s0)
7969 {
7970 if (TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], sn))
7971 avr_asm_len ("cpi %0,1", &all_regs_rtx[sn], plen, 1);
7972 else
7973 avr_asm_len ("sec" CR_TAB
7974 "cpc %0,__zero_reg__",
7975 &all_regs_rtx[sn], plen, 2);
7976 have_carry = true;
7977 }
7978 while (++sn < s0)
7979 avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
7980
7981 avr_asm_len (have_carry ? "sbci %0,128" : "subi %0,129",
7982 &all_regs_rtx[s0], plen, 1);
7983 for (sn = src.regno + src.fbyte; sn <= copied_msb; sn++)
7984 avr_asm_len ("sbci %0,255", &all_regs_rtx[sn], plen, 1);
7985 avr_asm_len ("\n0:", NULL, plen, 0);
7986 frac_rounded = true;
7987 }
226d57b0 7988 else if (use_src && overlap)
1a96adb9 7989 {
7990 avr_asm_len ("clr __tmp_reg__" CR_TAB
7991 "sbrc %1,0" CR_TAB
7992 "dec __tmp_reg__", xop, plen, 1);
7993 sn = src.regno;
7994 if (sn < s0)
7995 {
7996 avr_asm_len ("add %0,__tmp_reg__", &all_regs_rtx[sn], plen, 1);
7997 have_carry = true;
7998 }
7999
8000 while (++sn < s0)
8001 avr_asm_len ("adc %0,__tmp_reg__", &all_regs_rtx[sn], plen, 1);
8002
8003 if (have_carry)
8004 avr_asm_len ("clt" CR_TAB
8005 "bld __tmp_reg__,7" CR_TAB
8006 "adc %0,__tmp_reg__",
8007 &all_regs_rtx[s0], plen, 1);
8008 else
8009 avr_asm_len ("lsr __tmp_reg" CR_TAB
8010 "add %0,__tmp_reg__",
8011 &all_regs_rtx[s0], plen, 2);
8012 for (sn = src.regno + src.fbyte; sn <= copied_msb; sn++)
8013 avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8014 frac_rounded = true;
8015 }
226d57b0 8016 else if (overlap)
1a96adb9 8017 {
8018 bool use_src
8019 = (TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], s0)
8020 && (IN_RANGE (s0, dest.regno, dest.regno_msb)
8021 || reg_unused_after (insn, all_regs_rtx[s0])));
8022 xop[2] = all_regs_rtx[s0];
8023 unsigned sn = src.regno;
8024 if (!use_src || sn == s0)
8025 avr_asm_len ("mov __tmp_reg__,%2", xop, plen, 1);
8026 /* We need to consider to-be-discarded bits
8027 if the value is negative. */
8028 if (sn < s0)
8029 {
8030 avr_asm_len ("tst %0" CR_TAB
8031 "brpl 0f",
8032 &all_regs_rtx[src.regno_msb], plen, 2);
8033 /* Test to-be-discarded bytes for any nozero bits.
8034 ??? Could use OR or SBIW to test two registers at once. */
8035 if (sn < s0)
8036 avr_asm_len ("cp %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8037
8038 while (++sn < s0)
8039 avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8040 /* Set bit 0 in __tmp_reg__ if any of the lower bits was set. */
8041 if (use_src)
8042 avr_asm_len ("breq 0f" CR_TAB
8043 "ori %2,1"
8044 "\n0:\t" "mov __tmp_reg__,%2",
8045 xop, plen, 3);
8046 else
8047 avr_asm_len ("breq 0f" CR_TAB
8048 "set" CR_TAB
8049 "bld __tmp_reg__,0\n0:",
8050 xop, plen, 3);
8051 }
8052 lsb_in_tmp_reg = true;
8053 }
226d57b0 8054 }
8055
c8ec4eb6 8056 /* Step 1: Clear bytes at the low end and copy payload bits from source
8057 ====== to destination. */
8058
8059 int step = offset < 0 ? 1 : -1;
8060 unsigned d0 = offset < 0 ? dest.regno : dest.regno_msb;
8061
226d57b0 8062 // We cleared at least that number of registers.
c8ec4eb6 8063 int clr_n = 0;
8064
8065 for (; d0 >= dest.regno && d0 <= dest.regno_msb; d0 += step)
8066 {
8067 // Next regno of destination is needed for MOVW
8068 unsigned d1 = d0 + step;
8069
8070 // Current and next regno of source
2b5c3dd1 8071 signed s0 = d0 - offset;
8072 signed s1 = s0 + step;
c8ec4eb6 8073
8074 // Must current resp. next regno be CLRed? This applies to the low
8075 // bytes of the destination that have no associated source bytes.
2b5c3dd1 8076 bool clr0 = s0 < (signed) src.regno;
8077 bool clr1 = s1 < (signed) src.regno && d1 >= dest.regno;
c8ec4eb6 8078
8079 // First gather what code to emit (if any) and additional step to
8080 // apply if a MOVW is in use. xop[2] is destination rtx and xop[3]
8081 // is the source rtx for the current loop iteration.
8082 const char *code = NULL;
8083 int stepw = 0;
0dff9558 8084
c8ec4eb6 8085 if (clr0)
8086 {
8087 if (AVR_HAVE_MOVW && clr1 && clrw)
8088 {
8089 xop[2] = all_regs_rtx[d0 & ~1];
8090 xop[3] = clrw;
8091 code = "movw %2,%3";
8092 stepw = step;
8093 }
8094 else
8095 {
8096 xop[2] = all_regs_rtx[d0];
8097 code = "clr %2";
8098
8099 if (++clr_n >= 2
8100 && !clrw
8101 && d0 % 2 == (step > 0))
8102 {
8103 clrw = all_regs_rtx[d0 & ~1];
8104 }
8105 }
8106 }
2b5c3dd1 8107 else if (offset && s0 <= (signed) src.regno_msb)
c8ec4eb6 8108 {
8109 int movw = AVR_HAVE_MOVW && offset % 2 == 0
8110 && d0 % 2 == (offset > 0)
8111 && d1 <= dest.regno_msb && d1 >= dest.regno
2b5c3dd1 8112 && s1 <= (signed) src.regno_msb && s1 >= (signed) src.regno;
c8ec4eb6 8113
8114 xop[2] = all_regs_rtx[d0 & ~movw];
8115 xop[3] = all_regs_rtx[s0 & ~movw];
8116 code = movw ? "movw %2,%3" : "mov %2,%3";
8117 stepw = step * movw;
8118 }
8119
8120 if (code)
8121 {
8122 if (sign_extend && shift != ASHIFT && !sign_in_carry
8123 && (d0 == src.regno_msb || d0 + stepw == src.regno_msb))
8124 {
8125 /* We are going to override the sign bit. If we sign-extend,
8126 store the sign in the Carry flag. This is not needed if
1a96adb9 8127 the destination will be ASHIFT in the remainder because
c8ec4eb6 8128 the ASHIFT will set Carry without extra instruction. */
8129
8130 avr_asm_len ("lsl %0", &all_regs_rtx[src.regno_msb], plen, 1);
8131 sign_in_carry = true;
8132 }
8133
8134 unsigned src_msb = dest.regno_msb - sign_bytes - offset + 1;
8135
8136 if (!sign_extend && shift == ASHIFTRT && !msb_in_carry
8137 && src.ibyte > dest.ibyte
8138 && (d0 == src_msb || d0 + stepw == src_msb))
8139 {
8140 /* We are going to override the MSB. If we shift right,
8141 store the MSB in the Carry flag. This is only needed if
8142 we don't sign-extend becaue with sign-extension the MSB
8143 (the sign) will be produced by the sign extension. */
8144
8145 avr_asm_len ("lsr %0", &all_regs_rtx[src_msb], plen, 1);
8146 msb_in_carry = true;
8147 }
8148
8149 unsigned src_lsb = dest.regno - offset -1;
8150
8151 if (shift == ASHIFT && src.fbyte > dest.fbyte && !lsb_in_carry
226d57b0 8152 && !lsb_in_tmp_reg
c8ec4eb6 8153 && (d0 == src_lsb || d0 + stepw == src_lsb))
8154 {
8155 /* We are going to override the new LSB; store it into carry. */
8156
8157 avr_asm_len ("lsl %0", &all_regs_rtx[src_lsb], plen, 1);
8158 code_ashift = "rol %0";
8159 lsb_in_carry = true;
8160 }
8161
8162 avr_asm_len (code, xop, plen, 1);
8163 d0 += stepw;
8164 }
8165 }
8166
8167 /* Step 2: Shift destination left by 1 bit position. This might be needed
8168 ====== for signed input and unsigned output. */
8169
8170 if (shift == ASHIFT && src.fbyte > dest.fbyte && !lsb_in_carry)
8171 {
8172 unsigned s0 = dest.regno - offset -1;
8173
226d57b0 8174 /* n1169 4.1.4 says:
8175 "Conversions from a fixed-point to an integer type round toward zero."
8176 Hence, converting a fract type to integer only gives a non-zero result
8177 for -1. */
8178 if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8179 && SCALAR_FRACT_MODE_P (GET_MODE (xop[1]))
8180 && !TARGET_FRACT_CONV_TRUNC)
8181 {
8182 gcc_assert (s0 == src.regno_msb);
8183 /* Check if the input is -1. We do that by checking if negating
8184 the input causes an integer overflow. */
8185 unsigned sn = src.regno;
8186 avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx[sn++], plen, 1);
8187 while (sn <= s0)
8188 avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx[sn++], plen, 1);
8189
8190 /* Overflow goes with set carry. Clear carry otherwise. */
1a96adb9 8191 avr_asm_len ("brvs 0f" CR_TAB
8192 "clc\n0:", NULL, plen, 2);
226d57b0 8193 }
8194 /* Likewise, when converting from accumulator types to integer, we
8195 need to round up negative values. */
8196 else if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8197 && SCALAR_ACCUM_MODE_P (GET_MODE (xop[1]))
8198 && !TARGET_FRACT_CONV_TRUNC
8199 && !frac_rounded)
8200 {
8201 bool have_carry = false;
8202
8203 xop[2] = all_regs_rtx[s0];
8204 if (!lsb_in_tmp_reg && !MAY_CLOBBER (s0))
8205 avr_asm_len ("mov __tmp_reg__,%2", xop, plen, 1);
8206 avr_asm_len ("tst %0" CR_TAB "brpl 0f",
8207 &all_regs_rtx[src.regno_msb], plen, 2);
8208 if (!lsb_in_tmp_reg)
8209 {
8210 unsigned sn = src.regno;
8211 if (sn < s0)
8212 {
8213 avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx[sn],
8214 plen, 1);
8215 have_carry = true;
8216 }
8217 while (++sn < s0)
8218 avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx[sn], plen, 1);
8219 lsb_in_tmp_reg = !MAY_CLOBBER (s0);
8220 }
8221 /* Add in C and the rounding value 127. */
8222 /* If the destination msb is a sign byte, and in LD_REGS,
8223 grab it as a temporary. */
8224 if (sign_bytes
8225 && TEST_HARD_REG_BIT (reg_class_contents[LD_REGS],
8226 dest.regno_msb))
8227 {
8228 xop[3] = all_regs_rtx[dest.regno_msb];
8229 avr_asm_len ("ldi %3,127", xop, plen, 1);
8230 avr_asm_len ((have_carry && lsb_in_tmp_reg ? "adc __tmp_reg__,%3"
8231 : have_carry ? "adc %2,%3"
8232 : lsb_in_tmp_reg ? "add __tmp_reg__,%3"
8233 : "add %2,%3"),
8234 xop, plen, 1);
8235 }
8236 else
8237 {
8238 /* Fall back to use __zero_reg__ as a temporary. */
8239 avr_asm_len ("dec __zero_reg__", NULL, plen, 1);
8240 if (have_carry)
1a96adb9 8241 avr_asm_len ("clt" CR_TAB
8242 "bld __zero_reg__,7", NULL, plen, 2);
226d57b0 8243 else
8244 avr_asm_len ("lsr __zero_reg__", NULL, plen, 1);
1a96adb9 8245 avr_asm_len (have_carry && lsb_in_tmp_reg
8246 ? "adc __tmp_reg__,__zero_reg__"
8247 : have_carry ? "adc %2,__zero_reg__"
8248 : lsb_in_tmp_reg ? "add __tmp_reg__,__zero_reg__"
8249 : "add %2,__zero_reg__",
226d57b0 8250 xop, plen, 1);
8251 avr_asm_len ("eor __zero_reg__,__zero_reg__", NULL, plen, 1);
8252 }
1a96adb9 8253
8254 for (d0 = dest.regno + zero_bytes;
226d57b0 8255 d0 <= dest.regno_msb - sign_bytes; d0++)
8256 avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx[d0], plen, 1);
1a96adb9 8257
8258 avr_asm_len (lsb_in_tmp_reg
8259 ? "\n0:\t" "lsl __tmp_reg__"
8260 : "\n0:\t" "lsl %2",
226d57b0 8261 xop, plen, 1);
8262 }
8263 else if (MAY_CLOBBER (s0))
c8ec4eb6 8264 avr_asm_len ("lsl %0", &all_regs_rtx[s0], plen, 1);
8265 else
8266 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
8267 "lsl __tmp_reg__", &all_regs_rtx[s0], plen, 2);
8268
8269 code_ashift = "rol %0";
8270 lsb_in_carry = true;
8271 }
8272
8273 if (shift == ASHIFT)
8274 {
8275 for (d0 = dest.regno + zero_bytes;
8276 d0 <= dest.regno_msb - sign_bytes; d0++)
8277 {
8278 avr_asm_len (code_ashift, &all_regs_rtx[d0], plen, 1);
8279 code_ashift = "rol %0";
8280 }
8281
8282 lsb_in_carry = false;
8283 sign_in_carry = true;
8284 }
8285
8286 /* Step 4a: Store MSB in carry if we don't already have it or will produce
8287 ======= it in sign-extension below. */
8288
8289 if (!sign_extend && shift == ASHIFTRT && !msb_in_carry
8290 && src.ibyte > dest.ibyte)
8291 {
8292 unsigned s0 = dest.regno_msb - sign_bytes - offset + 1;
8293
8294 if (MAY_CLOBBER (s0))
8295 avr_asm_len ("lsr %0", &all_regs_rtx[s0], plen, 1);
8296 else
8297 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
8298 "lsr __tmp_reg__", &all_regs_rtx[s0], plen, 2);
8299
8300 msb_in_carry = true;
8301 }
8302
8303 /* Step 3: Sign-extend or zero-extend the destination as needed.
8304 ====== */
8305
8306 if (sign_extend && !sign_in_carry)
8307 {
8308 unsigned s0 = src.regno_msb;
0dff9558 8309
c8ec4eb6 8310 if (MAY_CLOBBER (s0))
8311 avr_asm_len ("lsl %0", &all_regs_rtx[s0], plen, 1);
8312 else
8313 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
8314 "lsl __tmp_reg__", &all_regs_rtx[s0], plen, 2);
8315
8316 sign_in_carry = true;
8317 }
8318
8319 gcc_assert (sign_in_carry + msb_in_carry + lsb_in_carry <= 1);
8320
8321 unsigned copies = 0;
8322 rtx movw = sign_extend ? NULL_RTX : clrw;
8323
8324 for (d0 = dest.regno_msb - sign_bytes + 1; d0 <= dest.regno_msb; d0++)
8325 {
8326 if (AVR_HAVE_MOVW && movw
8327 && d0 % 2 == 0 && d0 + 1 <= dest.regno_msb)
8328 {
8329 xop[2] = all_regs_rtx[d0];
8330 xop[3] = movw;
8331 avr_asm_len ("movw %2,%3", xop, plen, 1);
8332 d0++;
8333 }
8334 else
8335 {
8336 avr_asm_len (sign_extend ? "sbc %0,%0" : "clr %0",
8337 &all_regs_rtx[d0], plen, 1);
8338
8339 if (++copies >= 2 && !movw && d0 % 2 == 1)
8340 movw = all_regs_rtx[d0-1];
8341 }
8342 } /* for */
8343
8344
8345 /* Step 4: Right shift the destination. This might be needed for
8346 ====== conversions from unsigned to signed. */
8347
8348 if (shift == ASHIFTRT)
8349 {
8350 const char *code_ashiftrt = "lsr %0";
8351
8352 if (sign_extend || msb_in_carry)
8353 code_ashiftrt = "ror %0";
8354
8355 if (src.sbit && src.ibyte == dest.ibyte)
8356 code_ashiftrt = "asr %0";
8357
8358 for (d0 = dest.regno_msb - sign_bytes;
8359 d0 >= dest.regno + zero_bytes - 1 && d0 >= dest.regno; d0--)
8360 {
8361 avr_asm_len (code_ashiftrt, &all_regs_rtx[d0], plen, 1);
8362 code_ashiftrt = "ror %0";
8363 }
8364 }
8365
8366#undef MAY_CLOBBER
8367
8368 return "";
8369}
8370
8371
fdbf5b19 8372/* Output fixed-point rounding. XOP[0] = XOP[1] is the operand to round.
8373 XOP[2] is the rounding point, a CONST_INT. The function prints the
8374 instruction sequence if PLEN = NULL and computes the length in words
8375 of the sequence if PLEN != NULL. Most of this function deals with
8376 preparing operands for calls to `avr_out_plus' and `avr_out_bitop'. */
8377
8378const char*
375204de 8379avr_out_round (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *xop, int *plen)
fdbf5b19 8380{
3754d046 8381 machine_mode mode = GET_MODE (xop[0]);
8382 machine_mode imode = int_mode_for_mode (mode);
fdbf5b19 8383 // The smallest fractional bit not cleared by the rounding is 2^(-RP).
8384 int fbit = (int) GET_MODE_FBIT (mode);
8385 double_int i_add = double_int_zero.set_bit (fbit-1 - INTVAL (xop[2]));
85fbad9e 8386 wide_int wi_add = wi::set_bit_in_zero (fbit-1 - INTVAL (xop[2]),
8387 GET_MODE_PRECISION (imode));
fdbf5b19 8388 // Lengths of PLUS and AND parts.
8389 int len_add = 0, *plen_add = plen ? &len_add : NULL;
8390 int len_and = 0, *plen_and = plen ? &len_and : NULL;
8391
8392 // Add-Saturate 1/2 * 2^(-RP). Don't print the label "0:" when printing
8393 // the saturated addition so that we can emit the "rjmp 1f" before the
8394 // "0:" below.
8395
8396 rtx xadd = const_fixed_from_double_int (i_add, mode);
8397 rtx xpattern, xsrc, op[4];
8398
8399 xsrc = SIGNED_FIXED_POINT_MODE_P (mode)
8400 ? gen_rtx_SS_PLUS (mode, xop[1], xadd)
8401 : gen_rtx_US_PLUS (mode, xop[1], xadd);
8402 xpattern = gen_rtx_SET (VOIDmode, xop[0], xsrc);
8403
8404 op[0] = xop[0];
8405 op[1] = xop[1];
8406 op[2] = xadd;
8407 avr_out_plus (xpattern, op, plen_add, NULL, false /* Don't print "0:" */);
8408
8409 avr_asm_len ("rjmp 1f" CR_TAB
8410 "0:", NULL, plen_add, 1);
8411
8412 // Keep all bits from RP and higher: ... 2^(-RP)
8413 // Clear all bits from RP+1 and lower: 2^(-RP-1) ...
8414 // Rounding point ^^^^^^^
8415 // Added above ^^^^^^^^^
8416 rtx xreg = simplify_gen_subreg (imode, xop[0], mode, 0);
85fbad9e 8417 rtx xmask = immed_wide_int_const (-wi_add - wi_add, imode);
fdbf5b19 8418
8419 xpattern = gen_rtx_SET (VOIDmode, xreg, gen_rtx_AND (imode, xreg, xmask));
8420
8421 op[0] = xreg;
8422 op[1] = xreg;
8423 op[2] = xmask;
8424 op[3] = gen_rtx_SCRATCH (QImode);
8425 avr_out_bitop (xpattern, op, plen_and);
8426 avr_asm_len ("1:", NULL, plen, 0);
8427
8428 if (plen)
8429 *plen = len_add + len_and;
8430
8431 return "";
8432}
8433
8434
9643da7d 8435/* Create RTL split patterns for byte sized rotate expressions. This
8436 produces a series of move instructions and considers overlap situations.
8437 Overlapping non-HImode operands need a scratch register. */
8438
8439bool
8440avr_rotate_bytes (rtx operands[])
8441{
8442 int i, j;
3754d046 8443 machine_mode mode = GET_MODE (operands[0]);
9643da7d 8444 bool overlapped = reg_overlap_mentioned_p (operands[0], operands[1]);
8445 bool same_reg = rtx_equal_p (operands[0], operands[1]);
8446 int num = INTVAL (operands[2]);
8447 rtx scratch = operands[3];
8448 /* Work out if byte or word move is needed. Odd byte rotates need QImode.
8449 Word move if no scratch is needed, otherwise use size of scratch. */
3754d046 8450 machine_mode move_mode = QImode;
36f949a2 8451 int move_size, offset, size;
8452
9643da7d 8453 if (num & 0xf)
8454 move_mode = QImode;
8455 else if ((mode == SImode && !same_reg) || !overlapped)
8456 move_mode = HImode;
8457 else
8458 move_mode = GET_MODE (scratch);
8459
8460 /* Force DI rotate to use QI moves since other DI moves are currently split
8461 into QI moves so forward propagation works better. */
8462 if (mode == DImode)
8463 move_mode = QImode;
8464 /* Make scratch smaller if needed. */
ac191360 8465 if (SCRATCH != GET_CODE (scratch)
8466 && HImode == GET_MODE (scratch)
8467 && QImode == move_mode)
0dff9558 8468 scratch = simplify_gen_subreg (move_mode, scratch, HImode, 0);
9643da7d 8469
36f949a2 8470 move_size = GET_MODE_SIZE (move_mode);
9643da7d 8471 /* Number of bytes/words to rotate. */
36f949a2 8472 offset = (num >> 3) / move_size;
9643da7d 8473 /* Number of moves needed. */
36f949a2 8474 size = GET_MODE_SIZE (mode) / move_size;
9643da7d 8475 /* Himode byte swap is special case to avoid a scratch register. */
8476 if (mode == HImode && same_reg)
8477 {
8478 /* HImode byte swap, using xor. This is as quick as using scratch. */
8479 rtx src, dst;
8480 src = simplify_gen_subreg (move_mode, operands[1], mode, 0);
8481 dst = simplify_gen_subreg (move_mode, operands[0], mode, 1);
8482 if (!rtx_equal_p (dst, src))
8483 {
8484 emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
8485 emit_move_insn (src, gen_rtx_XOR (QImode, src, dst));
8486 emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
8487 }
0dff9558 8488 }
8489 else
9643da7d 8490 {
36f949a2 8491#define MAX_SIZE 8 /* GET_MODE_SIZE (DImode) / GET_MODE_SIZE (QImode) */
9643da7d 8492 /* Create linked list of moves to determine move order. */
8493 struct {
8494 rtx src, dst;
8495 int links;
36f949a2 8496 } move[MAX_SIZE + 8];
8497 int blocked, moves;
9643da7d 8498
36f949a2 8499 gcc_assert (size <= MAX_SIZE);
9643da7d 8500 /* Generate list of subreg moves. */
8501 for (i = 0; i < size; i++)
1a96adb9 8502 {
9643da7d 8503 int from = i;
0dff9558 8504 int to = (from + offset) % size;
9643da7d 8505 move[i].src = simplify_gen_subreg (move_mode, operands[1],
1a96adb9 8506 mode, from * move_size);
9643da7d 8507 move[i].dst = simplify_gen_subreg (move_mode, operands[0],
1a96adb9 8508 mode, to * move_size);
8509 move[i].links = -1;
8510 }
9643da7d 8511 /* Mark dependence where a dst of one move is the src of another move.
8512 The first move is a conflict as it must wait until second is
8513 performed. We ignore moves to self - we catch this later. */
8514 if (overlapped)
8515 for (i = 0; i < size; i++)
8516 if (reg_overlap_mentioned_p (move[i].dst, operands[1]))
8517 for (j = 0; j < size; j++)
8518 if (j != i && rtx_equal_p (move[j].src, move[i].dst))
8519 {
8520 /* The dst of move i is the src of move j. */
8521 move[i].links = j;
8522 break;
8523 }
8524
36f949a2 8525 blocked = -1;
8526 moves = 0;
9643da7d 8527 /* Go through move list and perform non-conflicting moves. As each
8528 non-overlapping move is made, it may remove other conflicts
8529 so the process is repeated until no conflicts remain. */
8530 do
8531 {
8532 blocked = -1;
8533 moves = 0;
8534 /* Emit move where dst is not also a src or we have used that
8535 src already. */
8536 for (i = 0; i < size; i++)
8537 if (move[i].src != NULL_RTX)
36f949a2 8538 {
8539 if (move[i].links == -1
8540 || move[move[i].links].src == NULL_RTX)
8541 {
8542 moves++;
8543 /* Ignore NOP moves to self. */
8544 if (!rtx_equal_p (move[i].dst, move[i].src))
8545 emit_move_insn (move[i].dst, move[i].src);
9643da7d 8546
36f949a2 8547 /* Remove conflict from list. */
8548 move[i].src = NULL_RTX;
8549 }
8550 else
8551 blocked = i;
8552 }
9643da7d 8553
8554 /* Check for deadlock. This is when no moves occurred and we have
8555 at least one blocked move. */
8556 if (moves == 0 && blocked != -1)
8557 {
8558 /* Need to use scratch register to break deadlock.
8559 Add move to put dst of blocked move into scratch.
8560 When this move occurs, it will break chain deadlock.
8561 The scratch register is substituted for real move. */
8562
ac191360 8563 gcc_assert (SCRATCH != GET_CODE (scratch));
8564
9643da7d 8565 move[size].src = move[blocked].dst;
8566 move[size].dst = scratch;
8567 /* Scratch move is never blocked. */
0dff9558 8568 move[size].links = -1;
9643da7d 8569 /* Make sure we have valid link. */
8570 gcc_assert (move[blocked].links != -1);
8571 /* Replace src of blocking move with scratch reg. */
8572 move[move[blocked].links].src = scratch;
4246a5c7 8573 /* Make dependent on scratch move occurring. */
0dff9558 8574 move[blocked].links = size;
9643da7d 8575 size=size+1;
8576 }
8577 }
8578 while (blocked != -1);
8579 }
8580 return true;
8581}
8582
017c5b98 8583
0dff9558 8584/* Worker function for `ADJUST_INSN_LENGTH'. */
a28e4651 8585/* Modifies the length assigned to instruction INSN
b0e2b973 8586 LEN is the initially computed length of the insn. */
a28e4651 8587
8588int
375204de 8589avr_adjust_insn_length (rtx_insn *insn, int len)
a28e4651 8590{
5bca95a8 8591 rtx *op = recog_data.operand;
28913f6b 8592 enum attr_adjust_len adjust_len;
8593
8594 /* Some complex insns don't need length adjustment and therefore
8595 the length need not/must not be adjusted for these insns.
8596 It is easier to state this in an insn attribute "adjust_len" than
8597 to clutter up code here... */
1a96adb9 8598
d44f2f7c 8599 if (JUMP_TABLE_DATA_P (insn) || recog_memoized (insn) == -1)
28913f6b 8600 {
8601 return len;
8602 }
8603
8604 /* Read from insn attribute "adjust_len" if/how length is to be adjusted. */
8605
8606 adjust_len = get_attr_adjust_len (insn);
8607
5bca95a8 8608 if (adjust_len == ADJUST_LEN_NO)
28913f6b 8609 {
5bca95a8 8610 /* Nothing to adjust: The length from attribute "length" is fine.
8611 This is the default. */
0dff9558 8612
5bca95a8 8613 return len;
8614 }
0dff9558 8615
5bca95a8 8616 /* Extract insn's operands. */
0dff9558 8617
5bca95a8 8618 extract_constrain_insn_cached (insn);
0dff9558 8619
5bca95a8 8620 /* Dispatch to right function. */
0dff9558 8621
5bca95a8 8622 switch (adjust_len)
8623 {
8624 case ADJUST_LEN_RELOAD_IN16: output_reload_inhi (op, op[2], &len); break;
02d9a2c3 8625 case ADJUST_LEN_RELOAD_IN24: avr_out_reload_inpsi (op, op[2], &len); break;
5bca95a8 8626 case ADJUST_LEN_RELOAD_IN32: output_reload_insisf (op, op[2], &len); break;
0dff9558 8627
5bca95a8 8628 case ADJUST_LEN_OUT_BITOP: avr_out_bitop (insn, op, &len); break;
0dff9558 8629
b4ebb666 8630 case ADJUST_LEN_PLUS: avr_out_plus (insn, op, &len); break;
915f904b 8631 case ADJUST_LEN_ADDTO_SP: avr_out_addto_sp (op, &len); break;
0dff9558 8632
5bca95a8 8633 case ADJUST_LEN_MOV8: output_movqi (insn, op, &len); break;
8634 case ADJUST_LEN_MOV16: output_movhi (insn, op, &len); break;
02d9a2c3 8635 case ADJUST_LEN_MOV24: avr_out_movpsi (insn, op, &len); break;
5bca95a8 8636 case ADJUST_LEN_MOV32: output_movsisf (insn, op, &len); break;
5bd39e93 8637 case ADJUST_LEN_MOVMEM: avr_out_movmem (insn, op, &len); break;
8638 case ADJUST_LEN_XLOAD: avr_out_xload (insn, op, &len); break;
4b72e680 8639 case ADJUST_LEN_LPM: avr_out_lpm (insn, op, &len); break;
5766e83c 8640 case ADJUST_LEN_SEXT: avr_out_sign_extend (insn, op, &len); break;
5bd39e93 8641
017c5b98 8642 case ADJUST_LEN_SFRACT: avr_out_fract (insn, op, true, &len); break;
8643 case ADJUST_LEN_UFRACT: avr_out_fract (insn, op, false, &len); break;
fdbf5b19 8644 case ADJUST_LEN_ROUND: avr_out_round (insn, op, &len); break;
017c5b98 8645
5bca95a8 8646 case ADJUST_LEN_TSTHI: avr_out_tsthi (insn, op, &len); break;
02d9a2c3 8647 case ADJUST_LEN_TSTPSI: avr_out_tstpsi (insn, op, &len); break;
5bca95a8 8648 case ADJUST_LEN_TSTSI: avr_out_tstsi (insn, op, &len); break;
8649 case ADJUST_LEN_COMPARE: avr_out_compare (insn, op, &len); break;
83921eda 8650 case ADJUST_LEN_COMPARE64: avr_out_compare64 (insn, op, &len); break;
9c501a04 8651
5bca95a8 8652 case ADJUST_LEN_LSHRQI: lshrqi3_out (insn, op, &len); break;
8653 case ADJUST_LEN_LSHRHI: lshrhi3_out (insn, op, &len); break;
8654 case ADJUST_LEN_LSHRSI: lshrsi3_out (insn, op, &len); break;
9c501a04 8655
5bca95a8 8656 case ADJUST_LEN_ASHRQI: ashrqi3_out (insn, op, &len); break;
8657 case ADJUST_LEN_ASHRHI: ashrhi3_out (insn, op, &len); break;
8658 case ADJUST_LEN_ASHRSI: ashrsi3_out (insn, op, &len); break;
9c501a04 8659
5bca95a8 8660 case ADJUST_LEN_ASHLQI: ashlqi3_out (insn, op, &len); break;
8661 case ADJUST_LEN_ASHLHI: ashlhi3_out (insn, op, &len); break;
8662 case ADJUST_LEN_ASHLSI: ashlsi3_out (insn, op, &len); break;
0dff9558 8663
02d9a2c3 8664 case ADJUST_LEN_ASHLPSI: avr_out_ashlpsi3 (insn, op, &len); break;
8665 case ADJUST_LEN_ASHRPSI: avr_out_ashrpsi3 (insn, op, &len); break;
8666 case ADJUST_LEN_LSHRPSI: avr_out_lshrpsi3 (insn, op, &len); break;
8667
48264eb8 8668 case ADJUST_LEN_CALL: len = AVR_HAVE_JMP_CALL ? 2 : 1; break;
8669
15b84087 8670 case ADJUST_LEN_INSERT_BITS: avr_out_insert_bits (op, &len); break;
384f6361 8671
5bca95a8 8672 default:
8673 gcc_unreachable();
a28e4651 8674 }
15b84087 8675
a28e4651 8676 return len;
8677}
8678
674a8f0b 8679/* Return nonzero if register REG dead after INSN. */
a28e4651 8680
8681int
375204de 8682reg_unused_after (rtx_insn *insn, rtx reg)
a28e4651 8683{
e511e253 8684 return (dead_or_set_p (insn, reg)
a28e4651 8685 || (REG_P(reg) && _reg_unused_after (insn, reg)));
8686}
8687
e3e08e7f 8688/* Return nonzero if REG is not used after INSN.
a28e4651 8689 We assume REG is a reload reg, and therefore does
8690 not live past labels. It may live past calls or jumps though. */
8691
8692int
375204de 8693_reg_unused_after (rtx_insn *insn, rtx reg)
a28e4651 8694{
8695 enum rtx_code code;
8696 rtx set;
8697
8698 /* If the reg is set by this instruction, then it is safe for our
8699 case. Disregard the case where this is a store to memory, since
8700 we are checking a register used in the store address. */
8701 set = single_set (insn);
8702 if (set && GET_CODE (SET_DEST (set)) != MEM
8703 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
8704 return 1;
8705
8706 while ((insn = NEXT_INSN (insn)))
8707 {
6720e96c 8708 rtx set;
a28e4651 8709 code = GET_CODE (insn);
8710
8711#if 0
8712 /* If this is a label that existed before reload, then the register
8713 if dead here. However, if this is a label added by reorg, then
8714 the register may still be live here. We can't tell the difference,
8715 so we just ignore labels completely. */
8716 if (code == CODE_LABEL)
8717 return 1;
8718 /* else */
8719#endif
8720
6720e96c 8721 if (!INSN_P (insn))
8722 continue;
8723
a28e4651 8724 if (code == JUMP_INSN)
8725 return 0;
8726
8727 /* If this is a sequence, we must handle them all at once.
8728 We could have for instance a call that sets the target register,
ebb11c7b 8729 and an insn in a delay slot that uses the register. In this case,
a28e4651 8730 we must return 0. */
8731 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
8732 {
50fc2d35 8733 rtx_sequence *seq = as_a <rtx_sequence *> (PATTERN (insn));
a28e4651 8734 int i;
8735 int retval = 0;
8736
50fc2d35 8737 for (i = 0; i < seq->len (); i++)
a28e4651 8738 {
50fc2d35 8739 rtx_insn *this_insn = seq->insn (i);
a28e4651 8740 rtx set = single_set (this_insn);
8741
aa90bb35 8742 if (CALL_P (this_insn))
a28e4651 8743 code = CALL_INSN;
aa90bb35 8744 else if (JUMP_P (this_insn))
a28e4651 8745 {
8746 if (INSN_ANNULLED_BRANCH_P (this_insn))
8747 return 0;
8748 code = JUMP_INSN;
8749 }
8750
8751 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
8752 return 0;
8753 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
8754 {
8755 if (GET_CODE (SET_DEST (set)) != MEM)
8756 retval = 1;
8757 else
8758 return 0;
8759 }
8760 if (set == 0
8761 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
8762 return 0;
8763 }
8764 if (retval == 1)
8765 return 1;
8766 else if (code == JUMP_INSN)
8767 return 0;
8768 }
8769
8770 if (code == CALL_INSN)
8771 {
8772 rtx tem;
8773 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
8774 if (GET_CODE (XEXP (tem, 0)) == USE
8775 && REG_P (XEXP (XEXP (tem, 0), 0))
8776 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
8777 return 0;
0dff9558 8778 if (call_used_regs[REGNO (reg)])
a28e4651 8779 return 1;
8780 }
8781
6720e96c 8782 set = single_set (insn);
a28e4651 8783
6720e96c 8784 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
8785 return 0;
8786 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
8787 return GET_CODE (SET_DEST (set)) != MEM;
8788 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
8789 return 0;
a28e4651 8790 }
8791 return 1;
8792}
8793
5bd39e93 8794
0dff9558 8795/* Implement `TARGET_ASM_INTEGER'. */
58356836 8796/* Target hook for assembling integer objects. The AVR version needs
8797 special handling for references to certain labels. */
a28e4651 8798
58356836 8799static bool
206a5129 8800avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
a28e4651 8801{
58356836 8802 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
5a9cc803 8803 && text_segment_operand (x, VOIDmode))
a28e4651 8804 {
90ef7269 8805 fputs ("\t.word\tgs(", asm_out_file);
58356836 8806 output_addr_const (asm_out_file, x);
8807 fputs (")\n", asm_out_file);
0dff9558 8808
5bd39e93 8809 return true;
8810 }
8811 else if (GET_MODE (x) == PSImode)
8812 {
5a9cc803 8813 /* This needs binutils 2.23+, see PR binutils/13503 */
8814
8815 fputs ("\t.byte\tlo8(", asm_out_file);
8816 output_addr_const (asm_out_file, x);
8817 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
0dff9558 8818
5a9cc803 8819 fputs ("\t.byte\thi8(", asm_out_file);
5bd39e93 8820 output_addr_const (asm_out_file, x);
5a9cc803 8821 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
0dff9558 8822
5a9cc803 8823 fputs ("\t.byte\thh8(", asm_out_file);
5bd39e93 8824 output_addr_const (asm_out_file, x);
5a9cc803 8825 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
0dff9558 8826
58356836 8827 return true;
a28e4651 8828 }
017c5b98 8829 else if (CONST_FIXED_P (x))
8830 {
8831 unsigned n;
8832
8833 /* varasm fails to handle big fixed modes that don't fit in hwi. */
8834
8835 for (n = 0; n < size; n++)
8836 {
8837 rtx xn = simplify_gen_subreg (QImode, x, GET_MODE (x), n);
8838 default_assemble_integer (xn, 1, aligned_p);
8839 }
8840
8841 return true;
8842 }
0dff9558 8843
58356836 8844 return default_assemble_integer (x, size, aligned_p);
a28e4651 8845}
8846
5bd39e93 8847
0dff9558 8848/* Implement `TARGET_CLASS_LIKELY_SPILLED_P'. */
a28e4651 8849/* Return value is nonzero if pseudos that have been
8850 assigned to registers of class CLASS would likely be spilled
8851 because registers of CLASS are needed for spill registers. */
8852
cb3959cc 8853static bool
8854avr_class_likely_spilled_p (reg_class_t c)
a28e4651 8855{
b4e6d2e2 8856 return (c != ALL_REGS &&
8857 (AVR_TINY ? 1 : c != ADDW_REGS));
a28e4651 8858}
8859
a28e4651 8860
0dff9558 8861/* Valid attributes:
8862 progmem - Put data to program memory.
8863 signal - Make a function to be hardware interrupt.
8864 After function prologue interrupts remain disabled.
8865 interrupt - Make a function to be hardware interrupt. Before function
8866 prologue interrupts are enabled by means of SEI.
8867 naked - Don't generate function prologue/epilogue and RET
8868 instruction. */
e3c541f0 8869
e3c541f0 8870/* Handle a "progmem" attribute; arguments as in
8871 struct attribute_spec.handler. */
0dff9558 8872
e3c541f0 8873static tree
206a5129 8874avr_handle_progmem_attribute (tree *node, tree name,
8875 tree args ATTRIBUTE_UNUSED,
8876 int flags ATTRIBUTE_UNUSED,
8877 bool *no_add_attrs)
e3c541f0 8878{
8879 if (DECL_P (*node))
a28e4651 8880 {
68e7ca0a 8881 if (TREE_CODE (*node) == TYPE_DECL)
8882 {
8883 /* This is really a decl attribute, not a type attribute,
8884 but try to handle it for GCC 3.0 backwards compatibility. */
8885
8886 tree type = TREE_TYPE (*node);
8887 tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
8888 tree newtype = build_type_attribute_variant (type, attr);
8889
8890 TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
8891 TREE_TYPE (*node) = newtype;
8892 *no_add_attrs = true;
8893 }
8894 else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
a28e4651 8895 {
b44e24e6 8896 *no_add_attrs = false;
e3c541f0 8897 }
8898 else
8899 {
67a779df 8900 warning (OPT_Wattributes, "%qE attribute ignored",
8901 name);
e3c541f0 8902 *no_add_attrs = true;
a28e4651 8903 }
a28e4651 8904 }
e3c541f0 8905
8906 return NULL_TREE;
a28e4651 8907}
8908
e3c541f0 8909/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
8910 struct attribute_spec.handler. */
206a5129 8911
e3c541f0 8912static tree
206a5129 8913avr_handle_fndecl_attribute (tree *node, tree name,
8914 tree args ATTRIBUTE_UNUSED,
8915 int flags ATTRIBUTE_UNUSED,
8916 bool *no_add_attrs)
e3c541f0 8917{
8918 if (TREE_CODE (*node) != FUNCTION_DECL)
8919 {
67a779df 8920 warning (OPT_Wattributes, "%qE attribute only applies to functions",
8921 name);
e3c541f0 8922 *no_add_attrs = true;
8923 }
8924
8925 return NULL_TREE;
8926}
a28e4651 8927
f86b386b 8928static tree
8929avr_handle_fntype_attribute (tree *node, tree name,
8930 tree args ATTRIBUTE_UNUSED,
8931 int flags ATTRIBUTE_UNUSED,
8932 bool *no_add_attrs)
8933{
8934 if (TREE_CODE (*node) != FUNCTION_TYPE)
8935 {
67a779df 8936 warning (OPT_Wattributes, "%qE attribute only applies to functions",
8937 name);
f86b386b 8938 *no_add_attrs = true;
8939 }
8940
8941 return NULL_TREE;
8942}
8943
c0d7a1d0 8944static tree
8945avr_handle_addr_attribute (tree *node, tree name, tree args,
8946 int flags ATTRIBUTE_UNUSED, bool *no_add)
8947{
8948 bool io_p = (strncmp (IDENTIFIER_POINTER (name), "io", 2) == 0);
8949 location_t loc = DECL_SOURCE_LOCATION (*node);
8950
8951 if (TREE_CODE (*node) != VAR_DECL)
8952 {
8953 warning_at (loc, 0, "%qE attribute only applies to variables", name);
8954 *no_add = true;
8955 }
8956
8957 if (args != NULL_TREE)
8958 {
8959 if (TREE_CODE (TREE_VALUE (args)) == NON_LVALUE_EXPR)
8960 TREE_VALUE (args) = TREE_OPERAND (TREE_VALUE (args), 0);
8961 tree arg = TREE_VALUE (args);
8962 if (TREE_CODE (arg) != INTEGER_CST)
8963 {
8964 warning (0, "%qE attribute allows only an integer constant argument",
8965 name);
8966 *no_add = true;
8967 }
8968 else if (io_p
8969 && (!tree_fits_shwi_p (arg)
8970 || !(strcmp (IDENTIFIER_POINTER (name), "io_low") == 0
8971 ? low_io_address_operand : io_address_operand)
8972 (GEN_INT (TREE_INT_CST_LOW (arg)), QImode)))
8973 {
8974 warning_at (loc, 0, "%qE attribute address out of range", name);
8975 *no_add = true;
8976 }
8977 else
8978 {
8979 tree attribs = DECL_ATTRIBUTES (*node);
8980 const char *names[] = { "io", "io_low", "address", NULL } ;
8981 for (const char **p = names; *p; p++)
8982 {
8983 tree other = lookup_attribute (*p, attribs);
8984 if (other && TREE_VALUE (other))
8985 {
8986 warning_at (loc, 0,
8987 "both %s and %qE attribute provide address",
8988 *p, name);
8989 *no_add = true;
8990 break;
8991 }
8992 }
8993 }
8994 }
8995
8996 if (*no_add == false && io_p && !TREE_THIS_VOLATILE (*node))
8997 warning_at (loc, 0, "%qE attribute on non-volatile variable", name);
8998
8999 return NULL_TREE;
9000}
9001
9002rtx
9003avr_eval_addr_attrib (rtx x)
9004{
9005 if (GET_CODE (x) == SYMBOL_REF
9006 && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_ADDRESS))
9007 {
9008 tree decl = SYMBOL_REF_DECL (x);
9009 tree attr = NULL_TREE;
9010
9011 if (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO)
9012 {
9013 attr = lookup_attribute ("io", DECL_ATTRIBUTES (decl));
9014 gcc_assert (attr);
9015 }
9016 if (!attr || !TREE_VALUE (attr))
9017 attr = lookup_attribute ("address", DECL_ATTRIBUTES (decl));
9018 gcc_assert (attr && TREE_VALUE (attr) && TREE_VALUE (TREE_VALUE (attr)));
9019 return GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))));
9020 }
9021 return x;
9022}
9023
a45076aa 9024
9025/* AVR attributes. */
9026static const struct attribute_spec
9027avr_attribute_table[] =
9028{
9029 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
9030 affects_type_identity } */
9031 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute,
9032 false },
9033 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute,
9034 false },
9035 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute,
9036 false },
9037 { "naked", 0, 0, false, true, true, avr_handle_fntype_attribute,
9038 false },
9039 { "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute,
9040 false },
9041 { "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute,
9042 false },
c0d7a1d0 9043 { "io", 0, 1, false, false, false, avr_handle_addr_attribute,
9044 false },
9045 { "io_low", 0, 1, false, false, false, avr_handle_addr_attribute,
9046 false },
9047 { "address", 1, 1, false, false, false, avr_handle_addr_attribute,
9048 false },
a45076aa 9049 { NULL, 0, 0, false, false, false, NULL, false }
9050};
9051
4202ef11 9052
9053/* Look if DECL shall be placed in program memory space by
9054 means of attribute `progmem' or some address-space qualifier.
9055 Return non-zero if DECL is data that must end up in Flash and
9056 zero if the data lives in RAM (.bss, .data, .rodata, ...).
0dff9558 9057
5bd39e93 9058 Return 2 if DECL is located in 24-bit flash address-space
4202ef11 9059 Return 1 if DECL is located in 16-bit flash address-space
9060 Return -1 if attribute `progmem' occurs in DECL or ATTRIBUTES
9061 Return 0 otherwise */
a28e4651 9062
9063int
148b2ce0 9064avr_progmem_p (tree decl, tree attributes)
a28e4651 9065{
9066 tree a;
9067
9068 if (TREE_CODE (decl) != VAR_DECL)
9069 return 0;
9070
590da9f2 9071 if (avr_decl_memx_p (decl))
5bd39e93 9072 return 2;
9073
590da9f2 9074 if (avr_decl_flash_p (decl))
4202ef11 9075 return 1;
9076
a28e4651 9077 if (NULL_TREE
148b2ce0 9078 != lookup_attribute ("progmem", attributes))
4202ef11 9079 return -1;
a28e4651 9080
4202ef11 9081 a = decl;
0dff9558 9082
a28e4651 9083 do
9084 a = TREE_TYPE(a);
9085 while (TREE_CODE (a) == ARRAY_TYPE);
9086
faf8f400 9087 if (a == error_mark_node)
9088 return 0;
9089
a28e4651 9090 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
4202ef11 9091 return -1;
0dff9558 9092
a28e4651 9093 return 0;
9094}
9095
4202ef11 9096
9097/* Scan type TYP for pointer references to address space ASn.
9098 Return ADDR_SPACE_GENERIC (i.e. 0) if all pointers targeting
9099 the AS are also declared to be CONST.
9d75589a 9100 Otherwise, return the respective address space, i.e. a value != 0. */
0dff9558 9101
4202ef11 9102static addr_space_t
9103avr_nonconst_pointer_addrspace (tree typ)
9104{
9105 while (ARRAY_TYPE == TREE_CODE (typ))
9106 typ = TREE_TYPE (typ);
9107
9108 if (POINTER_TYPE_P (typ))
9109 {
e508bf98 9110 addr_space_t as;
4202ef11 9111 tree target = TREE_TYPE (typ);
9112
9113 /* Pointer to function: Test the function's return type. */
0dff9558 9114
4202ef11 9115 if (FUNCTION_TYPE == TREE_CODE (target))
9116 return avr_nonconst_pointer_addrspace (TREE_TYPE (target));
9117
9118 /* "Ordinary" pointers... */
9119
9120 while (TREE_CODE (target) == ARRAY_TYPE)
9121 target = TREE_TYPE (target);
9122
e508bf98 9123 /* Pointers to non-generic address space must be const.
9124 Refuse address spaces outside the device's flash. */
0dff9558 9125
e508bf98 9126 as = TYPE_ADDR_SPACE (target);
0dff9558 9127
e508bf98 9128 if (!ADDR_SPACE_GENERIC_P (as)
9129 && (!TYPE_READONLY (target)
b4e6d2e2 9130 || avr_addrspace[as].segment >= avr_n_flash
9131 /* Also refuse __memx address space if we can't support it. */
9132 || (!AVR_HAVE_LPM && avr_addrspace[as].pointer_size > 2)))
e508bf98 9133 {
9134 return as;
4202ef11 9135 }
9136
9137 /* Scan pointer's target type. */
0dff9558 9138
4202ef11 9139 return avr_nonconst_pointer_addrspace (target);
9140 }
9141
9142 return ADDR_SPACE_GENERIC;
9143}
9144
9145
9d75589a 9146/* Sanity check NODE so that all pointers targeting non-generic address spaces
590da9f2 9147 go along with CONST qualifier. Writing to these address spaces should
4202ef11 9148 be detected and complained about as early as possible. */
9149
9150static bool
9151avr_pgm_check_var_decl (tree node)
9152{
9153 const char *reason = NULL;
0dff9558 9154
4202ef11 9155 addr_space_t as = ADDR_SPACE_GENERIC;
9156
9157 gcc_assert (as == 0);
0dff9558 9158
4202ef11 9159 if (avr_log.progmem)
9160 avr_edump ("%?: %t\n", node);
0dff9558 9161
4202ef11 9162 switch (TREE_CODE (node))
9163 {
9164 default:
9165 break;
9166
9167 case VAR_DECL:
9168 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
9169 reason = "variable";
9170 break;
9171
9172 case PARM_DECL:
9173 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
9174 reason = "function parameter";
9175 break;
0dff9558 9176
4202ef11 9177 case FIELD_DECL:
9178 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
9179 reason = "structure field";
9180 break;
0dff9558 9181
4202ef11 9182 case FUNCTION_DECL:
9183 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (TREE_TYPE (node))),
9184 as)
9185 reason = "return type of function";
9186 break;
9187
9188 case POINTER_TYPE:
9189 if (as = avr_nonconst_pointer_addrspace (node), as)
9190 reason = "pointer";
9191 break;
9192 }
9193
9194 if (reason)
9195 {
c0d7a1d0 9196 if (avr_addrspace[as].segment >= avr_n_flash)
e508bf98 9197 {
9198 if (TYPE_P (node))
9199 error ("%qT uses address space %qs beyond flash of %qs",
9200 node, avr_addrspace[as].name, avr_current_device->name);
9201 else
9202 error ("%s %q+D uses address space %qs beyond flash of %qs",
9203 reason, node, avr_addrspace[as].name,
9204 avr_current_device->name);
9205 }
4202ef11 9206 else
e508bf98 9207 {
9208 if (TYPE_P (node))
9209 error ("pointer targeting address space %qs must be const in %qT",
9210 avr_addrspace[as].name, node);
9211 else
9212 error ("pointer targeting address space %qs must be const"
9213 " in %s %q+D",
9214 avr_addrspace[as].name, reason, node);
9215 }
4202ef11 9216 }
9217
9218 return reason == NULL;
9219}
9220
9221
a179a371 9222/* Add the section attribute if the variable is in progmem. */
9223
7811991d 9224static void
206a5129 9225avr_insert_attributes (tree node, tree *attributes)
a28e4651 9226{
4202ef11 9227 avr_pgm_check_var_decl (node);
9228
a179a371 9229 if (TREE_CODE (node) == VAR_DECL
9230 && (TREE_STATIC (node) || DECL_EXTERNAL (node))
148b2ce0 9231 && avr_progmem_p (node, *attributes))
a28e4651 9232 {
e508bf98 9233 addr_space_t as;
c47985a0 9234 tree node0 = node;
9235
9236 /* For C++, we have to peel arrays in order to get correct
9237 determination of readonlyness. */
0dff9558 9238
c47985a0 9239 do
9240 node0 = TREE_TYPE (node0);
9241 while (TREE_CODE (node0) == ARRAY_TYPE);
9242
9243 if (error_mark_node == node0)
9244 return;
e508bf98 9245
9246 as = TYPE_ADDR_SPACE (TREE_TYPE (node));
9247
c0d7a1d0 9248 if (avr_addrspace[as].segment >= avr_n_flash)
e508bf98 9249 {
9250 error ("variable %q+D located in address space %qs"
9251 " beyond flash of %qs",
9252 node, avr_addrspace[as].name, avr_current_device->name);
9253 }
b4e6d2e2 9254 else if (!AVR_HAVE_LPM && avr_addrspace[as].pointer_size > 2)
9255 {
9256 error ("variable %q+D located in address space %qs"
9257 " which is not supported by %qs",
9258 node, avr_addrspace[as].name, avr_current_arch->arch_name);
9259 }
0dff9558 9260
4202ef11 9261 if (!TYPE_READONLY (node0)
9262 && !TREE_READONLY (node))
cb7c66a8 9263 {
4202ef11 9264 const char *reason = "__attribute__((progmem))";
9265
9266 if (!ADDR_SPACE_GENERIC_P (as))
9d734fa8 9267 reason = avr_addrspace[as].name;
0dff9558 9268
4202ef11 9269 if (avr_log.progmem)
9270 avr_edump ("\n%?: %t\n%t\n", node, node0);
0dff9558 9271
cb7c66a8 9272 error ("variable %q+D must be const in order to be put into"
4202ef11 9273 " read-only section by means of %qs", node, reason);
cb7c66a8 9274 }
a28e4651 9275 }
7b4a38a6 9276}
a28e4651 9277
7c2339f8 9278
9279/* Implement `ASM_OUTPUT_ALIGNED_DECL_LOCAL'. */
9280/* Implement `ASM_OUTPUT_ALIGNED_DECL_COMMON'. */
9281/* Track need of __do_clear_bss. */
9282
9283void
a45076aa 9284avr_asm_output_aligned_decl_common (FILE * stream,
c0d7a1d0 9285 tree decl,
a45076aa 9286 const char *name,
9287 unsigned HOST_WIDE_INT size,
7c2339f8 9288 unsigned int align, bool local_p)
9289{
c0d7a1d0 9290 rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
9291 rtx symbol;
9292
9293 if (mem != NULL_RTX && MEM_P (mem)
9294 && GET_CODE ((symbol = XEXP (mem, 0))) == SYMBOL_REF
9295 && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
9296 {
9297
9298 if (!local_p)
9299 {
9300 fprintf (stream, "\t.globl\t");
9301 assemble_name (stream, name);
9302 fprintf (stream, "\n");
9303 }
9304 if (SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS)
9305 {
9306 assemble_name (stream, name);
9307 fprintf (stream, " = %ld\n",
9308 (long) INTVAL (avr_eval_addr_attrib (symbol)));
9309 }
9310 else if (local_p)
9311 error_at (DECL_SOURCE_LOCATION (decl),
9312 "static IO declaration for %q+D needs an address", decl);
9313 return;
9314 }
9315
5be63f82 9316 /* __gnu_lto_v1 etc. are just markers for the linker injected by toplev.c.
9317 There is no need to trigger __do_clear_bss code for them. */
9318
9319 if (!STR_PREFIX_P (name, "__gnu_lto"))
9320 avr_need_clear_bss_p = true;
7c2339f8 9321
9322 if (local_p)
21440ca3 9323 ASM_OUTPUT_ALIGNED_LOCAL (stream, name, size, align);
9324 else
9325 ASM_OUTPUT_ALIGNED_COMMON (stream, name, size, align);
7c2339f8 9326}
9327
c0d7a1d0 9328void
9329avr_asm_asm_output_aligned_bss (FILE *file, tree decl, const char *name,
9330 unsigned HOST_WIDE_INT size, int align,
9331 void (*default_func)
9332 (FILE *, tree, const char *,
9333 unsigned HOST_WIDE_INT, int))
9334{
9335 rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
9336 rtx symbol;
9337
9338 if (mem != NULL_RTX && MEM_P (mem)
9339 && GET_CODE ((symbol = XEXP (mem, 0))) == SYMBOL_REF
9340 && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
9341 {
9342 if (!(SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS))
9343 error_at (DECL_SOURCE_LOCATION (decl),
9344 "IO definition for %q+D needs an address", decl);
9345 avr_asm_output_aligned_decl_common (file, decl, name, size, align, false);
9346 }
9347 else
9348 default_func (file, decl, name, size, align);
9349}
9350
7c2339f8 9351
9352/* Unnamed section callback for data_section
9353 to track need of __do_copy_data. */
9354
9355static void
9356avr_output_data_section_asm_op (const void *data)
9357{
9358 avr_need_copy_data_p = true;
0dff9558 9359
7c2339f8 9360 /* Dispatch to default. */
9361 output_section_asm_op (data);
9362}
9363
9364
9365/* Unnamed section callback for bss_section
9366 to track need of __do_clear_bss. */
9367
9368static void
9369avr_output_bss_section_asm_op (const void *data)
9370{
9371 avr_need_clear_bss_p = true;
0dff9558 9372
7c2339f8 9373 /* Dispatch to default. */
9374 output_section_asm_op (data);
9375}
9376
9377
5bd39e93 9378/* Unnamed section callback for progmem*.data sections. */
9379
9380static void
9381avr_output_progmem_section_asm_op (const void *data)
9382{
9383 fprintf (asm_out_file, "\t.section\t%s,\"a\",@progbits\n",
9384 (const char*) data);
9385}
9386
9387
7c2339f8 9388/* Implement `TARGET_ASM_INIT_SECTIONS'. */
2f14b1f9 9389
9390static void
9391avr_asm_init_sections (void)
9392{
c3f18f18 9393 /* Set up a section for jump tables. Alignment is handled by
9394 ASM_OUTPUT_BEFORE_CASE_LABEL. */
0dff9558 9395
c3f18f18 9396 if (AVR_HAVE_JMP_CALL)
9397 {
9398 progmem_swtable_section
9399 = get_unnamed_section (0, output_section_asm_op,
9400 "\t.section\t.progmem.gcc_sw_table"
9401 ",\"a\",@progbits");
9402 }
9403 else
9404 {
9405 progmem_swtable_section
9406 = get_unnamed_section (SECTION_CODE, output_section_asm_op,
9407 "\t.section\t.progmem.gcc_sw_table"
9408 ",\"ax\",@progbits");
9409 }
7c2339f8 9410
853000f2 9411 /* Override section callbacks to keep track of `avr_need_clear_bss_p'
9412 resp. `avr_need_copy_data_p'. */
0dff9558 9413
853000f2 9414 readonly_data_section->unnamed.callback = avr_output_data_section_asm_op;
7c2339f8 9415 data_section->unnamed.callback = avr_output_data_section_asm_op;
9416 bss_section->unnamed.callback = avr_output_bss_section_asm_op;
9417}
9418
9419
c3f18f18 9420/* Implement `TARGET_ASM_FUNCTION_RODATA_SECTION'. */
9421
9422static section*
9423avr_asm_function_rodata_section (tree decl)
9424{
9425 /* If a function is unused and optimized out by -ffunction-sections
9426 and --gc-sections, ensure that the same will happen for its jump
9427 tables by putting them into individual sections. */
9428
9429 unsigned int flags;
9430 section * frodata;
9431
9432 /* Get the frodata section from the default function in varasm.c
9433 but treat function-associated data-like jump tables as code
9434 rather than as user defined data. AVR has no constant pools. */
9435 {
9436 int fdata = flag_data_sections;
9437
9438 flag_data_sections = flag_function_sections;
9439 frodata = default_function_rodata_section (decl);
9440 flag_data_sections = fdata;
9441 flags = frodata->common.flags;
9442 }
9443
9444 if (frodata != readonly_data_section
9445 && flags & SECTION_NAMED)
9446 {
9447 /* Adjust section flags and replace section name prefix. */
9448
9449 unsigned int i;
9450
9451 static const char* const prefix[] =
9452 {
9453 ".rodata", ".progmem.gcc_sw_table",
9454 ".gnu.linkonce.r.", ".gnu.linkonce.t."
9455 };
9456
9457 for (i = 0; i < sizeof (prefix) / sizeof (*prefix); i += 2)
9458 {
9459 const char * old_prefix = prefix[i];
9460 const char * new_prefix = prefix[i+1];
9461 const char * name = frodata->named.name;
9462
9463 if (STR_PREFIX_P (name, old_prefix))
9464 {
1b6c82cc 9465 const char *rname = ACONCAT ((new_prefix,
9466 name + strlen (old_prefix), NULL));
c3f18f18 9467 flags &= ~SECTION_CODE;
9468 flags |= AVR_HAVE_JMP_CALL ? 0 : SECTION_CODE;
0dff9558 9469
c3f18f18 9470 return get_section (rname, flags, frodata->named.decl);
9471 }
9472 }
9473 }
0dff9558 9474
c3f18f18 9475 return progmem_swtable_section;
9476}
9477
9478
7c2339f8 9479/* Implement `TARGET_ASM_NAMED_SECTION'. */
9480/* Track need of __do_clear_bss, __do_copy_data for named sections. */
9481
853000f2 9482static void
7c2339f8 9483avr_asm_named_section (const char *name, unsigned int flags, tree decl)
9484{
bf412f98 9485 if (flags & AVR_SECTION_PROGMEM)
9486 {
9d734fa8 9487 addr_space_t as = (flags & AVR_SECTION_PROGMEM) / SECTION_MACH_DEP;
bf412f98 9488 const char *old_prefix = ".rodata";
0558f5da 9489 const char *new_prefix = avr_addrspace[as].section_name;
9490
bf412f98 9491 if (STR_PREFIX_P (name, old_prefix))
9492 {
1b6c82cc 9493 const char *sname = ACONCAT ((new_prefix,
9494 name + strlen (old_prefix), NULL));
9495 default_elf_asm_named_section (sname, flags, decl);
9496 return;
bf412f98 9497 }
9498
1b6c82cc 9499 default_elf_asm_named_section (new_prefix, flags, decl);
bf412f98 9500 return;
9501 }
0dff9558 9502
7c2339f8 9503 if (!avr_need_copy_data_p)
53026b2c 9504 avr_need_copy_data_p = (STR_PREFIX_P (name, ".data")
9505 || STR_PREFIX_P (name, ".rodata")
9506 || STR_PREFIX_P (name, ".gnu.linkonce.d"));
0dff9558 9507
7c2339f8 9508 if (!avr_need_clear_bss_p)
53026b2c 9509 avr_need_clear_bss_p = STR_PREFIX_P (name, ".bss");
0dff9558 9510
7c2339f8 9511 default_elf_asm_named_section (name, flags, decl);
2f14b1f9 9512}
9513
0dff9558 9514
9515/* Implement `TARGET_SECTION_TYPE_FLAGS'. */
9516
8a46ca38 9517static unsigned int
206a5129 9518avr_section_type_flags (tree decl, const char *name, int reloc)
8a46ca38 9519{
9520 unsigned int flags = default_section_type_flags (decl, name, reloc);
9521
53026b2c 9522 if (STR_PREFIX_P (name, ".noinit"))
8a46ca38 9523 {
9524 if (decl && TREE_CODE (decl) == VAR_DECL
9525 && DECL_INITIAL (decl) == NULL_TREE)
9526 flags |= SECTION_BSS; /* @nobits */
9527 else
c3ceba8e 9528 warning (0, "only uninitialized variables can be placed in the "
8a46ca38 9529 ".noinit section");
9530 }
9531
bf412f98 9532 if (decl && DECL_P (decl)
9d734fa8 9533 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
bf412f98 9534 {
9d734fa8 9535 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
9536
9537 /* Attribute progmem puts data in generic address space.
590da9f2 9538 Set section flags as if it was in __flash to get the right
9d734fa8 9539 section prefix in the remainder. */
5bd39e93 9540
9d734fa8 9541 if (ADDR_SPACE_GENERIC_P (as))
590da9f2 9542 as = ADDR_SPACE_FLASH;
5bd39e93 9543
9d734fa8 9544 flags |= as * SECTION_MACH_DEP;
bf412f98 9545 flags &= ~SECTION_WRITE;
4202ef11 9546 flags &= ~SECTION_BSS;
bf412f98 9547 }
0dff9558 9548
8a46ca38 9549 return flags;
9550}
9551
7c2339f8 9552
b44e24e6 9553/* Implement `TARGET_ENCODE_SECTION_INFO'. */
9554
9555static void
9d734fa8 9556avr_encode_section_info (tree decl, rtx rtl, int new_decl_p)
b44e24e6 9557{
9558 /* In avr_handle_progmem_attribute, DECL_INITIAL is not yet
9559 readily available, see PR34734. So we postpone the warning
9560 about uninitialized data in program memory section until here. */
0dff9558 9561
b44e24e6 9562 if (new_decl_p
9563 && decl && DECL_P (decl)
9564 && NULL_TREE == DECL_INITIAL (decl)
07b2ccdc 9565 && !DECL_EXTERNAL (decl)
b44e24e6 9566 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
9567 {
9568 warning (OPT_Wuninitialized,
9569 "uninitialized variable %q+D put into "
9570 "program memory area", decl);
9571 }
66824cc3 9572
9573 default_encode_section_info (decl, rtl, new_decl_p);
ed2541ea 9574
9575 if (decl && DECL_P (decl)
9576 && TREE_CODE (decl) != FUNCTION_DECL
9577 && MEM_P (rtl)
9578 && SYMBOL_REF == GET_CODE (XEXP (rtl, 0)))
9579 {
9580 rtx sym = XEXP (rtl, 0);
b8f9423d 9581 tree type = TREE_TYPE (decl);
c0d7a1d0 9582 tree attr = DECL_ATTRIBUTES (decl);
b8f9423d 9583 if (type == error_mark_node)
9584 return;
c0d7a1d0 9585
b8f9423d 9586 addr_space_t as = TYPE_ADDR_SPACE (type);
ed2541ea 9587
9588 /* PSTR strings are in generic space but located in flash:
9589 patch address space. */
0dff9558 9590
c0d7a1d0 9591 if (-1 == avr_progmem_p (decl, attr))
590da9f2 9592 as = ADDR_SPACE_FLASH;
ed2541ea 9593
9594 AVR_SYMBOL_SET_ADDR_SPACE (sym, as);
c0d7a1d0 9595
9596 tree io_low_attr = lookup_attribute ("io_low", attr);
9597 tree io_attr = lookup_attribute ("io", attr);
9598 tree addr_attr;
9599 if (io_low_attr
9600 && TREE_VALUE (io_low_attr) && TREE_VALUE (TREE_VALUE (io_low_attr)))
9601 addr_attr = io_attr;
9602 else if (io_attr
9603 && TREE_VALUE (io_attr) && TREE_VALUE (TREE_VALUE (io_attr)))
9604 addr_attr = io_attr;
9605 else
9606 addr_attr = lookup_attribute ("address", attr);
9607 if (io_low_attr
1a96adb9 9608 || (io_attr && addr_attr
9609 && low_io_address_operand
9610 (GEN_INT (TREE_INT_CST_LOW
9611 (TREE_VALUE (TREE_VALUE (addr_attr)))), QImode)))
c0d7a1d0 9612 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO_LOW;
9613 if (io_attr || io_low_attr)
9614 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO;
9615 /* If we have an (io) address attribute specification, but the variable
9616 is external, treat the address as only a tentative definition
9617 to be used to determine if an io port is in the lower range, but
9618 don't use the exact value for constant propagation. */
9619 if (addr_attr && !DECL_EXTERNAL (decl))
9620 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_ADDRESS;
ed2541ea 9621 }
b44e24e6 9622}
9623
9624
bf412f98 9625/* Implement `TARGET_ASM_SELECT_SECTION' */
9626
9627static section *
9628avr_asm_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
9629{
9630 section * sect = default_elf_select_section (decl, reloc, align);
0dff9558 9631
bf412f98 9632 if (decl && DECL_P (decl)
9d734fa8 9633 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
bf412f98 9634 {
9d734fa8 9635 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
0558f5da 9636
9637 /* __progmem__ goes in generic space but shall be allocated to
9638 .progmem.data */
9639
9640 if (ADDR_SPACE_GENERIC_P (as))
9641 as = ADDR_SPACE_FLASH;
0dff9558 9642
bf412f98 9643 if (sect->common.flags & SECTION_NAMED)
9644 {
9645 const char * name = sect->named.name;
9646 const char * old_prefix = ".rodata";
0558f5da 9647 const char * new_prefix = avr_addrspace[as].section_name;
bf412f98 9648
9649 if (STR_PREFIX_P (name, old_prefix))
9650 {
1b6c82cc 9651 const char *sname = ACONCAT ((new_prefix,
9652 name + strlen (old_prefix), NULL));
bf412f98 9653 return get_section (sname, sect->common.flags, sect->named.decl);
9654 }
9655 }
0558f5da 9656
9657 if (!progmem_section[as])
9658 {
9659 progmem_section[as]
9660 = get_unnamed_section (0, avr_output_progmem_section_asm_op,
9661 avr_addrspace[as].section_name);
9662 }
9663
9664 return progmem_section[as];
bf412f98 9665 }
9666
9667 return sect;
9668}
9669
7c2339f8 9670/* Implement `TARGET_ASM_FILE_START'. */
5bd39e93 9671/* Outputs some text at the start of each assembler file. */
a28e4651 9672
92c473b8 9673static void
206a5129 9674avr_file_start (void)
a28e4651 9675{
644ac9c5 9676 int sfr_offset = avr_current_arch->sfr_offset;
5bd39e93 9677
b2afd900 9678 if (avr_current_arch->asm_only)
c1535dd2 9679 error ("MCU %qs supported for assembler only", avr_current_device->name);
235d7594 9680
92c473b8 9681 default_file_start ();
9682
72851b68 9683 /* Print I/O addresses of some SFRs used with IN and OUT. */
9684
d32d7e3a 9685 if (AVR_HAVE_SPH)
72851b68 9686 fprintf (asm_out_file, "__SP_H__ = 0x%02x\n", avr_addr.sp_h - sfr_offset);
8c8193e1 9687
72851b68 9688 fprintf (asm_out_file, "__SP_L__ = 0x%02x\n", avr_addr.sp_l - sfr_offset);
9689 fprintf (asm_out_file, "__SREG__ = 0x%02x\n", avr_addr.sreg - sfr_offset);
0b6cf66f 9690 if (AVR_HAVE_RAMPZ)
9691 fprintf (asm_out_file, "__RAMPZ__ = 0x%02x\n", avr_addr.rampz - sfr_offset);
9692 if (AVR_HAVE_RAMPY)
9693 fprintf (asm_out_file, "__RAMPY__ = 0x%02x\n", avr_addr.rampy - sfr_offset);
9694 if (AVR_HAVE_RAMPX)
9695 fprintf (asm_out_file, "__RAMPX__ = 0x%02x\n", avr_addr.rampx - sfr_offset);
9696 if (AVR_HAVE_RAMPD)
9697 fprintf (asm_out_file, "__RAMPD__ = 0x%02x\n", avr_addr.rampd - sfr_offset);
b4e6d2e2 9698 if (AVR_XMEGA || AVR_TINY)
0b6cf66f 9699 fprintf (asm_out_file, "__CCP__ = 0x%02x\n", avr_addr.ccp - sfr_offset);
b4e6d2e2 9700 fprintf (asm_out_file, "__tmp_reg__ = %d\n", AVR_TMP_REGNO);
9701 fprintf (asm_out_file, "__zero_reg__ = %d\n", AVR_ZERO_REGNO);
a28e4651 9702}
9703
7c2339f8 9704
9705/* Implement `TARGET_ASM_FILE_END'. */
a28e4651 9706/* Outputs to the stdio stream FILE some
9707 appropriate text to go at the end of an assembler file. */
9708
f6940372 9709static void
206a5129 9710avr_file_end (void)
a28e4651 9711{
7c2339f8 9712 /* Output these only if there is anything in the
0dff9558 9713 .data* / .rodata* / .gnu.linkonce.* resp. .bss* or COMMON
7c2339f8 9714 input section(s) - some code size can be saved by not
9715 linking in the initialization code from libgcc if resp.
0dff9558 9716 sections are empty, see PR18145. */
7c2339f8 9717
9718 if (avr_need_copy_data_p)
9719 fputs (".global __do_copy_data\n", asm_out_file);
9720
9721 if (avr_need_clear_bss_p)
9722 fputs (".global __do_clear_bss\n", asm_out_file);
a28e4651 9723}
9724
0dff9558 9725
9726/* Worker function for `ADJUST_REG_ALLOC_ORDER'. */
a28e4651 9727/* Choose the order in which to allocate hard registers for
9728 pseudo-registers local to a basic block.
9729
9730 Store the desired register order in the array `reg_alloc_order'.
9731 Element 0 should be the register to allocate first; element 1, the
9732 next register; and so on. */
9733
9734void
0dff9558 9735avr_adjust_reg_alloc_order (void)
a28e4651 9736{
9737 unsigned int i;
0dff9558 9738 static const int order_0[] =
9739 {
9740 24, 25,
9741 18, 19, 20, 21, 22, 23,
9742 30, 31,
9743 26, 27, 28, 29,
9744 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
9745 0, 1,
9746 32, 33, 34, 35
a28e4651 9747 };
b4e6d2e2 9748 static const int tiny_order_0[] = {
9749 20, 21,
9750 22, 23,
9751 24, 25,
9752 30, 31,
9753 26, 27,
9754 28, 29,
9755 19, 18,
9756 16, 17,
9757 32, 33, 34, 35,
9758 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
9759 };
0dff9558 9760 static const int order_1[] =
9761 {
9762 18, 19, 20, 21, 22, 23, 24, 25,
9763 30, 31,
9764 26, 27, 28, 29,
9765 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
9766 0, 1,
9767 32, 33, 34, 35
a28e4651 9768 };
b4e6d2e2 9769 static const int tiny_order_1[] = {
9770 22, 23,
9771 24, 25,
9772 30, 31,
9773 26, 27,
9774 28, 29,
9775 21, 20, 19, 18,
9776 16, 17,
9777 32, 33, 34, 35,
9778 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
9779 };
0dff9558 9780 static const int order_2[] =
9781 {
9782 25, 24, 23, 22, 21, 20, 19, 18,
9783 30, 31,
9784 26, 27, 28, 29,
9785 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
9786 1, 0,
9787 32, 33, 34, 35
a28e4651 9788 };
0dff9558 9789
1a96adb9 9790 /* Select specific register allocation order.
9791 Tiny Core (ATtiny4/5/9/10/20/40) devices have only 16 registers,
9792 so different allocation order should be used. */
9793
9794 const int *order = (TARGET_ORDER_1 ? (AVR_TINY ? tiny_order_1 : order_1)
9795 : TARGET_ORDER_2 ? (AVR_TINY ? tiny_order_0 : order_2)
9796 : (AVR_TINY ? tiny_order_0 : order_0));
b4e6d2e2 9797
0dff9558 9798 for (i = 0; i < ARRAY_SIZE (order_0); ++i)
a28e4651 9799 reg_alloc_order[i] = order[i];
9800}
9801
433a5f02 9802
dfc1e3e4 9803/* Implement `TARGET_REGISTER_MOVE_COST' */
9804
9805static int
3754d046 9806avr_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
dfc1e3e4 9807 reg_class_t from, reg_class_t to)
9808{
9809 return (from == STACK_REG ? 6
9810 : to == STACK_REG ? 12
9811 : 2);
9812}
9813
9814
9815/* Implement `TARGET_MEMORY_MOVE_COST' */
9816
9817static int
3754d046 9818avr_memory_move_cost (machine_mode mode,
a45076aa 9819 reg_class_t rclass ATTRIBUTE_UNUSED,
dfc1e3e4 9820 bool in ATTRIBUTE_UNUSED)
9821{
9822 return (mode == QImode ? 2
9823 : mode == HImode ? 4
9824 : mode == SImode ? 8
9825 : mode == SFmode ? 8
9826 : 16);
9827}
9828
9829
433a5f02 9830/* Mutually recursive subroutine of avr_rtx_cost for calculating the
9831 cost of an RTX operand given its context. X is the rtx of the
9832 operand, MODE is its mode, and OUTER is the rtx_code of this
9833 operand's parent operator. */
a28e4651 9834
fab7adbf 9835static int
3754d046 9836avr_operand_rtx_cost (rtx x, machine_mode mode, enum rtx_code outer,
20d892d1 9837 int opno, bool speed)
a28e4651 9838{
433a5f02 9839 enum rtx_code code = GET_CODE (x);
9840 int total;
9841
a28e4651 9842 switch (code)
9843 {
433a5f02 9844 case REG:
9845 case SUBREG:
9846 return 0;
9847
a28e4651 9848 case CONST_INT:
017c5b98 9849 case CONST_FIXED:
433a5f02 9850 case CONST_DOUBLE:
9851 return COSTS_N_INSNS (GET_MODE_SIZE (mode));
9852
a28e4651 9853 default:
9854 break;
9855 }
433a5f02 9856
9857 total = 0;
20d892d1 9858 avr_rtx_costs (x, code, outer, opno, &total, speed);
433a5f02 9859 return total;
a28e4651 9860}
9861
ae86bb47 9862/* Worker function for AVR backend's rtx_cost function.
9863 X is rtx expression whose cost is to be calculated.
9864 Return true if the complete cost has been computed.
9865 Return false if subexpressions should be scanned.
9866 In either case, *TOTAL contains the cost result. */
433a5f02 9867
fab7adbf 9868static bool
ae86bb47 9869avr_rtx_costs_1 (rtx x, int codearg, int outer_code ATTRIBUTE_UNUSED,
9870 int opno ATTRIBUTE_UNUSED, int *total, bool speed)
fab7adbf 9871{
ef51d1e3 9872 enum rtx_code code = (enum rtx_code) codearg;
3754d046 9873 machine_mode mode = GET_MODE (x);
433a5f02 9874 HOST_WIDE_INT val;
fab7adbf 9875
9876 switch (code)
9877 {
9878 case CONST_INT:
017c5b98 9879 case CONST_FIXED:
433a5f02 9880 case CONST_DOUBLE:
9685fb69 9881 case SYMBOL_REF:
f9fb96f9 9882 case CONST:
9883 case LABEL_REF:
433a5f02 9884 /* Immediate constants are as cheap as registers. */
9885 *total = 0;
9886 return true;
9887
9888 case MEM:
433a5f02 9889 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
9890 return true;
9891
9892 case NEG:
9893 switch (mode)
fab7adbf 9894 {
433a5f02 9895 case QImode:
9896 case SFmode:
9897 *total = COSTS_N_INSNS (1);
9898 break;
9899
02d9a2c3 9900 case HImode:
9901 case PSImode:
9902 case SImode:
9903 *total = COSTS_N_INSNS (2 * GET_MODE_SIZE (mode) - 1);
9904 break;
433a5f02 9905
9906 default:
9907 return false;
fab7adbf 9908 }
20d892d1 9909 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
433a5f02 9910 return true;
9911
9912 case ABS:
9913 switch (mode)
fab7adbf 9914 {
433a5f02 9915 case QImode:
9916 case SFmode:
9917 *total = COSTS_N_INSNS (1);
9918 break;
9919
9920 default:
9921 return false;
fab7adbf 9922 }
20d892d1 9923 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
433a5f02 9924 return true;
fab7adbf 9925
433a5f02 9926 case NOT:
9927 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
20d892d1 9928 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
fab7adbf 9929 return true;
9930
433a5f02 9931 case ZERO_EXTEND:
9932 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
9933 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
20d892d1 9934 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
433a5f02 9935 return true;
9936
9937 case SIGN_EXTEND:
9938 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
9939 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
20d892d1 9940 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
433a5f02 9941 return true;
9942
9943 case PLUS:
9944 switch (mode)
9945 {
9946 case QImode:
37ee98f3 9947 if (AVR_HAVE_MUL
9948 && MULT == GET_CODE (XEXP (x, 0))
9949 && register_operand (XEXP (x, 1), QImode))
9950 {
9951 /* multiply-add */
9952 *total = COSTS_N_INSNS (speed ? 4 : 3);
9953 /* multiply-add with constant: will be split and load constant. */
9954 if (CONST_INT_P (XEXP (XEXP (x, 0), 1)))
9955 *total = COSTS_N_INSNS (1) + *total;
9956 return true;
9957 }
433a5f02 9958 *total = COSTS_N_INSNS (1);
9959 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
20d892d1 9960 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
433a5f02 9961 break;
9962
9963 case HImode:
73cd2c42 9964 if (AVR_HAVE_MUL
9965 && (MULT == GET_CODE (XEXP (x, 0))
9966 || ASHIFT == GET_CODE (XEXP (x, 0)))
9967 && register_operand (XEXP (x, 1), HImode)
9968 && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))
9969 || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))))
9970 {
37ee98f3 9971 /* multiply-add */
73cd2c42 9972 *total = COSTS_N_INSNS (speed ? 5 : 4);
37ee98f3 9973 /* multiply-add with constant: will be split and load constant. */
9974 if (CONST_INT_P (XEXP (XEXP (x, 0), 1)))
9975 *total = COSTS_N_INSNS (1) + *total;
73cd2c42 9976 return true;
9977 }
433a5f02 9978 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
9979 {
9980 *total = COSTS_N_INSNS (2);
20d892d1 9981 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
9982 speed);
433a5f02 9983 }
9984 else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
9985 *total = COSTS_N_INSNS (1);
9986 else
9987 *total = COSTS_N_INSNS (2);
9988 break;
9989
02d9a2c3 9990 case PSImode:
9991 if (!CONST_INT_P (XEXP (x, 1)))
9992 {
9993 *total = COSTS_N_INSNS (3);
9994 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
9995 speed);
9996 }
9997 else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
9998 *total = COSTS_N_INSNS (2);
9999 else
10000 *total = COSTS_N_INSNS (3);
10001 break;
10002
433a5f02 10003 case SImode:
10004 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10005 {
10006 *total = COSTS_N_INSNS (4);
20d892d1 10007 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10008 speed);
433a5f02 10009 }
10010 else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
10011 *total = COSTS_N_INSNS (1);
10012 else
10013 *total = COSTS_N_INSNS (4);
10014 break;
10015
10016 default:
10017 return false;
10018 }
20d892d1 10019 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
433a5f02 10020 return true;
10021
10022 case MINUS:
37ee98f3 10023 if (AVR_HAVE_MUL
10024 && QImode == mode
10025 && register_operand (XEXP (x, 0), QImode)
10026 && MULT == GET_CODE (XEXP (x, 1)))
10027 {
10028 /* multiply-sub */
10029 *total = COSTS_N_INSNS (speed ? 4 : 3);
10030 /* multiply-sub with constant: will be split and load constant. */
10031 if (CONST_INT_P (XEXP (XEXP (x, 1), 1)))
10032 *total = COSTS_N_INSNS (1) + *total;
10033 return true;
10034 }
73cd2c42 10035 if (AVR_HAVE_MUL
10036 && HImode == mode
10037 && register_operand (XEXP (x, 0), HImode)
10038 && (MULT == GET_CODE (XEXP (x, 1))
10039 || ASHIFT == GET_CODE (XEXP (x, 1)))
10040 && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))
10041 || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))))
10042 {
37ee98f3 10043 /* multiply-sub */
73cd2c42 10044 *total = COSTS_N_INSNS (speed ? 5 : 4);
37ee98f3 10045 /* multiply-sub with constant: will be split and load constant. */
10046 if (CONST_INT_P (XEXP (XEXP (x, 1), 1)))
10047 *total = COSTS_N_INSNS (1) + *total;
73cd2c42 10048 return true;
10049 }
02d9a2c3 10050 /* FALLTHRU */
433a5f02 10051 case AND:
10052 case IOR:
10053 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
20d892d1 10054 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
433a5f02 10055 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
20d892d1 10056 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
433a5f02 10057 return true;
10058
10059 case XOR:
10060 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
20d892d1 10061 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10062 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
433a5f02 10063 return true;
10064
10065 case MULT:
10066 switch (mode)
10067 {
10068 case QImode:
8cc5a1af 10069 if (AVR_HAVE_MUL)
f529eb25 10070 *total = COSTS_N_INSNS (!speed ? 3 : 4);
10071 else if (!speed)
4f0e2214 10072 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
433a5f02 10073 else
10074 return false;
ba92127f 10075 break;
433a5f02 10076
10077 case HImode:
8cc5a1af 10078 if (AVR_HAVE_MUL)
0b90fc76 10079 {
10080 rtx op0 = XEXP (x, 0);
10081 rtx op1 = XEXP (x, 1);
10082 enum rtx_code code0 = GET_CODE (op0);
10083 enum rtx_code code1 = GET_CODE (op1);
10084 bool ex0 = SIGN_EXTEND == code0 || ZERO_EXTEND == code0;
10085 bool ex1 = SIGN_EXTEND == code1 || ZERO_EXTEND == code1;
10086
10087 if (ex0
10088 && (u8_operand (op1, HImode)
10089 || s8_operand (op1, HImode)))
10090 {
10091 *total = COSTS_N_INSNS (!speed ? 4 : 6);
10092 return true;
10093 }
10094 if (ex0
10095 && register_operand (op1, HImode))
10096 {
10097 *total = COSTS_N_INSNS (!speed ? 5 : 8);
10098 return true;
10099 }
10100 else if (ex0 || ex1)
10101 {
10102 *total = COSTS_N_INSNS (!speed ? 3 : 5);
10103 return true;
10104 }
10105 else if (register_operand (op0, HImode)
10106 && (u8_operand (op1, HImode)
10107 || s8_operand (op1, HImode)))
10108 {
10109 *total = COSTS_N_INSNS (!speed ? 6 : 9);
10110 return true;
10111 }
10112 else
10113 *total = COSTS_N_INSNS (!speed ? 7 : 10);
10114 }
f529eb25 10115 else if (!speed)
4f0e2214 10116 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
433a5f02 10117 else
10118 return false;
ba92127f 10119 break;
433a5f02 10120
02d9a2c3 10121 case PSImode:
10122 if (!speed)
10123 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
10124 else
10125 *total = 10;
10126 break;
10127
713e2ad9 10128 case SImode:
10129 if (AVR_HAVE_MUL)
10130 {
10131 if (!speed)
10132 {
10133 /* Add some additional costs besides CALL like moves etc. */
10134
10135 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
10136 }
10137 else
10138 {
10139 /* Just a rough estimate. Even with -O2 we don't want bulky
10140 code expanded inline. */
10141
10142 *total = COSTS_N_INSNS (25);
10143 }
10144 }
10145 else
10146 {
10147 if (speed)
10148 *total = COSTS_N_INSNS (300);
10149 else
10150 /* Add some additional costs besides CALL like moves etc. */
10151 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
10152 }
0dff9558 10153
713e2ad9 10154 return true;
0dff9558 10155
433a5f02 10156 default:
10157 return false;
10158 }
20d892d1 10159 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10160 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
433a5f02 10161 return true;
10162
10163 case DIV:
10164 case MOD:
10165 case UDIV:
10166 case UMOD:
f529eb25 10167 if (!speed)
fd2db4d6 10168 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
433a5f02 10169 else
fd2db4d6 10170 *total = COSTS_N_INSNS (15 * GET_MODE_SIZE (mode));
20d892d1 10171 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
fd2db4d6 10172 /* For div/mod with const-int divisor we have at least the cost of
10173 loading the divisor. */
10174 if (CONST_INT_P (XEXP (x, 1)))
10175 *total += COSTS_N_INSNS (GET_MODE_SIZE (mode));
10176 /* Add some overall penaly for clobbering and moving around registers */
10177 *total += COSTS_N_INSNS (2);
433a5f02 10178 return true;
10179
8f14d2e0 10180 case ROTATE:
10181 switch (mode)
10182 {
10183 case QImode:
10184 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 4)
10185 *total = COSTS_N_INSNS (1);
10186
10187 break;
10188
10189 case HImode:
10190 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 8)
10191 *total = COSTS_N_INSNS (3);
10192
10193 break;
10194
10195 case SImode:
10196 if (CONST_INT_P (XEXP (x, 1)))
10197 switch (INTVAL (XEXP (x, 1)))
10198 {
10199 case 8:
10200 case 24:
10201 *total = COSTS_N_INSNS (5);
10202 break;
10203 case 16:
10204 *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 6);
10205 break;
10206 }
10207 break;
10208
10209 default:
10210 return false;
10211 }
20d892d1 10212 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
0dff9558 10213 return true;
8f14d2e0 10214
433a5f02 10215 case ASHIFT:
10216 switch (mode)
10217 {
10218 case QImode:
10219 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10220 {
f529eb25 10221 *total = COSTS_N_INSNS (!speed ? 4 : 17);
20d892d1 10222 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10223 speed);
433a5f02 10224 }
10225 else
10226 {
10227 val = INTVAL (XEXP (x, 1));
10228 if (val == 7)
10229 *total = COSTS_N_INSNS (3);
10230 else if (val >= 0 && val <= 7)
10231 *total = COSTS_N_INSNS (val);
10232 else
10233 *total = COSTS_N_INSNS (1);
10234 }
10235 break;
10236
10237 case HImode:
0b90fc76 10238 if (AVR_HAVE_MUL)
10239 {
10240 if (const_2_to_7_operand (XEXP (x, 1), HImode)
10241 && (SIGN_EXTEND == GET_CODE (XEXP (x, 0))
10242 || ZERO_EXTEND == GET_CODE (XEXP (x, 0))))
10243 {
10244 *total = COSTS_N_INSNS (!speed ? 4 : 6);
10245 return true;
10246 }
10247 }
0dff9558 10248
37ee98f3 10249 if (const1_rtx == (XEXP (x, 1))
10250 && SIGN_EXTEND == GET_CODE (XEXP (x, 0)))
10251 {
10252 *total = COSTS_N_INSNS (2);
10253 return true;
10254 }
0dff9558 10255
433a5f02 10256 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10257 {
f529eb25 10258 *total = COSTS_N_INSNS (!speed ? 5 : 41);
20d892d1 10259 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10260 speed);
433a5f02 10261 }
10262 else
10263 switch (INTVAL (XEXP (x, 1)))
10264 {
10265 case 0:
10266 *total = 0;
10267 break;
10268 case 1:
10269 case 8:
10270 *total = COSTS_N_INSNS (2);
10271 break;
10272 case 9:
10273 *total = COSTS_N_INSNS (3);
10274 break;
10275 case 2:
10276 case 3:
10277 case 10:
10278 case 15:
10279 *total = COSTS_N_INSNS (4);
10280 break;
10281 case 7:
10282 case 11:
10283 case 12:
10284 *total = COSTS_N_INSNS (5);
10285 break;
10286 case 4:
f529eb25 10287 *total = COSTS_N_INSNS (!speed ? 5 : 8);
433a5f02 10288 break;
10289 case 6:
12564c56 10290 *total = COSTS_N_INSNS (!speed ? 5 : 9);
433a5f02 10291 break;
10292 case 5:
f529eb25 10293 *total = COSTS_N_INSNS (!speed ? 5 : 10);
433a5f02 10294 break;
10295 default:
f529eb25 10296 *total = COSTS_N_INSNS (!speed ? 5 : 41);
20d892d1 10297 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10298 speed);
433a5f02 10299 }
10300 break;
10301
02d9a2c3 10302 case PSImode:
10303 if (!CONST_INT_P (XEXP (x, 1)))
10304 {
10305 *total = COSTS_N_INSNS (!speed ? 6 : 73);
10306 }
10307 else
10308 switch (INTVAL (XEXP (x, 1)))
10309 {
10310 case 0:
10311 *total = 0;
10312 break;
10313 case 1:
10314 case 8:
10315 case 16:
10316 *total = COSTS_N_INSNS (3);
10317 break;
10318 case 23:
10319 *total = COSTS_N_INSNS (5);
10320 break;
10321 default:
10322 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
10323 break;
10324 }
10325 break;
10326
433a5f02 10327 case SImode:
10328 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10329 {
f529eb25 10330 *total = COSTS_N_INSNS (!speed ? 7 : 113);
20d892d1 10331 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10332 speed);
433a5f02 10333 }
10334 else
10335 switch (INTVAL (XEXP (x, 1)))
10336 {
10337 case 0:
10338 *total = 0;
10339 break;
10340 case 24:
10341 *total = COSTS_N_INSNS (3);
10342 break;
10343 case 1:
10344 case 8:
10345 case 16:
10346 *total = COSTS_N_INSNS (4);
10347 break;
10348 case 31:
10349 *total = COSTS_N_INSNS (6);
10350 break;
10351 case 2:
f529eb25 10352 *total = COSTS_N_INSNS (!speed ? 7 : 8);
433a5f02 10353 break;
10354 default:
f529eb25 10355 *total = COSTS_N_INSNS (!speed ? 7 : 113);
20d892d1 10356 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10357 speed);
433a5f02 10358 }
10359 break;
10360
10361 default:
10362 return false;
10363 }
20d892d1 10364 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
433a5f02 10365 return true;
10366
10367 case ASHIFTRT:
10368 switch (mode)
10369 {
10370 case QImode:
10371 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10372 {
f529eb25 10373 *total = COSTS_N_INSNS (!speed ? 4 : 17);
20d892d1 10374 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10375 speed);
433a5f02 10376 }
10377 else
10378 {
10379 val = INTVAL (XEXP (x, 1));
10380 if (val == 6)
10381 *total = COSTS_N_INSNS (4);
10382 else if (val == 7)
10383 *total = COSTS_N_INSNS (2);
10384 else if (val >= 0 && val <= 7)
10385 *total = COSTS_N_INSNS (val);
10386 else
10387 *total = COSTS_N_INSNS (1);
10388 }
10389 break;
10390
10391 case HImode:
10392 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10393 {
f529eb25 10394 *total = COSTS_N_INSNS (!speed ? 5 : 41);
20d892d1 10395 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10396 speed);
433a5f02 10397 }
10398 else
10399 switch (INTVAL (XEXP (x, 1)))
10400 {
10401 case 0:
10402 *total = 0;
10403 break;
10404 case 1:
10405 *total = COSTS_N_INSNS (2);
10406 break;
10407 case 15:
10408 *total = COSTS_N_INSNS (3);
10409 break;
10410 case 2:
10411 case 7:
10412 case 8:
10413 case 9:
10414 *total = COSTS_N_INSNS (4);
10415 break;
10416 case 10:
10417 case 14:
10418 *total = COSTS_N_INSNS (5);
10419 break;
10420 case 11:
f529eb25 10421 *total = COSTS_N_INSNS (!speed ? 5 : 6);
433a5f02 10422 break;
10423 case 12:
f529eb25 10424 *total = COSTS_N_INSNS (!speed ? 5 : 7);
433a5f02 10425 break;
10426 case 6:
10427 case 13:
f529eb25 10428 *total = COSTS_N_INSNS (!speed ? 5 : 8);
433a5f02 10429 break;
10430 default:
f529eb25 10431 *total = COSTS_N_INSNS (!speed ? 5 : 41);
20d892d1 10432 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10433 speed);
433a5f02 10434 }
10435 break;
10436
02d9a2c3 10437 case PSImode:
10438 if (!CONST_INT_P (XEXP (x, 1)))
10439 {
10440 *total = COSTS_N_INSNS (!speed ? 6 : 73);
10441 }
10442 else
10443 switch (INTVAL (XEXP (x, 1)))
10444 {
10445 case 0:
10446 *total = 0;
10447 break;
10448 case 1:
10449 *total = COSTS_N_INSNS (3);
10450 break;
10451 case 16:
10452 case 8:
10453 *total = COSTS_N_INSNS (5);
10454 break;
10455 case 23:
10456 *total = COSTS_N_INSNS (4);
10457 break;
10458 default:
10459 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
10460 break;
10461 }
10462 break;
10463
433a5f02 10464 case SImode:
10465 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10466 {
f529eb25 10467 *total = COSTS_N_INSNS (!speed ? 7 : 113);
20d892d1 10468 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10469 speed);
433a5f02 10470 }
10471 else
10472 switch (INTVAL (XEXP (x, 1)))
10473 {
10474 case 0:
10475 *total = 0;
10476 break;
10477 case 1:
10478 *total = COSTS_N_INSNS (4);
10479 break;
10480 case 8:
10481 case 16:
10482 case 24:
10483 *total = COSTS_N_INSNS (6);
10484 break;
10485 case 2:
f529eb25 10486 *total = COSTS_N_INSNS (!speed ? 7 : 8);
433a5f02 10487 break;
10488 case 31:
0aab73c2 10489 *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 5);
433a5f02 10490 break;
10491 default:
f529eb25 10492 *total = COSTS_N_INSNS (!speed ? 7 : 113);
20d892d1 10493 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10494 speed);
433a5f02 10495 }
10496 break;
10497
10498 default:
10499 return false;
10500 }
20d892d1 10501 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
433a5f02 10502 return true;
10503
10504 case LSHIFTRT:
10505 switch (mode)
10506 {
10507 case QImode:
10508 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10509 {
f529eb25 10510 *total = COSTS_N_INSNS (!speed ? 4 : 17);
20d892d1 10511 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10512 speed);
433a5f02 10513 }
10514 else
10515 {
10516 val = INTVAL (XEXP (x, 1));
10517 if (val == 7)
10518 *total = COSTS_N_INSNS (3);
10519 else if (val >= 0 && val <= 7)
10520 *total = COSTS_N_INSNS (val);
10521 else
10522 *total = COSTS_N_INSNS (1);
10523 }
10524 break;
10525
10526 case HImode:
10527 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10528 {
f529eb25 10529 *total = COSTS_N_INSNS (!speed ? 5 : 41);
20d892d1 10530 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10531 speed);
433a5f02 10532 }
10533 else
10534 switch (INTVAL (XEXP (x, 1)))
10535 {
10536 case 0:
10537 *total = 0;
10538 break;
10539 case 1:
10540 case 8:
10541 *total = COSTS_N_INSNS (2);
10542 break;
10543 case 9:
10544 *total = COSTS_N_INSNS (3);
10545 break;
10546 case 2:
10547 case 10:
10548 case 15:
10549 *total = COSTS_N_INSNS (4);
10550 break;
10551 case 7:
10552 case 11:
10553 *total = COSTS_N_INSNS (5);
10554 break;
10555 case 3:
10556 case 12:
10557 case 13:
10558 case 14:
f529eb25 10559 *total = COSTS_N_INSNS (!speed ? 5 : 6);
433a5f02 10560 break;
10561 case 4:
f529eb25 10562 *total = COSTS_N_INSNS (!speed ? 5 : 7);
433a5f02 10563 break;
10564 case 5:
10565 case 6:
f529eb25 10566 *total = COSTS_N_INSNS (!speed ? 5 : 9);
433a5f02 10567 break;
10568 default:
f529eb25 10569 *total = COSTS_N_INSNS (!speed ? 5 : 41);
20d892d1 10570 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10571 speed);
433a5f02 10572 }
10573 break;
10574
02d9a2c3 10575 case PSImode:
10576 if (!CONST_INT_P (XEXP (x, 1)))
10577 {
10578 *total = COSTS_N_INSNS (!speed ? 6 : 73);
10579 }
10580 else
10581 switch (INTVAL (XEXP (x, 1)))
10582 {
10583 case 0:
10584 *total = 0;
10585 break;
10586 case 1:
10587 case 8:
10588 case 16:
10589 *total = COSTS_N_INSNS (3);
10590 break;
10591 case 23:
10592 *total = COSTS_N_INSNS (5);
10593 break;
10594 default:
10595 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
10596 break;
10597 }
10598 break;
10599
433a5f02 10600 case SImode:
10601 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10602 {
f529eb25 10603 *total = COSTS_N_INSNS (!speed ? 7 : 113);
20d892d1 10604 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10605 speed);
433a5f02 10606 }
10607 else
10608 switch (INTVAL (XEXP (x, 1)))
10609 {
10610 case 0:
10611 *total = 0;
10612 break;
10613 case 1:
10614 *total = COSTS_N_INSNS (4);
10615 break;
10616 case 2:
f529eb25 10617 *total = COSTS_N_INSNS (!speed ? 7 : 8);
433a5f02 10618 break;
10619 case 8:
10620 case 16:
10621 case 24:
10622 *total = COSTS_N_INSNS (4);
10623 break;
10624 case 31:
10625 *total = COSTS_N_INSNS (6);
10626 break;
10627 default:
f529eb25 10628 *total = COSTS_N_INSNS (!speed ? 7 : 113);
20d892d1 10629 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10630 speed);
433a5f02 10631 }
10632 break;
10633
10634 default:
10635 return false;
10636 }
20d892d1 10637 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
433a5f02 10638 return true;
10639
10640 case COMPARE:
10641 switch (GET_MODE (XEXP (x, 0)))
fab7adbf 10642 {
433a5f02 10643 case QImode:
10644 *total = COSTS_N_INSNS (1);
10645 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
20d892d1 10646 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
433a5f02 10647 break;
10648
10649 case HImode:
10650 *total = COSTS_N_INSNS (2);
10651 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
20d892d1 10652 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
433a5f02 10653 else if (INTVAL (XEXP (x, 1)) != 0)
10654 *total += COSTS_N_INSNS (1);
10655 break;
10656
02d9a2c3 10657 case PSImode:
10658 *total = COSTS_N_INSNS (3);
10659 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) != 0)
10660 *total += COSTS_N_INSNS (2);
10661 break;
10662
433a5f02 10663 case SImode:
10664 *total = COSTS_N_INSNS (4);
10665 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
20d892d1 10666 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
433a5f02 10667 else if (INTVAL (XEXP (x, 1)) != 0)
10668 *total += COSTS_N_INSNS (3);
10669 break;
10670
10671 default:
10672 return false;
fab7adbf 10673 }
20d892d1 10674 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
433a5f02 10675 return true;
10676
12bf3919 10677 case TRUNCATE:
10678 if (AVR_HAVE_MUL
10679 && LSHIFTRT == GET_CODE (XEXP (x, 0))
10680 && MULT == GET_CODE (XEXP (XEXP (x, 0), 0))
10681 && CONST_INT_P (XEXP (XEXP (x, 0), 1)))
10682 {
10683 if (QImode == mode || HImode == mode)
10684 {
10685 *total = COSTS_N_INSNS (2);
10686 return true;
10687 }
10688 }
10689 break;
10690
433a5f02 10691 default:
10692 break;
fab7adbf 10693 }
433a5f02 10694 return false;
fab7adbf 10695}
10696
ae86bb47 10697
10698/* Implement `TARGET_RTX_COSTS'. */
10699
10700static bool
10701avr_rtx_costs (rtx x, int codearg, int outer_code,
10702 int opno, int *total, bool speed)
10703{
10704 bool done = avr_rtx_costs_1 (x, codearg, outer_code,
10705 opno, total, speed);
10706
10707 if (avr_log.rtx_costs)
10708 {
10709 avr_edump ("\n%?=%b (%s) total=%d, outer=%C:\n%r\n",
10710 done, speed ? "speed" : "size", *total, outer_code, x);
10711 }
10712
10713 return done;
10714}
10715
8c3bcbe3 10716
10717/* Implement `TARGET_ADDRESS_COST'. */
a28e4651 10718
ec0457a8 10719static int
3754d046 10720avr_address_cost (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
b4ebb666 10721 addr_space_t as ATTRIBUTE_UNUSED,
10722 bool speed ATTRIBUTE_UNUSED)
a28e4651 10723{
8c3bcbe3 10724 int cost = 4;
0dff9558 10725
a28e4651 10726 if (GET_CODE (x) == PLUS
8c3bcbe3 10727 && CONST_INT_P (XEXP (x, 1))
10728 && (REG_P (XEXP (x, 0))
10729 || GET_CODE (XEXP (x, 0)) == SUBREG))
37ac04dc 10730 {
8c3bcbe3 10731 if (INTVAL (XEXP (x, 1)) >= 61)
10732 cost = 18;
37ac04dc 10733 }
8c3bcbe3 10734 else if (CONSTANT_ADDRESS_P (x))
10735 {
10736 if (optimize > 0
10737 && io_address_operand (x, QImode))
10738 cost = 2;
10739 }
10740
10741 if (avr_log.address_cost)
10742 avr_edump ("\n%?: %d = %r\n", cost, x);
0dff9558 10743
8c3bcbe3 10744 return cost;
a28e4651 10745}
10746
164f5b34 10747/* Test for extra memory constraint 'Q'.
10748 It's a memory address based on Y or Z pointer with valid displacement. */
a28e4651 10749
10750int
164f5b34 10751extra_constraint_Q (rtx x)
a28e4651 10752{
ae86bb47 10753 int ok = 0;
0dff9558 10754
164f5b34 10755 if (GET_CODE (XEXP (x,0)) == PLUS
10756 && REG_P (XEXP (XEXP (x,0), 0))
10757 && GET_CODE (XEXP (XEXP (x,0), 1)) == CONST_INT
10758 && (INTVAL (XEXP (XEXP (x,0), 1))
10759 <= MAX_LD_OFFSET (GET_MODE (x))))
a28e4651 10760 {
164f5b34 10761 rtx xx = XEXP (XEXP (x,0), 0);
10762 int regno = REGNO (xx);
0dff9558 10763
ae86bb47 10764 ok = (/* allocate pseudos */
10765 regno >= FIRST_PSEUDO_REGISTER
10766 /* strictly check */
10767 || regno == REG_Z || regno == REG_Y
10768 /* XXX frame & arg pointer checks */
10769 || xx == frame_pointer_rtx
10770 || xx == arg_pointer_rtx);
0dff9558 10771
ae86bb47 10772 if (avr_log.constraints)
10773 avr_edump ("\n%?=%d reload_completed=%d reload_in_progress=%d\n %r\n",
10774 ok, reload_completed, reload_in_progress, x);
a28e4651 10775 }
ae86bb47 10776
10777 return ok;
a28e4651 10778}
10779
20c71901 10780/* Convert condition code CONDITION to the valid AVR condition code. */
a28e4651 10781
10782RTX_CODE
206a5129 10783avr_normalize_condition (RTX_CODE condition)
a28e4651 10784{
10785 switch (condition)
10786 {
10787 case GT:
10788 return GE;
10789 case GTU:
10790 return GEU;
10791 case LE:
10792 return LT;
10793 case LEU:
10794 return LTU;
10795 default:
8ef66241 10796 gcc_unreachable ();
a28e4651 10797 }
10798}
10799
cffa155c 10800/* Helper function for `avr_reorg'. */
10801
10802static rtx
375204de 10803avr_compare_pattern (rtx_insn *insn)
cffa155c 10804{
10805 rtx pattern = single_set (insn);
10806
10807 if (pattern
10808 && NONJUMP_INSN_P (insn)
10809 && SET_DEST (pattern) == cc0_rtx
017c5b98 10810 && GET_CODE (SET_SRC (pattern)) == COMPARE)
cffa155c 10811 {
3754d046 10812 machine_mode mode0 = GET_MODE (XEXP (SET_SRC (pattern), 0));
10813 machine_mode mode1 = GET_MODE (XEXP (SET_SRC (pattern), 1));
017c5b98 10814
10815 /* The 64-bit comparisons have fixed operands ACC_A and ACC_B.
10816 They must not be swapped, thus skip them. */
10817
10818 if ((mode0 == VOIDmode || GET_MODE_SIZE (mode0) <= 4)
10819 && (mode1 == VOIDmode || GET_MODE_SIZE (mode1) <= 4))
10820 return pattern;
cffa155c 10821 }
10822
10823 return NULL_RTX;
10824}
10825
10826/* Helper function for `avr_reorg'. */
10827
10828/* Expansion of switch/case decision trees leads to code like
10829
10830 cc0 = compare (Reg, Num)
10831 if (cc0 == 0)
10832 goto L1
0dff9558 10833
cffa155c 10834 cc0 = compare (Reg, Num)
10835 if (cc0 > 0)
10836 goto L2
10837
10838 The second comparison is superfluous and can be deleted.
10839 The second jump condition can be transformed from a
10840 "difficult" one to a "simple" one because "cc0 > 0" and
10841 "cc0 >= 0" will have the same effect here.
10842
10843 This function relies on the way switch/case is being expaned
10844 as binary decision tree. For example code see PR 49903.
0dff9558 10845
cffa155c 10846 Return TRUE if optimization performed.
10847 Return FALSE if nothing changed.
10848
10849 INSN1 is a comparison, i.e. avr_compare_pattern != 0.
10850
10851 We don't want to do this in text peephole because it is
10852 tedious to work out jump offsets there and the second comparison
10853 might have been transormed by `avr_reorg'.
10854
10855 RTL peephole won't do because peephole2 does not scan across
0dff9558 10856 basic blocks. */
10857
cffa155c 10858static bool
375204de 10859avr_reorg_remove_redundant_compare (rtx_insn *insn1)
cffa155c 10860{
375204de 10861 rtx comp1, ifelse1, xcond1;
10862 rtx_insn *branch1;
10863 rtx comp2, ifelse2, xcond2;
10864 rtx_insn *branch2, *insn2;
cffa155c 10865 enum rtx_code code;
375204de 10866 rtx_insn *jump;
10867 rtx target, cond;
0dff9558 10868
cffa155c 10869 /* Look out for: compare1 - branch1 - compare2 - branch2 */
10870
10871 branch1 = next_nonnote_nondebug_insn (insn1);
10872 if (!branch1 || !JUMP_P (branch1))
10873 return false;
10874
10875 insn2 = next_nonnote_nondebug_insn (branch1);
10876 if (!insn2 || !avr_compare_pattern (insn2))
10877 return false;
10878
10879 branch2 = next_nonnote_nondebug_insn (insn2);
10880 if (!branch2 || !JUMP_P (branch2))
10881 return false;
10882
10883 comp1 = avr_compare_pattern (insn1);
10884 comp2 = avr_compare_pattern (insn2);
10885 xcond1 = single_set (branch1);
10886 xcond2 = single_set (branch2);
0dff9558 10887
cffa155c 10888 if (!comp1 || !comp2
10889 || !rtx_equal_p (comp1, comp2)
10890 || !xcond1 || SET_DEST (xcond1) != pc_rtx
10891 || !xcond2 || SET_DEST (xcond2) != pc_rtx
10892 || IF_THEN_ELSE != GET_CODE (SET_SRC (xcond1))
10893 || IF_THEN_ELSE != GET_CODE (SET_SRC (xcond2)))
10894 {
10895 return false;
10896 }
10897
10898 comp1 = SET_SRC (comp1);
10899 ifelse1 = SET_SRC (xcond1);
10900 ifelse2 = SET_SRC (xcond2);
10901
10902 /* comp<n> is COMPARE now and ifelse<n> is IF_THEN_ELSE. */
10903
10904 if (EQ != GET_CODE (XEXP (ifelse1, 0))
10905 || !REG_P (XEXP (comp1, 0))
10906 || !CONST_INT_P (XEXP (comp1, 1))
10907 || XEXP (ifelse1, 2) != pc_rtx
10908 || XEXP (ifelse2, 2) != pc_rtx
10909 || LABEL_REF != GET_CODE (XEXP (ifelse1, 1))
10910 || LABEL_REF != GET_CODE (XEXP (ifelse2, 1))
10911 || !COMPARISON_P (XEXP (ifelse2, 0))
10912 || cc0_rtx != XEXP (XEXP (ifelse1, 0), 0)
10913 || cc0_rtx != XEXP (XEXP (ifelse2, 0), 0)
10914 || const0_rtx != XEXP (XEXP (ifelse1, 0), 1)
10915 || const0_rtx != XEXP (XEXP (ifelse2, 0), 1))
10916 {
10917 return false;
10918 }
10919
10920 /* We filtered the insn sequence to look like
10921
10922 (set (cc0)
10923 (compare (reg:M N)
10924 (const_int VAL)))
10925 (set (pc)
10926 (if_then_else (eq (cc0)
10927 (const_int 0))
10928 (label_ref L1)
10929 (pc)))
0dff9558 10930
cffa155c 10931 (set (cc0)
10932 (compare (reg:M N)
10933 (const_int VAL)))
10934 (set (pc)
10935 (if_then_else (CODE (cc0)
10936 (const_int 0))
10937 (label_ref L2)
10938 (pc)))
10939 */
10940
10941 code = GET_CODE (XEXP (ifelse2, 0));
10942
10943 /* Map GT/GTU to GE/GEU which is easier for AVR.
10944 The first two instructions compare/branch on EQ
10945 so we may replace the difficult
0dff9558 10946
cffa155c 10947 if (x == VAL) goto L1;
10948 if (x > VAL) goto L2;
10949
10950 with easy
0dff9558 10951
cffa155c 10952 if (x == VAL) goto L1;
10953 if (x >= VAL) goto L2;
10954
10955 Similarly, replace LE/LEU by LT/LTU. */
0dff9558 10956
cffa155c 10957 switch (code)
10958 {
10959 case EQ:
10960 case LT: case LTU:
10961 case GE: case GEU:
10962 break;
10963
10964 case LE: case LEU:
10965 case GT: case GTU:
10966 code = avr_normalize_condition (code);
10967 break;
0dff9558 10968
cffa155c 10969 default:
10970 return false;
10971 }
10972
10973 /* Wrap the branches into UNSPECs so they won't be changed or
10974 optimized in the remainder. */
10975
10976 target = XEXP (XEXP (ifelse1, 1), 0);
10977 cond = XEXP (ifelse1, 0);
10978 jump = emit_jump_insn_after (gen_branch_unspec (target, cond), insn1);
10979
10980 JUMP_LABEL (jump) = JUMP_LABEL (branch1);
10981
10982 target = XEXP (XEXP (ifelse2, 1), 0);
10983 cond = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
10984 jump = emit_jump_insn_after (gen_branch_unspec (target, cond), insn2);
10985
10986 JUMP_LABEL (jump) = JUMP_LABEL (branch2);
10987
10988 /* The comparisons in insn1 and insn2 are exactly the same;
10989 insn2 is superfluous so delete it. */
0dff9558 10990
cffa155c 10991 delete_insn (insn2);
10992 delete_insn (branch1);
10993 delete_insn (branch2);
10994
10995 return true;
10996}
10997
10998
10999/* Implement `TARGET_MACHINE_DEPENDENT_REORG'. */
11000/* Optimize conditional jumps. */
a28e4651 11001
2efea8c0 11002static void
206a5129 11003avr_reorg (void)
a28e4651 11004{
375204de 11005 rtx_insn *insn = get_insns();
0dff9558 11006
cffa155c 11007 for (insn = next_real_insn (insn); insn; insn = next_real_insn (insn))
a28e4651 11008 {
cffa155c 11009 rtx pattern = avr_compare_pattern (insn);
0dff9558 11010
cffa155c 11011 if (!pattern)
11012 continue;
a28e4651 11013
cffa155c 11014 if (optimize
11015 && avr_reorg_remove_redundant_compare (insn))
11016 {
11017 continue;
11018 }
a28e4651 11019
cffa155c 11020 if (compare_diff_p (insn))
a28e4651 11021 {
cffa155c 11022 /* Now we work under compare insn with difficult branch. */
0dff9558 11023
cffa155c 11024 rtx next = next_real_insn (insn);
11025 rtx pat = PATTERN (next);
11026
11027 pattern = SET_SRC (pattern);
0dff9558 11028
cffa155c 11029 if (true_regnum (XEXP (pattern, 0)) >= 0
11030 && true_regnum (XEXP (pattern, 1)) >= 0)
11031 {
11032 rtx x = XEXP (pattern, 0);
11033 rtx src = SET_SRC (pat);
11034 rtx t = XEXP (src,0);
11035 PUT_CODE (t, swap_condition (GET_CODE (t)));
11036 XEXP (pattern, 0) = XEXP (pattern, 1);
11037 XEXP (pattern, 1) = x;
11038 INSN_CODE (next) = -1;
11039 }
11040 else if (true_regnum (XEXP (pattern, 0)) >= 0
11041 && XEXP (pattern, 1) == const0_rtx)
11042 {
11043 /* This is a tst insn, we can reverse it. */
11044 rtx src = SET_SRC (pat);
11045 rtx t = XEXP (src,0);
0dff9558 11046
cffa155c 11047 PUT_CODE (t, swap_condition (GET_CODE (t)));
11048 XEXP (pattern, 1) = XEXP (pattern, 0);
11049 XEXP (pattern, 0) = const0_rtx;
11050 INSN_CODE (next) = -1;
11051 INSN_CODE (insn) = -1;
11052 }
11053 else if (true_regnum (XEXP (pattern, 0)) >= 0
11054 && CONST_INT_P (XEXP (pattern, 1)))
11055 {
11056 rtx x = XEXP (pattern, 1);
11057 rtx src = SET_SRC (pat);
11058 rtx t = XEXP (src,0);
3754d046 11059 machine_mode mode = GET_MODE (XEXP (pattern, 0));
0dff9558 11060
cffa155c 11061 if (avr_simplify_comparison_p (mode, GET_CODE (t), x))
11062 {
11063 XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
11064 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
11065 INSN_CODE (next) = -1;
11066 INSN_CODE (insn) = -1;
11067 }
11068 }
11069 }
a28e4651 11070 }
11071}
11072
11073/* Returns register number for function return value.*/
11074
1086ba15 11075static inline unsigned int
206a5129 11076avr_ret_register (void)
a28e4651 11077{
11078 return 24;
11079}
11080
0dff9558 11081
11082/* Implement `TARGET_FUNCTION_VALUE_REGNO_P'. */
73475e84 11083
11084static bool
11085avr_function_value_regno_p (const unsigned int regno)
11086{
11087 return (regno == avr_ret_register ());
11088}
11089
0dff9558 11090
11091/* Implement `TARGET_LIBCALL_VALUE'. */
f2b32076 11092/* Create an RTX representing the place where a
a28e4651 11093 library function returns a value of mode MODE. */
11094
73475e84 11095static rtx
3754d046 11096avr_libcall_value (machine_mode mode,
73475e84 11097 const_rtx func ATTRIBUTE_UNUSED)
a28e4651 11098{
11099 int offs = GET_MODE_SIZE (mode);
0dff9558 11100
02d9a2c3 11101 if (offs <= 4)
11102 offs = (offs + 1) & ~1;
0dff9558 11103
73475e84 11104 return gen_rtx_REG (mode, avr_ret_register () + 2 - offs);
a28e4651 11105}
11106
0dff9558 11107
11108/* Implement `TARGET_FUNCTION_VALUE'. */
a28e4651 11109/* Create an RTX representing the place where a
11110 function returns a value of data type VALTYPE. */
11111
73475e84 11112static rtx
1086ba15 11113avr_function_value (const_tree type,
11114 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
11115 bool outgoing ATTRIBUTE_UNUSED)
a28e4651 11116{
1cb39658 11117 unsigned int offs;
73475e84 11118
a28e4651 11119 if (TYPE_MODE (type) != BLKmode)
1086ba15 11120 return avr_libcall_value (TYPE_MODE (type), NULL_RTX);
0dff9558 11121
a28e4651 11122 offs = int_size_in_bytes (type);
11123 if (offs < 2)
11124 offs = 2;
11125 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
11126 offs = GET_MODE_SIZE (SImode);
11127 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
11128 offs = GET_MODE_SIZE (DImode);
0dff9558 11129
73475e84 11130 return gen_rtx_REG (BLKmode, avr_ret_register () + 2 - offs);
a28e4651 11131}
11132
8a2a7305 11133int
8deb3959 11134test_hard_reg_class (enum reg_class rclass, rtx x)
8a2a7305 11135{
11136 int regno = true_regnum (x);
11137 if (regno < 0)
11138 return 0;
cb39cd35 11139
8deb3959 11140 if (TEST_HARD_REG_CLASS (rclass, regno))
cb39cd35 11141 return 1;
11142
11143 return 0;
8a2a7305 11144}
11145
2ebcbfe8 11146
8ef28ef2 11147/* Helper for jump_over_one_insn_p: Test if INSN is a 2-word instruction
11148 and thus is suitable to be skipped by CPSE, SBRC, etc. */
11149
11150static bool
375204de 11151avr_2word_insn_p (rtx_insn *insn)
8ef28ef2 11152{
c0d7a1d0 11153 if (TARGET_SKIP_BUG
8ef28ef2 11154 || !insn
11155 || 2 != get_attr_length (insn))
11156 {
11157 return false;
11158 }
11159
11160 switch (INSN_CODE (insn))
11161 {
11162 default:
11163 return false;
0dff9558 11164
8ef28ef2 11165 case CODE_FOR_movqi_insn:
017c5b98 11166 case CODE_FOR_movuqq_insn:
11167 case CODE_FOR_movqq_insn:
8ef28ef2 11168 {
11169 rtx set = single_set (insn);
11170 rtx src = SET_SRC (set);
11171 rtx dest = SET_DEST (set);
0dff9558 11172
8ef28ef2 11173 /* Factor out LDS and STS from movqi_insn. */
0dff9558 11174
8ef28ef2 11175 if (MEM_P (dest)
017c5b98 11176 && (REG_P (src) || src == CONST0_RTX (GET_MODE (dest))))
8ef28ef2 11177 {
11178 return CONSTANT_ADDRESS_P (XEXP (dest, 0));
11179 }
11180 else if (REG_P (dest)
11181 && MEM_P (src))
11182 {
11183 return CONSTANT_ADDRESS_P (XEXP (src, 0));
11184 }
0dff9558 11185
8ef28ef2 11186 return false;
11187 }
11188
11189 case CODE_FOR_call_insn:
11190 case CODE_FOR_call_value_insn:
11191 return true;
11192 }
11193}
11194
11195
2ebcbfe8 11196int
375204de 11197jump_over_one_insn_p (rtx_insn *insn, rtx dest)
2ebcbfe8 11198{
11199 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
11200 ? XEXP (dest, 0)
11201 : dest);
47fc0706 11202 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
11203 int dest_addr = INSN_ADDRESSES (uid);
8ef28ef2 11204 int jump_offset = dest_addr - jump_addr - get_attr_length (insn);
0dff9558 11205
8ef28ef2 11206 return (jump_offset == 1
11207 || (jump_offset == 2
11208 && avr_2word_insn_p (next_active_insn (insn))));
2ebcbfe8 11209}
a7690ba9 11210
0dff9558 11211
11212/* Worker function for `HARD_REGNO_MODE_OK'. */
a7690ba9 11213/* Returns 1 if a value of mode MODE can be stored starting with hard
0af74aa0 11214 register number REGNO. On the enhanced core, anything larger than
11215 1 byte must start in even numbered register for "movw" to work
11216 (this way we don't have to check for odd registers everywhere). */
a7690ba9 11217
11218int
3754d046 11219avr_hard_regno_mode_ok (int regno, machine_mode mode)
a7690ba9 11220{
3d4d979d 11221 /* NOTE: 8-bit values must not be disallowed for R28 or R29.
11222 Disallowing QI et al. in these regs might lead to code like
11223 (set (subreg:QI (reg:HI 28) n) ...)
11224 which will result in wrong code because reload does not
11225 handle SUBREGs of hard regsisters like this.
11226 This could be fixed in reload. However, it appears
11227 that fixing reload is not wanted by reload people. */
0dff9558 11228
3d4d979d 11229 /* Any GENERAL_REGS register can hold 8-bit values. */
0dff9558 11230
3d4d979d 11231 if (GET_MODE_SIZE (mode) == 1)
a7690ba9 11232 return 1;
60d76236 11233
3d4d979d 11234 /* FIXME: Ideally, the following test is not needed.
11235 However, it turned out that it can reduce the number
11236 of spill fails. AVR and it's poor endowment with
11237 address registers is extreme stress test for reload. */
0dff9558 11238
3d4d979d 11239 if (GET_MODE_SIZE (mode) >= 4
11240 && regno >= REG_X)
60d76236 11241 return 0;
11242
3d4d979d 11243 /* All modes larger than 8 bits should start in an even register. */
0dff9558 11244
a7690ba9 11245 return !(regno & 1);
11246}
e511e253 11247
e511e253 11248
f55cb01e 11249/* Implement `HARD_REGNO_CALL_PART_CLOBBERED'. */
11250
11251int
3754d046 11252avr_hard_regno_call_part_clobbered (unsigned regno, machine_mode mode)
f55cb01e 11253{
11254 /* FIXME: This hook gets called with MODE:REGNO combinations that don't
11255 represent valid hard registers like, e.g. HI:29. Returning TRUE
11256 for such registers can lead to performance degradation as mentioned
11257 in PR53595. Thus, report invalid hard registers as FALSE. */
0dff9558 11258
f55cb01e 11259 if (!avr_hard_regno_mode_ok (regno, mode))
11260 return 0;
0dff9558 11261
f55cb01e 11262 /* Return true if any of the following boundaries is crossed:
11263 17/18, 27/28 and 29/30. */
0dff9558 11264
f55cb01e 11265 return ((regno < 18 && regno + GET_MODE_SIZE (mode) > 18)
11266 || (regno < REG_Y && regno + GET_MODE_SIZE (mode) > REG_Y)
11267 || (regno < REG_Z && regno + GET_MODE_SIZE (mode) > REG_Z));
11268}
11269
11270
8b0ecac5 11271/* Implement `MODE_CODE_BASE_REG_CLASS'. */
11272
63477dcc 11273enum reg_class
3754d046 11274avr_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED,
4202ef11 11275 addr_space_t as, RTX_CODE outer_code,
8b0ecac5 11276 RTX_CODE index_code ATTRIBUTE_UNUSED)
11277{
4202ef11 11278 if (!ADDR_SPACE_GENERIC_P (as))
11279 {
11280 return POINTER_Z_REGS;
11281 }
0dff9558 11282
f9efb148 11283 if (!avr_strict_X)
11284 return reload_completed ? BASE_POINTER_REGS : POINTER_REGS;
11285
11286 return PLUS == outer_code ? BASE_POINTER_REGS : POINTER_REGS;
8b0ecac5 11287}
11288
11289
11290/* Implement `REGNO_MODE_CODE_OK_FOR_BASE_P'. */
11291
11292bool
11293avr_regno_mode_code_ok_for_base_p (int regno,
3754d046 11294 machine_mode mode ATTRIBUTE_UNUSED,
f8a8fc7b 11295 addr_space_t as ATTRIBUTE_UNUSED,
f9efb148 11296 RTX_CODE outer_code,
8b0ecac5 11297 RTX_CODE index_code ATTRIBUTE_UNUSED)
11298{
f9efb148 11299 bool ok = false;
0dff9558 11300
4202ef11 11301 if (!ADDR_SPACE_GENERIC_P (as))
11302 {
11303 if (regno < FIRST_PSEUDO_REGISTER
11304 && regno == REG_Z)
11305 {
11306 return true;
11307 }
0dff9558 11308
4202ef11 11309 if (reg_renumber)
11310 {
11311 regno = reg_renumber[regno];
0dff9558 11312
4202ef11 11313 if (regno == REG_Z)
11314 {
11315 return true;
11316 }
11317 }
0dff9558 11318
4202ef11 11319 return false;
11320 }
11321
8b0ecac5 11322 if (regno < FIRST_PSEUDO_REGISTER
11323 && (regno == REG_X
11324 || regno == REG_Y
11325 || regno == REG_Z
9f42c829 11326 || regno == ARG_POINTER_REGNUM))
8b0ecac5 11327 {
f9efb148 11328 ok = true;
8b0ecac5 11329 }
f9efb148 11330 else if (reg_renumber)
8b0ecac5 11331 {
11332 regno = reg_renumber[regno];
11333
11334 if (regno == REG_X
11335 || regno == REG_Y
11336 || regno == REG_Z
9f42c829 11337 || regno == ARG_POINTER_REGNUM)
8b0ecac5 11338 {
f9efb148 11339 ok = true;
8b0ecac5 11340 }
11341 }
f9efb148 11342
11343 if (avr_strict_X
11344 && PLUS == outer_code
11345 && regno == REG_X)
11346 {
11347 ok = false;
11348 }
11349
11350 return ok;
8b0ecac5 11351}
11352
11353
5bca95a8 11354/* A helper for `output_reload_insisf' and `output_reload_inhi'. */
28913f6b 11355/* Set 32-bit register OP[0] to compile-time constant OP[1].
11356 CLOBBER_REG is a QI clobber register or NULL_RTX.
11357 LEN == NULL: output instructions.
11358 LEN != NULL: set *LEN to the length of the instruction sequence
11359 (in words) printed with LEN = NULL.
11360 If CLEAR_P is true, OP[0] had been cleard to Zero already.
33817c7e 11361 If CLEAR_P is false, nothing is known about OP[0].
11362
11363 The effect on cc0 is as follows:
11364
f4806884 11365 Load 0 to any register except ZERO_REG : NONE
11366 Load ld register with any value : NONE
11367 Anything else: : CLOBBER */
9ce2d202 11368
28913f6b 11369static void
2f2d376f 11370output_reload_in_const (rtx *op, rtx clobber_reg, int *len, bool clear_p)
e511e253 11371{
9ce2d202 11372 rtx src = op[1];
11373 rtx dest = op[0];
11374 rtx xval, xdest[4];
11375 int ival[4];
11376 int clobber_val = 1234;
11377 bool cooked_clobber_p = false;
11378 bool set_p = false;
3754d046 11379 machine_mode mode = GET_MODE (dest);
4202ef11 11380 int n, n_bytes = GET_MODE_SIZE (mode);
0dff9558 11381
a49907f9 11382 gcc_assert (REG_P (dest)
11383 && CONSTANT_P (src));
37ac04dc 11384
11385 if (len)
9ce2d202 11386 *len = 0;
0dff9558 11387
9ce2d202 11388 /* (REG:SI 14) is special: It's neither in LD_REGS nor in NO_LD_REGS
11389 but has some subregs that are in LD_REGS. Use the MSB (REG:QI 17). */
0dff9558 11390
02d9a2c3 11391 if (REGNO (dest) < 16
11392 && REGNO (dest) + GET_MODE_SIZE (mode) > 16)
37ac04dc 11393 {
4202ef11 11394 clobber_reg = all_regs_rtx[REGNO (dest) + n_bytes - 1];
37ac04dc 11395 }
e511e253 11396
a49907f9 11397 /* We might need a clobber reg but don't have one. Look at the value to
11398 be loaded more closely. A clobber is only needed if it is a symbol
11399 or contains a byte that is neither 0, -1 or a power of 2. */
0dff9558 11400
9ce2d202 11401 if (NULL_RTX == clobber_reg
2f2d376f 11402 && !test_hard_reg_class (LD_REGS, dest)
017c5b98 11403 && (! (CONST_INT_P (src) || CONST_FIXED_P (src) || CONST_DOUBLE_P (src))
a49907f9 11404 || !avr_popcount_each_byte (src, n_bytes,
11405 (1 << 0) | (1 << 1) | (1 << 8))))
e511e253 11406 {
2f2d376f 11407 /* We have no clobber register but need one. Cook one up.
11408 That's cheaper than loading from constant pool. */
0dff9558 11409
2f2d376f 11410 cooked_clobber_p = true;
4202ef11 11411 clobber_reg = all_regs_rtx[REG_Z + 1];
2f2d376f 11412 avr_asm_len ("mov __tmp_reg__,%0", &clobber_reg, len, 1);
e511e253 11413 }
9ce2d202 11414
11415 /* Now start filling DEST from LSB to MSB. */
0dff9558 11416
a49907f9 11417 for (n = 0; n < n_bytes; n++)
e511e253 11418 {
a49907f9 11419 int ldreg_p;
9ce2d202 11420 bool done_byte = false;
4202ef11 11421 int j;
9ce2d202 11422 rtx xop[3];
11423
a49907f9 11424 /* Crop the n-th destination byte. */
11425
9ce2d202 11426 xdest[n] = simplify_gen_subreg (QImode, dest, mode, n);
a49907f9 11427 ldreg_p = test_hard_reg_class (LD_REGS, xdest[n]);
11428
11429 if (!CONST_INT_P (src)
017c5b98 11430 && !CONST_FIXED_P (src)
a49907f9 11431 && !CONST_DOUBLE_P (src))
11432 {
11433 static const char* const asm_code[][2] =
11434 {
11435 { "ldi %2,lo8(%1)" CR_TAB "mov %0,%2", "ldi %0,lo8(%1)" },
11436 { "ldi %2,hi8(%1)" CR_TAB "mov %0,%2", "ldi %0,hi8(%1)" },
11437 { "ldi %2,hlo8(%1)" CR_TAB "mov %0,%2", "ldi %0,hlo8(%1)" },
11438 { "ldi %2,hhi8(%1)" CR_TAB "mov %0,%2", "ldi %0,hhi8(%1)" }
11439 };
0dff9558 11440
a49907f9 11441 xop[0] = xdest[n];
11442 xop[1] = src;
11443 xop[2] = clobber_reg;
11444
ed2541ea 11445 avr_asm_len (asm_code[n][ldreg_p], xop, len, ldreg_p ? 1 : 2);
0dff9558 11446
a49907f9 11447 continue;
11448 }
11449
11450 /* Crop the n-th source byte. */
11451
11452 xval = simplify_gen_subreg (QImode, src, mode, n);
9ce2d202 11453 ival[n] = INTVAL (xval);
11454
11455 /* Look if we can reuse the low word by means of MOVW. */
0dff9558 11456
9ce2d202 11457 if (n == 2
a49907f9 11458 && n_bytes >= 4
9ce2d202 11459 && AVR_HAVE_MOVW)
11460 {
11461 rtx lo16 = simplify_gen_subreg (HImode, src, mode, 0);
11462 rtx hi16 = simplify_gen_subreg (HImode, src, mode, 2);
11463
11464 if (INTVAL (lo16) == INTVAL (hi16))
11465 {
28913f6b 11466 if (0 != INTVAL (lo16)
11467 || !clear_p)
11468 {
11469 avr_asm_len ("movw %C0,%A0", &op[0], len, 1);
11470 }
0dff9558 11471
9ce2d202 11472 break;
11473 }
11474 }
11475
33817c7e 11476 /* Don't use CLR so that cc0 is set as expected. */
0dff9558 11477
9ce2d202 11478 if (ival[n] == 0)
11479 {
28913f6b 11480 if (!clear_p)
f4806884 11481 avr_asm_len (ldreg_p ? "ldi %0,0"
b4e6d2e2 11482 : AVR_ZERO_REGNO == REGNO (xdest[n]) ? "clr %0"
f4806884 11483 : "mov %0,__zero_reg__",
33817c7e 11484 &xdest[n], len, 1);
9ce2d202 11485 continue;
11486 }
11487
11488 if (clobber_val == ival[n]
11489 && REGNO (clobber_reg) == REGNO (xdest[n]))
11490 {
11491 continue;
11492 }
11493
11494 /* LD_REGS can use LDI to move a constant value */
0dff9558 11495
a49907f9 11496 if (ldreg_p)
9ce2d202 11497 {
11498 xop[0] = xdest[n];
11499 xop[1] = xval;
11500 avr_asm_len ("ldi %0,lo8(%1)", xop, len, 1);
11501 continue;
11502 }
11503
11504 /* Try to reuse value already loaded in some lower byte. */
0dff9558 11505
9ce2d202 11506 for (j = 0; j < n; j++)
11507 if (ival[j] == ival[n])
11508 {
11509 xop[0] = xdest[n];
11510 xop[1] = xdest[j];
0dff9558 11511
9ce2d202 11512 avr_asm_len ("mov %0,%1", xop, len, 1);
11513 done_byte = true;
11514 break;
11515 }
11516
11517 if (done_byte)
11518 continue;
11519
11520 /* Need no clobber reg for -1: Use CLR/DEC */
0dff9558 11521
9ce2d202 11522 if (-1 == ival[n])
11523 {
28913f6b 11524 if (!clear_p)
11525 avr_asm_len ("clr %0", &xdest[n], len, 1);
0dff9558 11526
28913f6b 11527 avr_asm_len ("dec %0", &xdest[n], len, 1);
11528 continue;
11529 }
11530 else if (1 == ival[n])
11531 {
11532 if (!clear_p)
11533 avr_asm_len ("clr %0", &xdest[n], len, 1);
0dff9558 11534
28913f6b 11535 avr_asm_len ("inc %0", &xdest[n], len, 1);
9ce2d202 11536 continue;
11537 }
11538
11539 /* Use T flag or INC to manage powers of 2 if we have
11540 no clobber reg. */
11541
11542 if (NULL_RTX == clobber_reg
11543 && single_one_operand (xval, QImode))
11544 {
9ce2d202 11545 xop[0] = xdest[n];
11546 xop[1] = GEN_INT (exact_log2 (ival[n] & GET_MODE_MASK (QImode)));
11547
11548 gcc_assert (constm1_rtx != xop[1]);
11549
11550 if (!set_p)
11551 {
11552 set_p = true;
11553 avr_asm_len ("set", xop, len, 1);
11554 }
11555
28913f6b 11556 if (!clear_p)
11557 avr_asm_len ("clr %0", xop, len, 1);
0dff9558 11558
28913f6b 11559 avr_asm_len ("bld %0,%1", xop, len, 1);
9ce2d202 11560 continue;
11561 }
11562
11563 /* We actually need the LD_REGS clobber reg. */
11564
11565 gcc_assert (NULL_RTX != clobber_reg);
0dff9558 11566
9ce2d202 11567 xop[0] = xdest[n];
11568 xop[1] = xval;
11569 xop[2] = clobber_reg;
11570 clobber_val = ival[n];
0dff9558 11571
9ce2d202 11572 avr_asm_len ("ldi %2,lo8(%1)" CR_TAB
11573 "mov %0,%2", xop, len, 2);
e511e253 11574 }
0dff9558 11575
9ce2d202 11576 /* If we cooked up a clobber reg above, restore it. */
0dff9558 11577
9ce2d202 11578 if (cooked_clobber_p)
e511e253 11579 {
9ce2d202 11580 avr_asm_len ("mov %0,__tmp_reg__", &clobber_reg, len, 1);
e511e253 11581 }
28913f6b 11582}
11583
11584
2f2d376f 11585/* Reload the constant OP[1] into the HI register OP[0].
11586 CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
11587 into a NO_LD_REGS register. If CLOBBER_REG is NULL_RTX we either don't
11588 need a clobber reg or have to cook one up.
11589
11590 PLEN == NULL: Output instructions.
11591 PLEN != NULL: Output nothing. Set *PLEN to number of words occupied
11592 by the insns printed.
11593
11594 Return "". */
11595
11596const char*
11597output_reload_inhi (rtx *op, rtx clobber_reg, int *plen)
11598{
a49907f9 11599 output_reload_in_const (op, clobber_reg, plen, false);
2f2d376f 11600 return "";
11601}
11602
11603
28913f6b 11604/* Reload a SI or SF compile time constant OP[1] into the register OP[0].
11605 CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
11606 into a NO_LD_REGS register. If CLOBBER_REG is NULL_RTX we either don't
11607 need a clobber reg or have to cook one up.
11608
11609 LEN == NULL: Output instructions.
0dff9558 11610
b0e2b973 11611 LEN != NULL: Output nothing. Set *LEN to number of words occupied
28913f6b 11612 by the insns printed.
11613
11614 Return "". */
11615
11616const char *
5bca95a8 11617output_reload_insisf (rtx *op, rtx clobber_reg, int *len)
28913f6b 11618{
28913f6b 11619 if (AVR_HAVE_MOVW
644ac9c5 11620 && !test_hard_reg_class (LD_REGS, op[0])
11621 && (CONST_INT_P (op[1])
017c5b98 11622 || CONST_FIXED_P (op[1])
644ac9c5 11623 || CONST_DOUBLE_P (op[1])))
28913f6b 11624 {
11625 int len_clr, len_noclr;
0dff9558 11626
28913f6b 11627 /* In some cases it is better to clear the destination beforehand, e.g.
11628
11629 CLR R2 CLR R3 MOVW R4,R2 INC R2
11630
11631 is shorther than
11632
11633 CLR R2 INC R2 CLR R3 CLR R4 CLR R5
11634
11635 We find it too tedious to work that out in the print function.
11636 Instead, we call the print function twice to get the lengths of
11637 both methods and use the shortest one. */
0dff9558 11638
2f2d376f 11639 output_reload_in_const (op, clobber_reg, &len_clr, true);
11640 output_reload_in_const (op, clobber_reg, &len_noclr, false);
0dff9558 11641
28913f6b 11642 if (len_noclr - len_clr == 4)
11643 {
11644 /* Default needs 4 CLR instructions: clear register beforehand. */
0dff9558 11645
f4806884 11646 avr_asm_len ("mov %A0,__zero_reg__" CR_TAB
11647 "mov %B0,__zero_reg__" CR_TAB
28913f6b 11648 "movw %C0,%A0", &op[0], len, 3);
0dff9558 11649
2f2d376f 11650 output_reload_in_const (op, clobber_reg, len, true);
0dff9558 11651
28913f6b 11652 if (len)
11653 *len += 3;
11654
11655 return "";
11656 }
11657 }
11658
11659 /* Default: destination not pre-cleared. */
11660
2f2d376f 11661 output_reload_in_const (op, clobber_reg, len, false);
e511e253 11662 return "";
11663}
b681d971 11664
0dff9558 11665const char*
02d9a2c3 11666avr_out_reload_inpsi (rtx *op, rtx clobber_reg, int *len)
11667{
02d9a2c3 11668 output_reload_in_const (op, clobber_reg, len, false);
11669 return "";
11670}
11671
b681d971 11672
0dff9558 11673/* Worker function for `ASM_OUTPUT_ADDR_VEC_ELT'. */
11674
91b18013 11675void
206a5129 11676avr_output_addr_vec_elt (FILE *stream, int value)
91b18013 11677{
90ef7269 11678 if (AVR_HAVE_JMP_CALL)
11679 fprintf (stream, "\t.word gs(.L%d)\n", value);
91b18013 11680 else
11681 fprintf (stream, "\trjmp .L%d\n", value);
91b18013 11682}
11683
b4e6d2e2 11684static void
1a96adb9 11685avr_conditional_register_usage(void)
11686{
11687 if (AVR_TINY)
11688 {
11689 unsigned int i;
b4e6d2e2 11690
1a96adb9 11691 const int tiny_reg_alloc_order[] = {
11692 24, 25,
11693 22, 23,
11694 30, 31,
11695 26, 27,
11696 28, 29,
11697 21, 20, 19, 18,
11698 16, 17,
11699 32, 33, 34, 35,
11700 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
11701 };
b4e6d2e2 11702
1a96adb9 11703 /* Set R0-R17 as fixed registers. Reset R0-R17 in call used register list
11704 - R0-R15 are not available in Tiny Core devices
11705 - R16 and R17 are fixed registers. */
b4e6d2e2 11706
1a96adb9 11707 for (i = 0; i <= 17; i++)
11708 {
11709 fixed_regs[i] = 1;
11710 call_used_regs[i] = 1;
11711 }
b4e6d2e2 11712
1a96adb9 11713 /* Set R18 to R21 as callee saved registers
11714 - R18, R19, R20 and R21 are the callee saved registers in
11715 Tiny Core devices */
b4e6d2e2 11716
1a96adb9 11717 for (i = 18; i <= LAST_CALLEE_SAVED_REG; i++)
11718 {
11719 call_used_regs[i] = 0;
11720 }
b4e6d2e2 11721
1a96adb9 11722 /* Update register allocation order for Tiny Core devices */
11723
11724 for (i = 0; i < ARRAY_SIZE (tiny_reg_alloc_order); i++)
11725 {
11726 reg_alloc_order[i] = tiny_reg_alloc_order[i];
11727 }
11728
11729 CLEAR_HARD_REG_SET (reg_class_contents[(int) ADDW_REGS]);
11730 CLEAR_HARD_REG_SET (reg_class_contents[(int) NO_LD_REGS]);
11731 }
b4e6d2e2 11732}
0dff9558 11733
11734/* Implement `TARGET_HARD_REGNO_SCRATCH_OK'. */
5431d4c2 11735/* Returns true if SCRATCH are safe to be allocated as a scratch
51fe7379 11736 registers (for a define_peephole2) in the current function. */
11737
a45076aa 11738static bool
5431d4c2 11739avr_hard_regno_scratch_ok (unsigned int regno)
51fe7379 11740{
5431d4c2 11741 /* Interrupt functions can only use registers that have already been saved
11742 by the prologue, even if they would normally be call-clobbered. */
51fe7379 11743
5431d4c2 11744 if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
11745 && !df_regs_ever_live_p (regno))
11746 return false;
11747
3d4d979d 11748 /* Don't allow hard registers that might be part of the frame pointer.
11749 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
11750 and don't care for a frame pointer that spans more than one register. */
11751
11752 if ((!reload_completed || frame_pointer_needed)
11753 && (regno == REG_Y || regno == REG_Y + 1))
11754 {
11755 return false;
11756 }
11757
5431d4c2 11758 return true;
51fe7379 11759}
4af90ac0 11760
0dff9558 11761
11762/* Worker function for `HARD_REGNO_RENAME_OK'. */
afe7695c 11763/* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
11764
11765int
3d4d979d 11766avr_hard_regno_rename_ok (unsigned int old_reg,
afe7695c 11767 unsigned int new_reg)
11768{
11769 /* Interrupt functions can only use registers that have already been
11770 saved by the prologue, even if they would normally be
11771 call-clobbered. */
11772
11773 if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
11774 && !df_regs_ever_live_p (new_reg))
11775 return 0;
11776
3d4d979d 11777 /* Don't allow hard registers that might be part of the frame pointer.
11778 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
11779 and don't care for a frame pointer that spans more than one register. */
11780
11781 if ((!reload_completed || frame_pointer_needed)
11782 && (old_reg == REG_Y || old_reg == REG_Y + 1
11783 || new_reg == REG_Y || new_reg == REG_Y + 1))
11784 {
11785 return 0;
11786 }
0dff9558 11787
afe7695c 11788 return 1;
11789}
11790
dd7bbc23 11791/* Output a branch that tests a single bit of a register (QI, HI, SI or DImode)
4af90ac0 11792 or memory location in the I/O space (QImode only).
11793
11794 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
11795 Operand 1: register operand to test, or CONST_INT memory address.
dd7bbc23 11796 Operand 2: bit number.
4af90ac0 11797 Operand 3: label to jump to if the test is true. */
11798
0dff9558 11799const char*
375204de 11800avr_out_sbxx_branch (rtx_insn *insn, rtx operands[])
4af90ac0 11801{
11802 enum rtx_code comp = GET_CODE (operands[0]);
5bd39e93 11803 bool long_jump = get_attr_length (insn) >= 4;
11804 bool reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
4af90ac0 11805
11806 if (comp == GE)
11807 comp = EQ;
11808 else if (comp == LT)
11809 comp = NE;
11810
11811 if (reverse)
11812 comp = reverse_condition (comp);
11813
5bd39e93 11814 switch (GET_CODE (operands[1]))
4af90ac0 11815 {
5bd39e93 11816 default:
11817 gcc_unreachable();
0dff9558 11818
5bd39e93 11819 case CONST_INT:
c0d7a1d0 11820 case CONST:
11821 case SYMBOL_REF:
5bd39e93 11822
11823 if (low_io_address_operand (operands[1], QImode))
11824 {
11825 if (comp == EQ)
644ac9c5 11826 output_asm_insn ("sbis %i1,%2", operands);
5bd39e93 11827 else
644ac9c5 11828 output_asm_insn ("sbic %i1,%2", operands);
5bd39e93 11829 }
4af90ac0 11830 else
5bd39e93 11831 {
c0d7a1d0 11832 gcc_assert (io_address_operand (operands[1], QImode));
644ac9c5 11833 output_asm_insn ("in __tmp_reg__,%i1", operands);
5bd39e93 11834 if (comp == EQ)
11835 output_asm_insn ("sbrs __tmp_reg__,%2", operands);
11836 else
11837 output_asm_insn ("sbrc __tmp_reg__,%2", operands);
11838 }
11839
11840 break; /* CONST_INT */
11841
11842 case REG:
11843
16d17f31 11844 if (comp == EQ)
11845 output_asm_insn ("sbrs %T1%T2", operands);
11846 else
11847 output_asm_insn ("sbrc %T1%T2", operands);
5bd39e93 11848
11849 break; /* REG */
11850 } /* switch */
4af90ac0 11851
11852 if (long_jump)
5bd39e93 11853 return ("rjmp .+4" CR_TAB
11854 "jmp %x3");
11855
4af90ac0 11856 if (!reverse)
5bd39e93 11857 return "rjmp %x3";
11858
4af90ac0 11859 return "";
11860}
9aa7484c 11861
0dff9558 11862/* Worker function for `TARGET_ASM_CONSTRUCTOR'. */
6644435d 11863
9aa7484c 11864static void
206a5129 11865avr_asm_out_ctor (rtx symbol, int priority)
9aa7484c 11866{
11867 fputs ("\t.global __do_global_ctors\n", asm_out_file);
11868 default_ctor_section_asm_out_constructor (symbol, priority);
11869}
11870
0dff9558 11871
11872/* Worker function for `TARGET_ASM_DESTRUCTOR'. */
6644435d 11873
9aa7484c 11874static void
206a5129 11875avr_asm_out_dtor (rtx symbol, int priority)
9aa7484c 11876{
11877 fputs ("\t.global __do_global_dtors\n", asm_out_file);
11878 default_dtor_section_asm_out_destructor (symbol, priority);
11879}
11880
0dff9558 11881
11882/* Worker function for `TARGET_RETURN_IN_MEMORY'. */
6644435d 11883
cfd55026 11884static bool
fb80456a 11885avr_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
cfd55026 11886{
b4e6d2e2 11887 HOST_WIDE_INT size = int_size_in_bytes (type);
1a96adb9 11888 HOST_WIDE_INT ret_size_limit = AVR_TINY ? 4 : 8;
b4e6d2e2 11889
1a96adb9 11890 /* In avr, there are 8 return registers. But, for Tiny Core
11891 (ATtiny4/5/9/10/20/40) devices, only 4 registers are available.
11892 Return true if size is unknown or greater than the limit. */
11893
11894 if (size == -1 || size > ret_size_limit)
11895 {
11896 return true;
11897 }
39cc9599 11898 else
1a96adb9 11899 {
11900 return false;
11901 }
cfd55026 11902}
11903
6d8ed506 11904
11905/* Implement `CASE_VALUES_THRESHOLD'. */
11906/* Supply the default for --param case-values-threshold=0 */
b4a3be2d 11907
a45076aa 11908static unsigned int
11909avr_case_values_threshold (void)
b4a3be2d 11910{
6d8ed506 11911 /* The exact break-even point between a jump table and an if-else tree
11912 depends on several factors not available here like, e.g. if 8-bit
11913 comparisons can be used in the if-else tree or not, on the
11914 range of the case values, if the case value can be reused, on the
11915 register allocation, etc. '7' appears to be a good choice. */
0dff9558 11916
6d8ed506 11917 return 7;
b4a3be2d 11918}
11919
4202ef11 11920
11921/* Implement `TARGET_ADDR_SPACE_ADDRESS_MODE'. */
11922
3754d046 11923static machine_mode
5bd39e93 11924avr_addr_space_address_mode (addr_space_t as)
4202ef11 11925{
9d734fa8 11926 return avr_addrspace[as].pointer_size == 3 ? PSImode : HImode;
4202ef11 11927}
11928
11929
11930/* Implement `TARGET_ADDR_SPACE_POINTER_MODE'. */
11931
3754d046 11932static machine_mode
5bd39e93 11933avr_addr_space_pointer_mode (addr_space_t as)
4202ef11 11934{
9d734fa8 11935 return avr_addr_space_address_mode (as);
4202ef11 11936}
11937
11938
11939/* Helper for following function. */
11940
11941static bool
11942avr_reg_ok_for_pgm_addr (rtx reg, bool strict)
11943{
be6d8823 11944 gcc_assert (REG_P (reg));
4202ef11 11945
11946 if (strict)
11947 {
11948 return REGNO (reg) == REG_Z;
11949 }
0dff9558 11950
4202ef11 11951 /* Avoid combine to propagate hard regs. */
0dff9558 11952
4202ef11 11953 if (can_create_pseudo_p()
11954 && REGNO (reg) < REG_Z)
11955 {
11956 return false;
11957 }
0dff9558 11958
4202ef11 11959 return true;
11960}
11961
11962
11963/* Implement `TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P'. */
11964
11965static bool
3754d046 11966avr_addr_space_legitimate_address_p (machine_mode mode, rtx x,
4202ef11 11967 bool strict, addr_space_t as)
11968{
11969 bool ok = false;
11970
11971 switch (as)
11972 {
11973 default:
11974 gcc_unreachable();
0dff9558 11975
4202ef11 11976 case ADDR_SPACE_GENERIC:
11977 return avr_legitimate_address_p (mode, x, strict);
11978
590da9f2 11979 case ADDR_SPACE_FLASH:
11980 case ADDR_SPACE_FLASH1:
11981 case ADDR_SPACE_FLASH2:
11982 case ADDR_SPACE_FLASH3:
11983 case ADDR_SPACE_FLASH4:
11984 case ADDR_SPACE_FLASH5:
4202ef11 11985
11986 switch (GET_CODE (x))
11987 {
11988 case REG:
11989 ok = avr_reg_ok_for_pgm_addr (x, strict);
11990 break;
0dff9558 11991
4202ef11 11992 case POST_INC:
5bd39e93 11993 ok = avr_reg_ok_for_pgm_addr (XEXP (x, 0), strict);
4202ef11 11994 break;
0dff9558 11995
4202ef11 11996 default:
11997 break;
11998 }
11999
590da9f2 12000 break; /* FLASH */
0dff9558 12001
590da9f2 12002 case ADDR_SPACE_MEMX:
5bd39e93 12003 if (REG_P (x))
12004 ok = (!strict
12005 && can_create_pseudo_p());
12006
12007 if (LO_SUM == GET_CODE (x))
12008 {
12009 rtx hi = XEXP (x, 0);
12010 rtx lo = XEXP (x, 1);
12011
12012 ok = (REG_P (hi)
12013 && (!strict || REGNO (hi) < FIRST_PSEUDO_REGISTER)
12014 && REG_P (lo)
12015 && REGNO (lo) == REG_Z);
12016 }
0dff9558 12017
590da9f2 12018 break; /* MEMX */
4202ef11 12019 }
12020
12021 if (avr_log.legitimate_address_p)
12022 {
12023 avr_edump ("\n%?: ret=%b, mode=%m strict=%d "
12024 "reload_completed=%d reload_in_progress=%d %s:",
12025 ok, mode, strict, reload_completed, reload_in_progress,
12026 reg_renumber ? "(reg_renumber)" : "");
0dff9558 12027
4202ef11 12028 if (GET_CODE (x) == PLUS
12029 && REG_P (XEXP (x, 0))
12030 && CONST_INT_P (XEXP (x, 1))
12031 && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
12032 && reg_renumber)
12033 {
12034 avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
12035 true_regnum (XEXP (x, 0)));
12036 }
0dff9558 12037
4202ef11 12038 avr_edump ("\n%r\n", x);
12039 }
12040
12041 return ok;
12042}
12043
12044
12045/* Implement `TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS'. */
12046
12047static rtx
12048avr_addr_space_legitimize_address (rtx x, rtx old_x,
3754d046 12049 machine_mode mode, addr_space_t as)
4202ef11 12050{
12051 if (ADDR_SPACE_GENERIC_P (as))
12052 return avr_legitimize_address (x, old_x, mode);
12053
12054 if (avr_log.legitimize_address)
12055 {
12056 avr_edump ("\n%?: mode=%m\n %r\n", mode, old_x);
12057 }
12058
12059 return old_x;
12060}
12061
12062
12063/* Implement `TARGET_ADDR_SPACE_CONVERT'. */
12064
12065static rtx
12066avr_addr_space_convert (rtx src, tree type_from, tree type_to)
12067{
5bd39e93 12068 addr_space_t as_from = TYPE_ADDR_SPACE (TREE_TYPE (type_from));
12069 addr_space_t as_to = TYPE_ADDR_SPACE (TREE_TYPE (type_to));
12070
4202ef11 12071 if (avr_log.progmem)
12072 avr_edump ("\n%!: op = %r\nfrom = %t\nto = %t\n",
12073 src, type_from, type_to);
12074
ed2541ea 12075 /* Up-casting from 16-bit to 24-bit pointer. */
0dff9558 12076
590da9f2 12077 if (as_from != ADDR_SPACE_MEMX
12078 && as_to == ADDR_SPACE_MEMX)
5bd39e93 12079 {
ed2541ea 12080 int msb;
12081 rtx sym = src;
12082 rtx reg = gen_reg_rtx (PSImode);
12083
12084 while (CONST == GET_CODE (sym) || PLUS == GET_CODE (sym))
12085 sym = XEXP (sym, 0);
12086
12087 /* Look at symbol flags: avr_encode_section_info set the flags
12088 also if attribute progmem was seen so that we get the right
12089 promotion for, e.g. PSTR-like strings that reside in generic space
12090 but are located in flash. In that case we patch the incoming
12091 address space. */
5bd39e93 12092
ed2541ea 12093 if (SYMBOL_REF == GET_CODE (sym)
590da9f2 12094 && ADDR_SPACE_FLASH == AVR_SYMBOL_GET_ADDR_SPACE (sym))
5bd39e93 12095 {
590da9f2 12096 as_from = ADDR_SPACE_FLASH;
5bd39e93 12097 }
12098
ed2541ea 12099 /* Linearize memory: RAM has bit 23 set. */
0dff9558 12100
ed2541ea 12101 msb = ADDR_SPACE_GENERIC_P (as_from)
12102 ? 0x80
e508bf98 12103 : avr_addrspace[as_from].segment;
ed2541ea 12104
5bd39e93 12105 src = force_reg (Pmode, src);
0dff9558 12106
ed2541ea 12107 emit_insn (msb == 0
12108 ? gen_zero_extendhipsi2 (reg, src)
12109 : gen_n_extendhipsi2 (reg, gen_int_mode (msb, QImode), src));
0dff9558 12110
ed2541ea 12111 return reg;
12112 }
5bd39e93 12113
ed2541ea 12114 /* Down-casting from 24-bit to 16-bit throws away the high byte. */
5bd39e93 12115
590da9f2 12116 if (as_from == ADDR_SPACE_MEMX
12117 && as_to != ADDR_SPACE_MEMX)
ed2541ea 12118 {
12119 rtx new_src = gen_reg_rtx (Pmode);
12120
12121 src = force_reg (PSImode, src);
0dff9558 12122
ed2541ea 12123 emit_move_insn (new_src,
12124 simplify_gen_subreg (Pmode, src, PSImode, 0));
12125 return new_src;
5bd39e93 12126 }
0dff9558 12127
4202ef11 12128 return src;
12129}
12130
12131
12132/* Implement `TARGET_ADDR_SPACE_SUBSET_P'. */
12133
12134static bool
ed2541ea 12135avr_addr_space_subset_p (addr_space_t subset ATTRIBUTE_UNUSED,
12136 addr_space_t superset ATTRIBUTE_UNUSED)
4202ef11 12137{
ed2541ea 12138 /* Allow any kind of pointer mess. */
0dff9558 12139
5bd39e93 12140 return true;
12141}
12142
12143
1c72da59 12144/* Implement `TARGET_CONVERT_TO_TYPE'. */
12145
12146static tree
12147avr_convert_to_type (tree type, tree expr)
12148{
12149 /* Print a diagnose for pointer conversion that changes the address
12150 space of the pointer target to a non-enclosing address space,
12151 provided -Waddr-space-convert is on.
12152
12153 FIXME: Filter out cases where the target object is known to
12154 be located in the right memory, like in
12155
12156 (const __flash*) PSTR ("text")
12157
12158 Also try to distinguish between explicit casts requested by
12159 the user and implicit casts like
12160
12161 void f (const __flash char*);
12162
12163 void g (const char *p)
12164 {
12165 f ((const __flash*) p);
12166 }
12167
12168 under the assumption that an explicit casts means that the user
12169 knows what he is doing, e.g. interface with PSTR or old style
12170 code with progmem and pgm_read_xxx.
12171 */
12172
12173 if (avr_warn_addr_space_convert
12174 && expr != error_mark_node
12175 && POINTER_TYPE_P (type)
12176 && POINTER_TYPE_P (TREE_TYPE (expr)))
12177 {
12178 addr_space_t as_old = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (expr)));
12179 addr_space_t as_new = TYPE_ADDR_SPACE (TREE_TYPE (type));
1a96adb9 12180
1c72da59 12181 if (avr_log.progmem)
12182 avr_edump ("%?: type = %t\nexpr = %t\n\n", type, expr);
12183
12184 if (as_new != ADDR_SPACE_MEMX
12185 && as_new != as_old)
12186 {
12187 location_t loc = EXPR_LOCATION (expr);
12188 const char *name_old = avr_addrspace[as_old].name;
12189 const char *name_new = avr_addrspace[as_new].name;
12190
12191 warning (OPT_Waddr_space_convert,
12192 "conversion from address space %qs to address space %qs",
12193 ADDR_SPACE_GENERIC_P (as_old) ? "generic" : name_old,
12194 ADDR_SPACE_GENERIC_P (as_new) ? "generic" : name_new);
12195
12196 return fold_build1_loc (loc, ADDR_SPACE_CONVERT_EXPR, type, expr);
12197 }
12198 }
12199
12200 return NULL_TREE;
12201}
12202
12203
ed2541ea 12204/* Worker function for movmemhi expander.
5bd39e93 12205 XOP[0] Destination as MEM:BLK
12206 XOP[1] Source " "
12207 XOP[2] # Bytes to copy
12208
12209 Return TRUE if the expansion is accomplished.
12210 Return FALSE if the operand compination is not supported. */
12211
12212bool
12213avr_emit_movmemhi (rtx *xop)
12214{
12215 HOST_WIDE_INT count;
3754d046 12216 machine_mode loop_mode;
5bd39e93 12217 addr_space_t as = MEM_ADDR_SPACE (xop[1]);
f1222c71 12218 rtx loop_reg, addr1, a_src, a_dest, insn, xas;
5bd39e93 12219 rtx a_hi8 = NULL_RTX;
12220
590da9f2 12221 if (avr_mem_flash_p (xop[0]))
5bd39e93 12222 return false;
12223
12224 if (!CONST_INT_P (xop[2]))
12225 return false;
12226
12227 count = INTVAL (xop[2]);
12228 if (count <= 0)
12229 return false;
12230
12231 a_src = XEXP (xop[1], 0);
12232 a_dest = XEXP (xop[0], 0);
12233
5bd39e93 12234 if (PSImode == GET_MODE (a_src))
12235 {
590da9f2 12236 gcc_assert (as == ADDR_SPACE_MEMX);
ed2541ea 12237
12238 loop_mode = (count < 0x100) ? QImode : HImode;
12239 loop_reg = gen_rtx_REG (loop_mode, 24);
12240 emit_move_insn (loop_reg, gen_int_mode (count, loop_mode));
12241
5bd39e93 12242 addr1 = simplify_gen_subreg (HImode, a_src, PSImode, 0);
12243 a_hi8 = simplify_gen_subreg (QImode, a_src, PSImode, 2);
12244 }
12245 else
12246 {
e508bf98 12247 int segment = avr_addrspace[as].segment;
0dff9558 12248
ed2541ea 12249 if (segment
c0d7a1d0 12250 && avr_n_flash > 1)
ed2541ea 12251 {
12252 a_hi8 = GEN_INT (segment);
12253 emit_move_insn (rampz_rtx, a_hi8 = copy_to_mode_reg (QImode, a_hi8));
12254 }
12255 else if (!ADDR_SPACE_GENERIC_P (as))
12256 {
590da9f2 12257 as = ADDR_SPACE_FLASH;
ed2541ea 12258 }
0dff9558 12259
5bd39e93 12260 addr1 = a_src;
12261
ed2541ea 12262 loop_mode = (count <= 0x100) ? QImode : HImode;
12263 loop_reg = copy_to_mode_reg (loop_mode, gen_int_mode (count, loop_mode));
5bd39e93 12264 }
12265
12266 xas = GEN_INT (as);
12267
5bd39e93 12268 /* FIXME: Register allocator might come up with spill fails if it is left
ed2541ea 12269 on its own. Thus, we allocate the pointer registers by hand:
12270 Z = source address
12271 X = destination address */
5bd39e93 12272
12273 emit_move_insn (lpm_addr_reg_rtx, addr1);
f1222c71 12274 emit_move_insn (gen_rtx_REG (HImode, REG_X), a_dest);
5bd39e93 12275
12276 /* FIXME: Register allocator does a bad job and might spill address
12277 register(s) inside the loop leading to additional move instruction
12278 to/from stack which could clobber tmp_reg. Thus, do *not* emit
9d75589a 12279 load and store as separate insns. Instead, we perform the copy
5bd39e93 12280 by means of one monolithic insn. */
12281
ed2541ea 12282 gcc_assert (TMP_REGNO == LPM_REGNO);
12283
590da9f2 12284 if (as != ADDR_SPACE_MEMX)
5bd39e93 12285 {
ed2541ea 12286 /* Load instruction ([E]LPM or LD) is known at compile time:
12287 Do the copy-loop inline. */
0dff9558 12288
f1222c71 12289 rtx (*fun) (rtx, rtx, rtx)
5bd39e93 12290 = QImode == loop_mode ? gen_movmem_qi : gen_movmem_hi;
12291
f1222c71 12292 insn = fun (xas, loop_reg, loop_reg);
5bd39e93 12293 }
5bd39e93 12294 else
12295 {
f1222c71 12296 rtx (*fun) (rtx, rtx)
ed2541ea 12297 = QImode == loop_mode ? gen_movmemx_qi : gen_movmemx_hi;
12298
f1222c71 12299 emit_move_insn (gen_rtx_REG (QImode, 23), a_hi8);
0dff9558 12300
f1222c71 12301 insn = fun (xas, GEN_INT (avr_addr.rampz));
5bd39e93 12302 }
12303
12304 set_mem_addr_space (SET_SRC (XVECEXP (insn, 0, 0)), as);
12305 emit_insn (insn);
12306
4202ef11 12307 return true;
12308}
12309
12310
5bd39e93 12311/* Print assembler for movmem_qi, movmem_hi insns...
f1222c71 12312 $0 : Address Space
12313 $1, $2 : Loop register
12314 Z : Source address
12315 X : Destination address
5bd39e93 12316*/
12317
12318const char*
375204de 12319avr_out_movmem (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
5bd39e93 12320{
f1222c71 12321 addr_space_t as = (addr_space_t) INTVAL (op[0]);
3754d046 12322 machine_mode loop_mode = GET_MODE (op[1]);
f1222c71 12323 bool sbiw_p = test_hard_reg_class (ADDW_REGS, op[1]);
12324 rtx xop[3];
5bd39e93 12325
12326 if (plen)
12327 *plen = 0;
12328
f1222c71 12329 xop[0] = op[0];
12330 xop[1] = op[1];
12331 xop[2] = tmp_reg_rtx;
12332
5bd39e93 12333 /* Loop label */
12334
12335 avr_asm_len ("0:", xop, plen, 0);
12336
12337 /* Load with post-increment */
12338
12339 switch (as)
12340 {
12341 default:
12342 gcc_unreachable();
0dff9558 12343
5bd39e93 12344 case ADDR_SPACE_GENERIC:
12345
f1222c71 12346 avr_asm_len ("ld %2,Z+", xop, plen, 1);
5bd39e93 12347 break;
0dff9558 12348
590da9f2 12349 case ADDR_SPACE_FLASH:
5bd39e93 12350
12351 if (AVR_HAVE_LPMX)
6bdcc5e4 12352 avr_asm_len ("lpm %2,Z+", xop, plen, 1);
5bd39e93 12353 else
12354 avr_asm_len ("lpm" CR_TAB
f1222c71 12355 "adiw r30,1", xop, plen, 2);
5bd39e93 12356 break;
0dff9558 12357
590da9f2 12358 case ADDR_SPACE_FLASH1:
12359 case ADDR_SPACE_FLASH2:
12360 case ADDR_SPACE_FLASH3:
12361 case ADDR_SPACE_FLASH4:
12362 case ADDR_SPACE_FLASH5:
5bd39e93 12363
12364 if (AVR_HAVE_ELPMX)
f1222c71 12365 avr_asm_len ("elpm %2,Z+", xop, plen, 1);
5bd39e93 12366 else
12367 avr_asm_len ("elpm" CR_TAB
f1222c71 12368 "adiw r30,1", xop, plen, 2);
5bd39e93 12369 break;
12370 }
12371
12372 /* Store with post-increment */
12373
f1222c71 12374 avr_asm_len ("st X+,%2", xop, plen, 1);
5bd39e93 12375
12376 /* Decrement loop-counter and set Z-flag */
12377
12378 if (QImode == loop_mode)
12379 {
f1222c71 12380 avr_asm_len ("dec %1", xop, plen, 1);
5bd39e93 12381 }
12382 else if (sbiw_p)
12383 {
f1222c71 12384 avr_asm_len ("sbiw %1,1", xop, plen, 1);
5bd39e93 12385 }
12386 else
12387 {
f1222c71 12388 avr_asm_len ("subi %A1,1" CR_TAB
12389 "sbci %B1,0", xop, plen, 2);
5bd39e93 12390 }
12391
12392 /* Loop until zero */
0dff9558 12393
5bd39e93 12394 return avr_asm_len ("brne 0b", xop, plen, 1);
12395}
12396
12397
12398\f
c5be380e 12399/* Helper for __builtin_avr_delay_cycles */
12400
5af5ea69 12401static rtx
12402avr_mem_clobber (void)
12403{
12404 rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
12405 MEM_VOLATILE_P (mem) = 1;
12406 return mem;
12407}
12408
c5be380e 12409static void
12410avr_expand_delay_cycles (rtx operands0)
12411{
c1a60a68 12412 unsigned HOST_WIDE_INT cycles = UINTVAL (operands0) & GET_MODE_MASK (SImode);
c5be380e 12413 unsigned HOST_WIDE_INT cycles_used;
12414 unsigned HOST_WIDE_INT loop_count;
0dff9558 12415
c5be380e 12416 if (IN_RANGE (cycles, 83886082, 0xFFFFFFFF))
12417 {
12418 loop_count = ((cycles - 9) / 6) + 1;
12419 cycles_used = ((loop_count - 1) * 6) + 9;
5af5ea69 12420 emit_insn (gen_delay_cycles_4 (gen_int_mode (loop_count, SImode),
12421 avr_mem_clobber()));
c5be380e 12422 cycles -= cycles_used;
12423 }
0dff9558 12424
c5be380e 12425 if (IN_RANGE (cycles, 262145, 83886081))
12426 {
12427 loop_count = ((cycles - 7) / 5) + 1;
12428 if (loop_count > 0xFFFFFF)
12429 loop_count = 0xFFFFFF;
12430 cycles_used = ((loop_count - 1) * 5) + 7;
5af5ea69 12431 emit_insn (gen_delay_cycles_3 (gen_int_mode (loop_count, SImode),
12432 avr_mem_clobber()));
c5be380e 12433 cycles -= cycles_used;
12434 }
0dff9558 12435
c5be380e 12436 if (IN_RANGE (cycles, 768, 262144))
12437 {
12438 loop_count = ((cycles - 5) / 4) + 1;
12439 if (loop_count > 0xFFFF)
12440 loop_count = 0xFFFF;
12441 cycles_used = ((loop_count - 1) * 4) + 5;
5af5ea69 12442 emit_insn (gen_delay_cycles_2 (gen_int_mode (loop_count, HImode),
12443 avr_mem_clobber()));
c5be380e 12444 cycles -= cycles_used;
12445 }
0dff9558 12446
c5be380e 12447 if (IN_RANGE (cycles, 6, 767))
12448 {
12449 loop_count = cycles / 3;
0dff9558 12450 if (loop_count > 255)
c5be380e 12451 loop_count = 255;
12452 cycles_used = loop_count * 3;
5af5ea69 12453 emit_insn (gen_delay_cycles_1 (gen_int_mode (loop_count, QImode),
12454 avr_mem_clobber()));
c5be380e 12455 cycles -= cycles_used;
12456 }
0dff9558 12457
c5be380e 12458 while (cycles >= 2)
12459 {
12460 emit_insn (gen_nopv (GEN_INT(2)));
12461 cycles -= 2;
12462 }
12463
12464 if (cycles == 1)
12465 {
12466 emit_insn (gen_nopv (GEN_INT(1)));
12467 cycles--;
12468 }
12469}
12470
384f6361 12471
384f6361 12472/* Compute the image of x under f, i.e. perform x --> f(x) */
12473
12474static int
7b5733e8 12475avr_map (unsigned int f, int x)
384f6361 12476{
7b5733e8 12477 return x < 8 ? (f >> (4 * x)) & 0xf : 0;
384f6361 12478}
12479
12480
15b84087 12481/* Return some metrics of map A. */
384f6361 12482
15b84087 12483enum
12484 {
12485 /* Number of fixed points in { 0 ... 7 } */
12486 MAP_FIXED_0_7,
384f6361 12487
15b84087 12488 /* Size of preimage of non-fixed points in { 0 ... 7 } */
12489 MAP_NONFIXED_0_7,
0dff9558 12490
15b84087 12491 /* Mask representing the fixed points in { 0 ... 7 } */
12492 MAP_MASK_FIXED_0_7,
0dff9558 12493
15b84087 12494 /* Size of the preimage of { 0 ... 7 } */
12495 MAP_PREIMAGE_0_7,
0dff9558 12496
15b84087 12497 /* Mask that represents the preimage of { f } */
12498 MAP_MASK_PREIMAGE_F
12499 };
12500
12501static unsigned
7b5733e8 12502avr_map_metric (unsigned int a, int mode)
384f6361 12503{
15b84087 12504 unsigned i, metric = 0;
384f6361 12505
15b84087 12506 for (i = 0; i < 8; i++)
12507 {
12508 unsigned ai = avr_map (a, i);
384f6361 12509
15b84087 12510 if (mode == MAP_FIXED_0_7)
12511 metric += ai == i;
12512 else if (mode == MAP_NONFIXED_0_7)
12513 metric += ai < 8 && ai != i;
12514 else if (mode == MAP_MASK_FIXED_0_7)
12515 metric |= ((unsigned) (ai == i)) << i;
12516 else if (mode == MAP_PREIMAGE_0_7)
12517 metric += ai < 8;
12518 else if (mode == MAP_MASK_PREIMAGE_F)
12519 metric |= ((unsigned) (ai == 0xf)) << i;
12520 else
12521 gcc_unreachable();
12522 }
0dff9558 12523
15b84087 12524 return metric;
384f6361 12525}
12526
12527
15b84087 12528/* Return true if IVAL has a 0xf in its hexadecimal representation
12529 and false, otherwise. Only nibbles 0..7 are taken into account.
12530 Used as constraint helper for C0f and Cxf. */
384f6361 12531
15b84087 12532bool
12533avr_has_nibble_0xf (rtx ival)
12534{
7b5733e8 12535 unsigned int map = UINTVAL (ival) & GET_MODE_MASK (SImode);
12536 return 0 != avr_map_metric (map, MAP_MASK_PREIMAGE_F);
15b84087 12537}
384f6361 12538
384f6361 12539
15b84087 12540/* We have a set of bits that are mapped by a function F.
12541 Try to decompose F by means of a second function G so that
384f6361 12542
15b84087 12543 F = F o G^-1 o G
384f6361 12544
15b84087 12545 and
384f6361 12546
15b84087 12547 cost (F o G^-1) + cost (G) < cost (F)
384f6361 12548
15b84087 12549 Example: Suppose builtin insert_bits supplies us with the map
12550 F = 0x3210ffff. Instead of doing 4 bit insertions to get the high
12551 nibble of the result, we can just as well rotate the bits before inserting
12552 them and use the map 0x7654ffff which is cheaper than the original map.
12553 For this example G = G^-1 = 0x32107654 and F o G^-1 = 0x7654ffff. */
0dff9558 12554
15b84087 12555typedef struct
12556{
12557 /* tree code of binary function G */
12558 enum tree_code code;
384f6361 12559
15b84087 12560 /* The constant second argument of G */
12561 int arg;
384f6361 12562
15b84087 12563 /* G^-1, the inverse of G (*, arg) */
12564 unsigned ginv;
384f6361 12565
15b84087 12566 /* The cost of appplying G (*, arg) */
12567 int cost;
384f6361 12568
15b84087 12569 /* The composition F o G^-1 (*, arg) for some function F */
7b5733e8 12570 unsigned int map;
384f6361 12571
15b84087 12572 /* For debug purpose only */
12573 const char *str;
12574} avr_map_op_t;
384f6361 12575
15b84087 12576static const avr_map_op_t avr_map_op[] =
384f6361 12577 {
7b5733e8 12578 { LROTATE_EXPR, 0, 0x76543210, 0, 0, "id" },
12579 { LROTATE_EXPR, 1, 0x07654321, 2, 0, "<<<" },
12580 { LROTATE_EXPR, 2, 0x10765432, 4, 0, "<<<" },
12581 { LROTATE_EXPR, 3, 0x21076543, 4, 0, "<<<" },
12582 { LROTATE_EXPR, 4, 0x32107654, 1, 0, "<<<" },
12583 { LROTATE_EXPR, 5, 0x43210765, 3, 0, "<<<" },
12584 { LROTATE_EXPR, 6, 0x54321076, 5, 0, "<<<" },
12585 { LROTATE_EXPR, 7, 0x65432107, 3, 0, "<<<" },
12586 { RSHIFT_EXPR, 1, 0x6543210c, 1, 0, ">>" },
12587 { RSHIFT_EXPR, 1, 0x7543210c, 1, 0, ">>" },
12588 { RSHIFT_EXPR, 2, 0x543210cc, 2, 0, ">>" },
12589 { RSHIFT_EXPR, 2, 0x643210cc, 2, 0, ">>" },
12590 { RSHIFT_EXPR, 2, 0x743210cc, 2, 0, ">>" },
12591 { LSHIFT_EXPR, 1, 0xc7654321, 1, 0, "<<" },
12592 { LSHIFT_EXPR, 2, 0xcc765432, 2, 0, "<<" }
384f6361 12593 };
12594
12595
15b84087 12596/* Try to decompose F as F = (F o G^-1) o G as described above.
12597 The result is a struct representing F o G^-1 and G.
12598 If result.cost < 0 then such a decomposition does not exist. */
0dff9558 12599
15b84087 12600static avr_map_op_t
7b5733e8 12601avr_map_decompose (unsigned int f, const avr_map_op_t *g, bool val_const_p)
384f6361 12602{
15b84087 12603 int i;
12604 bool val_used_p = 0 != avr_map_metric (f, MAP_MASK_PREIMAGE_F);
12605 avr_map_op_t f_ginv = *g;
7b5733e8 12606 unsigned int ginv = g->ginv;
384f6361 12607
15b84087 12608 f_ginv.cost = -1;
0dff9558 12609
15b84087 12610 /* Step 1: Computing F o G^-1 */
384f6361 12611
15b84087 12612 for (i = 7; i >= 0; i--)
12613 {
12614 int x = avr_map (f, i);
0dff9558 12615
15b84087 12616 if (x <= 7)
12617 {
12618 x = avr_map (ginv, x);
384f6361 12619
15b84087 12620 /* The bit is no element of the image of G: no avail (cost = -1) */
0dff9558 12621
15b84087 12622 if (x > 7)
12623 return f_ginv;
12624 }
0dff9558 12625
7b5733e8 12626 f_ginv.map = (f_ginv.map << 4) + x;
15b84087 12627 }
384f6361 12628
15b84087 12629 /* Step 2: Compute the cost of the operations.
12630 The overall cost of doing an operation prior to the insertion is
12631 the cost of the insertion plus the cost of the operation. */
384f6361 12632
15b84087 12633 /* Step 2a: Compute cost of F o G^-1 */
384f6361 12634
15b84087 12635 if (0 == avr_map_metric (f_ginv.map, MAP_NONFIXED_0_7))
12636 {
12637 /* The mapping consists only of fixed points and can be folded
12638 to AND/OR logic in the remainder. Reasonable cost is 3. */
384f6361 12639
15b84087 12640 f_ginv.cost = 2 + (val_used_p && !val_const_p);
12641 }
12642 else
12643 {
12644 rtx xop[4];
384f6361 12645
15b84087 12646 /* Get the cost of the insn by calling the output worker with some
12647 fake values. Mimic effect of reloading xop[3]: Unused operands
12648 are mapped to 0 and used operands are reloaded to xop[0]. */
384f6361 12649
15b84087 12650 xop[0] = all_regs_rtx[24];
7b5733e8 12651 xop[1] = gen_int_mode (f_ginv.map, SImode);
15b84087 12652 xop[2] = all_regs_rtx[25];
12653 xop[3] = val_used_p ? xop[0] : const0_rtx;
0dff9558 12654
15b84087 12655 avr_out_insert_bits (xop, &f_ginv.cost);
0dff9558 12656
15b84087 12657 f_ginv.cost += val_const_p && val_used_p ? 1 : 0;
12658 }
0dff9558 12659
15b84087 12660 /* Step 2b: Add cost of G */
384f6361 12661
15b84087 12662 f_ginv.cost += g->cost;
384f6361 12663
15b84087 12664 if (avr_log.builtin)
12665 avr_edump (" %s%d=%d", g->str, g->arg, f_ginv.cost);
12666
12667 return f_ginv;
384f6361 12668}
12669
12670
15b84087 12671/* Insert bits from XOP[1] into XOP[0] according to MAP.
12672 XOP[0] and XOP[1] don't overlap.
12673 If FIXP_P = true: Move all bits according to MAP using BLD/BST sequences.
12674 If FIXP_P = false: Just move the bit if its position in the destination
12675 is different to its source position. */
384f6361 12676
12677static void
7b5733e8 12678avr_move_bits (rtx *xop, unsigned int map, bool fixp_p, int *plen)
384f6361 12679{
15b84087 12680 int bit_dest, b;
384f6361 12681
12682 /* T-flag contains this bit of the source, i.e. of XOP[1] */
12683 int t_bit_src = -1;
12684
384f6361 12685 /* We order the operations according to the requested source bit b. */
0dff9558 12686
15b84087 12687 for (b = 0; b < 8; b++)
12688 for (bit_dest = 0; bit_dest < 8; bit_dest++)
384f6361 12689 {
12690 int bit_src = avr_map (map, bit_dest);
0dff9558 12691
384f6361 12692 if (b != bit_src
15b84087 12693 || bit_src >= 8
12694 /* Same position: No need to copy as requested by FIXP_P. */
12695 || (bit_dest == bit_src && !fixp_p))
384f6361 12696 continue;
12697
12698 if (t_bit_src != bit_src)
12699 {
12700 /* Source bit is not yet in T: Store it to T. */
0dff9558 12701
384f6361 12702 t_bit_src = bit_src;
12703
15b84087 12704 xop[3] = GEN_INT (bit_src);
12705 avr_asm_len ("bst %T1%T3", xop, plen, 1);
384f6361 12706 }
12707
12708 /* Load destination bit with T. */
0dff9558 12709
15b84087 12710 xop[3] = GEN_INT (bit_dest);
12711 avr_asm_len ("bld %T0%T3", xop, plen, 1);
384f6361 12712 }
12713}
12714
12715
15b84087 12716/* PLEN == 0: Print assembler code for `insert_bits'.
12717 PLEN != 0: Compute code length in bytes.
0dff9558 12718
15b84087 12719 OP[0]: Result
12720 OP[1]: The mapping composed of nibbles. If nibble no. N is
12721 0: Bit N of result is copied from bit OP[2].0
12722 ... ...
12723 7: Bit N of result is copied from bit OP[2].7
12724 0xf: Bit N of result is copied from bit OP[3].N
12725 OP[2]: Bits to be inserted
12726 OP[3]: Target value */
384f6361 12727
12728const char*
15b84087 12729avr_out_insert_bits (rtx *op, int *plen)
384f6361 12730{
7b5733e8 12731 unsigned int map = UINTVAL (op[1]) & GET_MODE_MASK (SImode);
15b84087 12732 unsigned mask_fixed;
12733 bool fixp_p = true;
12734 rtx xop[4];
384f6361 12735
15b84087 12736 xop[0] = op[0];
12737 xop[1] = op[2];
12738 xop[2] = op[3];
384f6361 12739
15b84087 12740 gcc_assert (REG_P (xop[2]) || CONST_INT_P (xop[2]));
0dff9558 12741
384f6361 12742 if (plen)
12743 *plen = 0;
12744 else if (flag_print_asm_name)
7b5733e8 12745 fprintf (asm_out_file, ASM_COMMENT_START "map = 0x%08x\n", map);
384f6361 12746
15b84087 12747 /* If MAP has fixed points it might be better to initialize the result
12748 with the bits to be inserted instead of moving all bits by hand. */
0dff9558 12749
15b84087 12750 mask_fixed = avr_map_metric (map, MAP_MASK_FIXED_0_7);
384f6361 12751
15b84087 12752 if (REGNO (xop[0]) == REGNO (xop[1]))
12753 {
12754 /* Avoid early-clobber conflicts */
0dff9558 12755
15b84087 12756 avr_asm_len ("mov __tmp_reg__,%1", xop, plen, 1);
12757 xop[1] = tmp_reg_rtx;
12758 fixp_p = false;
384f6361 12759 }
12760
15b84087 12761 if (avr_map_metric (map, MAP_MASK_PREIMAGE_F))
384f6361 12762 {
15b84087 12763 /* XOP[2] is used and reloaded to XOP[0] already */
0dff9558 12764
15b84087 12765 int n_fix = 0, n_nofix = 0;
0dff9558 12766
15b84087 12767 gcc_assert (REG_P (xop[2]));
0dff9558 12768
15b84087 12769 /* Get the code size of the bit insertions; once with all bits
12770 moved and once with fixed points omitted. */
0dff9558 12771
15b84087 12772 avr_move_bits (xop, map, true, &n_fix);
12773 avr_move_bits (xop, map, false, &n_nofix);
12774
12775 if (fixp_p && n_fix - n_nofix > 3)
384f6361 12776 {
15b84087 12777 xop[3] = gen_int_mode (~mask_fixed, QImode);
0dff9558 12778
15b84087 12779 avr_asm_len ("eor %0,%1" CR_TAB
12780 "andi %0,%3" CR_TAB
12781 "eor %0,%1", xop, plen, 3);
12782 fixp_p = false;
384f6361 12783 }
12784 }
384f6361 12785 else
12786 {
15b84087 12787 /* XOP[2] is unused */
0dff9558 12788
15b84087 12789 if (fixp_p && mask_fixed)
12790 {
12791 avr_asm_len ("mov %0,%1", xop, plen, 1);
12792 fixp_p = false;
12793 }
384f6361 12794 }
0dff9558 12795
15b84087 12796 /* Move/insert remaining bits. */
384f6361 12797
15b84087 12798 avr_move_bits (xop, map, fixp_p, plen);
0dff9558 12799
384f6361 12800 return "";
12801}
12802
12803
c5be380e 12804/* IDs for all the AVR builtins. */
12805
12806enum avr_builtin_id
12807 {
f3297245 12808#define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
73263209 12809 AVR_BUILTIN_ ## NAME,
0dff9558 12810#include "builtins.def"
c19a2f5f 12811#undef DEF_BUILTIN
12812
12813 AVR_BUILTIN_COUNT
c5be380e 12814 };
12815
58cf0091 12816struct GTY(()) avr_builtin_description
12817{
12818 enum insn_code icode;
58cf0091 12819 int n_args;
12820 tree fndecl;
12821};
12822
12823
12824/* Notice that avr_bdesc[] and avr_builtin_id are initialized in such a way
12825 that a built-in's ID can be used to access the built-in by means of
12826 avr_bdesc[ID] */
12827
12828static GTY(()) struct avr_builtin_description
12829avr_bdesc[AVR_BUILTIN_COUNT] =
12830 {
f3297245 12831#define DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE, LIBNAME) \
73263209 12832 { (enum insn_code) CODE_FOR_ ## ICODE, N_ARGS, NULL_TREE },
0dff9558 12833#include "builtins.def"
58cf0091 12834#undef DEF_BUILTIN
12835 };
12836
12837
12838/* Implement `TARGET_BUILTIN_DECL'. */
12839
12840static tree
12841avr_builtin_decl (unsigned id, bool initialize_p ATTRIBUTE_UNUSED)
12842{
12843 if (id < AVR_BUILTIN_COUNT)
12844 return avr_bdesc[id].fndecl;
12845
12846 return error_mark_node;
12847}
12848
12849
02d9a2c3 12850static void
12851avr_init_builtin_int24 (void)
12852{
12853 tree int24_type = make_signed_type (GET_MODE_BITSIZE (PSImode));
12854 tree uint24_type = make_unsigned_type (GET_MODE_BITSIZE (PSImode));
12855
d0acfa59 12856 lang_hooks.types.register_builtin_type (int24_type, "__int24");
12857 lang_hooks.types.register_builtin_type (uint24_type, "__uint24");
02d9a2c3 12858}
12859
58cf0091 12860
c5be380e 12861/* Implement `TARGET_INIT_BUILTINS' */
12862/* Set up all builtin functions for this target. */
12863
12864static void
12865avr_init_builtins (void)
12866{
12867 tree void_ftype_void
c0010db9 12868 = build_function_type_list (void_type_node, NULL_TREE);
c5be380e 12869 tree uchar_ftype_uchar
0dff9558 12870 = build_function_type_list (unsigned_char_type_node,
c5be380e 12871 unsigned_char_type_node,
12872 NULL_TREE);
12873 tree uint_ftype_uchar_uchar
0dff9558 12874 = build_function_type_list (unsigned_type_node,
12875 unsigned_char_type_node,
c5be380e 12876 unsigned_char_type_node,
c5be380e 12877 NULL_TREE);
12878 tree int_ftype_char_char
0dff9558 12879 = build_function_type_list (integer_type_node,
12880 char_type_node,
c5be380e 12881 char_type_node,
c5be380e 12882 NULL_TREE);
12883 tree int_ftype_char_uchar
0dff9558 12884 = build_function_type_list (integer_type_node,
c5be380e 12885 char_type_node,
0dff9558 12886 unsigned_char_type_node,
c5be380e 12887 NULL_TREE);
12888 tree void_ftype_ulong
0dff9558 12889 = build_function_type_list (void_type_node,
c5be380e 12890 long_unsigned_type_node,
12891 NULL_TREE);
12892
15b84087 12893 tree uchar_ftype_ulong_uchar_uchar
384f6361 12894 = build_function_type_list (unsigned_char_type_node,
12895 long_unsigned_type_node,
12896 unsigned_char_type_node,
15b84087 12897 unsigned_char_type_node,
384f6361 12898 NULL_TREE);
12899
12ffadfa 12900 tree const_memx_void_node
73263209 12901 = build_qualified_type (void_type_node,
12902 TYPE_QUAL_CONST
12903 | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_MEMX));
12ffadfa 12904
12905 tree const_memx_ptr_type_node
73263209 12906 = build_pointer_type_for_mode (const_memx_void_node, PSImode, false);
0dff9558 12907
12ffadfa 12908 tree char_ftype_const_memx_ptr
73263209 12909 = build_function_type_list (char_type_node,
12910 const_memx_ptr_type_node,
12911 NULL);
12912
eafea251 12913#define ITYP(T) \
12914 lang_hooks.types.type_for_size (TYPE_PRECISION (T), TYPE_UNSIGNED (T))
1a96adb9 12915
eafea251 12916#define FX_FTYPE_FX(fx) \
12917 tree fx##r_ftype_##fx##r \
12918 = build_function_type_list (node_##fx##r, node_##fx##r, NULL); \
12919 tree fx##k_ftype_##fx##k \
12920 = build_function_type_list (node_##fx##k, node_##fx##k, NULL)
12921
12922#define FX_FTYPE_FX_INT(fx) \
12923 tree fx##r_ftype_##fx##r_int \
12924 = build_function_type_list (node_##fx##r, node_##fx##r, \
12925 integer_type_node, NULL); \
12926 tree fx##k_ftype_##fx##k_int \
12927 = build_function_type_list (node_##fx##k, node_##fx##k, \
12928 integer_type_node, NULL)
1a96adb9 12929
eafea251 12930#define INT_FTYPE_FX(fx) \
12931 tree int_ftype_##fx##r \
12932 = build_function_type_list (integer_type_node, node_##fx##r, NULL); \
12933 tree int_ftype_##fx##k \
12934 = build_function_type_list (integer_type_node, node_##fx##k, NULL)
12935
12936#define INTX_FTYPE_FX(fx) \
12937 tree int##fx##r_ftype_##fx##r \
12938 = build_function_type_list (ITYP (node_##fx##r), node_##fx##r, NULL); \
12939 tree int##fx##k_ftype_##fx##k \
12940 = build_function_type_list (ITYP (node_##fx##k), node_##fx##k, NULL)
12941
12942#define FX_FTYPE_INTX(fx) \
12943 tree fx##r_ftype_int##fx##r \
12944 = build_function_type_list (node_##fx##r, ITYP (node_##fx##r), NULL); \
12945 tree fx##k_ftype_int##fx##k \
12946 = build_function_type_list (node_##fx##k, ITYP (node_##fx##k), NULL)
12947
12948 tree node_hr = short_fract_type_node;
3e88585b 12949 tree node_nr = fract_type_node;
eafea251 12950 tree node_lr = long_fract_type_node;
12951 tree node_llr = long_long_fract_type_node;
12952
12953 tree node_uhr = unsigned_short_fract_type_node;
3e88585b 12954 tree node_unr = unsigned_fract_type_node;
eafea251 12955 tree node_ulr = unsigned_long_fract_type_node;
12956 tree node_ullr = unsigned_long_long_fract_type_node;
12957
12958 tree node_hk = short_accum_type_node;
3e88585b 12959 tree node_nk = accum_type_node;
eafea251 12960 tree node_lk = long_accum_type_node;
12961 tree node_llk = long_long_accum_type_node;
12962
12963 tree node_uhk = unsigned_short_accum_type_node;
3e88585b 12964 tree node_unk = unsigned_accum_type_node;
eafea251 12965 tree node_ulk = unsigned_long_accum_type_node;
12966 tree node_ullk = unsigned_long_long_accum_type_node;
12967
12968
12969 /* For absfx builtins. */
12970
12971 FX_FTYPE_FX (h);
3e88585b 12972 FX_FTYPE_FX (n);
eafea251 12973 FX_FTYPE_FX (l);
12974 FX_FTYPE_FX (ll);
12975
12976 /* For roundfx builtins. */
12977
12978 FX_FTYPE_FX_INT (h);
3e88585b 12979 FX_FTYPE_FX_INT (n);
eafea251 12980 FX_FTYPE_FX_INT (l);
12981 FX_FTYPE_FX_INT (ll);
12982
12983 FX_FTYPE_FX_INT (uh);
3e88585b 12984 FX_FTYPE_FX_INT (un);
eafea251 12985 FX_FTYPE_FX_INT (ul);
12986 FX_FTYPE_FX_INT (ull);
12987
12988 /* For countlsfx builtins. */
12989
12990 INT_FTYPE_FX (h);
3e88585b 12991 INT_FTYPE_FX (n);
eafea251 12992 INT_FTYPE_FX (l);
12993 INT_FTYPE_FX (ll);
12994
12995 INT_FTYPE_FX (uh);
3e88585b 12996 INT_FTYPE_FX (un);
eafea251 12997 INT_FTYPE_FX (ul);
12998 INT_FTYPE_FX (ull);
12999
13000 /* For bitsfx builtins. */
13001
13002 INTX_FTYPE_FX (h);
3e88585b 13003 INTX_FTYPE_FX (n);
eafea251 13004 INTX_FTYPE_FX (l);
13005 INTX_FTYPE_FX (ll);
13006
13007 INTX_FTYPE_FX (uh);
3e88585b 13008 INTX_FTYPE_FX (un);
eafea251 13009 INTX_FTYPE_FX (ul);
13010 INTX_FTYPE_FX (ull);
13011
13012 /* For fxbits builtins. */
13013
13014 FX_FTYPE_INTX (h);
3e88585b 13015 FX_FTYPE_INTX (n);
eafea251 13016 FX_FTYPE_INTX (l);
13017 FX_FTYPE_INTX (ll);
13018
13019 FX_FTYPE_INTX (uh);
3e88585b 13020 FX_FTYPE_INTX (un);
eafea251 13021 FX_FTYPE_INTX (ul);
13022 FX_FTYPE_INTX (ull);
13023
13024
f3297245 13025#define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
73263209 13026 { \
13027 int id = AVR_BUILTIN_ ## NAME; \
13028 const char *Name = "__builtin_avr_" #NAME; \
13029 char *name = (char*) alloca (1 + strlen (Name)); \
13030 \
13031 gcc_assert (id < AVR_BUILTIN_COUNT); \
13032 avr_bdesc[id].fndecl \
13033 = add_builtin_function (avr_tolower (name, Name), TYPE, id, \
f3297245 13034 BUILT_IN_MD, LIBNAME, NULL_TREE); \
73263209 13035 }
0dff9558 13036#include "builtins.def"
c19a2f5f 13037#undef DEF_BUILTIN
0dff9558 13038
02d9a2c3 13039 avr_init_builtin_int24 ();
c5be380e 13040}
13041
c5be380e 13042
d0acfa59 13043/* Subroutine of avr_expand_builtin to expand vanilla builtins
13044 with non-void result and 1 ... 3 arguments. */
c5be380e 13045
13046static rtx
d0acfa59 13047avr_default_expand_builtin (enum insn_code icode, tree exp, rtx target)
c5be380e 13048{
d0acfa59 13049 rtx pat, xop[3];
13050 int n, n_args = call_expr_nargs (exp);
3754d046 13051 machine_mode tmode = insn_data[icode].operand[0].mode;
c5be380e 13052
d0acfa59 13053 gcc_assert (n_args >= 1 && n_args <= 3);
0dff9558 13054
d0acfa59 13055 if (target == NULL_RTX
c5be380e 13056 || GET_MODE (target) != tmode
d0acfa59 13057 || !insn_data[icode].operand[0].predicate (target, tmode))
c5be380e 13058 {
13059 target = gen_reg_rtx (tmode);
13060 }
13061
d0acfa59 13062 for (n = 0; n < n_args; n++)
c5be380e 13063 {
d0acfa59 13064 tree arg = CALL_EXPR_ARG (exp, n);
13065 rtx op = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
3754d046 13066 machine_mode opmode = GET_MODE (op);
13067 machine_mode mode = insn_data[icode].operand[n+1].mode;
c5be380e 13068
d0acfa59 13069 if ((opmode == SImode || opmode == VOIDmode) && mode == HImode)
13070 {
13071 opmode = HImode;
13072 op = gen_lowpart (HImode, op);
13073 }
c5be380e 13074
d0acfa59 13075 /* In case the insn wants input operands in modes different from
13076 the result, abort. */
0dff9558 13077
d0acfa59 13078 gcc_assert (opmode == mode || opmode == VOIDmode);
c5be380e 13079
d0acfa59 13080 if (!insn_data[icode].operand[n+1].predicate (op, mode))
13081 op = copy_to_mode_reg (mode, op);
c5be380e 13082
d0acfa59 13083 xop[n] = op;
c5be380e 13084 }
13085
d0acfa59 13086 switch (n_args)
c5be380e 13087 {
d0acfa59 13088 case 1: pat = GEN_FCN (icode) (target, xop[0]); break;
13089 case 2: pat = GEN_FCN (icode) (target, xop[0], xop[1]); break;
13090 case 3: pat = GEN_FCN (icode) (target, xop[0], xop[1], xop[2]); break;
c5be380e 13091
d0acfa59 13092 default:
13093 gcc_unreachable();
15b84087 13094 }
0dff9558 13095
d0acfa59 13096 if (pat == NULL_RTX)
13097 return NULL_RTX;
15b84087 13098
13099 emit_insn (pat);
d0acfa59 13100
15b84087 13101 return target;
13102}
13103
c5be380e 13104
58cf0091 13105/* Implement `TARGET_EXPAND_BUILTIN'. */
c5be380e 13106/* Expand an expression EXP that calls a built-in function,
13107 with result going to TARGET if that's convenient
13108 (and in mode MODE if that's convenient).
13109 SUBTARGET may be used as the target for computing one of EXP's operands.
13110 IGNORE is nonzero if the value is to be ignored. */
13111
13112static rtx
13113avr_expand_builtin (tree exp, rtx target,
13114 rtx subtarget ATTRIBUTE_UNUSED,
3754d046 13115 machine_mode mode ATTRIBUTE_UNUSED,
f3297245 13116 int ignore)
c5be380e 13117{
c5be380e 13118 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
d0acfa59 13119 const char *bname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
c5be380e 13120 unsigned int id = DECL_FUNCTION_CODE (fndecl);
58cf0091 13121 const struct avr_builtin_description *d = &avr_bdesc[id];
c5be380e 13122 tree arg0;
13123 rtx op0;
13124
58cf0091 13125 gcc_assert (id < AVR_BUILTIN_COUNT);
13126
c5be380e 13127 switch (id)
13128 {
13129 case AVR_BUILTIN_NOP:
13130 emit_insn (gen_nopv (GEN_INT(1)));
13131 return 0;
0dff9558 13132
c5be380e 13133 case AVR_BUILTIN_DELAY_CYCLES:
13134 {
13135 arg0 = CALL_EXPR_ARG (exp, 0);
1086ba15 13136 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
c5be380e 13137
c19a2f5f 13138 if (!CONST_INT_P (op0))
384f6361 13139 error ("%s expects a compile time integer constant", bname);
c19a2f5f 13140 else
13141 avr_expand_delay_cycles (op0);
c5be380e 13142
d0acfa59 13143 return NULL_RTX;
c5be380e 13144 }
384f6361 13145
15b84087 13146 case AVR_BUILTIN_INSERT_BITS:
384f6361 13147 {
13148 arg0 = CALL_EXPR_ARG (exp, 0);
13149 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
13150
13151 if (!CONST_INT_P (op0))
13152 {
13153 error ("%s expects a compile time long integer constant"
13154 " as first argument", bname);
13155 return target;
13156 }
eafea251 13157
13158 break;
384f6361 13159 }
eafea251 13160
13161 case AVR_BUILTIN_ROUNDHR: case AVR_BUILTIN_ROUNDUHR:
13162 case AVR_BUILTIN_ROUNDR: case AVR_BUILTIN_ROUNDUR:
13163 case AVR_BUILTIN_ROUNDLR: case AVR_BUILTIN_ROUNDULR:
13164 case AVR_BUILTIN_ROUNDLLR: case AVR_BUILTIN_ROUNDULLR:
13165
13166 case AVR_BUILTIN_ROUNDHK: case AVR_BUILTIN_ROUNDUHK:
13167 case AVR_BUILTIN_ROUNDK: case AVR_BUILTIN_ROUNDUK:
13168 case AVR_BUILTIN_ROUNDLK: case AVR_BUILTIN_ROUNDULK:
13169 case AVR_BUILTIN_ROUNDLLK: case AVR_BUILTIN_ROUNDULLK:
13170
13171 /* Warn about odd rounding. Rounding points >= FBIT will have
13172 no effect. */
1a96adb9 13173
eafea251 13174 if (TREE_CODE (CALL_EXPR_ARG (exp, 1)) != INTEGER_CST)
13175 break;
13176
f9ae6f95 13177 int rbit = (int) TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1));
eafea251 13178
13179 if (rbit >= (int) GET_MODE_FBIT (mode))
13180 {
13181 warning (OPT_Wextra, "rounding to %d bits has no effect for "
13182 "fixed-point value with %d fractional bits",
13183 rbit, GET_MODE_FBIT (mode));
13184
13185 return expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX, mode,
13186 EXPAND_NORMAL);
13187 }
13188 else if (rbit <= - (int) GET_MODE_IBIT (mode))
13189 {
13190 warning (0, "rounding result will always be 0");
13191 return CONST0_RTX (mode);
13192 }
13193
13194 /* The rounding points RP satisfies now: -IBIT < RP < FBIT.
13195
13196 TR 18037 only specifies results for RP > 0. However, the
13197 remaining cases of -IBIT < RP <= 0 can easily be supported
13198 without any additional overhead. */
13199
13200 break; /* round */
c5be380e 13201 }
13202
f3297245 13203 /* No fold found and no insn: Call support function from libgcc. */
13204
13205 if (d->icode == CODE_FOR_nothing
13206 && DECL_ASSEMBLER_NAME (get_callee_fndecl (exp)) != NULL_TREE)
13207 {
13208 return expand_call (exp, target, ignore);
13209 }
13210
58cf0091 13211 /* No special treatment needed: vanilla expand. */
d0acfa59 13212
73263209 13213 gcc_assert (d->icode != CODE_FOR_nothing);
d0acfa59 13214 gcc_assert (d->n_args == call_expr_nargs (exp));
13215
13216 if (d->n_args == 0)
c19a2f5f 13217 {
58cf0091 13218 emit_insn ((GEN_FCN (d->icode)) (target));
d0acfa59 13219 return NULL_RTX;
c19a2f5f 13220 }
d0acfa59 13221
13222 return avr_default_expand_builtin (d->icode, exp, target);
c5be380e 13223}
13224
15b84087 13225
f3297245 13226/* Helper for `avr_fold_builtin' that folds absfx (FIXED_CST). */
13227
13228static tree
13229avr_fold_absfx (tree tval)
13230{
13231 if (FIXED_CST != TREE_CODE (tval))
13232 return NULL_TREE;
13233
13234 /* Our fixed-points have no padding: Use double_int payload directly. */
13235
13236 FIXED_VALUE_TYPE fval = TREE_FIXED_CST (tval);
13237 unsigned int bits = GET_MODE_BITSIZE (fval.mode);
13238 double_int ival = fval.data.sext (bits);
13239
13240 if (!ival.is_negative())
13241 return tval;
13242
13243 /* ISO/IEC TR 18037, 7.18a.6.2: The absfx functions are saturating. */
13244
13245 fval.data = (ival == double_int::min_value (bits, false).sext (bits))
13246 ? double_int::max_value (bits, false)
13247 : -ival;
13248
13249 return build_fixed (TREE_TYPE (tval), fval);
13250}
13251
13252
15b84087 13253/* Implement `TARGET_FOLD_BUILTIN'. */
13254
13255static tree
13256avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg,
13257 bool ignore ATTRIBUTE_UNUSED)
13258{
13259 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
13260 tree val_type = TREE_TYPE (TREE_TYPE (fndecl));
13261
13262 if (!optimize)
13263 return NULL_TREE;
0dff9558 13264
15b84087 13265 switch (fcode)
13266 {
13267 default:
13268 break;
13269
c19a2f5f 13270 case AVR_BUILTIN_SWAP:
13271 {
13272 return fold_build2 (LROTATE_EXPR, val_type, arg[0],
13273 build_int_cst (val_type, 4));
13274 }
0dff9558 13275
f3297245 13276 case AVR_BUILTIN_ABSHR:
13277 case AVR_BUILTIN_ABSR:
13278 case AVR_BUILTIN_ABSLR:
13279 case AVR_BUILTIN_ABSLLR:
13280
13281 case AVR_BUILTIN_ABSHK:
13282 case AVR_BUILTIN_ABSK:
13283 case AVR_BUILTIN_ABSLK:
13284 case AVR_BUILTIN_ABSLLK:
13285 /* GCC is not good with folding ABS for fixed-point. Do it by hand. */
13286
13287 return avr_fold_absfx (arg[0]);
13288
eafea251 13289 case AVR_BUILTIN_BITSHR: case AVR_BUILTIN_HRBITS:
13290 case AVR_BUILTIN_BITSHK: case AVR_BUILTIN_HKBITS:
13291 case AVR_BUILTIN_BITSUHR: case AVR_BUILTIN_UHRBITS:
13292 case AVR_BUILTIN_BITSUHK: case AVR_BUILTIN_UHKBITS:
13293
13294 case AVR_BUILTIN_BITSR: case AVR_BUILTIN_RBITS:
13295 case AVR_BUILTIN_BITSK: case AVR_BUILTIN_KBITS:
13296 case AVR_BUILTIN_BITSUR: case AVR_BUILTIN_URBITS:
13297 case AVR_BUILTIN_BITSUK: case AVR_BUILTIN_UKBITS:
13298
13299 case AVR_BUILTIN_BITSLR: case AVR_BUILTIN_LRBITS:
13300 case AVR_BUILTIN_BITSLK: case AVR_BUILTIN_LKBITS:
13301 case AVR_BUILTIN_BITSULR: case AVR_BUILTIN_ULRBITS:
13302 case AVR_BUILTIN_BITSULK: case AVR_BUILTIN_ULKBITS:
13303
13304 case AVR_BUILTIN_BITSLLR: case AVR_BUILTIN_LLRBITS:
13305 case AVR_BUILTIN_BITSLLK: case AVR_BUILTIN_LLKBITS:
13306 case AVR_BUILTIN_BITSULLR: case AVR_BUILTIN_ULLRBITS:
13307 case AVR_BUILTIN_BITSULLK: case AVR_BUILTIN_ULLKBITS:
13308
13309 gcc_assert (TYPE_PRECISION (val_type)
13310 == TYPE_PRECISION (TREE_TYPE (arg[0])));
13311
13312 return build1 (VIEW_CONVERT_EXPR, val_type, arg[0]);
13313
15b84087 13314 case AVR_BUILTIN_INSERT_BITS:
13315 {
13316 tree tbits = arg[1];
13317 tree tval = arg[2];
13318 tree tmap;
13319 tree map_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
7b5733e8 13320 unsigned int map;
15b84087 13321 bool changed = false;
13322 unsigned i;
13323 avr_map_op_t best_g;
c19a2f5f 13324
13325 if (TREE_CODE (arg[0]) != INTEGER_CST)
13326 {
13327 /* No constant as first argument: Don't fold this and run into
13328 error in avr_expand_builtin. */
0dff9558 13329
c19a2f5f 13330 break;
13331 }
0dff9558 13332
85fbad9e 13333 tmap = wide_int_to_tree (map_type, arg[0]);
08f4222b 13334 map = TREE_INT_CST_LOW (tmap);
15b84087 13335
13336 if (TREE_CODE (tval) != INTEGER_CST
13337 && 0 == avr_map_metric (map, MAP_MASK_PREIMAGE_F))
13338 {
13339 /* There are no F in the map, i.e. 3rd operand is unused.
13340 Replace that argument with some constant to render
13341 respective input unused. */
0dff9558 13342
15b84087 13343 tval = build_int_cst (val_type, 0);
13344 changed = true;
13345 }
13346
13347 if (TREE_CODE (tbits) != INTEGER_CST
13348 && 0 == avr_map_metric (map, MAP_PREIMAGE_0_7))
13349 {
13350 /* Similar for the bits to be inserted. If they are unused,
13351 we can just as well pass 0. */
0dff9558 13352
15b84087 13353 tbits = build_int_cst (val_type, 0);
13354 }
13355
13356 if (TREE_CODE (tbits) == INTEGER_CST)
13357 {
13358 /* Inserting bits known at compile time is easy and can be
13359 performed by AND and OR with appropriate masks. */
13360
f9ae6f95 13361 int bits = TREE_INT_CST_LOW (tbits);
15b84087 13362 int mask_ior = 0, mask_and = 0xff;
13363
13364 for (i = 0; i < 8; i++)
13365 {
13366 int mi = avr_map (map, i);
13367
13368 if (mi < 8)
13369 {
13370 if (bits & (1 << mi)) mask_ior |= (1 << i);
13371 else mask_and &= ~(1 << i);
13372 }
13373 }
13374
13375 tval = fold_build2 (BIT_IOR_EXPR, val_type, tval,
13376 build_int_cst (val_type, mask_ior));
13377 return fold_build2 (BIT_AND_EXPR, val_type, tval,
13378 build_int_cst (val_type, mask_and));
13379 }
13380
13381 if (changed)
13382 return build_call_expr (fndecl, 3, tmap, tbits, tval);
13383
13384 /* If bits don't change their position we can use vanilla logic
13385 to merge the two arguments. */
13386
13387 if (0 == avr_map_metric (map, MAP_NONFIXED_0_7))
13388 {
13389 int mask_f = avr_map_metric (map, MAP_MASK_PREIMAGE_F);
13390 tree tres, tmask = build_int_cst (val_type, mask_f ^ 0xff);
13391
13392 tres = fold_build2 (BIT_XOR_EXPR, val_type, tbits, tval);
13393 tres = fold_build2 (BIT_AND_EXPR, val_type, tres, tmask);
13394 return fold_build2 (BIT_XOR_EXPR, val_type, tres, tval);
13395 }
13396
13397 /* Try to decomposing map to reduce overall cost. */
13398
13399 if (avr_log.builtin)
7b5733e8 13400 avr_edump ("\n%?: %x\n%?: ROL cost: ", map);
0dff9558 13401
15b84087 13402 best_g = avr_map_op[0];
13403 best_g.cost = 1000;
0dff9558 13404
15b84087 13405 for (i = 0; i < sizeof (avr_map_op) / sizeof (*avr_map_op); i++)
13406 {
13407 avr_map_op_t g
13408 = avr_map_decompose (map, avr_map_op + i,
13409 TREE_CODE (tval) == INTEGER_CST);
13410
13411 if (g.cost >= 0 && g.cost < best_g.cost)
13412 best_g = g;
13413 }
13414
13415 if (avr_log.builtin)
13416 avr_edump ("\n");
0dff9558 13417
15b84087 13418 if (best_g.arg == 0)
13419 /* No optimization found */
13420 break;
0dff9558 13421
15b84087 13422 /* Apply operation G to the 2nd argument. */
0dff9558 13423
15b84087 13424 if (avr_log.builtin)
7b5733e8 13425 avr_edump ("%?: using OP(%s%d, %x) cost %d\n",
15b84087 13426 best_g.str, best_g.arg, best_g.map, best_g.cost);
13427
13428 /* Do right-shifts arithmetically: They copy the MSB instead of
13429 shifting in a non-usable value (0) as with logic right-shift. */
0dff9558 13430
15b84087 13431 tbits = fold_convert (signed_char_type_node, tbits);
13432 tbits = fold_build2 (best_g.code, signed_char_type_node, tbits,
13433 build_int_cst (val_type, best_g.arg));
13434 tbits = fold_convert (val_type, tbits);
13435
13436 /* Use map o G^-1 instead of original map to undo the effect of G. */
0dff9558 13437
85fbad9e 13438 tmap = wide_int_to_tree (map_type, best_g.map);
0dff9558 13439
15b84087 13440 return build_call_expr (fndecl, 3, tmap, tbits, tval);
13441 } /* AVR_BUILTIN_INSERT_BITS */
13442 }
13443
13444 return NULL_TREE;
13445}
13446
15b84087 13447\f
1602e4b0 13448
13449/* Initialize the GCC target structure. */
13450
13451#undef TARGET_ASM_ALIGNED_HI_OP
13452#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
13453#undef TARGET_ASM_ALIGNED_SI_OP
13454#define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
13455#undef TARGET_ASM_UNALIGNED_HI_OP
13456#define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
13457#undef TARGET_ASM_UNALIGNED_SI_OP
13458#define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
13459#undef TARGET_ASM_INTEGER
13460#define TARGET_ASM_INTEGER avr_assemble_integer
13461#undef TARGET_ASM_FILE_START
13462#define TARGET_ASM_FILE_START avr_file_start
13463#undef TARGET_ASM_FILE_END
13464#define TARGET_ASM_FILE_END avr_file_end
13465
13466#undef TARGET_ASM_FUNCTION_END_PROLOGUE
13467#define TARGET_ASM_FUNCTION_END_PROLOGUE avr_asm_function_end_prologue
13468#undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
13469#define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE avr_asm_function_begin_epilogue
13470
13471#undef TARGET_FUNCTION_VALUE
13472#define TARGET_FUNCTION_VALUE avr_function_value
13473#undef TARGET_LIBCALL_VALUE
13474#define TARGET_LIBCALL_VALUE avr_libcall_value
13475#undef TARGET_FUNCTION_VALUE_REGNO_P
13476#define TARGET_FUNCTION_VALUE_REGNO_P avr_function_value_regno_p
13477
13478#undef TARGET_ATTRIBUTE_TABLE
13479#define TARGET_ATTRIBUTE_TABLE avr_attribute_table
13480#undef TARGET_INSERT_ATTRIBUTES
13481#define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
13482#undef TARGET_SECTION_TYPE_FLAGS
13483#define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
13484
13485#undef TARGET_ASM_NAMED_SECTION
13486#define TARGET_ASM_NAMED_SECTION avr_asm_named_section
13487#undef TARGET_ASM_INIT_SECTIONS
13488#define TARGET_ASM_INIT_SECTIONS avr_asm_init_sections
13489#undef TARGET_ENCODE_SECTION_INFO
13490#define TARGET_ENCODE_SECTION_INFO avr_encode_section_info
13491#undef TARGET_ASM_SELECT_SECTION
13492#define TARGET_ASM_SELECT_SECTION avr_asm_select_section
13493
13494#undef TARGET_REGISTER_MOVE_COST
13495#define TARGET_REGISTER_MOVE_COST avr_register_move_cost
13496#undef TARGET_MEMORY_MOVE_COST
13497#define TARGET_MEMORY_MOVE_COST avr_memory_move_cost
13498#undef TARGET_RTX_COSTS
13499#define TARGET_RTX_COSTS avr_rtx_costs
13500#undef TARGET_ADDRESS_COST
13501#define TARGET_ADDRESS_COST avr_address_cost
13502#undef TARGET_MACHINE_DEPENDENT_REORG
13503#define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
13504#undef TARGET_FUNCTION_ARG
13505#define TARGET_FUNCTION_ARG avr_function_arg
13506#undef TARGET_FUNCTION_ARG_ADVANCE
13507#define TARGET_FUNCTION_ARG_ADVANCE avr_function_arg_advance
13508
ea679361 13509#undef TARGET_SET_CURRENT_FUNCTION
13510#define TARGET_SET_CURRENT_FUNCTION avr_set_current_function
13511
1602e4b0 13512#undef TARGET_RETURN_IN_MEMORY
13513#define TARGET_RETURN_IN_MEMORY avr_return_in_memory
13514
13515#undef TARGET_STRICT_ARGUMENT_NAMING
13516#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
13517
13518#undef TARGET_BUILTIN_SETJMP_FRAME_VALUE
13519#define TARGET_BUILTIN_SETJMP_FRAME_VALUE avr_builtin_setjmp_frame_value
13520
b4e6d2e2 13521#undef TARGET_CONDITIONAL_REGISTER_USAGE
13522#define TARGET_CONDITIONAL_REGISTER_USAGE avr_conditional_register_usage
13523
1602e4b0 13524#undef TARGET_HARD_REGNO_SCRATCH_OK
13525#define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok
13526#undef TARGET_CASE_VALUES_THRESHOLD
13527#define TARGET_CASE_VALUES_THRESHOLD avr_case_values_threshold
13528
13529#undef TARGET_FRAME_POINTER_REQUIRED
13530#define TARGET_FRAME_POINTER_REQUIRED avr_frame_pointer_required_p
13531#undef TARGET_CAN_ELIMINATE
13532#define TARGET_CAN_ELIMINATE avr_can_eliminate
13533
a28e3283 13534#undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
13535#define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS avr_allocate_stack_slots_for_args
13536
08c6cbd2 13537#undef TARGET_WARN_FUNC_RETURN
13538#define TARGET_WARN_FUNC_RETURN avr_warn_func_return
13539
1602e4b0 13540#undef TARGET_CLASS_LIKELY_SPILLED_P
13541#define TARGET_CLASS_LIKELY_SPILLED_P avr_class_likely_spilled_p
13542
13543#undef TARGET_OPTION_OVERRIDE
13544#define TARGET_OPTION_OVERRIDE avr_option_override
13545
13546#undef TARGET_CANNOT_MODIFY_JUMPS_P
13547#define TARGET_CANNOT_MODIFY_JUMPS_P avr_cannot_modify_jumps_p
13548
13549#undef TARGET_FUNCTION_OK_FOR_SIBCALL
13550#define TARGET_FUNCTION_OK_FOR_SIBCALL avr_function_ok_for_sibcall
13551
13552#undef TARGET_INIT_BUILTINS
13553#define TARGET_INIT_BUILTINS avr_init_builtins
13554
58cf0091 13555#undef TARGET_BUILTIN_DECL
13556#define TARGET_BUILTIN_DECL avr_builtin_decl
13557
1602e4b0 13558#undef TARGET_EXPAND_BUILTIN
13559#define TARGET_EXPAND_BUILTIN avr_expand_builtin
13560
13561#undef TARGET_FOLD_BUILTIN
13562#define TARGET_FOLD_BUILTIN avr_fold_builtin
13563
13564#undef TARGET_ASM_FUNCTION_RODATA_SECTION
13565#define TARGET_ASM_FUNCTION_RODATA_SECTION avr_asm_function_rodata_section
13566
13567#undef TARGET_SCALAR_MODE_SUPPORTED_P
13568#define TARGET_SCALAR_MODE_SUPPORTED_P avr_scalar_mode_supported_p
13569
017c5b98 13570#undef TARGET_BUILD_BUILTIN_VA_LIST
13571#define TARGET_BUILD_BUILTIN_VA_LIST avr_build_builtin_va_list
13572
13573#undef TARGET_FIXED_POINT_SUPPORTED_P
13574#define TARGET_FIXED_POINT_SUPPORTED_P hook_bool_void_true
13575
1c72da59 13576#undef TARGET_CONVERT_TO_TYPE
13577#define TARGET_CONVERT_TO_TYPE avr_convert_to_type
13578
1602e4b0 13579#undef TARGET_ADDR_SPACE_SUBSET_P
13580#define TARGET_ADDR_SPACE_SUBSET_P avr_addr_space_subset_p
13581
13582#undef TARGET_ADDR_SPACE_CONVERT
13583#define TARGET_ADDR_SPACE_CONVERT avr_addr_space_convert
13584
13585#undef TARGET_ADDR_SPACE_ADDRESS_MODE
13586#define TARGET_ADDR_SPACE_ADDRESS_MODE avr_addr_space_address_mode
13587
13588#undef TARGET_ADDR_SPACE_POINTER_MODE
13589#define TARGET_ADDR_SPACE_POINTER_MODE avr_addr_space_pointer_mode
13590
13591#undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
13592#define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
13593 avr_addr_space_legitimate_address_p
13594
13595#undef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
13596#define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS avr_addr_space_legitimize_address
13597
002565f0 13598#undef TARGET_MODE_DEPENDENT_ADDRESS_P
13599#define TARGET_MODE_DEPENDENT_ADDRESS_P avr_mode_dependent_address_p
13600
be6d8823 13601#undef TARGET_SECONDARY_RELOAD
13602#define TARGET_SECONDARY_RELOAD avr_secondary_reload
13603
1602e4b0 13604#undef TARGET_PRINT_OPERAND
13605#define TARGET_PRINT_OPERAND avr_print_operand
13606#undef TARGET_PRINT_OPERAND_ADDRESS
13607#define TARGET_PRINT_OPERAND_ADDRESS avr_print_operand_address
13608#undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
13609#define TARGET_PRINT_OPERAND_PUNCT_VALID_P avr_print_operand_punct_valid_p
13610
a45076aa 13611struct gcc_target targetm = TARGET_INITIALIZER;
c5be380e 13612
1602e4b0 13613\f
c84f2269 13614#include "gt-avr.h"