00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025 #include "coretypes.h"
00026 #include "tm.h"
00027 #include "rtl.h"
00028 #include "tree.h"
00029 #include "regs.h"
00030 #include "hard-reg-set.h"
00031 #include "real.h"
00032 #include "insn-config.h"
00033 #include "conditions.h"
00034 #include "output.h"
00035 #include "insn-attr.h"
00036 #include "flags.h"
00037 #include "recog.h"
00038 #include "expr.h"
00039 #include "optabs.h"
00040 #include "function.h"
00041 #include "obstack.h"
00042 #include "toplev.h"
00043 #include "tm_p.h"
00044 #include "target.h"
00045 #include "target-def.h"
00046
00047
00048
00049 int mn10300_unspec_int_label_counter;
00050
00051
00052
00053
00054
00055 int mn10300_protect_label;
00056
00057
00058 enum processor_type mn10300_processor = PROCESSOR_DEFAULT;
00059
00060
00061
00062
00063 #define REG_SAVE_BYTES (4 * regs_ever_live[2] \
00064 + 4 * regs_ever_live[3] \
00065 + 4 * regs_ever_live[6] \
00066 + 4 * regs_ever_live[7] \
00067 + 16 * (regs_ever_live[14] || regs_ever_live[15] \
00068 || regs_ever_live[16] || regs_ever_live[17]))
00069
00070
00071 static bool mn10300_handle_option (size_t, const char *, int);
00072 static int mn10300_address_cost_1 (rtx, int *);
00073 static int mn10300_address_cost (rtx);
00074 static bool mn10300_rtx_costs (rtx, int, int, int *);
00075 static void mn10300_file_start (void);
00076 static bool mn10300_return_in_memory (tree, tree);
00077 static rtx mn10300_builtin_saveregs (void);
00078 static bool mn10300_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
00079 tree, bool);
00080 static int mn10300_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
00081 tree, bool);
00082
00083
00084 #undef TARGET_ASM_ALIGNED_HI_OP
00085 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
00086
00087 #undef TARGET_RTX_COSTS
00088 #define TARGET_RTX_COSTS mn10300_rtx_costs
00089 #undef TARGET_ADDRESS_COST
00090 #define TARGET_ADDRESS_COST mn10300_address_cost
00091
00092 #undef TARGET_ASM_FILE_START
00093 #define TARGET_ASM_FILE_START mn10300_file_start
00094 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
00095 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
00096
00097 #undef TARGET_DEFAULT_TARGET_FLAGS
00098 #define TARGET_DEFAULT_TARGET_FLAGS MASK_MULT_BUG | MASK_PTR_A0D0
00099 #undef TARGET_HANDLE_OPTION
00100 #define TARGET_HANDLE_OPTION mn10300_handle_option
00101
00102 #undef TARGET_ENCODE_SECTION_INFO
00103 #define TARGET_ENCODE_SECTION_INFO mn10300_encode_section_info
00104
00105 #undef TARGET_PROMOTE_PROTOTYPES
00106 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
00107 #undef TARGET_RETURN_IN_MEMORY
00108 #define TARGET_RETURN_IN_MEMORY mn10300_return_in_memory
00109 #undef TARGET_PASS_BY_REFERENCE
00110 #define TARGET_PASS_BY_REFERENCE mn10300_pass_by_reference
00111 #undef TARGET_CALLEE_COPIES
00112 #define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true
00113 #undef TARGET_ARG_PARTIAL_BYTES
00114 #define TARGET_ARG_PARTIAL_BYTES mn10300_arg_partial_bytes
00115
00116 #undef TARGET_EXPAND_BUILTIN_SAVEREGS
00117 #define TARGET_EXPAND_BUILTIN_SAVEREGS mn10300_builtin_saveregs
00118
00119 static void mn10300_encode_section_info (tree, rtx, int);
00120 struct gcc_target targetm = TARGET_INITIALIZER;
00121
00122
00123
00124 static bool
00125 mn10300_handle_option (size_t code,
00126 const char *arg ATTRIBUTE_UNUSED,
00127 int value)
00128 {
00129 switch (code)
00130 {
00131 case OPT_mam33:
00132 mn10300_processor = value ? PROCESSOR_AM33 : PROCESSOR_MN10300;
00133 return true;
00134 case OPT_mam33_2:
00135 mn10300_processor = (value
00136 ? PROCESSOR_AM33_2
00137 : MIN (PROCESSOR_AM33, PROCESSOR_DEFAULT));
00138 return true;
00139 default:
00140 return true;
00141 }
00142 }
00143
00144
00145
00146 void
00147 mn10300_override_options (void)
00148 {
00149 if (TARGET_AM33)
00150 target_flags &= ~MASK_MULT_BUG;
00151 }
00152
00153 static void
00154 mn10300_file_start (void)
00155 {
00156 default_file_start ();
00157
00158 if (TARGET_AM33_2)
00159 fprintf (asm_out_file, "\t.am33_2\n");
00160 else if (TARGET_AM33)
00161 fprintf (asm_out_file, "\t.am33\n");
00162 }
00163
00164
00165
00166
00167
00168 void
00169 print_operand (FILE *file, rtx x, int code)
00170 {
00171 switch (code)
00172 {
00173 case 'b':
00174 case 'B':
00175 if (cc_status.mdep.fpCC)
00176 {
00177 switch (code == 'b' ? GET_CODE (x)
00178 : reverse_condition_maybe_unordered (GET_CODE (x)))
00179 {
00180 case NE:
00181 fprintf (file, "ne");
00182 break;
00183 case EQ:
00184 fprintf (file, "eq");
00185 break;
00186 case GE:
00187 fprintf (file, "ge");
00188 break;
00189 case GT:
00190 fprintf (file, "gt");
00191 break;
00192 case LE:
00193 fprintf (file, "le");
00194 break;
00195 case LT:
00196 fprintf (file, "lt");
00197 break;
00198 case ORDERED:
00199 fprintf (file, "lge");
00200 break;
00201 case UNORDERED:
00202 fprintf (file, "uo");
00203 break;
00204 case LTGT:
00205 fprintf (file, "lg");
00206 break;
00207 case UNEQ:
00208 fprintf (file, "ue");
00209 break;
00210 case UNGE:
00211 fprintf (file, "uge");
00212 break;
00213 case UNGT:
00214 fprintf (file, "ug");
00215 break;
00216 case UNLE:
00217 fprintf (file, "ule");
00218 break;
00219 case UNLT:
00220 fprintf (file, "ul");
00221 break;
00222 default:
00223 gcc_unreachable ();
00224 }
00225 break;
00226 }
00227
00228 switch (code == 'b' ? GET_CODE (x) : reverse_condition (GET_CODE (x)))
00229 {
00230 case NE:
00231 fprintf (file, "ne");
00232 break;
00233 case EQ:
00234 fprintf (file, "eq");
00235 break;
00236 case GE:
00237 fprintf (file, "ge");
00238 break;
00239 case GT:
00240 fprintf (file, "gt");
00241 break;
00242 case LE:
00243 fprintf (file, "le");
00244 break;
00245 case LT:
00246 fprintf (file, "lt");
00247 break;
00248 case GEU:
00249 fprintf (file, "cc");
00250 break;
00251 case GTU:
00252 fprintf (file, "hi");
00253 break;
00254 case LEU:
00255 fprintf (file, "ls");
00256 break;
00257 case LTU:
00258 fprintf (file, "cs");
00259 break;
00260 default:
00261 gcc_unreachable ();
00262 }
00263 break;
00264 case 'C':
00265
00266
00267
00268 if (GET_CODE (x) == REG)
00269 {
00270 fputc ('(', file);
00271 print_operand (file, x, 0);
00272 fputc (')', file);
00273 }
00274 else
00275 print_operand (file, x, 0);
00276 break;
00277
00278 case 'D':
00279 switch (GET_CODE (x))
00280 {
00281 case MEM:
00282 fputc ('(', file);
00283 output_address (XEXP (x, 0));
00284 fputc (')', file);
00285 break;
00286
00287 case REG:
00288 fprintf (file, "fd%d", REGNO (x) - 18);
00289 break;
00290
00291 default:
00292 gcc_unreachable ();
00293 }
00294 break;
00295
00296
00297 case 'L':
00298 switch (GET_CODE (x))
00299 {
00300 case MEM:
00301 fputc ('(', file);
00302 output_address (XEXP (x, 0));
00303 fputc (')', file);
00304 break;
00305
00306 case REG:
00307 fprintf (file, "%s", reg_names[REGNO (x)]);
00308 break;
00309
00310 case SUBREG:
00311 fprintf (file, "%s", reg_names[subreg_regno (x)]);
00312 break;
00313
00314 case CONST_DOUBLE:
00315 {
00316 long val[2];
00317 REAL_VALUE_TYPE rv;
00318
00319 switch (GET_MODE (x))
00320 {
00321 case DFmode:
00322 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
00323 REAL_VALUE_TO_TARGET_DOUBLE (rv, val);
00324 fprintf (file, "0x%lx", val[0]);
00325 break;;
00326 case SFmode:
00327 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
00328 REAL_VALUE_TO_TARGET_SINGLE (rv, val[0]);
00329 fprintf (file, "0x%lx", val[0]);
00330 break;;
00331 case VOIDmode:
00332 case DImode:
00333 print_operand_address (file,
00334 GEN_INT (CONST_DOUBLE_LOW (x)));
00335 break;
00336 default:
00337 break;
00338 }
00339 break;
00340 }
00341
00342 case CONST_INT:
00343 {
00344 rtx low, high;
00345 split_double (x, &low, &high);
00346 fprintf (file, "%ld", (long)INTVAL (low));
00347 break;
00348 }
00349
00350 default:
00351 gcc_unreachable ();
00352 }
00353 break;
00354
00355
00356 case 'H':
00357 switch (GET_CODE (x))
00358 {
00359 case MEM:
00360 fputc ('(', file);
00361 x = adjust_address (x, SImode, 4);
00362 output_address (XEXP (x, 0));
00363 fputc (')', file);
00364 break;
00365
00366 case REG:
00367 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
00368 break;
00369
00370 case SUBREG:
00371 fprintf (file, "%s", reg_names[subreg_regno (x) + 1]);
00372 break;
00373
00374 case CONST_DOUBLE:
00375 {
00376 long val[2];
00377 REAL_VALUE_TYPE rv;
00378
00379 switch (GET_MODE (x))
00380 {
00381 case DFmode:
00382 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
00383 REAL_VALUE_TO_TARGET_DOUBLE (rv, val);
00384 fprintf (file, "0x%lx", val[1]);
00385 break;;
00386 case SFmode:
00387 gcc_unreachable ();
00388 case VOIDmode:
00389 case DImode:
00390 print_operand_address (file,
00391 GEN_INT (CONST_DOUBLE_HIGH (x)));
00392 break;
00393 default:
00394 break;
00395 }
00396 break;
00397 }
00398
00399 case CONST_INT:
00400 {
00401 rtx low, high;
00402 split_double (x, &low, &high);
00403 fprintf (file, "%ld", (long)INTVAL (high));
00404 break;
00405 }
00406
00407 default:
00408 gcc_unreachable ();
00409 }
00410 break;
00411
00412 case 'A':
00413 fputc ('(', file);
00414 if (GET_CODE (XEXP (x, 0)) == REG)
00415 output_address (gen_rtx_PLUS (SImode, XEXP (x, 0), const0_rtx));
00416 else
00417 output_address (XEXP (x, 0));
00418 fputc (')', file);
00419 break;
00420
00421 case 'N':
00422 gcc_assert (INTVAL (x) >= -128 && INTVAL (x) <= 255);
00423 fprintf (file, "%d", (int)((~INTVAL (x)) & 0xff));
00424 break;
00425
00426 case 'U':
00427 gcc_assert (INTVAL (x) >= -128 && INTVAL (x) <= 255);
00428 fprintf (file, "%d", (int)(INTVAL (x) & 0xff));
00429 break;
00430
00431
00432
00433
00434
00435 case 'S':
00436 if (GET_CODE (x) == CONST_INT)
00437 {
00438 fprintf (file, "%d", (int)(INTVAL (x) & 0x1f));
00439 break;
00440 }
00441
00442
00443 default:
00444 switch (GET_CODE (x))
00445 {
00446 case MEM:
00447 fputc ('(', file);
00448 output_address (XEXP (x, 0));
00449 fputc (')', file);
00450 break;
00451
00452 case PLUS:
00453 output_address (x);
00454 break;
00455
00456 case REG:
00457 fprintf (file, "%s", reg_names[REGNO (x)]);
00458 break;
00459
00460 case SUBREG:
00461 fprintf (file, "%s", reg_names[subreg_regno (x)]);
00462 break;
00463
00464
00465 case CONST_DOUBLE:
00466 {
00467 unsigned long val;
00468 REAL_VALUE_TYPE rv;
00469
00470 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
00471 REAL_VALUE_TO_TARGET_SINGLE (rv, val);
00472 fprintf (file, "0x%lx", val);
00473 break;
00474 }
00475
00476 case CONST_INT:
00477 case SYMBOL_REF:
00478 case CONST:
00479 case LABEL_REF:
00480 case CODE_LABEL:
00481 case UNSPEC:
00482 print_operand_address (file, x);
00483 break;
00484 default:
00485 gcc_unreachable ();
00486 }
00487 break;
00488 }
00489 }
00490
00491
00492
00493 void
00494 print_operand_address (FILE *file, rtx addr)
00495 {
00496 switch (GET_CODE (addr))
00497 {
00498 case POST_INC:
00499 print_operand_address (file, XEXP (addr, 0));
00500 fputc ('+', file);
00501 break;
00502 case REG:
00503 print_operand (file, addr, 0);
00504 break;
00505 case PLUS:
00506 {
00507 rtx base, index;
00508 if (REG_P (XEXP (addr, 0))
00509 && REG_OK_FOR_BASE_P (XEXP (addr, 0)))
00510 base = XEXP (addr, 0), index = XEXP (addr, 1);
00511 else if (REG_P (XEXP (addr, 1))
00512 && REG_OK_FOR_BASE_P (XEXP (addr, 1)))
00513 base = XEXP (addr, 1), index = XEXP (addr, 0);
00514 else
00515 gcc_unreachable ();
00516 print_operand (file, index, 0);
00517 fputc (',', file);
00518 print_operand (file, base, 0);;
00519 break;
00520 }
00521 case SYMBOL_REF:
00522 output_addr_const (file, addr);
00523 break;
00524 default:
00525 output_addr_const (file, addr);
00526 break;
00527 }
00528 }
00529
00530
00531 static int
00532 fp_regs_to_save (void)
00533 {
00534 int i, n = 0;
00535
00536 if (! TARGET_AM33_2)
00537 return 0;
00538
00539 for (i = FIRST_FP_REGNUM; i <= LAST_FP_REGNUM; ++i)
00540 if (regs_ever_live[i] && ! call_used_regs[i])
00541 ++n;
00542
00543 return n;
00544 }
00545
00546
00547
00548
00549
00550
00551
00552 void
00553 mn10300_print_reg_list (FILE *file, int mask)
00554 {
00555 int need_comma;
00556 int i;
00557
00558 need_comma = 0;
00559 fputc ('[', file);
00560
00561 for (i = 0; i < FIRST_EXTENDED_REGNUM; i++)
00562 if ((mask & (1 << i)) != 0)
00563 {
00564 if (need_comma)
00565 fputc (',', file);
00566 fputs (reg_names [i], file);
00567 need_comma = 1;
00568 }
00569
00570 if ((mask & 0x3c000) != 0)
00571 {
00572 gcc_assert ((mask & 0x3c000) == 0x3c000);
00573 if (need_comma)
00574 fputc (',', file);
00575 fputs ("exreg1", file);
00576 need_comma = 1;
00577 }
00578
00579 fputc (']', file);
00580 }
00581
00582 int
00583 can_use_return_insn (void)
00584 {
00585
00586 int size = get_frame_size () + current_function_outgoing_args_size;
00587
00588
00589 size += current_function_outgoing_args_size ? 4 : 0;
00590
00591 return (reload_completed
00592 && size == 0
00593 && !regs_ever_live[2]
00594 && !regs_ever_live[3]
00595 && !regs_ever_live[6]
00596 && !regs_ever_live[7]
00597 && !regs_ever_live[14]
00598 && !regs_ever_live[15]
00599 && !regs_ever_live[16]
00600 && !regs_ever_live[17]
00601 && fp_regs_to_save () == 0
00602 && !frame_pointer_needed);
00603 }
00604
00605
00606
00607
00608
00609 int
00610 mn10300_get_live_callee_saved_regs (void)
00611 {
00612 int mask;
00613 int i;
00614
00615 mask = 0;
00616 for (i = 0; i <= LAST_EXTENDED_REGNUM; i++)
00617 if (regs_ever_live[i] && ! call_used_regs[i])
00618 mask |= (1 << i);
00619 if ((mask & 0x3c000) != 0)
00620 mask |= 0x3c000;
00621
00622 return mask;
00623 }
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644 void
00645 mn10300_gen_multiple_store (int mask)
00646 {
00647 if (mask != 0)
00648 {
00649 int i;
00650 int count;
00651 rtx par;
00652 int pari;
00653
00654
00655 count = 0;
00656 for (i = 0; i <= LAST_EXTENDED_REGNUM; i++)
00657 if ((mask & (1 << i)) != 0)
00658 count += 1;
00659
00660
00661
00662 par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count + 1));
00663
00664
00665 XVECEXP (par, 0, 0)
00666 = gen_rtx_SET (SImode,
00667 stack_pointer_rtx,
00668 gen_rtx_PLUS (SImode,
00669 stack_pointer_rtx,
00670 GEN_INT (-count * 4)));
00671
00672
00673 pari = 1;
00674 for (i = LAST_EXTENDED_REGNUM; i >= 0; i--)
00675 if ((mask & (1 << i)) != 0)
00676 {
00677 rtx address = gen_rtx_PLUS (SImode,
00678 stack_pointer_rtx,
00679 GEN_INT (-pari * 4));
00680 XVECEXP(par, 0, pari)
00681 = gen_rtx_SET (VOIDmode,
00682 gen_rtx_MEM (SImode, address),
00683 gen_rtx_REG (SImode, i));
00684 pari += 1;
00685 }
00686
00687 par = emit_insn (par);
00688 RTX_FRAME_RELATED_P (par) = 1;
00689 }
00690 }
00691
00692 void
00693 expand_prologue (void)
00694 {
00695 HOST_WIDE_INT size;
00696
00697
00698 size = get_frame_size () + current_function_outgoing_args_size;
00699 size += (current_function_outgoing_args_size ? 4 : 0);
00700
00701
00702 mn10300_gen_multiple_store (mn10300_get_live_callee_saved_regs ());
00703
00704 if (TARGET_AM33_2 && fp_regs_to_save ())
00705 {
00706 int num_regs_to_save = fp_regs_to_save (), i;
00707 HOST_WIDE_INT xsize;
00708 enum { save_sp_merge,
00709 save_sp_no_merge,
00710 save_sp_partial_merge,
00711 save_a0_merge,
00712 save_a0_no_merge } strategy;
00713 unsigned int strategy_size = (unsigned)-1, this_strategy_size;
00714 rtx reg;
00715 rtx insn;
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730 #define SIZE_ADD_AX(S) ((((S) >= (1 << 15)) || ((S) < -(1 << 15))) ? 6 \
00731 : (((S) >= (1 << 7)) || ((S) < -(1 << 7))) ? 4 : 2)
00732 #define SIZE_ADD_SP(S) ((((S) >= (1 << 15)) || ((S) < -(1 << 15))) ? 6 \
00733 : (((S) >= (1 << 7)) || ((S) < -(1 << 7))) ? 4 : 3)
00734 #define SIZE_FMOV_LIMIT(S,N,L,SIZE1,SIZE2,ELSE) \
00735 (((S) >= (L)) ? (SIZE1) * (N) \
00736 : ((S) + 4 * (N) >= (L)) ? (((L) - (S)) / 4 * (SIZE2) \
00737 + ((S) + 4 * (N) - (L)) / 4 * (SIZE1)) \
00738 : (ELSE))
00739 #define SIZE_FMOV_SP_(S,N) \
00740 (SIZE_FMOV_LIMIT ((S), (N), (1 << 24), 7, 6, \
00741 SIZE_FMOV_LIMIT ((S), (N), (1 << 8), 6, 4, \
00742 (S) ? 4 * (N) : 3 + 4 * ((N) - 1))))
00743 #define SIZE_FMOV_SP(S,N) (SIZE_FMOV_SP_ ((unsigned HOST_WIDE_INT)(S), (N)))
00744
00745
00746
00747 if (! frame_pointer_needed && size)
00748 {
00749
00750 this_strategy_size = SIZE_ADD_SP (-(size + 4 * num_regs_to_save));
00751
00752 this_strategy_size += SIZE_FMOV_SP (size, num_regs_to_save);
00753
00754 if (this_strategy_size < strategy_size)
00755 {
00756 strategy = save_sp_merge;
00757 strategy_size = this_strategy_size;
00758 }
00759 }
00760
00761
00762
00763 this_strategy_size = SIZE_ADD_SP (-4 * num_regs_to_save);
00764
00765 this_strategy_size += SIZE_FMOV_SP (0, num_regs_to_save);
00766 if (size)
00767 {
00768
00769 this_strategy_size += SIZE_ADD_SP (-size);
00770 }
00771
00772 if (this_strategy_size < strategy_size)
00773 {
00774 strategy = save_sp_no_merge;
00775 strategy_size = this_strategy_size;
00776 }
00777
00778
00779
00780 if (! frame_pointer_needed && size + 4 * num_regs_to_save > 128)
00781 {
00782
00783 this_strategy_size = SIZE_ADD_SP (-128);
00784
00785 this_strategy_size += SIZE_FMOV_SP (128 - 4 * num_regs_to_save,
00786 num_regs_to_save);
00787 if (size)
00788 {
00789
00790 this_strategy_size += SIZE_ADD_SP (128 - size);
00791 }
00792
00793 if (this_strategy_size < strategy_size)
00794 {
00795 strategy = save_sp_partial_merge;
00796 strategy_size = this_strategy_size;
00797 }
00798 }
00799
00800
00801
00802
00803 if (! frame_pointer_needed && size
00804 && call_used_regs[FIRST_ADDRESS_REGNUM]
00805 && ! fixed_regs[FIRST_ADDRESS_REGNUM])
00806 {
00807
00808 this_strategy_size = SIZE_ADD_SP (-(size + 4 * num_regs_to_save));
00809
00810 this_strategy_size++;
00811 if (size)
00812 {
00813
00814 this_strategy_size += SIZE_ADD_AX (size);
00815 }
00816
00817 this_strategy_size += 3 * num_regs_to_save;
00818
00819 if (this_strategy_size < strategy_size)
00820 {
00821 strategy = save_a0_merge;
00822 strategy_size = this_strategy_size;
00823 }
00824 }
00825
00826
00827
00828 if (call_used_regs[FIRST_ADDRESS_REGNUM]
00829 && ! fixed_regs[FIRST_ADDRESS_REGNUM])
00830 {
00831
00832 this_strategy_size = SIZE_ADD_SP (-4 * num_regs_to_save);
00833
00834 this_strategy_size++;
00835
00836 this_strategy_size += 3 * num_regs_to_save;
00837 if (size)
00838 {
00839
00840 this_strategy_size += SIZE_ADD_SP (-size);
00841 }
00842
00843 if (this_strategy_size < strategy_size)
00844 {
00845 strategy = save_a0_no_merge;
00846 strategy_size = this_strategy_size;
00847 }
00848 }
00849
00850
00851 switch (strategy)
00852 {
00853 case save_sp_no_merge:
00854 case save_a0_no_merge:
00855 emit_insn (gen_addsi3 (stack_pointer_rtx,
00856 stack_pointer_rtx,
00857 GEN_INT (-4 * num_regs_to_save)));
00858 xsize = 0;
00859 break;
00860
00861 case save_sp_partial_merge:
00862 emit_insn (gen_addsi3 (stack_pointer_rtx,
00863 stack_pointer_rtx,
00864 GEN_INT (-128)));
00865 xsize = 128 - 4 * num_regs_to_save;
00866 size -= xsize;
00867 break;
00868
00869 case save_sp_merge:
00870 case save_a0_merge:
00871 emit_insn (gen_addsi3 (stack_pointer_rtx,
00872 stack_pointer_rtx,
00873 GEN_INT (-(size + 4 * num_regs_to_save))));
00874
00875
00876 xsize = size;
00877
00878
00879 size = 0;
00880 break;
00881
00882 default:
00883 gcc_unreachable ();
00884 }
00885
00886
00887 switch (strategy)
00888 {
00889 case save_sp_merge:
00890 case save_sp_no_merge:
00891 case save_sp_partial_merge:
00892 reg = 0;
00893 break;
00894
00895 case save_a0_merge:
00896 case save_a0_no_merge:
00897 reg = gen_rtx_REG (SImode, FIRST_ADDRESS_REGNUM);
00898 emit_insn (gen_movsi (reg, stack_pointer_rtx));
00899 if (xsize)
00900 emit_insn (gen_addsi3 (reg, reg, GEN_INT (xsize)));
00901 reg = gen_rtx_POST_INC (SImode, reg);
00902 break;
00903
00904 default:
00905 gcc_unreachable ();
00906 }
00907
00908
00909 for (i = FIRST_FP_REGNUM; i <= LAST_FP_REGNUM; ++i)
00910 if (regs_ever_live[i] && ! call_used_regs[i])
00911 {
00912 rtx addr;
00913
00914 if (reg)
00915 addr = reg;
00916 else
00917 {
00918
00919 if (xsize)
00920 {
00921 addr = gen_rtx_PLUS (SImode,
00922 stack_pointer_rtx,
00923 GEN_INT (xsize));
00924 }
00925 else
00926 addr = stack_pointer_rtx;
00927
00928 xsize += 4;
00929 }
00930
00931 insn = emit_insn (gen_movsi (gen_rtx_MEM (SImode, addr),
00932 gen_rtx_REG (SImode, i)));
00933
00934 RTX_FRAME_RELATED_P (insn) = 1;
00935 }
00936 }
00937
00938
00939 if (frame_pointer_needed)
00940 emit_move_insn (frame_pointer_rtx, stack_pointer_rtx);
00941
00942
00943 if (size)
00944 emit_insn (gen_addsi3 (stack_pointer_rtx,
00945 stack_pointer_rtx,
00946 GEN_INT (-size)));
00947 if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
00948 {
00949 rtx insn = get_last_insn ();
00950 rtx last = emit_insn (gen_GOTaddr2picreg ());
00951
00952
00953
00954
00955 do
00956 {
00957 insn = NEXT_INSN (insn);
00958
00959 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
00960 const0_rtx,
00961 REG_NOTES (insn));
00962 }
00963 while (insn != last);
00964 }
00965 }
00966
00967 void
00968 expand_epilogue (void)
00969 {
00970 HOST_WIDE_INT size;
00971
00972
00973 size = get_frame_size () + current_function_outgoing_args_size;
00974 size += (current_function_outgoing_args_size ? 4 : 0);
00975
00976 if (TARGET_AM33_2 && fp_regs_to_save ())
00977 {
00978 int num_regs_to_save = fp_regs_to_save (), i;
00979 rtx reg = 0;
00980
00981
00982
00983
00984
00985
00986
00987
00988 if (frame_pointer_needed)
00989 reg = gen_rtx_REG (SImode, FRAME_POINTER_REGNUM);
00990
00991
00992
00993 else
00994 {
00995 enum { restore_sp_post_adjust,
00996 restore_sp_pre_adjust,
00997 restore_sp_partial_adjust,
00998 restore_a1 } strategy;
00999 unsigned int this_strategy_size, strategy_size = (unsigned)-1;
01000
01001
01002
01003 this_strategy_size = SIZE_FMOV_SP (size, num_regs_to_save);
01004
01005
01006 if (size + 4 * num_regs_to_save + REG_SAVE_BYTES > 255)
01007 {
01008
01009 this_strategy_size += SIZE_ADD_SP (size + 4 * num_regs_to_save);
01010 }
01011
01012
01013 if (! REG_SAVE_BYTES)
01014 this_strategy_size--;
01015
01016 if (this_strategy_size < strategy_size)
01017 {
01018 strategy = restore_sp_post_adjust;
01019 strategy_size = this_strategy_size;
01020 }
01021
01022
01023
01024 this_strategy_size = SIZE_ADD_SP (size);
01025
01026 this_strategy_size += SIZE_FMOV_SP (0, num_regs_to_save);
01027
01028
01029
01030 if (this_strategy_size < strategy_size)
01031 {
01032 strategy = restore_sp_pre_adjust;
01033 strategy_size = this_strategy_size;
01034 }
01035
01036
01037
01038
01039
01040 if (size + 4 * num_regs_to_save + REG_SAVE_BYTES > 255)
01041 {
01042
01043
01044 this_strategy_size = SIZE_ADD_SP (size + 4 * num_regs_to_save
01045 + REG_SAVE_BYTES - 252);
01046
01047 this_strategy_size += SIZE_FMOV_SP (252 - REG_SAVE_BYTES
01048 - 4 * num_regs_to_save,
01049 num_regs_to_save);
01050
01051
01052
01053 if (this_strategy_size < strategy_size)
01054 {
01055 strategy = restore_sp_partial_adjust;
01056 strategy_size = this_strategy_size;
01057 }
01058 }
01059
01060
01061
01062 if (call_used_regs[FIRST_ADDRESS_REGNUM+1]
01063 && ! fixed_regs[FIRST_ADDRESS_REGNUM+1])
01064 {
01065
01066 this_strategy_size = 1;
01067 if (size)
01068 {
01069
01070 this_strategy_size += SIZE_ADD_AX (size);
01071 }
01072
01073 this_strategy_size += 3 * num_regs_to_save;
01074
01075
01076 if (size + 4 * num_regs_to_save + REG_SAVE_BYTES > 255)
01077 {
01078
01079 this_strategy_size += 2;
01080 }
01081
01082
01083 if (! REG_SAVE_BYTES)
01084 this_strategy_size--;
01085
01086 if (this_strategy_size < strategy_size)
01087 {
01088 strategy = restore_a1;
01089 strategy_size = this_strategy_size;
01090 }
01091 }
01092
01093 switch (strategy)
01094 {
01095 case restore_sp_post_adjust:
01096 break;
01097
01098 case restore_sp_pre_adjust:
01099 emit_insn (gen_addsi3 (stack_pointer_rtx,
01100 stack_pointer_rtx,
01101 GEN_INT (size)));
01102 size = 0;
01103 break;
01104
01105 case restore_sp_partial_adjust:
01106 emit_insn (gen_addsi3 (stack_pointer_rtx,
01107 stack_pointer_rtx,
01108 GEN_INT (size + 4 * num_regs_to_save
01109 + REG_SAVE_BYTES - 252)));
01110 size = 252 - REG_SAVE_BYTES - 4 * num_regs_to_save;
01111 break;
01112
01113 case restore_a1:
01114 reg = gen_rtx_REG (SImode, FIRST_ADDRESS_REGNUM + 1);
01115 emit_insn (gen_movsi (reg, stack_pointer_rtx));
01116 if (size)
01117 emit_insn (gen_addsi3 (reg, reg, GEN_INT (size)));
01118 break;
01119
01120 default:
01121 gcc_unreachable ();
01122 }
01123 }
01124
01125
01126 if (reg)
01127 reg = gen_rtx_POST_INC (SImode, reg);
01128
01129 for (i = FIRST_FP_REGNUM; i <= LAST_FP_REGNUM; ++i)
01130 if (regs_ever_live[i] && ! call_used_regs[i])
01131 {
01132 rtx addr;
01133
01134 if (reg)
01135 addr = reg;
01136 else if (size)
01137 {
01138
01139
01140 addr = gen_rtx_PLUS (SImode,
01141 stack_pointer_rtx,
01142 GEN_INT (size));
01143 }
01144 else
01145 addr = stack_pointer_rtx;
01146
01147 size += 4;
01148
01149 emit_insn (gen_movsi (gen_rtx_REG (SImode, i),
01150 gen_rtx_MEM (SImode, addr)));
01151 }
01152
01153
01154
01155
01156 if (! frame_pointer_needed && reg && size + REG_SAVE_BYTES > 255)
01157 {
01158 emit_move_insn (stack_pointer_rtx, XEXP (reg, 0));
01159 size = 0;
01160 }
01161 }
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178 if (frame_pointer_needed)
01179 {
01180 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
01181 size = 0;
01182 }
01183 else if (size + REG_SAVE_BYTES > 255)
01184 {
01185 emit_insn (gen_addsi3 (stack_pointer_rtx,
01186 stack_pointer_rtx,
01187 GEN_INT (size)));
01188 size = 0;
01189 }
01190
01191
01192 if (size || regs_ever_live[2] || regs_ever_live[3]
01193 || regs_ever_live[6] || regs_ever_live[7]
01194 || regs_ever_live[14] || regs_ever_live[15]
01195 || regs_ever_live[16] || regs_ever_live[17]
01196 || frame_pointer_needed)
01197 emit_jump_insn (gen_return_internal_regs
01198 (GEN_INT (size + REG_SAVE_BYTES)));
01199 else
01200 emit_jump_insn (gen_return_internal ());
01201 }
01202
01203
01204
01205 void
01206 notice_update_cc (rtx body, rtx insn)
01207 {
01208 switch (get_attr_cc (insn))
01209 {
01210 case CC_NONE:
01211
01212 break;
01213
01214 case CC_NONE_0HIT:
01215
01216 if (cc_status.value1 != 0
01217 && reg_overlap_mentioned_p (recog_data.operand[0], cc_status.value1))
01218 cc_status.value1 = 0;
01219 break;
01220
01221 case CC_SET_ZN:
01222
01223
01224 CC_STATUS_INIT;
01225 cc_status.flags |= CC_NO_CARRY | CC_OVERFLOW_UNUSABLE;
01226 cc_status.value1 = recog_data.operand[0];
01227 break;
01228
01229 case CC_SET_ZNV:
01230
01231
01232 CC_STATUS_INIT;
01233 cc_status.flags |= CC_NO_CARRY;
01234 cc_status.value1 = recog_data.operand[0];
01235 break;
01236
01237 case CC_COMPARE:
01238
01239 CC_STATUS_INIT;
01240 cc_status.value1 = SET_SRC (body);
01241 if (GET_CODE (cc_status.value1) == COMPARE
01242 && GET_MODE (XEXP (cc_status.value1, 0)) == SFmode)
01243 cc_status.mdep.fpCC = 1;
01244 break;
01245
01246 case CC_CLOBBER:
01247
01248 CC_STATUS_INIT;
01249 break;
01250
01251 default:
01252 gcc_unreachable ();
01253 }
01254 }
01255
01256
01257
01258
01259
01260
01261 int
01262 store_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01263 {
01264 int count;
01265 int mask;
01266 int i;
01267 unsigned int last;
01268 rtx elt;
01269
01270 count = XVECLEN (op, 0);
01271 if (count < 2)
01272 return 0;
01273
01274
01275 elt = XVECEXP (op, 0, 0);
01276 if (GET_CODE (elt) != SET
01277 || GET_CODE (SET_DEST (elt)) != REG
01278 || REGNO (SET_DEST (elt)) != STACK_POINTER_REGNUM
01279 || GET_CODE (SET_SRC (elt)) != PLUS)
01280 return 0;
01281
01282
01283
01284
01285
01286 elt = SET_SRC (elt);
01287 if (GET_CODE (XEXP (elt, 0)) != REG
01288 || REGNO (XEXP (elt, 0)) != STACK_POINTER_REGNUM
01289 || GET_CODE (XEXP (elt, 1)) != CONST_INT
01290 || INTVAL (XEXP (elt, 1)) != -(count - 1) * 4)
01291 return 0;
01292
01293
01294
01295
01296
01297
01298
01299
01300 last = LAST_EXTENDED_REGNUM + 1;
01301 mask = 0;
01302 for (i = 1; i < count; i++)
01303 {
01304
01305 elt = XVECEXP (op, 0, i);
01306 if (GET_CODE (elt) != SET
01307 || GET_CODE (SET_DEST (elt)) != MEM
01308 || GET_CODE (SET_SRC (elt)) != REG
01309 || REGNO (SET_SRC (elt)) >= last)
01310 return 0;
01311
01312
01313
01314 last = REGNO (SET_SRC (elt));
01315 mask |= (1 << last);
01316
01317
01318 elt = XEXP (SET_DEST (elt), 0);
01319 if (GET_CODE (elt) != PLUS
01320 || GET_CODE (XEXP (elt, 0)) != REG
01321 || REGNO (XEXP (elt, 0)) != STACK_POINTER_REGNUM
01322 || GET_CODE (XEXP (elt, 1)) != CONST_INT
01323 || INTVAL (XEXP (elt, 1)) != -i * 4)
01324 return 0;
01325 }
01326
01327
01328 if ((mask & 0x3c000) != 0
01329 && (mask & 0x3c000) != 0x3c000)
01330 return 0;
01331
01332 return mask;
01333 }
01334
01335
01336
01337
01338
01339 enum reg_class
01340 mn10300_secondary_reload_class (enum reg_class class, enum machine_mode mode,
01341 rtx in)
01342 {
01343
01344
01345
01346 if ((GET_CODE (in) == MEM
01347 || (GET_CODE (in) == REG
01348 && REGNO (in) >= FIRST_PSEUDO_REGISTER)
01349 || (GET_CODE (in) == SUBREG
01350 && GET_CODE (SUBREG_REG (in)) == REG
01351 && REGNO (SUBREG_REG (in)) >= FIRST_PSEUDO_REGISTER))
01352 && (mode == QImode || mode == HImode)
01353 && (class == ADDRESS_REGS || class == SP_REGS
01354 || class == SP_OR_ADDRESS_REGS))
01355 {
01356 if (TARGET_AM33)
01357 return DATA_OR_EXTENDED_REGS;
01358 return DATA_REGS;
01359 }
01360
01361
01362
01363 if (class != SP_REGS
01364 && class != ADDRESS_REGS
01365 && class != SP_OR_ADDRESS_REGS
01366 && class != SP_OR_EXTENDED_REGS
01367 && class != ADDRESS_OR_EXTENDED_REGS
01368 && class != SP_OR_ADDRESS_OR_EXTENDED_REGS
01369 && (in == stack_pointer_rtx
01370 || (GET_CODE (in) == PLUS
01371 && (XEXP (in, 0) == stack_pointer_rtx
01372 || XEXP (in, 1) == stack_pointer_rtx))))
01373 return ADDRESS_REGS;
01374
01375 if (GET_CODE (in) == PLUS
01376 && (XEXP (in, 0) == stack_pointer_rtx
01377 || XEXP (in, 1) == stack_pointer_rtx))
01378 {
01379 if (TARGET_AM33)
01380 return DATA_OR_EXTENDED_REGS;
01381 return DATA_REGS;
01382 }
01383
01384 if (TARGET_AM33_2 && class == FP_REGS
01385 && GET_CODE (in) == MEM && ! OK_FOR_Q (in))
01386 {
01387 if (TARGET_AM33)
01388 return DATA_OR_EXTENDED_REGS;
01389 return DATA_REGS;
01390 }
01391
01392
01393 return NO_REGS;
01394 }
01395
01396 int
01397 initial_offset (int from, int to)
01398 {
01399
01400
01401 if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
01402 {
01403 if (regs_ever_live[2] || regs_ever_live[3]
01404 || regs_ever_live[6] || regs_ever_live[7]
01405 || regs_ever_live[14] || regs_ever_live[15]
01406 || regs_ever_live[16] || regs_ever_live[17]
01407 || fp_regs_to_save ()
01408 || frame_pointer_needed)
01409 return REG_SAVE_BYTES
01410 + 4 * fp_regs_to_save ();
01411 else
01412 return 0;
01413 }
01414
01415
01416
01417
01418 if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
01419 {
01420 if (regs_ever_live[2] || regs_ever_live[3]
01421 || regs_ever_live[6] || regs_ever_live[7]
01422 || regs_ever_live[14] || regs_ever_live[15]
01423 || regs_ever_live[16] || regs_ever_live[17]
01424 || fp_regs_to_save ()
01425 || frame_pointer_needed)
01426 return (get_frame_size () + REG_SAVE_BYTES
01427 + 4 * fp_regs_to_save ()
01428 + (current_function_outgoing_args_size
01429 ? current_function_outgoing_args_size + 4 : 0));
01430 else
01431 return (get_frame_size ()
01432 + (current_function_outgoing_args_size
01433 ? current_function_outgoing_args_size + 4 : 0));
01434 }
01435
01436
01437
01438
01439 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
01440 return (get_frame_size ()
01441 + (current_function_outgoing_args_size
01442 ? current_function_outgoing_args_size + 4 : 0));
01443
01444 gcc_unreachable ();
01445 }
01446
01447
01448
01449 static bool
01450 mn10300_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
01451 {
01452
01453 return (int_size_in_bytes (type) > 8
01454 || int_size_in_bytes (type) == 0
01455 || TYPE_MODE (type) == BLKmode);
01456 }
01457
01458
01459
01460 static rtx
01461 mn10300_builtin_saveregs (void)
01462 {
01463 rtx offset, mem;
01464 tree fntype = TREE_TYPE (current_function_decl);
01465 int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
01466 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
01467 != void_type_node)))
01468 ? UNITS_PER_WORD : 0);
01469 int set = get_varargs_alias_set ();
01470
01471 if (argadj)
01472 offset = plus_constant (current_function_arg_offset_rtx, argadj);
01473 else
01474 offset = current_function_arg_offset_rtx;
01475
01476 mem = gen_rtx_MEM (SImode, current_function_internal_arg_pointer);
01477 set_mem_alias_set (mem, set);
01478 emit_move_insn (mem, gen_rtx_REG (SImode, 0));
01479
01480 mem = gen_rtx_MEM (SImode,
01481 plus_constant (current_function_internal_arg_pointer, 4));
01482 set_mem_alias_set (mem, set);
01483 emit_move_insn (mem, gen_rtx_REG (SImode, 1));
01484
01485 return copy_to_reg (expand_binop (Pmode, add_optab,
01486 current_function_internal_arg_pointer,
01487 offset, 0, 0, OPTAB_LIB_WIDEN));
01488 }
01489
01490 void
01491 mn10300_va_start (tree valist, rtx nextarg)
01492 {
01493 nextarg = expand_builtin_saveregs ();
01494 std_expand_builtin_va_start (valist, nextarg);
01495 }
01496
01497
01498
01499 static bool
01500 mn10300_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
01501 enum machine_mode mode, tree type,
01502 bool named ATTRIBUTE_UNUSED)
01503 {
01504 unsigned HOST_WIDE_INT size;
01505
01506 if (type)
01507 size = int_size_in_bytes (type);
01508 else
01509 size = GET_MODE_SIZE (mode);
01510
01511 return (size > 8 || size == 0);
01512 }
01513
01514
01515
01516
01517 rtx
01518 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
01519 tree type, int named ATTRIBUTE_UNUSED)
01520 {
01521 rtx result = 0;
01522 int size, align;
01523
01524
01525 int nregs = 2;
01526
01527
01528 if (mode == BLKmode)
01529 size = int_size_in_bytes (type);
01530 else
01531 size = GET_MODE_SIZE (mode);
01532
01533
01534 align = size;
01535
01536 cum->nbytes = (cum->nbytes + 3) & ~3;
01537
01538
01539
01540 if (cum->nbytes > nregs * UNITS_PER_WORD)
01541 return 0;
01542
01543
01544
01545 if (type == NULL_TREE
01546 && cum->nbytes + size > nregs * UNITS_PER_WORD)
01547 return 0;
01548
01549 switch (cum->nbytes / UNITS_PER_WORD)
01550 {
01551 case 0:
01552 result = gen_rtx_REG (mode, 0);
01553 break;
01554 case 1:
01555 result = gen_rtx_REG (mode, 1);
01556 break;
01557 default:
01558 result = 0;
01559 }
01560
01561 return result;
01562 }
01563
01564
01565
01566
01567 static int
01568 mn10300_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
01569 tree type, bool named ATTRIBUTE_UNUSED)
01570 {
01571 int size, align;
01572
01573
01574 int nregs = 2;
01575
01576
01577 if (mode == BLKmode)
01578 size = int_size_in_bytes (type);
01579 else
01580 size = GET_MODE_SIZE (mode);
01581
01582
01583 align = size;
01584
01585 cum->nbytes = (cum->nbytes + 3) & ~3;
01586
01587
01588
01589 if (cum->nbytes > nregs * UNITS_PER_WORD)
01590 return 0;
01591
01592 if (cum->nbytes + size <= nregs * UNITS_PER_WORD)
01593 return 0;
01594
01595
01596
01597 if (type == NULL_TREE
01598 && cum->nbytes + size > nregs * UNITS_PER_WORD)
01599 return 0;
01600
01601 return nregs * UNITS_PER_WORD - cum->nbytes;
01602 }
01603
01604
01605
01606
01607
01608
01609
01610 rtx
01611 mn10300_function_value (tree valtype, tree func, int outgoing)
01612 {
01613 rtx rv;
01614 enum machine_mode mode = TYPE_MODE (valtype);
01615
01616 if (! POINTER_TYPE_P (valtype))
01617 return gen_rtx_REG (mode, FIRST_DATA_REGNUM);
01618 else if (! TARGET_PTR_A0D0 || ! outgoing
01619 || current_function_returns_struct)
01620 return gen_rtx_REG (mode, FIRST_ADDRESS_REGNUM);
01621
01622 rv = gen_rtx_PARALLEL (mode, rtvec_alloc (2));
01623 XVECEXP (rv, 0, 0)
01624 = gen_rtx_EXPR_LIST (VOIDmode,
01625 gen_rtx_REG (mode, FIRST_ADDRESS_REGNUM),
01626 GEN_INT (0));
01627
01628 XVECEXP (rv, 0, 1)
01629 = gen_rtx_EXPR_LIST (VOIDmode,
01630 gen_rtx_REG (mode, FIRST_DATA_REGNUM),
01631 GEN_INT (0));
01632 return rv;
01633 }
01634
01635
01636 const char *
01637 output_tst (rtx operand, rtx insn)
01638 {
01639 rtx temp;
01640 int past_call = 0;
01641
01642
01643
01644 temp = PREV_INSN (insn);
01645 while (optimize && temp)
01646 {
01647 rtx set;
01648
01649
01650
01651
01652 if (GET_CODE (temp) == CODE_LABEL
01653 || GET_CODE (temp) == JUMP_INSN
01654 || GET_CODE (temp) == BARRIER)
01655 break;
01656
01657 if (GET_CODE (temp) == CALL_INSN)
01658 past_call = 1;
01659
01660 if (GET_CODE (temp) == NOTE)
01661 {
01662 temp = PREV_INSN (temp);
01663 continue;
01664 }
01665
01666
01667 set = single_set (temp);
01668 if (!set)
01669 {
01670 temp = PREV_INSN (temp);
01671 continue;
01672 }
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684 if (REG_P (SET_DEST (set))
01685 && SET_SRC (set) == CONST0_RTX (GET_MODE (SET_DEST (set)))
01686 && !reg_set_between_p (SET_DEST (set), temp, insn)
01687 && (REGNO_REG_CLASS (REGNO (SET_DEST (set)))
01688 == REGNO_REG_CLASS (REGNO (operand)))
01689 && REGNO_REG_CLASS (REGNO (SET_DEST (set))) != EXTENDED_REGS
01690 && REGNO (SET_DEST (set)) != REGNO (operand)
01691 && (!past_call
01692 || !call_used_regs[REGNO (SET_DEST (set))]))
01693 {
01694 rtx xoperands[2];
01695 xoperands[0] = operand;
01696 xoperands[1] = SET_DEST (set);
01697
01698 output_asm_insn ("cmp %1,%0", xoperands);
01699 return "";
01700 }
01701
01702 if (REGNO_REG_CLASS (REGNO (operand)) == EXTENDED_REGS
01703 && REG_P (SET_DEST (set))
01704 && SET_SRC (set) == CONST0_RTX (GET_MODE (SET_DEST (set)))
01705 && !reg_set_between_p (SET_DEST (set), temp, insn)
01706 && (REGNO_REG_CLASS (REGNO (SET_DEST (set)))
01707 != REGNO_REG_CLASS (REGNO (operand)))
01708 && REGNO_REG_CLASS (REGNO (SET_DEST (set))) == EXTENDED_REGS
01709 && REGNO (SET_DEST (set)) != REGNO (operand)
01710 && (!past_call
01711 || !call_used_regs[REGNO (SET_DEST (set))]))
01712 {
01713 rtx xoperands[2];
01714 xoperands[0] = operand;
01715 xoperands[1] = SET_DEST (set);
01716
01717 output_asm_insn ("cmp %1,%0", xoperands);
01718 return "";
01719 }
01720 temp = PREV_INSN (temp);
01721 }
01722 return "cmp 0,%0";
01723 }
01724
01725 int
01726 impossible_plus_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01727 {
01728 if (GET_CODE (op) != PLUS)
01729 return 0;
01730
01731 if (XEXP (op, 0) == stack_pointer_rtx
01732 || XEXP (op, 1) == stack_pointer_rtx)
01733 return 1;
01734
01735 return 0;
01736 }
01737
01738
01739
01740 int
01741 mask_ok_for_mem_btst (int len, int bit)
01742 {
01743 unsigned int mask = 0;
01744
01745 while (len > 0)
01746 {
01747 mask |= (1 << bit);
01748 bit++;
01749 len--;
01750 }
01751
01752
01753 return (((mask & 0xff) == mask)
01754 || ((mask & 0xff00) == mask)
01755 || ((mask & 0xff0000) == mask)
01756 || ((mask & 0xff000000) == mask));
01757 }
01758
01759
01760
01761
01762 int
01763 symbolic_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01764 {
01765 switch (GET_CODE (op))
01766 {
01767 case SYMBOL_REF:
01768 case LABEL_REF:
01769 return 1;
01770 case CONST:
01771 op = XEXP (op, 0);
01772 return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
01773 || GET_CODE (XEXP (op, 0)) == LABEL_REF)
01774 && GET_CODE (XEXP (op, 1)) == CONST_INT);
01775 default:
01776 return 0;
01777 }
01778 }
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791
01792
01793
01794
01795 rtx
01796 legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
01797 enum machine_mode mode ATTRIBUTE_UNUSED)
01798 {
01799 if (flag_pic && ! legitimate_pic_operand_p (x))
01800 x = legitimize_pic_address (oldx, NULL_RTX);
01801
01802
01803
01804
01805 if (GET_CODE (x) == PLUS
01806 && symbolic_operand (XEXP (x, 1), VOIDmode))
01807 {
01808
01809
01810
01811
01812 rtx regx1, regy1, regy2, y;
01813
01814
01815 y = XEXP (x, 1);
01816 if (GET_CODE (y) == CONST)
01817 y = XEXP (y, 0);
01818
01819 if (GET_CODE (y) == PLUS || GET_CODE (y) == MINUS)
01820 {
01821 regx1 = force_reg (Pmode, force_operand (XEXP (x, 0), 0));
01822 regy1 = force_reg (Pmode, force_operand (XEXP (y, 0), 0));
01823 regy2 = force_reg (Pmode, force_operand (XEXP (y, 1), 0));
01824 regx1 = force_reg (Pmode,
01825 gen_rtx_fmt_ee (GET_CODE (y), Pmode, regx1, regy2));
01826 return force_reg (Pmode, gen_rtx_PLUS (Pmode, regx1, regy1));
01827 }
01828 }
01829 return x;
01830 }
01831
01832
01833
01834 rtx
01835 legitimize_pic_address (rtx orig, rtx reg)
01836 {
01837 if (GET_CODE (orig) == LABEL_REF
01838 || (GET_CODE (orig) == SYMBOL_REF
01839 && (CONSTANT_POOL_ADDRESS_P (orig)
01840 || ! MN10300_GLOBAL_P (orig))))
01841 {
01842 if (reg == 0)
01843 reg = gen_reg_rtx (Pmode);
01844
01845 emit_insn (gen_symGOTOFF2reg (reg, orig));
01846 return reg;
01847 }
01848 else if (GET_CODE (orig) == SYMBOL_REF)
01849 {
01850 if (reg == 0)
01851 reg = gen_reg_rtx (Pmode);
01852
01853 emit_insn (gen_symGOT2reg (reg, orig));
01854 return reg;
01855 }
01856 return orig;
01857 }
01858
01859
01860
01861 int
01862 legitimate_pic_operand_p (rtx x)
01863 {
01864 register const char *fmt;
01865 register int i;
01866
01867 if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
01868 return 0;
01869
01870 if (GET_CODE (x) == UNSPEC
01871 && (XINT (x, 1) == UNSPEC_PIC
01872 || XINT (x, 1) == UNSPEC_GOT
01873 || XINT (x, 1) == UNSPEC_GOTOFF
01874 || XINT (x, 1) == UNSPEC_PLT))
01875 return 1;
01876
01877 fmt = GET_RTX_FORMAT (GET_CODE (x));
01878 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
01879 {
01880 if (fmt[i] == 'E')
01881 {
01882 register int j;
01883
01884 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
01885 if (! legitimate_pic_operand_p (XVECEXP (x, i, j)))
01886 return 0;
01887 }
01888 else if (fmt[i] == 'e' && ! legitimate_pic_operand_p (XEXP (x, i)))
01889 return 0;
01890 }
01891
01892 return 1;
01893 }
01894
01895
01896
01897 bool
01898 legitimate_address_p (enum machine_mode mode, rtx x, int strict)
01899 {
01900 if (CONSTANT_ADDRESS_P (x)
01901 && (! flag_pic || legitimate_pic_operand_p (x)))
01902 return TRUE;
01903
01904 if (RTX_OK_FOR_BASE_P (x, strict))
01905 return TRUE;
01906
01907 if (TARGET_AM33
01908 && GET_CODE (x) == POST_INC
01909 && RTX_OK_FOR_BASE_P (XEXP (x, 0), strict)
01910 && (mode == SImode || mode == SFmode || mode == HImode))
01911 return TRUE;
01912
01913 if (GET_CODE (x) == PLUS)
01914 {
01915 rtx base = 0, index = 0;
01916
01917 if (REG_P (XEXP (x, 0))
01918 && REGNO_STRICT_OK_FOR_BASE_P (REGNO (XEXP (x, 0)), strict))
01919 {
01920 base = XEXP (x, 0);
01921 index = XEXP (x, 1);
01922 }
01923
01924 if (REG_P (XEXP (x, 1))
01925 && REGNO_STRICT_OK_FOR_BASE_P (REGNO (XEXP (x, 1)), strict))
01926 {
01927 base = XEXP (x, 1);
01928 index = XEXP (x, 0);
01929 }
01930
01931 if (base != 0 && index != 0)
01932 {
01933 if (GET_CODE (index) == CONST_INT)
01934 return TRUE;
01935 if (GET_CODE (index) == CONST
01936 && GET_CODE (XEXP (index, 0)) != PLUS
01937 && (! flag_pic
01938 || legitimate_pic_operand_p (index)))
01939 return TRUE;
01940 }
01941 }
01942
01943 return FALSE;
01944 }
01945
01946 static int
01947 mn10300_address_cost_1 (rtx x, int *unsig)
01948 {
01949 switch (GET_CODE (x))
01950 {
01951 case REG:
01952 switch (REGNO_REG_CLASS (REGNO (x)))
01953 {
01954 case SP_REGS:
01955 *unsig = 1;
01956 return 0;
01957
01958 case ADDRESS_REGS:
01959 return 1;
01960
01961 case DATA_REGS:
01962 case EXTENDED_REGS:
01963 case FP_REGS:
01964 return 3;
01965
01966 case NO_REGS:
01967 return 5;
01968
01969 default:
01970 gcc_unreachable ();
01971 }
01972
01973 case PLUS:
01974 case MINUS:
01975 case ASHIFT:
01976 case AND:
01977 case IOR:
01978 return (mn10300_address_cost_1 (XEXP (x, 0), unsig)
01979 + mn10300_address_cost_1 (XEXP (x, 1), unsig));
01980
01981 case EXPR_LIST:
01982 case SUBREG:
01983 case MEM:
01984 return mn10300_address_cost (XEXP (x, 0));
01985
01986 case ZERO_EXTEND:
01987 *unsig = 1;
01988 return mn10300_address_cost_1 (XEXP (x, 0), unsig);
01989
01990 case CONST_INT:
01991 if (INTVAL (x) == 0)
01992 return 0;
01993 if (INTVAL (x) + (*unsig ? 0 : 0x80) < 0x100)
01994 return 1;
01995 if (INTVAL (x) + (*unsig ? 0 : 0x8000) < 0x10000)
01996 return 3;
01997 if (INTVAL (x) + (*unsig ? 0 : 0x800000) < 0x1000000)
01998 return 5;
01999 return 7;
02000
02001 case CONST:
02002 case SYMBOL_REF:
02003 case LABEL_REF:
02004 return 8;
02005
02006 default:
02007 gcc_unreachable ();
02008
02009 }
02010 }
02011
02012 static int
02013 mn10300_address_cost (rtx x)
02014 {
02015 int s = 0;
02016 return mn10300_address_cost_1 (x, &s);
02017 }
02018
02019 static bool
02020 mn10300_rtx_costs (rtx x, int code, int outer_code, int *total)
02021 {
02022 switch (code)
02023 {
02024 case CONST_INT:
02025
02026 if (INTVAL (x) == 0 && outer_code == SET)
02027 *total = 0;
02028
02029 else if (INT_8_BITS (INTVAL (x)))
02030 *total = 1;
02031
02032
02033 else if (INT_16_BITS (INTVAL (x))
02034 || (INTVAL (x) & 0xffff) == 0
02035 || (INTVAL (x) & 0xffff0000) == 0)
02036 *total = 2;
02037 else
02038 *total = 4;
02039 return true;
02040
02041 case CONST:
02042 case LABEL_REF:
02043 case SYMBOL_REF:
02044
02045
02046 *total = 6;
02047 return true;
02048
02049 case CONST_DOUBLE:
02050
02051
02052 *total = 8;
02053 return true;
02054
02055
02056 case MOD:
02057 case DIV:
02058 case MULT:
02059 *total = 8;
02060 return true;
02061
02062 default:
02063 return false;
02064 }
02065 }
02066
02067
02068
02069
02070
02071 bool
02072 mn10300_wide_const_load_uses_clr (rtx operands[2])
02073 {
02074 long val[2];
02075
02076 if (GET_CODE (operands[0]) != REG
02077 || REGNO_REG_CLASS (REGNO (operands[0])) != DATA_REGS)
02078 return false;
02079
02080 switch (GET_CODE (operands[1]))
02081 {
02082 case CONST_INT:
02083 {
02084 rtx low, high;
02085 split_double (operands[1], &low, &high);
02086 val[0] = INTVAL (low);
02087 val[1] = INTVAL (high);
02088 }
02089 break;
02090
02091 case CONST_DOUBLE:
02092 if (GET_MODE (operands[1]) == DFmode)
02093 {
02094 REAL_VALUE_TYPE rv;
02095
02096 REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
02097 REAL_VALUE_TO_TARGET_DOUBLE (rv, val);
02098 }
02099 else if (GET_MODE (operands[1]) == VOIDmode
02100 || GET_MODE (operands[1]) == DImode)
02101 {
02102 val[0] = CONST_DOUBLE_LOW (operands[1]);
02103 val[1] = CONST_DOUBLE_HIGH (operands[1]);
02104 }
02105 break;
02106
02107 default:
02108 return false;
02109 }
02110
02111 return val[0] == 0 || val[1] == 0;
02112 }
02113
02114
02115
02116 static void
02117 mn10300_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
02118 {
02119 rtx symbol;
02120
02121 if (GET_CODE (rtl) != MEM)
02122 return;
02123 symbol = XEXP (rtl, 0);
02124 if (GET_CODE (symbol) != SYMBOL_REF)
02125 return;
02126
02127 if (flag_pic)
02128 SYMBOL_REF_FLAG (symbol) = (*targetm.binds_local_p) (decl);
02129 }