]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/avr/avr.c
alpha.c (alpha_start_function): Use switch_to_section.
[thirdparty/gcc.git] / gcc / config / avr / avr.c
CommitLineData
90e7678c 1/* Subroutines for insn-output.c for ATMEL AVR micro controllers
deeec1d8 2 Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005
283334f0 3 Free Software Foundation, Inc.
90e7678c
DC
4 Contributed by Denis Chertykov (denisc@overta.ru)
5
7ec022b2 6 This file is part of GCC.
90e7678c 7
7ec022b2 8 GCC is free software; you can redistribute it and/or modify
90e7678c
DC
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
7ec022b2 13 GCC is distributed in the hope that it will be useful,
90e7678c
DC
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
7ec022b2 19 along with GCC; see the file COPYING. If not, write to
39d14dda
KC
20 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
21 Boston, MA 02110-1301, USA. */
90e7678c
DC
22
23#include "config.h"
b8fa3ed6 24#include "system.h"
4977bab6
ZW
25#include "coretypes.h"
26#include "tm.h"
90e7678c
DC
27#include "rtl.h"
28#include "regs.h"
29#include "hard-reg-set.h"
30#include "real.h"
31#include "insn-config.h"
32#include "conditions.h"
90e7678c
DC
33#include "insn-attr.h"
34#include "flags.h"
35#include "reload.h"
36#include "tree.h"
3eaf7a3c 37#include "output.h"
90e7678c
DC
38#include "expr.h"
39#include "toplev.h"
40#include "obstack.h"
41#include "function.h"
42#include "recog.h"
baac771a 43#include "ggc.h"
90e7678c 44#include "tm_p.h"
672a6f42
NB
45#include "target.h"
46#include "target-def.h"
90e7678c 47
3454eb73
DC
48/* Maximal allowed offset for an address in the LD command */
49#define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
90e7678c 50
269e3795
SB
51static int avr_naked_function_p (tree);
52static int interrupt_function_p (tree);
53static int signal_function_p (tree);
54static int avr_regs_to_save (HARD_REG_SET *);
55static int sequent_regs_live (void);
56static const char *ptrreg_to_str (int);
57static const char *cond_string (enum rtx_code);
58static int avr_num_arg_regs (enum machine_mode, tree);
59static int out_adj_frame_ptr (FILE *, int);
60static int out_set_stack_ptr (FILE *, int, int);
61static RTX_CODE compare_condition (rtx insn);
62static int compare_sign_p (rtx insn);
63static tree avr_handle_progmem_attribute (tree *, tree, tree, int, bool *);
64static tree avr_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
91d231cb 65const struct attribute_spec avr_attribute_table[];
269e3795
SB
66static bool avr_assemble_integer (rtx, unsigned int, int);
67static void avr_file_start (void);
68static void avr_file_end (void);
69static void avr_output_function_prologue (FILE *, HOST_WIDE_INT);
70static void avr_output_function_epilogue (FILE *, HOST_WIDE_INT);
269e3795 71static void avr_insert_attributes (tree, tree *);
d6b5193b 72static void avr_asm_init_sections (void);
269e3795
SB
73static unsigned int avr_section_type_flags (tree, const char *, int);
74
75static void avr_reorg (void);
76static void avr_asm_out_ctor (rtx, int);
77static void avr_asm_out_dtor (rtx, int);
8f2bf9f1 78static int avr_operand_rtx_cost (rtx, enum machine_mode, enum rtx_code);
269e3795
SB
79static bool avr_rtx_costs (rtx, int, int, int *);
80static int avr_address_cost (rtx);
b069302c 81static bool avr_return_in_memory (tree, tree);
9af145ae 82
2c338472 83/* Allocate registers from r25 to r8 for parameters for function calls. */
90e7678c
DC
84#define FIRST_CUM_REG 26
85
f1c25d3b 86/* Temporary register RTX (gen_rtx_REG (QImode, TMP_REGNO)) */
baac771a 87static GTY(()) rtx tmp_reg_rtx;
90e7678c 88
f1c25d3b 89/* Zeroed register RTX (gen_rtx_REG (QImode, ZERO_REGNO)) */
baac771a 90static GTY(()) rtx zero_reg_rtx;
6bec29c9 91
90e7678c 92/* AVR register names {"r0", "r1", ..., "r31"} */
27c38fbe 93static const char *const avr_regnames[] = REGISTER_NAMES;
90e7678c
DC
94
95/* This holds the last insn address. */
96static int last_insn_address = 0;
97
98/* Commands count in the compiled file */
99static int commands_in_file;
100
101/* Commands in the functions prologues in the compiled file */
102static int commands_in_prologues;
103
104/* Commands in the functions epilogues in the compiled file */
105static int commands_in_epilogues;
106
107/* Prologue/Epilogue size in words */
108static int prologue_size;
109static int epilogue_size;
110
e9284adf
MM
111/* Size of all jump tables in the current function, in words. */
112static int jump_tables_size;
113
92c392e6
NB
114/* Preprocessor macros to define depending on MCU type. */
115const char *avr_base_arch_macro;
116const char *avr_extra_arch_macro;
117
d6b5193b
RS
118section *progmem_section;
119
6bec29c9
DC
120/* More than 8K of program memory: use "call" and "jmp". */
121int avr_mega_p = 0;
122
123/* Enhanced core: use "movw", "mul", ... */
124int avr_enhanced_p = 0;
125
bcb6a2be 126/* Assembler only. */
92c392e6
NB
127int avr_asm_only_p = 0;
128
129struct base_arch_s {
130 int asm_only;
131 int enhanced;
132 int mega;
133 const char *const macro;
134};
135
136static const struct base_arch_s avr_arch_types[] = {
137 { 1, 0, 0, NULL }, /* unknown device specified */
138 { 1, 0, 0, "__AVR_ARCH__=1" },
139 { 0, 0, 0, "__AVR_ARCH__=2" },
140 { 0, 0, 1, "__AVR_ARCH__=3" },
141 { 0, 1, 0, "__AVR_ARCH__=4" },
142 { 0, 1, 1, "__AVR_ARCH__=5" }
6bec29c9
DC
143};
144
145struct mcu_type_s {
8b60264b 146 const char *const name;
92c392e6
NB
147 int arch; /* index in avr_arch_types[] */
148 /* Must lie outside user's namespace. NULL == no macro. */
149 const char *const macro;
6bec29c9
DC
150};
151
152/* List of all known AVR MCU types - if updated, it has to be kept
153 in sync in several places (FIXME: is there a better way?):
154 - here
155 - avr.h (CPP_SPEC, LINK_SPEC, CRT_BINUTILS_SPECS)
156 - t-avr (MULTILIB_MATCHES)
157 - gas/config/tc-avr.c
158 - avr-libc */
159
160static const struct mcu_type_s avr_mcu_types[] = {
161 /* Classic, <= 8K. */
92c392e6
NB
162 { "avr2", 2, NULL },
163 { "at90s2313", 2, "__AVR_AT90S2313__" },
164 { "at90s2323", 2, "__AVR_AT90S2323__" },
165 { "at90s2333", 2, "__AVR_AT90S2333__" },
166 { "at90s2343", 2, "__AVR_AT90S2343__" },
167 { "attiny22", 2, "__AVR_ATtiny22__" },
168 { "attiny26", 2, "__AVR_ATtiny26__" },
169 { "at90s4414", 2, "__AVR_AT90S4414__" },
170 { "at90s4433", 2, "__AVR_AT90S4433__" },
171 { "at90s4434", 2, "__AVR_AT90S4434__" },
172 { "at90s8515", 2, "__AVR_AT90S8515__" },
173 { "at90c8534", 2, "__AVR_AT90C8534__" },
174 { "at90s8535", 2, "__AVR_AT90S8535__" },
25f2e176 175 { "at86rf401", 2, "__AVR_AT86RF401__" },
6b262ee8
MM
176 /* Classic + MOVW, <= 8K. */
177 { "attiny13", 2, "__AVR_ATtiny13__" },
178 { "attiny2313", 2, "__AVR_ATtiny2313__" },
6bec29c9 179 /* Classic, > 8K. */
92c392e6 180 { "avr3", 3, NULL },
e7d82ce2
MM
181 { "atmega103", 3, "__AVR_ATmega103__" },
182 { "atmega603", 3, "__AVR_ATmega603__" },
92c392e6
NB
183 { "at43usb320", 3, "__AVR_AT43USB320__" },
184 { "at43usb355", 3, "__AVR_AT43USB355__" },
185 { "at76c711", 3, "__AVR_AT76C711__" },
6bec29c9 186 /* Enhanced, <= 8K. */
92c392e6
NB
187 { "avr4", 4, NULL },
188 { "atmega8", 4, "__AVR_ATmega8__" },
35920225
TR
189 { "atmega48", 4, "__AVR_ATmega48__" },
190 { "atmega88", 4, "__AVR_ATmega88__" },
92c392e6 191 { "atmega8515", 4, "__AVR_ATmega8515__" },
25f2e176 192 { "atmega8535", 4, "__AVR_ATmega8535__" },
6bec29c9 193 /* Enhanced, > 8K. */
92c392e6
NB
194 { "avr5", 5, NULL },
195 { "atmega16", 5, "__AVR_ATmega16__" },
196 { "atmega161", 5, "__AVR_ATmega161__" },
197 { "atmega162", 5, "__AVR_ATmega162__" },
198 { "atmega163", 5, "__AVR_ATmega163__" },
35920225
TR
199 { "atmega165", 5, "__AVR_ATmega165__" },
200 { "atmega168", 5, "__AVR_ATmega168__" },
25f2e176 201 { "atmega169", 5, "__AVR_ATmega169__" },
92c392e6
NB
202 { "atmega32", 5, "__AVR_ATmega32__" },
203 { "atmega323", 5, "__AVR_ATmega323__" },
35920225
TR
204 { "atmega325", 5, "__AVR_ATmega325__" },
205 { "atmega3250", 5, "__AVR_ATmega3250__" },
92c392e6 206 { "atmega64", 5, "__AVR_ATmega64__" },
35920225
TR
207 { "atmega645", 5, "__AVR_ATmega645__" },
208 { "atmega6450", 5, "__AVR_ATmega6450__" },
92c392e6 209 { "atmega128", 5, "__AVR_ATmega128__" },
35920225 210 { "at90can128", 5, "__AVR_AT90CAN128__" },
92c392e6 211 { "at94k", 5, "__AVR_AT94K__" },
6bec29c9 212 /* Assembler only. */
92c392e6
NB
213 { "avr1", 1, NULL },
214 { "at90s1200", 1, "__AVR_AT90S1200__" },
92c392e6
NB
215 { "attiny11", 1, "__AVR_ATtiny11__" },
216 { "attiny12", 1, "__AVR_ATtiny12__" },
217 { "attiny15", 1, "__AVR_ATtiny15__" },
218 { "attiny28", 1, "__AVR_ATtiny28__" },
219 { NULL, 0, NULL }
6bec29c9 220};
90e7678c 221
1268b05f 222int avr_case_values_threshold = 30000;
672a6f42
NB
223\f
224/* Initialize the GCC target structure. */
301d03af
RS
225#undef TARGET_ASM_ALIGNED_HI_OP
226#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
10252a62
BH
227#undef TARGET_ASM_ALIGNED_SI_OP
228#define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
229#undef TARGET_ASM_UNALIGNED_HI_OP
230#define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
231#undef TARGET_ASM_UNALIGNED_SI_OP
232#define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
301d03af
RS
233#undef TARGET_ASM_INTEGER
234#define TARGET_ASM_INTEGER avr_assemble_integer
1bc7c5b6
ZW
235#undef TARGET_ASM_FILE_START
236#define TARGET_ASM_FILE_START avr_file_start
237#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
238#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
a5fe455b
ZW
239#undef TARGET_ASM_FILE_END
240#define TARGET_ASM_FILE_END avr_file_end
301d03af 241
08c148a8
NB
242#undef TARGET_ASM_FUNCTION_PROLOGUE
243#define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
244#undef TARGET_ASM_FUNCTION_EPILOGUE
245#define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
91d231cb
JM
246#undef TARGET_ATTRIBUTE_TABLE
247#define TARGET_ATTRIBUTE_TABLE avr_attribute_table
ab5c8549
JJ
248#undef TARGET_ASM_FUNCTION_RODATA_SECTION
249#define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
74b66b3c
RH
250#undef TARGET_INSERT_ATTRIBUTES
251#define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
c16e5a35
MM
252#undef TARGET_SECTION_TYPE_FLAGS
253#define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
3c50106f
RH
254#undef TARGET_RTX_COSTS
255#define TARGET_RTX_COSTS avr_rtx_costs
dcefdf67
RH
256#undef TARGET_ADDRESS_COST
257#define TARGET_ADDRESS_COST avr_address_cost
18dbd950
RS
258#undef TARGET_MACHINE_DEPENDENT_REORG
259#define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
672a6f42 260
b069302c
KH
261#undef TARGET_RETURN_IN_MEMORY
262#define TARGET_RETURN_IN_MEMORY avr_return_in_memory
263
264#undef TARGET_STRICT_ARGUMENT_NAMING
265#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
266
f6897b10 267struct gcc_target targetm = TARGET_INITIALIZER;
672a6f42 268\f
90e7678c 269void
269e3795 270avr_override_options (void)
90e7678c 271{
6bec29c9 272 const struct mcu_type_s *t;
92c392e6 273 const struct base_arch_s *base;
6bec29c9
DC
274
275 for (t = avr_mcu_types; t->name; t++)
276 if (strcmp (t->name, avr_mcu_name) == 0)
90e7678c 277 break;
6bec29c9
DC
278
279 if (!t->name)
90e7678c 280 {
c85ce869 281 fprintf (stderr, "unknown MCU '%s' specified\nKnown MCU names:\n",
6bec29c9
DC
282 avr_mcu_name);
283 for (t = avr_mcu_types; t->name; t++)
284 fprintf (stderr," %s\n", t->name);
6bec29c9
DC
285 }
286
92c392e6
NB
287 base = &avr_arch_types[t->arch];
288 avr_asm_only_p = base->asm_only;
289 avr_enhanced_p = base->enhanced;
290 avr_mega_p = base->mega;
291 avr_base_arch_macro = base->macro;
292 avr_extra_arch_macro = t->macro;
1268b05f
MM
293
294 if (optimize && !TARGET_NO_TABLEJUMP)
295 avr_case_values_threshold = (!AVR_MEGA || TARGET_CALL_PROLOGUES) ? 8 : 17;
90e7678c 296
baac771a
KH
297 tmp_reg_rtx = gen_rtx_REG (QImode, TMP_REGNO);
298 zero_reg_rtx = gen_rtx_REG (QImode, ZERO_REGNO);
90e7678c
DC
299}
300
2c338472 301/* return register class from register number. */
90e7678c 302
8b60264b 303static const int reg_class_tab[]={
90e7678c
DC
304 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
305 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
306 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
307 GENERAL_REGS, /* r0 - r15 */
308 LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,
309 LD_REGS, /* r16 - 23 */
310 ADDW_REGS,ADDW_REGS, /* r24,r25 */
311 POINTER_X_REGS,POINTER_X_REGS, /* r26,27 */
312 POINTER_Y_REGS,POINTER_Y_REGS, /* r28,r29 */
313 POINTER_Z_REGS,POINTER_Z_REGS, /* r30,r31 */
314 STACK_REG,STACK_REG /* SPL,SPH */
315};
316
2c338472 317/* Return register class for register R. */
90e7678c
DC
318
319enum reg_class
269e3795 320avr_regno_reg_class (int r)
90e7678c
DC
321{
322 if (r <= 33)
323 return reg_class_tab[r];
324 return ALL_REGS;
325}
326
327
328/* A C expression which defines the machine-dependent operand
329 constraint letters for register classes. If C is such a
330 letter, the value should be the register class corresponding to
331 it. Otherwise, the value should be `NO_REGS'. The register
332 letter `r', corresponding to class `GENERAL_REGS', will not be
333 passed to this macro; you do not need to handle it. */
334
335enum reg_class
269e3795 336avr_reg_class_from_letter (int c)
90e7678c
DC
337{
338 switch (c)
339 {
340 case 't' : return R0_REG;
341 case 'b' : return BASE_POINTER_REGS;
342 case 'e' : return POINTER_REGS;
343 case 'w' : return ADDW_REGS;
344 case 'd' : return LD_REGS;
345 case 'l' : return NO_LD_REGS;
346 case 'a' : return SIMPLE_LD_REGS;
347 case 'x' : return POINTER_X_REGS;
348 case 'y' : return POINTER_Y_REGS;
349 case 'z' : return POINTER_Z_REGS;
350 case 'q' : return STACK_REG;
351 default: break;
352 }
353 return NO_REGS;
354}
355
825dda42 356/* Return nonzero if FUNC is a naked function. */
90e7678c
DC
357
358static int
269e3795 359avr_naked_function_p (tree func)
90e7678c
DC
360{
361 tree a;
362
25b9575b 363 gcc_assert (TREE_CODE (func) == FUNCTION_DECL);
90e7678c 364
91d231cb 365 a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
90e7678c
DC
366 return a != NULL_TREE;
367}
368
369/* Return nonzero if FUNC is an interrupt function as specified
370 by the "interrupt" attribute. */
371
372static int
269e3795 373interrupt_function_p (tree func)
90e7678c
DC
374{
375 tree a;
376
377 if (TREE_CODE (func) != FUNCTION_DECL)
378 return 0;
379
91d231cb 380 a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
90e7678c
DC
381 return a != NULL_TREE;
382}
383
3454eb73 384/* Return nonzero if FUNC is a signal function as specified
90e7678c
DC
385 by the "signal" attribute. */
386
387static int
269e3795 388signal_function_p (tree func)
90e7678c
DC
389{
390 tree a;
391
392 if (TREE_CODE (func) != FUNCTION_DECL)
393 return 0;
394
91d231cb 395 a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
90e7678c
DC
396 return a != NULL_TREE;
397}
398
93febe68
MM
399/* Return the number of hard registers to push/pop in the prologue/epilogue
400 of the current function, and optionally store these registers in SET. */
401
402static int
269e3795 403avr_regs_to_save (HARD_REG_SET *set)
93febe68
MM
404{
405 int reg, count;
406 int int_or_sig_p = (interrupt_function_p (current_function_decl)
407 || signal_function_p (current_function_decl));
408 int leaf_func_p = leaf_function_p ();
409
410 if (set)
411 CLEAR_HARD_REG_SET (*set);
412 count = 0;
e52b6b63
MM
413
414 /* No need to save any registers if the function never returns. */
415 if (TREE_THIS_VOLATILE (current_function_decl))
416 return 0;
417
93febe68
MM
418 for (reg = 0; reg < 32; reg++)
419 {
420 /* Do not push/pop __tmp_reg__, __zero_reg__, as well as
421 any global register variables. */
422 if (fixed_regs[reg])
423 continue;
424
425 if ((int_or_sig_p && !leaf_func_p && call_used_regs[reg])
426 || (regs_ever_live[reg]
427 && (int_or_sig_p || !call_used_regs[reg])
428 && !(frame_pointer_needed
429 && (reg == REG_Y || reg == (REG_Y+1)))))
430 {
431 if (set)
432 SET_HARD_REG_BIT (*set, reg);
433 count++;
434 }
435 }
436 return count;
437}
438
2c338472 439/* Compute offset between arg_pointer and frame_pointer. */
90e7678c
DC
440
441int
269e3795 442initial_elimination_offset (int from, int to)
90e7678c 443{
3454eb73
DC
444 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
445 return 0;
446 else
447 {
93febe68 448 int offset = frame_pointer_needed ? 2 : 0;
3454eb73 449
93febe68 450 offset += avr_regs_to_save (NULL);
3454eb73 451 return get_frame_size () + 2 + 1 + offset;
90e7678c 452 }
90e7678c
DC
453}
454
126dbce0
MM
455/* Return 1 if the function epilogue is just a single "ret". */
456
457int
269e3795 458avr_simple_epilogue (void)
126dbce0
MM
459{
460 return (! frame_pointer_needed
461 && get_frame_size () == 0
462 && avr_regs_to_save (NULL) == 0
463 && ! interrupt_function_p (current_function_decl)
464 && ! signal_function_p (current_function_decl)
465 && ! avr_naked_function_p (current_function_decl)
466 && ! MAIN_NAME_P (DECL_NAME (current_function_decl))
467 && ! TREE_THIS_VOLATILE (current_function_decl));
468}
469
2c338472 470/* This function checks sequence of live registers. */
90e7678c
DC
471
472static int
269e3795 473sequent_regs_live (void)
90e7678c
DC
474{
475 int reg;
476 int live_seq=0;
477 int cur_seq=0;
478
479 for (reg = 0; reg < 18; ++reg)
480 {
481 if (!call_used_regs[reg])
482 {
483 if (regs_ever_live[reg])
484 {
485 ++live_seq;
486 ++cur_seq;
487 }
488 else
489 cur_seq = 0;
490 }
491 }
492
493 if (!frame_pointer_needed)
494 {
495 if (regs_ever_live[REG_Y])
496 {
497 ++live_seq;
498 ++cur_seq;
499 }
500 else
501 cur_seq = 0;
502
503 if (regs_ever_live[REG_Y+1])
504 {
505 ++live_seq;
506 ++cur_seq;
507 }
508 else
509 cur_seq = 0;
510 }
511 else
512 {
513 cur_seq += 2;
514 live_seq += 2;
515 }
516 return (cur_seq == live_seq) ? live_seq : 0;
517}
518
519
78cf8279
MM
520/* Output to FILE the asm instructions to adjust the frame pointer by
521 ADJ (r29:r28 -= ADJ;) which can be positive (prologue) or negative
522 (epilogue). Returns the number of instructions generated. */
523
524static int
269e3795 525out_adj_frame_ptr (FILE *file, int adj)
78cf8279
MM
526{
527 int size = 0;
528
529 if (adj)
530 {
c4984bad 531 if (TARGET_TINY_STACK)
78cf8279 532 {
c4984bad 533 if (adj < -63 || adj > 63)
d4ee4d25 534 warning (0, "large frame pointer change (%d) with -mtiny-stack", adj);
78cf8279 535
c4984bad
MM
536 /* The high byte (r29) doesn't change - prefer "subi" (1 cycle)
537 over "sbiw" (2 cycles, same size). */
538
539 fprintf (file, (AS2 (subi, r28, %d) CR_TAB), adj);
540 size++;
541 }
542 else if (adj < -63 || adj > 63)
543 {
544 fprintf (file, (AS2 (subi, r28, lo8(%d)) CR_TAB
545 AS2 (sbci, r29, hi8(%d)) CR_TAB),
6bec29c9 546 adj, adj);
c4984bad 547 size += 2;
78cf8279
MM
548 }
549 else if (adj < 0)
550 {
551 fprintf (file, (AS2 (adiw, r28, %d) CR_TAB), -adj);
552 size++;
553 }
554 else
555 {
556 fprintf (file, (AS2 (sbiw, r28, %d) CR_TAB), adj);
557 size++;
558 }
559 }
560 return size;
561}
562
563
564/* Output to FILE the asm instructions to copy r29:r28 to SPH:SPL,
565 handling various cases of interrupt enable flag state BEFORE and AFTER
566 (0=disabled, 1=enabled, -1=unknown/unchanged) and target_flags.
567 Returns the number of instructions generated. */
568
569static int
269e3795 570out_set_stack_ptr (FILE *file, int before, int after)
78cf8279 571{
c4984bad 572 int do_sph, do_cli, do_save, do_sei, lock_sph, size;
78cf8279 573
c4984bad
MM
574 /* The logic here is so that -mno-interrupts actually means
575 "it is safe to write SPH in one instruction, then SPL in the
576 next instruction, without disabling interrupts first".
577 The after != -1 case (interrupt/signal) is not affected. */
78cf8279
MM
578
579 do_sph = !TARGET_TINY_STACK;
c4984bad
MM
580 lock_sph = do_sph && !TARGET_NO_INTERRUPTS;
581 do_cli = (before != 0 && (after == 0 || lock_sph));
582 do_save = (do_cli && before == -1 && after == -1);
583 do_sei = ((do_cli || before != 1) && after == 1);
78cf8279
MM
584 size = 1;
585
586 if (do_save)
587 {
588 fprintf (file, AS2 (in, __tmp_reg__, __SREG__) CR_TAB);
589 size++;
590 }
591
592 if (do_cli)
593 {
594 fprintf (file, "cli" CR_TAB);
595 size++;
596 }
597
598 /* Do SPH first - maybe this will disable interrupts for one instruction
c4984bad
MM
599 someday (a suggestion has been sent to avr@atmel.com for consideration
600 in future devices - that would make -mno-interrupts always safe). */
78cf8279
MM
601 if (do_sph)
602 {
603 fprintf (file, AS2 (out, __SP_H__, r29) CR_TAB);
604 size++;
605 }
606
607 /* Set/restore the I flag now - interrupts will be really enabled only
cf14485b
MM
608 after the next instruction. This is not clearly documented, but
609 believed to be true for all AVR devices. */
78cf8279
MM
610 if (do_save)
611 {
612 fprintf (file, AS2 (out, __SREG__, __tmp_reg__) CR_TAB);
613 size++;
614 }
c4984bad 615 else if (do_sei)
78cf8279
MM
616 {
617 fprintf (file, "sei" CR_TAB);
618 size++;
619 }
620
621 fprintf (file, AS2 (out, __SP_L__, r28) "\n");
622
623 return size;
624}
625
626
2c338472 627/* Output function prologue. */
90e7678c 628
08c148a8 629static void
269e3795 630avr_output_function_prologue (FILE *file, HOST_WIDE_INT size)
90e7678c
DC
631{
632 int reg;
633 int interrupt_func_p;
634 int signal_func_p;
90e7678c
DC
635 int main_p;
636 int live_seq;
637 int minimize;
e52b6b63
MM
638
639 last_insn_address = 0;
640 jump_tables_size = 0;
641 prologue_size = 0;
7e53359d
KG
642 fprintf (file, "/* prologue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n",
643 size);
e52b6b63 644
90e7678c
DC
645 if (avr_naked_function_p (current_function_decl))
646 {
e52b6b63
MM
647 fputs ("/* prologue: naked */\n", file);
648 goto out;
90e7678c
DC
649 }
650
651 interrupt_func_p = interrupt_function_p (current_function_decl);
652 signal_func_p = signal_function_p (current_function_decl);
5b47282c 653 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
90e7678c
DC
654 live_seq = sequent_regs_live ();
655 minimize = (TARGET_CALL_PROLOGUES
656 && !interrupt_func_p && !signal_func_p && live_seq);
657
90e7678c
DC
658 if (interrupt_func_p)
659 {
660 fprintf (file,"\tsei\n");
661 ++prologue_size;
662 }
93febe68 663 if (interrupt_func_p || signal_func_p)
90e7678c
DC
664 {
665 fprintf (file, "\t"
666 AS1 (push,__zero_reg__) CR_TAB
667 AS1 (push,__tmp_reg__) CR_TAB
668 AS2 (in,__tmp_reg__,__SREG__) CR_TAB
669 AS1 (push,__tmp_reg__) CR_TAB
670 AS1 (clr,__zero_reg__) "\n");
671 prologue_size += 5;
672 }
673 if (main_p)
674 {
675 fprintf (file, ("\t"
7e53359d
KG
676 AS1 (ldi,r28) ",lo8(%s - " HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
677 AS1 (ldi,r29) ",hi8(%s - " HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
6bec29c9
DC
678 AS2 (out,__SP_H__,r29) CR_TAB
679 AS2 (out,__SP_L__,r28) "\n"),
680 avr_init_stack, size, avr_init_stack, size);
90e7678c
DC
681
682 prologue_size += 4;
683 }
684 else if (minimize && (frame_pointer_needed || live_seq > 6))
685 {
686 fprintf (file, ("\t"
7e53359d
KG
687 AS1 (ldi, r26) ",lo8(" HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
688 AS1 (ldi, r27) ",hi8(" HOST_WIDE_INT_PRINT_DEC ")" CR_TAB), size, size);
90e7678c 689
82b3eb42
MM
690 fputs ((AS2 (ldi,r30,pm_lo8(1f)) CR_TAB
691 AS2 (ldi,r31,pm_hi8(1f)) CR_TAB), file);
90e7678c
DC
692
693 prologue_size += 4;
694
695 if (AVR_MEGA)
696 {
697 fprintf (file, AS1 (jmp,__prologue_saves__+%d) "\n",
698 (18 - live_seq) * 2);
699 prologue_size += 2;
700 }
701 else
702 {
703 fprintf (file, AS1 (rjmp,__prologue_saves__+%d) "\n",
704 (18 - live_seq) * 2);
705 ++prologue_size;
706 }
82b3eb42 707 fputs ("1:\n", file);
90e7678c
DC
708 }
709 else
710 {
93febe68
MM
711 HARD_REG_SET set;
712
713 prologue_size += avr_regs_to_save (&set);
90e7678c
DC
714 for (reg = 0; reg < 32; ++reg)
715 {
93febe68 716 if (TEST_HARD_REG_BIT (set, reg))
90e7678c
DC
717 {
718 fprintf (file, "\t" AS1 (push,%s) "\n", avr_regnames[reg]);
90e7678c
DC
719 }
720 }
721 if (frame_pointer_needed)
722 {
908c8c7e
KH
723 fprintf (file, "\t"
724 AS1 (push,r28) CR_TAB
725 AS1 (push,r29) CR_TAB
726 AS2 (in,r28,__SP_L__) CR_TAB
727 AS2 (in,r29,__SP_H__) "\n");
728 prologue_size += 4;
729 if (size)
730 {
731 fputs ("\t", file);
732 prologue_size += out_adj_frame_ptr (file, size);
733
734 if (interrupt_func_p)
735 {
736 prologue_size += out_set_stack_ptr (file, 1, 1);
737 }
738 else if (signal_func_p)
739 {
740 prologue_size += out_set_stack_ptr (file, 0, 0);
741 }
742 else
743 {
744 prologue_size += out_set_stack_ptr (file, -1, -1);
745 }
746 }
90e7678c
DC
747 }
748 }
e52b6b63
MM
749
750 out:
90e7678c
DC
751 fprintf (file, "/* prologue end (size=%d) */\n", prologue_size);
752}
753
2c338472 754/* Output function epilogue. */
90e7678c 755
08c148a8 756static void
269e3795 757avr_output_function_epilogue (FILE *file, HOST_WIDE_INT size)
90e7678c
DC
758{
759 int reg;
760 int interrupt_func_p;
761 int signal_func_p;
90e7678c
DC
762 int main_p;
763 int function_size;
764 int live_seq;
765 int minimize;
e52b6b63
MM
766 rtx last = get_last_nonnote_insn ();
767
768 function_size = jump_tables_size;
769 if (last)
770 {
771 rtx first = get_first_nonnote_insn ();
772 function_size += (INSN_ADDRESSES (INSN_UID (last)) -
773 INSN_ADDRESSES (INSN_UID (first)));
774 function_size += get_attr_length (last);
775 }
776
7e53359d 777 fprintf (file, "/* epilogue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n", size);
e52b6b63 778 epilogue_size = 0;
90e7678c
DC
779
780 if (avr_naked_function_p (current_function_decl))
781 {
e52b6b63
MM
782 fputs ("/* epilogue: naked */\n", file);
783 goto out;
784 }
785
786 if (last && GET_CODE (last) == BARRIER)
787 {
788 fputs ("/* epilogue: noreturn */\n", file);
789 goto out;
90e7678c
DC
790 }
791
792 interrupt_func_p = interrupt_function_p (current_function_decl);
793 signal_func_p = signal_function_p (current_function_decl);
5b47282c 794 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
90e7678c
DC
795 live_seq = sequent_regs_live ();
796 minimize = (TARGET_CALL_PROLOGUES
797 && !interrupt_func_p && !signal_func_p && live_seq);
798
90e7678c
DC
799 if (main_p)
800 {
9af145ae
MM
801 /* Return value from main() is already in the correct registers
802 (r25:r24) as the exit() argument. */
803 if (AVR_MEGA)
804 {
805 fputs ("\t" AS1 (jmp,exit) "\n", file);
806 epilogue_size += 2;
807 }
808 else
809 {
810 fputs ("\t" AS1 (rjmp,exit) "\n", file);
811 ++epilogue_size;
812 }
90e7678c
DC
813 }
814 else if (minimize && (frame_pointer_needed || live_seq > 4))
815 {
816 fprintf (file, ("\t" AS2 (ldi, r30, %d) CR_TAB), live_seq);
817 ++epilogue_size;
818 if (frame_pointer_needed)
819 {
78cf8279 820 epilogue_size += out_adj_frame_ptr (file, -size);
90e7678c
DC
821 }
822 else
823 {
824 fprintf (file, (AS2 (in , r28, __SP_L__) CR_TAB
825 AS2 (in , r29, __SP_H__) CR_TAB));
826 epilogue_size += 2;
827 }
828
829 if (AVR_MEGA)
830 {
831 fprintf (file, AS1 (jmp,__epilogue_restores__+%d) "\n",
832 (18 - live_seq) * 2);
833 epilogue_size += 2;
834 }
835 else
836 {
837 fprintf (file, AS1 (rjmp,__epilogue_restores__+%d) "\n",
838 (18 - live_seq) * 2);
839 ++epilogue_size;
840 }
841 }
842 else
843 {
93febe68
MM
844 HARD_REG_SET set;
845
90e7678c
DC
846 if (frame_pointer_needed)
847 {
848 if (size)
849 {
78cf8279
MM
850 fputs ("\t", file);
851 epilogue_size += out_adj_frame_ptr (file, -size);
852
93febe68 853 if (interrupt_func_p || signal_func_p)
90e7678c 854 {
78cf8279 855 epilogue_size += out_set_stack_ptr (file, -1, 0);
90e7678c
DC
856 }
857 else
858 {
78cf8279 859 epilogue_size += out_set_stack_ptr (file, -1, -1);
90e7678c
DC
860 }
861 }
862 fprintf (file, "\t"
863 AS1 (pop,r29) CR_TAB
864 AS1 (pop,r28) "\n");
865 epilogue_size += 2;
866 }
867
93febe68 868 epilogue_size += avr_regs_to_save (&set);
90e7678c
DC
869 for (reg = 31; reg >= 0; --reg)
870 {
93febe68 871 if (TEST_HARD_REG_BIT (set, reg))
90e7678c
DC
872 {
873 fprintf (file, "\t" AS1 (pop,%s) "\n", avr_regnames[reg]);
90e7678c
DC
874 }
875 }
93febe68
MM
876
877 if (interrupt_func_p || signal_func_p)
90e7678c
DC
878 {
879 fprintf (file, "\t"
880 AS1 (pop,__tmp_reg__) CR_TAB
881 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
882 AS1 (pop,__tmp_reg__) CR_TAB
883 AS1 (pop,__zero_reg__) "\n");
884 epilogue_size += 4;
885 fprintf (file, "\treti\n");
886 }
887 else
888 fprintf (file, "\tret\n");
889 ++epilogue_size;
890 }
e52b6b63
MM
891
892 out:
90e7678c 893 fprintf (file, "/* epilogue end (size=%d) */\n", epilogue_size);
faed5cc3 894 fprintf (file, "/* function %s size %d (%d) */\n", current_function_name (),
90e7678c
DC
895 prologue_size + function_size + epilogue_size, function_size);
896 commands_in_file += prologue_size + function_size + epilogue_size;
897 commands_in_prologues += prologue_size;
898 commands_in_epilogues += epilogue_size;
899}
900
901
902/* Return nonzero if X (an RTX) is a legitimate memory address on the target
903 machine for a memory operand of mode MODE. */
904
905int
269e3795 906legitimate_address_p (enum machine_mode mode, rtx x, int strict)
90e7678c 907{
48ccfb40
DC
908 enum reg_class r = NO_REGS;
909
90e7678c
DC
910 if (TARGET_ALL_DEBUG)
911 {
912 fprintf (stderr, "mode: (%s) %s %s %s %s:",
913 GET_MODE_NAME(mode),
914 strict ? "(strict)": "",
915 reload_completed ? "(reload_completed)": "",
916 reload_in_progress ? "(reload_in_progress)": "",
917 reg_renumber ? "(reg_renumber)" : "");
918 if (GET_CODE (x) == PLUS
919 && REG_P (XEXP (x, 0))
920 && GET_CODE (XEXP (x, 1)) == CONST_INT
921 && INTVAL (XEXP (x, 1)) >= 0
3454eb73 922 && INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode)
90e7678c
DC
923 && reg_renumber
924 )
925 fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)),
926 true_regnum (XEXP (x, 0)));
927 debug_rtx (x);
928 }
929 if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
930 : REG_OK_FOR_BASE_NOSTRICT_P (x)))
48ccfb40 931 r = POINTER_REGS;
90e7678c 932 else if (CONSTANT_ADDRESS_P (x))
48ccfb40 933 r = ALL_REGS;
90e7678c
DC
934 else if (GET_CODE (x) == PLUS
935 && REG_P (XEXP (x, 0))
936 && GET_CODE (XEXP (x, 1)) == CONST_INT
937 && INTVAL (XEXP (x, 1)) >= 0)
938 {
3454eb73 939 int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
90e7678c
DC
940 if (fit)
941 {
942 if (! strict
6bec29c9
DC
943 || REGNO (XEXP (x,0)) == REG_Y
944 || REGNO (XEXP (x,0)) == REG_Z)
48ccfb40 945 r = BASE_POINTER_REGS;
90e7678c
DC
946 if (XEXP (x,0) == frame_pointer_rtx
947 || XEXP (x,0) == arg_pointer_rtx)
48ccfb40 948 r = BASE_POINTER_REGS;
90e7678c
DC
949 }
950 else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
48ccfb40 951 r = POINTER_Y_REGS;
90e7678c
DC
952 }
953 else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
954 && REG_P (XEXP (x, 0))
955 && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
956 : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
957 {
48ccfb40 958 r = POINTER_REGS;
90e7678c
DC
959 }
960 if (TARGET_ALL_DEBUG)
961 {
89a0b917 962 fprintf (stderr, " ret = %c\n", r + '0');
90e7678c 963 }
48ccfb40 964 return r == NO_REGS ? 0 : (int)r;
90e7678c
DC
965}
966
967/* Attempts to replace X with a valid
968 memory address for an operand of mode MODE */
969
970rtx
269e3795 971legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
90e7678c
DC
972{
973 x = oldx;
974 if (TARGET_ALL_DEBUG)
975 {
976 fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode));
977 debug_rtx (oldx);
978 }
979
980 if (GET_CODE (oldx) == PLUS
981 && REG_P (XEXP (oldx,0)))
982 {
983 if (REG_P (XEXP (oldx,1)))
984 x = force_reg (GET_MODE (oldx), oldx);
985 else if (GET_CODE (XEXP (oldx, 1)) == CONST_INT)
986 {
987 int offs = INTVAL (XEXP (oldx,1));
988 if (frame_pointer_rtx != XEXP (oldx,0))
3454eb73 989 if (offs > MAX_LD_OFFSET (mode))
90e7678c
DC
990 {
991 if (TARGET_ALL_DEBUG)
992 fprintf (stderr, "force_reg (big offset)\n");
993 x = force_reg (GET_MODE (oldx), oldx);
994 }
995 }
996 }
997 return x;
998}
999
1000
2c338472 1001/* Return a pointer register name as a string. */
90e7678c 1002
5fecfd8d 1003static const char *
269e3795 1004ptrreg_to_str (int regno)
90e7678c
DC
1005{
1006 switch (regno)
1007 {
1008 case REG_X: return "X";
1009 case REG_Y: return "Y";
1010 case REG_Z: return "Z";
1011 default:
25b9575b 1012 gcc_unreachable ();
90e7678c
DC
1013 }
1014 return NULL;
1015}
1016
1017/* Return the condition name as a string.
1018 Used in conditional jump constructing */
1019
5fecfd8d 1020static const char *
269e3795 1021cond_string (enum rtx_code code)
90e7678c
DC
1022{
1023 switch (code)
1024 {
1025 case NE:
1026 return "ne";
1027 case EQ:
1028 return "eq";
1029 case GE:
1030 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1031 return "pl";
1032 else
1033 return "ge";
90e7678c
DC
1034 case LT:
1035 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1036 return "mi";
1037 else
1038 return "lt";
1039 case GEU:
1040 return "sh";
90e7678c
DC
1041 case LTU:
1042 return "lo";
1043 default:
25b9575b 1044 gcc_unreachable ();
90e7678c
DC
1045 }
1046}
1047
2c338472 1048/* Output ADDR to FILE as address. */
90e7678c
DC
1049
1050void
269e3795 1051print_operand_address (FILE *file, rtx addr)
90e7678c
DC
1052{
1053 switch (GET_CODE (addr))
1054 {
1055 case REG:
1056 fprintf (file, ptrreg_to_str (REGNO (addr)));
1057 break;
1058
1059 case PRE_DEC:
1060 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1061 break;
1062
1063 case POST_INC:
1064 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
1065 break;
1066
1067 default:
1068 if (CONSTANT_ADDRESS_P (addr)
74b66b3c 1069 && ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (addr))
1a499b92 1070 || GET_CODE (addr) == LABEL_REF))
90e7678c
DC
1071 {
1072 fprintf (file, "pm(");
1073 output_addr_const (file,addr);
1074 fprintf (file ,")");
1075 }
1076 else
1077 output_addr_const (file, addr);
1078 }
1079}
1080
1081
2c338472 1082/* Output X as assembler operand to file FILE. */
90e7678c
DC
1083
1084void
269e3795 1085print_operand (FILE *file, rtx x, int code)
90e7678c
DC
1086{
1087 int abcd = 0;
1088
1089 if (code >= 'A' && code <= 'D')
1090 abcd = code - 'A';
1091
cf14485b
MM
1092 if (code == '~')
1093 {
1094 if (!AVR_MEGA)
1095 fputc ('r', file);
1096 }
1097 else if (REG_P (x))
90e7678c
DC
1098 {
1099 if (x == zero_reg_rtx)
cf14485b 1100 fprintf (file, "__zero_reg__");
90e7678c
DC
1101 else
1102 fprintf (file, reg_names[true_regnum (x) + abcd]);
1103 }
1104 else if (GET_CODE (x) == CONST_INT)
7e53359d 1105 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) + abcd);
90e7678c
DC
1106 else if (GET_CODE (x) == MEM)
1107 {
1108 rtx addr = XEXP (x,0);
6bec29c9
DC
1109
1110 if (CONSTANT_P (addr) && abcd)
90e7678c
DC
1111 {
1112 fputc ('(', file);
1113 output_address (addr);
1114 fprintf (file, ")+%d", abcd);
1115 }
cf14485b
MM
1116 else if (code == 'o')
1117 {
1118 if (GET_CODE (addr) != PLUS)
c725bd79 1119 fatal_insn ("bad address, not (reg+disp):", addr);
cf14485b
MM
1120
1121 print_operand (file, XEXP (addr, 1), 0);
1122 }
a6990185
MM
1123 else if (code == 'p' || code == 'r')
1124 {
1125 if (GET_CODE (addr) != POST_INC && GET_CODE (addr) != PRE_DEC)
1126 fatal_insn ("bad address, not post_inc or pre_dec:", addr);
1127
1128 if (code == 'p')
1129 print_operand_address (file, XEXP (addr, 0)); /* X, Y, Z */
1130 else
1131 print_operand (file, XEXP (addr, 0), 0); /* r26, r28, r30 */
1132 }
90e7678c
DC
1133 else if (GET_CODE (addr) == PLUS)
1134 {
1135 print_operand_address (file, XEXP (addr,0));
1136 if (REGNO (XEXP (addr, 0)) == REG_X)
c725bd79 1137 fatal_insn ("internal compiler error. Bad address:"
90e7678c
DC
1138 ,addr);
1139 fputc ('+', file);
1140 print_operand (file, XEXP (addr,1), code);
1141 }
1142 else
1143 print_operand_address (file, addr);
1144 }
1145 else if (GET_CODE (x) == CONST_DOUBLE)
1146 {
1147 long val;
1148 REAL_VALUE_TYPE rv;
1149 if (GET_MODE (x) != SFmode)
c725bd79 1150 fatal_insn ("internal compiler error. Unknown mode:", x);
90e7678c
DC
1151 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
1152 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
761c70aa 1153 fprintf (file, "0x%lx", val);
90e7678c
DC
1154 }
1155 else if (code == 'j')
761c70aa 1156 fputs (cond_string (GET_CODE (x)), file);
90e7678c 1157 else if (code == 'k')
761c70aa 1158 fputs (cond_string (reverse_condition (GET_CODE (x))), file);
90e7678c 1159 else
cdd9eb8f 1160 print_operand_address (file, x);
90e7678c
DC
1161}
1162
2c338472 1163/* Recognize operand OP of mode MODE used in call instructions. */
90e7678c
DC
1164
1165int
269e3795 1166call_insn_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
90e7678c
DC
1167{
1168 if (GET_CODE (op) == MEM)
1169 {
1170 rtx inside = XEXP (op, 0);
1171 if (register_operand (inside, Pmode))
1172 return 1;
1173 if (CONSTANT_ADDRESS_P (inside))
1174 return 1;
1175 }
1176 return 0;
1177}
1178
1179/* Update the condition code in the INSN. */
1180
1181void
269e3795 1182notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx insn)
90e7678c 1183{
3454eb73
DC
1184 rtx set;
1185
90e7678c
DC
1186 switch (get_attr_cc (insn))
1187 {
1188 case CC_NONE:
1189 /* Insn does not affect CC at all. */
1190 break;
1191
1192 case CC_SET_N:
1193 CC_STATUS_INIT;
1194 break;
1195
1196 case CC_SET_ZN:
3454eb73
DC
1197 set = single_set (insn);
1198 CC_STATUS_INIT;
1199 if (set)
1200 {
1201 cc_status.flags |= CC_NO_OVERFLOW;
1202 cc_status.value1 = SET_DEST (set);
1203 }
90e7678c
DC
1204 break;
1205
1206 case CC_SET_CZN:
1207 /* Insn sets the Z,N,C flags of CC to recog_operand[0].
1208 The V flag may or may not be known but that's ok because
1209 alter_cond will change tests to use EQ/NE. */
3454eb73
DC
1210 set = single_set (insn);
1211 CC_STATUS_INIT;
1212 if (set)
1213 {
1214 cc_status.value1 = SET_DEST (set);
1215 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1216 }
90e7678c
DC
1217 break;
1218
1219 case CC_COMPARE:
3454eb73
DC
1220 set = single_set (insn);
1221 CC_STATUS_INIT;
1222 if (set)
1223 cc_status.value1 = SET_SRC (set);
90e7678c 1224 break;
3454eb73 1225
90e7678c
DC
1226 case CC_CLOBBER:
1227 /* Insn doesn't leave CC in a usable state. */
1228 CC_STATUS_INIT;
3454eb73
DC
1229
1230 /* Correct CC for the ashrqi3 with the shift count as CONST_INT != 6 */
1231 set = single_set (insn);
1232 if (set)
1233 {
1234 rtx src = SET_SRC (set);
1235
1236 if (GET_CODE (src) == ASHIFTRT
1237 && GET_MODE (src) == QImode)
1238 {
1239 rtx x = XEXP (src, 1);
1240
1241 if (GET_CODE (x) == CONST_INT
a3cf5992 1242 && INTVAL (x) > 0
3454eb73
DC
1243 && INTVAL (x) != 6)
1244 {
1245 cc_status.value1 = SET_DEST (set);
1246 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
1247 }
1248 }
1249 }
90e7678c
DC
1250 break;
1251 }
1252}
1253
1254/* Return maximum number of consecutive registers of
1255 class CLASS needed to hold a value of mode MODE. */
1256
1257int
269e3795 1258class_max_nregs (enum reg_class class ATTRIBUTE_UNUSED,enum machine_mode mode)
90e7678c
DC
1259{
1260 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
1261}
1262
1263/* Choose mode for jump insn:
1264 1 - relative jump in range -63 <= x <= 62 ;
1265 2 - relative jump in range -2046 <= x <= 2045 ;
1266 3 - absolute jump (only for ATmega[16]03). */
1267
1268int
269e3795 1269avr_jump_mode (rtx x, rtx insn)
90e7678c 1270{
9d98a694
AO
1271 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_MODE (x) == LABEL_REF
1272 ? XEXP (x, 0) : x));
1273 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
90e7678c
DC
1274 int jump_distance = cur_addr - dest_addr;
1275
1276 if (-63 <= jump_distance && jump_distance <= 62)
1277 return 1;
1278 else if (-2046 <= jump_distance && jump_distance <= 2045)
1279 return 2;
1280 else if (AVR_MEGA)
1281 return 3;
1282
1283 return 2;
1284}
1285
56b871c1
DC
1286/* return an AVR condition jump commands.
1287 X is a comparison RTX.
1288 LEN is a number returned by avr_jump_mode function.
1289 if REVERSE nonzero then condition code in X must be reversed. */
90e7678c 1290
5fecfd8d 1291const char *
269e3795 1292ret_cond_branch (rtx x, int len, int reverse)
90e7678c 1293{
56b871c1
DC
1294 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
1295
90e7678c
DC
1296 switch (cond)
1297 {
1298 case GT:
1299 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
13e8651c 1300 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
90e7678c 1301 AS1 (brpl,%0)) :
13e8651c
TR
1302 len == 2 ? (AS1 (breq,.+4) CR_TAB
1303 AS1 (brmi,.+2) CR_TAB
90e7678c 1304 AS1 (rjmp,%0)) :
13e8651c
TR
1305 (AS1 (breq,.+6) CR_TAB
1306 AS1 (brmi,.+4) CR_TAB
90e7678c
DC
1307 AS1 (jmp,%0)));
1308
1309 else
13e8651c 1310 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
90e7678c 1311 AS1 (brge,%0)) :
13e8651c
TR
1312 len == 2 ? (AS1 (breq,.+4) CR_TAB
1313 AS1 (brlt,.+2) CR_TAB
90e7678c 1314 AS1 (rjmp,%0)) :
13e8651c
TR
1315 (AS1 (breq,.+6) CR_TAB
1316 AS1 (brlt,.+4) CR_TAB
90e7678c
DC
1317 AS1 (jmp,%0)));
1318 case GTU:
13e8651c 1319 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
90e7678c 1320 AS1 (brsh,%0)) :
13e8651c
TR
1321 len == 2 ? (AS1 (breq,.+4) CR_TAB
1322 AS1 (brlo,.+2) CR_TAB
90e7678c 1323 AS1 (rjmp,%0)) :
13e8651c
TR
1324 (AS1 (breq,.+6) CR_TAB
1325 AS1 (brlo,.+4) CR_TAB
90e7678c
DC
1326 AS1 (jmp,%0)));
1327 case LE:
1328 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
1329 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1330 AS1 (brmi,%0)) :
13e8651c
TR
1331 len == 2 ? (AS1 (breq,.+2) CR_TAB
1332 AS1 (brpl,.+2) CR_TAB
90e7678c 1333 AS1 (rjmp,%0)) :
13e8651c
TR
1334 (AS1 (breq,.+2) CR_TAB
1335 AS1 (brpl,.+4) CR_TAB
90e7678c
DC
1336 AS1 (jmp,%0)));
1337 else
1338 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1339 AS1 (brlt,%0)) :
13e8651c
TR
1340 len == 2 ? (AS1 (breq,.+2) CR_TAB
1341 AS1 (brge,.+2) CR_TAB
90e7678c 1342 AS1 (rjmp,%0)) :
13e8651c
TR
1343 (AS1 (breq,.+2) CR_TAB
1344 AS1 (brge,.+4) CR_TAB
90e7678c
DC
1345 AS1 (jmp,%0)));
1346 case LEU:
1347 return (len == 1 ? (AS1 (breq,%0) CR_TAB
1348 AS1 (brlo,%0)) :
13e8651c
TR
1349 len == 2 ? (AS1 (breq,.+2) CR_TAB
1350 AS1 (brsh,.+2) CR_TAB
90e7678c 1351 AS1 (rjmp,%0)) :
13e8651c
TR
1352 (AS1 (breq,.+2) CR_TAB
1353 AS1 (brsh,.+4) CR_TAB
90e7678c
DC
1354 AS1 (jmp,%0)));
1355 default:
56b871c1
DC
1356 if (reverse)
1357 {
1358 switch (len)
1359 {
1360 case 1:
1361 return AS1 (br%k1,%0);
1362 case 2:
13e8651c 1363 return (AS1 (br%j1,.+2) CR_TAB
56b871c1
DC
1364 AS1 (rjmp,%0));
1365 default:
13e8651c 1366 return (AS1 (br%j1,.+4) CR_TAB
56b871c1
DC
1367 AS1 (jmp,%0));
1368 }
1369 }
1370 else
1371 {
1372 switch (len)
1373 {
1374 case 1:
1375 return AS1 (br%j1,%0);
1376 case 2:
13e8651c 1377 return (AS1 (br%k1,.+2) CR_TAB
56b871c1
DC
1378 AS1 (rjmp,%0));
1379 default:
13e8651c 1380 return (AS1 (br%k1,.+4) CR_TAB
56b871c1
DC
1381 AS1 (jmp,%0));
1382 }
1383 }
90e7678c
DC
1384 }
1385 return "";
1386}
1387
1388/* Predicate function for immediate operand which fits to byte (8bit) */
1389
1390int
269e3795 1391byte_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
90e7678c
DC
1392{
1393 return (GET_CODE (op) == CONST_INT
1394 && INTVAL (op) <= 0xff && INTVAL (op) >= 0);
1395}
1396
1397/* Output all insn addresses and their sizes into the assembly language
1398 output file. This is helpful for debugging whether the length attributes
1399 in the md file are correct.
1400 Output insn cost for next insn. */
1401
1402void
269e3795
SB
1403final_prescan_insn (rtx insn, rtx *operand ATTRIBUTE_UNUSED,
1404 int num_operands ATTRIBUTE_UNUSED)
90e7678c
DC
1405{
1406 int uid = INSN_UID (insn);
1407
1408 if (TARGET_INSN_SIZE_DUMP || TARGET_ALL_DEBUG)
1409 {
9d98a694
AO
1410 fprintf (asm_out_file, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
1411 INSN_ADDRESSES (uid),
1412 INSN_ADDRESSES (uid) - last_insn_address,
1413 rtx_cost (PATTERN (insn), INSN));
90e7678c 1414 }
9d98a694 1415 last_insn_address = INSN_ADDRESSES (uid);
90e7678c
DC
1416}
1417
5fecfd8d 1418/* Return 0 if undefined, 1 if always true or always false. */
90e7678c
DC
1419
1420int
269e3795 1421avr_simplify_comparison_p (enum machine_mode mode, RTX_CODE operator, rtx x)
90e7678c
DC
1422{
1423 unsigned int max = (mode == QImode ? 0xff :
1424 mode == HImode ? 0xffff :
11f9ed1a 1425 mode == SImode ? 0xffffffff : 0);
90e7678c
DC
1426 if (max && operator && GET_CODE (x) == CONST_INT)
1427 {
1428 if (unsigned_condition (operator) != operator)
1429 max >>= 1;
1430
1431 if (max != (INTVAL (x) & max)
1432 && INTVAL (x) != 0xff)
1433 return 1;
1434 }
1435 return 0;
1436}
1437
1438
1439/* Returns nonzero if REGNO is the number of a hard
1440 register in which function arguments are sometimes passed. */
1441
1442int
269e3795 1443function_arg_regno_p(int r)
90e7678c
DC
1444{
1445 return (r >= 8 && r <= 25);
1446}
1447
1448/* Initializing the variable cum for the state at the beginning
1449 of the argument list. */
1450
1451void
269e3795
SB
1452init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
1453 tree fndecl ATTRIBUTE_UNUSED)
90e7678c
DC
1454{
1455 cum->nregs = 18;
1456 cum->regno = FIRST_CUM_REG;
d0749053 1457 if (!libname && fntype)
90e7678c
DC
1458 {
1459 int stdarg = (TYPE_ARG_TYPES (fntype) != 0
1460 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
1461 != void_type_node));
1462 if (stdarg)
1463 cum->nregs = 0;
1464 }
1465}
1466
c4984bad
MM
1467/* Returns the number of registers to allocate for a function argument. */
1468
1469static int
269e3795 1470avr_num_arg_regs (enum machine_mode mode, tree type)
c4984bad
MM
1471{
1472 int size;
1473
1474 if (mode == BLKmode)
1475 size = int_size_in_bytes (type);
1476 else
1477 size = GET_MODE_SIZE (mode);
1478
afee2a52
MM
1479 /* Align all function arguments to start in even-numbered registers.
1480 Odd-sized arguments leave holes above them. */
c4984bad 1481
afee2a52 1482 return (size + 1) & ~1;
c4984bad
MM
1483}
1484
90e7678c 1485/* Controls whether a function argument is passed
2c338472 1486 in a register, and which register. */
90e7678c
DC
1487
1488rtx
269e3795
SB
1489function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1490 int named ATTRIBUTE_UNUSED)
90e7678c 1491{
c4984bad 1492 int bytes = avr_num_arg_regs (mode, type);
90e7678c
DC
1493
1494 if (cum->nregs && bytes <= cum->nregs)
f1c25d3b 1495 return gen_rtx_REG (mode, cum->regno - bytes);
c4984bad 1496
90e7678c
DC
1497 return NULL_RTX;
1498}
1499
1500/* Update the summarizer variable CUM to advance past an argument
1501 in the argument list. */
1502
1503void
269e3795
SB
1504function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1505 int named ATTRIBUTE_UNUSED)
90e7678c 1506{
c4984bad 1507 int bytes = avr_num_arg_regs (mode, type);
90e7678c 1508
90e7678c
DC
1509 cum->nregs -= bytes;
1510 cum->regno -= bytes;
1511
1512 if (cum->nregs <= 0)
1513 {
1514 cum->nregs = 0;
1515 cum->regno = FIRST_CUM_REG;
1516 }
90e7678c
DC
1517}
1518
1519/***********************************************************************
1520 Functions for outputting various mov's for a various modes
1521************************************************************************/
5fecfd8d 1522const char *
269e3795 1523output_movqi (rtx insn, rtx operands[], int *l)
90e7678c 1524{
6bec29c9
DC
1525 int dummy;
1526 rtx dest = operands[0];
1527 rtx src = operands[1];
1528 int *real_l = l;
1529
1530 if (!l)
1531 l = &dummy;
1532
1533 *l = 1;
1534
1535 if (register_operand (dest, QImode))
90e7678c 1536 {
6bec29c9 1537 if (register_operand (src, QImode)) /* mov r,r */
90e7678c 1538 {
6bec29c9
DC
1539 if (test_hard_reg_class (STACK_REG, dest))
1540 return AS2 (out,%0,%1);
1541 else if (test_hard_reg_class (STACK_REG, src))
1542 return AS2 (in,%0,%1);
1543
1544 return AS2 (mov,%0,%1);
1545 }
1546 else if (CONSTANT_P (src))
1547 {
1548 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1549 return AS2 (ldi,%0,lo8(%1));
1550
1551 if (GET_CODE (src) == CONST_INT)
90e7678c 1552 {
6bec29c9
DC
1553 if (src == const0_rtx) /* mov r,L */
1554 return AS1 (clr,%0);
1555 else if (src == const1_rtx)
90e7678c 1556 {
6bec29c9
DC
1557 *l = 2;
1558 return (AS1 (clr,%0) CR_TAB
1559 AS1 (inc,%0));
1560 }
6bec29c9 1561 else if (src == constm1_rtx)
90e7678c 1562 {
6bec29c9 1563 /* Immediate constants -1 to any register */
6bec29c9
DC
1564 *l = 2;
1565 return (AS1 (clr,%0) CR_TAB
1566 AS1 (dec,%0));
90e7678c 1567 }
afee2a52
MM
1568 else
1569 {
1570 int bit_nr = exact_log2 (INTVAL (src));
1571
1572 if (bit_nr >= 0)
1573 {
6001794d
KH
1574 *l = 3;
1575 if (!real_l)
1576 output_asm_insn ((AS1 (clr,%0) CR_TAB
1577 "set"), operands);
afee2a52
MM
1578 if (!real_l)
1579 avr_output_bld (operands, bit_nr);
1580
1581 return "";
1582 }
1583 }
90e7678c 1584 }
6bec29c9
DC
1585
1586 /* Last resort, larger than loading from memory. */
1587 *l = 4;
1588 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1589 AS2 (ldi,r31,lo8(%1)) CR_TAB
1590 AS2 (mov,%0,r31) CR_TAB
1591 AS2 (mov,r31,__tmp_reg__));
1592 }
1593 else if (GET_CODE (src) == MEM)
1594 return out_movqi_r_mr (insn, operands, real_l); /* mov r,m */
1595 }
1596 else if (GET_CODE (dest) == MEM)
1597 {
5fecfd8d
MM
1598 const char *template;
1599
1600 if (src == const0_rtx)
1601 operands[1] = zero_reg_rtx;
1602
6bec29c9
DC
1603 template = out_movqi_mr_r (insn, operands, real_l);
1604
1605 if (!real_l)
1606 output_asm_insn (template, operands);
5fecfd8d
MM
1607
1608 operands[1] = src;
6bec29c9
DC
1609 }
1610 return "";
1611}
1612
1613
5fecfd8d 1614const char *
269e3795 1615output_movhi (rtx insn, rtx operands[], int *l)
6bec29c9
DC
1616{
1617 int dummy;
1618 rtx dest = operands[0];
1619 rtx src = operands[1];
1620 int *real_l = l;
1621
1622 if (!l)
1623 l = &dummy;
1624
1625 if (register_operand (dest, HImode))
1626 {
1627 if (register_operand (src, HImode)) /* mov r,r */
1628 {
1629 if (test_hard_reg_class (STACK_REG, dest))
90e7678c 1630 {
6bec29c9
DC
1631 if (TARGET_TINY_STACK)
1632 {
1633 *l = 1;
1634 return AS2 (out,__SP_L__,%A1);
1635 }
1636 else if (TARGET_NO_INTERRUPTS)
1637 {
1638 *l = 2;
1639 return (AS2 (out,__SP_H__,%B1) CR_TAB
1640 AS2 (out,__SP_L__,%A1));
1641 }
1642
1643 *l = 5;
1644 return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB
1645 "cli" CR_TAB
1646 AS2 (out,__SP_H__,%B1) CR_TAB
1647 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
1648 AS2 (out,__SP_L__,%A1));
1649 }
1650 else if (test_hard_reg_class (STACK_REG, src))
1651 {
1652 *l = 2;
1653 return (AS2 (in,%A0,__SP_L__) CR_TAB
1654 AS2 (in,%B0,__SP_H__));
1655 }
1656
1657 if (AVR_ENHANCED)
1658 {
1659 *l = 1;
1660 return (AS2 (movw,%0,%1));
1661 }
1662
5fecfd8d 1663 if (true_regnum (dest) > true_regnum (src))
6bec29c9
DC
1664 {
1665 *l = 2;
1666 return (AS2 (mov,%B0,%B1) CR_TAB
1667 AS2 (mov,%A0,%A1));
1668 }
1669 else
1670 {
1671 *l = 2;
1672 return (AS2 (mov,%A0,%A1) CR_TAB
1673 AS2 (mov,%B0,%B1));
1674 }
1675 }
1676 else if (CONSTANT_P (src))
1677 {
1678 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
1679 {
1680 *l = 2;
1681 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
1682 AS2 (ldi,%B0,hi8(%1)));
1683 }
1684
1685 if (GET_CODE (src) == CONST_INT)
1686 {
1687 if (src == const0_rtx) /* mov r,L */
1688 {
1689 *l = 2;
1690 return (AS1 (clr,%A0) CR_TAB
1691 AS1 (clr,%B0));
1692 }
1693 else if (src == const1_rtx)
1694 {
08f81276
MM
1695 *l = 3;
1696 return (AS1 (clr,%A0) CR_TAB
1697 AS1 (clr,%B0) CR_TAB
1698 AS1 (inc,%A0));
6bec29c9 1699 }
6bec29c9
DC
1700 else if (src == constm1_rtx)
1701 {
1702 /* Immediate constants -1 to any register */
6bec29c9
DC
1703 *l = 3;
1704 return (AS1 (clr,%0) CR_TAB
1705 AS1 (dec,%A0) CR_TAB
1706 AS2 (mov,%B0,%A0));
1707 }
afee2a52
MM
1708 else
1709 {
1710 int bit_nr = exact_log2 (INTVAL (src));
1711
1712 if (bit_nr >= 0)
1713 {
6001794d
KH
1714 *l = 4;
1715 if (!real_l)
1716 output_asm_insn ((AS1 (clr,%A0) CR_TAB
1717 AS1 (clr,%B0) CR_TAB
1718 "set"), operands);
afee2a52
MM
1719 if (!real_l)
1720 avr_output_bld (operands, bit_nr);
1721
1722 return "";
1723 }
1724 }
1725
6bec29c9
DC
1726 if ((INTVAL (src) & 0xff) == 0)
1727 {
1728 *l = 5;
1729 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1730 AS1 (clr,%A0) CR_TAB
1731 AS2 (ldi,r31,hi8(%1)) CR_TAB
1732 AS2 (mov,%B0,r31) CR_TAB
1733 AS2 (mov,r31,__tmp_reg__));
1734 }
1735 else if ((INTVAL (src) & 0xff00) == 0)
1736 {
1737 *l = 5;
1738 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1739 AS2 (ldi,r31,lo8(%1)) CR_TAB
1740 AS2 (mov,%A0,r31) CR_TAB
1741 AS1 (clr,%B0) CR_TAB
1742 AS2 (mov,r31,__tmp_reg__));
90e7678c 1743 }
90e7678c 1744 }
6bec29c9
DC
1745
1746 /* Last resort, equal to loading from memory. */
1747 *l = 6;
1748 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
1749 AS2 (ldi,r31,lo8(%1)) CR_TAB
1750 AS2 (mov,%A0,r31) CR_TAB
1751 AS2 (ldi,r31,hi8(%1)) CR_TAB
1752 AS2 (mov,%B0,r31) CR_TAB
1753 AS2 (mov,r31,__tmp_reg__));
1754 }
1755 else if (GET_CODE (src) == MEM)
1756 return out_movhi_r_mr (insn, operands, real_l); /* mov r,m */
1757 }
1758 else if (GET_CODE (dest) == MEM)
1759 {
5fecfd8d
MM
1760 const char *template;
1761
1762 if (src == const0_rtx)
1763 operands[1] = zero_reg_rtx;
1764
6bec29c9
DC
1765 template = out_movhi_mr_r (insn, operands, real_l);
1766
1767 if (!real_l)
1768 output_asm_insn (template, operands);
5fecfd8d
MM
1769
1770 operands[1] = src;
6bec29c9 1771 return "";
90e7678c 1772 }
c725bd79 1773 fatal_insn ("invalid insn:", insn);
6bec29c9
DC
1774 return "";
1775}
1776
5fecfd8d 1777const char *
269e3795 1778out_movqi_r_mr (rtx insn, rtx op[], int *l)
6bec29c9 1779{
5fecfd8d
MM
1780 rtx dest = op[0];
1781 rtx src = op[1];
1782 rtx x = XEXP (src, 0);
6bec29c9
DC
1783 int dummy;
1784
1785 if (!l)
1786 l = &dummy;
6bec29c9
DC
1787
1788 if (CONSTANT_ADDRESS_P (x))
1789 {
1a499b92 1790 if (avr_io_address_p (x, 1))
6bec29c9
DC
1791 {
1792 *l = 1;
1793 return AS2 (in,%0,%1-0x20);
1794 }
1795 *l = 2;
1796 return AS2 (lds,%0,%1);
1797 }
1798 /* memory access by reg+disp */
1799 else if (GET_CODE (x) == PLUS
1800 && REG_P (XEXP (x,0))
1801 && GET_CODE (XEXP (x,1)) == CONST_INT)
1802 {
5fecfd8d 1803 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (src))) >= 63)
6bec29c9
DC
1804 {
1805 int disp = INTVAL (XEXP (x,1));
1806 if (REGNO (XEXP (x,0)) != REG_Y)
c725bd79 1807 fatal_insn ("incorrect insn:",insn);
33d5e2dc 1808
5fecfd8d 1809 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
33d5e2dc
MM
1810 return *l = 3, (AS2 (adiw,r28,%o1-63) CR_TAB
1811 AS2 (ldd,%0,Y+63) CR_TAB
1812 AS2 (sbiw,r28,%o1-63));
1813
1814 return *l = 5, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1815 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1816 AS2 (ld,%0,Y) CR_TAB
1817 AS2 (subi,r28,lo8(%o1)) CR_TAB
1818 AS2 (sbci,r29,hi8(%o1)));
6bec29c9
DC
1819 }
1820 else if (REGNO (XEXP (x,0)) == REG_X)
1821 {
6bec29c9
DC
1822 /* This is a paranoid case LEGITIMIZE_RELOAD_ADDRESS must exclude
1823 it but I have this situation with extremal optimizing options. */
5fecfd8d 1824 if (reg_overlap_mentioned_p (dest, XEXP (x,0))
6bec29c9 1825 || reg_unused_after (insn, XEXP (x,0)))
33d5e2dc
MM
1826 return *l = 2, (AS2 (adiw,r26,%o1) CR_TAB
1827 AS2 (ld,%0,X));
1828
1829 return *l = 3, (AS2 (adiw,r26,%o1) CR_TAB
1830 AS2 (ld,%0,X) CR_TAB
1831 AS2 (sbiw,r26,%o1));
6bec29c9
DC
1832 }
1833 *l = 1;
1834 return AS2 (ldd,%0,%1);
1835 }
1836 *l = 1;
1837 return AS2 (ld,%0,%1);
90e7678c
DC
1838}
1839
5fecfd8d 1840const char *
269e3795 1841out_movhi_r_mr (rtx insn, rtx op[], int *l)
90e7678c 1842{
5fecfd8d
MM
1843 rtx dest = op[0];
1844 rtx src = op[1];
1845 rtx base = XEXP (src, 0);
1846 int reg_dest = true_regnum (dest);
1847 int reg_base = true_regnum (base);
a6990185
MM
1848 /* "volatile" forces reading low byte first, even if less efficient,
1849 for correct operation with 16-bit I/O registers. */
1850 int mem_volatile_p = MEM_VOLATILE_P (src);
6bec29c9 1851 int tmp;
90e7678c
DC
1852
1853 if (!l)
6bec29c9 1854 l = &tmp;
90e7678c
DC
1855
1856 if (reg_base > 0)
1857 {
1858 if (reg_dest == reg_base) /* R = (R) */
6bec29c9
DC
1859 {
1860 *l = 3;
1861 return (AS2 (ld,__tmp_reg__,%1+) CR_TAB
1862 AS2 (ld,%B0,%1) CR_TAB
1863 AS2 (mov,%A0,__tmp_reg__));
1864 }
90e7678c
DC
1865 else if (reg_base == REG_X) /* (R26) */
1866 {
5fecfd8d 1867 if (reg_unused_after (insn, base))
6bec29c9
DC
1868 {
1869 *l = 2;
1870 return (AS2 (ld,%A0,X+) CR_TAB
1871 AS2 (ld,%B0,X));
1872 }
1873 *l = 3;
1874 return (AS2 (ld,%A0,X+) CR_TAB
1875 AS2 (ld,%B0,X) CR_TAB
1876 AS2 (sbiw,r26,1));
90e7678c
DC
1877 }
1878 else /* (R) */
6bec29c9
DC
1879 {
1880 *l = 2;
1881 return (AS2 (ld,%A0,%1) CR_TAB
1882 AS2 (ldd,%B0,%1+1));
1883 }
90e7678c 1884 }
5fecfd8d 1885 else if (GET_CODE (base) == PLUS) /* (R + i) */
90e7678c 1886 {
5fecfd8d
MM
1887 int disp = INTVAL (XEXP (base, 1));
1888 int reg_base = true_regnum (XEXP (base, 0));
90e7678c 1889
5fecfd8d 1890 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
90e7678c 1891 {
5fecfd8d 1892 if (REGNO (XEXP (base, 0)) != REG_Y)
c725bd79 1893 fatal_insn ("incorrect insn:",insn);
6bec29c9 1894
5fecfd8d 1895 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
33d5e2dc
MM
1896 return *l = 4, (AS2 (adiw,r28,%o1-62) CR_TAB
1897 AS2 (ldd,%A0,Y+62) CR_TAB
1898 AS2 (ldd,%B0,Y+63) CR_TAB
1899 AS2 (sbiw,r28,%o1-62));
1900
1901 return *l = 6, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
1902 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
1903 AS2 (ld,%A0,Y) CR_TAB
1904 AS2 (ldd,%B0,Y+1) CR_TAB
1905 AS2 (subi,r28,lo8(%o1)) CR_TAB
1906 AS2 (sbci,r29,hi8(%o1)));
90e7678c
DC
1907 }
1908 if (reg_base == REG_X)
1909 {
1910 /* This is a paranoid case. LEGITIMIZE_RELOAD_ADDRESS must exclude
6bec29c9
DC
1911 it but I have this situation with extremal
1912 optimization options. */
1913
33d5e2dc 1914 *l = 4;
6bec29c9 1915 if (reg_base == reg_dest)
33d5e2dc
MM
1916 return (AS2 (adiw,r26,%o1) CR_TAB
1917 AS2 (ld,__tmp_reg__,X+) CR_TAB
1918 AS2 (ld,%B0,X) CR_TAB
1919 AS2 (mov,%A0,__tmp_reg__));
6bec29c9 1920
33d5e2dc
MM
1921 return (AS2 (adiw,r26,%o1) CR_TAB
1922 AS2 (ld,%A0,X+) CR_TAB
1923 AS2 (ld,%B0,X) CR_TAB
1924 AS2 (sbiw,r26,%o1+1));
6bec29c9
DC
1925 }
1926
1927 if (reg_base == reg_dest)
1928 {
1929 *l = 3;
1930 return (AS2 (ldd,__tmp_reg__,%A1) CR_TAB
1931 AS2 (ldd,%B0,%B1) CR_TAB
1932 AS2 (mov,%A0,__tmp_reg__));
90e7678c
DC
1933 }
1934
6bec29c9
DC
1935 *l = 2;
1936 return (AS2 (ldd,%A0,%A1) CR_TAB
1937 AS2 (ldd,%B0,%B1));
90e7678c 1938 }
5fecfd8d 1939 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
90e7678c 1940 {
5fecfd8d 1941 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
c725bd79 1942 fatal_insn ("incorrect insn:", insn);
6bec29c9 1943
a6990185
MM
1944 if (mem_volatile_p)
1945 {
1946 if (REGNO (XEXP (base, 0)) == REG_X)
1947 {
1948 *l = 4;
1949 return (AS2 (sbiw,r26,2) CR_TAB
1950 AS2 (ld,%A0,X+) CR_TAB
1951 AS2 (ld,%B0,X) CR_TAB
1952 AS2 (sbiw,r26,1));
1953 }
1954 else
1955 {
1956 *l = 3;
1957 return (AS2 (sbiw,%r1,2) CR_TAB
1958 AS2 (ld,%A0,%p1) CR_TAB
1959 AS2 (ldd,%B0,%p1+1));
1960 }
1961 }
1962
6bec29c9
DC
1963 *l = 2;
1964 return (AS2 (ld,%B0,%1) CR_TAB
1965 AS2 (ld,%A0,%1));
90e7678c 1966 }
5fecfd8d 1967 else if (GET_CODE (base) == POST_INC) /* (R++) */
90e7678c 1968 {
5fecfd8d 1969 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
c725bd79 1970 fatal_insn ("incorrect insn:", insn);
6bec29c9
DC
1971
1972 *l = 2;
1973 return (AS2 (ld,%A0,%1) CR_TAB
1974 AS2 (ld,%B0,%1));
90e7678c 1975 }
5fecfd8d 1976 else if (CONSTANT_ADDRESS_P (base))
6bec29c9 1977 {
1a499b92 1978 if (avr_io_address_p (base, 2))
5fecfd8d
MM
1979 {
1980 *l = 2;
1981 return (AS2 (in,%A0,%A1-0x20) CR_TAB
1982 AS2 (in,%B0,%B1-0x20));
1983 }
6bec29c9
DC
1984 *l = 4;
1985 return (AS2 (lds,%A0,%A1) CR_TAB
1986 AS2 (lds,%B0,%B1));
1987 }
1988
c725bd79 1989 fatal_insn ("unknown move insn:",insn);
90e7678c
DC
1990 return "";
1991}
1992
5fecfd8d 1993const char *
269e3795 1994out_movsi_r_mr (rtx insn, rtx op[], int *l)
90e7678c 1995{
5fecfd8d
MM
1996 rtx dest = op[0];
1997 rtx src = op[1];
1998 rtx base = XEXP (src, 0);
1999 int reg_dest = true_regnum (dest);
2000 int reg_base = true_regnum (base);
90e7678c 2001 int tmp;
6bec29c9 2002
90e7678c 2003 if (!l)
6bec29c9
DC
2004 l = &tmp;
2005
90e7678c
DC
2006 if (reg_base > 0)
2007 {
2008 if (reg_base == REG_X) /* (R26) */
2009 {
2010 if (reg_dest == REG_X)
dfaf5abf
MM
2011 /* "ld r26,-X" is undefined */
2012 return *l=7, (AS2 (adiw,r26,3) CR_TAB
2013 AS2 (ld,r29,X) CR_TAB
2014 AS2 (ld,r28,-X) CR_TAB
2015 AS2 (ld,__tmp_reg__,-X) CR_TAB
2016 AS2 (sbiw,r26,1) CR_TAB
2017 AS2 (ld,r26,X) CR_TAB
2018 AS2 (mov,r27,__tmp_reg__));
90e7678c
DC
2019 else if (reg_dest == REG_X - 2)
2020 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2021 AS2 (ld,%B0,X+) CR_TAB
2022 AS2 (ld,__tmp_reg__,X+) CR_TAB
2023 AS2 (ld,%D0,X) CR_TAB
2024 AS2 (mov,%C0,__tmp_reg__));
5fecfd8d 2025 else if (reg_unused_after (insn, base))
90e7678c
DC
2026 return *l=4, (AS2 (ld,%A0,X+) CR_TAB
2027 AS2 (ld,%B0,X+) CR_TAB
2028 AS2 (ld,%C0,X+) CR_TAB
2029 AS2 (ld,%D0,X));
2030 else
2031 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
2032 AS2 (ld,%B0,X+) CR_TAB
2033 AS2 (ld,%C0,X+) CR_TAB
2034 AS2 (ld,%D0,X) CR_TAB
2035 AS2 (sbiw,r26,3));
2036 }
2037 else
2038 {
2039 if (reg_dest == reg_base)
2040 return *l=5, (AS2 (ldd,%D0,%1+3) CR_TAB
2041 AS2 (ldd,%C0,%1+2) CR_TAB
2042 AS2 (ldd,__tmp_reg__,%1+1) CR_TAB
2043 AS2 (ld,%A0,%1) CR_TAB
2044 AS2 (mov,%B0,__tmp_reg__));
2045 else if (reg_base == reg_dest + 2)
2046 return *l=5, (AS2 (ld ,%A0,%1) CR_TAB
2047 AS2 (ldd,%B0,%1+1) CR_TAB
2048 AS2 (ldd,__tmp_reg__,%1+2) CR_TAB
2049 AS2 (ldd,%D0,%1+3) CR_TAB
2050 AS2 (mov,%C0,__tmp_reg__));
2051 else
2052 return *l=4, (AS2 (ld ,%A0,%1) CR_TAB
2053 AS2 (ldd,%B0,%1+1) CR_TAB
2054 AS2 (ldd,%C0,%1+2) CR_TAB
2055 AS2 (ldd,%D0,%1+3));
2056 }
2057 }
5fecfd8d 2058 else if (GET_CODE (base) == PLUS) /* (R + i) */
90e7678c 2059 {
5fecfd8d 2060 int disp = INTVAL (XEXP (base, 1));
90e7678c 2061
5fecfd8d 2062 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
90e7678c 2063 {
5fecfd8d 2064 if (REGNO (XEXP (base, 0)) != REG_Y)
c725bd79 2065 fatal_insn ("incorrect insn:",insn);
33d5e2dc 2066
5fecfd8d 2067 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
33d5e2dc
MM
2068 return *l = 6, (AS2 (adiw,r28,%o1-60) CR_TAB
2069 AS2 (ldd,%A0,Y+60) CR_TAB
2070 AS2 (ldd,%B0,Y+61) CR_TAB
2071 AS2 (ldd,%C0,Y+62) CR_TAB
2072 AS2 (ldd,%D0,Y+63) CR_TAB
2073 AS2 (sbiw,r28,%o1-60));
2074
2075 return *l = 8, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
2076 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
2077 AS2 (ld,%A0,Y) CR_TAB
2078 AS2 (ldd,%B0,Y+1) CR_TAB
2079 AS2 (ldd,%C0,Y+2) CR_TAB
2080 AS2 (ldd,%D0,Y+3) CR_TAB
2081 AS2 (subi,r28,lo8(%o1)) CR_TAB
2082 AS2 (sbci,r29,hi8(%o1)));
90e7678c
DC
2083 }
2084
5fecfd8d 2085 reg_base = true_regnum (XEXP (base, 0));
dfaf5abf
MM
2086 if (reg_base == REG_X)
2087 {
2088 /* R = (X + d) */
2089 if (reg_dest == REG_X)
2090 {
2091 *l = 7;
2092 /* "ld r26,-X" is undefined */
2093 return (AS2 (adiw,r26,%o1+3) CR_TAB
2094 AS2 (ld,r29,X) CR_TAB
2095 AS2 (ld,r28,-X) CR_TAB
2096 AS2 (ld,__tmp_reg__,-X) CR_TAB
2097 AS2 (sbiw,r26,1) CR_TAB
2098 AS2 (ld,r26,X) CR_TAB
2099 AS2 (mov,r27,__tmp_reg__));
2100 }
2101 *l = 6;
2102 if (reg_dest == REG_X - 2)
2103 return (AS2 (adiw,r26,%o1) CR_TAB
2104 AS2 (ld,r24,X+) CR_TAB
2105 AS2 (ld,r25,X+) CR_TAB
2106 AS2 (ld,__tmp_reg__,X+) CR_TAB
2107 AS2 (ld,r27,X) CR_TAB
2108 AS2 (mov,r26,__tmp_reg__));
2109
2110 return (AS2 (adiw,r26,%o1) CR_TAB
2111 AS2 (ld,%A0,X+) CR_TAB
2112 AS2 (ld,%B0,X+) CR_TAB
2113 AS2 (ld,%C0,X+) CR_TAB
2114 AS2 (ld,%D0,X) CR_TAB
2115 AS2 (sbiw,r26,%o1+3));
2116 }
90e7678c
DC
2117 if (reg_dest == reg_base)
2118 return *l=5, (AS2 (ldd,%D0,%D1) CR_TAB
2119 AS2 (ldd,%C0,%C1) CR_TAB
2120 AS2 (ldd,__tmp_reg__,%B1) CR_TAB
2121 AS2 (ldd,%A0,%A1) CR_TAB
2122 AS2 (mov,%B0,__tmp_reg__));
2123 else if (reg_dest == reg_base - 2)
2124 return *l=5, (AS2 (ldd,%A0,%A1) CR_TAB
2125 AS2 (ldd,%B0,%B1) CR_TAB
2126 AS2 (ldd,__tmp_reg__,%C1) CR_TAB
2127 AS2 (ldd,%D0,%D1) CR_TAB
2128 AS2 (mov,%C0,__tmp_reg__));
2129 return *l=4, (AS2 (ldd,%A0,%A1) CR_TAB
2130 AS2 (ldd,%B0,%B1) CR_TAB
2131 AS2 (ldd,%C0,%C1) CR_TAB
2132 AS2 (ldd,%D0,%D1));
2133 }
5fecfd8d 2134 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
90e7678c
DC
2135 return *l=4, (AS2 (ld,%D0,%1) CR_TAB
2136 AS2 (ld,%C0,%1) CR_TAB
2137 AS2 (ld,%B0,%1) CR_TAB
2138 AS2 (ld,%A0,%1));
5fecfd8d 2139 else if (GET_CODE (base) == POST_INC) /* (R++) */
90e7678c
DC
2140 return *l=4, (AS2 (ld,%A0,%1) CR_TAB
2141 AS2 (ld,%B0,%1) CR_TAB
2142 AS2 (ld,%C0,%1) CR_TAB
2143 AS2 (ld,%D0,%1));
5fecfd8d 2144 else if (CONSTANT_ADDRESS_P (base))
90e7678c
DC
2145 return *l=8, (AS2 (lds,%A0,%A1) CR_TAB
2146 AS2 (lds,%B0,%B1) CR_TAB
2147 AS2 (lds,%C0,%C1) CR_TAB
2148 AS2 (lds,%D0,%D1));
2149
c725bd79 2150 fatal_insn ("unknown move insn:",insn);
90e7678c
DC
2151 return "";
2152}
2153
5fecfd8d 2154const char *
269e3795 2155out_movsi_mr_r (rtx insn, rtx op[], int *l)
90e7678c 2156{
5fecfd8d
MM
2157 rtx dest = op[0];
2158 rtx src = op[1];
2159 rtx base = XEXP (dest, 0);
2160 int reg_base = true_regnum (base);
2161 int reg_src = true_regnum (src);
90e7678c 2162 int tmp;
6bec29c9 2163
90e7678c
DC
2164 if (!l)
2165 l = &tmp;
6bec29c9 2166
5fecfd8d 2167 if (CONSTANT_ADDRESS_P (base))
90e7678c
DC
2168 return *l=8,(AS2 (sts,%A0,%A1) CR_TAB
2169 AS2 (sts,%B0,%B1) CR_TAB
2170 AS2 (sts,%C0,%C1) CR_TAB
2171 AS2 (sts,%D0,%D1));
2172 if (reg_base > 0) /* (r) */
2173 {
2174 if (reg_base == REG_X) /* (R26) */
2175 {
5fecfd8d 2176 if (reg_src == REG_X)
90e7678c 2177 {
dfaf5abf 2178 /* "st X+,r26" is undefined */
5fecfd8d 2179 if (reg_unused_after (insn, base))
dfaf5abf
MM
2180 return *l=6, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2181 AS2 (st,X,r26) CR_TAB
2182 AS2 (adiw,r26,1) CR_TAB
2183 AS2 (st,X+,__tmp_reg__) CR_TAB
2184 AS2 (st,X+,r28) CR_TAB
2185 AS2 (st,X,r29));
90e7678c 2186 else
dfaf5abf
MM
2187 return *l=7, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2188 AS2 (st,X,r26) CR_TAB
2189 AS2 (adiw,r26,1) CR_TAB
2190 AS2 (st,X+,__tmp_reg__) CR_TAB
2191 AS2 (st,X+,r28) CR_TAB
2192 AS2 (st,X,r29) CR_TAB
2193 AS2 (sbiw,r26,3));
90e7678c 2194 }
5fecfd8d 2195 else if (reg_base == reg_src + 2)
90e7678c 2196 {
5fecfd8d 2197 if (reg_unused_after (insn, base))
90e7678c
DC
2198 return *l=7, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2199 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2200 AS2 (st,%0+,%A1) CR_TAB
2201 AS2 (st,%0+,%B1) CR_TAB
2202 AS2 (st,%0+,__zero_reg__) CR_TAB
2203 AS2 (st,%0,__tmp_reg__) CR_TAB
2204 AS1 (clr,__zero_reg__));
2205 else
2206 return *l=8, (AS2 (mov,__zero_reg__,%C1) CR_TAB
2207 AS2 (mov,__tmp_reg__,%D1) CR_TAB
2208 AS2 (st,%0+,%A1) CR_TAB
2209 AS2 (st,%0+,%B1) CR_TAB
2210 AS2 (st,%0+,__zero_reg__) CR_TAB
2211 AS2 (st,%0,__tmp_reg__) CR_TAB
2212 AS1 (clr,__zero_reg__) CR_TAB
2213 AS2 (sbiw,r26,3));
2214 }
2215 return *l=5, (AS2 (st,%0+,%A1) CR_TAB
2216 AS2 (st,%0+,%B1) CR_TAB
2217 AS2 (st,%0+,%C1) CR_TAB
2218 AS2 (st,%0,%D1) CR_TAB
2219 AS2 (sbiw,r26,3));
2220 }
2221 else
2222 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2223 AS2 (std,%0+1,%B1) CR_TAB
2224 AS2 (std,%0+2,%C1) CR_TAB
2225 AS2 (std,%0+3,%D1));
2226 }
5fecfd8d 2227 else if (GET_CODE (base) == PLUS) /* (R + i) */
90e7678c 2228 {
5fecfd8d 2229 int disp = INTVAL (XEXP (base, 1));
dfaf5abf 2230 reg_base = REGNO (XEXP (base, 0));
5fecfd8d 2231 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
90e7678c 2232 {
dfaf5abf 2233 if (reg_base != REG_Y)
c725bd79 2234 fatal_insn ("incorrect insn:",insn);
33d5e2dc 2235
5fecfd8d 2236 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
33d5e2dc
MM
2237 return *l = 6, (AS2 (adiw,r28,%o0-60) CR_TAB
2238 AS2 (std,Y+60,%A1) CR_TAB
2239 AS2 (std,Y+61,%B1) CR_TAB
2240 AS2 (std,Y+62,%C1) CR_TAB
2241 AS2 (std,Y+63,%D1) CR_TAB
2242 AS2 (sbiw,r28,%o0-60));
2243
2244 return *l = 8, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2245 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2246 AS2 (st,Y,%A1) CR_TAB
2247 AS2 (std,Y+1,%B1) CR_TAB
2248 AS2 (std,Y+2,%C1) CR_TAB
2249 AS2 (std,Y+3,%D1) CR_TAB
2250 AS2 (subi,r28,lo8(%o0)) CR_TAB
2251 AS2 (sbci,r29,hi8(%o0)));
90e7678c 2252 }
dfaf5abf
MM
2253 if (reg_base == REG_X)
2254 {
2255 /* (X + d) = R */
2256 if (reg_src == REG_X)
2257 {
2258 *l = 9;
2259 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2260 AS2 (mov,__zero_reg__,r27) CR_TAB
2261 AS2 (adiw,r26,%o0) CR_TAB
2262 AS2 (st,X+,__tmp_reg__) CR_TAB
2263 AS2 (st,X+,__zero_reg__) CR_TAB
2264 AS2 (st,X+,r28) CR_TAB
2265 AS2 (st,X,r29) CR_TAB
2266 AS1 (clr,__zero_reg__) CR_TAB
2267 AS2 (sbiw,r26,%o0+3));
2268 }
2269 else if (reg_src == REG_X - 2)
2270 {
2271 *l = 9;
2272 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2273 AS2 (mov,__zero_reg__,r27) CR_TAB
2274 AS2 (adiw,r26,%o0) CR_TAB
2275 AS2 (st,X+,r24) CR_TAB
2276 AS2 (st,X+,r25) CR_TAB
2277 AS2 (st,X+,__tmp_reg__) CR_TAB
2278 AS2 (st,X,__zero_reg__) CR_TAB
2279 AS1 (clr,__zero_reg__) CR_TAB
2280 AS2 (sbiw,r26,%o0+3));
2281 }
2282 *l = 6;
2283 return (AS2 (adiw,r26,%o0) CR_TAB
2284 AS2 (st,X+,%A1) CR_TAB
2285 AS2 (st,X+,%B1) CR_TAB
2286 AS2 (st,X+,%C1) CR_TAB
2287 AS2 (st,X,%D1) CR_TAB
2288 AS2 (sbiw,r26,%o0+3));
2289 }
90e7678c
DC
2290 return *l=4, (AS2 (std,%A0,%A1) CR_TAB
2291 AS2 (std,%B0,%B1) CR_TAB
2292 AS2 (std,%C0,%C1) CR_TAB
2293 AS2 (std,%D0,%D1));
2294 }
5fecfd8d 2295 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
90e7678c
DC
2296 return *l=4, (AS2 (st,%0,%D1) CR_TAB
2297 AS2 (st,%0,%C1) CR_TAB
2298 AS2 (st,%0,%B1) CR_TAB
2299 AS2 (st,%0,%A1));
5fecfd8d 2300 else if (GET_CODE (base) == POST_INC) /* (R++) */
90e7678c
DC
2301 return *l=4, (AS2 (st,%0,%A1) CR_TAB
2302 AS2 (st,%0,%B1) CR_TAB
2303 AS2 (st,%0,%C1) CR_TAB
2304 AS2 (st,%0,%D1));
c725bd79 2305 fatal_insn ("unknown move insn:",insn);
90e7678c
DC
2306 return "";
2307}
2308
5fecfd8d 2309const char *
269e3795 2310output_movsisf(rtx insn, rtx operands[], int *l)
90e7678c 2311{
6bec29c9
DC
2312 int dummy;
2313 rtx dest = operands[0];
2314 rtx src = operands[1];
2315 int *real_l = l;
2316
2317 if (!l)
2318 l = &dummy;
2319
2320 if (register_operand (dest, VOIDmode))
90e7678c 2321 {
6bec29c9 2322 if (register_operand (src, VOIDmode)) /* mov r,r */
c4984bad 2323 {
6bec29c9
DC
2324 if (true_regnum (dest) > true_regnum (src))
2325 {
2326 if (AVR_ENHANCED)
2327 {
2328 *l = 2;
2329 return (AS2 (movw,%C0,%C1) CR_TAB
2330 AS2 (movw,%A0,%A1));
2331 }
2332 *l = 4;
2333 return (AS2 (mov,%D0,%D1) CR_TAB
2334 AS2 (mov,%C0,%C1) CR_TAB
2335 AS2 (mov,%B0,%B1) CR_TAB
2336 AS2 (mov,%A0,%A1));
2337 }
c4984bad 2338 else
6bec29c9
DC
2339 {
2340 if (AVR_ENHANCED)
2341 {
2342 *l = 2;
2343 return (AS2 (movw,%A0,%A1) CR_TAB
2344 AS2 (movw,%C0,%C1));
2345 }
2346 *l = 4;
2347 return (AS2 (mov,%A0,%A1) CR_TAB
2348 AS2 (mov,%B0,%B1) CR_TAB
2349 AS2 (mov,%C0,%C1) CR_TAB
2350 AS2 (mov,%D0,%D1));
2351 }
c4984bad 2352 }
6bec29c9 2353 else if (CONSTANT_P (src))
c4984bad 2354 {
6bec29c9
DC
2355 if (test_hard_reg_class (LD_REGS, dest)) /* ldi d,i */
2356 {
2357 *l = 4;
2358 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
2359 AS2 (ldi,%B0,hi8(%1)) CR_TAB
2360 AS2 (ldi,%C0,hlo8(%1)) CR_TAB
2361 AS2 (ldi,%D0,hhi8(%1)));
2362 }
2363
2364 if (GET_CODE (src) == CONST_INT)
2365 {
83182544 2366 const char *const clr_op0 =
afee2a52
MM
2367 AVR_ENHANCED ? (AS1 (clr,%A0) CR_TAB
2368 AS1 (clr,%B0) CR_TAB
2369 AS2 (movw,%C0,%A0))
2370 : (AS1 (clr,%A0) CR_TAB
2371 AS1 (clr,%B0) CR_TAB
2372 AS1 (clr,%C0) CR_TAB
2373 AS1 (clr,%D0));
2374
6bec29c9
DC
2375 if (src == const0_rtx) /* mov r,L */
2376 {
afee2a52
MM
2377 *l = AVR_ENHANCED ? 3 : 4;
2378 return clr_op0;
6bec29c9
DC
2379 }
2380 else if (src == const1_rtx)
2381 {
afee2a52
MM
2382 if (!real_l)
2383 output_asm_insn (clr_op0, operands);
2384 *l = AVR_ENHANCED ? 4 : 5;
2385 return AS1 (inc,%A0);
6bec29c9
DC
2386 }
2387 else if (src == constm1_rtx)
2388 {
2389 /* Immediate constants -1 to any register */
6bec29c9
DC
2390 if (AVR_ENHANCED)
2391 {
2392 *l = 4;
2393 return (AS1 (clr,%A0) CR_TAB
2394 AS1 (dec,%A0) CR_TAB
2395 AS2 (mov,%B0,%A0) CR_TAB
2396 AS2 (movw,%C0,%A0));
2397 }
2398 *l = 5;
2399 return (AS1 (clr,%A0) CR_TAB
2400 AS1 (dec,%A0) CR_TAB
2401 AS2 (mov,%B0,%A0) CR_TAB
2402 AS2 (mov,%C0,%A0) CR_TAB
2403 AS2 (mov,%D0,%A0));
2404 }
afee2a52
MM
2405 else
2406 {
2407 int bit_nr = exact_log2 (INTVAL (src));
2408
2409 if (bit_nr >= 0)
2410 {
6001794d
KH
2411 *l = AVR_ENHANCED ? 5 : 6;
2412 if (!real_l)
afee2a52 2413 {
6001794d
KH
2414 output_asm_insn (clr_op0, operands);
2415 output_asm_insn ("set", operands);
afee2a52
MM
2416 }
2417 if (!real_l)
2418 avr_output_bld (operands, bit_nr);
2419
2420 return "";
2421 }
2422 }
6bec29c9
DC
2423 }
2424
2425 /* Last resort, better than loading from memory. */
2426 *l = 10;
2427 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
2428 AS2 (ldi,r31,lo8(%1)) CR_TAB
2429 AS2 (mov,%A0,r31) CR_TAB
2430 AS2 (ldi,r31,hi8(%1)) CR_TAB
2431 AS2 (mov,%B0,r31) CR_TAB
2432 AS2 (ldi,r31,hlo8(%1)) CR_TAB
2433 AS2 (mov,%C0,r31) CR_TAB
2434 AS2 (ldi,r31,hhi8(%1)) CR_TAB
2435 AS2 (mov,%D0,r31) CR_TAB
2436 AS2 (mov,r31,__tmp_reg__));
2437 }
2438 else if (GET_CODE (src) == MEM)
2439 return out_movsi_r_mr (insn, operands, real_l); /* mov r,m */
2440 }
2441 else if (GET_CODE (dest) == MEM)
2442 {
5fecfd8d
MM
2443 const char *template;
2444
2445 if (src == const0_rtx)
6bec29c9 2446 operands[1] = zero_reg_rtx;
5fecfd8d 2447
6bec29c9
DC
2448 template = out_movsi_mr_r (insn, operands, real_l);
2449
2450 if (!real_l)
2451 output_asm_insn (template, operands);
5fecfd8d
MM
2452
2453 operands[1] = src;
6bec29c9 2454 return "";
90e7678c 2455 }
c725bd79 2456 fatal_insn ("invalid insn:", insn);
90e7678c
DC
2457 return "";
2458}
2459
5fecfd8d 2460const char *
269e3795 2461out_movqi_mr_r (rtx insn, rtx op[], int *l)
90e7678c 2462{
5fecfd8d
MM
2463 rtx dest = op[0];
2464 rtx src = op[1];
2465 rtx x = XEXP (dest, 0);
6bec29c9 2466 int dummy;
90e7678c 2467
6bec29c9
DC
2468 if (!l)
2469 l = &dummy;
6bec29c9
DC
2470
2471 if (CONSTANT_ADDRESS_P (x))
90e7678c 2472 {
1a499b92 2473 if (avr_io_address_p (x, 1))
6bec29c9
DC
2474 {
2475 *l = 1;
2476 return AS2 (out,%0-0x20,%1);
2477 }
2478 *l = 2;
2479 return AS2 (sts,%0,%1);
2480 }
2481 /* memory access by reg+disp */
2482 else if (GET_CODE (x) == PLUS
2483 && REG_P (XEXP (x,0))
2484 && GET_CODE (XEXP (x,1)) == CONST_INT)
2485 {
5fecfd8d 2486 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (dest))) >= 63)
90e7678c 2487 {
6bec29c9
DC
2488 int disp = INTVAL (XEXP (x,1));
2489 if (REGNO (XEXP (x,0)) != REG_Y)
c725bd79 2490 fatal_insn ("incorrect insn:",insn);
33d5e2dc 2491
5fecfd8d 2492 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
33d5e2dc
MM
2493 return *l = 3, (AS2 (adiw,r28,%o0-63) CR_TAB
2494 AS2 (std,Y+63,%1) CR_TAB
2495 AS2 (sbiw,r28,%o0-63));
2496
2497 return *l = 5, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2498 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
2499 AS2 (st,Y,%1) CR_TAB
2500 AS2 (subi,r28,lo8(%o0)) CR_TAB
2501 AS2 (sbci,r29,hi8(%o0)));
6bec29c9
DC
2502 }
2503 else if (REGNO (XEXP (x,0)) == REG_X)
2504 {
5fecfd8d 2505 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
6bec29c9
DC
2506 {
2507 if (reg_unused_after (insn, XEXP (x,0)))
33d5e2dc
MM
2508 return *l = 3, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2509 AS2 (adiw,r26,%o0) CR_TAB
2510 AS2 (st,X,__tmp_reg__));
2511
2512 return *l = 4, (AS2 (mov,__tmp_reg__,%1) CR_TAB
2513 AS2 (adiw,r26,%o0) CR_TAB
2514 AS2 (st,X,__tmp_reg__) CR_TAB
2515 AS2 (sbiw,r26,%o0));
90e7678c 2516 }
6bec29c9 2517 else
90e7678c 2518 {
6bec29c9 2519 if (reg_unused_after (insn, XEXP (x,0)))
33d5e2dc
MM
2520 return *l = 2, (AS2 (adiw,r26,%o0) CR_TAB
2521 AS2 (st,X,%1));
2522
2523 return *l = 3, (AS2 (adiw,r26,%o0) CR_TAB
2524 AS2 (st,X,%1) CR_TAB
2525 AS2 (sbiw,r26,%o0));
90e7678c
DC
2526 }
2527 }
6bec29c9
DC
2528 *l = 1;
2529 return AS2 (std,%0,%1);
90e7678c 2530 }
6bec29c9
DC
2531 *l = 1;
2532 return AS2 (st,%0,%1);
90e7678c
DC
2533}
2534
5fecfd8d 2535const char *
269e3795 2536out_movhi_mr_r (rtx insn, rtx op[], int *l)
90e7678c 2537{
5fecfd8d
MM
2538 rtx dest = op[0];
2539 rtx src = op[1];
2540 rtx base = XEXP (dest, 0);
2541 int reg_base = true_regnum (base);
2542 int reg_src = true_regnum (src);
a6990185
MM
2543 /* "volatile" forces writing high byte first, even if less efficient,
2544 for correct operation with 16-bit I/O registers. */
2545 int mem_volatile_p = MEM_VOLATILE_P (dest);
90e7678c 2546 int tmp;
a6990185 2547
90e7678c
DC
2548 if (!l)
2549 l = &tmp;
5fecfd8d
MM
2550 if (CONSTANT_ADDRESS_P (base))
2551 {
1a499b92 2552 if (avr_io_address_p (base, 2))
5fecfd8d
MM
2553 {
2554 *l = 2;
2555 return (AS2 (out,%B0-0x20,%B1) CR_TAB
2556 AS2 (out,%A0-0x20,%A1));
2557 }
2558 return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB
2559 AS2 (sts,%A0,%A1));
2560 }
90e7678c
DC
2561 if (reg_base > 0)
2562 {
2563 if (reg_base == REG_X)
2564 {
5fecfd8d 2565 if (reg_src == REG_X)
90e7678c 2566 {
a6990185
MM
2567 /* "st X+,r26" and "st -X,r26" are undefined. */
2568 if (!mem_volatile_p && reg_unused_after (insn, src))
dfaf5abf
MM
2569 return *l=4, (AS2 (mov,__tmp_reg__,r27) CR_TAB
2570 AS2 (st,X,r26) CR_TAB
2571 AS2 (adiw,r26,1) CR_TAB
2572 AS2 (st,X,__tmp_reg__));
90e7678c 2573 else
dfaf5abf 2574 return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
dfaf5abf
MM
2575 AS2 (adiw,r26,1) CR_TAB
2576 AS2 (st,X,__tmp_reg__) CR_TAB
a6990185
MM
2577 AS2 (sbiw,r26,1) CR_TAB
2578 AS2 (st,X,r26));
90e7678c
DC
2579 }
2580 else
2581 {
a6990185 2582 if (!mem_volatile_p && reg_unused_after (insn, base))
90e7678c
DC
2583 return *l=2, (AS2 (st,X+,%A1) CR_TAB
2584 AS2 (st,X,%B1));
2585 else
a6990185
MM
2586 return *l=3, (AS2 (adiw,r26,1) CR_TAB
2587 AS2 (st,X,%B1) CR_TAB
2588 AS2 (st,-X,%A1));
90e7678c
DC
2589 }
2590 }
2591 else
a6990185
MM
2592 return *l=2, (AS2 (std,%0+1,%B1) CR_TAB
2593 AS2 (st,%0,%A1));
90e7678c 2594 }
5fecfd8d 2595 else if (GET_CODE (base) == PLUS)
90e7678c 2596 {
5fecfd8d 2597 int disp = INTVAL (XEXP (base, 1));
dfaf5abf 2598 reg_base = REGNO (XEXP (base, 0));
5fecfd8d 2599 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
90e7678c 2600 {
dfaf5abf 2601 if (reg_base != REG_Y)
c725bd79 2602 fatal_insn ("incorrect insn:",insn);
33d5e2dc 2603
5fecfd8d 2604 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
33d5e2dc 2605 return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
33d5e2dc 2606 AS2 (std,Y+63,%B1) CR_TAB
a6990185 2607 AS2 (std,Y+62,%A1) CR_TAB
33d5e2dc
MM
2608 AS2 (sbiw,r28,%o0-62));
2609
2610 return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
2611 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
33d5e2dc 2612 AS2 (std,Y+1,%B1) CR_TAB
a6990185 2613 AS2 (st,Y,%A1) CR_TAB
33d5e2dc
MM
2614 AS2 (subi,r28,lo8(%o0)) CR_TAB
2615 AS2 (sbci,r29,hi8(%o0)));
90e7678c 2616 }
dfaf5abf
MM
2617 if (reg_base == REG_X)
2618 {
2619 /* (X + d) = R */
2620 if (reg_src == REG_X)
a6990185 2621 {
dfaf5abf
MM
2622 *l = 7;
2623 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
2624 AS2 (mov,__zero_reg__,r27) CR_TAB
a6990185 2625 AS2 (adiw,r26,%o0+1) CR_TAB
dfaf5abf 2626 AS2 (st,X,__zero_reg__) CR_TAB
a6990185 2627 AS2 (st,-X,__tmp_reg__) CR_TAB
dfaf5abf 2628 AS1 (clr,__zero_reg__) CR_TAB
a6990185 2629 AS2 (sbiw,r26,%o0));
dfaf5abf
MM
2630 }
2631 *l = 4;
a6990185
MM
2632 return (AS2 (adiw,r26,%o0+1) CR_TAB
2633 AS2 (st,X,%B1) CR_TAB
2634 AS2 (st,-X,%A1) CR_TAB
2635 AS2 (sbiw,r26,%o0));
dfaf5abf 2636 }
a6990185
MM
2637 return *l=2, (AS2 (std,%B0,%B1) CR_TAB
2638 AS2 (std,%A0,%A1));
6bec29c9 2639 }
5fecfd8d 2640 else if (GET_CODE (base) == PRE_DEC) /* (--R) */
90e7678c
DC
2641 return *l=2, (AS2 (st,%0,%B1) CR_TAB
2642 AS2 (st,%0,%A1));
5fecfd8d 2643 else if (GET_CODE (base) == POST_INC) /* (R++) */
a6990185
MM
2644 {
2645 if (mem_volatile_p)
2646 {
2647 if (REGNO (XEXP (base, 0)) == REG_X)
2648 {
2649 *l = 4;
2650 return (AS2 (adiw,r26,1) CR_TAB
2651 AS2 (st,X,%B1) CR_TAB
2652 AS2 (st,-X,%A1) CR_TAB
2653 AS2 (adiw,r26,2));
2654 }
2655 else
2656 {
2657 *l = 3;
2658 return (AS2 (std,%p0+1,%B1) CR_TAB
2659 AS2 (st,%p0,%A1) CR_TAB
2660 AS2 (adiw,%r0,2));
2661 }
2662 }
2663
2664 *l = 2;
2665 return (AS2 (st,%0,%A1) CR_TAB
2666 AS2 (st,%0,%B1));
2667 }
c725bd79 2668 fatal_insn ("unknown move insn:",insn);
90e7678c
DC
2669 return "";
2670}
2671
2c338472 2672/* Return 1 if frame pointer for current function required. */
90e7678c
DC
2673
2674int
269e3795 2675frame_pointer_required_p (void)
90e7678c
DC
2676{
2677 return (current_function_calls_alloca
2678 || current_function_args_info.nregs == 0
90e7678c
DC
2679 || get_frame_size () > 0);
2680}
2681
89741abb 2682/* Returns the condition of compare insn INSN, or UNKNOWN. */
90e7678c 2683
89741abb 2684static RTX_CODE
269e3795 2685compare_condition (rtx insn)
90e7678c
DC
2686{
2687 rtx next = next_real_insn (insn);
2688 RTX_CODE cond = UNKNOWN;
89741abb 2689 if (next && GET_CODE (next) == JUMP_INSN)
90e7678c
DC
2690 {
2691 rtx pat = PATTERN (next);
2692 rtx src = SET_SRC (pat);
89741abb 2693 rtx t = XEXP (src, 0);
90e7678c
DC
2694 cond = GET_CODE (t);
2695 }
89741abb
MM
2696 return cond;
2697}
2698
2699/* Returns nonzero if INSN is a tst insn that only tests the sign. */
2700
2701static int
269e3795 2702compare_sign_p (rtx insn)
89741abb
MM
2703{
2704 RTX_CODE cond = compare_condition (insn);
2705 return (cond == GE || cond == LT);
2706}
2707
2708/* Returns nonzero if the next insn is a JUMP_INSN with a condition
2709 that needs to be swapped (GT, GTU, LE, LEU). */
2710
2711int
269e3795 2712compare_diff_p (rtx insn)
89741abb
MM
2713{
2714 RTX_CODE cond = compare_condition (insn);
90e7678c
DC
2715 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
2716}
2717
89741abb 2718/* Returns nonzero if INSN is a compare insn with the EQ or NE condition. */
90e7678c
DC
2719
2720int
269e3795 2721compare_eq_p (rtx insn)
90e7678c 2722{
89741abb 2723 RTX_CODE cond = compare_condition (insn);
90e7678c
DC
2724 return (cond == EQ || cond == NE);
2725}
2726
2727
2c338472 2728/* Output test instruction for HImode. */
90e7678c 2729
5fecfd8d 2730const char *
269e3795 2731out_tsthi (rtx insn, int *l)
90e7678c 2732{
89741abb 2733 if (compare_sign_p (insn))
90e7678c
DC
2734 {
2735 if (l) *l = 1;
2736 return AS1 (tst,%B0);
2737 }
89741abb
MM
2738 if (reg_unused_after (insn, SET_SRC (PATTERN (insn)))
2739 && compare_eq_p (insn))
90e7678c 2740 {
2c338472 2741 /* Faster than sbiw if we can clobber the operand. */
90e7678c 2742 if (l) *l = 1;
5fecfd8d 2743 return AS2 (or,%A0,%B0);
90e7678c 2744 }
5fecfd8d 2745 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
90e7678c
DC
2746 {
2747 if (l) *l = 1;
5fecfd8d 2748 return AS2 (sbiw,%0,0);
90e7678c
DC
2749 }
2750 if (l) *l = 2;
2751 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2752 AS2 (cpc,%B0,__zero_reg__));
2753}
2754
2755
2c338472 2756/* Output test instruction for SImode. */
90e7678c 2757
5fecfd8d 2758const char *
269e3795 2759out_tstsi (rtx insn, int *l)
90e7678c 2760{
89741abb 2761 if (compare_sign_p (insn))
90e7678c
DC
2762 {
2763 if (l) *l = 1;
2764 return AS1 (tst,%D0);
2765 }
c4984bad 2766 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
90e7678c
DC
2767 {
2768 if (l) *l = 3;
2769 return (AS2 (sbiw,%A0,0) CR_TAB
2770 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2771 AS2 (cpc,%D0,__zero_reg__));
2772 }
2773 if (l) *l = 4;
2774 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
2775 AS2 (cpc,%B0,__zero_reg__) CR_TAB
2776 AS2 (cpc,%C0,__zero_reg__) CR_TAB
2777 AS2 (cpc,%D0,__zero_reg__));
2778}
2779
2780
afee2a52
MM
2781/* Generate asm equivalent for various shifts.
2782 Shift count is a CONST_INT, MEM or REG.
2783 This only handles cases that are not already
2784 carefully hand-optimized in ?sh??i3_out. */
90e7678c
DC
2785
2786void
269e3795
SB
2787out_shift_with_cnt (const char *template, rtx insn, rtx operands[],
2788 int *len, int t_len)
90e7678c
DC
2789{
2790 rtx op[10];
afee2a52 2791 char str[500];
0db7ad3a 2792 int second_label = 1;
afee2a52
MM
2793 int saved_in_tmp = 0;
2794 int use_zero_reg = 0;
2795
90e7678c
DC
2796 op[0] = operands[0];
2797 op[1] = operands[1];
2798 op[2] = operands[2];
2799 op[3] = operands[3];
2800 str[0] = 0;
afee2a52
MM
2801
2802 if (len)
2803 *len = 1;
2804
2805 if (GET_CODE (operands[2]) == CONST_INT)
90e7678c 2806 {
afee2a52
MM
2807 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
2808 int count = INTVAL (operands[2]);
2809 int max_len = 10; /* If larger than this, always use a loop. */
2810
a3cf5992
MM
2811 if (count <= 0)
2812 {
2813 if (len)
2814 *len = 0;
2815 return;
2816 }
2817
afee2a52
MM
2818 if (count < 8 && !scratch)
2819 use_zero_reg = 1;
2820
2821 if (optimize_size)
2822 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
2823
2824 if (t_len * count <= max_len)
2825 {
2826 /* Output shifts inline with no loop - faster. */
2827 if (len)
2828 *len = t_len * count;
2829 else
2830 {
2831 while (count-- > 0)
2832 output_asm_insn (template, op);
2833 }
2834
2835 return;
2836 }
2837
2838 if (scratch)
2839 {
2840 if (!len)
2841 strcat (str, AS2 (ldi,%3,%2));
2842 }
2843 else if (use_zero_reg)
2844 {
2845 /* Hack to save one word: use __zero_reg__ as loop counter.
2846 Set one bit, then shift in a loop until it is 0 again. */
2847
2848 op[3] = zero_reg_rtx;
2849 if (len)
2850 *len = 2;
2851 else
2852 strcat (str, ("set" CR_TAB
2853 AS2 (bld,%3,%2-1)));
2854 }
90e7678c 2855 else
afee2a52
MM
2856 {
2857 /* No scratch register available, use one from LD_REGS (saved in
2858 __tmp_reg__) that doesn't overlap with registers to shift. */
2859
f1c25d3b 2860 op[3] = gen_rtx_REG (QImode,
afee2a52
MM
2861 ((true_regnum (operands[0]) - 1) & 15) + 16);
2862 op[4] = tmp_reg_rtx;
2863 saved_in_tmp = 1;
2864
2865 if (len)
2866 *len = 3; /* Includes "mov %3,%4" after the loop. */
2867 else
2868 strcat (str, (AS2 (mov,%4,%3) CR_TAB
2869 AS2 (ldi,%3,%2)));
2870 }
2871
0db7ad3a 2872 second_label = 0;
90e7678c
DC
2873 }
2874 else if (GET_CODE (operands[2]) == MEM)
2875 {
90e7678c 2876 rtx op_mov[10];
0db7ad3a 2877
90e7678c
DC
2878 op[3] = op_mov[0] = tmp_reg_rtx;
2879 op_mov[1] = op[2];
afee2a52
MM
2880
2881 if (len)
2882 out_movqi_r_mr (insn, op_mov, len);
90e7678c 2883 else
afee2a52 2884 output_asm_insn (out_movqi_r_mr (insn, op_mov, NULL), op_mov);
90e7678c 2885 }
c4984bad 2886 else if (register_operand (operands[2], QImode))
90e7678c 2887 {
90e7678c 2888 if (reg_unused_after (insn, operands[2]))
0db7ad3a 2889 op[3] = op[2];
90e7678c
DC
2890 else
2891 {
2892 op[3] = tmp_reg_rtx;
afee2a52
MM
2893 if (!len)
2894 strcat (str, (AS2 (mov,%3,%2) CR_TAB));
90e7678c 2895 }
afee2a52
MM
2896 }
2897 else
c725bd79 2898 fatal_insn ("bad shift insn:", insn);
afee2a52
MM
2899
2900 if (second_label)
2901 {
0db7ad3a
DC
2902 if (len)
2903 ++*len;
2904 else
2905 strcat (str, AS1 (rjmp,2f));
90e7678c 2906 }
afee2a52
MM
2907
2908 if (len)
2909 *len += t_len + 2; /* template + dec + brXX */
2910 else
90e7678c 2911 {
80b8585d 2912 strcat (str, "\n1:\t");
90e7678c 2913 strcat (str, template);
0db7ad3a 2914 strcat (str, second_label ? "\n2:\t" : "\n\t");
afee2a52
MM
2915 strcat (str, use_zero_reg ? AS1 (lsr,%3) : AS1 (dec,%3));
2916 strcat (str, CR_TAB);
2917 strcat (str, second_label ? AS1 (brpl,1b) : AS1 (brne,1b));
2918 if (saved_in_tmp)
2919 strcat (str, (CR_TAB AS2 (mov,%3,%4)));
90e7678c
DC
2920 output_asm_insn (str, op);
2921 }
2922}
2923
2924
2925/* 8bit shift left ((char)x << i) */
2926
5fecfd8d 2927const char *
269e3795 2928ashlqi3_out (rtx insn, rtx operands[], int *len)
90e7678c
DC
2929{
2930 if (GET_CODE (operands[2]) == CONST_INT)
2931 {
2932 int k;
3454eb73 2933
90e7678c
DC
2934 if (!len)
2935 len = &k;
3454eb73 2936
90e7678c
DC
2937 switch (INTVAL (operands[2]))
2938 {
3454eb73 2939 default:
a3cf5992
MM
2940 if (INTVAL (operands[2]) < 8)
2941 break;
2942
3454eb73
DC
2943 *len = 1;
2944 return AS1 (clr,%0);
2945
90e7678c 2946 case 1:
3454eb73 2947 *len = 1;
90e7678c 2948 return AS1 (lsl,%0);
3454eb73 2949
90e7678c 2950 case 2:
3454eb73 2951 *len = 2;
90e7678c
DC
2952 return (AS1 (lsl,%0) CR_TAB
2953 AS1 (lsl,%0));
3454eb73 2954
90e7678c 2955 case 3:
3454eb73 2956 *len = 3;
90e7678c
DC
2957 return (AS1 (lsl,%0) CR_TAB
2958 AS1 (lsl,%0) CR_TAB
2959 AS1 (lsl,%0));
3454eb73 2960
90e7678c 2961 case 4:
c4984bad 2962 if (test_hard_reg_class (LD_REGS, operands[0]))
90e7678c 2963 {
3454eb73 2964 *len = 2;
90e7678c
DC
2965 return (AS1 (swap,%0) CR_TAB
2966 AS2 (andi,%0,0xf0));
2967 }
3454eb73 2968 *len = 4;
90e7678c
DC
2969 return (AS1 (lsl,%0) CR_TAB
2970 AS1 (lsl,%0) CR_TAB
2971 AS1 (lsl,%0) CR_TAB
2972 AS1 (lsl,%0));
3454eb73 2973
90e7678c 2974 case 5:
c4984bad 2975 if (test_hard_reg_class (LD_REGS, operands[0]))
90e7678c 2976 {
3454eb73 2977 *len = 3;
90e7678c
DC
2978 return (AS1 (swap,%0) CR_TAB
2979 AS1 (lsl,%0) CR_TAB
2980 AS2 (andi,%0,0xe0));
2981 }
3454eb73 2982 *len = 5;
90e7678c
DC
2983 return (AS1 (lsl,%0) CR_TAB
2984 AS1 (lsl,%0) CR_TAB
2985 AS1 (lsl,%0) CR_TAB
2986 AS1 (lsl,%0) CR_TAB
2987 AS1 (lsl,%0));
3454eb73 2988
90e7678c 2989 case 6:
c4984bad 2990 if (test_hard_reg_class (LD_REGS, operands[0]))
90e7678c 2991 {
3454eb73 2992 *len = 4;
90e7678c
DC
2993 return (AS1 (swap,%0) CR_TAB
2994 AS1 (lsl,%0) CR_TAB
2995 AS1 (lsl,%0) CR_TAB
2996 AS2 (andi,%0,0xc0));
2997 }
3454eb73 2998 *len = 6;
90e7678c
DC
2999 return (AS1 (lsl,%0) CR_TAB
3000 AS1 (lsl,%0) CR_TAB
3001 AS1 (lsl,%0) CR_TAB
3002 AS1 (lsl,%0) CR_TAB
3003 AS1 (lsl,%0) CR_TAB
3004 AS1 (lsl,%0));
3454eb73 3005
90e7678c 3006 case 7:
3454eb73 3007 *len = 3;
90e7678c
DC
3008 return (AS1 (ror,%0) CR_TAB
3009 AS1 (clr,%0) CR_TAB
3010 AS1 (ror,%0));
3011 }
3012 }
3454eb73 3013 else if (CONSTANT_P (operands[2]))
c725bd79 3014 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3454eb73 3015
0db7ad3a 3016 out_shift_with_cnt (AS1 (lsl,%0),
afee2a52 3017 insn, operands, len, 1);
90e7678c
DC
3018 return "";
3019}
3020
3021
3022/* 16bit shift left ((short)x << i) */
3023
5fecfd8d 3024const char *
269e3795 3025ashlhi3_out (rtx insn, rtx operands[], int *len)
90e7678c
DC
3026{
3027 if (GET_CODE (operands[2]) == CONST_INT)
3028 {
afee2a52
MM
3029 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3030 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
90e7678c 3031 int k;
afee2a52 3032 int *t = len;
3454eb73 3033
90e7678c
DC
3034 if (!len)
3035 len = &k;
3454eb73 3036
90e7678c
DC
3037 switch (INTVAL (operands[2]))
3038 {
a3cf5992
MM
3039 default:
3040 if (INTVAL (operands[2]) < 16)
3041 break;
3042
3043 *len = 2;
3044 return (AS1 (clr,%B0) CR_TAB
3045 AS1 (clr,%A0));
3046
afee2a52
MM
3047 case 4:
3048 if (optimize_size && scratch)
3049 break; /* 5 */
3050 if (ldi_ok)
3051 {
3052 *len = 6;
3053 return (AS1 (swap,%A0) CR_TAB
3054 AS1 (swap,%B0) CR_TAB
3055 AS2 (andi,%B0,0xf0) CR_TAB
3056 AS2 (eor,%B0,%A0) CR_TAB
3057 AS2 (andi,%A0,0xf0) CR_TAB
3058 AS2 (eor,%B0,%A0));
3059 }
3060 if (scratch)
3061 {
3062 *len = 7;
3063 return (AS1 (swap,%A0) CR_TAB
3064 AS1 (swap,%B0) CR_TAB
3065 AS2 (ldi,%3,0xf0) CR_TAB
3066 AS2 (and,%B0,%3) CR_TAB
3067 AS2 (eor,%B0,%A0) CR_TAB
3068 AS2 (and,%A0,%3) CR_TAB
3069 AS2 (eor,%B0,%A0));
3070 }
3071 break; /* optimize_size ? 6 : 8 */
3454eb73 3072
afee2a52
MM
3073 case 5:
3074 if (optimize_size)
3075 break; /* scratch ? 5 : 6 */
3076 if (ldi_ok)
3077 {
3078 *len = 8;
3079 return (AS1 (lsl,%A0) CR_TAB
3080 AS1 (rol,%B0) CR_TAB
3081 AS1 (swap,%A0) CR_TAB
3082 AS1 (swap,%B0) CR_TAB
3083 AS2 (andi,%B0,0xf0) CR_TAB
3084 AS2 (eor,%B0,%A0) CR_TAB
3085 AS2 (andi,%A0,0xf0) CR_TAB
3086 AS2 (eor,%B0,%A0));
3087 }
3088 if (scratch)
3089 {
3090 *len = 9;
3091 return (AS1 (lsl,%A0) CR_TAB
3092 AS1 (rol,%B0) CR_TAB
3093 AS1 (swap,%A0) CR_TAB
3094 AS1 (swap,%B0) CR_TAB
3095 AS2 (ldi,%3,0xf0) CR_TAB
3096 AS2 (and,%B0,%3) CR_TAB
3097 AS2 (eor,%B0,%A0) CR_TAB
3098 AS2 (and,%A0,%3) CR_TAB
3099 AS2 (eor,%B0,%A0));
3100 }
3101 break; /* 10 */
3102
3103 case 6:
3104 if (optimize_size)
3105 break; /* scratch ? 5 : 6 */
3106 *len = 9;
3107 return (AS1 (clr,__tmp_reg__) CR_TAB
3108 AS1 (lsr,%B0) CR_TAB
3109 AS1 (ror,%A0) CR_TAB
3110 AS1 (ror,__tmp_reg__) CR_TAB
3111 AS1 (lsr,%B0) CR_TAB
3112 AS1 (ror,%A0) CR_TAB
3113 AS1 (ror,__tmp_reg__) CR_TAB
3114 AS2 (mov,%B0,%A0) CR_TAB
3115 AS2 (mov,%A0,__tmp_reg__));
3454eb73 3116
adcd8f77
MM
3117 case 7:
3118 *len = 5;
3119 return (AS1 (lsr,%B0) CR_TAB
3120 AS2 (mov,%B0,%A0) CR_TAB
3121 AS1 (clr,%A0) CR_TAB
3122 AS1 (ror,%B0) CR_TAB
3123 AS1 (ror,%A0));
3124
90e7678c
DC
3125 case 8:
3126 if (true_regnum (operands[0]) + 1 == true_regnum (operands[1]))
3127 return *len = 1, AS1 (clr,%A0);
3128 else
3129 return *len = 2, (AS2 (mov,%B0,%A1) CR_TAB
3130 AS1 (clr,%A0));
adcd8f77
MM
3131
3132 case 9:
3133 *len = 3;
3134 return (AS2 (mov,%B0,%A0) CR_TAB
3135 AS1 (clr,%A0) CR_TAB
3136 AS1 (lsl,%B0));
3137
3138 case 10:
3139 *len = 4;
3140 return (AS2 (mov,%B0,%A0) CR_TAB
3141 AS1 (clr,%A0) CR_TAB
3142 AS1 (lsl,%B0) CR_TAB
3143 AS1 (lsl,%B0));
3144
3145 case 11:
3146 *len = 5;
3147 return (AS2 (mov,%B0,%A0) CR_TAB
3148 AS1 (clr,%A0) CR_TAB
3149 AS1 (lsl,%B0) CR_TAB
3150 AS1 (lsl,%B0) CR_TAB
3151 AS1 (lsl,%B0));
3152
3153 case 12:
afee2a52 3154 if (ldi_ok)
adcd8f77
MM
3155 {
3156 *len = 4;
3157 return (AS2 (mov,%B0,%A0) CR_TAB
3158 AS1 (clr,%A0) CR_TAB
3159 AS1 (swap,%B0) CR_TAB
3160 AS2 (andi,%B0,0xf0));
3161 }
afee2a52
MM
3162 if (scratch)
3163 {
3164 *len = 5;
3165 return (AS2 (mov,%B0,%A0) CR_TAB
3166 AS1 (clr,%A0) CR_TAB
3167 AS1 (swap,%B0) CR_TAB
3168 AS2 (ldi,%3,0xf0) CR_TAB
3169 AS2 (and,%B0,%3));
3170 }
3171 *len = 6;
adcd8f77
MM
3172 return (AS2 (mov,%B0,%A0) CR_TAB
3173 AS1 (clr,%A0) CR_TAB
afee2a52
MM
3174 AS1 (lsl,%B0) CR_TAB
3175 AS1 (lsl,%B0) CR_TAB
3176 AS1 (lsl,%B0) CR_TAB
3177 AS1 (lsl,%B0));
adcd8f77
MM
3178
3179 case 13:
afee2a52 3180 if (ldi_ok)
adcd8f77
MM
3181 {
3182 *len = 5;
3183 return (AS2 (mov,%B0,%A0) CR_TAB
3184 AS1 (clr,%A0) CR_TAB
3185 AS1 (swap,%B0) CR_TAB
3186 AS1 (lsl,%B0) CR_TAB
3187 AS2 (andi,%B0,0xe0));
3188 }
afee2a52 3189 if (AVR_ENHANCED && scratch)
adcd8f77
MM
3190 {
3191 *len = 5;
3192 return (AS2 (ldi,%3,0x20) CR_TAB
3193 AS2 (mul,%A0,%3) CR_TAB
3194 AS2 (mov,%B0,r0) CR_TAB
3195 AS1 (clr,%A0) CR_TAB
3196 AS1 (clr,__zero_reg__));
3197 }
afee2a52
MM
3198 if (optimize_size && scratch)
3199 break; /* 5 */
3200 if (scratch)
3201 {
3202 *len = 6;
3203 return (AS2 (mov,%B0,%A0) CR_TAB
3204 AS1 (clr,%A0) CR_TAB
3205 AS1 (swap,%B0) CR_TAB
3206 AS1 (lsl,%B0) CR_TAB
3207 AS2 (ldi,%3,0xe0) CR_TAB
3208 AS2 (and,%B0,%3));
3209 }
3210 if (AVR_ENHANCED)
3211 {
3212 *len = 6;
3213 return ("set" CR_TAB
3214 AS2 (bld,r1,5) CR_TAB
3215 AS2 (mul,%A0,r1) CR_TAB
3216 AS2 (mov,%B0,r0) CR_TAB
3217 AS1 (clr,%A0) CR_TAB
3218 AS1 (clr,__zero_reg__));
3219 }
3220 *len = 7;
3221 return (AS2 (mov,%B0,%A0) CR_TAB
3222 AS1 (clr,%A0) CR_TAB
3223 AS1 (lsl,%B0) CR_TAB
3224 AS1 (lsl,%B0) CR_TAB
3225 AS1 (lsl,%B0) CR_TAB
3226 AS1 (lsl,%B0) CR_TAB
3227 AS1 (lsl,%B0));
adcd8f77
MM
3228
3229 case 14:
afee2a52
MM
3230 if (AVR_ENHANCED && ldi_ok)
3231 {
3232 *len = 5;
3233 return (AS2 (ldi,%B0,0x40) CR_TAB
3234 AS2 (mul,%A0,%B0) CR_TAB
3235 AS2 (mov,%B0,r0) CR_TAB
3236 AS1 (clr,%A0) CR_TAB
3237 AS1 (clr,__zero_reg__));
3238 }
3239 if (AVR_ENHANCED && scratch)
adcd8f77
MM
3240 {
3241 *len = 5;
3242 return (AS2 (ldi,%3,0x40) CR_TAB
3243 AS2 (mul,%A0,%3) CR_TAB
3244 AS2 (mov,%B0,r0) CR_TAB
3245 AS1 (clr,%A0) CR_TAB
3246 AS1 (clr,__zero_reg__));
3247 }
afee2a52
MM
3248 if (optimize_size && ldi_ok)
3249 {
3250 *len = 5;
3251 return (AS2 (mov,%B0,%A0) CR_TAB
3252 AS2 (ldi,%A0,6) "\n1:\t"
3253 AS1 (lsl,%B0) CR_TAB
3254 AS1 (dec,%A0) CR_TAB
3255 AS1 (brne,1b));
3256 }
3257 if (optimize_size && scratch)
3258 break; /* 5 */
3259 *len = 6;
3260 return (AS1 (clr,%B0) CR_TAB
3261 AS1 (lsr,%A0) CR_TAB
3262 AS1 (ror,%B0) CR_TAB
3263 AS1 (lsr,%A0) CR_TAB
3264 AS1 (ror,%B0) CR_TAB
3265 AS1 (clr,%A0));
adcd8f77
MM
3266
3267 case 15:
3268 *len = 4;
3269 return (AS1 (clr,%B0) CR_TAB
3270 AS1 (lsr,%A0) CR_TAB
3271 AS1 (ror,%B0) CR_TAB
3272 AS1 (clr,%A0));
90e7678c 3273 }
adcd8f77 3274 len = t;
90e7678c 3275 }
afee2a52
MM
3276 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3277 AS1 (rol,%B0)),
3278 insn, operands, len, 2);
90e7678c
DC
3279 return "";
3280}
3281
3282
3283/* 32bit shift left ((long)x << i) */
3284
5fecfd8d 3285const char *
269e3795 3286ashlsi3_out (rtx insn, rtx operands[], int *len)
90e7678c
DC
3287{
3288 if (GET_CODE (operands[2]) == CONST_INT)
3289 {
3290 int k;
afee2a52 3291 int *t = len;
3454eb73 3292
90e7678c
DC
3293 if (!len)
3294 len = &k;
3454eb73 3295
90e7678c
DC
3296 switch (INTVAL (operands[2]))
3297 {
a3cf5992
MM
3298 default:
3299 if (INTVAL (operands[2]) < 32)
3300 break;
3301
3302 if (AVR_ENHANCED)
3303 return *len = 3, (AS1 (clr,%D0) CR_TAB
3304 AS1 (clr,%C0) CR_TAB
3305 AS2 (movw,%A0,%C0));
3306 *len = 4;
3307 return (AS1 (clr,%D0) CR_TAB
3308 AS1 (clr,%C0) CR_TAB
3309 AS1 (clr,%B0) CR_TAB
3310 AS1 (clr,%A0));
3311
90e7678c
DC
3312 case 8:
3313 {
3314 int reg0 = true_regnum (operands[0]);
3315 int reg1 = true_regnum (operands[1]);
3454eb73 3316 *len = 4;
90e7678c
DC
3317 if (reg0 >= reg1)
3318 return (AS2 (mov,%D0,%C1) CR_TAB
3319 AS2 (mov,%C0,%B1) CR_TAB
3320 AS2 (mov,%B0,%A1) CR_TAB
3321 AS1 (clr,%A0));
3322 else if (reg0 + 1 == reg1)
3454eb73
DC
3323 {
3324 *len = 1;
3325 return AS1 (clr,%A0);
3326 }
90e7678c
DC
3327 else
3328 return (AS1 (clr,%A0) CR_TAB
3329 AS2 (mov,%B0,%A1) CR_TAB
3330 AS2 (mov,%C0,%B1) CR_TAB
3331 AS2 (mov,%D0,%C1));
3332 }
3454eb73 3333
90e7678c
DC
3334 case 16:
3335 {
3336 int reg0 = true_regnum (operands[0]);
3337 int reg1 = true_regnum (operands[1]);
3454eb73 3338 *len = 4;
6bec29c9 3339 if (AVR_ENHANCED && (reg0 + 2 != reg1))
c4984bad
MM
3340 {
3341 *len = 3;
3342 return (AS2 (movw,%C0,%A1) CR_TAB
3343 AS1 (clr,%B0) CR_TAB
3344 AS1 (clr,%A0));
3345 }
90e7678c
DC
3346 if (reg0 + 1 >= reg1)
3347 return (AS2 (mov,%D0,%B1) CR_TAB
3348 AS2 (mov,%C0,%A1) CR_TAB
3349 AS1 (clr,%B0) CR_TAB
3350 AS1 (clr,%A0));
3351 if (reg0 + 2 == reg1)
3454eb73
DC
3352 {
3353 *len = 2;
3354 return (AS1 (clr,%B0) CR_TAB
3355 AS1 (clr,%A0));
3356 }
90e7678c
DC
3357 else
3358 return (AS2 (mov,%C0,%A1) CR_TAB
3359 AS2 (mov,%D0,%B1) CR_TAB
3360 AS1 (clr,%B0) CR_TAB
3361 AS1 (clr,%A0));
3362 }
3454eb73 3363
90e7678c 3364 case 24:
3454eb73 3365 *len = 4;
90e7678c
DC
3366 if (true_regnum (operands[0]) + 3 != true_regnum (operands[1]))
3367 return (AS2 (mov,%D0,%A1) CR_TAB
3368 AS1 (clr,%C0) CR_TAB
3369 AS1 (clr,%B0) CR_TAB
3370 AS1 (clr,%A0));
3371 else
3454eb73
DC
3372 {
3373 *len = 3;
3374 return (AS1 (clr,%C0) CR_TAB
3375 AS1 (clr,%B0) CR_TAB
3376 AS1 (clr,%A0));
3377 }
adcd8f77
MM
3378
3379 case 31:
3380 *len = 6;
3381 return (AS1 (clr,%D0) CR_TAB
3382 AS1 (lsr,%A0) CR_TAB
3383 AS1 (ror,%D0) CR_TAB
3384 AS1 (clr,%C0) CR_TAB
3385 AS1 (clr,%B0) CR_TAB
3386 AS1 (clr,%A0));
90e7678c 3387 }
adcd8f77 3388 len = t;
90e7678c 3389 }
afee2a52
MM
3390 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
3391 AS1 (rol,%B0) CR_TAB
3392 AS1 (rol,%C0) CR_TAB
3393 AS1 (rol,%D0)),
3394 insn, operands, len, 4);
90e7678c
DC
3395 return "";
3396}
3397
3398/* 8bit arithmetic shift right ((signed char)x >> i) */
3399
5fecfd8d 3400const char *
269e3795 3401ashrqi3_out (rtx insn, rtx operands[], int *len)
90e7678c
DC
3402{
3403 if (GET_CODE (operands[2]) == CONST_INT)
3404 {
90e7678c 3405 int k;
3454eb73 3406
90e7678c
DC
3407 if (!len)
3408 len = &k;
3454eb73 3409
90e7678c
DC
3410 switch (INTVAL (operands[2]))
3411 {
90e7678c 3412 case 1:
3454eb73 3413 *len = 1;
90e7678c 3414 return AS1 (asr,%0);
3454eb73 3415
90e7678c 3416 case 2:
3454eb73 3417 *len = 2;
90e7678c
DC
3418 return (AS1 (asr,%0) CR_TAB
3419 AS1 (asr,%0));
3454eb73 3420
90e7678c 3421 case 3:
3454eb73 3422 *len = 3;
90e7678c
DC
3423 return (AS1 (asr,%0) CR_TAB
3424 AS1 (asr,%0) CR_TAB
3425 AS1 (asr,%0));
3454eb73 3426
90e7678c 3427 case 4:
3454eb73
DC
3428 *len = 4;
3429 return (AS1 (asr,%0) CR_TAB
3430 AS1 (asr,%0) CR_TAB
3431 AS1 (asr,%0) CR_TAB
3432 AS1 (asr,%0));
3433
3434 case 5:
3435 *len = 5;
90e7678c 3436 return (AS1 (asr,%0) CR_TAB
3454eb73 3437 AS1 (asr,%0) CR_TAB
90e7678c
DC
3438 AS1 (asr,%0) CR_TAB
3439 AS1 (asr,%0) CR_TAB
3440 AS1 (asr,%0));
3454eb73
DC
3441
3442 case 6:
3443 *len = 4;
3444 return (AS2 (bst,%0,6) CR_TAB
3445 AS1 (lsl,%0) CR_TAB
3446 AS2 (sbc,%0,%0) CR_TAB
3447 AS2 (bld,%0,0));
3448
3449 default:
a3cf5992
MM
3450 if (INTVAL (operands[2]) < 8)
3451 break;
3452
3453 /* fall through */
3454
3454eb73
DC
3455 case 7:
3456 *len = 2;
3457 return (AS1 (lsl,%0) CR_TAB
3458 AS2 (sbc,%0,%0));
90e7678c
DC
3459 }
3460 }
3454eb73 3461 else if (CONSTANT_P (operands[2]))
c725bd79 3462 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3454eb73 3463
0db7ad3a 3464 out_shift_with_cnt (AS1 (asr,%0),
afee2a52 3465 insn, operands, len, 1);
90e7678c
DC
3466 return "";
3467}
3468
3469
3470/* 16bit arithmetic shift right ((signed short)x >> i) */
3471
5fecfd8d 3472const char *
269e3795 3473ashrhi3_out (rtx insn, rtx operands[], int *len)
90e7678c
DC
3474{
3475 if (GET_CODE (operands[2]) == CONST_INT)
3476 {
afee2a52
MM
3477 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3478 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
90e7678c 3479 int k;
3454eb73
DC
3480 int *t = len;
3481
90e7678c
DC
3482 if (!len)
3483 len = &k;
3454eb73 3484
90e7678c
DC
3485 switch (INTVAL (operands[2]))
3486 {
afee2a52
MM
3487 case 4:
3488 case 5:
3489 /* XXX try to optimize this too? */
3490 break;
3454eb73 3491
afee2a52
MM
3492 case 6:
3493 if (optimize_size)
3494 break; /* scratch ? 5 : 6 */
3495 *len = 8;
3496 return (AS2 (mov,__tmp_reg__,%A0) CR_TAB
3497 AS2 (mov,%A0,%B0) CR_TAB
3498 AS1 (lsl,__tmp_reg__) CR_TAB
3499 AS1 (rol,%A0) CR_TAB
3500 AS2 (sbc,%B0,%B0) CR_TAB
3501 AS1 (lsl,__tmp_reg__) CR_TAB
3502 AS1 (rol,%A0) CR_TAB
3503 AS1 (rol,%B0));
3454eb73 3504
adcd8f77
MM
3505 case 7:
3506 *len = 4;
3507 return (AS1 (lsl,%A0) CR_TAB
3508 AS2 (mov,%A0,%B0) CR_TAB
3509 AS1 (rol,%A0) CR_TAB
3510 AS2 (sbc,%B0,%B0));
3511
90e7678c 3512 case 8:
afee2a52
MM
3513 {
3514 int reg0 = true_regnum (operands[0]);
3515 int reg1 = true_regnum (operands[1]);
3516
3517 if (reg0 == reg1)
3518 return *len = 3, (AS2 (mov,%A0,%B0) CR_TAB
3519 AS1 (lsl,%B0) CR_TAB
3520 AS2 (sbc,%B0,%B0));
3521 else if (reg0 == reg1 + 1)
3522 return *len = 3, (AS1 (clr,%B0) CR_TAB
3523 AS2 (sbrc,%A0,7) CR_TAB
3524 AS1 (dec,%B0));
3525
90e7678c
DC
3526 return *len = 4, (AS2 (mov,%A0,%B1) CR_TAB
3527 AS1 (clr,%B0) CR_TAB
3528 AS2 (sbrc,%A0,7) CR_TAB
3529 AS1 (dec,%B0));
afee2a52 3530 }
3454eb73 3531
adcd8f77
MM
3532 case 9:
3533 *len = 4;
3534 return (AS2 (mov,%A0,%B0) CR_TAB
3535 AS1 (lsl,%B0) CR_TAB
3536 AS2 (sbc,%B0,%B0) CR_TAB
3537 AS1 (asr,%A0));
3538
3539 case 10:
3540 *len = 5;
3541 return (AS2 (mov,%A0,%B0) CR_TAB
3542 AS1 (lsl,%B0) CR_TAB
3543 AS2 (sbc,%B0,%B0) CR_TAB
3544 AS1 (asr,%A0) CR_TAB
3545 AS1 (asr,%A0));
3546
3547 case 11:
afee2a52 3548 if (AVR_ENHANCED && ldi_ok)
adcd8f77
MM
3549 {
3550 *len = 5;
afee2a52
MM
3551 return (AS2 (ldi,%A0,0x20) CR_TAB
3552 AS2 (muls,%B0,%A0) CR_TAB
3553 AS2 (mov,%A0,r1) CR_TAB
3554 AS2 (sbc,%B0,%B0) CR_TAB
adcd8f77
MM
3555 AS1 (clr,__zero_reg__));
3556 }
afee2a52
MM
3557 if (optimize_size && scratch)
3558 break; /* 5 */
3559 *len = 6;
3560 return (AS2 (mov,%A0,%B0) CR_TAB
3561 AS1 (lsl,%B0) CR_TAB
3562 AS2 (sbc,%B0,%B0) CR_TAB
3563 AS1 (asr,%A0) CR_TAB
3564 AS1 (asr,%A0) CR_TAB
3565 AS1 (asr,%A0));
adcd8f77
MM
3566
3567 case 12:
afee2a52 3568 if (AVR_ENHANCED && ldi_ok)
adcd8f77
MM
3569 {
3570 *len = 5;
afee2a52
MM
3571 return (AS2 (ldi,%A0,0x10) CR_TAB
3572 AS2 (muls,%B0,%A0) CR_TAB
3573 AS2 (mov,%A0,r1) CR_TAB
3574 AS2 (sbc,%B0,%B0) CR_TAB
adcd8f77
MM
3575 AS1 (clr,__zero_reg__));
3576 }
afee2a52
MM
3577 if (optimize_size && scratch)
3578 break; /* 5 */
3579 *len = 7;
3580 return (AS2 (mov,%A0,%B0) CR_TAB
3581 AS1 (lsl,%B0) CR_TAB
3582 AS2 (sbc,%B0,%B0) CR_TAB
3583 AS1 (asr,%A0) CR_TAB
3584 AS1 (asr,%A0) CR_TAB
3585 AS1 (asr,%A0) CR_TAB
3586 AS1 (asr,%A0));
adcd8f77
MM
3587
3588 case 13:
afee2a52 3589 if (AVR_ENHANCED && ldi_ok)
adcd8f77
MM
3590 {
3591 *len = 5;
afee2a52
MM
3592 return (AS2 (ldi,%A0,0x08) CR_TAB
3593 AS2 (muls,%B0,%A0) CR_TAB
3594 AS2 (mov,%A0,r1) CR_TAB
3595 AS2 (sbc,%B0,%B0) CR_TAB
adcd8f77
MM
3596 AS1 (clr,__zero_reg__));
3597 }
afee2a52
MM
3598 if (optimize_size)
3599 break; /* scratch ? 5 : 7 */
3600 *len = 8;
3601 return (AS2 (mov,%A0,%B0) CR_TAB
3602 AS1 (lsl,%B0) CR_TAB
3603 AS2 (sbc,%B0,%B0) CR_TAB
3604 AS1 (asr,%A0) CR_TAB
3605 AS1 (asr,%A0) CR_TAB
3606 AS1 (asr,%A0) CR_TAB
3607 AS1 (asr,%A0) CR_TAB
3608 AS1 (asr,%A0));
adcd8f77
MM
3609
3610 case 14:
3611 *len = 5;
3612 return (AS1 (lsl,%B0) CR_TAB
3613 AS2 (sbc,%A0,%A0) CR_TAB
3614 AS1 (lsl,%B0) CR_TAB
3615 AS2 (mov,%B0,%A0) CR_TAB
3616 AS1 (rol,%A0));
3617
a3cf5992
MM
3618 default:
3619 if (INTVAL (operands[2]) < 16)
3620 break;
3621
3622 /* fall through */
3623
28e801e2
DC
3624 case 15:
3625 return *len = 3, (AS1 (lsl,%B0) CR_TAB
3626 AS2 (sbc,%A0,%A0) CR_TAB
3627 AS2 (mov,%B0,%A0));
90e7678c 3628 }
adcd8f77 3629 len = t;
90e7678c 3630 }
afee2a52
MM
3631 out_shift_with_cnt ((AS1 (asr,%B0) CR_TAB
3632 AS1 (ror,%A0)),
3633 insn, operands, len, 2);
90e7678c
DC
3634 return "";
3635}
3636
3637
3638/* 32bit arithmetic shift right ((signed long)x >> i) */
3639
5fecfd8d 3640const char *
269e3795 3641ashrsi3_out (rtx insn, rtx operands[], int *len)
90e7678c
DC
3642{
3643 if (GET_CODE (operands[2]) == CONST_INT)
3644 {
3645 int k;
3646 int *t = len;
3454eb73 3647
90e7678c
DC
3648 if (!len)
3649 len = &k;
3454eb73 3650
90e7678c
DC
3651 switch (INTVAL (operands[2]))
3652 {
90e7678c
DC
3653 case 8:
3654 {
3655 int reg0 = true_regnum (operands[0]);
3656 int reg1 = true_regnum (operands[1]);
3657 *len=6;
3658 if (reg0 <= reg1)
3659 return (AS2 (mov,%A0,%B1) CR_TAB
3660 AS2 (mov,%B0,%C1) CR_TAB
3661 AS2 (mov,%C0,%D1) CR_TAB
3662 AS1 (clr,%D0) CR_TAB
3663 AS2 (sbrc,%C0,7) CR_TAB
3664 AS1 (dec,%D0));
3665 else if (reg0 == reg1 + 1)
3454eb73
DC
3666 {
3667 *len = 3;
3668 return (AS1 (clr,%D0) CR_TAB
3669 AS2 (sbrc,%C0,7) CR_TAB
3670 AS1 (dec,%D0));
3671 }
90e7678c
DC
3672 else
3673 return (AS1 (clr,%D0) CR_TAB
28e801e2 3674 AS2 (sbrc,%D1,7) CR_TAB
90e7678c
DC
3675 AS1 (dec,%D0) CR_TAB
3676 AS2 (mov,%C0,%D1) CR_TAB
3677 AS2 (mov,%B0,%C1) CR_TAB
3678 AS2 (mov,%A0,%B1));
3679 }
3454eb73 3680
90e7678c
DC
3681 case 16:
3682 {
3683 int reg0 = true_regnum (operands[0]);
3684 int reg1 = true_regnum (operands[1]);
3685 *len=6;
6bec29c9 3686 if (AVR_ENHANCED && (reg0 != reg1 + 2))
c4984bad
MM
3687 {
3688 *len = 5;
3689 return (AS2 (movw,%A0,%C1) CR_TAB
3690 AS1 (clr,%D0) CR_TAB
3691 AS2 (sbrc,%B0,7) CR_TAB
3692 AS1 (com,%D0) CR_TAB
3693 AS2 (mov,%C0,%D0));
3694 }
90e7678c
DC
3695 if (reg0 <= reg1 + 1)
3696 return (AS2 (mov,%A0,%C1) CR_TAB
3697 AS2 (mov,%B0,%D1) CR_TAB
3698 AS1 (clr,%D0) CR_TAB
3699 AS2 (sbrc,%B0,7) CR_TAB
3700 AS1 (com,%D0) CR_TAB
3701 AS2 (mov,%C0,%D0));
3702 else if (reg0 == reg1 + 2)
3703 return *len = 4, (AS1 (clr,%D0) CR_TAB
3704 AS2 (sbrc,%B0,7) CR_TAB
3705 AS1 (com,%D0) CR_TAB
3706 AS2 (mov,%C0,%D0));
3707 else
3708 return (AS2 (mov,%B0,%D1) CR_TAB
3709 AS2 (mov,%A0,%C1) CR_TAB
3710 AS1 (clr,%D0) CR_TAB
3711 AS2 (sbrc,%B0,7) CR_TAB
3712 AS1 (com,%D0) CR_TAB
3713 AS2 (mov,%C0,%D0));
3714 }
3454eb73 3715
90e7678c
DC
3716 case 24:
3717 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
3718 return *len = 6, (AS2 (mov,%A0,%D1) CR_TAB
3719 AS1 (clr,%D0) CR_TAB
3720 AS2 (sbrc,%A0,7) CR_TAB
3721 AS1 (com,%D0) CR_TAB
3722 AS2 (mov,%B0,%D0) CR_TAB
3723 AS2 (mov,%C0,%D0));
3724 else
3725 return *len = 5, (AS1 (clr,%D0) CR_TAB
3726 AS2 (sbrc,%A0,7) CR_TAB
3727 AS1 (com,%D0) CR_TAB
3728 AS2 (mov,%B0,%D0) CR_TAB
3729 AS2 (mov,%C0,%D0));
adcd8f77 3730
a3cf5992
MM
3731 default:
3732 if (INTVAL (operands[2]) < 32)
3733 break;
3734
3735 /* fall through */
3736
adcd8f77
MM
3737 case 31:
3738 if (AVR_ENHANCED)
3739 return *len = 4, (AS1 (lsl,%D0) CR_TAB
3740 AS2 (sbc,%A0,%A0) CR_TAB
3741 AS2 (mov,%B0,%A0) CR_TAB
3742 AS2 (movw,%C0,%A0));
3743 else
3744 return *len = 5, (AS1 (lsl,%D0) CR_TAB
3745 AS2 (sbc,%A0,%A0) CR_TAB
3746 AS2 (mov,%B0,%A0) CR_TAB
3747 AS2 (mov,%C0,%A0) CR_TAB
3748 AS2 (mov,%D0,%A0));
90e7678c 3749 }
adcd8f77 3750 len = t;
90e7678c 3751 }
afee2a52
MM
3752 out_shift_with_cnt ((AS1 (asr,%D0) CR_TAB
3753 AS1 (ror,%C0) CR_TAB
3754 AS1 (ror,%B0) CR_TAB
3755 AS1 (ror,%A0)),
3756 insn, operands, len, 4);
90e7678c
DC
3757 return "";
3758}
3759
3760/* 8bit logic shift right ((unsigned char)x >> i) */
3761
5fecfd8d 3762const char *
269e3795 3763lshrqi3_out (rtx insn, rtx operands[], int *len)
90e7678c
DC
3764{
3765 if (GET_CODE (operands[2]) == CONST_INT)
3766 {
3767 int k;
3454eb73 3768
90e7678c
DC
3769 if (!len)
3770 len = &k;
3454eb73 3771
90e7678c
DC
3772 switch (INTVAL (operands[2]))
3773 {
3454eb73 3774 default:
a3cf5992
MM
3775 if (INTVAL (operands[2]) < 8)
3776 break;
3777
3454eb73
DC
3778 *len = 1;
3779 return AS1 (clr,%0);
3780
90e7678c 3781 case 1:
3454eb73 3782 *len = 1;
90e7678c 3783 return AS1 (lsr,%0);
3454eb73 3784
90e7678c 3785 case 2:
3454eb73 3786 *len = 2;
90e7678c
DC
3787 return (AS1 (lsr,%0) CR_TAB
3788 AS1 (lsr,%0));
3789 case 3:
3454eb73 3790 *len = 3;
90e7678c
DC
3791 return (AS1 (lsr,%0) CR_TAB
3792 AS1 (lsr,%0) CR_TAB
3793 AS1 (lsr,%0));
3454eb73 3794
90e7678c 3795 case 4:
c4984bad 3796 if (test_hard_reg_class (LD_REGS, operands[0]))
90e7678c
DC
3797 {
3798 *len=2;
3799 return (AS1 (swap,%0) CR_TAB
3800 AS2 (andi,%0,0x0f));
3801 }
3454eb73 3802 *len = 4;
90e7678c
DC
3803 return (AS1 (lsr,%0) CR_TAB
3804 AS1 (lsr,%0) CR_TAB
3805 AS1 (lsr,%0) CR_TAB
3806 AS1 (lsr,%0));
3454eb73 3807
90e7678c 3808 case 5:
c4984bad 3809 if (test_hard_reg_class (LD_REGS, operands[0]))
90e7678c 3810 {
3454eb73 3811 *len = 3;
90e7678c
DC
3812 return (AS1 (swap,%0) CR_TAB
3813 AS1 (lsr,%0) CR_TAB
3814 AS2 (andi,%0,0x7));
3815 }
3454eb73 3816 *len = 5;
90e7678c
DC
3817 return (AS1 (lsr,%0) CR_TAB
3818 AS1 (lsr,%0) CR_TAB
3819 AS1 (lsr,%0) CR_TAB
3820 AS1 (lsr,%0) CR_TAB
3821 AS1 (lsr,%0));
3454eb73 3822
90e7678c 3823 case 6:
c4984bad 3824 if (test_hard_reg_class (LD_REGS, operands[0]))
90e7678c 3825 {
3454eb73 3826 *len = 4;
90e7678c
DC
3827 return (AS1 (swap,%0) CR_TAB
3828 AS1 (lsr,%0) CR_TAB
3829 AS1 (lsr,%0) CR_TAB
3830 AS2 (andi,%0,0x3));
3831 }
3454eb73 3832 *len = 6;
90e7678c
DC
3833 return (AS1 (lsr,%0) CR_TAB
3834 AS1 (lsr,%0) CR_TAB
3835 AS1 (lsr,%0) CR_TAB
3836 AS1 (lsr,%0) CR_TAB
3837 AS1 (lsr,%0) CR_TAB
3838 AS1 (lsr,%0));
3454eb73 3839
90e7678c 3840 case 7:
3454eb73 3841 *len = 3;
90e7678c
DC
3842 return (AS1 (rol,%0) CR_TAB
3843 AS1 (clr,%0) CR_TAB
3844 AS1 (rol,%0));
3845 }
3846 }
3454eb73 3847 else if (CONSTANT_P (operands[2]))
c725bd79 3848 fatal_insn ("internal compiler error. Incorrect shift:", insn);
3454eb73 3849
0db7ad3a 3850 out_shift_with_cnt (AS1 (lsr,%0),
afee2a52 3851 insn, operands, len, 1);
90e7678c
DC
3852 return "";
3853}
3854
3855/* 16bit logic shift right ((unsigned short)x >> i) */
3856
5fecfd8d 3857const char *
269e3795 3858lshrhi3_out (rtx insn, rtx operands[], int *len)
90e7678c
DC
3859{
3860 if (GET_CODE (operands[2]) == CONST_INT)
3861 {
afee2a52
MM
3862 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
3863 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
90e7678c 3864 int k;
3454eb73 3865 int *t = len;
afee2a52 3866
90e7678c
DC
3867 if (!len)
3868 len = &k;
3454eb73 3869
90e7678c
DC
3870 switch (INTVAL (operands[2]))
3871 {
a3cf5992
MM
3872 default:
3873 if (INTVAL (operands[2]) < 16)
3874 break;
3875
3876 *len = 2;
3877 return (AS1 (clr,%B0) CR_TAB
3878 AS1 (clr,%A0));
3879
afee2a52
MM
3880 case 4:
3881 if (optimize_size && scratch)
3882 break; /* 5 */
3883 if (ldi_ok)
3884 {
3885 *len = 6;
3886 return (AS1 (swap,%B0) CR_TAB
3887 AS1 (swap,%A0) CR_TAB
3888 AS2 (andi,%A0,0x0f) CR_TAB
3889 AS2 (eor,%A0,%B0) CR_TAB
3890 AS2 (andi,%B0,0x0f) CR_TAB
3891 AS2 (eor,%A0,%B0));
3892 }
3893 if (scratch)
3894 {
3895 *len = 7;
3896 return (AS1 (swap,%B0) CR_TAB
3897 AS1 (swap,%A0) CR_TAB
3898 AS2 (ldi,%3,0x0f) CR_TAB
3899 AS2 (and,%A0,%3) CR_TAB
3900 AS2 (eor,%A0,%B0) CR_TAB
3901 AS2 (and,%B0,%3) CR_TAB
3902 AS2 (eor,%A0,%B0));
3903 }
3904 break; /* optimize_size ? 6 : 8 */
3905
3906 case 5:
3907 if (optimize_size)
3908 break; /* scratch ? 5 : 6 */
3909 if (ldi_ok)
3910 {
3911 *len = 8;
3912 return (AS1 (lsr,%B0) CR_TAB
3913 AS1 (ror,%A0) CR_TAB
3914 AS1 (swap,%B0) CR_TAB
3915 AS1 (swap,%A0) CR_TAB
3916 AS2 (andi,%A0,0x0f) CR_TAB
3917 AS2 (eor,%A0,%B0) CR_TAB
3918 AS2 (andi,%B0,0x0f) CR_TAB
3919 AS2 (eor,%A0,%B0));
3920 }
3921 if (scratch)
3922 {
3923 *len = 9;
3924 return (AS1 (lsr,%B0) CR_TAB
3925 AS1 (ror,%A0) CR_TAB
3926 AS1 (swap,%B0) CR_TAB
3927 AS1 (swap,%A0) CR_TAB
3928 AS2 (ldi,%3,0x0f) CR_TAB
3929 AS2 (and,%A0,%3) CR_TAB
3930 AS2 (eor,%A0,%B0) CR_TAB
3931 AS2 (and,%B0,%3) CR_TAB
3932 AS2 (eor,%A0,%B0));
3933 }
3934 break; /* 10 */
3935
3936 case 6:
3937 if (optimize_size)
3938 break; /* scratch ? 5 : 6 */
3939 *len = 9;
3940 return (AS1 (clr,__tmp_reg__) CR_TAB
3941 AS1 (lsl,%A0) CR_TAB
3942 AS1 (rol,%B0) CR_TAB
3943 AS1 (rol,__tmp_reg__) CR_TAB
3944 AS1 (lsl,%A0) CR_TAB
3945 AS1 (rol,%B0) CR_TAB
3946 AS1 (rol,__tmp_reg__) CR_TAB
3947 AS2 (mov,%A0,%B0) CR_TAB
3948 AS2 (mov,%B0,__tmp_reg__));
adcd8f77
MM
3949
3950 case 7:
3951 *len = 5;
3952 return (AS1 (lsl,%A0) CR_TAB
3953 AS2 (mov,%A0,%B0) CR_TAB
3954 AS1 (rol,%A0) CR_TAB
3955 AS2 (sbc,%B0,%B0) CR_TAB
3956 AS1 (neg,%B0));
3957
90e7678c
DC
3958 case 8:
3959 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 1)
3960 return *len = 2, (AS2 (mov,%A0,%B1) CR_TAB
3961 AS1 (clr,%B0));
3962 else
3963 return *len = 1, AS1 (clr,%B0);
adcd8f77
MM
3964
3965 case 9:
3966 *len = 3;
3967 return (AS2 (mov,%A0,%B0) CR_TAB
3968 AS1 (clr,%B0) CR_TAB
3969 AS1 (lsr,%A0));
3970
3971 case 10:
3972 *len = 4;
3973 return (AS2 (mov,%A0,%B0) CR_TAB
3974 AS1 (clr,%B0) CR_TAB
3975 AS1 (lsr,%A0) CR_TAB
3976 AS1 (lsr,%A0));
3977
3978 case 11:
3979 *len = 5;
3980 return (AS2 (mov,%A0,%B0) CR_TAB
3981 AS1 (clr,%B0) CR_TAB
3982 AS1 (lsr,%A0) CR_TAB
3983 AS1 (lsr,%A0) CR_TAB
3984 AS1 (lsr,%A0));
3985
3986 case 12:
afee2a52 3987 if (ldi_ok)
adcd8f77
MM
3988 {
3989 *len = 4;
3990 return (AS2 (mov,%A0,%B0) CR_TAB
3991 AS1 (clr,%B0) CR_TAB
3992 AS1 (swap,%A0) CR_TAB
3993 AS2 (andi,%A0,0x0f));
3994 }
afee2a52
MM
3995 if (scratch)
3996 {
3997 *len = 5;
3998 return (AS2 (mov,%A0,%B0) CR_TAB
3999 AS1 (clr,%B0) CR_TAB
4000 AS1 (swap,%A0) CR_TAB
4001 AS2 (ldi,%3,0x0f) CR_TAB
4002 AS2 (and,%A0,%3));
4003 }
4004 *len = 6;
adcd8f77
MM
4005 return (AS2 (mov,%A0,%B0) CR_TAB
4006 AS1 (clr,%B0) CR_TAB
afee2a52
MM
4007 AS1 (lsr,%A0) CR_TAB
4008 AS1 (lsr,%A0) CR_TAB
4009 AS1 (lsr,%A0) CR_TAB
4010 AS1 (lsr,%A0));
adcd8f77
MM
4011
4012 case 13:
afee2a52 4013 if (ldi_ok)
adcd8f77
MM
4014 {
4015 *len = 5;
4016 return (AS2 (mov,%A0,%B0) CR_TAB
4017 AS1 (clr,%B0) CR_TAB
4018 AS1 (swap,%A0) CR_TAB
4019 AS1 (lsr,%A0) CR_TAB
4020 AS2 (andi,%A0,0x07));
4021 }
afee2a52 4022 if (AVR_ENHANCED && scratch)
adcd8f77
MM
4023 {
4024 *len = 5;
4025 return (AS2 (ldi,%3,0x08) CR_TAB
4026 AS2 (mul,%B0,%3) CR_TAB
4027 AS2 (mov,%A0,r1) CR_TAB
4028 AS1 (clr,%B0) CR_TAB
4029 AS1 (clr,__zero_reg__));
4030 }
afee2a52
MM
4031 if (optimize_size && scratch)
4032 break; /* 5 */
4033 if (scratch)
4034 {
4035 *len = 6;
4036 return (AS2 (mov,%A0,%B0) CR_TAB
4037 AS1 (clr,%B0) CR_TAB
4038 AS1 (swap,%A0) CR_TAB
4039 AS1 (lsr,%A0) CR_TAB
4040 AS2 (ldi,%3,0x07) CR_TAB
4041 AS2 (and,%A0,%3));
4042 }
4043 if (AVR_ENHANCED)
4044 {
4045 *len = 6;
4046 return ("set" CR_TAB
4047 AS2 (bld,r1,3) CR_TAB
4048 AS2 (mul,%B0,r1) CR_TAB
4049 AS2 (mov,%A0,r1) CR_TAB
4050 AS1 (clr,%B0) CR_TAB
4051 AS1 (clr,__zero_reg__));
4052 }
4053 *len = 7;
4054 return (AS2 (mov,%A0,%B0) CR_TAB
4055 AS1 (clr,%B0) CR_TAB
4056 AS1 (lsr,%A0) CR_TAB
4057 AS1 (lsr,%A0) CR_TAB
4058 AS1 (lsr,%A0) CR_TAB
4059 AS1 (lsr,%A0) CR_TAB
4060 AS1 (lsr,%A0));
adcd8f77
MM
4061
4062 case 14:
afee2a52
MM
4063 if (AVR_ENHANCED && ldi_ok)
4064 {
4065 *len = 5;
4066 return (AS2 (ldi,%A0,0x04) CR_TAB
4067 AS2 (mul,%B0,%A0) CR_TAB
4068 AS2 (mov,%A0,r1) CR_TAB
4069 AS1 (clr,%B0) CR_TAB
4070 AS1 (clr,__zero_reg__));
4071 }
4072 if (AVR_ENHANCED && scratch)
adcd8f77
MM
4073 {
4074 *len = 5;
4075 return (AS2 (ldi,%3,0x04) CR_TAB
4076 AS2 (mul,%B0,%3) CR_TAB
4077 AS2 (mov,%A0,r1) CR_TAB
4078 AS1 (clr,%B0) CR_TAB
4079 AS1 (clr,__zero_reg__));
4080 }
afee2a52
MM
4081 if (optimize_size && ldi_ok)
4082 {
4083 *len = 5;
4084 return (AS2 (mov,%A0,%B0) CR_TAB
4085 AS2 (ldi,%B0,6) "\n1:\t"
4086 AS1 (lsr,%A0) CR_TAB
4087 AS1 (dec,%B0) CR_TAB
4088 AS1 (brne,1b));
4089 }
4090 if (optimize_size && scratch)
4091 break; /* 5 */
4092 *len = 6;
4093 return (AS1 (clr,%A0) CR_TAB
4094 AS1 (lsl,%B0) CR_TAB
4095 AS1 (rol,%A0) CR_TAB
4096 AS1 (lsl,%B0) CR_TAB
4097 AS1 (rol,%A0) CR_TAB
4098 AS1 (clr,%B0));
adcd8f77 4099
28e801e2 4100 case 15:
3454eb73 4101 *len = 4;
afee2a52
MM
4102 return (AS1 (clr,%A0) CR_TAB
4103 AS1 (lsl,%B0) CR_TAB
4104 AS1 (rol,%A0) CR_TAB
3454eb73 4105 AS1 (clr,%B0));
90e7678c 4106 }
adcd8f77 4107 len = t;
90e7678c 4108 }
afee2a52
MM
4109 out_shift_with_cnt ((AS1 (lsr,%B0) CR_TAB
4110 AS1 (ror,%A0)),
4111 insn, operands, len, 2);
90e7678c
DC
4112 return "";
4113}
4114
4115/* 32bit logic shift right ((unsigned int)x >> i) */
4116
5fecfd8d 4117const char *
269e3795 4118lshrsi3_out (rtx insn, rtx operands[], int *len)
90e7678c
DC
4119{
4120 if (GET_CODE (operands[2]) == CONST_INT)
4121 {
4122 int k;
3454eb73
DC
4123 int *t = len;
4124
90e7678c
DC
4125 if (!len)
4126 len = &k;
3454eb73 4127
90e7678c
DC
4128 switch (INTVAL (operands[2]))
4129 {
a3cf5992
MM
4130 default:
4131 if (INTVAL (operands[2]) < 32)
4132 break;
4133
4134 if (AVR_ENHANCED)
4135 return *len = 3, (AS1 (clr,%D0) CR_TAB
4136 AS1 (clr,%C0) CR_TAB
4137 AS2 (movw,%A0,%C0));
4138 *len = 4;
4139 return (AS1 (clr,%D0) CR_TAB
4140 AS1 (clr,%C0) CR_TAB
4141 AS1 (clr,%B0) CR_TAB
4142 AS1 (clr,%A0));
4143
90e7678c
DC
4144 case 8:
4145 {
4146 int reg0 = true_regnum (operands[0]);
4147 int reg1 = true_regnum (operands[1]);
3454eb73 4148 *len = 4;
90e7678c
DC
4149 if (reg0 <= reg1)
4150 return (AS2 (mov,%A0,%B1) CR_TAB
4151 AS2 (mov,%B0,%C1) CR_TAB
4152 AS2 (mov,%C0,%D1) CR_TAB
4153 AS1 (clr,%D0));
4154 else if (reg0 == reg1 + 1)
4155 return *len = 1, AS1 (clr,%D0);
4156 else
4157 return (AS1 (clr,%D0) CR_TAB
4158 AS2 (mov,%C0,%D1) CR_TAB
4159 AS2 (mov,%B0,%C1) CR_TAB
4160 AS2 (mov,%A0,%B1));
4161 }
3454eb73 4162
90e7678c
DC
4163 case 16:
4164 {
4165 int reg0 = true_regnum (operands[0]);
4166 int reg1 = true_regnum (operands[1]);
3454eb73 4167 *len = 4;
6bec29c9 4168 if (AVR_ENHANCED && (reg0 != reg1 + 2))
c4984bad
MM
4169 {
4170 *len = 3;
4171 return (AS2 (movw,%A0,%C1) CR_TAB
4172 AS1 (clr,%C0) CR_TAB
4173 AS1 (clr,%D0));
4174 }
90e7678c
DC
4175 if (reg0 <= reg1 + 1)
4176 return (AS2 (mov,%A0,%C1) CR_TAB
4177 AS2 (mov,%B0,%D1) CR_TAB
4178 AS1 (clr,%C0) CR_TAB
4179 AS1 (clr,%D0));
4180 else if (reg0 == reg1 + 2)
4181 return *len = 2, (AS1 (clr,%C0) CR_TAB
4182 AS1 (clr,%D0));
4183 else
4184 return (AS2 (mov,%B0,%D1) CR_TAB
4185 AS2 (mov,%A0,%C1) CR_TAB
4186 AS1 (clr,%C0) CR_TAB
4187 AS1 (clr,%D0));
4188 }
3454eb73 4189
90e7678c
DC
4190 case 24:
4191 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
4192 return *len = 4, (AS2 (mov,%A0,%D1) CR_TAB
4193 AS1 (clr,%B0) CR_TAB
4194 AS1 (clr,%C0) CR_TAB
4195 AS1 (clr,%D0));
4196 else
4197 return *len = 3, (AS1 (clr,%B0) CR_TAB
4198 AS1 (clr,%C0) CR_TAB
4199 AS1 (clr,%D0));
adcd8f77
MM
4200
4201 case 31:
4202 *len = 6;
4203 return (AS1 (clr,%A0) CR_TAB
4204 AS2 (sbrc,%D0,7) CR_TAB
4205 AS1 (inc,%A0) CR_TAB
4206 AS1 (clr,%B0) CR_TAB
4207 AS1 (clr,%C0) CR_TAB
4208 AS1 (clr,%D0));
90e7678c 4209 }
adcd8f77 4210 len = t;
90e7678c 4211 }
afee2a52
MM
4212 out_shift_with_cnt ((AS1 (lsr,%D0) CR_TAB
4213 AS1 (ror,%C0) CR_TAB
4214 AS1 (ror,%B0) CR_TAB
4215 AS1 (ror,%A0)),
4216 insn, operands, len, 4);
90e7678c
DC
4217 return "";
4218}
4219
4220/* Modifies the length assigned to instruction INSN
4221 LEN is the initially computed length of the insn. */
4222
4223int
269e3795 4224adjust_insn_length (rtx insn, int len)
90e7678c
DC
4225{
4226 rtx patt = PATTERN (insn);
4227 rtx set;
155b14a8 4228
90e7678c
DC
4229 if (GET_CODE (patt) == SET)
4230 {
4231 rtx op[10];
4232 op[1] = SET_SRC (patt);
4233 op[0] = SET_DEST (patt);
6bec29c9
DC
4234 if (general_operand (op[1], VOIDmode)
4235 && general_operand (op[0], VOIDmode))
4236 {
4237 switch (GET_MODE (op[0]))
4238 {
4239 case QImode:
4240 output_movqi (insn, op, &len);
4241 break;
4242 case HImode:
4243 output_movhi (insn, op, &len);
4244 break;
4245 case SImode:
4246 case SFmode:
4247 output_movsisf (insn, op, &len);
4248 break;
4249 default:
4250 break;
4251 }
4252 }
90e7678c
DC
4253 else if (op[0] == cc0_rtx && REG_P (op[1]))
4254 {
4255 switch (GET_MODE (op[1]))
4256 {
4257 case HImode: out_tsthi (insn,&len); break;
4258 case SImode: out_tstsi (insn,&len); break;
4259 default: break;
4260 }
4261 }
4262 else if (GET_CODE (op[1]) == AND)
4263 {
4264 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4265 {
4266 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4267 if (GET_MODE (op[1]) == SImode)
4268 len = (((mask & 0xff) != 0xff)
4269 + ((mask & 0xff00) != 0xff00)
11f9ed1a
KG
4270 + ((mask & 0xff0000L) != 0xff0000L)
4271 + ((mask & 0xff000000L) != 0xff000000L));
90e7678c
DC
4272 else if (GET_MODE (op[1]) == HImode)
4273 len = (((mask & 0xff) != 0xff)
4274 + ((mask & 0xff00) != 0xff00));
4275 }
4276 }
4277 else if (GET_CODE (op[1]) == IOR)
4278 {
4279 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
4280 {
4281 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
4282 if (GET_MODE (op[1]) == SImode)
5fecfd8d
MM
4283 len = (((mask & 0xff) != 0)
4284 + ((mask & 0xff00) != 0)
11f9ed1a
KG
4285 + ((mask & 0xff0000L) != 0)
4286 + ((mask & 0xff000000L) != 0));
90e7678c 4287 else if (GET_MODE (op[1]) == HImode)
5fecfd8d
MM
4288 len = (((mask & 0xff) != 0)
4289 + ((mask & 0xff00) != 0));
90e7678c
DC
4290 }
4291 }
4292 }
4293 set = single_set (insn);
4294 if (set)
4295 {
4296 rtx op[10];
155b14a8 4297
90e7678c
DC
4298 op[1] = SET_SRC (set);
4299 op[0] = SET_DEST (set);
155b14a8
DC
4300
4301 if (GET_CODE (patt) == PARALLEL
4302 && general_operand (op[1], VOIDmode)
4303 && general_operand (op[0], VOIDmode))
4304 {
4305 if (XVECLEN (patt, 0) == 2)
4306 op[2] = XVECEXP (patt, 0, 1);
4307
4308 switch (GET_MODE (op[0]))
4309 {
4310 case QImode:
4311 len = 2;
4312 break;
4313 case HImode:
4314 output_reload_inhi (insn, op, &len);
4315 break;
4316 case SImode:
4317 case SFmode:
4318 output_reload_insisf (insn, op, &len);
4319 break;
4320 default:
4321 break;
4322 }
4323 }
4324 else if (GET_CODE (op[1]) == ASHIFT
90e7678c
DC
4325 || GET_CODE (op[1]) == ASHIFTRT
4326 || GET_CODE (op[1]) == LSHIFTRT)
4327 {
4328 rtx ops[10];
4329 ops[0] = op[0];
4330 ops[1] = XEXP (op[1],0);
4331 ops[2] = XEXP (op[1],1);
4332 switch (GET_CODE (op[1]))
4333 {
4334 case ASHIFT:
4335 switch (GET_MODE (op[0]))
4336 {
4337 case QImode: ashlqi3_out (insn,ops,&len); break;
4338 case HImode: ashlhi3_out (insn,ops,&len); break;
4339 case SImode: ashlsi3_out (insn,ops,&len); break;
4340 default: break;
4341 }
4342 break;
4343 case ASHIFTRT:
4344 switch (GET_MODE (op[0]))
4345 {
4346 case QImode: ashrqi3_out (insn,ops,&len); break;
4347 case HImode: ashrhi3_out (insn,ops,&len); break;
4348 case SImode: ashrsi3_out (insn,ops,&len); break;
4349 default: break;
4350 }
4351 break;
4352 case LSHIFTRT:
4353 switch (GET_MODE (op[0]))
4354 {
4355 case QImode: lshrqi3_out (insn,ops,&len); break;
4356 case HImode: lshrhi3_out (insn,ops,&len); break;
4357 case SImode: lshrsi3_out (insn,ops,&len); break;
4358 default: break;
4359 }
4360 break;
4361 default:
4362 break;
4363 }
4364 }
4365 }
4366 return len;
4367}
4368
d6b4baa4 4369/* Return nonzero if register REG dead after INSN. */
90e7678c
DC
4370
4371int
269e3795 4372reg_unused_after (rtx insn, rtx reg)
90e7678c 4373{
6bec29c9 4374 return (dead_or_set_p (insn, reg)
90e7678c
DC
4375 || (REG_P(reg) && _reg_unused_after (insn, reg)));
4376}
4377
825dda42 4378/* Return nonzero if REG is not used after INSN.
90e7678c
DC
4379 We assume REG is a reload reg, and therefore does
4380 not live past labels. It may live past calls or jumps though. */
4381
4382int
269e3795 4383_reg_unused_after (rtx insn, rtx reg)
90e7678c
DC
4384{
4385 enum rtx_code code;
4386 rtx set;
4387
4388 /* If the reg is set by this instruction, then it is safe for our
4389 case. Disregard the case where this is a store to memory, since
4390 we are checking a register used in the store address. */
4391 set = single_set (insn);
4392 if (set && GET_CODE (SET_DEST (set)) != MEM
4393 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4394 return 1;
4395
4396 while ((insn = NEXT_INSN (insn)))
4397 {
ec8e098d 4398 rtx set;
90e7678c
DC
4399 code = GET_CODE (insn);
4400
4401#if 0
4402 /* If this is a label that existed before reload, then the register
4403 if dead here. However, if this is a label added by reorg, then
4404 the register may still be live here. We can't tell the difference,
4405 so we just ignore labels completely. */
4406 if (code == CODE_LABEL)
4407 return 1;
4408 /* else */
4409#endif
4410
ec8e098d
PB
4411 if (!INSN_P (insn))
4412 continue;
4413
90e7678c
DC
4414 if (code == JUMP_INSN)
4415 return 0;
4416
4417 /* If this is a sequence, we must handle them all at once.
4418 We could have for instance a call that sets the target register,
e03f5d43 4419 and an insn in a delay slot that uses the register. In this case,
90e7678c
DC
4420 we must return 0. */
4421 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
4422 {
4423 int i;
4424 int retval = 0;
4425
4426 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
4427 {
4428 rtx this_insn = XVECEXP (PATTERN (insn), 0, i);
4429 rtx set = single_set (this_insn);
4430
4431 if (GET_CODE (this_insn) == CALL_INSN)
4432 code = CALL_INSN;
4433 else if (GET_CODE (this_insn) == JUMP_INSN)
4434 {
4435 if (INSN_ANNULLED_BRANCH_P (this_insn))
4436 return 0;
4437 code = JUMP_INSN;
4438 }
4439
4440 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4441 return 0;
4442 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4443 {
4444 if (GET_CODE (SET_DEST (set)) != MEM)
4445 retval = 1;
4446 else
4447 return 0;
4448 }
4449 if (set == 0
4450 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
4451 return 0;
4452 }
4453 if (retval == 1)
4454 return 1;
4455 else if (code == JUMP_INSN)
4456 return 0;
4457 }
4458
4459 if (code == CALL_INSN)
4460 {
4461 rtx tem;
4462 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
4463 if (GET_CODE (XEXP (tem, 0)) == USE
4464 && REG_P (XEXP (XEXP (tem, 0), 0))
4465 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
4466 return 0;
4467 if (call_used_regs[REGNO (reg)])
4468 return 1;
4469 }
4470
ec8e098d 4471 set = single_set (insn);
90e7678c 4472
ec8e098d
PB
4473 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
4474 return 0;
4475 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
4476 return GET_CODE (SET_DEST (set)) != MEM;
4477 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
4478 return 0;
90e7678c
DC
4479 }
4480 return 1;
4481}
4482
301d03af
RS
4483/* Target hook for assembling integer objects. The AVR version needs
4484 special handling for references to certain labels. */
90e7678c 4485
301d03af 4486static bool
269e3795 4487avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
90e7678c 4488{
301d03af 4489 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
74b66b3c 4490 && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x))
301d03af 4491 || GET_CODE (x) == LABEL_REF))
90e7678c 4492 {
301d03af
RS
4493 fputs ("\t.word\tpm(", asm_out_file);
4494 output_addr_const (asm_out_file, x);
4495 fputs (")\n", asm_out_file);
4496 return true;
90e7678c 4497 }
301d03af 4498 return default_assemble_integer (x, size, aligned_p);
90e7678c
DC
4499}
4500
90e7678c
DC
4501/* The routine used to output NUL terminated strings. We use a special
4502 version of this for most svr4 targets because doing so makes the
4503 generated assembly code more compact (and thus faster to assemble)
4504 as well as more readable, especially for targets like the i386
4505 (where the only alternative is to output character sequences as
d6b4baa4 4506 comma separated lists of numbers). */
90e7678c
DC
4507
4508void
269e3795 4509gas_output_limited_string(FILE *file, const char *str)
90e7678c 4510{
5fecfd8d 4511 const unsigned char *_limited_str = (unsigned char *) str;
90e7678c 4512 unsigned ch;
8202cda0 4513 fprintf (file, "%s\"", STRING_ASM_OP);
90e7678c
DC
4514 for (; (ch = *_limited_str); _limited_str++)
4515 {
4516 int escape;
4517 switch (escape = ESCAPES[ch])
4518 {
4519 case 0:
4520 putc (ch, file);
4521 break;
4522 case 1:
4523 fprintf (file, "\\%03o", ch);
4524 break;
4525 default:
4526 putc ('\\', file);
4527 putc (escape, file);
4528 break;
4529 }
4530 }
4531 fprintf (file, "\"\n");
4532}
4533
4534/* The routine used to output sequences of byte values. We use a special
4535 version of this for most svr4 targets because doing so makes the
4536 generated assembly code more compact (and thus faster to assemble)
4537 as well as more readable. Note that if we find subparts of the
4538 character sequence which end with NUL (and which are shorter than
4539 STRING_LIMIT) we output those using ASM_OUTPUT_LIMITED_STRING. */
4540
4541void
269e3795 4542gas_output_ascii(FILE *file, const char *str, size_t length)
90e7678c 4543{
5fecfd8d
MM
4544 const unsigned char *_ascii_bytes = (const unsigned char *) str;
4545 const unsigned char *limit = _ascii_bytes + length;
90e7678c
DC
4546 unsigned bytes_in_chunk = 0;
4547 for (; _ascii_bytes < limit; _ascii_bytes++)
4548 {
5fecfd8d 4549 const unsigned char *p;
90e7678c
DC
4550 if (bytes_in_chunk >= 60)
4551 {
4552 fprintf (file, "\"\n");
4553 bytes_in_chunk = 0;
4554 }
4555 for (p = _ascii_bytes; p < limit && *p != '\0'; p++)
4556 continue;
4557 if (p < limit && (p - _ascii_bytes) <= (signed)STRING_LIMIT)
4558 {
4559 if (bytes_in_chunk > 0)
4560 {
4561 fprintf (file, "\"\n");
4562 bytes_in_chunk = 0;
4563 }
6bec29c9 4564 gas_output_limited_string (file, (char*)_ascii_bytes);
90e7678c
DC
4565 _ascii_bytes = p;
4566 }
4567 else
4568 {
4569 int escape;
4570 unsigned ch;
4571 if (bytes_in_chunk == 0)
4572 fprintf (file, "\t.ascii\t\"");
4573 switch (escape = ESCAPES[ch = *_ascii_bytes])
4574 {
4575 case 0:
4576 putc (ch, file);
4577 bytes_in_chunk++;
4578 break;
4579 case 1:
4580 fprintf (file, "\\%03o", ch);
4581 bytes_in_chunk += 4;
4582 break;
4583 default:
4584 putc ('\\', file);
4585 putc (escape, file);
4586 bytes_in_chunk += 2;
4587 break;
4588 }
4589 }
4590 }
4591 if (bytes_in_chunk > 0)
4592 fprintf (file, "\"\n");
4593}
4594
4595/* Return value is nonzero if pseudos that have been
4596 assigned to registers of class CLASS would likely be spilled
4597 because registers of CLASS are needed for spill registers. */
4598
4599enum reg_class
269e3795 4600class_likely_spilled_p (int c)
90e7678c
DC
4601{
4602 return (c != ALL_REGS && c != ADDW_REGS);
4603}
4604
91d231cb 4605/* Valid attributes:
90e7678c
DC
4606 progmem - put data to program memory;
4607 signal - make a function to be hardware interrupt. After function
c4984bad 4608 prologue interrupts are disabled;
90e7678c 4609 interrupt - make a function to be hardware interrupt. After function
c4984bad 4610 prologue interrupts are enabled;
91d231cb 4611 naked - don't generate function prologue/epilogue and `ret' command.
90e7678c 4612
91d231cb
JM
4613 Only `progmem' attribute valid for type. */
4614
4615const struct attribute_spec avr_attribute_table[] =
90e7678c 4616{
91d231cb
JM
4617 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4618 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute },
4619 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4620 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4621 { "naked", 0, 0, true, false, false, avr_handle_fndecl_attribute },
4622 { NULL, 0, 0, false, false, false, NULL }
4623};
90e7678c 4624
91d231cb
JM
4625/* Handle a "progmem" attribute; arguments as in
4626 struct attribute_spec.handler. */
4627static tree
269e3795
SB
4628avr_handle_progmem_attribute (tree *node, tree name,
4629 tree args ATTRIBUTE_UNUSED,
4630 int flags ATTRIBUTE_UNUSED,
4631 bool *no_add_attrs)
91d231cb
JM
4632{
4633 if (DECL_P (*node))
90e7678c 4634 {
b47cae3d
MM
4635 if (TREE_CODE (*node) == TYPE_DECL)
4636 {
4637 /* This is really a decl attribute, not a type attribute,
4638 but try to handle it for GCC 3.0 backwards compatibility. */
4639
4640 tree type = TREE_TYPE (*node);
4641 tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
4642 tree newtype = build_type_attribute_variant (type, attr);
4643
4644 TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
4645 TREE_TYPE (*node) = newtype;
4646 *no_add_attrs = true;
4647 }
4648 else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
90e7678c 4649 {
91d231cb
JM
4650 if (DECL_INITIAL (*node) == NULL_TREE && !DECL_EXTERNAL (*node))
4651 {
d4ee4d25 4652 warning (0, "only initialized variables can be placed into "
c725bd79 4653 "program memory area");
91d231cb
JM
4654 *no_add_attrs = true;
4655 }
4656 }
4657 else
4658 {
5c498b10
DD
4659 warning (OPT_Wattributes, "%qs attribute ignored",
4660 IDENTIFIER_POINTER (name));
91d231cb 4661 *no_add_attrs = true;
90e7678c 4662 }
90e7678c 4663 }
91d231cb
JM
4664
4665 return NULL_TREE;
90e7678c
DC
4666}
4667
91d231cb
JM
4668/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
4669 struct attribute_spec.handler. */
269e3795 4670
91d231cb 4671static tree
269e3795
SB
4672avr_handle_fndecl_attribute (tree *node, tree name,
4673 tree args ATTRIBUTE_UNUSED,
4674 int flags ATTRIBUTE_UNUSED,
4675 bool *no_add_attrs)
91d231cb
JM
4676{
4677 if (TREE_CODE (*node) != FUNCTION_DECL)
4678 {
5c498b10 4679 warning (OPT_Wattributes, "%qs attribute only applies to functions",
91d231cb
JM
4680 IDENTIFIER_POINTER (name));
4681 *no_add_attrs = true;
4682 }
97e45d9e
TR
4683 else
4684 {
4685 const char *func_name = IDENTIFIER_POINTER (DECL_NAME (*node));
4686 const char *attr = IDENTIFIER_POINTER (name);
4687
4688 /* If the function has the 'signal' or 'interrupt' attribute, test to
4689 make sure that the name of the function is "__vector_NN" so as to
4690 catch when the user misspells the interrupt vector name. */
4691
4692 if (strncmp (attr, "interrupt", strlen ("interrupt")) == 0)
4693 {
4694 if (strncmp (func_name, "__vector", strlen ("__vector")) != 0)
4695 {
c85ce869 4696 warning (0, "%qs appears to be a misspelled interrupt handler",
97e45d9e
TR
4697 func_name);
4698 }
4699 }
4700 else if (strncmp (attr, "signal", strlen ("signal")) == 0)
4701 {
4702 if (strncmp (func_name, "__vector", strlen ("__vector")) != 0)
4703 {
c85ce869 4704 warning (0, "%qs appears to be a misspelled signal handler",
97e45d9e
TR
4705 func_name);
4706 }
4707 }
4708 }
91d231cb
JM
4709
4710 return NULL_TREE;
4711}
90e7678c
DC
4712
4713/* Look for attribute `progmem' in DECL
c4984bad 4714 if found return 1, otherwise 0. */
90e7678c
DC
4715
4716int
427ee360 4717avr_progmem_p (tree decl, tree attributes)
90e7678c
DC
4718{
4719 tree a;
4720
4721 if (TREE_CODE (decl) != VAR_DECL)
4722 return 0;
4723
4724 if (NULL_TREE
427ee360 4725 != lookup_attribute ("progmem", attributes))
90e7678c
DC
4726 return 1;
4727
4728 a=decl;
4729 do
4730 a = TREE_TYPE(a);
4731 while (TREE_CODE (a) == ARRAY_TYPE);
4732
89741abb
MM
4733 if (a == error_mark_node)
4734 return 0;
4735
90e7678c
DC
4736 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
4737 return 1;
4738
4739 return 0;
4740}
4741
74b66b3c
RH
4742/* Add the section attribute if the variable is in progmem. */
4743
fb49053f 4744static void
269e3795 4745avr_insert_attributes (tree node, tree *attributes)
90e7678c 4746{
74b66b3c
RH
4747 if (TREE_CODE (node) == VAR_DECL
4748 && (TREE_STATIC (node) || DECL_EXTERNAL (node))
427ee360 4749 && avr_progmem_p (node, *attributes))
90e7678c 4750 {
74b66b3c
RH
4751 static const char dsec[] = ".progmem.data";
4752 *attributes = tree_cons (get_identifier ("section"),
4753 build_tree_list (NULL, build_string (strlen (dsec), dsec)),
4754 *attributes);
4755
4756 /* ??? This seems sketchy. Why can't the user declare the
4757 thing const in the first place? */
4758 TREE_READONLY (node) = 1;
90e7678c 4759 }
772c5265 4760}
90e7678c 4761
d6b5193b
RS
4762/* A get_unnamed_section callback for switching to progmem_section. */
4763
4764static void
4765avr_output_progmem_section_asm_op (const void *arg ATTRIBUTE_UNUSED)
4766{
4767 fprintf (asm_out_file,
4768 "\t.section .progmem.gcc_sw_table, \"%s\", @progbits\n",
4769 AVR_MEGA ? "a" : "ax");
4770 /* Should already be aligned, this is just to be safe if it isn't. */
4771 fprintf (asm_out_file, "\t.p2align 1\n");
4772}
4773
4774/* Implement TARGET_ASM_INIT_SECTIONS. */
4775
4776static void
4777avr_asm_init_sections (void)
4778{
4779 progmem_section = get_unnamed_section (AVR_MEGA ? 0 : SECTION_CODE,
4780 avr_output_progmem_section_asm_op,
4781 NULL);
4782 readonly_data_section = data_section;
4783}
4784
c16e5a35 4785static unsigned int
269e3795 4786avr_section_type_flags (tree decl, const char *name, int reloc)
c16e5a35
MM
4787{
4788 unsigned int flags = default_section_type_flags (decl, name, reloc);
4789
4790 if (strncmp (name, ".noinit", 7) == 0)
4791 {
4792 if (decl && TREE_CODE (decl) == VAR_DECL
4793 && DECL_INITIAL (decl) == NULL_TREE)
4794 flags |= SECTION_BSS; /* @nobits */
4795 else
d4ee4d25 4796 warning (0, "only uninitialized variables can be placed in the "
c16e5a35
MM
4797 ".noinit section");
4798 }
4799
4800 return flags;
4801}
4802
1bc7c5b6
ZW
4803/* Outputs some appropriate text to go at the start of an assembler
4804 file. */
90e7678c 4805
1bc7c5b6 4806static void
269e3795 4807avr_file_start (void)
90e7678c 4808{
bcb6a2be 4809 if (avr_asm_only_p)
9e637a26 4810 error ("MCU %qs supported for assembler only", avr_mcu_name);
bcb6a2be 4811
1bc7c5b6
ZW
4812 default_file_start ();
4813
4814 fprintf (asm_out_file, "\t.arch %s\n", avr_mcu_name);
90e7678c
DC
4815 fputs ("__SREG__ = 0x3f\n"
4816 "__SP_H__ = 0x3e\n"
1bc7c5b6 4817 "__SP_L__ = 0x3d\n", asm_out_file);
90e7678c 4818
368256d8 4819 fputs ("__tmp_reg__ = 0\n"
1bc7c5b6 4820 "__zero_reg__ = 1\n", asm_out_file);
9af145ae
MM
4821
4822 /* FIXME: output these only if there is anything in the .data / .bss
4823 sections - some code size could be saved by not linking in the
4824 initialization code from libgcc if one or both sections are empty. */
1bc7c5b6
ZW
4825 fputs ("\t.global __do_copy_data\n", asm_out_file);
4826 fputs ("\t.global __do_clear_bss\n", asm_out_file);
9af145ae 4827
90e7678c
DC
4828 commands_in_file = 0;
4829 commands_in_prologues = 0;
4830 commands_in_epilogues = 0;
4831}
4832
4833/* Outputs to the stdio stream FILE some
4834 appropriate text to go at the end of an assembler file. */
4835
a5fe455b 4836static void
269e3795 4837avr_file_end (void)
90e7678c 4838{
a5fe455b
ZW
4839 fputs ("/* File ", asm_out_file);
4840 output_quoted_string (asm_out_file, main_input_filename);
4841 fprintf (asm_out_file,
211a0cbe 4842 ": code %4d = 0x%04x (%4d), prologues %3d, epilogues %3d */\n",
90e7678c 4843 commands_in_file,
3454eb73 4844 commands_in_file,
90e7678c
DC
4845 commands_in_file - commands_in_prologues - commands_in_epilogues,
4846 commands_in_prologues, commands_in_epilogues);
4847}
4848
4849/* Choose the order in which to allocate hard registers for
4850 pseudo-registers local to a basic block.
4851
4852 Store the desired register order in the array `reg_alloc_order'.
4853 Element 0 should be the register to allocate first; element 1, the
4854 next register; and so on. */
4855
4856void
269e3795 4857order_regs_for_local_alloc (void)
90e7678c
DC
4858{
4859 unsigned int i;
8b60264b 4860 static const int order_0[] = {
90e7678c
DC
4861 24,25,
4862 18,19,
4863 20,21,
4864 22,23,
4865 30,31,
4866 26,27,
4867 28,29,
4868 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4869 0,1,
4870 32,33,34,35
4871 };
8b60264b 4872 static const int order_1[] = {
90e7678c
DC
4873 18,19,
4874 20,21,
4875 22,23,
4876 24,25,
4877 30,31,
4878 26,27,
4879 28,29,
4880 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4881 0,1,
4882 32,33,34,35
4883 };
8b60264b 4884 static const int order_2[] = {
90e7678c
DC
4885 25,24,
4886 23,22,
4887 21,20,
4888 19,18,
4889 30,31,
4890 26,27,
4891 28,29,
4892 17,16,
4893 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
4894 1,0,
4895 32,33,34,35
4896 };
4897
8b60264b
KG
4898 const int *order = (TARGET_ORDER_1 ? order_1 :
4899 TARGET_ORDER_2 ? order_2 :
4900 order_0);
5b47282c 4901 for (i=0; i < ARRAY_SIZE (order_0); ++i)
90e7678c
DC
4902 reg_alloc_order[i] = order[i];
4903}
4904
8f2bf9f1
RS
4905
4906/* Mutually recursive subroutine of avr_rtx_cost for calculating the
4907 cost of an RTX operand given its context. X is the rtx of the
4908 operand, MODE is its mode, and OUTER is the rtx_code of this
4909 operand's parent operator. */
90e7678c 4910
3c50106f 4911static int
8f2bf9f1 4912avr_operand_rtx_cost (rtx x, enum machine_mode mode, enum rtx_code outer)
90e7678c 4913{
8f2bf9f1
RS
4914 enum rtx_code code = GET_CODE (x);
4915 int total;
4916
90e7678c
DC
4917 switch (code)
4918 {
8f2bf9f1
RS
4919 case REG:
4920 case SUBREG:
4921 return 0;
4922
90e7678c 4923 case CONST_INT:
8f2bf9f1
RS
4924 case CONST_DOUBLE:
4925 return COSTS_N_INSNS (GET_MODE_SIZE (mode));
4926
90e7678c
DC
4927 default:
4928 break;
4929 }
8f2bf9f1
RS
4930
4931 total = 0;
4932 avr_rtx_costs (x, code, outer, &total);
4933 return total;
90e7678c
DC
4934}
4935
8f2bf9f1
RS
4936/* The AVR backend's rtx_cost function. X is rtx expression whose cost
4937 is to be calculated. Return true if the complete cost has been
4938 computed, and false if subexpressions should be scanned. In either
4939 case, *TOTAL contains the cost result. */
4940
3c50106f 4941static bool
269e3795 4942avr_rtx_costs (rtx x, int code, int outer_code, int *total)
3c50106f 4943{
8f2bf9f1
RS
4944 enum machine_mode mode = GET_MODE (x);
4945 HOST_WIDE_INT val;
3c50106f
RH
4946
4947 switch (code)
4948 {
4949 case CONST_INT:
8f2bf9f1
RS
4950 case CONST_DOUBLE:
4951 /* Immediate constants are as cheap as registers. */
4952 *total = 0;
4953 return true;
4954
4955 case MEM:
4956 case CONST:
4957 case LABEL_REF:
4958 case SYMBOL_REF:
4959 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
4960 return true;
4961
4962 case NEG:
4963 switch (mode)
3c50106f 4964 {
8f2bf9f1
RS
4965 case QImode:
4966 case SFmode:
4967 *total = COSTS_N_INSNS (1);
4968 break;
4969
4970 case HImode:
4971 *total = COSTS_N_INSNS (3);
4972 break;
4973
4974 case SImode:
4975 *total = COSTS_N_INSNS (7);
4976 break;
4977
4978 default:
4979 return false;
3c50106f 4980 }
8f2bf9f1
RS
4981 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
4982 return true;
4983
4984 case ABS:
4985 switch (mode)
3c50106f 4986 {
8f2bf9f1
RS
4987 case QImode:
4988 case SFmode:
4989 *total = COSTS_N_INSNS (1);
4990 break;
4991
4992 default:
4993 return false;
3c50106f 4994 }
8f2bf9f1
RS
4995 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
4996 return true;
3c50106f 4997
8f2bf9f1
RS
4998 case NOT:
4999 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
5000 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
3c50106f
RH
5001 return true;
5002
8f2bf9f1
RS
5003 case ZERO_EXTEND:
5004 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
5005 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
5006 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5007 return true;
5008
5009 case SIGN_EXTEND:
5010 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
5011 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
5012 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5013 return true;
5014
5015 case PLUS:
5016 switch (mode)
5017 {
5018 case QImode:
5019 *total = COSTS_N_INSNS (1);
5020 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5021 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5022 break;
5023
5024 case HImode:
5025 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5026 {
5027 *total = COSTS_N_INSNS (2);
5028 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5029 }
5030 else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
5031 *total = COSTS_N_INSNS (1);
5032 else
5033 *total = COSTS_N_INSNS (2);
5034 break;
5035
5036 case SImode:
5037 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5038 {
5039 *total = COSTS_N_INSNS (4);
5040 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5041 }
5042 else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
5043 *total = COSTS_N_INSNS (1);
5044 else
5045 *total = COSTS_N_INSNS (4);
5046 break;
5047
5048 default:
5049 return false;
5050 }
5051 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5052 return true;
5053
5054 case MINUS:
5055 case AND:
5056 case IOR:
5057 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
5058 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5059 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5060 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5061 return true;
5062
5063 case XOR:
5064 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
5065 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5066 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5067 return true;
5068
5069 case MULT:
5070 switch (mode)
5071 {
5072 case QImode:
5073 if (AVR_ENHANCED)
5074 *total = COSTS_N_INSNS (optimize_size ? 3 : 4);
5075 else if (optimize_size)
5076 *total = COSTS_N_INSNS (AVR_MEGA ? 2 : 1);
5077 else
5078 return false;
5079
5080 case HImode:
5081 if (AVR_ENHANCED)
5082 *total = COSTS_N_INSNS (optimize_size ? 7 : 10);
5083 else if (optimize_size)
5084 *total = COSTS_N_INSNS (AVR_MEGA ? 2 : 1);
5085 else
5086 return false;
5087
5088 default:
5089 return false;
5090 }
5091 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5092 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5093 return true;
5094
5095 case DIV:
5096 case MOD:
5097 case UDIV:
5098 case UMOD:
5099 if (optimize_size)
5100 *total = COSTS_N_INSNS (AVR_MEGA ? 2 : 1);
5101 else
5102 return false;
5103 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5104 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5105 return true;
5106
5107 case ASHIFT:
5108 switch (mode)
5109 {
5110 case QImode:
5111 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5112 {
5113 *total = COSTS_N_INSNS (optimize_size ? 4 : 17);
5114 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5115 }
5116 else
5117 {
5118 val = INTVAL (XEXP (x, 1));
5119 if (val == 7)
5120 *total = COSTS_N_INSNS (3);
5121 else if (val >= 0 && val <= 7)
5122 *total = COSTS_N_INSNS (val);
5123 else
5124 *total = COSTS_N_INSNS (1);
5125 }
5126 break;
5127
5128 case HImode:
5129 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5130 {
5131 *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
5132 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5133 }
5134 else
5135 switch (INTVAL (XEXP (x, 1)))
5136 {
5137 case 0:
5138 *total = 0;
5139 break;
5140 case 1:
5141 case 8:
5142 *total = COSTS_N_INSNS (2);
5143 break;
5144 case 9:
5145 *total = COSTS_N_INSNS (3);
5146 break;
5147 case 2:
5148 case 3:
5149 case 10:
5150 case 15:
5151 *total = COSTS_N_INSNS (4);
5152 break;
5153 case 7:
5154 case 11:
5155 case 12:
5156 *total = COSTS_N_INSNS (5);
5157 break;
5158 case 4:
5159 *total = COSTS_N_INSNS (optimize_size ? 5 : 8);
5160 break;
5161 case 6:
5162 *total = COSTS_N_INSNS (optimize_size ? 5 : 9);
5163 break;
5164 case 5:
5165 *total = COSTS_N_INSNS (optimize_size ? 5 : 10);
5166 break;
5167 default:
5168 *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
5169 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5170 }
5171 break;
5172
5173 case SImode:
5174 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5175 {
5176 *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
5177 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5178 }
5179 else
5180 switch (INTVAL (XEXP (x, 1)))
5181 {
5182 case 0:
5183 *total = 0;
5184 break;
5185 case 24:
5186 *total = COSTS_N_INSNS (3);
5187 break;
5188 case 1:
5189 case 8:
5190 case 16:
5191 *total = COSTS_N_INSNS (4);
5192 break;
5193 case 31:
5194 *total = COSTS_N_INSNS (6);
5195 break;
5196 case 2:
5197 *total = COSTS_N_INSNS (optimize_size ? 7 : 8);
5198 break;
5199 default:
5200 *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
5201 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5202 }
5203 break;
5204
5205 default:
5206 return false;
5207 }
5208 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5209 return true;
5210
5211 case ASHIFTRT:
5212 switch (mode)
5213 {
5214 case QImode:
5215 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5216 {
5217 *total = COSTS_N_INSNS (optimize_size ? 4 : 17);
5218 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5219 }
5220 else
5221 {
5222 val = INTVAL (XEXP (x, 1));
5223 if (val == 6)
5224 *total = COSTS_N_INSNS (4);
5225 else if (val == 7)
5226 *total = COSTS_N_INSNS (2);
5227 else if (val >= 0 && val <= 7)
5228 *total = COSTS_N_INSNS (val);
5229 else
5230 *total = COSTS_N_INSNS (1);
5231 }
5232 break;
5233
5234 case HImode:
5235 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5236 {
5237 *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
5238 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5239 }
5240 else
5241 switch (INTVAL (XEXP (x, 1)))
5242 {
5243 case 0:
5244 *total = 0;
5245 break;
5246 case 1:
5247 *total = COSTS_N_INSNS (2);
5248 break;
5249 case 15:
5250 *total = COSTS_N_INSNS (3);
5251 break;
5252 case 2:
5253 case 7:
5254 case 8:
5255 case 9:
5256 *total = COSTS_N_INSNS (4);
5257 break;
5258 case 10:
5259 case 14:
5260 *total = COSTS_N_INSNS (5);
5261 break;
5262 case 11:
5263 *total = COSTS_N_INSNS (optimize_size ? 5 : 6);
5264 break;
5265 case 12:
5266 *total = COSTS_N_INSNS (optimize_size ? 5 : 7);
5267 break;
5268 case 6:
5269 case 13:
5270 *total = COSTS_N_INSNS (optimize_size ? 5 : 8);
5271 break;
5272 default:
5273 *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
5274 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5275 }
5276 break;
5277
5278 case SImode:
5279 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5280 {
5281 *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
5282 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5283 }
5284 else
5285 switch (INTVAL (XEXP (x, 1)))
5286 {
5287 case 0:
5288 *total = 0;
5289 break;
5290 case 1:
5291 *total = COSTS_N_INSNS (4);
5292 break;
5293 case 8:
5294 case 16:
5295 case 24:
5296 *total = COSTS_N_INSNS (6);
5297 break;
5298 case 2:
5299 *total = COSTS_N_INSNS (optimize_size ? 7 : 8);
5300 break;
5301 case 31:
5302 *total = COSTS_N_INSNS (AVR_ENHANCED ? 4 : 5);
5303 break;
5304 default:
5305 *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
5306 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5307 }
5308 break;
5309
5310 default:
5311 return false;
5312 }
5313 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5314 return true;
5315
5316 case LSHIFTRT:
5317 switch (mode)
5318 {
5319 case QImode:
5320 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5321 {
5322 *total = COSTS_N_INSNS (optimize_size ? 4 : 17);
5323 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5324 }
5325 else
5326 {
5327 val = INTVAL (XEXP (x, 1));
5328 if (val == 7)
5329 *total = COSTS_N_INSNS (3);
5330 else if (val >= 0 && val <= 7)
5331 *total = COSTS_N_INSNS (val);
5332 else
5333 *total = COSTS_N_INSNS (1);
5334 }
5335 break;
5336
5337 case HImode:
5338 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5339 {
5340 *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
5341 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5342 }
5343 else
5344 switch (INTVAL (XEXP (x, 1)))
5345 {
5346 case 0:
5347 *total = 0;
5348 break;
5349 case 1:
5350 case 8:
5351 *total = COSTS_N_INSNS (2);
5352 break;
5353 case 9:
5354 *total = COSTS_N_INSNS (3);
5355 break;
5356 case 2:
5357 case 10:
5358 case 15:
5359 *total = COSTS_N_INSNS (4);
5360 break;
5361 case 7:
5362 case 11:
5363 *total = COSTS_N_INSNS (5);
5364 break;
5365 case 3:
5366 case 12:
5367 case 13:
5368 case 14:
5369 *total = COSTS_N_INSNS (optimize_size ? 5 : 6);
5370 break;
5371 case 4:
5372 *total = COSTS_N_INSNS (optimize_size ? 5 : 7);
5373 break;
5374 case 5:
5375 case 6:
5376 *total = COSTS_N_INSNS (optimize_size ? 5 : 9);
5377 break;
5378 default:
5379 *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
5380 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5381 }
5382 break;
5383
5384 case SImode:
5385 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5386 {
5387 *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
5388 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5389 }
5390 else
5391 switch (INTVAL (XEXP (x, 1)))
5392 {
5393 case 0:
5394 *total = 0;
5395 break;
5396 case 1:
5397 *total = COSTS_N_INSNS (4);
5398 break;
5399 case 2:
5400 *total = COSTS_N_INSNS (optimize_size ? 7 : 8);
5401 break;
5402 case 8:
5403 case 16:
5404 case 24:
5405 *total = COSTS_N_INSNS (4);
5406 break;
5407 case 31:
5408 *total = COSTS_N_INSNS (6);
5409 break;
5410 default:
5411 *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
5412 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5413 }
5414 break;
5415
5416 default:
5417 return false;
5418 }
5419 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5420 return true;
5421
5422 case COMPARE:
5423 switch (GET_MODE (XEXP (x, 0)))
3c50106f 5424 {
8f2bf9f1
RS
5425 case QImode:
5426 *total = COSTS_N_INSNS (1);
5427 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5428 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5429 break;
5430
5431 case HImode:
5432 *total = COSTS_N_INSNS (2);
5433 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5434 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5435 else if (INTVAL (XEXP (x, 1)) != 0)
5436 *total += COSTS_N_INSNS (1);
5437 break;
5438
5439 case SImode:
5440 *total = COSTS_N_INSNS (4);
5441 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5442 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
5443 else if (INTVAL (XEXP (x, 1)) != 0)
5444 *total += COSTS_N_INSNS (3);
5445 break;
5446
5447 default:
5448 return false;
3c50106f 5449 }
8f2bf9f1
RS
5450 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
5451 return true;
5452
5453 default:
5454 break;
3c50106f 5455 }
8f2bf9f1 5456 return false;
3c50106f
RH
5457}
5458
2c338472 5459/* Calculate the cost of a memory address. */
90e7678c 5460
dcefdf67 5461static int
269e3795 5462avr_address_cost (rtx x)
90e7678c
DC
5463{
5464 if (GET_CODE (x) == PLUS
5465 && GET_CODE (XEXP (x,1)) == CONST_INT
5466 && (REG_P (XEXP (x,0)) || GET_CODE (XEXP (x,0)) == SUBREG)
5467 && INTVAL (XEXP (x,1)) >= 61)
5468 return 18;
5469 if (CONSTANT_ADDRESS_P (x))
5fecfd8d 5470 {
1a499b92 5471 if (avr_io_address_p (x, 1))
5fecfd8d
MM
5472 return 2;
5473 return 4;
5474 }
90e7678c
DC
5475 return 4;
5476}
5477
5478/* EXTRA_CONSTRAINT helper */
5479
5480int
269e3795 5481extra_constraint (rtx x, int c)
90e7678c
DC
5482{
5483 if (c == 'Q'
5484 && GET_CODE (x) == MEM
5485 && GET_CODE (XEXP (x,0)) == PLUS)
5486 {
5487 if (TARGET_ALL_DEBUG)
5488 {
5489 fprintf (stderr, ("extra_constraint:\n"
5490 "reload_completed: %d\n"
5491 "reload_in_progress: %d\n"),
5492 reload_completed, reload_in_progress);
5493 debug_rtx (x);
5494 }
5495 if (GET_CODE (x) == MEM
5496 && GET_CODE (XEXP (x,0)) == PLUS
5497 && REG_P (XEXP (XEXP (x,0), 0))
5498 && GET_CODE (XEXP (XEXP (x,0), 1)) == CONST_INT
5499 && (INTVAL (XEXP (XEXP (x,0), 1))
3454eb73 5500 <= MAX_LD_OFFSET (GET_MODE (x))))
90e7678c
DC
5501 {
5502 rtx xx = XEXP (XEXP (x,0), 0);
5503 int regno = REGNO (xx);
5504 if (TARGET_ALL_DEBUG)
5505 {
5506 fprintf (stderr, ("extra_constraint:\n"
5507 "reload_completed: %d\n"
5508 "reload_in_progress: %d\n"),
5509 reload_completed, reload_in_progress);
5510 debug_rtx (x);
5511 }
5512 if (regno >= FIRST_PSEUDO_REGISTER)
5513 return 1; /* allocate pseudos */
5514 else if (regno == REG_Z || regno == REG_Y)
5515 return 1; /* strictly check */
5516 else if (xx == frame_pointer_rtx
5517 || xx == arg_pointer_rtx)
5518 return 1; /* XXX frame & arg pointer checks */
5519 }
5520 }
5521 return 0;
5522}
5523
2c338472 5524/* Convert condition code CONDITION to the valid AVR condition code. */
90e7678c
DC
5525
5526RTX_CODE
269e3795 5527avr_normalize_condition (RTX_CODE condition)
90e7678c
DC
5528{
5529 switch (condition)
5530 {
5531 case GT:
5532 return GE;
5533 case GTU:
5534 return GEU;
5535 case LE:
5536 return LT;
5537 case LEU:
5538 return LTU;
5539 default:
25b9575b 5540 gcc_unreachable ();
90e7678c
DC
5541 }
5542}
5543
cef1ccd6 5544/* This function optimizes conditional jumps. */
90e7678c 5545
18dbd950 5546static void
269e3795 5547avr_reorg (void)
90e7678c
DC
5548{
5549 rtx insn, pattern;
90e7678c 5550
18dbd950 5551 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
90e7678c 5552 {
33f77355
DC
5553 if (! (GET_CODE (insn) == INSN
5554 || GET_CODE (insn) == CALL_INSN
5555 || GET_CODE (insn) == JUMP_INSN)
90e7678c
DC
5556 || !single_set (insn))
5557 continue;
5558
5559 pattern = PATTERN (insn);
5560
90e7678c
DC
5561 if (GET_CODE (pattern) == PARALLEL)
5562 pattern = XVECEXP (pattern, 0, 0);
5563 if (GET_CODE (pattern) == SET
5564 && SET_DEST (pattern) == cc0_rtx
5565 && compare_diff_p (insn))
5566 {
5567 if (GET_CODE (SET_SRC (pattern)) == COMPARE)
5568 {
2c338472 5569 /* Now we work under compare insn. */
90e7678c
DC
5570
5571 pattern = SET_SRC (pattern);
5572 if (true_regnum (XEXP (pattern,0)) >= 0
5573 && true_regnum (XEXP (pattern,1)) >= 0 )
5574 {
5575 rtx x = XEXP (pattern,0);
5576 rtx next = next_real_insn (insn);
5577 rtx pat = PATTERN (next);
5578 rtx src = SET_SRC (pat);
5579 rtx t = XEXP (src,0);
5580 PUT_CODE (t, swap_condition (GET_CODE (t)));
5581 XEXP (pattern,0) = XEXP (pattern,1);
5582 XEXP (pattern,1) = x;
5583 INSN_CODE (next) = -1;
5584 }
5585 else if (true_regnum (XEXP (pattern,0)) >= 0
5586 && GET_CODE (XEXP (pattern,1)) == CONST_INT)
5587 {
5588 rtx x = XEXP (pattern,1);
5589 rtx next = next_real_insn (insn);
5590 rtx pat = PATTERN (next);
5591 rtx src = SET_SRC (pat);
5592 rtx t = XEXP (src,0);
651c5ed9 5593 enum machine_mode mode = GET_MODE (XEXP (pattern, 0));
90e7678c 5594
62e4d780 5595 if (avr_simplify_comparison_p (mode, GET_CODE (t), x))
90e7678c 5596 {
651c5ed9 5597 XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
90e7678c
DC
5598 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
5599 INSN_CODE (next) = -1;
5600 INSN_CODE (insn) = -1;
5601 }
5602 }
5603 }
5604 else if (true_regnum (SET_SRC (pattern)) >= 0)
5605 {
5606 /* This is a tst insn */
5607 rtx next = next_real_insn (insn);
5608 rtx pat = PATTERN (next);
5609 rtx src = SET_SRC (pat);
5610 rtx t = XEXP (src,0);
5611
33f77355 5612 PUT_CODE (t, swap_condition (GET_CODE (t)));
f1c25d3b
KH
5613 SET_SRC (pattern) = gen_rtx_NEG (GET_MODE (SET_SRC (pattern)),
5614 SET_SRC (pattern));
33f77355
DC
5615 INSN_CODE (next) = -1;
5616 INSN_CODE (insn) = -1;
90e7678c
DC
5617 }
5618 }
5619 }
5620}
5621
5622/* Returns register number for function return value.*/
5623
5624int
269e3795 5625avr_ret_register (void)
90e7678c
DC
5626{
5627 return 24;
5628}
5629
5630/* Ceate an RTX representing the place where a
5631 library function returns a value of mode MODE. */
5632
5633rtx
269e3795 5634avr_libcall_value (enum machine_mode mode)
90e7678c
DC
5635{
5636 int offs = GET_MODE_SIZE (mode);
5637 if (offs < 2)
5638 offs = 2;
f1c25d3b 5639 return gen_rtx_REG (mode, RET_REGISTER + 2 - offs);
90e7678c
DC
5640}
5641
5642/* Create an RTX representing the place where a
5643 function returns a value of data type VALTYPE. */
5644
5645rtx
269e3795 5646avr_function_value (tree type, tree func ATTRIBUTE_UNUSED)
90e7678c 5647{
3454eb73 5648 unsigned int offs;
56b871c1 5649
90e7678c
DC
5650 if (TYPE_MODE (type) != BLKmode)
5651 return avr_libcall_value (TYPE_MODE (type));
5652
5653 offs = int_size_in_bytes (type);
5654 if (offs < 2)
5655 offs = 2;
5656 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
5657 offs = GET_MODE_SIZE (SImode);
5658 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
5659 offs = GET_MODE_SIZE (DImode);
5660
f1c25d3b 5661 return gen_rtx_REG (BLKmode, RET_REGISTER + 2 - offs);
90e7678c
DC
5662}
5663
825dda42 5664/* Returns nonzero if the number MASK has only one bit set. */
90e7678c
DC
5665
5666int
269e3795 5667mask_one_bit_p (HOST_WIDE_INT mask)
90e7678c
DC
5668{
5669 int i;
5670 unsigned HOST_WIDE_INT n=mask;
5671 for (i = 0; i < 32; ++i)
5672 {
11f9ed1a 5673 if (n & 0x80000000L)
90e7678c 5674 {
11f9ed1a 5675 if (n & 0x7fffffffL)
90e7678c
DC
5676 return 0;
5677 else
5678 return 32-i;
5679 }
5680 n<<=1;
5681 }
5682 return 0;
5683}
5684
5685
5686/* Places additional restrictions on the register class to
5687 use when it is necessary to copy value X into a register
5688 in class CLASS. */
5689
5690enum reg_class
269e3795 5691preferred_reload_class (rtx x ATTRIBUTE_UNUSED, enum reg_class class)
90e7678c 5692{
90e7678c
DC
5693 return class;
5694}
5695
28e801e2 5696int
269e3795 5697test_hard_reg_class (enum reg_class class, rtx x)
28e801e2
DC
5698{
5699 int regno = true_regnum (x);
5700 if (regno < 0)
5701 return 0;
26af4041
MM
5702
5703 if (TEST_HARD_REG_CLASS (class, regno))
5704 return 1;
5705
5706 return 0;
28e801e2
DC
5707}
5708
b58c068a
DC
5709
5710int
269e3795 5711jump_over_one_insn_p (rtx insn, rtx dest)
b58c068a
DC
5712{
5713 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
5714 ? XEXP (dest, 0)
5715 : dest);
9d98a694
AO
5716 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
5717 int dest_addr = INSN_ADDRESSES (uid);
331ca350 5718 return dest_addr - jump_addr == get_attr_length (insn) + 1;
b58c068a 5719}
78cf8279
MM
5720
5721/* Returns 1 if a value of mode MODE can be stored starting with hard
c4984bad
MM
5722 register number REGNO. On the enhanced core, anything larger than
5723 1 byte must start in even numbered register for "movw" to work
5724 (this way we don't have to check for odd registers everywhere). */
78cf8279
MM
5725
5726int
269e3795 5727avr_hard_regno_mode_ok (int regno, enum machine_mode mode)
78cf8279 5728{
d2ebe27c
RS
5729 /* The only thing that can go into registers r28:r29 is a Pmode. */
5730 if (regno == REG_Y && mode == Pmode)
5731 return 1;
b96c434c 5732
d2ebe27c
RS
5733 /* Otherwise disallow all regno/mode combinations that span r28:r29. */
5734 if (regno <= (REG_Y + 1) && (regno + GET_MODE_SIZE (mode)) >= (REG_Y + 1))
678584fc
DC
5735 return 0;
5736
78cf8279
MM
5737 if (mode == QImode)
5738 return 1;
d2ebe27c
RS
5739
5740 /* Modes larger than QImode occupy consecutive registers. */
5741 if (regno + GET_MODE_SIZE (mode) > FIRST_PSEUDO_REGISTER)
5742 return 0;
5743
5744 /* All modes larger than QImode should start in an even register. */
78cf8279
MM
5745 return !(regno & 1);
5746}
6bec29c9 5747
6bec29c9 5748/* Returns 1 if X is a valid address for an I/O register of size SIZE
1a499b92
MM
5749 (1 or 2). Used for lds/sts -> in/out optimization. Add 0x20 to SIZE
5750 to check for the lower half of I/O space (for cbi/sbi/sbic/sbis). */
6bec29c9 5751
1a499b92 5752int
269e3795 5753avr_io_address_p (rtx x, int size)
6bec29c9
DC
5754{
5755 return (optimize > 0 && GET_CODE (x) == CONST_INT
5756 && INTVAL (x) >= 0x20 && INTVAL (x) <= 0x60 - size);
5757}
5758
5759/* Returns nonzero (bit number + 1) if X, or -X, is a constant power of 2. */
5760
5761int
269e3795 5762const_int_pow2_p (rtx x)
6bec29c9
DC
5763{
5764 if (GET_CODE (x) == CONST_INT)
5765 {
5766 HOST_WIDE_INT d = INTVAL (x);
5767 HOST_WIDE_INT abs_d = (d >= 0) ? d : -d;
5768 return exact_log2 (abs_d) + 1;
5769 }
5770 return 0;
5771}
5772
5fecfd8d 5773const char *
269e3795 5774output_reload_inhi (rtx insn ATTRIBUTE_UNUSED, rtx *operands, int *len)
6bec29c9 5775{
612105a6
DC
5776 int tmp;
5777 if (!len)
5778 len = &tmp;
5779
6bec29c9
DC
5780 if (GET_CODE (operands[1]) == CONST_INT)
5781 {
5782 int val = INTVAL (operands[1]);
5783 if ((val & 0xff) == 0)
5784 {
5785 *len = 3;
5786 return (AS2 (mov,%A0,__zero_reg__) CR_TAB
5787 AS2 (ldi,%2,hi8(%1)) CR_TAB
5788 AS2 (mov,%B0,%2));
5789 }
5790 else if ((val & 0xff00) == 0)
5791 {
5792 *len = 3;
5793 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5794 AS2 (mov,%A0,%2) CR_TAB
5795 AS2 (mov,%B0,__zero_reg__));
5796 }
5797 else if ((val & 0xff) == ((val & 0xff00) >> 8))
5798 {
5799 *len = 3;
5800 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5801 AS2 (mov,%A0,%2) CR_TAB
5802 AS2 (mov,%B0,%2));
5803 }
5804 }
5805 *len = 4;
5806 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
5807 AS2 (mov,%A0,%2) CR_TAB
5808 AS2 (ldi,%2,hi8(%1)) CR_TAB
5809 AS2 (mov,%B0,%2));
5810}
5811
5812
5fecfd8d 5813const char *
269e3795 5814output_reload_insisf (rtx insn ATTRIBUTE_UNUSED, rtx *operands, int *len)
6bec29c9 5815{
5fecfd8d
MM
5816 rtx src = operands[1];
5817 int cnst = (GET_CODE (src) == CONST_INT);
5818
5819 if (len)
5820 {
5821 if (cnst)
5822 *len = 4 + ((INTVAL (src) & 0xff) != 0)
5823 + ((INTVAL (src) & 0xff00) != 0)
5824 + ((INTVAL (src) & 0xff0000) != 0)
11f9ed1a 5825 + ((INTVAL (src) & 0xff000000) != 0);
5fecfd8d
MM
5826 else
5827 *len = 8;
5828
5829 return "";
5830 }
6bec29c9 5831
5fecfd8d 5832 if (cnst && ((INTVAL (src) & 0xff) == 0))
6bec29c9
DC
5833 output_asm_insn (AS2 (mov, %A0, __zero_reg__), operands);
5834 else
5835 {
5836 output_asm_insn (AS2 (ldi, %2, lo8(%1)), operands);
5837 output_asm_insn (AS2 (mov, %A0, %2), operands);
5838 }
5fecfd8d 5839 if (cnst && ((INTVAL (src) & 0xff00) == 0))
6bec29c9
DC
5840 output_asm_insn (AS2 (mov, %B0, __zero_reg__), operands);
5841 else
5842 {
5843 output_asm_insn (AS2 (ldi, %2, hi8(%1)), operands);
5844 output_asm_insn (AS2 (mov, %B0, %2), operands);
5845 }
5fecfd8d 5846 if (cnst && ((INTVAL (src) & 0xff0000) == 0))
6bec29c9
DC
5847 output_asm_insn (AS2 (mov, %C0, __zero_reg__), operands);
5848 else
5849 {
5850 output_asm_insn (AS2 (ldi, %2, hlo8(%1)), operands);
5851 output_asm_insn (AS2 (mov, %C0, %2), operands);
5852 }
11f9ed1a 5853 if (cnst && ((INTVAL (src) & 0xff000000) == 0))
6bec29c9
DC
5854 output_asm_insn (AS2 (mov, %D0, __zero_reg__), operands);
5855 else
5856 {
5857 output_asm_insn (AS2 (ldi, %2, hhi8(%1)), operands);
5858 output_asm_insn (AS2 (mov, %D0, %2), operands);
5859 }
5860 return "";
5861}
afee2a52
MM
5862
5863void
269e3795 5864avr_output_bld (rtx operands[], int bit_nr)
afee2a52
MM
5865{
5866 static char s[] = "bld %A0,0";
5867
5868 s[5] = 'A' + (bit_nr >> 3);
5869 s[8] = '0' + (bit_nr & 7);
5870 output_asm_insn (s, operands);
5871}
5872
e9284adf 5873void
269e3795 5874avr_output_addr_vec_elt (FILE *stream, int value)
e9284adf 5875{
d6b5193b 5876 switch_to_section (progmem_section);
e9284adf
MM
5877 if (AVR_MEGA)
5878 fprintf (stream, "\t.word pm(.L%d)\n", value);
5879 else
5880 fprintf (stream, "\trjmp .L%d\n", value);
5881
5882 jump_tables_size++;
5883}
5884
dcfb1a36
MM
5885/* Returns 1 if SCRATCH are safe to be allocated as a scratch
5886 registers (for a define_peephole2) in the current function. */
5887
5888int
269e3795 5889avr_peep2_scratch_safe (rtx scratch)
dcfb1a36
MM
5890{
5891 if ((interrupt_function_p (current_function_decl)
5892 || signal_function_p (current_function_decl))
5893 && leaf_function_p ())
5894 {
5895 int first_reg = true_regnum (scratch);
5896 int last_reg = first_reg + GET_MODE_SIZE (GET_MODE (scratch)) - 1;
5897 int reg;
5898
5899 for (reg = first_reg; reg <= last_reg; reg++)
5900 {
5901 if (!regs_ever_live[reg])
5902 return 0;
5903 }
5904 }
5905 return 1;
5906}
331ca350
MM
5907
5908/* Output a branch that tests a single bit of a register (QI, HI or SImode)
5909 or memory location in the I/O space (QImode only).
5910
5911 Operand 0: comparison operator (must be EQ or NE, compare bit to zero).
5912 Operand 1: register operand to test, or CONST_INT memory address.
5913 Operand 2: bit number (for QImode operand) or mask (HImode, SImode).
5914 Operand 3: label to jump to if the test is true. */
5915
5916const char *
269e3795 5917avr_out_sbxx_branch (rtx insn, rtx operands[])
331ca350
MM
5918{
5919 enum rtx_code comp = GET_CODE (operands[0]);
5920 int long_jump = (get_attr_length (insn) >= 4);
5921 int reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
5922
5923 if (comp == GE)
5924 comp = EQ;
5925 else if (comp == LT)
5926 comp = NE;
5927
5928 if (reverse)
5929 comp = reverse_condition (comp);
5930
5931 if (GET_CODE (operands[1]) == CONST_INT)
5932 {
5933 if (INTVAL (operands[1]) < 0x40)
5934 {
5935 if (comp == EQ)
5936 output_asm_insn (AS2 (sbis,%1-0x20,%2), operands);
5937 else
5938 output_asm_insn (AS2 (sbic,%1-0x20,%2), operands);
5939 }
5940 else
5941 {
5942 output_asm_insn (AS2 (in,__tmp_reg__,%1-0x20), operands);
5943 if (comp == EQ)
5944 output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands);
5945 else
5946 output_asm_insn (AS2 (sbrc,__tmp_reg__,%2), operands);
5947 }
5948 }
5949 else /* GET_CODE (operands[1]) == REG */
5950 {
5951 if (GET_MODE (operands[1]) == QImode)
5952 {
5953 if (comp == EQ)
5954 output_asm_insn (AS2 (sbrs,%1,%2), operands);
5955 else
5956 output_asm_insn (AS2 (sbrc,%1,%2), operands);
5957 }
5958 else /* HImode or SImode */
5959 {
5960 static char buf[] = "sbrc %A1,0";
5961 int bit_nr = exact_log2 (INTVAL (operands[2])
5962 & GET_MODE_MASK (GET_MODE (operands[1])));
5963
5964 buf[3] = (comp == EQ) ? 's' : 'c';
5965 buf[6] = 'A' + (bit_nr >> 3);
5966 buf[9] = '0' + (bit_nr & 7);
5967 output_asm_insn (buf, operands);
5968 }
5969 }
5970
5971 if (long_jump)
13e8651c 5972 return (AS1 (rjmp,.+4) CR_TAB
331ca350
MM
5973 AS1 (jmp,%3));
5974 if (!reverse)
5975 return AS1 (rjmp,%3);
5976 return "";
5977}
9af145ae 5978
bd5bd7ac
KH
5979/* Worker function for TARGET_ASM_CONSTRUCTOR. */
5980
9af145ae 5981static void
269e3795 5982avr_asm_out_ctor (rtx symbol, int priority)
9af145ae
MM
5983{
5984 fputs ("\t.global __do_global_ctors\n", asm_out_file);
5985 default_ctor_section_asm_out_constructor (symbol, priority);
5986}
5987
bd5bd7ac
KH
5988/* Worker function for TARGET_ASM_DESTRUCTOR. */
5989
9af145ae 5990static void
269e3795 5991avr_asm_out_dtor (rtx symbol, int priority)
9af145ae
MM
5992{
5993 fputs ("\t.global __do_global_dtors\n", asm_out_file);
5994 default_dtor_section_asm_out_destructor (symbol, priority);
5995}
5996
bd5bd7ac
KH
5997/* Worker function for TARGET_RETURN_IN_MEMORY. */
5998
b069302c
KH
5999static bool
6000avr_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
6001{
78bc94a2
KH
6002 if (TYPE_MODE (type) == BLKmode)
6003 {
6004 HOST_WIDE_INT size = int_size_in_bytes (type);
6005 return (size == -1 || size > 8);
6006 }
6007 else
6008 return false;
b069302c
KH
6009}
6010
baac771a 6011#include "gt-avr.h"