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