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