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