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