00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025 #include "coretypes.h"
00026 #include "tm.h"
00027 #include "rtl.h"
00028 #include "regs.h"
00029 #include "hard-reg-set.h"
00030 #include "real.h"
00031 #include "insn-config.h"
00032 #include "conditions.h"
00033 #include "insn-attr.h"
00034 #include "flags.h"
00035 #include "reload.h"
00036 #include "tree.h"
00037 #include "output.h"
00038 #include "expr.h"
00039 #include "toplev.h"
00040 #include "obstack.h"
00041 #include "function.h"
00042 #include "recog.h"
00043 #include "ggc.h"
00044 #include "tm_p.h"
00045 #include "target.h"
00046 #include "target-def.h"
00047
00048
00049 #define MAX_LD_OFFSET(MODE) (64 - (signed)GET_MODE_SIZE (MODE))
00050
00051 static int avr_naked_function_p (tree);
00052 static int interrupt_function_p (tree);
00053 static int signal_function_p (tree);
00054 static int avr_regs_to_save (HARD_REG_SET *);
00055 static int sequent_regs_live (void);
00056 static const char *ptrreg_to_str (int);
00057 static const char *cond_string (enum rtx_code);
00058 static int avr_num_arg_regs (enum machine_mode, tree);
00059 static int out_adj_frame_ptr (FILE *, int);
00060 static int out_set_stack_ptr (FILE *, int, int);
00061 static RTX_CODE compare_condition (rtx insn);
00062 static int compare_sign_p (rtx insn);
00063 static tree avr_handle_progmem_attribute (tree *, tree, tree, int, bool *);
00064 static tree avr_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
00065 const struct attribute_spec avr_attribute_table[];
00066 static bool avr_assemble_integer (rtx, unsigned int, int);
00067 static void avr_file_start (void);
00068 static void avr_file_end (void);
00069 static void avr_output_function_prologue (FILE *, HOST_WIDE_INT);
00070 static void avr_output_function_epilogue (FILE *, HOST_WIDE_INT);
00071 static void avr_insert_attributes (tree, tree *);
00072 static unsigned int avr_section_type_flags (tree, const char *, int);
00073
00074 static void avr_reorg (void);
00075 static void avr_asm_out_ctor (rtx, int);
00076 static void avr_asm_out_dtor (rtx, int);
00077 static int avr_operand_rtx_cost (rtx, enum machine_mode, enum rtx_code);
00078 static bool avr_rtx_costs (rtx, int, int, int *);
00079 static int avr_address_cost (rtx);
00080 static bool avr_return_in_memory (tree, tree);
00081
00082
00083 #define FIRST_CUM_REG 26
00084
00085
00086 static GTY(()) rtx tmp_reg_rtx;
00087
00088
00089 static GTY(()) rtx zero_reg_rtx;
00090
00091
00092 static const char *const avr_regnames[] = REGISTER_NAMES;
00093
00094
00095 static int last_insn_address = 0;
00096
00097
00098 static int commands_in_file;
00099
00100
00101 static int commands_in_prologues;
00102
00103
00104 static int commands_in_epilogues;
00105
00106
00107 static int prologue_size;
00108 static int epilogue_size;
00109
00110
00111 static int jump_tables_size;
00112
00113
00114 const char *avr_init_stack = "__stack";
00115
00116
00117 const char *avr_mcu_name = "avr2";
00118
00119
00120 const char *avr_base_arch_macro;
00121 const char *avr_extra_arch_macro;
00122
00123
00124 int avr_mega_p = 0;
00125
00126
00127 int avr_enhanced_p = 0;
00128
00129
00130 int avr_asm_only_p = 0;
00131
00132 struct base_arch_s {
00133 int asm_only;
00134 int enhanced;
00135 int mega;
00136 const char *const macro;
00137 };
00138
00139 static const struct base_arch_s avr_arch_types[] = {
00140 { 1, 0, 0, NULL },
00141 { 1, 0, 0, "__AVR_ARCH__=1" },
00142 { 0, 0, 0, "__AVR_ARCH__=2" },
00143 { 0, 0, 1, "__AVR_ARCH__=3" },
00144 { 0, 1, 0, "__AVR_ARCH__=4" },
00145 { 0, 1, 1, "__AVR_ARCH__=5" }
00146 };
00147
00148 struct mcu_type_s {
00149 const char *const name;
00150 int arch;
00151
00152 const char *const macro;
00153 };
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163 static const struct mcu_type_s avr_mcu_types[] = {
00164
00165 { "avr2", 2, NULL },
00166 { "at90s2313", 2, "__AVR_AT90S2313__" },
00167 { "at90s2323", 2, "__AVR_AT90S2323__" },
00168 { "at90s2333", 2, "__AVR_AT90S2333__" },
00169 { "at90s2343", 2, "__AVR_AT90S2343__" },
00170 { "attiny22", 2, "__AVR_ATtiny22__" },
00171 { "attiny26", 2, "__AVR_ATtiny26__" },
00172 { "at90s4414", 2, "__AVR_AT90S4414__" },
00173 { "at90s4433", 2, "__AVR_AT90S4433__" },
00174 { "at90s4434", 2, "__AVR_AT90S4434__" },
00175 { "at90s8515", 2, "__AVR_AT90S8515__" },
00176 { "at90c8534", 2, "__AVR_AT90C8534__" },
00177 { "at90s8535", 2, "__AVR_AT90S8535__" },
00178 { "at86rf401", 2, "__AVR_AT86RF401__" },
00179
00180 { "attiny13", 2, "__AVR_ATtiny13__" },
00181 { "attiny2313", 2, "__AVR_ATtiny2313__" },
00182
00183 { "avr3", 3, NULL },
00184 { "atmega103", 3, "__AVR_ATmega103__" },
00185 { "atmega603", 3, "__AVR_ATmega603__" },
00186 { "at43usb320", 3, "__AVR_AT43USB320__" },
00187 { "at43usb355", 3, "__AVR_AT43USB355__" },
00188 { "at76c711", 3, "__AVR_AT76C711__" },
00189
00190 { "avr4", 4, NULL },
00191 { "atmega8", 4, "__AVR_ATmega8__" },
00192 { "atmega48", 4, "__AVR_ATmega48__" },
00193 { "atmega88", 4, "__AVR_ATmega88__" },
00194 { "atmega8515", 4, "__AVR_ATmega8515__" },
00195 { "atmega8535", 4, "__AVR_ATmega8535__" },
00196
00197 { "avr5", 5, NULL },
00198 { "atmega16", 5, "__AVR_ATmega16__" },
00199 { "atmega161", 5, "__AVR_ATmega161__" },
00200 { "atmega162", 5, "__AVR_ATmega162__" },
00201 { "atmega163", 5, "__AVR_ATmega163__" },
00202 { "atmega165", 5, "__AVR_ATmega165__" },
00203 { "atmega168", 5, "__AVR_ATmega168__" },
00204 { "atmega169", 5, "__AVR_ATmega169__" },
00205 { "atmega32", 5, "__AVR_ATmega32__" },
00206 { "atmega323", 5, "__AVR_ATmega323__" },
00207 { "atmega325", 5, "__AVR_ATmega325__" },
00208 { "atmega3250", 5, "__AVR_ATmega3250__" },
00209 { "atmega64", 5, "__AVR_ATmega64__" },
00210 { "atmega645", 5, "__AVR_ATmega645__" },
00211 { "atmega6450", 5, "__AVR_ATmega6450__" },
00212 { "atmega128", 5, "__AVR_ATmega128__" },
00213 { "at90can128", 5, "__AVR_AT90CAN128__" },
00214 { "at94k", 5, "__AVR_AT94K__" },
00215
00216 { "avr1", 1, NULL },
00217 { "at90s1200", 1, "__AVR_AT90S1200__" },
00218 { "attiny11", 1, "__AVR_ATtiny11__" },
00219 { "attiny12", 1, "__AVR_ATtiny12__" },
00220 { "attiny15", 1, "__AVR_ATtiny15__" },
00221 { "attiny28", 1, "__AVR_ATtiny28__" },
00222 { NULL, 0, NULL }
00223 };
00224
00225 int avr_case_values_threshold = 30000;
00226
00227
00228 #undef TARGET_ASM_ALIGNED_HI_OP
00229 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
00230 #undef TARGET_ASM_ALIGNED_SI_OP
00231 #define TARGET_ASM_ALIGNED_SI_OP "\t.long\t"
00232 #undef TARGET_ASM_UNALIGNED_HI_OP
00233 #define TARGET_ASM_UNALIGNED_HI_OP "\t.word\t"
00234 #undef TARGET_ASM_UNALIGNED_SI_OP
00235 #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
00236 #undef TARGET_ASM_INTEGER
00237 #define TARGET_ASM_INTEGER avr_assemble_integer
00238 #undef TARGET_ASM_FILE_START
00239 #define TARGET_ASM_FILE_START avr_file_start
00240 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
00241 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
00242 #undef TARGET_ASM_FILE_END
00243 #define TARGET_ASM_FILE_END avr_file_end
00244
00245 #undef TARGET_ASM_FUNCTION_PROLOGUE
00246 #define TARGET_ASM_FUNCTION_PROLOGUE avr_output_function_prologue
00247 #undef TARGET_ASM_FUNCTION_EPILOGUE
00248 #define TARGET_ASM_FUNCTION_EPILOGUE avr_output_function_epilogue
00249 #undef TARGET_ATTRIBUTE_TABLE
00250 #define TARGET_ATTRIBUTE_TABLE avr_attribute_table
00251 #undef TARGET_ASM_FUNCTION_RODATA_SECTION
00252 #define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
00253 #undef TARGET_INSERT_ATTRIBUTES
00254 #define TARGET_INSERT_ATTRIBUTES avr_insert_attributes
00255 #undef TARGET_SECTION_TYPE_FLAGS
00256 #define TARGET_SECTION_TYPE_FLAGS avr_section_type_flags
00257 #undef TARGET_RTX_COSTS
00258 #define TARGET_RTX_COSTS avr_rtx_costs
00259 #undef TARGET_ADDRESS_COST
00260 #define TARGET_ADDRESS_COST avr_address_cost
00261 #undef TARGET_MACHINE_DEPENDENT_REORG
00262 #define TARGET_MACHINE_DEPENDENT_REORG avr_reorg
00263
00264 #undef TARGET_RETURN_IN_MEMORY
00265 #define TARGET_RETURN_IN_MEMORY avr_return_in_memory
00266
00267 #undef TARGET_STRICT_ARGUMENT_NAMING
00268 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
00269
00270 struct gcc_target targetm = TARGET_INITIALIZER;
00271
00272 void
00273 avr_override_options (void)
00274 {
00275 const struct mcu_type_s *t;
00276 const struct base_arch_s *base;
00277
00278 for (t = avr_mcu_types; t->name; t++)
00279 if (strcmp (t->name, avr_mcu_name) == 0)
00280 break;
00281
00282 if (!t->name)
00283 {
00284 fprintf (stderr, "unknown MCU `%s' specified\nKnown MCU names:\n",
00285 avr_mcu_name);
00286 for (t = avr_mcu_types; t->name; t++)
00287 fprintf (stderr," %s\n", t->name);
00288 }
00289
00290 base = &avr_arch_types[t->arch];
00291 avr_asm_only_p = base->asm_only;
00292 avr_enhanced_p = base->enhanced;
00293 avr_mega_p = base->mega;
00294 avr_base_arch_macro = base->macro;
00295 avr_extra_arch_macro = t->macro;
00296
00297 if (optimize && !TARGET_NO_TABLEJUMP)
00298 avr_case_values_threshold = (!AVR_MEGA || TARGET_CALL_PROLOGUES) ? 8 : 17;
00299
00300 tmp_reg_rtx = gen_rtx_REG (QImode, TMP_REGNO);
00301 zero_reg_rtx = gen_rtx_REG (QImode, ZERO_REGNO);
00302 }
00303
00304
00305
00306 static const int reg_class_tab[]={
00307 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
00308 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
00309 GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,GENERAL_REGS,
00310 GENERAL_REGS,
00311 LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,LD_REGS,
00312 LD_REGS,
00313 ADDW_REGS,ADDW_REGS,
00314 POINTER_X_REGS,POINTER_X_REGS,
00315 POINTER_Y_REGS,POINTER_Y_REGS,
00316 POINTER_Z_REGS,POINTER_Z_REGS,
00317 STACK_REG,STACK_REG
00318 };
00319
00320
00321
00322 enum reg_class
00323 avr_regno_reg_class (int r)
00324 {
00325 if (r <= 33)
00326 return reg_class_tab[r];
00327 return ALL_REGS;
00328 }
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 enum reg_class
00339 avr_reg_class_from_letter (int c)
00340 {
00341 switch (c)
00342 {
00343 case 't' : return R0_REG;
00344 case 'b' : return BASE_POINTER_REGS;
00345 case 'e' : return POINTER_REGS;
00346 case 'w' : return ADDW_REGS;
00347 case 'd' : return LD_REGS;
00348 case 'l' : return NO_LD_REGS;
00349 case 'a' : return SIMPLE_LD_REGS;
00350 case 'x' : return POINTER_X_REGS;
00351 case 'y' : return POINTER_Y_REGS;
00352 case 'z' : return POINTER_Z_REGS;
00353 case 'q' : return STACK_REG;
00354 default: break;
00355 }
00356 return NO_REGS;
00357 }
00358
00359
00360
00361 static int
00362 avr_naked_function_p (tree func)
00363 {
00364 tree a;
00365
00366 if (TREE_CODE (func) != FUNCTION_DECL)
00367 abort ();
00368
00369 a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
00370 return a != NULL_TREE;
00371 }
00372
00373
00374
00375
00376 static int
00377 interrupt_function_p (tree func)
00378 {
00379 tree a;
00380
00381 if (TREE_CODE (func) != FUNCTION_DECL)
00382 return 0;
00383
00384 a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
00385 return a != NULL_TREE;
00386 }
00387
00388
00389
00390
00391 static int
00392 signal_function_p (tree func)
00393 {
00394 tree a;
00395
00396 if (TREE_CODE (func) != FUNCTION_DECL)
00397 return 0;
00398
00399 a = lookup_attribute ("signal", DECL_ATTRIBUTES (func));
00400 return a != NULL_TREE;
00401 }
00402
00403
00404
00405
00406 static int
00407 avr_regs_to_save (HARD_REG_SET *set)
00408 {
00409 int reg, count;
00410 int int_or_sig_p = (interrupt_function_p (current_function_decl)
00411 || signal_function_p (current_function_decl));
00412 int leaf_func_p = leaf_function_p ();
00413
00414 if (set)
00415 CLEAR_HARD_REG_SET (*set);
00416 count = 0;
00417
00418
00419 if (TREE_THIS_VOLATILE (current_function_decl))
00420 return 0;
00421
00422 for (reg = 0; reg < 32; reg++)
00423 {
00424
00425
00426 if (fixed_regs[reg])
00427 continue;
00428
00429 if ((int_or_sig_p && !leaf_func_p && call_used_regs[reg])
00430 || (regs_ever_live[reg]
00431 && (int_or_sig_p || !call_used_regs[reg])
00432 && !(frame_pointer_needed
00433 && (reg == REG_Y || reg == (REG_Y+1)))))
00434 {
00435 if (set)
00436 SET_HARD_REG_BIT (*set, reg);
00437 count++;
00438 }
00439 }
00440 return count;
00441 }
00442
00443
00444
00445 int
00446 initial_elimination_offset (int from, int to)
00447 {
00448 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
00449 return 0;
00450 else
00451 {
00452 int offset = frame_pointer_needed ? 2 : 0;
00453
00454 offset += avr_regs_to_save (NULL);
00455 return get_frame_size () + 2 + 1 + offset;
00456 }
00457 }
00458
00459
00460
00461 int
00462 avr_simple_epilogue (void)
00463 {
00464 return (! frame_pointer_needed
00465 && get_frame_size () == 0
00466 && avr_regs_to_save (NULL) == 0
00467 && ! interrupt_function_p (current_function_decl)
00468 && ! signal_function_p (current_function_decl)
00469 && ! avr_naked_function_p (current_function_decl)
00470 && ! MAIN_NAME_P (DECL_NAME (current_function_decl))
00471 && ! TREE_THIS_VOLATILE (current_function_decl));
00472 }
00473
00474
00475
00476 static int
00477 sequent_regs_live (void)
00478 {
00479 int reg;
00480 int live_seq=0;
00481 int cur_seq=0;
00482
00483 for (reg = 0; reg < 18; ++reg)
00484 {
00485 if (!call_used_regs[reg])
00486 {
00487 if (regs_ever_live[reg])
00488 {
00489 ++live_seq;
00490 ++cur_seq;
00491 }
00492 else
00493 cur_seq = 0;
00494 }
00495 }
00496
00497 if (!frame_pointer_needed)
00498 {
00499 if (regs_ever_live[REG_Y])
00500 {
00501 ++live_seq;
00502 ++cur_seq;
00503 }
00504 else
00505 cur_seq = 0;
00506
00507 if (regs_ever_live[REG_Y+1])
00508 {
00509 ++live_seq;
00510 ++cur_seq;
00511 }
00512 else
00513 cur_seq = 0;
00514 }
00515 else
00516 {
00517 cur_seq += 2;
00518 live_seq += 2;
00519 }
00520 return (cur_seq == live_seq) ? live_seq : 0;
00521 }
00522
00523
00524
00525
00526
00527
00528 static int
00529 out_adj_frame_ptr (FILE *file, int adj)
00530 {
00531 int size = 0;
00532
00533 if (adj)
00534 {
00535 if (TARGET_TINY_STACK)
00536 {
00537 if (adj < -63 || adj > 63)
00538 warning ("large frame pointer change (%d) with -mtiny-stack", adj);
00539
00540
00541
00542
00543 fprintf (file, (AS2 (subi, r28, %d) CR_TAB), adj);
00544 size++;
00545 }
00546 else if (adj < -63 || adj > 63)
00547 {
00548 fprintf (file, (AS2 (subi, r28, lo8(%d)) CR_TAB
00549 AS2 (sbci, r29, hi8(%d)) CR_TAB),
00550 adj, adj);
00551 size += 2;
00552 }
00553 else if (adj < 0)
00554 {
00555 fprintf (file, (AS2 (adiw, r28, %d) CR_TAB), -adj);
00556 size++;
00557 }
00558 else
00559 {
00560 fprintf (file, (AS2 (sbiw, r28, %d) CR_TAB), adj);
00561 size++;
00562 }
00563 }
00564 return size;
00565 }
00566
00567
00568
00569
00570
00571
00572
00573 static int
00574 out_set_stack_ptr (FILE *file, int before, int after)
00575 {
00576 int do_sph, do_cli, do_save, do_sei, lock_sph, size;
00577
00578
00579
00580
00581
00582
00583 do_sph = !TARGET_TINY_STACK;
00584 lock_sph = do_sph && !TARGET_NO_INTERRUPTS;
00585 do_cli = (before != 0 && (after == 0 || lock_sph));
00586 do_save = (do_cli && before == -1 && after == -1);
00587 do_sei = ((do_cli || before != 1) && after == 1);
00588 size = 1;
00589
00590 if (do_save)
00591 {
00592 fprintf (file, AS2 (in, __tmp_reg__, __SREG__) CR_TAB);
00593 size++;
00594 }
00595
00596 if (do_cli)
00597 {
00598 fprintf (file, "cli" CR_TAB);
00599 size++;
00600 }
00601
00602
00603
00604
00605 if (do_sph)
00606 {
00607 fprintf (file, AS2 (out, __SP_H__, r29) CR_TAB);
00608 size++;
00609 }
00610
00611
00612
00613
00614 if (do_save)
00615 {
00616 fprintf (file, AS2 (out, __SREG__, __tmp_reg__) CR_TAB);
00617 size++;
00618 }
00619 else if (do_sei)
00620 {
00621 fprintf (file, "sei" CR_TAB);
00622 size++;
00623 }
00624
00625 fprintf (file, AS2 (out, __SP_L__, r28) "\n");
00626
00627 return size;
00628 }
00629
00630
00631
00632
00633 static void
00634 avr_output_function_prologue (FILE *file, HOST_WIDE_INT size)
00635 {
00636 int reg;
00637 int interrupt_func_p;
00638 int signal_func_p;
00639 int main_p;
00640 int live_seq;
00641 int minimize;
00642
00643 last_insn_address = 0;
00644 jump_tables_size = 0;
00645 prologue_size = 0;
00646 fprintf (file, "/* prologue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n",
00647 size);
00648
00649 if (avr_naked_function_p (current_function_decl))
00650 {
00651 fputs ("/* prologue: naked */\n", file);
00652 goto out;
00653 }
00654
00655 interrupt_func_p = interrupt_function_p (current_function_decl);
00656 signal_func_p = signal_function_p (current_function_decl);
00657 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
00658 live_seq = sequent_regs_live ();
00659 minimize = (TARGET_CALL_PROLOGUES
00660 && !interrupt_func_p && !signal_func_p && live_seq);
00661
00662 if (interrupt_func_p)
00663 {
00664 fprintf (file,"\tsei\n");
00665 ++prologue_size;
00666 }
00667 if (interrupt_func_p || signal_func_p)
00668 {
00669 fprintf (file, "\t"
00670 AS1 (push,__zero_reg__) CR_TAB
00671 AS1 (push,__tmp_reg__) CR_TAB
00672 AS2 (in,__tmp_reg__,__SREG__) CR_TAB
00673 AS1 (push,__tmp_reg__) CR_TAB
00674 AS1 (clr,__zero_reg__) "\n");
00675 prologue_size += 5;
00676 }
00677 if (main_p)
00678 {
00679 fprintf (file, ("\t"
00680 AS1 (ldi,r28) ",lo8(%s - " HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
00681 AS1 (ldi,r29) ",hi8(%s - " HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
00682 AS2 (out,__SP_H__,r29) CR_TAB
00683 AS2 (out,__SP_L__,r28) "\n"),
00684 avr_init_stack, size, avr_init_stack, size);
00685
00686 prologue_size += 4;
00687 }
00688 else if (minimize && (frame_pointer_needed || live_seq > 6))
00689 {
00690 fprintf (file, ("\t"
00691 AS1 (ldi, r26) ",lo8(" HOST_WIDE_INT_PRINT_DEC ")" CR_TAB
00692 AS1 (ldi, r27) ",hi8(" HOST_WIDE_INT_PRINT_DEC ")" CR_TAB), size, size);
00693
00694 fputs ((AS2 (ldi,r30,pm_lo8(1f)) CR_TAB
00695 AS2 (ldi,r31,pm_hi8(1f)) CR_TAB), file);
00696
00697 prologue_size += 4;
00698
00699 if (AVR_MEGA)
00700 {
00701 fprintf (file, AS1 (jmp,__prologue_saves__+%d) "\n",
00702 (18 - live_seq) * 2);
00703 prologue_size += 2;
00704 }
00705 else
00706 {
00707 fprintf (file, AS1 (rjmp,__prologue_saves__+%d) "\n",
00708 (18 - live_seq) * 2);
00709 ++prologue_size;
00710 }
00711 fputs ("1:\n", file);
00712 }
00713 else
00714 {
00715 HARD_REG_SET set;
00716
00717 prologue_size += avr_regs_to_save (&set);
00718 for (reg = 0; reg < 32; ++reg)
00719 {
00720 if (TEST_HARD_REG_BIT (set, reg))
00721 {
00722 fprintf (file, "\t" AS1 (push,%s) "\n", avr_regnames[reg]);
00723 }
00724 }
00725 if (frame_pointer_needed)
00726 {
00727 fprintf (file, "\t"
00728 AS1 (push,r28) CR_TAB
00729 AS1 (push,r29) CR_TAB
00730 AS2 (in,r28,__SP_L__) CR_TAB
00731 AS2 (in,r29,__SP_H__) "\n");
00732 prologue_size += 4;
00733 if (size)
00734 {
00735 fputs ("\t", file);
00736 prologue_size += out_adj_frame_ptr (file, size);
00737
00738 if (interrupt_func_p)
00739 {
00740 prologue_size += out_set_stack_ptr (file, 1, 1);
00741 }
00742 else if (signal_func_p)
00743 {
00744 prologue_size += out_set_stack_ptr (file, 0, 0);
00745 }
00746 else
00747 {
00748 prologue_size += out_set_stack_ptr (file, -1, -1);
00749 }
00750 }
00751 }
00752 }
00753
00754 out:
00755 fprintf (file, "/* prologue end (size=%d) */\n", prologue_size);
00756 }
00757
00758
00759
00760 static void
00761 avr_output_function_epilogue (FILE *file, HOST_WIDE_INT size)
00762 {
00763 int reg;
00764 int interrupt_func_p;
00765 int signal_func_p;
00766 int main_p;
00767 int function_size;
00768 int live_seq;
00769 int minimize;
00770 rtx last = get_last_nonnote_insn ();
00771
00772 function_size = jump_tables_size;
00773 if (last)
00774 {
00775 rtx first = get_first_nonnote_insn ();
00776 function_size += (INSN_ADDRESSES (INSN_UID (last)) -
00777 INSN_ADDRESSES (INSN_UID (first)));
00778 function_size += get_attr_length (last);
00779 }
00780
00781 fprintf (file, "/* epilogue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n", size);
00782 epilogue_size = 0;
00783
00784 if (avr_naked_function_p (current_function_decl))
00785 {
00786 fputs ("/* epilogue: naked */\n", file);
00787 goto out;
00788 }
00789
00790 if (last && GET_CODE (last) == BARRIER)
00791 {
00792 fputs ("/* epilogue: noreturn */\n", file);
00793 goto out;
00794 }
00795
00796 interrupt_func_p = interrupt_function_p (current_function_decl);
00797 signal_func_p = signal_function_p (current_function_decl);
00798 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
00799 live_seq = sequent_regs_live ();
00800 minimize = (TARGET_CALL_PROLOGUES
00801 && !interrupt_func_p && !signal_func_p && live_seq);
00802
00803 if (main_p)
00804 {
00805
00806
00807 if (AVR_MEGA)
00808 {
00809 fputs ("\t" AS1 (jmp,exit) "\n", file);
00810 epilogue_size += 2;
00811 }
00812 else
00813 {
00814 fputs ("\t" AS1 (rjmp,exit) "\n", file);
00815 ++epilogue_size;
00816 }
00817 }
00818 else if (minimize && (frame_pointer_needed || live_seq > 4))
00819 {
00820 fprintf (file, ("\t" AS2 (ldi, r30, %d) CR_TAB), live_seq);
00821 ++epilogue_size;
00822 if (frame_pointer_needed)
00823 {
00824 epilogue_size += out_adj_frame_ptr (file, -size);
00825 }
00826 else
00827 {
00828 fprintf (file, (AS2 (in , r28, __SP_L__) CR_TAB
00829 AS2 (in , r29, __SP_H__) CR_TAB));
00830 epilogue_size += 2;
00831 }
00832
00833 if (AVR_MEGA)
00834 {
00835 fprintf (file, AS1 (jmp,__epilogue_restores__+%d) "\n",
00836 (18 - live_seq) * 2);
00837 epilogue_size += 2;
00838 }
00839 else
00840 {
00841 fprintf (file, AS1 (rjmp,__epilogue_restores__+%d) "\n",
00842 (18 - live_seq) * 2);
00843 ++epilogue_size;
00844 }
00845 }
00846 else
00847 {
00848 HARD_REG_SET set;
00849
00850 if (frame_pointer_needed)
00851 {
00852 if (size)
00853 {
00854 fputs ("\t", file);
00855 epilogue_size += out_adj_frame_ptr (file, -size);
00856
00857 if (interrupt_func_p || signal_func_p)
00858 {
00859 epilogue_size += out_set_stack_ptr (file, -1, 0);
00860 }
00861 else
00862 {
00863 epilogue_size += out_set_stack_ptr (file, -1, -1);
00864 }
00865 }
00866 fprintf (file, "\t"
00867 AS1 (pop,r29) CR_TAB
00868 AS1 (pop,r28) "\n");
00869 epilogue_size += 2;
00870 }
00871
00872 epilogue_size += avr_regs_to_save (&set);
00873 for (reg = 31; reg >= 0; --reg)
00874 {
00875 if (TEST_HARD_REG_BIT (set, reg))
00876 {
00877 fprintf (file, "\t" AS1 (pop,%s) "\n", avr_regnames[reg]);
00878 }
00879 }
00880
00881 if (interrupt_func_p || signal_func_p)
00882 {
00883 fprintf (file, "\t"
00884 AS1 (pop,__tmp_reg__) CR_TAB
00885 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
00886 AS1 (pop,__tmp_reg__) CR_TAB
00887 AS1 (pop,__zero_reg__) "\n");
00888 epilogue_size += 4;
00889 fprintf (file, "\treti\n");
00890 }
00891 else
00892 fprintf (file, "\tret\n");
00893 ++epilogue_size;
00894 }
00895
00896 out:
00897 fprintf (file, "/* epilogue end (size=%d) */\n", epilogue_size);
00898 fprintf (file, "/* function %s size %d (%d) */\n", current_function_name (),
00899 prologue_size + function_size + epilogue_size, function_size);
00900 commands_in_file += prologue_size + function_size + epilogue_size;
00901 commands_in_prologues += prologue_size;
00902 commands_in_epilogues += epilogue_size;
00903 }
00904
00905
00906
00907
00908
00909 int
00910 legitimate_address_p (enum machine_mode mode, rtx x, int strict)
00911 {
00912 enum reg_class r = NO_REGS;
00913
00914 if (TARGET_ALL_DEBUG)
00915 {
00916 fprintf (stderr, "mode: (%s) %s %s %s %s:",
00917 GET_MODE_NAME(mode),
00918 strict ? "(strict)": "",
00919 reload_completed ? "(reload_completed)": "",
00920 reload_in_progress ? "(reload_in_progress)": "",
00921 reg_renumber ? "(reg_renumber)" : "");
00922 if (GET_CODE (x) == PLUS
00923 && REG_P (XEXP (x, 0))
00924 && GET_CODE (XEXP (x, 1)) == CONST_INT
00925 && INTVAL (XEXP (x, 1)) >= 0
00926 && INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode)
00927 && reg_renumber
00928 )
00929 fprintf (stderr, "(r%d ---> r%d)", REGNO (XEXP (x, 0)),
00930 true_regnum (XEXP (x, 0)));
00931 debug_rtx (x);
00932 }
00933 if (REG_P (x) && (strict ? REG_OK_FOR_BASE_STRICT_P (x)
00934 : REG_OK_FOR_BASE_NOSTRICT_P (x)))
00935 r = POINTER_REGS;
00936 else if (CONSTANT_ADDRESS_P (x))
00937 r = ALL_REGS;
00938 else if (GET_CODE (x) == PLUS
00939 && REG_P (XEXP (x, 0))
00940 && GET_CODE (XEXP (x, 1)) == CONST_INT
00941 && INTVAL (XEXP (x, 1)) >= 0)
00942 {
00943 int fit = INTVAL (XEXP (x, 1)) <= MAX_LD_OFFSET (mode);
00944 if (fit)
00945 {
00946 if (! strict
00947 || REGNO (XEXP (x,0)) == REG_Y
00948 || REGNO (XEXP (x,0)) == REG_Z)
00949 r = BASE_POINTER_REGS;
00950 if (XEXP (x,0) == frame_pointer_rtx
00951 || XEXP (x,0) == arg_pointer_rtx)
00952 r = BASE_POINTER_REGS;
00953 }
00954 else if (frame_pointer_needed && XEXP (x,0) == frame_pointer_rtx)
00955 r = POINTER_Y_REGS;
00956 }
00957 else if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC)
00958 && REG_P (XEXP (x, 0))
00959 && (strict ? REG_OK_FOR_BASE_STRICT_P (XEXP (x, 0))
00960 : REG_OK_FOR_BASE_NOSTRICT_P (XEXP (x, 0))))
00961 {
00962 r = POINTER_REGS;
00963 }
00964 if (TARGET_ALL_DEBUG)
00965 {
00966 fprintf (stderr, " ret = %c\n", r);
00967 }
00968 return r == NO_REGS ? 0 : (int)r;
00969 }
00970
00971
00972
00973
00974 rtx
00975 legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
00976 {
00977 x = oldx;
00978 if (TARGET_ALL_DEBUG)
00979 {
00980 fprintf (stderr, "legitimize_address mode: %s", GET_MODE_NAME(mode));
00981 debug_rtx (oldx);
00982 }
00983
00984 if (GET_CODE (oldx) == PLUS
00985 && REG_P (XEXP (oldx,0)))
00986 {
00987 if (REG_P (XEXP (oldx,1)))
00988 x = force_reg (GET_MODE (oldx), oldx);
00989 else if (GET_CODE (XEXP (oldx, 1)) == CONST_INT)
00990 {
00991 int offs = INTVAL (XEXP (oldx,1));
00992 if (frame_pointer_rtx != XEXP (oldx,0))
00993 if (offs > MAX_LD_OFFSET (mode))
00994 {
00995 if (TARGET_ALL_DEBUG)
00996 fprintf (stderr, "force_reg (big offset)\n");
00997 x = force_reg (GET_MODE (oldx), oldx);
00998 }
00999 }
01000 }
01001 return x;
01002 }
01003
01004
01005
01006
01007 static const char *
01008 ptrreg_to_str (int regno)
01009 {
01010 switch (regno)
01011 {
01012 case REG_X: return "X";
01013 case REG_Y: return "Y";
01014 case REG_Z: return "Z";
01015 default:
01016 abort ();
01017 }
01018 return NULL;
01019 }
01020
01021
01022
01023
01024 static const char *
01025 cond_string (enum rtx_code code)
01026 {
01027 switch (code)
01028 {
01029 case NE:
01030 return "ne";
01031 case EQ:
01032 return "eq";
01033 case GE:
01034 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
01035 return "pl";
01036 else
01037 return "ge";
01038 case LT:
01039 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
01040 return "mi";
01041 else
01042 return "lt";
01043 case GEU:
01044 return "sh";
01045 case LTU:
01046 return "lo";
01047 default:
01048 abort ();
01049 }
01050 }
01051
01052
01053
01054 void
01055 print_operand_address (FILE *file, rtx addr)
01056 {
01057 switch (GET_CODE (addr))
01058 {
01059 case REG:
01060 fprintf (file, ptrreg_to_str (REGNO (addr)));
01061 break;
01062
01063 case PRE_DEC:
01064 fprintf (file, "-%s", ptrreg_to_str (REGNO (XEXP (addr, 0))));
01065 break;
01066
01067 case POST_INC:
01068 fprintf (file, "%s+", ptrreg_to_str (REGNO (XEXP (addr, 0))));
01069 break;
01070
01071 default:
01072 if (CONSTANT_ADDRESS_P (addr)
01073 && ((GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (addr))
01074 || GET_CODE (addr) == LABEL_REF))
01075 {
01076 fprintf (file, "pm(");
01077 output_addr_const (file,addr);
01078 fprintf (file ,")");
01079 }
01080 else
01081 output_addr_const (file, addr);
01082 }
01083 }
01084
01085
01086
01087
01088 void
01089 print_operand (FILE *file, rtx x, int code)
01090 {
01091 int abcd = 0;
01092
01093 if (code >= 'A' && code <= 'D')
01094 abcd = code - 'A';
01095
01096 if (code == '~')
01097 {
01098 if (!AVR_MEGA)
01099 fputc ('r', file);
01100 }
01101 else if (REG_P (x))
01102 {
01103 if (x == zero_reg_rtx)
01104 fprintf (file, "__zero_reg__");
01105 else
01106 fprintf (file, reg_names[true_regnum (x) + abcd]);
01107 }
01108 else if (GET_CODE (x) == CONST_INT)
01109 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) + abcd);
01110 else if (GET_CODE (x) == MEM)
01111 {
01112 rtx addr = XEXP (x,0);
01113
01114 if (CONSTANT_P (addr) && abcd)
01115 {
01116 fputc ('(', file);
01117 output_address (addr);
01118 fprintf (file, ")+%d", abcd);
01119 }
01120 else if (code == 'o')
01121 {
01122 if (GET_CODE (addr) != PLUS)
01123 fatal_insn ("bad address, not (reg+disp):", addr);
01124
01125 print_operand (file, XEXP (addr, 1), 0);
01126 }
01127 else if (code == 'p' || code == 'r')
01128 {
01129 if (GET_CODE (addr) != POST_INC && GET_CODE (addr) != PRE_DEC)
01130 fatal_insn ("bad address, not post_inc or pre_dec:", addr);
01131
01132 if (code == 'p')
01133 print_operand_address (file, XEXP (addr, 0));
01134 else
01135 print_operand (file, XEXP (addr, 0), 0);
01136 }
01137 else if (GET_CODE (addr) == PLUS)
01138 {
01139 print_operand_address (file, XEXP (addr,0));
01140 if (REGNO (XEXP (addr, 0)) == REG_X)
01141 fatal_insn ("internal compiler error. Bad address:"
01142 ,addr);
01143 fputc ('+', file);
01144 print_operand (file, XEXP (addr,1), code);
01145 }
01146 else
01147 print_operand_address (file, addr);
01148 }
01149 else if (GET_CODE (x) == CONST_DOUBLE)
01150 {
01151 long val;
01152 REAL_VALUE_TYPE rv;
01153 if (GET_MODE (x) != SFmode)
01154 fatal_insn ("internal compiler error. Unknown mode:", x);
01155 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
01156 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
01157 fprintf (file, "0x%lx", val);
01158 }
01159 else if (code == 'j')
01160 fputs (cond_string (GET_CODE (x)), file);
01161 else if (code == 'k')
01162 fputs (cond_string (reverse_condition (GET_CODE (x))), file);
01163 else
01164 print_operand_address (file, x);
01165 }
01166
01167
01168
01169 int
01170 call_insn_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01171 {
01172 if (GET_CODE (op) == MEM)
01173 {
01174 rtx inside = XEXP (op, 0);
01175 if (register_operand (inside, Pmode))
01176 return 1;
01177 if (CONSTANT_ADDRESS_P (inside))
01178 return 1;
01179 }
01180 return 0;
01181 }
01182
01183
01184
01185 void
01186 notice_update_cc (rtx body ATTRIBUTE_UNUSED, rtx insn)
01187 {
01188 rtx set;
01189
01190 switch (get_attr_cc (insn))
01191 {
01192 case CC_NONE:
01193
01194 break;
01195
01196 case CC_SET_N:
01197 CC_STATUS_INIT;
01198 break;
01199
01200 case CC_SET_ZN:
01201 set = single_set (insn);
01202 CC_STATUS_INIT;
01203 if (set)
01204 {
01205 cc_status.flags |= CC_NO_OVERFLOW;
01206 cc_status.value1 = SET_DEST (set);
01207 }
01208 break;
01209
01210 case CC_SET_CZN:
01211
01212
01213
01214 set = single_set (insn);
01215 CC_STATUS_INIT;
01216 if (set)
01217 {
01218 cc_status.value1 = SET_DEST (set);
01219 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
01220 }
01221 break;
01222
01223 case CC_COMPARE:
01224 set = single_set (insn);
01225 CC_STATUS_INIT;
01226 if (set)
01227 cc_status.value1 = SET_SRC (set);
01228 break;
01229
01230 case CC_CLOBBER:
01231
01232 CC_STATUS_INIT;
01233
01234
01235 set = single_set (insn);
01236 if (set)
01237 {
01238 rtx src = SET_SRC (set);
01239
01240 if (GET_CODE (src) == ASHIFTRT
01241 && GET_MODE (src) == QImode)
01242 {
01243 rtx x = XEXP (src, 1);
01244
01245 if (GET_CODE (x) == CONST_INT
01246 && INTVAL (x) > 0
01247 && INTVAL (x) != 6)
01248 {
01249 cc_status.value1 = SET_DEST (set);
01250 cc_status.flags |= CC_OVERFLOW_UNUSABLE;
01251 }
01252 }
01253 }
01254 break;
01255 }
01256 }
01257
01258
01259
01260
01261 int
01262 class_max_nregs (enum reg_class class ATTRIBUTE_UNUSED,enum machine_mode mode)
01263 {
01264 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
01265 }
01266
01267
01268
01269
01270
01271
01272 int
01273 avr_jump_mode (rtx x, rtx insn)
01274 {
01275 int dest_addr = INSN_ADDRESSES (INSN_UID (GET_MODE (x) == LABEL_REF
01276 ? XEXP (x, 0) : x));
01277 int cur_addr = INSN_ADDRESSES (INSN_UID (insn));
01278 int jump_distance = cur_addr - dest_addr;
01279
01280 if (-63 <= jump_distance && jump_distance <= 62)
01281 return 1;
01282 else if (-2046 <= jump_distance && jump_distance <= 2045)
01283 return 2;
01284 else if (AVR_MEGA)
01285 return 3;
01286
01287 return 2;
01288 }
01289
01290
01291
01292
01293
01294
01295 const char *
01296 ret_cond_branch (rtx x, int len, int reverse)
01297 {
01298 RTX_CODE cond = reverse ? reverse_condition (GET_CODE (x)) : GET_CODE (x);
01299
01300 switch (cond)
01301 {
01302 case GT:
01303 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
01304 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
01305 AS1 (brpl,%0)) :
01306 len == 2 ? (AS1 (breq,.+4) CR_TAB
01307 AS1 (brmi,.+2) CR_TAB
01308 AS1 (rjmp,%0)) :
01309 (AS1 (breq,.+6) CR_TAB
01310 AS1 (brmi,.+4) CR_TAB
01311 AS1 (jmp,%0)));
01312
01313 else
01314 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
01315 AS1 (brge,%0)) :
01316 len == 2 ? (AS1 (breq,.+4) CR_TAB
01317 AS1 (brlt,.+2) CR_TAB
01318 AS1 (rjmp,%0)) :
01319 (AS1 (breq,.+6) CR_TAB
01320 AS1 (brlt,.+4) CR_TAB
01321 AS1 (jmp,%0)));
01322 case GTU:
01323 return (len == 1 ? (AS1 (breq,.+2) CR_TAB
01324 AS1 (brsh,%0)) :
01325 len == 2 ? (AS1 (breq,.+4) CR_TAB
01326 AS1 (brlo,.+2) CR_TAB
01327 AS1 (rjmp,%0)) :
01328 (AS1 (breq,.+6) CR_TAB
01329 AS1 (brlo,.+4) CR_TAB
01330 AS1 (jmp,%0)));
01331 case LE:
01332 if (cc_prev_status.flags & CC_OVERFLOW_UNUSABLE)
01333 return (len == 1 ? (AS1 (breq,%0) CR_TAB
01334 AS1 (brmi,%0)) :
01335 len == 2 ? (AS1 (breq,.+2) CR_TAB
01336 AS1 (brpl,.+2) CR_TAB
01337 AS1 (rjmp,%0)) :
01338 (AS1 (breq,.+2) CR_TAB
01339 AS1 (brpl,.+4) CR_TAB
01340 AS1 (jmp,%0)));
01341 else
01342 return (len == 1 ? (AS1 (breq,%0) CR_TAB
01343 AS1 (brlt,%0)) :
01344 len == 2 ? (AS1 (breq,.+2) CR_TAB
01345 AS1 (brge,.+2) CR_TAB
01346 AS1 (rjmp,%0)) :
01347 (AS1 (breq,.+2) CR_TAB
01348 AS1 (brge,.+4) CR_TAB
01349 AS1 (jmp,%0)));
01350 case LEU:
01351 return (len == 1 ? (AS1 (breq,%0) CR_TAB
01352 AS1 (brlo,%0)) :
01353 len == 2 ? (AS1 (breq,.+2) CR_TAB
01354 AS1 (brsh,.+2) CR_TAB
01355 AS1 (rjmp,%0)) :
01356 (AS1 (breq,.+2) CR_TAB
01357 AS1 (brsh,.+4) CR_TAB
01358 AS1 (jmp,%0)));
01359 default:
01360 if (reverse)
01361 {
01362 switch (len)
01363 {
01364 case 1:
01365 return AS1 (br%k1,%0);
01366 case 2:
01367 return (AS1 (br%j1,.+2) CR_TAB
01368 AS1 (rjmp,%0));
01369 default:
01370 return (AS1 (br%j1,.+4) CR_TAB
01371 AS1 (jmp,%0));
01372 }
01373 }
01374 else
01375 {
01376 switch (len)
01377 {
01378 case 1:
01379 return AS1 (br%j1,%0);
01380 case 2:
01381 return (AS1 (br%k1,.+2) CR_TAB
01382 AS1 (rjmp,%0));
01383 default:
01384 return (AS1 (br%k1,.+4) CR_TAB
01385 AS1 (jmp,%0));
01386 }
01387 }
01388 }
01389 return "";
01390 }
01391
01392
01393
01394 int
01395 byte_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01396 {
01397 return (GET_CODE (op) == CONST_INT
01398 && INTVAL (op) <= 0xff && INTVAL (op) >= 0);
01399 }
01400
01401
01402
01403
01404
01405
01406 void
01407 final_prescan_insn (rtx insn, rtx *operand ATTRIBUTE_UNUSED,
01408 int num_operands ATTRIBUTE_UNUSED)
01409 {
01410 int uid = INSN_UID (insn);
01411
01412 if (TARGET_INSN_SIZE_DUMP || TARGET_ALL_DEBUG)
01413 {
01414 fprintf (asm_out_file, "/*DEBUG: 0x%x\t\t%d\t%d */\n",
01415 INSN_ADDRESSES (uid),
01416 INSN_ADDRESSES (uid) - last_insn_address,
01417 rtx_cost (PATTERN (insn), INSN));
01418 }
01419 last_insn_address = INSN_ADDRESSES (uid);
01420 }
01421
01422
01423
01424 int
01425 avr_simplify_comparison_p (enum machine_mode mode, RTX_CODE operator, rtx x)
01426 {
01427 unsigned int max = (mode == QImode ? 0xff :
01428 mode == HImode ? 0xffff :
01429 mode == SImode ? 0xffffffff : 0);
01430 if (max && operator && GET_CODE (x) == CONST_INT)
01431 {
01432 if (unsigned_condition (operator) != operator)
01433 max >>= 1;
01434
01435 if (max != (INTVAL (x) & max)
01436 && INTVAL (x) != 0xff)
01437 return 1;
01438 }
01439 return 0;
01440 }
01441
01442
01443
01444
01445
01446 int
01447 function_arg_regno_p(int r)
01448 {
01449 return (r >= 8 && r <= 25);
01450 }
01451
01452
01453
01454
01455 void
01456 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
01457 tree fndecl ATTRIBUTE_UNUSED)
01458 {
01459 cum->nregs = 18;
01460 cum->regno = FIRST_CUM_REG;
01461 if (!libname && fntype)
01462 {
01463 int stdarg = (TYPE_ARG_TYPES (fntype) != 0
01464 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
01465 != void_type_node));
01466 if (stdarg)
01467 cum->nregs = 0;
01468 }
01469 }
01470
01471
01472
01473 static int
01474 avr_num_arg_regs (enum machine_mode mode, tree type)
01475 {
01476 int size;
01477
01478 if (mode == BLKmode)
01479 size = int_size_in_bytes (type);
01480 else
01481 size = GET_MODE_SIZE (mode);
01482
01483
01484
01485
01486 return (size + 1) & ~1;
01487 }
01488
01489
01490
01491
01492 rtx
01493 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
01494 int named ATTRIBUTE_UNUSED)
01495 {
01496 int bytes = avr_num_arg_regs (mode, type);
01497
01498 if (cum->nregs && bytes <= cum->nregs)
01499 return gen_rtx_REG (mode, cum->regno - bytes);
01500
01501 return NULL_RTX;
01502 }
01503
01504
01505
01506
01507 void
01508 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
01509 int named ATTRIBUTE_UNUSED)
01510 {
01511 int bytes = avr_num_arg_regs (mode, type);
01512
01513 cum->nregs -= bytes;
01514 cum->regno -= bytes;
01515
01516 if (cum->nregs <= 0)
01517 {
01518 cum->nregs = 0;
01519 cum->regno = FIRST_CUM_REG;
01520 }
01521 }
01522
01523
01524
01525
01526 const char *
01527 output_movqi (rtx insn, rtx operands[], int *l)
01528 {
01529 int dummy;
01530 rtx dest = operands[0];
01531 rtx src = operands[1];
01532 int *real_l = l;
01533
01534 if (!l)
01535 l = &dummy;
01536
01537 *l = 1;
01538
01539 if (register_operand (dest, QImode))
01540 {
01541 if (register_operand (src, QImode))
01542 {
01543 if (test_hard_reg_class (STACK_REG, dest))
01544 return AS2 (out,%0,%1);
01545 else if (test_hard_reg_class (STACK_REG, src))
01546 return AS2 (in,%0,%1);
01547
01548 return AS2 (mov,%0,%1);
01549 }
01550 else if (CONSTANT_P (src))
01551 {
01552 if (test_hard_reg_class (LD_REGS, dest))
01553 return AS2 (ldi,%0,lo8(%1));
01554
01555 if (GET_CODE (src) == CONST_INT)
01556 {
01557 if (src == const0_rtx)
01558 return AS1 (clr,%0);
01559 else if (src == const1_rtx)
01560 {
01561 *l = 2;
01562 return (AS1 (clr,%0) CR_TAB
01563 AS1 (inc,%0));
01564 }
01565 else if (src == constm1_rtx)
01566 {
01567
01568 *l = 2;
01569 return (AS1 (clr,%0) CR_TAB
01570 AS1 (dec,%0));
01571 }
01572 else
01573 {
01574 int bit_nr = exact_log2 (INTVAL (src));
01575
01576 if (bit_nr >= 0)
01577 {
01578 *l = 3;
01579 if (!real_l)
01580 output_asm_insn ((AS1 (clr,%0) CR_TAB
01581 "set"), operands);
01582 if (!real_l)
01583 avr_output_bld (operands, bit_nr);
01584
01585 return "";
01586 }
01587 }
01588 }
01589
01590
01591 *l = 4;
01592 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
01593 AS2 (ldi,r31,lo8(%1)) CR_TAB
01594 AS2 (mov,%0,r31) CR_TAB
01595 AS2 (mov,r31,__tmp_reg__));
01596 }
01597 else if (GET_CODE (src) == MEM)
01598 return out_movqi_r_mr (insn, operands, real_l);
01599 }
01600 else if (GET_CODE (dest) == MEM)
01601 {
01602 const char *template;
01603
01604 if (src == const0_rtx)
01605 operands[1] = zero_reg_rtx;
01606
01607 template = out_movqi_mr_r (insn, operands, real_l);
01608
01609 if (!real_l)
01610 output_asm_insn (template, operands);
01611
01612 operands[1] = src;
01613 }
01614 return "";
01615 }
01616
01617
01618 const char *
01619 output_movhi (rtx insn, rtx operands[], int *l)
01620 {
01621 int dummy;
01622 rtx dest = operands[0];
01623 rtx src = operands[1];
01624 int *real_l = l;
01625
01626 if (!l)
01627 l = &dummy;
01628
01629 if (register_operand (dest, HImode))
01630 {
01631 if (register_operand (src, HImode))
01632 {
01633 if (test_hard_reg_class (STACK_REG, dest))
01634 {
01635 if (TARGET_TINY_STACK)
01636 {
01637 *l = 1;
01638 return AS2 (out,__SP_L__,%A1);
01639 }
01640 else if (TARGET_NO_INTERRUPTS)
01641 {
01642 *l = 2;
01643 return (AS2 (out,__SP_H__,%B1) CR_TAB
01644 AS2 (out,__SP_L__,%A1));
01645 }
01646
01647 *l = 5;
01648 return (AS2 (in,__tmp_reg__,__SREG__) CR_TAB
01649 "cli" CR_TAB
01650 AS2 (out,__SP_H__,%B1) CR_TAB
01651 AS2 (out,__SREG__,__tmp_reg__) CR_TAB
01652 AS2 (out,__SP_L__,%A1));
01653 }
01654 else if (test_hard_reg_class (STACK_REG, src))
01655 {
01656 *l = 2;
01657 return (AS2 (in,%A0,__SP_L__) CR_TAB
01658 AS2 (in,%B0,__SP_H__));
01659 }
01660
01661 if (AVR_ENHANCED)
01662 {
01663 *l = 1;
01664 return (AS2 (movw,%0,%1));
01665 }
01666
01667 if (true_regnum (dest) > true_regnum (src))
01668 {
01669 *l = 2;
01670 return (AS2 (mov,%B0,%B1) CR_TAB
01671 AS2 (mov,%A0,%A1));
01672 }
01673 else
01674 {
01675 *l = 2;
01676 return (AS2 (mov,%A0,%A1) CR_TAB
01677 AS2 (mov,%B0,%B1));
01678 }
01679 }
01680 else if (CONSTANT_P (src))
01681 {
01682 if (test_hard_reg_class (LD_REGS, dest))
01683 {
01684 *l = 2;
01685 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
01686 AS2 (ldi,%B0,hi8(%1)));
01687 }
01688
01689 if (GET_CODE (src) == CONST_INT)
01690 {
01691 if (src == const0_rtx)
01692 {
01693 *l = 2;
01694 return (AS1 (clr,%A0) CR_TAB
01695 AS1 (clr,%B0));
01696 }
01697 else if (src == const1_rtx)
01698 {
01699 *l = 3;
01700 return (AS1 (clr,%A0) CR_TAB
01701 AS1 (clr,%B0) CR_TAB
01702 AS1 (inc,%A0));
01703 }
01704 else if (src == constm1_rtx)
01705 {
01706
01707 *l = 3;
01708 return (AS1 (clr,%0) CR_TAB
01709 AS1 (dec,%A0) CR_TAB
01710 AS2 (mov,%B0,%A0));
01711 }
01712 else
01713 {
01714 int bit_nr = exact_log2 (INTVAL (src));
01715
01716 if (bit_nr >= 0)
01717 {
01718 *l = 4;
01719 if (!real_l)
01720 output_asm_insn ((AS1 (clr,%A0) CR_TAB
01721 AS1 (clr,%B0) CR_TAB
01722 "set"), operands);
01723 if (!real_l)
01724 avr_output_bld (operands, bit_nr);
01725
01726 return "";
01727 }
01728 }
01729
01730 if ((INTVAL (src) & 0xff) == 0)
01731 {
01732 *l = 5;
01733 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
01734 AS1 (clr,%A0) CR_TAB
01735 AS2 (ldi,r31,hi8(%1)) CR_TAB
01736 AS2 (mov,%B0,r31) CR_TAB
01737 AS2 (mov,r31,__tmp_reg__));
01738 }
01739 else if ((INTVAL (src) & 0xff00) == 0)
01740 {
01741 *l = 5;
01742 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
01743 AS2 (ldi,r31,lo8(%1)) CR_TAB
01744 AS2 (mov,%A0,r31) CR_TAB
01745 AS1 (clr,%B0) CR_TAB
01746 AS2 (mov,r31,__tmp_reg__));
01747 }
01748 }
01749
01750
01751 *l = 6;
01752 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
01753 AS2 (ldi,r31,lo8(%1)) CR_TAB
01754 AS2 (mov,%A0,r31) CR_TAB
01755 AS2 (ldi,r31,hi8(%1)) CR_TAB
01756 AS2 (mov,%B0,r31) CR_TAB
01757 AS2 (mov,r31,__tmp_reg__));
01758 }
01759 else if (GET_CODE (src) == MEM)
01760 return out_movhi_r_mr (insn, operands, real_l);
01761 }
01762 else if (GET_CODE (dest) == MEM)
01763 {
01764 const char *template;
01765
01766 if (src == const0_rtx)
01767 operands[1] = zero_reg_rtx;
01768
01769 template = out_movhi_mr_r (insn, operands, real_l);
01770
01771 if (!real_l)
01772 output_asm_insn (template, operands);
01773
01774 operands[1] = src;
01775 return "";
01776 }
01777 fatal_insn ("invalid insn:", insn);
01778 return "";
01779 }
01780
01781 const char *
01782 out_movqi_r_mr (rtx insn, rtx op[], int *l)
01783 {
01784 rtx dest = op[0];
01785 rtx src = op[1];
01786 rtx x = XEXP (src, 0);
01787 int dummy;
01788
01789 if (!l)
01790 l = &dummy;
01791
01792 if (CONSTANT_ADDRESS_P (x))
01793 {
01794 if (avr_io_address_p (x, 1))
01795 {
01796 *l = 1;
01797 return AS2 (in,%0,%1-0x20);
01798 }
01799 *l = 2;
01800 return AS2 (lds,%0,%1);
01801 }
01802
01803 else if (GET_CODE (x) == PLUS
01804 && REG_P (XEXP (x,0))
01805 && GET_CODE (XEXP (x,1)) == CONST_INT)
01806 {
01807 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (src))) >= 63)
01808 {
01809 int disp = INTVAL (XEXP (x,1));
01810 if (REGNO (XEXP (x,0)) != REG_Y)
01811 fatal_insn ("incorrect insn:",insn);
01812
01813 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
01814 return *l = 3, (AS2 (adiw,r28,%o1-63) CR_TAB
01815 AS2 (ldd,%0,Y+63) CR_TAB
01816 AS2 (sbiw,r28,%o1-63));
01817
01818 return *l = 5, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
01819 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
01820 AS2 (ld,%0,Y) CR_TAB
01821 AS2 (subi,r28,lo8(%o1)) CR_TAB
01822 AS2 (sbci,r29,hi8(%o1)));
01823 }
01824 else if (REGNO (XEXP (x,0)) == REG_X)
01825 {
01826
01827
01828 if (reg_overlap_mentioned_p (dest, XEXP (x,0))
01829 || reg_unused_after (insn, XEXP (x,0)))
01830 return *l = 2, (AS2 (adiw,r26,%o1) CR_TAB
01831 AS2 (ld,%0,X));
01832
01833 return *l = 3, (AS2 (adiw,r26,%o1) CR_TAB
01834 AS2 (ld,%0,X) CR_TAB
01835 AS2 (sbiw,r26,%o1));
01836 }
01837 *l = 1;
01838 return AS2 (ldd,%0,%1);
01839 }
01840 *l = 1;
01841 return AS2 (ld,%0,%1);
01842 }
01843
01844 const char *
01845 out_movhi_r_mr (rtx insn, rtx op[], int *l)
01846 {
01847 rtx dest = op[0];
01848 rtx src = op[1];
01849 rtx base = XEXP (src, 0);
01850 int reg_dest = true_regnum (dest);
01851 int reg_base = true_regnum (base);
01852
01853
01854 int mem_volatile_p = MEM_VOLATILE_P (src);
01855 int tmp;
01856
01857 if (!l)
01858 l = &tmp;
01859
01860 if (reg_base > 0)
01861 {
01862 if (reg_dest == reg_base)
01863 {
01864 *l = 3;
01865 return (AS2 (ld,__tmp_reg__,%1+) CR_TAB
01866 AS2 (ld,%B0,%1) CR_TAB
01867 AS2 (mov,%A0,__tmp_reg__));
01868 }
01869 else if (reg_base == REG_X)
01870 {
01871 if (reg_unused_after (insn, base))
01872 {
01873 *l = 2;
01874 return (AS2 (ld,%A0,X+) CR_TAB
01875 AS2 (ld,%B0,X));
01876 }
01877 *l = 3;
01878 return (AS2 (ld,%A0,X+) CR_TAB
01879 AS2 (ld,%B0,X) CR_TAB
01880 AS2 (sbiw,r26,1));
01881 }
01882 else
01883 {
01884 *l = 2;
01885 return (AS2 (ld,%A0,%1) CR_TAB
01886 AS2 (ldd,%B0,%1+1));
01887 }
01888 }
01889 else if (GET_CODE (base) == PLUS)
01890 {
01891 int disp = INTVAL (XEXP (base, 1));
01892 int reg_base = true_regnum (XEXP (base, 0));
01893
01894 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
01895 {
01896 if (REGNO (XEXP (base, 0)) != REG_Y)
01897 fatal_insn ("incorrect insn:",insn);
01898
01899 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
01900 return *l = 4, (AS2 (adiw,r28,%o1-62) CR_TAB
01901 AS2 (ldd,%A0,Y+62) CR_TAB
01902 AS2 (ldd,%B0,Y+63) CR_TAB
01903 AS2 (sbiw,r28,%o1-62));
01904
01905 return *l = 6, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
01906 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
01907 AS2 (ld,%A0,Y) CR_TAB
01908 AS2 (ldd,%B0,Y+1) CR_TAB
01909 AS2 (subi,r28,lo8(%o1)) CR_TAB
01910 AS2 (sbci,r29,hi8(%o1)));
01911 }
01912 if (reg_base == REG_X)
01913 {
01914
01915
01916
01917
01918 *l = 4;
01919 if (reg_base == reg_dest)
01920 return (AS2 (adiw,r26,%o1) CR_TAB
01921 AS2 (ld,__tmp_reg__,X+) CR_TAB
01922 AS2 (ld,%B0,X) CR_TAB
01923 AS2 (mov,%A0,__tmp_reg__));
01924
01925 return (AS2 (adiw,r26,%o1) CR_TAB
01926 AS2 (ld,%A0,X+) CR_TAB
01927 AS2 (ld,%B0,X) CR_TAB
01928 AS2 (sbiw,r26,%o1+1));
01929 }
01930
01931 if (reg_base == reg_dest)
01932 {
01933 *l = 3;
01934 return (AS2 (ldd,__tmp_reg__,%A1) CR_TAB
01935 AS2 (ldd,%B0,%B1) CR_TAB
01936 AS2 (mov,%A0,__tmp_reg__));
01937 }
01938
01939 *l = 2;
01940 return (AS2 (ldd,%A0,%A1) CR_TAB
01941 AS2 (ldd,%B0,%B1));
01942 }
01943 else if (GET_CODE (base) == PRE_DEC)
01944 {
01945 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
01946 fatal_insn ("incorrect insn:", insn);
01947
01948 if (mem_volatile_p)
01949 {
01950 if (REGNO (XEXP (base, 0)) == REG_X)
01951 {
01952 *l = 4;
01953 return (AS2 (sbiw,r26,2) CR_TAB
01954 AS2 (ld,%A0,X+) CR_TAB
01955 AS2 (ld,%B0,X) CR_TAB
01956 AS2 (sbiw,r26,1));
01957 }
01958 else
01959 {
01960 *l = 3;
01961 return (AS2 (sbiw,%r1,2) CR_TAB
01962 AS2 (ld,%A0,%p1) CR_TAB
01963 AS2 (ldd,%B0,%p1+1));
01964 }
01965 }
01966
01967 *l = 2;
01968 return (AS2 (ld,%B0,%1) CR_TAB
01969 AS2 (ld,%A0,%1));
01970 }
01971 else if (GET_CODE (base) == POST_INC)
01972 {
01973 if (reg_overlap_mentioned_p (dest, XEXP (base, 0)))
01974 fatal_insn ("incorrect insn:", insn);
01975
01976 *l = 2;
01977 return (AS2 (ld,%A0,%1) CR_TAB
01978 AS2 (ld,%B0,%1));
01979 }
01980 else if (CONSTANT_ADDRESS_P (base))
01981 {
01982 if (avr_io_address_p (base, 2))
01983 {
01984 *l = 2;
01985 return (AS2 (in,%A0,%A1-0x20) CR_TAB
01986 AS2 (in,%B0,%B1-0x20));
01987 }
01988 *l = 4;
01989 return (AS2 (lds,%A0,%A1) CR_TAB
01990 AS2 (lds,%B0,%B1));
01991 }
01992
01993 fatal_insn ("unknown move insn:",insn);
01994 return "";
01995 }
01996
01997 const char *
01998 out_movsi_r_mr (rtx insn, rtx op[], int *l)
01999 {
02000 rtx dest = op[0];
02001 rtx src = op[1];
02002 rtx base = XEXP (src, 0);
02003 int reg_dest = true_regnum (dest);
02004 int reg_base = true_regnum (base);
02005 int tmp;
02006
02007 if (!l)
02008 l = &tmp;
02009
02010 if (reg_base > 0)
02011 {
02012 if (reg_base == REG_X)
02013 {
02014 if (reg_dest == REG_X)
02015
02016 return *l=7, (AS2 (adiw,r26,3) CR_TAB
02017 AS2 (ld,r29,X) CR_TAB
02018 AS2 (ld,r28,-X) CR_TAB
02019 AS2 (ld,__tmp_reg__,-X) CR_TAB
02020 AS2 (sbiw,r26,1) CR_TAB
02021 AS2 (ld,r26,X) CR_TAB
02022 AS2 (mov,r27,__tmp_reg__));
02023 else if (reg_dest == REG_X - 2)
02024 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
02025 AS2 (ld,%B0,X+) CR_TAB
02026 AS2 (ld,__tmp_reg__,X+) CR_TAB
02027 AS2 (ld,%D0,X) CR_TAB
02028 AS2 (mov,%C0,__tmp_reg__));
02029 else if (reg_unused_after (insn, base))
02030 return *l=4, (AS2 (ld,%A0,X+) CR_TAB
02031 AS2 (ld,%B0,X+) CR_TAB
02032 AS2 (ld,%C0,X+) CR_TAB
02033 AS2 (ld,%D0,X));
02034 else
02035 return *l=5, (AS2 (ld,%A0,X+) CR_TAB
02036 AS2 (ld,%B0,X+) CR_TAB
02037 AS2 (ld,%C0,X+) CR_TAB
02038 AS2 (ld,%D0,X) CR_TAB
02039 AS2 (sbiw,r26,3));
02040 }
02041 else
02042 {
02043 if (reg_dest == reg_base)
02044 return *l=5, (AS2 (ldd,%D0,%1+3) CR_TAB
02045 AS2 (ldd,%C0,%1+2) CR_TAB
02046 AS2 (ldd,__tmp_reg__,%1+1) CR_TAB
02047 AS2 (ld,%A0,%1) CR_TAB
02048 AS2 (mov,%B0,__tmp_reg__));
02049 else if (reg_base == reg_dest + 2)
02050 return *l=5, (AS2 (ld ,%A0,%1) CR_TAB
02051 AS2 (ldd,%B0,%1+1) CR_TAB
02052 AS2 (ldd,__tmp_reg__,%1+2) CR_TAB
02053 AS2 (ldd,%D0,%1+3) CR_TAB
02054 AS2 (mov,%C0,__tmp_reg__));
02055 else
02056 return *l=4, (AS2 (ld ,%A0,%1) CR_TAB
02057 AS2 (ldd,%B0,%1+1) CR_TAB
02058 AS2 (ldd,%C0,%1+2) CR_TAB
02059 AS2 (ldd,%D0,%1+3));
02060 }
02061 }
02062 else if (GET_CODE (base) == PLUS)
02063 {
02064 int disp = INTVAL (XEXP (base, 1));
02065
02066 if (disp > MAX_LD_OFFSET (GET_MODE (src)))
02067 {
02068 if (REGNO (XEXP (base, 0)) != REG_Y)
02069 fatal_insn ("incorrect insn:",insn);
02070
02071 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (src)))
02072 return *l = 6, (AS2 (adiw,r28,%o1-60) CR_TAB
02073 AS2 (ldd,%A0,Y+60) CR_TAB
02074 AS2 (ldd,%B0,Y+61) CR_TAB
02075 AS2 (ldd,%C0,Y+62) CR_TAB
02076 AS2 (ldd,%D0,Y+63) CR_TAB
02077 AS2 (sbiw,r28,%o1-60));
02078
02079 return *l = 8, (AS2 (subi,r28,lo8(-%o1)) CR_TAB
02080 AS2 (sbci,r29,hi8(-%o1)) CR_TAB
02081 AS2 (ld,%A0,Y) CR_TAB
02082 AS2 (ldd,%B0,Y+1) CR_TAB
02083 AS2 (ldd,%C0,Y+2) CR_TAB
02084 AS2 (ldd,%D0,Y+3) CR_TAB
02085 AS2 (subi,r28,lo8(%o1)) CR_TAB
02086 AS2 (sbci,r29,hi8(%o1)));
02087 }
02088
02089 reg_base = true_regnum (XEXP (base, 0));
02090 if (reg_base == REG_X)
02091 {
02092
02093 if (reg_dest == REG_X)
02094 {
02095 *l = 7;
02096
02097 return (AS2 (adiw,r26,%o1+3) CR_TAB
02098 AS2 (ld,r29,X) CR_TAB
02099 AS2 (ld,r28,-X) CR_TAB
02100 AS2 (ld,__tmp_reg__,-X) CR_TAB
02101 AS2 (sbiw,r26,1) CR_TAB
02102 AS2 (ld,r26,X) CR_TAB
02103 AS2 (mov,r27,__tmp_reg__));
02104 }
02105 *l = 6;
02106 if (reg_dest == REG_X - 2)
02107 return (AS2 (adiw,r26,%o1) CR_TAB
02108 AS2 (ld,r24,X+) CR_TAB
02109 AS2 (ld,r25,X+) CR_TAB
02110 AS2 (ld,__tmp_reg__,X+) CR_TAB
02111 AS2 (ld,r27,X) CR_TAB
02112 AS2 (mov,r26,__tmp_reg__));
02113
02114 return (AS2 (adiw,r26,%o1) CR_TAB
02115 AS2 (ld,%A0,X+) CR_TAB
02116 AS2 (ld,%B0,X+) CR_TAB
02117 AS2 (ld,%C0,X+) CR_TAB
02118 AS2 (ld,%D0,X) CR_TAB
02119 AS2 (sbiw,r26,%o1+3));
02120 }
02121 if (reg_dest == reg_base)
02122 return *l=5, (AS2 (ldd,%D0,%D1) CR_TAB
02123 AS2 (ldd,%C0,%C1) CR_TAB
02124 AS2 (ldd,__tmp_reg__,%B1) CR_TAB
02125 AS2 (ldd,%A0,%A1) CR_TAB
02126 AS2 (mov,%B0,__tmp_reg__));
02127 else if (reg_dest == reg_base - 2)
02128 return *l=5, (AS2 (ldd,%A0,%A1) CR_TAB
02129 AS2 (ldd,%B0,%B1) CR_TAB
02130 AS2 (ldd,__tmp_reg__,%C1) CR_TAB
02131 AS2 (ldd,%D0,%D1) CR_TAB
02132 AS2 (mov,%C0,__tmp_reg__));
02133 return *l=4, (AS2 (ldd,%A0,%A1) CR_TAB
02134 AS2 (ldd,%B0,%B1) CR_TAB
02135 AS2 (ldd,%C0,%C1) CR_TAB
02136 AS2 (ldd,%D0,%D1));
02137 }
02138 else if (GET_CODE (base) == PRE_DEC)
02139 return *l=4, (AS2 (ld,%D0,%1) CR_TAB
02140 AS2 (ld,%C0,%1) CR_TAB
02141 AS2 (ld,%B0,%1) CR_TAB
02142 AS2 (ld,%A0,%1));
02143 else if (GET_CODE (base) == POST_INC)
02144 return *l=4, (AS2 (ld,%A0,%1) CR_TAB
02145 AS2 (ld,%B0,%1) CR_TAB
02146 AS2 (ld,%C0,%1) CR_TAB
02147 AS2 (ld,%D0,%1));
02148 else if (CONSTANT_ADDRESS_P (base))
02149 return *l=8, (AS2 (lds,%A0,%A1) CR_TAB
02150 AS2 (lds,%B0,%B1) CR_TAB
02151 AS2 (lds,%C0,%C1) CR_TAB
02152 AS2 (lds,%D0,%D1));
02153
02154 fatal_insn ("unknown move insn:",insn);
02155 return "";
02156 }
02157
02158 const char *
02159 out_movsi_mr_r (rtx insn, rtx op[], int *l)
02160 {
02161 rtx dest = op[0];
02162 rtx src = op[1];
02163 rtx base = XEXP (dest, 0);
02164 int reg_base = true_regnum (base);
02165 int reg_src = true_regnum (src);
02166 int tmp;
02167
02168 if (!l)
02169 l = &tmp;
02170
02171 if (CONSTANT_ADDRESS_P (base))
02172 return *l=8,(AS2 (sts,%A0,%A1) CR_TAB
02173 AS2 (sts,%B0,%B1) CR_TAB
02174 AS2 (sts,%C0,%C1) CR_TAB
02175 AS2 (sts,%D0,%D1));
02176 if (reg_base > 0)
02177 {
02178 if (reg_base == REG_X)
02179 {
02180 if (reg_src == REG_X)
02181 {
02182
02183 if (reg_unused_after (insn, base))
02184 return *l=6, (AS2 (mov,__tmp_reg__,r27) CR_TAB
02185 AS2 (st,X,r26) CR_TAB
02186 AS2 (adiw,r26,1) CR_TAB
02187 AS2 (st,X+,__tmp_reg__) CR_TAB
02188 AS2 (st,X+,r28) CR_TAB
02189 AS2 (st,X,r29));
02190 else
02191 return *l=7, (AS2 (mov,__tmp_reg__,r27) CR_TAB
02192 AS2 (st,X,r26) CR_TAB
02193 AS2 (adiw,r26,1) CR_TAB
02194 AS2 (st,X+,__tmp_reg__) CR_TAB
02195 AS2 (st,X+,r28) CR_TAB
02196 AS2 (st,X,r29) CR_TAB
02197 AS2 (sbiw,r26,3));
02198 }
02199 else if (reg_base == reg_src + 2)
02200 {
02201 if (reg_unused_after (insn, base))
02202 return *l=7, (AS2 (mov,__zero_reg__,%C1) CR_TAB
02203 AS2 (mov,__tmp_reg__,%D1) CR_TAB
02204 AS2 (st,%0+,%A1) CR_TAB
02205 AS2 (st,%0+,%B1) CR_TAB
02206 AS2 (st,%0+,__zero_reg__) CR_TAB
02207 AS2 (st,%0,__tmp_reg__) CR_TAB
02208 AS1 (clr,__zero_reg__));
02209 else
02210 return *l=8, (AS2 (mov,__zero_reg__,%C1) CR_TAB
02211 AS2 (mov,__tmp_reg__,%D1) CR_TAB
02212 AS2 (st,%0+,%A1) CR_TAB
02213 AS2 (st,%0+,%B1) CR_TAB
02214 AS2 (st,%0+,__zero_reg__) CR_TAB
02215 AS2 (st,%0,__tmp_reg__) CR_TAB
02216 AS1 (clr,__zero_reg__) CR_TAB
02217 AS2 (sbiw,r26,3));
02218 }
02219 return *l=5, (AS2 (st,%0+,%A1) CR_TAB
02220 AS2 (st,%0+,%B1) CR_TAB
02221 AS2 (st,%0+,%C1) CR_TAB
02222 AS2 (st,%0,%D1) CR_TAB
02223 AS2 (sbiw,r26,3));
02224 }
02225 else
02226 return *l=4, (AS2 (st,%0,%A1) CR_TAB
02227 AS2 (std,%0+1,%B1) CR_TAB
02228 AS2 (std,%0+2,%C1) CR_TAB
02229 AS2 (std,%0+3,%D1));
02230 }
02231 else if (GET_CODE (base) == PLUS)
02232 {
02233 int disp = INTVAL (XEXP (base, 1));
02234 reg_base = REGNO (XEXP (base, 0));
02235 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
02236 {
02237 if (reg_base != REG_Y)
02238 fatal_insn ("incorrect insn:",insn);
02239
02240 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
02241 return *l = 6, (AS2 (adiw,r28,%o0-60) CR_TAB
02242 AS2 (std,Y+60,%A1) CR_TAB
02243 AS2 (std,Y+61,%B1) CR_TAB
02244 AS2 (std,Y+62,%C1) CR_TAB
02245 AS2 (std,Y+63,%D1) CR_TAB
02246 AS2 (sbiw,r28,%o0-60));
02247
02248 return *l = 8, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
02249 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
02250 AS2 (st,Y,%A1) CR_TAB
02251 AS2 (std,Y+1,%B1) CR_TAB
02252 AS2 (std,Y+2,%C1) CR_TAB
02253 AS2 (std,Y+3,%D1) CR_TAB
02254 AS2 (subi,r28,lo8(%o0)) CR_TAB
02255 AS2 (sbci,r29,hi8(%o0)));
02256 }
02257 if (reg_base == REG_X)
02258 {
02259
02260 if (reg_src == REG_X)
02261 {
02262 *l = 9;
02263 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
02264 AS2 (mov,__zero_reg__,r27) CR_TAB
02265 AS2 (adiw,r26,%o0) CR_TAB
02266 AS2 (st,X+,__tmp_reg__) CR_TAB
02267 AS2 (st,X+,__zero_reg__) CR_TAB
02268 AS2 (st,X+,r28) CR_TAB
02269 AS2 (st,X,r29) CR_TAB
02270 AS1 (clr,__zero_reg__) CR_TAB
02271 AS2 (sbiw,r26,%o0+3));
02272 }
02273 else if (reg_src == REG_X - 2)
02274 {
02275 *l = 9;
02276 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
02277 AS2 (mov,__zero_reg__,r27) CR_TAB
02278 AS2 (adiw,r26,%o0) CR_TAB
02279 AS2 (st,X+,r24) CR_TAB
02280 AS2 (st,X+,r25) CR_TAB
02281 AS2 (st,X+,__tmp_reg__) CR_TAB
02282 AS2 (st,X,__zero_reg__) CR_TAB
02283 AS1 (clr,__zero_reg__) CR_TAB
02284 AS2 (sbiw,r26,%o0+3));
02285 }
02286 *l = 6;
02287 return (AS2 (adiw,r26,%o0) CR_TAB
02288 AS2 (st,X+,%A1) CR_TAB
02289 AS2 (st,X+,%B1) CR_TAB
02290 AS2 (st,X+,%C1) CR_TAB
02291 AS2 (st,X,%D1) CR_TAB
02292 AS2 (sbiw,r26,%o0+3));
02293 }
02294 return *l=4, (AS2 (std,%A0,%A1) CR_TAB
02295 AS2 (std,%B0,%B1) CR_TAB
02296 AS2 (std,%C0,%C1) CR_TAB
02297 AS2 (std,%D0,%D1));
02298 }
02299 else if (GET_CODE (base) == PRE_DEC)
02300 return *l=4, (AS2 (st,%0,%D1) CR_TAB
02301 AS2 (st,%0,%C1) CR_TAB
02302 AS2 (st,%0,%B1) CR_TAB
02303 AS2 (st,%0,%A1));
02304 else if (GET_CODE (base) == POST_INC)
02305 return *l=4, (AS2 (st,%0,%A1) CR_TAB
02306 AS2 (st,%0,%B1) CR_TAB
02307 AS2 (st,%0,%C1) CR_TAB
02308 AS2 (st,%0,%D1));
02309 fatal_insn ("unknown move insn:",insn);
02310 return "";
02311 }
02312
02313 const char *
02314 output_movsisf(rtx insn, rtx operands[], int *l)
02315 {
02316 int dummy;
02317 rtx dest = operands[0];
02318 rtx src = operands[1];
02319 int *real_l = l;
02320
02321 if (!l)
02322 l = &dummy;
02323
02324 if (register_operand (dest, VOIDmode))
02325 {
02326 if (register_operand (src, VOIDmode))
02327 {
02328 if (true_regnum (dest) > true_regnum (src))
02329 {
02330 if (AVR_ENHANCED)
02331 {
02332 *l = 2;
02333 return (AS2 (movw,%C0,%C1) CR_TAB
02334 AS2 (movw,%A0,%A1));
02335 }
02336 *l = 4;
02337 return (AS2 (mov,%D0,%D1) CR_TAB
02338 AS2 (mov,%C0,%C1) CR_TAB
02339 AS2 (mov,%B0,%B1) CR_TAB
02340 AS2 (mov,%A0,%A1));
02341 }
02342 else
02343 {
02344 if (AVR_ENHANCED)
02345 {
02346 *l = 2;
02347 return (AS2 (movw,%A0,%A1) CR_TAB
02348 AS2 (movw,%C0,%C1));
02349 }
02350 *l = 4;
02351 return (AS2 (mov,%A0,%A1) CR_TAB
02352 AS2 (mov,%B0,%B1) CR_TAB
02353 AS2 (mov,%C0,%C1) CR_TAB
02354 AS2 (mov,%D0,%D1));
02355 }
02356 }
02357 else if (CONSTANT_P (src))
02358 {
02359 if (test_hard_reg_class (LD_REGS, dest))
02360 {
02361 *l = 4;
02362 return (AS2 (ldi,%A0,lo8(%1)) CR_TAB
02363 AS2 (ldi,%B0,hi8(%1)) CR_TAB
02364 AS2 (ldi,%C0,hlo8(%1)) CR_TAB
02365 AS2 (ldi,%D0,hhi8(%1)));
02366 }
02367
02368 if (GET_CODE (src) == CONST_INT)
02369 {
02370 const char *const clr_op0 =
02371 AVR_ENHANCED ? (AS1 (clr,%A0) CR_TAB
02372 AS1 (clr,%B0) CR_TAB
02373 AS2 (movw,%C0,%A0))
02374 : (AS1 (clr,%A0) CR_TAB
02375 AS1 (clr,%B0) CR_TAB
02376 AS1 (clr,%C0) CR_TAB
02377 AS1 (clr,%D0));
02378
02379 if (src == const0_rtx)
02380 {
02381 *l = AVR_ENHANCED ? 3 : 4;
02382 return clr_op0;
02383 }
02384 else if (src == const1_rtx)
02385 {
02386 if (!real_l)
02387 output_asm_insn (clr_op0, operands);
02388 *l = AVR_ENHANCED ? 4 : 5;
02389 return AS1 (inc,%A0);
02390 }
02391 else if (src == constm1_rtx)
02392 {
02393
02394 if (AVR_ENHANCED)
02395 {
02396 *l = 4;
02397 return (AS1 (clr,%A0) CR_TAB
02398 AS1 (dec,%A0) CR_TAB
02399 AS2 (mov,%B0,%A0) CR_TAB
02400 AS2 (movw,%C0,%A0));
02401 }
02402 *l = 5;
02403 return (AS1 (clr,%A0) CR_TAB
02404 AS1 (dec,%A0) CR_TAB
02405 AS2 (mov,%B0,%A0) CR_TAB
02406 AS2 (mov,%C0,%A0) CR_TAB
02407 AS2 (mov,%D0,%A0));
02408 }
02409 else
02410 {
02411 int bit_nr = exact_log2 (INTVAL (src));
02412
02413 if (bit_nr >= 0)
02414 {
02415 *l = AVR_ENHANCED ? 5 : 6;
02416 if (!real_l)
02417 {
02418 output_asm_insn (clr_op0, operands);
02419 output_asm_insn ("set", operands);
02420 }
02421 if (!real_l)
02422 avr_output_bld (operands, bit_nr);
02423
02424 return "";
02425 }
02426 }
02427 }
02428
02429
02430 *l = 10;
02431 return (AS2 (mov,__tmp_reg__,r31) CR_TAB
02432 AS2 (ldi,r31,lo8(%1)) CR_TAB
02433 AS2 (mov,%A0,r31) CR_TAB
02434 AS2 (ldi,r31,hi8(%1)) CR_TAB
02435 AS2 (mov,%B0,r31) CR_TAB
02436 AS2 (ldi,r31,hlo8(%1)) CR_TAB
02437 AS2 (mov,%C0,r31) CR_TAB
02438 AS2 (ldi,r31,hhi8(%1)) CR_TAB
02439 AS2 (mov,%D0,r31) CR_TAB
02440 AS2 (mov,r31,__tmp_reg__));
02441 }
02442 else if (GET_CODE (src) == MEM)
02443 return out_movsi_r_mr (insn, operands, real_l);
02444 }
02445 else if (GET_CODE (dest) == MEM)
02446 {
02447 const char *template;
02448
02449 if (src == const0_rtx)
02450 operands[1] = zero_reg_rtx;
02451
02452 template = out_movsi_mr_r (insn, operands, real_l);
02453
02454 if (!real_l)
02455 output_asm_insn (template, operands);
02456
02457 operands[1] = src;
02458 return "";
02459 }
02460 fatal_insn ("invalid insn:", insn);
02461 return "";
02462 }
02463
02464 const char *
02465 out_movqi_mr_r (rtx insn, rtx op[], int *l)
02466 {
02467 rtx dest = op[0];
02468 rtx src = op[1];
02469 rtx x = XEXP (dest, 0);
02470 int dummy;
02471
02472 if (!l)
02473 l = &dummy;
02474
02475 if (CONSTANT_ADDRESS_P (x))
02476 {
02477 if (avr_io_address_p (x, 1))
02478 {
02479 *l = 1;
02480 return AS2 (out,%0-0x20,%1);
02481 }
02482 *l = 2;
02483 return AS2 (sts,%0,%1);
02484 }
02485
02486 else if (GET_CODE (x) == PLUS
02487 && REG_P (XEXP (x,0))
02488 && GET_CODE (XEXP (x,1)) == CONST_INT)
02489 {
02490 if ((INTVAL (XEXP (x,1)) - GET_MODE_SIZE (GET_MODE (dest))) >= 63)
02491 {
02492 int disp = INTVAL (XEXP (x,1));
02493 if (REGNO (XEXP (x,0)) != REG_Y)
02494 fatal_insn ("incorrect insn:",insn);
02495
02496 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
02497 return *l = 3, (AS2 (adiw,r28,%o0-63) CR_TAB
02498 AS2 (std,Y+63,%1) CR_TAB
02499 AS2 (sbiw,r28,%o0-63));
02500
02501 return *l = 5, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
02502 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
02503 AS2 (st,Y,%1) CR_TAB
02504 AS2 (subi,r28,lo8(%o0)) CR_TAB
02505 AS2 (sbci,r29,hi8(%o0)));
02506 }
02507 else if (REGNO (XEXP (x,0)) == REG_X)
02508 {
02509 if (reg_overlap_mentioned_p (src, XEXP (x, 0)))
02510 {
02511 if (reg_unused_after (insn, XEXP (x,0)))
02512 return *l = 3, (AS2 (mov,__tmp_reg__,%1) CR_TAB
02513 AS2 (adiw,r26,%o0) CR_TAB
02514 AS2 (st,X,__tmp_reg__));
02515
02516 return *l = 4, (AS2 (mov,__tmp_reg__,%1) CR_TAB
02517 AS2 (adiw,r26,%o0) CR_TAB
02518 AS2 (st,X,__tmp_reg__) CR_TAB
02519 AS2 (sbiw,r26,%o0));
02520 }
02521 else
02522 {
02523 if (reg_unused_after (insn, XEXP (x,0)))
02524 return *l = 2, (AS2 (adiw,r26,%o0) CR_TAB
02525 AS2 (st,X,%1));
02526
02527 return *l = 3, (AS2 (adiw,r26,%o0) CR_TAB
02528 AS2 (st,X,%1) CR_TAB
02529 AS2 (sbiw,r26,%o0));
02530 }
02531 }
02532 *l = 1;
02533 return AS2 (std,%0,%1);
02534 }
02535 *l = 1;
02536 return AS2 (st,%0,%1);
02537 }
02538
02539 const char *
02540 out_movhi_mr_r (rtx insn, rtx op[], int *l)
02541 {
02542 rtx dest = op[0];
02543 rtx src = op[1];
02544 rtx base = XEXP (dest, 0);
02545 int reg_base = true_regnum (base);
02546 int reg_src = true_regnum (src);
02547
02548
02549 int mem_volatile_p = MEM_VOLATILE_P (dest);
02550 int tmp;
02551
02552 if (!l)
02553 l = &tmp;
02554 if (CONSTANT_ADDRESS_P (base))
02555 {
02556 if (avr_io_address_p (base, 2))
02557 {
02558 *l = 2;
02559 return (AS2 (out,%B0-0x20,%B1) CR_TAB
02560 AS2 (out,%A0-0x20,%A1));
02561 }
02562 return *l = 4, (AS2 (sts,%B0,%B1) CR_TAB
02563 AS2 (sts,%A0,%A1));
02564 }
02565 if (reg_base > 0)
02566 {
02567 if (reg_base == REG_X)
02568 {
02569 if (reg_src == REG_X)
02570 {
02571
02572 if (!mem_volatile_p && reg_unused_after (insn, src))
02573 return *l=4, (AS2 (mov,__tmp_reg__,r27) CR_TAB
02574 AS2 (st,X,r26) CR_TAB
02575 AS2 (adiw,r26,1) CR_TAB
02576 AS2 (st,X,__tmp_reg__));
02577 else
02578 return *l=5, (AS2 (mov,__tmp_reg__,r27) CR_TAB
02579 AS2 (adiw,r26,1) CR_TAB
02580 AS2 (st,X,__tmp_reg__) CR_TAB
02581 AS2 (sbiw,r26,1) CR_TAB
02582 AS2 (st,X,r26));
02583 }
02584 else
02585 {
02586 if (!mem_volatile_p && reg_unused_after (insn, base))
02587 return *l=2, (AS2 (st,X+,%A1) CR_TAB
02588 AS2 (st,X,%B1));
02589 else
02590 return *l=3, (AS2 (adiw,r26,1) CR_TAB
02591 AS2 (st,X,%B1) CR_TAB
02592 AS2 (st,-X,%A1));
02593 }
02594 }
02595 else
02596 return *l=2, (AS2 (std,%0+1,%B1) CR_TAB
02597 AS2 (st,%0,%A1));
02598 }
02599 else if (GET_CODE (base) == PLUS)
02600 {
02601 int disp = INTVAL (XEXP (base, 1));
02602 reg_base = REGNO (XEXP (base, 0));
02603 if (disp > MAX_LD_OFFSET (GET_MODE (dest)))
02604 {
02605 if (reg_base != REG_Y)
02606 fatal_insn ("incorrect insn:",insn);
02607
02608 if (disp <= 63 + MAX_LD_OFFSET (GET_MODE (dest)))
02609 return *l = 4, (AS2 (adiw,r28,%o0-62) CR_TAB
02610 AS2 (std,Y+63,%B1) CR_TAB
02611 AS2 (std,Y+62,%A1) CR_TAB
02612 AS2 (sbiw,r28,%o0-62));
02613
02614 return *l = 6, (AS2 (subi,r28,lo8(-%o0)) CR_TAB
02615 AS2 (sbci,r29,hi8(-%o0)) CR_TAB
02616 AS2 (std,Y+1,%B1) CR_TAB
02617 AS2 (st,Y,%A1) CR_TAB
02618 AS2 (subi,r28,lo8(%o0)) CR_TAB
02619 AS2 (sbci,r29,hi8(%o0)));
02620 }
02621 if (reg_base == REG_X)
02622 {
02623
02624 if (reg_src == REG_X)
02625 {
02626 *l = 7;
02627 return (AS2 (mov,__tmp_reg__,r26) CR_TAB
02628 AS2 (mov,__zero_reg__,r27) CR_TAB
02629 AS2 (adiw,r26,%o0+1) CR_TAB
02630 AS2 (st,X,__zero_reg__) CR_TAB
02631 AS2 (st,-X,__tmp_reg__) CR_TAB
02632 AS1 (clr,__zero_reg__) CR_TAB
02633 AS2 (sbiw,r26,%o0));
02634 }
02635 *l = 4;
02636 return (AS2 (adiw,r26,%o0+1) CR_TAB
02637 AS2 (st,X,%B1) CR_TAB
02638 AS2 (st,-X,%A1) CR_TAB
02639 AS2 (sbiw,r26,%o0));
02640 }
02641 return *l=2, (AS2 (std,%B0,%B1) CR_TAB
02642 AS2 (std,%A0,%A1));
02643 }
02644 else if (GET_CODE (base) == PRE_DEC)
02645 return *l=2, (AS2 (st,%0,%B1) CR_TAB
02646 AS2 (st,%0,%A1));
02647 else if (GET_CODE (base) == POST_INC)
02648 {
02649 if (mem_volatile_p)
02650 {
02651 if (REGNO (XEXP (base, 0)) == REG_X)
02652 {
02653 *l = 4;
02654 return (AS2 (adiw,r26,1) CR_TAB
02655 AS2 (st,X,%B1) CR_TAB
02656 AS2 (st,-X,%A1) CR_TAB
02657 AS2 (adiw,r26,2));
02658 }
02659 else
02660 {
02661 *l = 3;
02662 return (AS2 (std,%p0+1,%B1) CR_TAB
02663 AS2 (st,%p0,%A1) CR_TAB
02664 AS2 (adiw,%r0,2));
02665 }
02666 }
02667
02668 *l = 2;
02669 return (AS2 (st,%0,%A1) CR_TAB
02670 AS2 (st,%0,%B1));
02671 }
02672 fatal_insn ("unknown move insn:",insn);
02673 return "";
02674 }
02675
02676
02677
02678 int
02679 frame_pointer_required_p (void)
02680 {
02681 return (current_function_calls_alloca
02682 || current_function_args_info.nregs == 0
02683 || get_frame_size () > 0);
02684 }
02685
02686
02687
02688 static RTX_CODE
02689 compare_condition (rtx insn)
02690 {
02691 rtx next = next_real_insn (insn);
02692 RTX_CODE cond = UNKNOWN;
02693 if (next && GET_CODE (next) == JUMP_INSN)
02694 {
02695 rtx pat = PATTERN (next);
02696 rtx src = SET_SRC (pat);
02697 rtx t = XEXP (src, 0);
02698 cond = GET_CODE (t);
02699 }
02700 return cond;
02701 }
02702
02703
02704
02705 static int
02706 compare_sign_p (rtx insn)
02707 {
02708 RTX_CODE cond = compare_condition (insn);
02709 return (cond == GE || cond == LT);
02710 }
02711
02712
02713
02714
02715 int
02716 compare_diff_p (rtx insn)
02717 {
02718 RTX_CODE cond = compare_condition (insn);
02719 return (cond == GT || cond == GTU || cond == LE || cond == LEU) ? cond : 0;
02720 }
02721
02722
02723
02724 int
02725 compare_eq_p (rtx insn)
02726 {
02727 RTX_CODE cond = compare_condition (insn);
02728 return (cond == EQ || cond == NE);
02729 }
02730
02731
02732
02733
02734 const char *
02735 out_tsthi (rtx insn, int *l)
02736 {
02737 if (compare_sign_p (insn))
02738 {
02739 if (l) *l = 1;
02740 return AS1 (tst,%B0);
02741 }
02742 if (reg_unused_after (insn, SET_SRC (PATTERN (insn)))
02743 && compare_eq_p (insn))
02744 {
02745
02746 if (l) *l = 1;
02747 return AS2 (or,%A0,%B0);
02748 }
02749 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
02750 {
02751 if (l) *l = 1;
02752 return AS2 (sbiw,%0,0);
02753 }
02754 if (l) *l = 2;
02755 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
02756 AS2 (cpc,%B0,__zero_reg__));
02757 }
02758
02759
02760
02761
02762 const char *
02763 out_tstsi (rtx insn, int *l)
02764 {
02765 if (compare_sign_p (insn))
02766 {
02767 if (l) *l = 1;
02768 return AS1 (tst,%D0);
02769 }
02770 if (test_hard_reg_class (ADDW_REGS, SET_SRC (PATTERN (insn))))
02771 {
02772 if (l) *l = 3;
02773 return (AS2 (sbiw,%A0,0) CR_TAB
02774 AS2 (cpc,%C0,__zero_reg__) CR_TAB
02775 AS2 (cpc,%D0,__zero_reg__));
02776 }
02777 if (l) *l = 4;
02778 return (AS2 (cp,%A0,__zero_reg__) CR_TAB
02779 AS2 (cpc,%B0,__zero_reg__) CR_TAB
02780 AS2 (cpc,%C0,__zero_reg__) CR_TAB
02781 AS2 (cpc,%D0,__zero_reg__));
02782 }
02783
02784
02785
02786
02787
02788
02789
02790 void
02791 out_shift_with_cnt (const char *template, rtx insn, rtx operands[],
02792 int *len, int t_len)
02793 {
02794 rtx op[10];
02795 char str[500];
02796 int second_label = 1;
02797 int saved_in_tmp = 0;
02798 int use_zero_reg = 0;
02799
02800 op[0] = operands[0];
02801 op[1] = operands[1];
02802 op[2] = operands[2];
02803 op[3] = operands[3];
02804 str[0] = 0;
02805
02806 if (len)
02807 *len = 1;
02808
02809 if (GET_CODE (operands[2]) == CONST_INT)
02810 {
02811 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
02812 int count = INTVAL (operands[2]);
02813 int max_len = 10;
02814
02815 if (count <= 0)
02816 {
02817 if (len)
02818 *len = 0;
02819 return;
02820 }
02821
02822 if (count < 8 && !scratch)
02823 use_zero_reg = 1;
02824
02825 if (optimize_size)
02826 max_len = t_len + (scratch ? 3 : (use_zero_reg ? 4 : 5));
02827
02828 if (t_len * count <= max_len)
02829 {
02830
02831 if (len)
02832 *len = t_len * count;
02833 else
02834 {
02835 while (count-- > 0)
02836 output_asm_insn (template, op);
02837 }
02838
02839 return;
02840 }
02841
02842 if (scratch)
02843 {
02844 if (!len)
02845 strcat (str, AS2 (ldi,%3,%2));
02846 }
02847 else if (use_zero_reg)
02848 {
02849
02850
02851
02852 op[3] = zero_reg_rtx;
02853 if (len)
02854 *len = 2;
02855 else
02856 strcat (str, ("set" CR_TAB
02857 AS2 (bld,%3,%2-1)));
02858 }
02859 else
02860 {
02861
02862
02863
02864 op[3] = gen_rtx_REG (QImode,
02865 ((true_regnum (operands[0]) - 1) & 15) + 16);
02866 op[4] = tmp_reg_rtx;
02867 saved_in_tmp = 1;
02868
02869 if (len)
02870 *len = 3;
02871 else
02872 strcat (str, (AS2 (mov,%4,%3) CR_TAB
02873 AS2 (ldi,%3,%2)));
02874 }
02875
02876 second_label = 0;
02877 }
02878 else if (GET_CODE (operands[2]) == MEM)
02879 {
02880 rtx op_mov[10];
02881
02882 op[3] = op_mov[0] = tmp_reg_rtx;
02883 op_mov[1] = op[2];
02884
02885 if (len)
02886 out_movqi_r_mr (insn, op_mov, len);
02887 else
02888 output_asm_insn (out_movqi_r_mr (insn, op_mov, NULL), op_mov);
02889 }
02890 else if (register_operand (operands[2], QImode))
02891 {
02892 if (reg_unused_after (insn, operands[2]))
02893 op[3] = op[2];
02894 else
02895 {
02896 op[3] = tmp_reg_rtx;
02897 if (!len)
02898 strcat (str, (AS2 (mov,%3,%2) CR_TAB));
02899 }
02900 }
02901 else
02902 fatal_insn ("bad shift insn:", insn);
02903
02904 if (second_label)
02905 {
02906 if (len)
02907 ++*len;
02908 else
02909 strcat (str, AS1 (rjmp,2f));
02910 }
02911
02912 if (len)
02913 *len += t_len + 2;
02914 else
02915 {
02916 strcat (str, "\n1:\t");
02917 strcat (str, template);
02918 strcat (str, second_label ? "\n2:\t" : "\n\t");
02919 strcat (str, use_zero_reg ? AS1 (lsr,%3) : AS1 (dec,%3));
02920 strcat (str, CR_TAB);
02921 strcat (str, second_label ? AS1 (brpl,1b) : AS1 (brne,1b));
02922 if (saved_in_tmp)
02923 strcat (str, (CR_TAB AS2 (mov,%3,%4)));
02924 output_asm_insn (str, op);
02925 }
02926 }
02927
02928
02929
02930
02931 const char *
02932 ashlqi3_out (rtx insn, rtx operands[], int *len)
02933 {
02934 if (GET_CODE (operands[2]) == CONST_INT)
02935 {
02936 int k;
02937
02938 if (!len)
02939 len = &k;
02940
02941 switch (INTVAL (operands[2]))
02942 {
02943 default:
02944 if (INTVAL (operands[2]) < 8)
02945 break;
02946
02947 *len = 1;
02948 return AS1 (clr,%0);
02949
02950 case 1:
02951 *len = 1;
02952 return AS1 (lsl,%0);
02953
02954 case 2:
02955 *len = 2;
02956 return (AS1 (lsl,%0) CR_TAB
02957 AS1 (lsl,%0));
02958
02959 case 3:
02960 *len = 3;
02961 return (AS1 (lsl,%0) CR_TAB
02962 AS1 (lsl,%0) CR_TAB
02963 AS1 (lsl,%0));
02964
02965 case 4:
02966 if (test_hard_reg_class (LD_REGS, operands[0]))
02967 {
02968 *len = 2;
02969 return (AS1 (swap,%0) CR_TAB
02970 AS2 (andi,%0,0xf0));
02971 }
02972 *len = 4;
02973 return (AS1 (lsl,%0) CR_TAB
02974 AS1 (lsl,%0) CR_TAB
02975 AS1 (lsl,%0) CR_TAB
02976 AS1 (lsl,%0));
02977
02978 case 5:
02979 if (test_hard_reg_class (LD_REGS, operands[0]))
02980 {
02981 *len = 3;
02982 return (AS1 (swap,%0) CR_TAB
02983 AS1 (lsl,%0) CR_TAB
02984 AS2 (andi,%0,0xe0));
02985 }
02986 *len = 5;
02987 return (AS1 (lsl,%0) CR_TAB
02988 AS1 (lsl,%0) CR_TAB
02989 AS1 (lsl,%0) CR_TAB
02990 AS1 (lsl,%0) CR_TAB
02991 AS1 (lsl,%0));
02992
02993 case 6:
02994 if (test_hard_reg_class (LD_REGS, operands[0]))
02995 {
02996 *len = 4;
02997 return (AS1 (swap,%0) CR_TAB
02998 AS1 (lsl,%0) CR_TAB
02999 AS1 (lsl,%0) CR_TAB
03000 AS2 (andi,%0,0xc0));
03001 }
03002 *len = 6;
03003 return (AS1 (lsl,%0) CR_TAB
03004 AS1 (lsl,%0) CR_TAB
03005 AS1 (lsl,%0) CR_TAB
03006 AS1 (lsl,%0) CR_TAB
03007 AS1 (lsl,%0) CR_TAB
03008 AS1 (lsl,%0));
03009
03010 case 7:
03011 *len = 3;
03012 return (AS1 (ror,%0) CR_TAB
03013 AS1 (clr,%0) CR_TAB
03014 AS1 (ror,%0));
03015 }
03016 }
03017 else if (CONSTANT_P (operands[2]))
03018 fatal_insn ("internal compiler error. Incorrect shift:", insn);
03019
03020 out_shift_with_cnt (AS1 (lsl,%0),
03021 insn, operands, len, 1);
03022 return "";
03023 }
03024
03025
03026
03027
03028 const char *
03029 ashlhi3_out (rtx insn, rtx operands[], int *len)
03030 {
03031 if (GET_CODE (operands[2]) == CONST_INT)
03032 {
03033 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
03034 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
03035 int k;
03036 int *t = len;
03037
03038 if (!len)
03039 len = &k;
03040
03041 switch (INTVAL (operands[2]))
03042 {
03043 default:
03044 if (INTVAL (operands[2]) < 16)
03045 break;
03046
03047 *len = 2;
03048 return (AS1 (clr,%B0) CR_TAB
03049 AS1 (clr,%A0));
03050
03051 case 4:
03052 if (optimize_size && scratch)
03053 break;
03054 if (ldi_ok)
03055 {
03056 *len = 6;
03057 return (AS1 (swap,%A0) CR_TAB
03058 AS1 (swap,%B0) CR_TAB
03059 AS2 (andi,%B0,0xf0) CR_TAB
03060 AS2 (eor,%B0,%A0) CR_TAB
03061 AS2 (andi,%A0,0xf0) CR_TAB
03062 AS2 (eor,%B0,%A0));
03063 }
03064 if (scratch)
03065 {
03066 *len = 7;
03067 return (AS1 (swap,%A0) CR_TAB
03068 AS1 (swap,%B0) CR_TAB
03069 AS2 (ldi,%3,0xf0) CR_TAB
03070 AS2 (and,%B0,%3) CR_TAB
03071 AS2 (eor,%B0,%A0) CR_TAB
03072 AS2 (and,%A0,%3) CR_TAB
03073 AS2 (eor,%B0,%A0));
03074 }
03075 break;
03076
03077 case 5:
03078 if (optimize_size)
03079 break;
03080 if (ldi_ok)
03081 {
03082 *len = 8;
03083 return (AS1 (lsl,%A0) CR_TAB
03084 AS1 (rol,%B0) CR_TAB
03085 AS1 (swap,%A0) CR_TAB
03086 AS1 (swap,%B0) CR_TAB
03087 AS2 (andi,%B0,0xf0) CR_TAB
03088 AS2 (eor,%B0,%A0) CR_TAB
03089 AS2 (andi,%A0,0xf0) CR_TAB
03090 AS2 (eor,%B0,%A0));
03091 }
03092 if (scratch)
03093 {
03094 *len = 9;
03095 return (AS1 (lsl,%A0) CR_TAB
03096 AS1 (rol,%B0) CR_TAB
03097 AS1 (swap,%A0) CR_TAB
03098 AS1 (swap,%B0) CR_TAB
03099 AS2 (ldi,%3,0xf0) CR_TAB
03100 AS2 (and,%B0,%3) CR_TAB
03101 AS2 (eor,%B0,%A0) CR_TAB
03102 AS2 (and,%A0,%3) CR_TAB
03103 AS2 (eor,%B0,%A0));
03104 }
03105 break;
03106
03107 case 6:
03108 if (optimize_size)
03109 break;
03110 *len = 9;
03111 return (AS1 (clr,__tmp_reg__) CR_TAB
03112 AS1 (lsr,%B0) CR_TAB
03113 AS1 (ror,%A0) CR_TAB
03114 AS1 (ror,__tmp_reg__) CR_TAB
03115 AS1 (lsr,%B0) CR_TAB
03116 AS1 (ror,%A0) CR_TAB
03117 AS1 (ror,__tmp_reg__) CR_TAB
03118 AS2 (mov,%B0,%A0) CR_TAB
03119 AS2 (mov,%A0,__tmp_reg__));
03120
03121 case 7:
03122 *len = 5;
03123 return (AS1 (lsr,%B0) CR_TAB
03124 AS2 (mov,%B0,%A0) CR_TAB
03125 AS1 (clr,%A0) CR_TAB
03126 AS1 (ror,%B0) CR_TAB
03127 AS1 (ror,%A0));
03128
03129 case 8:
03130 if (true_regnum (operands[0]) + 1 == true_regnum (operands[1]))
03131 return *len = 1, AS1 (clr,%A0);
03132 else
03133 return *len = 2, (AS2 (mov,%B0,%A1) CR_TAB
03134 AS1 (clr,%A0));
03135
03136 case 9:
03137 *len = 3;
03138 return (AS2 (mov,%B0,%A0) CR_TAB
03139 AS1 (clr,%A0) CR_TAB
03140 AS1 (lsl,%B0));
03141
03142 case 10:
03143 *len = 4;
03144 return (AS2 (mov,%B0,%A0) CR_TAB
03145 AS1 (clr,%A0) CR_TAB
03146 AS1 (lsl,%B0) CR_TAB
03147 AS1 (lsl,%B0));
03148
03149 case 11:
03150 *len = 5;
03151 return (AS2 (mov,%B0,%A0) CR_TAB
03152 AS1 (clr,%A0) CR_TAB
03153 AS1 (lsl,%B0) CR_TAB
03154 AS1 (lsl,%B0) CR_TAB
03155 AS1 (lsl,%B0));
03156
03157 case 12:
03158 if (ldi_ok)
03159 {
03160 *len = 4;
03161 return (AS2 (mov,%B0,%A0) CR_TAB
03162 AS1 (clr,%A0) CR_TAB
03163 AS1 (swap,%B0) CR_TAB
03164 AS2 (andi,%B0,0xf0));
03165 }
03166 if (scratch)
03167 {
03168 *len = 5;
03169 return (AS2 (mov,%B0,%A0) CR_TAB
03170 AS1 (clr,%A0) CR_TAB
03171 AS1 (swap,%B0) CR_TAB
03172 AS2 (ldi,%3,0xf0) CR_TAB
03173 AS2 (and,%B0,%3));
03174 }
03175 *len = 6;
03176 return (AS2 (mov,%B0,%A0) CR_TAB
03177 AS1 (clr,%A0) CR_TAB
03178 AS1 (lsl,%B0) CR_TAB
03179 AS1 (lsl,%B0) CR_TAB
03180 AS1 (lsl,%B0) CR_TAB
03181 AS1 (lsl,%B0));
03182
03183 case 13:
03184 if (ldi_ok)
03185 {
03186 *len = 5;
03187 return (AS2 (mov,%B0,%A0) CR_TAB
03188 AS1 (clr,%A0) CR_TAB
03189 AS1 (swap,%B0) CR_TAB
03190 AS1 (lsl,%B0) CR_TAB
03191 AS2 (andi,%B0,0xe0));
03192 }
03193 if (AVR_ENHANCED && scratch)
03194 {
03195 *len = 5;
03196 return (AS2 (ldi,%3,0x20) CR_TAB
03197 AS2 (mul,%A0,%3) CR_TAB
03198 AS2 (mov,%B0,r0) CR_TAB
03199 AS1 (clr,%A0) CR_TAB
03200 AS1 (clr,__zero_reg__));
03201 }
03202 if (optimize_size && scratch)
03203 break;
03204 if (scratch)
03205 {
03206 *len = 6;
03207 return (AS2 (mov,%B0,%A0) CR_TAB
03208 AS1 (clr,%A0) CR_TAB
03209 AS1 (swap,%B0) CR_TAB
03210 AS1 (lsl,%B0) CR_TAB
03211 AS2 (ldi,%3,0xe0) CR_TAB
03212 AS2 (and,%B0,%3));
03213 }
03214 if (AVR_ENHANCED)
03215 {
03216 *len = 6;
03217 return ("set" CR_TAB
03218 AS2 (bld,r1,5) CR_TAB
03219 AS2 (mul,%A0,r1) CR_TAB
03220 AS2 (mov,%B0,r0) CR_TAB
03221 AS1 (clr,%A0) CR_TAB
03222 AS1 (clr,__zero_reg__));
03223 }
03224 *len = 7;
03225 return (AS2 (mov,%B0,%A0) CR_TAB
03226 AS1 (clr,%A0) CR_TAB
03227 AS1 (lsl,%B0) CR_TAB
03228 AS1 (lsl,%B0) CR_TAB
03229 AS1 (lsl,%B0) CR_TAB
03230 AS1 (lsl,%B0) CR_TAB
03231 AS1 (lsl,%B0));
03232
03233 case 14:
03234 if (AVR_ENHANCED && ldi_ok)
03235 {
03236 *len = 5;
03237 return (AS2 (ldi,%B0,0x40) CR_TAB
03238 AS2 (mul,%A0,%B0) CR_TAB
03239 AS2 (mov,%B0,r0) CR_TAB
03240 AS1 (clr,%A0) CR_TAB
03241 AS1 (clr,__zero_reg__));
03242 }
03243 if (AVR_ENHANCED && scratch)
03244 {
03245 *len = 5;
03246 return (AS2 (ldi,%3,0x40) CR_TAB
03247 AS2 (mul,%A0,%3) CR_TAB
03248 AS2 (mov,%B0,r0) CR_TAB
03249 AS1 (clr,%A0) CR_TAB
03250 AS1 (clr,__zero_reg__));
03251 }
03252 if (optimize_size && ldi_ok)
03253 {
03254 *len = 5;
03255 return (AS2 (mov,%B0,%A0) CR_TAB
03256 AS2 (ldi,%A0,6) "\n1:\t"
03257 AS1 (lsl,%B0) CR_TAB
03258 AS1 (dec,%A0) CR_TAB
03259 AS1 (brne,1b));
03260 }
03261 if (optimize_size && scratch)
03262 break;
03263 *len = 6;
03264 return (AS1 (clr,%B0) CR_TAB
03265 AS1 (lsr,%A0) CR_TAB
03266 AS1 (ror,%B0) CR_TAB
03267 AS1 (lsr,%A0) CR_TAB
03268 AS1 (ror,%B0) CR_TAB
03269 AS1 (clr,%A0));
03270
03271 case 15:
03272 *len = 4;
03273 return (AS1 (clr,%B0) CR_TAB
03274 AS1 (lsr,%A0) CR_TAB
03275 AS1 (ror,%B0) CR_TAB
03276 AS1 (clr,%A0));
03277 }
03278 len = t;
03279 }
03280 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
03281 AS1 (rol,%B0)),
03282 insn, operands, len, 2);
03283 return "";
03284 }
03285
03286
03287
03288
03289 const char *
03290 ashlsi3_out (rtx insn, rtx operands[], int *len)
03291 {
03292 if (GET_CODE (operands[2]) == CONST_INT)
03293 {
03294 int k;
03295 int *t = len;
03296
03297 if (!len)
03298 len = &k;
03299
03300 switch (INTVAL (operands[2]))
03301 {
03302 default:
03303 if (INTVAL (operands[2]) < 32)
03304 break;
03305
03306 if (AVR_ENHANCED)
03307 return *len = 3, (AS1 (clr,%D0) CR_TAB
03308 AS1 (clr,%C0) CR_TAB
03309 AS2 (movw,%A0,%C0));
03310 *len = 4;
03311 return (AS1 (clr,%D0) CR_TAB
03312 AS1 (clr,%C0) CR_TAB
03313 AS1 (clr,%B0) CR_TAB
03314 AS1 (clr,%A0));
03315
03316 case 8:
03317 {
03318 int reg0 = true_regnum (operands[0]);
03319 int reg1 = true_regnum (operands[1]);
03320 *len = 4;
03321 if (reg0 >= reg1)
03322 return (AS2 (mov,%D0,%C1) CR_TAB
03323 AS2 (mov,%C0,%B1) CR_TAB
03324 AS2 (mov,%B0,%A1) CR_TAB
03325 AS1 (clr,%A0));
03326 else if (reg0 + 1 == reg1)
03327 {
03328 *len = 1;
03329 return AS1 (clr,%A0);
03330 }
03331 else
03332 return (AS1 (clr,%A0) CR_TAB
03333 AS2 (mov,%B0,%A1) CR_TAB
03334 AS2 (mov,%C0,%B1) CR_TAB
03335 AS2 (mov,%D0,%C1));
03336 }
03337
03338 case 16:
03339 {
03340 int reg0 = true_regnum (operands[0]);
03341 int reg1 = true_regnum (operands[1]);
03342 *len = 4;
03343 if (AVR_ENHANCED && (reg0 + 2 != reg1))
03344 {
03345 *len = 3;
03346 return (AS2 (movw,%C0,%A1) CR_TAB
03347 AS1 (clr,%B0) CR_TAB
03348 AS1 (clr,%A0));
03349 }
03350 if (reg0 + 1 >= reg1)
03351 return (AS2 (mov,%D0,%B1) CR_TAB
03352 AS2 (mov,%C0,%A1) CR_TAB
03353 AS1 (clr,%B0) CR_TAB
03354 AS1 (clr,%A0));
03355 if (reg0 + 2 == reg1)
03356 {
03357 *len = 2;
03358 return (AS1 (clr,%B0) CR_TAB
03359 AS1 (clr,%A0));
03360 }
03361 else
03362 return (AS2 (mov,%C0,%A1) CR_TAB
03363 AS2 (mov,%D0,%B1) CR_TAB
03364 AS1 (clr,%B0) CR_TAB
03365 AS1 (clr,%A0));
03366 }
03367
03368 case 24:
03369 *len = 4;
03370 if (true_regnum (operands[0]) + 3 != true_regnum (operands[1]))
03371 return (AS2 (mov,%D0,%A1) CR_TAB
03372 AS1 (clr,%C0) CR_TAB
03373 AS1 (clr,%B0) CR_TAB
03374 AS1 (clr,%A0));
03375 else
03376 {
03377 *len = 3;
03378 return (AS1 (clr,%C0) CR_TAB
03379 AS1 (clr,%B0) CR_TAB
03380 AS1 (clr,%A0));
03381 }
03382
03383 case 31:
03384 *len = 6;
03385 return (AS1 (clr,%D0) CR_TAB
03386 AS1 (lsr,%A0) CR_TAB
03387 AS1 (ror,%D0) CR_TAB
03388 AS1 (clr,%C0) CR_TAB
03389 AS1 (clr,%B0) CR_TAB
03390 AS1 (clr,%A0));
03391 }
03392 len = t;
03393 }
03394 out_shift_with_cnt ((AS1 (lsl,%A0) CR_TAB
03395 AS1 (rol,%B0) CR_TAB
03396 AS1 (rol,%C0) CR_TAB
03397 AS1 (rol,%D0)),
03398 insn, operands, len, 4);
03399 return "";
03400 }
03401
03402
03403
03404 const char *
03405 ashrqi3_out (rtx insn, rtx operands[], int *len)
03406 {
03407 if (GET_CODE (operands[2]) == CONST_INT)
03408 {
03409 int k;
03410
03411 if (!len)
03412 len = &k;
03413
03414 switch (INTVAL (operands[2]))
03415 {
03416 case 1:
03417 *len = 1;
03418 return AS1 (asr,%0);
03419
03420 case 2:
03421 *len = 2;
03422 return (AS1 (asr,%0) CR_TAB
03423 AS1 (asr,%0));
03424
03425 case 3:
03426 *len = 3;
03427 return (AS1 (asr,%0) CR_TAB
03428 AS1 (asr,%0) CR_TAB
03429 AS1 (asr,%0));
03430
03431 case 4:
03432 *len = 4;
03433 return (AS1 (asr,%0) CR_TAB
03434 AS1 (asr,%0) CR_TAB
03435 AS1 (asr,%0) CR_TAB
03436 AS1 (asr,%0));
03437
03438 case 5:
03439 *len = 5;
03440 return (AS1 (asr,%0) CR_TAB
03441 AS1 (asr,%0) CR_TAB
03442 AS1 (asr,%0) CR_TAB
03443 AS1 (asr,%0) CR_TAB
03444 AS1 (asr,%0));
03445
03446 case 6:
03447 *len = 4;
03448 return (AS2 (bst,%0,6) CR_TAB
03449 AS1 (lsl,%0) CR_TAB
03450 AS2 (sbc,%0,%0) CR_TAB
03451 AS2 (bld,%0,0));
03452
03453 default:
03454 if (INTVAL (operands[2]) < 8)
03455 break;
03456
03457
03458
03459 case 7:
03460 *len = 2;
03461 return (AS1 (lsl,%0) CR_TAB
03462 AS2 (sbc,%0,%0));
03463 }
03464 }
03465 else if (CONSTANT_P (operands[2]))
03466 fatal_insn ("internal compiler error. Incorrect shift:", insn);
03467
03468 out_shift_with_cnt (AS1 (asr,%0),
03469 insn, operands, len, 1);
03470 return "";
03471 }
03472
03473
03474
03475
03476 const char *
03477 ashrhi3_out (rtx insn, rtx operands[], int *len)
03478 {
03479 if (GET_CODE (operands[2]) == CONST_INT)
03480 {
03481 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
03482 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
03483 int k;
03484 int *t = len;
03485
03486 if (!len)
03487 len = &k;
03488
03489 switch (INTVAL (operands[2]))
03490 {
03491 case 4:
03492 case 5:
03493
03494 break;
03495
03496 case 6:
03497 if (optimize_size)
03498 break;
03499 *len = 8;
03500 return (AS2 (mov,__tmp_reg__,%A0) CR_TAB
03501 AS2 (mov,%A0,%B0) CR_TAB
03502 AS1 (lsl,__tmp_reg__) CR_TAB
03503 AS1 (rol,%A0) CR_TAB
03504 AS2 (sbc,%B0,%B0) CR_TAB
03505 AS1 (lsl,__tmp_reg__) CR_TAB
03506 AS1 (rol,%A0) CR_TAB
03507 AS1 (rol,%B0));
03508
03509 case 7:
03510 *len = 4;
03511 return (AS1 (lsl,%A0) CR_TAB
03512 AS2 (mov,%A0,%B0) CR_TAB
03513 AS1 (rol,%A0) CR_TAB
03514 AS2 (sbc,%B0,%B0));
03515
03516 case 8:
03517 {
03518 int reg0 = true_regnum (operands[0]);
03519 int reg1 = true_regnum (operands[1]);
03520
03521 if (reg0 == reg1)
03522 return *len = 3, (AS2 (mov,%A0,%B0) CR_TAB
03523 AS1 (lsl,%B0) CR_TAB
03524 AS2 (sbc,%B0,%B0));
03525 else if (reg0 == reg1 + 1)
03526 return *len = 3, (AS1 (clr,%B0) CR_TAB
03527 AS2 (sbrc,%A0,7) CR_TAB
03528 AS1 (dec,%B0));
03529
03530 return *len = 4, (AS2 (mov,%A0,%B1) CR_TAB
03531 AS1 (clr,%B0) CR_TAB
03532 AS2 (sbrc,%A0,7) CR_TAB
03533 AS1 (dec,%B0));
03534 }
03535
03536 case 9:
03537 *len = 4;
03538 return (AS2 (mov,%A0,%B0) CR_TAB
03539 AS1 (lsl,%B0) CR_TAB
03540 AS2 (sbc,%B0,%B0) CR_TAB
03541 AS1 (asr,%A0));
03542
03543 case 10:
03544 *len = 5;
03545 return (AS2 (mov,%A0,%B0) CR_TAB
03546 AS1 (lsl,%B0) CR_TAB
03547 AS2 (sbc,%B0,%B0) CR_TAB
03548 AS1 (asr,%A0) CR_TAB
03549 AS1 (asr,%A0));
03550
03551 case 11:
03552 if (AVR_ENHANCED && ldi_ok)
03553 {
03554 *len = 5;
03555 return (AS2 (ldi,%A0,0x20) CR_TAB
03556 AS2 (muls,%B0,%A0) CR_TAB
03557 AS2 (mov,%A0,r1) CR_TAB
03558 AS2 (sbc,%B0,%B0) CR_TAB
03559 AS1 (clr,__zero_reg__));
03560 }
03561 if (optimize_size && scratch)
03562 break;
03563 *len = 6;
03564 return (AS2 (mov,%A0,%B0) CR_TAB
03565 AS1 (lsl,%B0) CR_TAB
03566 AS2 (sbc,%B0,%B0) CR_TAB
03567 AS1 (asr,%A0) CR_TAB
03568 AS1 (asr,%A0) CR_TAB
03569 AS1 (asr,%A0));
03570
03571 case 12:
03572 if (AVR_ENHANCED && ldi_ok)
03573 {
03574 *len = 5;
03575 return (AS2 (ldi,%A0,0x10) CR_TAB
03576 AS2 (muls,%B0,%A0) CR_TAB
03577 AS2 (mov,%A0,r1) CR_TAB
03578 AS2 (sbc,%B0,%B0) CR_TAB
03579 AS1 (clr,__zero_reg__));
03580 }
03581 if (optimize_size && scratch)
03582 break;
03583 *len = 7;
03584 return (AS2 (mov,%A0,%B0) CR_TAB
03585 AS1 (lsl,%B0) CR_TAB
03586 AS2 (sbc,%B0,%B0) CR_TAB
03587 AS1 (asr,%A0) CR_TAB
03588 AS1 (asr,%A0) CR_TAB
03589 AS1 (asr,%A0) CR_TAB
03590 AS1 (asr,%A0));
03591
03592 case 13:
03593 if (AVR_ENHANCED && ldi_ok)
03594 {
03595 *len = 5;
03596 return (AS2 (ldi,%A0,0x08) CR_TAB
03597 AS2 (muls,%B0,%A0) CR_TAB
03598 AS2 (mov,%A0,r1) CR_TAB
03599 AS2 (sbc,%B0,%B0) CR_TAB
03600 AS1 (clr,__zero_reg__));
03601 }
03602 if (optimize_size)
03603 break;
03604 *len = 8;
03605 return (AS2 (mov,%A0,%B0) CR_TAB
03606 AS1 (lsl,%B0) CR_TAB
03607 AS2 (sbc,%B0,%B0) CR_TAB
03608 AS1 (asr,%A0) CR_TAB
03609 AS1 (asr,%A0) CR_TAB
03610 AS1 (asr,%A0) CR_TAB
03611 AS1 (asr,%A0) CR_TAB
03612 AS1 (asr,%A0));
03613
03614 case 14:
03615 *len = 5;
03616 return (AS1 (lsl,%B0) CR_TAB
03617 AS2 (sbc,%A0,%A0) CR_TAB
03618 AS1 (lsl,%B0) CR_TAB
03619 AS2 (mov,%B0,%A0) CR_TAB
03620 AS1 (rol,%A0));
03621
03622 default:
03623 if (INTVAL (operands[2]) < 16)
03624 break;
03625
03626
03627
03628 case 15:
03629 return *len = 3, (AS1 (lsl,%B0) CR_TAB
03630 AS2 (sbc,%A0,%A0) CR_TAB
03631 AS2 (mov,%B0,%A0));
03632 }
03633 len = t;
03634 }
03635 out_shift_with_cnt ((AS1 (asr,%B0) CR_TAB
03636 AS1 (ror,%A0)),
03637 insn, operands, len, 2);
03638 return "";
03639 }
03640
03641
03642
03643
03644 const char *
03645 ashrsi3_out (rtx insn, rtx operands[], int *len)
03646 {
03647 if (GET_CODE (operands[2]) == CONST_INT)
03648 {
03649 int k;
03650 int *t = len;
03651
03652 if (!len)
03653 len = &k;
03654
03655 switch (INTVAL (operands[2]))
03656 {
03657 case 8:
03658 {
03659 int reg0 = true_regnum (operands[0]);
03660 int reg1 = true_regnum (operands[1]);
03661 *len=6;
03662 if (reg0 <= reg1)
03663 return (AS2 (mov,%A0,%B1) CR_TAB
03664 AS2 (mov,%B0,%C1) CR_TAB
03665 AS2 (mov,%C0,%D1) CR_TAB
03666 AS1 (clr,%D0) CR_TAB
03667 AS2 (sbrc,%C0,7) CR_TAB
03668 AS1 (dec,%D0));
03669 else if (reg0 == reg1 + 1)
03670 {
03671 *len = 3;
03672 return (AS1 (clr,%D0) CR_TAB
03673 AS2 (sbrc,%C0,7) CR_TAB
03674 AS1 (dec,%D0));
03675 }
03676 else
03677 return (AS1 (clr,%D0) CR_TAB
03678 AS2 (sbrc,%D1,7) CR_TAB
03679 AS1 (dec,%D0) CR_TAB
03680 AS2 (mov,%C0,%D1) CR_TAB
03681 AS2 (mov,%B0,%C1) CR_TAB
03682 AS2 (mov,%A0,%B1));
03683 }
03684
03685 case 16:
03686 {
03687 int reg0 = true_regnum (operands[0]);
03688 int reg1 = true_regnum (operands[1]);
03689 *len=6;
03690 if (AVR_ENHANCED && (reg0 != reg1 + 2))
03691 {
03692 *len = 5;
03693 return (AS2 (movw,%A0,%C1) CR_TAB
03694 AS1 (clr,%D0) CR_TAB
03695 AS2 (sbrc,%B0,7) CR_TAB
03696 AS1 (com,%D0) CR_TAB
03697 AS2 (mov,%C0,%D0));
03698 }
03699 if (reg0 <= reg1 + 1)
03700 return (AS2 (mov,%A0,%C1) CR_TAB
03701 AS2 (mov,%B0,%D1) CR_TAB
03702 AS1 (clr,%D0) CR_TAB
03703 AS2 (sbrc,%B0,7) CR_TAB
03704 AS1 (com,%D0) CR_TAB
03705 AS2 (mov,%C0,%D0));
03706 else if (reg0 == reg1 + 2)
03707 return *len = 4, (AS1 (clr,%D0) CR_TAB
03708 AS2 (sbrc,%B0,7) CR_TAB
03709 AS1 (com,%D0) CR_TAB
03710 AS2 (mov,%C0,%D0));
03711 else
03712 return (AS2 (mov,%B0,%D1) CR_TAB
03713 AS2 (mov,%A0,%C1) CR_TAB
03714 AS1 (clr,%D0) CR_TAB
03715 AS2 (sbrc,%B0,7) CR_TAB
03716 AS1 (com,%D0) CR_TAB
03717 AS2 (mov,%C0,%D0));
03718 }
03719
03720 case 24:
03721 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
03722 return *len = 6, (AS2 (mov,%A0,%D1) CR_TAB
03723 AS1 (clr,%D0) CR_TAB
03724 AS2 (sbrc,%A0,7) CR_TAB
03725 AS1 (com,%D0) CR_TAB
03726 AS2 (mov,%B0,%D0) CR_TAB
03727 AS2 (mov,%C0,%D0));
03728 else
03729 return *len = 5, (AS1 (clr,%D0) CR_TAB
03730 AS2 (sbrc,%A0,7) CR_TAB
03731 AS1 (com,%D0) CR_TAB
03732 AS2 (mov,%B0,%D0) CR_TAB
03733 AS2 (mov,%C0,%D0));
03734
03735 default:
03736 if (INTVAL (operands[2]) < 32)
03737 break;
03738
03739
03740
03741 case 31:
03742 if (AVR_ENHANCED)
03743 return *len = 4, (AS1 (lsl,%D0) CR_TAB
03744 AS2 (sbc,%A0,%A0) CR_TAB
03745 AS2 (mov,%B0,%A0) CR_TAB
03746 AS2 (movw,%C0,%A0));
03747 else
03748 return *len = 5, (AS1 (lsl,%D0) CR_TAB
03749 AS2 (sbc,%A0,%A0) CR_TAB
03750 AS2 (mov,%B0,%A0) CR_TAB
03751 AS2 (mov,%C0,%A0) CR_TAB
03752 AS2 (mov,%D0,%A0));
03753 }
03754 len = t;
03755 }
03756 out_shift_with_cnt ((AS1 (asr,%D0) CR_TAB
03757 AS1 (ror,%C0) CR_TAB
03758 AS1 (ror,%B0) CR_TAB
03759 AS1 (ror,%A0)),
03760 insn, operands, len, 4);
03761 return "";
03762 }
03763
03764
03765
03766 const char *
03767 lshrqi3_out (rtx insn, rtx operands[], int *len)
03768 {
03769 if (GET_CODE (operands[2]) == CONST_INT)
03770 {
03771 int k;
03772
03773 if (!len)
03774 len = &k;
03775
03776 switch (INTVAL (operands[2]))
03777 {
03778 default:
03779 if (INTVAL (operands[2]) < 8)
03780 break;
03781
03782 *len = 1;
03783 return AS1 (clr,%0);
03784
03785 case 1:
03786 *len = 1;
03787 return AS1 (lsr,%0);
03788
03789 case 2:
03790 *len = 2;
03791 return (AS1 (lsr,%0) CR_TAB
03792 AS1 (lsr,%0));
03793 case 3:
03794 *len = 3;
03795 return (AS1 (lsr,%0) CR_TAB
03796 AS1 (lsr,%0) CR_TAB
03797 AS1 (lsr,%0));
03798
03799 case 4:
03800 if (test_hard_reg_class (LD_REGS, operands[0]))
03801 {
03802 *len=2;
03803 return (AS1 (swap,%0) CR_TAB
03804 AS2 (andi,%0,0x0f));
03805 }
03806 *len = 4;
03807 return (AS1 (lsr,%0) CR_TAB
03808 AS1 (lsr,%0) CR_TAB
03809 AS1 (lsr,%0) CR_TAB
03810 AS1 (lsr,%0));
03811
03812 case 5:
03813 if (test_hard_reg_class (LD_REGS, operands[0]))
03814 {
03815 *len = 3;
03816 return (AS1 (swap,%0) CR_TAB
03817 AS1 (lsr,%0) CR_TAB
03818 AS2 (andi,%0,0x7));
03819 }
03820 *len = 5;
03821 return (AS1 (lsr,%0) CR_TAB
03822 AS1 (lsr,%0) CR_TAB
03823 AS1 (lsr,%0) CR_TAB
03824 AS1 (lsr,%0) CR_TAB
03825 AS1 (lsr,%0));
03826
03827 case 6:
03828 if (test_hard_reg_class (LD_REGS, operands[0]))
03829 {
03830 *len = 4;
03831 return (AS1 (swap,%0) CR_TAB
03832 AS1 (lsr,%0) CR_TAB
03833 AS1 (lsr,%0) CR_TAB
03834 AS2 (andi,%0,0x3));
03835 }
03836 *len = 6;
03837 return (AS1 (lsr,%0) CR_TAB
03838 AS1 (lsr,%0) CR_TAB
03839 AS1 (lsr,%0) CR_TAB
03840 AS1 (lsr,%0) CR_TAB
03841 AS1 (lsr,%0) CR_TAB
03842 AS1 (lsr,%0));
03843
03844 case 7:
03845 *len = 3;
03846 return (AS1 (rol,%0) CR_TAB
03847 AS1 (clr,%0) CR_TAB
03848 AS1 (rol,%0));
03849 }
03850 }
03851 else if (CONSTANT_P (operands[2]))
03852 fatal_insn ("internal compiler error. Incorrect shift:", insn);
03853
03854 out_shift_with_cnt (AS1 (lsr,%0),
03855 insn, operands, len, 1);
03856 return "";
03857 }
03858
03859
03860
03861 const char *
03862 lshrhi3_out (rtx insn, rtx operands[], int *len)
03863 {
03864 if (GET_CODE (operands[2]) == CONST_INT)
03865 {
03866 int scratch = (GET_CODE (PATTERN (insn)) == PARALLEL);
03867 int ldi_ok = test_hard_reg_class (LD_REGS, operands[0]);
03868 int k;
03869 int *t = len;
03870
03871 if (!len)
03872 len = &k;
03873
03874 switch (INTVAL (operands[2]))
03875 {
03876 default:
03877 if (INTVAL (operands[2]) < 16)
03878 break;
03879
03880 *len = 2;
03881 return (AS1 (clr,%B0) CR_TAB
03882 AS1 (clr,%A0));
03883
03884 case 4:
03885 if (optimize_size && scratch)
03886 break;
03887 if (ldi_ok)
03888 {
03889 *len = 6;
03890 return (AS1 (swap,%B0) CR_TAB
03891 AS1 (swap,%A0) CR_TAB
03892 AS2 (andi,%A0,0x0f) CR_TAB
03893 AS2 (eor,%A0,%B0) CR_TAB
03894 AS2 (andi,%B0,0x0f) CR_TAB
03895 AS2 (eor,%A0,%B0));
03896 }
03897 if (scratch)
03898 {
03899 *len = 7;
03900 return (AS1 (swap,%B0) CR_TAB
03901 AS1 (swap,%A0) CR_TAB
03902 AS2 (ldi,%3,0x0f) CR_TAB
03903 AS2 (and,%A0,%3) CR_TAB
03904 AS2 (eor,%A0,%B0) CR_TAB
03905 AS2 (and,%B0,%3) CR_TAB
03906 AS2 (eor,%A0,%B0));
03907 }
03908 break;
03909
03910 case 5:
03911 if (optimize_size)
03912 break;
03913 if (ldi_ok)
03914 {
03915 *len = 8;
03916 return (AS1 (lsr,%B0) CR_TAB
03917 AS1 (ror,%A0) CR_TAB
03918 AS1 (swap,%B0) CR_TAB
03919 AS1 (swap,%A0) CR_TAB
03920 AS2 (andi,%A0,0x0f) CR_TAB
03921 AS2 (eor,%A0,%B0) CR_TAB
03922 AS2 (andi,%B0,0x0f) CR_TAB
03923 AS2 (eor,%A0,%B0));
03924 }
03925 if (scratch)
03926 {
03927 *len = 9;
03928 return (AS1 (lsr,%B0) CR_TAB
03929 AS1 (ror,%A0) CR_TAB
03930 AS1 (swap,%B0) CR_TAB
03931 AS1 (swap,%A0) CR_TAB
03932 AS2 (ldi,%3,0x0f) CR_TAB
03933 AS2 (and,%A0,%3) CR_TAB
03934 AS2 (eor,%A0,%B0) CR_TAB
03935 AS2 (and,%B0,%3) CR_TAB
03936 AS2 (eor,%A0,%B0));
03937 }
03938 break;
03939
03940 case 6:
03941 if (optimize_size)
03942 break;
03943 *len = 9;
03944 return (AS1 (clr,__tmp_reg__) CR_TAB
03945 AS1 (lsl,%A0) CR_TAB
03946 AS1 (rol,%B0) CR_TAB
03947 AS1 (rol,__tmp_reg__) CR_TAB
03948 AS1 (lsl,%A0) CR_TAB
03949 AS1 (rol,%B0) CR_TAB
03950 AS1 (rol,__tmp_reg__) CR_TAB
03951 AS2 (mov,%A0,%B0) CR_TAB
03952 AS2 (mov,%B0,__tmp_reg__));
03953
03954 case 7:
03955 *len = 5;
03956 return (AS1 (lsl,%A0) CR_TAB
03957 AS2 (mov,%A0,%B0) CR_TAB
03958 AS1 (rol,%A0) CR_TAB
03959 AS2 (sbc,%B0,%B0) CR_TAB
03960 AS1 (neg,%B0));
03961
03962 case 8:
03963 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 1)
03964 return *len = 2, (AS2 (mov,%A0,%B1) CR_TAB
03965 AS1 (clr,%B0));
03966 else
03967 return *len = 1, AS1 (clr,%B0);
03968
03969 case 9:
03970 *len = 3;
03971 return (AS2 (mov,%A0,%B0) CR_TAB
03972 AS1 (clr,%B0) CR_TAB
03973 AS1 (lsr,%A0));
03974
03975 case 10:
03976 *len = 4;
03977 return (AS2 (mov,%A0,%B0) CR_TAB
03978 AS1 (clr,%B0) CR_TAB
03979 AS1 (lsr,%A0) CR_TAB
03980 AS1 (lsr,%A0));
03981
03982 case 11:
03983 *len = 5;
03984 return (AS2 (mov,%A0,%B0) CR_TAB
03985 AS1 (clr,%B0) CR_TAB
03986 AS1 (lsr,%A0) CR_TAB
03987 AS1 (lsr,%A0) CR_TAB
03988 AS1 (lsr,%A0));
03989
03990 case 12:
03991 if (ldi_ok)
03992 {
03993 *len = 4;
03994 return (AS2 (mov,%A0,%B0) CR_TAB
03995 AS1 (clr,%B0) CR_TAB
03996 AS1 (swap,%A0) CR_TAB
03997 AS2 (andi,%A0,0x0f));
03998 }
03999 if (scratch)
04000 {
04001 *len = 5;
04002 return (AS2 (mov,%A0,%B0) CR_TAB
04003 AS1 (clr,%B0) CR_TAB
04004 AS1 (swap,%A0) CR_TAB
04005 AS2 (ldi,%3,0x0f) CR_TAB
04006 AS2 (and,%A0,%3));
04007 }
04008 *len = 6;
04009 return (AS2 (mov,%A0,%B0) CR_TAB
04010 AS1 (clr,%B0) CR_TAB
04011 AS1 (lsr,%A0) CR_TAB
04012 AS1 (lsr,%A0) CR_TAB
04013 AS1 (lsr,%A0) CR_TAB
04014 AS1 (lsr,%A0));
04015
04016 case 13:
04017 if (ldi_ok)
04018 {
04019 *len = 5;
04020 return (AS2 (mov,%A0,%B0) CR_TAB
04021 AS1 (clr,%B0) CR_TAB
04022 AS1 (swap,%A0) CR_TAB
04023 AS1 (lsr,%A0) CR_TAB
04024 AS2 (andi,%A0,0x07));
04025 }
04026 if (AVR_ENHANCED && scratch)
04027 {
04028 *len = 5;
04029 return (AS2 (ldi,%3,0x08) CR_TAB
04030 AS2 (mul,%B0,%3) CR_TAB
04031 AS2 (mov,%A0,r1) CR_TAB
04032 AS1 (clr,%B0) CR_TAB
04033 AS1 (clr,__zero_reg__));
04034 }
04035 if (optimize_size && scratch)
04036 break;
04037 if (scratch)
04038 {
04039 *len = 6;
04040 return (AS2 (mov,%A0,%B0) CR_TAB
04041 AS1 (clr,%B0) CR_TAB
04042 AS1 (swap,%A0) CR_TAB
04043 AS1 (lsr,%A0) CR_TAB
04044 AS2 (ldi,%3,0x07) CR_TAB
04045 AS2 (and,%A0,%3));
04046 }
04047 if (AVR_ENHANCED)
04048 {
04049 *len = 6;
04050 return ("set" CR_TAB
04051 AS2 (bld,r1,3) CR_TAB
04052 AS2 (mul,%B0,r1) CR_TAB
04053 AS2 (mov,%A0,r1) CR_TAB
04054 AS1 (clr,%B0) CR_TAB
04055 AS1 (clr,__zero_reg__));
04056 }
04057 *len = 7;
04058 return (AS2 (mov,%A0,%B0) CR_TAB
04059 AS1 (clr,%B0) CR_TAB
04060 AS1 (lsr,%A0) CR_TAB
04061 AS1 (lsr,%A0) CR_TAB
04062 AS1 (lsr,%A0) CR_TAB
04063 AS1 (lsr,%A0) CR_TAB
04064 AS1 (lsr,%A0));
04065
04066 case 14:
04067 if (AVR_ENHANCED && ldi_ok)
04068 {
04069 *len = 5;
04070 return (AS2 (ldi,%A0,0x04) CR_TAB
04071 AS2 (mul,%B0,%A0) CR_TAB
04072 AS2 (mov,%A0,r1) CR_TAB
04073 AS1 (clr,%B0) CR_TAB
04074 AS1 (clr,__zero_reg__));
04075 }
04076 if (AVR_ENHANCED && scratch)
04077 {
04078 *len = 5;
04079 return (AS2 (ldi,%3,0x04) CR_TAB
04080 AS2 (mul,%B0,%3) CR_TAB
04081 AS2 (mov,%A0,r1) CR_TAB
04082 AS1 (clr,%B0) CR_TAB
04083 AS1 (clr,__zero_reg__));
04084 }
04085 if (optimize_size && ldi_ok)
04086 {
04087 *len = 5;
04088 return (AS2 (mov,%A0,%B0) CR_TAB
04089 AS2 (ldi,%B0,6) "\n1:\t"
04090 AS1 (lsr,%A0) CR_TAB
04091 AS1 (dec,%B0) CR_TAB
04092 AS1 (brne,1b));
04093 }
04094 if (optimize_size && scratch)
04095 break;
04096 *len = 6;
04097 return (AS1 (clr,%A0) CR_TAB
04098 AS1 (lsl,%B0) CR_TAB
04099 AS1 (rol,%A0) CR_TAB
04100 AS1 (lsl,%B0) CR_TAB
04101 AS1 (rol,%A0) CR_TAB
04102 AS1 (clr,%B0));
04103
04104 case 15:
04105 *len = 4;
04106 return (AS1 (clr,%A0) CR_TAB
04107 AS1 (lsl,%B0) CR_TAB
04108 AS1 (rol,%A0) CR_TAB
04109 AS1 (clr,%B0));
04110 }
04111 len = t;
04112 }
04113 out_shift_with_cnt ((AS1 (lsr,%B0) CR_TAB
04114 AS1 (ror,%A0)),
04115 insn, operands, len, 2);
04116 return "";
04117 }
04118
04119
04120
04121 const char *
04122 lshrsi3_out (rtx insn, rtx operands[], int *len)
04123 {
04124 if (GET_CODE (operands[2]) == CONST_INT)
04125 {
04126 int k;
04127 int *t = len;
04128
04129 if (!len)
04130 len = &k;
04131
04132 switch (INTVAL (operands[2]))
04133 {
04134 default:
04135 if (INTVAL (operands[2]) < 32)
04136 break;
04137
04138 if (AVR_ENHANCED)
04139 return *len = 3, (AS1 (clr,%D0) CR_TAB
04140 AS1 (clr,%C0) CR_TAB
04141 AS2 (movw,%A0,%C0));
04142 *len = 4;
04143 return (AS1 (clr,%D0) CR_TAB
04144 AS1 (clr,%C0) CR_TAB
04145 AS1 (clr,%B0) CR_TAB
04146 AS1 (clr,%A0));
04147
04148 case 8:
04149 {
04150 int reg0 = true_regnum (operands[0]);
04151 int reg1 = true_regnum (operands[1]);
04152 *len = 4;
04153 if (reg0 <= reg1)
04154 return (AS2 (mov,%A0,%B1) CR_TAB
04155 AS2 (mov,%B0,%C1) CR_TAB
04156 AS2 (mov,%C0,%D1) CR_TAB
04157 AS1 (clr,%D0));
04158 else if (reg0 == reg1 + 1)
04159 return *len = 1, AS1 (clr,%D0);
04160 else
04161 return (AS1 (clr,%D0) CR_TAB
04162 AS2 (mov,%C0,%D1) CR_TAB
04163 AS2 (mov,%B0,%C1) CR_TAB
04164 AS2 (mov,%A0,%B1));
04165 }
04166
04167 case 16:
04168 {
04169 int reg0 = true_regnum (operands[0]);
04170 int reg1 = true_regnum (operands[1]);
04171 *len = 4;
04172 if (AVR_ENHANCED && (reg0 != reg1 + 2))
04173 {
04174 *len = 3;
04175 return (AS2 (movw,%A0,%C1) CR_TAB
04176 AS1 (clr,%C0) CR_TAB
04177 AS1 (clr,%D0));
04178 }
04179 if (reg0 <= reg1 + 1)
04180 return (AS2 (mov,%A0,%C1) CR_TAB
04181 AS2 (mov,%B0,%D1) CR_TAB
04182 AS1 (clr,%C0) CR_TAB
04183 AS1 (clr,%D0));
04184 else if (reg0 == reg1 + 2)
04185 return *len = 2, (AS1 (clr,%C0) CR_TAB
04186 AS1 (clr,%D0));
04187 else
04188 return (AS2 (mov,%B0,%D1) CR_TAB
04189 AS2 (mov,%A0,%C1) CR_TAB
04190 AS1 (clr,%C0) CR_TAB
04191 AS1 (clr,%D0));
04192 }
04193
04194 case 24:
04195 if (true_regnum (operands[0]) != true_regnum (operands[1]) + 3)
04196 return *len = 4, (AS2 (mov,%A0,%D1) CR_TAB
04197 AS1 (clr,%B0) CR_TAB
04198 AS1 (clr,%C0) CR_TAB
04199 AS1 (clr,%D0));
04200 else
04201 return *len = 3, (AS1 (clr,%B0) CR_TAB
04202 AS1 (clr,%C0) CR_TAB
04203 AS1 (clr,%D0));
04204
04205 case 31:
04206 *len = 6;
04207 return (AS1 (clr,%A0) CR_TAB
04208 AS2 (sbrc,%D0,7) CR_TAB
04209 AS1 (inc,%A0) CR_TAB
04210 AS1 (clr,%B0) CR_TAB
04211 AS1 (clr,%C0) CR_TAB
04212 AS1 (clr,%D0));
04213 }
04214 len = t;
04215 }
04216 out_shift_with_cnt ((AS1 (lsr,%D0) CR_TAB
04217 AS1 (ror,%C0) CR_TAB
04218 AS1 (ror,%B0) CR_TAB
04219 AS1 (ror,%A0)),
04220 insn, operands, len, 4);
04221 return "";
04222 }
04223
04224
04225
04226
04227 int
04228 adjust_insn_length (rtx insn, int len)
04229 {
04230 rtx patt = PATTERN (insn);
04231 rtx set;
04232
04233 if (GET_CODE (patt) == SET)
04234 {
04235 rtx op[10];
04236 op[1] = SET_SRC (patt);
04237 op[0] = SET_DEST (patt);
04238 if (general_operand (op[1], VOIDmode)
04239 && general_operand (op[0], VOIDmode))
04240 {
04241 switch (GET_MODE (op[0]))
04242 {
04243 case QImode:
04244 output_movqi (insn, op, &len);
04245 break;
04246 case HImode:
04247 output_movhi (insn, op, &len);
04248 break;
04249 case SImode:
04250 case SFmode:
04251 output_movsisf (insn, op, &len);
04252 break;
04253 default:
04254 break;
04255 }
04256 }
04257 else if (op[0] == cc0_rtx && REG_P (op[1]))
04258 {
04259 switch (GET_MODE (op[1]))
04260 {
04261 case HImode: out_tsthi (insn,&len); break;
04262 case SImode: out_tstsi (insn,&len); break;
04263 default: break;
04264 }
04265 }
04266 else if (GET_CODE (op[1]) == AND)
04267 {
04268 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
04269 {
04270 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
04271 if (GET_MODE (op[1]) == SImode)
04272 len = (((mask & 0xff) != 0xff)
04273 + ((mask & 0xff00) != 0xff00)
04274 + ((mask & 0xff0000L) != 0xff0000L)
04275 + ((mask & 0xff000000L) != 0xff000000L));
04276 else if (GET_MODE (op[1]) == HImode)
04277 len = (((mask & 0xff) != 0xff)
04278 + ((mask & 0xff00) != 0xff00));
04279 }
04280 }
04281 else if (GET_CODE (op[1]) == IOR)
04282 {
04283 if (GET_CODE (XEXP (op[1],1)) == CONST_INT)
04284 {
04285 HOST_WIDE_INT mask = INTVAL (XEXP (op[1],1));
04286 if (GET_MODE (op[1]) == SImode)
04287 len = (((mask & 0xff) != 0)
04288 + ((mask & 0xff00) != 0)
04289 + ((mask & 0xff0000L) != 0)
04290 + ((mask & 0xff000000L) != 0));
04291 else if (GET_MODE (op[1]) == HImode)
04292 len = (((mask & 0xff) != 0)
04293 + ((mask & 0xff00) != 0));
04294 }
04295 }
04296 }
04297 set = single_set (insn);
04298 if (set)
04299 {
04300 rtx op[10];
04301
04302 op[1] = SET_SRC (set);
04303 op[0] = SET_DEST (set);
04304
04305 if (GET_CODE (patt) == PARALLEL
04306 && general_operand (op[1], VOIDmode)
04307 && general_operand (op[0], VOIDmode))
04308 {
04309 if (XVECLEN (patt, 0) == 2)
04310 op[2] = XVECEXP (patt, 0, 1);
04311
04312 switch (GET_MODE (op[0]))
04313 {
04314 case QImode:
04315 len = 2;
04316 break;
04317 case HImode:
04318 output_reload_inhi (insn, op, &len);
04319 break;
04320 case SImode:
04321 case SFmode:
04322 output_reload_insisf (insn, op, &len);
04323 break;
04324 default:
04325 break;
04326 }
04327 }
04328 else if (GET_CODE (op[1]) == ASHIFT
04329 || GET_CODE (op[1]) == ASHIFTRT
04330 || GET_CODE (op[1]) == LSHIFTRT)
04331 {
04332 rtx ops[10];
04333 ops[0] = op[0];
04334 ops[1] = XEXP (op[1],0);
04335 ops[2] = XEXP (op[1],1);
04336 switch (GET_CODE (op[1]))
04337 {
04338 case ASHIFT:
04339 switch (GET_MODE (op[0]))
04340 {
04341 case QImode: ashlqi3_out (insn,ops,&len); break;
04342 case HImode: ashlhi3_out (insn,ops,&len); break;
04343 case SImode: ashlsi3_out (insn,ops,&len); break;
04344 default: break;
04345 }
04346 break;
04347 case ASHIFTRT:
04348 switch (GET_MODE (op[0]))
04349 {
04350 case QImode: ashrqi3_out (insn,ops,&len); break;
04351 case HImode: ashrhi3_out (insn,ops,&len); break;
04352 case SImode: ashrsi3_out (insn,ops,&len); break;
04353 default: break;
04354 }
04355 break;
04356 case LSHIFTRT:
04357 switch (GET_MODE (op[0]))
04358 {
04359 case QImode: lshrqi3_out (insn,ops,&len); break;
04360 case HImode: lshrhi3_out (insn,ops,&len); break;
04361 case SImode: lshrsi3_out (insn,ops,&len); break;
04362 default: break;
04363 }
04364 break;
04365 default:
04366 break;
04367 }
04368 }
04369 }
04370 return len;
04371 }
04372
04373
04374
04375 int
04376 reg_unused_after (rtx insn, rtx reg)
04377 {
04378 return (dead_or_set_p (insn, reg)
04379 || (REG_P(reg) && _reg_unused_after (insn, reg)));
04380 }
04381
04382
04383
04384
04385
04386 int
04387 _reg_unused_after (rtx insn, rtx reg)
04388 {
04389 enum rtx_code code;
04390 rtx set;
04391
04392
04393
04394
04395 set = single_set (insn);
04396 if (set && GET_CODE (SET_DEST (set)) != MEM
04397 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
04398 return 1;
04399
04400 while ((insn = NEXT_INSN (insn)))
04401 {
04402 rtx set;
04403 code = GET_CODE (insn);
04404
04405 #if 0
04406
04407
04408
04409
04410 if (code == CODE_LABEL)
04411 return 1;
04412
04413 #endif
04414
04415 if (!INSN_P (insn))
04416 continue;
04417
04418 if (code == JUMP_INSN)
04419 return 0;
04420
04421
04422
04423
04424
04425 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
04426 {
04427 int i;
04428 int retval = 0;
04429
04430 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
04431 {
04432 rtx this_insn = XVECEXP (PATTERN (insn), 0, i);
04433 rtx set = single_set (this_insn);
04434
04435 if (GET_CODE (this_insn) == CALL_INSN)
04436 code = CALL_INSN;
04437 else if (GET_CODE (this_insn) == JUMP_INSN)
04438 {
04439 if (INSN_ANNULLED_BRANCH_P (this_insn))
04440 return 0;
04441 code = JUMP_INSN;
04442 }
04443
04444 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
04445 return 0;
04446 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
04447 {
04448 if (GET_CODE (SET_DEST (set)) != MEM)
04449 retval = 1;
04450 else
04451 return 0;
04452 }
04453 if (set == 0
04454 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
04455 return 0;
04456 }
04457 if (retval == 1)
04458 return 1;
04459 else if (code == JUMP_INSN)
04460 return 0;
04461 }
04462
04463 if (code == CALL_INSN)
04464 {
04465 rtx tem;
04466 for (tem = CALL_INSN_FUNCTION_USAGE (insn); tem; tem = XEXP (tem, 1))
04467 if (GET_CODE (XEXP (tem, 0)) == USE
04468 && REG_P (XEXP (XEXP (tem, 0), 0))
04469 && reg_overlap_mentioned_p (reg, XEXP (XEXP (tem, 0), 0)))
04470 return 0;
04471 if (call_used_regs[REGNO (reg)])
04472 return 1;
04473 }
04474
04475 set = single_set (insn);
04476
04477 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
04478 return 0;
04479 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
04480 return GET_CODE (SET_DEST (set)) != MEM;
04481 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
04482 return 0;
04483 }
04484 return 1;
04485 }
04486
04487
04488
04489
04490 static bool
04491 avr_assemble_integer (rtx x, unsigned int size, int aligned_p)
04492 {
04493 if (size == POINTER_SIZE / BITS_PER_UNIT && aligned_p
04494 && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x))
04495 || GET_CODE (x) == LABEL_REF))
04496 {
04497 fputs ("\t.word\tpm(", asm_out_file);
04498 output_addr_const (asm_out_file, x);
04499 fputs (")\n", asm_out_file);
04500 return true;
04501 }
04502 return default_assemble_integer (x, size, aligned_p);
04503 }
04504
04505
04506
04507
04508
04509
04510
04511
04512 void
04513 gas_output_limited_string(FILE *file, const char *str)
04514 {
04515 const unsigned char *_limited_str = (unsigned char *) str;
04516 unsigned ch;
04517 fprintf (file, "%s\"", STRING_ASM_OP);
04518 for (; (ch = *_limited_str); _limited_str++)
04519 {
04520 int escape;
04521 switch (escape = ESCAPES[ch])
04522 {
04523 case 0:
04524 putc (ch, file);
04525 break;
04526 case 1:
04527 fprintf (file, "\\%03o", ch);
04528 break;
04529 default:
04530 putc ('\\', file);
04531 putc (escape, file);
04532 break;
04533 }
04534 }
04535 fprintf (file, "\"\n");
04536 }
04537
04538
04539
04540
04541
04542
04543
04544
04545 void
04546 gas_output_ascii(FILE *file, const char *str, size_t length)
04547 {
04548 const unsigned char *_ascii_bytes = (const unsigned char *) str;
04549 const unsigned char *limit = _ascii_bytes + length;
04550 unsigned bytes_in_chunk = 0;
04551 for (; _ascii_bytes < limit; _ascii_bytes++)
04552 {
04553 const unsigned char *p;
04554 if (bytes_in_chunk >= 60)
04555 {
04556 fprintf (file, "\"\n");
04557 bytes_in_chunk = 0;
04558 }
04559 for (p = _ascii_bytes; p < limit && *p != '\0'; p++)
04560 continue;
04561 if (p < limit && (p - _ascii_bytes) <= (signed)STRING_LIMIT)
04562 {
04563 if (bytes_in_chunk > 0)
04564 {
04565 fprintf (file, "\"\n");
04566 bytes_in_chunk = 0;
04567 }
04568 gas_output_limited_string (file, (char*)_ascii_bytes);
04569 _ascii_bytes = p;
04570 }
04571 else
04572 {
04573 int escape;
04574 unsigned ch;
04575 if (bytes_in_chunk == 0)
04576 fprintf (file, "\t.ascii\t\"");
04577 switch (escape = ESCAPES[ch = *_ascii_bytes])
04578 {
04579 case 0:
04580 putc (ch, file);
04581 bytes_in_chunk++;
04582 break;
04583 case 1:
04584 fprintf (file, "\\%03o", ch);
04585 bytes_in_chunk += 4;
04586 break;
04587 default:
04588 putc ('\\', file);
04589 putc (escape, file);
04590 bytes_in_chunk += 2;
04591 break;
04592 }
04593 }
04594 }
04595 if (bytes_in_chunk > 0)
04596 fprintf (file, "\"\n");
04597 }
04598
04599
04600
04601
04602
04603 enum reg_class
04604 class_likely_spilled_p (int c)
04605 {
04606 return (c != ALL_REGS && c != ADDW_REGS);
04607 }
04608
04609
04610
04611
04612
04613
04614
04615
04616
04617
04618
04619 const struct attribute_spec avr_attribute_table[] =
04620 {
04621
04622 { "progmem", 0, 0, false, false, false, avr_handle_progmem_attribute },
04623 { "signal", 0, 0, true, false, false, avr_handle_fndecl_attribute },
04624 { "interrupt", 0, 0, true, false, false, avr_handle_fndecl_attribute },
04625 { "naked", 0, 0, true, false, false, avr_handle_fndecl_attribute },
04626 { NULL, 0, 0, false, false, false, NULL }
04627 };
04628
04629
04630
04631 static tree
04632 avr_handle_progmem_attribute (tree *node, tree name,
04633 tree args ATTRIBUTE_UNUSED,
04634 int flags ATTRIBUTE_UNUSED,
04635 bool *no_add_attrs)
04636 {
04637 if (DECL_P (*node))
04638 {
04639 if (TREE_CODE (*node) == TYPE_DECL)
04640 {
04641
04642
04643
04644 tree type = TREE_TYPE (*node);
04645 tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
04646 tree newtype = build_type_attribute_variant (type, attr);
04647
04648 TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
04649 TREE_TYPE (*node) = newtype;
04650 *no_add_attrs = true;
04651 }
04652 else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
04653 {
04654 if (DECL_INITIAL (*node) == NULL_TREE && !DECL_EXTERNAL (*node))
04655 {
04656 warning ("only initialized variables can be placed into "
04657 "program memory area");
04658 *no_add_attrs = true;
04659 }
04660 }
04661 else
04662 {
04663 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
04664 *no_add_attrs = true;
04665 }
04666 }
04667
04668 return NULL_TREE;
04669 }
04670
04671
04672
04673
04674 static tree
04675 avr_handle_fndecl_attribute (tree *node, tree name,
04676 tree args ATTRIBUTE_UNUSED,
04677 int flags ATTRIBUTE_UNUSED,
04678 bool *no_add_attrs)
04679 {
04680 if (TREE_CODE (*node) != FUNCTION_DECL)
04681 {
04682 warning ("%qs attribute only applies to functions",
04683 IDENTIFIER_POINTER (name));
04684 *no_add_attrs = true;
04685 }
04686 else
04687 {
04688 const char *func_name = IDENTIFIER_POINTER (DECL_NAME (*node));
04689 const char *attr = IDENTIFIER_POINTER (name);
04690
04691
04692
04693
04694
04695 if (strncmp (attr, "interrupt", strlen ("interrupt")) == 0)
04696 {
04697 if (strncmp (func_name, "__vector", strlen ("__vector")) != 0)
04698 {
04699 warning ("`%s' appears to be a misspelled interrupt handler",
04700 func_name);
04701 }
04702 }
04703 else if (strncmp (attr, "signal", strlen ("signal")) == 0)
04704 {
04705 if (strncmp (func_name, "__vector", strlen ("__vector")) != 0)
04706 {
04707 warning ("`%s' appears to be a misspelled signal handler",
04708 func_name);
04709 }
04710 }
04711 }
04712
04713 return NULL_TREE;
04714 }
04715
04716
04717
04718
04719 int
04720 avr_progmem_p (tree decl, tree attributes)
04721 {
04722 tree a;
04723
04724 if (TREE_CODE (decl) != VAR_DECL)
04725 return 0;
04726
04727 if (NULL_TREE
04728 != lookup_attribute ("progmem", attributes))
04729 return 1;
04730
04731 a=decl;
04732 do
04733 a = TREE_TYPE(a);
04734 while (TREE_CODE (a) == ARRAY_TYPE);
04735
04736 if (a == error_mark_node)
04737 return 0;
04738
04739 if (NULL_TREE != lookup_attribute ("progmem", TYPE_ATTRIBUTES (a)))
04740 return 1;
04741
04742 return 0;
04743 }
04744
04745
04746
04747 static void
04748 avr_insert_attributes (tree node, tree *attributes)
04749 {
04750 if (TREE_CODE (node) == VAR_DECL
04751 && (TREE_STATIC (node) || DECL_EXTERNAL (node))
04752 && avr_progmem_p (node, *attributes))
04753 {
04754 static const char dsec[] = ".progmem.data";
04755 *attributes = tree_cons (get_identifier ("section"),
04756 build_tree_list (NULL, build_string (strlen (dsec), dsec)),
04757 *attributes);
04758
04759
04760
04761 TREE_READONLY (node) = 1;
04762 }
04763 }
04764
04765 static unsigned int
04766 avr_section_type_flags (tree decl, const char *name, int reloc)
04767 {
04768 unsigned int flags = default_section_type_flags (decl, name, reloc);
04769
04770 if (strncmp (name, ".noinit", 7) == 0)
04771 {
04772 if (decl && TREE_CODE (decl) == VAR_DECL
04773 && DECL_INITIAL (decl) == NULL_TREE)
04774 flags |= SECTION_BSS;
04775 else
04776 warning ("only uninitialized variables can be placed in the "
04777 ".noinit section");
04778 }
04779
04780 return flags;
04781 }
04782
04783
04784
04785
04786 static void
04787 avr_file_start (void)
04788 {
04789 if (avr_asm_only_p)
04790 error ("MCU %qs supported for assembler only", avr_mcu_name);
04791
04792 default_file_start ();
04793
04794 fprintf (asm_out_file, "\t.arch %s\n", avr_mcu_name);
04795 fputs ("__SREG__ = 0x3f\n"
04796 "__SP_H__ = 0x3e\n"
04797 "__SP_L__ = 0x3d\n", asm_out_file);
04798
04799 fputs ("__tmp_reg__ = 0\n"
04800 "__zero_reg__ = 1\n", asm_out_file);
04801
04802
04803
04804
04805 fputs ("\t.global __do_copy_data\n", asm_out_file);
04806 fputs ("\t.global __do_clear_bss\n", asm_out_file);
04807
04808 commands_in_file = 0;
04809 commands_in_prologues = 0;
04810 commands_in_epilogues = 0;
04811 }
04812
04813
04814
04815
04816 static void
04817 avr_file_end (void)
04818 {
04819 fputs ("/* File ", asm_out_file);
04820 output_quoted_string (asm_out_file, main_input_filename);
04821 fprintf (asm_out_file,
04822 ": code %4d = 0x%04x (%4d), prologues %3d, epilogues %3d */\n",
04823 commands_in_file,
04824 commands_in_file,
04825 commands_in_file - commands_in_prologues - commands_in_epilogues,
04826 commands_in_prologues, commands_in_epilogues);
04827 }
04828
04829
04830
04831
04832
04833
04834
04835
04836 void
04837 order_regs_for_local_alloc (void)
04838 {
04839 unsigned int i;
04840 static const int order_0[] = {
04841 24,25,
04842 18,19,
04843 20,21,
04844 22,23,
04845 30,31,
04846 26,27,
04847 28,29,
04848 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
04849 0,1,
04850 32,33,34,35
04851 };
04852 static const int order_1[] = {
04853 18,19,
04854 20,21,
04855 22,23,
04856 24,25,
04857 30,31,
04858 26,27,
04859 28,29,
04860 17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,
04861 0,1,
04862 32,33,34,35
04863 };
04864 static const int order_2[] = {
04865 25,24,
04866 23,22,
04867 21,20,
04868 19,18,
04869 30,31,
04870 26,27,
04871 28,29,
04872 17,16,
04873 15,14,13,12,11,10,9,8,7,6,5,4,3,2,
04874 1,0,
04875 32,33,34,35
04876 };
04877
04878 const int *order = (TARGET_ORDER_1 ? order_1 :
04879 TARGET_ORDER_2 ? order_2 :
04880 order_0);
04881 for (i=0; i < ARRAY_SIZE (order_0); ++i)
04882 reg_alloc_order[i] = order[i];
04883 }
04884
04885
04886
04887
04888
04889
04890
04891 static int
04892 avr_operand_rtx_cost (rtx x, enum machine_mode mode, enum rtx_code outer)
04893 {
04894 enum rtx_code code = GET_CODE (x);
04895 int total;
04896
04897 switch (code)
04898 {
04899 case REG:
04900 case SUBREG:
04901 return 0;
04902
04903 case CONST_INT:
04904 case CONST_DOUBLE:
04905 return COSTS_N_INSNS (GET_MODE_SIZE (mode));
04906
04907 default:
04908 break;
04909 }
04910
04911 total = 0;
04912 avr_rtx_costs (x, code, outer, &total);
04913 return total;
04914 }
04915
04916
04917
04918
04919
04920
04921 static bool
04922 avr_rtx_costs (rtx x, int code, int outer_code, int *total)
04923 {
04924 enum machine_mode mode = GET_MODE (x);
04925 HOST_WIDE_INT val;
04926
04927 switch (code)
04928 {
04929 case CONST_INT:
04930 case CONST_DOUBLE:
04931
04932 *total = 0;
04933 return true;
04934
04935 case MEM:
04936 case CONST:
04937 case LABEL_REF:
04938 case SYMBOL_REF:
04939 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
04940 return true;
04941
04942 case NEG:
04943 switch (mode)
04944 {
04945 case QImode:
04946 case SFmode:
04947 *total = COSTS_N_INSNS (1);
04948 break;
04949
04950 case HImode:
04951 *total = COSTS_N_INSNS (3);
04952 break;
04953
04954 case SImode:
04955 *total = COSTS_N_INSNS (7);
04956 break;
04957
04958 default:
04959 return false;
04960 }
04961 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
04962 return true;
04963
04964 case ABS:
04965 switch (mode)
04966 {
04967 case QImode:
04968 case SFmode:
04969 *total = COSTS_N_INSNS (1);
04970 break;
04971
04972 default:
04973 return false;
04974 }
04975 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
04976 return true;
04977
04978 case NOT:
04979 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
04980 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
04981 return true;
04982
04983 case ZERO_EXTEND:
04984 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode)
04985 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
04986 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
04987 return true;
04988
04989 case SIGN_EXTEND:
04990 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) + 2
04991 - GET_MODE_SIZE (GET_MODE (XEXP (x, 0))));
04992 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
04993 return true;
04994
04995 case PLUS:
04996 switch (mode)
04997 {
04998 case QImode:
04999 *total = COSTS_N_INSNS (1);
05000 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
05001 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05002 break;
05003
05004 case HImode:
05005 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
05006 {
05007 *total = COSTS_N_INSNS (2);
05008 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05009 }
05010 else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
05011 *total = COSTS_N_INSNS (1);
05012 else
05013 *total = COSTS_N_INSNS (2);
05014 break;
05015
05016 case SImode:
05017 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
05018 {
05019 *total = COSTS_N_INSNS (4);
05020 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05021 }
05022 else if (INTVAL (XEXP (x, 1)) >= -63 && INTVAL (XEXP (x, 1)) <= 63)
05023 *total = COSTS_N_INSNS (1);
05024 else
05025 *total = COSTS_N_INSNS (4);
05026 break;
05027
05028 default:
05029 return false;
05030 }
05031 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
05032 return true;
05033
05034 case MINUS:
05035 case AND:
05036 case IOR:
05037 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
05038 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
05039 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
05040 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05041 return true;
05042
05043 case XOR:
05044 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode));
05045 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
05046 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05047 return true;
05048
05049 case MULT:
05050 switch (mode)
05051 {
05052 case QImode:
05053 if (AVR_ENHANCED)
05054 *total = COSTS_N_INSNS (optimize_size ? 3 : 4);
05055 else if (optimize_size)
05056 *total = COSTS_N_INSNS (AVR_MEGA ? 2 : 1);
05057 else
05058 return false;
05059
05060 case HImode:
05061 if (AVR_ENHANCED)
05062 *total = COSTS_N_INSNS (optimize_size ? 7 : 10);
05063 else if (optimize_size)
05064 *total = COSTS_N_INSNS (AVR_MEGA ? 2 : 1);
05065 else
05066 return false;
05067
05068 default:
05069 return false;
05070 }
05071 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
05072 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05073 return true;
05074
05075 case DIV:
05076 case MOD:
05077 case UDIV:
05078 case UMOD:
05079 if (optimize_size)
05080 *total = COSTS_N_INSNS (AVR_MEGA ? 2 : 1);
05081 else
05082 return false;
05083 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
05084 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05085 return true;
05086
05087 case ASHIFT:
05088 switch (mode)
05089 {
05090 case QImode:
05091 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
05092 {
05093 *total = COSTS_N_INSNS (optimize_size ? 4 : 17);
05094 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05095 }
05096 else
05097 {
05098 val = INTVAL (XEXP (x, 1));
05099 if (val == 7)
05100 *total = COSTS_N_INSNS (3);
05101 else if (val >= 0 && val <= 7)
05102 *total = COSTS_N_INSNS (val);
05103 else
05104 *total = COSTS_N_INSNS (1);
05105 }
05106 break;
05107
05108 case HImode:
05109 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
05110 {
05111 *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
05112 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05113 }
05114 else
05115 switch (INTVAL (XEXP (x, 1)))
05116 {
05117 case 0:
05118 *total = 0;
05119 break;
05120 case 1:
05121 case 8:
05122 *total = COSTS_N_INSNS (2);
05123 break;
05124 case 9:
05125 *total = COSTS_N_INSNS (3);
05126 break;
05127 case 2:
05128 case 3:
05129 case 10:
05130 case 15:
05131 *total = COSTS_N_INSNS (4);
05132 break;
05133 case 7:
05134 case 11:
05135 case 12:
05136 *total = COSTS_N_INSNS (5);
05137 break;
05138 case 4:
05139 *total = COSTS_N_INSNS (optimize_size ? 5 : 8);
05140 break;
05141 case 6:
05142 *total = COSTS_N_INSNS (optimize_size ? 5 : 9);
05143 break;
05144 case 5:
05145 *total = COSTS_N_INSNS (optimize_size ? 5 : 10);
05146 break;
05147 default:
05148 *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
05149 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05150 }
05151 break;
05152
05153 case SImode:
05154 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
05155 {
05156 *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
05157 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05158 }
05159 else
05160 switch (INTVAL (XEXP (x, 1)))
05161 {
05162 case 0:
05163 *total = 0;
05164 break;
05165 case 24:
05166 *total = COSTS_N_INSNS (3);
05167 break;
05168 case 1:
05169 case 8:
05170 case 16:
05171 *total = COSTS_N_INSNS (4);
05172 break;
05173 case 31:
05174 *total = COSTS_N_INSNS (6);
05175 break;
05176 case 2:
05177 *total = COSTS_N_INSNS (optimize_size ? 7 : 8);
05178 break;
05179 default:
05180 *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
05181 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05182 }
05183 break;
05184
05185 default:
05186 return false;
05187 }
05188 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
05189 return true;
05190
05191 case ASHIFTRT:
05192 switch (mode)
05193 {
05194 case QImode:
05195 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
05196 {
05197 *total = COSTS_N_INSNS (optimize_size ? 4 : 17);
05198 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05199 }
05200 else
05201 {
05202 val = INTVAL (XEXP (x, 1));
05203 if (val == 6)
05204 *total = COSTS_N_INSNS (4);
05205 else if (val == 7)
05206 *total = COSTS_N_INSNS (2);
05207 else if (val >= 0 && val <= 7)
05208 *total = COSTS_N_INSNS (val);
05209 else
05210 *total = COSTS_N_INSNS (1);
05211 }
05212 break;
05213
05214 case HImode:
05215 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
05216 {
05217 *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
05218 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05219 }
05220 else
05221 switch (INTVAL (XEXP (x, 1)))
05222 {
05223 case 0:
05224 *total = 0;
05225 break;
05226 case 1:
05227 *total = COSTS_N_INSNS (2);
05228 break;
05229 case 15:
05230 *total = COSTS_N_INSNS (3);
05231 break;
05232 case 2:
05233 case 7:
05234 case 8:
05235 case 9:
05236 *total = COSTS_N_INSNS (4);
05237 break;
05238 case 10:
05239 case 14:
05240 *total = COSTS_N_INSNS (5);
05241 break;
05242 case 11:
05243 *total = COSTS_N_INSNS (optimize_size ? 5 : 6);
05244 break;
05245 case 12:
05246 *total = COSTS_N_INSNS (optimize_size ? 5 : 7);
05247 break;
05248 case 6:
05249 case 13:
05250 *total = COSTS_N_INSNS (optimize_size ? 5 : 8);
05251 break;
05252 default:
05253 *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
05254 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05255 }
05256 break;
05257
05258 case SImode:
05259 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
05260 {
05261 *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
05262 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05263 }
05264 else
05265 switch (INTVAL (XEXP (x, 1)))
05266 {
05267 case 0:
05268 *total = 0;
05269 break;
05270 case 1:
05271 *total = COSTS_N_INSNS (4);
05272 break;
05273 case 8:
05274 case 16:
05275 case 24:
05276 *total = COSTS_N_INSNS (6);
05277 break;
05278 case 2:
05279 *total = COSTS_N_INSNS (optimize_size ? 7 : 8);
05280 break;
05281 case 31:
05282 *total = COSTS_N_INSNS (AVR_ENHANCED ? 4 : 5);
05283 break;
05284 default:
05285 *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
05286 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05287 }
05288 break;
05289
05290 default:
05291 return false;
05292 }
05293 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
05294 return true;
05295
05296 case LSHIFTRT:
05297 switch (mode)
05298 {
05299 case QImode:
05300 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
05301 {
05302 *total = COSTS_N_INSNS (optimize_size ? 4 : 17);
05303 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05304 }
05305 else
05306 {
05307 val = INTVAL (XEXP (x, 1));
05308 if (val == 7)
05309 *total = COSTS_N_INSNS (3);
05310 else if (val >= 0 && val <= 7)
05311 *total = COSTS_N_INSNS (val);
05312 else
05313 *total = COSTS_N_INSNS (1);
05314 }
05315 break;
05316
05317 case HImode:
05318 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
05319 {
05320 *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
05321 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05322 }
05323 else
05324 switch (INTVAL (XEXP (x, 1)))
05325 {
05326 case 0:
05327 *total = 0;
05328 break;
05329 case 1:
05330 case 8:
05331 *total = COSTS_N_INSNS (2);
05332 break;
05333 case 9:
05334 *total = COSTS_N_INSNS (3);
05335 break;
05336 case 2:
05337 case 10:
05338 case 15:
05339 *total = COSTS_N_INSNS (4);
05340 break;
05341 case 7:
05342 case 11:
05343 *total = COSTS_N_INSNS (5);
05344 break;
05345 case 3:
05346 case 12:
05347 case 13:
05348 case 14:
05349 *total = COSTS_N_INSNS (optimize_size ? 5 : 6);
05350 break;
05351 case 4:
05352 *total = COSTS_N_INSNS (optimize_size ? 5 : 7);
05353 break;
05354 case 5:
05355 case 6:
05356 *total = COSTS_N_INSNS (optimize_size ? 5 : 9);
05357 break;
05358 default:
05359 *total = COSTS_N_INSNS (optimize_size ? 5 : 41);
05360 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05361 }
05362 break;
05363
05364 case SImode:
05365 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
05366 {
05367 *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
05368 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05369 }
05370 else
05371 switch (INTVAL (XEXP (x, 1)))
05372 {
05373 case 0:
05374 *total = 0;
05375 break;
05376 case 1:
05377 *total = COSTS_N_INSNS (4);
05378 break;
05379 case 2:
05380 *total = COSTS_N_INSNS (optimize_size ? 7 : 8);
05381 break;
05382 case 8:
05383 case 16:
05384 case 24:
05385 *total = COSTS_N_INSNS (4);
05386 break;
05387 case 31:
05388 *total = COSTS_N_INSNS (6);
05389 break;
05390 default:
05391 *total = COSTS_N_INSNS (optimize_size ? 7 : 113);
05392 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05393 }
05394 break;
05395
05396 default:
05397 return false;
05398 }
05399 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
05400 return true;
05401
05402 case COMPARE:
05403 switch (GET_MODE (XEXP (x, 0)))
05404 {
05405 case QImode:
05406 *total = COSTS_N_INSNS (1);
05407 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
05408 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05409 break;
05410
05411 case HImode:
05412 *total = COSTS_N_INSNS (2);
05413 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
05414 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05415 else if (INTVAL (XEXP (x, 1)) != 0)
05416 *total += COSTS_N_INSNS (1);
05417 break;
05418
05419 case SImode:
05420 *total = COSTS_N_INSNS (4);
05421 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
05422 *total += avr_operand_rtx_cost (XEXP (x, 1), mode, code);
05423 else if (INTVAL (XEXP (x, 1)) != 0)
05424 *total += COSTS_N_INSNS (3);
05425 break;
05426
05427 default:
05428 return false;
05429 }
05430 *total += avr_operand_rtx_cost (XEXP (x, 0), mode, code);
05431 return true;
05432
05433 default:
05434 break;
05435 }
05436 return false;
05437 }
05438
05439
05440
05441 static int
05442 avr_address_cost (rtx x)
05443 {
05444 if (GET_CODE (x) == PLUS
05445 && GET_CODE (XEXP (x,1)) == CONST_INT
05446 && (REG_P (XEXP (x,0)) || GET_CODE (XEXP (x,0)) == SUBREG)
05447 && INTVAL (XEXP (x,1)) >= 61)
05448 return 18;
05449 if (CONSTANT_ADDRESS_P (x))
05450 {
05451 if (avr_io_address_p (x, 1))
05452 return 2;
05453 return 4;
05454 }
05455 return 4;
05456 }
05457
05458
05459
05460 int
05461 extra_constraint (rtx x, int c)
05462 {
05463 if (c == 'Q'
05464 && GET_CODE (x) == MEM
05465 && GET_CODE (XEXP (x,0)) == PLUS)
05466 {
05467 if (TARGET_ALL_DEBUG)
05468 {
05469 fprintf (stderr, ("extra_constraint:\n"
05470 "reload_completed: %d\n"
05471 "reload_in_progress: %d\n"),
05472 reload_completed, reload_in_progress);
05473 debug_rtx (x);
05474 }
05475 if (GET_CODE (x) == MEM
05476 && GET_CODE (XEXP (x,0)) == PLUS
05477 && REG_P (XEXP (XEXP (x,0), 0))
05478 && GET_CODE (XEXP (XEXP (x,0), 1)) == CONST_INT
05479 && (INTVAL (XEXP (XEXP (x,0), 1))
05480 <= MAX_LD_OFFSET (GET_MODE (x))))
05481 {
05482 rtx xx = XEXP (XEXP (x,0), 0);
05483 int regno = REGNO (xx);
05484 if (TARGET_ALL_DEBUG)
05485 {
05486 fprintf (stderr, ("extra_constraint:\n"
05487 "reload_completed: %d\n"
05488 "reload_in_progress: %d\n"),
05489 reload_completed, reload_in_progress);
05490 debug_rtx (x);
05491 }
05492 if (regno >= FIRST_PSEUDO_REGISTER)
05493 return 1;
05494 else if (regno == REG_Z || regno == REG_Y)
05495 return 1;
05496 else if (xx == frame_pointer_rtx
05497 || xx == arg_pointer_rtx)
05498 return 1;
05499 }
05500 }
05501 return 0;
05502 }
05503
05504
05505
05506 RTX_CODE
05507 avr_normalize_condition (RTX_CODE condition)
05508 {
05509 switch (condition)
05510 {
05511 case GT:
05512 return GE;
05513 case GTU:
05514 return GEU;
05515 case LE:
05516 return LT;
05517 case LEU:
05518 return LTU;
05519 default:
05520 abort ();
05521 }
05522 }
05523
05524
05525
05526 static void
05527 avr_reorg (void)
05528 {
05529 rtx insn, pattern;
05530
05531 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
05532 {
05533 if (! (GET_CODE (insn) == INSN
05534 || GET_CODE (insn) == CALL_INSN
05535 || GET_CODE (insn) == JUMP_INSN)
05536 || !single_set (insn))
05537 continue;
05538
05539 pattern = PATTERN (insn);
05540
05541 if (GET_CODE (pattern) == PARALLEL)
05542 pattern = XVECEXP (pattern, 0, 0);
05543 if (GET_CODE (pattern) == SET
05544 && SET_DEST (pattern) == cc0_rtx
05545 && compare_diff_p (insn))
05546 {
05547 if (GET_CODE (SET_SRC (pattern)) == COMPARE)
05548 {
05549
05550
05551 pattern = SET_SRC (pattern);
05552 if (true_regnum (XEXP (pattern,0)) >= 0
05553 && true_regnum (XEXP (pattern,1)) >= 0 )
05554 {
05555 rtx x = XEXP (pattern,0);
05556 rtx next = next_real_insn (insn);
05557 rtx pat = PATTERN (next);
05558 rtx src = SET_SRC (pat);
05559 rtx t = XEXP (src,0);
05560 PUT_CODE (t, swap_condition (GET_CODE (t)));
05561 XEXP (pattern,0) = XEXP (pattern,1);
05562 XEXP (pattern,1) = x;
05563 INSN_CODE (next) = -1;
05564 }
05565 else if (true_regnum (XEXP (pattern,0)) >= 0
05566 && GET_CODE (XEXP (pattern,1)) == CONST_INT)
05567 {
05568 rtx x = XEXP (pattern,1);
05569 rtx next = next_real_insn (insn);
05570 rtx pat = PATTERN (next);
05571 rtx src = SET_SRC (pat);
05572 rtx t = XEXP (src,0);
05573 enum machine_mode mode = GET_MODE (XEXP (pattern, 0));
05574
05575 if (avr_simplify_comparison_p (mode, GET_CODE (t), x))
05576 {
05577 XEXP (pattern, 1) = gen_int_mode (INTVAL (x) + 1, mode);
05578 PUT_CODE (t, avr_normalize_condition (GET_CODE (t)));
05579 INSN_CODE (next) = -1;
05580 INSN_CODE (insn) = -1;
05581 }
05582 }
05583 }
05584 else if (true_regnum (SET_SRC (pattern)) >= 0)
05585 {
05586
05587 rtx next = next_real_insn (insn);
05588 rtx pat = PATTERN (next);
05589 rtx src = SET_SRC (pat);
05590 rtx t = XEXP (src,0);
05591
05592 PUT_CODE (t, swap_condition (GET_CODE (t)));
05593 SET_SRC (pattern) = gen_rtx_NEG (GET_MODE (SET_SRC (pattern)),
05594 SET_SRC (pattern));
05595 INSN_CODE (next) = -1;
05596 INSN_CODE (insn) = -1;
05597 }
05598 }
05599 }
05600 }
05601
05602
05603
05604 int
05605 avr_ret_register (void)
05606 {
05607 return 24;
05608 }
05609
05610
05611
05612
05613 rtx
05614 avr_libcall_value (enum machine_mode mode)
05615 {
05616 int offs = GET_MODE_SIZE (mode);
05617 if (offs < 2)
05618 offs = 2;
05619 return gen_rtx_REG (mode, RET_REGISTER + 2 - offs);
05620 }
05621
05622
05623
05624
05625 rtx
05626 avr_function_value (tree type, tree func ATTRIBUTE_UNUSED)
05627 {
05628 unsigned int offs;
05629
05630 if (TYPE_MODE (type) != BLKmode)
05631 return avr_libcall_value (TYPE_MODE (type));
05632
05633 offs = int_size_in_bytes (type);
05634 if (offs < 2)
05635 offs = 2;
05636 if (offs > 2 && offs < GET_MODE_SIZE (SImode))
05637 offs = GET_MODE_SIZE (SImode);
05638 else if (offs > GET_MODE_SIZE (SImode) && offs < GET_MODE_SIZE (DImode))
05639 offs = GET_MODE_SIZE (DImode);
05640
05641 return gen_rtx_REG (BLKmode, RET_REGISTER + 2 - offs);
05642 }
05643
05644
05645
05646 int
05647 mask_one_bit_p (HOST_WIDE_INT mask)
05648 {
05649 int i;
05650 unsigned HOST_WIDE_INT n=mask;
05651 for (i = 0; i < 32; ++i)
05652 {
05653 if (n & 0x80000000L)
05654 {
05655 if (n & 0x7fffffffL)
05656 return 0;
05657 else
05658 return 32-i;
05659 }
05660 n<<=1;
05661 }
05662 return 0;
05663 }
05664
05665
05666
05667
05668
05669
05670 enum reg_class
05671 preferred_reload_class (rtx x ATTRIBUTE_UNUSED, enum reg_class class)
05672 {
05673 return class;
05674 }
05675
05676 int
05677 test_hard_reg_class (enum reg_class class, rtx x)
05678 {
05679 int regno = true_regnum (x);
05680 if (regno < 0)
05681 return 0;
05682
05683 if (TEST_HARD_REG_CLASS (class, regno))
05684 return 1;
05685
05686 return 0;
05687 }
05688
05689
05690 int
05691 jump_over_one_insn_p (rtx insn, rtx dest)
05692 {
05693 int uid = INSN_UID (GET_CODE (dest) == LABEL_REF
05694 ? XEXP (dest, 0)
05695 : dest);
05696 int jump_addr = INSN_ADDRESSES (INSN_UID (insn));
05697 int dest_addr = INSN_ADDRESSES (uid);
05698 return dest_addr - jump_addr == get_attr_length (insn) + 1;
05699 }
05700
05701
05702
05703
05704
05705
05706 int
05707 avr_hard_regno_mode_ok (int regno, enum machine_mode mode)
05708 {
05709
05710 if (regno == REG_Y && mode == Pmode)
05711 return 1;
05712
05713
05714 if (regno <= (REG_Y + 1) && (regno + GET_MODE_SIZE (mode)) >= (REG_Y + 1))
05715 return 0;
05716
05717 if (mode == QImode)
05718 return 1;
05719
05720
05721 if (regno + GET_MODE_SIZE (mode) > FIRST_PSEUDO_REGISTER)
05722 return 0;
05723
05724
05725 return !(regno & 1);
05726 }
05727
05728
05729
05730
05731
05732 int
05733 avr_io_address_p (rtx x, int size)
05734 {
05735 return (optimize > 0 && GET_CODE (x) == CONST_INT
05736 && INTVAL (x) >= 0x20 && INTVAL (x) <= 0x60 - size);
05737 }
05738
05739
05740
05741 int
05742 const_int_pow2_p (rtx x)
05743 {
05744 if (GET_CODE (x) == CONST_INT)
05745 {
05746 HOST_WIDE_INT d = INTVAL (x);
05747 HOST_WIDE_INT abs_d = (d >= 0) ? d : -d;
05748 return exact_log2 (abs_d) + 1;
05749 }
05750 return 0;
05751 }
05752
05753 const char *
05754 output_reload_inhi (rtx insn ATTRIBUTE_UNUSED, rtx *operands, int *len)
05755 {
05756 int tmp;
05757 if (!len)
05758 len = &tmp;
05759
05760 if (GET_CODE (operands[1]) == CONST_INT)
05761 {
05762 int val = INTVAL (operands[1]);
05763 if ((val & 0xff) == 0)
05764 {
05765 *len = 3;
05766 return (AS2 (mov,%A0,__zero_reg__) CR_TAB
05767 AS2 (ldi,%2,hi8(%1)) CR_TAB
05768 AS2 (mov,%B0,%2));
05769 }
05770 else if ((val & 0xff00) == 0)
05771 {
05772 *len = 3;
05773 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
05774 AS2 (mov,%A0,%2) CR_TAB
05775 AS2 (mov,%B0,__zero_reg__));
05776 }
05777 else if ((val & 0xff) == ((val & 0xff00) >> 8))
05778 {
05779 *len = 3;
05780 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
05781 AS2 (mov,%A0,%2) CR_TAB
05782 AS2 (mov,%B0,%2));
05783 }
05784 }
05785 *len = 4;
05786 return (AS2 (ldi,%2,lo8(%1)) CR_TAB
05787 AS2 (mov,%A0,%2) CR_TAB
05788 AS2 (ldi,%2,hi8(%1)) CR_TAB
05789 AS2 (mov,%B0,%2));
05790 }
05791
05792
05793 const char *
05794 output_reload_insisf (rtx insn ATTRIBUTE_UNUSED, rtx *operands, int *len)
05795 {
05796 rtx src = operands[1];
05797 int cnst = (GET_CODE (src) == CONST_INT);
05798
05799 if (len)
05800 {
05801 if (cnst)
05802 *len = 4 + ((INTVAL (src) & 0xff) != 0)
05803 + ((INTVAL (src) & 0xff00) != 0)
05804 + ((INTVAL (src) & 0xff0000) != 0)
05805 + ((INTVAL (src) & 0xff000000) != 0);
05806 else
05807 *len = 8;
05808
05809 return "";
05810 }
05811
05812 if (cnst && ((INTVAL (src) & 0xff) == 0))
05813 output_asm_insn (AS2 (mov, %A0, __zero_reg__), operands);
05814 else
05815 {
05816 output_asm_insn (AS2 (ldi, %2, lo8(%1)), operands);
05817 output_asm_insn (AS2 (mov, %A0, %2), operands);
05818 }
05819 if (cnst && ((INTVAL (src) & 0xff00) == 0))
05820 output_asm_insn (AS2 (mov, %B0, __zero_reg__), operands);
05821 else
05822 {
05823 output_asm_insn (AS2 (ldi, %2, hi8(%1)), operands);
05824 output_asm_insn (AS2 (mov, %B0, %2), operands);
05825 }
05826 if (cnst && ((INTVAL (src) & 0xff0000) == 0))
05827 output_asm_insn (AS2 (mov, %C0, __zero_reg__), operands);
05828 else
05829 {
05830 output_asm_insn (AS2 (ldi, %2, hlo8(%1)), operands);
05831 output_asm_insn (AS2 (mov, %C0, %2), operands);
05832 }
05833 if (cnst && ((INTVAL (src) & 0xff000000) == 0))
05834 output_asm_insn (AS2 (mov, %D0, __zero_reg__), operands);
05835 else
05836 {
05837 output_asm_insn (AS2 (ldi, %2, hhi8(%1)), operands);
05838 output_asm_insn (AS2 (mov, %D0, %2), operands);
05839 }
05840 return "";
05841 }
05842
05843 void
05844 avr_output_bld (rtx operands[], int bit_nr)
05845 {
05846 static char s[] = "bld %A0,0";
05847
05848 s[5] = 'A' + (bit_nr >> 3);
05849 s[8] = '0' + (bit_nr & 7);
05850 output_asm_insn (s, operands);
05851 }
05852
05853 void
05854 avr_output_addr_vec_elt (FILE *stream, int value)
05855 {
05856 progmem_section ();
05857 if (AVR_MEGA)
05858 fprintf (stream, "\t.word pm(.L%d)\n", value);
05859 else
05860 fprintf (stream, "\trjmp .L%d\n", value);
05861
05862 jump_tables_size++;
05863 }
05864
05865
05866
05867
05868 int
05869 avr_peep2_scratch_safe (rtx scratch)
05870 {
05871 if ((interrupt_function_p (current_function_decl)
05872 || signal_function_p (current_function_decl))
05873 && leaf_function_p ())
05874 {
05875 int first_reg = true_regnum (scratch);
05876 int last_reg = first_reg + GET_MODE_SIZE (GET_MODE (scratch)) - 1;
05877 int reg;
05878
05879 for (reg = first_reg; reg <= last_reg; reg++)
05880 {
05881 if (!regs_ever_live[reg])
05882 return 0;
05883 }
05884 }
05885 return 1;
05886 }
05887
05888
05889
05890
05891
05892
05893
05894
05895
05896 const char *
05897 avr_out_sbxx_branch (rtx insn, rtx operands[])
05898 {
05899 enum rtx_code comp = GET_CODE (operands[0]);
05900 int long_jump = (get_attr_length (insn) >= 4);
05901 int reverse = long_jump || jump_over_one_insn_p (insn, operands[3]);
05902
05903 if (comp == GE)
05904 comp = EQ;
05905 else if (comp == LT)
05906 comp = NE;
05907
05908 if (reverse)
05909 comp = reverse_condition (comp);
05910
05911 if (GET_CODE (operands[1]) == CONST_INT)
05912 {
05913 if (INTVAL (operands[1]) < 0x40)
05914 {
05915 if (comp == EQ)
05916 output_asm_insn (AS2 (sbis,%1-0x20,%2), operands);
05917 else
05918 output_asm_insn (AS2 (sbic,%1-0x20,%2), operands);
05919 }
05920 else
05921 {
05922 output_asm_insn (AS2 (in,__tmp_reg__,%1-0x20), operands);
05923 if (comp == EQ)
05924 output_asm_insn (AS2 (sbrs,__tmp_reg__,%2), operands);
05925 else
05926 output_asm_insn (AS2 (sbrc,__tmp_reg__,%2), operands);
05927 }
05928 }
05929 else
05930 {
05931 if (GET_MODE (operands[1]) == QImode)
05932 {
05933 if (comp == EQ)
05934 output_asm_insn (AS2 (sbrs,%1,%2), operands);
05935 else
05936 output_asm_insn (AS2 (sbrc,%1,%2), operands);
05937 }
05938 else
05939 {
05940 static char buf[] = "sbrc %A1,0";
05941 int bit_nr = exact_log2 (INTVAL (operands[2])
05942 & GET_MODE_MASK (GET_MODE (operands[1])));
05943
05944 buf[3] = (comp == EQ) ? 's' : 'c';
05945 buf[6] = 'A' + (bit_nr >> 3);
05946 buf[9] = '0' + (bit_nr & 7);
05947 output_asm_insn (buf, operands);
05948 }
05949 }
05950
05951 if (long_jump)
05952 return (AS1 (rjmp,.+4) CR_TAB
05953 AS1 (jmp,%3));
05954 if (!reverse)
05955 return AS1 (rjmp,%3);
05956 return "";
05957 }
05958
05959
05960
05961 static void
05962 avr_asm_out_ctor (rtx symbol, int priority)
05963 {
05964 fputs ("\t.global __do_global_ctors\n", asm_out_file);
05965 default_ctor_section_asm_out_constructor (symbol, priority);
05966 }
05967
05968
05969
05970 static void
05971 avr_asm_out_dtor (rtx symbol, int priority)
05972 {
05973 fputs ("\t.global __do_global_dtors\n", asm_out_file);
05974 default_dtor_section_asm_out_destructor (symbol, priority);
05975 }
05976
05977
05978
05979 static bool
05980 avr_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
05981 {
05982 if (TYPE_MODE (type) == BLKmode)
05983 {
05984 HOST_WIDE_INT size = int_size_in_bytes (type);
05985 return (size == -1 || size > 8);
05986 }
05987 else
05988 return false;
05989 }
05990
05991 #include "gt-avr.h"