00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "config.h"
00027 #include "system.h"
00028 #include "coretypes.h"
00029 #include "tm.h"
00030 #include "rtl.h"
00031 #include "tree.h"
00032 #include "regs.h"
00033 #include "hard-reg-set.h"
00034 #include "basic-block.h"
00035 #include "real.h"
00036 #include "insn-config.h"
00037 #include "insn-attr.h"
00038 #include "conditions.h"
00039 #include "output.h"
00040 #include "function.h"
00041 #include "expr.h"
00042 #include "optabs.h"
00043 #include "libfuncs.h"
00044 #include "flags.h"
00045 #include "recog.h"
00046 #include "ggc.h"
00047 #include "cpplib.h"
00048 #include "toplev.h"
00049 #include "tm_p.h"
00050 #include "target.h"
00051 #include "target-def.h"
00052 #include "langhooks.h"
00053
00054 rtx smulhi3_libfunc;
00055 rtx umulhi3_libfunc;
00056 rtx fix_truncqfhi2_libfunc;
00057 rtx fixuns_truncqfhi2_libfunc;
00058 rtx fix_trunchfhi2_libfunc;
00059 rtx fixuns_trunchfhi2_libfunc;
00060 rtx floathiqf2_libfunc;
00061 rtx floatunshiqf2_libfunc;
00062 rtx floathihf2_libfunc;
00063 rtx floatunshihf2_libfunc;
00064
00065 static int c4x_leaf_function;
00066
00067 static const char *const float_reg_names[] = FLOAT_REGISTER_NAMES;
00068
00069
00070
00071
00072
00073
00074 enum reg_class c4x_regclass_map[FIRST_PSEUDO_REGISTER] =
00075 {
00076
00077 R0R1_REGS,
00078 R0R1_REGS,
00079 R2R3_REGS,
00080 R2R3_REGS,
00081 EXT_LOW_REGS,
00082 EXT_LOW_REGS,
00083 EXT_LOW_REGS,
00084 EXT_LOW_REGS,
00085 ADDR_REGS,
00086 ADDR_REGS,
00087 ADDR_REGS,
00088 ADDR_REGS,
00089 ADDR_REGS,
00090 ADDR_REGS,
00091 ADDR_REGS,
00092 ADDR_REGS,
00093 DP_REG,
00094 INDEX_REGS,
00095 INDEX_REGS,
00096 BK_REG,
00097 SP_REG,
00098 ST_REG,
00099 NO_REGS,
00100 NO_REGS,
00101 NO_REGS,
00102 INT_REGS,
00103 INT_REGS,
00104 RC_REG,
00105 EXT_REGS,
00106 EXT_REGS,
00107 EXT_REGS,
00108 EXT_REGS,
00109 };
00110
00111 enum machine_mode c4x_caller_save_map[FIRST_PSEUDO_REGISTER] =
00112 {
00113
00114 HFmode,
00115 HFmode,
00116 HFmode,
00117 HFmode,
00118 QFmode,
00119 QFmode,
00120 QImode,
00121 QImode,
00122 QImode,
00123 QImode,
00124 QImode,
00125 QImode,
00126 QImode,
00127 QImode,
00128 QImode,
00129 QImode,
00130 VOIDmode,
00131 QImode,
00132 QImode,
00133 QImode,
00134 VOIDmode,
00135 VOIDmode,
00136 VOIDmode,
00137 VOIDmode,
00138 VOIDmode,
00139 QImode,
00140 QImode,
00141 VOIDmode,
00142 QFmode,
00143 HFmode,
00144 HFmode,
00145 HFmode,
00146 };
00147
00148
00149
00150
00151
00152 rtx c4x_compare_op0;
00153 rtx c4x_compare_op1;
00154
00155 const char *c4x_rpts_cycles_string;
00156 int c4x_rpts_cycles = 0;
00157 const char *c4x_cpu_version_string;
00158 int c4x_cpu_version = 40;
00159
00160
00161
00162 tree code_tree = NULL_TREE;
00163 tree data_tree = NULL_TREE;
00164 tree pure_tree = NULL_TREE;
00165 tree noreturn_tree = NULL_TREE;
00166 tree interrupt_tree = NULL_TREE;
00167 tree naked_tree = NULL_TREE;
00168
00169
00170 static int c4x_isr_reg_used_p (unsigned int);
00171 static int c4x_leaf_function_p (void);
00172 static int c4x_naked_function_p (void);
00173 static int c4x_immed_float_p (rtx);
00174 static int c4x_a_register (rtx);
00175 static int c4x_x_register (rtx);
00176 static int c4x_immed_int_constant (rtx);
00177 static int c4x_immed_float_constant (rtx);
00178 static int c4x_K_constant (rtx);
00179 static int c4x_N_constant (rtx);
00180 static int c4x_O_constant (rtx);
00181 static int c4x_R_indirect (rtx);
00182 static int c4x_S_indirect (rtx);
00183 static void c4x_S_address_parse (rtx , int *, int *, int *, int *);
00184 static int c4x_valid_operands (enum rtx_code, rtx *, enum machine_mode, int);
00185 static int c4x_arn_reg_operand (rtx, enum machine_mode, unsigned int);
00186 static int c4x_arn_mem_operand (rtx, enum machine_mode, unsigned int);
00187 static void c4x_file_start (void);
00188 static void c4x_file_end (void);
00189 static void c4x_check_attribute (const char *, tree, tree, tree *);
00190 static int c4x_r11_set_p (rtx);
00191 static int c4x_rptb_valid_p (rtx, rtx);
00192 static void c4x_reorg (void);
00193 static int c4x_label_ref_used_p (rtx, rtx);
00194 static tree c4x_handle_fntype_attribute (tree *, tree, tree, int, bool *);
00195 const struct attribute_spec c4x_attribute_table[];
00196 static void c4x_insert_attributes (tree, tree *);
00197 static void c4x_asm_named_section (const char *, unsigned int, tree);
00198 static int c4x_adjust_cost (rtx, rtx, rtx, int);
00199 static void c4x_globalize_label (FILE *, const char *);
00200 static bool c4x_rtx_costs (rtx, int, int, int *);
00201 static int c4x_address_cost (rtx);
00202 static void c4x_init_libfuncs (void);
00203 static void c4x_external_libcall (rtx);
00204 static rtx c4x_struct_value_rtx (tree, int);
00205 static tree c4x_gimplify_va_arg_expr (tree, tree, tree *, tree *);
00206
00207
00208 #undef TARGET_ASM_BYTE_OP
00209 #define TARGET_ASM_BYTE_OP "\t.word\t"
00210 #undef TARGET_ASM_ALIGNED_HI_OP
00211 #define TARGET_ASM_ALIGNED_HI_OP NULL
00212 #undef TARGET_ASM_ALIGNED_SI_OP
00213 #define TARGET_ASM_ALIGNED_SI_OP NULL
00214 #undef TARGET_ASM_FILE_START
00215 #define TARGET_ASM_FILE_START c4x_file_start
00216 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
00217 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
00218 #undef TARGET_ASM_FILE_END
00219 #define TARGET_ASM_FILE_END c4x_file_end
00220
00221 #undef TARGET_ASM_EXTERNAL_LIBCALL
00222 #define TARGET_ASM_EXTERNAL_LIBCALL c4x_external_libcall
00223
00224 #undef TARGET_ATTRIBUTE_TABLE
00225 #define TARGET_ATTRIBUTE_TABLE c4x_attribute_table
00226
00227 #undef TARGET_INSERT_ATTRIBUTES
00228 #define TARGET_INSERT_ATTRIBUTES c4x_insert_attributes
00229
00230 #undef TARGET_INIT_BUILTINS
00231 #define TARGET_INIT_BUILTINS c4x_init_builtins
00232
00233 #undef TARGET_EXPAND_BUILTIN
00234 #define TARGET_EXPAND_BUILTIN c4x_expand_builtin
00235
00236 #undef TARGET_SCHED_ADJUST_COST
00237 #define TARGET_SCHED_ADJUST_COST c4x_adjust_cost
00238
00239 #undef TARGET_ASM_GLOBALIZE_LABEL
00240 #define TARGET_ASM_GLOBALIZE_LABEL c4x_globalize_label
00241
00242 #undef TARGET_RTX_COSTS
00243 #define TARGET_RTX_COSTS c4x_rtx_costs
00244 #undef TARGET_ADDRESS_COST
00245 #define TARGET_ADDRESS_COST c4x_address_cost
00246
00247 #undef TARGET_MACHINE_DEPENDENT_REORG
00248 #define TARGET_MACHINE_DEPENDENT_REORG c4x_reorg
00249
00250 #undef TARGET_INIT_LIBFUNCS
00251 #define TARGET_INIT_LIBFUNCS c4x_init_libfuncs
00252
00253 #undef TARGET_STRUCT_VALUE_RTX
00254 #define TARGET_STRUCT_VALUE_RTX c4x_struct_value_rtx
00255
00256 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
00257 #define TARGET_GIMPLIFY_VA_ARG_EXPR c4x_gimplify_va_arg_expr
00258
00259 struct gcc_target targetm = TARGET_INITIALIZER;
00260
00261
00262
00263
00264
00265
00266 void
00267 c4x_override_options (void)
00268 {
00269 if (c4x_rpts_cycles_string)
00270 c4x_rpts_cycles = atoi (c4x_rpts_cycles_string);
00271 else
00272 c4x_rpts_cycles = 0;
00273
00274 if (TARGET_C30)
00275 c4x_cpu_version = 30;
00276 else if (TARGET_C31)
00277 c4x_cpu_version = 31;
00278 else if (TARGET_C32)
00279 c4x_cpu_version = 32;
00280 else if (TARGET_C33)
00281 c4x_cpu_version = 33;
00282 else if (TARGET_C40)
00283 c4x_cpu_version = 40;
00284 else if (TARGET_C44)
00285 c4x_cpu_version = 44;
00286 else
00287 c4x_cpu_version = 40;
00288
00289
00290 if (c4x_cpu_version_string)
00291 {
00292 const char *p = c4x_cpu_version_string;
00293
00294
00295 if (*p == 'c' || *p == 'C')
00296 p++;
00297 c4x_cpu_version = atoi (p);
00298 }
00299
00300 target_flags &= ~(C30_FLAG | C31_FLAG | C32_FLAG | C33_FLAG |
00301 C40_FLAG | C44_FLAG);
00302
00303 switch (c4x_cpu_version)
00304 {
00305 case 30: target_flags |= C30_FLAG; break;
00306 case 31: target_flags |= C31_FLAG; break;
00307 case 32: target_flags |= C32_FLAG; break;
00308 case 33: target_flags |= C33_FLAG; break;
00309 case 40: target_flags |= C40_FLAG; break;
00310 case 44: target_flags |= C44_FLAG; break;
00311 default:
00312 warning ("unknown CPU version %d, using 40.\n", c4x_cpu_version);
00313 c4x_cpu_version = 40;
00314 target_flags |= C40_FLAG;
00315 }
00316
00317 if (TARGET_C30 || TARGET_C31 || TARGET_C32 || TARGET_C33)
00318 target_flags |= C3X_FLAG;
00319 else
00320 target_flags &= ~C3X_FLAG;
00321
00322
00323 set_fast_math_flags (1);
00324
00325
00326
00327 if (! TARGET_ALIASES && ! flag_argument_noalias)
00328 flag_argument_noalias = 1;
00329 }
00330
00331
00332
00333
00334 void
00335 c4x_optimization_options (int level ATTRIBUTE_UNUSED,
00336 int size ATTRIBUTE_UNUSED)
00337 {
00338
00339
00340
00341
00342 flag_schedule_insns = 0;
00343 }
00344
00345
00346
00347
00348 #define C4X_ASCII_LIMIT 40
00349
00350 void
00351 c4x_output_ascii (FILE *stream, const char *ptr, int len)
00352 {
00353 char sbuf[C4X_ASCII_LIMIT + 1];
00354 int s, l, special, first = 1, onlys;
00355
00356 if (len)
00357 fprintf (stream, "\t.byte\t");
00358
00359 for (s = l = 0; len > 0; --len, ++ptr)
00360 {
00361 onlys = 0;
00362
00363
00364 special = *ptr == '\"' || *ptr == '\\';
00365
00366
00367 if ((! TARGET_TI || ! special) && *ptr >= 0x20 && *ptr < 0x7f)
00368 {
00369 if (special)
00370 sbuf[s++] = '\\';
00371 sbuf[s++] = *ptr;
00372 if (s < C4X_ASCII_LIMIT - 1)
00373 continue;
00374 onlys = 1;
00375 }
00376 if (s)
00377 {
00378 if (first)
00379 first = 0;
00380 else
00381 {
00382 fputc (',', stream);
00383 l++;
00384 }
00385
00386 sbuf[s] = 0;
00387 fprintf (stream, "\"%s\"", sbuf);
00388 l += s + 2;
00389 if (TARGET_TI && l >= 80 && len > 1)
00390 {
00391 fprintf (stream, "\n\t.byte\t");
00392 first = 1;
00393 l = 0;
00394 }
00395
00396 s = 0;
00397 }
00398 if (onlys)
00399 continue;
00400
00401 if (first)
00402 first = 0;
00403 else
00404 {
00405 fputc (',', stream);
00406 l++;
00407 }
00408
00409 fprintf (stream, "%d", *ptr);
00410 l += 3;
00411 if (TARGET_TI && l >= 80 && len > 1)
00412 {
00413 fprintf (stream, "\n\t.byte\t");
00414 first = 1;
00415 l = 0;
00416 }
00417 }
00418 if (s)
00419 {
00420 if (! first)
00421 fputc (',', stream);
00422
00423 sbuf[s] = 0;
00424 fprintf (stream, "\"%s\"", sbuf);
00425 s = 0;
00426 }
00427 fputc ('\n', stream);
00428 }
00429
00430
00431 int
00432 c4x_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
00433 {
00434 switch (mode)
00435 {
00436 #if Pmode != QImode
00437 case Pmode:
00438 #endif
00439 case QImode:
00440 return IS_INT_REGNO (regno);
00441
00442 case QFmode:
00443 case HFmode:
00444 return IS_EXT_REGNO (regno);
00445
00446 case CCmode:
00447 case CC_NOOVmode:
00448 return IS_ST_REGNO (regno);
00449
00450 case HImode:
00451
00452
00453
00454 return IS_INT_REGNO (regno)
00455 && IS_INT_REGNO (regno + 1)
00456 && (regno & 1) == 0;
00457
00458 default:
00459 return 0;
00460 }
00461
00462 return 0;
00463 }
00464
00465
00466 int
00467 c4x_hard_regno_rename_ok (unsigned int regno1, unsigned int regno2)
00468 {
00469
00470
00471 if (IS_FLOAT_CALL_SAVED_REGNO (regno1) && IS_INT_CALL_SAVED_REGNO (regno2))
00472 return 0;
00473 if (IS_INT_CALL_SAVED_REGNO (regno1) && IS_FLOAT_CALL_SAVED_REGNO (regno2))
00474 return 0;
00475
00476
00477
00478 if (IS_EXT_REGNO (regno1) && ! IS_EXT_REGNO (regno2))
00479 return 0;
00480 if (IS_EXT_REGNO (regno2) && ! IS_EXT_REGNO (regno1))
00481 return 0;
00482 return 1;
00483 }
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512 static const int c4x_int_reglist[3][6] =
00513 {
00514 {AR2_REGNO, R2_REGNO, R3_REGNO, RC_REGNO, RS_REGNO, RE_REGNO},
00515 {AR2_REGNO, R3_REGNO, RC_REGNO, RS_REGNO, RE_REGNO, 0},
00516 {AR2_REGNO, RC_REGNO, RS_REGNO, RE_REGNO, 0, 0}
00517 };
00518
00519 static const int c4x_fp_reglist[2] = {R2_REGNO, R3_REGNO};
00520
00521
00522
00523
00524
00525
00526 void
00527 c4x_init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname)
00528 {
00529 tree param, next_param;
00530
00531 cum->floats = cum->ints = 0;
00532 cum->init = 0;
00533 cum->var = 0;
00534 cum->args = 0;
00535
00536 if (TARGET_DEBUG)
00537 {
00538 fprintf (stderr, "\nc4x_init_cumulative_args (");
00539 if (fntype)
00540 {
00541 tree ret_type = TREE_TYPE (fntype);
00542
00543 fprintf (stderr, "fntype code = %s, ret code = %s",
00544 tree_code_name[(int) TREE_CODE (fntype)],
00545 tree_code_name[(int) TREE_CODE (ret_type)]);
00546 }
00547 else
00548 fprintf (stderr, "no fntype");
00549
00550 if (libname)
00551 fprintf (stderr, ", libname = %s", XSTR (libname, 0));
00552 }
00553
00554 cum->prototype = (fntype && TYPE_ARG_TYPES (fntype));
00555
00556 for (param = fntype ? TYPE_ARG_TYPES (fntype) : 0;
00557 param; param = next_param)
00558 {
00559 tree type;
00560
00561 next_param = TREE_CHAIN (param);
00562
00563 type = TREE_VALUE (param);
00564 if (type && type != void_type_node)
00565 {
00566 enum machine_mode mode;
00567
00568
00569
00570 if (! next_param)
00571 cum->var = 1;
00572
00573 if ((mode = TYPE_MODE (type)))
00574 {
00575 if (! targetm.calls.must_pass_in_stack (mode, type))
00576 {
00577
00578 if (mode == QFmode || mode == HFmode)
00579 cum->floats++;
00580
00581
00582 else if (mode == QImode || mode == Pmode)
00583 cum->ints++;
00584 }
00585 }
00586 cum->args++;
00587 }
00588 }
00589
00590 if (TARGET_DEBUG)
00591 fprintf (stderr, "%s%s, args = %d)\n",
00592 cum->prototype ? ", prototype" : "",
00593 cum->var ? ", variable args" : "",
00594 cum->args);
00595 }
00596
00597
00598
00599
00600
00601
00602 void
00603 c4x_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
00604 tree type, int named)
00605 {
00606 if (TARGET_DEBUG)
00607 fprintf (stderr, "c4x_function_adv(mode=%s, named=%d)\n\n",
00608 GET_MODE_NAME (mode), named);
00609 if (! TARGET_MEMPARM
00610 && named
00611 && type
00612 && ! targetm.calls.must_pass_in_stack (mode, type))
00613 {
00614
00615 if (mode == QFmode || mode == HFmode)
00616 cum->floats++;
00617
00618 else if (mode == QImode || mode == Pmode)
00619 cum->ints++;
00620 }
00621 else if (! TARGET_MEMPARM && ! type)
00622 {
00623
00624 if (mode == QFmode || mode == HFmode)
00625 cum->floats++;
00626 else if (mode == QImode || mode == Pmode)
00627 cum->ints++;
00628 }
00629 return;
00630 }
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646 struct rtx_def *
00647 c4x_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
00648 tree type, int named)
00649 {
00650 int reg = 0;
00651
00652 if (! cum->init)
00653 {
00654
00655 cum->maxfloats = (cum->floats > 2) ? 2 : cum->floats;
00656
00657
00658
00659 cum->maxints = (cum->ints > 6 - cum->maxfloats) ?
00660 6 - cum->maxfloats : cum->ints;
00661
00662
00663 if (! cum->prototype)
00664 cum->maxints = 6;
00665
00666 cum->ints = cum->floats = 0;
00667 cum->init = 1;
00668 }
00669
00670
00671
00672 if (type == void_type_node)
00673 return 0;
00674
00675 if (! TARGET_MEMPARM
00676 && named
00677 && type
00678 && ! targetm.calls.must_pass_in_stack (mode, type))
00679 {
00680
00681 if (mode == QFmode || mode == HFmode)
00682 {
00683 if (cum->floats < cum->maxfloats)
00684 reg = c4x_fp_reglist[cum->floats];
00685 }
00686
00687 else if (mode == QImode || mode == Pmode)
00688 {
00689 if (cum->ints < cum->maxints)
00690 reg = c4x_int_reglist[cum->maxfloats][cum->ints];
00691 }
00692 }
00693 else if (! TARGET_MEMPARM && ! type)
00694 {
00695
00696
00697
00698
00699
00700
00701
00702 if (mode == QFmode || mode == HFmode)
00703 reg = c4x_fp_reglist[cum->floats];
00704 else if (mode == QImode || mode == Pmode)
00705 reg = c4x_int_reglist[0][cum->ints];
00706 }
00707
00708 if (TARGET_DEBUG)
00709 {
00710 fprintf (stderr, "c4x_function_arg(mode=%s, named=%d",
00711 GET_MODE_NAME (mode), named);
00712 if (reg)
00713 fprintf (stderr, ", reg=%s", reg_names[reg]);
00714 else
00715 fprintf (stderr, ", stack");
00716 fprintf (stderr, ")\n");
00717 }
00718 if (reg)
00719 return gen_rtx_REG (mode, reg);
00720 else
00721 return NULL_RTX;
00722 }
00723
00724
00725
00726
00727 static tree
00728 c4x_gimplify_va_arg_expr (tree valist, tree type,
00729 tree *pre_p ATTRIBUTE_UNUSED,
00730 tree *post_p ATTRIBUTE_UNUSED)
00731 {
00732 tree t;
00733 bool indirect;
00734
00735 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
00736 if (indirect)
00737 type = build_pointer_type (type);
00738
00739 t = build (PREDECREMENT_EXPR, TREE_TYPE (valist), valist,
00740 build_int_cst (NULL_TREE, int_size_in_bytes (type)));
00741 t = fold_convert (build_pointer_type (type), t);
00742 t = build_fold_indirect_ref (t);
00743
00744 if (indirect)
00745 t = build_fold_indirect_ref (t);
00746
00747 return t;
00748 }
00749
00750
00751 static int
00752 c4x_isr_reg_used_p (unsigned int regno)
00753 {
00754
00755 if (regno == FRAME_POINTER_REGNUM
00756 || IS_ST_REGNO (regno))
00757 return 0;
00758
00759
00760
00761
00762 if (IS_DP_REGNO (regno))
00763 return ! TARGET_SMALL || TARGET_PARANOID;
00764
00765
00766 if (c4x_leaf_function)
00767 return regs_ever_live[regno] && fixed_regs[regno] == 0;
00768
00769
00770
00771
00772 return IS_EXT_REGNO (regno)
00773 || ((regs_ever_live[regno] || call_used_regs[regno])
00774 && fixed_regs[regno] == 0);
00775 }
00776
00777
00778 static int
00779 c4x_leaf_function_p (void)
00780 {
00781
00782
00783
00784
00785
00786
00787 if (lookup_attribute ("leaf_pretend",
00788 TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
00789 return 1;
00790
00791
00792
00793
00794
00795
00796
00797
00798 if (leaf_function_p ())
00799 return 1;
00800
00801 return 0;
00802 }
00803
00804
00805 static int
00806 c4x_naked_function_p (void)
00807 {
00808 tree type;
00809
00810 type = TREE_TYPE (current_function_decl);
00811 return lookup_attribute ("naked", TYPE_ATTRIBUTES (type)) != NULL;
00812 }
00813
00814
00815 int
00816 c4x_interrupt_function_p (void)
00817 {
00818 const char *cfun_name;
00819 if (lookup_attribute ("interrupt",
00820 TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl))))
00821 return 1;
00822
00823
00824 cfun_name = current_function_name ();
00825 return cfun_name[0] == 'c'
00826 && cfun_name[1] == '_'
00827 && cfun_name[2] == 'i'
00828 && cfun_name[3] == 'n'
00829 && cfun_name[4] == 't'
00830 && ISDIGIT (cfun_name[5])
00831 && ISDIGIT (cfun_name[6]);
00832 }
00833
00834 void
00835 c4x_expand_prologue (void)
00836 {
00837 unsigned int regno;
00838 int size = get_frame_size ();
00839 rtx insn;
00840
00841
00842
00843
00844 int dont_push_ar3;
00845
00846
00847 if (c4x_naked_function_p ())
00848 {
00849 return;
00850 }
00851
00852
00853 if (c4x_interrupt_function_p ())
00854 {
00855 c4x_leaf_function = c4x_leaf_function_p ();
00856
00857 insn = emit_insn (gen_push_st ());
00858 RTX_FRAME_RELATED_P (insn) = 1;
00859 if (size)
00860 {
00861 insn = emit_insn (gen_pushqi ( gen_rtx_REG (QImode, AR3_REGNO)));
00862 RTX_FRAME_RELATED_P (insn) = 1;
00863 insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, AR3_REGNO),
00864 gen_rtx_REG (QImode, SP_REGNO)));
00865 RTX_FRAME_RELATED_P (insn) = 1;
00866
00867
00868
00869
00870
00871
00872
00873 if (size > 32767)
00874 error ("ISR %s requires %d words of local vars, max is 32767",
00875 current_function_name (), size);
00876
00877 insn = emit_insn (gen_addqi3 (gen_rtx_REG (QImode, SP_REGNO),
00878 gen_rtx_REG (QImode, SP_REGNO),
00879 GEN_INT (size)));
00880 RTX_FRAME_RELATED_P (insn) = 1;
00881 }
00882 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
00883 {
00884 if (c4x_isr_reg_used_p (regno))
00885 {
00886 if (regno == DP_REGNO)
00887 {
00888 insn = emit_insn (gen_push_dp ());
00889 RTX_FRAME_RELATED_P (insn) = 1;
00890 }
00891 else
00892 {
00893 insn = emit_insn (gen_pushqi (gen_rtx_REG (QImode, regno)));
00894 RTX_FRAME_RELATED_P (insn) = 1;
00895 if (IS_EXT_REGNO (regno))
00896 {
00897 insn = emit_insn (gen_pushqf
00898 (gen_rtx_REG (QFmode, regno)));
00899 RTX_FRAME_RELATED_P (insn) = 1;
00900 }
00901 }
00902 }
00903 }
00904
00905
00906
00907 if (regs_ever_live[RC_REGNO]
00908 || regs_ever_live[RS_REGNO]
00909 || regs_ever_live[RE_REGNO])
00910 {
00911 insn = emit_insn (gen_andn_st (GEN_INT(~0x100)));
00912 RTX_FRAME_RELATED_P (insn) = 1;
00913 }
00914
00915
00916
00917 if (TARGET_SMALL && TARGET_PARANOID)
00918 {
00919 insn = emit_insn (gen_set_ldp_prologue
00920 (gen_rtx_REG (QImode, DP_REGNO),
00921 gen_rtx_SYMBOL_REF (QImode, "data_sec")));
00922 RTX_FRAME_RELATED_P (insn) = 1;
00923 }
00924 }
00925 else
00926 {
00927 if (frame_pointer_needed)
00928 {
00929 if ((size != 0)
00930 || (current_function_args_size != 0)
00931 || (optimize < 2))
00932 {
00933 insn = emit_insn (gen_pushqi ( gen_rtx_REG (QImode, AR3_REGNO)));
00934 RTX_FRAME_RELATED_P (insn) = 1;
00935 insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, AR3_REGNO),
00936 gen_rtx_REG (QImode, SP_REGNO)));
00937 RTX_FRAME_RELATED_P (insn) = 1;
00938 dont_push_ar3 = 1;
00939 }
00940 else
00941 {
00942
00943 dont_push_ar3 = 1;
00944 }
00945 }
00946 else
00947 {
00948
00949 dont_push_ar3 = 0;
00950 if ((size != 0) || (current_function_args_size != 0))
00951 {
00952
00953
00954
00955 size += 1;
00956 }
00957 }
00958
00959 if (size > 32767)
00960 {
00961
00962
00963 if (TARGET_C3X)
00964 {
00965 insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, R1_REGNO),
00966 GEN_INT(size >> 16)));
00967 RTX_FRAME_RELATED_P (insn) = 1;
00968 insn = emit_insn (gen_lshrqi3 (gen_rtx_REG (QImode, R1_REGNO),
00969 gen_rtx_REG (QImode, R1_REGNO),
00970 GEN_INT(-16)));
00971 RTX_FRAME_RELATED_P (insn) = 1;
00972 }
00973 else
00974 {
00975 insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, R1_REGNO),
00976 GEN_INT(size & ~0xffff)));
00977 RTX_FRAME_RELATED_P (insn) = 1;
00978 }
00979 insn = emit_insn (gen_iorqi3 (gen_rtx_REG (QImode, R1_REGNO),
00980 gen_rtx_REG (QImode, R1_REGNO),
00981 GEN_INT(size & 0xffff)));
00982 RTX_FRAME_RELATED_P (insn) = 1;
00983 insn = emit_insn (gen_addqi3 (gen_rtx_REG (QImode, SP_REGNO),
00984 gen_rtx_REG (QImode, SP_REGNO),
00985 gen_rtx_REG (QImode, R1_REGNO)));
00986 RTX_FRAME_RELATED_P (insn) = 1;
00987 }
00988 else if (size != 0)
00989 {
00990
00991
00992 insn = emit_insn (gen_addqi3 (gen_rtx_REG (QImode, SP_REGNO),
00993 gen_rtx_REG (QImode, SP_REGNO),
00994 GEN_INT (size)));
00995 RTX_FRAME_RELATED_P (insn) = 1;
00996 }
00997
00998 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
00999 {
01000 if (regs_ever_live[regno] && ! call_used_regs[regno])
01001 {
01002 if (IS_FLOAT_CALL_SAVED_REGNO (regno))
01003 {
01004 if (TARGET_PRESERVE_FLOAT)
01005 {
01006 insn = emit_insn (gen_pushqi
01007 (gen_rtx_REG (QImode, regno)));
01008 RTX_FRAME_RELATED_P (insn) = 1;
01009 }
01010 insn = emit_insn (gen_pushqf (gen_rtx_REG (QFmode, regno)));
01011 RTX_FRAME_RELATED_P (insn) = 1;
01012 }
01013 else if ((! dont_push_ar3) || (regno != AR3_REGNO))
01014 {
01015 insn = emit_insn (gen_pushqi ( gen_rtx_REG (QImode, regno)));
01016 RTX_FRAME_RELATED_P (insn) = 1;
01017 }
01018 }
01019 }
01020 }
01021 }
01022
01023
01024 void
01025 c4x_expand_epilogue(void)
01026 {
01027 int regno;
01028 int jump = 0;
01029 int dont_pop_ar3;
01030 rtx insn;
01031 int size = get_frame_size ();
01032
01033
01034 if (c4x_naked_function_p ())
01035 {
01036 insn = emit_jump_insn (gen_return_from_epilogue ());
01037 RTX_FRAME_RELATED_P (insn) = 1;
01038 return;
01039 }
01040
01041
01042 if (c4x_interrupt_function_p ())
01043 {
01044 for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; --regno)
01045 {
01046 if (! c4x_isr_reg_used_p (regno))
01047 continue;
01048 if (regno == DP_REGNO)
01049 {
01050 insn = emit_insn (gen_pop_dp ());
01051 RTX_FRAME_RELATED_P (insn) = 1;
01052 }
01053 else
01054 {
01055
01056
01057 if (IS_EXT_REGNO (regno))
01058 {
01059 insn = emit_insn (gen_popqf_unspec
01060 (gen_rtx_REG (QFmode, regno)));
01061 RTX_FRAME_RELATED_P (insn) = 1;
01062 }
01063 insn = emit_insn (gen_popqi_unspec (gen_rtx_REG (QImode, regno)));
01064 RTX_FRAME_RELATED_P (insn) = 1;
01065 }
01066 }
01067 if (size)
01068 {
01069 insn = emit_insn (gen_subqi3 (gen_rtx_REG (QImode, SP_REGNO),
01070 gen_rtx_REG (QImode, SP_REGNO),
01071 GEN_INT(size)));
01072 RTX_FRAME_RELATED_P (insn) = 1;
01073 insn = emit_insn (gen_popqi
01074 (gen_rtx_REG (QImode, AR3_REGNO)));
01075 RTX_FRAME_RELATED_P (insn) = 1;
01076 }
01077 insn = emit_insn (gen_pop_st ());
01078 RTX_FRAME_RELATED_P (insn) = 1;
01079 insn = emit_jump_insn (gen_return_from_interrupt_epilogue ());
01080 RTX_FRAME_RELATED_P (insn) = 1;
01081 }
01082 else
01083 {
01084 if (frame_pointer_needed)
01085 {
01086 if ((size != 0)
01087 || (current_function_args_size != 0)
01088 || (optimize < 2))
01089 {
01090 insn = emit_insn
01091 (gen_movqi (gen_rtx_REG (QImode, R2_REGNO),
01092 gen_rtx_MEM (QImode,
01093 gen_rtx_PLUS
01094 (QImode, gen_rtx_REG (QImode,
01095 AR3_REGNO),
01096 constm1_rtx))));
01097 RTX_FRAME_RELATED_P (insn) = 1;
01098
01099
01100
01101 size += 2;
01102 jump = 1;
01103 dont_pop_ar3 = 1;
01104 }
01105 else
01106 {
01107
01108
01109 dont_pop_ar3 = 1;
01110 }
01111 }
01112 else
01113 {
01114 dont_pop_ar3 = 0;
01115 if (size || current_function_args_size)
01116 {
01117
01118
01119
01120 size += 1;
01121 }
01122 }
01123
01124
01125
01126 for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
01127 {
01128 if (regs_ever_live[regno] && ! call_used_regs[regno])
01129 {
01130 if (regno == AR3_REGNO && dont_pop_ar3)
01131 continue;
01132
01133 if (IS_FLOAT_CALL_SAVED_REGNO (regno))
01134 {
01135 insn = emit_insn (gen_popqf_unspec
01136 (gen_rtx_REG (QFmode, regno)));
01137 RTX_FRAME_RELATED_P (insn) = 1;
01138 if (TARGET_PRESERVE_FLOAT)
01139 {
01140 insn = emit_insn (gen_popqi_unspec
01141 (gen_rtx_REG (QImode, regno)));
01142 RTX_FRAME_RELATED_P (insn) = 1;
01143 }
01144 }
01145 else
01146 {
01147 insn = emit_insn (gen_popqi (gen_rtx_REG (QImode, regno)));
01148 RTX_FRAME_RELATED_P (insn) = 1;
01149 }
01150 }
01151 }
01152
01153 if (frame_pointer_needed)
01154 {
01155 if ((size != 0)
01156 || (current_function_args_size != 0)
01157 || (optimize < 2))
01158 {
01159
01160 insn = emit_insn
01161 (gen_movqi
01162 (gen_rtx_REG (QImode, AR3_REGNO),
01163 gen_rtx_MEM (QImode, gen_rtx_REG (QImode, AR3_REGNO))));
01164
01165 RTX_FRAME_RELATED_P (insn) = 1;
01166 }
01167 }
01168
01169 if (size > 32767)
01170 {
01171
01172
01173 if (TARGET_C3X)
01174 {
01175 insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, R3_REGNO),
01176 GEN_INT(size >> 16)));
01177 RTX_FRAME_RELATED_P (insn) = 1;
01178 insn = emit_insn (gen_lshrqi3 (gen_rtx_REG (QImode, R3_REGNO),
01179 gen_rtx_REG (QImode, R3_REGNO),
01180 GEN_INT(-16)));
01181 RTX_FRAME_RELATED_P (insn) = 1;
01182 }
01183 else
01184 {
01185 insn = emit_insn (gen_movqi (gen_rtx_REG (QImode, R3_REGNO),
01186 GEN_INT(size & ~0xffff)));
01187 RTX_FRAME_RELATED_P (insn) = 1;
01188 }
01189 insn = emit_insn (gen_iorqi3 (gen_rtx_REG (QImode, R3_REGNO),
01190 gen_rtx_REG (QImode, R3_REGNO),
01191 GEN_INT(size & 0xffff)));
01192 RTX_FRAME_RELATED_P (insn) = 1;
01193 insn = emit_insn (gen_subqi3 (gen_rtx_REG (QImode, SP_REGNO),
01194 gen_rtx_REG (QImode, SP_REGNO),
01195 gen_rtx_REG (QImode, R3_REGNO)));
01196 RTX_FRAME_RELATED_P (insn) = 1;
01197 }
01198 else if (size != 0)
01199 {
01200
01201
01202 insn = emit_insn (gen_subqi3 (gen_rtx_REG (QImode, SP_REGNO),
01203 gen_rtx_REG (QImode, SP_REGNO),
01204 GEN_INT(size)));
01205 RTX_FRAME_RELATED_P (insn) = 1;
01206 }
01207
01208 if (jump)
01209 {
01210 insn = emit_jump_insn (gen_return_indirect_internal
01211 (gen_rtx_REG (QImode, R2_REGNO)));
01212 RTX_FRAME_RELATED_P (insn) = 1;
01213 }
01214 else
01215 {
01216 insn = emit_jump_insn (gen_return_from_epilogue ());
01217 RTX_FRAME_RELATED_P (insn) = 1;
01218 }
01219 }
01220 }
01221
01222
01223 int
01224 c4x_null_epilogue_p (void)
01225 {
01226 int regno;
01227
01228 if (reload_completed
01229 && ! c4x_naked_function_p ()
01230 && ! c4x_interrupt_function_p ()
01231 && ! current_function_calls_alloca
01232 && ! current_function_args_size
01233 && ! (optimize < 2)
01234 && ! get_frame_size ())
01235 {
01236 for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; regno--)
01237 if (regs_ever_live[regno] && ! call_used_regs[regno]
01238 && (regno != AR3_REGNO))
01239 return 1;
01240 return 0;
01241 }
01242 return 1;
01243 }
01244
01245
01246 int
01247 c4x_emit_move_sequence (rtx *operands, enum machine_mode mode)
01248 {
01249 rtx op0 = operands[0];
01250 rtx op1 = operands[1];
01251
01252 if (! reload_in_progress
01253 && ! REG_P (op0)
01254 && ! REG_P (op1)
01255 && ! (stik_const_operand (op1, mode) && ! push_operand (op0, mode)))
01256 op1 = force_reg (mode, op1);
01257
01258 if (GET_CODE (op1) == LO_SUM
01259 && GET_MODE (op1) == Pmode
01260 && dp_reg_operand (XEXP (op1, 0), mode))
01261 {
01262
01263
01264 op1 = XEXP (op1, 1);
01265 }
01266
01267 if (symbolic_address_operand (op1, mode))
01268 {
01269 if (TARGET_LOAD_ADDRESS)
01270 {
01271
01272
01273 emit_insn (gen_load_immed_address (op0, op1));
01274 return 1;
01275 }
01276 else
01277 {
01278
01279 op1 = force_const_mem (Pmode, op1);
01280 }
01281 }
01282 else if (mode == HFmode && CONSTANT_P (op1) && ! LEGITIMATE_CONSTANT_P (op1))
01283 {
01284
01285
01286 op1 = force_const_mem (mode, op1);
01287 }
01288
01289
01290
01291
01292
01293 if (TARGET_EXPOSE_LDP
01294 && ! (reload_in_progress || reload_completed)
01295 && GET_CODE (op1) == MEM
01296 && symbolic_address_operand (XEXP (op1, 0), Pmode))
01297 {
01298 rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO);
01299 if (! TARGET_SMALL)
01300 emit_insn (gen_set_ldp (dp_reg, XEXP (op1, 0)));
01301 op1 = change_address (op1, mode,
01302 gen_rtx_LO_SUM (Pmode, dp_reg, XEXP (op1, 0)));
01303 }
01304
01305 if (TARGET_EXPOSE_LDP
01306 && ! (reload_in_progress || reload_completed)
01307 && GET_CODE (op0) == MEM
01308 && symbolic_address_operand (XEXP (op0, 0), Pmode))
01309 {
01310 rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO);
01311 if (! TARGET_SMALL)
01312 emit_insn (gen_set_ldp (dp_reg, XEXP (op0, 0)));
01313 op0 = change_address (op0, mode,
01314 gen_rtx_LO_SUM (Pmode, dp_reg, XEXP (op0, 0)));
01315 }
01316
01317 if (GET_CODE (op0) == SUBREG
01318 && mixed_subreg_operand (op0, mode))
01319 {
01320
01321
01322
01323 if (reload_in_progress || reload_completed)
01324 abort ();
01325 if (GET_MODE (SUBREG_REG (op0)) == QImode)
01326 op0 = SUBREG_REG (op0);
01327 else if (GET_MODE (SUBREG_REG (op0)) == HImode)
01328 {
01329 op0 = copy_rtx (op0);
01330 PUT_MODE (op0, QImode);
01331 }
01332 else
01333 abort ();
01334
01335 if (mode == QFmode)
01336 emit_insn (gen_storeqf_int_clobber (op0, op1));
01337 else
01338 abort ();
01339 return 1;
01340 }
01341
01342 if (GET_CODE (op1) == SUBREG
01343 && mixed_subreg_operand (op1, mode))
01344 {
01345
01346
01347
01348 if (reload_in_progress || reload_completed)
01349 abort ();
01350 if (GET_MODE (SUBREG_REG (op1)) == QImode)
01351 op1 = SUBREG_REG (op1);
01352 else if (GET_MODE (SUBREG_REG (op1)) == HImode)
01353 {
01354 op1 = copy_rtx (op1);
01355 PUT_MODE (op1, QImode);
01356 }
01357 else
01358 abort ();
01359
01360 if (mode == QFmode)
01361 emit_insn (gen_loadqf_int_clobber (op0, op1));
01362 else
01363 abort ();
01364 return 1;
01365 }
01366
01367 if (mode == QImode
01368 && reg_operand (op0, mode)
01369 && const_int_operand (op1, mode)
01370 && ! IS_INT16_CONST (INTVAL (op1))
01371 && ! IS_HIGH_CONST (INTVAL (op1)))
01372 {
01373 emit_insn (gen_loadqi_big_constant (op0, op1));
01374 return 1;
01375 }
01376
01377 if (mode == HImode
01378 && reg_operand (op0, mode)
01379 && const_int_operand (op1, mode))
01380 {
01381 emit_insn (gen_loadhi_big_constant (op0, op1));
01382 return 1;
01383 }
01384
01385
01386 operands[0] = op0;
01387 operands[1] = op1;
01388
01389
01390 return 0;
01391 }
01392
01393
01394 void
01395 c4x_emit_libcall (rtx libcall, enum rtx_code code,
01396 enum machine_mode dmode, enum machine_mode smode,
01397 int noperands, rtx *operands)
01398 {
01399 rtx ret;
01400 rtx insns;
01401 rtx equiv;
01402
01403 start_sequence ();
01404 switch (noperands)
01405 {
01406 case 2:
01407 ret = emit_library_call_value (libcall, NULL_RTX, 1, dmode, 1,
01408 operands[1], smode);
01409 equiv = gen_rtx_fmt_e (code, dmode, operands[1]);
01410 break;
01411
01412 case 3:
01413 ret = emit_library_call_value (libcall, NULL_RTX, 1, dmode, 2,
01414 operands[1], smode, operands[2], smode);
01415 equiv = gen_rtx_fmt_ee (code, dmode, operands[1], operands[2]);
01416 break;
01417
01418 default:
01419 abort ();
01420 }
01421
01422 insns = get_insns ();
01423 end_sequence ();
01424 emit_libcall_block (insns, operands[0], ret, equiv);
01425 }
01426
01427
01428 void
01429 c4x_emit_libcall3 (rtx libcall, enum rtx_code code,
01430 enum machine_mode mode, rtx *operands)
01431 {
01432 c4x_emit_libcall (libcall, code, mode, mode, 3, operands);
01433 }
01434
01435
01436 void
01437 c4x_emit_libcall_mulhi (rtx libcall, enum rtx_code code,
01438 enum machine_mode mode, rtx *operands)
01439 {
01440 rtx ret;
01441 rtx insns;
01442 rtx equiv;
01443
01444 start_sequence ();
01445 ret = emit_library_call_value (libcall, NULL_RTX, 1, mode, 2,
01446 operands[1], mode, operands[2], mode);
01447 equiv = gen_rtx_TRUNCATE (mode,
01448 gen_rtx_LSHIFTRT (HImode,
01449 gen_rtx_MULT (HImode,
01450 gen_rtx_fmt_e (code, HImode, operands[1]),
01451 gen_rtx_fmt_e (code, HImode, operands[2])),
01452 GEN_INT (32)));
01453 insns = get_insns ();
01454 end_sequence ();
01455 emit_libcall_block (insns, operands[0], ret, equiv);
01456 }
01457
01458
01459 int
01460 c4x_legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
01461 {
01462 rtx base = NULL_RTX;
01463 rtx indx = NULL_RTX;
01464 rtx disp = NULL_RTX;
01465 enum rtx_code code;
01466
01467 code = GET_CODE (addr);
01468 switch (code)
01469 {
01470
01471
01472
01473
01474 case PRE_DEC:
01475 case PRE_INC:
01476 case POST_DEC:
01477 if (mode != QImode && mode != QFmode)
01478 return 0;
01479
01480 case POST_INC:
01481 base = XEXP (addr, 0);
01482 if (! REG_P (base))
01483 return 0;
01484 break;
01485
01486 case PRE_MODIFY:
01487 case POST_MODIFY:
01488 {
01489 rtx op0 = XEXP (addr, 0);
01490 rtx op1 = XEXP (addr, 1);
01491
01492 if (mode != QImode && mode != QFmode)
01493 return 0;
01494
01495 if (! REG_P (op0)
01496 || (GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS))
01497 return 0;
01498 base = XEXP (op1, 0);
01499 if (! REG_P (base))
01500 return 0;
01501 if (REGNO (base) != REGNO (op0))
01502 return 0;
01503 if (REG_P (XEXP (op1, 1)))
01504 indx = XEXP (op1, 1);
01505 else
01506 disp = XEXP (op1, 1);
01507 }
01508 break;
01509
01510
01511 case REG:
01512 base = addr;
01513 break;
01514
01515
01516 case PLUS:
01517 {
01518 rtx op0 = XEXP (addr, 0);
01519 rtx op1 = XEXP (addr, 1);
01520 enum rtx_code code0 = GET_CODE (op0);
01521
01522 switch (code0)
01523 {
01524 case REG:
01525 if (REG_P (op1))
01526 {
01527 base = op0;
01528 indx = op1;
01529 if (IS_INDEX_REG (base) || IS_ADDR_REG (indx))
01530 {
01531 base = op1;
01532 indx = op0;
01533 }
01534 }
01535 else
01536 {
01537 base = op0;
01538 disp = op1;
01539 }
01540 break;
01541
01542 default:
01543 return 0;
01544 }
01545 }
01546 break;
01547
01548
01549 case LO_SUM:
01550 {
01551 rtx op0 = XEXP (addr, 0);
01552 rtx op1 = XEXP (addr, 1);
01553
01554
01555
01556
01557
01558 if (mode == HImode || mode == HFmode)
01559 return 0;
01560
01561 if (!REG_P (op0) || REGNO (op0) != DP_REGNO)
01562 return 0;
01563
01564 if ((GET_CODE (op1) == SYMBOL_REF || GET_CODE (op1) == LABEL_REF))
01565 return 1;
01566
01567 if (GET_CODE (op1) == CONST)
01568 return 1;
01569 return 0;
01570 }
01571 break;
01572
01573
01574 case CONST:
01575
01576 case LABEL_REF:
01577 case SYMBOL_REF:
01578 if (! TARGET_EXPOSE_LDP && ! strict && mode != HFmode && mode != HImode)
01579 return 1;
01580
01581
01582 return 0;
01583
01584
01585
01586
01587
01588
01589
01590 case CONST_INT:
01591 return 0;
01592
01593
01594 case MEM:
01595 return 0;
01596
01597 case CONST_DOUBLE:
01598 fatal_insn ("using CONST_DOUBLE for address", addr);
01599
01600 default:
01601 return 0;
01602 }
01603
01604
01605 if (base)
01606 {
01607
01608 if (indx && (mode == HImode || mode == HFmode))
01609 return 0;
01610
01611
01612 if (REGNO (base) == DP_REGNO)
01613 return 1;
01614 if (strict && ! REGNO_OK_FOR_BASE_P (REGNO (base)))
01615 return 0;
01616 else if (! strict && ! IS_ADDR_OR_PSEUDO_REG (base))
01617 return 0;
01618 }
01619
01620
01621 if (indx)
01622 {
01623 if (GET_CODE (indx) != REG)
01624 return 0;
01625 if (strict && ! REGNO_OK_FOR_INDEX_P (REGNO (indx)))
01626 return 0;
01627 else if (! strict && ! IS_INDEX_OR_PSEUDO_REG (indx))
01628 return 0;
01629 }
01630
01631
01632 if (disp)
01633 {
01634 if (GET_CODE (disp) != CONST_INT)
01635 return 0;
01636 if (mode == HImode || mode == HFmode)
01637 {
01638
01639 if (! IS_DISP8_OFF_CONST (INTVAL (disp)))
01640 return 0;
01641 }
01642 else
01643 {
01644 if (! IS_DISP8_CONST (INTVAL (disp)))
01645 return 0;
01646 }
01647
01648 if (indx)
01649 return 0;
01650 }
01651 return 1;
01652 }
01653
01654
01655 rtx
01656 c4x_legitimize_address (rtx orig ATTRIBUTE_UNUSED,
01657 enum machine_mode mode ATTRIBUTE_UNUSED)
01658 {
01659 if (GET_CODE (orig) == SYMBOL_REF
01660 || GET_CODE (orig) == LABEL_REF)
01661 {
01662 if (mode == HImode || mode == HFmode)
01663 {
01664
01665
01666 rtx addr_reg = gen_reg_rtx (Pmode);
01667 emit_move_insn (addr_reg, orig);
01668 return addr_reg;
01669 }
01670 else
01671 {
01672 rtx dp_reg = gen_rtx_REG (Pmode, DP_REGNO);
01673
01674 if (! TARGET_SMALL)
01675 emit_insn (gen_set_ldp (dp_reg, orig));
01676
01677 return gen_rtx_LO_SUM (Pmode, dp_reg, orig);
01678 }
01679 }
01680
01681 return NULL_RTX;
01682 }
01683
01684
01685
01686
01687
01688
01689
01690
01691 static int
01692 c4x_address_cost (rtx addr)
01693 {
01694 switch (GET_CODE (addr))
01695 {
01696 case REG:
01697 return 1;
01698
01699 case POST_INC:
01700 case POST_DEC:
01701 case PRE_INC:
01702 case PRE_DEC:
01703 return 1;
01704
01705
01706 case SYMBOL_REF:
01707 case LABEL_REF:
01708 case CONST:
01709 return 10;
01710
01711 case LO_SUM:
01712 {
01713 rtx op1 = XEXP (addr, 1);
01714
01715 if (GET_CODE (op1) == LABEL_REF || GET_CODE (op1) == SYMBOL_REF)
01716 return TARGET_SMALL ? 3 : 4;
01717
01718 if (GET_CODE (op1) == CONST)
01719 {
01720 rtx offset = const0_rtx;
01721
01722 op1 = eliminate_constant_term (op1, &offset);
01723
01724
01725 if (GET_CODE (op1) == LABEL_REF)
01726 return 3;
01727
01728 if (GET_CODE (op1) != SYMBOL_REF)
01729 return 4;
01730
01731 if (INTVAL (offset) == 0)
01732 return 3;
01733
01734 return 4;
01735 }
01736 fatal_insn ("c4x_address_cost: Invalid addressing mode", addr);
01737 }
01738 break;
01739
01740 case PLUS:
01741 {
01742 register rtx op0 = XEXP (addr, 0);
01743 register rtx op1 = XEXP (addr, 1);
01744
01745 if (GET_CODE (op0) != REG)
01746 break;
01747
01748 switch (GET_CODE (op1))
01749 {
01750 default:
01751 break;
01752
01753 case REG:
01754
01755
01756 return 2;
01757
01758 case CONST_INT:
01759
01760
01761 if (TARGET_DEVEL && IS_UINT5_CONST (INTVAL (op1)))
01762 return 1;
01763
01764 if (IS_DISP1_CONST (INTVAL (op1)))
01765 return 1;
01766
01767 if (! TARGET_C3X && IS_UINT5_CONST (INTVAL (op1)))
01768 return 2;
01769
01770 return 3;
01771 }
01772 }
01773 default:
01774 break;
01775 }
01776
01777 return 4;
01778 }
01779
01780
01781 rtx
01782 c4x_gen_compare_reg (enum rtx_code code, rtx x, rtx y)
01783 {
01784 enum machine_mode mode = SELECT_CC_MODE (code, x, y);
01785 rtx cc_reg;
01786
01787 if (mode == CC_NOOVmode
01788 && (code == LE || code == GE || code == LT || code == GT))
01789 return NULL_RTX;
01790
01791 cc_reg = gen_rtx_REG (mode, ST_REGNO);
01792 emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
01793 gen_rtx_COMPARE (mode, x, y)));
01794 return cc_reg;
01795 }
01796
01797 char *
01798 c4x_output_cbranch (const char *form, rtx seq)
01799 {
01800 int delayed = 0;
01801 int annultrue = 0;
01802 int annulfalse = 0;
01803 rtx delay;
01804 char *cp;
01805 static char str[100];
01806
01807 if (final_sequence)
01808 {
01809 delay = XVECEXP (final_sequence, 0, 1);
01810 delayed = ! INSN_ANNULLED_BRANCH_P (seq);
01811 annultrue = INSN_ANNULLED_BRANCH_P (seq) && ! INSN_FROM_TARGET_P (delay);
01812 annulfalse = INSN_ANNULLED_BRANCH_P (seq) && INSN_FROM_TARGET_P (delay);
01813 }
01814 strcpy (str, form);
01815 cp = &str [strlen (str)];
01816 if (delayed)
01817 {
01818 *cp++ = '%';
01819 *cp++ = '#';
01820 }
01821 if (annultrue)
01822 {
01823 *cp++ = 'a';
01824 *cp++ = 't';
01825 }
01826 if (annulfalse)
01827 {
01828 *cp++ = 'a';
01829 *cp++ = 'f';
01830 }
01831 *cp++ = '\t';
01832 *cp++ = '%';
01833 *cp++ = 'l';
01834 *cp++ = '1';
01835 *cp = 0;
01836 return str;
01837 }
01838
01839 void
01840 c4x_print_operand (FILE *file, rtx op, int letter)
01841 {
01842 rtx op1;
01843 enum rtx_code code;
01844
01845 switch (letter)
01846 {
01847 case '#':
01848 if (final_sequence)
01849 fprintf (file, "d");
01850 return;
01851 }
01852
01853 code = GET_CODE (op);
01854 switch (letter)
01855 {
01856 case 'A':
01857 if (code == CONST_INT || code == SYMBOL_REF || code == CONST)
01858 fprintf (file, "@");
01859 break;
01860
01861 case 'H':
01862 output_addr_const (file, op);
01863 return;
01864
01865 case 'I':
01866 code = reverse_condition (code);
01867 break;
01868
01869 case 'L':
01870 if (code != CONST_INT)
01871 fatal_insn ("c4x_print_operand: %%L inconsistency", op);
01872 fprintf (file, "%d", exact_log2 (INTVAL (op)));
01873 return;
01874
01875 case 'N':
01876 if (code != CONST_INT)
01877 fatal_insn ("c4x_print_operand: %%N inconsistency", op);
01878 fprintf (file, HOST_WIDE_INT_PRINT_DEC, ~INTVAL (op));
01879 return;
01880
01881 case 'K':
01882 if (! TARGET_SMALL
01883 && code == MEM
01884 && GET_CODE (XEXP (op, 0)) == LO_SUM
01885 && GET_CODE (XEXP (XEXP (op, 0), 0)) == REG
01886 && REGNO (XEXP (XEXP (op, 0), 0)) == DP_REGNO)
01887 {
01888 op1 = XEXP (XEXP (op, 0), 1);
01889 if (GET_CODE(op1) == CONST_INT || GET_CODE(op1) == SYMBOL_REF)
01890 {
01891 fprintf (file, "\t%s\t@", TARGET_C3X ? "ldp" : "ldpk");
01892 output_address (XEXP (adjust_address (op, VOIDmode, 1), 0));
01893 fprintf (file, "\n");
01894 }
01895 }
01896 return;
01897
01898 case 'M':
01899 if (! TARGET_SMALL
01900 && code == MEM
01901 && (GET_CODE (XEXP (op, 0)) == CONST
01902 || GET_CODE (XEXP (op, 0)) == SYMBOL_REF))
01903 {
01904 fprintf (file, "%s\t@", TARGET_C3X ? "ldp" : "ldpk");
01905 output_address (XEXP (op, 0));
01906 fprintf (file, "\n\t");
01907 }
01908 return;
01909
01910 case 'O':
01911 if (code == MEM && c4x_autoinc_operand (op, Pmode))
01912 break;
01913 else if (code == MEM)
01914 output_address (XEXP (adjust_address (op, VOIDmode, 1), 0));
01915 else if (code == REG)
01916 fprintf (file, "%s", reg_names[REGNO (op) + 1]);
01917 else
01918 fatal_insn ("c4x_print_operand: %%O inconsistency", op);
01919 return;
01920
01921 case 'C':
01922 break;
01923
01924 case 'U':
01925 if (code != SYMBOL_REF)
01926 fprintf (file, "u");
01927 return;
01928
01929 default:
01930 break;
01931 }
01932
01933 switch (code)
01934 {
01935 case REG:
01936 if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
01937 && ! TARGET_TI)
01938 fprintf (file, "%s", float_reg_names[REGNO (op)]);
01939 else
01940 fprintf (file, "%s", reg_names[REGNO (op)]);
01941 break;
01942
01943 case MEM:
01944 output_address (XEXP (op, 0));
01945 break;
01946
01947 case CONST_DOUBLE:
01948 {
01949 char str[64];
01950
01951 real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (op),
01952 sizeof (str), 0, 1);
01953 fprintf (file, "%s", str);
01954 }
01955 break;
01956
01957 case CONST_INT:
01958 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (op));
01959 break;
01960
01961 case NE:
01962 fprintf (file, "ne");
01963 break;
01964
01965 case EQ:
01966 fprintf (file, "eq");
01967 break;
01968
01969 case GE:
01970 fprintf (file, "ge");
01971 break;
01972
01973 case GT:
01974 fprintf (file, "gt");
01975 break;
01976
01977 case LE:
01978 fprintf (file, "le");
01979 break;
01980
01981 case LT:
01982 fprintf (file, "lt");
01983 break;
01984
01985 case GEU:
01986 fprintf (file, "hs");
01987 break;
01988
01989 case GTU:
01990 fprintf (file, "hi");
01991 break;
01992
01993 case LEU:
01994 fprintf (file, "ls");
01995 break;
01996
01997 case LTU:
01998 fprintf (file, "lo");
01999 break;
02000
02001 case SYMBOL_REF:
02002 output_addr_const (file, op);
02003 break;
02004
02005 case CONST:
02006 output_addr_const (file, XEXP (op, 0));
02007 break;
02008
02009 case CODE_LABEL:
02010 break;
02011
02012 default:
02013 fatal_insn ("c4x_print_operand: Bad operand case", op);
02014 break;
02015 }
02016 }
02017
02018
02019 void
02020 c4x_print_operand_address (FILE *file, rtx addr)
02021 {
02022 switch (GET_CODE (addr))
02023 {
02024 case REG:
02025 fprintf (file, "*%s", reg_names[REGNO (addr)]);
02026 break;
02027
02028 case PRE_DEC:
02029 fprintf (file, "*--%s", reg_names[REGNO (XEXP (addr, 0))]);
02030 break;
02031
02032 case POST_INC:
02033 fprintf (file, "*%s++", reg_names[REGNO (XEXP (addr, 0))]);
02034 break;
02035
02036 case POST_MODIFY:
02037 {
02038 rtx op0 = XEXP (XEXP (addr, 1), 0);
02039 rtx op1 = XEXP (XEXP (addr, 1), 1);
02040
02041 if (GET_CODE (XEXP (addr, 1)) == PLUS && REG_P (op1))
02042 fprintf (file, "*%s++(%s)", reg_names[REGNO (op0)],
02043 reg_names[REGNO (op1)]);
02044 else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) > 0)
02045 fprintf (file, "*%s++(" HOST_WIDE_INT_PRINT_DEC ")",
02046 reg_names[REGNO (op0)], INTVAL (op1));
02047 else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) < 0)
02048 fprintf (file, "*%s--(" HOST_WIDE_INT_PRINT_DEC ")",
02049 reg_names[REGNO (op0)], -INTVAL (op1));
02050 else if (GET_CODE (XEXP (addr, 1)) == MINUS && REG_P (op1))
02051 fprintf (file, "*%s--(%s)", reg_names[REGNO (op0)],
02052 reg_names[REGNO (op1)]);
02053 else
02054 fatal_insn ("c4x_print_operand_address: Bad post_modify", addr);
02055 }
02056 break;
02057
02058 case PRE_MODIFY:
02059 {
02060 rtx op0 = XEXP (XEXP (addr, 1), 0);
02061 rtx op1 = XEXP (XEXP (addr, 1), 1);
02062
02063 if (GET_CODE (XEXP (addr, 1)) == PLUS && REG_P (op1))
02064 fprintf (file, "*++%s(%s)", reg_names[REGNO (op0)],
02065 reg_names[REGNO (op1)]);
02066 else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) > 0)
02067 fprintf (file, "*++%s(" HOST_WIDE_INT_PRINT_DEC ")",
02068 reg_names[REGNO (op0)], INTVAL (op1));
02069 else if (GET_CODE (XEXP (addr, 1)) == PLUS && INTVAL (op1) < 0)
02070 fprintf (file, "*--%s(" HOST_WIDE_INT_PRINT_DEC ")",
02071 reg_names[REGNO (op0)], -INTVAL (op1));
02072 else if (GET_CODE (XEXP (addr, 1)) == MINUS && REG_P (op1))
02073 fprintf (file, "*--%s(%s)", reg_names[REGNO (op0)],
02074 reg_names[REGNO (op1)]);
02075 else
02076 fatal_insn ("c4x_print_operand_address: Bad pre_modify", addr);
02077 }
02078 break;
02079
02080 case PRE_INC:
02081 fprintf (file, "*++%s", reg_names[REGNO (XEXP (addr, 0))]);
02082 break;
02083
02084 case POST_DEC:
02085 fprintf (file, "*%s--", reg_names[REGNO (XEXP (addr, 0))]);
02086 break;
02087
02088 case PLUS:
02089 {
02090 rtx op0 = XEXP (addr, 0);
02091 rtx op1 = XEXP (addr, 1);
02092
02093 if (REG_P (op0))
02094 {
02095 if (REG_P (op1))
02096 {
02097 if (IS_INDEX_REG (op0))
02098 {
02099 fprintf (file, "*+%s(%s)",
02100 reg_names[REGNO (op1)],
02101 reg_names[REGNO (op0)]);
02102 }
02103 else
02104 {
02105 fprintf (file, "*+%s(%s)",
02106 reg_names[REGNO (op0)],
02107 reg_names[REGNO (op1)]);
02108 }
02109 }
02110 else if (INTVAL (op1) < 0)
02111 {
02112 fprintf (file, "*-%s(" HOST_WIDE_INT_PRINT_DEC ")",
02113 reg_names[REGNO (op0)],
02114 -INTVAL (op1));
02115 }
02116 else
02117 {
02118 fprintf (file, "*+%s(" HOST_WIDE_INT_PRINT_DEC ")",
02119 reg_names[REGNO (op0)],
02120 INTVAL (op1));
02121 }
02122 }
02123 else
02124 fatal_insn ("c4x_print_operand_address: Bad operand case", addr);
02125 }
02126 break;
02127
02128 case LO_SUM:
02129 {
02130 rtx op0 = XEXP (addr, 0);
02131 rtx op1 = XEXP (addr, 1);
02132
02133 if (REG_P (op0) && REGNO (op0) == DP_REGNO)
02134 c4x_print_operand_address (file, op1);
02135 else
02136 fatal_insn ("c4x_print_operand_address: Bad operand case", addr);
02137 }
02138 break;
02139
02140 case CONST:
02141 case SYMBOL_REF:
02142 case LABEL_REF:
02143 fprintf (file, "@");
02144 output_addr_const (file, addr);
02145 break;
02146
02147
02148 case CONST_INT:
02149
02150 default:
02151 fatal_insn ("c4x_print_operand_address: Bad operand case", addr);
02152 break;
02153 }
02154 }
02155
02156
02157
02158
02159
02160 static int
02161 c4x_immed_float_p (rtx op)
02162 {
02163 long convval[2];
02164 int exponent;
02165 REAL_VALUE_TYPE r;
02166
02167 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
02168 if (GET_MODE (op) == HFmode)
02169 REAL_VALUE_TO_TARGET_DOUBLE (r, convval);
02170 else
02171 {
02172 REAL_VALUE_TO_TARGET_SINGLE (r, convval[0]);
02173 convval[1] = 0;
02174 }
02175
02176
02177 exponent = (((convval[0] >> 24) & 0xff) ^ 0x80) - 0x80;
02178 if (exponent == -128)
02179 return 1;
02180 if ((convval[0] & 0x00000fff) != 0 || convval[1] != 0)
02181 return 0;
02182 return (exponent <= 7)
02183 && (exponent >= -7);
02184 }
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206 int
02207 c4x_rptb_nop_p (rtx insn)
02208 {
02209 rtx start_label;
02210 int i;
02211
02212
02213 start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 1), 0);
02214
02215
02216
02217 do {
02218 insn = previous_insn (insn);
02219 } while (GET_CODE (insn) == NOTE
02220 || GET_CODE (insn) == USE
02221 || GET_CODE (insn) == CLOBBER);
02222 if (GET_CODE (insn) == CODE_LABEL)
02223 return 1;
02224
02225 for (i = 0; i < 4; i++)
02226 {
02227
02228 while (GET_CODE (insn) == NOTE || GET_CODE (insn) == CODE_LABEL
02229 || GET_CODE (insn) == USE || GET_CODE (insn) == CLOBBER)
02230 {
02231 if (insn == start_label)
02232 return i == 0;
02233
02234 insn = previous_insn (insn);
02235 };
02236
02237
02238
02239
02240 if (GET_CODE (insn) == JUMP_INSN)
02241 return 1;
02242 insn = previous_insn (insn);
02243 }
02244 return 0;
02245 }
02246
02247
02248
02249
02250
02251
02252
02253
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264 static int
02265 c4x_label_ref_used_p (rtx x, rtx code_label)
02266 {
02267 enum rtx_code code;
02268 int i, j;
02269 const char *fmt;
02270
02271 if (x == 0)
02272 return 0;
02273
02274 code = GET_CODE (x);
02275 if (code == LABEL_REF)
02276 return INSN_UID (XEXP (x,0)) == INSN_UID (code_label);
02277
02278 fmt = GET_RTX_FORMAT (code);
02279 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
02280 {
02281 if (fmt[i] == 'e')
02282 {
02283 if (c4x_label_ref_used_p (XEXP (x, i), code_label))
02284 return 1;
02285 }
02286 else if (fmt[i] == 'E')
02287 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
02288 if (c4x_label_ref_used_p (XVECEXP (x, i, j), code_label))
02289 return 1;
02290 }
02291 return 0;
02292 }
02293
02294
02295 static int
02296 c4x_rptb_valid_p (rtx insn, rtx start_label)
02297 {
02298 rtx end = insn;
02299 rtx start;
02300 rtx tmp;
02301
02302
02303 for (; insn; insn = PREV_INSN (insn))
02304 if (insn == start_label)
02305 break;
02306
02307
02308
02309 if (! insn)
02310 return 0;
02311
02312 start = insn;
02313
02314 for (insn = PREV_INSN (start); insn; insn = PREV_INSN (insn))
02315 {
02316 if (GET_CODE (insn) == CODE_LABEL)
02317 {
02318 for (tmp = NEXT_INSN (start); tmp != end; tmp = NEXT_INSN(tmp))
02319 if (GET_CODE (tmp) == JUMP_INSN
02320 && c4x_label_ref_used_p (tmp, insn))
02321 return 0;
02322 }
02323 }
02324 for (insn = NEXT_INSN (end); insn; insn = NEXT_INSN (insn))
02325 {
02326 if (GET_CODE (insn) == CODE_LABEL)
02327 {
02328 for (tmp = NEXT_INSN (start); tmp != end; tmp = NEXT_INSN(tmp))
02329 if (GET_CODE (tmp) == JUMP_INSN
02330 && c4x_label_ref_used_p (tmp, insn))
02331 return 0;
02332 }
02333 }
02334
02335 for (insn = NEXT_INSN (start); insn != end; insn = NEXT_INSN (insn))
02336 {
02337 if (GET_CODE (insn) == CODE_LABEL)
02338 {
02339 for (tmp = NEXT_INSN (end); tmp; tmp = NEXT_INSN(tmp))
02340 if (GET_CODE (tmp) == JUMP_INSN
02341 && c4x_label_ref_used_p (tmp, insn))
02342 return 0;
02343 for (tmp = PREV_INSN (start); tmp; tmp = PREV_INSN(tmp))
02344 if (GET_CODE (tmp) == JUMP_INSN
02345 && c4x_label_ref_used_p (tmp, insn))
02346 return 0;
02347 }
02348 }
02349
02350
02351 return 1;
02352 }
02353
02354
02355 void
02356 c4x_rptb_insert (rtx insn)
02357 {
02358 rtx end_label;
02359 rtx start_label;
02360 rtx new_start_label;
02361 rtx count_reg;
02362
02363
02364
02365
02366
02367 count_reg = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 0), 0);
02368 if (REGNO (count_reg) != RC_REGNO)
02369 return;
02370
02371
02372 start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 1), 0);
02373
02374 if (! c4x_rptb_valid_p (insn, start_label))
02375 {
02376
02377
02378 emit_insn_before (gen_addqi3 (count_reg, count_reg, constm1_rtx), insn);
02379 emit_insn_before (gen_cmpqi (count_reg, const0_rtx), insn);
02380 emit_insn_before (gen_bge (start_label), insn);
02381 LABEL_NUSES (start_label)++;
02382 delete_insn (insn);
02383 return;
02384 }
02385
02386 end_label = gen_label_rtx ();
02387 LABEL_NUSES (end_label)++;
02388 emit_label_after (end_label, insn);
02389
02390 new_start_label = gen_label_rtx ();
02391 LABEL_NUSES (new_start_label)++;
02392
02393 for (; insn; insn = PREV_INSN (insn))
02394 {
02395 if (insn == start_label)
02396 break;
02397 if (GET_CODE (insn) == JUMP_INSN &&
02398 JUMP_LABEL (insn) == start_label)
02399 redirect_jump (insn, new_start_label, 0);
02400 }
02401 if (! insn)
02402 fatal_insn ("c4x_rptb_insert: Cannot find start label", start_label);
02403
02404 emit_label_after (new_start_label, insn);
02405
02406 if (TARGET_RPTS && c4x_rptb_rpts_p (PREV_INSN (insn), 0))
02407 emit_insn_after (gen_rpts_top (new_start_label, end_label), insn);
02408 else
02409 emit_insn_after (gen_rptb_top (new_start_label, end_label), insn);
02410 if (LABEL_NUSES (start_label) == 0)
02411 delete_insn (start_label);
02412 }
02413
02414
02415
02416
02417
02418
02419
02420
02421
02422
02423
02424
02425 static void
02426 c4x_reorg (void)
02427 {
02428 rtx insn;
02429
02430 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
02431 {
02432
02433 if (INSN_P (insn))
02434 {
02435 int insn_code_number;
02436 rtx old;
02437
02438 insn_code_number = recog_memoized (insn);
02439
02440 if (insn_code_number < 0)
02441 continue;
02442
02443
02444
02445 if (insn_code_number == CODE_FOR_rptb_end)
02446 c4x_rptb_insert(insn);
02447
02448
02449
02450 old = insn;
02451
02452
02453 if (! INSN_DELETED_P (old))
02454 insn = try_split (PATTERN(old), old, 1);
02455
02456
02457
02458
02459 if (INSN_DELETED_P (old))
02460 {
02461 PUT_CODE (old, NOTE);
02462 NOTE_LINE_NUMBER (old) = NOTE_INSN_DELETED;
02463 NOTE_SOURCE_FILE (old) = 0;
02464 }
02465 }
02466 }
02467 }
02468
02469
02470 static int
02471 c4x_a_register (rtx op)
02472 {
02473 return REG_P (op) && IS_ADDR_OR_PSEUDO_REG (op);
02474 }
02475
02476
02477 static int
02478 c4x_x_register (rtx op)
02479 {
02480 return REG_P (op) && IS_INDEX_OR_PSEUDO_REG (op);
02481 }
02482
02483
02484 static int
02485 c4x_immed_int_constant (rtx op)
02486 {
02487 if (GET_CODE (op) != CONST_INT)
02488 return 0;
02489
02490 return GET_MODE (op) == VOIDmode
02491 || GET_MODE_CLASS (GET_MODE (op)) == MODE_INT
02492 || GET_MODE_CLASS (GET_MODE (op)) == MODE_PARTIAL_INT;
02493 }
02494
02495
02496 static int
02497 c4x_immed_float_constant (rtx op)
02498 {
02499 if (GET_CODE (op) != CONST_DOUBLE)
02500 return 0;
02501
02502
02503
02504
02505
02506 return GET_MODE (op) == QFmode || GET_MODE (op) == HFmode;
02507 }
02508
02509
02510 int
02511 c4x_shiftable_constant (rtx op)
02512 {
02513 int i;
02514 int mask;
02515 int val = INTVAL (op);
02516
02517 for (i = 0; i < 16; i++)
02518 {
02519 if (val & (1 << i))
02520 break;
02521 }
02522 mask = ((0xffff >> i) << 16) | 0xffff;
02523 if (IS_INT16_CONST (val & (1 << 31) ? (val >> i) | ~mask
02524 : (val >> i) & mask))
02525 return i;
02526 return -1;
02527 }
02528
02529
02530 int
02531 c4x_H_constant (rtx op)
02532 {
02533 return c4x_immed_float_constant (op) && c4x_immed_float_p (op);
02534 }
02535
02536
02537 int
02538 c4x_I_constant (rtx op)
02539 {
02540 return c4x_immed_int_constant (op) && IS_INT16_CONST (INTVAL (op));
02541 }
02542
02543
02544 int
02545 c4x_J_constant (rtx op)
02546 {
02547 if (TARGET_C3X)
02548 return 0;
02549 return c4x_immed_int_constant (op) && IS_INT8_CONST (INTVAL (op));
02550 }
02551
02552
02553 static int
02554 c4x_K_constant (rtx op)
02555 {
02556 if (TARGET_C3X || ! c4x_immed_int_constant (op))
02557 return 0;
02558 return IS_INT5_CONST (INTVAL (op));
02559 }
02560
02561
02562 int
02563 c4x_L_constant (rtx op)
02564 {
02565 return c4x_immed_int_constant (op) && IS_UINT16_CONST (INTVAL (op));
02566 }
02567
02568
02569 static int
02570 c4x_N_constant (rtx op)
02571 {
02572 return c4x_immed_int_constant (op) && IS_NOT_UINT16_CONST (INTVAL (op));
02573 }
02574
02575
02576 static int
02577 c4x_O_constant (rtx op)
02578 {
02579 return c4x_immed_int_constant (op) && IS_HIGH_CONST (INTVAL (op));
02580 }
02581
02582
02583
02584
02585
02586
02587
02588
02589
02590
02591
02592 int
02593 c4x_Q_constraint (rtx op)
02594 {
02595 enum machine_mode mode = GET_MODE (op);
02596
02597 if (GET_CODE (op) != MEM)
02598 return 0;
02599 op = XEXP (op, 0);
02600 switch (GET_CODE (op))
02601 {
02602 case REG:
02603 return 1;
02604
02605 case PLUS:
02606 {
02607 rtx op0 = XEXP (op, 0);
02608 rtx op1 = XEXP (op, 1);
02609
02610 if (! REG_P (op0))
02611 return 0;
02612
02613 if (REG_P (op1))
02614 return 1;
02615
02616 if (GET_CODE (op1) != CONST_INT)
02617 return 0;
02618
02619
02620 if (mode == HImode || mode == HFmode)
02621 return IS_DISP8_OFF_CONST (INTVAL (op1));
02622
02623 return IS_DISP8_CONST (INTVAL (op1));
02624 }
02625 break;
02626
02627 default:
02628 break;
02629 }
02630 return 0;
02631 }
02632
02633
02634
02635
02636
02637 int
02638 c4x_R_constraint (rtx op)
02639 {
02640 enum machine_mode mode = GET_MODE (op);
02641
02642 if (TARGET_C3X)
02643 return 0;
02644 if (GET_CODE (op) != MEM)
02645 return 0;
02646 op = XEXP (op, 0);
02647 switch (GET_CODE (op))
02648 {
02649 case REG:
02650 return 1;
02651
02652 case PLUS:
02653 {
02654 rtx op0 = XEXP (op, 0);
02655 rtx op1 = XEXP (op, 1);
02656
02657 if (! REG_P (op0))
02658 return 0;
02659
02660 if (GET_CODE (op1) != CONST_INT)
02661 return 0;
02662
02663
02664 if (mode == HImode || mode == HFmode)
02665 return IS_UINT5_CONST (INTVAL (op1) + 1);
02666
02667 return IS_UINT5_CONST (INTVAL (op1));
02668 }
02669 break;
02670
02671 default:
02672 break;
02673 }
02674 return 0;
02675 }
02676
02677
02678 static int
02679 c4x_R_indirect (rtx op)
02680 {
02681 enum machine_mode mode = GET_MODE (op);
02682
02683 if (TARGET_C3X || GET_CODE (op) != MEM)
02684 return 0;
02685
02686 op = XEXP (op, 0);
02687 switch (GET_CODE (op))
02688 {
02689 case REG:
02690 return IS_ADDR_OR_PSEUDO_REG (op);
02691
02692 case PLUS:
02693 {
02694 rtx op0 = XEXP (op, 0);
02695 rtx op1 = XEXP (op, 1);
02696
02697
02698 if (mode == HImode || mode == HFmode)
02699 return IS_ADDR_OR_PSEUDO_REG (op0)
02700 && GET_CODE (op1) == CONST_INT
02701 && IS_UINT5_CONST (INTVAL (op1) + 1);
02702
02703 return REG_P (op0)
02704 && IS_ADDR_OR_PSEUDO_REG (op0)
02705 && GET_CODE (op1) == CONST_INT
02706 && IS_UINT5_CONST (INTVAL (op1));
02707 }
02708 break;
02709
02710 default:
02711 break;
02712 }
02713 return 0;
02714 }
02715
02716
02717
02718
02719
02720
02721
02722 int
02723 c4x_S_constraint (rtx op)
02724 {
02725 enum machine_mode mode = GET_MODE (op);
02726 if (GET_CODE (op) != MEM)
02727 return 0;
02728 op = XEXP (op, 0);
02729 switch (GET_CODE (op))
02730 {
02731 case REG:
02732 return 1;
02733
02734 case PRE_MODIFY:
02735 case POST_MODIFY:
02736 {
02737 rtx op0 = XEXP (op, 0);
02738 rtx op1 = XEXP (op, 1);
02739
02740 if ((GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS)
02741 || (op0 != XEXP (op1, 0)))
02742 return 0;
02743
02744 op0 = XEXP (op1, 0);
02745 op1 = XEXP (op1, 1);
02746 return REG_P (op0) && REG_P (op1);
02747
02748
02749 }
02750 break;
02751
02752 case PLUS:
02753 {
02754 rtx op0 = XEXP (op, 0);
02755 rtx op1 = XEXP (op, 1);
02756
02757 if (!REG_P (op0))
02758 return 0;
02759
02760 if (REG_P (op1))
02761 return 1;
02762
02763 if (GET_CODE (op1) != CONST_INT)
02764 return 0;
02765
02766
02767 if (mode == HImode || mode == HFmode)
02768 return IS_DISP1_OFF_CONST (INTVAL (op1));
02769
02770 return IS_DISP1_CONST (INTVAL (op1));
02771 }
02772 break;
02773
02774 default:
02775 break;
02776 }
02777 return 0;
02778 }
02779
02780
02781 static int
02782 c4x_S_indirect (rtx op)
02783 {
02784 enum machine_mode mode = GET_MODE (op);
02785 if (GET_CODE (op) != MEM)
02786 return 0;
02787
02788 op = XEXP (op, 0);
02789 switch (GET_CODE (op))
02790 {
02791 case PRE_DEC:
02792 case POST_DEC:
02793 if (mode != QImode && mode != QFmode)
02794 return 0;
02795 case PRE_INC:
02796 case POST_INC:
02797 op = XEXP (op, 0);
02798
02799 case REG:
02800 return IS_ADDR_OR_PSEUDO_REG (op);
02801
02802 case PRE_MODIFY:
02803 case POST_MODIFY:
02804 {
02805 rtx op0 = XEXP (op, 0);
02806 rtx op1 = XEXP (op, 1);
02807
02808 if (mode != QImode && mode != QFmode)
02809 return 0;
02810
02811 if ((GET_CODE (op1) != PLUS && GET_CODE (op1) != MINUS)
02812 || (op0 != XEXP (op1, 0)))
02813 return 0;
02814
02815 op0 = XEXP (op1, 0);
02816 op1 = XEXP (op1, 1);
02817 return REG_P (op0) && IS_ADDR_OR_PSEUDO_REG (op0)
02818 && REG_P (op1) && IS_INDEX_OR_PSEUDO_REG (op1);
02819
02820
02821 }
02822
02823 case PLUS:
02824 {
02825 rtx op0 = XEXP (op, 0);
02826 rtx op1 = XEXP (op, 1);
02827
02828 if (REG_P (op0))
02829 {
02830
02831 if (mode == HImode || mode == HFmode)
02832 return IS_ADDR_OR_PSEUDO_REG (op0)
02833 && GET_CODE (op1) == CONST_INT
02834 && IS_DISP1_OFF_CONST (INTVAL (op1));
02835
02836 if (REG_P (op1))
02837 return (IS_INDEX_OR_PSEUDO_REG (op1)
02838 && IS_ADDR_OR_PSEUDO_REG (op0))
02839 || (IS_ADDR_OR_PSEUDO_REG (op1)
02840 && IS_INDEX_OR_PSEUDO_REG (op0));
02841
02842 return IS_ADDR_OR_PSEUDO_REG (op0)
02843 && GET_CODE (op1) == CONST_INT
02844 && IS_DISP1_CONST (INTVAL (op1));
02845 }
02846 }
02847 break;
02848
02849 default:
02850 break;
02851 }
02852 return 0;
02853 }
02854
02855
02856
02857
02858 int
02859 c4x_T_constraint (rtx op)
02860 {
02861 if (GET_CODE (op) != MEM)
02862 return 0;
02863 op = XEXP (op, 0);
02864
02865 if (GET_CODE (op) != LO_SUM)
02866 {
02867
02868 return GET_CODE (op) == SYMBOL_REF
02869 && GET_MODE (op) == Pmode
02870 && SYMBOL_REF_FUNCTION_P (op);
02871 }
02872
02873
02874 if (GET_MODE (op) == HImode || GET_CODE (op) == HFmode)
02875 return 0;
02876
02877 if ((GET_CODE (XEXP (op, 0)) == REG)
02878 && (REGNO (XEXP (op, 0)) == DP_REGNO))
02879 return c4x_U_constraint (XEXP (op, 1));
02880
02881 return 0;
02882 }
02883
02884
02885
02886
02887 int
02888 c4x_U_constraint (rtx op)
02889 {
02890
02891 return GET_CODE (op) == CONST
02892 || GET_CODE (op) == SYMBOL_REF
02893 || GET_CODE (op) == LABEL_REF;
02894 }
02895
02896
02897 int
02898 c4x_autoinc_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02899 {
02900 if (GET_CODE (op) == MEM)
02901 {
02902 enum rtx_code code = GET_CODE (XEXP (op, 0));
02903
02904 if (code == PRE_INC
02905 || code == PRE_DEC
02906 || code == POST_INC
02907 || code == POST_DEC
02908 || code == PRE_MODIFY
02909 || code == POST_MODIFY
02910 )
02911 return 1;
02912 }
02913 return 0;
02914 }
02915
02916
02917
02918
02919 int
02920 any_operand (register rtx op ATTRIBUTE_UNUSED,
02921 enum machine_mode mode ATTRIBUTE_UNUSED)
02922 {
02923 return 1;
02924 }
02925
02926
02927
02928
02929 int
02930 fp_zero_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02931 {
02932 REAL_VALUE_TYPE r;
02933
02934 if (GET_CODE (op) != CONST_DOUBLE)
02935 return 0;
02936 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
02937 return REAL_VALUES_EQUAL (r, dconst0);
02938 }
02939
02940
02941 int
02942 const_operand (register rtx op, register enum machine_mode mode)
02943 {
02944 switch (mode)
02945 {
02946 case QFmode:
02947 case HFmode:
02948 if (GET_CODE (op) != CONST_DOUBLE
02949 || GET_MODE (op) != mode
02950 || GET_MODE_CLASS (mode) != MODE_FLOAT)
02951 return 0;
02952
02953 return c4x_immed_float_p (op);
02954
02955 #if Pmode != QImode
02956 case Pmode:
02957 #endif
02958 case QImode:
02959 if (GET_CODE (op) != CONST_INT
02960 || (GET_MODE (op) != VOIDmode && GET_MODE (op) != mode)
02961 || GET_MODE_CLASS (mode) != MODE_INT)
02962 return 0;
02963
02964 return IS_HIGH_CONST (INTVAL (op)) || IS_INT16_CONST (INTVAL (op));
02965
02966 case HImode:
02967 return 0;
02968
02969 default:
02970 return 0;
02971 }
02972 }
02973
02974
02975 int
02976 stik_const_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02977 {
02978 return c4x_K_constant (op);
02979 }
02980
02981
02982 int
02983 not_const_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02984 {
02985 return c4x_N_constant (op);
02986 }
02987
02988
02989 int
02990 reg_operand (rtx op, enum machine_mode mode)
02991 {
02992 if (GET_CODE (op) == SUBREG
02993 && GET_MODE (op) == QFmode)
02994 return 0;
02995 return register_operand (op, mode);
02996 }
02997
02998
02999 int
03000 mixed_subreg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
03001 {
03002
03003
03004 if (GET_CODE (op) == SUBREG
03005 && (GET_MODE (op) == QFmode)
03006 && (GET_MODE (SUBREG_REG (op)) == QImode
03007 || GET_MODE (SUBREG_REG (op)) == HImode))
03008 return 1;
03009 return 0;
03010 }
03011
03012
03013 int
03014 reg_imm_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
03015 {
03016 if (REG_P (op) || CONSTANT_P (op))
03017 return 1;
03018 return 0;
03019 }
03020
03021
03022 int
03023 not_modify_reg (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
03024 {
03025 if (REG_P (op) || CONSTANT_P (op))
03026 return 1;
03027 if (GET_CODE (op) != MEM)
03028 return 0;
03029 op = XEXP (op, 0);
03030 switch (GET_CODE (op))
03031 {
03032 case REG:
03033 return 1;
03034
03035 case PLUS:
03036 {
03037 rtx op0 = XEXP (op, 0);
03038 rtx op1 = XEXP (op, 1);
03039
03040 if (! REG_P (op0))
03041 return 0;
03042
03043 if (REG_P (op1) || GET_CODE (op1) == CONST_INT)
03044 return 1;
03045 }
03046
03047 case LO_SUM:
03048 {
03049 rtx op0 = XEXP (op, 0);
03050
03051 if (REG_P (op0) && REGNO (op0) == DP_REGNO)
03052 return 1;
03053 }
03054 break;
03055
03056 case CONST:
03057 case SYMBOL_REF:
03058 case LABEL_REF:
03059 return 1;
03060
03061 default:
03062 break;
03063 }
03064 return 0;
03065 }
03066
03067
03068 int
03069 not_rc_reg (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
03070 {
03071 if (REG_P (op) && REGNO (op) == RC_REGNO)
03072 return 0;
03073 return 1;
03074 }
03075
03076
03077
03078
03079 int
03080 r0r1_reg_operand (rtx op, enum machine_mode mode)
03081 {
03082 if (! reg_operand (op, mode))
03083 return 0;
03084 if (GET_CODE (op) == SUBREG)
03085 op = SUBREG_REG (op);
03086 return REG_P (op) && IS_R0R1_OR_PSEUDO_REG (op);
03087 }
03088
03089
03090
03091
03092 int
03093 r2r3_reg_operand (rtx op, enum machine_mode mode)
03094 {
03095 if (! reg_operand (op, mode))
03096 return 0;
03097 if (GET_CODE (op) == SUBREG)
03098 op = SUBREG_REG (op);
03099 return REG_P (op) && IS_R2R3_OR_PSEUDO_REG (op);
03100 }
03101
03102
03103
03104
03105 int
03106 ext_low_reg_operand (rtx op, enum machine_mode mode)
03107 {
03108 if (! reg_operand (op, mode))
03109 return 0;
03110 if (GET_CODE (op) == SUBREG)
03111 op = SUBREG_REG (op);
03112 return REG_P (op) && IS_EXT_LOW_OR_PSEUDO_REG (op);
03113 }
03114
03115
03116
03117
03118 int
03119 ext_reg_operand (rtx op, enum machine_mode mode)
03120 {
03121 if (! reg_operand (op, mode))
03122 return 0;
03123 if (GET_CODE (op) == SUBREG)
03124 op = SUBREG_REG (op);
03125 if (! REG_P (op))
03126 return 0;
03127 return IS_EXT_OR_PSEUDO_REG (op);
03128 }
03129
03130
03131
03132
03133 int
03134 std_reg_operand (rtx op, enum machine_mode mode)
03135 {
03136 if (! reg_operand (op, mode))
03137 return 0;
03138 if (GET_CODE (op) == SUBREG)
03139 op = SUBREG_REG (op);
03140 return REG_P (op) && IS_STD_OR_PSEUDO_REG (op);
03141 }
03142
03143
03144
03145 int
03146 std_or_reg_operand (rtx op, enum machine_mode mode)
03147 {
03148 if (reload_in_progress)
03149 return std_reg_operand (op, mode);
03150 return reg_operand (op, mode);
03151 }
03152
03153
03154
03155 int
03156 addr_reg_operand (rtx op, enum machine_mode mode)
03157 {
03158 if (! reg_operand (op, mode))
03159 return 0;
03160 return c4x_a_register (op);
03161 }
03162
03163
03164
03165
03166 int
03167 index_reg_operand (rtx op, enum machine_mode mode)
03168 {
03169 if (! reg_operand (op, mode))
03170 return 0;
03171 if (GET_CODE (op) == SUBREG)
03172 op = SUBREG_REG (op);
03173 return c4x_x_register (op);
03174 }
03175
03176
03177
03178
03179 int
03180 dp_reg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
03181 {
03182 return REG_P (op) && IS_DP_OR_PSEUDO_REG (op);
03183 }
03184
03185
03186
03187
03188 int
03189 sp_reg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
03190 {
03191 return REG_P (op) && IS_SP_OR_PSEUDO_REG (op);
03192 }
03193
03194
03195
03196
03197 int
03198 st_reg_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
03199 {
03200 return REG_P (op) && IS_ST_OR_PSEUDO_REG (op);
03201 }
03202
03203
03204
03205
03206 int
03207 rc_reg_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
03208 {
03209 return REG_P (op) && IS_RC_OR_PSEUDO_REG (op);
03210 }
03211
03212
03213 int
03214 call_address_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
03215 {
03216 return (REG_P (op) || symbolic_address_operand (op, mode));
03217 }
03218
03219
03220
03221
03222 int
03223 symbolic_address_operand (register rtx op,
03224 enum machine_mode mode ATTRIBUTE_UNUSED)
03225 {
03226 switch (GET_CODE (op))
03227 {
03228 case CONST:
03229 case SYMBOL_REF:
03230 case LABEL_REF:
03231 return 1;
03232 default:
03233 return 0;
03234 }
03235 }
03236
03237
03238
03239
03240 int
03241 dst_operand (rtx op, enum machine_mode mode)
03242 {
03243 if (GET_CODE (op) == SUBREG
03244 && mixed_subreg_operand (op, mode))
03245 return 0;
03246
03247 if (REG_P (op))
03248 return reg_operand (op, mode);
03249
03250 return nonimmediate_operand (op, mode);
03251 }
03252
03253
03254
03255
03256 int
03257 src_operand (rtx op, enum machine_mode mode)
03258 {
03259 if (GET_CODE (op) == SUBREG
03260 && mixed_subreg_operand (op, mode))
03261 return 0;
03262
03263 if (REG_P (op))
03264 return reg_operand (op, mode);
03265
03266 if (mode == VOIDmode)
03267 mode = GET_MODE (op);
03268
03269 if (GET_CODE (op) == CONST_INT)
03270 return (mode == QImode || mode == Pmode || mode == HImode)
03271 && c4x_I_constant (op);
03272
03273
03274 if (GET_CODE (op) == CONST_DOUBLE)
03275 return c4x_H_constant (op);
03276
03277
03278
03279 if (GET_CODE (op) == SYMBOL_REF
03280 || GET_CODE (op) == LABEL_REF
03281 || GET_CODE (op) == CONST)
03282 return 0;
03283
03284
03285
03286
03287
03288 if (GET_CODE (op) == MEM
03289 && ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
03290 || GET_CODE (XEXP (op, 0)) == LABEL_REF
03291 || GET_CODE (XEXP (op, 0)) == CONST)))
03292 return !TARGET_EXPOSE_LDP &&
03293 ! TARGET_LOAD_DIRECT_MEMS && GET_MODE (op) == mode;
03294
03295 return general_operand (op, mode);
03296 }
03297
03298
03299 int
03300 src_hi_operand (rtx op, enum machine_mode mode)
03301 {
03302 if (c4x_O_constant (op))
03303 return 1;
03304 return src_operand (op, mode);
03305 }
03306
03307
03308
03309
03310 int
03311 lsrc_operand (rtx op, enum machine_mode mode)
03312 {
03313 if (mode == VOIDmode)
03314 mode = GET_MODE (op);
03315
03316 if (mode != QImode && mode != Pmode)
03317 fatal_insn ("mode not QImode", op);
03318
03319 if (GET_CODE (op) == CONST_INT)
03320 return c4x_L_constant (op) || c4x_J_constant (op);
03321
03322 return src_operand (op, mode);
03323 }
03324
03325
03326
03327
03328 int
03329 tsrc_operand (rtx op, enum machine_mode mode)
03330 {
03331 if (mode == VOIDmode)
03332 mode = GET_MODE (op);
03333
03334 if (mode != QImode && mode != Pmode)
03335 fatal_insn ("mode not QImode", op);
03336
03337 if (GET_CODE (op) == CONST_INT)
03338 return c4x_L_constant (op) || c4x_N_constant (op) || c4x_J_constant (op);
03339
03340 return src_operand (op, mode);
03341 }
03342
03343
03344
03345
03346 int
03347 nonimmediate_src_operand (rtx op, enum machine_mode mode)
03348 {
03349 if (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE)
03350 return 0;
03351
03352 return src_operand (op, mode);
03353 }
03354
03355
03356
03357
03358 int
03359 nonimmediate_lsrc_operand (rtx op, enum machine_mode mode)
03360 {
03361 if (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE)
03362 return 0;
03363
03364 return lsrc_operand (op, mode);
03365 }
03366
03367
03368 int
03369 reg_or_const_operand (rtx op, enum machine_mode mode)
03370 {
03371 return reg_operand (op, mode) || const_operand (op, mode);
03372 }
03373
03374
03375
03376
03377 int
03378 par_ind_operand (rtx op, enum machine_mode mode)
03379 {
03380 if (mode != VOIDmode && mode != GET_MODE (op))
03381 return 0;
03382
03383 return c4x_S_indirect (op);
03384 }
03385
03386
03387
03388
03389 int
03390 parallel_operand (rtx op, enum machine_mode mode)
03391 {
03392 return ext_low_reg_operand (op, mode) || par_ind_operand (op, mode);
03393 }
03394
03395
03396 static void
03397 c4x_S_address_parse (rtx op, int *base, int *incdec, int *index, int *disp)
03398 {
03399 *base = 0;
03400 *incdec = 0;
03401 *index = 0;
03402 *disp = 0;
03403
03404 if (GET_CODE (op) != MEM)
03405 fatal_insn ("invalid indirect memory address", op);
03406
03407 op = XEXP (op, 0);
03408 switch (GET_CODE (op))
03409 {
03410 case PRE_DEC:
03411 *base = REGNO (XEXP (op, 0));
03412 *incdec = 1;
03413 *disp = -1;
03414 return;
03415
03416 case POST_DEC:
03417 *base = REGNO (XEXP (op, 0));
03418 *incdec = 1;
03419 *disp = 0;
03420 return;
03421
03422 case PRE_INC:
03423 *base = REGNO (XEXP (op, 0));
03424 *incdec = 1;
03425 *disp = 1;
03426 return;
03427
03428 case POST_INC:
03429 *base = REGNO (XEXP (op, 0));
03430 *incdec = 1;
03431 *disp = 0;
03432 return;
03433
03434 case POST_MODIFY:
03435 *base = REGNO (XEXP (op, 0));
03436 if (REG_P (XEXP (XEXP (op, 1), 1)))
03437 {
03438 *index = REGNO (XEXP (XEXP (op, 1), 1));
03439 *disp = 0;
03440 }
03441 else
03442 *disp = INTVAL (XEXP (XEXP (op, 1), 1));
03443 *incdec = 1;
03444 return;
03445
03446 case PRE_MODIFY:
03447 *base = REGNO (XEXP (op, 0));
03448 if (REG_P (XEXP (XEXP (op, 1), 1)))
03449 {
03450 *index = REGNO (XEXP (XEXP (op, 1), 1));
03451 *disp = 1;
03452 }
03453 else
03454 *disp = INTVAL (XEXP (XEXP (op, 1), 1));
03455 *incdec = 1;
03456
03457 return;
03458
03459 case REG:
03460 *base = REGNO (op);
03461 return;
03462
03463 case PLUS:
03464 {
03465 rtx op0 = XEXP (op, 0);
03466 rtx op1 = XEXP (op, 1);
03467
03468 if (c4x_a_register (op0))
03469 {
03470 if (c4x_x_register (op1))
03471 {
03472 *base = REGNO (op0);
03473 *index = REGNO (op1);
03474 return;
03475 }
03476 else if ((GET_CODE (op1) == CONST_INT
03477 && IS_DISP1_CONST (INTVAL (op1))))
03478 {
03479 *base = REGNO (op0);
03480 *disp = INTVAL (op1);
03481 return;
03482 }
03483 }
03484 else if (c4x_x_register (op0) && c4x_a_register (op1))
03485 {
03486 *base = REGNO (op1);
03487 *index = REGNO (op0);
03488 return;
03489 }
03490 }
03491
03492
03493 default:
03494 fatal_insn ("invalid indirect (S) memory address", op);
03495 }
03496 }
03497
03498
03499 int
03500 c4x_address_conflict (rtx op0, rtx op1, int store0, int store1)
03501 {
03502 int base0;
03503 int base1;
03504 int incdec0;
03505 int incdec1;
03506 int index0;
03507 int index1;
03508 int disp0;
03509 int disp1;
03510
03511 if (MEM_VOLATILE_P (op0) && MEM_VOLATILE_P (op1))
03512 return 1;
03513
03514 c4x_S_address_parse (op0, &base0, &incdec0, &index0, &disp0);
03515 c4x_S_address_parse (op1, &base1, &incdec1, &index1, &disp1);
03516
03517 if (store0 && store1)
03518 {
03519
03520
03521
03522
03523
03524
03525
03526
03527
03528 if (! flag_argument_noalias)
03529 {
03530 if (MEM_VOLATILE_P (op0) || MEM_VOLATILE_P (op1))
03531 return 1;
03532 }
03533 }
03534
03535
03536
03537
03538
03539
03540
03541 if (base0 == base1 && incdec0 && incdec0)
03542 return 1;
03543
03544
03545
03546
03547 if (! TARGET_DEVEL && base0 == base1 && (incdec0 || incdec1))
03548 return 1;
03549
03550
03551
03552 if (base0 == base1 && disp0 == disp1 && index0 == index1)
03553 return 1;
03554
03555
03556 return 0;
03557 }
03558
03559
03560
03561
03562 int
03563 c4x_label_conflict (rtx insn, rtx jump, rtx db)
03564 {
03565 while (insn)
03566 {
03567 if (GET_CODE (insn) == CODE_LABEL)
03568 {
03569 if (CODE_LABEL_NUMBER (jump) == CODE_LABEL_NUMBER (insn))
03570 return 1;
03571 if (CODE_LABEL_NUMBER (db) == CODE_LABEL_NUMBER (insn))
03572 return 0;
03573 }
03574 insn = PREV_INSN (insn);
03575 }
03576 return 1;
03577 }
03578
03579
03580
03581
03582 int
03583 valid_parallel_load_store (rtx *operands,
03584 enum machine_mode mode ATTRIBUTE_UNUSED)
03585 {
03586 rtx op0 = operands[0];
03587 rtx op1 = operands[1];
03588 rtx op2 = operands[2];
03589 rtx op3 = operands[3];
03590
03591 if (GET_CODE (op0) == SUBREG)
03592 op0 = SUBREG_REG (op0);
03593 if (GET_CODE (op1) == SUBREG)
03594 op1 = SUBREG_REG (op1);
03595 if (GET_CODE (op2) == SUBREG)
03596 op2 = SUBREG_REG (op2);
03597 if (GET_CODE (op3) == SUBREG)
03598 op3 = SUBREG_REG (op3);
03599
03600
03601
03602
03603
03604
03605
03606
03607 if (GET_CODE (op0) == REG
03608 && ((GET_CODE (op2) == MEM && reg_mentioned_p (op0, XEXP (op2, 0)))
03609 || (GET_CODE (op3) == MEM && reg_mentioned_p (op0, XEXP (op3, 0)))))
03610 return 0;
03611
03612
03613 if (GET_CODE (op0) == REG && GET_CODE (op2) == REG)
03614 return (REGNO (op0) != REGNO (op2))
03615 && GET_CODE (op1) == MEM && GET_CODE (op3) == MEM
03616 && ! c4x_address_conflict (op1, op3, 0, 0);
03617
03618
03619 if (GET_CODE (op1) == REG && GET_CODE (op3) == REG)
03620 return GET_CODE (op0) == MEM && GET_CODE (op2) == MEM
03621 && ! c4x_address_conflict (op0, op2, 1, 1);
03622
03623
03624 if (GET_CODE (op0) == REG && GET_CODE (op3) == REG)
03625 return GET_CODE (op1) == MEM && GET_CODE (op2) == MEM
03626 && ! c4x_address_conflict (op1, op2, 0, 1);
03627
03628
03629 if (GET_CODE (op1) == REG && GET_CODE (op2) == REG)
03630 return GET_CODE (op0) == MEM && GET_CODE (op3) == MEM
03631 && ! c4x_address_conflict (op0, op3, 1, 0);
03632
03633 return 0;
03634 }
03635
03636
03637 int
03638 valid_parallel_operands_4 (rtx *operands,
03639 enum machine_mode mode ATTRIBUTE_UNUSED)
03640 {
03641 rtx op0 = operands[0];
03642 rtx op2 = operands[2];
03643
03644 if (GET_CODE (op0) == SUBREG)
03645 op0 = SUBREG_REG (op0);
03646 if (GET_CODE (op2) == SUBREG)
03647 op2 = SUBREG_REG (op2);
03648
03649
03650
03651
03652 if (GET_CODE (op0) == REG
03653 && GET_CODE (op2) == MEM
03654 && reg_mentioned_p (op0, XEXP (op2, 0)))
03655 return 0;
03656
03657 return 1;
03658 }
03659
03660
03661 int
03662 valid_parallel_operands_5 (rtx *operands,
03663 enum machine_mode mode ATTRIBUTE_UNUSED)
03664 {
03665 int regs = 0;
03666 rtx op0 = operands[0];
03667 rtx op1 = operands[1];
03668 rtx op2 = operands[2];
03669 rtx op3 = operands[3];
03670
03671 if (GET_CODE (op0) == SUBREG)
03672 op0 = SUBREG_REG (op0);
03673 if (GET_CODE (op1) == SUBREG)
03674 op1 = SUBREG_REG (op1);
03675 if (GET_CODE (op2) == SUBREG)
03676 op2 = SUBREG_REG (op2);
03677
03678
03679
03680
03681 if (GET_CODE (op1) == REG)
03682 regs++;
03683 if (GET_CODE (op2) == REG)
03684 regs++;
03685
03686 if (regs != 1)
03687 return 0;
03688
03689
03690
03691
03692 if (GET_CODE (op0) == REG
03693 && GET_CODE (op3) == MEM
03694 && reg_mentioned_p (op0, XEXP (op3, 0)))
03695 return 0;
03696
03697 return 1;
03698 }
03699
03700
03701 int
03702 valid_parallel_operands_6 (rtx *operands,
03703 enum machine_mode mode ATTRIBUTE_UNUSED)
03704 {
03705 int regs = 0;
03706 rtx op0 = operands[0];
03707 rtx op1 = operands[1];
03708 rtx op2 = operands[2];
03709 rtx op4 = operands[4];
03710 rtx op5 = operands[5];
03711
03712 if (GET_CODE (op1) == SUBREG)
03713 op1 = SUBREG_REG (op1);
03714 if (GET_CODE (op2) == SUBREG)
03715 op2 = SUBREG_REG (op2);
03716 if (GET_CODE (op4) == SUBREG)
03717 op4 = SUBREG_REG (op4);
03718 if (GET_CODE (op5) == SUBREG)
03719 op5 = SUBREG_REG (op5);
03720
03721
03722
03723
03724
03725 if (GET_CODE (op1) == REG)
03726 regs++;
03727 if (GET_CODE (op2) == REG)
03728 regs++;
03729 if (GET_CODE (op4) == REG)
03730 regs++;
03731 if (GET_CODE (op5) == REG)
03732 regs++;
03733
03734
03735
03736 if (regs != 2)
03737 return 0;
03738
03739
03740
03741
03742 if (GET_CODE (op0) == REG
03743 && ((GET_CODE (op4) == MEM && reg_mentioned_p (op0, XEXP (op4, 0)))
03744 || (GET_CODE (op5) == MEM && reg_mentioned_p (op0, XEXP (op5, 0)))))
03745 return 0;
03746
03747 return 1;
03748 }
03749
03750
03751
03752
03753
03754
03755
03756 static int
03757 c4x_valid_operands (enum rtx_code code, rtx *operands,
03758 enum machine_mode mode ATTRIBUTE_UNUSED,
03759 int force)
03760 {
03761 rtx op0;
03762 rtx op1;
03763 rtx op2;
03764 enum rtx_code code1;
03765 enum rtx_code code2;
03766
03767
03768
03769 if (code == IF_THEN_ELSE)
03770 return 1 || (operands[0] == operands[2] || operands[0] == operands[3]);
03771
03772 if (code == COMPARE)
03773 {
03774 op1 = operands[0];
03775 op2 = operands[1];
03776 }
03777 else
03778 {
03779 op1 = operands[1];
03780 op2 = operands[2];
03781 }
03782
03783 op0 = operands[0];
03784
03785 if (GET_CODE (op0) == SUBREG)
03786 op0 = SUBREG_REG (op0);
03787 if (GET_CODE (op1) == SUBREG)
03788 op1 = SUBREG_REG (op1);
03789 if (GET_CODE (op2) == SUBREG)
03790 op2 = SUBREG_REG (op2);
03791
03792 code1 = GET_CODE (op1);
03793 code2 = GET_CODE (op2);
03794
03795
03796 if (code1 == REG && code2 == REG)
03797 return 1;
03798
03799 if (code1 == MEM && code2 == MEM)
03800 {
03801 if (c4x_S_indirect (op1) && c4x_S_indirect (op2))
03802 return 1;
03803 return c4x_R_indirect (op1) && c4x_R_indirect (op2);
03804 }
03805
03806
03807 if (code1 == code2)
03808 return 0;
03809
03810 if (code1 == REG)
03811 {
03812 switch (code2)
03813 {
03814 case CONST_INT:
03815 if (c4x_J_constant (op2) && c4x_R_indirect (op1))
03816 return 1;
03817 break;
03818
03819 case CONST_DOUBLE:
03820 if (! c4x_H_constant (op2))
03821 return 0;
03822 break;
03823
03824
03825 case MEM:
03826 break;
03827
03828 default:
03829 fatal_insn ("c4x_valid_operands: Internal error", op2);
03830 break;
03831 }
03832
03833 if (GET_CODE (op0) == SCRATCH)
03834 return 1;
03835
03836 if (!REG_P (op0))
03837 return 0;
03838
03839
03840
03841 return ! force || code == COMPARE || REGNO (op1) == REGNO (op0);
03842 }
03843
03844
03845
03846 if (code == ASHIFTRT || code == LSHIFTRT
03847 || code == ASHIFT || code == COMPARE)
03848 return code2 == REG
03849 && (c4x_S_indirect (op1) || c4x_R_indirect (op1));
03850
03851
03852
03853
03854
03855
03856 if (code2 == REG)
03857 {
03858 switch (code1)
03859 {
03860 case CONST_INT:
03861 break;
03862
03863 case CONST_DOUBLE:
03864 if (! c4x_H_constant (op1))
03865 return 0;
03866 break;
03867
03868
03869 case MEM:
03870 break;
03871
03872 default:
03873 abort ();
03874 break;
03875 }
03876
03877 if (GET_CODE (op0) == SCRATCH)
03878 return 1;
03879
03880 if (!REG_P (op0))
03881 return 0;
03882
03883
03884
03885 return ! force || REGNO (op1) == REGNO (op0);
03886 }
03887
03888 if (c4x_J_constant (op1) && c4x_R_indirect (op2))
03889 return 1;
03890
03891 return 0;
03892 }
03893
03894
03895 int valid_operands (enum rtx_code code, rtx *operands, enum machine_mode mode)
03896 {
03897
03898
03899
03900
03901
03902
03903
03904
03905
03906 return ! optimize || c4x_valid_operands (code, operands, mode, 0);
03907 }
03908
03909
03910 int
03911 legitimize_operands (enum rtx_code code, rtx *operands, enum machine_mode mode)
03912 {
03913
03914 if (code == COMPARE)
03915 {
03916
03917
03918
03919
03920
03921
03922
03923
03924
03925
03926
03927
03928
03929
03930 if (! reload_in_progress
03931 && TARGET_HOIST
03932 && optimize > 0
03933 && GET_CODE (operands[1]) == CONST_INT
03934 && rtx_cost (operands[1], code) > 1)
03935 operands[1] = force_reg (mode, operands[1]);
03936
03937 if (! reload_in_progress
03938 && ! c4x_valid_operands (code, operands, mode, 0))
03939 operands[0] = force_reg (mode, operands[0]);
03940 return 1;
03941 }
03942
03943
03944
03945
03946 if (! reload_in_progress
03947 && ! ((code == PLUS || code == MINUS) && mode == Pmode)
03948 && TARGET_HOIST
03949 && optimize > 1
03950 && GET_CODE (operands[2]) == CONST_INT
03951 && rtx_cost (operands[2], code) > 1)
03952 operands[2] = force_reg (mode, operands[2]);
03953
03954
03955
03956
03957
03958
03959
03960
03961
03962
03963
03964 if (! reload_in_progress
03965 && ! c4x_valid_operands (code, operands, mode, TARGET_FORCE))
03966 {
03967
03968
03969
03970 operands[1] = force_reg (mode, operands[1]);
03971 if (TARGET_FORCE)
03972 {
03973 emit_move_insn (operands[0], operands[1]);
03974 operands[1] = copy_rtx (operands[0]);
03975 }
03976 else
03977 {
03978
03979 if (! c4x_valid_operands (code, operands, mode, 0))
03980 operands[2] = force_reg (mode, operands[2]);
03981 }
03982 }
03983
03984
03985
03986 if ((code == ASHIFTRT || code == LSHIFTRT)
03987 && (GET_CODE (operands[2]) != CONST_INT))
03988 operands[2] = gen_rtx_NEG (mode, negate_rtx (mode, operands[2]));
03989
03990
03991
03992
03993
03994
03995 if (((code == ASHIFTRT || code == LSHIFTRT || code == ASHIFT)
03996 && (GET_CODE (operands[2]) == CONST_INT))
03997 && INTVAL (operands[2]) > (GET_MODE_BITSIZE (mode) - 1))
03998 operands[2]
03999 = GEN_INT (INTVAL (operands[2]) & (GET_MODE_BITSIZE (mode) - 1));
04000
04001 return 1;
04002 }
04003
04004
04005
04006
04007 int
04008 group1_reg_operand (rtx op, enum machine_mode mode)
04009 {
04010 if (mode != VOIDmode && mode != GET_MODE (op))
04011 return 0;
04012 if (GET_CODE (op) == SUBREG)
04013 op = SUBREG_REG (op);
04014 return REG_P (op) && (! reload_completed || IS_GROUP1_REG (op));
04015 }
04016
04017
04018 int
04019 group1_mem_operand (rtx op, enum machine_mode mode)
04020 {
04021 if (mode != VOIDmode && mode != GET_MODE (op))
04022 return 0;
04023
04024 if (GET_CODE (op) == MEM)
04025 {
04026 op = XEXP (op, 0);
04027 if (GET_CODE (op) == PLUS)
04028 {
04029 rtx op0 = XEXP (op, 0);
04030 rtx op1 = XEXP (op, 1);
04031
04032 if ((REG_P (op0) && (! reload_completed || IS_GROUP1_REG (op0)))
04033 || (REG_P (op1) && (! reload_completed || IS_GROUP1_REG (op1))))
04034 return 1;
04035 }
04036 else if ((REG_P (op)) && (! reload_completed || IS_GROUP1_REG (op)))
04037 return 1;
04038 }
04039
04040 return 0;
04041 }
04042
04043
04044
04045
04046 int
04047 arx_reg_operand (rtx op, enum machine_mode mode)
04048 {
04049 if (mode != VOIDmode && mode != GET_MODE (op))
04050 return 0;
04051 if (GET_CODE (op) == SUBREG)
04052 op = SUBREG_REG (op);
04053 return REG_P (op) && (! reload_completed || IS_ADDR_REG (op));
04054 }
04055
04056
04057 static int
04058 c4x_arn_reg_operand (rtx op, enum machine_mode mode, unsigned int regno)
04059 {
04060 if (mode != VOIDmode && mode != GET_MODE (op))
04061 return 0;
04062 if (GET_CODE (op) == SUBREG)
04063 op = SUBREG_REG (op);
04064 return REG_P (op) && (! reload_completed || (REGNO (op) == regno));
04065 }
04066
04067
04068 static int
04069 c4x_arn_mem_operand (rtx op, enum machine_mode mode, unsigned int regno)
04070 {
04071 if (mode != VOIDmode && mode != GET_MODE (op))
04072 return 0;
04073
04074 if (GET_CODE (op) == MEM)
04075 {
04076 op = XEXP (op, 0);
04077 switch (GET_CODE (op))
04078 {
04079 case PRE_DEC:
04080 case POST_DEC:
04081 case PRE_INC:
04082 case POST_INC:
04083 op = XEXP (op, 0);
04084
04085 case REG:
04086 return REG_P (op) && (! reload_completed || (REGNO (op) == regno));
04087
04088 case PRE_MODIFY:
04089 case POST_MODIFY:
04090 if (REG_P (XEXP (op, 0)) && (! reload_completed
04091 || (REGNO (XEXP (op, 0)) == regno)))
04092 return 1;
04093 if (REG_P (XEXP (XEXP (op, 1), 1))
04094 && (! reload_completed
04095 || (REGNO (XEXP (XEXP (op, 1), 1)) == regno)))
04096 return 1;
04097 break;
04098
04099 case PLUS:
04100 {
04101 rtx op0 = XEXP (op, 0);
04102 rtx op1 = XEXP (op, 1);
04103
04104 if ((REG_P (op0) && (! reload_completed
04105 || (REGNO (op0) == regno)))
04106 || (REG_P (op1) && (! reload_completed
04107 || (REGNO (op1) == regno))))
04108 return 1;
04109 }
04110 break;
04111
04112 default:
04113 break;
04114 }
04115 }
04116 return 0;
04117 }
04118
04119
04120 int
04121 ar0_reg_operand (rtx op, enum machine_mode mode)
04122 {
04123 return c4x_arn_reg_operand (op, mode, AR0_REGNO);
04124 }
04125
04126
04127 int
04128 ar0_mem_operand (rtx op, enum machine_mode mode)
04129 {
04130 return c4x_arn_mem_operand (op, mode, AR0_REGNO);
04131 }
04132
04133
04134 int
04135 ar1_reg_operand (rtx op, enum machine_mode mode)
04136 {
04137 return c4x_arn_reg_operand (op, mode, AR1_REGNO);
04138 }
04139
04140
04141 int
04142 ar1_mem_operand (rtx op, enum machine_mode mode)
04143 {
04144 return c4x_arn_mem_operand (op, mode, AR1_REGNO);
04145 }
04146
04147
04148 int
04149 ar2_reg_operand (rtx op, enum machine_mode mode)
04150 {
04151 return c4x_arn_reg_operand (op, mode, AR2_REGNO);
04152 }
04153
04154
04155 int
04156 ar2_mem_operand (rtx op, enum machine_mode mode)
04157 {
04158 return c4x_arn_mem_operand (op, mode, AR2_REGNO);
04159 }
04160
04161
04162 int
04163 ar3_reg_operand (rtx op, enum machine_mode mode)
04164 {
04165 return c4x_arn_reg_operand (op, mode, AR3_REGNO);
04166 }
04167
04168
04169 int
04170 ar3_mem_operand (rtx op, enum machine_mode mode)
04171 {
04172 return c4x_arn_mem_operand (op, mode, AR3_REGNO);
04173 }
04174
04175
04176 int
04177 ar4_reg_operand (rtx op, enum machine_mode mode)
04178 {
04179 return c4x_arn_reg_operand (op, mode, AR4_REGNO);
04180 }
04181
04182
04183 int
04184 ar4_mem_operand (rtx op, enum machine_mode mode)
04185 {
04186 return c4x_arn_mem_operand (op, mode, AR4_REGNO);
04187 }
04188
04189
04190 int
04191 ar5_reg_operand (rtx op, enum machine_mode mode)
04192 {
04193 return c4x_arn_reg_operand (op, mode, AR5_REGNO);
04194 }
04195
04196
04197 int
04198 ar5_mem_operand (rtx op, enum machine_mode mode)
04199 {
04200 return c4x_arn_mem_operand (op, mode, AR5_REGNO);
04201 }
04202
04203
04204 int
04205 ar6_reg_operand (rtx op, enum machine_mode mode)
04206 {
04207 return c4x_arn_reg_operand (op, mode, AR6_REGNO);
04208 }
04209
04210
04211 int
04212 ar6_mem_operand (rtx op, enum machine_mode mode)
04213 {
04214 return c4x_arn_mem_operand (op, mode, AR6_REGNO);
04215 }
04216
04217
04218 int
04219 ar7_reg_operand (rtx op, enum machine_mode mode)
04220 {
04221 return c4x_arn_reg_operand (op, mode, AR7_REGNO);
04222 }
04223
04224
04225 int
04226 ar7_mem_operand (rtx op, enum machine_mode mode)
04227 {
04228 return c4x_arn_mem_operand (op, mode, AR7_REGNO);
04229 }
04230
04231
04232 int
04233 ir0_reg_operand (rtx op, enum machine_mode mode)
04234 {
04235 return c4x_arn_reg_operand (op, mode, IR0_REGNO);
04236 }
04237
04238
04239 int
04240 ir0_mem_operand (rtx op, enum machine_mode mode)
04241 {
04242 return c4x_arn_mem_operand (op, mode, IR0_REGNO);
04243 }
04244
04245
04246 int
04247 ir1_reg_operand (rtx op, enum machine_mode mode)
04248 {
04249 return c4x_arn_reg_operand (op, mode, IR1_REGNO);
04250 }
04251
04252
04253 int
04254 ir1_mem_operand (rtx op, enum machine_mode mode)
04255 {
04256 return c4x_arn_mem_operand (op, mode, IR1_REGNO);
04257 }
04258
04259
04260
04261
04262
04263 rtx
04264 c4x_operand_subword (rtx op, int i, int validate_address,
04265 enum machine_mode mode)
04266 {
04267 if (mode != HImode && mode != HFmode)
04268 fatal_insn ("c4x_operand_subword: invalid mode", op);
04269
04270 if (mode == HFmode && REG_P (op))
04271 fatal_insn ("c4x_operand_subword: invalid operand", op);
04272
04273 if (GET_CODE (op) == MEM)
04274 {
04275 enum rtx_code code = GET_CODE (XEXP (op, 0));
04276 enum machine_mode mode = GET_MODE (XEXP (op, 0));
04277 enum machine_mode submode;
04278
04279 submode = mode;
04280 if (mode == HImode)
04281 submode = QImode;
04282 else if (mode == HFmode)
04283 submode = QFmode;
04284
04285 switch (code)
04286 {
04287 case POST_INC:
04288 case PRE_INC:
04289 return gen_rtx_MEM (submode, XEXP (op, 0));
04290
04291 case POST_DEC:
04292 case PRE_DEC:
04293 case PRE_MODIFY:
04294 case POST_MODIFY:
04295
04296
04297 fatal_insn ("c4x_operand_subword: invalid autoincrement", op);
04298
04299 case SYMBOL_REF:
04300 case LABEL_REF:
04301 case CONST:
04302 case CONST_INT:
04303 fatal_insn ("c4x_operand_subword: invalid address", op);
04304
04305
04306
04307
04308
04309
04310
04311
04312
04313 case LO_SUM:
04314 fatal_insn ("c4x_operand_subword: address not offsettable", op);
04315
04316 default:
04317 break;
04318 }
04319 }
04320
04321 return operand_subword (op, i, validate_address, mode);
04322 }
04323
04324 struct name_list
04325 {
04326 struct name_list *next;
04327 const char *name;
04328 };
04329
04330 static struct name_list *global_head;
04331 static struct name_list *extern_head;
04332
04333
04334
04335
04336
04337 void
04338 c4x_global_label (const char *name)
04339 {
04340 struct name_list *p, *last;
04341
04342
04343
04344 p = global_head;
04345 while (p)
04346 {
04347 if (strcmp (p->name, name) == 0)
04348 return;
04349 p = p->next;
04350 }
04351 p = (struct name_list *) xmalloc (sizeof *p);
04352 p->next = global_head;
04353 p->name = name;
04354 global_head = p;
04355
04356
04357 last = NULL;
04358 p = extern_head;
04359 while (p)
04360 {
04361 if (strcmp (p->name, name) == 0)
04362 {
04363 if (last)
04364 last->next = p->next;
04365 else
04366 extern_head = p->next;
04367 break;
04368 }
04369 last = p;
04370 p = p->next;
04371 }
04372 }
04373
04374
04375
04376
04377 void
04378 c4x_external_ref (const char *name)
04379 {
04380 struct name_list *p;
04381
04382
04383 p = extern_head;
04384 while (p)
04385 {
04386 if (strcmp (p->name, name) == 0)
04387 return;
04388 p = p->next;
04389 }
04390
04391
04392 p = global_head;
04393 while (p)
04394 {
04395 if (strcmp (p->name, name) == 0)
04396 return;
04397 p = p->next;
04398 }
04399 p = (struct name_list *) xmalloc (sizeof *p);
04400 p->next = extern_head;
04401 p->name = name;
04402 extern_head = p;
04403 }
04404
04405
04406
04407
04408
04409 static void
04410 c4x_file_start (void)
04411 {
04412 int dspversion = 0;
04413 if (TARGET_C30) dspversion = 30;
04414 if (TARGET_C31) dspversion = 31;
04415 if (TARGET_C32) dspversion = 32;
04416 if (TARGET_C33) dspversion = 33;
04417 if (TARGET_C40) dspversion = 40;
04418 if (TARGET_C44) dspversion = 44;
04419
04420 default_file_start ();
04421 fprintf (asm_out_file, "\t.version\t%d\n", dspversion);
04422 fputs ("\n\t.data\ndata_sec:\n", asm_out_file);
04423 }
04424
04425
04426 static void
04427 c4x_file_end (void)
04428 {
04429 struct name_list *p;
04430
04431
04432 p = extern_head;
04433 while (p)
04434 {
04435 fprintf (asm_out_file, "\t.ref\t");
04436 assemble_name (asm_out_file, p->name);
04437 fprintf (asm_out_file, "\n");
04438 p = p->next;
04439 }
04440 fprintf (asm_out_file, "\t.end\n");
04441 }
04442
04443
04444 static void
04445 c4x_check_attribute (const char *attrib, tree list, tree decl, tree *attributes)
04446 {
04447 while (list != NULL_TREE
04448 && IDENTIFIER_POINTER (TREE_PURPOSE (list))
04449 != IDENTIFIER_POINTER (DECL_NAME (decl)))
04450 list = TREE_CHAIN (list);
04451 if (list)
04452 *attributes = tree_cons (get_identifier (attrib), TREE_VALUE (list),
04453 *attributes);
04454 }
04455
04456
04457 static void
04458 c4x_insert_attributes (tree decl, tree *attributes)
04459 {
04460 switch (TREE_CODE (decl))
04461 {
04462 case FUNCTION_DECL:
04463 c4x_check_attribute ("section", code_tree, decl, attributes);
04464 c4x_check_attribute ("const", pure_tree, decl, attributes);
04465 c4x_check_attribute ("noreturn", noreturn_tree, decl, attributes);
04466 c4x_check_attribute ("interrupt", interrupt_tree, decl, attributes);
04467 c4x_check_attribute ("naked", naked_tree, decl, attributes);
04468 break;
04469
04470 case VAR_DECL:
04471 c4x_check_attribute ("section", data_tree, decl, attributes);
04472 break;
04473
04474 default:
04475 break;
04476 }
04477 }
04478
04479
04480 const struct attribute_spec c4x_attribute_table[] =
04481 {
04482
04483 { "interrupt", 0, 0, false, true, true, c4x_handle_fntype_attribute },
04484 { "naked", 0, 0, false, true, true, c4x_handle_fntype_attribute },
04485 { "leaf_pretend", 0, 0, false, true, true, c4x_handle_fntype_attribute },
04486 { NULL, 0, 0, false, false, false, NULL }
04487 };
04488
04489
04490
04491 static tree
04492 c4x_handle_fntype_attribute (tree *node, tree name,
04493 tree args ATTRIBUTE_UNUSED,
04494 int flags ATTRIBUTE_UNUSED,
04495 bool *no_add_attrs)
04496 {
04497 if (TREE_CODE (*node) != FUNCTION_TYPE)
04498 {
04499 warning ("%qs attribute only applies to functions",
04500 IDENTIFIER_POINTER (name));
04501 *no_add_attrs = true;
04502 }
04503
04504 return NULL_TREE;
04505 }
04506
04507
04508
04509
04510 int
04511 c4x_rptb_rpts_p (rtx insn, rtx op)
04512 {
04513
04514
04515 insn = NEXT_INSN (insn);
04516 if (GET_CODE (insn) != CODE_LABEL)
04517 {
04518
04519
04520
04521
04522
04523 if (TARGET_DEBUG)
04524 fatal_insn("c4x_rptb_rpts_p: Repeat block top label moved\n",
04525 insn);
04526 return 0;
04527 }
04528
04529
04530 insn = next_nonnote_insn (insn);
04531
04532
04533 if (! INSN_P (insn))
04534 return 0;
04535
04536
04537 insn = next_nonnote_insn (insn);
04538
04539 if (! INSN_P (insn))
04540 return 0;
04541
04542 if (recog_memoized (insn) != CODE_FOR_rptb_end)
04543 return 0;
04544
04545 if (TARGET_RPTS)
04546 return 1;
04547
04548 return (GET_CODE (op) == CONST_INT) && TARGET_RPTS_CYCLES (INTVAL (op));
04549 }
04550
04551
04552
04553
04554 static int
04555 c4x_r11_set_p(rtx x)
04556 {
04557 rtx set;
04558 int i, j;
04559 const char *fmt;
04560
04561 if (x == 0)
04562 return 0;
04563
04564 if (INSN_P (x) && GET_CODE (PATTERN (x)) == SEQUENCE)
04565 x = XVECEXP (PATTERN (x), 0, XVECLEN (PATTERN (x), 0) - 1);
04566
04567 if (INSN_P (x) && (set = single_set (x)))
04568 x = SET_DEST (set);
04569
04570 if (GET_CODE (x) == REG && REGNO (x) == R11_REGNO)
04571 return 1;
04572
04573 fmt = GET_RTX_FORMAT (GET_CODE (x));
04574 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
04575 {
04576 if (fmt[i] == 'e')
04577 {
04578 if (c4x_r11_set_p (XEXP (x, i)))
04579 return 1;
04580 }
04581 else if (fmt[i] == 'E')
04582 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
04583 if (c4x_r11_set_p (XVECEXP (x, i, j)))
04584 return 1;
04585 }
04586 return 0;
04587 }
04588
04589
04590
04591
04592
04593 int
04594 c4x_check_laj_p (rtx insn)
04595 {
04596 insn = prev_nonnote_insn (insn);
04597
04598
04599 if (insn == 0)
04600 return 0;
04601
04602
04603
04604
04605 if (GET_CODE (insn) == CODE_LABEL)
04606 return 1;
04607
04608
04609 if (c4x_r11_set_p (insn))
04610 return 1;
04611
04612
04613 return 0;
04614 }
04615
04616
04617
04618
04619
04620
04621
04622
04623 #define SET_USE_COST 3
04624 #define SETLDA_USE_COST 2
04625 #define READ_USE_COST 2
04626
04627 static int
04628 c4x_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
04629 {
04630
04631
04632 if (flag_schedule_insns == 0 && ! reload_completed)
04633 return 0;
04634
04635
04636
04637
04638
04639
04640
04641
04642
04643 if (recog_memoized (dep_insn) < 0)
04644 return 0;
04645
04646 if (REG_NOTE_KIND (link) == 0)
04647 {
04648 int max = 0;
04649
04650
04651
04652 if (TARGET_C3X)
04653 {
04654 if (get_attr_setgroup1 (dep_insn) && get_attr_usegroup1 (insn))
04655 max = SET_USE_COST > max ? SET_USE_COST : max;
04656 if (get_attr_readarx (dep_insn) && get_attr_usegroup1 (insn))
04657 max = READ_USE_COST > max ? READ_USE_COST : max;
04658 }
04659 else
04660 {
04661
04662
04663
04664
04665
04666 if (get_attr_setar0 (dep_insn) && get_attr_usear0 (insn))
04667 max = SET_USE_COST > max ? SET_USE_COST : max;
04668 if (get_attr_setlda_ar0 (dep_insn) && get_attr_usear0 (insn))
04669 max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
04670 if (get_attr_readar0 (dep_insn) && get_attr_usear0 (insn))
04671 max = READ_USE_COST > max ? READ_USE_COST : max;
04672
04673 if (get_attr_setar1 (dep_insn) && get_attr_usear1 (insn))
04674 max = SET_USE_COST > max ? SET_USE_COST : max;
04675 if (get_attr_setlda_ar1 (dep_insn) && get_attr_usear1 (insn))
04676 max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
04677 if (get_attr_readar1 (dep_insn) && get_attr_usear1 (insn))
04678 max = READ_USE_COST > max ? READ_USE_COST : max;
04679
04680 if (get_attr_setar2 (dep_insn) && get_attr_usear2 (insn))
04681 max = SET_USE_COST > max ? SET_USE_COST : max;
04682 if (get_attr_setlda_ar2 (dep_insn) && get_attr_usear2 (insn))
04683 max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
04684 if (get_attr_readar2 (dep_insn) && get_attr_usear2 (insn))
04685 max = READ_USE_COST > max ? READ_USE_COST : max;
04686
04687 if (get_attr_setar3 (dep_insn) && get_attr_usear3 (insn))
04688 max = SET_USE_COST > max ? SET_USE_COST : max;
04689 if (get_attr_setlda_ar3 (dep_insn) && get_attr_usear3 (insn))
04690 max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
04691 if (get_attr_readar3 (dep_insn) && get_attr_usear3 (insn))
04692 max = READ_USE_COST > max ? READ_USE_COST : max;
04693
04694 if (get_attr_setar4 (dep_insn) && get_attr_usear4 (insn))
04695 max = SET_USE_COST > max ? SET_USE_COST : max;
04696 if (get_attr_setlda_ar4 (dep_insn) && get_attr_usear4 (insn))
04697 max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
04698 if (get_attr_readar4 (dep_insn) && get_attr_usear4 (insn))
04699 max = READ_USE_COST > max ? READ_USE_COST : max;
04700
04701 if (get_attr_setar5 (dep_insn) && get_attr_usear5 (insn))
04702 max = SET_USE_COST > max ? SET_USE_COST : max;
04703 if (get_attr_setlda_ar5 (dep_insn) && get_attr_usear5 (insn))
04704 max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
04705 if (get_attr_readar5 (dep_insn) && get_attr_usear5 (insn))
04706 max = READ_USE_COST > max ? READ_USE_COST : max;
04707
04708 if (get_attr_setar6 (dep_insn) && get_attr_usear6 (insn))
04709 max = SET_USE_COST > max ? SET_USE_COST : max;
04710 if (get_attr_setlda_ar6 (dep_insn) && get_attr_usear6 (insn))
04711 max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
04712 if (get_attr_readar6 (dep_insn) && get_attr_usear6 (insn))
04713 max = READ_USE_COST > max ? READ_USE_COST : max;
04714
04715 if (get_attr_setar7 (dep_insn) && get_attr_usear7 (insn))
04716 max = SET_USE_COST > max ? SET_USE_COST : max;
04717 if (get_attr_setlda_ar7 (dep_insn) && get_attr_usear7 (insn))
04718 max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
04719 if (get_attr_readar7 (dep_insn) && get_attr_usear7 (insn))
04720 max = READ_USE_COST > max ? READ_USE_COST : max;
04721
04722 if (get_attr_setir0 (dep_insn) && get_attr_useir0 (insn))
04723 max = SET_USE_COST > max ? SET_USE_COST : max;
04724 if (get_attr_setlda_ir0 (dep_insn) && get_attr_useir0 (insn))
04725 max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
04726
04727 if (get_attr_setir1 (dep_insn) && get_attr_useir1 (insn))
04728 max = SET_USE_COST > max ? SET_USE_COST : max;
04729 if (get_attr_setlda_ir1 (dep_insn) && get_attr_useir1 (insn))
04730 max = SETLDA_USE_COST > max ? SETLDA_USE_COST : max;
04731 }
04732
04733 if (max)
04734 cost = max;
04735
04736
04737
04738 return cost;
04739 }
04740 else if (REG_NOTE_KIND (link) == REG_DEP_ANTI)
04741 {
04742
04743
04744
04745
04746 return 0;
04747 }
04748 else if (REG_NOTE_KIND (link) == REG_DEP_OUTPUT)
04749 {
04750
04751
04752
04753
04754 return 0;
04755 }
04756 else
04757 abort ();
04758 }
04759
04760 void
04761 c4x_init_builtins (void)
04762 {
04763 tree endlink = void_list_node;
04764
04765 lang_hooks.builtin_function ("fast_ftoi",
04766 build_function_type
04767 (integer_type_node,
04768 tree_cons (NULL_TREE, double_type_node,
04769 endlink)),
04770 C4X_BUILTIN_FIX, BUILT_IN_MD, NULL, NULL_TREE);
04771 lang_hooks.builtin_function ("ansi_ftoi",
04772 build_function_type
04773 (integer_type_node,
04774 tree_cons (NULL_TREE, double_type_node,
04775 endlink)),
04776 C4X_BUILTIN_FIX_ANSI, BUILT_IN_MD, NULL,
04777 NULL_TREE);
04778 if (TARGET_C3X)
04779 lang_hooks.builtin_function ("fast_imult",
04780 build_function_type
04781 (integer_type_node,
04782 tree_cons (NULL_TREE, integer_type_node,
04783 tree_cons (NULL_TREE,
04784 integer_type_node,
04785 endlink))),
04786 C4X_BUILTIN_MPYI, BUILT_IN_MD, NULL,
04787 NULL_TREE);
04788 else
04789 {
04790 lang_hooks.builtin_function ("toieee",
04791 build_function_type
04792 (double_type_node,
04793 tree_cons (NULL_TREE, double_type_node,
04794 endlink)),
04795 C4X_BUILTIN_TOIEEE, BUILT_IN_MD, NULL,
04796 NULL_TREE);
04797 lang_hooks.builtin_function ("frieee",
04798 build_function_type
04799 (double_type_node,
04800 tree_cons (NULL_TREE, double_type_node,
04801 endlink)),
04802 C4X_BUILTIN_FRIEEE, BUILT_IN_MD, NULL,
04803 NULL_TREE);
04804 lang_hooks.builtin_function ("fast_invf",
04805 build_function_type
04806 (double_type_node,
04807 tree_cons (NULL_TREE, double_type_node,
04808 endlink)),
04809 C4X_BUILTIN_RCPF, BUILT_IN_MD, NULL,
04810 NULL_TREE);
04811 }
04812 }
04813
04814
04815 rtx
04816 c4x_expand_builtin (tree exp, rtx target,
04817 rtx subtarget ATTRIBUTE_UNUSED,
04818 enum machine_mode mode ATTRIBUTE_UNUSED,
04819 int ignore ATTRIBUTE_UNUSED)
04820 {
04821 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
04822 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
04823 tree arglist = TREE_OPERAND (exp, 1);
04824 tree arg0, arg1;
04825 rtx r0, r1;
04826
04827 switch (fcode)
04828 {
04829 case C4X_BUILTIN_FIX:
04830 arg0 = TREE_VALUE (arglist);
04831 r0 = expand_expr (arg0, NULL_RTX, QFmode, 0);
04832 if (! target || ! register_operand (target, QImode))
04833 target = gen_reg_rtx (QImode);
04834 emit_insn (gen_fixqfqi_clobber (target, r0));
04835 return target;
04836
04837 case C4X_BUILTIN_FIX_ANSI:
04838 arg0 = TREE_VALUE (arglist);
04839 r0 = expand_expr (arg0, NULL_RTX, QFmode, 0);
04840 if (! target || ! register_operand (target, QImode))
04841 target = gen_reg_rtx (QImode);
04842 emit_insn (gen_fix_truncqfqi2 (target, r0));
04843 return target;
04844
04845 case C4X_BUILTIN_MPYI:
04846 if (! TARGET_C3X)
04847 break;
04848 arg0 = TREE_VALUE (arglist);
04849 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
04850 r0 = expand_expr (arg0, NULL_RTX, QImode, 0);
04851 r1 = expand_expr (arg1, NULL_RTX, QImode, 0);
04852 if (! target || ! register_operand (target, QImode))
04853 target = gen_reg_rtx (QImode);
04854 emit_insn (gen_mulqi3_24_clobber (target, r0, r1));
04855 return target;
04856
04857 case C4X_BUILTIN_TOIEEE:
04858 if (TARGET_C3X)
04859 break;
04860 arg0 = TREE_VALUE (arglist);
04861 r0 = expand_expr (arg0, NULL_RTX, QFmode, 0);
04862 if (! target || ! register_operand (target, QFmode))
04863 target = gen_reg_rtx (QFmode);
04864 emit_insn (gen_toieee (target, r0));
04865 return target;
04866
04867 case C4X_BUILTIN_FRIEEE:
04868 if (TARGET_C3X)
04869 break;
04870 arg0 = TREE_VALUE (arglist);
04871 r0 = expand_expr (arg0, NULL_RTX, QFmode, 0);
04872 if (register_operand (r0, QFmode))
04873 {
04874 r1 = assign_stack_local (QFmode, GET_MODE_SIZE (QFmode), 0);
04875 emit_move_insn (r1, r0);
04876 r0 = r1;
04877 }
04878 if (! target || ! register_operand (target, QFmode))
04879 target = gen_reg_rtx (QFmode);
04880 emit_insn (gen_frieee (target, r0));
04881 return target;
04882
04883 case C4X_BUILTIN_RCPF:
04884 if (TARGET_C3X)
04885 break;
04886 arg0 = TREE_VALUE (arglist);
04887 r0 = expand_expr (arg0, NULL_RTX, QFmode, 0);
04888 if (! target || ! register_operand (target, QFmode))
04889 target = gen_reg_rtx (QFmode);
04890 emit_insn (gen_rcpfqf_clobber (target, r0));
04891 return target;
04892 }
04893 return NULL_RTX;
04894 }
04895
04896 static void
04897 c4x_init_libfuncs (void)
04898 {
04899 set_optab_libfunc (smul_optab, QImode, "__mulqi3");
04900 set_optab_libfunc (sdiv_optab, QImode, "__divqi3");
04901 set_optab_libfunc (udiv_optab, QImode, "__udivqi3");
04902 set_optab_libfunc (smod_optab, QImode, "__modqi3");
04903 set_optab_libfunc (umod_optab, QImode, "__umodqi3");
04904 set_optab_libfunc (sdiv_optab, QFmode, "__divqf3");
04905 set_optab_libfunc (smul_optab, HFmode, "__mulhf3");
04906 set_optab_libfunc (sdiv_optab, HFmode, "__divhf3");
04907 set_optab_libfunc (smul_optab, HImode, "__mulhi3");
04908 set_optab_libfunc (sdiv_optab, HImode, "__divhi3");
04909 set_optab_libfunc (udiv_optab, HImode, "__udivhi3");
04910 set_optab_libfunc (smod_optab, HImode, "__modhi3");
04911 set_optab_libfunc (umod_optab, HImode, "__umodhi3");
04912 set_optab_libfunc (ffs_optab, QImode, "__ffs");
04913 smulhi3_libfunc = init_one_libfunc ("__smulhi3_high");
04914 umulhi3_libfunc = init_one_libfunc ("__umulhi3_high");
04915 fix_truncqfhi2_libfunc = init_one_libfunc ("__fix_truncqfhi2");
04916 fixuns_truncqfhi2_libfunc = init_one_libfunc ("__ufix_truncqfhi2");
04917 fix_trunchfhi2_libfunc = init_one_libfunc ("__fix_trunchfhi2");
04918 fixuns_trunchfhi2_libfunc = init_one_libfunc ("__ufix_trunchfhi2");
04919 floathiqf2_libfunc = init_one_libfunc ("__floathiqf2");
04920 floatunshiqf2_libfunc = init_one_libfunc ("__ufloathiqf2");
04921 floathihf2_libfunc = init_one_libfunc ("__floathihf2");
04922 floatunshihf2_libfunc = init_one_libfunc ("__ufloathihf2");
04923 }
04924
04925 static void
04926 c4x_asm_named_section (const char *name, unsigned int flags ATTRIBUTE_UNUSED,
04927 tree decl ATTRIBUTE_UNUSED)
04928 {
04929 fprintf (asm_out_file, "\t.sect\t\"%s\"\n", name);
04930 }
04931
04932 static void
04933 c4x_globalize_label (FILE *stream, const char *name)
04934 {
04935 default_globalize_label (stream, name);
04936 c4x_global_label (name);
04937 }
04938
04939 #define SHIFT_CODE_P(C) \
04940 ((C) == ASHIFT || (C) == ASHIFTRT || (C) == LSHIFTRT)
04941 #define LOGICAL_CODE_P(C) \
04942 ((C) == NOT || (C) == AND || (C) == IOR || (C) == XOR)
04943
04944
04945
04946
04947
04948 static bool
04949 c4x_rtx_costs (rtx x, int code, int outer_code, int *total)
04950 {
04951 HOST_WIDE_INT val;
04952
04953 switch (code)
04954 {
04955
04956
04957
04958
04959
04960 case CONST_INT:
04961 val = INTVAL (x);
04962 if (c4x_J_constant (x))
04963 *total = 0;
04964 else if (! TARGET_C3X
04965 && outer_code == AND
04966 && (val == 255 || val == 65535))
04967 *total = 0;
04968 else if (! TARGET_C3X
04969 && (outer_code == ASHIFTRT || outer_code == LSHIFTRT)
04970 && (val == 16 || val == 24))
04971 *total = 0;
04972 else if (TARGET_C3X && SHIFT_CODE_P (outer_code))
04973 *total = 3;
04974 else if (LOGICAL_CODE_P (outer_code)
04975 ? c4x_L_constant (x) : c4x_I_constant (x))
04976 *total = 2;
04977 else
04978 *total = 4;
04979 return true;
04980
04981 case CONST:
04982 case LABEL_REF:
04983 case SYMBOL_REF:
04984 *total = 4;
04985 return true;
04986
04987 case CONST_DOUBLE:
04988 if (c4x_H_constant (x))
04989 *total = 2;
04990 else if (GET_MODE (x) == QFmode)
04991 *total = 4;
04992 else
04993 *total = 8;
04994 return true;
04995
04996
04997
04998
04999
05000
05001
05002 case PLUS:
05003 case MINUS:
05004 case AND:
05005 case IOR:
05006 case XOR:
05007 case ASHIFT:
05008 case ASHIFTRT:
05009 case LSHIFTRT:
05010 *total = COSTS_N_INSNS (1);
05011 return true;
05012
05013 case MULT:
05014 *total = COSTS_N_INSNS (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
05015 || TARGET_MPYI ? 1 : 14);
05016 return true;
05017
05018 case DIV:
05019 case UDIV:
05020 case MOD:
05021 case UMOD:
05022 *total = COSTS_N_INSNS (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT
05023 ? 15 : 50);
05024 return true;
05025
05026 default:
05027 return false;
05028 }
05029 }
05030
05031
05032
05033 static void
05034 c4x_external_libcall (rtx fun)
05035 {
05036
05037 c4x_external_ref (XSTR (fun, 0));
05038 }
05039
05040
05041
05042 static rtx
05043 c4x_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
05044 int incoming ATTRIBUTE_UNUSED)
05045 {
05046 return gen_rtx_REG (Pmode, AR0_REGNO);
05047 }