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