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