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