]> gcc.gnu.org Git - gcc.git/blame - gcc/config/avr/avr.c
Move MEMMODEL_* from coretypes.h to memmodel.h
[gcc.git] / gcc / config / avr / avr.c
CommitLineData
90e7678c 1/* Subroutines for insn-output.c for ATMEL AVR micro controllers
818ab71a 2 Copyright (C) 1998-2016 Free Software Foundation, Inc.
92bffc14 3 Contributed by Denis Chertykov (chertykov@gmail.com)
90e7678c 4
7ec022b2 5 This file is part of GCC.
90e7678c 6
7ec022b2 7 GCC is free software; you can redistribute it and/or modify
90e7678c 8 it under the terms of the GNU General Public License as published by
2f83c7d6 9 the Free Software Foundation; either version 3, or (at your option)
90e7678c
DC
10 any later version.
11
7ec022b2 12 GCC is distributed in the hope that it will be useful,
90e7678c
DC
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
2f83c7d6
NC
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
90e7678c
DC
20
21#include "config.h"
b8fa3ed6 22#include "system.h"
4977bab6 23#include "coretypes.h"
c7131fb2 24#include "backend.h"
e11c4407 25#include "target.h"
90e7678c 26#include "rtl.h"
e11c4407
AM
27#include "c-family/c-common.h"
28#include "cfghooks.h"
c7131fb2 29#include "df.h"
4d0cdd0c 30#include "memmodel.h"
e11c4407
AM
31#include "tm_p.h"
32#include "optabs.h"
90e7678c 33#include "regs.h"
e11c4407
AM
34#include "emit-rtl.h"
35#include "recog.h"
90e7678c 36#include "conditions.h"
90e7678c 37#include "insn-attr.h"
90e7678c 38#include "reload.h"
f9d29866 39#include "varasm.h"
d8a2d370
DN
40#include "calls.h"
41#include "stor-layout.h"
3eaf7a3c 42#include "output.h"
36566b39 43#include "explow.h"
90e7678c 44#include "expr.h"
43ea6502 45#include "langhooks.h"
60393bbc 46#include "cfgrtl.h"
c7088aea 47#include "params.h"
9b2b7279 48#include "builtins.h"
2b4293a3
GJL
49#include "context.h"
50#include "tree-pass.h"
90e7678c 51
994c5d85 52/* This file should be included last. */
d58627a0
RS
53#include "target-def.h"
54
3454eb73
DC
55/* Maximal allowed offset for an address in the LD command */
56#define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
90e7678c 57
f2814222
GJL
58/* Return true if STR starts with PREFIX and false, otherwise. */
59#define STR_PREFIX_P(STR,PREFIX) (0 == strncmp (STR, PREFIX, strlen (PREFIX)))
60
562f552b
GJL
61/* The 4 bits starting at SECTION_MACH_DEP are reserved to store the
62 address space where data is to be located.
00892272 63 As the only non-generic address spaces are all located in flash,
562f552b
GJL
64 this can be used to test if data shall go into some .progmem* section.
65 This must be the rightmost field of machine dependent section flags. */
7bc6df2c 66#define AVR_SECTION_PROGMEM (0xf * SECTION_MACH_DEP)
886a64f9 67
cba300dd
GJL
68/* Similar 4-bit region for SYMBOL_REF_FLAGS. */
69#define AVR_SYMBOL_FLAG_PROGMEM (0xf * SYMBOL_FLAG_MACH_DEP)
70
71/* Similar 4-bit region in SYMBOL_REF_FLAGS:
72 Set address-space AS in SYMBOL_REF_FLAGS of SYM */
73#define AVR_SYMBOL_SET_ADDR_SPACE(SYM,AS) \
74 do { \
75 SYMBOL_REF_FLAGS (sym) &= ~AVR_SYMBOL_FLAG_PROGMEM; \
76 SYMBOL_REF_FLAGS (sym) |= (AS) * SYMBOL_FLAG_MACH_DEP; \
77 } while (0)
78
79/* Read address-space from SYMBOL_REF_FLAGS of SYM */
80#define AVR_SYMBOL_GET_ADDR_SPACE(SYM) \
81 ((SYMBOL_REF_FLAGS (sym) & AVR_SYMBOL_FLAG_PROGMEM) \
82 / SYMBOL_FLAG_MACH_DEP)
83
c25e1d82
GJL
84/* (AVR_TINY only): Symbol has attribute progmem */
85#define AVR_SYMBOL_FLAG_TINY_PM \
3ce9aa83 86 (SYMBOL_FLAG_MACH_DEP << 7)
c25e1d82 87
c1dd9790 88#define TINY_ADIW(REG1, REG2, I) \
0c9ef7ad
GJL
89 "subi " #REG1 ",lo8(-(" #I "))" CR_TAB \
90 "sbci " #REG2 ",hi8(-(" #I "))"
c1dd9790
JR
91
92#define TINY_SBIW(REG1, REG2, I) \
0c9ef7ad
GJL
93 "subi " #REG1 ",lo8((" #I "))" CR_TAB \
94 "sbci " #REG2 ",hi8((" #I "))"
c1dd9790
JR
95
96#define AVR_TMP_REGNO (AVR_TINY ? TMP_REGNO_TINY : TMP_REGNO)
97#define AVR_ZERO_REGNO (AVR_TINY ? ZERO_REGNO_TINY : ZERO_REGNO)
98
562f552b
GJL
99/* Known address spaces. The order must be the same as in the respective
100 enum from avr.h (or designated initialized must be used). */
e5669488
GJL
101const avr_addrspace_t avr_addrspace[ADDR_SPACE_COUNT] =
102{
103 { ADDR_SPACE_RAM, 0, 2, "", 0, NULL },
104 { ADDR_SPACE_FLASH, 1, 2, "__flash", 0, ".progmem.data" },
105 { ADDR_SPACE_FLASH1, 1, 2, "__flash1", 1, ".progmem1.data" },
106 { ADDR_SPACE_FLASH2, 1, 2, "__flash2", 2, ".progmem2.data" },
107 { ADDR_SPACE_FLASH3, 1, 2, "__flash3", 3, ".progmem3.data" },
108 { ADDR_SPACE_FLASH4, 1, 2, "__flash4", 4, ".progmem4.data" },
109 { ADDR_SPACE_FLASH5, 1, 2, "__flash5", 5, ".progmem5.data" },
110 { ADDR_SPACE_MEMX, 1, 3, "__memx", 0, ".progmemx.data" },
562f552b
GJL
111};
112
562f552b 113
82b37806
GJL
114/* Holding RAM addresses of some SFRs used by the compiler and that
115 are unique over all devices in an architecture like 'avr4'. */
00892272 116
82b37806
GJL
117typedef struct
118{
00892272 119 /* SREG: The processor status */
82b37806
GJL
120 int sreg;
121
2da8c1ad
GJL
122 /* RAMPX, RAMPY, RAMPD and CCP of XMEGA */
123 int ccp;
124 int rampd;
125 int rampx;
126 int rampy;
127
00892272 128 /* RAMPZ: The high byte of 24-bit address used with ELPM */
82b37806
GJL
129 int rampz;
130
131 /* SP: The stack pointer and its low and high byte */
132 int sp_l;
133 int sp_h;
134} avr_addr_t;
135
136static avr_addr_t avr_addr;
137
d2111e2f
GJL
138
139/* Prototypes for local helper functions. */
140
98024b4e
DM
141static const char* out_movqi_r_mr (rtx_insn *, rtx[], int*);
142static const char* out_movhi_r_mr (rtx_insn *, rtx[], int*);
143static const char* out_movsi_r_mr (rtx_insn *, rtx[], int*);
144static const char* out_movqi_mr_r (rtx_insn *, rtx[], int*);
145static const char* out_movhi_mr_r (rtx_insn *, rtx[], int*);
146static const char* out_movsi_mr_r (rtx_insn *, rtx[], int*);
147
148static int get_sequence_length (rtx_insn *insns);
269e3795
SB
149static int sequent_regs_live (void);
150static const char *ptrreg_to_str (int);
151static const char *cond_string (enum rtx_code);
ef4bddc2
RS
152static int avr_num_arg_regs (machine_mode, const_tree);
153static int avr_operand_rtx_cost (rtx, machine_mode, enum rtx_code,
0098895f
GJL
154 int, bool);
155static void output_reload_in_const (rtx*, rtx, int*, bool);
4fc2b4ff 156static struct machine_function * avr_init_machine_status (void);
d2111e2f
GJL
157
158
159/* Prototypes for hook implementors if needed before their implementation. */
160
e548c9df 161static bool avr_rtx_costs (rtx, machine_mode, int, int, int*, bool);
d2111e2f 162
1bf29643 163
2c338472 164/* Allocate registers from r25 to r8 for parameters for function calls. */
90e7678c
DC
165#define FIRST_CUM_REG 26
166
c1dd9790
JR
167/* Last call saved register */
168#define LAST_CALLEE_SAVED_REG (AVR_TINY ? 19 : 17)
169
7c209481 170/* Implicit target register of LPM instruction (R0) */
38ee0815
GJL
171extern GTY(()) rtx lpm_reg_rtx;
172rtx lpm_reg_rtx;
7c209481
GJL
173
174/* (Implicit) address register of LPM instruction (R31:R30 = Z) */
38ee0815
GJL
175extern GTY(()) rtx lpm_addr_reg_rtx;
176rtx lpm_addr_reg_rtx;
7c209481 177
38ee0815
GJL
178/* Temporary register RTX (reg:QI TMP_REGNO) */
179extern GTY(()) rtx tmp_reg_rtx;
180rtx tmp_reg_rtx;
90e7678c 181
38ee0815
GJL
182/* Zeroed register RTX (reg:QI ZERO_REGNO) */
183extern GTY(()) rtx zero_reg_rtx;
184rtx zero_reg_rtx;
185
186/* RTXs for all general purpose registers as QImode */
187extern GTY(()) rtx all_regs_rtx[32];
188rtx all_regs_rtx[32];
6bec29c9 189
2da8c1ad
GJL
190/* SREG, the processor status */
191extern GTY(()) rtx sreg_rtx;
192rtx sreg_rtx;
193
194/* RAMP* special function registers */
195extern GTY(()) rtx rampd_rtx;
196extern GTY(()) rtx rampx_rtx;
197extern GTY(()) rtx rampy_rtx;
38ee0815 198extern GTY(()) rtx rampz_rtx;
2da8c1ad
GJL
199rtx rampd_rtx;
200rtx rampx_rtx;
201rtx rampy_rtx;
38ee0815 202rtx rampz_rtx;
7bc6df2c
GJL
203
204/* RTX containing the strings "" and "e", respectively */
205static GTY(()) rtx xstring_empty;
206static GTY(()) rtx xstring_e;
207
19298da4 208/* Current architecture. */
4a2caf6c 209const avr_arch_t *avr_arch;
6bec29c9 210
562f552b 211/* Unnamed sections associated to __attribute__((progmem)) aka. PROGMEM
e5669488
GJL
212 or to address space __flash* or __memx. Only used as singletons inside
213 avr_asm_select_section, but it must not be local there because of GTY. */
214static GTY(()) section *progmem_section[ADDR_SPACE_COUNT];
7bc6df2c 215
8c57e547
GJL
216/* Condition for insns/expanders from avr-dimode.md. */
217bool avr_have_dimode = true;
218
516edfdd
GJL
219/* To track if code will use .bss and/or .data. */
220bool avr_need_clear_bss_p = false;
221bool avr_need_copy_data_p = false;
222
672a6f42 223\f
e52a8b71
GJL
224/* Transform UP into lowercase and write the result to LO.
225 You must provide enough space for LO. Return LO. */
226
227static char*
228avr_tolower (char *lo, const char *up)
229{
230 char *lo0 = lo;
231
232 for (; *up; up++, lo++)
233 *lo = TOLOWER (*up);
234
235 *lo = '\0';
236
237 return lo0;
238}
239
886a64f9 240
6ebe2d6c
GJL
241/* Custom function to count number of set bits. */
242
243static inline int
244avr_popcount (unsigned int val)
245{
246 int pop = 0;
247
248 while (val)
249 {
250 val &= val-1;
251 pop++;
252 }
253
254 return pop;
255}
256
257
20633efc
GJL
258/* Constraint helper function. XVAL is a CONST_INT or a CONST_DOUBLE.
259 Return true if the least significant N_BYTES bytes of XVAL all have a
260 popcount in POP_MASK and false, otherwise. POP_MASK represents a subset
261 of integers which contains an integer N iff bit N of POP_MASK is set. */
00892272 262
6ebe2d6c
GJL
263bool
264avr_popcount_each_byte (rtx xval, int n_bytes, int pop_mask)
265{
266 int i;
267
ef4bddc2 268 machine_mode mode = GET_MODE (xval);
20633efc
GJL
269
270 if (VOIDmode == mode)
271 mode = SImode;
272
6ebe2d6c
GJL
273 for (i = 0; i < n_bytes; i++)
274 {
20633efc 275 rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
6ebe2d6c
GJL
276 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
277
278 if (0 == (pop_mask & (1 << avr_popcount (val8))))
279 return false;
280 }
281
282 return true;
283}
284
e55e4056
GJL
285
286/* Access some RTX as INT_MODE. If X is a CONST_FIXED we can get
287 the bit representation of X by "casting" it to CONST_INT. */
288
289rtx
290avr_to_int_mode (rtx x)
291{
ef4bddc2 292 machine_mode mode = GET_MODE (x);
e55e4056
GJL
293
294 return VOIDmode == mode
295 ? x
296 : simplify_gen_subreg (int_mode_for_mode (mode), x, mode, 0);
297}
298
76beabf4 299namespace {
e55e4056 300
2b4293a3
GJL
301static const pass_data avr_pass_data_recompute_notes =
302{
303 RTL_PASS, // type
304 "", // name (will be patched)
305 OPTGROUP_NONE, // optinfo_flags
306 TV_DF_SCAN, // tv_id
307 0, // properties_required
308 0, // properties_provided
309 0, // properties_destroyed
310 0, // todo_flags_start
311 TODO_df_finish | TODO_df_verify // todo_flags_finish
312};
313
314
315class avr_pass_recompute_notes : public rtl_opt_pass
316{
317public:
318 avr_pass_recompute_notes (gcc::context *ctxt, const char *name)
319 : rtl_opt_pass (avr_pass_data_recompute_notes, ctxt)
320 {
321 this->name = name;
322 }
323
324 virtual unsigned int execute (function*)
325 {
326 df_note_add_problem ();
327 df_analyze ();
328
329 return 0;
330 }
331}; // avr_pass_recompute_notes
332
76beabf4 333} // anon namespace
2b4293a3 334
76beabf4
GJL
335rtl_opt_pass*
336make_avr_pass_recompute_notes (gcc::context *ctxt)
2b4293a3 337{
76beabf4 338 return new avr_pass_recompute_notes (ctxt, "avr-notes-free-cfg");
2b4293a3
GJL
339}
340
341
4a2caf6c
GJL
342/* Set `avr_arch' as specified by `-mmcu='.
343 Return true on success. */
344
345static bool
346avr_set_core_architecture (void)
347{
348 /* Search for mcu core architecture. */
349
350 if (!avr_mmcu)
351 avr_mmcu = AVR_MMCU_DEFAULT;
352
353 avr_arch = &avr_arch_types[0];
354
355 for (const avr_mcu_t *mcu = avr_mcu_types; ; mcu++)
356 {
357 if (NULL == mcu->name)
358 {
359 /* Reached the end of `avr_mcu_types'. This should actually never
360 happen as options are provided by device-specs. It could be a
361 typo in a device-specs or calling the compiler proper directly
362 with -mmcu=<device>. */
363
364 error ("unknown core architecture %qs specified with %qs",
365 avr_mmcu, "-mmcu=");
366 avr_inform_core_architectures ();
367 break;
368 }
369 else if (0 == strcmp (mcu->name, avr_mmcu)
370 // Is this a proper architecture ?
371 && NULL == mcu->macro)
372 {
373 avr_arch = &avr_arch_types[mcu->arch_id];
374 if (avr_n_flash < 0)
375 avr_n_flash = mcu->n_flash;
376
377 return true;
378 }
379 }
380
381 return false;
382}
383
384
e55e4056
GJL
385/* Implement `TARGET_OPTION_OVERRIDE'. */
386
c5387660
JM
387static void
388avr_option_override (void)
90e7678c 389{
6e4f81db
V
390 /* Disable -fdelete-null-pointer-checks option for AVR target.
391 This option compiler assumes that dereferencing of a null pointer
392 would halt the program. For AVR this assumption is not true and
393 programs can safely dereference null pointers. Changes made by this
394 option may not work properly for AVR. So disable this option. */
395
6c7ac15d
AS
396 flag_delete_null_pointer_checks = 0;
397
e8ac5ac9
GJL
398 /* caller-save.c looks for call-clobbered hard registers that are assigned
399 to pseudos that cross calls and tries so save-restore them around calls
400 in order to reduce the number of stack slots needed.
401
00892272 402 This might lead to situations where reload is no more able to cope
e8ac5ac9
GJL
403 with the challenge of AVR's very few address registers and fails to
404 perform the requested spills. */
00892272 405
e8ac5ac9
GJL
406 if (avr_strict_X)
407 flag_caller_saves = 0;
408
c7088aea
SKS
409 /* Allow optimizer to introduce store data races. This used to be the
410 default - it was changed because bigger targets did not see any
411 performance decrease. For the AVR though, disallowing data races
412 introduces additional code in LIM and increases reg pressure. */
413
414 maybe_set_param_value (PARAM_ALLOW_STORE_DATA_RACES, 1,
415 global_options.x_param_values,
416 global_options_set.x_param_values);
417
16bbc875
GJL
418 /* Unwind tables currently require a frame pointer for correctness,
419 see toplev.c:process_options(). */
420
421 if ((flag_unwind_tables
422 || flag_non_call_exceptions
423 || flag_asynchronous_unwind_tables)
424 && !ACCUMULATE_OUTGOING_ARGS)
425 {
426 flag_omit_frame_pointer = 0;
427 }
16bbc875 428
9af06df3
SKS
429 if (flag_pic == 1)
430 warning (OPT_fpic, "-fpic is not supported");
431 if (flag_pic == 2)
432 warning (OPT_fPIC, "-fPIC is not supported");
433 if (flag_pie == 1)
434 warning (OPT_fpie, "-fpie is not supported");
435 if (flag_pie == 2)
436 warning (OPT_fPIE, "-fPIE is not supported");
437
4a2caf6c
GJL
438 if (!avr_set_core_architecture())
439 return;
00892272
GJL
440
441 /* RAM addresses of some SFRs common to all devices in respective arch. */
82b37806
GJL
442
443 /* SREG: Status Register containing flags like I (global IRQ) */
4a2caf6c 444 avr_addr.sreg = 0x3F + avr_arch->sfr_offset;
82b37806
GJL
445
446 /* RAMPZ: Address' high part when loading via ELPM */
4a2caf6c 447 avr_addr.rampz = 0x3B + avr_arch->sfr_offset;
82b37806 448
4a2caf6c
GJL
449 avr_addr.rampy = 0x3A + avr_arch->sfr_offset;
450 avr_addr.rampx = 0x39 + avr_arch->sfr_offset;
451 avr_addr.rampd = 0x38 + avr_arch->sfr_offset;
452 avr_addr.ccp = (AVR_TINY ? 0x3C : 0x34) + avr_arch->sfr_offset;
2da8c1ad 453
82b37806 454 /* SP: Stack Pointer (SP_H:SP_L) */
4a2caf6c 455 avr_addr.sp_l = 0x3D + avr_arch->sfr_offset;
82b37806 456 avr_addr.sp_h = avr_addr.sp_l + 1;
1268b05f 457
4fc2b4ff 458 init_machine_status = avr_init_machine_status;
6c7dfafe
GJL
459
460 avr_log_set_avr_log();
90e7678c
DC
461}
462
4fc2b4ff
AH
463/* Function to set up the backend function structure. */
464
465static struct machine_function *
466avr_init_machine_status (void)
467{
766090c2 468 return ggc_cleared_alloc<machine_function> ();
4fc2b4ff
AH
469}
470
7bc6df2c
GJL
471
472/* Implement `INIT_EXPANDERS'. */
473/* The function works like a singleton. */
474
475void
476avr_init_expanders (void)
477{
478 int regno;
479
7bc6df2c
GJL
480 for (regno = 0; regno < 32; regno ++)
481 all_regs_rtx[regno] = gen_rtx_REG (QImode, regno);
482
483 lpm_reg_rtx = all_regs_rtx[LPM_REGNO];
c1dd9790
JR
484 tmp_reg_rtx = all_regs_rtx[AVR_TMP_REGNO];
485 zero_reg_rtx = all_regs_rtx[AVR_ZERO_REGNO];
7bc6df2c
GJL
486
487 lpm_addr_reg_rtx = gen_rtx_REG (HImode, REG_Z);
488
2da8c1ad
GJL
489 sreg_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.sreg));
490 rampd_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampd));
491 rampx_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampx));
492 rampy_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampy));
82b37806 493 rampz_rtx = gen_rtx_MEM (QImode, GEN_INT (avr_addr.rampz));
7bc6df2c
GJL
494
495 xstring_empty = gen_rtx_CONST_STRING (VOIDmode, "");
496 xstring_e = gen_rtx_CONST_STRING (VOIDmode, "e");
c1dd9790
JR
497
498 /* TINY core does not have regs r10-r16, but avr-dimode.md expects them
499 to be present */
500 if (AVR_TINY)
0c9ef7ad 501 avr_have_dimode = false;
7bc6df2c
GJL
502}
503
504
00892272 505/* Implement `REGNO_REG_CLASS'. */
2c338472 506/* Return register class for register R. */
90e7678c
DC
507
508enum reg_class
269e3795 509avr_regno_reg_class (int r)
90e7678c 510{
61af7eb4
GJL
511 static const enum reg_class reg_class_tab[] =
512 {
513 R0_REG,
514 /* r1 - r15 */
515 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
516 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
517 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
518 NO_LD_REGS, NO_LD_REGS, NO_LD_REGS, NO_LD_REGS,
519 /* r16 - r23 */
520 SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
521 SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS, SIMPLE_LD_REGS,
522 /* r24, r25 */
523 ADDW_REGS, ADDW_REGS,
524 /* X: r26, 27 */
525 POINTER_X_REGS, POINTER_X_REGS,
526 /* Y: r28, r29 */
527 POINTER_Y_REGS, POINTER_Y_REGS,
528 /* Z: r30, r31 */
529 POINTER_Z_REGS, POINTER_Z_REGS,
530 /* SP: SPL, SPH */
531 STACK_REG, STACK_REG
532 };
533
90e7678c
DC
534 if (r <= 33)
535 return reg_class_tab[r];
00892272 536
90e7678c
DC
537 return ALL_REGS;
538}
539
e4fe948a 540
e55e4056
GJL
541/* Implement `TARGET_SCALAR_MODE_SUPPORTED_P'. */
542
e4fe948a 543static bool
ef4bddc2 544avr_scalar_mode_supported_p (machine_mode mode)
e4fe948a 545{
e55e4056
GJL
546 if (ALL_FIXED_POINT_MODE_P (mode))
547 return true;
548
e4fe948a
GJL
549 if (PSImode == mode)
550 return true;
551
552 return default_scalar_mode_supported_p (mode);
553}
554
555
00892272 556/* Return TRUE if DECL is a VAR_DECL located in flash and FALSE, otherwise. */
7c209481
GJL
557
558static bool
3a840863 559avr_decl_flash_p (tree decl)
7c209481 560{
7bc6df2c
GJL
561 if (TREE_CODE (decl) != VAR_DECL
562 || TREE_TYPE (decl) == error_mark_node)
563 {
564 return false;
565 }
7c209481
GJL
566
567 return !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (TREE_TYPE (decl)));
568}
569
570
00892272 571/* Return TRUE if DECL is a VAR_DECL located in the 24-bit flash
7bc6df2c 572 address space and FALSE, otherwise. */
00892272 573
7bc6df2c 574static bool
3a840863 575avr_decl_memx_p (tree decl)
7bc6df2c
GJL
576{
577 if (TREE_CODE (decl) != VAR_DECL
578 || TREE_TYPE (decl) == error_mark_node)
579 {
580 return false;
581 }
582
3a840863 583 return (ADDR_SPACE_MEMX == TYPE_ADDR_SPACE (TREE_TYPE (decl)));
7bc6df2c
GJL
584}
585
586
00892272 587/* Return TRUE if X is a MEM rtx located in flash and FALSE, otherwise. */
7c209481
GJL
588
589bool
3a840863 590avr_mem_flash_p (rtx x)
7c209481
GJL
591{
592 return (MEM_P (x)
593 && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x)));
594}
595
596
00892272 597/* Return TRUE if X is a MEM rtx located in the 24-bit flash
7bc6df2c
GJL
598 address space and FALSE, otherwise. */
599
600bool
3a840863 601avr_mem_memx_p (rtx x)
7bc6df2c
GJL
602{
603 return (MEM_P (x)
3a840863 604 && ADDR_SPACE_MEMX == MEM_ADDR_SPACE (x));
7bc6df2c
GJL
605}
606
607
980a0ff4
GJL
608/* A helper for the subsequent function attribute used to dig for
609 attribute 'name' in a FUNCTION_DECL or FUNCTION_TYPE */
610
611static inline int
612avr_lookup_function_attribute1 (const_tree func, const char *name)
613{
614 if (FUNCTION_DECL == TREE_CODE (func))
615 {
616 if (NULL_TREE != lookup_attribute (name, DECL_ATTRIBUTES (func)))
617 {
618 return true;
619 }
00892272 620
980a0ff4
GJL
621 func = TREE_TYPE (func);
622 }
623
624 gcc_assert (TREE_CODE (func) == FUNCTION_TYPE
625 || TREE_CODE (func) == METHOD_TYPE);
00892272 626
980a0ff4
GJL
627 return NULL_TREE != lookup_attribute (name, TYPE_ATTRIBUTES (func));
628}
629
825dda42 630/* Return nonzero if FUNC is a naked function. */
90e7678c
DC
631
632static int
269e3795 633avr_naked_function_p (tree func)
90e7678c 634{
980a0ff4 635 return avr_lookup_function_attribute1 (func, "naked");
90e7678c
DC
636}
637
638/* Return nonzero if FUNC is an interrupt function as specified
639 by the "interrupt" attribute. */
640
641static int
eac188c5 642avr_interrupt_function_p (tree func)
90e7678c 643{
980a0ff4 644 return avr_lookup_function_attribute1 (func, "interrupt");
90e7678c
DC
645}
646
3454eb73 647/* Return nonzero if FUNC is a signal function as specified
90e7678c
DC
648 by the "signal" attribute. */
649
650static int
eac188c5 651avr_signal_function_p (tree func)
90e7678c 652{
980a0ff4 653 return avr_lookup_function_attribute1 (func, "signal");
90e7678c
DC
654}
655
4103605f 656/* Return nonzero if FUNC is an OS_task function. */
96ac4c9b
AS
657
658static int
659avr_OS_task_function_p (tree func)
660{
980a0ff4 661 return avr_lookup_function_attribute1 (func, "OS_task");
96ac4c9b
AS
662}
663
4103605f 664/* Return nonzero if FUNC is an OS_main function. */
9b678d96
AS
665
666static int
667avr_OS_main_function_p (tree func)
668{
980a0ff4 669 return avr_lookup_function_attribute1 (func, "OS_main");
9b678d96
AS
670}
671
d702f362 672
eac188c5
GJL
673/* Implement `TARGET_SET_CURRENT_FUNCTION'. */
674/* Sanity cheching for above function attributes. */
675
676static void
677avr_set_current_function (tree decl)
678{
679 location_t loc;
680 const char *isr;
681
682 if (decl == NULL_TREE
683 || current_function_decl == NULL_TREE
684 || current_function_decl == error_mark_node
b1bdc68d 685 || ! cfun->machine
eac188c5
GJL
686 || cfun->machine->attributes_checked_p)
687 return;
688
689 loc = DECL_SOURCE_LOCATION (decl);
690
691 cfun->machine->is_naked = avr_naked_function_p (decl);
692 cfun->machine->is_signal = avr_signal_function_p (decl);
693 cfun->machine->is_interrupt = avr_interrupt_function_p (decl);
694 cfun->machine->is_OS_task = avr_OS_task_function_p (decl);
695 cfun->machine->is_OS_main = avr_OS_main_function_p (decl);
696
697 isr = cfun->machine->is_interrupt ? "interrupt" : "signal";
698
699 /* Too much attributes make no sense as they request conflicting features. */
700
701 if (cfun->machine->is_OS_task + cfun->machine->is_OS_main
702 + (cfun->machine->is_signal || cfun->machine->is_interrupt) > 1)
703 error_at (loc, "function attributes %qs, %qs and %qs are mutually"
704 " exclusive", "OS_task", "OS_main", isr);
705
706 /* 'naked' will hide effects of 'OS_task' and 'OS_main'. */
707
708 if (cfun->machine->is_naked
709 && (cfun->machine->is_OS_task || cfun->machine->is_OS_main))
710 warning_at (loc, OPT_Wattributes, "function attributes %qs and %qs have"
711 " no effect on %qs function", "OS_task", "OS_main", "naked");
712
713 if (cfun->machine->is_interrupt || cfun->machine->is_signal)
714 {
715 tree args = TYPE_ARG_TYPES (TREE_TYPE (decl));
716 tree ret = TREE_TYPE (TREE_TYPE (decl));
52b3f9e2
GJL
717 const char *name;
718
719 name = DECL_ASSEMBLER_NAME_SET_P (decl)
2832dc22 720 ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))
52b3f9e2 721 : IDENTIFIER_POINTER (DECL_NAME (decl));
00892272 722
2832dc22
GJL
723 /* Skip a leading '*' that might still prefix the assembler name,
724 e.g. in non-LTO runs. */
725
726 name = default_strip_name_encoding (name);
727
eac188c5
GJL
728 /* Silently ignore 'signal' if 'interrupt' is present. AVR-LibC startet
729 using this when it switched from SIGNAL and INTERRUPT to ISR. */
730
731 if (cfun->machine->is_interrupt)
732 cfun->machine->is_signal = 0;
733
734 /* Interrupt handlers must be void __vector (void) functions. */
735
736 if (args && TREE_CODE (TREE_VALUE (args)) != VOID_TYPE)
737 error_at (loc, "%qs function cannot have arguments", isr);
738
739 if (TREE_CODE (ret) != VOID_TYPE)
740 error_at (loc, "%qs function cannot return a value", isr);
741
742 /* If the function has the 'signal' or 'interrupt' attribute, ensure
743 that the name of the function is "__vector_NN" so as to catch
744 when the user misspells the vector name. */
745
746 if (!STR_PREFIX_P (name, "__vector"))
22fba352
PS
747 warning_at (loc, OPT_Wmisspelled_isr, "%qs appears to be a misspelled "
748 "%s handler, missing __vector prefix", name, isr);
eac188c5
GJL
749 }
750
00892272
GJL
751 /* Don't print the above diagnostics more than once. */
752
eac188c5
GJL
753 cfun->machine->attributes_checked_p = 1;
754}
755
756
d702f362 757/* Implement `ACCUMULATE_OUTGOING_ARGS'. */
45958634
GJL
758
759int
d702f362
GJL
760avr_accumulate_outgoing_args (void)
761{
762 if (!cfun)
763 return TARGET_ACCUMULATE_OUTGOING_ARGS;
764
765 /* FIXME: For setjmp and in avr_builtin_setjmp_frame_value we don't know
766 what offset is correct. In some cases it is relative to
767 virtual_outgoing_args_rtx and in others it is relative to
768 virtual_stack_vars_rtx. For example code see
769 gcc.c-torture/execute/built-in-setjmp.c
770 gcc.c-torture/execute/builtins/sprintf-chk.c */
00892272 771
d702f362
GJL
772 return (TARGET_ACCUMULATE_OUTGOING_ARGS
773 && !(cfun->calls_setjmp
774 || cfun->has_nonlocal_label));
775}
776
777
778/* Report contribution of accumulated outgoing arguments to stack size. */
779
780static inline int
781avr_outgoing_args_size (void)
782{
783 return ACCUMULATE_OUTGOING_ARGS ? crtl->outgoing_args_size : 0;
784}
785
786
787/* Implement `STARTING_FRAME_OFFSET'. */
788/* This is the offset from the frame pointer register to the first stack slot
789 that contains a variable living in the frame. */
790
791int
792avr_starting_frame_offset (void)
793{
794 return 1 + avr_outgoing_args_size ();
795}
796
797
93febe68
MM
798/* Return the number of hard registers to push/pop in the prologue/epilogue
799 of the current function, and optionally store these registers in SET. */
800
801static int
269e3795 802avr_regs_to_save (HARD_REG_SET *set)
93febe68
MM
803{
804 int reg, count;
eac188c5 805 int int_or_sig_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
4c75f709 806
93febe68
MM
807 if (set)
808 CLEAR_HARD_REG_SET (*set);
809 count = 0;
e52b6b63 810
00892272 811 /* No need to save any registers if the function never returns or
4103605f 812 has the "OS_task" or "OS_main" attribute. */
00892272 813
96ac4c9b 814 if (TREE_THIS_VOLATILE (current_function_decl)
9b678d96
AS
815 || cfun->machine->is_OS_task
816 || cfun->machine->is_OS_main)
e52b6b63
MM
817 return 0;
818
93febe68
MM
819 for (reg = 0; reg < 32; reg++)
820 {
821 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
d702f362 822 any global register variables. */
00892272 823
93febe68 824 if (fixed_regs[reg])
d702f362 825 continue;
93febe68 826
416ff32e 827 if ((int_or_sig_p && !crtl->is_leaf && call_used_regs[reg])
d702f362
GJL
828 || (df_regs_ever_live_p (reg)
829 && (int_or_sig_p || !call_used_regs[reg])
830 /* Don't record frame pointer registers here. They are treated
831 indivitually in prologue. */
832 && !(frame_pointer_needed
833 && (reg == REG_Y || reg == (REG_Y+1)))))
834 {
835 if (set)
836 SET_HARD_REG_BIT (*set, reg);
837 count++;
838 }
93febe68
MM
839 }
840 return count;
841}
842
cee8f252
SKS
843
844/* Implement `TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS' */
845
846static bool
847avr_allocate_stack_slots_for_args (void)
848{
849 return !cfun->machine->is_naked;
850}
851
852
c21ca196
AS
853/* Return true if register FROM can be eliminated via register TO. */
854
d2111e2f 855static bool
3134fb19 856avr_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
c21ca196 857{
8aa7d1fc
JR
858 return ((frame_pointer_needed && to == FRAME_POINTER_REGNUM)
859 || !frame_pointer_needed);
c21ca196
AS
860}
861
d45eae79 862
00892272 863/* Implement `TARGET_WARN_FUNC_RETURN'. */
d45eae79
SL
864
865static bool
866avr_warn_func_return (tree decl)
867{
868 /* Naked functions are implemented entirely in assembly, including the
869 return sequence, so suppress warnings about this. */
00892272 870
d45eae79
SL
871 return !avr_naked_function_p (decl);
872}
873
2c338472 874/* Compute offset between arg_pointer and frame_pointer. */
90e7678c
DC
875
876int
cfbaed3b 877avr_initial_elimination_offset (int from, int to)
90e7678c 878{
cfbaed3b
DC
879 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
880 return 0;
881 else
3454eb73 882 {
cfbaed3b
DC
883 int offset = frame_pointer_needed ? 2 : 0;
884 int avr_pc_size = AVR_HAVE_EIJMP_EICALL ? 3 : 2;
00892272 885
93febe68 886 offset += avr_regs_to_save (NULL);
cfbaed3b
DC
887 return (get_frame_size () + avr_outgoing_args_size()
888 + avr_pc_size + 1 + offset);
90e7678c 889 }
90e7678c
DC
890}
891
e55e4056
GJL
892
893/* Helper for the function below. */
894
895static void
ef4bddc2 896avr_adjust_type_node (tree *node, machine_mode mode, int sat_p)
e55e4056
GJL
897{
898 *node = make_node (FIXED_POINT_TYPE);
899 TYPE_SATURATING (*node) = sat_p;
900 TYPE_UNSIGNED (*node) = UNSIGNED_FIXED_POINT_MODE_P (mode);
901 TYPE_IBIT (*node) = GET_MODE_IBIT (mode);
902 TYPE_FBIT (*node) = GET_MODE_FBIT (mode);
903 TYPE_PRECISION (*node) = GET_MODE_BITSIZE (mode);
fe37c7af 904 SET_TYPE_ALIGN (*node, 8);
e55e4056
GJL
905 SET_TYPE_MODE (*node, mode);
906
907 layout_type (*node);
908}
909
910
911/* Implement `TARGET_BUILD_BUILTIN_VA_LIST'. */
912
913static tree
914avr_build_builtin_va_list (void)
915{
916 /* avr-modes.def adjusts [U]TA to be 64-bit modes with 48 fractional bits.
917 This is more appropriate for the 8-bit machine AVR than 128-bit modes.
918 The ADJUST_IBIT/FBIT are handled in toplev:init_adjust_machine_modes()
919 which is auto-generated by genmodes, but the compiler assigns [U]DAmode
920 to the long long accum modes instead of the desired [U]TAmode.
921
922 Fix this now, right after node setup in tree.c:build_common_tree_nodes().
923 This must run before c-cppbuiltin.c:builtin_define_fixed_point_constants()
924 which built-in defines macros like __ULLACCUM_FBIT__ that are used by
925 libgcc to detect IBIT and FBIT. */
926
927 avr_adjust_type_node (&ta_type_node, TAmode, 0);
928 avr_adjust_type_node (&uta_type_node, UTAmode, 0);
929 avr_adjust_type_node (&sat_ta_type_node, TAmode, 1);
930 avr_adjust_type_node (&sat_uta_type_node, UTAmode, 1);
931
932 unsigned_long_long_accum_type_node = uta_type_node;
933 long_long_accum_type_node = ta_type_node;
934 sat_unsigned_long_long_accum_type_node = sat_uta_type_node;
935 sat_long_long_accum_type_node = sat_ta_type_node;
936
937 /* Dispatch to the default handler. */
00892272 938
e55e4056
GJL
939 return std_build_builtin_va_list ();
940}
941
942
943/* Implement `TARGET_BUILTIN_SETJMP_FRAME_VALUE'. */
00892272 944/* Actual start of frame is virtual_stack_vars_rtx this is offset from
1bf29643
AH
945 frame pointer by +STARTING_FRAME_OFFSET.
946 Using saved frame = virtual_stack_vars_rtx - STARTING_FRAME_OFFSET
947 avoids creating add/sub of offset in nonlocal goto and setjmp. */
948
d2111e2f
GJL
949static rtx
950avr_builtin_setjmp_frame_value (void)
1bf29643 951{
e55e4056
GJL
952 rtx xval = gen_reg_rtx (Pmode);
953 emit_insn (gen_subhi3 (xval, virtual_stack_vars_rtx,
954 gen_int_mode (STARTING_FRAME_OFFSET, Pmode)));
955 return xval;
1bf29643
AH
956}
957
e55e4056 958
00892272 959/* Return contents of MEM at frame pointer + stack size + 1 (+2 if 3-byte PC).
a212a5d4 960 This is return address of function. */
00892272
GJL
961
962rtx
3f02a5f3 963avr_return_addr_rtx (int count, rtx tem)
a212a5d4
AH
964{
965 rtx r;
00892272 966
4103605f 967 /* Can only return this function's return address. Others not supported. */
a212a5d4
AH
968 if (count)
969 return NULL;
970
971 if (AVR_3_BYTE_PC)
972 {
973 r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+2");
00892272
GJL
974 warning (0, "%<builtin_return_address%> contains only 2 bytes"
975 " of address");
a212a5d4
AH
976 }
977 else
978 r = gen_rtx_SYMBOL_REF (Pmode, ".L__stack_usage+1");
979
980 r = gen_rtx_PLUS (Pmode, tem, r);
981 r = gen_frame_mem (Pmode, memory_address (Pmode, r));
982 r = gen_rtx_ROTATE (HImode, r, GEN_INT (8));
983 return r;
984}
985
126dbce0
MM
986/* Return 1 if the function epilogue is just a single "ret". */
987
988int
269e3795 989avr_simple_epilogue (void)
126dbce0
MM
990{
991 return (! frame_pointer_needed
d702f362
GJL
992 && get_frame_size () == 0
993 && avr_outgoing_args_size() == 0
994 && avr_regs_to_save (NULL) == 0
eac188c5
GJL
995 && ! cfun->machine->is_interrupt
996 && ! cfun->machine->is_signal
997 && ! cfun->machine->is_naked
d702f362 998 && ! TREE_THIS_VOLATILE (current_function_decl));
126dbce0
MM
999}
1000
2c338472 1001/* This function checks sequence of live registers. */
90e7678c
DC
1002
1003static int
269e3795 1004sequent_regs_live (void)
90e7678c
DC
1005{
1006 int reg;
00892272
GJL
1007 int live_seq = 0;
1008 int cur_seq = 0;
90e7678c 1009
c1dd9790 1010 for (reg = 0; reg <= LAST_CALLEE_SAVED_REG; ++reg)
90e7678c 1011 {
1e3a7e86
GJL
1012 if (fixed_regs[reg])
1013 {
1014 /* Don't recognize sequences that contain global register
1015 variables. */
00892272 1016
1e3a7e86
GJL
1017 if (live_seq != 0)
1018 return 0;
1019 else
1020 continue;
1021 }
00892272 1022
90e7678c 1023 if (!call_used_regs[reg])
00892272
GJL
1024 {
1025 if (df_regs_ever_live_p (reg))
1026 {
1027 ++live_seq;
1028 ++cur_seq;
1029 }
1030 else
1031 cur_seq = 0;
1032 }
90e7678c
DC
1033 }
1034
1035 if (!frame_pointer_needed)
1036 {
6fb5fa3c 1037 if (df_regs_ever_live_p (REG_Y))
00892272
GJL
1038 {
1039 ++live_seq;
1040 ++cur_seq;
1041 }
90e7678c 1042 else
00892272 1043 cur_seq = 0;
90e7678c 1044
6fb5fa3c 1045 if (df_regs_ever_live_p (REG_Y+1))
00892272
GJL
1046 {
1047 ++live_seq;
1048 ++cur_seq;
1049 }
90e7678c 1050 else
00892272 1051 cur_seq = 0;
90e7678c
DC
1052 }
1053 else
1054 {
1055 cur_seq += 2;
1056 live_seq += 2;
1057 }
1058 return (cur_seq == live_seq) ? live_seq : 0;
1059}
1060
97822902
AS
1061/* Obtain the length sequence of insns. */
1062
1063int
98024b4e 1064get_sequence_length (rtx_insn *insns)
97822902 1065{
98024b4e 1066 rtx_insn *insn;
97822902 1067 int length;
00892272 1068
97822902
AS
1069 for (insn = insns, length = 0; insn; insn = NEXT_INSN (insn))
1070 length += get_attr_length (insn);
00892272 1071
97822902
AS
1072 return length;
1073}
1074
00892272
GJL
1075
1076/* Implement `INCOMING_RETURN_ADDR_RTX'. */
bdfe906f
RH
1077
1078rtx
1079avr_incoming_return_addr_rtx (void)
1080{
1081 /* The return address is at the top of the stack. Note that the push
1082 was via post-decrement, which means the actual address is off by one. */
0a81f074 1083 return gen_frame_mem (HImode, plus_constant (Pmode, stack_pointer_rtx, 1));
bdfe906f
RH
1084}
1085
1086/* Helper for expand_prologue. Emit a push of a byte register. */
1087
1088static void
1089emit_push_byte (unsigned regno, bool frame_related_p)
1090{
98024b4e
DM
1091 rtx mem, reg;
1092 rtx_insn *insn;
bdfe906f
RH
1093
1094 mem = gen_rtx_POST_DEC (HImode, stack_pointer_rtx);
1095 mem = gen_frame_mem (QImode, mem);
1096 reg = gen_rtx_REG (QImode, regno);
1097
f7df4a84 1098 insn = emit_insn (gen_rtx_SET (mem, reg));
bdfe906f
RH
1099 if (frame_related_p)
1100 RTX_FRAME_RELATED_P (insn) = 1;
1101
1102 cfun->machine->stack_usage++;
1103}
1104
2da8c1ad
GJL
1105
1106/* Helper for expand_prologue. Emit a push of a SFR via tmp_reg.
1107 SFR is a MEM representing the memory location of the SFR.
1108 If CLR_P then clear the SFR after the push using zero_reg. */
1109
1110static void
1111emit_push_sfr (rtx sfr, bool frame_related_p, bool clr_p)
1112{
98024b4e 1113 rtx_insn *insn;
00892272 1114
2da8c1ad
GJL
1115 gcc_assert (MEM_P (sfr));
1116
1117 /* IN __tmp_reg__, IO(SFR) */
1118 insn = emit_move_insn (tmp_reg_rtx, sfr);
1119 if (frame_related_p)
1120 RTX_FRAME_RELATED_P (insn) = 1;
00892272 1121
2da8c1ad 1122 /* PUSH __tmp_reg__ */
c1dd9790 1123 emit_push_byte (AVR_TMP_REGNO, frame_related_p);
2da8c1ad
GJL
1124
1125 if (clr_p)
1126 {
1127 /* OUT IO(SFR), __zero_reg__ */
1128 insn = emit_move_insn (sfr, const0_rtx);
1129 if (frame_related_p)
1130 RTX_FRAME_RELATED_P (insn) = 1;
1131 }
1132}
1133
d702f362
GJL
1134static void
1135avr_prologue_setup_frame (HOST_WIDE_INT size, HARD_REG_SET set)
1136{
98024b4e 1137 rtx_insn *insn;
d702f362
GJL
1138 bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1139 int live_seq = sequent_regs_live ();
1140
ae606c28
GJL
1141 HOST_WIDE_INT size_max
1142 = (HOST_WIDE_INT) GET_MODE_MASK (AVR_HAVE_8BIT_SP ? QImode : Pmode);
1143
d702f362 1144 bool minimize = (TARGET_CALL_PROLOGUES
ae606c28 1145 && size < size_max
d702f362
GJL
1146 && live_seq
1147 && !isr_p
1148 && !cfun->machine->is_OS_task
c1dd9790
JR
1149 && !cfun->machine->is_OS_main
1150 && !AVR_TINY);
00892272 1151
d702f362
GJL
1152 if (minimize
1153 && (frame_pointer_needed
1154 || avr_outgoing_args_size() > 8
1155 || (AVR_2_BYTE_PC && live_seq > 6)
00892272 1156 || live_seq > 7))
d702f362
GJL
1157 {
1158 rtx pattern;
1159 int first_reg, reg, offset;
1160
00892272 1161 emit_move_insn (gen_rtx_REG (HImode, REG_X),
d702f362
GJL
1162 gen_int_mode (size, HImode));
1163
1164 pattern = gen_call_prologue_saves (gen_int_mode (live_seq, HImode),
1165 gen_int_mode (live_seq+size, HImode));
1166 insn = emit_insn (pattern);
1167 RTX_FRAME_RELATED_P (insn) = 1;
1168
1169 /* Describe the effect of the unspec_volatile call to prologue_saves.
1170 Note that this formulation assumes that add_reg_note pushes the
1171 notes to the front. Thus we build them in the reverse order of
1172 how we want dwarf2out to process them. */
1173
cfbaed3b 1174 /* The function does always set frame_pointer_rtx, but whether that
d702f362
GJL
1175 is going to be permanent in the function is frame_pointer_needed. */
1176
1177 add_reg_note (insn, REG_CFA_ADJUST_CFA,
f7df4a84
RS
1178 gen_rtx_SET ((frame_pointer_needed
1179 ? frame_pointer_rtx
1180 : stack_pointer_rtx),
0a81f074 1181 plus_constant (Pmode, stack_pointer_rtx,
6aa52a58 1182 -(size + live_seq))));
d702f362
GJL
1183
1184 /* Note that live_seq always contains r28+r29, but the other
1185 registers to be saved are all below 18. */
1186
c1dd9790 1187 first_reg = (LAST_CALLEE_SAVED_REG + 1) - (live_seq - 2);
d702f362
GJL
1188
1189 for (reg = 29, offset = -live_seq + 1;
1190 reg >= first_reg;
c1dd9790 1191 reg = (reg == 28 ? LAST_CALLEE_SAVED_REG : reg - 1), ++offset)
d702f362
GJL
1192 {
1193 rtx m, r;
1194
0a81f074 1195 m = gen_rtx_MEM (QImode, plus_constant (Pmode, stack_pointer_rtx,
6aa52a58 1196 offset));
d702f362 1197 r = gen_rtx_REG (QImode, reg);
f7df4a84 1198 add_reg_note (insn, REG_CFA_OFFSET, gen_rtx_SET (m, r));
d702f362
GJL
1199 }
1200
1201 cfun->machine->stack_usage += size + live_seq;
1202 }
1203 else /* !minimize */
1204 {
1205 int reg;
00892272 1206
d702f362
GJL
1207 for (reg = 0; reg < 32; ++reg)
1208 if (TEST_HARD_REG_BIT (set, reg))
1209 emit_push_byte (reg, true);
1210
1211 if (frame_pointer_needed
1212 && (!(cfun->machine->is_OS_task || cfun->machine->is_OS_main)))
1213 {
1214 /* Push frame pointer. Always be consistent about the
1215 ordering of pushes -- epilogue_restores expects the
1216 register pair to be pushed low byte first. */
00892272 1217
d702f362
GJL
1218 emit_push_byte (REG_Y, true);
1219 emit_push_byte (REG_Y + 1, true);
1220 }
00892272 1221
d702f362
GJL
1222 if (frame_pointer_needed
1223 && size == 0)
1224 {
cfbaed3b 1225 insn = emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
d702f362
GJL
1226 RTX_FRAME_RELATED_P (insn) = 1;
1227 }
00892272 1228
d702f362
GJL
1229 if (size != 0)
1230 {
1231 /* Creating a frame can be done by direct manipulation of the
1232 stack or via the frame pointer. These two methods are:
1233 fp = sp
1234 fp -= size
1235 sp = fp
1236 or
1237 sp -= size
1238 fp = sp (*)
1239 the optimum method depends on function type, stack and
1240 frame size. To avoid a complex logic, both methods are
1241 tested and shortest is selected.
1242
1243 There is also the case where SIZE != 0 and no frame pointer is
1244 needed; this can occur if ACCUMULATE_OUTGOING_ARGS is on.
1245 In that case, insn (*) is not needed in that case.
1246 We use the X register as scratch. This is save because in X
1247 is call-clobbered.
1248 In an interrupt routine, the case of SIZE != 0 together with
1249 !frame_pointer_needed can only occur if the function is not a
1250 leaf function and thus X has already been saved. */
00892272 1251
0b262c28 1252 int irq_state = -1;
bb6f2bac 1253 HOST_WIDE_INT size_cfa = size, neg_size;
98024b4e
DM
1254 rtx_insn *fp_plus_insns;
1255 rtx fp, my_fp;
d702f362
GJL
1256
1257 gcc_assert (frame_pointer_needed
1258 || !isr_p
416ff32e 1259 || !crtl->is_leaf);
00892272 1260
d702f362 1261 fp = my_fp = (frame_pointer_needed
cfbaed3b 1262 ? frame_pointer_rtx
d702f362 1263 : gen_rtx_REG (Pmode, REG_X));
00892272 1264
d702f362
GJL
1265 if (AVR_HAVE_8BIT_SP)
1266 {
1267 /* The high byte (r29) does not change:
0b262c28 1268 Prefer SUBI (1 cycle) over SBIW (2 cycles, same size). */
d702f362 1269
cfbaed3b 1270 my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
d702f362
GJL
1271 }
1272
ae606c28
GJL
1273 /* Cut down size and avoid size = 0 so that we don't run
1274 into ICE like PR52488 in the remainder. */
1275
1276 if (size > size_max)
1277 {
1278 /* Don't error so that insane code from newlib still compiles
1279 and does not break building newlib. As PR51345 is implemented
7fd6378e 1280 now, there are multilib variants with -msp8.
00892272 1281
ae606c28
GJL
1282 If user wants sanity checks he can use -Wstack-usage=
1283 or similar options.
1284
1285 For CFA we emit the original, non-saturated size so that
1286 the generic machinery is aware of the real stack usage and
1287 will print the above diagnostic as expected. */
00892272 1288
ae606c28
GJL
1289 size = size_max;
1290 }
1291
1292 size = trunc_int_for_mode (size, GET_MODE (my_fp));
bb6f2bac 1293 neg_size = trunc_int_for_mode (-size, GET_MODE (my_fp));
00892272 1294
d702f362 1295 /************ Method 1: Adjust frame pointer ************/
00892272 1296
d702f362
GJL
1297 start_sequence ();
1298
1299 /* Normally, the dwarf2out frame-related-expr interpreter does
1300 not expect to have the CFA change once the frame pointer is
1301 set up. Thus, we avoid marking the move insn below and
1302 instead indicate that the entire operation is complete after
1303 the frame pointer subtraction is done. */
00892272 1304
d702f362 1305 insn = emit_move_insn (fp, stack_pointer_rtx);
0b262c28
GJL
1306 if (frame_pointer_needed)
1307 {
1308 RTX_FRAME_RELATED_P (insn) = 1;
1309 add_reg_note (insn, REG_CFA_ADJUST_CFA,
f7df4a84 1310 gen_rtx_SET (fp, stack_pointer_rtx));
0b262c28 1311 }
d702f362 1312
55796e90 1313 insn = emit_move_insn (my_fp, plus_constant (GET_MODE (my_fp),
bb6f2bac
GJL
1314 my_fp, neg_size));
1315
d702f362
GJL
1316 if (frame_pointer_needed)
1317 {
0b262c28 1318 RTX_FRAME_RELATED_P (insn) = 1;
d702f362 1319 add_reg_note (insn, REG_CFA_ADJUST_CFA,
f7df4a84
RS
1320 gen_rtx_SET (fp, plus_constant (Pmode, fp,
1321 -size_cfa)));
d702f362 1322 }
00892272 1323
d702f362
GJL
1324 /* Copy to stack pointer. Note that since we've already
1325 changed the CFA to the frame pointer this operation
0b262c28
GJL
1326 need not be annotated if frame pointer is needed.
1327 Always move through unspec, see PR50063.
1328 For meaning of irq_state see movhi_sp_r insn. */
d702f362 1329
0b262c28
GJL
1330 if (cfun->machine->is_interrupt)
1331 irq_state = 1;
1332
1333 if (TARGET_NO_INTERRUPTS
1334 || cfun->machine->is_signal
1335 || cfun->machine->is_OS_main)
1336 irq_state = 0;
d702f362 1337
0b262c28
GJL
1338 if (AVR_HAVE_8BIT_SP)
1339 irq_state = 2;
1340
1341 insn = emit_insn (gen_movhi_sp_r (stack_pointer_rtx,
1342 fp, GEN_INT (irq_state)));
1343 if (!frame_pointer_needed)
1344 {
1345 RTX_FRAME_RELATED_P (insn) = 1;
1346 add_reg_note (insn, REG_CFA_ADJUST_CFA,
f7df4a84 1347 gen_rtx_SET (stack_pointer_rtx,
0a81f074 1348 plus_constant (Pmode,
6aa52a58
GJL
1349 stack_pointer_rtx,
1350 -size_cfa)));
0b262c28 1351 }
00892272 1352
d702f362
GJL
1353 fp_plus_insns = get_insns ();
1354 end_sequence ();
00892272 1355
d702f362
GJL
1356 /************ Method 2: Adjust Stack pointer ************/
1357
1358 /* Stack adjustment by means of RCALL . and/or PUSH __TMP_REG__
1359 can only handle specific offsets. */
00892272 1360
d702f362
GJL
1361 if (avr_sp_immediate_operand (gen_int_mode (-size, HImode), HImode))
1362 {
98024b4e 1363 rtx_insn *sp_plus_insns;
00892272 1364
d702f362
GJL
1365 start_sequence ();
1366
0b262c28 1367 insn = emit_move_insn (stack_pointer_rtx,
0a81f074 1368 plus_constant (Pmode, stack_pointer_rtx,
6aa52a58 1369 -size));
d702f362 1370 RTX_FRAME_RELATED_P (insn) = 1;
0b262c28 1371 add_reg_note (insn, REG_CFA_ADJUST_CFA,
f7df4a84 1372 gen_rtx_SET (stack_pointer_rtx,
0a81f074 1373 plus_constant (Pmode,
00892272 1374 stack_pointer_rtx,
6aa52a58 1375 -size_cfa)));
d702f362
GJL
1376 if (frame_pointer_needed)
1377 {
1378 insn = emit_move_insn (fp, stack_pointer_rtx);
1379 RTX_FRAME_RELATED_P (insn) = 1;
1380 }
1381
1382 sp_plus_insns = get_insns ();
1383 end_sequence ();
1384
1385 /************ Use shortest method ************/
00892272 1386
d702f362
GJL
1387 emit_insn (get_sequence_length (sp_plus_insns)
1388 < get_sequence_length (fp_plus_insns)
1389 ? sp_plus_insns
1390 : fp_plus_insns);
1391 }
1392 else
1393 {
1394 emit_insn (fp_plus_insns);
1395 }
1396
ae606c28 1397 cfun->machine->stack_usage += size_cfa;
d702f362
GJL
1398 } /* !minimize && size != 0 */
1399 } /* !minimize */
1400}
1401
bdfe906f 1402
4fc2b4ff 1403/* Output function prologue. */
90e7678c 1404
4fc2b4ff 1405void
00892272 1406avr_expand_prologue (void)
78cf8279 1407{
d6f77715 1408 HARD_REG_SET set;
d702f362
GJL
1409 HOST_WIDE_INT size;
1410
1411 size = get_frame_size() + avr_outgoing_args_size();
00892272 1412
a212a5d4 1413 cfun->machine->stack_usage = 0;
00892272 1414
4fc2b4ff
AH
1415 /* Prologue: naked. */
1416 if (cfun->machine->is_naked)
78cf8279 1417 {
4fc2b4ff 1418 return;
78cf8279 1419 }
78cf8279 1420
d6f77715 1421 avr_regs_to_save (&set);
78cf8279 1422
4fc2b4ff 1423 if (cfun->machine->is_interrupt || cfun->machine->is_signal)
78cf8279 1424 {
bdfe906f 1425 /* Enable interrupts. */
4fc2b4ff 1426 if (cfun->machine->is_interrupt)
d702f362 1427 emit_insn (gen_enable_interrupt ());
00892272 1428
4fc2b4ff 1429 /* Push zero reg. */
c1dd9790 1430 emit_push_byte (AVR_ZERO_REGNO, true);
4fc2b4ff
AH
1431
1432 /* Push tmp reg. */
c1dd9790 1433 emit_push_byte (AVR_TMP_REGNO, true);
4fc2b4ff
AH
1434
1435 /* Push SREG. */
bdfe906f 1436 /* ??? There's no dwarf2 column reserved for SREG. */
2da8c1ad 1437 emit_push_sfr (sreg_rtx, false, false /* clr */);
d6f77715 1438
4fc2b4ff 1439 /* Clear zero reg. */
bdfe906f 1440 emit_move_insn (zero_reg_rtx, const0_rtx);
78cf8279 1441
4fc2b4ff 1442 /* Prevent any attempt to delete the setting of ZERO_REG! */
c41c1387 1443 emit_use (zero_reg_rtx);
2da8c1ad
GJL
1444
1445 /* Push and clear RAMPD/X/Y/Z if present and low-part register is used.
1446 ??? There are no dwarf2 columns reserved for RAMPD/X/Y/Z. */
00892272 1447
2da8c1ad
GJL
1448 if (AVR_HAVE_RAMPD)
1449 emit_push_sfr (rampd_rtx, false /* frame-related */, true /* clr */);
1450
1451 if (AVR_HAVE_RAMPX
1452 && TEST_HARD_REG_BIT (set, REG_X)
1453 && TEST_HARD_REG_BIT (set, REG_X + 1))
1454 {
1455 emit_push_sfr (rampx_rtx, false /* frame-related */, true /* clr */);
1456 }
1457
1458 if (AVR_HAVE_RAMPY
1459 && (frame_pointer_needed
1460 || (TEST_HARD_REG_BIT (set, REG_Y)
1461 && TEST_HARD_REG_BIT (set, REG_Y + 1))))
1462 {
1463 emit_push_sfr (rampy_rtx, false /* frame-related */, true /* clr */);
1464 }
1465
42601c63 1466 if (AVR_HAVE_RAMPZ
2da8c1ad
GJL
1467 && TEST_HARD_REG_BIT (set, REG_Z)
1468 && TEST_HARD_REG_BIT (set, REG_Z + 1))
1469 {
42601c63 1470 emit_push_sfr (rampz_rtx, false /* frame-related */, AVR_HAVE_RAMPD);
2da8c1ad
GJL
1471 }
1472 } /* is_interrupt is_signal */
247df3b6 1473
d702f362 1474 avr_prologue_setup_frame (size, set);
00892272 1475
a11e0df4 1476 if (flag_stack_usage_info)
bdd9dab6 1477 current_function_static_stack_size = cfun->machine->stack_usage + INCOMING_FRAME_SP_OFFSET;
78cf8279
MM
1478}
1479
00892272
GJL
1480
1481/* Implement `TARGET_ASM_FUNCTION_END_PROLOGUE'. */
4fc2b4ff 1482/* Output summary at end of function prologue. */
90e7678c 1483
08c148a8 1484static void
4fc2b4ff 1485avr_asm_function_end_prologue (FILE *file)
90e7678c 1486{
4fc2b4ff 1487 if (cfun->machine->is_naked)
90e7678c 1488 {
e52b6b63 1489 fputs ("/* prologue: naked */\n", file);
90e7678c 1490 }
4fc2b4ff 1491 else
90e7678c 1492 {
4fc2b4ff
AH
1493 if (cfun->machine->is_interrupt)
1494 {
1495 fputs ("/* prologue: Interrupt */\n", file);
1496 }
1497 else if (cfun->machine->is_signal)
1498 {
1499 fputs ("/* prologue: Signal */\n", file);
1500 }
90e7678c 1501 else
4fc2b4ff 1502 fputs ("/* prologue: function */\n", file);
90e7678c 1503 }
d702f362
GJL
1504
1505 if (ACCUMULATE_OUTGOING_ARGS)
1506 fprintf (file, "/* outgoing args size = %d */\n",
1507 avr_outgoing_args_size());
1508
4fc2b4ff
AH
1509 fprintf (file, "/* frame size = " HOST_WIDE_INT_PRINT_DEC " */\n",
1510 get_frame_size());
a212a5d4
AH
1511 fprintf (file, "/* stack size = %d */\n",
1512 cfun->machine->stack_usage);
1513 /* Create symbol stack offset here so all functions have it. Add 1 to stack
1514 usage for offset so that SP + .L__stack_offset = return address. */
1515 fprintf (file, ".L__stack_usage = %d\n", cfun->machine->stack_usage);
4fc2b4ff 1516}
93febe68 1517
908c8c7e 1518
00892272 1519/* Implement `EPILOGUE_USES'. */
e52b6b63 1520
4fc2b4ff
AH
1521int
1522avr_epilogue_uses (int regno ATTRIBUTE_UNUSED)
1523{
00892272 1524 if (reload_completed
4fc2b4ff
AH
1525 && cfun->machine
1526 && (cfun->machine->is_interrupt || cfun->machine->is_signal))
1527 return 1;
1528 return 0;
90e7678c
DC
1529}
1530
00892272 1531/* Helper for avr_expand_epilogue. Emit a pop of a byte register. */
bdfe906f
RH
1532
1533static void
1534emit_pop_byte (unsigned regno)
1535{
1536 rtx mem, reg;
1537
1538 mem = gen_rtx_PRE_INC (HImode, stack_pointer_rtx);
1539 mem = gen_frame_mem (QImode, mem);
1540 reg = gen_rtx_REG (QImode, regno);
1541
f7df4a84 1542 emit_insn (gen_rtx_SET (reg, mem));
bdfe906f
RH
1543}
1544
4fc2b4ff 1545/* Output RTL epilogue. */
90e7678c 1546
4fc2b4ff 1547void
00892272 1548avr_expand_epilogue (bool sibcall_p)
90e7678c
DC
1549{
1550 int reg;
90e7678c 1551 int live_seq;
00892272 1552 HARD_REG_SET set;
90e7678c 1553 int minimize;
d702f362
GJL
1554 HOST_WIDE_INT size;
1555 bool isr_p = cfun->machine->is_interrupt || cfun->machine->is_signal;
1556
1557 size = get_frame_size() + avr_outgoing_args_size();
00892272 1558
4fc2b4ff
AH
1559 /* epilogue: naked */
1560 if (cfun->machine->is_naked)
e52b6b63 1561 {
980a0ff4 1562 gcc_assert (!sibcall_p);
00892272 1563
8819eb78 1564 emit_jump_insn (gen_return ());
4fc2b4ff 1565 return;
90e7678c
DC
1566 }
1567
d6f77715 1568 avr_regs_to_save (&set);
90e7678c 1569 live_seq = sequent_regs_live ();
00892272 1570
90e7678c 1571 minimize = (TARGET_CALL_PROLOGUES
d702f362
GJL
1572 && live_seq
1573 && !isr_p
1574 && !cfun->machine->is_OS_task
c1dd9790
JR
1575 && !cfun->machine->is_OS_main
1576 && !AVR_TINY);
00892272 1577
d702f362
GJL
1578 if (minimize
1579 && (live_seq > 4
1580 || frame_pointer_needed
1581 || size))
90e7678c 1582 {
d702f362 1583 /* Get rid of frame. */
00892272 1584
d702f362
GJL
1585 if (!frame_pointer_needed)
1586 {
cfbaed3b 1587 emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
d702f362
GJL
1588 }
1589
1590 if (size)
1591 {
cfbaed3b 1592 emit_move_insn (frame_pointer_rtx,
0a81f074 1593 plus_constant (Pmode, frame_pointer_rtx, size));
d702f362 1594 }
00892272 1595
8819eb78 1596 emit_insn (gen_epilogue_restores (gen_int_mode (live_seq, HImode)));
d702f362 1597 return;
90e7678c 1598 }
00892272 1599
d702f362 1600 if (size)
90e7678c 1601 {
d702f362 1602 /* Try two methods to adjust stack and select shortest. */
0b262c28
GJL
1603
1604 int irq_state = -1;
d702f362 1605 rtx fp, my_fp;
98024b4e 1606 rtx_insn *fp_plus_insns;
ae606c28 1607 HOST_WIDE_INT size_max;
bdfe906f 1608
d702f362
GJL
1609 gcc_assert (frame_pointer_needed
1610 || !isr_p
416ff32e 1611 || !crtl->is_leaf);
00892272 1612
d702f362 1613 fp = my_fp = (frame_pointer_needed
cfbaed3b 1614 ? frame_pointer_rtx
d702f362 1615 : gen_rtx_REG (Pmode, REG_X));
97822902 1616
d702f362
GJL
1617 if (AVR_HAVE_8BIT_SP)
1618 {
1619 /* The high byte (r29) does not change:
1620 Prefer SUBI (1 cycle) over SBIW (2 cycles). */
00892272 1621
cfbaed3b 1622 my_fp = all_regs_rtx[FRAME_POINTER_REGNUM];
d702f362 1623 }
ae606c28
GJL
1624
1625 /* For rationale see comment in prologue generation. */
1626
1627 size_max = (HOST_WIDE_INT) GET_MODE_MASK (GET_MODE (my_fp));
1628 if (size > size_max)
1629 size = size_max;
1630 size = trunc_int_for_mode (size, GET_MODE (my_fp));
00892272 1631
d702f362 1632 /********** Method 1: Adjust fp register **********/
00892272 1633
d702f362 1634 start_sequence ();
97822902 1635
d702f362
GJL
1636 if (!frame_pointer_needed)
1637 emit_move_insn (fp, stack_pointer_rtx);
97822902 1638
55796e90 1639 emit_move_insn (my_fp, plus_constant (GET_MODE (my_fp), my_fp, size));
97822902 1640
d702f362 1641 /* Copy to stack pointer. */
0b262c28
GJL
1642
1643 if (TARGET_NO_INTERRUPTS)
1644 irq_state = 0;
1645
1646 if (AVR_HAVE_8BIT_SP)
1647 irq_state = 2;
1648
1649 emit_insn (gen_movhi_sp_r (stack_pointer_rtx, fp,
1650 GEN_INT (irq_state)));
bdfe906f 1651
d702f362 1652 fp_plus_insns = get_insns ();
00892272 1653 end_sequence ();
97822902 1654
d702f362 1655 /********** Method 2: Adjust Stack pointer **********/
00892272 1656
d702f362
GJL
1657 if (avr_sp_immediate_operand (gen_int_mode (size, HImode), HImode))
1658 {
98024b4e 1659 rtx_insn *sp_plus_insns;
97822902 1660
d702f362 1661 start_sequence ();
97822902 1662
d702f362 1663 emit_move_insn (stack_pointer_rtx,
0a81f074 1664 plus_constant (Pmode, stack_pointer_rtx, size));
bdfe906f 1665
d702f362
GJL
1666 sp_plus_insns = get_insns ();
1667 end_sequence ();
bdfe906f 1668
d702f362 1669 /************ Use shortest method ************/
00892272 1670
d702f362
GJL
1671 emit_insn (get_sequence_length (sp_plus_insns)
1672 < get_sequence_length (fp_plus_insns)
1673 ? sp_plus_insns
1674 : fp_plus_insns);
1675 }
1676 else
1677 emit_insn (fp_plus_insns);
1678 } /* size != 0 */
00892272 1679
d702f362
GJL
1680 if (frame_pointer_needed
1681 && !(cfun->machine->is_OS_task || cfun->machine->is_OS_main))
1682 {
00892272 1683 /* Restore previous frame_pointer. See avr_expand_prologue for
d702f362 1684 rationale for not using pophi. */
00892272 1685
d702f362
GJL
1686 emit_pop_byte (REG_Y + 1);
1687 emit_pop_byte (REG_Y);
1688 }
93febe68 1689
d702f362 1690 /* Restore used registers. */
00892272 1691
d702f362
GJL
1692 for (reg = 31; reg >= 0; --reg)
1693 if (TEST_HARD_REG_BIT (set, reg))
1694 emit_pop_byte (reg);
4fc2b4ff 1695
d702f362
GJL
1696 if (isr_p)
1697 {
2da8c1ad
GJL
1698 /* Restore RAMPZ/Y/X/D using tmp_reg as scratch.
1699 The conditions to restore them must be tha same as in prologue. */
00892272 1700
42601c63
GJL
1701 if (AVR_HAVE_RAMPZ
1702 && TEST_HARD_REG_BIT (set, REG_Z)
1703 && TEST_HARD_REG_BIT (set, REG_Z + 1))
2da8c1ad
GJL
1704 {
1705 emit_pop_byte (TMP_REGNO);
42601c63 1706 emit_move_insn (rampz_rtx, tmp_reg_rtx);
2da8c1ad
GJL
1707 }
1708
1709 if (AVR_HAVE_RAMPY
1710 && (frame_pointer_needed
1711 || (TEST_HARD_REG_BIT (set, REG_Y)
1712 && TEST_HARD_REG_BIT (set, REG_Y + 1))))
1713 {
1714 emit_pop_byte (TMP_REGNO);
1715 emit_move_insn (rampy_rtx, tmp_reg_rtx);
1716 }
1717
42601c63
GJL
1718 if (AVR_HAVE_RAMPX
1719 && TEST_HARD_REG_BIT (set, REG_X)
1720 && TEST_HARD_REG_BIT (set, REG_X + 1))
d702f362 1721 {
bdfe906f 1722 emit_pop_byte (TMP_REGNO);
42601c63 1723 emit_move_insn (rampx_rtx, tmp_reg_rtx);
4fc2b4ff 1724 }
e52b6b63 1725
2da8c1ad
GJL
1726 if (AVR_HAVE_RAMPD)
1727 {
1728 emit_pop_byte (TMP_REGNO);
1729 emit_move_insn (rampd_rtx, tmp_reg_rtx);
1730 }
1731
1732 /* Restore SREG using tmp_reg as scratch. */
00892272 1733
c1dd9790 1734 emit_pop_byte (AVR_TMP_REGNO);
2da8c1ad 1735 emit_move_insn (sreg_rtx, tmp_reg_rtx);
d702f362
GJL
1736
1737 /* Restore tmp REG. */
c1dd9790 1738 emit_pop_byte (AVR_TMP_REGNO);
d702f362
GJL
1739
1740 /* Restore zero REG. */
c1dd9790 1741 emit_pop_byte (AVR_ZERO_REGNO);
4fc2b4ff 1742 }
d702f362
GJL
1743
1744 if (!sibcall_p)
1745 emit_jump_insn (gen_return ());
90e7678c
DC
1746}
1747
00892272
GJL
1748
1749/* Implement `TARGET_ASM_FUNCTION_BEGIN_EPILOGUE'. */
4fc2b4ff
AH
1750
1751static void
1752avr_asm_function_begin_epilogue (FILE *file)
1753{
1754 fprintf (file, "/* epilogue start */\n");
1755}
90e7678c 1756
6609216e 1757
00892272 1758/* Implement `TARGET_CANNOT_MODITY_JUMPS_P'. */
6609216e
GJL
1759
1760static bool
1761avr_cannot_modify_jumps_p (void)
1762{
1763
1764 /* Naked Functions must not have any instructions after
1765 their epilogue, see PR42240 */
00892272 1766
6609216e
GJL
1767 if (reload_completed
1768 && cfun->machine
1769 && cfun->machine->is_naked)
1770 {
1771 return true;
1772 }
1773
1774 return false;
1775}
1776
1777
03b29b0a
GJL
1778/* Implement `TARGET_MODE_DEPENDENT_ADDRESS_P'. */
1779
03b29b0a 1780static bool
3fd1e31d 1781avr_mode_dependent_address_p (const_rtx addr ATTRIBUTE_UNUSED, addr_space_t as)
03b29b0a 1782{
3fd1e31d
GJL
1783 /* FIXME: Non-generic addresses are not mode-dependent in themselves.
1784 This hook just serves to hack around PR rtl-optimization/52543 by
1785 claiming that non-generic addresses were mode-dependent so that
1786 lower-subreg.c will skip these addresses. lower-subreg.c sets up fake
1787 RTXes to probe SET and MEM costs and assumes that MEM is always in the
1788 generic address space which is not true. */
1789
1790 return !ADDR_SPACE_GENERIC_P (as);
03b29b0a
GJL
1791}
1792
1793
8efab2c5
GJL
1794/* Helper function for `avr_legitimate_address_p'. */
1795
1796static inline bool
86fc3d06 1797avr_reg_ok_for_addr_p (rtx reg, addr_space_t as,
e8ac5ac9 1798 RTX_CODE outer_code, bool strict)
8efab2c5
GJL
1799{
1800 return (REG_P (reg)
86fc3d06
UW
1801 && (avr_regno_mode_code_ok_for_base_p (REGNO (reg), QImode,
1802 as, outer_code, UNKNOWN)
8efab2c5
GJL
1803 || (!strict
1804 && REGNO (reg) >= FIRST_PSEUDO_REGISTER)));
1805}
1806
1807
90e7678c
DC
1808/* Return nonzero if X (an RTX) is a legitimate memory address on the target
1809 machine for a memory operand of mode MODE. */
1810
8efab2c5 1811static bool
ef4bddc2 1812avr_legitimate_address_p (machine_mode mode, rtx x, bool strict)
90e7678c 1813{
e8ac5ac9 1814 bool ok = CONSTANT_ADDRESS_P (x);
00892272 1815
e8ac5ac9 1816 switch (GET_CODE (x))
90e7678c 1817 {
e8ac5ac9
GJL
1818 case REG:
1819 ok = avr_reg_ok_for_addr_p (x, ADDR_SPACE_GENERIC,
1820 MEM, strict);
1821
1822 if (strict
e55e4056 1823 && GET_MODE_SIZE (mode) > 4
e8ac5ac9 1824 && REG_X == REGNO (x))
8efab2c5 1825 {
e8ac5ac9 1826 ok = false;
8efab2c5 1827 }
e8ac5ac9
GJL
1828 break;
1829
1830 case POST_INC:
1831 case PRE_DEC:
1832 ok = avr_reg_ok_for_addr_p (XEXP (x, 0), ADDR_SPACE_GENERIC,
1833 GET_CODE (x), strict);
1834 break;
ab758510 1835
e8ac5ac9
GJL
1836 case PLUS:
1837 {
1838 rtx reg = XEXP (x, 0);
1839 rtx op1 = XEXP (x, 1);
00892272 1840
e8ac5ac9
GJL
1841 if (REG_P (reg)
1842 && CONST_INT_P (op1)
1843 && INTVAL (op1) >= 0)
1844 {
1845 bool fit = IN_RANGE (INTVAL (op1), 0, MAX_LD_OFFSET (mode));
1846
1847 if (fit)
1848 {
1849 ok = (! strict
1850 || avr_reg_ok_for_addr_p (reg, ADDR_SPACE_GENERIC,
1851 PLUS, strict));
00892272 1852
e8ac5ac9
GJL
1853 if (reg == frame_pointer_rtx
1854 || reg == arg_pointer_rtx)
1855 {
1856 ok = true;
1857 }
1858 }
1859 else if (frame_pointer_needed
1860 && reg == frame_pointer_rtx)
1861 {
1862 ok = true;
1863 }
1864 }
1865 }
1866 break;
00892272 1867
e8ac5ac9
GJL
1868 default:
1869 break;
1870 }
00892272 1871
d713426e
GJL
1872 if (AVR_TINY
1873 && CONSTANT_ADDRESS_P (x))
1874 {
1875 /* avrtiny's load / store instructions only cover addresses 0..0xbf:
1876 IN / OUT range is 0..0x3f and LDS / STS can access 0x40..0xbf. */
1877
1878 ok = (CONST_INT_P (x)
1879 && IN_RANGE (INTVAL (x), 0, 0xc0 - GET_MODE_SIZE (mode)));
1880 }
1881
ab758510 1882 if (avr_log.legitimate_address_p)
90e7678c 1883 {
e8ac5ac9 1884 avr_edump ("\n%?: ret=%d, mode=%m strict=%d "
ab758510 1885 "reload_completed=%d reload_in_progress=%d %s:",
e8ac5ac9 1886 ok, mode, strict, reload_completed, reload_in_progress,
ab758510 1887 reg_renumber ? "(reg_renumber)" : "");
00892272 1888
ab758510
GJL
1889 if (GET_CODE (x) == PLUS
1890 && REG_P (XEXP (x, 0))
1891 && CONST_INT_P (XEXP (x, 1))
1892 && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
1893 && reg_renumber)
1894 {
1895 avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
1896 true_regnum (XEXP (x, 0)));
1897 }
00892272 1898
ab758510 1899 avr_edump ("\n%r\n", x);
90e7678c 1900 }
00892272 1901
e8ac5ac9 1902 return ok;
90e7678c
DC
1903}
1904
7c209481
GJL
1905
1906/* Former implementation of TARGET_LEGITIMIZE_ADDRESS,
1907 now only a helper for avr_addr_space_legitimize_address. */
90e7678c
DC
1908/* Attempts to replace X with a valid
1909 memory address for an operand of mode MODE */
1910
8efab2c5 1911static rtx
ef4bddc2 1912avr_legitimize_address (rtx x, rtx oldx, machine_mode mode)
90e7678c 1913{
cfbaed3b 1914 bool big_offset_p = false;
00892272 1915
cfbaed3b 1916 x = oldx;
00892272 1917
dbe9dfdd
GJL
1918 if (AVR_TINY)
1919 {
1920 if (CONSTANT_ADDRESS_P (x)
1921 && !(CONST_INT_P (x)
1922 && IN_RANGE (INTVAL (x), 0, 0xc0 - GET_MODE_SIZE (mode))))
1923 {
1924 x = force_reg (Pmode, x);
1925 }
1926 }
1927
cfbaed3b
DC
1928 if (GET_CODE (oldx) == PLUS
1929 && REG_P (XEXP (oldx, 0)))
1930 {
1931 if (REG_P (XEXP (oldx, 1)))
1932 x = force_reg (GET_MODE (oldx), oldx);
1933 else if (CONST_INT_P (XEXP (oldx, 1)))
1934 {
00892272 1935 int offs = INTVAL (XEXP (oldx, 1));
cfbaed3b
DC
1936 if (frame_pointer_rtx != XEXP (oldx, 0)
1937 && offs > MAX_LD_OFFSET (mode))
1938 {
1939 big_offset_p = true;
1940 x = force_reg (GET_MODE (oldx), oldx);
1941 }
1942 }
1943 }
00892272 1944
cfbaed3b
DC
1945 if (avr_log.legitimize_address)
1946 {
1947 avr_edump ("\n%?: mode=%m\n %r\n", mode, oldx);
1948
1949 if (x != oldx)
1950 avr_edump (" %s --> %r\n", big_offset_p ? "(big offset)" : "", x);
1951 }
1952
90e7678c
DC
1953 return x;
1954}
1955
1956
36a50ab6
GJL
1957/* Implement `LEGITIMIZE_RELOAD_ADDRESS'. */
1958/* This will allow register R26/27 to be used where it is no worse than normal
1959 base pointers R28/29 or R30/31. For example, if base offset is greater
1960 than 63 bytes or for R++ or --R addressing. */
1961
1962rtx
ef4bddc2 1963avr_legitimize_reload_address (rtx *px, machine_mode mode,
36a50ab6
GJL
1964 int opnum, int type, int addr_type,
1965 int ind_levels ATTRIBUTE_UNUSED,
1966 rtx (*mk_memloc)(rtx,int))
1967{
c1a330ef 1968 rtx x = *px;
00892272 1969
36a50ab6
GJL
1970 if (avr_log.legitimize_reload_address)
1971 avr_edump ("\n%?:%m %r\n", mode, x);
00892272 1972
36a50ab6
GJL
1973 if (1 && (GET_CODE (x) == POST_INC
1974 || GET_CODE (x) == PRE_DEC))
1975 {
1976 push_reload (XEXP (x, 0), XEXP (x, 0), &XEXP (x, 0), &XEXP (x, 0),
1977 POINTER_REGS, GET_MODE (x), GET_MODE (x), 0, 0,
1978 opnum, RELOAD_OTHER);
00892272 1979
36a50ab6 1980 if (avr_log.legitimize_reload_address)
c1a330ef 1981 avr_edump (" RCLASS.1 = %R\n IN = %r\n OUT = %r\n",
36a50ab6 1982 POINTER_REGS, XEXP (x, 0), XEXP (x, 0));
00892272 1983
36a50ab6
GJL
1984 return x;
1985 }
00892272 1986
36a50ab6
GJL
1987 if (GET_CODE (x) == PLUS
1988 && REG_P (XEXP (x, 0))
1989 && 0 == reg_equiv_constant (REGNO (XEXP (x, 0)))
1990 && CONST_INT_P (XEXP (x, 1))
1991 && INTVAL (XEXP (x, 1)) >= 1)
1992 {
1993 bool fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
00892272 1994
36a50ab6
GJL
1995 if (fit)
1996 {
1997 if (reg_equiv_address (REGNO (XEXP (x, 0))) != 0)
1998 {
1999 int regno = REGNO (XEXP (x, 0));
2000 rtx mem = mk_memloc (x, regno);
00892272 2001
36a50ab6
GJL
2002 push_reload (XEXP (mem, 0), NULL_RTX, &XEXP (mem, 0), NULL,
2003 POINTER_REGS, Pmode, VOIDmode, 0, 0,
1f85d2fb 2004 1, (enum reload_type) addr_type);
00892272 2005
36a50ab6 2006 if (avr_log.legitimize_reload_address)
c1a330ef 2007 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
36a50ab6 2008 POINTER_REGS, XEXP (mem, 0), NULL_RTX);
00892272 2009
36a50ab6
GJL
2010 push_reload (mem, NULL_RTX, &XEXP (x, 0), NULL,
2011 BASE_POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
1f85d2fb 2012 opnum, (enum reload_type) type);
00892272 2013
36a50ab6 2014 if (avr_log.legitimize_reload_address)
c1a330ef 2015 avr_edump (" RCLASS.2 = %R\n IN = %r\n OUT = %r\n",
36a50ab6 2016 BASE_POINTER_REGS, mem, NULL_RTX);
00892272 2017
36a50ab6
GJL
2018 return x;
2019 }
2020 }
2021 else if (! (frame_pointer_needed
cfbaed3b 2022 && XEXP (x, 0) == frame_pointer_rtx))
36a50ab6 2023 {
c1a330ef 2024 push_reload (x, NULL_RTX, px, NULL,
36a50ab6 2025 POINTER_REGS, GET_MODE (x), VOIDmode, 0, 0,
1f85d2fb 2026 opnum, (enum reload_type) type);
00892272 2027
36a50ab6 2028 if (avr_log.legitimize_reload_address)
c1a330ef 2029 avr_edump (" RCLASS.3 = %R\n IN = %r\n OUT = %r\n",
36a50ab6 2030 POINTER_REGS, x, NULL_RTX);
00892272 2031
36a50ab6
GJL
2032 return x;
2033 }
2034 }
00892272 2035
36a50ab6
GJL
2036 return NULL_RTX;
2037}
2038
2039
1e6a67d1 2040/* Helper function to print assembler resp. track instruction
e4fe948a 2041 sequence lengths. Always return "".
00892272 2042
1e6a67d1
GJL
2043 If PLEN == NULL:
2044 Output assembler code from template TPL with operands supplied
2045 by OPERANDS. This is just forwarding to output_asm_insn.
00892272 2046
1e6a67d1 2047 If PLEN != NULL:
a7c0acd0
GJL
2048 If N_WORDS >= 0 Add N_WORDS to *PLEN.
2049 If N_WORDS < 0 Set *PLEN to -N_WORDS.
1e6a67d1
GJL
2050 Don't output anything.
2051*/
2052
e4fe948a 2053static const char*
1e6a67d1
GJL
2054avr_asm_len (const char* tpl, rtx* operands, int* plen, int n_words)
2055{
2056 if (NULL == plen)
2057 {
2058 output_asm_insn (tpl, operands);
2059 }
2060 else
2061 {
a7c0acd0
GJL
2062 if (n_words < 0)
2063 *plen = -n_words;
2064 else
2065 *plen += n_words;
1e6a67d1 2066 }
e4fe948a
GJL
2067
2068 return "";
1e6a67d1
GJL
2069}
2070
2071
2c338472 2072/* Return a pointer register name as a string. */
90e7678c 2073
00892272 2074static const char*
269e3795 2075ptrreg_to_str (int regno)
90e7678c
DC
2076{
2077 switch (regno)
2078 {
2079 case REG_X: return "X";
2080 case REG_Y: return "Y";
2081 case REG_Z: return "Z";
2082 default:
d2111e2f
GJL
2083 output_operand_lossage ("address operand requires constraint for"
2084 " X, Y, or Z register");
90e7678c
DC
2085 }
2086 return NULL;
2087}
2088
2089/* Return the condition name as a string.
2090 Used in conditional jump constructing */
2091
00892272 2092static const char*
269e3795 2093cond_string (enum rtx_code code)
90e7678c
DC
2094{
2095 switch (code)
2096 {
2097 case NE:
2098 return "ne";
2099 case EQ:
2100 return "eq";
2101 case GE:
2102 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
00892272 2103 return "pl";
90e7678c 2104 else
00892272 2105 return "ge";
90e7678c
DC
2106 case LT:
2107 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
00892272 2108 return "mi";
90e7678c 2109 else
00892272 2110 return "lt";
90e7678c
DC
2111 case GEU:
2112 return "sh";
90e7678c
DC
2113 case LTU:
2114 return "lo";
2115 default:
25b9575b 2116 gcc_unreachable ();
90e7678c 2117 }
e4fe948a
GJL
2118
2119 return "";
90e7678c
DC
2120}
2121
666b67b1 2122
c25e1d82
GJL
2123/* Return true if rtx X is a CONST or SYMBOL_REF with progmem.
2124 This must be used for AVR_TINY only because on other cores
2125 the flash memory is not visible in the RAM address range and
2126 cannot be read by, say, LD instruction. */
2127
2128static bool
2129avr_address_tiny_pm_p (rtx x)
2130{
2131 if (CONST == GET_CODE (x))
2132 x = XEXP (XEXP (x, 0), 0);
2133
2134 if (SYMBOL_REF_P (x))
2135 return SYMBOL_REF_FLAGS (x) & AVR_SYMBOL_FLAG_TINY_PM;
2136
2137 return false;
2138}
2139
666b67b1 2140/* Implement `TARGET_PRINT_OPERAND_ADDRESS'. */
2c338472 2141/* Output ADDR to FILE as address. */
90e7678c 2142
666b67b1 2143static void
cc8ca59e 2144avr_print_operand_address (FILE *file, machine_mode /*mode*/, rtx addr)
90e7678c 2145{
c25e1d82
GJL
2146 if (AVR_TINY
2147 && avr_address_tiny_pm_p (addr))
2148 {
2149 addr = plus_constant (Pmode, addr, AVR_TINY_PM_OFFSET);
2150 }
2151
90e7678c
DC
2152 switch (GET_CODE (addr))
2153 {
2154 case REG:
b4f26c06 2155 fprintf (file, "%s", ptrreg_to_str (REGNO (addr)));
90e7678c
DC
2156 break;
2157
2158 case PRE_DEC:
2159 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
2160 break;
2161
2162 case POST_INC:
2163 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
2164 break;
2165
2166 default:
2167 if (CONSTANT_ADDRESS_P (addr)
00892272
GJL
2168 && text_segment_operand (addr, VOIDmode))
2169 {
2170 rtx x = addr;
2171 if (GET_CODE (x) == CONST)
2172 x = XEXP (x, 0);
2173 if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x,1)) == CONST_INT)
2174 {
2175 /* Assembler gs() will implant word address. Make offset
2176 a byte offset inside gs() for assembler. This is
2177 needed because the more logical (constant+gs(sym)) is not
2178 accepted by gas. For 128K and smaller devices this is ok.
2179 For large devices it will create a trampoline to offset
d2111e2f 2180 from symbol which may not be what the user really wanted. */
00892272
GJL
2181
2182 fprintf (file, "gs(");
2183 output_addr_const (file, XEXP (x,0));
d2111e2f
GJL
2184 fprintf (file, "+" HOST_WIDE_INT_PRINT_DEC ")",
2185 2 * INTVAL (XEXP (x, 1)));
00892272
GJL
2186 if (AVR_3_BYTE_PC)
2187 if (warning (0, "pointer offset from symbol maybe incorrect"))
2188 {
2189 output_addr_const (stderr, addr);
2190 fprintf(stderr,"\n");
2191 }
2192 }
2193 else
2194 {
2195 fprintf (file, "gs(");
2196 output_addr_const (file, addr);
2197 fprintf (file, ")");
2198 }
2199 }
90e7678c 2200 else
00892272 2201 output_addr_const (file, addr);
90e7678c
DC
2202 }
2203}
2204
2205
666b67b1
GJL
2206/* Implement `TARGET_PRINT_OPERAND_PUNCT_VALID_P'. */
2207
2208static bool
2209avr_print_operand_punct_valid_p (unsigned char code)
2210{
2211 return code == '~' || code == '!';
2212}
2213
2214
2215/* Implement `TARGET_PRINT_OPERAND'. */
49b2772e
GJL
2216/* Output X as assembler operand to file FILE.
2217 For a description of supported %-codes, see top of avr.md. */
2218
666b67b1
GJL
2219static void
2220avr_print_operand (FILE *file, rtx x, int code)
90e7678c 2221{
c1dd9790 2222 int abcd = 0, ef = 0, ij = 0;
90e7678c
DC
2223
2224 if (code >= 'A' && code <= 'D')
2225 abcd = code - 'A';
c1dd9790
JR
2226 else if (code == 'E' || code == 'F')
2227 ef = code - 'E';
2228 else if (code == 'I' || code == 'J')
2229 ij = code - 'I';
90e7678c 2230
cf14485b
MM
2231 if (code == '~')
2232 {
5dc77808 2233 if (!AVR_HAVE_JMP_CALL)
00892272 2234 fputc ('r', file);
cf14485b 2235 }
693092fb
BH
2236 else if (code == '!')
2237 {
2238 if (AVR_HAVE_EIJMP_EICALL)
00892272 2239 fputc ('e', file);
693092fb 2240 }
49b2772e
GJL
2241 else if (code == 't'
2242 || code == 'T')
2243 {
2244 static int t_regno = -1;
2245 static int t_nbits = -1;
2246
2247 if (REG_P (x) && t_regno < 0 && code == 'T')
2248 {
2249 t_regno = REGNO (x);
2250 t_nbits = GET_MODE_BITSIZE (GET_MODE (x));
2251 }
2252 else if (CONST_INT_P (x) && t_regno >= 0
2253 && IN_RANGE (INTVAL (x), 0, t_nbits - 1))
2254 {
2255 int bpos = INTVAL (x);
2256
2257 fprintf (file, "%s", reg_names[t_regno + bpos / 8]);
2258 if (code == 'T')
2259 fprintf (file, ",%d", bpos % 8);
2260
2261 t_regno = -1;
2262 }
2263 else
2264 fatal_insn ("operands to %T/%t must be reg + const_int:", x);
2265 }
c1dd9790
JR
2266 else if (code == 'E' || code == 'F')
2267 {
2268 rtx op = XEXP(x, 0);
b4f26c06 2269 fprintf (file, "%s", reg_names[REGNO (op) + ef]);
c1dd9790
JR
2270 }
2271 else if (code == 'I' || code == 'J')
2272 {
2273 rtx op = XEXP(XEXP(x, 0), 0);
b4f26c06 2274 fprintf (file, "%s", reg_names[REGNO (op) + ij]);
c1dd9790 2275 }
cf14485b 2276 else if (REG_P (x))
90e7678c
DC
2277 {
2278 if (x == zero_reg_rtx)
51526856
GJL
2279 fprintf (file, "__zero_reg__");
2280 else if (code == 'r' && REGNO (x) < 32)
2281 fprintf (file, "%d", (int) REGNO (x));
90e7678c 2282 else
b4f26c06 2283 fprintf (file, "%s", reg_names[REGNO (x) + abcd]);
90e7678c 2284 }
2cc11a88
GJL
2285 else if (CONST_INT_P (x))
2286 {
2287 HOST_WIDE_INT ival = INTVAL (x);
00892272 2288
2cc11a88
GJL
2289 if ('i' != code)
2290 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival + abcd);
2291 else if (low_io_address_operand (x, VOIDmode)
2292 || high_io_address_operand (x, VOIDmode))
2293 {
2da8c1ad
GJL
2294 if (AVR_HAVE_RAMPZ && ival == avr_addr.rampz)
2295 fprintf (file, "__RAMPZ__");
2296 else if (AVR_HAVE_RAMPY && ival == avr_addr.rampy)
2297 fprintf (file, "__RAMPY__");
2298 else if (AVR_HAVE_RAMPX && ival == avr_addr.rampx)
2299 fprintf (file, "__RAMPX__");
2300 else if (AVR_HAVE_RAMPD && ival == avr_addr.rampd)
2301 fprintf (file, "__RAMPD__");
c1dd9790 2302 else if ((AVR_XMEGA || AVR_TINY) && ival == avr_addr.ccp)
2da8c1ad 2303 fprintf (file, "__CCP__");
82b37806
GJL
2304 else if (ival == avr_addr.sreg) fprintf (file, "__SREG__");
2305 else if (ival == avr_addr.sp_l) fprintf (file, "__SP_L__");
2306 else if (ival == avr_addr.sp_h) fprintf (file, "__SP_H__");
2307 else
2cc11a88 2308 {
2cc11a88 2309 fprintf (file, HOST_WIDE_INT_PRINT_HEX,
4a2caf6c 2310 ival - avr_arch->sfr_offset);
2cc11a88
GJL
2311 }
2312 }
2313 else
2314 fatal_insn ("bad address, not an I/O address:", x);
2315 }
2316 else if (MEM_P (x))
90e7678c 2317 {
d2111e2f 2318 rtx addr = XEXP (x, 0);
00892272 2319
846428f1 2320 if (code == 'm')
00892272 2321 {
d2111e2f 2322 if (!CONSTANT_P (addr))
5436efaa 2323 fatal_insn ("bad address, not a constant:", addr);
d2111e2f
GJL
2324 /* Assembler template with m-code is data - not progmem section */
2325 if (text_segment_operand (addr, VOIDmode))
2326 if (warning (0, "accessing data memory with"
2327 " program memory address"))
2328 {
2329 output_addr_const (stderr, addr);
2330 fprintf(stderr,"\n");
2331 }
2332 output_addr_const (file, addr);
00892272 2333 }
5436efaa
GJL
2334 else if (code == 'i')
2335 {
666b67b1 2336 avr_print_operand (file, addr, 'i');
5436efaa 2337 }
cf14485b 2338 else if (code == 'o')
00892272
GJL
2339 {
2340 if (GET_CODE (addr) != PLUS)
2341 fatal_insn ("bad address, not (reg+disp):", addr);
cf14485b 2342
00892272
GJL
2343 avr_print_operand (file, XEXP (addr, 1), 0);
2344 }
c1dd9790
JR
2345 else if (code == 'b')
2346 {
2347 if (GET_CODE (addr) != PLUS)
2348 fatal_insn ("bad address, not (reg+disp):", addr);
2349
cc8ca59e 2350 avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
c1dd9790 2351 }
a6990185
MM
2352 else if (code == 'p' || code == 'r')
2353 {
2354 if (GET_CODE (addr) != POST_INC && GET_CODE (addr) != PRE_DEC)
2355 fatal_insn ("bad address, not post_inc or pre_dec:", addr);
00892272 2356
a6990185 2357 if (code == 'p')
cc8ca59e
JB
2358 /* X, Y, Z */
2359 avr_print_operand_address (file, VOIDmode, XEXP (addr, 0));
a6990185 2360 else
666b67b1 2361 avr_print_operand (file, XEXP (addr, 0), 0); /* r26, r28, r30 */
a6990185 2362 }
90e7678c 2363 else if (GET_CODE (addr) == PLUS)
00892272 2364 {
cc8ca59e 2365 avr_print_operand_address (file, VOIDmode, XEXP (addr,0));
00892272
GJL
2366 if (REGNO (XEXP (addr, 0)) == REG_X)
2367 fatal_insn ("internal compiler error. Bad address:"
2368 ,addr);
2369 fputc ('+', file);
2370 avr_print_operand (file, XEXP (addr,1), code);
2371 }
90e7678c 2372 else
cc8ca59e 2373 avr_print_operand_address (file, VOIDmode, addr);
90e7678c 2374 }
2cc11a88
GJL
2375 else if (code == 'i')
2376 {
f9d29866
JR
2377 if (GET_CODE (x) == SYMBOL_REF && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO))
2378 avr_print_operand_address
cc8ca59e 2379 (file, VOIDmode, plus_constant (HImode, x, -avr_arch->sfr_offset));
f9d29866
JR
2380 else
2381 fatal_insn ("bad address, not an I/O address:", x);
2cc11a88 2382 }
846428f1
AH
2383 else if (code == 'x')
2384 {
2385 /* Constant progmem address - like used in jmp or call */
2386 if (0 == text_segment_operand (x, VOIDmode))
d2111e2f
GJL
2387 if (warning (0, "accessing program memory"
2388 " with data memory address"))
00892272
GJL
2389 {
2390 output_addr_const (stderr, x);
2391 fprintf(stderr,"\n");
2392 }
846428f1
AH
2393 /* Use normal symbol for direct address no linker trampoline needed */
2394 output_addr_const (file, x);
2395 }
51526856 2396 else if (CONST_FIXED_P (x))
e55e4056
GJL
2397 {
2398 HOST_WIDE_INT ival = INTVAL (avr_to_int_mode (x));
2399 if (code != 0)
c2a939b1 2400 output_operand_lossage ("Unsupported code '%c' for fixed-point:",
e55e4056
GJL
2401 code);
2402 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ival);
2403 }
90e7678c
DC
2404 else if (GET_CODE (x) == CONST_DOUBLE)
2405 {
2406 long val;
90e7678c 2407 if (GET_MODE (x) != SFmode)
00892272 2408 fatal_insn ("internal compiler error. Unknown mode:", x);
34a72c33 2409 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), val);
761c70aa 2410 fprintf (file, "0x%lx", val);
90e7678c 2411 }
7bc6df2c
GJL
2412 else if (GET_CODE (x) == CONST_STRING)
2413 fputs (XSTR (x, 0), file);
90e7678c 2414 else if (code == 'j')
761c70aa 2415 fputs (cond_string (GET_CODE (x)), file);
90e7678c 2416 else if (code == 'k')
761c70aa 2417 fputs (cond_string (reverse_condition (GET_CODE (x))), file);
90e7678c 2418 else
cc8ca59e 2419 avr_print_operand_address (file, VOIDmode, x);
90e7678c
DC
2420}
2421
00892272 2422
998f15f3
SKS
2423/* Implement TARGET_USE_BY_PIECES_INFRASTRUCTURE_P. */
2424
2425/* Prefer sequence of loads/stores for moves of size upto
2426 two - two pairs of load/store instructions are always better
2427 than the 5 instruction sequence for a loop (1 instruction
2428 for loop counter setup, and 4 for the body of the loop). */
2429
2430static bool
2431avr_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size,
2432 unsigned int align ATTRIBUTE_UNUSED,
2433 enum by_pieces_operation op,
2434 bool speed_p)
2435{
2436
2437 if (op != MOVE_BY_PIECES || (speed_p && (size > (MOVE_MAX_PIECES))))
2438 return default_use_by_pieces_infrastructure_p (size, align, op, speed_p);
2439
2440 return size <= (MOVE_MAX_PIECES);
2441}
2442
2443
00892272 2444/* Worker function for `NOTICE_UPDATE_CC'. */
90e7678c
DC
2445/* Update the condition code in the INSN. */
2446
2447void
647d790d 2448avr_notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx_insn *insn)
90e7678c 2449{
3454eb73 2450 rtx set;
05058b6e 2451 enum attr_cc cc = get_attr_cc (insn);
00892272 2452
05058b6e 2453 switch (cc)
90e7678c 2454 {
05058b6e
GJL
2455 default:
2456 break;
2457
51526856 2458 case CC_PLUS:
299c4b5f 2459 case CC_LDI:
05058b6e
GJL
2460 {
2461 rtx *op = recog_data.operand;
2462 int len_dummy, icc;
00892272 2463
05058b6e
GJL
2464 /* Extract insn's operands. */
2465 extract_constrain_insn_cached (insn);
2f47b8d3 2466
299c4b5f
GJL
2467 switch (cc)
2468 {
2469 default:
2470 gcc_unreachable();
00892272 2471
51526856
GJL
2472 case CC_PLUS:
2473 avr_out_plus (insn, op, &len_dummy, &icc);
e55e4056
GJL
2474 cc = (enum attr_cc) icc;
2475 break;
2476
299c4b5f
GJL
2477 case CC_LDI:
2478
2479 cc = (op[1] == CONST0_RTX (GET_MODE (op[0]))
2480 && reg_overlap_mentioned_p (op[0], zero_reg_rtx))
00892272 2481 /* Loading zero-reg with 0 uses CLR and thus clobbers cc0. */
299c4b5f
GJL
2482 ? CC_CLOBBER
2483 /* Any other "r,rL" combination does not alter cc0. */
2484 : CC_NONE;
00892272 2485
299c4b5f
GJL
2486 break;
2487 } /* inner switch */
2488
05058b6e
GJL
2489 break;
2490 }
299c4b5f 2491 } /* outer swicth */
05058b6e
GJL
2492
2493 switch (cc)
2494 {
2495 default:
2496 /* Special values like CC_OUT_PLUS from above have been
2497 mapped to "standard" CC_* values so we never come here. */
00892272 2498
05058b6e
GJL
2499 gcc_unreachable();
2500 break;
00892272 2501
90e7678c 2502 case CC_NONE:
bc084f84
GJL
2503 /* Insn does not affect CC at all, but it might set some registers
2504 that are stored in cc_status. If such a register is affected by
2505 the current insn, for example by means of a SET or a CLOBBER,
2506 then we must reset cc_status; cf. PR77326.
2507
2508 Unfortunately, set_of cannot be used as reg_overlap_mentioned_p
2509 will abort on COMPARE (which might be found in cc_status.value1/2).
2510 Thus work out the registers set by the insn and regs mentioned
2511 in cc_status.value1/2. */
2512
2513 if (cc_status.value1
2514 || cc_status.value2)
2515 {
2516 HARD_REG_SET regs_used;
2517 HARD_REG_SET regs_set;
2518 CLEAR_HARD_REG_SET (regs_used);
2519
2520 if (cc_status.value1
2521 && !CONSTANT_P (cc_status.value1))
2522 {
2523 find_all_hard_regs (cc_status.value1, &regs_used);
2524 }
2525
2526 if (cc_status.value2
2527 && !CONSTANT_P (cc_status.value2))
2528 {
2529 find_all_hard_regs (cc_status.value2, &regs_used);
2530 }
2531
2532 find_all_hard_reg_sets (insn, &regs_set, false);
2533
2534 if (hard_reg_set_intersect_p (regs_used, regs_set))
2535 {
2536 CC_STATUS_INIT;
2537 }
2538 }
2539
2540 break; // CC_NONE
90e7678c
DC
2541
2542 case CC_SET_N:
2543 CC_STATUS_INIT;
2544 break;
2545
2546 case CC_SET_ZN:
3454eb73
DC
2547 set = single_set (insn);
2548 CC_STATUS_INIT;
2549 if (set)
00892272
GJL
2550 {
2551 cc_status.flags |= CC_NO_OVERFLOW;
2552 cc_status.value1 = SET_DEST (set);
2553 }
90e7678c
DC
2554 break;
2555
b8469805
GJL
2556 case CC_SET_VZN:
2557 /* Insn like INC, DEC, NEG that set Z,N,V. We currently don't make use
2558 of this combination, cf. also PR61055. */
2559 CC_STATUS_INIT;
2560 break;
2561
90e7678c
DC
2562 case CC_SET_CZN:
2563 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
2564 The V flag may or may not be known but that's ok because
2565 alter_cond will change tests to use EQ/NE. */
3454eb73
DC
2566 set = single_set (insn);
2567 CC_STATUS_INIT;
2568 if (set)
00892272
GJL
2569 {
2570 cc_status.value1 = SET_DEST (set);
2571 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
2572 }
90e7678c
DC
2573 break;
2574
2575 case CC_COMPARE:
3454eb73
DC
2576 set = single_set (insn);
2577 CC_STATUS_INIT;
2578 if (set)
00892272 2579 cc_status.value1 = SET_SRC (set);
90e7678c 2580 break;
00892272 2581
90e7678c
DC
2582 case CC_CLOBBER:
2583 /* Insn doesn't leave CC in a usable state. */
2584 CC_STATUS_INIT;
2585 break;
2586 }
2587}
2588
90e7678c
DC
2589/* Choose mode for jump insn:
2590 1 - relative jump in range -63 <= x <= 62 ;
2591 2 - relative jump in range -2046 <= x <= 2045 ;
2592 3 - absolute jump (only for ATmega[16]03). */
2593
2594int
98024b4e 2595avr_jump_mode (rtx x, rtx_insn *insn)
90e7678c 2596{
5a82ecd9 2597 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_CODE (x) == LABEL_REF
00892272 2598 ? XEXP (x, 0) : x));
9d98a694 2599 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
90e7678c 2600 int jump_distance = cur_addr - dest_addr;
00892272 2601
90e7678c
DC
2602 if (-63 <= jump_distance && jump_distance <= 62)
2603 return 1;
2604 else if (-2046 <= jump_distance && jump_distance <= 2045)
2605 return 2;
5dc77808 2606 else if (AVR_HAVE_JMP_CALL)
90e7678c 2607 return 3;
00892272 2608
90e7678c
DC
2609 return 2;
2610}
2611
00892272 2612/* Return an AVR condition jump commands.
56b871c1
DC
2613 X is a comparison RTX.
2614 LEN is a number returned by avr_jump_mode function.
00892272 2615 If REVERSE nonzero then condition code in X must be reversed. */
90e7678c 2616
00892272 2617const char*
269e3795 2618ret_cond_branch (rtx x, int len, int reverse)
90e7678c 2619{
56b871c1 2620 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
00892272 2621
90e7678c
DC
2622 switch (cond)
2623 {
2624 case GT:
2625 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
c2453253
GJL
2626 return (len == 1 ? ("breq .+2" CR_TAB
2627 "brpl %0") :
2628 len == 2 ? ("breq .+4" CR_TAB
2629 "brmi .+2" CR_TAB
2630 "rjmp %0") :
2631 ("breq .+6" CR_TAB
2632 "brmi .+4" CR_TAB
2633 "jmp %0"));
00892272 2634
90e7678c 2635 else
c2453253
GJL
2636 return (len == 1 ? ("breq .+2" CR_TAB
2637 "brge %0") :
2638 len == 2 ? ("breq .+4" CR_TAB
2639 "brlt .+2" CR_TAB
2640 "rjmp %0") :
2641 ("breq .+6" CR_TAB
2642 "brlt .+4" CR_TAB
2643 "jmp %0"));
90e7678c 2644 case GTU:
c2453253
GJL
2645 return (len == 1 ? ("breq .+2" CR_TAB
2646 "brsh %0") :
2647 len == 2 ? ("breq .+4" CR_TAB
2648 "brlo .+2" CR_TAB
2649 "rjmp %0") :
2650 ("breq .+6" CR_TAB
2651 "brlo .+4" CR_TAB
2652 "jmp %0"));
90e7678c
DC
2653 case LE:
2654 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
c2453253
GJL
2655 return (len == 1 ? ("breq %0" CR_TAB
2656 "brmi %0") :
2657 len == 2 ? ("breq .+2" CR_TAB
2658 "brpl .+2" CR_TAB
2659 "rjmp %0") :
2660 ("breq .+2" CR_TAB
2661 "brpl .+4" CR_TAB
2662 "jmp %0"));
90e7678c 2663 else
c2453253
GJL
2664 return (len == 1 ? ("breq %0" CR_TAB
2665 "brlt %0") :
2666 len == 2 ? ("breq .+2" CR_TAB
2667 "brge .+2" CR_TAB
2668 "rjmp %0") :
2669 ("breq .+2" CR_TAB
2670 "brge .+4" CR_TAB
2671 "jmp %0"));
90e7678c 2672 case LEU:
c2453253
GJL
2673 return (len == 1 ? ("breq %0" CR_TAB
2674 "brlo %0") :
2675 len == 2 ? ("breq .+2" CR_TAB
2676 "brsh .+2" CR_TAB
2677 "rjmp %0") :
2678 ("breq .+2" CR_TAB
2679 "brsh .+4" CR_TAB
2680 "jmp %0"));
90e7678c 2681 default:
56b871c1
DC
2682 if (reverse)
2683 {
2684 switch (len)
2685 {
2686 case 1:
c2453253 2687 return "br%k1 %0";
56b871c1 2688 case 2:
c2453253
GJL
2689 return ("br%j1 .+2" CR_TAB
2690 "rjmp %0");
56b871c1 2691 default:
c2453253
GJL
2692 return ("br%j1 .+4" CR_TAB
2693 "jmp %0");
56b871c1
DC
2694 }
2695 }
c2453253
GJL
2696 else
2697 {
2698 switch (len)
2699 {
2700 case 1:
2701 return "br%j1 %0";
2702 case 2:
2703 return ("br%k1 .+2" CR_TAB
2704 "rjmp %0");
2705 default:
2706 return ("br%k1 .+4" CR_TAB
2707 "jmp %0");
2708 }
2709 }
90e7678c
DC
2710 }
2711 return "";
2712}
2713
00892272
GJL
2714
2715/* Worker function for `FINAL_PRESCAN_INSN'. */
007a178c 2716/* Output insn cost for next insn. */
90e7678c
DC
2717
2718void
98024b4e 2719avr_final_prescan_insn (rtx_insn *insn, rtx *operand ATTRIBUTE_UNUSED,
00892272 2720 int num_operands ATTRIBUTE_UNUSED)
90e7678c 2721{
ab758510 2722 if (avr_log.rtx_costs)
90e7678c 2723 {
e9514725
GJL
2724 rtx set = single_set (insn);
2725
2726 if (set)
2727 fprintf (asm_out_file, "/* DEBUG: cost = %d. */\n",
e548c9df
AM
2728 set_src_cost (SET_SRC (set), GET_MODE (SET_DEST (set)),
2729 optimize_insn_for_speed_p ()));
e9514725
GJL
2730 else
2731 fprintf (asm_out_file, "/* DEBUG: pattern-cost = %d. */\n",
e548c9df 2732 rtx_cost (PATTERN (insn), VOIDmode, INSN, 0,
00892272 2733 optimize_insn_for_speed_p()));
90e7678c 2734 }
90e7678c
DC
2735}
2736
5fecfd8d 2737/* Return 0 if undefined, 1 if always true or always false. */
90e7678c
DC
2738
2739int
ef4bddc2 2740avr_simplify_comparison_p (machine_mode mode, RTX_CODE op, rtx x)
90e7678c
DC
2741{
2742 unsigned int max = (mode == QImode ? 0xff :
2743 mode == HImode ? 0xffff :
e4fe948a 2744 mode == PSImode ? 0xffffff :
11f9ed1a 2745 mode == SImode ? 0xffffffff : 0);
00892272 2746 if (max && op && CONST_INT_P (x))
90e7678c 2747 {
0a2aaacc 2748 if (unsigned_condition (op) != op)
00892272 2749 max >>= 1;
90e7678c
DC
2750
2751 if (max != (INTVAL (x) & max)
00892272
GJL
2752 && INTVAL (x) != 0xff)
2753 return 1;
90e7678c
DC
2754 }
2755 return 0;
2756}
2757
2758
00892272 2759/* Worker function for `FUNCTION_ARG_REGNO_P'. */
90e7678c
DC
2760/* Returns nonzero if REGNO is the number of a hard
2761 register in which function arguments are sometimes passed. */
2762
2763int
00892272 2764avr_function_arg_regno_p(int r)
90e7678c 2765{
c1dd9790 2766 return (AVR_TINY ? r >= 20 && r <= 25 : r >= 8 && r <= 25);
90e7678c
DC
2767}
2768
00892272
GJL
2769
2770/* Worker function for `INIT_CUMULATIVE_ARGS'. */
90e7678c
DC
2771/* Initializing the variable cum for the state at the beginning
2772 of the argument list. */
2773
2774void
00892272
GJL
2775avr_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
2776 tree fndecl ATTRIBUTE_UNUSED)
90e7678c 2777{
c1dd9790 2778 cum->nregs = AVR_TINY ? 6 : 18;
90e7678c 2779 cum->regno = FIRST_CUM_REG;
f38958e8
NF
2780 if (!libname && stdarg_p (fntype))
2781 cum->nregs = 0;
980a0ff4
GJL
2782
2783 /* Assume the calle may be tail called */
00892272 2784
980a0ff4 2785 cfun->machine->sibcall_fails = 0;
90e7678c
DC
2786}
2787
c4984bad
MM
2788/* Returns the number of registers to allocate for a function argument. */
2789
2790static int
ef4bddc2 2791avr_num_arg_regs (machine_mode mode, const_tree type)
c4984bad
MM
2792{
2793 int size;
2794
2795 if (mode == BLKmode)
2796 size = int_size_in_bytes (type);
2797 else
2798 size = GET_MODE_SIZE (mode);
2799
afee2a52
MM
2800 /* Align all function arguments to start in even-numbered registers.
2801 Odd-sized arguments leave holes above them. */
c4984bad 2802
afee2a52 2803 return (size + 1) & ~1;
c4984bad
MM
2804}
2805
00892272
GJL
2806
2807/* Implement `TARGET_FUNCTION_ARG'. */
90e7678c 2808/* Controls whether a function argument is passed
2c338472 2809 in a register, and which register. */
90e7678c 2810
733bdfbd 2811static rtx
ef4bddc2 2812avr_function_arg (cumulative_args_t cum_v, machine_mode mode,
00892272 2813 const_tree type, bool named ATTRIBUTE_UNUSED)
90e7678c 2814{
d5cc9181 2815 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
c4984bad 2816 int bytes = avr_num_arg_regs (mode, type);
90e7678c
DC
2817
2818 if (cum->nregs && bytes <= cum->nregs)
f1c25d3b 2819 return gen_rtx_REG (mode, cum->regno - bytes);
c4984bad 2820
90e7678c
DC
2821 return NULL_RTX;
2822}
2823
00892272
GJL
2824
2825/* Implement `TARGET_FUNCTION_ARG_ADVANCE'. */
90e7678c
DC
2826/* Update the summarizer variable CUM to advance past an argument
2827 in the argument list. */
00892272 2828
733bdfbd 2829static void
ef4bddc2 2830avr_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
00892272 2831 const_tree type, bool named ATTRIBUTE_UNUSED)
90e7678c 2832{
d5cc9181 2833 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
c4984bad 2834 int bytes = avr_num_arg_regs (mode, type);
90e7678c 2835
90e7678c
DC
2836 cum->nregs -= bytes;
2837 cum->regno -= bytes;
2838
00892272 2839 /* A parameter is being passed in a call-saved register. As the original
980a0ff4
GJL
2840 contents of these regs has to be restored before leaving the function,
2841 a function must not pass arguments in call-saved regs in order to get
00892272
GJL
2842 tail-called. */
2843
3f5ea9dc
GJL
2844 if (cum->regno >= 8
2845 && cum->nregs >= 0
980a0ff4
GJL
2846 && !call_used_regs[cum->regno])
2847 {
2848 /* FIXME: We ship info on failing tail-call in struct machine_function.
2849 This uses internals of calls.c:expand_call() and the way args_so_far
00892272
GJL
2850 is used. targetm.function_ok_for_sibcall() needs to be extended to
2851 pass &args_so_far, too. At present, CUMULATIVE_ARGS is target
2852 dependent so that such an extension is not wanted. */
2853
980a0ff4
GJL
2854 cfun->machine->sibcall_fails = 1;
2855 }
2856
f24a5190
GJL
2857 /* Test if all registers needed by the ABI are actually available. If the
2858 user has fixed a GPR needed to pass an argument, an (implicit) function
e3e28585 2859 call will clobber that fixed register. See PR45099 for an example. */
00892272 2860
3f5ea9dc
GJL
2861 if (cum->regno >= 8
2862 && cum->nregs >= 0)
f24a5190
GJL
2863 {
2864 int regno;
2865
2866 for (regno = cum->regno; regno < cum->regno + bytes; regno++)
2867 if (fixed_regs[regno])
e3e28585
GJL
2868 warning (0, "fixed register %s used to pass parameter to function",
2869 reg_names[regno]);
f24a5190 2870 }
00892272 2871
90e7678c
DC
2872 if (cum->nregs <= 0)
2873 {
2874 cum->nregs = 0;
2875 cum->regno = FIRST_CUM_REG;
2876 }
90e7678c
DC
2877}
2878
980a0ff4
GJL
2879/* Implement `TARGET_FUNCTION_OK_FOR_SIBCALL' */
2880/* Decide whether we can make a sibling call to a function. DECL is the
2881 declaration of the function being targeted by the call and EXP is the
00892272 2882 CALL_EXPR representing the call. */
980a0ff4
GJL
2883
2884static bool
2885avr_function_ok_for_sibcall (tree decl_callee, tree exp_callee)
2886{
2887 tree fntype_callee;
2888
2889 /* Tail-calling must fail if callee-saved regs are used to pass
2890 function args. We must not tail-call when `epilogue_restores'
2891 is used. Unfortunately, we cannot tell at this point if that
2892 actually will happen or not, and we cannot step back from
00892272
GJL
2893 tail-calling. Thus, we inhibit tail-calling with -mcall-prologues. */
2894
980a0ff4
GJL
2895 if (cfun->machine->sibcall_fails
2896 || TARGET_CALL_PROLOGUES)
2897 {
2898 return false;
2899 }
00892272 2900
980a0ff4
GJL
2901 fntype_callee = TREE_TYPE (CALL_EXPR_FN (exp_callee));
2902
2903 if (decl_callee)
2904 {
2905 decl_callee = TREE_TYPE (decl_callee);
2906 }
2907 else
2908 {
2909 decl_callee = fntype_callee;
00892272 2910
980a0ff4
GJL
2911 while (FUNCTION_TYPE != TREE_CODE (decl_callee)
2912 && METHOD_TYPE != TREE_CODE (decl_callee))
2913 {
2914 decl_callee = TREE_TYPE (decl_callee);
2915 }
2916 }
2917
2918 /* Ensure that caller and callee have compatible epilogues */
00892272 2919
eac188c5
GJL
2920 if (cfun->machine->is_interrupt
2921 || cfun->machine->is_signal
2922 || cfun->machine->is_naked
980a0ff4 2923 || avr_naked_function_p (decl_callee)
00892272 2924 /* FIXME: For OS_task and OS_main, this might be over-conservative. */
980a0ff4 2925 || (avr_OS_task_function_p (decl_callee)
eac188c5 2926 != cfun->machine->is_OS_task)
980a0ff4 2927 || (avr_OS_main_function_p (decl_callee)
eac188c5 2928 != cfun->machine->is_OS_main))
980a0ff4
GJL
2929 {
2930 return false;
2931 }
00892272 2932
980a0ff4
GJL
2933 return true;
2934}
2935
90e7678c
DC
2936/***********************************************************************
2937 Functions for outputting various mov's for a various modes
2938************************************************************************/
7c209481
GJL
2939
2940/* Return true if a value of mode MODE is read from flash by
2941 __load_* function from libgcc. */
2942
2943bool
2944avr_load_libgcc_p (rtx op)
2945{
ef4bddc2 2946 machine_mode mode = GET_MODE (op);
7c209481 2947 int n_bytes = GET_MODE_SIZE (mode);
00892272 2948
7c209481
GJL
2949 return (n_bytes > 2
2950 && !AVR_HAVE_LPMX
3fd1e31d 2951 && avr_mem_flash_p (op));
7c209481
GJL
2952}
2953
7bc6df2c
GJL
2954/* Return true if a value of mode MODE is read by __xload_* function. */
2955
2956bool
ef4bddc2 2957avr_xload_libgcc_p (machine_mode mode)
7bc6df2c
GJL
2958{
2959 int n_bytes = GET_MODE_SIZE (mode);
00892272 2960
7bc6df2c 2961 return (n_bytes > 1
f9d29866 2962 || avr_n_flash > 1);
7bc6df2c
GJL
2963}
2964
2965
3fd1e31d
GJL
2966/* Fixme: This is a hack because secondary reloads don't works as expected.
2967
2968 Find an unused d-register to be used as scratch in INSN.
2969 EXCLUDE is either NULL_RTX or some register. In the case where EXCLUDE
2970 is a register, skip all possible return values that overlap EXCLUDE.
2971 The policy for the returned register is similar to that of
2972 `reg_unused_after', i.e. the returned register may overlap the SET_DEST
2973 of INSN.
2974
2975 Return a QImode d-register or NULL_RTX if nothing found. */
2976
2977static rtx
98024b4e 2978avr_find_unused_d_reg (rtx_insn *insn, rtx exclude)
3fd1e31d
GJL
2979{
2980 int regno;
2981 bool isr_p = (avr_interrupt_function_p (current_function_decl)
2982 || avr_signal_function_p (current_function_decl));
2983
2984 for (regno = 16; regno < 32; regno++)
2985 {
2986 rtx reg = all_regs_rtx[regno];
00892272 2987
3fd1e31d
GJL
2988 if ((exclude
2989 && reg_overlap_mentioned_p (exclude, reg))
2990 || fixed_regs[regno])
2991 {
2992 continue;
2993 }
2994
2995 /* Try non-live register */
2996
2997 if (!df_regs_ever_live_p (regno)
2998 && (TREE_THIS_VOLATILE (current_function_decl)
2999 || cfun->machine->is_OS_task
3000 || cfun->machine->is_OS_main
3001 || (!isr_p && call_used_regs[regno])))
3002 {
3003 return reg;
3004 }
3005
3006 /* Any live register can be used if it is unused after.
3007 Prologue/epilogue will care for it as needed. */
00892272 3008
3fd1e31d
GJL
3009 if (df_regs_ever_live_p (regno)
3010 && reg_unused_after (insn, reg))
3011 {
3012 return reg;
3013 }
3014 }
3015
3016 return NULL_RTX;
3017}
3018
3019
3020/* Helper function for the next function in the case where only restricted
3021 version of LPM instruction is available. */
3022
3023static const char*
98024b4e 3024avr_out_lpm_no_lpmx (rtx_insn *insn, rtx *xop, int *plen)
3fd1e31d
GJL
3025{
3026 rtx dest = xop[0];
3027 rtx addr = xop[1];
3028 int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
3029 int regno_dest;
3030
3031 regno_dest = REGNO (dest);
3032
3033 /* The implicit target register of LPM. */
3034 xop[3] = lpm_reg_rtx;
3035
3036 switch (GET_CODE (addr))
3037 {
3038 default:
3039 gcc_unreachable();
3040
3041 case REG:
3042
3043 gcc_assert (REG_Z == REGNO (addr));
3044
3045 switch (n_bytes)
3046 {
3047 default:
3048 gcc_unreachable();
3049
3050 case 1:
3051 avr_asm_len ("%4lpm", xop, plen, 1);
3052
3053 if (regno_dest != LPM_REGNO)
3054 avr_asm_len ("mov %0,%3", xop, plen, 1);
3055
3056 return "";
3057
3058 case 2:
3059 if (REGNO (dest) == REG_Z)
3060 return avr_asm_len ("%4lpm" CR_TAB
3061 "push %3" CR_TAB
3062 "adiw %2,1" CR_TAB
3063 "%4lpm" CR_TAB
3064 "mov %B0,%3" CR_TAB
3065 "pop %A0", xop, plen, 6);
00892272 3066
3fd1e31d
GJL
3067 avr_asm_len ("%4lpm" CR_TAB
3068 "mov %A0,%3" CR_TAB
3069 "adiw %2,1" CR_TAB
3070 "%4lpm" CR_TAB
3071 "mov %B0,%3", xop, plen, 5);
00892272 3072
3fd1e31d
GJL
3073 if (!reg_unused_after (insn, addr))
3074 avr_asm_len ("sbiw %2,1", xop, plen, 1);
00892272 3075
3fd1e31d
GJL
3076 break; /* 2 */
3077 }
00892272 3078
3fd1e31d
GJL
3079 break; /* REG */
3080
3081 case POST_INC:
3082
3083 gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
3084 && n_bytes <= 4);
3085
3086 if (regno_dest == LPM_REGNO)
3087 avr_asm_len ("%4lpm" CR_TAB
3088 "adiw %2,1", xop, plen, 2);
3089 else
3090 avr_asm_len ("%4lpm" CR_TAB
3091 "mov %A0,%3" CR_TAB
3092 "adiw %2,1", xop, plen, 3);
3093
3094 if (n_bytes >= 2)
3095 avr_asm_len ("%4lpm" CR_TAB
3096 "mov %B0,%3" CR_TAB
3097 "adiw %2,1", xop, plen, 3);
3098
3099 if (n_bytes >= 3)
3100 avr_asm_len ("%4lpm" CR_TAB
3101 "mov %C0,%3" CR_TAB
3102 "adiw %2,1", xop, plen, 3);
3103
3104 if (n_bytes >= 4)
3105 avr_asm_len ("%4lpm" CR_TAB
3106 "mov %D0,%3" CR_TAB
3107 "adiw %2,1", xop, plen, 3);
3108
3109 break; /* POST_INC */
00892272 3110
3fd1e31d 3111 } /* switch CODE (addr) */
00892272 3112
3fd1e31d
GJL
3113 return "";
3114}
3115
3116
7c209481
GJL
3117/* If PLEN == NULL: Ouput instructions to load a value from a memory location
3118 OP[1] in AS1 to register OP[0].
3119 If PLEN != 0 set *PLEN to the length in words of the instruction sequence.
3120 Return "". */
3121
1a910f8f 3122const char*
98024b4e 3123avr_out_lpm (rtx_insn *insn, rtx *op, int *plen)
7c209481 3124{
3fd1e31d 3125 rtx xop[7];
7c209481
GJL
3126 rtx dest = op[0];
3127 rtx src = SET_SRC (single_set (insn));
3128 rtx addr;
3129 int n_bytes = GET_MODE_SIZE (GET_MODE (dest));
3fd1e31d 3130 int segment;
562f552b 3131 RTX_CODE code;
cba300dd 3132 addr_space_t as = MEM_ADDR_SPACE (src);
7c209481
GJL
3133
3134 if (plen)
3135 *plen = 0;
00892272 3136
7c209481
GJL
3137 if (MEM_P (dest))
3138 {
3139 warning (0, "writing to address space %qs not supported",
562f552b 3140 avr_addrspace[MEM_ADDR_SPACE (dest)].name);
00892272 3141
7c209481
GJL
3142 return "";
3143 }
3144
562f552b
GJL
3145 addr = XEXP (src, 0);
3146 code = GET_CODE (addr);
7bc6df2c 3147
562f552b 3148 gcc_assert (REG_P (dest));
cba300dd 3149 gcc_assert (REG == code || POST_INC == code);
7c209481 3150
03b29b0a 3151 xop[0] = dest;
3fd1e31d
GJL
3152 xop[1] = addr;
3153 xop[2] = lpm_addr_reg_rtx;
3154 xop[4] = xstring_empty;
3155 xop[5] = tmp_reg_rtx;
3156 xop[6] = XEXP (rampz_rtx, 0);
562f552b 3157
3fd1e31d
GJL
3158 segment = avr_addrspace[as].segment;
3159
3160 /* Set RAMPZ as needed. */
3161
3162 if (segment)
3163 {
3164 xop[4] = GEN_INT (segment);
3165 xop[3] = avr_find_unused_d_reg (insn, lpm_addr_reg_rtx);
3166
3167 if (xop[3] != NULL_RTX)
3168 {
3169 avr_asm_len ("ldi %3,%4" CR_TAB
3170 "out %i6,%3", xop, plen, 2);
3171 }
3172 else if (segment == 1)
3173 {
3174 avr_asm_len ("clr %5" CR_TAB
3175 "inc %5" CR_TAB
3176 "out %i6,%5", xop, plen, 3);
3177 }
3178 else
3179 {
3180 avr_asm_len ("mov %5,%2" CR_TAB
3181 "ldi %2,%4" CR_TAB
3182 "out %i6,%2" CR_TAB
3183 "mov %2,%5", xop, plen, 4);
3184 }
00892272 3185
3fd1e31d
GJL
3186 xop[4] = xstring_e;
3187
3188 if (!AVR_HAVE_ELPMX)
3189 return avr_out_lpm_no_lpmx (insn, xop, plen);
3190 }
3191 else if (!AVR_HAVE_LPMX)
3192 {
3193 return avr_out_lpm_no_lpmx (insn, xop, plen);
3194 }
3195
3196 /* We have [E]LPMX: Output reading from Flash the comfortable way. */
3197
3198 switch (GET_CODE (addr))
7c209481
GJL
3199 {
3200 default:
3201 gcc_unreachable();
3202
3203 case REG:
3204
3205 gcc_assert (REG_Z == REGNO (addr));
3206
3fd1e31d
GJL
3207 switch (n_bytes)
3208 {
3209 default:
3210 gcc_unreachable();
7c209481 3211
3fd1e31d
GJL
3212 case 1:
3213 return avr_asm_len ("%4lpm %0,%a2", xop, plen, 1);
7c209481 3214
3fd1e31d
GJL
3215 case 2:
3216 if (REGNO (dest) == REG_Z)
3217 return avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3218 "%4lpm %B0,%a2" CR_TAB
3219 "mov %A0,%5", xop, plen, 3);
3220 else
3221 {
3222 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3223 "%4lpm %B0,%a2", xop, plen, 2);
00892272 3224
3fd1e31d
GJL
3225 if (!reg_unused_after (insn, addr))
3226 avr_asm_len ("sbiw %2,1", xop, plen, 1);
3227 }
00892272 3228
3fd1e31d 3229 break; /* 2 */
7c209481 3230
3fd1e31d 3231 case 3:
7c209481 3232
3fd1e31d
GJL
3233 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3234 "%4lpm %B0,%a2+" CR_TAB
3235 "%4lpm %C0,%a2", xop, plen, 3);
00892272 3236
3fd1e31d
GJL
3237 if (!reg_unused_after (insn, addr))
3238 avr_asm_len ("sbiw %2,2", xop, plen, 1);
3239
3240 break; /* 3 */
00892272 3241
3fd1e31d
GJL
3242 case 4:
3243
3244 avr_asm_len ("%4lpm %A0,%a2+" CR_TAB
3245 "%4lpm %B0,%a2+", xop, plen, 2);
00892272 3246
3fd1e31d
GJL
3247 if (REGNO (dest) == REG_Z - 2)
3248 return avr_asm_len ("%4lpm %5,%a2+" CR_TAB
3249 "%4lpm %C0,%a2" CR_TAB
3250 "mov %D0,%5", xop, plen, 3);
3251 else
7c209481 3252 {
3fd1e31d
GJL
3253 avr_asm_len ("%4lpm %C0,%a2+" CR_TAB
3254 "%4lpm %D0,%a2", xop, plen, 2);
00892272 3255
3fd1e31d
GJL
3256 if (!reg_unused_after (insn, addr))
3257 avr_asm_len ("sbiw %2,3", xop, plen, 1);
7c209481
GJL
3258 }
3259
3fd1e31d
GJL
3260 break; /* 4 */
3261 } /* n_bytes */
00892272 3262
3fd1e31d
GJL
3263 break; /* REG */
3264
3265 case POST_INC:
3266
3267 gcc_assert (REG_Z == REGNO (XEXP (addr, 0))
3268 && n_bytes <= 4);
3269
3270 avr_asm_len ("%4lpm %A0,%a2+", xop, plen, 1);
3271 if (n_bytes >= 2) avr_asm_len ("%4lpm %B0,%a2+", xop, plen, 1);
3272 if (n_bytes >= 3) avr_asm_len ("%4lpm %C0,%a2+", xop, plen, 1);
3273 if (n_bytes >= 4) avr_asm_len ("%4lpm %D0,%a2+", xop, plen, 1);
3274
3275 break; /* POST_INC */
3276
3277 } /* switch CODE (addr) */
3278
3279 if (xop[4] == xstring_e && AVR_HAVE_RAMPD)
b30e10ab 3280 {
00892272 3281 /* Reset RAMPZ to 0 so that EBI devices don't read garbage from RAM. */
3fd1e31d
GJL
3282
3283 xop[0] = zero_reg_rtx;
3284 avr_asm_len ("out %i6,%0", xop, plen, 1);
b30e10ab
GJL
3285 }
3286
7c209481
GJL
3287 return "";
3288}
3289
3290
cba300dd 3291/* Worker function for xload_8 insn. */
7bc6df2c
GJL
3292
3293const char*
98024b4e 3294avr_out_xload (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
7bc6df2c 3295{
cba300dd 3296 rtx xop[4];
7bc6df2c 3297
cba300dd 3298 xop[0] = op[0];
7bc6df2c
GJL
3299 xop[1] = op[1];
3300 xop[2] = lpm_addr_reg_rtx;
cba300dd 3301 xop[3] = AVR_HAVE_LPMX ? op[0] : lpm_reg_rtx;
7bc6df2c 3302
d5a6ef82 3303 avr_asm_len (AVR_HAVE_LPMX ? "lpm %3,%a2" : "lpm", xop, plen, -1);
7bc6df2c 3304
61108225 3305 avr_asm_len ("sbrc %1,7" CR_TAB
d5a6ef82 3306 "ld %3,%a2", xop, plen, 2);
7bc6df2c 3307
cba300dd
GJL
3308 if (REGNO (xop[0]) != REGNO (xop[3]))
3309 avr_asm_len ("mov %0,%3", xop, plen, 1);
00892272 3310
7bc6df2c
GJL
3311 return "";
3312}
3313
0c9ef7ad 3314
03b29b0a 3315const char*
98024b4e 3316output_movqi (rtx_insn *insn, rtx operands[], int *plen)
90e7678c 3317{
6bec29c9
DC
3318 rtx dest = operands[0];
3319 rtx src = operands[1];
00892272 3320
3a840863
GJL
3321 if (avr_mem_flash_p (src)
3322 || avr_mem_flash_p (dest))
7c209481 3323 {
3fd1e31d 3324 return avr_out_lpm (insn, operands, plen);
7c209481
GJL
3325 }
3326
e55e4056
GJL
3327 gcc_assert (1 == GET_MODE_SIZE (GET_MODE (dest)));
3328
3329 if (REG_P (dest))
90e7678c 3330 {
e55e4056 3331 if (REG_P (src)) /* mov r,r */
3fd1e31d
GJL
3332 {
3333 if (test_hard_reg_class (STACK_REG, dest))
3334 return avr_asm_len ("out %0,%1", operands, plen, -1);
3335 else if (test_hard_reg_class (STACK_REG, src))
3336 return avr_asm_len ("in %0,%1", operands, plen, -1);
00892272 3337
3fd1e31d
GJL
3338 return avr_asm_len ("mov %0,%1", operands, plen, -1);
3339 }
6bec29c9 3340 else if (CONSTANT_P (src))
0098895f 3341 {
3fd1e31d 3342 output_reload_in_const (operands, NULL_RTX, plen, false);
0098895f
GJL
3343 return "";
3344 }
03b29b0a 3345 else if (MEM_P (src))
3fd1e31d 3346 return out_movqi_r_mr (insn, operands, plen); /* mov r,m */
6bec29c9 3347 }
03b29b0a 3348 else if (MEM_P (dest))
6bec29c9 3349 {
5436efaa 3350 rtx xop[2];
5fecfd8d 3351
5436efaa 3352 xop[0] = dest;
e55e4056 3353 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
6bec29c9 3354
3fd1e31d 3355 return out_movqi_mr_r (insn, xop, plen);
6bec29c9 3356 }
3fd1e31d 3357
6bec29c9
DC
3358 return "";
3359}
3360
3361
5fecfd8d 3362const char *
98024b4e 3363output_movhi (rtx_insn *insn, rtx xop[], int *plen)
6bec29c9 3364{
28c5e6b5
GJL
3365 rtx dest = xop[0];
3366 rtx src = xop[1];
3367
3368 gcc_assert (GET_MODE_SIZE (GET_MODE (dest)) == 2);
00892272 3369
3a840863
GJL
3370 if (avr_mem_flash_p (src)
3371 || avr_mem_flash_p (dest))
7c209481 3372 {
28c5e6b5 3373 return avr_out_lpm (insn, xop, plen);
7c209481
GJL
3374 }
3375
e55e4056
GJL
3376 gcc_assert (2 == GET_MODE_SIZE (GET_MODE (dest)));
3377
28c5e6b5 3378 if (REG_P (dest))
6bec29c9 3379 {
28c5e6b5
GJL
3380 if (REG_P (src)) /* mov r,r */
3381 {
3382 if (test_hard_reg_class (STACK_REG, dest))
3383 {
3384 if (AVR_HAVE_8BIT_SP)
3385 return avr_asm_len ("out __SP_L__,%A1", xop, plen, -1);
2da8c1ad
GJL
3386
3387 if (AVR_XMEGA)
3388 return avr_asm_len ("out __SP_L__,%A1" CR_TAB
3389 "out __SP_H__,%B1", xop, plen, -2);
00892272 3390
28c5e6b5 3391 /* Use simple load of SP if no interrupts are used. */
00892272 3392
28c5e6b5
GJL
3393 return TARGET_NO_INTERRUPTS
3394 ? avr_asm_len ("out __SP_H__,%B1" CR_TAB
3395 "out __SP_L__,%A1", xop, plen, -2)
28c5e6b5
GJL
3396 : avr_asm_len ("in __tmp_reg__,__SREG__" CR_TAB
3397 "cli" CR_TAB
3398 "out __SP_H__,%B1" CR_TAB
3399 "out __SREG__,__tmp_reg__" CR_TAB
3400 "out __SP_L__,%A1", xop, plen, -5);
3401 }
3402 else if (test_hard_reg_class (STACK_REG, src))
3403 {
7fd6378e 3404 return !AVR_HAVE_SPH
28c5e6b5
GJL
3405 ? avr_asm_len ("in %A0,__SP_L__" CR_TAB
3406 "clr %B0", xop, plen, -2)
00892272 3407
28c5e6b5
GJL
3408 : avr_asm_len ("in %A0,__SP_L__" CR_TAB
3409 "in %B0,__SP_H__", xop, plen, -2);
3410 }
6bec29c9 3411
28c5e6b5
GJL
3412 return AVR_HAVE_MOVW
3413 ? avr_asm_len ("movw %0,%1", xop, plen, -1)
3414
3415 : avr_asm_len ("mov %A0,%A1" CR_TAB
3416 "mov %B0,%B1", xop, plen, -2);
3417 } /* REG_P (src) */
6bec29c9 3418 else if (CONSTANT_P (src))
20633efc 3419 {
28c5e6b5
GJL
3420 return output_reload_inhi (xop, NULL, plen);
3421 }
3422 else if (MEM_P (src))
3423 {
3424 return out_movhi_r_mr (insn, xop, plen); /* mov r,m */
20633efc 3425 }
6bec29c9 3426 }
28c5e6b5 3427 else if (MEM_P (dest))
6bec29c9 3428 {
5436efaa 3429 rtx xop[2];
5fecfd8d 3430
5436efaa 3431 xop[0] = dest;
e55e4056 3432 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
5fecfd8d 3433
28c5e6b5 3434 return out_movhi_mr_r (insn, xop, plen);
90e7678c 3435 }
00892272 3436
c725bd79 3437 fatal_insn ("invalid insn:", insn);
00892272 3438
6bec29c9
DC
3439 return "";
3440}
3441
0c9ef7ad 3442
c1dd9790 3443/* Same as out_movqi_r_mr, but TINY does not have ADIW or SBIW */
0c9ef7ad 3444
c1dd9790
JR
3445static const char*
3446avr_out_movqi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
3447{
3448 rtx dest = op[0];
3449 rtx src = op[1];
3450 rtx x = XEXP (src, 0);
3451
3452 avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
0c9ef7ad 3453 "ld %0,%b1" , op, plen, -3);
c1dd9790
JR
3454
3455 if (!reg_overlap_mentioned_p (dest, XEXP (x,0))
0c9ef7ad
GJL
3456 && !reg_unused_after (insn, XEXP (x,0)))
3457 avr_asm_len (TINY_SBIW (%I1, %J1, %o1), op, plen, 2);
c1dd9790
JR
3458
3459 return "";
3460}
3461
5436efaa 3462static const char*
98024b4e 3463out_movqi_r_mr (rtx_insn *insn, rtx op[], int *plen)
6bec29c9 3464{
5fecfd8d
MM
3465 rtx dest = op[0];
3466 rtx src = op[1];
3467 rtx x = XEXP (src, 0);
00892272 3468
6bec29c9
DC
3469 if (CONSTANT_ADDRESS_P (x))
3470 {
c1dd9790 3471 int n_words = AVR_TINY ? 1 : 2;
5436efaa
GJL
3472 return optimize > 0 && io_address_operand (x, QImode)
3473 ? avr_asm_len ("in %0,%i1", op, plen, -1)
c1dd9790 3474 : avr_asm_len ("lds %0,%m1", op, plen, -n_words);
6bec29c9 3475 }
c1dd9790
JR
3476
3477 if (GET_CODE (x) == PLUS
7bc6df2c
GJL
3478 && REG_P (XEXP (x, 0))
3479 && CONST_INT_P (XEXP (x, 1)))
6bec29c9 3480 {
7bc6df2c 3481 /* memory access by reg+disp */
33d5e2dc 3482
7bc6df2c 3483 int disp = INTVAL (XEXP (x, 1));
00892272 3484
c1dd9790
JR
3485 if (AVR_TINY)
3486 return avr_out_movqi_r_mr_reg_disp_tiny (insn, op, plen);
3487
7bc6df2c
GJL
3488 if (disp - GET_MODE_SIZE (GET_MODE (src)) >= 63)
3489 {
3490 if (REGNO (XEXP (x, 0)) != REG_Y)
3491 fatal_insn ("incorrect insn:",insn);
33d5e2dc 3492
7bc6df2c
GJL
3493 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
3494 return avr_asm_len ("adiw r28,%o1-63" CR_TAB
3495 "ldd %0,Y+63" CR_TAB
3496 "sbiw r28,%o1-63", op, plen, -3);
3497
3498 return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
3499 "sbci r29,hi8(-%o1)" CR_TAB
3500 "ld %0,Y" CR_TAB
3501 "subi r28,lo8(%o1)" CR_TAB
3502 "sbci r29,hi8(%o1)", op, plen, -5);
3503 }
3504 else if (REGNO (XEXP (x, 0)) == REG_X)
3505 {
3506 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
3507 it but I have this situation with extremal optimizing options. */
00892272 3508
7bc6df2c
GJL
3509 avr_asm_len ("adiw r26,%o1" CR_TAB
3510 "ld %0,X", op, plen, -2);
00892272 3511
7bc6df2c
GJL
3512 if (!reg_overlap_mentioned_p (dest, XEXP (x,0))
3513 && !reg_unused_after (insn, XEXP (x,0)))
3514 {
3515 avr_asm_len ("sbiw r26,%o1", op, plen, 1);
3516 }
3517
3518 return "";
3519 }
3520
3521 return avr_asm_len ("ldd %0,%1", op, plen, -1);
6bec29c9 3522 }
00892272 3523
7bc6df2c 3524 return avr_asm_len ("ld %0,%1", op, plen, -1);
90e7678c
DC
3525}
3526
0c9ef7ad 3527
c1dd9790 3528/* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
0c9ef7ad 3529
c1dd9790 3530static const char*
dbe9dfdd 3531avr_out_movhi_r_mr_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
c1dd9790
JR
3532{
3533 rtx dest = op[0];
3534 rtx src = op[1];
3535 rtx base = XEXP (src, 0);
3536
3537 int reg_dest = true_regnum (dest);
3538 int reg_base = true_regnum (base);
3539
3540 if (reg_dest == reg_base) /* R = (R) */
0c9ef7ad
GJL
3541 return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
3542 "ld %B0,%1" CR_TAB
3543 "mov %A0,__tmp_reg__", op, plen, -3);
c1dd9790 3544
dbe9dfdd
GJL
3545 avr_asm_len ("ld %A0,%1+" CR_TAB
3546 "ld %B0,%1", op, plen, -2);
3547
3548 if (!reg_unused_after (insn, base))
3549 avr_asm_len (TINY_SBIW (%E1, %F1, 1), op, plen, 2);
3550
3551 return "";
c1dd9790
JR
3552}
3553
0c9ef7ad 3554
c1dd9790 3555/* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
0c9ef7ad 3556
c1dd9790 3557static const char*
dbe9dfdd 3558avr_out_movhi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
c1dd9790
JR
3559{
3560 rtx dest = op[0];
3561 rtx src = op[1];
3562 rtx base = XEXP (src, 0);
3563
3564 int reg_dest = true_regnum (dest);
3565 int reg_base = true_regnum (XEXP (base, 0));
3566
3567 if (reg_base == reg_dest)
0c9ef7ad 3568 {
c1dd9790 3569 return avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
0c9ef7ad
GJL
3570 "ld __tmp_reg__,%b1+" CR_TAB
3571 "ld %B0,%b1" CR_TAB
3572 "mov %A0,__tmp_reg__", op, plen, -5);
3573 }
c1dd9790 3574 else
0c9ef7ad 3575 {
dbe9dfdd
GJL
3576 avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
3577 "ld %A0,%b1+" CR_TAB
3578 "ld %B0,%b1", op, plen, -4);
3579
3580 if (!reg_unused_after (insn, XEXP (base, 0)))
3581 avr_asm_len (TINY_SBIW (%I1, %J1, %o1+1), op, plen, 2);
3582
3583 return "";
0c9ef7ad
GJL
3584 }
3585}
3586
c1dd9790
JR
3587
3588/* Same as movhi_r_mr, but TINY does not have ADIW, SBIW and LDD */
0c9ef7ad 3589
c1dd9790
JR
3590static const char*
3591avr_out_movhi_r_mr_pre_dec_tiny (rtx_insn *insn, rtx op[], int *plen)
3592{
3593 int mem_volatile_p = 0;
3594 rtx dest = op[0];
3595 rtx src = op[1];
3596 rtx base = XEXP (src, 0);
3597
3598 /* "volatile" forces reading low byte first, even if less efficient,
3599 for correct operation with 16-bit I/O registers. */
3600 mem_volatile_p = MEM_VOLATILE_P (src);
3601
3602 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
0c9ef7ad 3603 fatal_insn ("incorrect insn:", insn);
c1dd9790
JR
3604
3605 if (!mem_volatile_p)
0c9ef7ad
GJL
3606 return avr_asm_len ("ld %B0,%1" CR_TAB
3607 "ld %A0,%1", op, plen, -2);
c1dd9790
JR
3608
3609 return avr_asm_len (TINY_SBIW (%I1, %J1, 2) CR_TAB
0c9ef7ad
GJL
3610 "ld %A0,%p1+" CR_TAB
3611 "ld %B0,%p1" CR_TAB
3612 TINY_SBIW (%I1, %J1, 1), op, plen, -6);
c1dd9790
JR
3613}
3614
0c9ef7ad 3615
5436efaa 3616static const char*
98024b4e 3617out_movhi_r_mr (rtx_insn *insn, rtx op[], int *plen)
90e7678c 3618{
5fecfd8d
MM
3619 rtx dest = op[0];
3620 rtx src = op[1];
3621 rtx base = XEXP (src, 0);
3622 int reg_dest = true_regnum (dest);
3623 int reg_base = true_regnum (base);
a6990185
MM
3624 /* "volatile" forces reading low byte first, even if less efficient,
3625 for correct operation with 16-bit I/O registers. */
3626 int mem_volatile_p = MEM_VOLATILE_P (src);
90e7678c
DC
3627
3628 if (reg_base > 0)
3629 {
c1dd9790 3630 if (AVR_TINY)
dbe9dfdd 3631 return avr_out_movhi_r_mr_reg_no_disp_tiny (insn, op, plen);
c1dd9790 3632
90e7678c 3633 if (reg_dest == reg_base) /* R = (R) */
5436efaa
GJL
3634 return avr_asm_len ("ld __tmp_reg__,%1+" CR_TAB
3635 "ld %B0,%1" CR_TAB
3636 "mov %A0,__tmp_reg__", op, plen, -3);
3637
3638 if (reg_base != REG_X)
3639 return avr_asm_len ("ld %A0,%1" CR_TAB
3640 "ldd %B0,%1+1", op, plen, -2);
00892272 3641
5436efaa
GJL
3642 avr_asm_len ("ld %A0,X+" CR_TAB
3643 "ld %B0,X", op, plen, -2);
00892272 3644
5436efaa
GJL
3645 if (!reg_unused_after (insn, base))
3646 avr_asm_len ("sbiw r26,1", op, plen, 1);
3647
3648 return "";
90e7678c 3649 }
5fecfd8d 3650 else if (GET_CODE (base) == PLUS) /* (R + i) */
90e7678c 3651 {
5fecfd8d
MM
3652 int disp = INTVAL (XEXP (base, 1));
3653 int reg_base = true_regnum (XEXP (base, 0));
00892272 3654
c1dd9790 3655 if (AVR_TINY)
dbe9dfdd 3656 return avr_out_movhi_r_mr_reg_disp_tiny (insn, op, plen);
c1dd9790 3657
5fecfd8d 3658 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
5436efaa
GJL
3659 {
3660 if (REGNO (XEXP (base, 0)) != REG_Y)
3661 fatal_insn ("incorrect insn:",insn);
00892272 3662
5436efaa
GJL
3663 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (src))
3664 ? avr_asm_len ("adiw r28,%o1-62" CR_TAB
3665 "ldd %A0,Y+62" CR_TAB
3666 "ldd %B0,Y+63" CR_TAB
3667 "sbiw r28,%o1-62", op, plen, -4)
3668
c1dd9790 3669 : avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
5436efaa
GJL
3670 "sbci r29,hi8(-%o1)" CR_TAB
3671 "ld %A0,Y" CR_TAB
3672 "ldd %B0,Y+1" CR_TAB
3673 "subi r28,lo8(%o1)" CR_TAB
3674 "sbci r29,hi8(%o1)", op, plen, -6);
3675 }
3676
3677 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
3678 it but I have this situation with extremal
3679 optimization options. */
33d5e2dc 3680
90e7678c 3681 if (reg_base == REG_X)
5436efaa
GJL
3682 return reg_base == reg_dest
3683 ? avr_asm_len ("adiw r26,%o1" CR_TAB
3684 "ld __tmp_reg__,X+" CR_TAB
3685 "ld %B0,X" CR_TAB
3686 "mov %A0,__tmp_reg__", op, plen, -4)
6bec29c9 3687
5436efaa
GJL
3688 : avr_asm_len ("adiw r26,%o1" CR_TAB
3689 "ld %A0,X+" CR_TAB
3690 "ld %B0,X" CR_TAB
3691 "sbiw r26,%o1+1", op, plen, -4);
6bec29c9 3692
5436efaa
GJL
3693 return reg_base == reg_dest
3694 ? avr_asm_len ("ldd __tmp_reg__,%A1" CR_TAB
3695 "ldd %B0,%B1" CR_TAB
3696 "mov %A0,__tmp_reg__", op, plen, -3)
3697
3698 : avr_asm_len ("ldd %A0,%A1" CR_TAB
3699 "ldd %B0,%B1", op, plen, -2);
90e7678c 3700 }
5fecfd8d 3701 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
90e7678c 3702 {
c1dd9790 3703 if (AVR_TINY)
0c9ef7ad 3704 return avr_out_movhi_r_mr_pre_dec_tiny (insn, op, plen);
c1dd9790 3705
5fecfd8d 3706 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
5436efaa 3707 fatal_insn ("incorrect insn:", insn);
6bec29c9 3708
5436efaa
GJL
3709 if (!mem_volatile_p)
3710 return avr_asm_len ("ld %B0,%1" CR_TAB
3711 "ld %A0,%1", op, plen, -2);
00892272 3712
5436efaa
GJL
3713 return REGNO (XEXP (base, 0)) == REG_X
3714 ? avr_asm_len ("sbiw r26,2" CR_TAB
3715 "ld %A0,X+" CR_TAB
3716 "ld %B0,X" CR_TAB
3717 "sbiw r26,1", op, plen, -4)
00892272 3718
5436efaa
GJL
3719 : avr_asm_len ("sbiw %r1,2" CR_TAB
3720 "ld %A0,%p1" CR_TAB
3721 "ldd %B0,%p1+1", op, plen, -3);
90e7678c 3722 }
5fecfd8d 3723 else if (GET_CODE (base) == POST_INC) /* (R++) */
90e7678c 3724 {
5fecfd8d 3725 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
5436efaa 3726 fatal_insn ("incorrect insn:", insn);
6bec29c9 3727
5436efaa
GJL
3728 return avr_asm_len ("ld %A0,%1" CR_TAB
3729 "ld %B0,%1", op, plen, -2);
90e7678c 3730 }
5fecfd8d 3731 else if (CONSTANT_ADDRESS_P (base))
6bec29c9 3732 {
c1dd9790 3733 int n_words = AVR_TINY ? 2 : 4;
5436efaa
GJL
3734 return optimize > 0 && io_address_operand (base, HImode)
3735 ? avr_asm_len ("in %A0,%i1" CR_TAB
3736 "in %B0,%i1+1", op, plen, -2)
3737
3738 : avr_asm_len ("lds %A0,%m1" CR_TAB
c1dd9790 3739 "lds %B0,%m1+1", op, plen, -n_words);
6bec29c9 3740 }
00892272 3741
c725bd79 3742 fatal_insn ("unknown move insn:",insn);
90e7678c
DC
3743 return "";
3744}
3745
c1dd9790
JR
3746static const char*
3747avr_out_movsi_r_mr_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *l)
3748{
3749 rtx dest = op[0];
3750 rtx src = op[1];
3751 rtx base = XEXP (src, 0);
3752 int reg_dest = true_regnum (dest);
3753 int reg_base = true_regnum (base);
3754
3755 if (reg_dest == reg_base)
3756 {
0c9ef7ad
GJL
3757 /* "ld r26,-X" is undefined */
3758 return *l = 9, (TINY_ADIW (%E1, %F1, 3) CR_TAB
3759 "ld %D0,%1" CR_TAB
3760 "ld %C0,-%1" CR_TAB
3761 "ld __tmp_reg__,-%1" CR_TAB
3762 TINY_SBIW (%E1, %F1, 1) CR_TAB
3763 "ld %A0,%1" CR_TAB
3764 "mov %B0,__tmp_reg__");
c1dd9790
JR
3765 }
3766 else if (reg_dest == reg_base - 2)
3767 {
0c9ef7ad
GJL
3768 return *l = 5, ("ld %A0,%1+" CR_TAB
3769 "ld %B0,%1+" CR_TAB
3770 "ld __tmp_reg__,%1+" CR_TAB
3771 "ld %D0,%1" CR_TAB
3772 "mov %C0,__tmp_reg__");
c1dd9790
JR
3773 }
3774 else if (reg_unused_after (insn, base))
3775 {
0c9ef7ad
GJL
3776 return *l = 4, ("ld %A0,%1+" CR_TAB
3777 "ld %B0,%1+" CR_TAB
3778 "ld %C0,%1+" CR_TAB
3779 "ld %D0,%1");
c1dd9790
JR
3780 }
3781 else
3782 {
0c9ef7ad
GJL
3783 return *l = 6, ("ld %A0,%1+" CR_TAB
3784 "ld %B0,%1+" CR_TAB
3785 "ld %C0,%1+" CR_TAB
3786 "ld %D0,%1" CR_TAB
3787 TINY_SBIW (%E1, %F1, 3));
c1dd9790
JR
3788 }
3789}
3790
0c9ef7ad 3791
c1dd9790
JR
3792static const char*
3793avr_out_movsi_r_mr_reg_disp_tiny (rtx_insn *insn, rtx op[], int *l)
3794{
3795 rtx dest = op[0];
3796 rtx src = op[1];
3797 rtx base = XEXP (src, 0);
3798 int reg_dest = true_regnum (dest);
3799 int reg_base = true_regnum (XEXP (base, 0));
3800
3801 if (reg_dest == reg_base)
3802 {
0c9ef7ad
GJL
3803 /* "ld r26,-X" is undefined */
3804 return *l = 9, (TINY_ADIW (%I1, %J1, %o1+3) CR_TAB
3805 "ld %D0,%b1" CR_TAB
3806 "ld %C0,-%b1" CR_TAB
3807 "ld __tmp_reg__,-%b1" CR_TAB
3808 TINY_SBIW (%I1, %J1, 1) CR_TAB
3809 "ld %A0,%b1" CR_TAB
3810 "mov %B0,__tmp_reg__");
c1dd9790
JR
3811 }
3812 else if (reg_dest == reg_base - 2)
3813 {
0c9ef7ad
GJL
3814 return *l = 7, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
3815 "ld %A0,%b1+" CR_TAB
3816 "ld %B0,%b1+" CR_TAB
3817 "ld __tmp_reg__,%b1+" CR_TAB
3818 "ld %D0,%b1" CR_TAB
3819 "mov %C0,__tmp_reg__");
c1dd9790
JR
3820 }
3821 else if (reg_unused_after (insn, XEXP (base, 0)))
3822 {
0c9ef7ad
GJL
3823 return *l = 6, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
3824 "ld %A0,%b1+" CR_TAB
3825 "ld %B0,%b1+" CR_TAB
3826 "ld %C0,%b1+" CR_TAB
3827 "ld %D0,%b1");
c1dd9790
JR
3828 }
3829 else
3830 {
0c9ef7ad
GJL
3831 return *l = 8, (TINY_ADIW (%I1, %J1, %o1) CR_TAB
3832 "ld %A0,%b1+" CR_TAB
3833 "ld %B0,%b1+" CR_TAB
3834 "ld %C0,%b1+" CR_TAB
3835 "ld %D0,%b1" CR_TAB
3836 TINY_SBIW (%I1, %J1, %o1+3));
c1dd9790
JR
3837 }
3838}
3839
5436efaa 3840static const char*
98024b4e 3841out_movsi_r_mr (rtx_insn *insn, rtx op[], int *l)
90e7678c 3842{
5fecfd8d
MM
3843 rtx dest = op[0];
3844 rtx src = op[1];
3845 rtx base = XEXP (src, 0);
3846 int reg_dest = true_regnum (dest);
3847 int reg_base = true_regnum (base);
90e7678c 3848 int tmp;
6bec29c9 3849
90e7678c 3850 if (!l)
6bec29c9 3851 l = &tmp;
00892272 3852
90e7678c
DC
3853 if (reg_base > 0)
3854 {
c1dd9790
JR
3855 if (AVR_TINY)
3856 return avr_out_movsi_r_mr_reg_no_disp_tiny (insn, op, l);
3857
90e7678c
DC
3858 if (reg_base == REG_X) /* (R26) */
3859 {
3860 if (reg_dest == REG_X)
dfaf5abf 3861 /* "ld r26,-X" is undefined */
c2453253
GJL
3862 return *l=7, ("adiw r26,3" CR_TAB
3863 "ld r29,X" CR_TAB
3864 "ld r28,-X" CR_TAB
3865 "ld __tmp_reg__,-X" CR_TAB
3866 "sbiw r26,1" CR_TAB
3867 "ld r26,X" CR_TAB
3868 "mov r27,__tmp_reg__");
90e7678c 3869 else if (reg_dest == REG_X - 2)
c2453253
GJL
3870 return *l=5, ("ld %A0,X+" CR_TAB
3871 "ld %B0,X+" CR_TAB
3872 "ld __tmp_reg__,X+" CR_TAB
3873 "ld %D0,X" CR_TAB
3874 "mov %C0,__tmp_reg__");
5fecfd8d 3875 else if (reg_unused_after (insn, base))
c2453253
GJL
3876 return *l=4, ("ld %A0,X+" CR_TAB
3877 "ld %B0,X+" CR_TAB
3878 "ld %C0,X+" CR_TAB
3879 "ld %D0,X");
90e7678c 3880 else
c2453253
GJL
3881 return *l=5, ("ld %A0,X+" CR_TAB
3882 "ld %B0,X+" CR_TAB
3883 "ld %C0,X+" CR_TAB
3884 "ld %D0,X" CR_TAB
3885 "sbiw r26,3");
90e7678c
DC
3886 }
3887 else
3888 {
3889 if (reg_dest == reg_base)
c2453253
GJL
3890 return *l=5, ("ldd %D0,%1+3" CR_TAB
3891 "ldd %C0,%1+2" CR_TAB
3892 "ldd __tmp_reg__,%1+1" CR_TAB
3893 "ld %A0,%1" CR_TAB
3894 "mov %B0,__tmp_reg__");
90e7678c 3895 else if (reg_base == reg_dest + 2)
c2453253
GJL
3896 return *l=5, ("ld %A0,%1" CR_TAB
3897 "ldd %B0,%1+1" CR_TAB
3898 "ldd __tmp_reg__,%1+2" CR_TAB
3899 "ldd %D0,%1+3" CR_TAB
3900 "mov %C0,__tmp_reg__");
90e7678c 3901 else
c2453253
GJL
3902 return *l=4, ("ld %A0,%1" CR_TAB
3903 "ldd %B0,%1+1" CR_TAB
3904 "ldd %C0,%1+2" CR_TAB
3905 "ldd %D0,%1+3");
90e7678c
DC
3906 }
3907 }
5fecfd8d 3908 else if (GET_CODE (base) == PLUS) /* (R + i) */
90e7678c 3909 {
5fecfd8d 3910 int disp = INTVAL (XEXP (base, 1));
00892272 3911
c1dd9790
JR
3912 if (AVR_TINY)
3913 return avr_out_movsi_r_mr_reg_disp_tiny (insn, op, l);
3914
5fecfd8d 3915 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
90e7678c 3916 {
5fecfd8d 3917 if (REGNO (XEXP (base, 0)) != REG_Y)
c725bd79 3918 fatal_insn ("incorrect insn:",insn);
33d5e2dc 3919
5fecfd8d 3920 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
c2453253
GJL
3921 return *l = 6, ("adiw r28,%o1-60" CR_TAB
3922 "ldd %A0,Y+60" CR_TAB
3923 "ldd %B0,Y+61" CR_TAB
3924 "ldd %C0,Y+62" CR_TAB
3925 "ldd %D0,Y+63" CR_TAB
3926 "sbiw r28,%o1-60");
3927
3928 return *l = 8, ("subi r28,lo8(-%o1)" CR_TAB
3929 "sbci r29,hi8(-%o1)" CR_TAB
3930 "ld %A0,Y" CR_TAB
3931 "ldd %B0,Y+1" CR_TAB
3932 "ldd %C0,Y+2" CR_TAB
3933 "ldd %D0,Y+3" CR_TAB
3934 "subi r28,lo8(%o1)" CR_TAB
3935 "sbci r29,hi8(%o1)");
90e7678c
DC
3936 }
3937
5fecfd8d 3938 reg_base = true_regnum (XEXP (base, 0));
dfaf5abf
MM
3939 if (reg_base == REG_X)
3940 {
3941 /* R = (X + d) */
3942 if (reg_dest == REG_X)
3943 {
3944 *l = 7;
3945 /* "ld r26,-X" is undefined */
c2453253
GJL
3946 return ("adiw r26,%o1+3" CR_TAB
3947 "ld r29,X" CR_TAB
3948 "ld r28,-X" CR_TAB
3949 "ld __tmp_reg__,-X" CR_TAB
3950 "sbiw r26,1" CR_TAB
3951 "ld r26,X" CR_TAB
3952 "mov r27,__tmp_reg__");
dfaf5abf
MM
3953 }
3954 *l = 6;
3955 if (reg_dest == REG_X - 2)
c2453253
GJL
3956 return ("adiw r26,%o1" CR_TAB
3957 "ld r24,X+" CR_TAB
3958 "ld r25,X+" CR_TAB
3959 "ld __tmp_reg__,X+" CR_TAB
3960 "ld r27,X" CR_TAB
3961 "mov r26,__tmp_reg__");
3962
3963 return ("adiw r26,%o1" CR_TAB
3964 "ld %A0,X+" CR_TAB
3965 "ld %B0,X+" CR_TAB
3966 "ld %C0,X+" CR_TAB
3967 "ld %D0,X" CR_TAB
3968 "sbiw r26,%o1+3");
dfaf5abf 3969 }
90e7678c 3970 if (reg_dest == reg_base)
c2453253
GJL
3971 return *l=5, ("ldd %D0,%D1" CR_TAB
3972 "ldd %C0,%C1" CR_TAB
3973 "ldd __tmp_reg__,%B1" CR_TAB
3974 "ldd %A0,%A1" CR_TAB
3975 "mov %B0,__tmp_reg__");
90e7678c 3976 else if (reg_dest == reg_base - 2)
c2453253
GJL
3977 return *l=5, ("ldd %A0,%A1" CR_TAB
3978 "ldd %B0,%B1" CR_TAB
3979 "ldd __tmp_reg__,%C1" CR_TAB
3980 "ldd %D0,%D1" CR_TAB
3981 "mov %C0,__tmp_reg__");
3982 return *l=4, ("ldd %A0,%A1" CR_TAB
3983 "ldd %B0,%B1" CR_TAB
3984 "ldd %C0,%C1" CR_TAB
3985 "ldd %D0,%D1");
90e7678c 3986 }
5fecfd8d 3987 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
c2453253
GJL
3988 return *l=4, ("ld %D0,%1" CR_TAB
3989 "ld %C0,%1" CR_TAB
3990 "ld %B0,%1" CR_TAB
3991 "ld %A0,%1");
5fecfd8d 3992 else if (GET_CODE (base) == POST_INC) /* (R++) */
c2453253
GJL
3993 return *l=4, ("ld %A0,%1" CR_TAB
3994 "ld %B0,%1" CR_TAB
3995 "ld %C0,%1" CR_TAB
3996 "ld %D0,%1");
5fecfd8d 3997 else if (CONSTANT_ADDRESS_P (base))
c1dd9790
JR
3998 {
3999 if (io_address_operand (base, SImode))
4000 {
4001 *l = 4;
4002 return ("in %A0,%i1" CR_TAB
4003 "in %B0,%i1+1" CR_TAB
4004 "in %C0,%i1+2" CR_TAB
4005 "in %D0,%i1+3");
4006 }
4007 else
4008 {
4009 *l = AVR_TINY ? 4 : 8;
4010 return ("lds %A0,%m1" CR_TAB
c2453253
GJL
4011 "lds %B0,%m1+1" CR_TAB
4012 "lds %C0,%m1+2" CR_TAB
4013 "lds %D0,%m1+3");
c1dd9790
JR
4014 }
4015 }
00892272 4016
c725bd79 4017 fatal_insn ("unknown move insn:",insn);
90e7678c
DC
4018 return "";
4019}
4020
c1dd9790
JR
4021static const char*
4022avr_out_movsi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *l)
4023{
4024 rtx dest = op[0];
4025 rtx src = op[1];
4026 rtx base = XEXP (dest, 0);
4027 int reg_base = true_regnum (base);
4028 int reg_src = true_regnum (src);
0c9ef7ad 4029
c1dd9790
JR
4030 if (reg_base == reg_src)
4031 {
4032 /* "ld r26,-X" is undefined */
4033 if (reg_unused_after (insn, base))
0c9ef7ad
GJL
4034 {
4035 return *l = 7, ("mov __tmp_reg__, %B1" CR_TAB
4036 "st %0,%A1" CR_TAB
4037 TINY_ADIW (%E0, %F0, 1) CR_TAB
4038 "st %0+,__tmp_reg__" CR_TAB
4039 "st %0+,%C1" CR_TAB
4040 "st %0+,%D1");
c1dd9790
JR
4041 }
4042 else
4043 {
0c9ef7ad
GJL
4044 return *l = 9, ("mov __tmp_reg__, %B1" CR_TAB
4045 "st %0,%A1" CR_TAB
4046 TINY_ADIW (%E0, %F0, 1) CR_TAB
4047 "st %0+,__tmp_reg__" CR_TAB
4048 "st %0+,%C1" CR_TAB
4049 "st %0+,%D1" CR_TAB
4050 TINY_SBIW (%E0, %F0, 3));
c1dd9790
JR
4051 }
4052 }
0c9ef7ad
GJL
4053 else if (reg_base == reg_src + 2)
4054 {
4055 if (reg_unused_after (insn, base))
4056 return *l = 7, ("mov __zero_reg__,%C1" CR_TAB
c1dd9790
JR
4057 "mov __tmp_reg__,%D1" CR_TAB
4058 "st %0+,%A1" CR_TAB
4059 "st %0+,%B1" CR_TAB
4060 "st %0+,__zero_reg__" CR_TAB
4061 "st %0,__tmp_reg__" CR_TAB
4062 "clr __zero_reg__");
0c9ef7ad
GJL
4063 else
4064 return *l = 9, ("mov __zero_reg__,%C1" CR_TAB
4065 "mov __tmp_reg__,%D1" CR_TAB
4066 "st %0+,%A1" CR_TAB
4067 "st %0+,%B1" CR_TAB
4068 "st %0+,__zero_reg__" CR_TAB
4069 "st %0,__tmp_reg__" CR_TAB
4070 "clr __zero_reg__" CR_TAB
4071 TINY_SBIW (%E0, %F0, 3));
4072 }
c1dd9790 4073
0c9ef7ad
GJL
4074 return *l = 6, ("st %0+,%A1" CR_TAB
4075 "st %0+,%B1" CR_TAB
4076 "st %0+,%C1" CR_TAB
4077 "st %0,%D1" CR_TAB
4078 TINY_SBIW (%E0, %F0, 3));
c1dd9790
JR
4079}
4080
4081static const char*
4082avr_out_movsi_mr_r_reg_disp_tiny (rtx op[], int *l)
4083{
4084 rtx dest = op[0];
4085 rtx src = op[1];
4086 rtx base = XEXP (dest, 0);
4087 int reg_base = REGNO (XEXP (base, 0));
4088 int reg_src =true_regnum (src);
4089
4090 if (reg_base == reg_src)
4091 {
0c9ef7ad
GJL
4092 *l = 11;
4093 return ("mov __tmp_reg__,%A2" CR_TAB
4094 "mov __zero_reg__,%B2" CR_TAB
c1dd9790 4095 TINY_ADIW (%I0, %J0, %o0) CR_TAB
0c9ef7ad
GJL
4096 "st %b0+,__tmp_reg__" CR_TAB
4097 "st %b0+,__zero_reg__" CR_TAB
4098 "st %b0+,%C2" CR_TAB
4099 "st %b0,%D2" CR_TAB
4100 "clr __zero_reg__" CR_TAB
4101 TINY_SBIW (%I0, %J0, %o0+3));
4102 }
c1dd9790
JR
4103 else if (reg_src == reg_base - 2)
4104 {
0c9ef7ad
GJL
4105 *l = 11;
4106 return ("mov __tmp_reg__,%C2" CR_TAB
4107 "mov __zero_reg__,%D2" CR_TAB
4108 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4109 "st %b0+,%A0" CR_TAB
4110 "st %b0+,%B0" CR_TAB
4111 "st %b0+,__tmp_reg__" CR_TAB
4112 "st %b0,__zero_reg__" CR_TAB
4113 "clr __zero_reg__" CR_TAB
4114 TINY_SBIW (%I0, %J0, %o0+3));
4115 }
c1dd9790
JR
4116 *l = 8;
4117 return (TINY_ADIW (%I0, %J0, %o0) CR_TAB
0c9ef7ad
GJL
4118 "st %b0+,%A1" CR_TAB
4119 "st %b0+,%B1" CR_TAB
4120 "st %b0+,%C1" CR_TAB
4121 "st %b0,%D1" CR_TAB
4122 TINY_SBIW (%I0, %J0, %o0+3));
c1dd9790
JR
4123}
4124
5436efaa 4125static const char*
98024b4e 4126out_movsi_mr_r (rtx_insn *insn, rtx op[], int *l)
90e7678c 4127{
5fecfd8d
MM
4128 rtx dest = op[0];
4129 rtx src = op[1];
4130 rtx base = XEXP (dest, 0);
4131 int reg_base = true_regnum (base);
4132 int reg_src = true_regnum (src);
90e7678c 4133 int tmp;
00892272 4134
90e7678c
DC
4135 if (!l)
4136 l = &tmp;
00892272 4137
5fecfd8d 4138 if (CONSTANT_ADDRESS_P (base))
c1dd9790
JR
4139 {
4140 if (io_address_operand (base, SImode))
4141 {
4142 return *l=4,("out %i0, %A1" CR_TAB
4143 "out %i0+1,%B1" CR_TAB
4144 "out %i0+2,%C1" CR_TAB
4145 "out %i0+3,%D1");
4146 }
4147 else
4148 {
4149 *l = AVR_TINY ? 4 : 8;
4150 return ("sts %m0,%A1" CR_TAB
4151 "sts %m0+1,%B1" CR_TAB
4152 "sts %m0+2,%C1" CR_TAB
4153 "sts %m0+3,%D1");
4154 }
4155 }
4156
90e7678c
DC
4157 if (reg_base > 0) /* (r) */
4158 {
c1dd9790
JR
4159 if (AVR_TINY)
4160 return avr_out_movsi_mr_r_reg_no_disp_tiny (insn, op, l);
4161
90e7678c
DC
4162 if (reg_base == REG_X) /* (R26) */
4163 {
5fecfd8d 4164 if (reg_src == REG_X)
90e7678c 4165 {
dfaf5abf 4166 /* "st X+,r26" is undefined */
5fecfd8d 4167 if (reg_unused_after (insn, base))
c2453253
GJL
4168 return *l=6, ("mov __tmp_reg__,r27" CR_TAB
4169 "st X,r26" CR_TAB
4170 "adiw r26,1" CR_TAB
4171 "st X+,__tmp_reg__" CR_TAB
4172 "st X+,r28" CR_TAB
4173 "st X,r29");
90e7678c 4174 else
c2453253
GJL
4175 return *l=7, ("mov __tmp_reg__,r27" CR_TAB
4176 "st X,r26" CR_TAB
4177 "adiw r26,1" CR_TAB
4178 "st X+,__tmp_reg__" CR_TAB
4179 "st X+,r28" CR_TAB
4180 "st X,r29" CR_TAB
4181 "sbiw r26,3");
90e7678c 4182 }
5fecfd8d 4183 else if (reg_base == reg_src + 2)
90e7678c 4184 {
5fecfd8d 4185 if (reg_unused_after (insn, base))
c2453253
GJL
4186 return *l=7, ("mov __zero_reg__,%C1" CR_TAB
4187 "mov __tmp_reg__,%D1" CR_TAB
4188 "st %0+,%A1" CR_TAB
4189 "st %0+,%B1" CR_TAB
4190 "st %0+,__zero_reg__" CR_TAB
4191 "st %0,__tmp_reg__" CR_TAB
4192 "clr __zero_reg__");
90e7678c 4193 else
c2453253
GJL
4194 return *l=8, ("mov __zero_reg__,%C1" CR_TAB
4195 "mov __tmp_reg__,%D1" CR_TAB
4196 "st %0+,%A1" CR_TAB
4197 "st %0+,%B1" CR_TAB
4198 "st %0+,__zero_reg__" CR_TAB
4199 "st %0,__tmp_reg__" CR_TAB
4200 "clr __zero_reg__" CR_TAB
4201 "sbiw r26,3");
90e7678c 4202 }
c2453253
GJL
4203 return *l=5, ("st %0+,%A1" CR_TAB
4204 "st %0+,%B1" CR_TAB
4205 "st %0+,%C1" CR_TAB
4206 "st %0,%D1" CR_TAB
4207 "sbiw r26,3");
90e7678c
DC
4208 }
4209 else
c2453253
GJL
4210 return *l=4, ("st %0,%A1" CR_TAB
4211 "std %0+1,%B1" CR_TAB
4212 "std %0+2,%C1" CR_TAB
4213 "std %0+3,%D1");
90e7678c 4214 }
5fecfd8d 4215 else if (GET_CODE (base) == PLUS) /* (R + i) */
90e7678c 4216 {
5fecfd8d 4217 int disp = INTVAL (XEXP (base, 1));
c1dd9790
JR
4218
4219 if (AVR_TINY)
4220 return avr_out_movsi_mr_r_reg_disp_tiny (op, l);
4221
dfaf5abf 4222 reg_base = REGNO (XEXP (base, 0));
5fecfd8d 4223 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
90e7678c 4224 {
dfaf5abf 4225 if (reg_base != REG_Y)
c725bd79 4226 fatal_insn ("incorrect insn:",insn);
33d5e2dc 4227
5fecfd8d 4228 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
c2453253
GJL
4229 return *l = 6, ("adiw r28,%o0-60" CR_TAB
4230 "std Y+60,%A1" CR_TAB
4231 "std Y+61,%B1" CR_TAB
4232 "std Y+62,%C1" CR_TAB
4233 "std Y+63,%D1" CR_TAB
4234 "sbiw r28,%o0-60");
4235
4236 return *l = 8, ("subi r28,lo8(-%o0)" CR_TAB
4237 "sbci r29,hi8(-%o0)" CR_TAB
4238 "st Y,%A1" CR_TAB
4239 "std Y+1,%B1" CR_TAB
4240 "std Y+2,%C1" CR_TAB
4241 "std Y+3,%D1" CR_TAB
4242 "subi r28,lo8(%o0)" CR_TAB
4243 "sbci r29,hi8(%o0)");
90e7678c 4244 }
dfaf5abf
MM
4245 if (reg_base == REG_X)
4246 {
4247 /* (X + d) = R */
4248 if (reg_src == REG_X)
4249 {
4250 *l = 9;
c2453253
GJL
4251 return ("mov __tmp_reg__,r26" CR_TAB
4252 "mov __zero_reg__,r27" CR_TAB
4253 "adiw r26,%o0" CR_TAB
4254 "st X+,__tmp_reg__" CR_TAB
4255 "st X+,__zero_reg__" CR_TAB
4256 "st X+,r28" CR_TAB
4257 "st X,r29" CR_TAB
4258 "clr __zero_reg__" CR_TAB
4259 "sbiw r26,%o0+3");
dfaf5abf
MM
4260 }
4261 else if (reg_src == REG_X - 2)
4262 {
4263 *l = 9;
c2453253
GJL
4264 return ("mov __tmp_reg__,r26" CR_TAB
4265 "mov __zero_reg__,r27" CR_TAB
4266 "adiw r26,%o0" CR_TAB
4267 "st X+,r24" CR_TAB
4268 "st X+,r25" CR_TAB
4269 "st X+,__tmp_reg__" CR_TAB
4270 "st X,__zero_reg__" CR_TAB
4271 "clr __zero_reg__" CR_TAB
4272 "sbiw r26,%o0+3");
dfaf5abf
MM
4273 }
4274 *l = 6;
c2453253
GJL
4275 return ("adiw r26,%o0" CR_TAB
4276 "st X+,%A1" CR_TAB
4277 "st X+,%B1" CR_TAB
4278 "st X+,%C1" CR_TAB
4279 "st X,%D1" CR_TAB
4280 "sbiw r26,%o0+3");
dfaf5abf 4281 }
c2453253
GJL
4282 return *l=4, ("std %A0,%A1" CR_TAB
4283 "std %B0,%B1" CR_TAB
4284 "std %C0,%C1" CR_TAB
4285 "std %D0,%D1");
90e7678c 4286 }
5fecfd8d 4287 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
c2453253
GJL
4288 return *l=4, ("st %0,%D1" CR_TAB
4289 "st %0,%C1" CR_TAB
4290 "st %0,%B1" CR_TAB
4291 "st %0,%A1");
5fecfd8d 4292 else if (GET_CODE (base) == POST_INC) /* (R++) */
c2453253
GJL
4293 return *l=4, ("st %0,%A1" CR_TAB
4294 "st %0,%B1" CR_TAB
4295 "st %0,%C1" CR_TAB
4296 "st %0,%D1");
c725bd79 4297 fatal_insn ("unknown move insn:",insn);
90e7678c
DC
4298 return "";
4299}
4300
5fecfd8d 4301const char *
98024b4e 4302output_movsisf (rtx_insn *insn, rtx operands[], int *l)
90e7678c 4303{
6bec29c9
DC
4304 int dummy;
4305 rtx dest = operands[0];
4306 rtx src = operands[1];
4307 int *real_l = l;
00892272 4308
3a840863
GJL
4309 if (avr_mem_flash_p (src)
4310 || avr_mem_flash_p (dest))
7c209481
GJL
4311 {
4312 return avr_out_lpm (insn, operands, real_l);
4313 }
4314
6bec29c9
DC
4315 if (!l)
4316 l = &dummy;
00892272 4317
e55e4056
GJL
4318 gcc_assert (4 == GET_MODE_SIZE (GET_MODE (dest)));
4319 if (REG_P (dest))
90e7678c 4320 {
e55e4056 4321 if (REG_P (src)) /* mov r,r */
c4984bad 4322 {
6bec29c9
DC
4323 if (true_regnum (dest) > true_regnum (src))
4324 {
4301ec4f 4325 if (AVR_HAVE_MOVW)
6bec29c9
DC
4326 {
4327 *l = 2;
c2453253
GJL
4328 return ("movw %C0,%C1" CR_TAB
4329 "movw %A0,%A1");
6bec29c9
DC
4330 }
4331 *l = 4;
c2453253
GJL
4332 return ("mov %D0,%D1" CR_TAB
4333 "mov %C0,%C1" CR_TAB
4334 "mov %B0,%B1" CR_TAB
4335 "mov %A0,%A1");
6bec29c9 4336 }
c4984bad 4337 else
6bec29c9 4338 {
4301ec4f 4339 if (AVR_HAVE_MOVW)
6bec29c9
DC
4340 {
4341 *l = 2;
c2453253
GJL
4342 return ("movw %A0,%A1" CR_TAB
4343 "movw %C0,%C1");
6bec29c9
DC
4344 }
4345 *l = 4;
c2453253
GJL
4346 return ("mov %A0,%A1" CR_TAB
4347 "mov %B0,%B1" CR_TAB
4348 "mov %C0,%C1" CR_TAB
4349 "mov %D0,%D1");
6bec29c9 4350 }
c4984bad 4351 }
6bec29c9 4352 else if (CONSTANT_P (src))
c4984bad 4353 {
5436efaa
GJL
4354 return output_reload_insisf (operands, NULL_RTX, real_l);
4355 }
e55e4056 4356 else if (MEM_P (src))
6bec29c9
DC
4357 return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
4358 }
e55e4056 4359 else if (MEM_P (dest))
6bec29c9 4360 {
0a2aaacc 4361 const char *templ;
5fecfd8d 4362
1e6a67d1 4363 if (src == CONST0_RTX (GET_MODE (dest)))
6bec29c9 4364 operands[1] = zero_reg_rtx;
5fecfd8d 4365
0a2aaacc 4366 templ = out_movsi_mr_r (insn, operands, real_l);
6bec29c9
DC
4367
4368 if (!real_l)
0a2aaacc 4369 output_asm_insn (templ, operands);
5fecfd8d
MM
4370
4371 operands[1] = src;
6bec29c9 4372 return "";
90e7678c 4373 }
c725bd79 4374 fatal_insn ("invalid insn:", insn);
90e7678c
DC
4375 return "";
4376}
4377
e4fe948a
GJL
4378
4379/* Handle loads of 24-bit types from memory to register. */
4380
c1dd9790
JR
4381static const char*
4382avr_out_load_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
4383{
4384 rtx dest = op[0];
4385 rtx src = op[1];
4386 rtx base = XEXP (src, 0);
4387 int reg_dest = true_regnum (dest);
4388 int reg_base = true_regnum (base);
4389
4390 if (reg_base == reg_dest)
4391 {
4392 return avr_asm_len (TINY_ADIW (%E1, %F1, 2) CR_TAB
4393 "ld %C0,%1" CR_TAB
0c9ef7ad 4394 "ld __tmp_reg__,-%1" CR_TAB
c1dd9790 4395 TINY_SBIW (%E1, %F1, 1) CR_TAB
0c9ef7ad 4396 "ld %A0,%1" CR_TAB
c1dd9790
JR
4397 "mov %B0,__tmp_reg__", op, plen, -8);
4398 }
4399 else
4400 {
9e46366d
PS
4401 avr_asm_len ("ld %A0,%1+" CR_TAB
4402 "ld %B0,%1+" CR_TAB
4403 "ld %C0,%1", op, plen, -3);
c1dd9790 4404
dbe9dfdd
GJL
4405 if (reg_dest != reg_base - 2
4406 && !reg_unused_after (insn, base))
c1dd9790
JR
4407 {
4408 avr_asm_len (TINY_SBIW (%E1, %F1, 2), op, plen, 2);
4409 }
4410 return "";
4411 }
4412}
4413
4414static const char*
4415avr_out_load_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
4416{
4417 rtx dest = op[0];
4418 rtx src = op[1];
4419 rtx base = XEXP (src, 0);
4420 int reg_dest = true_regnum (dest);
4421 int reg_base = true_regnum (base);
4422
4423 reg_base = true_regnum (XEXP (base, 0));
4424 if (reg_base == reg_dest)
4425 {
4426 return avr_asm_len (TINY_ADIW (%I1, %J1, %o1+2) CR_TAB
4427 "ld %C0,%b1" CR_TAB
4428 "ld __tmp_reg__,-%b1" CR_TAB
4429 TINY_SBIW (%I1, %J1, 1) CR_TAB
4430 "ld %A0,%b1" CR_TAB
4431 "mov %B0,__tmp_reg__", op, plen, -8);
4432 }
4433 else
4434 {
4435 avr_asm_len (TINY_ADIW (%I1, %J1, %o1) CR_TAB
dbe9dfdd
GJL
4436 "ld %A0,%b1+" CR_TAB
4437 "ld %B0,%b1+" CR_TAB
4438 "ld %C0,%b1", op, plen, -5);
c1dd9790 4439
dbe9dfdd 4440 if (reg_dest != reg_base - 2
c1dd9790 4441 && !reg_unused_after (insn, XEXP (base, 0)))
dbe9dfdd 4442 avr_asm_len (TINY_SBIW (%I1, %J1, %o1+2), op, plen, 2);
0c9ef7ad 4443
c1dd9790
JR
4444 return "";
4445 }
4446}
4447
e4fe948a 4448static const char*
98024b4e 4449avr_out_load_psi (rtx_insn *insn, rtx *op, int *plen)
e4fe948a
GJL
4450{
4451 rtx dest = op[0];
4452 rtx src = op[1];
4453 rtx base = XEXP (src, 0);
4454 int reg_dest = true_regnum (dest);
4455 int reg_base = true_regnum (base);
00892272 4456
e4fe948a
GJL
4457 if (reg_base > 0)
4458 {
c1dd9790
JR
4459 if (AVR_TINY)
4460 return avr_out_load_psi_reg_no_disp_tiny (insn, op, plen);
4461
e4fe948a
GJL
4462 if (reg_base == REG_X) /* (R26) */
4463 {
4464 if (reg_dest == REG_X)
4465 /* "ld r26,-X" is undefined */
4466 return avr_asm_len ("adiw r26,2" CR_TAB
4467 "ld r28,X" CR_TAB
4468 "ld __tmp_reg__,-X" CR_TAB
4469 "sbiw r26,1" CR_TAB
4470 "ld r26,X" CR_TAB
4471 "mov r27,__tmp_reg__", op, plen, -6);
4472 else
4473 {
4474 avr_asm_len ("ld %A0,X+" CR_TAB
4475 "ld %B0,X+" CR_TAB
4476 "ld %C0,X", op, plen, -3);
4477
4478 if (reg_dest != REG_X - 2
4479 && !reg_unused_after (insn, base))
4480 {
4481 avr_asm_len ("sbiw r26,2", op, plen, 1);
4482 }
4483
4484 return "";
4485 }
4486 }
4487 else /* reg_base != REG_X */
4488 {
4489 if (reg_dest == reg_base)
4490 return avr_asm_len ("ldd %C0,%1+2" CR_TAB
4491 "ldd __tmp_reg__,%1+1" CR_TAB
4492 "ld %A0,%1" CR_TAB
4493 "mov %B0,__tmp_reg__", op, plen, -4);
4494 else
4495 return avr_asm_len ("ld %A0,%1" CR_TAB
4496 "ldd %B0,%1+1" CR_TAB
4497 "ldd %C0,%1+2", op, plen, -3);
4498 }
4499 }
4500 else if (GET_CODE (base) == PLUS) /* (R + i) */
4501 {
4502 int disp = INTVAL (XEXP (base, 1));
00892272 4503
c1dd9790
JR
4504 if (AVR_TINY)
4505 return avr_out_load_psi_reg_disp_tiny (insn, op, plen);
4506
e4fe948a
GJL
4507 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
4508 {
4509 if (REGNO (XEXP (base, 0)) != REG_Y)
4510 fatal_insn ("incorrect insn:",insn);
4511
4512 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
4513 return avr_asm_len ("adiw r28,%o1-61" CR_TAB
4514 "ldd %A0,Y+61" CR_TAB
4515 "ldd %B0,Y+62" CR_TAB
4516 "ldd %C0,Y+63" CR_TAB
4517 "sbiw r28,%o1-61", op, plen, -5);
4518
4519 return avr_asm_len ("subi r28,lo8(-%o1)" CR_TAB
4520 "sbci r29,hi8(-%o1)" CR_TAB
4521 "ld %A0,Y" CR_TAB
4522 "ldd %B0,Y+1" CR_TAB
4523 "ldd %C0,Y+2" CR_TAB
4524 "subi r28,lo8(%o1)" CR_TAB
4525 "sbci r29,hi8(%o1)", op, plen, -7);
4526 }
4527
4528 reg_base = true_regnum (XEXP (base, 0));
4529 if (reg_base == REG_X)
4530 {
4531 /* R = (X + d) */
4532 if (reg_dest == REG_X)
4533 {
4534 /* "ld r26,-X" is undefined */
4535 return avr_asm_len ("adiw r26,%o1+2" CR_TAB
4536 "ld r28,X" CR_TAB
4537 "ld __tmp_reg__,-X" CR_TAB
4538 "sbiw r26,1" CR_TAB
4539 "ld r26,X" CR_TAB
4540 "mov r27,__tmp_reg__", op, plen, -6);
4541 }
00892272 4542
20955f5a
GJL
4543 avr_asm_len ("adiw r26,%o1" CR_TAB
4544 "ld %A0,X+" CR_TAB
4545 "ld %B0,X+" CR_TAB
4546 "ld %C0,X", op, plen, -4);
e4fe948a 4547
20955f5a
GJL
4548 if (reg_dest != REG_W
4549 && !reg_unused_after (insn, XEXP (base, 0)))
4550 avr_asm_len ("sbiw r26,%o1+2", op, plen, 1);
e4fe948a 4551
20955f5a 4552 return "";
e4fe948a 4553 }
00892272 4554
e4fe948a
GJL
4555 if (reg_dest == reg_base)
4556 return avr_asm_len ("ldd %C0,%C1" CR_TAB
4557 "ldd __tmp_reg__,%B1" CR_TAB
4558 "ldd %A0,%A1" CR_TAB
4559 "mov %B0,__tmp_reg__", op, plen, -4);
4560
4561 return avr_asm_len ("ldd %A0,%A1" CR_TAB
4562 "ldd %B0,%B1" CR_TAB
4563 "ldd %C0,%C1", op, plen, -3);
4564 }
4565 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4566 return avr_asm_len ("ld %C0,%1" CR_TAB
4567 "ld %B0,%1" CR_TAB
4568 "ld %A0,%1", op, plen, -3);
4569 else if (GET_CODE (base) == POST_INC) /* (R++) */
4570 return avr_asm_len ("ld %A0,%1" CR_TAB
4571 "ld %B0,%1" CR_TAB
4572 "ld %C0,%1", op, plen, -3);
4573
4574 else if (CONSTANT_ADDRESS_P (base))
c1dd9790
JR
4575 {
4576 int n_words = AVR_TINY ? 3 : 6;
4577 return avr_asm_len ("lds %A0,%m1" CR_TAB
4578 "lds %B0,%m1+1" CR_TAB
4579 "lds %C0,%m1+2", op, plen , -n_words);
4580 }
00892272 4581
e4fe948a
GJL
4582 fatal_insn ("unknown move insn:",insn);
4583 return "";
4584}
4585
c1dd9790
JR
4586
4587static const char*
4588avr_out_store_psi_reg_no_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
4589{
4590 rtx dest = op[0];
4591 rtx src = op[1];
4592 rtx base = XEXP (dest, 0);
4593 int reg_base = true_regnum (base);
4594 int reg_src = true_regnum (src);
4595
4596 if (reg_base == reg_src)
4597 {
4598 avr_asm_len ("st %0,%A1" CR_TAB
4599 "mov __tmp_reg__,%B1" CR_TAB
4600 TINY_ADIW (%E0, %F0, 1) CR_TAB /* st X+, r27 is undefined */
4601 "st %0+,__tmp_reg__" CR_TAB
4602 "st %0,%C1", op, plen, -6);
4603
4604 }
4605 else if (reg_src == reg_base - 2)
4606 {
4607 avr_asm_len ("st %0,%A1" CR_TAB
4608 "mov __tmp_reg__,%C1" CR_TAB
4609 TINY_ADIW (%E0, %F0, 1) CR_TAB
4610 "st %0+,%B1" CR_TAB
4611 "st %0,__tmp_reg__", op, plen, 6);
4612 }
4613 else
4614 {
4615 avr_asm_len ("st %0+,%A1" CR_TAB
4616 "st %0+,%B1" CR_TAB
4617 "st %0,%C1", op, plen, -3);
4618 }
4619
4620 if (!reg_unused_after (insn, base))
4621 avr_asm_len (TINY_SBIW (%E0, %F0, 2), op, plen, 2);
4622
4623 return "";
4624}
4625
4626static const char*
dbe9dfdd 4627avr_out_store_psi_reg_disp_tiny (rtx_insn *insn, rtx *op, int *plen)
c1dd9790
JR
4628{
4629 rtx dest = op[0];
4630 rtx src = op[1];
4631 rtx base = XEXP (dest, 0);
4632 int reg_base = REGNO (XEXP (base, 0));
4633 int reg_src = true_regnum (src);
4634
4635 if (reg_src == reg_base)
dbe9dfdd
GJL
4636 avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
4637 "mov __zero_reg__,%B1" CR_TAB
4638 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4639 "st %b0+,__tmp_reg__" CR_TAB
4640 "st %b0+,__zero_reg__" CR_TAB
4641 "st %b0,%C1" CR_TAB
4642 "clr __zero_reg__", op, plen, -8);
c1dd9790 4643 else if (reg_src == reg_base - 2)
dbe9dfdd
GJL
4644 avr_asm_len ("mov __tmp_reg__,%C1" CR_TAB
4645 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4646 "st %b0+,%A1" CR_TAB
4647 "st %b0+,%B1" CR_TAB
4648 "st %b0,__tmp_reg__", op, plen, -6);
4649 else
4650 avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
4651 "st %b0+,%A1" CR_TAB
4652 "st %b0+,%B1" CR_TAB
4653 "st %b0,%C1", op, plen, -5);
4654
4655 if (!reg_unused_after (insn, XEXP (base, 0)))
4656 avr_asm_len (TINY_SBIW (%I0, %J0, %o0+2), op, plen, 2);
c1dd9790 4657
dbe9dfdd 4658 return "";
c1dd9790
JR
4659}
4660
e4fe948a
GJL
4661/* Handle store of 24-bit type from register or zero to memory. */
4662
4663static const char*
98024b4e 4664avr_out_store_psi (rtx_insn *insn, rtx *op, int *plen)
e4fe948a
GJL
4665{
4666 rtx dest = op[0];
4667 rtx src = op[1];
4668 rtx base = XEXP (dest, 0);
4669 int reg_base = true_regnum (base);
00892272 4670
e4fe948a 4671 if (CONSTANT_ADDRESS_P (base))
c1dd9790
JR
4672 {
4673 int n_words = AVR_TINY ? 3 : 6;
4674 return avr_asm_len ("sts %m0,%A1" CR_TAB
4675 "sts %m0+1,%B1" CR_TAB
4676 "sts %m0+2,%C1", op, plen, -n_words);
4677 }
00892272 4678
e4fe948a
GJL
4679 if (reg_base > 0) /* (r) */
4680 {
c1dd9790
JR
4681 if (AVR_TINY)
4682 return avr_out_store_psi_reg_no_disp_tiny (insn, op, plen);
4683
e4fe948a
GJL
4684 if (reg_base == REG_X) /* (R26) */
4685 {
4686 gcc_assert (!reg_overlap_mentioned_p (base, src));
00892272 4687
e4fe948a
GJL
4688 avr_asm_len ("st %0+,%A1" CR_TAB
4689 "st %0+,%B1" CR_TAB
4690 "st %0,%C1", op, plen, -3);
4691
4692 if (!reg_unused_after (insn, base))
4693 avr_asm_len ("sbiw r26,2", op, plen, 1);
4694
4695 return "";
4696 }
4697 else
4698 return avr_asm_len ("st %0,%A1" CR_TAB
4699 "std %0+1,%B1" CR_TAB
4700 "std %0+2,%C1", op, plen, -3);
4701 }
4702 else if (GET_CODE (base) == PLUS) /* (R + i) */
4703 {
4704 int disp = INTVAL (XEXP (base, 1));
c1dd9790
JR
4705
4706 if (AVR_TINY)
dbe9dfdd 4707 return avr_out_store_psi_reg_disp_tiny (insn, op, plen);
c1dd9790 4708
e4fe948a
GJL
4709 reg_base = REGNO (XEXP (base, 0));
4710
4711 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
4712 {
4713 if (reg_base != REG_Y)
4714 fatal_insn ("incorrect insn:",insn);
4715
4716 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
4717 return avr_asm_len ("adiw r28,%o0-61" CR_TAB
4718 "std Y+61,%A1" CR_TAB
4719 "std Y+62,%B1" CR_TAB
4720 "std Y+63,%C1" CR_TAB
079f1420 4721 "sbiw r28,%o0-61", op, plen, -5);
e4fe948a
GJL
4722
4723 return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
4724 "sbci r29,hi8(-%o0)" CR_TAB
4725 "st Y,%A1" CR_TAB
4726 "std Y+1,%B1" CR_TAB
4727 "std Y+2,%C1" CR_TAB
4728 "subi r28,lo8(%o0)" CR_TAB
4729 "sbci r29,hi8(%o0)", op, plen, -7);
4730 }
4731 if (reg_base == REG_X)
4732 {
4733 /* (X + d) = R */
4734 gcc_assert (!reg_overlap_mentioned_p (XEXP (base, 0), src));
00892272 4735
e4fe948a
GJL
4736 avr_asm_len ("adiw r26,%o0" CR_TAB
4737 "st X+,%A1" CR_TAB
4738 "st X+,%B1" CR_TAB
4739 "st X,%C1", op, plen, -4);
4740
4741 if (!reg_unused_after (insn, XEXP (base, 0)))
4742 avr_asm_len ("sbiw r26,%o0+2", op, plen, 1);
4743
4744 return "";
4745 }
00892272 4746
e4fe948a
GJL
4747 return avr_asm_len ("std %A0,%A1" CR_TAB
4748 "std %B0,%B1" CR_TAB
4749 "std %C0,%C1", op, plen, -3);
4750 }
4751 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
4752 return avr_asm_len ("st %0,%C1" CR_TAB
4753 "st %0,%B1" CR_TAB
4754 "st %0,%A1", op, plen, -3);
4755 else if (GET_CODE (base) == POST_INC) /* (R++) */
4756 return avr_asm_len ("st %0,%A1" CR_TAB
4757 "st %0,%B1" CR_TAB
4758 "st %0,%C1", op, plen, -3);
4759
4760 fatal_insn ("unknown move insn:",insn);
4761 return "";
4762}
4763
4764
4765/* Move around 24-bit stuff. */
4766
4767const char *
98024b4e 4768avr_out_movpsi (rtx_insn *insn, rtx *op, int *plen)
e4fe948a
GJL
4769{
4770 rtx dest = op[0];
4771 rtx src = op[1];
00892272 4772
3a840863
GJL
4773 if (avr_mem_flash_p (src)
4774 || avr_mem_flash_p (dest))
7c209481
GJL
4775 {
4776 return avr_out_lpm (insn, op, plen);
4777 }
00892272 4778
e4fe948a
GJL
4779 if (register_operand (dest, VOIDmode))
4780 {
4781 if (register_operand (src, VOIDmode)) /* mov r,r */
4782 {
4783 if (true_regnum (dest) > true_regnum (src))
4784 {
4785 avr_asm_len ("mov %C0,%C1", op, plen, -1);
4786
4787 if (AVR_HAVE_MOVW)
4788 return avr_asm_len ("movw %A0,%A1", op, plen, 1);
4789 else
4790 return avr_asm_len ("mov %B0,%B1" CR_TAB
4791 "mov %A0,%A1", op, plen, 2);
4792 }
4793 else
4794 {
4795 if (AVR_HAVE_MOVW)
4796 avr_asm_len ("movw %A0,%A1", op, plen, -1);
4797 else
4798 avr_asm_len ("mov %A0,%A1" CR_TAB
4799 "mov %B0,%B1", op, plen, -2);
00892272 4800
e4fe948a
GJL
4801 return avr_asm_len ("mov %C0,%C1", op, plen, 1);
4802 }
4803 }
e4fe948a
GJL
4804 else if (CONSTANT_P (src))
4805 {
5436efaa 4806 return avr_out_reload_inpsi (op, NULL_RTX, plen);
e4fe948a
GJL
4807 }
4808 else if (MEM_P (src))
4809 return avr_out_load_psi (insn, op, plen); /* mov r,m */
4810 }
4811 else if (MEM_P (dest))
4812 {
5436efaa
GJL
4813 rtx xop[2];
4814
4815 xop[0] = dest;
4816 xop[1] = src == CONST0_RTX (GET_MODE (dest)) ? zero_reg_rtx : src;
00892272 4817
5436efaa 4818 return avr_out_store_psi (insn, xop, plen);
e4fe948a 4819 }
00892272 4820
e4fe948a
GJL
4821 fatal_insn ("invalid insn:", insn);
4822 return "";
4823}
4824
c1dd9790
JR
4825static const char*
4826avr_out_movqi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
4827{
4828 rtx dest = op[0];
4829 rtx src = op[1];
4830 rtx x = XEXP (dest, 0);
4831
4832 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
4833 {
4834 avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
4835 TINY_ADIW (%I0, %J0, %o0) CR_TAB
4836 "st %b0,__tmp_reg__", op, plen, -4);
4837 }
4838 else
4839 {
4840 avr_asm_len (TINY_ADIW (%I0, %J0, %o0) CR_TAB
dbe9dfdd 4841 "st %b0,%1", op, plen, -3);
c1dd9790
JR
4842 }
4843
4844 if (!reg_unused_after (insn, XEXP (x,0)))
4845 avr_asm_len (TINY_SBIW (%I0, %J0, %o0), op, plen, 2);
4846
4847 return "";
4848}
e4fe948a 4849
5436efaa 4850static const char*
98024b4e 4851out_movqi_mr_r (rtx_insn *insn, rtx op[], int *plen)
90e7678c 4852{
5fecfd8d
MM
4853 rtx dest = op[0];
4854 rtx src = op[1];
4855 rtx x = XEXP (dest, 0);
00892272 4856
6bec29c9 4857 if (CONSTANT_ADDRESS_P (x))
90e7678c 4858 {
c1dd9790 4859 int n_words = AVR_TINY ? 1 : 2;
5436efaa
GJL
4860 return optimize > 0 && io_address_operand (x, QImode)
4861 ? avr_asm_len ("out %i0,%1", op, plen, -1)
c1dd9790 4862 : avr_asm_len ("sts %m0,%1", op, plen, -n_words);
6bec29c9 4863 }
7bc6df2c
GJL
4864 else if (GET_CODE (x) == PLUS
4865 && REG_P (XEXP (x, 0))
4866 && CONST_INT_P (XEXP (x, 1)))
6bec29c9 4867 {
7bc6df2c 4868 /* memory access by reg+disp */
33d5e2dc 4869
7bc6df2c 4870 int disp = INTVAL (XEXP (x, 1));
33d5e2dc 4871
c1dd9790
JR
4872 if (AVR_TINY)
4873 return avr_out_movqi_mr_r_reg_disp_tiny (insn, op, plen);
4874
7bc6df2c
GJL
4875 if (disp - GET_MODE_SIZE (GET_MODE (dest)) >= 63)
4876 {
4877 if (REGNO (XEXP (x, 0)) != REG_Y)
4878 fatal_insn ("incorrect insn:",insn);
4879
4880 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
4881 return avr_asm_len ("adiw r28,%o0-63" CR_TAB
4882 "std Y+63,%1" CR_TAB
4883 "sbiw r28,%o0-63", op, plen, -3);
4884
4885 return avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
4886 "sbci r29,hi8(-%o0)" CR_TAB
4887 "st Y,%1" CR_TAB
4888 "subi r28,lo8(%o0)" CR_TAB
4889 "sbci r29,hi8(%o0)", op, plen, -5);
4890 }
6bec29c9 4891 else if (REGNO (XEXP (x,0)) == REG_X)
7bc6df2c
GJL
4892 {
4893 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
4894 {
4895 avr_asm_len ("mov __tmp_reg__,%1" CR_TAB
4896 "adiw r26,%o0" CR_TAB
4897 "st X,__tmp_reg__", op, plen, -3);
4898 }
4899 else
4900 {
4901 avr_asm_len ("adiw r26,%o0" CR_TAB
4902 "st X,%1", op, plen, -2);
4903 }
00892272 4904
7bc6df2c
GJL
4905 if (!reg_unused_after (insn, XEXP (x,0)))
4906 avr_asm_len ("sbiw r26,%o0", op, plen, 1);
33d5e2dc 4907
7bc6df2c
GJL
4908 return "";
4909 }
00892272 4910
733ccf09 4911 return avr_asm_len ("std %0,%1", op, plen, -1);
90e7678c 4912 }
00892272 4913
4f053457 4914 return avr_asm_len ("st %0,%1", op, plen, -1);
90e7678c
DC
4915}
4916
2da8c1ad
GJL
4917
4918/* Helper for the next function for XMEGA. It does the same
4919 but with low byte first. */
4920
5436efaa 4921static const char*
98024b4e 4922avr_out_movhi_mr_r_xmega (rtx_insn *insn, rtx op[], int *plen)
90e7678c 4923{
5fecfd8d
MM
4924 rtx dest = op[0];
4925 rtx src = op[1];
4926 rtx base = XEXP (dest, 0);
4927 int reg_base = true_regnum (base);
4928 int reg_src = true_regnum (src);
2da8c1ad
GJL
4929
4930 /* "volatile" forces writing low byte first, even if less efficient,
4931 for correct operation with 16-bit I/O registers like SP. */
a6990185 4932 int mem_volatile_p = MEM_VOLATILE_P (dest);
a6990185 4933
2da8c1ad 4934 if (CONSTANT_ADDRESS_P (base))
c1dd9790
JR
4935 {
4936 int n_words = AVR_TINY ? 2 : 4;
4937 return optimize > 0 && io_address_operand (base, HImode)
4938 ? avr_asm_len ("out %i0,%A1" CR_TAB
4939 "out %i0+1,%B1", op, plen, -2)
2da8c1ad 4940
c1dd9790
JR
4941 : avr_asm_len ("sts %m0,%A1" CR_TAB
4942 "sts %m0+1,%B1", op, plen, -n_words);
4943 }
00892272 4944
2da8c1ad
GJL
4945 if (reg_base > 0)
4946 {
4947 if (reg_base != REG_X)
4948 return avr_asm_len ("st %0,%A1" CR_TAB
4949 "std %0+1,%B1", op, plen, -2);
00892272 4950
2da8c1ad
GJL
4951 if (reg_src == REG_X)
4952 /* "st X+,r26" and "st -X,r26" are undefined. */
4953 avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
4954 "st X,r26" CR_TAB
4955 "adiw r26,1" CR_TAB
4956 "st X,__tmp_reg__", op, plen, -4);
4957 else
4958 avr_asm_len ("st X+,%A1" CR_TAB
4959 "st X,%B1", op, plen, -2);
39e73abc
GJL
4960
4961 return reg_unused_after (insn, base)
2da8c1ad
GJL
4962 ? ""
4963 : avr_asm_len ("sbiw r26,1", op, plen, 1);
4964 }
4965 else if (GET_CODE (base) == PLUS)
4966 {
4967 int disp = INTVAL (XEXP (base, 1));
4968 reg_base = REGNO (XEXP (base, 0));
4969 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
4970 {
4971 if (reg_base != REG_Y)
4972 fatal_insn ("incorrect insn:",insn);
00892272 4973
2da8c1ad
GJL
4974 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
4975 ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
4976 "std Y+62,%A1" CR_TAB
4977 "std Y+63,%B1" CR_TAB
4978 "sbiw r28,%o0-62", op, plen, -4)
4979
4980 : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
4981 "sbci r29,hi8(-%o0)" CR_TAB
4982 "st Y,%A1" CR_TAB
4983 "std Y+1,%B1" CR_TAB
4984 "subi r28,lo8(%o0)" CR_TAB
4985 "sbci r29,hi8(%o0)", op, plen, -6);
4986 }
00892272 4987
2da8c1ad
GJL
4988 if (reg_base != REG_X)
4989 return avr_asm_len ("std %A0,%A1" CR_TAB
4990 "std %B0,%B1", op, plen, -2);
4991 /* (X + d) = R */
4992 return reg_src == REG_X
4993 ? avr_asm_len ("mov __tmp_reg__,r26" CR_TAB
4994 "mov __zero_reg__,r27" CR_TAB
4995 "adiw r26,%o0" CR_TAB
4996 "st X+,__tmp_reg__" CR_TAB
4997 "st X,__zero_reg__" CR_TAB
4998 "clr __zero_reg__" CR_TAB
4999 "sbiw r26,%o0+1", op, plen, -7)
5000
5001 : avr_asm_len ("adiw r26,%o0" CR_TAB
5002 "st X+,%A1" CR_TAB
5003 "st X,%B1" CR_TAB
5004 "sbiw r26,%o0+1", op, plen, -4);
5005 }
5006 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5007 {
5008 if (!mem_volatile_p)
5009 return avr_asm_len ("st %0,%B1" CR_TAB
5010 "st %0,%A1", op, plen, -2);
5011
5012 return REGNO (XEXP (base, 0)) == REG_X
5013 ? avr_asm_len ("sbiw r26,2" CR_TAB
5014 "st X+,%A1" CR_TAB
5015 "st X,%B1" CR_TAB
5016 "sbiw r26,1", op, plen, -4)
5017
5018 : avr_asm_len ("sbiw %r0,2" CR_TAB
5019 "st %p0,%A1" CR_TAB
5020 "std %p0+1,%B1", op, plen, -3);
5021 }
5022 else if (GET_CODE (base) == POST_INC) /* (R++) */
5023 {
5024 return avr_asm_len ("st %0,%A1" CR_TAB
5025 "st %0,%B1", op, plen, -2);
00892272 5026
2da8c1ad
GJL
5027 }
5028 fatal_insn ("unknown move insn:",insn);
5029 return "";
5030}
5031
c1dd9790
JR
5032static const char*
5033avr_out_movhi_mr_r_reg_no_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
5034{
5035 rtx dest = op[0];
5036 rtx src = op[1];
5037 rtx base = XEXP (dest, 0);
5038 int reg_base = true_regnum (base);
5039 int reg_src = true_regnum (src);
5040 int mem_volatile_p = MEM_VOLATILE_P (dest);
5041
5042 if (reg_base == reg_src)
5043 {
5044 return !mem_volatile_p && reg_unused_after (insn, src)
5045 ? avr_asm_len ("mov __tmp_reg__,%B1" CR_TAB
5046 "st %0,%A1" CR_TAB
5047 TINY_ADIW (%E0, %F0, 1) CR_TAB
5048 "st %0,__tmp_reg__", op, plen, -5)
5049 : avr_asm_len ("mov __tmp_reg__,%B1" CR_TAB
5050 TINY_ADIW (%E0, %F0, 1) CR_TAB
5051 "st %0,__tmp_reg__" CR_TAB
5052 TINY_SBIW (%E0, %F0, 1) CR_TAB
5053 "st %0, %A1", op, plen, -7);
5054 }
5055
5056 return !mem_volatile_p && reg_unused_after (insn, base)
5057 ? avr_asm_len ("st %0+,%A1" CR_TAB
5058 "st %0,%B1", op, plen, -2)
5059 : avr_asm_len (TINY_ADIW (%E0, %F0, 1) CR_TAB
5060 "st %0,%B1" CR_TAB
5061 "st -%0,%A1", op, plen, -4);
5062}
5063
5064static const char*
dbe9dfdd 5065avr_out_movhi_mr_r_reg_disp_tiny (rtx_insn *insn, rtx op[], int *plen)
c1dd9790
JR
5066{
5067 rtx dest = op[0];
5068 rtx src = op[1];
5069 rtx base = XEXP (dest, 0);
5070 int reg_base = REGNO (XEXP (base, 0));
5071 int reg_src = true_regnum (src);
5072
dbe9dfdd
GJL
5073 if (reg_src == reg_base)
5074 avr_asm_len ("mov __tmp_reg__,%A1" CR_TAB
5075 "mov __zero_reg__,%B1" CR_TAB
5076 TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
5077 "st %b0,__zero_reg__" CR_TAB
5078 "st -%b0,__tmp_reg__" CR_TAB
5079 "clr __zero_reg__", op, plen, -7);
5080 else
5081 avr_asm_len (TINY_ADIW (%I0, %J0, %o0+1) CR_TAB
5082 "st %b0,%B1" CR_TAB
5083 "st -%b0,%A1", op, plen, -4);
5084
5085 if (!reg_unused_after (insn, XEXP (base, 0)))
5086 avr_asm_len (TINY_SBIW (%I0, %J0, %o0), op, plen, 2);
5087
5088 return "";
c1dd9790
JR
5089}
5090
5091static const char*
5092avr_out_movhi_mr_r_post_inc_tiny (rtx op[], int *plen)
5093{
5094 return avr_asm_len (TINY_ADIW (%I0, %J0, 1) CR_TAB
5095 "st %p0,%B1" CR_TAB
5096 "st -%p0,%A1" CR_TAB
5097 TINY_ADIW (%I0, %J0, 2), op, plen, -6);
5098}
2da8c1ad
GJL
5099
5100static const char*
98024b4e 5101out_movhi_mr_r (rtx_insn *insn, rtx op[], int *plen)
2da8c1ad
GJL
5102{
5103 rtx dest = op[0];
5104 rtx src = op[1];
5105 rtx base = XEXP (dest, 0);
5106 int reg_base = true_regnum (base);
5107 int reg_src = true_regnum (src);
5108 int mem_volatile_p;
5109
5110 /* "volatile" forces writing high-byte first (no-xmega) resp.
5111 low-byte first (xmega) even if less efficient, for correct
5112 operation with 16-bit I/O registers like. */
5113
5114 if (AVR_XMEGA)
5115 return avr_out_movhi_mr_r_xmega (insn, op, plen);
5116
5117 mem_volatile_p = MEM_VOLATILE_P (dest);
5118
5fecfd8d 5119 if (CONSTANT_ADDRESS_P (base))
c1dd9790
JR
5120 {
5121 int n_words = AVR_TINY ? 2 : 4;
5122 return optimize > 0 && io_address_operand (base, HImode)
5123 ? avr_asm_len ("out %i0+1,%B1" CR_TAB
5124 "out %i0,%A1", op, plen, -2)
5436efaa 5125
c1dd9790
JR
5126 : avr_asm_len ("sts %m0+1,%B1" CR_TAB
5127 "sts %m0,%A1", op, plen, -n_words);
5128 }
00892272 5129
90e7678c
DC
5130 if (reg_base > 0)
5131 {
c1dd9790
JR
5132 if (AVR_TINY)
5133 return avr_out_movhi_mr_r_reg_no_disp_tiny (insn, op, plen);
5134
5436efaa
GJL
5135 if (reg_base != REG_X)
5136 return avr_asm_len ("std %0+1,%B1" CR_TAB
5137 "st %0,%A1", op, plen, -2);
00892272 5138
5436efaa
GJL
5139 if (reg_src == REG_X)
5140 /* "st X+,r26" and "st -X,r26" are undefined. */
5141 return !mem_volatile_p && reg_unused_after (insn, src)
5142 ? avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5143 "st X,r26" CR_TAB
5144 "adiw r26,1" CR_TAB
5145 "st X,__tmp_reg__", op, plen, -4)
5146
5147 : avr_asm_len ("mov __tmp_reg__,r27" CR_TAB
5148 "adiw r26,1" CR_TAB
5149 "st X,__tmp_reg__" CR_TAB
5150 "sbiw r26,1" CR_TAB
5151 "st X,r26", op, plen, -5);
00892272 5152
5436efaa
GJL
5153 return !mem_volatile_p && reg_unused_after (insn, base)
5154 ? avr_asm_len ("st X+,%A1" CR_TAB
5155 "st X,%B1", op, plen, -2)
5156 : avr_asm_len ("adiw r26,1" CR_TAB
5157 "st X,%B1" CR_TAB
5158 "st -X,%A1", op, plen, -3);
90e7678c 5159 }
5fecfd8d 5160 else if (GET_CODE (base) == PLUS)
90e7678c 5161 {
5fecfd8d 5162 int disp = INTVAL (XEXP (base, 1));
c1dd9790
JR
5163
5164 if (AVR_TINY)
dbe9dfdd 5165 return avr_out_movhi_mr_r_reg_disp_tiny (insn, op, plen);
c1dd9790 5166
dfaf5abf 5167 reg_base = REGNO (XEXP (base, 0));
5fecfd8d 5168 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
5436efaa
GJL
5169 {
5170 if (reg_base != REG_Y)
5171 fatal_insn ("incorrect insn:",insn);
00892272 5172
5436efaa
GJL
5173 return disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest))
5174 ? avr_asm_len ("adiw r28,%o0-62" CR_TAB
5175 "std Y+63,%B1" CR_TAB
5176 "std Y+62,%A1" CR_TAB
5177 "sbiw r28,%o0-62", op, plen, -4)
5178
5179 : avr_asm_len ("subi r28,lo8(-%o0)" CR_TAB
5180 "sbci r29,hi8(-%o0)" CR_TAB
5181 "std Y+1,%B1" CR_TAB
5182 "st Y,%A1" CR_TAB
5183 "subi r28,lo8(%o0)" CR_TAB
5184 "sbci r29,hi8(%o0)", op, plen, -6);
5185 }
00892272 5186
5436efaa
GJL
5187 if (reg_base != REG_X)
5188 return avr_asm_len ("std %B0,%B1" CR_TAB
5189 "std %A0,%A1", op, plen, -2);
5190 /* (X + d) = R */
5191 return reg_src == REG_X
5192 ? avr_asm_len ("mov __tmp_reg__,r26" CR_TAB
5193 "mov __zero_reg__,r27" CR_TAB
5194 "adiw r26,%o0+1" CR_TAB
5195 "st X,__zero_reg__" CR_TAB
5196 "st -X,__tmp_reg__" CR_TAB
5197 "clr __zero_reg__" CR_TAB
5198 "sbiw r26,%o0", op, plen, -7)
5199
5200 : avr_asm_len ("adiw r26,%o0+1" CR_TAB
5201 "st X,%B1" CR_TAB
5202 "st -X,%A1" CR_TAB
5203 "sbiw r26,%o0", op, plen, -4);
6bec29c9 5204 }
5fecfd8d 5205 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
5436efaa
GJL
5206 {
5207 return avr_asm_len ("st %0,%B1" CR_TAB
5208 "st %0,%A1", op, plen, -2);
5209 }
5fecfd8d 5210 else if (GET_CODE (base) == POST_INC) /* (R++) */
a6990185 5211 {
5436efaa
GJL
5212 if (!mem_volatile_p)
5213 return avr_asm_len ("st %0,%A1" CR_TAB
5214 "st %0,%B1", op, plen, -2);
00892272 5215
c1dd9790
JR
5216 if (AVR_TINY)
5217 return avr_out_movhi_mr_r_post_inc_tiny (op, plen);
5218
5436efaa
GJL
5219 return REGNO (XEXP (base, 0)) == REG_X
5220 ? avr_asm_len ("adiw r26,1" CR_TAB
5221 "st X,%B1" CR_TAB
5222 "st -X,%A1" CR_TAB
5223 "adiw r26,2", op, plen, -4)
a6990185 5224
5436efaa
GJL
5225 : avr_asm_len ("std %p0+1,%B1" CR_TAB
5226 "st %p0,%A1" CR_TAB
5227 "adiw %r0,2", op, plen, -3);
a6990185 5228 }
c725bd79 5229 fatal_insn ("unknown move insn:",insn);
90e7678c
DC
5230 return "";
5231}
5232
2c338472 5233/* Return 1 if frame pointer for current function required. */
90e7678c 5234
d2111e2f 5235static bool
c21ca196 5236avr_frame_pointer_required_p (void)
90e7678c 5237{
e3b5732b 5238 return (cfun->calls_alloca
d702f362
GJL
5239 || cfun->calls_setjmp
5240 || cfun->has_nonlocal_label
5241 || crtl->args.info.nregs == 0
5242 || get_frame_size () > 0);
90e7678c
DC
5243}
5244
89741abb 5245/* Returns the condition of compare insn INSN, or UNKNOWN. */
90e7678c 5246
89741abb 5247static RTX_CODE
98024b4e 5248compare_condition (rtx_insn *insn)
90e7678c 5249{
98024b4e 5250 rtx_insn *next = next_real_insn (insn);
f3713778
GJL
5251
5252 if (next && JUMP_P (next))
90e7678c
DC
5253 {
5254 rtx pat = PATTERN (next);
5255 rtx src = SET_SRC (pat);
00892272 5256
f3713778
GJL
5257 if (IF_THEN_ELSE == GET_CODE (src))
5258 return GET_CODE (XEXP (src, 0));
90e7678c 5259 }
00892272 5260
f3713778 5261 return UNKNOWN;
89741abb
MM
5262}
5263
89741abb 5264
a7c0acd0
GJL
5265/* Returns true iff INSN is a tst insn that only tests the sign. */
5266
5267static bool
98024b4e 5268compare_sign_p (rtx_insn *insn)
89741abb
MM
5269{
5270 RTX_CODE cond = compare_condition (insn);
5271 return (cond == GE || cond == LT);
5272}
5273
a7c0acd0
GJL
5274
5275/* Returns true iff the next insn is a JUMP_INSN with a condition
89741abb
MM
5276 that needs to be swapped (GT, GTU, LE, LEU). */
5277
a7c0acd0 5278static bool
98024b4e 5279compare_diff_p (rtx_insn *insn)
89741abb
MM
5280{
5281 RTX_CODE cond = compare_condition (insn);
90e7678c
DC
5282 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
5283}
5284
a7c0acd0 5285/* Returns true iff INSN is a compare insn with the EQ or NE condition. */
90e7678c 5286
a7c0acd0 5287static bool
98024b4e 5288compare_eq_p (rtx_insn *insn)
90e7678c 5289{
89741abb 5290 RTX_CODE cond = compare_condition (insn);
90e7678c
DC
5291 return (cond == EQ || cond == NE);
5292}
5293
5294
a7c0acd0
GJL
5295/* Output compare instruction
5296
5297 compare (XOP[0], XOP[1])
5298
00892272 5299 for a register XOP[0] and a compile-time constant XOP[1]. Return "".
a7c0acd0
GJL
5300 XOP[2] is an 8-bit scratch register as needed.
5301
5302 PLEN == NULL: Output instructions.
5303 PLEN != NULL: Set *PLEN to the length (in words) of the sequence.
5304 Don't output anything. */
5305
5306const char*
98024b4e 5307avr_out_compare (rtx_insn *insn, rtx *xop, int *plen)
a7c0acd0
GJL
5308{
5309 /* Register to compare and value to compare against. */
5310 rtx xreg = xop[0];
5311 rtx xval = xop[1];
00892272 5312
a7c0acd0 5313 /* MODE of the comparison. */
ef4bddc2 5314 machine_mode mode;
a7c0acd0
GJL
5315
5316 /* Number of bytes to operate on. */
e55e4056 5317 int i, n_bytes = GET_MODE_SIZE (GET_MODE (xreg));
a7c0acd0
GJL
5318
5319 /* Value (0..0xff) held in clobber register xop[2] or -1 if unknown. */
5320 int clobber_val = -1;
5321
e55e4056
GJL
5322 /* Map fixed mode operands to integer operands with the same binary
5323 representation. They are easier to handle in the remainder. */
5324
51526856 5325 if (CONST_FIXED_P (xval))
e55e4056
GJL
5326 {
5327 xreg = avr_to_int_mode (xop[0]);
5328 xval = avr_to_int_mode (xop[1]);
5329 }
00892272 5330
e55e4056
GJL
5331 mode = GET_MODE (xreg);
5332
8c57e547
GJL
5333 gcc_assert (REG_P (xreg));
5334 gcc_assert ((CONST_INT_P (xval) && n_bytes <= 4)
5335 || (const_double_operand (xval, VOIDmode) && n_bytes == 8));
00892272 5336
a7c0acd0
GJL
5337 if (plen)
5338 *plen = 0;
5339
31fd727b 5340 /* Comparisons == +/-1 and != +/-1 can be done similar to camparing
8c57e547 5341 against 0 by ORing the bytes. This is one instruction shorter.
e55e4056 5342 Notice that 64-bit comparisons are always against reg:ALL8 18 (ACC_A)
8c57e547 5343 and therefore don't use this. */
31fd727b
GJL
5344
5345 if (!test_hard_reg_class (LD_REGS, xreg)
5346 && compare_eq_p (insn)
5347 && reg_unused_after (insn, xreg))
5348 {
5349 if (xval == const1_rtx)
5350 {
5351 avr_asm_len ("dec %A0" CR_TAB
5352 "or %A0,%B0", xop, plen, 2);
00892272 5353
e4fe948a
GJL
5354 if (n_bytes >= 3)
5355 avr_asm_len ("or %A0,%C0", xop, plen, 1);
5356
5357 if (n_bytes >= 4)
5358 avr_asm_len ("or %A0,%D0", xop, plen, 1);
31fd727b
GJL
5359
5360 return "";
5361 }
5362 else if (xval == constm1_rtx)
5363 {
e4fe948a
GJL
5364 if (n_bytes >= 4)
5365 avr_asm_len ("and %A0,%D0", xop, plen, 1);
00892272 5366
e4fe948a
GJL
5367 if (n_bytes >= 3)
5368 avr_asm_len ("and %A0,%C0", xop, plen, 1);
00892272 5369
e4fe948a
GJL
5370 return avr_asm_len ("and %A0,%B0" CR_TAB
5371 "com %A0", xop, plen, 2);
31fd727b
GJL
5372 }
5373 }
5374
be88b0c7
GJL
5375 /* Comparisons == -1 and != -1 of a d-register that's used after the
5376 comparison. (If it's unused after we use CPI / SBCI or ADIW sequence
5377 from below.) Instead of CPI Rlo,-1 / LDI Rx,-1 / CPC Rhi,Rx we can
5378 use CPI Rlo,-1 / CPC Rhi,Rlo which is 1 instruction shorter:
5379 If CPI is true then Rlo contains -1 and we can use Rlo instead of Rx
5380 when CPC'ing the high part. If CPI is false then CPC cannot render
5381 the result to true. This also works for the more generic case where
5382 the constant is of the form 0xabab. */
5383
5384 if (n_bytes == 2
d51553e0 5385 && xval != const0_rtx
be88b0c7
GJL
5386 && test_hard_reg_class (LD_REGS, xreg)
5387 && compare_eq_p (insn)
5388 && !reg_unused_after (insn, xreg))
5389 {
5390 rtx xlo8 = simplify_gen_subreg (QImode, xval, mode, 0);
5391 rtx xhi8 = simplify_gen_subreg (QImode, xval, mode, 1);
5392
5393 if (INTVAL (xlo8) == INTVAL (xhi8))
5394 {
5395 xop[0] = xreg;
5396 xop[1] = xlo8;
5397
5398 return avr_asm_len ("cpi %A0,%1" CR_TAB
5399 "cpc %B0,%A0", xop, plen, 2);
5400 }
5401 }
5402
a7c0acd0
GJL
5403 for (i = 0; i < n_bytes; i++)
5404 {
5405 /* We compare byte-wise. */
5406 rtx reg8 = simplify_gen_subreg (QImode, xreg, mode, i);
5407 rtx xval8 = simplify_gen_subreg (QImode, xval, mode, i);
5408
5409 /* 8-bit value to compare with this byte. */
5410 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
5411
5412 /* Registers R16..R31 can operate with immediate. */
5413 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
5414
5415 xop[0] = reg8;
5416 xop[1] = gen_int_mode (val8, QImode);
5417
5418 /* Word registers >= R24 can use SBIW/ADIW with 0..63. */
5419
5420 if (i == 0
5421 && test_hard_reg_class (ADDW_REGS, reg8))
5422 {
5423 int val16 = trunc_int_for_mode (INTVAL (xval), HImode);
00892272 5424
a7c0acd0
GJL
5425 if (IN_RANGE (val16, 0, 63)
5426 && (val8 == 0
5427 || reg_unused_after (insn, xreg)))
5428 {
c1dd9790
JR
5429 if (AVR_TINY)
5430 avr_asm_len (TINY_SBIW (%A0, %B0, %1), xop, plen, 2);
5431 else
5432 avr_asm_len ("sbiw %0,%1", xop, plen, 1);
5433
a7c0acd0
GJL
5434 i++;
5435 continue;
5436 }
5437
5438 if (n_bytes == 2
5439 && IN_RANGE (val16, -63, -1)
5440 && compare_eq_p (insn)
5441 && reg_unused_after (insn, xreg))
5442 {
c1dd9790
JR
5443 return AVR_TINY
5444 ? avr_asm_len (TINY_ADIW (%A0, %B0, %n1), xop, plen, 2)
5445 : avr_asm_len ("adiw %0,%n1", xop, plen, 1);
a7c0acd0
GJL
5446 }
5447 }
5448
5449 /* Comparing against 0 is easy. */
00892272 5450
a7c0acd0
GJL
5451 if (val8 == 0)
5452 {
5453 avr_asm_len (i == 0
5454 ? "cp %0,__zero_reg__"
5455 : "cpc %0,__zero_reg__", xop, plen, 1);
5456 continue;
5457 }
5458
5459 /* Upper registers can compare and subtract-with-carry immediates.
5460 Notice that compare instructions do the same as respective subtract
5461 instruction; the only difference is that comparisons don't write
5462 the result back to the target register. */
5463
5464 if (ld_reg_p)
5465 {
5466 if (i == 0)
5467 {
5468 avr_asm_len ("cpi %0,%1", xop, plen, 1);
5469 continue;
5470 }
5471 else if (reg_unused_after (insn, xreg))
5472 {
5473 avr_asm_len ("sbci %0,%1", xop, plen, 1);
5474 continue;
5475 }
5476 }
5477
5478 /* Must load the value into the scratch register. */
5479
5480 gcc_assert (REG_P (xop[2]));
00892272 5481
a7c0acd0
GJL
5482 if (clobber_val != (int) val8)
5483 avr_asm_len ("ldi %2,%1", xop, plen, 1);
5484 clobber_val = (int) val8;
00892272 5485
a7c0acd0
GJL
5486 avr_asm_len (i == 0
5487 ? "cp %0,%2"
5488 : "cpc %0,%2", xop, plen, 1);
5489 }
5490
5491 return "";
5492}
5493
5494
8c57e547
GJL
5495/* Prepare operands of compare_const_di2 to be used with avr_out_compare. */
5496
5497const char*
98024b4e 5498avr_out_compare64 (rtx_insn *insn, rtx *op, int *plen)
8c57e547
GJL
5499{
5500 rtx xop[3];
5501
5502 xop[0] = gen_rtx_REG (DImode, 18);
5503 xop[1] = op[0];
5504 xop[2] = op[1];
5505
5506 return avr_out_compare (insn, xop, plen);
5507}
5508
2c338472 5509/* Output test instruction for HImode. */
90e7678c 5510
a7c0acd0 5511const char*
98024b4e 5512avr_out_tsthi (rtx_insn *insn, rtx *op, int *plen)
90e7678c 5513{
89741abb 5514 if (compare_sign_p (insn))
90e7678c 5515 {
a7c0acd0 5516 avr_asm_len ("tst %B0", op, plen, -1);
90e7678c 5517 }
a7c0acd0
GJL
5518 else if (reg_unused_after (insn, op[0])
5519 && compare_eq_p (insn))
90e7678c 5520 {
2c338472 5521 /* Faster than sbiw if we can clobber the operand. */
a7c0acd0 5522 avr_asm_len ("or %A0,%B0", op, plen, -1);
90e7678c 5523 }
a7c0acd0 5524 else
90e7678c 5525 {
a7c0acd0 5526 avr_out_compare (insn, op, plen);
90e7678c 5527 }
a7c0acd0
GJL
5528
5529 return "";
90e7678c
DC
5530}
5531
5532
e4fe948a
GJL
5533/* Output test instruction for PSImode. */
5534
5535const char*
98024b4e 5536avr_out_tstpsi (rtx_insn *insn, rtx *op, int *plen)
e4fe948a
GJL
5537{
5538 if (compare_sign_p (insn))
5539 {
5540 avr_asm_len ("tst %C0", op, plen, -1);
5541 }
5542 else if (reg_unused_after (insn, op[0])
5543 && compare_eq_p (insn))
5544 {
5545 /* Faster than sbiw if we can clobber the operand. */
5546 avr_asm_len ("or %A0,%B0" CR_TAB
5547 "or %A0,%C0", op, plen, -2);
5548 }
5549 else
5550 {
5551 avr_out_compare (insn, op, plen);
5552 }
5553
5554 return "";
5555}
5556
5557
2c338472 5558/* Output test instruction for SImode. */
90e7678c 5559
a7c0acd0 5560const char*
98024b4e 5561avr_out_tstsi (rtx_insn *insn, rtx *op, int *plen)
90e7678c 5562{
89741abb 5563 if (compare_sign_p (insn))
90e7678c 5564 {
a7c0acd0 5565 avr_asm_len ("tst %D0", op, plen, -1);
90e7678c 5566 }
a7c0acd0
GJL
5567 else if (reg_unused_after (insn, op[0])
5568 && compare_eq_p (insn))
90e7678c 5569 {
a7c0acd0
GJL
5570 /* Faster than sbiw if we can clobber the operand. */
5571 avr_asm_len ("or %A0,%B0" CR_TAB
5572 "or %A0,%C0" CR_TAB
5573 "or %A0,%D0", op, plen, -3);
5574 }
5575 else
5576 {
5577 avr_out_compare (insn, op, plen);
90e7678c 5578 }
a7c0acd0
GJL
5579
5580 return "";
90e7678c
DC
5581}
5582
5583
5436efaa
GJL
5584/* Generate asm equivalent for various shifts. This only handles cases
5585 that are not already carefully hand-optimized in ?sh??i3_out.
5586
5587 OPERANDS[0] resp. %0 in TEMPL is the operand to be shifted.
5588 OPERANDS[2] is the shift count as CONST_INT, MEM or REG.
5589 OPERANDS[3] is a QImode scratch register from LD regs if
5590 available and SCRATCH, otherwise (no scratch available)
5591
5592 TEMPL is an assembler template that shifts by one position.
5593 T_LEN is the length of this template. */
90e7678c
DC
5594
5595void
98024b4e 5596out_shift_with_cnt (const char *templ, rtx_insn *insn, rtx operands[],
5436efaa 5597 int *plen, int t_len)
90e7678c 5598{
5436efaa
GJL
5599 bool second_label = true;
5600 bool saved_in_tmp = false;
5601 bool use_zero_reg = false;
5602 rtx op[5];
afee2a52 5603
90e7678c
DC
5604 op[0] = operands[0];
5605 op[1] = operands[1];
5606 op[2] = operands[2];
5607 op[3] = operands[3];
afee2a52 5608
5436efaa
GJL
5609 if (plen)
5610 *plen = 0;
afee2a52 5611
7c209481 5612 if (CONST_INT_P (operands[2]))
90e7678c 5613 {
7c209481
GJL
5614 bool scratch = (GET_CODE (PATTERN (insn)) == PARALLEL
5615 && REG_P (operands[3]));
afee2a52
MM
5616 int count = INTVAL (operands[2]);
5617 int max_len = 10; /* If larger than this, always use a loop. */
5618
a3cf5992 5619 if (count <= 0)
5436efaa 5620 return;
a3cf5992 5621
afee2a52 5622 if (count < 8 && !scratch)
5436efaa 5623 use_zero_reg = true;
afee2a52
MM
5624
5625 if (optimize_size)
5436efaa 5626 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
afee2a52
MM
5627
5628 if (t_len * count <= max_len)
5436efaa
GJL
5629 {
5630 /* Output shifts inline with no loop - faster. */
00892272 5631
5436efaa
GJL
5632 while (count-- > 0)
5633 avr_asm_len (templ, op, plen, t_len);
afee2a52 5634
5436efaa
GJL
5635 return;
5636 }
afee2a52
MM
5637
5638 if (scratch)
5436efaa
GJL
5639 {
5640 avr_asm_len ("ldi %3,%2", op, plen, 1);
5641 }
afee2a52 5642 else if (use_zero_reg)
5436efaa
GJL
5643 {
5644 /* Hack to save one word: use __zero_reg__ as loop counter.
5645 Set one bit, then shift in a loop until it is 0 again. */
afee2a52 5646
5436efaa
GJL
5647 op[3] = zero_reg_rtx;
5648
5649 avr_asm_len ("set" CR_TAB
5650 "bld %3,%2-1", op, plen, 2);
5651 }
90e7678c 5652 else
5436efaa
GJL
5653 {
5654 /* No scratch register available, use one from LD_REGS (saved in
5655 __tmp_reg__) that doesn't overlap with registers to shift. */
afee2a52 5656
5436efaa
GJL
5657 op[3] = all_regs_rtx[((REGNO (op[0]) - 1) & 15) + 16];
5658 op[4] = tmp_reg_rtx;
5659 saved_in_tmp = true;
afee2a52 5660
5436efaa
GJL
5661 avr_asm_len ("mov %4,%3" CR_TAB
5662 "ldi %3,%2", op, plen, 2);
5663 }
afee2a52 5664
5436efaa 5665 second_label = false;
90e7678c 5666 }
5436efaa 5667 else if (MEM_P (op[2]))
90e7678c 5668 {
5436efaa 5669 rtx op_mov[2];
00892272 5670
5436efaa 5671 op_mov[0] = op[3] = tmp_reg_rtx;
90e7678c 5672 op_mov[1] = op[2];
afee2a52 5673
5436efaa 5674 out_movqi_r_mr (insn, op_mov, plen);
90e7678c 5675 }
5436efaa 5676 else if (register_operand (op[2], QImode))
90e7678c 5677 {
5436efaa 5678 op[3] = op[2];
00892272 5679
5436efaa
GJL
5680 if (!reg_unused_after (insn, op[2])
5681 || reg_overlap_mentioned_p (op[0], op[2]))
f4da258f 5682 {
5436efaa
GJL
5683 op[3] = tmp_reg_rtx;
5684 avr_asm_len ("mov %3,%2", op, plen, 1);
f4da258f 5685 }
afee2a52
MM
5686 }
5687 else
c725bd79 5688 fatal_insn ("bad shift insn:", insn);
afee2a52
MM
5689
5690 if (second_label)
5436efaa 5691 avr_asm_len ("rjmp 2f", op, plen, 1);
afee2a52 5692
5436efaa
GJL
5693 avr_asm_len ("1:", op, plen, 0);
5694 avr_asm_len (templ, op, plen, t_len);
5695
5696 if (second_label)
5697 avr_asm_len ("2:", op, plen, 0);
5698
5699 avr_asm_len (use_zero_reg ? "lsr %3" : "dec %3", op, plen, 1);
5700 avr_asm_len (second_label ? "brpl 1b" : "brne 1b", op, plen, 1);
5701
5702 if (saved_in_tmp)
5703 avr_asm_len ("mov %3,%4", op, plen, 1);
90e7678c
DC
5704}
5705
5706
5707/* 8bit shift left ((char)x << i) */
5708
5fecfd8d 5709const char *
98024b4e 5710ashlqi3_out (rtx_insn *insn, rtx operands[], int *len)
90e7678c
DC
5711{
5712 if (GET_CODE (operands[2]) == CONST_INT)
5713 {
5714 int k;
3454eb73 5715
90e7678c
DC
5716 if (!len)
5717 len = &k;
3454eb73 5718
90e7678c
DC
5719 switch (INTVAL (operands[2]))
5720 {
3454eb73 5721 default:
a3cf5992
MM
5722 if (INTVAL (operands[2]) < 8)
5723 break;
5724
3454eb73 5725 *len = 1;
c2453253 5726 return "clr %0";
00892272 5727
90e7678c 5728 case 1:
3454eb73 5729 *len = 1;
c2453253 5730 return "lsl %0";
00892272 5731
90e7678c 5732 case 2:
3454eb73 5733 *len = 2;
c2453253
GJL
5734 return ("lsl %0" CR_TAB
5735 "lsl %0");
3454eb73 5736
90e7678c 5737 case 3:
3454eb73 5738 *len = 3;
c2453253
GJL
5739 return ("lsl %0" CR_TAB
5740 "lsl %0" CR_TAB
5741 "lsl %0");
3454eb73 5742
90e7678c 5743 case 4:
c4984bad 5744 if (test_hard_reg_class (LD_REGS, operands[0]))
90e7678c 5745 {
3454eb73 5746 *len = 2;
c2453253
GJL
5747 return ("swap %0" CR_TAB
5748 "andi %0,0xf0");
90e7678c 5749 }
3454eb73 5750 *len = 4;
c2453253
GJL
5751 return ("lsl %0" CR_TAB
5752 "lsl %0" CR_TAB
5753 "lsl %0" CR_TAB
5754 "lsl %0");
3454eb73 5755
90e7678c 5756 case 5:
c4984bad 5757 if (test_hard_reg_class (LD_REGS, operands[0]))
90e7678c 5758 {
3454eb73 5759 *len = 3;
c2453253
GJL
5760 return ("swap %0" CR_TAB
5761 "lsl %0" CR_TAB
5762 "andi %0,0xe0");
90e7678c 5763 }
3454eb73 5764 *len = 5;
c2453253
GJL
5765 return ("lsl %0" CR_TAB
5766 "lsl %0" CR_TAB
5767 "lsl %0" CR_TAB
5768 "lsl %0" CR_TAB
5769 "lsl %0");
3454eb73 5770
90e7678c 5771 case 6:
c4984bad 5772 if (test_hard_reg_class (LD_REGS, operands[0]))
90e7678c 5773 {
3454eb73 5774 *len = 4;
c2453253
GJL
5775 return ("swap %0" CR_TAB
5776 "lsl %0" CR_TAB
5777 "lsl %0" CR_TAB
5778 "andi %0,0xc0");
90e7678c 5779 }
3454eb73 5780 *len = 6;
c2453253
GJL
5781 return ("lsl %0" CR_TAB
5782 "lsl %0" CR_TAB
5783 "lsl %0" CR_TAB
5784 "lsl %0" CR_TAB
5785 "lsl %0" CR_TAB
5786 "lsl %0");
3454eb73 5787
90e7678c 5788 case 7:
3454eb73 5789 *len = 3;
c2453253
GJL
5790 return ("ror %0" CR_TAB
5791 "clr %0" CR_TAB
5792 "ror %0");
90e7678c
DC
5793 }
5794 }
3454eb73 5795 else if (CONSTANT_P (operands[2]))
c725bd79 5796 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3454eb73 5797
c2453253
GJL
5798 out_shift_with_cnt ("lsl %0",
5799 insn, operands, len, 1);
90e7678c
DC
5800 return "";
5801}
5802
5803
5804/* 16bit shift left ((short)x << i) */
5805
5fecfd8d 5806const char *
98024b4e 5807ashlhi3_out (rtx_insn *insn, rtx operands[], int *len)
90e7678c
DC
5808{
5809 if (GET_CODE (operands[2]) == CONST_INT)
5810 {
afee2a52
MM
5811 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
5812 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
90e7678c 5813 int k;
afee2a52 5814 int *t = len;
3454eb73 5815
90e7678c
DC
5816 if (!len)
5817 len = &k;
00892272 5818
90e7678c
DC
5819 switch (INTVAL (operands[2]))
5820 {
a3cf5992
MM
5821 default:
5822 if (INTVAL (operands[2]) < 16)
5823 break;
5824
5825 *len = 2;
c2453253
GJL
5826 return ("clr %B0" CR_TAB
5827 "clr %A0");
a3cf5992 5828
afee2a52
MM
5829 case 4:
5830 if (optimize_size && scratch)
5831 break; /* 5 */
5832 if (ldi_ok)
5833 {
5834 *len = 6;
c2453253
GJL
5835 return ("swap %A0" CR_TAB
5836 "swap %B0" CR_TAB
5837 "andi %B0,0xf0" CR_TAB
5838 "eor %B0,%A0" CR_TAB
5839 "andi %A0,0xf0" CR_TAB
5840 "eor %B0,%A0");
afee2a52
MM
5841 }
5842 if (scratch)
5843 {
5844 *len = 7;
c2453253
GJL
5845 return ("swap %A0" CR_TAB
5846 "swap %B0" CR_TAB
5847 "ldi %3,0xf0" CR_TAB
5a82ecd9 5848 "and %B0,%3" CR_TAB
c2453253 5849 "eor %B0,%A0" CR_TAB
5a82ecd9 5850 "and %A0,%3" CR_TAB
c2453253 5851 "eor %B0,%A0");
afee2a52
MM
5852 }
5853 break; /* optimize_size ? 6 : 8 */
3454eb73 5854
afee2a52
MM
5855 case 5:
5856 if (optimize_size)
5857 break; /* scratch ? 5 : 6 */
5858 if (ldi_ok)
5859 {
5860 *len = 8;
c2453253
GJL
5861 return ("lsl %A0" CR_TAB
5862 "rol %B0" CR_TAB
5863 "swap %A0" CR_TAB
5864 "swap %B0" CR_TAB
5865 "andi %B0,0xf0" CR_TAB
5866 "eor %B0,%A0" CR_TAB
5867 "andi %A0,0xf0" CR_TAB
5868 "eor %B0,%A0");
afee2a52
MM
5869 }
5870 if (scratch)
5871 {
5872 *len = 9;
c2453253
GJL
5873 return ("lsl %A0" CR_TAB
5874 "rol %B0" CR_TAB
5875 "swap %A0" CR_TAB
5876 "swap %B0" CR_TAB
5877 "ldi %3,0xf0" CR_TAB
5a82ecd9 5878 "and %B0,%3" CR_TAB
c2453253 5879 "eor %B0,%A0" CR_TAB
5a82ecd9 5880 "and %A0,%3" CR_TAB
c2453253 5881 "eor %B0,%A0");
afee2a52
MM
5882 }
5883 break; /* 10 */
5884
5885 case 6:
5886 if (optimize_size)
5887 break; /* scratch ? 5 : 6 */
5888 *len = 9;
c2453253
GJL
5889 return ("clr __tmp_reg__" CR_TAB
5890 "lsr %B0" CR_TAB
5891 "ror %A0" CR_TAB
5892 "ror __tmp_reg__" CR_TAB
5893 "lsr %B0" CR_TAB
5894 "ror %A0" CR_TAB
5895 "ror __tmp_reg__" CR_TAB
5896 "mov %B0,%A0" CR_TAB
5897 "mov %A0,__tmp_reg__");
3454eb73 5898
adcd8f77
MM
5899 case 7:
5900 *len = 5;
c2453253
GJL
5901 return ("lsr %B0" CR_TAB
5902 "mov %B0,%A0" CR_TAB
5903 "clr %A0" CR_TAB
5904 "ror %B0" CR_TAB
5905 "ror %A0");
adcd8f77 5906
90e7678c 5907 case 8:
c2453253
GJL
5908 return *len = 2, ("mov %B0,%A1" CR_TAB
5909 "clr %A0");
adcd8f77
MM
5910
5911 case 9:
5912 *len = 3;
c2453253
GJL
5913 return ("mov %B0,%A0" CR_TAB
5914 "clr %A0" CR_TAB
5915 "lsl %B0");
adcd8f77
MM
5916
5917 case 10:
5918 *len = 4;
c2453253
GJL
5919 return ("mov %B0,%A0" CR_TAB
5920 "clr %A0" CR_TAB
5921 "lsl %B0" CR_TAB
5922 "lsl %B0");
adcd8f77
MM
5923
5924 case 11:
5925 *len = 5;
c2453253
GJL
5926 return ("mov %B0,%A0" CR_TAB
5927 "clr %A0" CR_TAB
5928 "lsl %B0" CR_TAB
5929 "lsl %B0" CR_TAB
5930 "lsl %B0");
adcd8f77
MM
5931
5932 case 12:
afee2a52 5933 if (ldi_ok)
adcd8f77
MM
5934 {
5935 *len = 4;
c2453253
GJL
5936 return ("mov %B0,%A0" CR_TAB
5937 "clr %A0" CR_TAB
5938 "swap %B0" CR_TAB
5939 "andi %B0,0xf0");
adcd8f77 5940 }
afee2a52
MM
5941 if (scratch)
5942 {
5943 *len = 5;
c2453253
GJL
5944 return ("mov %B0,%A0" CR_TAB
5945 "clr %A0" CR_TAB
5946 "swap %B0" CR_TAB
5947 "ldi %3,0xf0" CR_TAB
5a82ecd9 5948 "and %B0,%3");
afee2a52
MM
5949 }
5950 *len = 6;
c2453253
GJL
5951 return ("mov %B0,%A0" CR_TAB
5952 "clr %A0" CR_TAB
5953 "lsl %B0" CR_TAB
5954 "lsl %B0" CR_TAB
5955 "lsl %B0" CR_TAB
5956 "lsl %B0");
adcd8f77
MM
5957
5958 case 13:
afee2a52 5959 if (ldi_ok)
adcd8f77
MM
5960 {
5961 *len = 5;
c2453253
GJL
5962 return ("mov %B0,%A0" CR_TAB
5963 "clr %A0" CR_TAB
5964 "swap %B0" CR_TAB
5965 "lsl %B0" CR_TAB
5966 "andi %B0,0xe0");
adcd8f77 5967 }
dd6d1f8c 5968 if (AVR_HAVE_MUL && scratch)
adcd8f77
MM
5969 {
5970 *len = 5;
c2453253
GJL
5971 return ("ldi %3,0x20" CR_TAB
5972 "mul %A0,%3" CR_TAB
5973 "mov %B0,r0" CR_TAB
5974 "clr %A0" CR_TAB
5975 "clr __zero_reg__");
adcd8f77 5976 }
afee2a52
MM
5977 if (optimize_size && scratch)
5978 break; /* 5 */
5979 if (scratch)
5980 {
5981 *len = 6;
c2453253
GJL
5982 return ("mov %B0,%A0" CR_TAB
5983 "clr %A0" CR_TAB
5984 "swap %B0" CR_TAB
5985 "lsl %B0" CR_TAB
5986 "ldi %3,0xe0" CR_TAB
5a82ecd9 5987 "and %B0,%3");
afee2a52 5988 }
dd6d1f8c 5989 if (AVR_HAVE_MUL)
afee2a52
MM
5990 {
5991 *len = 6;
5992 return ("set" CR_TAB
c2453253
GJL
5993 "bld r1,5" CR_TAB
5994 "mul %A0,r1" CR_TAB
5995 "mov %B0,r0" CR_TAB
5996 "clr %A0" CR_TAB
5997 "clr __zero_reg__");
afee2a52
MM
5998 }
5999 *len = 7;
c2453253
GJL
6000 return ("mov %B0,%A0" CR_TAB
6001 "clr %A0" CR_TAB
6002 "lsl %B0" CR_TAB
6003 "lsl %B0" CR_TAB
6004 "lsl %B0" CR_TAB
6005 "lsl %B0" CR_TAB
6006 "lsl %B0");
adcd8f77
MM
6007
6008 case 14:
dd6d1f8c 6009 if (AVR_HAVE_MUL && ldi_ok)
afee2a52
MM
6010 {
6011 *len = 5;
c2453253
GJL
6012 return ("ldi %B0,0x40" CR_TAB
6013 "mul %A0,%B0" CR_TAB
6014 "mov %B0,r0" CR_TAB
6015 "clr %A0" CR_TAB
6016 "clr __zero_reg__");
afee2a52 6017 }
dd6d1f8c 6018 if (AVR_HAVE_MUL && scratch)
adcd8f77
MM
6019 {
6020 *len = 5;
c2453253
GJL
6021 return ("ldi %3,0x40" CR_TAB
6022 "mul %A0,%3" CR_TAB
6023 "mov %B0,r0" CR_TAB
6024 "clr %A0" CR_TAB
6025 "clr __zero_reg__");
adcd8f77 6026 }
afee2a52
MM
6027 if (optimize_size && ldi_ok)
6028 {
6029 *len = 5;
c2453253
GJL
6030 return ("mov %B0,%A0" CR_TAB
6031 "ldi %A0,6" "\n1:\t"
6032 "lsl %B0" CR_TAB
6033 "dec %A0" CR_TAB
6034 "brne 1b");
afee2a52
MM
6035 }
6036 if (optimize_size && scratch)
6037 break; /* 5 */
6038 *len = 6;
c2453253
GJL
6039 return ("clr %B0" CR_TAB
6040 "lsr %A0" CR_TAB
6041 "ror %B0" CR_TAB
6042 "lsr %A0" CR_TAB
6043 "ror %B0" CR_TAB
6044 "clr %A0");
adcd8f77
MM
6045
6046 case 15:
6047 *len = 4;
c2453253
GJL
6048 return ("clr %B0" CR_TAB
6049 "lsr %A0" CR_TAB
6050 "ror %B0" CR_TAB
6051 "clr %A0");
90e7678c 6052 }
adcd8f77 6053 len = t;
90e7678c 6054 }
c2453253
GJL
6055 out_shift_with_cnt ("lsl %A0" CR_TAB
6056 "rol %B0", insn, operands, len, 2);
90e7678c
DC
6057 return "";
6058}
6059
6060
e4fe948a
GJL
6061/* 24-bit shift left */
6062
6063const char*
98024b4e 6064avr_out_ashlpsi3 (rtx_insn *insn, rtx *op, int *plen)
e4fe948a
GJL
6065{
6066 if (plen)
6067 *plen = 0;
00892272 6068
e4fe948a
GJL
6069 if (CONST_INT_P (op[2]))
6070 {
6071 switch (INTVAL (op[2]))
6072 {
6073 default:
6074 if (INTVAL (op[2]) < 24)
6075 break;
6076
6077 return avr_asm_len ("clr %A0" CR_TAB
6078 "clr %B0" CR_TAB
6079 "clr %C0", op, plen, 3);
6080
6081 case 8:
6082 {
6083 int reg0 = REGNO (op[0]);
6084 int reg1 = REGNO (op[1]);
00892272 6085
e4fe948a
GJL
6086 if (reg0 >= reg1)
6087 return avr_asm_len ("mov %C0,%B1" CR_TAB
6088 "mov %B0,%A1" CR_TAB
6089 "clr %A0", op, plen, 3);
6090 else
6091 return avr_asm_len ("clr %A0" CR_TAB
6092 "mov %B0,%A1" CR_TAB
6093 "mov %C0,%B1", op, plen, 3);
6094 }
6095
6096 case 16:
6097 {
6098 int reg0 = REGNO (op[0]);
6099 int reg1 = REGNO (op[1]);
6100
6101 if (reg0 + 2 != reg1)
6102 avr_asm_len ("mov %C0,%A0", op, plen, 1);
00892272 6103
e4fe948a
GJL
6104 return avr_asm_len ("clr %B0" CR_TAB
6105 "clr %A0", op, plen, 2);
6106 }
6107
6108 case 23:
6109 return avr_asm_len ("clr %C0" CR_TAB
6110 "lsr %A0" CR_TAB
6111 "ror %C0" CR_TAB
6112 "clr %B0" CR_TAB
6113 "clr %A0", op, plen, 5);
6114 }
6115 }
00892272 6116
e4fe948a
GJL
6117 out_shift_with_cnt ("lsl %A0" CR_TAB
6118 "rol %B0" CR_TAB
6119 "rol %C0", insn, op, plen, 3);
6120 return "";
6121}
6122
6123
90e7678c
DC
6124/* 32bit shift left ((long)x << i) */
6125
5fecfd8d 6126const char *
98024b4e 6127ashlsi3_out (rtx_insn *insn, rtx operands[], int *len)
90e7678c
DC
6128{
6129 if (GET_CODE (operands[2]) == CONST_INT)
6130 {
6131 int k;
afee2a52 6132 int *t = len;
00892272 6133
90e7678c
DC
6134 if (!len)
6135 len = &k;
00892272 6136
90e7678c
DC
6137 switch (INTVAL (operands[2]))
6138 {
a3cf5992
MM
6139 default:
6140 if (INTVAL (operands[2]) < 32)
6141 break;
6142
4301ec4f 6143 if (AVR_HAVE_MOVW)
c2453253
GJL
6144 return *len = 3, ("clr %D0" CR_TAB
6145 "clr %C0" CR_TAB
6146 "movw %A0,%C0");
a3cf5992 6147 *len = 4;
c2453253
GJL
6148 return ("clr %D0" CR_TAB
6149 "clr %C0" CR_TAB
6150 "clr %B0" CR_TAB
6151 "clr %A0");
a3cf5992 6152
90e7678c
DC
6153 case 8:
6154 {
6155 int reg0 = true_regnum (operands[0]);
6156 int reg1 = true_regnum (operands[1]);
3454eb73 6157 *len = 4;
90e7678c 6158 if (reg0 >= reg1)
c2453253
GJL
6159 return ("mov %D0,%C1" CR_TAB
6160 "mov %C0,%B1" CR_TAB
6161 "mov %B0,%A1" CR_TAB
6162 "clr %A0");
90e7678c 6163 else
c2453253
GJL
6164 return ("clr %A0" CR_TAB
6165 "mov %B0,%A1" CR_TAB
6166 "mov %C0,%B1" CR_TAB
6167 "mov %D0,%C1");
90e7678c 6168 }
3454eb73 6169
90e7678c
DC
6170 case 16:
6171 {
6172 int reg0 = true_regnum (operands[0]);
6173 int reg1 = true_regnum (operands[1]);
90e7678c 6174 if (reg0 + 2 == reg1)
c2453253
GJL
6175 return *len = 2, ("clr %B0" CR_TAB
6176 "clr %A0");
120b24f7 6177 if (AVR_HAVE_MOVW)
c2453253
GJL
6178 return *len = 3, ("movw %C0,%A1" CR_TAB
6179 "clr %B0" CR_TAB
6180 "clr %A0");
90e7678c 6181 else
c2453253
GJL
6182 return *len = 4, ("mov %C0,%A1" CR_TAB
6183 "mov %D0,%B1" CR_TAB
6184 "clr %B0" CR_TAB
6185 "clr %A0");
90e7678c 6186 }
3454eb73 6187
90e7678c 6188 case 24:
3454eb73 6189 *len = 4;
c2453253
GJL
6190 return ("mov %D0,%A1" CR_TAB
6191 "clr %C0" CR_TAB
6192 "clr %B0" CR_TAB
6193 "clr %A0");
adcd8f77
MM
6194
6195 case 31:
6196 *len = 6;
c2453253
GJL
6197 return ("clr %D0" CR_TAB
6198 "lsr %A0" CR_TAB
6199 "ror %D0" CR_TAB
6200 "clr %C0" CR_TAB
6201 "clr %B0" CR_TAB
6202 "clr %A0");
90e7678c 6203 }
adcd8f77 6204 len = t;
90e7678c 6205 }
c2453253
GJL
6206 out_shift_with_cnt ("lsl %A0" CR_TAB
6207 "rol %B0" CR_TAB
6208 "rol %C0" CR_TAB
6209 "rol %D0", insn, operands, len, 4);
90e7678c
DC
6210 return "";
6211}
6212
6213/* 8bit arithmetic shift right ((signed char)x >> i) */
6214
5fecfd8d 6215const char *
98024b4e 6216ashrqi3_out (rtx_insn *insn, rtx operands[], int *len)
90e7678c
DC
6217{
6218 if (GET_CODE (operands[2]) == CONST_INT)
6219 {
90e7678c 6220 int k;
3454eb73 6221
90e7678c
DC
6222 if (!len)
6223 len = &k;
3454eb73 6224
90e7678c
DC
6225 switch (INTVAL (operands[2]))
6226 {
90e7678c 6227 case 1:
3454eb73 6228 *len = 1;
c2453253 6229 return "asr %0";
3454eb73 6230
90e7678c 6231 case 2:
3454eb73 6232 *len = 2;
c2453253
GJL
6233 return ("asr %0" CR_TAB
6234 "asr %0");
3454eb73 6235
90e7678c 6236 case 3:
3454eb73 6237 *len = 3;
c2453253
GJL
6238 return ("asr %0" CR_TAB
6239 "asr %0" CR_TAB
6240 "asr %0");
3454eb73 6241
90e7678c 6242 case 4:
3454eb73 6243 *len = 4;
c2453253
GJL
6244 return ("asr %0" CR_TAB
6245 "asr %0" CR_TAB
6246 "asr %0" CR_TAB
6247 "asr %0");
3454eb73
DC
6248
6249 case 5:
6250 *len = 5;
c2453253
GJL
6251 return ("asr %0" CR_TAB
6252 "asr %0" CR_TAB
6253 "asr %0" CR_TAB
6254 "asr %0" CR_TAB
6255 "asr %0");
3454eb73
DC
6256
6257 case 6:
6258 *len = 4;
c2453253
GJL
6259 return ("bst %0,6" CR_TAB
6260 "lsl %0" CR_TAB
6261 "sbc %0,%0" CR_TAB
6262 "bld %0,0");
3454eb73
DC
6263
6264 default:
a3cf5992
MM
6265 if (INTVAL (operands[2]) < 8)
6266 break;
6267
6268 /* fall through */
6269
3454eb73
DC
6270 case 7:
6271 *len = 2;
c2453253
GJL
6272 return ("lsl %0" CR_TAB
6273 "sbc %0,%0");
90e7678c
DC
6274 }
6275 }
3454eb73 6276 else if (CONSTANT_P (operands[2]))
c725bd79 6277 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3454eb73 6278
c2453253
GJL
6279 out_shift_with_cnt ("asr %0",
6280 insn, operands, len, 1);
90e7678c
DC
6281 return "";
6282}
6283
6284
6285/* 16bit arithmetic shift right ((signed short)x >> i) */
6286
5fecfd8d 6287const char *
98024b4e 6288ashrhi3_out (rtx_insn *insn, rtx operands[], int *len)
90e7678c
DC
6289{
6290 if (GET_CODE (operands[2]) == CONST_INT)
6291 {
afee2a52
MM
6292 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
6293 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
90e7678c 6294 int k;
3454eb73 6295 int *t = len;
00892272 6296
90e7678c
DC
6297 if (!len)
6298 len = &k;
3454eb73 6299
90e7678c
DC
6300 switch (INTVAL (operands[2]))
6301 {
afee2a52
MM
6302 case 4:
6303 case 5:
6304 /* XXX try to optimize this too? */
6305 break;
3454eb73 6306
afee2a52
MM
6307 case 6:
6308 if (optimize_size)
6309 break; /* scratch ? 5 : 6 */
6310 *len = 8;
c2453253
GJL
6311 return ("mov __tmp_reg__,%A0" CR_TAB
6312 "mov %A0,%B0" CR_TAB
6313 "lsl __tmp_reg__" CR_TAB
6314 "rol %A0" CR_TAB
6315 "sbc %B0,%B0" CR_TAB
6316 "lsl __tmp_reg__" CR_TAB
6317 "rol %A0" CR_TAB
6318 "rol %B0");
3454eb73 6319
adcd8f77
MM
6320 case 7:
6321 *len = 4;
c2453253
GJL
6322 return ("lsl %A0" CR_TAB
6323 "mov %A0,%B0" CR_TAB
6324 "rol %A0" CR_TAB
6325 "sbc %B0,%B0");
adcd8f77 6326
90e7678c 6327 case 8:
afee2a52
MM
6328 {
6329 int reg0 = true_regnum (operands[0]);
6330 int reg1 = true_regnum (operands[1]);
6331
6332 if (reg0 == reg1)
c2453253
GJL
6333 return *len = 3, ("mov %A0,%B0" CR_TAB
6334 "lsl %B0" CR_TAB
6335 "sbc %B0,%B0");
00892272 6336 else
c2453253
GJL
6337 return *len = 4, ("mov %A0,%B1" CR_TAB
6338 "clr %B0" CR_TAB
6339 "sbrc %A0,7" CR_TAB
6340 "dec %B0");
afee2a52 6341 }
3454eb73 6342
adcd8f77
MM
6343 case 9:
6344 *len = 4;
c2453253
GJL
6345 return ("mov %A0,%B0" CR_TAB
6346 "lsl %B0" CR_TAB
6347 "sbc %B0,%B0" CR_TAB
6348 "asr %A0");
adcd8f77
MM
6349
6350 case 10:
6351 *len = 5;
c2453253
GJL
6352 return ("mov %A0,%B0" CR_TAB
6353 "lsl %B0" CR_TAB
6354 "sbc %B0,%B0" CR_TAB
6355 "asr %A0" CR_TAB
6356 "asr %A0");
adcd8f77
MM
6357
6358 case 11:
dd6d1f8c 6359 if (AVR_HAVE_MUL && ldi_ok)
adcd8f77
MM
6360 {
6361 *len = 5;
c2453253
GJL
6362 return ("ldi %A0,0x20" CR_TAB
6363 "muls %B0,%A0" CR_TAB
6364 "mov %A0,r1" CR_TAB
6365 "sbc %B0,%B0" CR_TAB
6366 "clr __zero_reg__");
adcd8f77 6367 }
afee2a52
MM
6368 if (optimize_size && scratch)
6369 break; /* 5 */
6370 *len = 6;
c2453253
GJL
6371 return ("mov %A0,%B0" CR_TAB
6372 "lsl %B0" CR_TAB
6373 "sbc %B0,%B0" CR_TAB
6374 "asr %A0" CR_TAB
6375 "asr %A0" CR_TAB
6376 "asr %A0");
adcd8f77
MM
6377
6378 case 12:
dd6d1f8c 6379 if (AVR_HAVE_MUL && ldi_ok)
adcd8f77
MM
6380 {
6381 *len = 5;
c2453253
GJL
6382 return ("ldi %A0,0x10" CR_TAB
6383 "muls %B0,%A0" CR_TAB
6384 "mov %A0,r1" CR_TAB
6385 "sbc %B0,%B0" CR_TAB
6386 "clr __zero_reg__");
adcd8f77 6387 }
afee2a52
MM
6388 if (optimize_size && scratch)
6389 break; /* 5 */
6390 *len = 7;
c2453253
GJL
6391 return ("mov %A0,%B0" CR_TAB
6392 "lsl %B0" CR_TAB
6393 "sbc %B0,%B0" CR_TAB
6394 "asr %A0" CR_TAB
6395 "asr %A0" CR_TAB
6396 "asr %A0" CR_TAB
6397 "asr %A0");
adcd8f77
MM
6398
6399 case 13:
dd6d1f8c 6400 if (AVR_HAVE_MUL && ldi_ok)
adcd8f77
MM
6401 {
6402 *len = 5;
c2453253
GJL
6403 return ("ldi %A0,0x08" CR_TAB
6404 "muls %B0,%A0" CR_TAB
6405 "mov %A0,r1" CR_TAB
6406 "sbc %B0,%B0" CR_TAB
6407 "clr __zero_reg__");
adcd8f77 6408 }
afee2a52
MM
6409 if (optimize_size)
6410 break; /* scratch ? 5 : 7 */
6411 *len = 8;
c2453253
GJL
6412 return ("mov %A0,%B0" CR_TAB
6413 "lsl %B0" CR_TAB
6414 "sbc %B0,%B0" CR_TAB
6415 "asr %A0" CR_TAB
6416 "asr %A0" CR_TAB
6417 "asr %A0" CR_TAB
6418 "asr %A0" CR_TAB
6419 "asr %A0");
adcd8f77
MM
6420
6421 case 14:
6422 *len = 5;
c2453253
GJL
6423 return ("lsl %B0" CR_TAB
6424 "sbc %A0,%A0" CR_TAB
6425 "lsl %B0" CR_TAB
6426 "mov %B0,%A0" CR_TAB
6427 "rol %A0");
adcd8f77 6428
a3cf5992
MM
6429 default:
6430 if (INTVAL (operands[2]) < 16)
6431 break;
6432
6433 /* fall through */
6434
28e801e2 6435 case 15:
c2453253
GJL
6436 return *len = 3, ("lsl %B0" CR_TAB
6437 "sbc %A0,%A0" CR_TAB
6438 "mov %B0,%A0");
90e7678c 6439 }
adcd8f77 6440 len = t;
90e7678c 6441 }
c2453253
GJL
6442 out_shift_with_cnt ("asr %B0" CR_TAB
6443 "ror %A0", insn, operands, len, 2);
90e7678c
DC
6444 return "";
6445}
6446
6447
e4fe948a
GJL
6448/* 24-bit arithmetic shift right */
6449
6450const char*
98024b4e 6451avr_out_ashrpsi3 (rtx_insn *insn, rtx *op, int *plen)
e4fe948a
GJL
6452{
6453 int dest = REGNO (op[0]);
6454 int src = REGNO (op[1]);
6455
6456 if (CONST_INT_P (op[2]))
6457 {
6458 if (plen)
6459 *plen = 0;
00892272 6460
e4fe948a
GJL
6461 switch (INTVAL (op[2]))
6462 {
6463 case 8:
6464 if (dest <= src)
6465 return avr_asm_len ("mov %A0,%B1" CR_TAB
6466 "mov %B0,%C1" CR_TAB
6467 "clr %C0" CR_TAB
6468 "sbrc %B0,7" CR_TAB
6469 "dec %C0", op, plen, 5);
6470 else
6471 return avr_asm_len ("clr %C0" CR_TAB
6472 "sbrc %C1,7" CR_TAB
6473 "dec %C0" CR_TAB
6474 "mov %B0,%C1" CR_TAB
6475 "mov %A0,%B1", op, plen, 5);
00892272 6476
e4fe948a
GJL
6477 case 16:
6478 if (dest != src + 2)
6479 avr_asm_len ("mov %A0,%C1", op, plen, 1);
00892272 6480
e4fe948a
GJL
6481 return avr_asm_len ("clr %B0" CR_TAB
6482 "sbrc %A0,7" CR_TAB
6483 "com %B0" CR_TAB
6484 "mov %C0,%B0", op, plen, 4);
6485
6486 default:
6487 if (INTVAL (op[2]) < 24)
6488 break;
6489
6490 /* fall through */
6491
9ecd3a64 6492 case 23:
e4fe948a
GJL
6493 return avr_asm_len ("lsl %C0" CR_TAB
6494 "sbc %A0,%A0" CR_TAB
6495 "mov %B0,%A0" CR_TAB
6496 "mov %C0,%A0", op, plen, 4);
6497 } /* switch */
6498 }
00892272 6499
e4fe948a
GJL
6500 out_shift_with_cnt ("asr %C0" CR_TAB
6501 "ror %B0" CR_TAB
6502 "ror %A0", insn, op, plen, 3);
6503 return "";
6504}
6505
6506
00892272 6507/* 32-bit arithmetic shift right ((signed long)x >> i) */
90e7678c 6508
5fecfd8d 6509const char *
98024b4e 6510ashrsi3_out (rtx_insn *insn, rtx operands[], int *len)
90e7678c
DC
6511{
6512 if (GET_CODE (operands[2]) == CONST_INT)
6513 {
6514 int k;
6515 int *t = len;
00892272 6516
90e7678c
DC
6517 if (!len)
6518 len = &k;
00892272 6519
90e7678c
DC
6520 switch (INTVAL (operands[2]))
6521 {
90e7678c
DC
6522 case 8:
6523 {
6524 int reg0 = true_regnum (operands[0]);
6525 int reg1 = true_regnum (operands[1]);
6526 *len=6;
6527 if (reg0 <= reg1)
c2453253
GJL
6528 return ("mov %A0,%B1" CR_TAB
6529 "mov %B0,%C1" CR_TAB
6530 "mov %C0,%D1" CR_TAB
6531 "clr %D0" CR_TAB
6532 "sbrc %C0,7" CR_TAB
6533 "dec %D0");
90e7678c 6534 else
c2453253
GJL
6535 return ("clr %D0" CR_TAB
6536 "sbrc %D1,7" CR_TAB
6537 "dec %D0" CR_TAB
6538 "mov %C0,%D1" CR_TAB
6539 "mov %B0,%C1" CR_TAB
6540 "mov %A0,%B1");
90e7678c 6541 }
00892272 6542
90e7678c
DC
6543 case 16:
6544 {
6545 int reg0 = true_regnum (operands[0]);
6546 int reg1 = true_regnum (operands[1]);
00892272 6547
120b24f7 6548 if (reg0 == reg1 + 2)
c2453253
GJL
6549 return *len = 4, ("clr %D0" CR_TAB
6550 "sbrc %B0,7" CR_TAB
6551 "com %D0" CR_TAB
6552 "mov %C0,%D0");
120b24f7 6553 if (AVR_HAVE_MOVW)
c2453253
GJL
6554 return *len = 5, ("movw %A0,%C1" CR_TAB
6555 "clr %D0" CR_TAB
6556 "sbrc %B0,7" CR_TAB
6557 "com %D0" CR_TAB
6558 "mov %C0,%D0");
00892272 6559 else
c2453253
GJL
6560 return *len = 6, ("mov %B0,%D1" CR_TAB
6561 "mov %A0,%C1" CR_TAB
6562 "clr %D0" CR_TAB
6563 "sbrc %B0,7" CR_TAB
6564 "com %D0" CR_TAB
6565 "mov %C0,%D0");
90e7678c 6566 }
3454eb73 6567
90e7678c 6568 case 24:
c2453253
GJL
6569 return *len = 6, ("mov %A0,%D1" CR_TAB
6570 "clr %D0" CR_TAB
6571 "sbrc %A0,7" CR_TAB
6572 "com %D0" CR_TAB
6573 "mov %B0,%D0" CR_TAB
6574 "mov %C0,%D0");
adcd8f77 6575
a3cf5992
MM
6576 default:
6577 if (INTVAL (operands[2]) < 32)
6578 break;
6579
6580 /* fall through */
6581
adcd8f77 6582 case 31:
4301ec4f 6583 if (AVR_HAVE_MOVW)
c2453253
GJL
6584 return *len = 4, ("lsl %D0" CR_TAB
6585 "sbc %A0,%A0" CR_TAB
6586 "mov %B0,%A0" CR_TAB
6587 "movw %C0,%A0");
adcd8f77 6588 else
c2453253
GJL
6589 return *len = 5, ("lsl %D0" CR_TAB
6590 "sbc %A0,%A0" CR_TAB
6591 "mov %B0,%A0" CR_TAB
6592 "mov %C0,%A0" CR_TAB
6593 "mov %D0,%A0");
90e7678c 6594 }
adcd8f77 6595 len = t;
90e7678c 6596 }
c2453253
GJL
6597 out_shift_with_cnt ("asr %D0" CR_TAB
6598 "ror %C0" CR_TAB
6599 "ror %B0" CR_TAB
6600 "ror %A0", insn, operands, len, 4);
90e7678c
DC
6601 return "";
6602}
6603
00892272 6604/* 8-bit logic shift right ((unsigned char)x >> i) */
90e7678c 6605
5fecfd8d 6606const char *
98024b4e 6607lshrqi3_out (rtx_insn *insn, rtx operands[], int *len)
90e7678c
DC
6608{
6609 if (GET_CODE (operands[2]) == CONST_INT)
6610 {
6611 int k;
3454eb73 6612
90e7678c
DC
6613 if (!len)
6614 len = &k;
00892272 6615
90e7678c
DC
6616 switch (INTVAL (operands[2]))
6617 {
3454eb73 6618 default:
a3cf5992
MM
6619 if (INTVAL (operands[2]) < 8)
6620 break;
6621
3454eb73 6622 *len = 1;
c2453253 6623 return "clr %0";
3454eb73 6624
90e7678c 6625 case 1:
3454eb73 6626 *len = 1;
c2453253 6627 return "lsr %0";
3454eb73 6628
90e7678c 6629 case 2:
3454eb73 6630 *len = 2;
c2453253
GJL
6631 return ("lsr %0" CR_TAB
6632 "lsr %0");
90e7678c 6633 case 3:
3454eb73 6634 *len = 3;
c2453253
GJL
6635 return ("lsr %0" CR_TAB
6636 "lsr %0" CR_TAB
6637 "lsr %0");
00892272 6638
90e7678c 6639 case 4:
c4984bad 6640 if (test_hard_reg_class (LD_REGS, operands[0]))
90e7678c
DC
6641 {
6642 *len=2;
c2453253
GJL
6643 return ("swap %0" CR_TAB
6644 "andi %0,0x0f");
90e7678c 6645 }
3454eb73 6646 *len = 4;
c2453253
GJL
6647 return ("lsr %0" CR_TAB
6648 "lsr %0" CR_TAB
6649 "lsr %0" CR_TAB
6650 "lsr %0");
00892272 6651
90e7678c 6652 case 5:
c4984bad 6653 if (test_hard_reg_class (LD_REGS, operands[0]))
90e7678c 6654 {
3454eb73 6655 *len = 3;
c2453253
GJL
6656 return ("swap %0" CR_TAB
6657 "lsr %0" CR_TAB
6658 "andi %0,0x7");
90e7678c 6659 }
3454eb73 6660 *len = 5;
c2453253
GJL
6661 return ("lsr %0" CR_TAB
6662 "lsr %0" CR_TAB
6663 "lsr %0" CR_TAB
6664 "lsr %0" CR_TAB
6665 "lsr %0");
00892272 6666
90e7678c 6667 case 6:
c4984bad 6668 if (test_hard_reg_class (LD_REGS, operands[0]))
90e7678c 6669 {
3454eb73 6670 *len = 4;
c2453253
GJL
6671 return ("swap %0" CR_TAB
6672 "lsr %0" CR_TAB
6673 "lsr %0" CR_TAB
6674 "andi %0,0x3");
90e7678c 6675 }
3454eb73 6676 *len = 6;
c2453253
GJL
6677 return ("lsr %0" CR_TAB
6678 "lsr %0" CR_TAB
6679 "lsr %0" CR_TAB
6680 "lsr %0" CR_TAB
6681 "lsr %0" CR_TAB
6682 "lsr %0");
00892272 6683
90e7678c 6684 case 7:
3454eb73 6685 *len = 3;
c2453253
GJL
6686 return ("rol %0" CR_TAB
6687 "clr %0" CR_TAB
6688 "rol %0");
90e7678c
DC
6689 }
6690 }
3454eb73 6691 else if (CONSTANT_P (operands[2]))
c725bd79 6692 fatal_insn ("internal compiler error. Incorrect shift:", insn);
00892272 6693
c2453253
GJL
6694 out_shift_with_cnt ("lsr %0",
6695 insn, operands, len, 1);
90e7678c
DC
6696 return "";
6697}
6698
00892272 6699/* 16-bit logic shift right ((unsigned short)x >> i) */
90e7678c 6700
5fecfd8d 6701const char *
98024b4e 6702lshrhi3_out (rtx_insn *insn, rtx operands[], int *len)
90e7678c
DC
6703{
6704 if (GET_CODE (operands[2]) == CONST_INT)
6705 {
afee2a52
MM
6706 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
6707 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
90e7678c 6708 int k;
3454eb73 6709 int *t = len;
afee2a52 6710
90e7678c
DC
6711 if (!len)
6712 len = &k;
00892272 6713
90e7678c
DC
6714 switch (INTVAL (operands[2]))
6715 {
a3cf5992
MM
6716 default:
6717 if (INTVAL (operands[2]) < 16)
6718 break;
6719
6720 *len = 2;
c2453253
GJL
6721 return ("clr %B0" CR_TAB
6722 "clr %A0");
a3cf5992 6723
afee2a52
MM
6724 case 4:
6725 if (optimize_size && scratch)
6726 break; /* 5 */
6727 if (ldi_ok)
6728 {
6729 *len = 6;
c2453253
GJL
6730 return ("swap %B0" CR_TAB
6731 "swap %A0" CR_TAB
6732 "andi %A0,0x0f" CR_TAB
6733 "eor %A0,%B0" CR_TAB
6734 "andi %B0,0x0f" CR_TAB
6735 "eor %A0,%B0");
afee2a52
MM
6736 }
6737 if (scratch)
6738 {
6739 *len = 7;
c2453253
GJL
6740 return ("swap %B0" CR_TAB
6741 "swap %A0" CR_TAB
6742 "ldi %3,0x0f" CR_TAB
5a82ecd9 6743 "and %A0,%3" CR_TAB
c2453253 6744 "eor %A0,%B0" CR_TAB
5a82ecd9 6745 "and %B0,%3" CR_TAB
c2453253 6746 "eor %A0,%B0");
afee2a52
MM
6747 }
6748 break; /* optimize_size ? 6 : 8 */
6749
6750 case 5:
6751 if (optimize_size)
6752 break; /* scratch ? 5 : 6 */
6753 if (ldi_ok)
6754 {
6755 *len = 8;
c2453253
GJL
6756 return ("lsr %B0" CR_TAB
6757 "ror %A0" CR_TAB
6758 "swap %B0" CR_TAB
6759 "swap %A0" CR_TAB
6760 "andi %A0,0x0f" CR_TAB
6761 "eor %A0,%B0" CR_TAB
6762 "andi %B0,0x0f" CR_TAB
6763 "eor %A0,%B0");
afee2a52
MM
6764 }
6765 if (scratch)
6766 {
6767 *len = 9;
c2453253
GJL
6768 return ("lsr %B0" CR_TAB
6769 "ror %A0" CR_TAB
6770 "swap %B0" CR_TAB
6771 "swap %A0" CR_TAB
6772 "ldi %3,0x0f" CR_TAB
5a82ecd9 6773 "and %A0,%3" CR_TAB
c2453253 6774 "eor %A0,%B0" CR_TAB
5a82ecd9 6775 "and %B0,%3" CR_TAB
c2453253 6776 "eor %A0,%B0");
afee2a52
MM
6777 }
6778 break; /* 10 */
6779
6780 case 6:
6781 if (optimize_size)
6782 break; /* scratch ? 5 : 6 */
6783 *len = 9;
c2453253
GJL
6784 return ("clr __tmp_reg__" CR_TAB
6785 "lsl %A0" CR_TAB
6786 "rol %B0" CR_TAB
6787 "rol __tmp_reg__" CR_TAB
6788 "lsl %A0" CR_TAB
6789 "rol %B0" CR_TAB
6790 "rol __tmp_reg__" CR_TAB
6791 "mov %A0,%B0" CR_TAB
6792 "mov %B0,__tmp_reg__");
adcd8f77
MM
6793
6794 case 7:
6795 *len = 5;
c2453253
GJL
6796 return ("lsl %A0" CR_TAB
6797 "mov %A0,%B0" CR_TAB
6798 "rol %A0" CR_TAB
6799 "sbc %B0,%B0" CR_TAB
6800 "neg %B0");
adcd8f77 6801
90e7678c 6802 case 8:
c2453253
GJL
6803 return *len = 2, ("mov %A0,%B1" CR_TAB
6804 "clr %B0");
adcd8f77
MM
6805
6806 case 9:
6807 *len = 3;
c2453253
GJL
6808 return ("mov %A0,%B0" CR_TAB
6809 "clr %B0" CR_TAB
6810 "lsr %A0");
adcd8f77
MM
6811
6812 case 10:
6813 *len = 4;
c2453253
GJL
6814 return ("mov %A0,%B0" CR_TAB
6815 "clr %B0" CR_TAB
6816 "lsr %A0" CR_TAB
6817 "lsr %A0");
adcd8f77
MM
6818
6819 case 11:
6820 *len = 5;
c2453253
GJL
6821 return ("mov %A0,%B0" CR_TAB
6822 "clr %B0" CR_TAB
6823 "lsr %A0" CR_TAB
6824 "lsr %A0" CR_TAB
6825 "lsr %A0");
adcd8f77
MM
6826
6827 case 12:
afee2a52 6828 if (ldi_ok)
adcd8f77
MM
6829 {
6830 *len = 4;
c2453253
GJL
6831 return ("mov %A0,%B0" CR_TAB
6832 "clr %B0" CR_TAB
6833 "swap %A0" CR_TAB
6834 "andi %A0,0x0f");
adcd8f77 6835 }
afee2a52
MM
6836 if (scratch)
6837 {
6838 *len = 5;
c2453253
GJL
6839 return ("mov %A0,%B0" CR_TAB
6840 "clr %B0" CR_TAB
6841 "swap %A0" CR_TAB
6842 "ldi %3,0x0f" CR_TAB
5a82ecd9 6843 "and %A0,%3");
afee2a52
MM
6844 }
6845 *len = 6;
c2453253
GJL
6846 return ("mov %A0,%B0" CR_TAB
6847 "clr %B0" CR_TAB
6848 "lsr %A0" CR_TAB
6849 "lsr %A0" CR_TAB
6850 "lsr %A0" CR_TAB
6851 "lsr %A0");
adcd8f77
MM
6852
6853 case 13:
afee2a52 6854 if (ldi_ok)
adcd8f77
MM
6855 {
6856 *len = 5;
c2453253
GJL
6857 return ("mov %A0,%B0" CR_TAB
6858 "clr %B0" CR_TAB
6859 "swap %A0" CR_TAB
6860 "lsr %A0" CR_TAB
6861 "andi %A0,0x07");
adcd8f77 6862 }
dd6d1f8c 6863 if (AVR_HAVE_MUL && scratch)
adcd8f77
MM
6864 {
6865 *len = 5;
c2453253
GJL
6866 return ("ldi %3,0x08" CR_TAB
6867 "mul %B0,%3" CR_TAB
6868 "mov %A0,r1" CR_TAB
6869 "clr %B0" CR_TAB
6870 "clr __zero_reg__");
adcd8f77 6871 }
afee2a52
MM
6872 if (optimize_size && scratch)
6873 break; /* 5 */
6874 if (scratch)
6875 {
6876 *len = 6;
c2453253
GJL
6877 return ("mov %A0,%B0" CR_TAB
6878 "clr %B0" CR_TAB
6879 "swap %A0" CR_TAB
6880 "lsr %A0" CR_TAB
6881 "ldi %3,0x07" CR_TAB
5a82ecd9 6882 "and %A0,%3");
afee2a52 6883 }
dd6d1f8c 6884 if (AVR_HAVE_MUL)
afee2a52
MM
6885 {
6886 *len = 6;
6887 return ("set" CR_TAB
c2453253
GJL
6888 "bld r1,3" CR_TAB
6889 "mul %B0,r1" CR_TAB
6890 "mov %A0,r1" CR_TAB
6891 "clr %B0" CR_TAB
6892 "clr __zero_reg__");
afee2a52
MM
6893 }
6894 *len = 7;
c2453253
GJL
6895 return ("mov %A0,%B0" CR_TAB
6896 "clr %B0" CR_TAB
6897 "lsr %A0" CR_TAB
6898 "lsr %A0" CR_TAB
6899 "lsr %A0" CR_TAB
6900 "lsr %A0" CR_TAB
6901 "lsr %A0");
adcd8f77
MM
6902
6903 case 14:
dd6d1f8c 6904 if (AVR_HAVE_MUL && ldi_ok)
afee2a52
MM
6905 {
6906 *len = 5;
c2453253
GJL
6907 return ("ldi %A0,0x04" CR_TAB
6908 "mul %B0,%A0" CR_TAB
6909 "mov %A0,r1" CR_TAB
6910 "clr %B0" CR_TAB
6911 "clr __zero_reg__");
afee2a52 6912 }
dd6d1f8c 6913 if (AVR_HAVE_MUL && scratch)
adcd8f77
MM
6914 {
6915 *len = 5;
c2453253
GJL
6916 return ("ldi %3,0x04" CR_TAB
6917 "mul %B0,%3" CR_TAB
6918 "mov %A0,r1" CR_TAB
6919 "clr %B0" CR_TAB
6920 "clr __zero_reg__");
adcd8f77 6921 }
afee2a52
MM
6922 if (optimize_size && ldi_ok)
6923 {
6924 *len = 5;
c2453253
GJL
6925 return ("mov %A0,%B0" CR_TAB
6926 "ldi %B0,6" "\n1:\t"
6927 "lsr %A0" CR_TAB
6928 "dec %B0" CR_TAB
6929 "brne 1b");
afee2a52
MM
6930 }
6931 if (optimize_size && scratch)
6932 break; /* 5 */
6933 *len = 6;
c2453253
GJL
6934 return ("clr %A0" CR_TAB
6935 "lsl %B0" CR_TAB
6936 "rol %A0" CR_TAB
6937 "lsl %B0" CR_TAB
6938 "rol %A0" CR_TAB
6939 "clr %B0");
adcd8f77 6940
28e801e2 6941 case 15:
3454eb73 6942 *len = 4;
c2453253
GJL
6943 return ("clr %A0" CR_TAB
6944 "lsl %B0" CR_TAB
6945 "rol %A0" CR_TAB
6946 "clr %B0");
90e7678c 6947 }
adcd8f77 6948 len = t;
90e7678c 6949 }
c2453253
GJL
6950 out_shift_with_cnt ("lsr %B0" CR_TAB
6951 "ror %A0", insn, operands, len, 2);
90e7678c
DC
6952 return "";
6953}
6954
e4fe948a
GJL
6955
6956/* 24-bit logic shift right */
6957
6958const char*
98024b4e 6959avr_out_lshrpsi3 (rtx_insn *insn, rtx *op, int *plen)
e4fe948a
GJL
6960{
6961 int dest = REGNO (op[0]);
6962 int src = REGNO (op[1]);
6963
6964 if (CONST_INT_P (op[2]))
6965 {
6966 if (plen)
6967 *plen = 0;
00892272 6968
e4fe948a
GJL
6969 switch (INTVAL (op[2]))
6970 {
6971 case 8:
6972 if (dest <= src)
6973 return avr_asm_len ("mov %A0,%B1" CR_TAB
6974 "mov %B0,%C1" CR_TAB
6975 "clr %C0", op, plen, 3);
6976 else
6977 return avr_asm_len ("clr %C0" CR_TAB
6978 "mov %B0,%C1" CR_TAB
6979 "mov %A0,%B1", op, plen, 3);
00892272 6980
e4fe948a
GJL
6981 case 16:
6982 if (dest != src + 2)
6983 avr_asm_len ("mov %A0,%C1", op, plen, 1);
00892272 6984
e4fe948a
GJL
6985 return avr_asm_len ("clr %B0" CR_TAB
6986 "clr %C0", op, plen, 2);
6987
6988 default:
6989 if (INTVAL (op[2]) < 24)
6990 break;
6991
6992 /* fall through */
6993
6994 case 23:
6995 return avr_asm_len ("clr %A0" CR_TAB
6996 "sbrc %C0,7" CR_TAB
6997 "inc %A0" CR_TAB
6998 "clr %B0" CR_TAB
6999 "clr %C0", op, plen, 5);
7000 } /* switch */
7001 }
00892272 7002
e4fe948a
GJL
7003 out_shift_with_cnt ("lsr %C0" CR_TAB
7004 "ror %B0" CR_TAB
7005 "ror %A0", insn, op, plen, 3);
7006 return "";
7007}
7008
7009
00892272 7010/* 32-bit logic shift right ((unsigned int)x >> i) */
90e7678c 7011
5fecfd8d 7012const char *
98024b4e 7013lshrsi3_out (rtx_insn *insn, rtx operands[], int *len)
90e7678c
DC
7014{
7015 if (GET_CODE (operands[2]) == CONST_INT)
7016 {
7017 int k;
3454eb73 7018 int *t = len;
00892272 7019
90e7678c
DC
7020 if (!len)
7021 len = &k;
00892272 7022
90e7678c
DC
7023 switch (INTVAL (operands[2]))
7024 {
a3cf5992
MM
7025 default:
7026 if (INTVAL (operands[2]) < 32)
7027 break;
7028
4301ec4f 7029 if (AVR_HAVE_MOVW)
c2453253
GJL
7030 return *len = 3, ("clr %D0" CR_TAB
7031 "clr %C0" CR_TAB
7032 "movw %A0,%C0");
a3cf5992 7033 *len = 4;
c2453253
GJL
7034 return ("clr %D0" CR_TAB
7035 "clr %C0" CR_TAB
7036 "clr %B0" CR_TAB
7037 "clr %A0");
a3cf5992 7038
90e7678c
DC
7039 case 8:
7040 {
7041 int reg0 = true_regnum (operands[0]);
7042 int reg1 = true_regnum (operands[1]);
3454eb73 7043 *len = 4;
90e7678c 7044 if (reg0 <= reg1)
c2453253
GJL
7045 return ("mov %A0,%B1" CR_TAB
7046 "mov %B0,%C1" CR_TAB
7047 "mov %C0,%D1" CR_TAB
7048 "clr %D0");
90e7678c 7049 else
c2453253
GJL
7050 return ("clr %D0" CR_TAB
7051 "mov %C0,%D1" CR_TAB
7052 "mov %B0,%C1" CR_TAB
00892272 7053 "mov %A0,%B1");
90e7678c 7054 }
00892272 7055
90e7678c
DC
7056 case 16:
7057 {
7058 int reg0 = true_regnum (operands[0]);
7059 int reg1 = true_regnum (operands[1]);
120b24f7
AS
7060
7061 if (reg0 == reg1 + 2)
c2453253
GJL
7062 return *len = 2, ("clr %C0" CR_TAB
7063 "clr %D0");
120b24f7 7064 if (AVR_HAVE_MOVW)
c2453253
GJL
7065 return *len = 3, ("movw %A0,%C1" CR_TAB
7066 "clr %C0" CR_TAB
7067 "clr %D0");
90e7678c 7068 else
c2453253
GJL
7069 return *len = 4, ("mov %B0,%D1" CR_TAB
7070 "mov %A0,%C1" CR_TAB
7071 "clr %C0" CR_TAB
7072 "clr %D0");
90e7678c 7073 }
00892272 7074
90e7678c 7075 case 24:
c2453253
GJL
7076 return *len = 4, ("mov %A0,%D1" CR_TAB
7077 "clr %B0" CR_TAB
7078 "clr %C0" CR_TAB
7079 "clr %D0");
adcd8f77
MM
7080
7081 case 31:
7082 *len = 6;
c2453253
GJL
7083 return ("clr %A0" CR_TAB
7084 "sbrc %D0,7" CR_TAB
7085 "inc %A0" CR_TAB
7086 "clr %B0" CR_TAB
7087 "clr %C0" CR_TAB
7088 "clr %D0");
90e7678c 7089 }
adcd8f77 7090 len = t;
90e7678c 7091 }
c2453253
GJL
7092 out_shift_with_cnt ("lsr %D0" CR_TAB
7093 "ror %C0" CR_TAB
7094 "ror %B0" CR_TAB
7095 "ror %A0", insn, operands, len, 4);
90e7678c
DC
7096 return "";
7097}
7098
6ebe2d6c 7099
51526856
GJL
7100/* Output addition of register XOP[0] and compile time constant XOP[2].
7101 CODE == PLUS: perform addition by using ADD instructions or
7102 CODE == MINUS: perform addition by using SUB instructions:
00892272 7103
59024515 7104 XOP[0] = XOP[0] + XOP[2]
00892272 7105
51526856 7106 Or perform addition/subtraction with register XOP[2] depending on CODE:
00892272 7107
51526856 7108 XOP[0] = XOP[0] +/- XOP[2]
59024515 7109
51526856
GJL
7110 If PLEN == NULL, print assembler instructions to perform the operation;
7111 otherwise, set *PLEN to the length of the instruction sequence (in words)
7112 printed with PLEN == NULL. XOP[3] is an 8-bit scratch register or NULL_RTX.
7113 Set *PCC to effect on cc0 according to respective CC_* insn attribute.
7114
7115 CODE_SAT == UNKNOWN: Perform ordinary, non-saturating operation.
7116 CODE_SAT != UNKNOWN: Perform operation and saturate according to CODE_SAT.
7117 If CODE_SAT != UNKNOWN then SIGN contains the sign of the summand resp.
7118 the subtrahend in the original insn, provided it is a compile time constant.
7119 In all other cases, SIGN is 0.
7120
02371798
GJL
7121 If OUT_LABEL is true, print the final 0: label which is needed for
7122 saturated addition / subtraction. The only case where OUT_LABEL = false
7123 is useful is for saturated addition / subtraction performed during
7124 fixed-point rounding, cf. `avr_out_round'. */
59024515
GJL
7125
7126static void
51526856 7127avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc,
02371798 7128 enum rtx_code code_sat, int sign, bool out_label)
59024515
GJL
7129{
7130 /* MODE of the operation. */
ef4bddc2 7131 machine_mode mode = GET_MODE (xop[0]);
59024515 7132
e55e4056 7133 /* INT_MODE of the same size. */
ef4bddc2 7134 machine_mode imode = int_mode_for_mode (mode);
e55e4056 7135
59024515
GJL
7136 /* Number of bytes to operate on. */
7137 int i, n_bytes = GET_MODE_SIZE (mode);
7138
7139 /* Value (0..0xff) held in clobber register op[3] or -1 if unknown. */
7140 int clobber_val = -1;
7141
7142 /* op[0]: 8-bit destination register
7143 op[1]: 8-bit const int
7144 op[2]: 8-bit scratch register */
7145 rtx op[3];
7146
7147 /* Started the operation? Before starting the operation we may skip
7148 adding 0. This is no more true after the operation started because
7149 carry must be taken into account. */
7150 bool started = false;
7151
7152 /* Value to add. There are two ways to add VAL: R += VAL and R -= -VAL. */
7153 rtx xval = xop[2];
7154
51526856
GJL
7155 /* Output a BRVC instruction. Only needed with saturation. */
7156 bool out_brvc = true;
7157
7158 if (plen)
7159 *plen = 0;
7160
7161 if (REG_P (xop[2]))
7162 {
b8469805 7163 *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_CLOBBER;
51526856
GJL
7164
7165 for (i = 0; i < n_bytes; i++)
7166 {
7167 /* We operate byte-wise on the destination. */
7168 op[0] = simplify_gen_subreg (QImode, xop[0], mode, i);
7169 op[1] = simplify_gen_subreg (QImode, xop[2], mode, i);
7170
7171 if (i == 0)
7172 avr_asm_len (code == PLUS ? "add %0,%1" : "sub %0,%1",
7173 op, plen, 1);
7174 else
7175 avr_asm_len (code == PLUS ? "adc %0,%1" : "sbc %0,%1",
7176 op, plen, 1);
7177 }
7178
7179 if (reg_overlap_mentioned_p (xop[0], xop[2]))
7180 {
7181 gcc_assert (REGNO (xop[0]) == REGNO (xop[2]));
00892272 7182
51526856
GJL
7183 if (MINUS == code)
7184 return;
7185 }
7186
7187 goto saturate;
7188 }
7189
2f47b8d3
GJL
7190 /* Except in the case of ADIW with 16-bit register (see below)
7191 addition does not set cc0 in a usable way. */
00892272 7192
05058b6e
GJL
7193 *pcc = (MINUS == code) ? CC_SET_CZN : CC_CLOBBER;
7194
e55e4056
GJL
7195 if (CONST_FIXED_P (xval))
7196 xval = avr_to_int_mode (xval);
7197
51526856 7198 /* Adding/Subtracting zero is a no-op. */
00892272 7199
51526856
GJL
7200 if (xval == const0_rtx)
7201 {
7202 *pcc = CC_NONE;
7203 return;
7204 }
7205
59024515 7206 if (MINUS == code)
e55e4056 7207 xval = simplify_unary_operation (NEG, imode, xval, imode);
59024515
GJL
7208
7209 op[2] = xop[3];
7210
51526856
GJL
7211 if (SS_PLUS == code_sat && MINUS == code
7212 && sign < 0
7213 && 0x80 == (INTVAL (simplify_gen_subreg (QImode, xval, imode, n_bytes-1))
7214 & GET_MODE_MASK (QImode)))
7215 {
7216 /* We compute x + 0x80 by means of SUB instructions. We negated the
7217 constant subtrahend above and are left with x - (-128) so that we
7218 need something like SUBI r,128 which does not exist because SUBI sets
7219 V according to the sign of the subtrahend. Notice the only case
7220 where this must be done is when NEG overflowed in case [2s] because
7221 the V computation needs the right sign of the subtrahend. */
00892272 7222
51526856
GJL
7223 rtx msb = simplify_gen_subreg (QImode, xop[0], mode, n_bytes-1);
7224
7225 avr_asm_len ("subi %0,128" CR_TAB
7226 "brmi 0f", &msb, plen, 2);
7227 out_brvc = false;
7228
7229 goto saturate;
7230 }
59024515
GJL
7231
7232 for (i = 0; i < n_bytes; i++)
7233 {
7234 /* We operate byte-wise on the destination. */
7235 rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
e55e4056 7236 rtx xval8 = simplify_gen_subreg (QImode, xval, imode, i);
59024515
GJL
7237
7238 /* 8-bit value to operate with this byte. */
7239 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
7240
7241 /* Registers R16..R31 can operate with immediate. */
7242 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
7243
7244 op[0] = reg8;
5436efaa 7245 op[1] = gen_int_mode (val8, QImode);
05058b6e
GJL
7246
7247 /* To get usable cc0 no low-bytes must have been skipped. */
00892272 7248
05058b6e
GJL
7249 if (i && !started)
7250 *pcc = CC_CLOBBER;
00892272 7251
e4fe948a
GJL
7252 if (!started
7253 && i % 2 == 0
7254 && i + 2 <= n_bytes
59024515
GJL
7255 && test_hard_reg_class (ADDW_REGS, reg8))
7256 {
e55e4056 7257 rtx xval16 = simplify_gen_subreg (HImode, xval, imode, i);
59024515
GJL
7258 unsigned int val16 = UINTVAL (xval16) & GET_MODE_MASK (HImode);
7259
7260 /* Registers R24, X, Y, Z can use ADIW/SBIW with constants < 64
7261 i.e. operate word-wise. */
7262
7263 if (val16 < 64)
7264 {
7265 if (val16 != 0)
7266 {
7267 started = true;
7268 avr_asm_len (code == PLUS ? "adiw %0,%1" : "sbiw %0,%1",
7269 op, plen, 1);
2f47b8d3
GJL
7270
7271 if (n_bytes == 2 && PLUS == code)
b8469805 7272 *pcc = CC_SET_CZN;
59024515
GJL
7273 }
7274
7275 i++;
7276 continue;
7277 }
7278 }
7279
7280 if (val8 == 0)
7281 {
7282 if (started)
7283 avr_asm_len (code == PLUS
7284 ? "adc %0,__zero_reg__" : "sbc %0,__zero_reg__",
7285 op, plen, 1);
7286 continue;
7287 }
2f47b8d3 7288 else if ((val8 == 1 || val8 == 0xff)
51526856 7289 && UNKNOWN == code_sat
2f47b8d3
GJL
7290 && !started
7291 && i == n_bytes - 1)
e4fe948a 7292 {
2f47b8d3
GJL
7293 avr_asm_len ((code == PLUS) ^ (val8 == 1) ? "dec %0" : "inc %0",
7294 op, plen, 1);
b8469805 7295 *pcc = CC_CLOBBER;
2f47b8d3 7296 break;
e4fe948a 7297 }
59024515
GJL
7298
7299 switch (code)
7300 {
7301 case PLUS:
7302
51526856
GJL
7303 gcc_assert (plen != NULL || (op[2] && REG_P (op[2])));
7304
7305 if (plen != NULL && UNKNOWN != code_sat)
7306 {
7307 /* This belongs to the x + 0x80 corner case. The code with
7308 ADD instruction is not smaller, thus make this case
7309 expensive so that the caller won't pick it. */
7310
7311 *plen += 10;
7312 break;
7313 }
59024515
GJL
7314
7315 if (clobber_val != (int) val8)
7316 avr_asm_len ("ldi %2,%1", op, plen, 1);
7317 clobber_val = (int) val8;
00892272 7318
59024515
GJL
7319 avr_asm_len (started ? "adc %0,%2" : "add %0,%2", op, plen, 1);
7320
7321 break; /* PLUS */
7322
7323 case MINUS:
7324
7325 if (ld_reg_p)
7326 avr_asm_len (started ? "sbci %0,%1" : "subi %0,%1", op, plen, 1);
7327 else
7328 {
7329 gcc_assert (plen != NULL || REG_P (op[2]));
7330
7331 if (clobber_val != (int) val8)
7332 avr_asm_len ("ldi %2,%1", op, plen, 1);
7333 clobber_val = (int) val8;
00892272 7334
59024515
GJL
7335 avr_asm_len (started ? "sbc %0,%2" : "sub %0,%2", op, plen, 1);
7336 }
7337
7338 break; /* MINUS */
00892272 7339
59024515
GJL
7340 default:
7341 /* Unknown code */
7342 gcc_unreachable();
7343 }
7344
7345 started = true;
7346
7347 } /* for all sub-bytes */
05058b6e 7348
51526856 7349 saturate:
59024515 7350
51526856
GJL
7351 if (UNKNOWN == code_sat)
7352 return;
59024515 7353
51526856 7354 *pcc = (int) CC_CLOBBER;
59024515 7355
51526856 7356 /* Vanilla addition/subtraction is done. We are left with saturation.
00892272 7357
51526856
GJL
7358 We have to compute A = A <op> B where A is a register and
7359 B is a register or a non-zero compile time constant CONST.
7360 A is register class "r" if unsigned && B is REG. Otherwise, A is in "d".
00892272 7361 B stands for the original operand $2 in INSN. In the case of B = CONST,
51526856 7362 SIGN in { -1, 1 } is the sign of B. Otherwise, SIGN is 0.
00892272 7363
51526856 7364 CODE is the instruction flavor we use in the asm sequence to perform <op>.
00892272
GJL
7365
7366
51526856
GJL
7367 unsigned
7368 operation | code | sat if | b is | sat value | case
7369 -----------------+-------+----------+--------------+-----------+-------
7370 + as a + b | add | C == 1 | const, reg | u+ = 0xff | [1u]
7371 + as a - (-b) | sub | C == 0 | const | u+ = 0xff | [2u]
7372 - as a - b | sub | C == 1 | const, reg | u- = 0 | [3u]
7373 - as a + (-b) | add | C == 0 | const | u- = 0 | [4u]
00892272
GJL
7374
7375
51526856
GJL
7376 signed
7377 operation | code | sat if | b is | sat value | case
7378 -----------------+-------+----------+--------------+-----------+-------
7379 + as a + b | add | V == 1 | const, reg | s+ | [1s]
7380 + as a - (-b) | sub | V == 1 | const | s+ | [2s]
7381 - as a - b | sub | V == 1 | const, reg | s- | [3s]
7382 - as a + (-b) | add | V == 1 | const | s- | [4s]
00892272 7383
51526856
GJL
7384 s+ = b < 0 ? -0x80 : 0x7f
7385 s- = b < 0 ? 0x7f : -0x80
00892272 7386
51526856
GJL
7387 The cases a - b actually perform a - (-(-b)) if B is CONST.
7388 */
59024515 7389
51526856
GJL
7390 op[0] = simplify_gen_subreg (QImode, xop[0], mode, n_bytes-1);
7391 op[1] = n_bytes > 1
7392 ? simplify_gen_subreg (QImode, xop[0], mode, n_bytes-2)
7393 : NULL_RTX;
59024515 7394
51526856
GJL
7395 bool need_copy = true;
7396 int len_call = 1 + AVR_HAVE_JMP_CALL;
00892272 7397
51526856
GJL
7398 switch (code_sat)
7399 {
7400 default:
7401 gcc_unreachable();
7402
7403 case SS_PLUS:
7404 case SS_MINUS:
51526856
GJL
7405
7406 if (out_brvc)
7407 avr_asm_len ("brvc 0f", op, plen, 1);
7408
7409 if (reg_overlap_mentioned_p (xop[0], xop[2]))
7410 {
7411 /* [1s,reg] */
7412
7413 if (n_bytes == 1)
7414 avr_asm_len ("ldi %0,0x7f" CR_TAB
7415 "adc %0,__zero_reg__", op, plen, 2);
7416 else
7417 avr_asm_len ("ldi %0,0x7f" CR_TAB
7418 "ldi %1,0xff" CR_TAB
7419 "adc %1,__zero_reg__" CR_TAB
7420 "adc %0,__zero_reg__", op, plen, 4);
7421 }
7422 else if (sign == 0 && PLUS == code)
7423 {
7424 /* [1s,reg] */
7425
7426 op[2] = simplify_gen_subreg (QImode, xop[2], mode, n_bytes-1);
7427
7428 if (n_bytes == 1)
7429 avr_asm_len ("ldi %0,0x80" CR_TAB
7430 "sbrs %2,7" CR_TAB
7431 "dec %0", op, plen, 3);
7432 else
7433 avr_asm_len ("ldi %0,0x80" CR_TAB
7434 "cp %2,%0" CR_TAB
7435 "sbc %1,%1" CR_TAB
7436 "sbci %0,0", op, plen, 4);
7437 }
7438 else if (sign == 0 && MINUS == code)
7439 {
7440 /* [3s,reg] */
7441
7442 op[2] = simplify_gen_subreg (QImode, xop[2], mode, n_bytes-1);
7443
7444 if (n_bytes == 1)
7445 avr_asm_len ("ldi %0,0x7f" CR_TAB
7446 "sbrs %2,7" CR_TAB
7447 "inc %0", op, plen, 3);
7448 else
7449 avr_asm_len ("ldi %0,0x7f" CR_TAB
7450 "cp %0,%2" CR_TAB
7451 "sbc %1,%1" CR_TAB
7452 "sbci %0,-1", op, plen, 4);
7453 }
7454 else if ((sign < 0) ^ (SS_MINUS == code_sat))
7455 {
7456 /* [1s,const,B < 0] [2s,B < 0] */
7457 /* [3s,const,B > 0] [4s,B > 0] */
7458
7459 if (n_bytes == 8)
7460 {
7461 avr_asm_len ("%~call __clr_8", op, plen, len_call);
7462 need_copy = false;
7463 }
7464
7465 avr_asm_len ("ldi %0,0x80", op, plen, 1);
7466 if (n_bytes > 1 && need_copy)
7467 avr_asm_len ("clr %1", op, plen, 1);
7468 }
7469 else if ((sign > 0) ^ (SS_MINUS == code_sat))
7470 {
7471 /* [1s,const,B > 0] [2s,B > 0] */
7472 /* [3s,const,B < 0] [4s,B < 0] */
7473
7474 if (n_bytes == 8)
7475 {
7476 avr_asm_len ("sec" CR_TAB
7477 "%~call __sbc_8", op, plen, 1 + len_call);
7478 need_copy = false;
7479 }
7480
7481 avr_asm_len ("ldi %0,0x7f", op, plen, 1);
7482 if (n_bytes > 1 && need_copy)
7483 avr_asm_len ("ldi %1,0xff", op, plen, 1);
7484 }
7485 else
7486 gcc_unreachable();
00892272 7487
51526856
GJL
7488 break;
7489
7490 case US_PLUS:
7491 /* [1u] : [2u] */
00892272 7492
51526856 7493 avr_asm_len (PLUS == code ? "brcc 0f" : "brcs 0f", op, plen, 1);
00892272 7494
51526856
GJL
7495 if (n_bytes == 8)
7496 {
7497 if (MINUS == code)
7498 avr_asm_len ("sec", op, plen, 1);
7499 avr_asm_len ("%~call __sbc_8", op, plen, len_call);
7500
7501 need_copy = false;
7502 }
7503 else
7504 {
7505 if (MINUS == code && !test_hard_reg_class (LD_REGS, op[0]))
0c9ef7ad
GJL
7506 avr_asm_len ("sec" CR_TAB
7507 "sbc %0,%0", op, plen, 2);
51526856
GJL
7508 else
7509 avr_asm_len (PLUS == code ? "sbc %0,%0" : "ldi %0,0xff",
7510 op, plen, 1);
7511 }
7512 break; /* US_PLUS */
00892272 7513
51526856
GJL
7514 case US_MINUS:
7515 /* [4u] : [3u] */
7516
7517 avr_asm_len (PLUS == code ? "brcs 0f" : "brcc 0f", op, plen, 1);
7518
7519 if (n_bytes == 8)
7520 {
7521 avr_asm_len ("%~call __clr_8", op, plen, len_call);
7522 need_copy = false;
7523 }
7524 else
7525 avr_asm_len ("clr %0", op, plen, 1);
00892272 7526
51526856
GJL
7527 break;
7528 }
59024515 7529
51526856
GJL
7530 /* We set the MSB in the unsigned case and the 2 MSBs in the signed case.
7531 Now copy the right value to the LSBs. */
00892272 7532
51526856 7533 if (need_copy && n_bytes > 1)
05058b6e 7534 {
51526856
GJL
7535 if (US_MINUS == code_sat || US_PLUS == code_sat)
7536 {
7537 avr_asm_len ("mov %1,%0", op, plen, 1);
7538
7539 if (n_bytes > 2)
7540 {
7541 op[0] = xop[0];
7542 if (AVR_HAVE_MOVW)
7543 avr_asm_len ("movw %0,%1", op, plen, 1);
7544 else
7545 avr_asm_len ("mov %A0,%1" CR_TAB
7546 "mov %B0,%1", op, plen, 2);
7547 }
7548 }
7549 else if (n_bytes > 2)
7550 {
7551 op[0] = xop[0];
7552 avr_asm_len ("mov %A0,%1" CR_TAB
7553 "mov %B0,%1", op, plen, 2);
7554 }
05058b6e 7555 }
59024515 7556
51526856
GJL
7557 if (need_copy && n_bytes == 8)
7558 {
7559 if (AVR_HAVE_MOVW)
7560 avr_asm_len ("movw %r0+2,%0" CR_TAB
7561 "movw %r0+4,%0", xop, plen, 2);
7562 else
7563 avr_asm_len ("mov %r0+2,%0" CR_TAB
7564 "mov %r0+3,%0" CR_TAB
7565 "mov %r0+4,%0" CR_TAB
7566 "mov %r0+5,%0", xop, plen, 4);
7567 }
7568
02371798
GJL
7569 if (out_label)
7570 avr_asm_len ("0:", op, plen, 0);
59024515
GJL
7571}
7572
7573
51526856
GJL
7574/* Output addition/subtraction of register XOP[0] and a constant XOP[2] that
7575 is ont a compile-time constant:
2f47b8d3 7576
51526856
GJL
7577 XOP[0] = XOP[0] +/- XOP[2]
7578
7579 This is a helper for the function below. The only insns that need this
7580 are additions/subtraction for pointer modes, i.e. HImode and PSImode. */
7581
7582static const char*
7583avr_out_plus_symbol (rtx *xop, enum rtx_code code, int *plen, int *pcc)
2f47b8d3 7584{
ef4bddc2 7585 machine_mode mode = GET_MODE (xop[0]);
2f47b8d3 7586
51526856 7587 /* Only pointer modes want to add symbols. */
00892272 7588
51526856 7589 gcc_assert (mode == HImode || mode == PSImode);
2f47b8d3 7590
51526856
GJL
7591 *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_SET_N;
7592
7593 avr_asm_len (PLUS == code
7594 ? "subi %A0,lo8(-(%2))" CR_TAB "sbci %B0,hi8(-(%2))"
7595 : "subi %A0,lo8(%2)" CR_TAB "sbci %B0,hi8(%2)",
7596 xop, plen, -2);
7597
c8f35794 7598 if (PSImode == mode)
51526856 7599 avr_asm_len (PLUS == code
c8f35794 7600 ? "sbci %C0,hlo8(-(%2))"
51526856
GJL
7601 : "sbci %C0,hlo8(%2)", xop, plen, 1);
7602 return "";
2f47b8d3
GJL
7603}
7604
8c57e547 7605
51526856 7606/* Prepare operands of addition/subtraction to be used with avr_out_plus_1.
00892272 7607
02371798
GJL
7608 INSN is a single_set insn or an insn pattern with a binary operation as
7609 SET_SRC that is one of: PLUS, SS_PLUS, US_PLUS, MINUS, SS_MINUS, US_MINUS.
51526856
GJL
7610
7611 XOP are the operands of INSN. In the case of 64-bit operations with
7612 constant XOP[] has just one element: The summand/subtrahend in XOP[0].
7613 The non-saturating insns up to 32 bits may or may not supply a "d" class
7614 scratch as XOP[3].
7615
7616 If PLEN == NULL output the instructions.
7617 If PLEN != NULL set *PLEN to the length of the sequence in words.
e55e4056 7618
51526856
GJL
7619 PCC is a pointer to store the instructions' effect on cc0.
7620 PCC may be NULL.
e55e4056 7621
51526856
GJL
7622 PLEN and PCC default to NULL.
7623
02371798
GJL
7624 OUT_LABEL defaults to TRUE. For a description, see AVR_OUT_PLUS_1.
7625
51526856 7626 Return "" */
e55e4056
GJL
7627
7628const char*
02371798 7629avr_out_plus (rtx insn, rtx *xop, int *plen, int *pcc, bool out_label)
e55e4056 7630{
51526856
GJL
7631 int cc_plus, cc_minus, cc_dummy;
7632 int len_plus, len_minus;
e55e4056 7633 rtx op[4];
e8a54173 7634 rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
02371798 7635 rtx xdest = SET_DEST (xpattern);
ef4bddc2
RS
7636 machine_mode mode = GET_MODE (xdest);
7637 machine_mode imode = int_mode_for_mode (mode);
51526856 7638 int n_bytes = GET_MODE_SIZE (mode);
02371798 7639 enum rtx_code code_sat = GET_CODE (SET_SRC (xpattern));
51526856
GJL
7640 enum rtx_code code
7641 = (PLUS == code_sat || SS_PLUS == code_sat || US_PLUS == code_sat
7642 ? PLUS : MINUS);
e55e4056 7643
51526856
GJL
7644 if (!pcc)
7645 pcc = &cc_dummy;
e55e4056 7646
51526856 7647 /* PLUS and MINUS don't saturate: Use modular wrap-around. */
00892272 7648
51526856
GJL
7649 if (PLUS == code_sat || MINUS == code_sat)
7650 code_sat = UNKNOWN;
e55e4056 7651
51526856
GJL
7652 if (n_bytes <= 4 && REG_P (xop[2]))
7653 {
02371798 7654 avr_out_plus_1 (xop, plen, code, pcc, code_sat, 0, out_label);
51526856
GJL
7655 return "";
7656 }
e55e4056 7657
51526856
GJL
7658 if (8 == n_bytes)
7659 {
7660 op[0] = gen_rtx_REG (DImode, ACC_A);
7661 op[1] = gen_rtx_REG (DImode, ACC_A);
7662 op[2] = avr_to_int_mode (xop[0]);
7663 }
7664 else
7665 {
7666 if (!REG_P (xop[2])
7667 && !CONST_INT_P (xop[2])
7668 && !CONST_FIXED_P (xop[2]))
7669 {
7670 return avr_out_plus_symbol (xop, code, plen, pcc);
7671 }
00892272 7672
51526856
GJL
7673 op[0] = avr_to_int_mode (xop[0]);
7674 op[1] = avr_to_int_mode (xop[1]);
7675 op[2] = avr_to_int_mode (xop[2]);
7676 }
e55e4056 7677
51526856
GJL
7678 /* Saturations and 64-bit operations don't have a clobber operand.
7679 For the other cases, the caller will provide a proper XOP[3]. */
00892272 7680
02371798
GJL
7681 xpattern = INSN_P (insn) ? PATTERN (insn) : insn;
7682 op[3] = PARALLEL == GET_CODE (xpattern) ? xop[3] : NULL_RTX;
8c57e547 7683
51526856 7684 /* Saturation will need the sign of the original operand. */
8c57e547 7685
51526856
GJL
7686 rtx xmsb = simplify_gen_subreg (QImode, op[2], imode, n_bytes-1);
7687 int sign = INTVAL (xmsb) < 0 ? -1 : 1;
8c57e547 7688
51526856
GJL
7689 /* If we subtract and the subtrahend is a constant, then negate it
7690 so that avr_out_plus_1 can be used. */
8c57e547 7691
51526856
GJL
7692 if (MINUS == code)
7693 op[2] = simplify_unary_operation (NEG, imode, op[2], imode);
8c57e547 7694
51526856 7695 /* Work out the shortest sequence. */
e55e4056 7696
8f3a3138
GJL
7697 avr_out_plus_1 (op, &len_minus, MINUS, &cc_minus, code_sat, sign, out_label);
7698 avr_out_plus_1 (op, &len_plus, PLUS, &cc_plus, code_sat, sign, out_label);
e55e4056 7699
51526856
GJL
7700 if (plen)
7701 {
7702 *plen = (len_minus <= len_plus) ? len_minus : len_plus;
7703 *pcc = (len_minus <= len_plus) ? cc_minus : cc_plus;
7704 }
7705 else if (len_minus <= len_plus)
02371798 7706 avr_out_plus_1 (op, NULL, MINUS, pcc, code_sat, sign, out_label);
51526856 7707 else
02371798 7708 avr_out_plus_1 (op, NULL, PLUS, pcc, code_sat, sign, out_label);
e55e4056 7709
51526856 7710 return "";
e55e4056
GJL
7711}
7712
7713
6ebe2d6c
GJL
7714/* Output bit operation (IOR, AND, XOR) with register XOP[0] and compile
7715 time constant XOP[2]:
7716
7717 XOP[0] = XOP[0] <op> XOP[2]
7718
7719 and return "". If PLEN == NULL, print assembler instructions to perform the
7720 operation; otherwise, set *PLEN to the length of the instruction sequence
7721 (in words) printed with PLEN == NULL. XOP[3] is either an 8-bit clobber
02371798
GJL
7722 register or SCRATCH if no clobber register is needed for the operation.
7723 INSN is an INSN_P or a pattern of an insn. */
6ebe2d6c
GJL
7724
7725const char*
7726avr_out_bitop (rtx insn, rtx *xop, int *plen)
7727{
7728 /* CODE and MODE of the operation. */
e8a54173 7729 rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
02371798 7730 enum rtx_code code = GET_CODE (SET_SRC (xpattern));
ef4bddc2 7731 machine_mode mode = GET_MODE (xop[0]);
6ebe2d6c
GJL
7732
7733 /* Number of bytes to operate on. */
7734 int i, n_bytes = GET_MODE_SIZE (mode);
7735
7736 /* Value of T-flag (0 or 1) or -1 if unknow. */
7737 int set_t = -1;
7738
7739 /* Value (0..0xff) held in clobber register op[3] or -1 if unknown. */
7740 int clobber_val = -1;
7741
7742 /* op[0]: 8-bit destination register
7743 op[1]: 8-bit const int
be88b0c7 7744 op[2]: 8-bit clobber register, SCRATCH or NULL_RTX.
6ebe2d6c
GJL
7745 op[3]: 8-bit register containing 0xff or NULL_RTX */
7746 rtx op[4];
7747
be88b0c7 7748 op[2] = QImode == mode ? NULL_RTX : xop[3];
6ebe2d6c
GJL
7749 op[3] = NULL_RTX;
7750
7751 if (plen)
7752 *plen = 0;
7753
7754 for (i = 0; i < n_bytes; i++)
7755 {
7756 /* We operate byte-wise on the destination. */
7757 rtx reg8 = simplify_gen_subreg (QImode, xop[0], mode, i);
7758 rtx xval8 = simplify_gen_subreg (QImode, xop[2], mode, i);
7759
7760 /* 8-bit value to operate with this byte. */
7761 unsigned int val8 = UINTVAL (xval8) & GET_MODE_MASK (QImode);
7762
7763 /* Number of bits set in the current byte of the constant. */
7764 int pop8 = avr_popcount (val8);
7765
7766 /* Registers R16..R31 can operate with immediate. */
7767 bool ld_reg_p = test_hard_reg_class (LD_REGS, reg8);
7768
7769 op[0] = reg8;
7770 op[1] = GEN_INT (val8);
00892272 7771
6ebe2d6c
GJL
7772 switch (code)
7773 {
7774 case IOR:
7775
7776 if (0 == pop8)
7777 continue;
7778 else if (ld_reg_p)
7779 avr_asm_len ("ori %0,%1", op, plen, 1);
7780 else if (1 == pop8)
7781 {
7782 if (set_t != 1)
7783 avr_asm_len ("set", op, plen, 1);
7784 set_t = 1;
00892272 7785
6ebe2d6c
GJL
7786 op[1] = GEN_INT (exact_log2 (val8));
7787 avr_asm_len ("bld %0,%1", op, plen, 1);
7788 }
7789 else if (8 == pop8)
7790 {
7791 if (op[3] != NULL_RTX)
7792 avr_asm_len ("mov %0,%3", op, plen, 1);
7793 else
7794 avr_asm_len ("clr %0" CR_TAB
7795 "dec %0", op, plen, 2);
7796
7797 op[3] = op[0];
7798 }
7799 else
7800 {
7801 if (clobber_val != (int) val8)
7802 avr_asm_len ("ldi %2,%1", op, plen, 1);
7803 clobber_val = (int) val8;
00892272 7804
6ebe2d6c
GJL
7805 avr_asm_len ("or %0,%2", op, plen, 1);
7806 }
7807
7808 continue; /* IOR */
7809
7810 case AND:
7811
7812 if (8 == pop8)
7813 continue;
7814 else if (0 == pop8)
7815 avr_asm_len ("clr %0", op, plen, 1);
7816 else if (ld_reg_p)
7817 avr_asm_len ("andi %0,%1", op, plen, 1);
7818 else if (7 == pop8)
7819 {
7820 if (set_t != 0)
7821 avr_asm_len ("clt", op, plen, 1);
7822 set_t = 0;
00892272 7823
6ebe2d6c
GJL
7824 op[1] = GEN_INT (exact_log2 (GET_MODE_MASK (QImode) & ~val8));
7825 avr_asm_len ("bld %0,%1", op, plen, 1);
7826 }
7827 else
7828 {
7829 if (clobber_val != (int) val8)
7830 avr_asm_len ("ldi %2,%1", op, plen, 1);
7831 clobber_val = (int) val8;
00892272 7832
6ebe2d6c
GJL
7833 avr_asm_len ("and %0,%2", op, plen, 1);
7834 }
7835
7836 continue; /* AND */
00892272 7837
6ebe2d6c
GJL
7838 case XOR:
7839
7840 if (0 == pop8)
7841 continue;
7842 else if (8 == pop8)
7843 avr_asm_len ("com %0", op, plen, 1);
7844 else if (ld_reg_p && val8 == (1 << 7))
7845 avr_asm_len ("subi %0,%1", op, plen, 1);
7846 else
7847 {
7848 if (clobber_val != (int) val8)
7849 avr_asm_len ("ldi %2,%1", op, plen, 1);
7850 clobber_val = (int) val8;
00892272 7851
6ebe2d6c
GJL
7852 avr_asm_len ("eor %0,%2", op, plen, 1);
7853 }
7854
7855 continue; /* XOR */
00892272 7856
6ebe2d6c
GJL
7857 default:
7858 /* Unknown rtx_code */
7859 gcc_unreachable();
7860 }
7861 } /* for all sub-bytes */
7862
7863 return "";
7864}
7865
180ee6d1 7866
8e3d9e67
GJL
7867/* Output sign extension from XOP[1] to XOP[0] and return "".
7868 If PLEN == NULL, print assembler instructions to perform the operation;
7869 otherwise, set *PLEN to the length of the instruction sequence (in words)
7870 as printed with PLEN == NULL. */
7871
7872const char*
7873avr_out_sign_extend (rtx_insn *insn, rtx *xop, int *plen)
7874{
7875 // Size in bytes of source resp. destination operand.
7876 unsigned n_src = GET_MODE_SIZE (GET_MODE (xop[1]));
7877 unsigned n_dest = GET_MODE_SIZE (GET_MODE (xop[0]));
7878 rtx r_msb = all_regs_rtx[REGNO (xop[1]) + n_src - 1];
7879
7880 if (plen)
7881 *plen = 0;
7882
7883 // Copy destination to source
7884
7885 if (REGNO (xop[0]) != REGNO (xop[1]))
7886 {
7887 gcc_assert (n_src <= 2);
7888
7889 if (n_src == 2)
7890 avr_asm_len (AVR_HAVE_MOVW
7891 ? "movw %0,%1"
7892 : "mov %B0,%B1", xop, plen, 1);
7893 if (n_src == 1 || !AVR_HAVE_MOVW)
7894 avr_asm_len ("mov %A0,%A1", xop, plen, 1);
7895 }
7896
7897 // Set Carry to the sign bit MSB.7...
7898
7899 if (REGNO (xop[0]) == REGNO (xop[1])
7900 || !reg_unused_after (insn, r_msb))
7901 {
7902 avr_asm_len ("mov __tmp_reg__,%0", &r_msb, plen, 1);
7903 r_msb = tmp_reg_rtx;
7904 }
7905
7906 avr_asm_len ("lsl %0", &r_msb, plen, 1);
7907
7908 // ...and propagate it to all the new sign bits
7909
7910 for (unsigned n = n_src; n < n_dest; n++)
7911 avr_asm_len ("sbc %0,%0", &all_regs_rtx[REGNO (xop[0]) + n], plen, 1);
7912
7913 return "";
7914}
7915
7916
180ee6d1
GJL
7917/* PLEN == NULL: Output code to add CONST_INT OP[0] to SP.
7918 PLEN != NULL: Set *PLEN to the length of that sequence.
7919 Return "". */
7920
7921const char*
7922avr_out_addto_sp (rtx *op, int *plen)
7923{
7924 int pc_len = AVR_2_BYTE_PC ? 2 : 3;
7925 int addend = INTVAL (op[0]);
7926
7927 if (plen)
7928 *plen = 0;
7929
7930 if (addend < 0)
7931 {
7932 if (flag_verbose_asm || flag_print_asm_name)
7933 avr_asm_len (ASM_COMMENT_START "SP -= %n0", op, plen, 0);
00892272 7934
180ee6d1
GJL
7935 while (addend <= -pc_len)
7936 {
7937 addend += pc_len;
7938 avr_asm_len ("rcall .", op, plen, 1);
7939 }
7940
7941 while (addend++ < 0)
7942 avr_asm_len ("push __zero_reg__", op, plen, 1);
7943 }
7944 else if (addend > 0)
7945 {
7946 if (flag_verbose_asm || flag_print_asm_name)
7947 avr_asm_len (ASM_COMMENT_START "SP += %0", op, plen, 0);
7948
7949 while (addend-- > 0)
7950 avr_asm_len ("pop __tmp_reg__", op, plen, 1);
7951 }
7952
7953 return "";
7954}
7955
7956
fa626987
GJL
7957/* Output instructions to insert an inverted bit into OPERANDS[0]:
7958 $0.$1 = ~$2.$3 if XBITNO = NULL
7959 $0.$1 = ~$2.XBITNO if XBITNO != NULL.
7960 If PLEN = NULL then output the respective instruction sequence which
7961 is a combination of BST / BLD and some instruction(s) to invert the bit.
7962 If PLEN != NULL then store the length of the sequence (in words) in *PLEN.
7963 Return "". */
7964
7965const char*
7966avr_out_insert_notbit (rtx_insn *insn, rtx operands[], rtx xbitno, int *plen)
7967{
7968 rtx op[4] = { operands[0], operands[1], operands[2],
7969 xbitno == NULL_RTX ? operands [3] : xbitno };
7970
7971 if (INTVAL (op[1]) == 7
7972 && test_hard_reg_class (LD_REGS, op[0]))
7973 {
7974 /* If the inserted bit number is 7 and we have a d-reg, then invert
7975 the bit after the insertion by means of SUBI *,0x80. */
7976
7977 if (INTVAL (op[3]) == 7
7978 && REGNO (op[0]) == REGNO (op[2]))
7979 {
7980 avr_asm_len ("subi %0,0x80", op, plen, -1);
7981 }
7982 else
7983 {
7984 avr_asm_len ("bst %2,%3" CR_TAB
7985 "bld %0,%1" CR_TAB
7986 "subi %0,0x80", op, plen, -3);
7987 }
7988 }
7989 else if (test_hard_reg_class (LD_REGS, op[0])
7990 && (INTVAL (op[1]) != INTVAL (op[3])
7991 || !reg_overlap_mentioned_p (op[0], op[2])))
7992 {
7993 /* If the destination bit is in a d-reg we can jump depending
7994 on the source bit and use ANDI / ORI. This just applies if we
7995 have not an early-clobber situation with the bit. */
7996
7997 avr_asm_len ("andi %0,~(1<<%1)" CR_TAB
7998 "sbrs %2,%3" CR_TAB
7999 "ori %0,1<<%1", op, plen, -3);
8000 }
8001 else
8002 {
8003 /* Otherwise, invert the bit by means of COM before we store it with
8004 BST and then undo the COM if needed. */
8005
8006 avr_asm_len ("com %2" CR_TAB
8007 "bst %2,%3", op, plen, -2);
8008
8009 if (!reg_unused_after (insn, op[2])
8010 // A simple 'reg_unused_after' is not enough because that function
8011 // assumes that the destination register is overwritten completely
8012 // and hence is in order for our purpose. This is not the case
8013 // with BLD which just changes one bit of the destination.
8014 || reg_overlap_mentioned_p (op[0], op[2]))
8015 {
8016 /* Undo the COM from above. */
8017 avr_asm_len ("com %2", op, plen, 1);
8018 }
8019
8020 avr_asm_len ("bld %0,%1", op, plen, 1);
8021 }
8022
8023 return "";
8024}
8025
8026
e13d9d5a
GJL
8027/* Outputs instructions needed for fixed point type conversion.
8028 This includes converting between any fixed point type, as well
8029 as converting to any integer type. Conversion between integer
8030 types is not supported.
8031
8032 Converting signed fractional types requires a bit shift if converting
8033 to or from any unsigned fractional type because the decimal place is
8034 shifted by 1 bit. When the destination is a signed fractional, the sign
8035 is stored in either the carry or T bit. */
8036
8037const char*
98024b4e 8038avr_out_fract (rtx_insn *insn, rtx operands[], bool intsigned, int *plen)
e13d9d5a
GJL
8039{
8040 size_t i;
8041 rtx xop[6];
8042 RTX_CODE shift = UNKNOWN;
8043 bool sign_in_carry = false;
8044 bool msb_in_carry = false;
67518c93 8045 bool lsb_in_tmp_reg = false;
e13d9d5a 8046 bool lsb_in_carry = false;
67518c93 8047 bool frac_rounded = false;
e13d9d5a
GJL
8048 const char *code_ashift = "lsl %0";
8049
00892272 8050
e13d9d5a
GJL
8051#define MAY_CLOBBER(RR) \
8052 /* Shorthand used below. */ \
8053 ((sign_bytes \
8054 && IN_RANGE (RR, dest.regno_msb - sign_bytes + 1, dest.regno_msb)) \
67518c93 8055 || (offset && IN_RANGE (RR, dest.regno, dest.regno_msb)) \
e13d9d5a
GJL
8056 || (reg_unused_after (insn, all_regs_rtx[RR]) \
8057 && !IN_RANGE (RR, dest.regno, dest.regno_msb)))
8058
8059 struct
8060 {
8061 /* bytes : Length of operand in bytes.
8062 ibyte : Length of integral part in bytes.
8063 fbyte, fbit : Length of fractional part in bytes, bits. */
8064
8065 bool sbit;
8066 unsigned fbit, bytes, ibyte, fbyte;
8067 unsigned regno, regno_msb;
8068 } dest, src, *val[2] = { &dest, &src };
8069
8070 if (plen)
8071 *plen = 0;
8072
8073 /* Step 0: Determine information on source and destination operand we
8074 ====== will need in the remainder. */
8075
8076 for (i = 0; i < sizeof (val) / sizeof (*val); i++)
8077 {
ef4bddc2 8078 machine_mode mode;
e13d9d5a
GJL
8079
8080 xop[i] = operands[i];
8081
8082 mode = GET_MODE (xop[i]);
8083
8084 val[i]->bytes = GET_MODE_SIZE (mode);
8085 val[i]->regno = REGNO (xop[i]);
8086 val[i]->regno_msb = REGNO (xop[i]) + val[i]->bytes - 1;
8087
8088 if (SCALAR_INT_MODE_P (mode))
8089 {
8090 val[i]->sbit = intsigned;
8091 val[i]->fbit = 0;
8092 }
8093 else if (ALL_SCALAR_FIXED_POINT_MODE_P (mode))
8094 {
8095 val[i]->sbit = SIGNED_SCALAR_FIXED_POINT_MODE_P (mode);
8096 val[i]->fbit = GET_MODE_FBIT (mode);
8097 }
8098 else
8099 fatal_insn ("unsupported fixed-point conversion", insn);
8100
8101 val[i]->fbyte = (1 + val[i]->fbit) / BITS_PER_UNIT;
8102 val[i]->ibyte = val[i]->bytes - val[i]->fbyte;
8103 }
8104
8105 // Byte offset of the decimal point taking into account different place
8106 // of the decimal point in input and output and different register numbers
8107 // of input and output.
8108 int offset = dest.regno - src.regno + dest.fbyte - src.fbyte;
8109
8110 // Number of destination bytes that will come from sign / zero extension.
8111 int sign_bytes = (dest.ibyte - src.ibyte) * (dest.ibyte > src.ibyte);
8112
8113 // Number of bytes at the low end to be filled with zeros.
8114 int zero_bytes = (dest.fbyte - src.fbyte) * (dest.fbyte > src.fbyte);
8115
8116 // Do we have a 16-Bit register that is cleared?
8117 rtx clrw = NULL_RTX;
00892272 8118
e13d9d5a
GJL
8119 bool sign_extend = src.sbit && sign_bytes;
8120
8121 if (0 == dest.fbit % 8 && 7 == src.fbit % 8)
8122 shift = ASHIFT;
8123 else if (7 == dest.fbit % 8 && 0 == src.fbit % 8)
8124 shift = ASHIFTRT;
8125 else if (dest.fbit % 8 == src.fbit % 8)
8126 shift = UNKNOWN;
8127 else
8128 gcc_unreachable();
8129
67518c93 8130 /* If we need to round the fraction part, we might need to save/round it
0c9ef7ad 8131 before clobbering any of it in Step 1. Also, we might want to do
67518c93
JR
8132 the rounding now to make use of LD_REGS. */
8133 if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8134 && SCALAR_ACCUM_MODE_P (GET_MODE (xop[1]))
8135 && !TARGET_FRACT_CONV_TRUNC)
8136 {
8137 bool overlap
0c9ef7ad
GJL
8138 = (src.regno <=
8139 (offset ? dest.regno_msb - sign_bytes : dest.regno + zero_bytes - 1)
8140 && dest.regno - offset -1 >= dest.regno);
67518c93
JR
8141 unsigned s0 = dest.regno - offset -1;
8142 bool use_src = true;
8143 unsigned sn;
8144 unsigned copied_msb = src.regno_msb;
8145 bool have_carry = false;
8146
8147 if (src.ibyte > dest.ibyte)
0c9ef7ad 8148 copied_msb -= src.ibyte - dest.ibyte;
67518c93
JR
8149
8150 for (sn = s0; sn <= copied_msb; sn++)
0c9ef7ad
GJL
8151 if (!IN_RANGE (sn, dest.regno, dest.regno_msb)
8152 && !reg_unused_after (insn, all_regs_rtx[sn]))
8153 use_src = false;
67518c93 8154 if (use_src && TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], s0))
0c9ef7ad
GJL
8155 {
8156 avr_asm_len ("tst %0" CR_TAB "brpl 0f",
8157 &all_regs_rtx[src.regno_msb], plen, 2);
8158 sn = src.regno;
8159 if (sn < s0)
8160 {
8161 if (TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], sn))
8162 avr_asm_len ("cpi %0,1", &all_regs_rtx[sn], plen, 1);
8163 else
8164 avr_asm_len ("sec" CR_TAB
8165 "cpc %0,__zero_reg__",
8166 &all_regs_rtx[sn], plen, 2);
8167 have_carry = true;
8168 }
8169 while (++sn < s0)
8170 avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8171
8172 avr_asm_len (have_carry ? "sbci %0,128" : "subi %0,129",
8173 &all_regs_rtx[s0], plen, 1);
8174 for (sn = src.regno + src.fbyte; sn <= copied_msb; sn++)
8175 avr_asm_len ("sbci %0,255", &all_regs_rtx[sn], plen, 1);
8176 avr_asm_len ("\n0:", NULL, plen, 0);
8177 frac_rounded = true;
8178 }
67518c93 8179 else if (use_src && overlap)
0c9ef7ad
GJL
8180 {
8181 avr_asm_len ("clr __tmp_reg__" CR_TAB
8182 "sbrc %1,0" CR_TAB
8183 "dec __tmp_reg__", xop, plen, 1);
8184 sn = src.regno;
8185 if (sn < s0)
8186 {
8187 avr_asm_len ("add %0,__tmp_reg__", &all_regs_rtx[sn], plen, 1);
8188 have_carry = true;
8189 }
8190
8191 while (++sn < s0)
8192 avr_asm_len ("adc %0,__tmp_reg__", &all_regs_rtx[sn], plen, 1);
8193
8194 if (have_carry)
8195 avr_asm_len ("clt" CR_TAB
8196 "bld __tmp_reg__,7" CR_TAB
8197 "adc %0,__tmp_reg__",
8198 &all_regs_rtx[s0], plen, 1);
8199 else
8200 avr_asm_len ("lsr __tmp_reg" CR_TAB
8201 "add %0,__tmp_reg__",
8202 &all_regs_rtx[s0], plen, 2);
8203 for (sn = src.regno + src.fbyte; sn <= copied_msb; sn++)
8204 avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8205 frac_rounded = true;
8206 }
67518c93 8207 else if (overlap)
0c9ef7ad
GJL
8208 {
8209 bool use_src
8210 = (TEST_HARD_REG_BIT (reg_class_contents[LD_REGS], s0)
8211 && (IN_RANGE (s0, dest.regno, dest.regno_msb)
8212 || reg_unused_after (insn, all_regs_rtx[s0])));
8213 xop[2] = all_regs_rtx[s0];
8214 unsigned sn = src.regno;
8215 if (!use_src || sn == s0)
8216 avr_asm_len ("mov __tmp_reg__,%2", xop, plen, 1);
8217 /* We need to consider to-be-discarded bits
8218 if the value is negative. */
8219 if (sn < s0)
8220 {
8221 avr_asm_len ("tst %0" CR_TAB
8222 "brpl 0f",
8223 &all_regs_rtx[src.regno_msb], plen, 2);
8224 /* Test to-be-discarded bytes for any nozero bits.
8225 ??? Could use OR or SBIW to test two registers at once. */
8226 if (sn < s0)
8227 avr_asm_len ("cp %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8228
8229 while (++sn < s0)
8230 avr_asm_len ("cpc %0,__zero_reg__", &all_regs_rtx[sn], plen, 1);
8231 /* Set bit 0 in __tmp_reg__ if any of the lower bits was set. */
8232 if (use_src)
8233 avr_asm_len ("breq 0f" CR_TAB
8234 "ori %2,1"
8235 "\n0:\t" "mov __tmp_reg__,%2",
8236 xop, plen, 3);
8237 else
8238 avr_asm_len ("breq 0f" CR_TAB
8239 "set" CR_TAB
8240 "bld __tmp_reg__,0\n0:",
8241 xop, plen, 3);
8242 }
8243 lsb_in_tmp_reg = true;
8244 }
67518c93
JR
8245 }
8246
e13d9d5a
GJL
8247 /* Step 1: Clear bytes at the low end and copy payload bits from source
8248 ====== to destination. */
8249
8250 int step = offset < 0 ? 1 : -1;
8251 unsigned d0 = offset < 0 ? dest.regno : dest.regno_msb;
8252
67518c93 8253 // We cleared at least that number of registers.
e13d9d5a
GJL
8254 int clr_n = 0;
8255
8256 for (; d0 >= dest.regno && d0 <= dest.regno_msb; d0 += step)
8257 {
8258 // Next regno of destination is needed for MOVW
8259 unsigned d1 = d0 + step;
8260
8261 // Current and next regno of source
a861ffa4
GJL
8262 signed s0 = d0 - offset;
8263 signed s1 = s0 + step;
e13d9d5a
GJL
8264
8265 // Must current resp. next regno be CLRed? This applies to the low
8266 // bytes of the destination that have no associated source bytes.
a861ffa4
GJL
8267 bool clr0 = s0 < (signed) src.regno;
8268 bool clr1 = s1 < (signed) src.regno && d1 >= dest.regno;
e13d9d5a
GJL
8269
8270 // First gather what code to emit (if any) and additional step to
8271 // apply if a MOVW is in use. xop[2] is destination rtx and xop[3]
8272 // is the source rtx for the current loop iteration.
8273 const char *code = NULL;
8274 int stepw = 0;
00892272 8275
e13d9d5a
GJL
8276 if (clr0)
8277 {
8278 if (AVR_HAVE_MOVW && clr1 && clrw)
8279 {
8280 xop[2] = all_regs_rtx[d0 & ~1];
8281 xop[3] = clrw;
8282 code = "movw %2,%3";
8283 stepw = step;
8284 }
8285 else
8286 {
8287 xop[2] = all_regs_rtx[d0];
8288 code = "clr %2";
8289
8290 if (++clr_n >= 2
8291 && !clrw
8292 && d0 % 2 == (step > 0))
8293 {
8294 clrw = all_regs_rtx[d0 & ~1];
8295 }
8296 }
8297 }
a861ffa4 8298 else if (offset && s0 <= (signed) src.regno_msb)
e13d9d5a
GJL
8299 {
8300 int movw = AVR_HAVE_MOVW && offset % 2 == 0
8301 && d0 % 2 == (offset > 0)
8302 && d1 <= dest.regno_msb && d1 >= dest.regno
a861ffa4 8303 && s1 <= (signed) src.regno_msb && s1 >= (signed) src.regno;
e13d9d5a
GJL
8304
8305 xop[2] = all_regs_rtx[d0 & ~movw];
8306 xop[3] = all_regs_rtx[s0 & ~movw];
8307 code = movw ? "movw %2,%3" : "mov %2,%3";
8308 stepw = step * movw;
8309 }
8310
8311 if (code)
8312 {
8313 if (sign_extend && shift != ASHIFT && !sign_in_carry
8314 && (d0 == src.regno_msb || d0 + stepw == src.regno_msb))
8315 {
8316 /* We are going to override the sign bit. If we sign-extend,
8317 store the sign in the Carry flag. This is not needed if
0c9ef7ad 8318 the destination will be ASHIFT in the remainder because
e13d9d5a
GJL
8319 the ASHIFT will set Carry without extra instruction. */
8320
8321 avr_asm_len ("lsl %0", &all_regs_rtx[src.regno_msb], plen, 1);
8322 sign_in_carry = true;
8323 }
8324
8325 unsigned src_msb = dest.regno_msb - sign_bytes - offset + 1;
8326
8327 if (!sign_extend && shift == ASHIFTRT && !msb_in_carry
8328 && src.ibyte > dest.ibyte
8329 && (d0 == src_msb || d0 + stepw == src_msb))
8330 {
8331 /* We are going to override the MSB. If we shift right,
8332 store the MSB in the Carry flag. This is only needed if
8333 we don't sign-extend becaue with sign-extension the MSB
8334 (the sign) will be produced by the sign extension. */
8335
8336 avr_asm_len ("lsr %0", &all_regs_rtx[src_msb], plen, 1);
8337 msb_in_carry = true;
8338 }
8339
8340 unsigned src_lsb = dest.regno - offset -1;
8341
8342 if (shift == ASHIFT && src.fbyte > dest.fbyte && !lsb_in_carry
67518c93 8343 && !lsb_in_tmp_reg
e13d9d5a
GJL
8344 && (d0 == src_lsb || d0 + stepw == src_lsb))
8345 {
8346 /* We are going to override the new LSB; store it into carry. */
8347
8348 avr_asm_len ("lsl %0", &all_regs_rtx[src_lsb], plen, 1);
8349 code_ashift = "rol %0";
8350 lsb_in_carry = true;
8351 }
8352
8353 avr_asm_len (code, xop, plen, 1);
8354 d0 += stepw;
8355 }
8356 }
8357
8358 /* Step 2: Shift destination left by 1 bit position. This might be needed
8359 ====== for signed input and unsigned output. */
8360
8361 if (shift == ASHIFT && src.fbyte > dest.fbyte && !lsb_in_carry)
8362 {
8363 unsigned s0 = dest.regno - offset -1;
8364
67518c93
JR
8365 /* n1169 4.1.4 says:
8366 "Conversions from a fixed-point to an integer type round toward zero."
8367 Hence, converting a fract type to integer only gives a non-zero result
8368 for -1. */
8369 if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8370 && SCALAR_FRACT_MODE_P (GET_MODE (xop[1]))
8371 && !TARGET_FRACT_CONV_TRUNC)
8372 {
8373 gcc_assert (s0 == src.regno_msb);
8374 /* Check if the input is -1. We do that by checking if negating
8375 the input causes an integer overflow. */
8376 unsigned sn = src.regno;
8377 avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx[sn++], plen, 1);
8378 while (sn <= s0)
8379 avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx[sn++], plen, 1);
8380
8381 /* Overflow goes with set carry. Clear carry otherwise. */
0c9ef7ad
GJL
8382 avr_asm_len ("brvs 0f" CR_TAB
8383 "clc\n0:", NULL, plen, 2);
67518c93
JR
8384 }
8385 /* Likewise, when converting from accumulator types to integer, we
8386 need to round up negative values. */
8387 else if (SCALAR_INT_MODE_P (GET_MODE (xop[0]))
8388 && SCALAR_ACCUM_MODE_P (GET_MODE (xop[1]))
8389 && !TARGET_FRACT_CONV_TRUNC
8390 && !frac_rounded)
8391 {
8392 bool have_carry = false;
8393
8394 xop[2] = all_regs_rtx[s0];
8395 if (!lsb_in_tmp_reg && !MAY_CLOBBER (s0))
8396 avr_asm_len ("mov __tmp_reg__,%2", xop, plen, 1);
8397 avr_asm_len ("tst %0" CR_TAB "brpl 0f",
8398 &all_regs_rtx[src.regno_msb], plen, 2);
8399 if (!lsb_in_tmp_reg)
8400 {
8401 unsigned sn = src.regno;
8402 if (sn < s0)
8403 {
8404 avr_asm_len ("cp __zero_reg__,%0", &all_regs_rtx[sn],
8405 plen, 1);
8406 have_carry = true;
8407 }
8408 while (++sn < s0)
8409 avr_asm_len ("cpc __zero_reg__,%0", &all_regs_rtx[sn], plen, 1);
8410 lsb_in_tmp_reg = !MAY_CLOBBER (s0);
8411 }
8412 /* Add in C and the rounding value 127. */
8413 /* If the destination msb is a sign byte, and in LD_REGS,
8414 grab it as a temporary. */
8415 if (sign_bytes
8416 && TEST_HARD_REG_BIT (reg_class_contents[LD_REGS],
8417 dest.regno_msb))
8418 {
8419 xop[3] = all_regs_rtx[dest.regno_msb];
8420 avr_asm_len ("ldi %3,127", xop, plen, 1);
8421 avr_asm_len ((have_carry && lsb_in_tmp_reg ? "adc __tmp_reg__,%3"
8422 : have_carry ? "adc %2,%3"
8423 : lsb_in_tmp_reg ? "add __tmp_reg__,%3"
8424 : "add %2,%3"),
8425 xop, plen, 1);
8426 }
8427 else
8428 {
8429 /* Fall back to use __zero_reg__ as a temporary. */
8430 avr_asm_len ("dec __zero_reg__", NULL, plen, 1);
8431 if (have_carry)
0c9ef7ad
GJL
8432 avr_asm_len ("clt" CR_TAB
8433 "bld __zero_reg__,7", NULL, plen, 2);
67518c93
JR
8434 else
8435 avr_asm_len ("lsr __zero_reg__", NULL, plen, 1);
0c9ef7ad
GJL
8436 avr_asm_len (have_carry && lsb_in_tmp_reg
8437 ? "adc __tmp_reg__,__zero_reg__"
8438 : have_carry ? "adc %2,__zero_reg__"
8439 : lsb_in_tmp_reg ? "add __tmp_reg__,__zero_reg__"
8440 : "add %2,__zero_reg__",
67518c93
JR
8441 xop, plen, 1);
8442 avr_asm_len ("eor __zero_reg__,__zero_reg__", NULL, plen, 1);
8443 }
0c9ef7ad
GJL
8444
8445 for (d0 = dest.regno + zero_bytes;
67518c93
JR
8446 d0 <= dest.regno_msb - sign_bytes; d0++)
8447 avr_asm_len ("adc %0,__zero_reg__", &all_regs_rtx[d0], plen, 1);
0c9ef7ad
GJL
8448
8449 avr_asm_len (lsb_in_tmp_reg
8450 ? "\n0:\t" "lsl __tmp_reg__"
8451 : "\n0:\t" "lsl %2",
67518c93
JR
8452 xop, plen, 1);
8453 }
8454 else if (MAY_CLOBBER (s0))
e13d9d5a
GJL
8455 avr_asm_len ("lsl %0", &all_regs_rtx[s0], plen, 1);
8456 else
8457 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
8458 "lsl __tmp_reg__", &all_regs_rtx[s0], plen, 2);
8459
8460 code_ashift = "rol %0";
8461 lsb_in_carry = true;
8462 }
8463
8464 if (shift == ASHIFT)
8465 {
8466 for (d0 = dest.regno + zero_bytes;
8467 d0 <= dest.regno_msb - sign_bytes; d0++)
8468 {
8469 avr_asm_len (code_ashift, &all_regs_rtx[d0], plen, 1);
8470 code_ashift = "rol %0";
8471 }
8472
8473 lsb_in_carry = false;
8474 sign_in_carry = true;
8475 }
8476
8477 /* Step 4a: Store MSB in carry if we don't already have it or will produce
8478 ======= it in sign-extension below. */
8479
8480 if (!sign_extend && shift == ASHIFTRT && !msb_in_carry
8481 && src.ibyte > dest.ibyte)
8482 {
8483 unsigned s0 = dest.regno_msb - sign_bytes - offset + 1;
8484
8485 if (MAY_CLOBBER (s0))
8486 avr_asm_len ("lsr %0", &all_regs_rtx[s0], plen, 1);
8487 else
8488 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
8489 "lsr __tmp_reg__", &all_regs_rtx[s0], plen, 2);
8490
8491 msb_in_carry = true;
8492 }
8493
8494 /* Step 3: Sign-extend or zero-extend the destination as needed.
8495 ====== */
8496
8497 if (sign_extend && !sign_in_carry)
8498 {
8499 unsigned s0 = src.regno_msb;
00892272 8500
e13d9d5a
GJL
8501 if (MAY_CLOBBER (s0))
8502 avr_asm_len ("lsl %0", &all_regs_rtx[s0], plen, 1);
8503 else
8504 avr_asm_len ("mov __tmp_reg__,%0" CR_TAB
8505 "lsl __tmp_reg__", &all_regs_rtx[s0], plen, 2);
8506
8507 sign_in_carry = true;
8508 }
8509
8510 gcc_assert (sign_in_carry + msb_in_carry + lsb_in_carry <= 1);
8511
8512 unsigned copies = 0;
8513 rtx movw = sign_extend ? NULL_RTX : clrw;
8514
8515 for (d0 = dest.regno_msb - sign_bytes + 1; d0 <= dest.regno_msb; d0++)
8516 {
8517 if (AVR_HAVE_MOVW && movw
8518 && d0 % 2 == 0 && d0 + 1 <= dest.regno_msb)
8519 {
8520 xop[2] = all_regs_rtx[d0];
8521 xop[3] = movw;
8522 avr_asm_len ("movw %2,%3", xop, plen, 1);
8523 d0++;
8524 }
8525 else
8526 {
8527 avr_asm_len (sign_extend ? "sbc %0,%0" : "clr %0",
8528 &all_regs_rtx[d0], plen, 1);
8529
8530 if (++copies >= 2 && !movw && d0 % 2 == 1)
8531 movw = all_regs_rtx[d0-1];
8532 }
8533 } /* for */
8534
8535
8536 /* Step 4: Right shift the destination. This might be needed for
8537 ====== conversions from unsigned to signed. */
8538
8539 if (shift == ASHIFTRT)
8540 {
8541 const char *code_ashiftrt = "lsr %0";
8542
8543 if (sign_extend || msb_in_carry)
8544 code_ashiftrt = "ror %0";
8545
8546 if (src.sbit && src.ibyte == dest.ibyte)
8547 code_ashiftrt = "asr %0";
8548
8549 for (d0 = dest.regno_msb - sign_bytes;
8550 d0 >= dest.regno + zero_bytes - 1 && d0 >= dest.regno; d0--)
8551 {
8552 avr_asm_len (code_ashiftrt, &all_regs_rtx[d0], plen, 1);
8553 code_ashiftrt = "ror %0";
8554 }
8555 }
8556
8557#undef MAY_CLOBBER
8558
8559 return "";
8560}
8561
8562
02371798
GJL
8563/* Output fixed-point rounding. XOP[0] = XOP[1] is the operand to round.
8564 XOP[2] is the rounding point, a CONST_INT. The function prints the
8565 instruction sequence if PLEN = NULL and computes the length in words
8566 of the sequence if PLEN != NULL. Most of this function deals with
8567 preparing operands for calls to `avr_out_plus' and `avr_out_bitop'. */
8568
8569const char*
98024b4e 8570avr_out_round (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *xop, int *plen)
02371798 8571{
ef4bddc2
RS
8572 machine_mode mode = GET_MODE (xop[0]);
8573 machine_mode imode = int_mode_for_mode (mode);
02371798
GJL
8574 // The smallest fractional bit not cleared by the rounding is 2^(-RP).
8575 int fbit = (int) GET_MODE_FBIT (mode);
8576 double_int i_add = double_int_zero.set_bit (fbit-1 - INTVAL (xop[2]));
807e902e
KZ
8577 wide_int wi_add = wi::set_bit_in_zero (fbit-1 - INTVAL (xop[2]),
8578 GET_MODE_PRECISION (imode));
02371798
GJL
8579 // Lengths of PLUS and AND parts.
8580 int len_add = 0, *plen_add = plen ? &len_add : NULL;
8581 int len_and = 0, *plen_and = plen ? &len_and : NULL;
8582
8583 // Add-Saturate 1/2 * 2^(-RP). Don't print the label "0:" when printing
8584 // the saturated addition so that we can emit the "rjmp 1f" before the
8585 // "0:" below.
8586
8587 rtx xadd = const_fixed_from_double_int (i_add, mode);
8588 rtx xpattern, xsrc, op[4];
8589
8590 xsrc = SIGNED_FIXED_POINT_MODE_P (mode)
8591 ? gen_rtx_SS_PLUS (mode, xop[1], xadd)
8592 : gen_rtx_US_PLUS (mode, xop[1], xadd);
f7df4a84 8593 xpattern = gen_rtx_SET (xop[0], xsrc);
02371798
GJL
8594
8595 op[0] = xop[0];
8596 op[1] = xop[1];
8597 op[2] = xadd;
8598 avr_out_plus (xpattern, op, plen_add, NULL, false /* Don't print "0:" */);
8599
8600 avr_asm_len ("rjmp 1f" CR_TAB
8601 "0:", NULL, plen_add, 1);
8602
8603 // Keep all bits from RP and higher: ... 2^(-RP)
8604 // Clear all bits from RP+1 and lower: 2^(-RP-1) ...
8605 // Rounding point ^^^^^^^
8606 // Added above ^^^^^^^^^
8607 rtx xreg = simplify_gen_subreg (imode, xop[0], mode, 0);
807e902e 8608 rtx xmask = immed_wide_int_const (-wi_add - wi_add, imode);
02371798 8609
f7df4a84 8610 xpattern = gen_rtx_SET (xreg, gen_rtx_AND (imode, xreg, xmask));
02371798
GJL
8611
8612 op[0] = xreg;
8613 op[1] = xreg;
8614 op[2] = xmask;
8615 op[3] = gen_rtx_SCRATCH (QImode);
8616 avr_out_bitop (xpattern, op, plen_and);
8617 avr_asm_len ("1:", NULL, plen, 0);
8618
8619 if (plen)
8620 *plen = len_add + len_and;
8621
8622 return "";
8623}
8624
8625
58f0ea2f
AH
8626/* Create RTL split patterns for byte sized rotate expressions. This
8627 produces a series of move instructions and considers overlap situations.
8628 Overlapping non-HImode operands need a scratch register. */
8629
8630bool
8631avr_rotate_bytes (rtx operands[])
8632{
8633 int i, j;
ef4bddc2 8634 machine_mode mode = GET_MODE (operands[0]);
58f0ea2f
AH
8635 bool overlapped = reg_overlap_mentioned_p (operands[0], operands[1]);
8636 bool same_reg = rtx_equal_p (operands[0], operands[1]);
8637 int num = INTVAL (operands[2]);
8638 rtx scratch = operands[3];
8639 /* Work out if byte or word move is needed. Odd byte rotates need QImode.
8640 Word move if no scratch is needed, otherwise use size of scratch. */
ef4bddc2 8641 machine_mode move_mode = QImode;
3f02a5f3
JR
8642 int move_size, offset, size;
8643
58f0ea2f
AH
8644 if (num & 0xf)
8645 move_mode = QImode;
8646 else if ((mode == SImode && !same_reg) || !overlapped)
8647 move_mode = HImode;
8648 else
8649 move_mode = GET_MODE (scratch);
8650
8651 /* Force DI rotate to use QI moves since other DI moves are currently split
8652 into QI moves so forward propagation works better. */
8653 if (mode == DImode)
8654 move_mode = QImode;
8655 /* Make scratch smaller if needed. */
d772f97c
GJL
8656 if (SCRATCH != GET_CODE (scratch)
8657 && HImode == GET_MODE (scratch)
8658 && QImode == move_mode)
00892272 8659 scratch = simplify_gen_subreg (move_mode, scratch, HImode, 0);
58f0ea2f 8660
3f02a5f3 8661 move_size = GET_MODE_SIZE (move_mode);
58f0ea2f 8662 /* Number of bytes/words to rotate. */
3f02a5f3 8663 offset = (num >> 3) / move_size;
58f0ea2f 8664 /* Number of moves needed. */
3f02a5f3 8665 size = GET_MODE_SIZE (mode) / move_size;
58f0ea2f
AH
8666 /* Himode byte swap is special case to avoid a scratch register. */
8667 if (mode == HImode && same_reg)
8668 {
8669 /* HImode byte swap, using xor. This is as quick as using scratch. */
8670 rtx src, dst;
8671 src = simplify_gen_subreg (move_mode, operands[1], mode, 0);
8672 dst = simplify_gen_subreg (move_mode, operands[0], mode, 1);
8673 if (!rtx_equal_p (dst, src))
8674 {
8675 emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
8676 emit_move_insn (src, gen_rtx_XOR (QImode, src, dst));
8677 emit_move_insn (dst, gen_rtx_XOR (QImode, dst, src));
8678 }
00892272
GJL
8679 }
8680 else
58f0ea2f 8681 {
3f02a5f3 8682#define MAX_SIZE 8 /* GET_MODE_SIZE (DImode) / GET_MODE_SIZE (QImode) */
58f0ea2f
AH
8683 /* Create linked list of moves to determine move order. */
8684 struct {
8685 rtx src, dst;
8686 int links;
3f02a5f3
JR
8687 } move[MAX_SIZE + 8];
8688 int blocked, moves;
58f0ea2f 8689
3f02a5f3 8690 gcc_assert (size <= MAX_SIZE);
58f0ea2f
AH
8691 /* Generate list of subreg moves. */
8692 for (i = 0; i < size; i++)
0c9ef7ad 8693 {
58f0ea2f 8694 int from = i;
00892272 8695 int to = (from + offset) % size;
58f0ea2f 8696 move[i].src = simplify_gen_subreg (move_mode, operands[1],
0c9ef7ad 8697 mode, from * move_size);
58f0ea2f 8698 move[i].dst = simplify_gen_subreg (move_mode, operands[0],
0c9ef7ad
GJL
8699 mode, to * move_size);
8700 move[i].links = -1;
8701 }
58f0ea2f
AH
8702 /* Mark dependence where a dst of one move is the src of another move.
8703 The first move is a conflict as it must wait until second is
8704 performed. We ignore moves to self - we catch this later. */
8705 if (overlapped)
8706 for (i = 0; i < size; i++)
8707 if (reg_overlap_mentioned_p (move[i].dst, operands[1]))
8708 for (j = 0; j < size; j++)
8709 if (j != i && rtx_equal_p (move[j].src, move[i].dst))
8710 {
8711 /* The dst of move i is the src of move j. */
8712 move[i].links = j;
8713 break;
8714 }
8715
3f02a5f3
JR
8716 blocked = -1;
8717 moves = 0;
58f0ea2f
AH
8718 /* Go through move list and perform non-conflicting moves. As each
8719 non-overlapping move is made, it may remove other conflicts
8720 so the process is repeated until no conflicts remain. */
8721 do
8722 {
8723 blocked = -1;
8724 moves = 0;
8725 /* Emit move where dst is not also a src or we have used that
8726 src already. */
8727 for (i = 0; i < size; i++)
8728 if (move[i].src != NULL_RTX)
3f02a5f3
JR
8729 {
8730 if (move[i].links == -1
8731 || move[move[i].links].src == NULL_RTX)
8732 {
8733 moves++;
8734 /* Ignore NOP moves to self. */
8735 if (!rtx_equal_p (move[i].dst, move[i].src))
8736 emit_move_insn (move[i].dst, move[i].src);
58f0ea2f 8737
3f02a5f3
JR
8738 /* Remove conflict from list. */
8739 move[i].src = NULL_RTX;
8740 }
8741 else
8742 blocked = i;
8743 }
58f0ea2f
AH
8744
8745 /* Check for deadlock. This is when no moves occurred and we have
8746 at least one blocked move. */
8747 if (moves == 0 && blocked != -1)
8748 {
8749 /* Need to use scratch register to break deadlock.
8750 Add move to put dst of blocked move into scratch.
8751 When this move occurs, it will break chain deadlock.
8752 The scratch register is substituted for real move. */
8753
d772f97c
GJL
8754 gcc_assert (SCRATCH != GET_CODE (scratch));
8755
58f0ea2f
AH
8756 move[size].src = move[blocked].dst;
8757 move[size].dst = scratch;
8758 /* Scratch move is never blocked. */
00892272 8759 move[size].links = -1;
58f0ea2f
AH
8760 /* Make sure we have valid link. */
8761 gcc_assert (move[blocked].links != -1);
8762 /* Replace src of blocking move with scratch reg. */
8763 move[move[blocked].links].src = scratch;
631b20a7 8764 /* Make dependent on scratch move occurring. */
00892272 8765 move[blocked].links = size;
58f0ea2f
AH
8766 size=size+1;
8767 }
8768 }
8769 while (blocked != -1);
8770 }
8771 return true;
8772}
8773
e55e4056 8774
00892272 8775/* Worker function for `ADJUST_INSN_LENGTH'. */
90e7678c 8776/* Modifies the length assigned to instruction INSN
4103605f 8777 LEN is the initially computed length of the insn. */
90e7678c
DC
8778
8779int
98024b4e 8780avr_adjust_insn_length (rtx_insn *insn, int len)
90e7678c 8781{
8a6a05ce 8782 rtx *op = recog_data.operand;
8dab2ba5
GJL
8783 enum attr_adjust_len adjust_len;
8784
8785 /* Some complex insns don't need length adjustment and therefore
8786 the length need not/must not be adjusted for these insns.
8787 It is easier to state this in an insn attribute "adjust_len" than
8788 to clutter up code here... */
0c9ef7ad 8789
94ba1bd5
GJL
8790 if (!NONDEBUG_INSN_P (insn)
8791 || -1 == recog_memoized (insn))
8dab2ba5
GJL
8792 {
8793 return len;
8794 }
8795
8796 /* Read from insn attribute "adjust_len" if/how length is to be adjusted. */
8797
8798 adjust_len = get_attr_adjust_len (insn);
8799
8a6a05ce 8800 if (adjust_len == ADJUST_LEN_NO)
8dab2ba5 8801 {
8a6a05ce
GJL
8802 /* Nothing to adjust: The length from attribute "length" is fine.
8803 This is the default. */
00892272 8804
8a6a05ce
GJL
8805 return len;
8806 }
00892272 8807
8a6a05ce 8808 /* Extract insn's operands. */
00892272 8809
8a6a05ce 8810 extract_constrain_insn_cached (insn);
00892272 8811
8a6a05ce 8812 /* Dispatch to right function. */
00892272 8813
8a6a05ce
GJL
8814 switch (adjust_len)
8815 {
8816 case ADJUST_LEN_RELOAD_IN16: output_reload_inhi (op, op[2], &len); break;
e4fe948a 8817 case ADJUST_LEN_RELOAD_IN24: avr_out_reload_inpsi (op, op[2], &len); break;
8a6a05ce 8818 case ADJUST_LEN_RELOAD_IN32: output_reload_insisf (op, op[2], &len); break;
00892272 8819
8a6a05ce 8820 case ADJUST_LEN_OUT_BITOP: avr_out_bitop (insn, op, &len); break;
00892272 8821
51526856 8822 case ADJUST_LEN_PLUS: avr_out_plus (insn, op, &len); break;
180ee6d1 8823 case ADJUST_LEN_ADDTO_SP: avr_out_addto_sp (op, &len); break;
00892272 8824
8a6a05ce
GJL
8825 case ADJUST_LEN_MOV8: output_movqi (insn, op, &len); break;
8826 case ADJUST_LEN_MOV16: output_movhi (insn, op, &len); break;
e4fe948a 8827 case ADJUST_LEN_MOV24: avr_out_movpsi (insn, op, &len); break;
8a6a05ce 8828 case ADJUST_LEN_MOV32: output_movsisf (insn, op, &len); break;
7bc6df2c
GJL
8829 case ADJUST_LEN_MOVMEM: avr_out_movmem (insn, op, &len); break;
8830 case ADJUST_LEN_XLOAD: avr_out_xload (insn, op, &len); break;
8e3d9e67 8831 case ADJUST_LEN_SEXT: avr_out_sign_extend (insn, op, &len); break;
7bc6df2c 8832
e55e4056
GJL
8833 case ADJUST_LEN_SFRACT: avr_out_fract (insn, op, true, &len); break;
8834 case ADJUST_LEN_UFRACT: avr_out_fract (insn, op, false, &len); break;
02371798 8835 case ADJUST_LEN_ROUND: avr_out_round (insn, op, &len); break;
e55e4056 8836
8a6a05ce 8837 case ADJUST_LEN_TSTHI: avr_out_tsthi (insn, op, &len); break;
e4fe948a 8838 case ADJUST_LEN_TSTPSI: avr_out_tstpsi (insn, op, &len); break;
8a6a05ce
GJL
8839 case ADJUST_LEN_TSTSI: avr_out_tstsi (insn, op, &len); break;
8840 case ADJUST_LEN_COMPARE: avr_out_compare (insn, op, &len); break;
8c57e547 8841 case ADJUST_LEN_COMPARE64: avr_out_compare64 (insn, op, &len); break;
155b14a8 8842
8a6a05ce
GJL
8843 case ADJUST_LEN_LSHRQI: lshrqi3_out (insn, op, &len); break;
8844 case ADJUST_LEN_LSHRHI: lshrhi3_out (insn, op, &len); break;
8845 case ADJUST_LEN_LSHRSI: lshrsi3_out (insn, op, &len); break;
155b14a8 8846
8a6a05ce
GJL
8847 case ADJUST_LEN_ASHRQI: ashrqi3_out (insn, op, &len); break;
8848 case ADJUST_LEN_ASHRHI: ashrhi3_out (insn, op, &len); break;
8849 case ADJUST_LEN_ASHRSI: ashrsi3_out (insn, op, &len); break;
155b14a8 8850
8a6a05ce
GJL
8851 case ADJUST_LEN_ASHLQI: ashlqi3_out (insn, op, &len); break;
8852 case ADJUST_LEN_ASHLHI: ashlhi3_out (insn, op, &len); break;
8853 case ADJUST_LEN_ASHLSI: ashlsi3_out (insn, op, &len); break;
00892272 8854
e4fe948a
GJL
8855 case ADJUST_LEN_ASHLPSI: avr_out_ashlpsi3 (insn, op, &len); break;
8856 case ADJUST_LEN_ASHRPSI: avr_out_ashrpsi3 (insn, op, &len); break;
8857 case ADJUST_LEN_LSHRPSI: avr_out_lshrpsi3 (insn, op, &len); break;
8858
7c3297ce
GJL
8859 case ADJUST_LEN_CALL: len = AVR_HAVE_JMP_CALL ? 2 : 1; break;
8860
0c578db6 8861 case ADJUST_LEN_INSERT_BITS: avr_out_insert_bits (op, &len); break;
49b2772e 8862
fa626987
GJL
8863 case ADJUST_LEN_INSV_NOTBIT:
8864 avr_out_insert_notbit (insn, op, NULL_RTX, &len);
8865 break;
8866 case ADJUST_LEN_INSV_NOTBIT_0:
8867 avr_out_insert_notbit (insn, op, const0_rtx, &len);
8868 break;
8869 case ADJUST_LEN_INSV_NOTBIT_7:
8870 avr_out_insert_notbit (insn, op, GEN_INT (7), &len);
8871 break;
8872
8a6a05ce
GJL
8873 default:
8874 gcc_unreachable();
90e7678c 8875 }
0c578db6 8876
90e7678c
DC
8877 return len;
8878}
8879
d6b4baa4 8880/* Return nonzero if register REG dead after INSN. */
90e7678c
DC
8881
8882int
98024b4e 8883reg_unused_after (rtx_insn *insn, rtx reg)
90e7678c 8884{
6bec29c9 8885 return (dead_or_set_p (insn, reg)
90e7678c
DC
8886 || (REG_P(reg) && _reg_unused_after (insn, reg)));
8887}
8888
825dda42 8889/* Return nonzero if REG is not used after INSN.
90e7678c
DC
8890 We assume REG is a reload reg, and therefore does
8891 not live past labels. It may live past calls or jumps though. */
8892
8893int
98024b4e 8894_reg_unused_after (rtx_insn *insn, rtx reg)
90e7678c
DC
8895{
8896 enum rtx_code code;
8897 rtx set;
8898
8899 /* If the reg is set by this instruction, then it is safe for our
8900 case. Disregard the case where this is a store to memory, since
8901 we are checking a register used in the store address. */
8902 set = single_set (insn);
8903 if (set && GET_CODE (SET_DEST (set)) != MEM
8904 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
8905 return 1;
8906
8907 while ((insn = NEXT_INSN (insn)))
8908 {
ec8e098d 8909 rtx set;
90e7678c
DC
8910 code = GET_CODE (insn);
8911
8912#if 0
8913 /* If this is a label that existed before reload, then the register
8914 if dead here. However, if this is a label added by reorg, then
8915 the register may still be live here. We can't tell the difference,
8916 so we just ignore labels completely. */
8917 if (code == CODE_LABEL)
8918 return 1;
8919 /* else */
8920#endif
8921
ec8e098d
PB
8922 if (!INSN_P (insn))
8923 continue;
8924
90e7678c
DC
8925 if (code == JUMP_INSN)
8926 return 0;
8927
8928 /* If this is a sequence, we must handle them all at once.
8929 We could have for instance a call that sets the target register,
e03f5d43 8930 and an insn in a delay slot that uses the register. In this case,
90e7678c
DC
8931 we must return 0. */
8932 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
8933 {
e8a54173 8934 rtx_sequence *seq = as_a <rtx_sequence *> (PATTERN (insn));
90e7678c
DC
8935 int i;
8936 int retval = 0;
8937
e8a54173 8938 for (i = 0; i < seq->len (); i++)
90e7678c 8939 {
e8a54173 8940 rtx_insn *this_insn = seq->insn (i);
90e7678c
DC
8941 rtx set = single_set (this_insn);
8942
b64925dc 8943 if (CALL_P (this_insn))
90e7678c 8944 code = CALL_INSN;
b64925dc 8945 else if (JUMP_P (this_insn))
90e7678c
DC
8946 {
8947 if (INSN_ANNULLED_BRANCH_P (this_insn))
8948 return 0;
8949 code = JUMP_INSN;
8950 }
8951
8952 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
8953 return 0;
8954 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
8955 {
8956 if (GET_CODE (SET_DEST (set)) != MEM)
8957 retval = 1;
8958 else
8959 return 0;
8960 }
8961 if (set == 0
8962 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
8963 return 0;
8964 }
8965 if (retval == 1)
8966 return 1;
8967 else if (code == JUMP_INSN)
8968 return 0;
8969 }
8970
8971 if (code == CALL_INSN)
8972 {
8973 rtx tem;
8974 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
8975 if (GET_CODE (XEXP (tem, 0)) == USE
8976 && REG_P (XEXP (XEXP (tem, 0), 0))
8977 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
8978 return 0;
00892272 8979 if (call_used_regs[REGNO (reg)])
90e7678c
DC
8980 return 1;
8981 }
8982
ec8e098d 8983 set = single_set (insn);
90e7678c 8984
ec8e098d
PB
8985 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
8986 return 0;
8987 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
8988 return GET_CODE (SET_DEST (set)) != MEM;
8989 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
8990 return 0;
90e7678c
DC
8991 }
8992 return 1;
8993}
8994
7bc6df2c 8995
00892272 8996/* Implement `TARGET_ASM_INTEGER'. */
301d03af
RS
8997/* Target hook for assembling integer objects. The AVR version needs
8998 special handling for references to certain labels. */
90e7678c 8999
301d03af 9000static bool
269e3795 9001avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
90e7678c 9002{
301d03af 9003 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
5bb53d1a 9004 && text_segment_operand (x, VOIDmode))
90e7678c 9005 {
693092fb 9006 fputs ("\t.word\tgs(", asm_out_file);
301d03af
RS
9007 output_addr_const (asm_out_file, x);
9008 fputs (")\n", asm_out_file);
00892272 9009
7bc6df2c
GJL
9010 return true;
9011 }
9012 else if (GET_MODE (x) == PSImode)
9013 {
5bb53d1a
GJL
9014 /* This needs binutils 2.23+, see PR binutils/13503 */
9015
9016 fputs ("\t.byte\tlo8(", asm_out_file);
9017 output_addr_const (asm_out_file, x);
9018 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
00892272 9019
5bb53d1a 9020 fputs ("\t.byte\thi8(", asm_out_file);
7bc6df2c 9021 output_addr_const (asm_out_file, x);
5bb53d1a 9022 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
00892272 9023
5bb53d1a 9024 fputs ("\t.byte\thh8(", asm_out_file);
7bc6df2c 9025 output_addr_const (asm_out_file, x);
5bb53d1a 9026 fputs (")" ASM_COMMENT_START "need binutils PR13503\n", asm_out_file);
00892272 9027
301d03af 9028 return true;
90e7678c 9029 }
e55e4056
GJL
9030 else if (CONST_FIXED_P (x))
9031 {
9032 unsigned n;
9033
9034 /* varasm fails to handle big fixed modes that don't fit in hwi. */
9035
9036 for (n = 0; n < size; n++)
9037 {
9038 rtx xn = simplify_gen_subreg (QImode, x, GET_MODE (x), n);
9039 default_assemble_integer (xn, 1, aligned_p);
9040 }
9041
9042 return true;
9043 }
00892272 9044
c25e1d82
GJL
9045 if (AVR_TINY
9046 && avr_address_tiny_pm_p (x))
9047 {
9048 x = plus_constant (Pmode, x, AVR_TINY_PM_OFFSET);
9049 }
9050
301d03af 9051 return default_assemble_integer (x, size, aligned_p);
90e7678c
DC
9052}
9053
7bc6df2c 9054
00892272 9055/* Implement `TARGET_CLASS_LIKELY_SPILLED_P'. */
90e7678c
DC
9056/* Return value is nonzero if pseudos that have been
9057 assigned to registers of class CLASS would likely be spilled
9058 because registers of CLASS are needed for spill registers. */
9059
c21136ee
AS
9060static bool
9061avr_class_likely_spilled_p (reg_class_t c)
90e7678c 9062{
c1dd9790
JR
9063 return (c != ALL_REGS &&
9064 (AVR_TINY ? 1 : c != ADDW_REGS));
90e7678c
DC
9065}
9066
90e7678c 9067
00892272
GJL
9068/* Valid attributes:
9069 progmem - Put data to program memory.
9070 signal - Make a function to be hardware interrupt.
9071 After function prologue interrupts remain disabled.
9072 interrupt - Make a function to be hardware interrupt. Before function
9073 prologue interrupts are enabled by means of SEI.
9074 naked - Don't generate function prologue/epilogue and RET
9075 instruction. */
91d231cb 9076
91d231cb
JM
9077/* Handle a "progmem" attribute; arguments as in
9078 struct attribute_spec.handler. */
00892272 9079
91d231cb 9080static tree
269e3795
SB
9081avr_handle_progmem_attribute (tree *node, tree name,
9082 tree args ATTRIBUTE_UNUSED,
9083 int flags ATTRIBUTE_UNUSED,
9084 bool *no_add_attrs)
91d231cb
JM
9085{
9086 if (DECL_P (*node))
90e7678c 9087 {
b47cae3d
MM
9088 if (TREE_CODE (*node) == TYPE_DECL)
9089 {
9090 /* This is really a decl attribute, not a type attribute,
9091 but try to handle it for GCC 3.0 backwards compatibility. */
9092
9093 tree type = TREE_TYPE (*node);
9094 tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
9095 tree newtype = build_type_attribute_variant (type, attr);
9096
9097 TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
9098 TREE_TYPE (*node) = newtype;
9099 *no_add_attrs = true;
9100 }
9101 else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
90e7678c 9102 {
946c8b23 9103 *no_add_attrs = false;
91d231cb
JM
9104 }
9105 else
9106 {
29d08eba
JM
9107 warning (OPT_Wattributes, "%qE attribute ignored",
9108 name);
91d231cb 9109 *no_add_attrs = true;
90e7678c 9110 }
90e7678c 9111 }
91d231cb
JM
9112
9113 return NULL_TREE;
90e7678c
DC
9114}
9115
91d231cb
JM
9116/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
9117 struct attribute_spec.handler. */
269e3795 9118
91d231cb 9119static tree
269e3795
SB
9120avr_handle_fndecl_attribute (tree *node, tree name,
9121 tree args ATTRIBUTE_UNUSED,
9122 int flags ATTRIBUTE_UNUSED,
9123 bool *no_add_attrs)
91d231cb
JM
9124{
9125 if (TREE_CODE (*node) != FUNCTION_DECL)
9126 {
29d08eba
JM
9127 warning (OPT_Wattributes, "%qE attribute only applies to functions",
9128 name);
91d231cb
JM
9129 *no_add_attrs = true;
9130 }
9131
9132 return NULL_TREE;
9133}
90e7678c 9134
44190aed
AS
9135static tree
9136avr_handle_fntype_attribute (tree *node, tree name,
9137 tree args ATTRIBUTE_UNUSED,
9138 int flags ATTRIBUTE_UNUSED,
9139 bool *no_add_attrs)
9140{
9141 if (TREE_CODE (*node) != FUNCTION_TYPE)
9142 {
29d08eba
JM
9143 warning (OPT_Wattributes, "%qE attribute only applies to functions",
9144 name);
44190aed
AS
9145 *no_add_attrs = true;
9146 }
9147
9148 return NULL_TREE;
9149}
9150
f9d29866
JR
9151static tree
9152avr_handle_addr_attribute (tree *node, tree name, tree args,
9153 int flags ATTRIBUTE_UNUSED, bool *no_add)
9154{
9155 bool io_p = (strncmp (IDENTIFIER_POINTER (name), "io", 2) == 0);
9156 location_t loc = DECL_SOURCE_LOCATION (*node);
9157
9158 if (TREE_CODE (*node) != VAR_DECL)
9159 {
9160 warning_at (loc, 0, "%qE attribute only applies to variables", name);
9161 *no_add = true;
9162 }
9163
9164 if (args != NULL_TREE)
9165 {
9166 if (TREE_CODE (TREE_VALUE (args)) == NON_LVALUE_EXPR)
9167 TREE_VALUE (args) = TREE_OPERAND (TREE_VALUE (args), 0);
9168 tree arg = TREE_VALUE (args);
9169 if (TREE_CODE (arg) != INTEGER_CST)
9170 {
9171 warning (0, "%qE attribute allows only an integer constant argument",
9172 name);
9173 *no_add = true;
9174 }
9175 else if (io_p
9176 && (!tree_fits_shwi_p (arg)
9177 || !(strcmp (IDENTIFIER_POINTER (name), "io_low") == 0
9178 ? low_io_address_operand : io_address_operand)
9179 (GEN_INT (TREE_INT_CST_LOW (arg)), QImode)))
9180 {
9181 warning_at (loc, 0, "%qE attribute address out of range", name);
9182 *no_add = true;
9183 }
9184 else
9185 {
9186 tree attribs = DECL_ATTRIBUTES (*node);
9187 const char *names[] = { "io", "io_low", "address", NULL } ;
9188 for (const char **p = names; *p; p++)
9189 {
9190 tree other = lookup_attribute (*p, attribs);
9191 if (other && TREE_VALUE (other))
9192 {
9193 warning_at (loc, 0,
9194 "both %s and %qE attribute provide address",
9195 *p, name);
9196 *no_add = true;
9197 break;
9198 }
9199 }
9200 }
9201 }
9202
9203 if (*no_add == false && io_p && !TREE_THIS_VOLATILE (*node))
9204 warning_at (loc, 0, "%qE attribute on non-volatile variable", name);
9205
9206 return NULL_TREE;
9207}
9208
9209rtx
9210avr_eval_addr_attrib (rtx x)
9211{
9212 if (GET_CODE (x) == SYMBOL_REF
9213 && (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_ADDRESS))
9214 {
9215 tree decl = SYMBOL_REF_DECL (x);
9216 tree attr = NULL_TREE;
9217
9218 if (SYMBOL_REF_FLAGS (x) & SYMBOL_FLAG_IO)
9219 {
9220 attr = lookup_attribute ("io", DECL_ATTRIBUTES (decl));
b52ec220
SKS
9221 if (!attr || !TREE_VALUE (attr))
9222 attr = lookup_attribute ("io_low", DECL_ATTRIBUTES (decl));
f9d29866
JR
9223 gcc_assert (attr);
9224 }
9225 if (!attr || !TREE_VALUE (attr))
9226 attr = lookup_attribute ("address", DECL_ATTRIBUTES (decl));
9227 gcc_assert (attr && TREE_VALUE (attr) && TREE_VALUE (TREE_VALUE (attr)));
9228 return GEN_INT (TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr))));
9229 }
9230 return x;
9231}
9232
d2111e2f
GJL
9233
9234/* AVR attributes. */
9235static const struct attribute_spec
9236avr_attribute_table[] =
9237{
9238 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
9239 affects_type_identity } */
9240 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute,
9241 false },
9242 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute,
9243 false },
9244 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute,
9245 false },
9246 { "naked", 0, 0, false, true, true, avr_handle_fntype_attribute,
9247 false },
9248 { "OS_task", 0, 0, false, true, true, avr_handle_fntype_attribute,
9249 false },
9250 { "OS_main", 0, 0, false, true, true, avr_handle_fntype_attribute,
9251 false },
f9d29866
JR
9252 { "io", 0, 1, false, false, false, avr_handle_addr_attribute,
9253 false },
9254 { "io_low", 0, 1, false, false, false, avr_handle_addr_attribute,
9255 false },
9256 { "address", 1, 1, false, false, false, avr_handle_addr_attribute,
9257 false },
d2111e2f
GJL
9258 { NULL, 0, 0, false, false, false, NULL, false }
9259};
9260
7c209481 9261
2d06ca74
GJL
9262/* Return true if we support address space AS for the architecture in effect
9263 and false, otherwise. If LOC is not UNKNOWN_LOCATION then also issue
9264 a respective error. */
9265
9266bool
9267avr_addr_space_supported_p (addr_space_t as, location_t loc)
9268{
9269 if (AVR_TINY)
9270 {
9271 if (loc != UNKNOWN_LOCATION)
9272 error_at (loc, "address spaces are not supported for reduced "
9273 "Tiny devices");
9274 return false;
9275 }
9276 else if (avr_addrspace[as].segment >= avr_n_flash)
9277 {
9278 if (loc != UNKNOWN_LOCATION)
9279 error_at (loc, "address space %qs not supported for devices with "
9280 "flash size up to %d KiB", avr_addrspace[as].name,
9281 64 * avr_n_flash);
9282 return false;
9283 }
9284
9285 return true;
9286}
9287
9288
9289/* Implement `TARGET_ADDR_SPACE_DIAGNOSE_USAGE'. */
9290
9291static void
9292avr_addr_space_diagnose_usage (addr_space_t as, location_t loc)
9293{
9294 (void) avr_addr_space_supported_p (as, loc);
9295}
9296
9297
7c209481
GJL
9298/* Look if DECL shall be placed in program memory space by
9299 means of attribute `progmem' or some address-space qualifier.
9300 Return non-zero if DECL is data that must end up in Flash and
9301 zero if the data lives in RAM (.bss, .data, .rodata, ...).
00892272 9302
7bc6df2c 9303 Return 2 if DECL is located in 24-bit flash address-space
7c209481
GJL
9304 Return 1 if DECL is located in 16-bit flash address-space
9305 Return -1 if attribute `progmem' occurs in DECL or ATTRIBUTES
9306 Return 0 otherwise */
90e7678c
DC
9307
9308int
427ee360 9309avr_progmem_p (tree decl, tree attributes)
90e7678c
DC
9310{
9311 tree a;
9312
9313 if (TREE_CODE (decl) != VAR_DECL)
9314 return 0;
9315
3a840863 9316 if (avr_decl_memx_p (decl))
7bc6df2c
GJL
9317 return 2;
9318
3a840863 9319 if (avr_decl_flash_p (decl))
7c209481
GJL
9320 return 1;
9321
90e7678c 9322 if (NULL_TREE
427ee360 9323 != lookup_attribute ("progmem", attributes))
7c209481 9324 return -1;
90e7678c 9325
7c209481 9326 a = decl;
00892272 9327
90e7678c
DC
9328 do
9329 a = TREE_TYPE(a);
9330 while (TREE_CODE (a) == ARRAY_TYPE);
9331
89741abb
MM
9332 if (a == error_mark_node)
9333 return 0;
9334
90e7678c 9335 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
7c209481 9336 return -1;
00892272 9337
90e7678c
DC
9338 return 0;
9339}
9340
7c209481
GJL
9341
9342/* Scan type TYP for pointer references to address space ASn.
9343 Return ADDR_SPACE_GENERIC (i.e. 0) if all pointers targeting
9344 the AS are also declared to be CONST.
073a8998 9345 Otherwise, return the respective address space, i.e. a value != 0. */
00892272 9346
7c209481
GJL
9347static addr_space_t
9348avr_nonconst_pointer_addrspace (tree typ)
9349{
9350 while (ARRAY_TYPE == TREE_CODE (typ))
9351 typ = TREE_TYPE (typ);
9352
9353 if (POINTER_TYPE_P (typ))
9354 {
bae3b1bf 9355 addr_space_t as;
7c209481
GJL
9356 tree target = TREE_TYPE (typ);
9357
9358 /* Pointer to function: Test the function's return type. */
00892272 9359
7c209481
GJL
9360 if (FUNCTION_TYPE == TREE_CODE (target))
9361 return avr_nonconst_pointer_addrspace (TREE_TYPE (target));
9362
9363 /* "Ordinary" pointers... */
9364
9365 while (TREE_CODE (target) == ARRAY_TYPE)
9366 target = TREE_TYPE (target);
9367
2d06ca74 9368 /* Pointers to non-generic address space must be const. */
00892272 9369
bae3b1bf 9370 as = TYPE_ADDR_SPACE (target);
00892272 9371
bae3b1bf 9372 if (!ADDR_SPACE_GENERIC_P (as)
2d06ca74
GJL
9373 && !TYPE_READONLY (target)
9374 && avr_addr_space_supported_p (as))
bae3b1bf
GJL
9375 {
9376 return as;
7c209481
GJL
9377 }
9378
9379 /* Scan pointer's target type. */
00892272 9380
7c209481
GJL
9381 return avr_nonconst_pointer_addrspace (target);
9382 }
9383
9384 return ADDR_SPACE_GENERIC;
9385}
9386
9387
073a8998 9388/* Sanity check NODE so that all pointers targeting non-generic address spaces
3a840863 9389 go along with CONST qualifier. Writing to these address spaces should
7c209481
GJL
9390 be detected and complained about as early as possible. */
9391
9392static bool
9393avr_pgm_check_var_decl (tree node)
9394{
9395 const char *reason = NULL;
00892272 9396
7c209481
GJL
9397 addr_space_t as = ADDR_SPACE_GENERIC;
9398
9399 gcc_assert (as == 0);
00892272 9400
7c209481
GJL
9401 if (avr_log.progmem)
9402 avr_edump ("%?: %t\n", node);
00892272 9403
7c209481
GJL
9404 switch (TREE_CODE (node))
9405 {
9406 default:
9407 break;
9408
9409 case VAR_DECL:
9410 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
9411 reason = "variable";
9412 break;
9413
9414 case PARM_DECL:
9415 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
9416 reason = "function parameter";
9417 break;
00892272 9418
7c209481
GJL
9419 case FIELD_DECL:
9420 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (node)), as)
9421 reason = "structure field";
9422 break;
00892272 9423
7c209481
GJL
9424 case FUNCTION_DECL:
9425 if (as = avr_nonconst_pointer_addrspace (TREE_TYPE (TREE_TYPE (node))),
9426 as)
9427 reason = "return type of function";
9428 break;
9429
9430 case POINTER_TYPE:
9431 if (as = avr_nonconst_pointer_addrspace (node), as)
9432 reason = "pointer";
9433 break;
9434 }
9435
9436 if (reason)
9437 {
2d06ca74
GJL
9438 if (TYPE_P (node))
9439 error ("pointer targeting address space %qs must be const in %qT",
9440 avr_addrspace[as].name, node);
7c209481 9441 else
2d06ca74
GJL
9442 error ("pointer targeting address space %qs must be const"
9443 " in %s %q+D",
9444 avr_addrspace[as].name, reason, node);
7c209481
GJL
9445 }
9446
9447 return reason == NULL;
9448}
9449
9450
74b66b3c
RH
9451/* Add the section attribute if the variable is in progmem. */
9452
fb49053f 9453static void
269e3795 9454avr_insert_attributes (tree node, tree *attributes)
90e7678c 9455{
7c209481
GJL
9456 avr_pgm_check_var_decl (node);
9457
74b66b3c
RH
9458 if (TREE_CODE (node) == VAR_DECL
9459 && (TREE_STATIC (node) || DECL_EXTERNAL (node))
427ee360 9460 && avr_progmem_p (node, *attributes))
90e7678c 9461 {
bae3b1bf 9462 addr_space_t as;
db297e20
GJL
9463 tree node0 = node;
9464
9465 /* For C++, we have to peel arrays in order to get correct
9466 determination of readonlyness. */
00892272 9467
db297e20
GJL
9468 do
9469 node0 = TREE_TYPE (node0);
9470 while (TREE_CODE (node0) == ARRAY_TYPE);
9471
9472 if (error_mark_node == node0)
9473 return;
bae3b1bf
GJL
9474
9475 as = TYPE_ADDR_SPACE (TREE_TYPE (node));
9476
7c209481
GJL
9477 if (!TYPE_READONLY (node0)
9478 && !TREE_READONLY (node))
8a9b55f3 9479 {
7c209481
GJL
9480 const char *reason = "__attribute__((progmem))";
9481
9482 if (!ADDR_SPACE_GENERIC_P (as))
562f552b 9483 reason = avr_addrspace[as].name;
00892272 9484
7c209481
GJL
9485 if (avr_log.progmem)
9486 avr_edump ("\n%?: %t\n%t\n", node, node0);
00892272 9487
8a9b55f3 9488 error ("variable %q+D must be const in order to be put into"
7c209481 9489 " read-only section by means of %qs", node, reason);
8a9b55f3 9490 }
90e7678c 9491 }
772c5265 9492}
90e7678c 9493
516edfdd
GJL
9494
9495/* Implement `ASM_OUTPUT_ALIGNED_DECL_LOCAL'. */
9496/* Implement `ASM_OUTPUT_ALIGNED_DECL_COMMON'. */
9497/* Track need of __do_clear_bss. */
9498
9499void
d2111e2f 9500avr_asm_output_aligned_decl_common (FILE * stream,
f9d29866 9501 tree decl,
d2111e2f
GJL
9502 const char *name,
9503 unsigned HOST_WIDE_INT size,
516edfdd
GJL
9504 unsigned int align, bool local_p)
9505{
f9d29866
JR
9506 rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
9507 rtx symbol;
9508
9509 if (mem != NULL_RTX && MEM_P (mem)
9510 && GET_CODE ((symbol = XEXP (mem, 0))) == SYMBOL_REF
9511 && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
9512 {
9513
9514 if (!local_p)
9515 {
9516 fprintf (stream, "\t.globl\t");
9517 assemble_name (stream, name);
9518 fprintf (stream, "\n");
9519 }
9520 if (SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS)
9521 {
9522 assemble_name (stream, name);
9523 fprintf (stream, " = %ld\n",
9524 (long) INTVAL (avr_eval_addr_attrib (symbol)));
9525 }
9526 else if (local_p)
9527 error_at (DECL_SOURCE_LOCATION (decl),
9528 "static IO declaration for %q+D needs an address", decl);
9529 return;
9530 }
9531
219db888
GJL
9532 /* __gnu_lto_v1 etc. are just markers for the linker injected by toplev.c.
9533 There is no need to trigger __do_clear_bss code for them. */
9534
9535 if (!STR_PREFIX_P (name, "__gnu_lto"))
9536 avr_need_clear_bss_p = true;
516edfdd
GJL
9537
9538 if (local_p)
880962ac
GJL
9539 ASM_OUTPUT_ALIGNED_LOCAL (stream, name, size, align);
9540 else
9541 ASM_OUTPUT_ALIGNED_COMMON (stream, name, size, align);
516edfdd
GJL
9542}
9543
f9d29866
JR
9544void
9545avr_asm_asm_output_aligned_bss (FILE *file, tree decl, const char *name,
9546 unsigned HOST_WIDE_INT size, int align,
9547 void (*default_func)
9548 (FILE *, tree, const char *,
9549 unsigned HOST_WIDE_INT, int))
9550{
9551 rtx mem = decl == NULL_TREE ? NULL_RTX : DECL_RTL (decl);
9552 rtx symbol;
9553
9554 if (mem != NULL_RTX && MEM_P (mem)
9555 && GET_CODE ((symbol = XEXP (mem, 0))) == SYMBOL_REF
9556 && (SYMBOL_REF_FLAGS (symbol) & (SYMBOL_FLAG_IO | SYMBOL_FLAG_ADDRESS)))
9557 {
9558 if (!(SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_ADDRESS))
9559 error_at (DECL_SOURCE_LOCATION (decl),
9560 "IO definition for %q+D needs an address", decl);
9561 avr_asm_output_aligned_decl_common (file, decl, name, size, align, false);
9562 }
9563 else
9564 default_func (file, decl, name, size, align);
9565}
9566
516edfdd
GJL
9567
9568/* Unnamed section callback for data_section
9569 to track need of __do_copy_data. */
9570
9571static void
9572avr_output_data_section_asm_op (const void *data)
9573{
9574 avr_need_copy_data_p = true;
00892272 9575
516edfdd
GJL
9576 /* Dispatch to default. */
9577 output_section_asm_op (data);
9578}
9579
9580
9581/* Unnamed section callback for bss_section
9582 to track need of __do_clear_bss. */
9583
9584static void
9585avr_output_bss_section_asm_op (const void *data)
9586{
9587 avr_need_clear_bss_p = true;
00892272 9588
516edfdd
GJL
9589 /* Dispatch to default. */
9590 output_section_asm_op (data);
9591}
9592
9593
7bc6df2c
GJL
9594/* Unnamed section callback for progmem*.data sections. */
9595
9596static void
9597avr_output_progmem_section_asm_op (const void *data)
9598{
9599 fprintf (asm_out_file, "\t.section\t%s,\"a\",@progbits\n",
9600 (const char*) data);
9601}
9602
9603
516edfdd 9604/* Implement `TARGET_ASM_INIT_SECTIONS'. */
d6b5193b
RS
9605
9606static void
9607avr_asm_init_sections (void)
9608{
eb1dcdff
GJL
9609 /* Override section callbacks to keep track of `avr_need_clear_bss_p'
9610 resp. `avr_need_copy_data_p'. */
00892272 9611
eb1dcdff 9612 readonly_data_section->unnamed.callback = avr_output_data_section_asm_op;
516edfdd
GJL
9613 data_section->unnamed.callback = avr_output_data_section_asm_op;
9614 bss_section->unnamed.callback = avr_output_bss_section_asm_op;
9615}
9616
9617
9618/* Implement `TARGET_ASM_NAMED_SECTION'. */
9619/* Track need of __do_clear_bss, __do_copy_data for named sections. */
9620
eb1dcdff 9621static void
516edfdd
GJL
9622avr_asm_named_section (const char *name, unsigned int flags, tree decl)
9623{
886a64f9
GJL
9624 if (flags & AVR_SECTION_PROGMEM)
9625 {
562f552b 9626 addr_space_t as = (flags & AVR_SECTION_PROGMEM) / SECTION_MACH_DEP;
886a64f9 9627 const char *old_prefix = ".rodata";
e5669488
GJL
9628 const char *new_prefix = avr_addrspace[as].section_name;
9629
886a64f9
GJL
9630 if (STR_PREFIX_P (name, old_prefix))
9631 {
543a341c
GJL
9632 const char *sname = ACONCAT ((new_prefix,
9633 name + strlen (old_prefix), NULL));
9634 default_elf_asm_named_section (sname, flags, decl);
9635 return;
886a64f9
GJL
9636 }
9637
543a341c 9638 default_elf_asm_named_section (new_prefix, flags, decl);
886a64f9
GJL
9639 return;
9640 }
00892272 9641
516edfdd 9642 if (!avr_need_copy_data_p)
f2814222
GJL
9643 avr_need_copy_data_p = (STR_PREFIX_P (name, ".data")
9644 || STR_PREFIX_P (name, ".rodata")
9645 || STR_PREFIX_P (name, ".gnu.linkonce.d"));
00892272 9646
516edfdd 9647 if (!avr_need_clear_bss_p)
f2814222 9648 avr_need_clear_bss_p = STR_PREFIX_P (name, ".bss");
00892272 9649
516edfdd 9650 default_elf_asm_named_section (name, flags, decl);
d6b5193b
RS
9651}
9652
00892272
GJL
9653
9654/* Implement `TARGET_SECTION_TYPE_FLAGS'. */
9655
c16e5a35 9656static unsigned int
269e3795 9657avr_section_type_flags (tree decl, const char *name, int reloc)
c16e5a35
MM
9658{
9659 unsigned int flags = default_section_type_flags (decl, name, reloc);
9660
f2814222 9661 if (STR_PREFIX_P (name, ".noinit"))
c16e5a35
MM
9662 {
9663 if (decl && TREE_CODE (decl) == VAR_DECL
9664 && DECL_INITIAL (decl) == NULL_TREE)
9665 flags |= SECTION_BSS; /* @nobits */
9666 else
d4ee4d25 9667 warning (0, "only uninitialized variables can be placed in the "
c16e5a35
MM
9668 ".noinit section");
9669 }
9670
886a64f9 9671 if (decl && DECL_P (decl)
562f552b 9672 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
886a64f9 9673 {
562f552b
GJL
9674 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
9675
9676 /* Attribute progmem puts data in generic address space.
3a840863 9677 Set section flags as if it was in __flash to get the right
562f552b 9678 section prefix in the remainder. */
7bc6df2c 9679
562f552b 9680 if (ADDR_SPACE_GENERIC_P (as))
3a840863 9681 as = ADDR_SPACE_FLASH;
7bc6df2c 9682
562f552b 9683 flags |= as * SECTION_MACH_DEP;
886a64f9 9684 flags &= ~SECTION_WRITE;
7c209481 9685 flags &= ~SECTION_BSS;
886a64f9 9686 }
00892272 9687
c16e5a35
MM
9688 return flags;
9689}
9690
516edfdd 9691
946c8b23
GJL
9692/* Implement `TARGET_ENCODE_SECTION_INFO'. */
9693
9694static void
562f552b 9695avr_encode_section_info (tree decl, rtx rtl, int new_decl_p)
946c8b23
GJL
9696{
9697 /* In avr_handle_progmem_attribute, DECL_INITIAL is not yet
9698 readily available, see PR34734. So we postpone the warning
9699 about uninitialized data in program memory section until here. */
00892272 9700
946c8b23
GJL
9701 if (new_decl_p
9702 && decl && DECL_P (decl)
9703 && NULL_TREE == DECL_INITIAL (decl)
ab8c5093 9704 && !DECL_EXTERNAL (decl)
946c8b23
GJL
9705 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
9706 {
9707 warning (OPT_Wuninitialized,
9708 "uninitialized variable %q+D put into "
9709 "program memory area", decl);
9710 }
d17fc175
GJL
9711
9712 default_encode_section_info (decl, rtl, new_decl_p);
cba300dd
GJL
9713
9714 if (decl && DECL_P (decl)
9715 && TREE_CODE (decl) != FUNCTION_DECL
9716 && MEM_P (rtl)
c25e1d82 9717 && SYMBOL_REF_P (XEXP (rtl, 0)))
cba300dd
GJL
9718 {
9719 rtx sym = XEXP (rtl, 0);
6e022d7b 9720 tree type = TREE_TYPE (decl);
f9d29866 9721 tree attr = DECL_ATTRIBUTES (decl);
6e022d7b
JR
9722 if (type == error_mark_node)
9723 return;
f9d29866 9724
6e022d7b 9725 addr_space_t as = TYPE_ADDR_SPACE (type);
cba300dd
GJL
9726
9727 /* PSTR strings are in generic space but located in flash:
9728 patch address space. */
00892272 9729
c25e1d82
GJL
9730 if (!AVR_TINY
9731 && -1 == avr_progmem_p (decl, attr))
3a840863 9732 as = ADDR_SPACE_FLASH;
cba300dd
GJL
9733
9734 AVR_SYMBOL_SET_ADDR_SPACE (sym, as);
f9d29866
JR
9735
9736 tree io_low_attr = lookup_attribute ("io_low", attr);
9737 tree io_attr = lookup_attribute ("io", attr);
9738 tree addr_attr;
9739 if (io_low_attr
9740 && TREE_VALUE (io_low_attr) && TREE_VALUE (TREE_VALUE (io_low_attr)))
9741 addr_attr = io_attr;
9742 else if (io_attr
9743 && TREE_VALUE (io_attr) && TREE_VALUE (TREE_VALUE (io_attr)))
9744 addr_attr = io_attr;
9745 else
9746 addr_attr = lookup_attribute ("address", attr);
9747 if (io_low_attr
0c9ef7ad
GJL
9748 || (io_attr && addr_attr
9749 && low_io_address_operand
9750 (GEN_INT (TREE_INT_CST_LOW
9751 (TREE_VALUE (TREE_VALUE (addr_attr)))), QImode)))
f9d29866
JR
9752 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO_LOW;
9753 if (io_attr || io_low_attr)
9754 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_IO;
9755 /* If we have an (io) address attribute specification, but the variable
9756 is external, treat the address as only a tentative definition
9757 to be used to determine if an io port is in the lower range, but
9758 don't use the exact value for constant propagation. */
9759 if (addr_attr && !DECL_EXTERNAL (decl))
9760 SYMBOL_REF_FLAGS (sym) |= SYMBOL_FLAG_ADDRESS;
cba300dd 9761 }
c25e1d82
GJL
9762
9763 if (AVR_TINY
9764 && decl
9765 && VAR_DECL == TREE_CODE (decl)
9766 && -1 == avr_progmem_p (decl, DECL_ATTRIBUTES (decl))
9767 && MEM_P (rtl)
9768 && SYMBOL_REF_P (XEXP (rtl, 0)))
9769 {
9770 /* Tag symbols for later addition of 0x4000 (AVR_TINY_PM_OFFSET). */
9771
9772 rtx sym = XEXP (rtl, 0);
9773 SYMBOL_REF_FLAGS (sym) |= AVR_SYMBOL_FLAG_TINY_PM;
9774 }
946c8b23
GJL
9775}
9776
9777
886a64f9
GJL
9778/* Implement `TARGET_ASM_SELECT_SECTION' */
9779
9780static section *
9781avr_asm_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
9782{
9783 section * sect = default_elf_select_section (decl, reloc, align);
00892272 9784
886a64f9 9785 if (decl && DECL_P (decl)
562f552b 9786 && avr_progmem_p (decl, DECL_ATTRIBUTES (decl)))
886a64f9 9787 {
562f552b 9788 addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
e5669488
GJL
9789
9790 /* __progmem__ goes in generic space but shall be allocated to
9791 .progmem.data */
9792
9793 if (ADDR_SPACE_GENERIC_P (as))
9794 as = ADDR_SPACE_FLASH;
00892272 9795
886a64f9
GJL
9796 if (sect->common.flags & SECTION_NAMED)
9797 {
9798 const char * name = sect->named.name;
9799 const char * old_prefix = ".rodata";
e5669488 9800 const char * new_prefix = avr_addrspace[as].section_name;
886a64f9
GJL
9801
9802 if (STR_PREFIX_P (name, old_prefix))
9803 {
543a341c
GJL
9804 const char *sname = ACONCAT ((new_prefix,
9805 name + strlen (old_prefix), NULL));
7b4e0769
SKS
9806 return get_section (sname,
9807 sect->common.flags & ~SECTION_DECLARED,
9808 sect->named.decl);
886a64f9
GJL
9809 }
9810 }
e5669488
GJL
9811
9812 if (!progmem_section[as])
9813 {
9814 progmem_section[as]
9815 = get_unnamed_section (0, avr_output_progmem_section_asm_op,
9816 avr_addrspace[as].section_name);
9817 }
9818
9819 return progmem_section[as];
886a64f9
GJL
9820 }
9821
9822 return sect;
9823}
9824
516edfdd 9825/* Implement `TARGET_ASM_FILE_START'. */
7bc6df2c 9826/* Outputs some text at the start of each assembler file. */
90e7678c 9827
1bc7c5b6 9828static void
269e3795 9829avr_file_start (void)
90e7678c 9830{
4a2caf6c 9831 int sfr_offset = avr_arch->sfr_offset;
7bc6df2c 9832
4a2caf6c
GJL
9833 if (avr_arch->asm_only)
9834 error ("architecture %qs supported for assembler only", avr_mmcu);
bcb6a2be 9835
1bc7c5b6
ZW
9836 default_file_start ();
9837
82b37806
GJL
9838 /* Print I/O addresses of some SFRs used with IN and OUT. */
9839
7fd6378e 9840 if (AVR_HAVE_SPH)
82b37806 9841 fprintf (asm_out_file, "__SP_H__ = 0x%02x\n", avr_addr.sp_h - sfr_offset);
28c5e6b5 9842
82b37806
GJL
9843 fprintf (asm_out_file, "__SP_L__ = 0x%02x\n", avr_addr.sp_l - sfr_offset);
9844 fprintf (asm_out_file, "__SREG__ = 0x%02x\n", avr_addr.sreg - sfr_offset);
2da8c1ad
GJL
9845 if (AVR_HAVE_RAMPZ)
9846 fprintf (asm_out_file, "__RAMPZ__ = 0x%02x\n", avr_addr.rampz - sfr_offset);
9847 if (AVR_HAVE_RAMPY)
9848 fprintf (asm_out_file, "__RAMPY__ = 0x%02x\n", avr_addr.rampy - sfr_offset);
9849 if (AVR_HAVE_RAMPX)
9850 fprintf (asm_out_file, "__RAMPX__ = 0x%02x\n", avr_addr.rampx - sfr_offset);
9851 if (AVR_HAVE_RAMPD)
9852 fprintf (asm_out_file, "__RAMPD__ = 0x%02x\n", avr_addr.rampd - sfr_offset);
c1dd9790 9853 if (AVR_XMEGA || AVR_TINY)
2da8c1ad 9854 fprintf (asm_out_file, "__CCP__ = 0x%02x\n", avr_addr.ccp - sfr_offset);
c1dd9790
JR
9855 fprintf (asm_out_file, "__tmp_reg__ = %d\n", AVR_TMP_REGNO);
9856 fprintf (asm_out_file, "__zero_reg__ = %d\n", AVR_ZERO_REGNO);
90e7678c
DC
9857}
9858
516edfdd
GJL
9859
9860/* Implement `TARGET_ASM_FILE_END'. */
90e7678c
DC
9861/* Outputs to the stdio stream FILE some
9862 appropriate text to go at the end of an assembler file. */
9863
a5fe455b 9864static void
269e3795 9865avr_file_end (void)
90e7678c 9866{
516edfdd 9867 /* Output these only if there is anything in the
00892272 9868 .data* / .rodata* / .gnu.linkonce.* resp. .bss* or COMMON
516edfdd
GJL
9869 input section(s) - some code size can be saved by not
9870 linking in the initialization code from libgcc if resp.
00892272 9871 sections are empty, see PR18145. */
516edfdd
GJL
9872
9873 if (avr_need_copy_data_p)
9874 fputs (".global __do_copy_data\n", asm_out_file);
9875
9876 if (avr_need_clear_bss_p)
9877 fputs (".global __do_clear_bss\n", asm_out_file);
90e7678c
DC
9878}
9879
00892272
GJL
9880
9881/* Worker function for `ADJUST_REG_ALLOC_ORDER'. */
90e7678c
DC
9882/* Choose the order in which to allocate hard registers for
9883 pseudo-registers local to a basic block.
9884
9885 Store the desired register order in the array `reg_alloc_order'.
9886 Element 0 should be the register to allocate first; element 1, the
9887 next register; and so on. */
9888
9889void
00892272 9890avr_adjust_reg_alloc_order (void)
90e7678c
DC
9891{
9892 unsigned int i;
00892272
GJL
9893 static const int order_0[] =
9894 {
9895 24, 25,
9896 18, 19, 20, 21, 22, 23,
9897 30, 31,
9898 26, 27, 28, 29,
9899 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
9900 0, 1,
9901 32, 33, 34, 35
90e7678c 9902 };
c1dd9790
JR
9903 static const int tiny_order_0[] = {
9904 20, 21,
9905 22, 23,
9906 24, 25,
9907 30, 31,
9908 26, 27,
9909 28, 29,
9910 19, 18,
9911 16, 17,
9912 32, 33, 34, 35,
9913 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
9914 };
00892272
GJL
9915 static const int order_1[] =
9916 {
9917 18, 19, 20, 21, 22, 23, 24, 25,
9918 30, 31,
9919 26, 27, 28, 29,
9920 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
9921 0, 1,
9922 32, 33, 34, 35
90e7678c 9923 };
c1dd9790
JR
9924 static const int tiny_order_1[] = {
9925 22, 23,
9926 24, 25,
9927 30, 31,
9928 26, 27,
9929 28, 29,
9930 21, 20, 19, 18,
9931 16, 17,
9932 32, 33, 34, 35,
9933 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
9934 };
00892272
GJL
9935 static const int order_2[] =
9936 {
9937 25, 24, 23, 22, 21, 20, 19, 18,
9938 30, 31,
9939 26, 27, 28, 29,
9940 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
9941 1, 0,
9942 32, 33, 34, 35
90e7678c 9943 };
00892272 9944
0c9ef7ad
GJL
9945 /* Select specific register allocation order.
9946 Tiny Core (ATtiny4/5/9/10/20/40) devices have only 16 registers,
9947 so different allocation order should be used. */
9948
9949 const int *order = (TARGET_ORDER_1 ? (AVR_TINY ? tiny_order_1 : order_1)
9950 : TARGET_ORDER_2 ? (AVR_TINY ? tiny_order_0 : order_2)
9951 : (AVR_TINY ? tiny_order_0 : order_0));
c1dd9790 9952
00892272 9953 for (i = 0; i < ARRAY_SIZE (order_0); ++i)
90e7678c
DC
9954 reg_alloc_order[i] = order[i];
9955}
9956
8f2bf9f1 9957
5f892aa0
GJL
9958/* Implement `TARGET_REGISTER_MOVE_COST' */
9959
9960static int
ef4bddc2 9961avr_register_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
5f892aa0
GJL
9962 reg_class_t from, reg_class_t to)
9963{
9964 return (from == STACK_REG ? 6
9965 : to == STACK_REG ? 12
9966 : 2);
9967}
9968
9969
9970/* Implement `TARGET_MEMORY_MOVE_COST' */
9971
9972static int
ef4bddc2 9973avr_memory_move_cost (machine_mode mode,
d2111e2f 9974 reg_class_t rclass ATTRIBUTE_UNUSED,
5f892aa0
GJL
9975 bool in ATTRIBUTE_UNUSED)
9976{
9977 return (mode == QImode ? 2
9978 : mode == HImode ? 4
9979 : mode == SImode ? 8
9980 : mode == SFmode ? 8
9981 : 16);
9982}
9983
9984
8f2bf9f1
RS
9985/* Mutually recursive subroutine of avr_rtx_cost for calculating the
9986 cost of an RTX operand given its context. X is the rtx of the
9987 operand, MODE is its mode, and OUTER is the rtx_code of this
9988 operand's parent operator. */
90e7678c 9989
3c50106f 9990static int
ef4bddc2 9991avr_operand_rtx_cost (rtx x, machine_mode mode, enum rtx_code outer,
68f932c4 9992 int opno, bool speed)
90e7678c 9993{
8f2bf9f1
RS
9994 enum rtx_code code = GET_CODE (x);
9995 int total;
9996
90e7678c
DC
9997 switch (code)
9998 {
8f2bf9f1
RS
9999 case REG:
10000 case SUBREG:
10001 return 0;
10002
90e7678c 10003 case CONST_INT:
e55e4056 10004 case CONST_FIXED:
8f2bf9f1
RS
10005 case CONST_DOUBLE:
10006 return COSTS_N_INSNS (GET_MODE_SIZE (mode));
10007
90e7678c
DC
10008 default:
10009 break;
10010 }
8f2bf9f1
RS
10011
10012 total = 0;
e548c9df 10013 avr_rtx_costs (x, mode, outer, opno, &total, speed);
8f2bf9f1 10014 return total;
90e7678c
DC
10015}
10016
ab758510
GJL
10017/* Worker function for AVR backend's rtx_cost function.
10018 X is rtx expression whose cost is to be calculated.
10019 Return true if the complete cost has been computed.
10020 Return false if subexpressions should be scanned.
10021 In either case, *TOTAL contains the cost result. */
8f2bf9f1 10022
3c50106f 10023static bool
e548c9df 10024avr_rtx_costs_1 (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED,
ab758510 10025 int opno ATTRIBUTE_UNUSED, int *total, bool speed)
3c50106f 10026{
e548c9df 10027 enum rtx_code code = GET_CODE (x);
8f2bf9f1 10028 HOST_WIDE_INT val;
3c50106f
RH
10029
10030 switch (code)
10031 {
10032 case CONST_INT:
e55e4056 10033 case CONST_FIXED:
8f2bf9f1 10034 case CONST_DOUBLE:
73451ae7 10035 case SYMBOL_REF:
21f3ae2f
GJL
10036 case CONST:
10037 case LABEL_REF:
8f2bf9f1
RS
10038 /* Immediate constants are as cheap as registers. */
10039 *total = 0;
10040 return true;
10041
10042 case MEM:
8f2bf9f1
RS
10043 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
10044 return true;
10045
10046 case NEG:
10047 switch (mode)
3c50106f 10048 {
8f2bf9f1
RS
10049 case QImode:
10050 case SFmode:
10051 *total = COSTS_N_INSNS (1);
10052 break;
10053
e4fe948a
GJL
10054 case HImode:
10055 case PSImode:
10056 case SImode:
10057 *total = COSTS_N_INSNS (2 * GET_MODE_SIZE (mode) - 1);
10058 break;
8f2bf9f1
RS
10059
10060 default:
10061 return false;
3c50106f 10062 }
68f932c4 10063 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
8f2bf9f1
RS
10064 return true;
10065
10066 case ABS:
10067 switch (mode)
3c50106f 10068 {
8f2bf9f1
RS
10069 case QImode:
10070 case SFmode:
10071 *total = COSTS_N_INSNS (1);
10072 break;
10073
10074 default:
10075 return false;
3c50106f 10076 }
68f932c4 10077 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
8f2bf9f1 10078 return true;
3c50106f 10079
8f2bf9f1
RS
10080 case NOT:
10081 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
68f932c4 10082 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
3c50106f
RH
10083 return true;
10084
8f2bf9f1
RS
10085 case ZERO_EXTEND:
10086 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
10087 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
e548c9df
AM
10088 *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
10089 code, 0, speed);
8f2bf9f1
RS
10090 return true;
10091
10092 case SIGN_EXTEND:
10093 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
10094 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
e548c9df
AM
10095 *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
10096 code, 0, speed);
8f2bf9f1
RS
10097 return true;
10098
10099 case PLUS:
10100 switch (mode)
10101 {
10102 case QImode:
1b65da7d
GJL
10103 if (AVR_HAVE_MUL
10104 && MULT == GET_CODE (XEXP (x, 0))
10105 && register_operand (XEXP (x, 1), QImode))
10106 {
10107 /* multiply-add */
10108 *total = COSTS_N_INSNS (speed ? 4 : 3);
10109 /* multiply-add with constant: will be split and load constant. */
10110 if (CONST_INT_P (XEXP (XEXP (x, 0), 1)))
10111 *total = COSTS_N_INSNS (1) + *total;
10112 return true;
10113 }
8f2bf9f1
RS
10114 *total = COSTS_N_INSNS (1);
10115 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
68f932c4 10116 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
8f2bf9f1
RS
10117 break;
10118
10119 case HImode:
3e0cef6d
GJL
10120 if (AVR_HAVE_MUL
10121 && (MULT == GET_CODE (XEXP (x, 0))
10122 || ASHIFT == GET_CODE (XEXP (x, 0)))
10123 && register_operand (XEXP (x, 1), HImode)
10124 && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))
10125 || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 0), 0))))
10126 {
1b65da7d 10127 /* multiply-add */
3e0cef6d 10128 *total = COSTS_N_INSNS (speed ? 5 : 4);
1b65da7d
GJL
10129 /* multiply-add with constant: will be split and load constant. */
10130 if (CONST_INT_P (XEXP (XEXP (x, 0), 1)))
10131 *total = COSTS_N_INSNS (1) + *total;
3e0cef6d
GJL
10132 return true;
10133 }
8f2bf9f1
RS
10134 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10135 {
10136 *total = COSTS_N_INSNS (2);
68f932c4
RS
10137 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10138 speed);
8f2bf9f1
RS
10139 }
10140 else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
10141 *total = COSTS_N_INSNS (1);
10142 else
10143 *total = COSTS_N_INSNS (2);
10144 break;
10145
e4fe948a
GJL
10146 case PSImode:
10147 if (!CONST_INT_P (XEXP (x, 1)))
10148 {
10149 *total = COSTS_N_INSNS (3);
10150 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10151 speed);
10152 }
10153 else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
10154 *total = COSTS_N_INSNS (2);
10155 else
10156 *total = COSTS_N_INSNS (3);
10157 break;
10158
8f2bf9f1
RS
10159 case SImode:
10160 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10161 {
10162 *total = COSTS_N_INSNS (4);
68f932c4
RS
10163 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10164 speed);
8f2bf9f1
RS
10165 }
10166 else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
10167 *total = COSTS_N_INSNS (1);
10168 else
10169 *total = COSTS_N_INSNS (4);
10170 break;
10171
10172 default:
10173 return false;
10174 }
68f932c4 10175 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
8f2bf9f1
RS
10176 return true;
10177
10178 case MINUS:
1b65da7d
GJL
10179 if (AVR_HAVE_MUL
10180 && QImode == mode
10181 && register_operand (XEXP (x, 0), QImode)
10182 && MULT == GET_CODE (XEXP (x, 1)))
10183 {
10184 /* multiply-sub */
10185 *total = COSTS_N_INSNS (speed ? 4 : 3);
10186 /* multiply-sub with constant: will be split and load constant. */
10187 if (CONST_INT_P (XEXP (XEXP (x, 1), 1)))
10188 *total = COSTS_N_INSNS (1) + *total;
10189 return true;
10190 }
3e0cef6d
GJL
10191 if (AVR_HAVE_MUL
10192 && HImode == mode
10193 && register_operand (XEXP (x, 0), HImode)
10194 && (MULT == GET_CODE (XEXP (x, 1))
10195 || ASHIFT == GET_CODE (XEXP (x, 1)))
10196 && (ZERO_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))
10197 || SIGN_EXTEND == GET_CODE (XEXP (XEXP (x, 1), 0))))
10198 {
1b65da7d 10199 /* multiply-sub */
3e0cef6d 10200 *total = COSTS_N_INSNS (speed ? 5 : 4);
1b65da7d
GJL
10201 /* multiply-sub with constant: will be split and load constant. */
10202 if (CONST_INT_P (XEXP (XEXP (x, 1), 1)))
10203 *total = COSTS_N_INSNS (1) + *total;
3e0cef6d
GJL
10204 return true;
10205 }
e4fe948a 10206 /* FALLTHRU */
8f2bf9f1
RS
10207 case AND:
10208 case IOR:
10209 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
68f932c4 10210 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
8f2bf9f1 10211 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
68f932c4 10212 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
8f2bf9f1
RS
10213 return true;
10214
10215 case XOR:
10216 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
68f932c4
RS
10217 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10218 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
8f2bf9f1
RS
10219 return true;
10220
10221 case MULT:
10222 switch (mode)
10223 {
10224 case QImode:
dd6d1f8c 10225 if (AVR_HAVE_MUL)
f40751dd
JH
10226 *total = COSTS_N_INSNS (!speed ? 3 : 4);
10227 else if (!speed)
5dc77808 10228 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
8f2bf9f1
RS
10229 else
10230 return false;
c8bbabf2 10231 break;
8f2bf9f1
RS
10232
10233 case HImode:
dd6d1f8c 10234 if (AVR_HAVE_MUL)
8c352fa8
GJL
10235 {
10236 rtx op0 = XEXP (x, 0);
10237 rtx op1 = XEXP (x, 1);
10238 enum rtx_code code0 = GET_CODE (op0);
10239 enum rtx_code code1 = GET_CODE (op1);
10240 bool ex0 = SIGN_EXTEND == code0 || ZERO_EXTEND == code0;
10241 bool ex1 = SIGN_EXTEND == code1 || ZERO_EXTEND == code1;
10242
10243 if (ex0
10244 && (u8_operand (op1, HImode)
10245 || s8_operand (op1, HImode)))
10246 {
10247 *total = COSTS_N_INSNS (!speed ? 4 : 6);
10248 return true;
10249 }
10250 if (ex0
10251 && register_operand (op1, HImode))
10252 {
10253 *total = COSTS_N_INSNS (!speed ? 5 : 8);
10254 return true;
10255 }
10256 else if (ex0 || ex1)
10257 {
10258 *total = COSTS_N_INSNS (!speed ? 3 : 5);
10259 return true;
10260 }
10261 else if (register_operand (op0, HImode)
10262 && (u8_operand (op1, HImode)
10263 || s8_operand (op1, HImode)))
10264 {
10265 *total = COSTS_N_INSNS (!speed ? 6 : 9);
10266 return true;
10267 }
10268 else
10269 *total = COSTS_N_INSNS (!speed ? 7 : 10);
10270 }
f40751dd 10271 else if (!speed)
5dc77808 10272 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
8f2bf9f1
RS
10273 else
10274 return false;
c8bbabf2 10275 break;
8f2bf9f1 10276
e4fe948a
GJL
10277 case PSImode:
10278 if (!speed)
10279 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
10280 else
10281 *total = 10;
10282 break;
10283
296799ba 10284 case SImode:
33989cff 10285 case DImode:
296799ba
GJL
10286 if (AVR_HAVE_MUL)
10287 {
10288 if (!speed)
10289 {
10290 /* Add some additional costs besides CALL like moves etc. */
10291
10292 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
10293 }
10294 else
10295 {
10296 /* Just a rough estimate. Even with -O2 we don't want bulky
10297 code expanded inline. */
10298
10299 *total = COSTS_N_INSNS (25);
10300 }
10301 }
10302 else
10303 {
10304 if (speed)
10305 *total = COSTS_N_INSNS (300);
10306 else
10307 /* Add some additional costs besides CALL like moves etc. */
10308 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 5 : 4);
10309 }
00892272 10310
33989cff
SKS
10311 if (mode == DImode)
10312 *total *= 2;
10313
10314 return true;
00892272 10315
8f2bf9f1
RS
10316 default:
10317 return false;
10318 }
68f932c4
RS
10319 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
10320 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1, speed);
8f2bf9f1
RS
10321 return true;
10322
10323 case DIV:
10324 case MOD:
10325 case UDIV:
10326 case UMOD:
f40751dd 10327 if (!speed)
f1f59bc7 10328 *total = COSTS_N_INSNS (AVR_HAVE_JMP_CALL ? 2 : 1);
8f2bf9f1 10329 else
f1f59bc7 10330 *total = COSTS_N_INSNS (15 * GET_MODE_SIZE (mode));
68f932c4 10331 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
f1f59bc7
GJL
10332 /* For div/mod with const-int divisor we have at least the cost of
10333 loading the divisor. */
10334 if (CONST_INT_P (XEXP (x, 1)))
10335 *total += COSTS_N_INSNS (GET_MODE_SIZE (mode));
10336 /* Add some overall penaly for clobbering and moving around registers */
10337 *total += COSTS_N_INSNS (2);
8f2bf9f1
RS
10338 return true;
10339
15fe850f
AS
10340 case ROTATE:
10341 switch (mode)
10342 {
10343 case QImode:
10344 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 4)
10345 *total = COSTS_N_INSNS (1);
10346
10347 break;
10348
10349 case HImode:
10350 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) == 8)
10351 *total = COSTS_N_INSNS (3);
10352
10353 break;
10354
10355 case SImode:
10356 if (CONST_INT_P (XEXP (x, 1)))
10357 switch (INTVAL (XEXP (x, 1)))
10358 {
10359 case 8:
10360 case 24:
10361 *total = COSTS_N_INSNS (5);
10362 break;
10363 case 16:
10364 *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 6);
10365 break;
10366 }
10367 break;
10368
10369 default:
10370 return false;
10371 }
68f932c4 10372 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
00892272 10373 return true;
15fe850f 10374
8f2bf9f1
RS
10375 case ASHIFT:
10376 switch (mode)
10377 {
10378 case QImode:
10379 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10380 {
f40751dd 10381 *total = COSTS_N_INSNS (!speed ? 4 : 17);
68f932c4
RS
10382 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10383 speed);
8f2bf9f1
RS
10384 }
10385 else
10386 {
10387 val = INTVAL (XEXP (x, 1));
10388 if (val == 7)
10389 *total = COSTS_N_INSNS (3);
10390 else if (val >= 0 && val <= 7)
10391 *total = COSTS_N_INSNS (val);
10392 else
10393 *total = COSTS_N_INSNS (1);
10394 }
10395 break;
10396
10397 case HImode:
8c352fa8
GJL
10398 if (AVR_HAVE_MUL)
10399 {
10400 if (const_2_to_7_operand (XEXP (x, 1), HImode)
10401 && (SIGN_EXTEND == GET_CODE (XEXP (x, 0))
10402 || ZERO_EXTEND == GET_CODE (XEXP (x, 0))))
10403 {
10404 *total = COSTS_N_INSNS (!speed ? 4 : 6);
10405 return true;
10406 }
10407 }
00892272 10408
1b65da7d
GJL
10409 if (const1_rtx == (XEXP (x, 1))
10410 && SIGN_EXTEND == GET_CODE (XEXP (x, 0)))
10411 {
10412 *total = COSTS_N_INSNS (2);
10413 return true;
10414 }
00892272 10415
8f2bf9f1
RS
10416 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10417 {
f40751dd 10418 *total = COSTS_N_INSNS (!speed ? 5 : 41);
68f932c4
RS
10419 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10420 speed);
8f2bf9f1
RS
10421 }
10422 else
10423 switch (INTVAL (XEXP (x, 1)))
10424 {
10425 case 0:
10426 *total = 0;
10427 break;
10428 case 1:
10429 case 8:
10430 *total = COSTS_N_INSNS (2);
10431 break;
10432 case 9:
10433 *total = COSTS_N_INSNS (3);
10434 break;
10435 case 2:
10436 case 3:
10437 case 10:
10438 case 15:
10439 *total = COSTS_N_INSNS (4);
10440 break;
10441 case 7:
10442 case 11:
10443 case 12:
10444 *total = COSTS_N_INSNS (5);
10445 break;
10446 case 4:
f40751dd 10447 *total = COSTS_N_INSNS (!speed ? 5 : 8);
8f2bf9f1
RS
10448 break;
10449 case 6:
1f494b6d 10450 *total = COSTS_N_INSNS (!speed ? 5 : 9);
8f2bf9f1
RS
10451 break;
10452 case 5:
f40751dd 10453 *total = COSTS_N_INSNS (!speed ? 5 : 10);
8f2bf9f1
RS
10454 break;
10455 default:
f40751dd 10456 *total = COSTS_N_INSNS (!speed ? 5 : 41);
68f932c4
RS
10457 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10458 speed);
8f2bf9f1
RS
10459 }
10460 break;
10461
e4fe948a
GJL
10462 case PSImode:
10463 if (!CONST_INT_P (XEXP (x, 1)))
10464 {
10465 *total = COSTS_N_INSNS (!speed ? 6 : 73);
10466 }
10467 else
10468 switch (INTVAL (XEXP (x, 1)))
10469 {
10470 case 0:
10471 *total = 0;
10472 break;
10473 case 1:
10474 case 8:
10475 case 16:
10476 *total = COSTS_N_INSNS (3);
10477 break;
10478 case 23:
10479 *total = COSTS_N_INSNS (5);
10480 break;
10481 default:
10482 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
10483 break;
10484 }
10485 break;
10486
8f2bf9f1
RS
10487 case SImode:
10488 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10489 {
f40751dd 10490 *total = COSTS_N_INSNS (!speed ? 7 : 113);
68f932c4
RS
10491 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10492 speed);
8f2bf9f1
RS
10493 }
10494 else
10495 switch (INTVAL (XEXP (x, 1)))
10496 {
10497 case 0:
10498 *total = 0;
10499 break;
10500 case 24:
10501 *total = COSTS_N_INSNS (3);
10502 break;
10503 case 1:
10504 case 8:
10505 case 16:
10506 *total = COSTS_N_INSNS (4);
10507 break;
10508 case 31:
10509 *total = COSTS_N_INSNS (6);
10510 break;
10511 case 2:
f40751dd 10512 *total = COSTS_N_INSNS (!speed ? 7 : 8);
8f2bf9f1
RS
10513 break;
10514 default:
f40751dd 10515 *total = COSTS_N_INSNS (!speed ? 7 : 113);
68f932c4
RS
10516 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10517 speed);
8f2bf9f1
RS
10518 }
10519 break;
10520
10521 default:
10522 return false;
10523 }
68f932c4 10524 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
8f2bf9f1
RS
10525 return true;
10526
10527 case ASHIFTRT:
10528 switch (mode)
10529 {
10530 case QImode:
10531 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10532 {
f40751dd 10533 *total = COSTS_N_INSNS (!speed ? 4 : 17);
68f932c4
RS
10534 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10535 speed);
8f2bf9f1
RS
10536 }
10537 else
10538 {
10539 val = INTVAL (XEXP (x, 1));
10540 if (val == 6)
10541 *total = COSTS_N_INSNS (4);
10542 else if (val == 7)
10543 *total = COSTS_N_INSNS (2);
10544 else if (val >= 0 && val <= 7)
10545 *total = COSTS_N_INSNS (val);
10546 else
10547 *total = COSTS_N_INSNS (1);
10548 }
10549 break;
10550
10551 case HImode:
10552 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10553 {
f40751dd 10554 *total = COSTS_N_INSNS (!speed ? 5 : 41);
68f932c4
RS
10555 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10556 speed);
8f2bf9f1
RS
10557 }
10558 else
10559 switch (INTVAL (XEXP (x, 1)))
10560 {
10561 case 0:
10562 *total = 0;
10563 break;
10564 case 1:
10565 *total = COSTS_N_INSNS (2);
10566 break;
10567 case 15:
10568 *total = COSTS_N_INSNS (3);
10569 break;
10570 case 2:
10571 case 7:
10572 case 8:
10573 case 9:
10574 *total = COSTS_N_INSNS (4);
10575 break;
10576 case 10:
10577 case 14:
10578 *total = COSTS_N_INSNS (5);
10579 break;
10580 case 11:
f40751dd 10581 *total = COSTS_N_INSNS (!speed ? 5 : 6);
8f2bf9f1
RS
10582 break;
10583 case 12:
f40751dd 10584 *total = COSTS_N_INSNS (!speed ? 5 : 7);
8f2bf9f1
RS
10585 break;
10586 case 6:
10587 case 13:
f40751dd 10588 *total = COSTS_N_INSNS (!speed ? 5 : 8);
8f2bf9f1
RS
10589 break;
10590 default:
f40751dd 10591 *total = COSTS_N_INSNS (!speed ? 5 : 41);
68f932c4
RS
10592 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10593 speed);
8f2bf9f1
RS
10594 }
10595 break;
10596
e4fe948a
GJL
10597 case PSImode:
10598 if (!CONST_INT_P (XEXP (x, 1)))
10599 {
10600 *total = COSTS_N_INSNS (!speed ? 6 : 73);
10601 }
10602 else
10603 switch (INTVAL (XEXP (x, 1)))
10604 {
10605 case 0:
10606 *total = 0;
10607 break;
10608 case 1:
10609 *total = COSTS_N_INSNS (3);
10610 break;
10611 case 16:
10612 case 8:
10613 *total = COSTS_N_INSNS (5);
10614 break;
10615 case 23:
10616 *total = COSTS_N_INSNS (4);
10617 break;
10618 default:
10619 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
10620 break;
10621 }
10622 break;
10623
8f2bf9f1
RS
10624 case SImode:
10625 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10626 {
f40751dd 10627 *total = COSTS_N_INSNS (!speed ? 7 : 113);
68f932c4
RS
10628 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10629 speed);
8f2bf9f1
RS
10630 }
10631 else
10632 switch (INTVAL (XEXP (x, 1)))
10633 {
10634 case 0:
10635 *total = 0;
10636 break;
10637 case 1:
10638 *total = COSTS_N_INSNS (4);
10639 break;
10640 case 8:
10641 case 16:
10642 case 24:
10643 *total = COSTS_N_INSNS (6);
10644 break;
10645 case 2:
f40751dd 10646 *total = COSTS_N_INSNS (!speed ? 7 : 8);
8f2bf9f1
RS
10647 break;
10648 case 31:
4301ec4f 10649 *total = COSTS_N_INSNS (AVR_HAVE_MOVW ? 4 : 5);
8f2bf9f1
RS
10650 break;
10651 default:
f40751dd 10652 *total = COSTS_N_INSNS (!speed ? 7 : 113);
68f932c4
RS
10653 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10654 speed);
8f2bf9f1
RS
10655 }
10656 break;
10657
10658 default:
10659 return false;
10660 }
68f932c4 10661 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
8f2bf9f1
RS
10662 return true;
10663
10664 case LSHIFTRT:
10665 switch (mode)
10666 {
10667 case QImode:
10668 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10669 {
f40751dd 10670 *total = COSTS_N_INSNS (!speed ? 4 : 17);
68f932c4
RS
10671 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10672 speed);
8f2bf9f1
RS
10673 }
10674 else
10675 {
10676 val = INTVAL (XEXP (x, 1));
10677 if (val == 7)
10678 *total = COSTS_N_INSNS (3);
10679 else if (val >= 0 && val <= 7)
10680 *total = COSTS_N_INSNS (val);
10681 else
10682 *total = COSTS_N_INSNS (1);
10683 }
10684 break;
10685
10686 case HImode:
10687 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10688 {
f40751dd 10689 *total = COSTS_N_INSNS (!speed ? 5 : 41);
68f932c4
RS
10690 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10691 speed);
8f2bf9f1
RS
10692 }
10693 else
10694 switch (INTVAL (XEXP (x, 1)))
10695 {
10696 case 0:
10697 *total = 0;
10698 break;
10699 case 1:
10700 case 8:
10701 *total = COSTS_N_INSNS (2);
10702 break;
10703 case 9:
10704 *total = COSTS_N_INSNS (3);
10705 break;
10706 case 2:
10707 case 10:
10708 case 15:
10709 *total = COSTS_N_INSNS (4);
10710 break;
10711 case 7:
10712 case 11:
10713 *total = COSTS_N_INSNS (5);
10714 break;
10715 case 3:
10716 case 12:
10717 case 13:
10718 case 14:
f40751dd 10719 *total = COSTS_N_INSNS (!speed ? 5 : 6);
8f2bf9f1
RS
10720 break;
10721 case 4:
f40751dd 10722 *total = COSTS_N_INSNS (!speed ? 5 : 7);
8f2bf9f1
RS
10723 break;
10724 case 5:
10725 case 6:
f40751dd 10726 *total = COSTS_N_INSNS (!speed ? 5 : 9);
8f2bf9f1
RS
10727 break;
10728 default:
f40751dd 10729 *total = COSTS_N_INSNS (!speed ? 5 : 41);
68f932c4
RS
10730 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10731 speed);
8f2bf9f1
RS
10732 }
10733 break;
10734
e4fe948a
GJL
10735 case PSImode:
10736 if (!CONST_INT_P (XEXP (x, 1)))
10737 {
10738 *total = COSTS_N_INSNS (!speed ? 6 : 73);
10739 }
10740 else
10741 switch (INTVAL (XEXP (x, 1)))
10742 {
10743 case 0:
10744 *total = 0;
10745 break;
10746 case 1:
10747 case 8:
10748 case 16:
10749 *total = COSTS_N_INSNS (3);
10750 break;
10751 case 23:
10752 *total = COSTS_N_INSNS (5);
10753 break;
10754 default:
10755 *total = COSTS_N_INSNS (!speed ? 5 : 3 * INTVAL (XEXP (x, 1)));
10756 break;
10757 }
10758 break;
10759
8f2bf9f1
RS
10760 case SImode:
10761 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
10762 {
f40751dd 10763 *total = COSTS_N_INSNS (!speed ? 7 : 113);
68f932c4
RS
10764 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10765 speed);
8f2bf9f1
RS
10766 }
10767 else
10768 switch (INTVAL (XEXP (x, 1)))
10769 {
10770 case 0:
10771 *total = 0;
10772 break;
10773 case 1:
10774 *total = COSTS_N_INSNS (4);
10775 break;
10776 case 2:
f40751dd 10777 *total = COSTS_N_INSNS (!speed ? 7 : 8);
8f2bf9f1
RS
10778 break;
10779 case 8:
10780 case 16:
10781 case 24:
10782 *total = COSTS_N_INSNS (4);
10783 break;
10784 case 31:
10785 *total = COSTS_N_INSNS (6);
10786 break;
10787 default:
f40751dd 10788 *total = COSTS_N_INSNS (!speed ? 7 : 113);
68f932c4
RS
10789 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code, 1,
10790 speed);
8f2bf9f1
RS
10791 }
10792 break;
10793
10794 default:
10795 return false;
10796 }
68f932c4 10797 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code, 0, speed);
8f2bf9f1
RS
10798 return true;
10799
10800 case COMPARE:
10801 switch (GET_MODE (XEXP (x, 0)))
3c50106f 10802 {
8f2bf9f1
RS
10803 case QImode:
10804 *total = COSTS_N_INSNS (1);
10805 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
e548c9df
AM
10806 *total += avr_operand_rtx_cost (XEXP (x, 1), QImode, code,
10807 1, speed);
8f2bf9f1
RS
10808 break;
10809
10810 case HImode:
10811 *total = COSTS_N_INSNS (2);
10812 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
e548c9df
AM
10813 *total += avr_operand_rtx_cost (XEXP (x, 1), HImode, code,
10814 1, speed);
8f2bf9f1
RS
10815 else if (INTVAL (XEXP (x, 1)) != 0)
10816 *total += COSTS_N_INSNS (1);
10817 break;
10818
e4fe948a
GJL
10819 case PSImode:
10820 *total = COSTS_N_INSNS (3);
10821 if (CONST_INT_P (XEXP (x, 1)) && INTVAL (XEXP (x, 1)) != 0)
10822 *total += COSTS_N_INSNS (2);
10823 break;
10824
8f2bf9f1
RS
10825 case SImode:
10826 *total = COSTS_N_INSNS (4);
10827 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
e548c9df
AM
10828 *total += avr_operand_rtx_cost (XEXP (x, 1), SImode, code,
10829 1, speed);
8f2bf9f1
RS
10830 else if (INTVAL (XEXP (x, 1)) != 0)
10831 *total += COSTS_N_INSNS (3);
10832 break;
10833
10834 default:
10835 return false;
3c50106f 10836 }
e548c9df
AM
10837 *total += avr_operand_rtx_cost (XEXP (x, 0), GET_MODE (XEXP (x, 0)),
10838 code, 0, speed);
8f2bf9f1
RS
10839 return true;
10840
7ece3881
GJL
10841 case TRUNCATE:
10842 if (AVR_HAVE_MUL
10843 && LSHIFTRT == GET_CODE (XEXP (x, 0))
10844 && MULT == GET_CODE (XEXP (XEXP (x, 0), 0))
10845 && CONST_INT_P (XEXP (XEXP (x, 0), 1)))
10846 {
10847 if (QImode == mode || HImode == mode)
10848 {
10849 *total = COSTS_N_INSNS (2);
10850 return true;
10851 }
10852 }
10853 break;
10854
8f2bf9f1
RS
10855 default:
10856 break;
3c50106f 10857 }
8f2bf9f1 10858 return false;
3c50106f
RH
10859}
10860
ab758510
GJL
10861
10862/* Implement `TARGET_RTX_COSTS'. */
10863
10864static bool
e548c9df 10865avr_rtx_costs (rtx x, machine_mode mode, int outer_code,
ab758510
GJL
10866 int opno, int *total, bool speed)
10867{
e548c9df 10868 bool done = avr_rtx_costs_1 (x, mode, outer_code,
ab758510
GJL
10869 opno, total, speed);
10870
10871 if (avr_log.rtx_costs)
10872 {
10873 avr_edump ("\n%?=%b (%s) total=%d, outer=%C:\n%r\n",
10874 done, speed ? "speed" : "size", *total, outer_code, x);
10875 }
10876
10877 return done;
10878}
10879
fe780c13
GJL
10880
10881/* Implement `TARGET_ADDRESS_COST'. */
90e7678c 10882
dcefdf67 10883static int
ef4bddc2 10884avr_address_cost (rtx x, machine_mode mode ATTRIBUTE_UNUSED,
51526856
GJL
10885 addr_space_t as ATTRIBUTE_UNUSED,
10886 bool speed ATTRIBUTE_UNUSED)
90e7678c 10887{
fe780c13 10888 int cost = 4;
00892272 10889
90e7678c 10890 if (GET_CODE (x) == PLUS
fe780c13
GJL
10891 && CONST_INT_P (XEXP (x, 1))
10892 && (REG_P (XEXP (x, 0))
10893 || GET_CODE (XEXP (x, 0)) == SUBREG))
5fecfd8d 10894 {
33989cff 10895 if (INTVAL (XEXP (x, 1)) > MAX_LD_OFFSET(mode))
fe780c13 10896 cost = 18;
5fecfd8d 10897 }
fe780c13
GJL
10898 else if (CONSTANT_ADDRESS_P (x))
10899 {
10900 if (optimize > 0
10901 && io_address_operand (x, QImode))
10902 cost = 2;
10903 }
10904
10905 if (avr_log.address_cost)
10906 avr_edump ("\n%?: %d = %r\n", cost, x);
00892272 10907
fe780c13 10908 return cost;
90e7678c
DC
10909}
10910
2d67effa
DC
10911/* Test for extra memory constraint 'Q'.
10912 It's a memory address based on Y or Z pointer with valid displacement. */
90e7678c
DC
10913
10914int
2d67effa 10915extra_constraint_Q (rtx x)
90e7678c 10916{
ab758510 10917 int ok = 0;
00892272 10918
2d67effa
DC
10919 if (GET_CODE (XEXP (x,0)) == PLUS
10920 && REG_P (XEXP (XEXP (x,0), 0))
10921 && GET_CODE (XEXP (XEXP (x,0), 1)) == CONST_INT
10922 && (INTVAL (XEXP (XEXP (x,0), 1))
10923 <= MAX_LD_OFFSET (GET_MODE (x))))
90e7678c 10924 {
2d67effa
DC
10925 rtx xx = XEXP (XEXP (x,0), 0);
10926 int regno = REGNO (xx);
00892272 10927
ab758510
GJL
10928 ok = (/* allocate pseudos */
10929 regno >= FIRST_PSEUDO_REGISTER
10930 /* strictly check */
10931 || regno == REG_Z || regno == REG_Y
10932 /* XXX frame & arg pointer checks */
10933 || xx == frame_pointer_rtx
10934 || xx == arg_pointer_rtx);
00892272 10935
ab758510
GJL
10936 if (avr_log.constraints)
10937 avr_edump ("\n%?=%d reload_completed=%d reload_in_progress=%d\n %r\n",
10938 ok, reload_completed, reload_in_progress, x);
90e7678c 10939 }
ab758510
GJL
10940
10941 return ok;
90e7678c
DC
10942}
10943
2c338472 10944/* Convert condition code CONDITION to the valid AVR condition code. */
90e7678c
DC
10945
10946RTX_CODE
269e3795 10947avr_normalize_condition (RTX_CODE condition)
90e7678c
DC
10948{
10949 switch (condition)
10950 {
10951 case GT:
10952 return GE;
10953 case GTU:
10954 return GEU;
10955 case LE:
10956 return LT;
10957 case LEU:
10958 return LTU;
10959 default:
25b9575b 10960 gcc_unreachable ();
90e7678c
DC
10961 }
10962}
10963
f3713778
GJL
10964/* Helper function for `avr_reorg'. */
10965
10966static rtx
98024b4e 10967avr_compare_pattern (rtx_insn *insn)
f3713778
GJL
10968{
10969 rtx pattern = single_set (insn);
10970
10971 if (pattern
10972 && NONJUMP_INSN_P (insn)
10973 && SET_DEST (pattern) == cc0_rtx
e55e4056 10974 && GET_CODE (SET_SRC (pattern)) == COMPARE)
f3713778 10975 {
ef4bddc2
RS
10976 machine_mode mode0 = GET_MODE (XEXP (SET_SRC (pattern), 0));
10977 machine_mode mode1 = GET_MODE (XEXP (SET_SRC (pattern), 1));
e55e4056
GJL
10978
10979 /* The 64-bit comparisons have fixed operands ACC_A and ACC_B.
10980 They must not be swapped, thus skip them. */
10981
10982 if ((mode0 == VOIDmode || GET_MODE_SIZE (mode0) <= 4)
10983 && (mode1 == VOIDmode || GET_MODE_SIZE (mode1) <= 4))
10984 return pattern;
f3713778
GJL
10985 }
10986
10987 return NULL_RTX;
10988}
10989
10990/* Helper function for `avr_reorg'. */
10991
10992/* Expansion of switch/case decision trees leads to code like
10993
10994 cc0 = compare (Reg, Num)
10995 if (cc0 == 0)
10996 goto L1
00892272 10997
f3713778
GJL
10998 cc0 = compare (Reg, Num)
10999 if (cc0 > 0)
11000 goto L2
11001
11002 The second comparison is superfluous and can be deleted.
11003 The second jump condition can be transformed from a
11004 "difficult" one to a "simple" one because "cc0 > 0" and
11005 "cc0 >= 0" will have the same effect here.
11006
11007 This function relies on the way switch/case is being expaned
11008 as binary decision tree. For example code see PR 49903.
00892272 11009
f3713778
GJL
11010 Return TRUE if optimization performed.
11011 Return FALSE if nothing changed.
11012
11013 INSN1 is a comparison, i.e. avr_compare_pattern != 0.
11014
11015 We don't want to do this in text peephole because it is
11016 tedious to work out jump offsets there and the second comparison
11017 might have been transormed by `avr_reorg'.
11018
11019 RTL peephole won't do because peephole2 does not scan across
00892272
GJL
11020 basic blocks. */
11021
f3713778 11022static bool
98024b4e 11023avr_reorg_remove_redundant_compare (rtx_insn *insn1)
f3713778 11024{
98024b4e
DM
11025 rtx comp1, ifelse1, xcond1;
11026 rtx_insn *branch1;
11027 rtx comp2, ifelse2, xcond2;
11028 rtx_insn *branch2, *insn2;
f3713778 11029 enum rtx_code code;
98024b4e
DM
11030 rtx_insn *jump;
11031 rtx target, cond;
00892272 11032
f3713778
GJL
11033 /* Look out for: compare1 - branch1 - compare2 - branch2 */
11034
11035 branch1 = next_nonnote_nondebug_insn (insn1);
11036 if (!branch1 || !JUMP_P (branch1))
11037 return false;
11038
11039 insn2 = next_nonnote_nondebug_insn (branch1);
11040 if (!insn2 || !avr_compare_pattern (insn2))
11041 return false;
11042
11043 branch2 = next_nonnote_nondebug_insn (insn2);
11044 if (!branch2 || !JUMP_P (branch2))
11045 return false;
11046
11047 comp1 = avr_compare_pattern (insn1);
11048 comp2 = avr_compare_pattern (insn2);
11049 xcond1 = single_set (branch1);
11050 xcond2 = single_set (branch2);
00892272 11051
f3713778
GJL
11052 if (!comp1 || !comp2
11053 || !rtx_equal_p (comp1, comp2)
11054 || !xcond1 || SET_DEST (xcond1) != pc_rtx
11055 || !xcond2 || SET_DEST (xcond2) != pc_rtx
11056 || IF_THEN_ELSE != GET_CODE (SET_SRC (xcond1))
11057 || IF_THEN_ELSE != GET_CODE (SET_SRC (xcond2)))
11058 {
11059 return false;
11060 }
11061
11062 comp1 = SET_SRC (comp1);
11063 ifelse1 = SET_SRC (xcond1);
11064 ifelse2 = SET_SRC (xcond2);
11065
11066 /* comp<n> is COMPARE now and ifelse<n> is IF_THEN_ELSE. */
11067
11068 if (EQ != GET_CODE (XEXP (ifelse1, 0))
11069 || !REG_P (XEXP (comp1, 0))
11070 || !CONST_INT_P (XEXP (comp1, 1))
11071 || XEXP (ifelse1, 2) != pc_rtx
11072 || XEXP (ifelse2, 2) != pc_rtx
11073 || LABEL_REF != GET_CODE (XEXP (ifelse1, 1))
11074 || LABEL_REF != GET_CODE (XEXP (ifelse2, 1))
11075 || !COMPARISON_P (XEXP (ifelse2, 0))
11076 || cc0_rtx != XEXP (XEXP (ifelse1, 0), 0)
11077 || cc0_rtx != XEXP (XEXP (ifelse2, 0), 0)
11078 || const0_rtx != XEXP (XEXP (ifelse1, 0), 1)
11079 || const0_rtx != XEXP (XEXP (ifelse2, 0), 1))
11080 {
11081 return false;
11082 }
11083
11084 /* We filtered the insn sequence to look like
11085
11086 (set (cc0)
11087 (compare (reg:M N)
11088 (const_int VAL)))
11089 (set (pc)
11090 (if_then_else (eq (cc0)
11091 (const_int 0))
11092 (label_ref L1)
11093 (pc)))
00892272 11094
f3713778
GJL
11095 (set (cc0)
11096 (compare (reg:M N)
11097 (const_int VAL)))
11098 (set (pc)
11099 (if_then_else (CODE (cc0)
11100 (const_int 0))
11101 (label_ref L2)
11102 (pc)))
11103 */
11104
11105 code = GET_CODE (XEXP (ifelse2, 0));
11106
11107 /* Map GT/GTU to GE/GEU which is easier for AVR.
11108 The first two instructions compare/branch on EQ
11109 so we may replace the difficult
00892272 11110
f3713778
GJL
11111 if (x == VAL) goto L1;
11112 if (x > VAL) goto L2;
11113
11114 with easy
00892272 11115
f3713778
GJL
11116 if (x == VAL) goto L1;
11117 if (x >= VAL) goto L2;
11118
11119 Similarly, replace LE/LEU by LT/LTU. */
00892272 11120
f3713778
GJL
11121 switch (code)
11122 {
11123 case EQ:
11124 case LT: case LTU:
11125 case GE: case GEU:
11126 break;
11127
11128 case LE: case LEU:
11129 case GT: case GTU:
11130 code = avr_normalize_condition (code);
11131 break;
00892272 11132
f3713778
GJL
11133 default:
11134 return false;
11135 }
11136
11137 /* Wrap the branches into UNSPECs so they won't be changed or
11138 optimized in the remainder. */
11139
11140 target = XEXP (XEXP (ifelse1, 1), 0);
11141 cond = XEXP (ifelse1, 0);
11142 jump = emit_jump_insn_after (gen_branch_unspec (target, cond), insn1);
11143
11144 JUMP_LABEL (jump) = JUMP_LABEL (branch1);
11145
11146 target = XEXP (XEXP (ifelse2, 1), 0);
11147 cond = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
11148 jump = emit_jump_insn_after (gen_branch_unspec (target, cond), insn2);
11149
11150 JUMP_LABEL (jump) = JUMP_LABEL (branch2);
11151
11152 /* The comparisons in insn1 and insn2 are exactly the same;
11153 insn2 is superfluous so delete it. */
00892272 11154
f3713778
GJL
11155 delete_insn (insn2);
11156 delete_insn (branch1);
11157 delete_insn (branch2);
11158
11159 return true;
11160}
11161
11162
11163/* Implement `TARGET_MACHINE_DEPENDENT_REORG'. */
11164/* Optimize conditional jumps. */
90e7678c 11165
18dbd950 11166static void
269e3795 11167avr_reorg (void)
90e7678c 11168{
98024b4e 11169 rtx_insn *insn = get_insns();
00892272 11170
f3713778 11171 for (insn = next_real_insn (insn); insn; insn = next_real_insn (insn))
90e7678c 11172 {
f3713778 11173 rtx pattern = avr_compare_pattern (insn);
00892272 11174
f3713778
GJL
11175 if (!pattern)
11176 continue;
90e7678c 11177
f3713778
GJL
11178 if (optimize
11179 && avr_reorg_remove_redundant_compare (insn))
11180 {
11181 continue;
11182 }
90e7678c 11183
f3713778 11184 if (compare_diff_p (insn))
90e7678c 11185 {
f3713778 11186 /* Now we work under compare insn with difficult branch. */
00892272 11187
21afc57d 11188 rtx_insn *next = next_real_insn (insn);
f3713778
GJL
11189 rtx pat = PATTERN (next);
11190
11191 pattern = SET_SRC (pattern);
00892272 11192
f3713778
GJL
11193 if (true_regnum (XEXP (pattern, 0)) >= 0
11194 && true_regnum (XEXP (pattern, 1)) >= 0)
11195 {
11196 rtx x = XEXP (pattern, 0);
11197 rtx src = SET_SRC (pat);
11198 rtx t = XEXP (src,0);
11199 PUT_CODE (t, swap_condition (GET_CODE (t)));
11200 XEXP (pattern, 0) = XEXP (pattern, 1);
11201 XEXP (pattern, 1) = x;
11202 INSN_CODE (next) = -1;
11203 }
11204 else if (true_regnum (XEXP (pattern, 0)) >= 0
11205 && XEXP (pattern, 1) == const0_rtx)
11206 {
11207 /* This is a tst insn, we can reverse it. */
11208 rtx src = SET_SRC (pat);
11209 rtx t = XEXP (src,0);
00892272 11210
f3713778
GJL
11211 PUT_CODE (t, swap_condition (GET_CODE (t)));
11212 XEXP (pattern, 1) = XEXP (pattern, 0);
11213 XEXP (pattern, 0) = const0_rtx;
11214 INSN_CODE (next) = -1;
11215 INSN_CODE (insn) = -1;
11216 }
11217 else if (true_regnum (XEXP (pattern, 0)) >= 0
11218 && CONST_INT_P (XEXP (pattern, 1)))
11219 {
11220 rtx x = XEXP (pattern, 1);
11221 rtx src = SET_SRC (pat);
11222 rtx t = XEXP (src,0);
ef4bddc2 11223 machine_mode mode = GET_MODE (XEXP (pattern, 0));
00892272 11224
f3713778
GJL
11225 if (avr_simplify_comparison_p (mode, GET_CODE (t), x))
11226 {
11227 XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
11228 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
11229 INSN_CODE (next) = -1;
11230 INSN_CODE (insn) = -1;
11231 }
11232 }
11233 }
90e7678c
DC
11234 }
11235}
11236
11237/* Returns register number for function return value.*/
11238
fd01a351 11239static inline unsigned int
269e3795 11240avr_ret_register (void)
90e7678c
DC
11241{
11242 return 24;
11243}
11244
00892272
GJL
11245
11246/* Implement `TARGET_FUNCTION_VALUE_REGNO_P'. */
68fd7765
AS
11247
11248static bool
11249avr_function_value_regno_p (const unsigned int regno)
11250{
11251 return (regno == avr_ret_register ());
11252}
11253
00892272
GJL
11254
11255/* Implement `TARGET_LIBCALL_VALUE'. */
9f5ed61a 11256/* Create an RTX representing the place where a
90e7678c
DC
11257 library function returns a value of mode MODE. */
11258
68fd7765 11259static rtx
ef4bddc2 11260avr_libcall_value (machine_mode mode,
68fd7765 11261 const_rtx func ATTRIBUTE_UNUSED)
90e7678c
DC
11262{
11263 int offs = GET_MODE_SIZE (mode);
00892272 11264
e4fe948a
GJL
11265 if (offs <= 4)
11266 offs = (offs + 1) & ~1;
00892272 11267
68fd7765 11268 return gen_rtx_REG (mode, avr_ret_register () + 2 - offs);
90e7678c
DC
11269}
11270
00892272
GJL
11271
11272/* Implement `TARGET_FUNCTION_VALUE'. */
90e7678c
DC
11273/* Create an RTX representing the place where a
11274 function returns a value of data type VALTYPE. */
11275
68fd7765 11276static rtx
fd01a351
GJL
11277avr_function_value (const_tree type,
11278 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
11279 bool outgoing ATTRIBUTE_UNUSED)
90e7678c 11280{
3454eb73 11281 unsigned int offs;
68fd7765 11282
90e7678c 11283 if (TYPE_MODE (type) != BLKmode)
fd01a351 11284 return avr_libcall_value (TYPE_MODE (type), NULL_RTX);
00892272 11285
90e7678c
DC
11286 offs = int_size_in_bytes (type);
11287 if (offs < 2)
11288 offs = 2;
11289 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
11290 offs = GET_MODE_SIZE (SImode);
11291 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
11292 offs = GET_MODE_SIZE (DImode);
00892272 11293
68fd7765 11294 return gen_rtx_REG (BLKmode, avr_ret_register () + 2 - offs);
90e7678c
DC
11295}
11296
28e801e2 11297int
0a2aaacc 11298test_hard_reg_class (enum reg_class rclass, rtx x)
28e801e2
DC
11299{
11300 int regno = true_regnum (x);
11301 if (regno < 0)
11302 return 0;
26af4041 11303
0a2aaacc 11304 if (TEST_HARD_REG_CLASS (rclass, regno))
26af4041
MM
11305 return 1;
11306
11307 return 0;
28e801e2
DC
11308}
11309
b58c068a 11310
9bc9ee67
GJL
11311/* Helper for jump_over_one_insn_p: Test if INSN is a 2-word instruction
11312 and thus is suitable to be skipped by CPSE, SBRC, etc. */
11313
11314static bool
98024b4e 11315avr_2word_insn_p (rtx_insn *insn)
9bc9ee67 11316{
f9d29866 11317 if (TARGET_SKIP_BUG
9bc9ee67
GJL
11318 || !insn
11319 || 2 != get_attr_length (insn))
11320 {
11321 return false;
11322 }
11323
11324 switch (INSN_CODE (insn))
11325 {
11326 default:
11327 return false;
00892272 11328
9bc9ee67 11329 case CODE_FOR_movqi_insn:
e55e4056
GJL
11330 case CODE_FOR_movuqq_insn:
11331 case CODE_FOR_movqq_insn:
9bc9ee67
GJL
11332 {
11333 rtx set = single_set (insn);
11334 rtx src = SET_SRC (set);
11335 rtx dest = SET_DEST (set);
00892272 11336
9bc9ee67 11337 /* Factor out LDS and STS from movqi_insn. */
00892272 11338
9bc9ee67 11339 if (MEM_P (dest)
e55e4056 11340 && (REG_P (src) || src == CONST0_RTX (GET_MODE (dest))))
9bc9ee67
GJL
11341 {
11342 return CONSTANT_ADDRESS_P (XEXP (dest, 0));
11343 }
11344 else if (REG_P (dest)
11345 && MEM_P (src))
11346 {
11347 return CONSTANT_ADDRESS_P (XEXP (src, 0));
11348 }
00892272 11349
9bc9ee67
GJL
11350 return false;
11351 }
11352
11353 case CODE_FOR_call_insn:
11354 case CODE_FOR_call_value_insn:
11355 return true;
11356 }
11357}
11358
11359
b58c068a 11360int
98024b4e 11361jump_over_one_insn_p (rtx_insn *insn, rtx dest)
b58c068a
DC
11362{
11363 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
11364 ? XEXP (dest, 0)
11365 : dest);
9d98a694
AO
11366 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
11367 int dest_addr = INSN_ADDRESSES (uid);
9bc9ee67 11368 int jump_offset = dest_addr - jump_addr - get_attr_length (insn);
00892272 11369
9bc9ee67
GJL
11370 return (jump_offset == 1
11371 || (jump_offset == 2
11372 && avr_2word_insn_p (next_active_insn (insn))));
b58c068a 11373}
78cf8279 11374
00892272
GJL
11375
11376/* Worker function for `HARD_REGNO_MODE_OK'. */
78cf8279 11377/* Returns 1 if a value of mode MODE can be stored starting with hard
c4984bad
MM
11378 register number REGNO. On the enhanced core, anything larger than
11379 1 byte must start in even numbered register for "movw" to work
11380 (this way we don't have to check for odd registers everywhere). */
78cf8279
MM
11381
11382int
ef4bddc2 11383avr_hard_regno_mode_ok (int regno, machine_mode mode)
78cf8279 11384{
3e4f8484
GJL
11385 /* NOTE: 8-bit values must not be disallowed for R28 or R29.
11386 Disallowing QI et al. in these regs might lead to code like
11387 (set (subreg:QI (reg:HI 28) n) ...)
11388 which will result in wrong code because reload does not
11389 handle SUBREGs of hard regsisters like this.
11390 This could be fixed in reload. However, it appears
11391 that fixing reload is not wanted by reload people. */
00892272 11392
3e4f8484 11393 /* Any GENERAL_REGS register can hold 8-bit values. */
00892272 11394
3e4f8484 11395 if (GET_MODE_SIZE (mode) == 1)
78cf8279 11396 return 1;
d2ebe27c 11397
3e4f8484
GJL
11398 /* FIXME: Ideally, the following test is not needed.
11399 However, it turned out that it can reduce the number
11400 of spill fails. AVR and it's poor endowment with
11401 address registers is extreme stress test for reload. */
00892272 11402
3e4f8484
GJL
11403 if (GET_MODE_SIZE (mode) >= 4
11404 && regno >= REG_X)
d2ebe27c
RS
11405 return 0;
11406
3e4f8484 11407 /* All modes larger than 8 bits should start in an even register. */
00892272 11408
78cf8279
MM
11409 return !(regno & 1);
11410}
6bec29c9 11411
6bec29c9 11412
b04ffa56
GJL
11413/* Implement `HARD_REGNO_CALL_PART_CLOBBERED'. */
11414
11415int
ef4bddc2 11416avr_hard_regno_call_part_clobbered (unsigned regno, machine_mode mode)
b04ffa56
GJL
11417{
11418 /* FIXME: This hook gets called with MODE:REGNO combinations that don't
11419 represent valid hard registers like, e.g. HI:29. Returning TRUE
11420 for such registers can lead to performance degradation as mentioned
11421 in PR53595. Thus, report invalid hard registers as FALSE. */
00892272 11422
b04ffa56
GJL
11423 if (!avr_hard_regno_mode_ok (regno, mode))
11424 return 0;
00892272 11425
b04ffa56 11426 /* Return true if any of the following boundaries is crossed:
4e2c881f 11427 17/18 or 19/20 (if AVR_TINY), 27/28 and 29/30. */
00892272 11428
4e2c881f
PS
11429 return ((regno <= LAST_CALLEE_SAVED_REG &&
11430 regno + GET_MODE_SIZE (mode) > (LAST_CALLEE_SAVED_REG + 1))
b04ffa56
GJL
11431 || (regno < REG_Y && regno + GET_MODE_SIZE (mode) > REG_Y)
11432 || (regno < REG_Z && regno + GET_MODE_SIZE (mode) > REG_Z));
11433}
11434
11435
8efab2c5
GJL
11436/* Implement `MODE_CODE_BASE_REG_CLASS'. */
11437
ed2d1466 11438enum reg_class
ef4bddc2 11439avr_mode_code_base_reg_class (machine_mode mode ATTRIBUTE_UNUSED,
7c209481 11440 addr_space_t as, RTX_CODE outer_code,
8efab2c5
GJL
11441 RTX_CODE index_code ATTRIBUTE_UNUSED)
11442{
7c209481
GJL
11443 if (!ADDR_SPACE_GENERIC_P (as))
11444 {
11445 return POINTER_Z_REGS;
11446 }
00892272 11447
e8ac5ac9
GJL
11448 if (!avr_strict_X)
11449 return reload_completed ? BASE_POINTER_REGS : POINTER_REGS;
11450
11451 return PLUS == outer_code ? BASE_POINTER_REGS : POINTER_REGS;
8efab2c5
GJL
11452}
11453
11454
11455/* Implement `REGNO_MODE_CODE_OK_FOR_BASE_P'. */
11456
11457bool
11458avr_regno_mode_code_ok_for_base_p (int regno,
ef4bddc2 11459 machine_mode mode ATTRIBUTE_UNUSED,
86fc3d06 11460 addr_space_t as ATTRIBUTE_UNUSED,
e8ac5ac9 11461 RTX_CODE outer_code,
8efab2c5
GJL
11462 RTX_CODE index_code ATTRIBUTE_UNUSED)
11463{
e8ac5ac9 11464 bool ok = false;
00892272 11465
7c209481
GJL
11466 if (!ADDR_SPACE_GENERIC_P (as))
11467 {
11468 if (regno < FIRST_PSEUDO_REGISTER
11469 && regno == REG_Z)
11470 {
11471 return true;
11472 }
00892272 11473
7c209481
GJL
11474 if (reg_renumber)
11475 {
11476 regno = reg_renumber[regno];
00892272 11477
7c209481
GJL
11478 if (regno == REG_Z)
11479 {
11480 return true;
11481 }
11482 }
00892272 11483
7c209481
GJL
11484 return false;
11485 }
11486
8efab2c5
GJL
11487 if (regno < FIRST_PSEUDO_REGISTER
11488 && (regno == REG_X
11489 || regno == REG_Y
11490 || regno == REG_Z
cfbaed3b 11491 || regno == ARG_POINTER_REGNUM))
8efab2c5 11492 {
e8ac5ac9 11493 ok = true;
8efab2c5 11494 }
e8ac5ac9 11495 else if (reg_renumber)
8efab2c5
GJL
11496 {
11497 regno = reg_renumber[regno];
11498
11499 if (regno == REG_X
11500 || regno == REG_Y
11501 || regno == REG_Z
cfbaed3b 11502 || regno == ARG_POINTER_REGNUM)
8efab2c5 11503 {
e8ac5ac9 11504 ok = true;
8efab2c5
GJL
11505 }
11506 }
e8ac5ac9
GJL
11507
11508 if (avr_strict_X
11509 && PLUS == outer_code
11510 && regno == REG_X)
11511 {
11512 ok = false;
11513 }
11514
11515 return ok;
8efab2c5
GJL
11516}
11517
11518
8a6a05ce 11519/* A helper for `output_reload_insisf' and `output_reload_inhi'. */
8dab2ba5
GJL
11520/* Set 32-bit register OP[0] to compile-time constant OP[1].
11521 CLOBBER_REG is a QI clobber register or NULL_RTX.
11522 LEN == NULL: output instructions.
11523 LEN != NULL: set *LEN to the length of the instruction sequence
11524 (in words) printed with LEN = NULL.
11525 If CLEAR_P is true, OP[0] had been cleard to Zero already.
648a7cdc
GJL
11526 If CLEAR_P is false, nothing is known about OP[0].
11527
11528 The effect on cc0 is as follows:
11529
299c4b5f
GJL
11530 Load 0 to any register except ZERO_REG : NONE
11531 Load ld register with any value : NONE
11532 Anything else: : CLOBBER */
1e6a67d1 11533
8dab2ba5 11534static void
20633efc 11535output_reload_in_const (rtx *op, rtx clobber_reg, int *len, bool clear_p)
6bec29c9 11536{
1e6a67d1
GJL
11537 rtx src = op[1];
11538 rtx dest = op[0];
11539 rtx xval, xdest[4];
11540 int ival[4];
11541 int clobber_val = 1234;
11542 bool cooked_clobber_p = false;
11543 bool set_p = false;
ef4bddc2 11544 machine_mode mode = GET_MODE (dest);
7c209481 11545 int n, n_bytes = GET_MODE_SIZE (mode);
00892272 11546
0098895f
GJL
11547 gcc_assert (REG_P (dest)
11548 && CONSTANT_P (src));
5fecfd8d
MM
11549
11550 if (len)
1e6a67d1 11551 *len = 0;
00892272 11552
1e6a67d1
GJL
11553 /* (REG:SI 14) is special: It's neither in LD_REGS nor in NO_LD_REGS
11554 but has some subregs that are in LD_REGS. Use the MSB (REG:QI 17). */
00892272 11555
e4fe948a
GJL
11556 if (REGNO (dest) < 16
11557 && REGNO (dest) + GET_MODE_SIZE (mode) > 16)
5fecfd8d 11558 {
7c209481 11559 clobber_reg = all_regs_rtx[REGNO (dest) + n_bytes - 1];
5fecfd8d 11560 }
6bec29c9 11561
0098895f
GJL
11562 /* We might need a clobber reg but don't have one. Look at the value to
11563 be loaded more closely. A clobber is only needed if it is a symbol
11564 or contains a byte that is neither 0, -1 or a power of 2. */
00892272 11565
1e6a67d1 11566 if (NULL_RTX == clobber_reg
20633efc 11567 && !test_hard_reg_class (LD_REGS, dest)
e55e4056 11568 && (! (CONST_INT_P (src) || CONST_FIXED_P (src) || CONST_DOUBLE_P (src))
0098895f
GJL
11569 || !avr_popcount_each_byte (src, n_bytes,
11570 (1 << 0) | (1 << 1) | (1 << 8))))
6bec29c9 11571 {
20633efc
GJL
11572 /* We have no clobber register but need one. Cook one up.
11573 That's cheaper than loading from constant pool. */
00892272 11574
20633efc 11575 cooked_clobber_p = true;
7c209481 11576 clobber_reg = all_regs_rtx[REG_Z + 1];
20633efc 11577 avr_asm_len ("mov __tmp_reg__,%0", &clobber_reg, len, 1);
6bec29c9 11578 }
1e6a67d1
GJL
11579
11580 /* Now start filling DEST from LSB to MSB. */
00892272 11581
0098895f 11582 for (n = 0; n < n_bytes; n++)
6bec29c9 11583 {
0098895f 11584 int ldreg_p;
1e6a67d1 11585 bool done_byte = false;
7c209481 11586 int j;
1e6a67d1
GJL
11587 rtx xop[3];
11588
0098895f
GJL
11589 /* Crop the n-th destination byte. */
11590
1e6a67d1 11591 xdest[n] = simplify_gen_subreg (QImode, dest, mode, n);
0098895f
GJL
11592 ldreg_p = test_hard_reg_class (LD_REGS, xdest[n]);
11593
11594 if (!CONST_INT_P (src)
e55e4056 11595 && !CONST_FIXED_P (src)
0098895f
GJL
11596 && !CONST_DOUBLE_P (src))
11597 {
11598 static const char* const asm_code[][2] =
11599 {
11600 { "ldi %2,lo8(%1)" CR_TAB "mov %0,%2", "ldi %0,lo8(%1)" },
11601 { "ldi %2,hi8(%1)" CR_TAB "mov %0,%2", "ldi %0,hi8(%1)" },
11602 { "ldi %2,hlo8(%1)" CR_TAB "mov %0,%2", "ldi %0,hlo8(%1)" },
11603 { "ldi %2,hhi8(%1)" CR_TAB "mov %0,%2", "ldi %0,hhi8(%1)" }
11604 };
00892272 11605
0098895f
GJL
11606 xop[0] = xdest[n];
11607 xop[1] = src;
11608 xop[2] = clobber_reg;
11609
cba300dd 11610 avr_asm_len (asm_code[n][ldreg_p], xop, len, ldreg_p ? 1 : 2);
00892272 11611
0098895f
GJL
11612 continue;
11613 }
11614
11615 /* Crop the n-th source byte. */
11616
11617 xval = simplify_gen_subreg (QImode, src, mode, n);
1e6a67d1
GJL
11618 ival[n] = INTVAL (xval);
11619
11620 /* Look if we can reuse the low word by means of MOVW. */
00892272 11621
1e6a67d1 11622 if (n == 2
0098895f 11623 && n_bytes >= 4
1e6a67d1
GJL
11624 && AVR_HAVE_MOVW)
11625 {
11626 rtx lo16 = simplify_gen_subreg (HImode, src, mode, 0);
11627 rtx hi16 = simplify_gen_subreg (HImode, src, mode, 2);
11628
11629 if (INTVAL (lo16) == INTVAL (hi16))
11630 {
8dab2ba5
GJL
11631 if (0 != INTVAL (lo16)
11632 || !clear_p)
11633 {
11634 avr_asm_len ("movw %C0,%A0", &op[0], len, 1);
11635 }
00892272 11636
1e6a67d1
GJL
11637 break;
11638 }
11639 }
11640
648a7cdc 11641 /* Don't use CLR so that cc0 is set as expected. */
00892272 11642
1e6a67d1
GJL
11643 if (ival[n] == 0)
11644 {
8dab2ba5 11645 if (!clear_p)
299c4b5f 11646 avr_asm_len (ldreg_p ? "ldi %0,0"
c1dd9790 11647 : AVR_ZERO_REGNO == REGNO (xdest[n]) ? "clr %0"
299c4b5f 11648 : "mov %0,__zero_reg__",
648a7cdc 11649 &xdest[n], len, 1);
1e6a67d1
GJL
11650 continue;
11651 }
11652
11653 if (clobber_val == ival[n]
11654 && REGNO (clobber_reg) == REGNO (xdest[n]))
11655 {
11656 continue;
11657 }
11658
11659 /* LD_REGS can use LDI to move a constant value */
00892272 11660
0098895f 11661 if (ldreg_p)
1e6a67d1
GJL
11662 {
11663 xop[0] = xdest[n];
11664 xop[1] = xval;
11665 avr_asm_len ("ldi %0,lo8(%1)", xop, len, 1);
11666 continue;
11667 }
11668
11669 /* Try to reuse value already loaded in some lower byte. */
00892272 11670
1e6a67d1
GJL
11671 for (j = 0; j < n; j++)
11672 if (ival[j] == ival[n])
11673 {
11674 xop[0] = xdest[n];
11675 xop[1] = xdest[j];
00892272 11676
1e6a67d1
GJL
11677 avr_asm_len ("mov %0,%1", xop, len, 1);
11678 done_byte = true;
11679 break;
11680 }
11681
11682 if (done_byte)
11683 continue;
11684
11685 /* Need no clobber reg for -1: Use CLR/DEC */
00892272 11686
1e6a67d1
GJL
11687 if (-1 == ival[n])
11688 {
8dab2ba5
GJL
11689 if (!clear_p)
11690 avr_asm_len ("clr %0", &xdest[n], len, 1);
00892272 11691
8dab2ba5
GJL
11692 avr_asm_len ("dec %0", &xdest[n], len, 1);
11693 continue;
11694 }
11695 else if (1 == ival[n])
11696 {
11697 if (!clear_p)
11698 avr_asm_len ("clr %0", &xdest[n], len, 1);
00892272 11699
8dab2ba5 11700 avr_asm_len ("inc %0", &xdest[n], len, 1);
1e6a67d1
GJL
11701 continue;
11702 }
11703
11704 /* Use T flag or INC to manage powers of 2 if we have
11705 no clobber reg. */
11706
11707 if (NULL_RTX == clobber_reg
11708 && single_one_operand (xval, QImode))
11709 {
1e6a67d1
GJL
11710 xop[0] = xdest[n];
11711 xop[1] = GEN_INT (exact_log2 (ival[n] & GET_MODE_MASK (QImode)));
11712
11713 gcc_assert (constm1_rtx != xop[1]);
11714
11715 if (!set_p)
11716 {
11717 set_p = true;
11718 avr_asm_len ("set", xop, len, 1);
11719 }
11720
8dab2ba5
GJL
11721 if (!clear_p)
11722 avr_asm_len ("clr %0", xop, len, 1);
00892272 11723
8dab2ba5 11724 avr_asm_len ("bld %0,%1", xop, len, 1);
1e6a67d1
GJL
11725 continue;
11726 }
11727
11728 /* We actually need the LD_REGS clobber reg. */
11729
11730 gcc_assert (NULL_RTX != clobber_reg);
00892272 11731
1e6a67d1
GJL
11732 xop[0] = xdest[n];
11733 xop[1] = xval;
11734 xop[2] = clobber_reg;
11735 clobber_val = ival[n];
00892272 11736
1e6a67d1
GJL
11737 avr_asm_len ("ldi %2,lo8(%1)" CR_TAB
11738 "mov %0,%2", xop, len, 2);
6bec29c9 11739 }
00892272 11740
1e6a67d1 11741 /* If we cooked up a clobber reg above, restore it. */
00892272 11742
1e6a67d1 11743 if (cooked_clobber_p)
6bec29c9 11744 {
1e6a67d1 11745 avr_asm_len ("mov %0,__tmp_reg__", &clobber_reg, len, 1);
6bec29c9 11746 }
8dab2ba5
GJL
11747}
11748
11749
20633efc
GJL
11750/* Reload the constant OP[1] into the HI register OP[0].
11751 CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
11752 into a NO_LD_REGS register. If CLOBBER_REG is NULL_RTX we either don't
11753 need a clobber reg or have to cook one up.
11754
11755 PLEN == NULL: Output instructions.
11756 PLEN != NULL: Output nothing. Set *PLEN to number of words occupied
11757 by the insns printed.
11758
11759 Return "". */
11760
11761const char*
11762output_reload_inhi (rtx *op, rtx clobber_reg, int *plen)
11763{
0098895f 11764 output_reload_in_const (op, clobber_reg, plen, false);
20633efc
GJL
11765 return "";
11766}
11767
11768
8dab2ba5
GJL
11769/* Reload a SI or SF compile time constant OP[1] into the register OP[0].
11770 CLOBBER_REG is a QI clobber reg needed to move vast majority of consts
11771 into a NO_LD_REGS register. If CLOBBER_REG is NULL_RTX we either don't
11772 need a clobber reg or have to cook one up.
11773
11774 LEN == NULL: Output instructions.
00892272 11775
4103605f 11776 LEN != NULL: Output nothing. Set *LEN to number of words occupied
8dab2ba5
GJL
11777 by the insns printed.
11778
11779 Return "". */
11780
11781const char *
8a6a05ce 11782output_reload_insisf (rtx *op, rtx clobber_reg, int *len)
8dab2ba5 11783{
8dab2ba5 11784 if (AVR_HAVE_MOVW
5436efaa
GJL
11785 && !test_hard_reg_class (LD_REGS, op[0])
11786 && (CONST_INT_P (op[1])
e55e4056 11787 || CONST_FIXED_P (op[1])
5436efaa 11788 || CONST_DOUBLE_P (op[1])))
8dab2ba5
GJL
11789 {
11790 int len_clr, len_noclr;
00892272 11791
8dab2ba5
GJL
11792 /* In some cases it is better to clear the destination beforehand, e.g.
11793
11794 CLR R2 CLR R3 MOVW R4,R2 INC R2
11795
11796 is shorther than
11797
11798 CLR R2 INC R2 CLR R3 CLR R4 CLR R5
11799
11800 We find it too tedious to work that out in the print function.
11801 Instead, we call the print function twice to get the lengths of
11802 both methods and use the shortest one. */
00892272 11803
20633efc
GJL
11804 output_reload_in_const (op, clobber_reg, &len_clr, true);
11805 output_reload_in_const (op, clobber_reg, &len_noclr, false);
00892272 11806
8dab2ba5
GJL
11807 if (len_noclr - len_clr == 4)
11808 {
11809 /* Default needs 4 CLR instructions: clear register beforehand. */
00892272 11810
299c4b5f
GJL
11811 avr_asm_len ("mov %A0,__zero_reg__" CR_TAB
11812 "mov %B0,__zero_reg__" CR_TAB
8dab2ba5 11813 "movw %C0,%A0", &op[0], len, 3);
00892272 11814
20633efc 11815 output_reload_in_const (op, clobber_reg, len, true);
00892272 11816
8dab2ba5
GJL
11817 if (len)
11818 *len += 3;
11819
11820 return "";
11821 }
11822 }
11823
11824 /* Default: destination not pre-cleared. */
11825
20633efc 11826 output_reload_in_const (op, clobber_reg, len, false);
6bec29c9
DC
11827 return "";
11828}
afee2a52 11829
00892272 11830const char*
e4fe948a
GJL
11831avr_out_reload_inpsi (rtx *op, rtx clobber_reg, int *len)
11832{
e4fe948a
GJL
11833 output_reload_in_const (op, clobber_reg, len, false);
11834 return "";
11835}
11836
afee2a52 11837
00892272
GJL
11838/* Worker function for `ASM_OUTPUT_ADDR_VEC_ELT'. */
11839
e9284adf 11840void
269e3795 11841avr_output_addr_vec_elt (FILE *stream, int value)
e9284adf 11842{
693092fb
BH
11843 if (AVR_HAVE_JMP_CALL)
11844 fprintf (stream, "\t.word gs(.L%d)\n", value);
e9284adf
MM
11845 else
11846 fprintf (stream, "\trjmp .L%d\n", value);
e9284adf
MM
11847}
11848
c1dd9790 11849static void
0c9ef7ad
GJL
11850avr_conditional_register_usage(void)
11851{
11852 if (AVR_TINY)
11853 {
11854 unsigned int i;
c1dd9790 11855
0c9ef7ad
GJL
11856 const int tiny_reg_alloc_order[] = {
11857 24, 25,
11858 22, 23,
11859 30, 31,
11860 26, 27,
11861 28, 29,
11862 21, 20, 19, 18,
11863 16, 17,
11864 32, 33, 34, 35,
11865 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
11866 };
c1dd9790 11867
0c9ef7ad
GJL
11868 /* Set R0-R17 as fixed registers. Reset R0-R17 in call used register list
11869 - R0-R15 are not available in Tiny Core devices
11870 - R16 and R17 are fixed registers. */
c1dd9790 11871
0c9ef7ad
GJL
11872 for (i = 0; i <= 17; i++)
11873 {
11874 fixed_regs[i] = 1;
11875 call_used_regs[i] = 1;
11876 }
c1dd9790 11877
0c9ef7ad
GJL
11878 /* Set R18 to R21 as callee saved registers
11879 - R18, R19, R20 and R21 are the callee saved registers in
11880 Tiny Core devices */
c1dd9790 11881
0c9ef7ad
GJL
11882 for (i = 18; i <= LAST_CALLEE_SAVED_REG; i++)
11883 {
11884 call_used_regs[i] = 0;
11885 }
c1dd9790 11886
0c9ef7ad
GJL
11887 /* Update register allocation order for Tiny Core devices */
11888
11889 for (i = 0; i < ARRAY_SIZE (tiny_reg_alloc_order); i++)
11890 {
11891 reg_alloc_order[i] = tiny_reg_alloc_order[i];
11892 }
11893
11894 CLEAR_HARD_REG_SET (reg_class_contents[(int) ADDW_REGS]);
11895 CLEAR_HARD_REG_SET (reg_class_contents[(int) NO_LD_REGS]);
11896 }
c1dd9790 11897}
00892272
GJL
11898
11899/* Implement `TARGET_HARD_REGNO_SCRATCH_OK'. */
1cf0a7f1 11900/* Returns true if SCRATCH are safe to be allocated as a scratch
dcfb1a36
MM
11901 registers (for a define_peephole2) in the current function. */
11902
d2111e2f 11903static bool
1cf0a7f1 11904avr_hard_regno_scratch_ok (unsigned int regno)
dcfb1a36 11905{
1cf0a7f1
AS
11906 /* Interrupt functions can only use registers that have already been saved
11907 by the prologue, even if they would normally be call-clobbered. */
dcfb1a36 11908
1cf0a7f1
AS
11909 if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
11910 && !df_regs_ever_live_p (regno))
11911 return false;
11912
3e4f8484
GJL
11913 /* Don't allow hard registers that might be part of the frame pointer.
11914 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
11915 and don't care for a frame pointer that spans more than one register. */
11916
11917 if ((!reload_completed || frame_pointer_needed)
11918 && (regno == REG_Y || regno == REG_Y + 1))
11919 {
11920 return false;
11921 }
11922
1cf0a7f1 11923 return true;
dcfb1a36 11924}
331ca350 11925
00892272
GJL
11926
11927/* Worker function for `HARD_REGNO_RENAME_OK'. */
91635d08
AS
11928/* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
11929
11930int
3e4f8484 11931avr_hard_regno_rename_ok (unsigned int old_reg,
91635d08
AS
11932 unsigned int new_reg)
11933{
11934 /* Interrupt functions can only use registers that have already been
11935 saved by the prologue, even if they would normally be
11936 call-clobbered. */
11937
11938 if ((cfun->machine->is_interrupt || cfun->machine->is_signal)
11939 && !df_regs_ever_live_p (new_reg))
11940 return 0;
11941
3e4f8484
GJL
11942 /* Don't allow hard registers that might be part of the frame pointer.
11943 Some places in the compiler just test for [HARD_]FRAME_POINTER_REGNUM
11944 and don't care for a frame pointer that spans more than one register. */
11945
11946 if ((!reload_completed || frame_pointer_needed)
11947 && (old_reg == REG_Y || old_reg == REG_Y + 1
11948 || new_reg == REG_Y || new_reg == REG_Y + 1))
11949 {
11950 return 0;
11951 }
00892272 11952
91635d08
AS
11953 return 1;
11954}
11955
ed1f5d71 11956/* Output a branch that tests a single bit of a register (QI, HI, SI or DImode)
331ca350
MM
11957 or memory location in the I/O space (QImode only).
11958
11959 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
11960 Operand 1: register operand to test, or CONST_INT memory address.
ed1f5d71 11961 Operand 2: bit number.
331ca350
MM
11962 Operand 3: label to jump to if the test is true. */
11963
00892272 11964const char*
98024b4e 11965avr_out_sbxx_branch (rtx_insn *insn, rtx operands[])
331ca350
MM
11966{
11967 enum rtx_code comp = GET_CODE (operands[0]);
7bc6df2c
GJL
11968 bool long_jump = get_attr_length (insn) >= 4;
11969 bool reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
331ca350
MM
11970
11971 if (comp == GE)
11972 comp = EQ;
11973 else if (comp == LT)
11974 comp = NE;
11975
11976 if (reverse)
11977 comp = reverse_condition (comp);
11978
7bc6df2c 11979 switch (GET_CODE (operands[1]))
331ca350 11980 {
7bc6df2c
GJL
11981 default:
11982 gcc_unreachable();
00892272 11983
7bc6df2c 11984 case CONST_INT:
f9d29866
JR
11985 case CONST:
11986 case SYMBOL_REF:
7bc6df2c
GJL
11987
11988 if (low_io_address_operand (operands[1], QImode))
11989 {
11990 if (comp == EQ)
5436efaa 11991 output_asm_insn ("sbis %i1,%2", operands);
7bc6df2c 11992 else
5436efaa 11993 output_asm_insn ("sbic %i1,%2", operands);
7bc6df2c 11994 }
331ca350 11995 else
7bc6df2c 11996 {
f9d29866 11997 gcc_assert (io_address_operand (operands[1], QImode));
5436efaa 11998 output_asm_insn ("in __tmp_reg__,%i1", operands);
7bc6df2c
GJL
11999 if (comp == EQ)
12000 output_asm_insn ("sbrs __tmp_reg__,%2", operands);
12001 else
12002 output_asm_insn ("sbrc __tmp_reg__,%2", operands);
12003 }
12004
12005 break; /* CONST_INT */
12006
12007 case REG:
12008
20848609
GJL
12009 if (comp == EQ)
12010 output_asm_insn ("sbrs %T1%T2", operands);
12011 else
12012 output_asm_insn ("sbrc %T1%T2", operands);
7bc6df2c
GJL
12013
12014 break; /* REG */
12015 } /* switch */
331ca350
MM
12016
12017 if (long_jump)
7bc6df2c
GJL
12018 return ("rjmp .+4" CR_TAB
12019 "jmp %x3");
12020
331ca350 12021 if (!reverse)
7bc6df2c
GJL
12022 return "rjmp %x3";
12023
331ca350
MM
12024 return "";
12025}
9af145ae 12026
00892272 12027/* Worker function for `TARGET_ASM_CONSTRUCTOR'. */
bd5bd7ac 12028
9af145ae 12029static void
269e3795 12030avr_asm_out_ctor (rtx symbol, int priority)
9af145ae
MM
12031{
12032 fputs ("\t.global __do_global_ctors\n", asm_out_file);
12033 default_ctor_section_asm_out_constructor (symbol, priority);
12034}
12035
00892272
GJL
12036
12037/* Worker function for `TARGET_ASM_DESTRUCTOR'. */
bd5bd7ac 12038
9af145ae 12039static void
269e3795 12040avr_asm_out_dtor (rtx symbol, int priority)
9af145ae
MM
12041{
12042 fputs ("\t.global __do_global_dtors\n", asm_out_file);
12043 default_dtor_section_asm_out_destructor (symbol, priority);
12044}
12045
00892272
GJL
12046
12047/* Worker function for `TARGET_RETURN_IN_MEMORY'. */
bd5bd7ac 12048
b069302c 12049static bool
586de218 12050avr_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
b069302c 12051{
c1dd9790 12052 HOST_WIDE_INT size = int_size_in_bytes (type);
0c9ef7ad 12053 HOST_WIDE_INT ret_size_limit = AVR_TINY ? 4 : 8;
c1dd9790 12054
0c9ef7ad
GJL
12055 /* In avr, there are 8 return registers. But, for Tiny Core
12056 (ATtiny4/5/9/10/20/40) devices, only 4 registers are available.
12057 Return true if size is unknown or greater than the limit. */
12058
12059 if (size == -1 || size > ret_size_limit)
12060 {
12061 return true;
12062 }
78bc94a2 12063 else
0c9ef7ad
GJL
12064 {
12065 return false;
12066 }
b069302c
KH
12067}
12068
102375cc
GJL
12069
12070/* Implement `CASE_VALUES_THRESHOLD'. */
12071/* Supply the default for --param case-values-threshold=0 */
4223ff5f 12072
d2111e2f
GJL
12073static unsigned int
12074avr_case_values_threshold (void)
4223ff5f 12075{
102375cc
GJL
12076 /* The exact break-even point between a jump table and an if-else tree
12077 depends on several factors not available here like, e.g. if 8-bit
12078 comparisons can be used in the if-else tree or not, on the
12079 range of the case values, if the case value can be reused, on the
12080 register allocation, etc. '7' appears to be a good choice. */
00892272 12081
102375cc 12082 return 7;
4223ff5f
AS
12083}
12084
7c209481
GJL
12085
12086/* Implement `TARGET_ADDR_SPACE_ADDRESS_MODE'. */
12087
ef4bddc2 12088static machine_mode
7bc6df2c 12089avr_addr_space_address_mode (addr_space_t as)
7c209481 12090{
562f552b 12091 return avr_addrspace[as].pointer_size == 3 ? PSImode : HImode;
7c209481
GJL
12092}
12093
12094
12095/* Implement `TARGET_ADDR_SPACE_POINTER_MODE'. */
12096
ef4bddc2 12097static machine_mode
7bc6df2c 12098avr_addr_space_pointer_mode (addr_space_t as)
7c209481 12099{
562f552b 12100 return avr_addr_space_address_mode (as);
7c209481
GJL
12101}
12102
12103
12104/* Helper for following function. */
12105
12106static bool
12107avr_reg_ok_for_pgm_addr (rtx reg, bool strict)
12108{
3fd1e31d 12109 gcc_assert (REG_P (reg));
7c209481
GJL
12110
12111 if (strict)
12112 {
12113 return REGNO (reg) == REG_Z;
12114 }
00892272 12115
7c209481 12116 /* Avoid combine to propagate hard regs. */
00892272 12117
7c209481
GJL
12118 if (can_create_pseudo_p()
12119 && REGNO (reg) < REG_Z)
12120 {
12121 return false;
12122 }
00892272 12123
7c209481
GJL
12124 return true;
12125}
12126
12127
12128/* Implement `TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P'. */
12129
12130static bool
ef4bddc2 12131avr_addr_space_legitimate_address_p (machine_mode mode, rtx x,
7c209481
GJL
12132 bool strict, addr_space_t as)
12133{
12134 bool ok = false;
12135
12136 switch (as)
12137 {
12138 default:
12139 gcc_unreachable();
00892272 12140
7c209481
GJL
12141 case ADDR_SPACE_GENERIC:
12142 return avr_legitimate_address_p (mode, x, strict);
12143
3a840863
GJL
12144 case ADDR_SPACE_FLASH:
12145 case ADDR_SPACE_FLASH1:
12146 case ADDR_SPACE_FLASH2:
12147 case ADDR_SPACE_FLASH3:
12148 case ADDR_SPACE_FLASH4:
12149 case ADDR_SPACE_FLASH5:
7c209481
GJL
12150
12151 switch (GET_CODE (x))
12152 {
12153 case REG:
12154 ok = avr_reg_ok_for_pgm_addr (x, strict);
12155 break;
00892272 12156
7c209481 12157 case POST_INC:
7bc6df2c 12158 ok = avr_reg_ok_for_pgm_addr (XEXP (x, 0), strict);
7c209481 12159 break;
00892272 12160
7c209481
GJL
12161 default:
12162 break;
12163 }
12164
3a840863 12165 break; /* FLASH */
00892272 12166
3a840863 12167 case ADDR_SPACE_MEMX:
7bc6df2c
GJL
12168 if (REG_P (x))
12169 ok = (!strict
12170 && can_create_pseudo_p());
12171
12172 if (LO_SUM == GET_CODE (x))
12173 {
12174 rtx hi = XEXP (x, 0);
12175 rtx lo = XEXP (x, 1);
12176
12177 ok = (REG_P (hi)
12178 && (!strict || REGNO (hi) < FIRST_PSEUDO_REGISTER)
12179 && REG_P (lo)
12180 && REGNO (lo) == REG_Z);
12181 }
00892272 12182
3a840863 12183 break; /* MEMX */
7c209481
GJL
12184 }
12185
12186 if (avr_log.legitimate_address_p)
12187 {
12188 avr_edump ("\n%?: ret=%b, mode=%m strict=%d "
12189 "reload_completed=%d reload_in_progress=%d %s:",
12190 ok, mode, strict, reload_completed, reload_in_progress,
12191 reg_renumber ? "(reg_renumber)" : "");
00892272 12192
7c209481
GJL
12193 if (GET_CODE (x) == PLUS
12194 && REG_P (XEXP (x, 0))
12195 && CONST_INT_P (XEXP (x, 1))
12196 && IN_RANGE (INTVAL (XEXP (x, 1)), 0, MAX_LD_OFFSET (mode))
12197 && reg_renumber)
12198 {
12199 avr_edump ("(r%d ---> r%d)", REGNO (XEXP (x, 0)),
12200 true_regnum (XEXP (x, 0)));
12201 }
00892272 12202
7c209481
GJL
12203 avr_edump ("\n%r\n", x);
12204 }
12205
12206 return ok;
12207}
12208
12209
12210/* Implement `TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS'. */
12211
12212static rtx
12213avr_addr_space_legitimize_address (rtx x, rtx old_x,
ef4bddc2 12214 machine_mode mode, addr_space_t as)
7c209481
GJL
12215{
12216 if (ADDR_SPACE_GENERIC_P (as))
12217 return avr_legitimize_address (x, old_x, mode);
12218
12219 if (avr_log.legitimize_address)
12220 {
12221 avr_edump ("\n%?: mode=%m\n %r\n", mode, old_x);
12222 }
12223
12224 return old_x;
12225}
12226
12227
12228/* Implement `TARGET_ADDR_SPACE_CONVERT'. */
12229
12230static rtx
12231avr_addr_space_convert (rtx src, tree type_from, tree type_to)
12232{
7bc6df2c
GJL
12233 addr_space_t as_from = TYPE_ADDR_SPACE (TREE_TYPE (type_from));
12234 addr_space_t as_to = TYPE_ADDR_SPACE (TREE_TYPE (type_to));
12235
7c209481
GJL
12236 if (avr_log.progmem)
12237 avr_edump ("\n%!: op = %r\nfrom = %t\nto = %t\n",
12238 src, type_from, type_to);
12239
cba300dd 12240 /* Up-casting from 16-bit to 24-bit pointer. */
00892272 12241
3a840863
GJL
12242 if (as_from != ADDR_SPACE_MEMX
12243 && as_to == ADDR_SPACE_MEMX)
7bc6df2c 12244 {
cba300dd
GJL
12245 int msb;
12246 rtx sym = src;
12247 rtx reg = gen_reg_rtx (PSImode);
12248
12249 while (CONST == GET_CODE (sym) || PLUS == GET_CODE (sym))
12250 sym = XEXP (sym, 0);
12251
12252 /* Look at symbol flags: avr_encode_section_info set the flags
12253 also if attribute progmem was seen so that we get the right
12254 promotion for, e.g. PSTR-like strings that reside in generic space
12255 but are located in flash. In that case we patch the incoming
12256 address space. */
7bc6df2c 12257
cba300dd 12258 if (SYMBOL_REF == GET_CODE (sym)
3a840863 12259 && ADDR_SPACE_FLASH == AVR_SYMBOL_GET_ADDR_SPACE (sym))
7bc6df2c 12260 {
3a840863 12261 as_from = ADDR_SPACE_FLASH;
7bc6df2c
GJL
12262 }
12263
cba300dd 12264 /* Linearize memory: RAM has bit 23 set. */
00892272 12265
cba300dd
GJL
12266 msb = ADDR_SPACE_GENERIC_P (as_from)
12267 ? 0x80
bae3b1bf 12268 : avr_addrspace[as_from].segment;
cba300dd 12269
7bc6df2c 12270 src = force_reg (Pmode, src);
00892272 12271
cba300dd
GJL
12272 emit_insn (msb == 0
12273 ? gen_zero_extendhipsi2 (reg, src)
12274 : gen_n_extendhipsi2 (reg, gen_int_mode (msb, QImode), src));
00892272 12275
cba300dd
GJL
12276 return reg;
12277 }
7bc6df2c 12278
cba300dd 12279 /* Down-casting from 24-bit to 16-bit throws away the high byte. */
7bc6df2c 12280
3a840863
GJL
12281 if (as_from == ADDR_SPACE_MEMX
12282 && as_to != ADDR_SPACE_MEMX)
cba300dd
GJL
12283 {
12284 rtx new_src = gen_reg_rtx (Pmode);
12285
12286 src = force_reg (PSImode, src);
00892272 12287
cba300dd
GJL
12288 emit_move_insn (new_src,
12289 simplify_gen_subreg (Pmode, src, PSImode, 0));
12290 return new_src;
7bc6df2c 12291 }
00892272 12292
7c209481
GJL
12293 return src;
12294}
12295
12296
12297/* Implement `TARGET_ADDR_SPACE_SUBSET_P'. */
12298
12299static bool
cba300dd
GJL
12300avr_addr_space_subset_p (addr_space_t subset ATTRIBUTE_UNUSED,
12301 addr_space_t superset ATTRIBUTE_UNUSED)
7c209481 12302{
cba300dd 12303 /* Allow any kind of pointer mess. */
00892272 12304
7bc6df2c
GJL
12305 return true;
12306}
12307
12308
f22e3c85
GJL
12309/* Implement `TARGET_CONVERT_TO_TYPE'. */
12310
12311static tree
12312avr_convert_to_type (tree type, tree expr)
12313{
12314 /* Print a diagnose for pointer conversion that changes the address
12315 space of the pointer target to a non-enclosing address space,
12316 provided -Waddr-space-convert is on.
12317
12318 FIXME: Filter out cases where the target object is known to
12319 be located in the right memory, like in
12320
12321 (const __flash*) PSTR ("text")
12322
12323 Also try to distinguish between explicit casts requested by
12324 the user and implicit casts like
12325
12326 void f (const __flash char*);
12327
12328 void g (const char *p)
12329 {
12330 f ((const __flash*) p);
12331 }
12332
12333 under the assumption that an explicit casts means that the user
12334 knows what he is doing, e.g. interface with PSTR or old style
12335 code with progmem and pgm_read_xxx.
12336 */
12337
12338 if (avr_warn_addr_space_convert
12339 && expr != error_mark_node
12340 && POINTER_TYPE_P (type)
12341 && POINTER_TYPE_P (TREE_TYPE (expr)))
12342 {
12343 addr_space_t as_old = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (expr)));
12344 addr_space_t as_new = TYPE_ADDR_SPACE (TREE_TYPE (type));
0c9ef7ad 12345
f22e3c85
GJL
12346 if (avr_log.progmem)
12347 avr_edump ("%?: type = %t\nexpr = %t\n\n", type, expr);
12348
12349 if (as_new != ADDR_SPACE_MEMX
12350 && as_new != as_old)
12351 {
12352 location_t loc = EXPR_LOCATION (expr);
12353 const char *name_old = avr_addrspace[as_old].name;
12354 const char *name_new = avr_addrspace[as_new].name;
12355
12356 warning (OPT_Waddr_space_convert,
12357 "conversion from address space %qs to address space %qs",
12358 ADDR_SPACE_GENERIC_P (as_old) ? "generic" : name_old,
12359 ADDR_SPACE_GENERIC_P (as_new) ? "generic" : name_new);
12360
12361 return fold_build1_loc (loc, ADDR_SPACE_CONVERT_EXPR, type, expr);
12362 }
12363 }
12364
12365 return NULL_TREE;
12366}
12367
12368
00e641f1
GJL
12369/* PR63633: The middle-end might come up with hard regs as input operands.
12370
12371 RMASK is a bit mask representing a subset of hard registers R0...R31:
12372 Rn is an element of that set iff bit n of RMASK is set.
12373 OPMASK describes a subset of OP[]: If bit n of OPMASK is 1 then
12374 OP[n] has to be fixed; otherwise OP[n] is left alone.
12375
12376 For each element of OPMASK which is a hard register overlapping RMASK,
12377 replace OP[n] with a newly created pseudo register
12378
12379 HREG == 0: Also emit a move insn that copies the contents of that
12380 hard register into the new pseudo.
12381
12382 HREG != 0: Also set HREG[n] to the hard register. */
12383
12384static void
12385avr_fix_operands (rtx *op, rtx *hreg, unsigned opmask, unsigned rmask)
12386{
12387 for (; opmask; opmask >>= 1, op++)
12388 {
12389 rtx reg = *op;
12390
12391 if (hreg)
12392 *hreg = NULL_RTX;
12393
12394 if ((opmask & 1)
12395 && REG_P (reg)
12396 && REGNO (reg) < FIRST_PSEUDO_REGISTER
12397 // This hard-reg overlaps other prohibited hard regs?
12398 && (rmask & regmask (GET_MODE (reg), REGNO (reg))))
12399 {
12400 *op = gen_reg_rtx (GET_MODE (reg));
12401 if (hreg == NULL)
12402 emit_move_insn (*op, reg);
12403 else
12404 *hreg = reg;
12405 }
12406
12407 if (hreg)
12408 hreg++;
12409 }
12410}
12411
12412
12413void
12414avr_fix_inputs (rtx *op, unsigned opmask, unsigned rmask)
12415{
12416 avr_fix_operands (op, NULL, opmask, rmask);
12417}
12418
12419
12420/* Helper for the function below: If bit n of MASK is set and
12421 HREG[n] != NULL, then emit a move insn to copy OP[n] to HREG[n].
12422 Otherwise do nothing for that n. Return TRUE. */
12423
12424static bool
12425avr_move_fixed_operands (rtx *op, rtx *hreg, unsigned mask)
12426{
12427 for (; mask; mask >>= 1, op++, hreg++)
12428 if ((mask & 1)
12429 && *hreg)
12430 emit_move_insn (*hreg, *op);
12431
12432 return true;
12433}
12434
12435
12436/* PR63633: The middle-end might come up with hard regs as output operands.
12437
12438 GEN is a sequence generating function like gen_mulsi3 with 3 operands OP[].
12439 RMASK is a bit mask representing a subset of hard registers R0...R31:
12440 Rn is an element of that set iff bit n of RMASK is set.
12441 OPMASK describes a subset of OP[]: If bit n of OPMASK is 1 then
12442 OP[n] has to be fixed; otherwise OP[n] is left alone.
12443
12444 Emit the insn sequence as generated by GEN() with all elements of OPMASK
12445 which are hard registers overlapping RMASK replaced by newly created
12446 pseudo registers. After the sequence has been emitted, emit insns that
12447 move the contents of respective pseudos to their hard regs. */
12448
12449bool
12450avr_emit3_fix_outputs (rtx (*gen)(rtx,rtx,rtx), rtx *op,
12451 unsigned opmask, unsigned rmask)
12452{
12453 const int n = 3;
12454 rtx hreg[n];
12455
12456 /* It is letigimate for GEN to call this function, and in order not to
12457 get self-recursive we use the following static kludge. This is the
12458 only way not to duplicate all expanders and to avoid ugly and
12459 hard-to-maintain C-code instead of the much more appreciated RTL
12460 representation as supplied by define_expand. */
12461 static bool lock = false;
12462
12463 gcc_assert (opmask < (1u << n));
12464
12465 if (lock)
12466 return false;
12467
12468 avr_fix_operands (op, hreg, opmask, rmask);
12469
12470 lock = true;
12471 emit_insn (gen (op[0], op[1], op[2]));
12472 lock = false;
12473
12474 return avr_move_fixed_operands (op, hreg, opmask);
12475}
12476
12477
cba300dd 12478/* Worker function for movmemhi expander.
7bc6df2c
GJL
12479 XOP[0] Destination as MEM:BLK
12480 XOP[1] Source " "
12481 XOP[2] # Bytes to copy
12482
12483 Return TRUE if the expansion is accomplished.
12484 Return FALSE if the operand compination is not supported. */
12485
12486bool
12487avr_emit_movmemhi (rtx *xop)
12488{
12489 HOST_WIDE_INT count;
ef4bddc2 12490 machine_mode loop_mode;
7bc6df2c 12491 addr_space_t as = MEM_ADDR_SPACE (xop[1]);
8310dca7 12492 rtx loop_reg, addr1, a_src, a_dest, insn, xas;
7bc6df2c
GJL
12493 rtx a_hi8 = NULL_RTX;
12494
3a840863 12495 if (avr_mem_flash_p (xop[0]))
7bc6df2c
GJL
12496 return false;
12497
12498 if (!CONST_INT_P (xop[2]))
12499 return false;
12500
12501 count = INTVAL (xop[2]);
12502 if (count <= 0)
12503 return false;
12504
12505 a_src = XEXP (xop[1], 0);
12506 a_dest = XEXP (xop[0], 0);
12507
7bc6df2c
GJL
12508 if (PSImode == GET_MODE (a_src))
12509 {
3a840863 12510 gcc_assert (as == ADDR_SPACE_MEMX);
cba300dd
GJL
12511
12512 loop_mode = (count < 0x100) ? QImode : HImode;
12513 loop_reg = gen_rtx_REG (loop_mode, 24);
12514 emit_move_insn (loop_reg, gen_int_mode (count, loop_mode));
12515
7bc6df2c
GJL
12516 addr1 = simplify_gen_subreg (HImode, a_src, PSImode, 0);
12517 a_hi8 = simplify_gen_subreg (QImode, a_src, PSImode, 2);
12518 }
12519 else
12520 {
bae3b1bf 12521 int segment = avr_addrspace[as].segment;
00892272 12522
cba300dd 12523 if (segment
f9d29866 12524 && avr_n_flash > 1)
cba300dd
GJL
12525 {
12526 a_hi8 = GEN_INT (segment);
12527 emit_move_insn (rampz_rtx, a_hi8 = copy_to_mode_reg (QImode, a_hi8));
12528 }
12529 else if (!ADDR_SPACE_GENERIC_P (as))
12530 {
3a840863 12531 as = ADDR_SPACE_FLASH;
cba300dd 12532 }
00892272 12533
7bc6df2c
GJL
12534 addr1 = a_src;
12535
cba300dd
GJL
12536 loop_mode = (count <= 0x100) ? QImode : HImode;
12537 loop_reg = copy_to_mode_reg (loop_mode, gen_int_mode (count, loop_mode));
7bc6df2c
GJL
12538 }
12539
12540 xas = GEN_INT (as);
12541
7bc6df2c 12542 /* FIXME: Register allocator might come up with spill fails if it is left
cba300dd
GJL
12543 on its own. Thus, we allocate the pointer registers by hand:
12544 Z = source address
12545 X = destination address */
7bc6df2c
GJL
12546
12547 emit_move_insn (lpm_addr_reg_rtx, addr1);
8310dca7 12548 emit_move_insn (gen_rtx_REG (HImode, REG_X), a_dest);
7bc6df2c
GJL
12549
12550 /* FIXME: Register allocator does a bad job and might spill address
12551 register(s) inside the loop leading to additional move instruction
12552 to/from stack which could clobber tmp_reg. Thus, do *not* emit
073a8998 12553 load and store as separate insns. Instead, we perform the copy
7bc6df2c
GJL
12554 by means of one monolithic insn. */
12555
cba300dd
GJL
12556 gcc_assert (TMP_REGNO == LPM_REGNO);
12557
3a840863 12558 if (as != ADDR_SPACE_MEMX)
7bc6df2c 12559 {
cba300dd
GJL
12560 /* Load instruction ([E]LPM or LD) is known at compile time:
12561 Do the copy-loop inline. */
00892272 12562
8310dca7 12563 rtx (*fun) (rtx, rtx, rtx)
7bc6df2c
GJL
12564 = QImode == loop_mode ? gen_movmem_qi : gen_movmem_hi;
12565
8310dca7 12566 insn = fun (xas, loop_reg, loop_reg);
7bc6df2c 12567 }
7bc6df2c
GJL
12568 else
12569 {
8310dca7 12570 rtx (*fun) (rtx, rtx)
cba300dd
GJL
12571 = QImode == loop_mode ? gen_movmemx_qi : gen_movmemx_hi;
12572
8310dca7 12573 emit_move_insn (gen_rtx_REG (QImode, 23), a_hi8);
00892272 12574
8310dca7 12575 insn = fun (xas, GEN_INT (avr_addr.rampz));
7bc6df2c
GJL
12576 }
12577
12578 set_mem_addr_space (SET_SRC (XVECEXP (insn, 0, 0)), as);
12579 emit_insn (insn);
12580
7c209481
GJL
12581 return true;
12582}
12583
12584
7bc6df2c 12585/* Print assembler for movmem_qi, movmem_hi insns...
8310dca7
GJL
12586 $0 : Address Space
12587 $1, $2 : Loop register
12588 Z : Source address
12589 X : Destination address
7bc6df2c
GJL
12590*/
12591
12592const char*
98024b4e 12593avr_out_movmem (rtx_insn *insn ATTRIBUTE_UNUSED, rtx *op, int *plen)
7bc6df2c 12594{
8310dca7 12595 addr_space_t as = (addr_space_t) INTVAL (op[0]);
ef4bddc2 12596 machine_mode loop_mode = GET_MODE (op[1]);
8310dca7
GJL
12597 bool sbiw_p = test_hard_reg_class (ADDW_REGS, op[1]);
12598 rtx xop[3];
7bc6df2c
GJL
12599
12600 if (plen)
12601 *plen = 0;
12602
8310dca7
GJL
12603 xop[0] = op[0];
12604 xop[1] = op[1];
12605 xop[2] = tmp_reg_rtx;
12606
7bc6df2c
GJL
12607 /* Loop label */
12608
12609 avr_asm_len ("0:", xop, plen, 0);
12610
12611 /* Load with post-increment */
12612
12613 switch (as)
12614 {
12615 default:
12616 gcc_unreachable();
00892272 12617
7bc6df2c
GJL
12618 case ADDR_SPACE_GENERIC:
12619
8310dca7 12620 avr_asm_len ("ld %2,Z+", xop, plen, 1);
7bc6df2c 12621 break;
00892272 12622
3a840863 12623 case ADDR_SPACE_FLASH:
7bc6df2c
GJL
12624
12625 if (AVR_HAVE_LPMX)
2f986dce 12626 avr_asm_len ("lpm %2,Z+", xop, plen, 1);
7bc6df2c
GJL
12627 else
12628 avr_asm_len ("lpm" CR_TAB
8310dca7 12629 "adiw r30,1", xop, plen, 2);
7bc6df2c 12630 break;
00892272 12631
3a840863
GJL
12632 case ADDR_SPACE_FLASH1:
12633 case ADDR_SPACE_FLASH2:
12634 case ADDR_SPACE_FLASH3:
12635 case ADDR_SPACE_FLASH4:
12636 case ADDR_SPACE_FLASH5:
7bc6df2c
GJL
12637
12638 if (AVR_HAVE_ELPMX)
8310dca7 12639 avr_asm_len ("elpm %2,Z+", xop, plen, 1);
7bc6df2c
GJL
12640 else
12641 avr_asm_len ("elpm" CR_TAB
8310dca7 12642 "adiw r30,1", xop, plen, 2);
7bc6df2c
GJL
12643 break;
12644 }
12645
12646 /* Store with post-increment */
12647
8310dca7 12648 avr_asm_len ("st X+,%2", xop, plen, 1);
7bc6df2c
GJL
12649
12650 /* Decrement loop-counter and set Z-flag */
12651
12652 if (QImode == loop_mode)
12653 {
8310dca7 12654 avr_asm_len ("dec %1", xop, plen, 1);
7bc6df2c
GJL
12655 }
12656 else if (sbiw_p)
12657 {
8310dca7 12658 avr_asm_len ("sbiw %1,1", xop, plen, 1);
7bc6df2c
GJL
12659 }
12660 else
12661 {
8310dca7
GJL
12662 avr_asm_len ("subi %A1,1" CR_TAB
12663 "sbci %B1,0", xop, plen, 2);
7bc6df2c
GJL
12664 }
12665
12666 /* Loop until zero */
00892272 12667
7bc6df2c
GJL
12668 return avr_asm_len ("brne 0b", xop, plen, 1);
12669}
12670
12671
12672\f
43ea6502
AS
12673/* Helper for __builtin_avr_delay_cycles */
12674
d93417c8
GJL
12675static rtx
12676avr_mem_clobber (void)
12677{
12678 rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
12679 MEM_VOLATILE_P (mem) = 1;
12680 return mem;
12681}
12682
43ea6502
AS
12683static void
12684avr_expand_delay_cycles (rtx operands0)
12685{
b8db7f86 12686 unsigned HOST_WIDE_INT cycles = UINTVAL (operands0) & GET_MODE_MASK (SImode);
43ea6502
AS
12687 unsigned HOST_WIDE_INT cycles_used;
12688 unsigned HOST_WIDE_INT loop_count;
00892272 12689
43ea6502
AS
12690 if (IN_RANGE (cycles, 83886082, 0xFFFFFFFF))
12691 {
12692 loop_count = ((cycles - 9) / 6) + 1;
12693 cycles_used = ((loop_count - 1) * 6) + 9;
d93417c8
GJL
12694 emit_insn (gen_delay_cycles_4 (gen_int_mode (loop_count, SImode),
12695 avr_mem_clobber()));
43ea6502
AS
12696 cycles -= cycles_used;
12697 }
00892272 12698
43ea6502
AS
12699 if (IN_RANGE (cycles, 262145, 83886081))
12700 {
12701 loop_count = ((cycles - 7) / 5) + 1;
12702 if (loop_count > 0xFFFFFF)
12703 loop_count = 0xFFFFFF;
12704 cycles_used = ((loop_count - 1) * 5) + 7;
d93417c8
GJL
12705 emit_insn (gen_delay_cycles_3 (gen_int_mode (loop_count, SImode),
12706 avr_mem_clobber()));
43ea6502
AS
12707 cycles -= cycles_used;
12708 }
00892272 12709
43ea6502
AS
12710 if (IN_RANGE (cycles, 768, 262144))
12711 {
12712 loop_count = ((cycles - 5) / 4) + 1;
12713 if (loop_count > 0xFFFF)
12714 loop_count = 0xFFFF;
12715 cycles_used = ((loop_count - 1) * 4) + 5;
d93417c8
GJL
12716 emit_insn (gen_delay_cycles_2 (gen_int_mode (loop_count, HImode),
12717 avr_mem_clobber()));
43ea6502
AS
12718 cycles -= cycles_used;
12719 }
00892272 12720
43ea6502
AS
12721 if (IN_RANGE (cycles, 6, 767))
12722 {
12723 loop_count = cycles / 3;
00892272 12724 if (loop_count > 255)
43ea6502
AS
12725 loop_count = 255;
12726 cycles_used = loop_count * 3;
d93417c8
GJL
12727 emit_insn (gen_delay_cycles_1 (gen_int_mode (loop_count, QImode),
12728 avr_mem_clobber()));
43ea6502
AS
12729 cycles -= cycles_used;
12730 }
00892272 12731
43ea6502
AS
12732 while (cycles >= 2)
12733 {
12734 emit_insn (gen_nopv (GEN_INT(2)));
12735 cycles -= 2;
12736 }
12737
12738 if (cycles == 1)
12739 {
12740 emit_insn (gen_nopv (GEN_INT(1)));
12741 cycles--;
12742 }
12743}
12744
49b2772e 12745
ee52b11b
GJL
12746static void
12747avr_expand_nops (rtx operands0)
12748{
12749 unsigned HOST_WIDE_INT n_nops = UINTVAL (operands0) & GET_MODE_MASK (HImode);
12750
12751 while (n_nops--)
12752 {
12753 emit_insn (gen_nopv (const1_rtx));
12754 }
12755}
12756
12757
49b2772e
GJL
12758/* Compute the image of x under f, i.e. perform x --> f(x) */
12759
12760static int
7405bd18 12761avr_map (unsigned int f, int x)
49b2772e 12762{
7405bd18 12763 return x < 8 ? (f >> (4 * x)) & 0xf : 0;
49b2772e
GJL
12764}
12765
12766
0c578db6 12767/* Return some metrics of map A. */
49b2772e 12768
0c578db6
GJL
12769enum
12770 {
12771 /* Number of fixed points in { 0 ... 7 } */
12772 MAP_FIXED_0_7,
49b2772e 12773
0c578db6
GJL
12774 /* Size of preimage of non-fixed points in { 0 ... 7 } */
12775 MAP_NONFIXED_0_7,
00892272 12776
0c578db6
GJL
12777 /* Mask representing the fixed points in { 0 ... 7 } */
12778 MAP_MASK_FIXED_0_7,
00892272 12779
0c578db6
GJL
12780 /* Size of the preimage of { 0 ... 7 } */
12781 MAP_PREIMAGE_0_7,
00892272 12782
0c578db6
GJL
12783 /* Mask that represents the preimage of { f } */
12784 MAP_MASK_PREIMAGE_F
12785 };
12786
12787static unsigned
7405bd18 12788avr_map_metric (unsigned int a, int mode)
49b2772e 12789{
0c578db6 12790 unsigned i, metric = 0;
49b2772e 12791
0c578db6
GJL
12792 for (i = 0; i < 8; i++)
12793 {
12794 unsigned ai = avr_map (a, i);
49b2772e 12795
0c578db6
GJL
12796 if (mode == MAP_FIXED_0_7)
12797 metric += ai == i;
12798 else if (mode == MAP_NONFIXED_0_7)
12799 metric += ai < 8 && ai != i;
12800 else if (mode == MAP_MASK_FIXED_0_7)
12801 metric |= ((unsigned) (ai == i)) << i;
12802 else if (mode == MAP_PREIMAGE_0_7)
12803 metric += ai < 8;
12804 else if (mode == MAP_MASK_PREIMAGE_F)
12805 metric |= ((unsigned) (ai == 0xf)) << i;
12806 else
12807 gcc_unreachable();
12808 }
00892272 12809
0c578db6 12810 return metric;
49b2772e
GJL
12811}
12812
12813
0c578db6
GJL
12814/* Return true if IVAL has a 0xf in its hexadecimal representation
12815 and false, otherwise. Only nibbles 0..7 are taken into account.
12816 Used as constraint helper for C0f and Cxf. */
49b2772e 12817
0c578db6
GJL
12818bool
12819avr_has_nibble_0xf (rtx ival)
12820{
7405bd18
RS
12821 unsigned int map = UINTVAL (ival) & GET_MODE_MASK (SImode);
12822 return 0 != avr_map_metric (map, MAP_MASK_PREIMAGE_F);
0c578db6 12823}
49b2772e 12824
49b2772e 12825
0c578db6
GJL
12826/* We have a set of bits that are mapped by a function F.
12827 Try to decompose F by means of a second function G so that
49b2772e 12828
0c578db6 12829 F = F o G^-1 o G
49b2772e 12830
0c578db6 12831 and
49b2772e 12832
0c578db6 12833 cost (F o G^-1) + cost (G) < cost (F)
49b2772e 12834
0c578db6
GJL
12835 Example: Suppose builtin insert_bits supplies us with the map
12836 F = 0x3210ffff. Instead of doing 4 bit insertions to get the high
12837 nibble of the result, we can just as well rotate the bits before inserting
12838 them and use the map 0x7654ffff which is cheaper than the original map.
12839 For this example G = G^-1 = 0x32107654 and F o G^-1 = 0x7654ffff. */
00892272 12840
0c578db6
GJL
12841typedef struct
12842{
12843 /* tree code of binary function G */
12844 enum tree_code code;
49b2772e 12845
0c578db6
GJL
12846 /* The constant second argument of G */
12847 int arg;
49b2772e 12848
0c578db6
GJL
12849 /* G^-1, the inverse of G (*, arg) */
12850 unsigned ginv;
49b2772e 12851
0c578db6
GJL
12852 /* The cost of appplying G (*, arg) */
12853 int cost;
49b2772e 12854
0c578db6 12855 /* The composition F o G^-1 (*, arg) for some function F */
7405bd18 12856 unsigned int map;
49b2772e 12857
0c578db6
GJL
12858 /* For debug purpose only */
12859 const char *str;
12860} avr_map_op_t;
49b2772e 12861
0c578db6 12862static const avr_map_op_t avr_map_op[] =
49b2772e 12863 {
7405bd18
RS
12864 { LROTATE_EXPR, 0, 0x76543210, 0, 0, "id" },
12865 { LROTATE_EXPR, 1, 0x07654321, 2, 0, "<<<" },
12866 { LROTATE_EXPR, 2, 0x10765432, 4, 0, "<<<" },
12867 { LROTATE_EXPR, 3, 0x21076543, 4, 0, "<<<" },
12868 { LROTATE_EXPR, 4, 0x32107654, 1, 0, "<<<" },
12869 { LROTATE_EXPR, 5, 0x43210765, 3, 0, "<<<" },
12870 { LROTATE_EXPR, 6, 0x54321076, 5, 0, "<<<" },
12871 { LROTATE_EXPR, 7, 0x65432107, 3, 0, "<<<" },
12872 { RSHIFT_EXPR, 1, 0x6543210c, 1, 0, ">>" },
12873 { RSHIFT_EXPR, 1, 0x7543210c, 1, 0, ">>" },
12874 { RSHIFT_EXPR, 2, 0x543210cc, 2, 0, ">>" },
12875 { RSHIFT_EXPR, 2, 0x643210cc, 2, 0, ">>" },
12876 { RSHIFT_EXPR, 2, 0x743210cc, 2, 0, ">>" },
12877 { LSHIFT_EXPR, 1, 0xc7654321, 1, 0, "<<" },
12878 { LSHIFT_EXPR, 2, 0xcc765432, 2, 0, "<<" }
49b2772e
GJL
12879 };
12880
12881
0c578db6
GJL
12882/* Try to decompose F as F = (F o G^-1) o G as described above.
12883 The result is a struct representing F o G^-1 and G.
12884 If result.cost < 0 then such a decomposition does not exist. */
00892272 12885
0c578db6 12886static avr_map_op_t
7405bd18 12887avr_map_decompose (unsigned int f, const avr_map_op_t *g, bool val_const_p)
49b2772e 12888{
0c578db6
GJL
12889 int i;
12890 bool val_used_p = 0 != avr_map_metric (f, MAP_MASK_PREIMAGE_F);
12891 avr_map_op_t f_ginv = *g;
7405bd18 12892 unsigned int ginv = g->ginv;
49b2772e 12893
0c578db6 12894 f_ginv.cost = -1;
00892272 12895
0c578db6 12896 /* Step 1: Computing F o G^-1 */
49b2772e 12897
0c578db6
GJL
12898 for (i = 7; i >= 0; i--)
12899 {
12900 int x = avr_map (f, i);
00892272 12901
0c578db6
GJL
12902 if (x <= 7)
12903 {
12904 x = avr_map (ginv, x);
49b2772e 12905
0c578db6 12906 /* The bit is no element of the image of G: no avail (cost = -1) */
00892272 12907
0c578db6
GJL
12908 if (x > 7)
12909 return f_ginv;
12910 }
00892272 12911
7405bd18 12912 f_ginv.map = (f_ginv.map << 4) + x;
0c578db6 12913 }
49b2772e 12914
0c578db6
GJL
12915 /* Step 2: Compute the cost of the operations.
12916 The overall cost of doing an operation prior to the insertion is
12917 the cost of the insertion plus the cost of the operation. */
49b2772e 12918
0c578db6 12919 /* Step 2a: Compute cost of F o G^-1 */
49b2772e 12920
0c578db6
GJL
12921 if (0 == avr_map_metric (f_ginv.map, MAP_NONFIXED_0_7))
12922 {
12923 /* The mapping consists only of fixed points and can be folded
12924 to AND/OR logic in the remainder. Reasonable cost is 3. */
49b2772e 12925
0c578db6
GJL
12926 f_ginv.cost = 2 + (val_used_p && !val_const_p);
12927 }
12928 else
12929 {
12930 rtx xop[4];
49b2772e 12931
0c578db6
GJL
12932 /* Get the cost of the insn by calling the output worker with some
12933 fake values. Mimic effect of reloading xop[3]: Unused operands
12934 are mapped to 0 and used operands are reloaded to xop[0]. */
49b2772e 12935
0c578db6 12936 xop[0] = all_regs_rtx[24];
7405bd18 12937 xop[1] = gen_int_mode (f_ginv.map, SImode);
0c578db6
GJL
12938 xop[2] = all_regs_rtx[25];
12939 xop[3] = val_used_p ? xop[0] : const0_rtx;
00892272 12940
0c578db6 12941 avr_out_insert_bits (xop, &f_ginv.cost);
00892272 12942
0c578db6
GJL
12943 f_ginv.cost += val_const_p && val_used_p ? 1 : 0;
12944 }
00892272 12945
0c578db6 12946 /* Step 2b: Add cost of G */
49b2772e 12947
0c578db6 12948 f_ginv.cost += g->cost;
49b2772e 12949
0c578db6
GJL
12950 if (avr_log.builtin)
12951 avr_edump (" %s%d=%d", g->str, g->arg, f_ginv.cost);
12952
12953 return f_ginv;
49b2772e
GJL
12954}
12955
12956
0c578db6
GJL
12957/* Insert bits from XOP[1] into XOP[0] according to MAP.
12958 XOP[0] and XOP[1] don't overlap.
12959 If FIXP_P = true: Move all bits according to MAP using BLD/BST sequences.
12960 If FIXP_P = false: Just move the bit if its position in the destination
12961 is different to its source position. */
49b2772e
GJL
12962
12963static void
7405bd18 12964avr_move_bits (rtx *xop, unsigned int map, bool fixp_p, int *plen)
49b2772e 12965{
0c578db6 12966 int bit_dest, b;
49b2772e
GJL
12967
12968 /* T-flag contains this bit of the source, i.e. of XOP[1] */
12969 int t_bit_src = -1;
12970
49b2772e 12971 /* We order the operations according to the requested source bit b. */
00892272 12972
0c578db6
GJL
12973 for (b = 0; b < 8; b++)
12974 for (bit_dest = 0; bit_dest < 8; bit_dest++)
49b2772e
GJL
12975 {
12976 int bit_src = avr_map (map, bit_dest);
00892272 12977
49b2772e 12978 if (b != bit_src
0c578db6
GJL
12979 || bit_src >= 8
12980 /* Same position: No need to copy as requested by FIXP_P. */
12981 || (bit_dest == bit_src && !fixp_p))
49b2772e
GJL
12982 continue;
12983
12984 if (t_bit_src != bit_src)
12985 {
12986 /* Source bit is not yet in T: Store it to T. */
00892272 12987
49b2772e
GJL
12988 t_bit_src = bit_src;
12989
0c578db6
GJL
12990 xop[3] = GEN_INT (bit_src);
12991 avr_asm_len ("bst %T1%T3", xop, plen, 1);
49b2772e
GJL
12992 }
12993
12994 /* Load destination bit with T. */
00892272 12995
0c578db6
GJL
12996 xop[3] = GEN_INT (bit_dest);
12997 avr_asm_len ("bld %T0%T3", xop, plen, 1);
49b2772e
GJL
12998 }
12999}
13000
13001
0c578db6
GJL
13002/* PLEN == 0: Print assembler code for `insert_bits'.
13003 PLEN != 0: Compute code length in bytes.
00892272 13004
0c578db6
GJL
13005 OP[0]: Result
13006 OP[1]: The mapping composed of nibbles. If nibble no. N is
13007 0: Bit N of result is copied from bit OP[2].0
13008 ... ...
13009 7: Bit N of result is copied from bit OP[2].7
13010 0xf: Bit N of result is copied from bit OP[3].N
13011 OP[2]: Bits to be inserted
13012 OP[3]: Target value */
49b2772e
GJL
13013
13014const char*
0c578db6 13015avr_out_insert_bits (rtx *op, int *plen)
49b2772e 13016{
7405bd18 13017 unsigned int map = UINTVAL (op[1]) & GET_MODE_MASK (SImode);
0c578db6
GJL
13018 unsigned mask_fixed;
13019 bool fixp_p = true;
13020 rtx xop[4];
49b2772e 13021
0c578db6
GJL
13022 xop[0] = op[0];
13023 xop[1] = op[2];
13024 xop[2] = op[3];
49b2772e 13025
0c578db6 13026 gcc_assert (REG_P (xop[2]) || CONST_INT_P (xop[2]));
00892272 13027
49b2772e
GJL
13028 if (plen)
13029 *plen = 0;
13030 else if (flag_print_asm_name)
7405bd18 13031 fprintf (asm_out_file, ASM_COMMENT_START "map = 0x%08x\n", map);
49b2772e 13032
0c578db6
GJL
13033 /* If MAP has fixed points it might be better to initialize the result
13034 with the bits to be inserted instead of moving all bits by hand. */
00892272 13035
0c578db6 13036 mask_fixed = avr_map_metric (map, MAP_MASK_FIXED_0_7);
49b2772e 13037
0c578db6
GJL
13038 if (REGNO (xop[0]) == REGNO (xop[1]))
13039 {
13040 /* Avoid early-clobber conflicts */
00892272 13041
0c578db6
GJL
13042 avr_asm_len ("mov __tmp_reg__,%1", xop, plen, 1);
13043 xop[1] = tmp_reg_rtx;
13044 fixp_p = false;
49b2772e
GJL
13045 }
13046
0c578db6 13047 if (avr_map_metric (map, MAP_MASK_PREIMAGE_F))
49b2772e 13048 {
0c578db6 13049 /* XOP[2] is used and reloaded to XOP[0] already */
00892272 13050
0c578db6 13051 int n_fix = 0, n_nofix = 0;
00892272 13052
0c578db6 13053 gcc_assert (REG_P (xop[2]));
00892272 13054
0c578db6
GJL
13055 /* Get the code size of the bit insertions; once with all bits
13056 moved and once with fixed points omitted. */
00892272 13057
0c578db6
GJL
13058 avr_move_bits (xop, map, true, &n_fix);
13059 avr_move_bits (xop, map, false, &n_nofix);
13060
13061 if (fixp_p && n_fix - n_nofix > 3)
49b2772e 13062 {
0c578db6 13063 xop[3] = gen_int_mode (~mask_fixed, QImode);
00892272 13064
0c578db6
GJL
13065 avr_asm_len ("eor %0,%1" CR_TAB
13066 "andi %0,%3" CR_TAB
13067 "eor %0,%1", xop, plen, 3);
13068 fixp_p = false;
49b2772e
GJL
13069 }
13070 }
49b2772e
GJL
13071 else
13072 {
0c578db6 13073 /* XOP[2] is unused */
00892272 13074
0c578db6
GJL
13075 if (fixp_p && mask_fixed)
13076 {
13077 avr_asm_len ("mov %0,%1", xop, plen, 1);
13078 fixp_p = false;
13079 }
49b2772e 13080 }
00892272 13081
0c578db6 13082 /* Move/insert remaining bits. */
49b2772e 13083
0c578db6 13084 avr_move_bits (xop, map, fixp_p, plen);
00892272 13085
49b2772e
GJL
13086 return "";
13087}
13088
13089
43ea6502
AS
13090/* IDs for all the AVR builtins. */
13091
13092enum avr_builtin_id
13093 {
556f9906 13094#define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
e52a8b71 13095 AVR_BUILTIN_ ## NAME,
00892272 13096#include "builtins.def"
639d0302
GJL
13097#undef DEF_BUILTIN
13098
13099 AVR_BUILTIN_COUNT
43ea6502
AS
13100 };
13101
911ba855
GJL
13102struct GTY(()) avr_builtin_description
13103{
13104 enum insn_code icode;
911ba855
GJL
13105 int n_args;
13106 tree fndecl;
13107};
13108
13109
13110/* Notice that avr_bdesc[] and avr_builtin_id are initialized in such a way
13111 that a built-in's ID can be used to access the built-in by means of
13112 avr_bdesc[ID] */
13113
13114static GTY(()) struct avr_builtin_description
13115avr_bdesc[AVR_BUILTIN_COUNT] =
13116 {
556f9906 13117#define DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE, LIBNAME) \
e52a8b71 13118 { (enum insn_code) CODE_FOR_ ## ICODE, N_ARGS, NULL_TREE },
00892272 13119#include "builtins.def"
911ba855
GJL
13120#undef DEF_BUILTIN
13121 };
13122
13123
13124/* Implement `TARGET_BUILTIN_DECL'. */
13125
13126static tree
13127avr_builtin_decl (unsigned id, bool initialize_p ATTRIBUTE_UNUSED)
13128{
13129 if (id < AVR_BUILTIN_COUNT)
13130 return avr_bdesc[id].fndecl;
13131
13132 return error_mark_node;
13133}
13134
13135
e4fe948a
GJL
13136static void
13137avr_init_builtin_int24 (void)
13138{
13139 tree int24_type = make_signed_type (GET_MODE_BITSIZE (PSImode));
13140 tree uint24_type = make_unsigned_type (GET_MODE_BITSIZE (PSImode));
13141
eb6bb559
GJL
13142 lang_hooks.types.register_builtin_type (int24_type, "__int24");
13143 lang_hooks.types.register_builtin_type (uint24_type, "__uint24");
e4fe948a
GJL
13144}
13145
911ba855 13146
43ea6502
AS
13147/* Implement `TARGET_INIT_BUILTINS' */
13148/* Set up all builtin functions for this target. */
13149
13150static void
13151avr_init_builtins (void)
13152{
13153 tree void_ftype_void
c19afe52 13154 = build_function_type_list (void_type_node, NULL_TREE);
43ea6502 13155 tree uchar_ftype_uchar
00892272 13156 = build_function_type_list (unsigned_char_type_node,
43ea6502
AS
13157 unsigned_char_type_node,
13158 NULL_TREE);
13159 tree uint_ftype_uchar_uchar
00892272
GJL
13160 = build_function_type_list (unsigned_type_node,
13161 unsigned_char_type_node,
43ea6502 13162 unsigned_char_type_node,
43ea6502
AS
13163 NULL_TREE);
13164 tree int_ftype_char_char
00892272
GJL
13165 = build_function_type_list (integer_type_node,
13166 char_type_node,
43ea6502 13167 char_type_node,
43ea6502
AS
13168 NULL_TREE);
13169 tree int_ftype_char_uchar
00892272 13170 = build_function_type_list (integer_type_node,
43ea6502 13171 char_type_node,
00892272 13172 unsigned_char_type_node,
43ea6502
AS
13173 NULL_TREE);
13174 tree void_ftype_ulong
00892272 13175 = build_function_type_list (void_type_node,
43ea6502
AS
13176 long_unsigned_type_node,
13177 NULL_TREE);
13178
0c578db6 13179 tree uchar_ftype_ulong_uchar_uchar
49b2772e
GJL
13180 = build_function_type_list (unsigned_char_type_node,
13181 long_unsigned_type_node,
13182 unsigned_char_type_node,
0c578db6 13183 unsigned_char_type_node,
49b2772e
GJL
13184 NULL_TREE);
13185
1619fcfc 13186 tree const_memx_void_node
e52a8b71
GJL
13187 = build_qualified_type (void_type_node,
13188 TYPE_QUAL_CONST
13189 | ENCODE_QUAL_ADDR_SPACE (ADDR_SPACE_MEMX));
1619fcfc
GJL
13190
13191 tree const_memx_ptr_type_node
e52a8b71 13192 = build_pointer_type_for_mode (const_memx_void_node, PSImode, false);
00892272 13193
1619fcfc 13194 tree char_ftype_const_memx_ptr
e52a8b71
GJL
13195 = build_function_type_list (char_type_node,
13196 const_memx_ptr_type_node,
13197 NULL);
13198
85d768f3
GJL
13199#define ITYP(T) \
13200 lang_hooks.types.type_for_size (TYPE_PRECISION (T), TYPE_UNSIGNED (T))
0c9ef7ad 13201
85d768f3
GJL
13202#define FX_FTYPE_FX(fx) \
13203 tree fx##r_ftype_##fx##r \
13204 = build_function_type_list (node_##fx##r, node_##fx##r, NULL); \
13205 tree fx##k_ftype_##fx##k \
13206 = build_function_type_list (node_##fx##k, node_##fx##k, NULL)
13207
13208#define FX_FTYPE_FX_INT(fx) \
13209 tree fx##r_ftype_##fx##r_int \
13210 = build_function_type_list (node_##fx##r, node_##fx##r, \
13211 integer_type_node, NULL); \
13212 tree fx##k_ftype_##fx##k_int \
13213 = build_function_type_list (node_##fx##k, node_##fx##k, \
13214 integer_type_node, NULL)
0c9ef7ad 13215
85d768f3
GJL
13216#define INT_FTYPE_FX(fx) \
13217 tree int_ftype_##fx##r \
13218 = build_function_type_list (integer_type_node, node_##fx##r, NULL); \
13219 tree int_ftype_##fx##k \
13220 = build_function_type_list (integer_type_node, node_##fx##k, NULL)
13221
13222#define INTX_FTYPE_FX(fx) \
13223 tree int##fx##r_ftype_##fx##r \
13224 = build_function_type_list (ITYP (node_##fx##r), node_##fx##r, NULL); \
13225 tree int##fx##k_ftype_##fx##k \
13226 = build_function_type_list (ITYP (node_##fx##k), node_##fx##k, NULL)
13227
13228#define FX_FTYPE_INTX(fx) \
13229 tree fx##r_ftype_int##fx##r \
13230 = build_function_type_list (node_##fx##r, ITYP (node_##fx##r), NULL); \
13231 tree fx##k_ftype_int##fx##k \
13232 = build_function_type_list (node_##fx##k, ITYP (node_##fx##k), NULL)
13233
13234 tree node_hr = short_fract_type_node;
ff24afc8 13235 tree node_nr = fract_type_node;
85d768f3
GJL
13236 tree node_lr = long_fract_type_node;
13237 tree node_llr = long_long_fract_type_node;
13238
13239 tree node_uhr = unsigned_short_fract_type_node;
ff24afc8 13240 tree node_unr = unsigned_fract_type_node;
85d768f3
GJL
13241 tree node_ulr = unsigned_long_fract_type_node;
13242 tree node_ullr = unsigned_long_long_fract_type_node;
13243
13244 tree node_hk = short_accum_type_node;
ff24afc8 13245 tree node_nk = accum_type_node;
85d768f3
GJL
13246 tree node_lk = long_accum_type_node;
13247 tree node_llk = long_long_accum_type_node;
13248
13249 tree node_uhk = unsigned_short_accum_type_node;
ff24afc8 13250 tree node_unk = unsigned_accum_type_node;
85d768f3
GJL
13251 tree node_ulk = unsigned_long_accum_type_node;
13252 tree node_ullk = unsigned_long_long_accum_type_node;
13253
13254
13255 /* For absfx builtins. */
13256
13257 FX_FTYPE_FX (h);
ff24afc8 13258 FX_FTYPE_FX (n);
85d768f3
GJL
13259 FX_FTYPE_FX (l);
13260 FX_FTYPE_FX (ll);
13261
13262 /* For roundfx builtins. */
13263
13264 FX_FTYPE_FX_INT (h);
ff24afc8 13265 FX_FTYPE_FX_INT (n);
85d768f3
GJL
13266 FX_FTYPE_FX_INT (l);
13267 FX_FTYPE_FX_INT (ll);
13268
13269 FX_FTYPE_FX_INT (uh);
ff24afc8 13270 FX_FTYPE_FX_INT (un);
85d768f3
GJL
13271 FX_FTYPE_FX_INT (ul);
13272 FX_FTYPE_FX_INT (ull);
13273
13274 /* For countlsfx builtins. */
13275
13276 INT_FTYPE_FX (h);
ff24afc8 13277 INT_FTYPE_FX (n);
85d768f3
GJL
13278 INT_FTYPE_FX (l);
13279 INT_FTYPE_FX (ll);
13280
13281 INT_FTYPE_FX (uh);
ff24afc8 13282 INT_FTYPE_FX (un);
85d768f3
GJL
13283 INT_FTYPE_FX (ul);
13284 INT_FTYPE_FX (ull);
13285
13286 /* For bitsfx builtins. */
13287
13288 INTX_FTYPE_FX (h);
ff24afc8 13289 INTX_FTYPE_FX (n);
85d768f3
GJL
13290 INTX_FTYPE_FX (l);
13291 INTX_FTYPE_FX (ll);
13292
13293 INTX_FTYPE_FX (uh);
ff24afc8 13294 INTX_FTYPE_FX (un);
85d768f3
GJL
13295 INTX_FTYPE_FX (ul);
13296 INTX_FTYPE_FX (ull);
13297
13298 /* For fxbits builtins. */
13299
13300 FX_FTYPE_INTX (h);
ff24afc8 13301 FX_FTYPE_INTX (n);
85d768f3
GJL
13302 FX_FTYPE_INTX (l);
13303 FX_FTYPE_INTX (ll);
13304
13305 FX_FTYPE_INTX (uh);
ff24afc8 13306 FX_FTYPE_INTX (un);
85d768f3
GJL
13307 FX_FTYPE_INTX (ul);
13308 FX_FTYPE_INTX (ull);
13309
13310
556f9906 13311#define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
e52a8b71
GJL
13312 { \
13313 int id = AVR_BUILTIN_ ## NAME; \
13314 const char *Name = "__builtin_avr_" #NAME; \
13315 char *name = (char*) alloca (1 + strlen (Name)); \
13316 \
13317 gcc_assert (id < AVR_BUILTIN_COUNT); \
13318 avr_bdesc[id].fndecl \
13319 = add_builtin_function (avr_tolower (name, Name), TYPE, id, \
556f9906 13320 BUILT_IN_MD, LIBNAME, NULL_TREE); \
e52a8b71 13321 }
00892272 13322#include "builtins.def"
639d0302 13323#undef DEF_BUILTIN
00892272 13324
e4fe948a 13325 avr_init_builtin_int24 ();
43ea6502
AS
13326}
13327
43ea6502 13328
eb6bb559
GJL
13329/* Subroutine of avr_expand_builtin to expand vanilla builtins
13330 with non-void result and 1 ... 3 arguments. */
43ea6502
AS
13331
13332static rtx
eb6bb559 13333avr_default_expand_builtin (enum insn_code icode, tree exp, rtx target)
43ea6502 13334{
eb6bb559
GJL
13335 rtx pat, xop[3];
13336 int n, n_args = call_expr_nargs (exp);
ef4bddc2 13337 machine_mode tmode = insn_data[icode].operand[0].mode;
43ea6502 13338
eb6bb559 13339 gcc_assert (n_args >= 1 && n_args <= 3);
00892272 13340
eb6bb559 13341 if (target == NULL_RTX
43ea6502 13342 || GET_MODE (target) != tmode
eb6bb559 13343 || !insn_data[icode].operand[0].predicate (target, tmode))
43ea6502
AS
13344 {
13345 target = gen_reg_rtx (tmode);
13346 }
13347
eb6bb559 13348 for (n = 0; n < n_args; n++)
43ea6502 13349 {
eb6bb559
GJL
13350 tree arg = CALL_EXPR_ARG (exp, n);
13351 rtx op = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
ef4bddc2
RS
13352 machine_mode opmode = GET_MODE (op);
13353 machine_mode mode = insn_data[icode].operand[n+1].mode;
43ea6502 13354
eb6bb559
GJL
13355 if ((opmode == SImode || opmode == VOIDmode) && mode == HImode)
13356 {
13357 opmode = HImode;
13358 op = gen_lowpart (HImode, op);
13359 }
43ea6502 13360
eb6bb559
GJL
13361 /* In case the insn wants input operands in modes different from
13362 the result, abort. */
00892272 13363
eb6bb559 13364 gcc_assert (opmode == mode || opmode == VOIDmode);
43ea6502 13365
eb6bb559
GJL
13366 if (!insn_data[icode].operand[n+1].predicate (op, mode))
13367 op = copy_to_mode_reg (mode, op);
43ea6502 13368
eb6bb559 13369 xop[n] = op;
43ea6502
AS
13370 }
13371
eb6bb559 13372 switch (n_args)
43ea6502 13373 {
eb6bb559
GJL
13374 case 1: pat = GEN_FCN (icode) (target, xop[0]); break;
13375 case 2: pat = GEN_FCN (icode) (target, xop[0], xop[1]); break;
13376 case 3: pat = GEN_FCN (icode) (target, xop[0], xop[1], xop[2]); break;
43ea6502 13377
eb6bb559
GJL
13378 default:
13379 gcc_unreachable();
0c578db6 13380 }
00892272 13381
eb6bb559
GJL
13382 if (pat == NULL_RTX)
13383 return NULL_RTX;
0c578db6
GJL
13384
13385 emit_insn (pat);
eb6bb559 13386
0c578db6
GJL
13387 return target;
13388}
13389
43ea6502 13390
911ba855 13391/* Implement `TARGET_EXPAND_BUILTIN'. */
43ea6502
AS
13392/* Expand an expression EXP that calls a built-in function,
13393 with result going to TARGET if that's convenient
13394 (and in mode MODE if that's convenient).
13395 SUBTARGET may be used as the target for computing one of EXP's operands.
13396 IGNORE is nonzero if the value is to be ignored. */
13397
13398static rtx
13399avr_expand_builtin (tree exp, rtx target,
13400 rtx subtarget ATTRIBUTE_UNUSED,
ef4bddc2 13401 machine_mode mode ATTRIBUTE_UNUSED,
556f9906 13402 int ignore)
43ea6502 13403{
43ea6502 13404 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
eb6bb559 13405 const char *bname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
43ea6502 13406 unsigned int id = DECL_FUNCTION_CODE (fndecl);
911ba855 13407 const struct avr_builtin_description *d = &avr_bdesc[id];
43ea6502
AS
13408 tree arg0;
13409 rtx op0;
13410
911ba855
GJL
13411 gcc_assert (id < AVR_BUILTIN_COUNT);
13412
43ea6502
AS
13413 switch (id)
13414 {
13415 case AVR_BUILTIN_NOP:
13416 emit_insn (gen_nopv (GEN_INT(1)));
13417 return 0;
00892272 13418
43ea6502
AS
13419 case AVR_BUILTIN_DELAY_CYCLES:
13420 {
13421 arg0 = CALL_EXPR_ARG (exp, 0);
fd01a351 13422 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
43ea6502 13423
639d0302 13424 if (!CONST_INT_P (op0))
49b2772e 13425 error ("%s expects a compile time integer constant", bname);
639d0302
GJL
13426 else
13427 avr_expand_delay_cycles (op0);
43ea6502 13428
eb6bb559 13429 return NULL_RTX;
43ea6502 13430 }
49b2772e 13431
ee52b11b
GJL
13432 case AVR_BUILTIN_NOPS:
13433 {
13434 arg0 = CALL_EXPR_ARG (exp, 0);
13435 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
13436
13437 if (!CONST_INT_P (op0))
13438 error ("%s expects a compile time integer constant", bname);
13439 else
13440 avr_expand_nops (op0);
13441
13442 return NULL_RTX;
13443 }
13444
0c578db6 13445 case AVR_BUILTIN_INSERT_BITS:
49b2772e
GJL
13446 {
13447 arg0 = CALL_EXPR_ARG (exp, 0);
13448 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
13449
13450 if (!CONST_INT_P (op0))
13451 {
13452 error ("%s expects a compile time long integer constant"
13453 " as first argument", bname);
13454 return target;
13455 }
85d768f3
GJL
13456
13457 break;
49b2772e 13458 }
85d768f3
GJL
13459
13460 case AVR_BUILTIN_ROUNDHR: case AVR_BUILTIN_ROUNDUHR:
13461 case AVR_BUILTIN_ROUNDR: case AVR_BUILTIN_ROUNDUR:
13462 case AVR_BUILTIN_ROUNDLR: case AVR_BUILTIN_ROUNDULR:
13463 case AVR_BUILTIN_ROUNDLLR: case AVR_BUILTIN_ROUNDULLR:
13464
13465 case AVR_BUILTIN_ROUNDHK: case AVR_BUILTIN_ROUNDUHK:
13466 case AVR_BUILTIN_ROUNDK: case AVR_BUILTIN_ROUNDUK:
13467 case AVR_BUILTIN_ROUNDLK: case AVR_BUILTIN_ROUNDULK:
13468 case AVR_BUILTIN_ROUNDLLK: case AVR_BUILTIN_ROUNDULLK:
13469
13470 /* Warn about odd rounding. Rounding points >= FBIT will have
13471 no effect. */
0c9ef7ad 13472
85d768f3
GJL
13473 if (TREE_CODE (CALL_EXPR_ARG (exp, 1)) != INTEGER_CST)
13474 break;
13475
13476 int rbit = (int) TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1));
13477
13478 if (rbit >= (int) GET_MODE_FBIT (mode))
13479 {
13480 warning (OPT_Wextra, "rounding to %d bits has no effect for "
13481 "fixed-point value with %d fractional bits",
13482 rbit, GET_MODE_FBIT (mode));
13483
13484 return expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX, mode,
13485 EXPAND_NORMAL);
13486 }
13487 else if (rbit <= - (int) GET_MODE_IBIT (mode))
13488 {
13489 warning (0, "rounding result will always be 0");
13490 return CONST0_RTX (mode);
13491 }
13492
13493 /* The rounding points RP satisfies now: -IBIT < RP < FBIT.
13494
13495 TR 18037 only specifies results for RP > 0. However, the
13496 remaining cases of -IBIT < RP <= 0 can easily be supported
13497 without any additional overhead. */
13498
13499 break; /* round */
43ea6502
AS
13500 }
13501
556f9906
GJL
13502 /* No fold found and no insn: Call support function from libgcc. */
13503
13504 if (d->icode == CODE_FOR_nothing
13505 && DECL_ASSEMBLER_NAME (get_callee_fndecl (exp)) != NULL_TREE)
13506 {
13507 return expand_call (exp, target, ignore);
13508 }
13509
911ba855 13510 /* No special treatment needed: vanilla expand. */
eb6bb559 13511
e52a8b71 13512 gcc_assert (d->icode != CODE_FOR_nothing);
eb6bb559
GJL
13513 gcc_assert (d->n_args == call_expr_nargs (exp));
13514
13515 if (d->n_args == 0)
639d0302 13516 {
911ba855 13517 emit_insn ((GEN_FCN (d->icode)) (target));
eb6bb559 13518 return NULL_RTX;
639d0302 13519 }
eb6bb559
GJL
13520
13521 return avr_default_expand_builtin (d->icode, exp, target);
43ea6502
AS
13522}
13523
0c578db6 13524
556f9906
GJL
13525/* Helper for `avr_fold_builtin' that folds absfx (FIXED_CST). */
13526
13527static tree
13528avr_fold_absfx (tree tval)
13529{
13530 if (FIXED_CST != TREE_CODE (tval))
13531 return NULL_TREE;
13532
13533 /* Our fixed-points have no padding: Use double_int payload directly. */
13534
13535 FIXED_VALUE_TYPE fval = TREE_FIXED_CST (tval);
13536 unsigned int bits = GET_MODE_BITSIZE (fval.mode);
13537 double_int ival = fval.data.sext (bits);
13538
13539 if (!ival.is_negative())
13540 return tval;
13541
13542 /* ISO/IEC TR 18037, 7.18a.6.2: The absfx functions are saturating. */
13543
13544 fval.data = (ival == double_int::min_value (bits, false).sext (bits))
13545 ? double_int::max_value (bits, false)
13546 : -ival;
13547
13548 return build_fixed (TREE_TYPE (tval), fval);
13549}
13550
13551
0c578db6
GJL
13552/* Implement `TARGET_FOLD_BUILTIN'. */
13553
13554static tree
13555avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg,
13556 bool ignore ATTRIBUTE_UNUSED)
13557{
13558 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
13559 tree val_type = TREE_TYPE (TREE_TYPE (fndecl));
13560
13561 if (!optimize)
13562 return NULL_TREE;
00892272 13563
0c578db6
GJL
13564 switch (fcode)
13565 {
13566 default:
13567 break;
13568
639d0302
GJL
13569 case AVR_BUILTIN_SWAP:
13570 {
13571 return fold_build2 (LROTATE_EXPR, val_type, arg[0],
13572 build_int_cst (val_type, 4));
13573 }
00892272 13574
556f9906
GJL
13575 case AVR_BUILTIN_ABSHR:
13576 case AVR_BUILTIN_ABSR:
13577 case AVR_BUILTIN_ABSLR:
13578 case AVR_BUILTIN_ABSLLR:
13579
13580 case AVR_BUILTIN_ABSHK:
13581 case AVR_BUILTIN_ABSK:
13582 case AVR_BUILTIN_ABSLK:
13583 case AVR_BUILTIN_ABSLLK:
13584 /* GCC is not good with folding ABS for fixed-point. Do it by hand. */
13585
13586 return avr_fold_absfx (arg[0]);
13587
85d768f3
GJL
13588 case AVR_BUILTIN_BITSHR: case AVR_BUILTIN_HRBITS:
13589 case AVR_BUILTIN_BITSHK: case AVR_BUILTIN_HKBITS:
13590 case AVR_BUILTIN_BITSUHR: case AVR_BUILTIN_UHRBITS:
13591 case AVR_BUILTIN_BITSUHK: case AVR_BUILTIN_UHKBITS:
13592
13593 case AVR_BUILTIN_BITSR: case AVR_BUILTIN_RBITS:
13594 case AVR_BUILTIN_BITSK: case AVR_BUILTIN_KBITS:
13595 case AVR_BUILTIN_BITSUR: case AVR_BUILTIN_URBITS:
13596 case AVR_BUILTIN_BITSUK: case AVR_BUILTIN_UKBITS:
13597
13598 case AVR_BUILTIN_BITSLR: case AVR_BUILTIN_LRBITS:
13599 case AVR_BUILTIN_BITSLK: case AVR_BUILTIN_LKBITS:
13600 case AVR_BUILTIN_BITSULR: case AVR_BUILTIN_ULRBITS:
13601 case AVR_BUILTIN_BITSULK: case AVR_BUILTIN_ULKBITS:
13602
13603 case AVR_BUILTIN_BITSLLR: case AVR_BUILTIN_LLRBITS:
13604 case AVR_BUILTIN_BITSLLK: case AVR_BUILTIN_LLKBITS:
13605 case AVR_BUILTIN_BITSULLR: case AVR_BUILTIN_ULLRBITS:
13606 case AVR_BUILTIN_BITSULLK: case AVR_BUILTIN_ULLKBITS:
13607
13608 gcc_assert (TYPE_PRECISION (val_type)
13609 == TYPE_PRECISION (TREE_TYPE (arg[0])));
13610
13611 return build1 (VIEW_CONVERT_EXPR, val_type, arg[0]);
13612
0c578db6
GJL
13613 case AVR_BUILTIN_INSERT_BITS:
13614 {
13615 tree tbits = arg[1];
13616 tree tval = arg[2];
13617 tree tmap;
13618 tree map_type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
7405bd18 13619 unsigned int map;
0c578db6
GJL
13620 bool changed = false;
13621 unsigned i;
13622 avr_map_op_t best_g;
639d0302
GJL
13623
13624 if (TREE_CODE (arg[0]) != INTEGER_CST)
13625 {
13626 /* No constant as first argument: Don't fold this and run into
13627 error in avr_expand_builtin. */
00892272 13628
639d0302
GJL
13629 break;
13630 }
00892272 13631
807e902e 13632 tmap = wide_int_to_tree (map_type, arg[0]);
7405bd18 13633 map = TREE_INT_CST_LOW (tmap);
0c578db6
GJL
13634
13635 if (TREE_CODE (tval) != INTEGER_CST
13636 && 0 == avr_map_metric (map, MAP_MASK_PREIMAGE_F))
13637 {
13638 /* There are no F in the map, i.e. 3rd operand is unused.
13639 Replace that argument with some constant to render
13640 respective input unused. */
00892272 13641
0c578db6
GJL
13642 tval = build_int_cst (val_type, 0);
13643 changed = true;
13644 }
13645
13646 if (TREE_CODE (tbits) != INTEGER_CST
13647 && 0 == avr_map_metric (map, MAP_PREIMAGE_0_7))
13648 {
13649 /* Similar for the bits to be inserted. If they are unused,
13650 we can just as well pass 0. */
00892272 13651
0c578db6
GJL
13652 tbits = build_int_cst (val_type, 0);
13653 }
13654
13655 if (TREE_CODE (tbits) == INTEGER_CST)
13656 {
13657 /* Inserting bits known at compile time is easy and can be
13658 performed by AND and OR with appropriate masks. */
13659
13660 int bits = TREE_INT_CST_LOW (tbits);
13661 int mask_ior = 0, mask_and = 0xff;
13662
13663 for (i = 0; i < 8; i++)
13664 {
13665 int mi = avr_map (map, i);
13666
13667 if (mi < 8)
13668 {
13669 if (bits & (1 << mi)) mask_ior |= (1 << i);
13670 else mask_and &= ~(1 << i);
13671 }
13672 }
13673
13674 tval = fold_build2 (BIT_IOR_EXPR, val_type, tval,
13675 build_int_cst (val_type, mask_ior));
13676 return fold_build2 (BIT_AND_EXPR, val_type, tval,
13677 build_int_cst (val_type, mask_and));
13678 }
13679
13680 if (changed)
13681 return build_call_expr (fndecl, 3, tmap, tbits, tval);
13682
13683 /* If bits don't change their position we can use vanilla logic
13684 to merge the two arguments. */
13685
13686 if (0 == avr_map_metric (map, MAP_NONFIXED_0_7))
13687 {
13688 int mask_f = avr_map_metric (map, MAP_MASK_PREIMAGE_F);
13689 tree tres, tmask = build_int_cst (val_type, mask_f ^ 0xff);
13690
13691 tres = fold_build2 (BIT_XOR_EXPR, val_type, tbits, tval);
13692 tres = fold_build2 (BIT_AND_EXPR, val_type, tres, tmask);
13693 return fold_build2 (BIT_XOR_EXPR, val_type, tres, tval);
13694 }
13695
13696 /* Try to decomposing map to reduce overall cost. */
13697
13698 if (avr_log.builtin)
7405bd18 13699 avr_edump ("\n%?: %x\n%?: ROL cost: ", map);
00892272 13700
0c578db6
GJL
13701 best_g = avr_map_op[0];
13702 best_g.cost = 1000;
00892272 13703
0c578db6
GJL
13704 for (i = 0; i < sizeof (avr_map_op) / sizeof (*avr_map_op); i++)
13705 {
13706 avr_map_op_t g
13707 = avr_map_decompose (map, avr_map_op + i,
13708 TREE_CODE (tval) == INTEGER_CST);
13709
13710 if (g.cost >= 0 && g.cost < best_g.cost)
13711 best_g = g;
13712 }
13713
13714 if (avr_log.builtin)
13715 avr_edump ("\n");
00892272 13716
0c578db6
GJL
13717 if (best_g.arg == 0)
13718 /* No optimization found */
13719 break;
00892272 13720
0c578db6 13721 /* Apply operation G to the 2nd argument. */
00892272 13722
0c578db6 13723 if (avr_log.builtin)
7405bd18 13724 avr_edump ("%?: using OP(%s%d, %x) cost %d\n",
0c578db6
GJL
13725 best_g.str, best_g.arg, best_g.map, best_g.cost);
13726
13727 /* Do right-shifts arithmetically: They copy the MSB instead of
13728 shifting in a non-usable value (0) as with logic right-shift. */
00892272 13729
0c578db6
GJL
13730 tbits = fold_convert (signed_char_type_node, tbits);
13731 tbits = fold_build2 (best_g.code, signed_char_type_node, tbits,
13732 build_int_cst (val_type, best_g.arg));
13733 tbits = fold_convert (val_type, tbits);
13734
13735 /* Use map o G^-1 instead of original map to undo the effect of G. */
00892272 13736
807e902e 13737 tmap = wide_int_to_tree (map_type, best_g.map);
00892272 13738
0c578db6
GJL
13739 return build_call_expr (fndecl, 3, tmap, tbits, tval);
13740 } /* AVR_BUILTIN_INSERT_BITS */
13741 }
13742
13743 return NULL_TREE;
13744}
13745
0c578db6 13746\f
43c626f0
GJL
13747
13748/* Initialize the GCC target structure. */
13749
13750#undef TARGET_ASM_ALIGNED_HI_OP
13751#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
13752#undef TARGET_ASM_ALIGNED_SI_OP
13753#define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
13754#undef TARGET_ASM_UNALIGNED_HI_OP
13755#define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
13756#undef TARGET_ASM_UNALIGNED_SI_OP
13757#define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
13758#undef TARGET_ASM_INTEGER
13759#define TARGET_ASM_INTEGER avr_assemble_integer
13760#undef TARGET_ASM_FILE_START
13761#define TARGET_ASM_FILE_START avr_file_start
13762#undef TARGET_ASM_FILE_END
13763#define TARGET_ASM_FILE_END avr_file_end
13764
13765#undef TARGET_ASM_FUNCTION_END_PROLOGUE
13766#define TARGET_ASM_FUNCTION_END_PROLOGUE avr_asm_function_end_prologue
13767#undef TARGET_ASM_FUNCTION_BEGIN_EPILOGUE
13768#define TARGET_ASM_FUNCTION_BEGIN_EPILOGUE avr_asm_function_begin_epilogue
13769
13770#undef TARGET_FUNCTION_VALUE
13771#define TARGET_FUNCTION_VALUE avr_function_value
13772#undef TARGET_LIBCALL_VALUE
13773#define TARGET_LIBCALL_VALUE avr_libcall_value
13774#undef TARGET_FUNCTION_VALUE_REGNO_P
13775#define TARGET_FUNCTION_VALUE_REGNO_P avr_function_value_regno_p
13776
13777#undef TARGET_ATTRIBUTE_TABLE
13778#define TARGET_ATTRIBUTE_TABLE avr_attribute_table
13779#undef TARGET_INSERT_ATTRIBUTES
13780#define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
13781#undef TARGET_SECTION_TYPE_FLAGS
13782#define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
13783
13784#undef TARGET_ASM_NAMED_SECTION
13785#define TARGET_ASM_NAMED_SECTION avr_asm_named_section
13786#undef TARGET_ASM_INIT_SECTIONS
13787#define TARGET_ASM_INIT_SECTIONS avr_asm_init_sections
13788#undef TARGET_ENCODE_SECTION_INFO
13789#define TARGET_ENCODE_SECTION_INFO avr_encode_section_info
13790#undef TARGET_ASM_SELECT_SECTION
13791#define TARGET_ASM_SELECT_SECTION avr_asm_select_section
13792
13793#undef TARGET_REGISTER_MOVE_COST
13794#define TARGET_REGISTER_MOVE_COST avr_register_move_cost
13795#undef TARGET_MEMORY_MOVE_COST
13796#define TARGET_MEMORY_MOVE_COST avr_memory_move_cost
13797#undef TARGET_RTX_COSTS
13798#define TARGET_RTX_COSTS avr_rtx_costs
13799#undef TARGET_ADDRESS_COST
13800#define TARGET_ADDRESS_COST avr_address_cost
13801#undef TARGET_MACHINE_DEPENDENT_REORG
13802#define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
13803#undef TARGET_FUNCTION_ARG
13804#define TARGET_FUNCTION_ARG avr_function_arg
13805#undef TARGET_FUNCTION_ARG_ADVANCE
13806#define TARGET_FUNCTION_ARG_ADVANCE avr_function_arg_advance
13807
eac188c5
GJL
13808#undef TARGET_SET_CURRENT_FUNCTION
13809#define TARGET_SET_CURRENT_FUNCTION avr_set_current_function
13810
43c626f0
GJL
13811#undef TARGET_RETURN_IN_MEMORY
13812#define TARGET_RETURN_IN_MEMORY avr_return_in_memory
13813
13814#undef TARGET_STRICT_ARGUMENT_NAMING
13815#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
13816
13817#undef TARGET_BUILTIN_SETJMP_FRAME_VALUE
13818#define TARGET_BUILTIN_SETJMP_FRAME_VALUE avr_builtin_setjmp_frame_value
13819
c1dd9790
JR
13820#undef TARGET_CONDITIONAL_REGISTER_USAGE
13821#define TARGET_CONDITIONAL_REGISTER_USAGE avr_conditional_register_usage
13822
43c626f0
GJL
13823#undef TARGET_HARD_REGNO_SCRATCH_OK
13824#define TARGET_HARD_REGNO_SCRATCH_OK avr_hard_regno_scratch_ok
13825#undef TARGET_CASE_VALUES_THRESHOLD
13826#define TARGET_CASE_VALUES_THRESHOLD avr_case_values_threshold
13827
13828#undef TARGET_FRAME_POINTER_REQUIRED
13829#define TARGET_FRAME_POINTER_REQUIRED avr_frame_pointer_required_p
13830#undef TARGET_CAN_ELIMINATE
13831#define TARGET_CAN_ELIMINATE avr_can_eliminate
13832
cee8f252
SKS
13833#undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
13834#define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS avr_allocate_stack_slots_for_args
13835
d45eae79
SL
13836#undef TARGET_WARN_FUNC_RETURN
13837#define TARGET_WARN_FUNC_RETURN avr_warn_func_return
13838
43c626f0
GJL
13839#undef TARGET_CLASS_LIKELY_SPILLED_P
13840#define TARGET_CLASS_LIKELY_SPILLED_P avr_class_likely_spilled_p
13841
13842#undef TARGET_OPTION_OVERRIDE
13843#define TARGET_OPTION_OVERRIDE avr_option_override
13844
13845#undef TARGET_CANNOT_MODIFY_JUMPS_P
13846#define TARGET_CANNOT_MODIFY_JUMPS_P avr_cannot_modify_jumps_p
13847
13848#undef TARGET_FUNCTION_OK_FOR_SIBCALL
13849#define TARGET_FUNCTION_OK_FOR_SIBCALL avr_function_ok_for_sibcall
13850
13851#undef TARGET_INIT_BUILTINS
13852#define TARGET_INIT_BUILTINS avr_init_builtins
13853
911ba855
GJL
13854#undef TARGET_BUILTIN_DECL
13855#define TARGET_BUILTIN_DECL avr_builtin_decl
13856
43c626f0
GJL
13857#undef TARGET_EXPAND_BUILTIN
13858#define TARGET_EXPAND_BUILTIN avr_expand_builtin
13859
13860#undef TARGET_FOLD_BUILTIN
13861#define TARGET_FOLD_BUILTIN avr_fold_builtin
13862
43c626f0
GJL
13863#undef TARGET_SCALAR_MODE_SUPPORTED_P
13864#define TARGET_SCALAR_MODE_SUPPORTED_P avr_scalar_mode_supported_p
13865
e55e4056
GJL
13866#undef TARGET_BUILD_BUILTIN_VA_LIST
13867#define TARGET_BUILD_BUILTIN_VA_LIST avr_build_builtin_va_list
13868
13869#undef TARGET_FIXED_POINT_SUPPORTED_P
13870#define TARGET_FIXED_POINT_SUPPORTED_P hook_bool_void_true
13871
f22e3c85
GJL
13872#undef TARGET_CONVERT_TO_TYPE
13873#define TARGET_CONVERT_TO_TYPE avr_convert_to_type
13874
d81db636
SB
13875#undef TARGET_LRA_P
13876#define TARGET_LRA_P hook_bool_void_false
13877
43c626f0
GJL
13878#undef TARGET_ADDR_SPACE_SUBSET_P
13879#define TARGET_ADDR_SPACE_SUBSET_P avr_addr_space_subset_p
13880
13881#undef TARGET_ADDR_SPACE_CONVERT
13882#define TARGET_ADDR_SPACE_CONVERT avr_addr_space_convert
13883
13884#undef TARGET_ADDR_SPACE_ADDRESS_MODE
13885#define TARGET_ADDR_SPACE_ADDRESS_MODE avr_addr_space_address_mode
13886
13887#undef TARGET_ADDR_SPACE_POINTER_MODE
13888#define TARGET_ADDR_SPACE_POINTER_MODE avr_addr_space_pointer_mode
13889
13890#undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
13891#define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
13892 avr_addr_space_legitimate_address_p
13893
13894#undef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
13895#define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS avr_addr_space_legitimize_address
13896
2d06ca74
GJL
13897#undef TARGET_ADDR_SPACE_DIAGNOSE_USAGE
13898#define TARGET_ADDR_SPACE_DIAGNOSE_USAGE avr_addr_space_diagnose_usage
13899
03b29b0a
GJL
13900#undef TARGET_MODE_DEPENDENT_ADDRESS_P
13901#define TARGET_MODE_DEPENDENT_ADDRESS_P avr_mode_dependent_address_p
13902
43c626f0
GJL
13903#undef TARGET_PRINT_OPERAND
13904#define TARGET_PRINT_OPERAND avr_print_operand
13905#undef TARGET_PRINT_OPERAND_ADDRESS
13906#define TARGET_PRINT_OPERAND_ADDRESS avr_print_operand_address
13907#undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
13908#define TARGET_PRINT_OPERAND_PUNCT_VALID_P avr_print_operand_punct_valid_p
13909
998f15f3
SKS
13910#undef TARGET_USE_BY_PIECES_INFRASTRUCTURE_P
13911#define TARGET_USE_BY_PIECES_INFRASTRUCTURE_P \
13912 avr_use_by_pieces_infrastructure_p
13913
d2111e2f 13914struct gcc_target targetm = TARGET_INITIALIZER;
43ea6502 13915
43c626f0 13916\f
baac771a 13917#include "gt-avr.h"
This page took 6.9423 seconds and 5 git commands to generate.