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