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 #include "config.h"
00026 #include "system.h"
00027 #include "coretypes.h"
00028 #include "tm.h"
00029 #include "tree.h"
00030 #include "rtl.h"
00031 #include "regs.h"
00032 #include "hard-reg-set.h"
00033 #include "real.h"
00034 #include "insn-config.h"
00035 #include "conditions.h"
00036 #include "output.h"
00037 #include "insn-attr.h"
00038 #include "flags.h"
00039 #include "function.h"
00040 #include "expr.h"
00041 #include "recog.h"
00042 #include "toplev.h"
00043 #include "tm_p.h"
00044 #include "target.h"
00045 #include "target-def.h"
00046
00047
00048 int arc_cpu_type;
00049
00050
00051
00052 const char *arc_mangle_cpu;
00053
00054
00055
00056 rtx arc_compare_op0, arc_compare_op1;
00057
00058
00059 const char *arc_text_section;
00060 const char *arc_data_section;
00061 const char *arc_rodata_section;
00062
00063
00064 char arc_punct_chars[256];
00065
00066
00067
00068 static int arc_ccfsm_state;
00069 static int arc_ccfsm_current_cc;
00070 static rtx arc_ccfsm_target_insn;
00071 static int arc_ccfsm_target_label;
00072
00073
00074
00075 #define MAX_INSNS_SKIPPED 3
00076
00077
00078
00079
00080
00081 static int last_insn_set_cc_p;
00082 static int current_insn_set_cc_p;
00083 static bool arc_handle_option (size_t, const char *, int);
00084 static void record_cc_ref (rtx);
00085 static void arc_init_reg_tables (void);
00086 static int get_arc_condition_code (rtx);
00087 const struct attribute_spec arc_attribute_table[];
00088 static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *);
00089 static bool arc_assemble_integer (rtx, unsigned int, int);
00090 static void arc_output_function_prologue (FILE *, HOST_WIDE_INT);
00091 static void arc_output_function_epilogue (FILE *, HOST_WIDE_INT);
00092 static void arc_file_start (void);
00093 static void arc_internal_label (FILE *, const char *, unsigned long);
00094 static void arc_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
00095 tree, int *, int);
00096 static bool arc_rtx_costs (rtx, int, int, int *);
00097 static int arc_address_cost (rtx);
00098 static void arc_external_libcall (rtx);
00099 static bool arc_return_in_memory (tree, tree);
00100 static bool arc_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
00101 tree, bool);
00102
00103
00104 #undef TARGET_ASM_ALIGNED_HI_OP
00105 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
00106 #undef TARGET_ASM_ALIGNED_SI_OP
00107 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
00108 #undef TARGET_ASM_INTEGER
00109 #define TARGET_ASM_INTEGER arc_assemble_integer
00110
00111 #undef TARGET_ASM_FUNCTION_PROLOGUE
00112 #define TARGET_ASM_FUNCTION_PROLOGUE arc_output_function_prologue
00113 #undef TARGET_ASM_FUNCTION_EPILOGUE
00114 #define TARGET_ASM_FUNCTION_EPILOGUE arc_output_function_epilogue
00115 #undef TARGET_ASM_FILE_START
00116 #define TARGET_ASM_FILE_START arc_file_start
00117 #undef TARGET_ATTRIBUTE_TABLE
00118 #define TARGET_ATTRIBUTE_TABLE arc_attribute_table
00119 #undef TARGET_ASM_INTERNAL_LABEL
00120 #define TARGET_ASM_INTERNAL_LABEL arc_internal_label
00121 #undef TARGET_ASM_EXTERNAL_LIBCALL
00122 #define TARGET_ASM_EXTERNAL_LIBCALL arc_external_libcall
00123
00124 #undef TARGET_HANDLE_OPTION
00125 #define TARGET_HANDLE_OPTION arc_handle_option
00126
00127 #undef TARGET_RTX_COSTS
00128 #define TARGET_RTX_COSTS arc_rtx_costs
00129 #undef TARGET_ADDRESS_COST
00130 #define TARGET_ADDRESS_COST arc_address_cost
00131
00132 #undef TARGET_PROMOTE_FUNCTION_ARGS
00133 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
00134 #undef TARGET_PROMOTE_FUNCTION_RETURN
00135 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
00136 #undef TARGET_PROMOTE_PROTOTYPES
00137 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
00138
00139 #undef TARGET_RETURN_IN_MEMORY
00140 #define TARGET_RETURN_IN_MEMORY arc_return_in_memory
00141 #undef TARGET_PASS_BY_REFERENCE
00142 #define TARGET_PASS_BY_REFERENCE arc_pass_by_reference
00143 #undef TARGET_CALLEE_COPIES
00144 #define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true
00145
00146 #undef TARGET_SETUP_INCOMING_VARARGS
00147 #define TARGET_SETUP_INCOMING_VARARGS arc_setup_incoming_varargs
00148
00149 struct gcc_target targetm = TARGET_INITIALIZER;
00150
00151
00152
00153 static bool
00154 arc_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
00155 {
00156 switch (code)
00157 {
00158 case OPT_mcpu_:
00159 return strcmp (arg, "base") == 0 || ARC_EXTENSION_CPU (arg);
00160
00161 default:
00162 return true;
00163 }
00164 }
00165
00166
00167
00168 void
00169 arc_init (void)
00170 {
00171 char *tmp;
00172
00173
00174 arc_text_section = tmp = xmalloc (strlen (arc_text_string) + sizeof (ARC_SECTION_FORMAT) + 1);
00175 sprintf (tmp, ARC_SECTION_FORMAT, arc_text_string);
00176 arc_data_section = tmp = xmalloc (strlen (arc_data_string) + sizeof (ARC_SECTION_FORMAT) + 1);
00177 sprintf (tmp, ARC_SECTION_FORMAT, arc_data_string);
00178 arc_rodata_section = tmp = xmalloc (strlen (arc_rodata_string) + sizeof (ARC_SECTION_FORMAT) + 1);
00179 sprintf (tmp, ARC_SECTION_FORMAT, arc_rodata_string);
00180
00181 arc_init_reg_tables ();
00182
00183
00184 memset (arc_punct_chars, 0, sizeof (arc_punct_chars));
00185 arc_punct_chars['#'] = 1;
00186 arc_punct_chars['*'] = 1;
00187 arc_punct_chars['?'] = 1;
00188 arc_punct_chars['!'] = 1;
00189 arc_punct_chars['~'] = 1;
00190 }
00191
00192
00193 static const char *const arc_condition_codes[] =
00194 {
00195 "al", 0, "eq", "ne", "p", "n", "c", "nc", "v", "nv",
00196 "gt", "le", "ge", "lt", "hi", "ls", "pnz", 0
00197 };
00198
00199 #define ARC_INVERSE_CONDITION_CODE(X) ((X) ^ 1)
00200
00201
00202
00203
00204
00205 static int
00206 get_arc_condition_code (rtx comparison)
00207 {
00208 switch (GET_CODE (comparison))
00209 {
00210 case EQ : return 2;
00211 case NE : return 3;
00212 case GT : return 10;
00213 case LE : return 11;
00214 case GE : return 12;
00215 case LT : return 13;
00216 case GTU : return 14;
00217 case LEU : return 15;
00218 case LTU : return 6;
00219 case GEU : return 7;
00220 default : gcc_unreachable ();
00221 }
00222
00223 return (42);
00224 }
00225
00226
00227
00228
00229 enum machine_mode
00230 arc_select_cc_mode (enum rtx_code op,
00231 rtx x ATTRIBUTE_UNUSED,
00232 rtx y ATTRIBUTE_UNUSED)
00233 {
00234 switch (op)
00235 {
00236 case EQ :
00237 case NE :
00238 return CCZNmode;
00239 default :
00240 switch (GET_CODE (x))
00241 {
00242 case AND :
00243 case IOR :
00244 case XOR :
00245 case SIGN_EXTEND :
00246 case ZERO_EXTEND :
00247 return CCZNmode;
00248 case ASHIFT :
00249 case ASHIFTRT :
00250 case LSHIFTRT :
00251 return CCZNCmode;
00252 default:
00253 break;
00254 }
00255 }
00256 return CCmode;
00257 }
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268 enum arc_mode_class {
00269 C_MODE,
00270 S_MODE, D_MODE, T_MODE, O_MODE,
00271 SF_MODE, DF_MODE, TF_MODE, OF_MODE
00272 };
00273
00274
00275 #define C_MODES (1 << (int) C_MODE)
00276
00277
00278 #define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
00279
00280
00281 #define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
00282
00283
00284 #define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
00285
00286
00287
00288 const unsigned int arc_hard_regno_mode_ok[] = {
00289 T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES,
00290 T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES,
00291 T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, D_MODES,
00292 D_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
00293
00294
00295 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
00296 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
00297 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
00298 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, C_MODES
00299 };
00300
00301 unsigned int arc_mode_class [NUM_MACHINE_MODES];
00302
00303 enum reg_class arc_regno_reg_class[FIRST_PSEUDO_REGISTER];
00304
00305 static void
00306 arc_init_reg_tables (void)
00307 {
00308 int i;
00309
00310 for (i = 0; i < NUM_MACHINE_MODES; i++)
00311 {
00312 switch (GET_MODE_CLASS (i))
00313 {
00314 case MODE_INT:
00315 case MODE_PARTIAL_INT:
00316 case MODE_COMPLEX_INT:
00317 if (GET_MODE_SIZE (i) <= 4)
00318 arc_mode_class[i] = 1 << (int) S_MODE;
00319 else if (GET_MODE_SIZE (i) == 8)
00320 arc_mode_class[i] = 1 << (int) D_MODE;
00321 else if (GET_MODE_SIZE (i) == 16)
00322 arc_mode_class[i] = 1 << (int) T_MODE;
00323 else if (GET_MODE_SIZE (i) == 32)
00324 arc_mode_class[i] = 1 << (int) O_MODE;
00325 else
00326 arc_mode_class[i] = 0;
00327 break;
00328 case MODE_FLOAT:
00329 case MODE_COMPLEX_FLOAT:
00330 if (GET_MODE_SIZE (i) <= 4)
00331 arc_mode_class[i] = 1 << (int) SF_MODE;
00332 else if (GET_MODE_SIZE (i) == 8)
00333 arc_mode_class[i] = 1 << (int) DF_MODE;
00334 else if (GET_MODE_SIZE (i) == 16)
00335 arc_mode_class[i] = 1 << (int) TF_MODE;
00336 else if (GET_MODE_SIZE (i) == 32)
00337 arc_mode_class[i] = 1 << (int) OF_MODE;
00338 else
00339 arc_mode_class[i] = 0;
00340 break;
00341 case MODE_CC:
00342 arc_mode_class[i] = 1 << (int) C_MODE;
00343 break;
00344 default:
00345 arc_mode_class[i] = 0;
00346 break;
00347 }
00348 }
00349
00350 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
00351 {
00352 if (i < 60)
00353 arc_regno_reg_class[i] = GENERAL_REGS;
00354 else if (i == 60)
00355 arc_regno_reg_class[i] = LPCOUNT_REG;
00356 else if (i == 61)
00357 arc_regno_reg_class[i] = NO_REGS ;
00358 else
00359 arc_regno_reg_class[i] = NO_REGS;
00360 }
00361 }
00362
00363
00364
00365
00366
00367
00368
00369 const struct attribute_spec arc_attribute_table[] =
00370 {
00371
00372 { "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute },
00373 { NULL, 0, 0, false, false, false, NULL }
00374 };
00375
00376
00377
00378 static tree
00379 arc_handle_interrupt_attribute (tree *node ATTRIBUTE_UNUSED,
00380 tree name,
00381 tree args,
00382 int flags ATTRIBUTE_UNUSED,
00383 bool *no_add_attrs)
00384 {
00385 tree value = TREE_VALUE (args);
00386
00387 if (TREE_CODE (value) != STRING_CST)
00388 {
00389 warning (OPT_Wattributes,
00390 "argument of %qs attribute is not a string constant",
00391 IDENTIFIER_POINTER (name));
00392 *no_add_attrs = true;
00393 }
00394 else if (strcmp (TREE_STRING_POINTER (value), "ilink1")
00395 && strcmp (TREE_STRING_POINTER (value), "ilink2"))
00396 {
00397 warning (OPT_Wattributes,
00398 "argument of %qs attribute is not \"ilink1\" or \"ilink2\"",
00399 IDENTIFIER_POINTER (name));
00400 *no_add_attrs = true;
00401 }
00402
00403 return NULL_TREE;
00404 }
00405
00406
00407
00408
00409 int
00410 call_address_operand (rtx op, enum machine_mode mode)
00411 {
00412 return (symbolic_operand (op, mode)
00413 || (GET_CODE (op) == CONST_INT && LEGITIMATE_CONSTANT_P (op))
00414 || (GET_CODE (op) == REG));
00415 }
00416
00417 int
00418 call_operand (rtx op, enum machine_mode mode)
00419 {
00420 if (GET_CODE (op) != MEM)
00421 return 0;
00422 op = XEXP (op, 0);
00423 return call_address_operand (op, mode);
00424 }
00425
00426
00427
00428 int
00429 symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
00430 {
00431 switch (GET_CODE (op))
00432 {
00433 case SYMBOL_REF:
00434 case LABEL_REF:
00435 case CONST :
00436 return 1;
00437 default:
00438 return 0;
00439 }
00440 }
00441
00442
00443
00444
00445 int
00446 symbolic_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
00447 {
00448 if (GET_CODE (op) == SUBREG)
00449 op = SUBREG_REG (op);
00450 if (GET_CODE (op) != MEM)
00451 return 0;
00452 op = XEXP (op, 0);
00453 return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST
00454 || GET_CODE (op) == LABEL_REF);
00455 }
00456
00457
00458
00459 int
00460 short_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
00461 {
00462 if (GET_CODE (op) != CONST_INT)
00463 return 0;
00464 return SMALL_INT (INTVAL (op));
00465 }
00466
00467
00468
00469
00470 int
00471 long_immediate_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
00472 {
00473 switch (GET_CODE (op))
00474 {
00475 case SYMBOL_REF :
00476 case LABEL_REF :
00477 case CONST :
00478 return 1;
00479 case CONST_INT :
00480 return !SMALL_INT (INTVAL (op));
00481 case CONST_DOUBLE :
00482
00483
00484
00485 return 1;
00486 default:
00487 break;
00488 }
00489 return 0;
00490 }
00491
00492
00493
00494
00495
00496
00497
00498 int
00499 long_immediate_loadstore_operand (rtx op,
00500 enum machine_mode mode ATTRIBUTE_UNUSED)
00501 {
00502 if (GET_CODE (op) != MEM)
00503 return 0;
00504
00505 op = XEXP (op, 0);
00506 switch (GET_CODE (op))
00507 {
00508 case SYMBOL_REF :
00509 case LABEL_REF :
00510 case CONST :
00511 return 1;
00512 case CONST_INT :
00513
00514
00515
00516
00517 return 1;
00518 case CONST_DOUBLE :
00519
00520
00521
00522 return 1;
00523 case REG :
00524 return 0;
00525 case PLUS :
00526 if (GET_CODE (XEXP (op, 1)) == CONST_INT
00527 && !SMALL_INT (INTVAL (XEXP (op, 1))))
00528 return 1;
00529 return 0;
00530 default:
00531 break;
00532 }
00533 return 0;
00534 }
00535
00536
00537
00538
00539 int
00540 move_src_operand (rtx op, enum machine_mode mode)
00541 {
00542 switch (GET_CODE (op))
00543 {
00544 case SYMBOL_REF :
00545 case LABEL_REF :
00546 case CONST :
00547 return 1;
00548 case CONST_INT :
00549 return (LARGE_INT (INTVAL (op)));
00550 case CONST_DOUBLE :
00551
00552
00553
00554 if (mode == SImode)
00555 return arc_double_limm_p (op);
00556
00557 if (mode == SFmode)
00558 return GET_MODE (op) == SFmode;
00559 return 0;
00560 case REG :
00561 return register_operand (op, mode);
00562 case SUBREG :
00563
00564
00565 if (GET_CODE (SUBREG_REG (op)) == MEM)
00566 return address_operand (XEXP (SUBREG_REG (op), 0), mode);
00567 else
00568 return register_operand (op, mode);
00569 case MEM :
00570 return address_operand (XEXP (op, 0), mode);
00571 default :
00572 return 0;
00573 }
00574 }
00575
00576
00577
00578
00579 int
00580 move_double_src_operand (rtx op, enum machine_mode mode)
00581 {
00582 switch (GET_CODE (op))
00583 {
00584 case REG :
00585 return register_operand (op, mode);
00586 case SUBREG :
00587
00588
00589 if (GET_CODE (SUBREG_REG (op)) == MEM)
00590 return move_double_src_operand (SUBREG_REG (op), mode);
00591 else
00592 return register_operand (op, mode);
00593 case MEM :
00594
00595 if (GET_CODE (XEXP (op, 0)) == PRE_DEC
00596 || GET_CODE (XEXP (op, 0)) == PRE_INC)
00597 return 0;
00598 return address_operand (XEXP (op, 0), mode);
00599 case CONST_INT :
00600 case CONST_DOUBLE :
00601 return 1;
00602 default :
00603 return 0;
00604 }
00605 }
00606
00607
00608
00609 int
00610 move_dest_operand (rtx op, enum machine_mode mode)
00611 {
00612 switch (GET_CODE (op))
00613 {
00614 case REG :
00615 return register_operand (op, mode);
00616 case SUBREG :
00617
00618
00619 if (GET_CODE (SUBREG_REG (op)) == MEM)
00620 return address_operand (XEXP (SUBREG_REG (op), 0), mode);
00621 else
00622 return register_operand (op, mode);
00623 case MEM :
00624 return address_operand (XEXP (op, 0), mode);
00625 default :
00626 return 0;
00627 }
00628 }
00629
00630
00631
00632 int
00633 load_update_operand (rtx op, enum machine_mode mode)
00634 {
00635 if (GET_CODE (op) != MEM
00636 || GET_MODE (op) != mode)
00637 return 0;
00638 op = XEXP (op, 0);
00639 if (GET_CODE (op) != PLUS
00640 || GET_MODE (op) != Pmode
00641 || !register_operand (XEXP (op, 0), Pmode)
00642 || !nonmemory_operand (XEXP (op, 1), Pmode))
00643 return 0;
00644 return 1;
00645 }
00646
00647
00648
00649 int
00650 store_update_operand (rtx op, enum machine_mode mode)
00651 {
00652 if (GET_CODE (op) != MEM
00653 || GET_MODE (op) != mode)
00654 return 0;
00655 op = XEXP (op, 0);
00656 if (GET_CODE (op) != PLUS
00657 || GET_MODE (op) != Pmode
00658 || !register_operand (XEXP (op, 0), Pmode)
00659 || !(GET_CODE (XEXP (op, 1)) == CONST_INT
00660 && SMALL_INT (INTVAL (XEXP (op, 1)))))
00661 return 0;
00662 return 1;
00663 }
00664
00665
00666
00667
00668
00669 int
00670 nonvol_nonimm_operand (rtx op, enum machine_mode mode)
00671 {
00672 if (GET_CODE (op) == MEM && MEM_VOLATILE_P (op))
00673 return 0;
00674 return nonimmediate_operand (op, mode);
00675 }
00676
00677
00678
00679
00680
00681 int
00682 const_sint32_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
00683 {
00684
00685 return (GET_CODE (op) == CONST_INT
00686 && (INTVAL (op) >= (-0x7fffffff - 1) && INTVAL (op) <= 0x7fffffff));
00687 }
00688
00689
00690
00691
00692
00693 int
00694 const_uint32_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
00695 {
00696 #if HOST_BITS_PER_WIDE_INT > 32
00697
00698 return (GET_CODE (op) == CONST_INT
00699 && (INTVAL (op) >= 0 && INTVAL (op) <= 0xffffffffL));
00700 #else
00701 return ((GET_CODE (op) == CONST_INT && INTVAL (op) >= 0)
00702 || (GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_HIGH (op) == 0));
00703 #endif
00704 }
00705
00706
00707
00708
00709
00710
00711
00712 int
00713 proper_comparison_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
00714 {
00715 enum rtx_code code;
00716 if (!COMPARISON_P (op))
00717 return 0;
00718
00719 code = GET_CODE (op);
00720 if (GET_MODE (XEXP (op, 0)) == CCZNmode)
00721 return (code == EQ || code == NE);
00722 if (GET_MODE (XEXP (op, 0)) == CCZNCmode)
00723 return (code == EQ || code == NE
00724 || code == LTU || code == GEU || code == GTU || code == LEU);
00725 return 1;
00726 }
00727
00728
00729
00730
00731
00732
00733 rtx
00734 gen_compare_reg (enum rtx_code code, rtx x, rtx y)
00735 {
00736 enum machine_mode mode = SELECT_CC_MODE (code, x, y);
00737 rtx cc_reg;
00738
00739 cc_reg = gen_rtx_REG (mode, 61);
00740
00741 emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
00742 gen_rtx_COMPARE (mode, x, y)));
00743
00744 return cc_reg;
00745 }
00746
00747
00748
00749
00750 int
00751 arc_double_limm_p (rtx value)
00752 {
00753 HOST_WIDE_INT low, high;
00754
00755 gcc_assert (GET_CODE (value) == CONST_DOUBLE);
00756
00757 low = CONST_DOUBLE_LOW (value);
00758 high = CONST_DOUBLE_HIGH (value);
00759
00760 if (low & 0x80000000)
00761 {
00762 return (((unsigned HOST_WIDE_INT) low <= 0xffffffff && high == 0)
00763 || (((low & - (unsigned HOST_WIDE_INT) 0x80000000)
00764 == - (unsigned HOST_WIDE_INT) 0x80000000)
00765 && high == -1));
00766 }
00767 else
00768 {
00769 return (unsigned HOST_WIDE_INT) low <= 0x7fffffff && high == 0;
00770 }
00771 }
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785 static void
00786 arc_setup_incoming_varargs (CUMULATIVE_ARGS *cum,
00787 enum machine_mode mode,
00788 tree type ATTRIBUTE_UNUSED,
00789 int *pretend_size,
00790 int no_rtl)
00791 {
00792 int first_anon_arg;
00793
00794
00795 gcc_assert (mode != BLKmode);
00796
00797 first_anon_arg = *cum + ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
00798 / UNITS_PER_WORD);
00799
00800 if (first_anon_arg < MAX_ARC_PARM_REGS && !no_rtl)
00801 {
00802
00803 int first_reg_offset = first_anon_arg;
00804
00805 int size = MAX_ARC_PARM_REGS - first_reg_offset;
00806
00807 int align_slop = size & 1;
00808 rtx regblock;
00809
00810 regblock = gen_rtx_MEM (BLKmode,
00811 plus_constant (arg_pointer_rtx,
00812 FIRST_PARM_OFFSET (0)
00813 + align_slop * UNITS_PER_WORD));
00814 set_mem_alias_set (regblock, get_varargs_alias_set ());
00815 set_mem_align (regblock, BITS_PER_WORD);
00816 move_block_from_reg (first_reg_offset, regblock,
00817 MAX_ARC_PARM_REGS - first_reg_offset);
00818
00819 *pretend_size = ((MAX_ARC_PARM_REGS - first_reg_offset + align_slop)
00820 * UNITS_PER_WORD);
00821 }
00822 }
00823
00824
00825
00826
00827
00828
00829
00830 static bool
00831 arc_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total)
00832 {
00833 switch (code)
00834 {
00835
00836
00837
00838 case CONST_INT:
00839 if (SMALL_INT (INTVAL (x)))
00840 {
00841 *total = 0;
00842 return true;
00843 }
00844
00845
00846 case CONST:
00847 case LABEL_REF:
00848 case SYMBOL_REF:
00849 *total = COSTS_N_INSNS (1);
00850 return true;
00851
00852 case CONST_DOUBLE:
00853 {
00854 rtx high, low;
00855 split_double (x, &high, &low);
00856 *total = COSTS_N_INSNS (!SMALL_INT (INTVAL (high))
00857 + !SMALL_INT (INTVAL (low)));
00858 return true;
00859 }
00860
00861
00862
00863
00864 case ASHIFT:
00865 case ASHIFTRT:
00866 case LSHIFTRT:
00867 if (TARGET_SHIFTER)
00868 *total = COSTS_N_INSNS (1);
00869 else if (GET_CODE (XEXP (x, 1)) != CONST_INT)
00870 *total = COSTS_N_INSNS (16);
00871 else
00872 *total = COSTS_N_INSNS (INTVAL (XEXP ((x), 1)));
00873 return false;
00874
00875 default:
00876 return false;
00877 }
00878 }
00879
00880
00881
00882
00883
00884 static int
00885 arc_address_cost (rtx addr)
00886 {
00887 switch (GET_CODE (addr))
00888 {
00889 case REG :
00890 return 1;
00891
00892 case LABEL_REF :
00893 case SYMBOL_REF :
00894 case CONST :
00895 return 2;
00896
00897 case PLUS :
00898 {
00899 register rtx plus0 = XEXP (addr, 0);
00900 register rtx plus1 = XEXP (addr, 1);
00901
00902 if (GET_CODE (plus0) != REG)
00903 break;
00904
00905 switch (GET_CODE (plus1))
00906 {
00907 case CONST_INT :
00908 return SMALL_INT (plus1) ? 1 : 2;
00909 case CONST :
00910 case SYMBOL_REF :
00911 case LABEL_REF :
00912 return 2;
00913 default:
00914 break;
00915 }
00916 break;
00917 }
00918 default:
00919 break;
00920 }
00921
00922 return 4;
00923 }
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975 struct arc_frame_info
00976 {
00977 unsigned int total_size;
00978 unsigned int extra_size;
00979 unsigned int pretend_size;
00980 unsigned int args_size;
00981 unsigned int reg_size;
00982 unsigned int var_size;
00983 unsigned int reg_offset;
00984 unsigned int gmask;
00985 int initialized;
00986 };
00987
00988
00989 static struct arc_frame_info current_frame_info;
00990
00991
00992 static struct arc_frame_info zero_frame_info;
00993
00994
00995
00996
00997
00998
00999 enum arc_function_type
01000 arc_compute_function_type (tree decl)
01001 {
01002 tree a;
01003
01004 static enum arc_function_type fn_type = ARC_FUNCTION_UNKNOWN;
01005
01006 static tree last_fn = NULL_TREE;
01007
01008
01009 if (decl == NULL_TREE)
01010 {
01011 fn_type = ARC_FUNCTION_UNKNOWN;
01012 last_fn = NULL_TREE;
01013 return fn_type;
01014 }
01015
01016 if (decl == last_fn && fn_type != ARC_FUNCTION_UNKNOWN)
01017 return fn_type;
01018
01019
01020 fn_type = ARC_FUNCTION_NORMAL;
01021
01022
01023 for (a = DECL_ATTRIBUTES (current_function_decl);
01024 a;
01025 a = TREE_CHAIN (a))
01026 {
01027 tree name = TREE_PURPOSE (a), args = TREE_VALUE (a);
01028
01029 if (name == get_identifier ("__interrupt__")
01030 && list_length (args) == 1
01031 && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
01032 {
01033 tree value = TREE_VALUE (args);
01034
01035 if (!strcmp (TREE_STRING_POINTER (value), "ilink1"))
01036 fn_type = ARC_FUNCTION_ILINK1;
01037 else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))
01038 fn_type = ARC_FUNCTION_ILINK2;
01039 else
01040 gcc_unreachable ();
01041 break;
01042 }
01043 }
01044
01045 last_fn = decl;
01046 return fn_type;
01047 }
01048
01049 #define ILINK1_REGNUM 29
01050 #define ILINK2_REGNUM 30
01051 #define RETURN_ADDR_REGNUM 31
01052 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
01053 #define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
01054
01055
01056
01057
01058 #define MUST_SAVE_REGISTER(regno, interrupt_p) \
01059 ((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \
01060 && (regs_ever_live[regno] && (!call_used_regs[regno] || interrupt_p)))
01061
01062 #define MUST_SAVE_RETURN_ADDR (regs_ever_live[RETURN_ADDR_REGNUM])
01063
01064
01065
01066
01067
01068
01069 unsigned int
01070 arc_compute_frame_size (int size )
01071 {
01072 int regno;
01073 unsigned int total_size, var_size, args_size, pretend_size, extra_size;
01074 unsigned int reg_size, reg_offset;
01075 unsigned int gmask;
01076 enum arc_function_type fn_type;
01077 int interrupt_p;
01078
01079 var_size = size;
01080 args_size = current_function_outgoing_args_size;
01081 pretend_size = current_function_pretend_args_size;
01082 extra_size = FIRST_PARM_OFFSET (0);
01083 total_size = extra_size + pretend_size + args_size + var_size;
01084 reg_offset = FIRST_PARM_OFFSET(0) + current_function_outgoing_args_size;
01085 reg_size = 0;
01086 gmask = 0;
01087
01088
01089
01090 fn_type = arc_compute_function_type (current_function_decl);
01091 interrupt_p = ARC_INTERRUPT_P (fn_type);
01092
01093
01094
01095
01096 for (regno = 0; regno <= 31; regno++)
01097 {
01098 if (MUST_SAVE_REGISTER (regno, interrupt_p))
01099 {
01100 reg_size += UNITS_PER_WORD;
01101 gmask |= 1 << regno;
01102 }
01103 }
01104
01105 total_size += reg_size;
01106
01107
01108
01109
01110 if (total_size == extra_size
01111 && !MUST_SAVE_RETURN_ADDR)
01112 total_size = extra_size = 0;
01113
01114 total_size = ARC_STACK_ALIGN (total_size);
01115
01116
01117 current_frame_info.total_size = total_size;
01118 current_frame_info.extra_size = extra_size;
01119 current_frame_info.pretend_size = pretend_size;
01120 current_frame_info.var_size = var_size;
01121 current_frame_info.args_size = args_size;
01122 current_frame_info.reg_size = reg_size;
01123 current_frame_info.reg_offset = reg_offset;
01124 current_frame_info.gmask = gmask;
01125 current_frame_info.initialized = reload_completed;
01126
01127
01128 return total_size;
01129 }
01130
01131
01132
01133 void
01134 arc_save_restore (FILE *file,
01135 const char *base_reg,
01136 unsigned int offset,
01137 unsigned int gmask,
01138 const char *op)
01139 {
01140 int regno;
01141
01142 if (gmask == 0)
01143 return;
01144
01145 for (regno = 0; regno <= 31; regno++)
01146 {
01147 if ((gmask & (1L << regno)) != 0)
01148 {
01149 fprintf (file, "\t%s %s,[%s,%d]\n",
01150 op, reg_names[regno], base_reg, offset);
01151 offset += UNITS_PER_WORD;
01152 }
01153 }
01154 }
01155
01156
01157
01158
01159
01160 static bool
01161 arc_assemble_integer (rtx x, unsigned int size, int aligned_p)
01162 {
01163 if (size == UNITS_PER_WORD && aligned_p
01164 && ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x))
01165 || GET_CODE (x) == LABEL_REF))
01166 {
01167 fputs ("\t.word\t%st(", asm_out_file);
01168 output_addr_const (asm_out_file, x);
01169 fputs (")\n", asm_out_file);
01170 return true;
01171 }
01172 return default_assemble_integer (x, size, aligned_p);
01173 }
01174
01175
01176
01177 static void
01178 arc_output_function_prologue (FILE *file, HOST_WIDE_INT size)
01179 {
01180 const char *sp_str = reg_names[STACK_POINTER_REGNUM];
01181 const char *fp_str = reg_names[FRAME_POINTER_REGNUM];
01182 unsigned int gmask = current_frame_info.gmask;
01183 enum arc_function_type fn_type = arc_compute_function_type (current_function_decl);
01184
01185
01186
01187 if (ARC_INTERRUPT_P (fn_type))
01188 {
01189 fprintf (file, "\t%s interrupt handler\n",
01190 ASM_COMMENT_START);
01191 fprintf (file, "\tsub %s,%s,16\n", sp_str, sp_str);
01192 }
01193
01194
01195 fprintf (file, "\t%s BEGIN PROLOGUE %s vars= %d, regs= %d, args= %d, extra= %d\n",
01196 ASM_COMMENT_START, ASM_COMMENT_START,
01197 current_frame_info.var_size,
01198 current_frame_info.reg_size / 4,
01199 current_frame_info.args_size,
01200 current_frame_info.extra_size);
01201
01202 size = ARC_STACK_ALIGN (size);
01203 size = (! current_frame_info.initialized
01204 ? arc_compute_frame_size (size)
01205 : current_frame_info.total_size);
01206
01207
01208 gcc_assert (size || !gmask);
01209
01210
01211 if (current_frame_info.pretend_size != 0)
01212 fprintf (file, "\tsub %s,%s,%d\n",
01213 sp_str, sp_str, current_frame_info.pretend_size);
01214
01215
01216 if (MUST_SAVE_RETURN_ADDR)
01217 fprintf (file, "\tst %s,[%s,%d]\n",
01218 reg_names[RETURN_ADDR_REGNUM], sp_str, UNITS_PER_WORD);
01219
01220
01221 if (frame_pointer_needed)
01222 {
01223 fprintf (file, "\tst %s,[%s]\n", fp_str, sp_str);
01224 fprintf (file, "\tmov %s,%s\n", fp_str, sp_str);
01225 }
01226
01227
01228
01229
01230
01231
01232
01233
01234 if (size - current_frame_info.pretend_size > 0)
01235 fprintf (file, "\tsub %s,%s," HOST_WIDE_INT_PRINT_DEC "\n",
01236 sp_str, sp_str, size - current_frame_info.pretend_size);
01237
01238
01239
01240 arc_save_restore (file, sp_str, current_frame_info.reg_offset,
01241
01242
01243 gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK),
01244 "st");
01245
01246 fprintf (file, "\t%s END PROLOGUE\n", ASM_COMMENT_START);
01247 }
01248
01249
01250
01251
01252 static void
01253 arc_output_function_epilogue (FILE *file, HOST_WIDE_INT size)
01254 {
01255 rtx epilogue_delay = current_function_epilogue_delay_list;
01256 int noepilogue = FALSE;
01257 enum arc_function_type fn_type = arc_compute_function_type (current_function_decl);
01258
01259
01260 fprintf (file, "\t%s EPILOGUE\n", ASM_COMMENT_START);
01261
01262 size = ARC_STACK_ALIGN (size);
01263 size = (!current_frame_info.initialized
01264 ? arc_compute_frame_size (size)
01265 : current_frame_info.total_size);
01266
01267 if (size == 0 && epilogue_delay == 0)
01268 {
01269 rtx insn = get_last_insn ();
01270
01271
01272
01273 if (GET_CODE (insn) == NOTE)
01274 insn = prev_nonnote_insn (insn);
01275 if (insn && GET_CODE (insn) == BARRIER)
01276 noepilogue = TRUE;
01277 }
01278
01279 if (!noepilogue)
01280 {
01281 unsigned int pretend_size = current_frame_info.pretend_size;
01282 unsigned int frame_size = size - pretend_size;
01283 int restored, fp_restored_p;
01284 int can_trust_sp_p = !current_function_calls_alloca;
01285 const char *sp_str = reg_names[STACK_POINTER_REGNUM];
01286 const char *fp_str = reg_names[FRAME_POINTER_REGNUM];
01287
01288
01289
01290
01291
01292
01293 if (!can_trust_sp_p)
01294 {
01295 gcc_assert (frame_pointer_needed);
01296 fprintf (file,"\tsub %s,%s,%d\t\t%s sp not trusted here\n",
01297 sp_str, fp_str, frame_size, ASM_COMMENT_START);
01298 }
01299
01300
01301 arc_save_restore (file, sp_str, current_frame_info.reg_offset,
01302
01303
01304 current_frame_info.gmask & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK),
01305 "ld");
01306
01307 if (MUST_SAVE_RETURN_ADDR)
01308 fprintf (file, "\tld %s,[%s,%d]\n",
01309 reg_names[RETURN_ADDR_REGNUM],
01310 frame_pointer_needed ? fp_str : sp_str,
01311 UNITS_PER_WORD + (frame_pointer_needed ? 0 : frame_size));
01312
01313
01314
01315 restored = 0;
01316 fp_restored_p = 0;
01317
01318
01319
01320
01321
01322 if (MUST_SAVE_RETURN_ADDR && epilogue_delay != NULL_RTX)
01323 {
01324 final_scan_insn (XEXP (epilogue_delay, 0), file, 1, 1, NULL);
01325 epilogue_delay = NULL_RTX;
01326 }
01327
01328 if (frame_pointer_needed)
01329 {
01330
01331
01332 if (epilogue_delay != NULL_RTX
01333 || !SMALL_INT (frame_size)
01334 || pretend_size
01335 || ARC_INTERRUPT_P (fn_type))
01336 {
01337
01338 fprintf (file, "\tld.a %s,[%s,%d]\n", fp_str, sp_str, frame_size);
01339 restored += frame_size;
01340 fp_restored_p = 1;
01341 }
01342 }
01343 else if (!SMALL_INT (size )
01344 || ARC_INTERRUPT_P (fn_type))
01345 {
01346 fprintf (file, "\tadd %s,%s,%d\n", sp_str, sp_str, frame_size);
01347 restored += frame_size;
01348 }
01349
01350
01351
01352 if (ARC_INTERRUPT_P (fn_type))
01353 {
01354 if (epilogue_delay)
01355 {
01356 final_scan_insn (XEXP (epilogue_delay, 0), file, 1, 1, NULL);
01357 }
01358 }
01359
01360
01361 {
01362 static const int regs[4] = {
01363 0, RETURN_ADDR_REGNUM, ILINK1_REGNUM, ILINK2_REGNUM
01364 };
01365
01366
01367 if (ARC_INTERRUPT_P (fn_type))
01368 fprintf (file, "\tj.d.f %s\n", reg_names[regs[fn_type]]);
01369 else
01370 fprintf (file, "\tj.d %s\n", reg_names[regs[fn_type]]);
01371 }
01372
01373
01374
01375
01376
01377
01378 if (ARC_INTERRUPT_P (fn_type))
01379 fprintf (file, "\tadd %s,%s,16\n", sp_str, sp_str);
01380 else if (epilogue_delay != NULL_RTX)
01381 {
01382 gcc_assert (!frame_pointer_needed || fp_restored_p);
01383 gcc_assert (restored >= size);
01384 final_scan_insn (XEXP (epilogue_delay, 0), file, 1, 1, NULL);
01385 }
01386 else if (frame_pointer_needed && !fp_restored_p)
01387 {
01388 gcc_assert (SMALL_INT (frame_size));
01389
01390 fprintf (file, "\tld.a %s,[%s,%d]\n", fp_str, sp_str, frame_size);
01391 }
01392 else if (restored < size)
01393 {
01394 gcc_assert (SMALL_INT (size - restored));
01395 fprintf (file, "\tadd %s,%s," HOST_WIDE_INT_PRINT_DEC "\n",
01396 sp_str, sp_str, size - restored);
01397 }
01398 else
01399 fprintf (file, "\tnop\n");
01400 }
01401
01402
01403 current_frame_info = zero_frame_info;
01404 arc_compute_function_type (NULL_TREE);
01405 }
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415 int
01416 arc_delay_slots_for_epilogue (void)
01417 {
01418 if (arc_compute_function_type (current_function_decl) != ARC_FUNCTION_NORMAL)
01419 return 0;
01420 if (!current_frame_info.initialized)
01421 (void) arc_compute_frame_size (get_frame_size ());
01422 if (current_frame_info.total_size == 0)
01423 return 1;
01424 return 0;
01425 }
01426
01427
01428
01429
01430
01431 int
01432 arc_eligible_for_epilogue_delay (rtx trial, int slot)
01433 {
01434 gcc_assert (!slot);
01435
01436 if (get_attr_length (trial) == 1
01437
01438
01439
01440
01441
01442
01443
01444 && current_frame_info.gmask == 0
01445 && ! reg_mentioned_p (stack_pointer_rtx, PATTERN (trial))
01446 && ! reg_mentioned_p (frame_pointer_rtx, PATTERN (trial)))
01447 return 1;
01448 return 0;
01449 }
01450
01451
01452
01453 int
01454 shift_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01455 {
01456 switch (GET_CODE (op))
01457 {
01458 case ASHIFTRT:
01459 case LSHIFTRT:
01460 case ASHIFT:
01461 return 1;
01462 default:
01463 return 0;
01464 }
01465 }
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481 const char *
01482 output_shift (rtx *operands)
01483 {
01484 rtx shift = operands[3];
01485 enum machine_mode mode = GET_MODE (shift);
01486 enum rtx_code code = GET_CODE (shift);
01487 const char *shift_one;
01488
01489 gcc_assert (mode == SImode);
01490
01491 switch (code)
01492 {
01493 case ASHIFT: shift_one = "asl %0,%0"; break;
01494 case ASHIFTRT: shift_one = "asr %0,%0"; break;
01495 case LSHIFTRT: shift_one = "lsr %0,%0"; break;
01496 default: gcc_unreachable ();
01497 }
01498
01499 if (GET_CODE (operands[2]) != CONST_INT)
01500 {
01501 if (optimize)
01502 {
01503 output_asm_insn ("sub.f 0,%2,0", operands);
01504 output_asm_insn ("mov lp_count,%2", operands);
01505 output_asm_insn ("bz 2f", operands);
01506 }
01507 else
01508 output_asm_insn ("mov %4,%2", operands);
01509 goto shiftloop;
01510 }
01511 else
01512 {
01513 int n = INTVAL (operands[2]);
01514
01515
01516 if (n < 0)
01517 n = 0;
01518
01519
01520
01521 else if (n > GET_MODE_BITSIZE (mode))
01522 n = GET_MODE_BITSIZE (mode);
01523
01524
01525 if (n <= 8)
01526 {
01527 while (--n >= 0)
01528 output_asm_insn (shift_one, operands);
01529 }
01530
01531 else if (n == BITS_PER_WORD - 1)
01532 {
01533 switch (code)
01534 {
01535 case ASHIFT :
01536 output_asm_insn ("and %0,%0,1\n\tror %0,%0", operands);
01537 break;
01538 case ASHIFTRT :
01539
01540 output_asm_insn ("asl.f 0,%0\n\tsbc %0,0,0", operands);
01541 break;
01542 case LSHIFTRT :
01543
01544 output_asm_insn ("asl.f 0,%0\n\tadc %0,0,0", operands);
01545 break;
01546 default:
01547 break;
01548 }
01549 }
01550
01551 else
01552 {
01553 char buf[100];
01554
01555 if (optimize)
01556 output_asm_insn ("mov lp_count,%c2", operands);
01557 else
01558 output_asm_insn ("mov %4,%c2", operands);
01559 shiftloop:
01560 if (optimize)
01561 {
01562 if (flag_pic)
01563 sprintf (buf, "lr %%4,[status]\n\tadd %%4,%%4,6\t%s single insn loop start",
01564 ASM_COMMENT_START);
01565 else
01566 sprintf (buf, "mov %%4,%%%%st(1f)\t%s (single insn loop start) >> 2",
01567 ASM_COMMENT_START);
01568 output_asm_insn (buf, operands);
01569 output_asm_insn ("sr %4,[lp_start]", operands);
01570 output_asm_insn ("add %4,%4,1", operands);
01571 output_asm_insn ("sr %4,[lp_end]", operands);
01572 output_asm_insn ("nop\n\tnop", operands);
01573 if (flag_pic)
01574 fprintf (asm_out_file, "\t%s single insn loop\n",
01575 ASM_COMMENT_START);
01576 else
01577 fprintf (asm_out_file, "1:\t%s single insn loop\n",
01578 ASM_COMMENT_START);
01579 output_asm_insn (shift_one, operands);
01580 fprintf (asm_out_file, "2:\t%s end single insn loop\n",
01581 ASM_COMMENT_START);
01582 }
01583 else
01584 {
01585 fprintf (asm_out_file, "1:\t%s begin shift loop\n",
01586 ASM_COMMENT_START);
01587 output_asm_insn ("sub.f %4,%4,1", operands);
01588 output_asm_insn ("nop", operands);
01589 output_asm_insn ("bn.nd 2f", operands);
01590 output_asm_insn (shift_one, operands);
01591 output_asm_insn ("b.nd 1b", operands);
01592 fprintf (asm_out_file, "2:\t%s end shift loop\n",
01593 ASM_COMMENT_START);
01594 }
01595 }
01596 }
01597
01598 return "";
01599 }
01600
01601
01602
01603
01604
01605
01606
01607 void
01608 arc_initialize_trampoline (rtx tramp ATTRIBUTE_UNUSED,
01609 rtx fnaddr ATTRIBUTE_UNUSED,
01610 rtx cxt ATTRIBUTE_UNUSED)
01611 {
01612 }
01613
01614
01615
01616
01617 static void
01618 arc_file_start (void)
01619 {
01620 default_file_start ();
01621 fprintf (asm_out_file, "\t.cpu %s\n", arc_cpu_string);
01622 }
01623
01624
01625
01626
01627
01628 void
01629 arc_print_operand (FILE *file, rtx x, int code)
01630 {
01631 switch (code)
01632 {
01633 case '#' :
01634
01635 case '*' :
01636
01637 if (!final_sequence || XVECLEN (final_sequence, 0) == 1)
01638 {
01639
01640 fputs (".nd", file);
01641 }
01642 else
01643 {
01644 rtx jump = XVECEXP (final_sequence, 0, 0);
01645 rtx delay = XVECEXP (final_sequence, 0, 1);
01646 if (INSN_ANNULLED_BRANCH_P (jump))
01647 fputs (INSN_FROM_TARGET_P (delay) ? ".jd" : ".nd", file);
01648 else
01649 fputs (".d", file);
01650 }
01651 return;
01652 case '?' :
01653 case '!' :
01654
01655
01656 if (arc_ccfsm_state == 3 || arc_ccfsm_state == 4)
01657 {
01658
01659 if (final_sequence && XVECLEN (final_sequence, 0) == 2)
01660 {
01661 rtx insn = XVECEXP (final_sequence, 0, 1);
01662
01663
01664
01665 if (INSN_ANNULLED_BRANCH_P (insn))
01666 {
01667 if (INSN_FROM_TARGET_P (insn))
01668 fprintf (file, "%s%s",
01669 code == '?' ? "." : "",
01670 arc_condition_codes[ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current_cc)]);
01671 else
01672 fprintf (file, "%s%s",
01673 code == '?' ? "." : "",
01674 arc_condition_codes[arc_ccfsm_current_cc]);
01675 }
01676 else
01677 {
01678
01679
01680 ;
01681 }
01682 }
01683 else
01684 {
01685
01686 fprintf (file, "%s%s",
01687 code == '?' ? "." : "",
01688 arc_condition_codes[arc_ccfsm_current_cc]);
01689 }
01690 }
01691 return;
01692 case '~' :
01693
01694
01695 if (last_insn_set_cc_p)
01696 fputs ("nop\n\t", file);
01697 return;
01698 case 'd' :
01699 fputs (arc_condition_codes[get_arc_condition_code (x)], file);
01700 return;
01701 case 'D' :
01702 fputs (arc_condition_codes[ARC_INVERSE_CONDITION_CODE
01703 (get_arc_condition_code (x))],
01704 file);
01705 return;
01706 case 'R' :
01707
01708
01709 if (GET_CODE (x) == REG)
01710 fputs (reg_names[REGNO (x)+1], file);
01711 else if (GET_CODE (x) == MEM)
01712 {
01713 fputc ('[', file);
01714
01715
01716
01717
01718 if (GET_CODE (XEXP (x, 0)) == PRE_INC
01719 || GET_CODE (XEXP (x, 0)) == PRE_DEC)
01720 output_address (plus_constant (XEXP (XEXP (x, 0), 0), 4));
01721 else
01722 output_address (plus_constant (XEXP (x, 0), 4));
01723 fputc (']', file);
01724 }
01725 else
01726 output_operand_lossage ("invalid operand to %%R code");
01727 return;
01728 case 'S' :
01729 if ((GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (x))
01730 || GET_CODE (x) == LABEL_REF)
01731 {
01732 fprintf (file, "%%st(");
01733 output_addr_const (file, x);
01734 fprintf (file, ")");
01735 return;
01736 }
01737 break;
01738 case 'H' :
01739 case 'L' :
01740 if (GET_CODE (x) == REG)
01741 {
01742
01743 if ((TARGET_BIG_ENDIAN != 0) ^ (code == 'L'))
01744 fputs (reg_names[REGNO (x)], file);
01745 else
01746 fputs (reg_names[REGNO (x)+1], file);
01747 }
01748 else if (GET_CODE (x) == CONST_INT
01749 || GET_CODE (x) == CONST_DOUBLE)
01750 {
01751 rtx first, second;
01752
01753 split_double (x, &first, &second);
01754 fprintf (file, "0x%08lx",
01755 (long)(code == 'L' ? INTVAL (first) : INTVAL (second)));
01756 }
01757 else
01758 output_operand_lossage ("invalid operand to %%H/%%L code");
01759 return;
01760 case 'A' :
01761 {
01762 char str[30];
01763
01764 gcc_assert (GET_CODE (x) == CONST_DOUBLE
01765 && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT);
01766
01767 real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (x), sizeof (str), 0, 1);
01768 fprintf (file, "%s", str);
01769 return;
01770 }
01771 case 'U' :
01772
01773 if (GET_CODE (x) == MEM)
01774 {
01775 if (GET_CODE (XEXP (x, 0)) == PRE_INC
01776 || GET_CODE (XEXP (x, 0)) == PRE_DEC)
01777 fputs (".a", file);
01778 }
01779 else
01780 output_operand_lossage ("invalid operand to %%U code");
01781 return;
01782 case 'V' :
01783
01784
01785 if (GET_CODE (x) == MEM)
01786 {
01787 if (MEM_VOLATILE_P (x))
01788 fputs (".di", file);
01789 }
01790 else
01791 output_operand_lossage ("invalid operand to %%V code");
01792 return;
01793 case 0 :
01794
01795 break;
01796 default :
01797
01798 output_operand_lossage ("invalid operand output code");
01799 }
01800
01801 switch (GET_CODE (x))
01802 {
01803 case REG :
01804 fputs (reg_names[REGNO (x)], file);
01805 break;
01806 case MEM :
01807 fputc ('[', file);
01808 if (GET_CODE (XEXP (x, 0)) == PRE_INC)
01809 output_address (plus_constant (XEXP (XEXP (x, 0), 0),
01810 GET_MODE_SIZE (GET_MODE (x))));
01811 else if (GET_CODE (XEXP (x, 0)) == PRE_DEC)
01812 output_address (plus_constant (XEXP (XEXP (x, 0), 0),
01813 - GET_MODE_SIZE (GET_MODE (x))));
01814 else
01815 output_address (XEXP (x, 0));
01816 fputc (']', file);
01817 break;
01818 case CONST_DOUBLE :
01819
01820 if (GET_MODE (x) == SFmode)
01821 {
01822 REAL_VALUE_TYPE d;
01823 long l;
01824
01825 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
01826 REAL_VALUE_TO_TARGET_SINGLE (d, l);
01827 fprintf (file, "0x%08lx", l);
01828 break;
01829 }
01830
01831 default :
01832 output_addr_const (file, x);
01833 break;
01834 }
01835 }
01836
01837
01838
01839 void
01840 arc_print_operand_address (FILE *file, rtx addr)
01841 {
01842 register rtx base, index = 0;
01843 int offset = 0;
01844
01845 switch (GET_CODE (addr))
01846 {
01847 case REG :
01848 fputs (reg_names[REGNO (addr)], file);
01849 break;
01850 case SYMBOL_REF :
01851 if ( 0 && SYMBOL_REF_FUNCTION_P (addr))
01852 {
01853 fprintf (file, "%%st(");
01854 output_addr_const (file, addr);
01855 fprintf (file, ")");
01856 }
01857 else
01858 output_addr_const (file, addr);
01859 break;
01860 case PLUS :
01861 if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
01862 offset = INTVAL (XEXP (addr, 0)), base = XEXP (addr, 1);
01863 else if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
01864 offset = INTVAL (XEXP (addr, 1)), base = XEXP (addr, 0);
01865 else
01866 base = XEXP (addr, 0), index = XEXP (addr, 1);
01867 gcc_assert (GET_CODE (base) == REG);
01868 fputs (reg_names[REGNO (base)], file);
01869 if (index == 0)
01870 {
01871 if (offset != 0)
01872 fprintf (file, ",%d", offset);
01873 }
01874 else
01875 {
01876 switch (GET_CODE (index))
01877 {
01878 case REG:
01879 fprintf (file, ",%s", reg_names[REGNO (index)]);
01880 break;
01881 case SYMBOL_REF:
01882 fputc (',', file), output_addr_const (file, index);
01883 break;
01884 default:
01885 gcc_unreachable ();
01886 }
01887 }
01888 break;
01889 case PRE_INC :
01890 case PRE_DEC :
01891
01892
01893 gcc_unreachable ();
01894 break;
01895 default :
01896 output_addr_const (file, addr);
01897 break;
01898 }
01899 }
01900
01901
01902
01903 static void
01904 record_cc_ref (rtx insn)
01905 {
01906 last_insn_set_cc_p = current_insn_set_cc_p;
01907
01908 switch (get_attr_cond (insn))
01909 {
01910 case COND_SET :
01911 case COND_SET_ZN :
01912 case COND_SET_ZNC :
01913 if (get_attr_length (insn) == 1)
01914 current_insn_set_cc_p = 1;
01915 else
01916 current_insn_set_cc_p = 0;
01917 break;
01918 default :
01919 current_insn_set_cc_p = 0;
01920 break;
01921 }
01922 }
01923
01924
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959 void
01960 arc_final_prescan_insn (rtx insn,
01961 rtx *opvec ATTRIBUTE_UNUSED,
01962 int noperands ATTRIBUTE_UNUSED)
01963 {
01964
01965 register rtx body = PATTERN (insn);
01966
01967
01968
01969 int reverse = 0;
01970
01971
01972 int seeking_return = 0;
01973
01974
01975
01976 rtx start_insn = insn;
01977
01978
01979 record_cc_ref (insn);
01980
01981
01982
01983
01984 if (optimize < 2 || TARGET_NO_COND_EXEC)
01985 return;
01986
01987
01988
01989 if (arc_ccfsm_state == 4)
01990 {
01991 if (insn == arc_ccfsm_target_insn)
01992 {
01993 arc_ccfsm_target_insn = NULL;
01994 arc_ccfsm_state = 0;
01995 }
01996 return;
01997 }
01998
01999
02000
02001
02002
02003
02004 if (arc_ccfsm_state == 3)
02005 {
02006 if (simplejump_p (insn))
02007 {
02008 start_insn = next_nonnote_insn (start_insn);
02009 if (GET_CODE (start_insn) == BARRIER)
02010 {
02011
02012 start_insn = next_nonnote_insn (start_insn);
02013 }
02014 if (GET_CODE (start_insn) == CODE_LABEL
02015 && CODE_LABEL_NUMBER (start_insn) == arc_ccfsm_target_label
02016 && LABEL_NUSES (start_insn) == 1)
02017 reverse = TRUE;
02018 else
02019 return;
02020 }
02021 else if (GET_CODE (body) == RETURN)
02022 {
02023 start_insn = next_nonnote_insn (start_insn);
02024 if (GET_CODE (start_insn) == BARRIER)
02025 start_insn = next_nonnote_insn (start_insn);
02026 if (GET_CODE (start_insn) == CODE_LABEL
02027 && CODE_LABEL_NUMBER (start_insn) == arc_ccfsm_target_label
02028 && LABEL_NUSES (start_insn) == 1)
02029 {
02030 reverse = TRUE;
02031 seeking_return = 1;
02032 }
02033 else
02034 return;
02035 }
02036 else
02037 return;
02038 }
02039
02040 if (GET_CODE (insn) != JUMP_INSN)
02041 return;
02042
02043
02044
02045 if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0) > 0)
02046 body = XVECEXP (body, 0, 0);
02047
02048 if (reverse
02049 || (GET_CODE (body) == SET && GET_CODE (SET_DEST (body)) == PC
02050 && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE))
02051 {
02052 int insns_skipped = 0, fail = FALSE, succeed = FALSE;
02053
02054 int then_not_else = TRUE;
02055
02056 int next_must_be_target_label_p;
02057 rtx this_insn = start_insn, label = 0;
02058
02059
02060 if (reverse)
02061 {
02062 if (!seeking_return)
02063 label = XEXP (SET_SRC (body), 0);
02064 }
02065 else if (GET_CODE (XEXP (SET_SRC (body), 1)) == LABEL_REF)
02066 label = XEXP (XEXP (SET_SRC (body), 1), 0);
02067 else if (GET_CODE (XEXP (SET_SRC (body), 2)) == LABEL_REF)
02068 {
02069 label = XEXP (XEXP (SET_SRC (body), 2), 0);
02070 then_not_else = FALSE;
02071 }
02072 else if (GET_CODE (XEXP (SET_SRC (body), 1)) == RETURN)
02073 seeking_return = 1;
02074 else if (GET_CODE (XEXP (SET_SRC (body), 2)) == RETURN)
02075 {
02076 seeking_return = 1;
02077 then_not_else = FALSE;
02078 }
02079 else
02080 gcc_unreachable ();
02081
02082
02083
02084
02085 for (insns_skipped = 0, next_must_be_target_label_p = FALSE;
02086 !fail && !succeed && insns_skipped < MAX_INSNS_SKIPPED;
02087 insns_skipped++)
02088 {
02089 rtx scanbody;
02090
02091 this_insn = next_nonnote_insn (this_insn);
02092 if (!this_insn)
02093 break;
02094
02095 if (next_must_be_target_label_p)
02096 {
02097 if (GET_CODE (this_insn) == BARRIER)
02098 continue;
02099 if (GET_CODE (this_insn) == CODE_LABEL
02100 && this_insn == label)
02101 {
02102 arc_ccfsm_state = 1;
02103 succeed = TRUE;
02104 }
02105 else
02106 fail = TRUE;
02107 break;
02108 }
02109
02110 scanbody = PATTERN (this_insn);
02111
02112 switch (GET_CODE (this_insn))
02113 {
02114 case CODE_LABEL:
02115
02116
02117 if (this_insn == label)
02118 {
02119 arc_ccfsm_state = 1;
02120 succeed = TRUE;
02121 }
02122 else
02123 fail = TRUE;
02124 break;
02125
02126 case BARRIER:
02127
02128
02129
02130
02131 next_must_be_target_label_p = TRUE;
02132 break;
02133
02134 case CALL_INSN:
02135
02136
02137
02138
02139 if (get_attr_cond (this_insn) == COND_CANUSE)
02140 next_must_be_target_label_p = TRUE;
02141 else
02142 fail = TRUE;
02143 break;
02144
02145 case JUMP_INSN:
02146
02147
02148
02149
02150
02151 if (GET_CODE (scanbody) == SET
02152 && GET_CODE (SET_DEST (scanbody)) == PC)
02153 {
02154 if (GET_CODE (SET_SRC (scanbody)) == LABEL_REF
02155 && XEXP (SET_SRC (scanbody), 0) == label && !reverse)
02156 {
02157 arc_ccfsm_state = 2;
02158 succeed = TRUE;
02159 }
02160 else if (GET_CODE (SET_SRC (scanbody)) == IF_THEN_ELSE)
02161 fail = TRUE;
02162 }
02163 else if (GET_CODE (scanbody) == RETURN
02164 && seeking_return)
02165 {
02166 arc_ccfsm_state = 2;
02167 succeed = TRUE;
02168 }
02169 else if (GET_CODE (scanbody) == PARALLEL)
02170 {
02171 if (get_attr_cond (this_insn) != COND_CANUSE)
02172 fail = TRUE;
02173 }
02174 break;
02175
02176 case INSN:
02177
02178
02179 if (GET_CODE (scanbody) == SET
02180 || GET_CODE (scanbody) == PARALLEL)
02181 {
02182 if (get_attr_cond (this_insn) != COND_CANUSE)
02183 fail = TRUE;
02184 }
02185
02186 else
02187 fail = TRUE;
02188 break;
02189
02190 default:
02191 break;
02192 }
02193 }
02194
02195 if (succeed)
02196 {
02197 if ((!seeking_return) && (arc_ccfsm_state == 1 || reverse))
02198 arc_ccfsm_target_label = CODE_LABEL_NUMBER (label);
02199 else
02200 {
02201 gcc_assert (seeking_return || arc_ccfsm_state == 2);
02202 while (this_insn && GET_CODE (PATTERN (this_insn)) == USE)
02203 {
02204 this_insn = next_nonnote_insn (this_insn);
02205 gcc_assert (!this_insn
02206 || (GET_CODE (this_insn) != BARRIER
02207 && GET_CODE (this_insn) != CODE_LABEL));
02208 }
02209 if (!this_insn)
02210 {
02211
02212 extract_insn_cached (insn);
02213 arc_ccfsm_state = 0;
02214 arc_ccfsm_target_insn = NULL;
02215 return;
02216 }
02217 arc_ccfsm_target_insn = this_insn;
02218 }
02219
02220
02221
02222 if (!reverse)
02223 arc_ccfsm_current_cc = get_arc_condition_code (XEXP (SET_SRC (body),
02224 0));
02225
02226 if (reverse || then_not_else)
02227 arc_ccfsm_current_cc = ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current_cc);
02228 }
02229
02230
02231
02232
02233 extract_insn_cached (insn);
02234 }
02235 }
02236
02237
02238
02239
02240
02241
02242 void
02243 arc_ccfsm_at_label (const char *prefix, int num)
02244 {
02245 if (arc_ccfsm_state == 3 && arc_ccfsm_target_label == num
02246 && !strcmp (prefix, "L"))
02247 {
02248 arc_ccfsm_state = 0;
02249 arc_ccfsm_target_insn = NULL_RTX;
02250 }
02251 }
02252
02253
02254
02255
02256 int
02257 arc_ccfsm_branch_deleted_p (void)
02258 {
02259 if (arc_ccfsm_state == 1 || arc_ccfsm_state == 2)
02260 return 1;
02261 return 0;
02262 }
02263
02264
02265
02266
02267 void
02268 arc_ccfsm_record_branch_deleted (void)
02269 {
02270
02271 arc_ccfsm_state += 2;
02272
02273
02274
02275
02276 current_insn_set_cc_p = last_insn_set_cc_p;
02277 }
02278
02279 void
02280 arc_va_start (tree valist, rtx nextarg)
02281 {
02282
02283 if (current_function_args_info < 8
02284 && (current_function_args_info & 1))
02285 nextarg = plus_constant (nextarg, UNITS_PER_WORD);
02286
02287 std_expand_builtin_va_start (valist, nextarg);
02288 }
02289
02290
02291
02292
02293 static void
02294 arc_internal_label (FILE *stream, const char *prefix, unsigned long labelno)
02295 {
02296 arc_ccfsm_at_label (prefix, labelno);
02297 default_internal_label (stream, prefix, labelno);
02298 }
02299
02300
02301
02302 static void
02303 arc_external_libcall (rtx fun ATTRIBUTE_UNUSED)
02304 {
02305 #if 0
02306
02307
02308
02309 if (TARGET_MANGLE_CPU_LIBGCC)
02310 {
02311 fprintf (FILE, "\t.rename\t_%s, _%s%s\n",
02312 XSTR (SYMREF, 0), XSTR (SYMREF, 0),
02313 arc_mangle_suffix);
02314 }
02315 #endif
02316 }
02317
02318
02319
02320 static bool
02321 arc_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
02322 {
02323 if (AGGREGATE_TYPE_P (type))
02324 return true;
02325 else
02326 {
02327 HOST_WIDE_INT size = int_size_in_bytes (type);
02328 return (size == -1 || size > 8);
02329 }
02330 }
02331
02332
02333
02334
02335 static bool
02336 arc_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
02337 enum machine_mode mode, tree type,
02338 bool named ATTRIBUTE_UNUSED)
02339 {
02340 unsigned HOST_WIDE_INT size;
02341
02342 if (type)
02343 {
02344 if (AGGREGATE_TYPE_P (type))
02345 return true;
02346 size = int_size_in_bytes (type);
02347 }
02348 else
02349 size = GET_MODE_SIZE (mode);
02350
02351 return size > 8;
02352 }