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