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