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