00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025 #include "coretypes.h"
00026 #include "tm.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 "insn-attr.h"
00034 #include "flags.h"
00035 #include "tree.h"
00036 #include "expr.h"
00037 #include "except.h"
00038 #include "function.h"
00039 #include "toplev.h"
00040 #include "recog.h"
00041 #include "tm_p.h"
00042 #include "debug.h"
00043 #include "output.h"
00044 #include "target.h"
00045 #include "target-def.h"
00046 #include "ggc.h"
00047 #include "optabs.h"
00048
00049
00050
00051 #define ADDITIVE_SIZE_MODIFIER(size) \
00052 ((size) <= 63 ? "q" : (size) <= 255 ? "u.b" : (size) <= 65535 ? "u.w" : ".d")
00053
00054 #define ASSERT_PLT_UNSPEC(x) \
00055 do \
00056 { \
00057 if (XEXP (x, 1) != NULL_RTX \
00058 || (GET_CODE (XVECEXP (x, 0, 0)) != SYMBOL_REF \
00059 && GET_CODE (XVECEXP (x, 0, 0)) != LABEL_REF)) \
00060 abort (); \
00061 } while (0)
00062
00063 #define LOSE_AND_RETURN(msgid, x) \
00064 do \
00065 { \
00066 cris_operand_lossage (msgid, x); \
00067 return; \
00068 } while (0)
00069
00070
00071 struct machine_function GTY(())
00072 {
00073 int needs_return_address_on_stack;
00074 };
00075
00076
00077
00078 static char cris_output_insn_is_bound = 0;
00079
00080
00081
00082
00083
00084 static int cris_pic_sympart_only = 0;
00085
00086
00087
00088 static int in_code = 0;
00089
00090
00091 static int cris_reg_overlap_mentioned_p (rtx, rtx);
00092
00093 static void cris_print_base (rtx, FILE *);
00094
00095 static void cris_print_index (rtx, FILE *);
00096
00097 static void cris_output_addr_const (FILE *, rtx);
00098
00099 static struct machine_function * cris_init_machine_status (void);
00100
00101 static rtx cris_struct_value_rtx (tree, int);
00102
00103 static void cris_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
00104 tree type, int *, int);
00105
00106 static int cris_initial_frame_pointer_offset (void);
00107
00108 static int saved_regs_mentioned (rtx);
00109
00110 static void cris_target_asm_function_prologue (FILE *, HOST_WIDE_INT);
00111
00112 static void cris_target_asm_function_epilogue (FILE *, HOST_WIDE_INT);
00113
00114 static void cris_operand_lossage (const char *, rtx);
00115
00116 static void cris_asm_output_mi_thunk
00117 (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT, tree);
00118
00119 static void cris_file_start (void);
00120 static void cris_init_libfuncs (void);
00121
00122 static bool cris_rtx_costs (rtx, int, int, int *);
00123 static int cris_address_cost (rtx);
00124 static bool cris_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
00125 tree, bool);
00126 static int cris_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
00127 tree, bool);
00128
00129
00130
00131
00132 static char save_last[80];
00133
00134
00135 const char *cris_max_stackframe_str;
00136
00137
00138 const char *cris_cpu_str;
00139
00140
00141 const char *cris_tune_str;
00142
00143
00144 const char *cris_elinux_stacksize_str;
00145
00146
00147
00148 int cris_max_stackframe = 0;
00149
00150
00151 int cris_cpu_version = CRIS_DEFAULT_CPU_VERSION;
00152
00153 #undef TARGET_ASM_ALIGNED_HI_OP
00154 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
00155 #undef TARGET_ASM_ALIGNED_SI_OP
00156 #define TARGET_ASM_ALIGNED_SI_OP "\t.dword\t"
00157 #undef TARGET_ASM_ALIGNED_DI_OP
00158 #define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"
00159
00160
00161
00162
00163 #undef TARGET_ASM_UNALIGNED_HI_OP
00164 #define TARGET_ASM_UNALIGNED_HI_OP TARGET_ASM_ALIGNED_HI_OP
00165
00166 #undef TARGET_ASM_UNALIGNED_SI_OP
00167 #define TARGET_ASM_UNALIGNED_SI_OP TARGET_ASM_ALIGNED_SI_OP
00168
00169 #undef TARGET_ASM_UNALIGNED_DI_OP
00170 #define TARGET_ASM_UNALIGNED_DI_OP TARGET_ASM_ALIGNED_DI_OP
00171
00172 #undef TARGET_ASM_FUNCTION_PROLOGUE
00173 #define TARGET_ASM_FUNCTION_PROLOGUE cris_target_asm_function_prologue
00174
00175 #undef TARGET_ASM_FUNCTION_EPILOGUE
00176 #define TARGET_ASM_FUNCTION_EPILOGUE cris_target_asm_function_epilogue
00177
00178 #undef TARGET_ASM_OUTPUT_MI_THUNK
00179 #define TARGET_ASM_OUTPUT_MI_THUNK cris_asm_output_mi_thunk
00180 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
00181 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
00182
00183 #undef TARGET_ASM_FILE_START
00184 #define TARGET_ASM_FILE_START cris_file_start
00185
00186 #undef TARGET_INIT_LIBFUNCS
00187 #define TARGET_INIT_LIBFUNCS cris_init_libfuncs
00188
00189 #undef TARGET_RTX_COSTS
00190 #define TARGET_RTX_COSTS cris_rtx_costs
00191 #undef TARGET_ADDRESS_COST
00192 #define TARGET_ADDRESS_COST cris_address_cost
00193
00194 #undef TARGET_PROMOTE_FUNCTION_ARGS
00195 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
00196 #undef TARGET_STRUCT_VALUE_RTX
00197 #define TARGET_STRUCT_VALUE_RTX cris_struct_value_rtx
00198 #undef TARGET_SETUP_INCOMING_VARARGS
00199 #define TARGET_SETUP_INCOMING_VARARGS cris_setup_incoming_varargs
00200 #undef TARGET_PASS_BY_REFERENCE
00201 #define TARGET_PASS_BY_REFERENCE cris_pass_by_reference
00202 #undef TARGET_ARG_PARTIAL_BYTES
00203 #define TARGET_ARG_PARTIAL_BYTES cris_arg_partial_bytes
00204
00205 struct gcc_target targetm = TARGET_INITIALIZER;
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 int
00217 cris_bdap_operand (rtx op, enum machine_mode mode)
00218 {
00219 register enum rtx_code code = GET_CODE (op);
00220
00221 if (mode != SImode && (mode != VOIDmode || GET_MODE (op) != VOIDmode))
00222 return 0;
00223
00224
00225 if (register_operand (op, mode)
00226 || (CONSTANT_P (op) && !(flag_pic && cris_symbol (op))))
00227 return 1;
00228
00229
00230 if (code == MEM)
00231 {
00232 rtx tem = XEXP (op, 0);
00233
00234 if (mode == SImode
00235 && (register_operand (tem, SImode)
00236 || (GET_CODE (tem) == POST_INC
00237 && register_operand (XEXP (tem, 0), SImode))))
00238 return 1;
00239 else
00240 return 0;
00241 }
00242
00243
00244 if (code == SIGN_EXTEND)
00245 {
00246 rtx tem = XEXP (op, 0);
00247
00248 if (GET_CODE (tem) != MEM)
00249 return 0;
00250
00251 tem = XEXP (tem, 0);
00252 if (mode == SImode
00253 && (register_operand (tem, SImode)
00254 || (GET_CODE (tem) == POST_INC
00255 && register_operand (XEXP (tem, 0), SImode))))
00256 return 1;
00257 else
00258 return 0;
00259 }
00260
00261 return 0;
00262 }
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273 int
00274 cris_bdap_biap_operand (rtx op, enum machine_mode mode)
00275 {
00276 register enum rtx_code code = GET_CODE (op);
00277 rtx reg;
00278 rtx val;
00279
00280
00281 if (cris_bdap_operand (op, mode))
00282 return 1;
00283
00284 if (mode != SImode && (mode != VOIDmode || GET_MODE (op) != VOIDmode))
00285 return 0;
00286
00287
00288 if (code != MULT)
00289 return 0;
00290
00291
00292 if (GET_CODE (XEXP (op, 0)) == CONST_INT)
00293 {
00294 val = XEXP (op, 0);
00295 reg = XEXP (op, 1);
00296 }
00297 else
00298 {
00299 val = XEXP (op, 1);
00300 reg = XEXP (op, 0);
00301 }
00302
00303
00304 if (! register_operand (reg, SImode) || GET_CODE (val) != CONST_INT)
00305 return 0;
00306
00307
00308 if ((code == MULT
00309 && (INTVAL (val) == 1 || INTVAL (val) == 2 || INTVAL (val) == 4)))
00310 return 1;
00311
00312 return 0;
00313 }
00314
00315
00316
00317
00318 int
00319 cris_orthogonal_operator (rtx x, enum machine_mode mode)
00320 {
00321 enum rtx_code code = GET_CODE (x);
00322
00323 if (mode == VOIDmode)
00324 mode = GET_MODE (x);
00325
00326 return (GET_MODE (x) == mode
00327 && (code == PLUS || code == MINUS
00328 || code == IOR || code == AND || code == UMIN));
00329 }
00330
00331
00332
00333
00334 int
00335 cris_commutative_orth_op (rtx x, enum machine_mode mode)
00336 {
00337 enum rtx_code code = GET_CODE (x);
00338
00339 if (mode == VOIDmode)
00340 mode = GET_MODE (x);
00341
00342 return (GET_MODE (x) == mode &&
00343 (code == PLUS
00344 || code == IOR || code == AND || code == UMIN));
00345 }
00346
00347
00348
00349
00350
00351
00352 int
00353 cris_operand_extend_operator (rtx x, enum machine_mode mode)
00354 {
00355 enum rtx_code code = GET_CODE (x);
00356
00357 if (mode == VOIDmode)
00358 mode = GET_MODE (x);
00359
00360 return (GET_MODE (x) == mode
00361 && (code == PLUS || code == MINUS || code == UMIN));
00362 }
00363
00364
00365
00366 int
00367 cris_additive_operand_extend_operator (rtx x, enum machine_mode mode)
00368 {
00369 enum rtx_code code = GET_CODE (x);
00370
00371 if (mode == VOIDmode)
00372 mode = GET_MODE (x);
00373
00374 return (GET_MODE (x) == mode
00375 && (code == PLUS || code == MINUS));
00376 }
00377
00378
00379
00380
00381 int
00382 cris_extend_operator (rtx x, enum machine_mode mode)
00383 {
00384 enum rtx_code code = GET_CODE (x);
00385
00386 if (mode == VOIDmode)
00387 mode = GET_MODE (x);
00388
00389 return
00390 (GET_MODE (x) == mode && (code == SIGN_EXTEND || code == ZERO_EXTEND));
00391 }
00392
00393
00394
00395 int
00396 cris_plus_or_bound_operator (rtx x, enum machine_mode mode)
00397 {
00398 enum rtx_code code = GET_CODE (x);
00399
00400 if (mode == VOIDmode)
00401 mode = GET_MODE (x);
00402
00403 return
00404 (GET_MODE (x) == mode && (code == UMIN || code == PLUS));
00405 }
00406
00407
00408
00409
00410
00411 int
00412 cris_mem_op (rtx x, enum machine_mode mode)
00413 {
00414 if (mode == VOIDmode)
00415 mode = GET_MODE (x);
00416
00417 return GET_MODE (x) == mode && GET_CODE (x) == MEM;
00418 }
00419
00420
00421
00422
00423
00424 int
00425 cris_general_operand_or_symbol (rtx op, enum machine_mode mode)
00426 {
00427 return general_operand (op, mode)
00428 || (CONSTANT_P (op) && cris_symbol (op));
00429 }
00430
00431
00432
00433
00434
00435 int
00436 cris_general_operand_or_gotless_symbol (rtx op, enum machine_mode mode)
00437 {
00438 return general_operand (op, mode)
00439 || (CONSTANT_P (op) && cris_gotless_symbol (op));
00440 }
00441
00442
00443
00444
00445
00446 int
00447 cris_general_operand_or_plt_symbol (rtx op, enum machine_mode mode)
00448 {
00449 return general_operand (op, mode)
00450 || (GET_CODE (op) == CONST
00451 && GET_CODE (XEXP (op, 0)) == UNSPEC
00452 && !TARGET_AVOID_GOTPLT);
00453 }
00454
00455
00456
00457
00458
00459
00460
00461 int
00462 cris_mem_call_operand (rtx op, enum machine_mode mode)
00463 {
00464 rtx xmem;
00465
00466 if (GET_CODE (op) != MEM)
00467 return 0;
00468
00469 if (memory_operand (op, mode))
00470 return 1;
00471
00472 xmem = XEXP (op, 0);
00473
00474 return cris_general_operand_or_symbol (xmem, GET_MODE (op));
00475 }
00476
00477
00478
00479 void
00480 cris_conditional_register_usage (void)
00481 {
00482
00483
00484 if (flag_pic)
00485 fixed_regs[PIC_OFFSET_TABLE_REGNUM]
00486 = call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
00487 }
00488
00489
00490
00491
00492 int
00493 cris_cfun_uses_pic_table (void)
00494 {
00495 return current_function_uses_pic_offset_table;
00496 }
00497
00498
00499
00500
00501
00502 const char *
00503 cris_op_str (rtx x)
00504 {
00505 cris_output_insn_is_bound = 0;
00506 switch (GET_CODE (x))
00507 {
00508 case PLUS:
00509 return "add";
00510 break;
00511
00512 case MINUS:
00513 return "sub";
00514 break;
00515
00516 case MULT:
00517
00518
00519
00520
00521 abort ();
00522 break;
00523
00524 case DIV:
00525 return "div";
00526 break;
00527
00528 case AND:
00529 return "and";
00530 break;
00531
00532 case IOR:
00533 return "or";
00534 break;
00535
00536 case XOR:
00537 return "xor";
00538 break;
00539
00540 case NOT:
00541 return "not";
00542 break;
00543
00544 case ASHIFT:
00545 return "lsl";
00546 break;
00547
00548 case LSHIFTRT:
00549 return "lsr";
00550 break;
00551
00552 case ASHIFTRT:
00553 return "asr";
00554 break;
00555
00556 case UMIN:
00557
00558
00559 cris_output_insn_is_bound = 1;
00560 return "bound";
00561 break;
00562
00563 default:
00564 return "Unknown operator";
00565 break;
00566 }
00567 }
00568
00569
00570
00571
00572
00573
00574 static void
00575 cris_operand_lossage (const char *msgid, rtx op)
00576 {
00577 debug_rtx (op);
00578 output_operand_lossage ("%s", msgid);
00579 }
00580
00581
00582
00583 static void
00584 cris_print_index (rtx index, FILE *file)
00585 {
00586 rtx inner = XEXP (index, 0);
00587
00588
00589
00590 if (GET_CODE (index) != CONST_INT || INTVAL (index) >= 0)
00591 putc ('+', file);
00592
00593 if (REG_P (index))
00594 fprintf (file, "$%s.b", reg_names[REGNO (index)]);
00595 else if (CONSTANT_P (index))
00596 cris_output_addr_const (file, index);
00597 else if (GET_CODE (index) == MULT)
00598 {
00599 fprintf (file, "$%s.",
00600 reg_names[REGNO (XEXP (index, 0))]);
00601
00602 putc (INTVAL (XEXP (index, 1)) == 2 ? 'w' : 'd', file);
00603 }
00604 else if (GET_CODE (index) == SIGN_EXTEND &&
00605 GET_CODE (inner) == MEM)
00606 {
00607 rtx inner_inner = XEXP (inner, 0);
00608
00609 if (GET_CODE (inner_inner) == POST_INC)
00610 {
00611 fprintf (file, "[$%s+].",
00612 reg_names[REGNO (XEXP (inner_inner, 0))]);
00613 putc (GET_MODE (inner) == HImode ? 'w' : 'b', file);
00614 }
00615 else
00616 {
00617 fprintf (file, "[$%s].", reg_names[REGNO (inner_inner)]);
00618
00619 putc (GET_MODE (inner) == HImode ? 'w' : 'b', file);
00620 }
00621 }
00622 else if (GET_CODE (index) == MEM)
00623 {
00624 if (GET_CODE (inner) == POST_INC)
00625 fprintf (file, "[$%s+].d", reg_names[REGNO (XEXP (inner, 0))]);
00626 else
00627 fprintf (file, "[$%s].d", reg_names[REGNO (inner)]);
00628 }
00629 else
00630 cris_operand_lossage ("unexpected index-type in cris_print_index",
00631 index);
00632 }
00633
00634
00635
00636 static void
00637 cris_print_base (rtx base, FILE *file)
00638 {
00639 if (REG_P (base))
00640 fprintf (file, "$%s", reg_names[REGNO (base)]);
00641 else if (GET_CODE (base) == POST_INC)
00642 fprintf (file, "$%s+", reg_names[REGNO (XEXP (base, 0))]);
00643 else
00644 cris_operand_lossage ("unexpected base-type in cris_print_base",
00645 base);
00646 }
00647
00648
00649
00650 int
00651 cris_fatal (char *arg)
00652 {
00653 internal_error (arg);
00654
00655
00656 return 0;
00657 }
00658
00659
00660
00661 static GTY(()) unsigned long cfa_label_num = 0;
00662
00663
00664
00665 static void
00666 cris_target_asm_function_prologue (FILE *file, HOST_WIDE_INT size)
00667 {
00668 int regno;
00669
00670
00671 int cfoa_size = current_function_outgoing_args_size;
00672 int last_movem_reg = -1;
00673 int doing_dwarf = dwarf2out_do_frame ();
00674 int framesize;
00675 int faked_args_size = 0;
00676 int cfa_write_offset = 0;
00677 static char cfa_label[30];
00678 int return_address_on_stack
00679 = regs_ever_live[CRIS_SRP_REGNUM]
00680 || cfun->machine->needs_return_address_on_stack != 0;
00681
00682
00683 if (!TARGET_PROLOGUE_EPILOGUE)
00684 return;
00685
00686 if (size < 0)
00687 abort ();
00688
00689
00690 if (TARGET_STACK_ALIGN)
00691 size = TARGET_ALIGN_BY_32 ? (size + 3) & ~3 : (size + 1) & ~1;
00692
00693 if (current_function_pretend_args_size)
00694 {
00695 int pretend = current_function_pretend_args_size;
00696 for (regno = CRIS_FIRST_ARG_REG + CRIS_MAX_ARGS_IN_REGS - 1;
00697 pretend > 0;
00698 regno--, pretend -= 4)
00699 {
00700 fprintf (file, "\tpush $%s\n", reg_names[regno]);
00701 faked_args_size += 4;
00702 }
00703 }
00704
00705 framesize = faked_args_size;
00706
00707 if (doing_dwarf)
00708 {
00709
00710
00711
00712
00713
00714
00715 int cfa_offset
00716 = faked_args_size
00717 + (return_address_on_stack ? 4 : 0)
00718 + (frame_pointer_needed ? 4 : 0);
00719
00720 int cfa_reg;
00721
00722 if (frame_pointer_needed)
00723 cfa_reg = FRAME_POINTER_REGNUM;
00724 else
00725 {
00726 cfa_reg = STACK_POINTER_REGNUM;
00727 cfa_offset += cris_initial_frame_pointer_offset ();
00728 }
00729
00730 ASM_GENERATE_INTERNAL_LABEL (cfa_label, "LCFIT",
00731 cfa_label_num++);
00732 dwarf2out_def_cfa (cfa_label, cfa_reg, cfa_offset);
00733
00734 cfa_write_offset = - faked_args_size - 4;
00735 }
00736
00737
00738 if (return_address_on_stack)
00739 {
00740 fprintf (file, "\tPush $srp\n");
00741 framesize += 4;
00742
00743 if (doing_dwarf)
00744 {
00745 dwarf2out_return_save (cfa_label, cfa_write_offset);
00746 cfa_write_offset -= 4;
00747 }
00748 }
00749
00750
00751 if (frame_pointer_needed)
00752 {
00753 fprintf (file, "\tpush $%s\n\tmove.d $sp,$%s\n",
00754 reg_names[FRAME_POINTER_REGNUM],
00755 reg_names[FRAME_POINTER_REGNUM]);
00756 framesize += 4;
00757
00758 if (doing_dwarf)
00759 {
00760 dwarf2out_reg_save (cfa_label, FRAME_POINTER_REGNUM,
00761 cfa_write_offset);
00762 cfa_write_offset -= 4;
00763 }
00764 }
00765
00766
00767 cfa_write_offset -= size;
00768
00769
00770
00771 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
00772 {
00773 if ((((regs_ever_live[regno]
00774 && !call_used_regs[regno])
00775 || (regno == (int) PIC_OFFSET_TABLE_REGNUM
00776 && (current_function_uses_pic_offset_table
00777
00778 || (flag_pic
00779 && regs_ever_live[regno + 1]
00780 && !call_used_regs[regno + 1]))))
00781 && (regno != FRAME_POINTER_REGNUM || !frame_pointer_needed)
00782 && regno != CRIS_SRP_REGNUM)
00783 || (current_function_calls_eh_return
00784 && (regno == EH_RETURN_DATA_REGNO (0)
00785 || regno == EH_RETURN_DATA_REGNO (1)
00786 || regno == EH_RETURN_DATA_REGNO (2)
00787 || regno == EH_RETURN_DATA_REGNO (3))))
00788 {
00789
00790 if (regno == last_movem_reg + 1)
00791
00792 last_movem_reg++;
00793 else
00794 {
00795
00796
00797 if (last_movem_reg != -1)
00798 {
00799
00800
00801
00802
00803 if ((last_movem_reg + 1) * 4 + size >= 64
00804 && (last_movem_reg + 1) * 4 + size <= 128
00805 && cris_cpu_version >= CRIS_CPU_SVINTO
00806 && TARGET_SIDE_EFFECT_PREFIXES)
00807 fprintf (file, "\tmovem $%s,[$sp=$sp-"HOST_WIDE_INT_PRINT_DEC"]\n",
00808 reg_names[last_movem_reg],
00809 (last_movem_reg + 1) * 4 + size);
00810 else
00811 {
00812
00813 fprintf (file, "\tsub%s "HOST_WIDE_INT_PRINT_DEC",$sp\n",
00814 ADDITIVE_SIZE_MODIFIER ((last_movem_reg + 1)
00815 * 4 + size),
00816 (last_movem_reg + 1) * 4 + size);
00817
00818 fprintf (file, "\tmovem $%s,[$sp]\n",
00819 reg_names[last_movem_reg]);
00820 }
00821
00822 framesize += (last_movem_reg + 1) * 4 + size;
00823
00824 if (TARGET_PDEBUG)
00825 fprintf (file, "; frame "HOST_WIDE_INT_PRINT_DEC
00826 ", #regs %d, bytes %d args %d\n",
00827 size,
00828 last_movem_reg + 1,
00829 (last_movem_reg + 1) * 4,
00830 current_function_args_size);
00831
00832 last_movem_reg = -1;
00833 size = 0;
00834 }
00835 else if (size > 0)
00836 {
00837
00838
00839 fprintf (file, "\tSub%s "HOST_WIDE_INT_PRINT_DEC",$sp\n",
00840 ADDITIVE_SIZE_MODIFIER (size),
00841 size);
00842 framesize += size;
00843 size = 0;
00844 }
00845
00846 fprintf (file, "\tPush $%s\n", reg_names[regno]);
00847 framesize += 4;
00848 }
00849
00850 if (doing_dwarf)
00851 {
00852
00853
00854
00855 dwarf2out_reg_save (cfa_label, regno, cfa_write_offset);
00856 cfa_write_offset -= 4;
00857 }
00858 }
00859 }
00860
00861
00862
00863 if (last_movem_reg != -1)
00864 {
00865
00866
00867
00868
00869
00870 if ((last_movem_reg + 1) * 4 + size >= 64
00871 && (last_movem_reg + 1) * 4 + size <= 128
00872 && cris_cpu_version >= CRIS_CPU_SVINTO
00873 && TARGET_SIDE_EFFECT_PREFIXES)
00874 fprintf (file, "\tmovem $%s,[$sp=$sp-"HOST_WIDE_INT_PRINT_DEC"]\n",
00875 reg_names[last_movem_reg],
00876 (last_movem_reg+1) * 4 + size);
00877 else
00878 {
00879
00880
00881 fprintf (file, "\tsub%s "HOST_WIDE_INT_PRINT_DEC",$sp\n",
00882 ADDITIVE_SIZE_MODIFIER ((last_movem_reg + 1) * 4 + size),
00883 (last_movem_reg + 1) * 4 + size);
00884
00885
00886
00887
00888 fprintf (file, "\tmovem $%s,[$sp]\n", reg_names[last_movem_reg]);
00889 }
00890
00891 framesize += (last_movem_reg + 1) * 4 + size;
00892
00893 if (TARGET_PDEBUG)
00894 fprintf (file, "; frame "HOST_WIDE_INT_PRINT_DEC
00895 ", #regs %d, bytes %d args %d\n",
00896 size,
00897 last_movem_reg + 1,
00898 (last_movem_reg + 1) * 4,
00899 current_function_args_size);
00900
00901
00902 if (cfoa_size)
00903 {
00904
00905
00906 fprintf (file, "\tSub%s %d,$sp\n",
00907 ADDITIVE_SIZE_MODIFIER (cfoa_size),
00908 cfoa_size);
00909 framesize += cfoa_size;
00910 }
00911 }
00912 else if ((size + cfoa_size) > 0)
00913 {
00914
00915
00916
00917 fprintf (file, "\tSub%s "HOST_WIDE_INT_PRINT_DEC",$sp\n",
00918 ADDITIVE_SIZE_MODIFIER (size + cfoa_size),
00919 cfoa_size + size);
00920 framesize += size + cfoa_size;
00921 }
00922
00923
00924 if (current_function_uses_pic_offset_table)
00925 fprintf (file, "\tmove.d $pc,$%s\n\tsub.d .:GOTOFF,$%s\n",
00926 reg_names[PIC_OFFSET_TABLE_REGNUM],
00927 reg_names[PIC_OFFSET_TABLE_REGNUM]);
00928
00929 if (doing_dwarf)
00930 ASM_OUTPUT_LABEL (file, cfa_label);
00931
00932 if (TARGET_PDEBUG)
00933 fprintf (file,
00934 "; parm #%d @ %d; frame " HOST_WIDE_INT_PRINT_DEC
00935 ", FP-SP is %d; leaf: %s%s; fp %s, outg: %d arg %d\n",
00936 CRIS_MAX_ARGS_IN_REGS + 1, FIRST_PARM_OFFSET (0),
00937 get_frame_size (),
00938 cris_initial_frame_pointer_offset (),
00939 leaf_function_p () ? "yes" : "no",
00940 return_address_on_stack ? "no" :"yes",
00941 frame_pointer_needed ? "yes" : "no",
00942 cfoa_size, current_function_args_size);
00943
00944 if (cris_max_stackframe && framesize > cris_max_stackframe)
00945 warning ("stackframe too big: %d bytes", framesize);
00946 }
00947
00948
00949
00950
00951
00952 static int
00953 saved_regs_mentioned (rtx x)
00954 {
00955 int i;
00956 const char *fmt;
00957 RTX_CODE code;
00958
00959
00960
00961 code = GET_CODE (x);
00962
00963 switch (code)
00964 {
00965 case REG:
00966 i = REGNO (x);
00967 return !call_used_regs[i];
00968
00969 case SUBREG:
00970
00971
00972 i = REGNO (SUBREG_REG (x));
00973 return !call_used_regs[i];
00974
00975 default:
00976 ;
00977 }
00978
00979 fmt = GET_RTX_FORMAT (code);
00980 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
00981 {
00982 if (fmt[i] == 'e')
00983 {
00984 if (saved_regs_mentioned (XEXP (x, i)))
00985 return 1;
00986 }
00987 else if (fmt[i] == 'E')
00988 {
00989 int j;
00990 for (j = XVECLEN (x, i) - 1; j >=0; j--)
00991 if (saved_regs_mentioned (XEXP (x, i)))
00992 return 1;
00993 }
00994 }
00995
00996 return 0;
00997 }
00998
00999
01000
01001 int
01002 cris_eligible_for_epilogue_delay (rtx insn)
01003 {
01004
01005 if (get_attr_slottable (insn) != SLOTTABLE_YES)
01006 return 0;
01007
01008
01009
01010 if (reg_mentioned_p (stack_pointer_rtx, PATTERN (insn)))
01011 return 0;
01012
01013
01014
01015 if (frame_pointer_needed
01016 && reg_mentioned_p (frame_pointer_rtx, PATTERN (insn)))
01017 return 0;
01018
01019
01020
01021
01022 if (saved_regs_mentioned (PATTERN (insn)))
01023 return 0;
01024
01025
01026 return 1;
01027 }
01028
01029
01030
01031
01032 int
01033 cris_delay_slots_for_epilogue (void)
01034 {
01035
01036
01037 if (regs_ever_live[CRIS_SRP_REGNUM]
01038 || cfun->machine->needs_return_address_on_stack != 0)
01039 return 0;
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049 cris_target_asm_function_epilogue (NULL, get_frame_size ());
01050
01051 if (*save_last)
01052 return 1;
01053 return 0;
01054 }
01055
01056
01057
01058
01059
01060 static void
01061 cris_target_asm_function_epilogue (FILE *file, HOST_WIDE_INT size)
01062 {
01063 int regno;
01064 int last_movem_reg = -1;
01065 rtx insn = get_last_insn ();
01066 int argspace_offset = current_function_outgoing_args_size;
01067 int pretend = current_function_pretend_args_size;
01068 int return_address_on_stack
01069 = regs_ever_live[CRIS_SRP_REGNUM]
01070 || cfun->machine->needs_return_address_on_stack != 0;
01071
01072 save_last[0] = 0;
01073
01074 if (file && !TARGET_PROLOGUE_EPILOGUE)
01075 return;
01076
01077 if (TARGET_PDEBUG && file)
01078 fprintf (file, ";;\n");
01079
01080
01081 if (TARGET_STACK_ALIGN)
01082 size = TARGET_ALIGN_BY_32 ? (size + 3) & ~3 : (size + 1) & ~1;
01083
01084
01085
01086 if (GET_CODE (insn) == NOTE)
01087 insn = prev_nonnote_insn (insn);
01088 if (insn
01089 && (GET_CODE (insn) == BARRIER
01090
01091
01092
01093
01094 || (GET_CODE (insn) == JUMP_INSN
01095 && GET_CODE (PATTERN (insn)) == RETURN)))
01096 {
01097 if (TARGET_PDEBUG && file)
01098 fprintf (file, ";;;;;\n");
01099 return;
01100 }
01101
01102
01103
01104 for (regno = 0;
01105 regno < FIRST_PSEUDO_REGISTER;
01106 regno++)
01107 if ((((regs_ever_live[regno]
01108 && !call_used_regs[regno])
01109 || (regno == (int) PIC_OFFSET_TABLE_REGNUM
01110 && (current_function_uses_pic_offset_table
01111
01112 || (flag_pic
01113 && regs_ever_live[regno + 1]
01114 && !call_used_regs[regno + 1]))))
01115 && (regno != FRAME_POINTER_REGNUM || !frame_pointer_needed)
01116 && regno != CRIS_SRP_REGNUM)
01117 || (current_function_calls_eh_return
01118 && (regno == EH_RETURN_DATA_REGNO (0)
01119 || regno == EH_RETURN_DATA_REGNO (1)
01120 || regno == EH_RETURN_DATA_REGNO (2)
01121 || regno == EH_RETURN_DATA_REGNO (3))))
01122
01123 {
01124 if (regno == last_movem_reg + 1)
01125 last_movem_reg++;
01126 else
01127 break;
01128 }
01129
01130 for (regno = FIRST_PSEUDO_REGISTER - 1;
01131 regno > last_movem_reg;
01132 regno--)
01133 if ((((regs_ever_live[regno]
01134 && !call_used_regs[regno])
01135 || (regno == (int) PIC_OFFSET_TABLE_REGNUM
01136 && (current_function_uses_pic_offset_table
01137
01138 || (flag_pic
01139 && regs_ever_live[regno + 1]
01140 && !call_used_regs[regno + 1]))))
01141 && (regno != FRAME_POINTER_REGNUM || !frame_pointer_needed)
01142 && regno != CRIS_SRP_REGNUM)
01143 || (current_function_calls_eh_return
01144 && (regno == EH_RETURN_DATA_REGNO (0)
01145 || regno == EH_RETURN_DATA_REGNO (1)
01146 || regno == EH_RETURN_DATA_REGNO (2)
01147 || regno == EH_RETURN_DATA_REGNO (3))))
01148 {
01149 if (argspace_offset)
01150 {
01151
01152
01153 if (file)
01154 fprintf (file, "\tAdd%s %d,$sp\n",
01155 ADDITIVE_SIZE_MODIFIER (argspace_offset),
01156 argspace_offset);
01157
01158
01159 argspace_offset = 0;
01160 }
01161
01162
01163 if (*save_last && file)
01164 fprintf (file, save_last);
01165 sprintf (save_last, "\tPop $%s\n", reg_names[regno]);
01166 }
01167
01168 if (last_movem_reg != -1)
01169 {
01170 if (argspace_offset)
01171 {
01172
01173
01174 if (*save_last && file)
01175 {
01176 fprintf (file, save_last);
01177 *save_last = 0;
01178 }
01179
01180 if (file)
01181 fprintf (file, "\tAdd%s %d,$sp\n",
01182 ADDITIVE_SIZE_MODIFIER (argspace_offset),
01183 argspace_offset);
01184 argspace_offset = 0;
01185 }
01186
01187 else if (*save_last && file)
01188 fprintf (file, save_last);
01189 sprintf (save_last, "\tmovem [$sp+],$%s\n", reg_names[last_movem_reg]);
01190 }
01191
01192
01193 if (frame_pointer_needed)
01194 {
01195 if (*save_last && file)
01196 fprintf (file, save_last);
01197
01198 if (file)
01199 fprintf (file, "\tmove.d $%s,$sp\n",
01200 reg_names[FRAME_POINTER_REGNUM]);
01201 sprintf (save_last, "\tPop $%s\n",
01202 reg_names[FRAME_POINTER_REGNUM]);
01203 }
01204 else
01205 {
01206
01207
01208
01209
01210
01211 size += argspace_offset;
01212
01213 if (size)
01214 {
01215 if (*save_last && file)
01216 fprintf (file, save_last);
01217
01218 sprintf (save_last, "\tadd%s "HOST_WIDE_INT_PRINT_DEC",$sp\n",
01219 ADDITIVE_SIZE_MODIFIER (size), size);
01220 }
01221
01222
01223
01224 if (size > 63)
01225 {
01226 if (file)
01227 fprintf (file, save_last);
01228 *save_last = 0;
01229 }
01230 }
01231
01232
01233
01234
01235 if (return_address_on_stack && pretend == 0)
01236 {
01237 if (*save_last && file)
01238 fprintf (file, save_last);
01239 *save_last = 0;
01240
01241 if (file)
01242 {
01243 if (current_function_calls_eh_return)
01244 {
01245
01246
01247 fprintf (file, "\tpop $srp\n");
01248 fprintf (file, "\tret\n");
01249 fprintf (file, "\tadd.d $%s,$sp\n", reg_names[CRIS_STACKADJ_REG]);
01250 }
01251 else
01252 fprintf (file, "\tJump [$sp+]\n");
01253
01254
01255 if (current_function_epilogue_delay_list)
01256 internal_error ("allocated but unused delay list in epilogue");
01257 }
01258 return;
01259 }
01260
01261
01262
01263
01264
01265 if (current_function_calls_eh_return)
01266 internal_error ("unexpected function type needing stack adjustment for\
01267 __builtin_eh_return");
01268
01269
01270
01271 if (pretend)
01272 {
01273
01274 if (return_address_on_stack)
01275 {
01276 if (*save_last && file)
01277 fprintf (file, save_last);
01278 *save_last = 0;
01279
01280 if (file)
01281 fprintf (file, "\tpop $srp\n");
01282 }
01283
01284 if (*save_last && file)
01285 fprintf (file, save_last);
01286
01287 sprintf (save_last, "\tadd%s %d,$sp\n",
01288 ADDITIVE_SIZE_MODIFIER (pretend), pretend);
01289 }
01290
01291
01292 if (file && current_function_epilogue_delay_list)
01293 {
01294
01295
01296
01297 if (*save_last)
01298 fprintf (file, save_last);
01299
01300 fprintf (file, "\tRet\n");
01301
01302
01303 final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
01304 file, 1, -2, 1, NULL);
01305 }
01306 else if (file)
01307 {
01308 fprintf (file, "\tRet\n");
01309
01310
01311
01312 if (*save_last)
01313 fprintf (file, save_last);
01314 else
01315 fprintf (file, "\tnOp\n");
01316 }
01317 }
01318
01319
01320
01321 void
01322 cris_print_operand (FILE *file, rtx x, int code)
01323 {
01324 rtx operand = x;
01325
01326
01327 static const char *const mults[] = { "BAD:0", ".b", ".w", "BAD:3", ".d" };
01328
01329
01330
01331
01332
01333
01334
01335 switch (code)
01336 {
01337 case 'b':
01338
01339
01340 if (GET_CODE (x) != CONST_INT
01341 || ! CONST_OK_FOR_LETTER_P (INTVAL (x), 'O'))
01342 LOSE_AND_RETURN ("invalid operand for 'b' modifier", x);
01343 fprintf (file, HOST_WIDE_INT_PRINT_DEC,
01344 INTVAL (x)| (INTVAL (x) <= 255 ? ~255 : ~65535));
01345 return;
01346
01347 case 'x':
01348
01349 fprintf (file, "%s", cris_op_str (operand));
01350 return;
01351
01352 case 'v':
01353
01354 if (! flag_pic || ! CONSTANT_P (x) || ! cris_gotless_symbol (x))
01355 LOSE_AND_RETURN ("invalid operand for 'v' modifier", x);
01356 cris_pic_sympart_only++;
01357 cris_output_addr_const (file, x);
01358 cris_pic_sympart_only--;
01359 return;
01360
01361 case 'P':
01362
01363
01364 if (! flag_pic || ! CONSTANT_P (x) || ! cris_gotless_symbol (x))
01365 LOSE_AND_RETURN ("invalid operand for 'P' modifier", x);
01366 fprintf (file, "$%s", reg_names [PIC_OFFSET_TABLE_REGNUM]);
01367 return;
01368
01369 case 'p':
01370
01371 if (GET_CODE (x) != CONST_INT || exact_log2 (INTVAL (x)) < 0 )
01372 LOSE_AND_RETURN ("invalid operand for 'p' modifier", x);
01373 fprintf (file, "%d", exact_log2 (INTVAL (x)));
01374 return;
01375
01376 case 's':
01377
01378
01379
01380 cris_output_insn_is_bound = 0;
01381 if (GET_MODE (x) == VOIDmode && GET_CODE (x) == CONST_INT)
01382 {
01383 if (INTVAL (x) >= 0)
01384 {
01385 if (INTVAL (x) <= 255)
01386 putc ('b', file);
01387 else if (INTVAL (x) <= 65535)
01388 putc ('w', file);
01389 else
01390 putc ('d', file);
01391 }
01392 else
01393 putc ('d', file);
01394 return;
01395 }
01396
01397
01398 putc ((GET_MODE (x) == SImode || GET_MODE (x) == SFmode)
01399 ? 'd' : GET_MODE (x) == HImode ? 'w'
01400 : GET_MODE (x) == QImode ? 'b'
01401
01402 : 'X',
01403 file);
01404 return;
01405
01406 case 'z':
01407
01408
01409 if (GET_CODE (x) != CONST_INT
01410 || INTVAL (x) < -32768 || INTVAL (x) > 65535)
01411 LOSE_AND_RETURN ("invalid operand for 'z' modifier", x);
01412 putc (INTVAL (x) >= -128 && INTVAL (x) <= 255 ? 'b' : 'w', file);
01413 return;
01414
01415 case '#':
01416
01417
01418 if (dbr_sequence_length () == 0)
01419 fputs ("\n\tnop", file);
01420 return;
01421
01422 case '!':
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433 if (TARGET_MUL_BUG)
01434 fputs (optimize_size
01435 ? ".p2alignw 2,0x050f\n\t"
01436 : ".p2alignw 5,0x050f,2\n\t", file);
01437 return;
01438
01439 case 'H':
01440
01441 switch (GET_CODE (operand))
01442 {
01443 case CONST_INT:
01444 if (HOST_BITS_PER_WIDE_INT == 32)
01445
01446 fprintf (file, INTVAL (operand) < 0 ? "-1" : "0");
01447 else
01448 fprintf (file, "0x%x", (unsigned int)(INTVAL (x) >> 31 >> 1));
01449 return;
01450
01451 case CONST_DOUBLE:
01452
01453 if (GET_MODE (operand) == VOIDmode)
01454 {
01455 fprintf (file, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_HIGH (x));
01456 return;
01457 }
01458 else
01459 LOSE_AND_RETURN ("invalid operand for 'H' modifier", x);
01460
01461 case REG:
01462
01463
01464 if (REGNO (operand) > STACK_POINTER_REGNUM - 2)
01465 LOSE_AND_RETURN ("bad register", operand);
01466 fprintf (file, "$%s", reg_names[REGNO (operand) + 1]);
01467 return;
01468
01469 case MEM:
01470
01471 {
01472 rtx adj_mem = operand;
01473 int size
01474 = GET_MODE_BITSIZE (GET_MODE (operand)) / BITS_PER_UNIT;
01475
01476
01477
01478
01479
01480 if (GET_CODE (XEXP (adj_mem, 0)) != POST_INC)
01481 adj_mem
01482 = adjust_address (adj_mem, GET_MODE (adj_mem), size / 2);
01483
01484 output_address (XEXP (adj_mem, 0));
01485 return;
01486 }
01487
01488 default:
01489 LOSE_AND_RETURN ("invalid operand for 'H' modifier", x);
01490 }
01491
01492 case 'L':
01493
01494 operand = XEXP (operand, 0);
01495 break;
01496
01497 case 'e':
01498
01499
01500 if (GET_CODE (operand) != SIGN_EXTEND
01501 && GET_CODE (operand) != ZERO_EXTEND
01502 && GET_CODE (operand) != CONST_INT)
01503 LOSE_AND_RETURN ("invalid operand for 'e' modifier", x);
01504
01505 if (cris_output_insn_is_bound)
01506 {
01507 cris_output_insn_is_bound = 0;
01508 return;
01509 }
01510
01511 putc (GET_CODE (operand) == SIGN_EXTEND
01512 || (GET_CODE (operand) == CONST_INT && INTVAL (operand) < 0)
01513 ? 's' : 'u', file);
01514 return;
01515
01516 case 'm':
01517
01518
01519 if (GET_CODE (operand) != SIGN_EXTEND && GET_CODE (operand) != ZERO_EXTEND)
01520 LOSE_AND_RETURN ("invalid operand for 'm' modifier", x);
01521 cris_print_operand (file, XEXP (operand, 0), 's');
01522 return;
01523
01524 case 'M':
01525
01526 if (GET_CODE (operand) == CONST_DOUBLE)
01527 {
01528 fprintf (file, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x));
01529 return;
01530 }
01531 else if (HOST_BITS_PER_WIDE_INT > 32 && GET_CODE (operand) == CONST_INT)
01532 {
01533 fprintf (file, HOST_WIDE_INT_PRINT_HEX,
01534 INTVAL (x) & ((unsigned int) 0x7fffffff * 2 + 1));
01535 return;
01536 }
01537
01538
01539 break;
01540
01541 case 'A':
01542
01543
01544 if (GET_CODE (operand) != CONST_INT)
01545 LOSE_AND_RETURN ("invalid operand for 'A' modifier", x);
01546 fprintf (file, INTVAL (operand) < 0 ? "adds.w" : "addq");
01547 return;
01548
01549 case 'D':
01550
01551
01552 if (GET_CODE (operand) != CONST_INT)
01553 LOSE_AND_RETURN ("invalid operand for 'D' modifier", x);
01554 fprintf (file, INTVAL (operand) < 0 ? "subs.w" : "subq");
01555 return;
01556
01557 case 'S':
01558
01559
01560 cris_print_index (operand, file);
01561 return;
01562
01563 case 'T':
01564
01565
01566 if (GET_CODE (operand) != CONST_INT || INTVAL (operand) > 4)
01567 LOSE_AND_RETURN ("invalid operand for 'T' modifier", x);
01568 fprintf (file, "%s", mults[INTVAL (operand)]);
01569 return;
01570
01571 case 0:
01572
01573 break;
01574
01575 default:
01576 LOSE_AND_RETURN ("invalid operand modifier letter", x);
01577 }
01578
01579
01580 switch (GET_CODE (operand))
01581 {
01582 case REG:
01583 if (REGNO (operand) > 15)
01584 internal_error ("internal error: bad register: %d", REGNO (operand));
01585 fprintf (file, "$%s", reg_names[REGNO (operand)]);
01586 return;
01587
01588 case MEM:
01589 output_address (XEXP (operand, 0));
01590 return;
01591
01592 case CONST_DOUBLE:
01593 if (GET_MODE (operand) == VOIDmode)
01594
01595 output_addr_const (file, operand);
01596 else
01597 {
01598
01599
01600
01601 REAL_VALUE_TYPE r;
01602 long l;
01603
01604
01605 REAL_VALUE_FROM_CONST_DOUBLE (r, operand);
01606 REAL_VALUE_TO_TARGET_SINGLE (r, l);
01607
01608 fprintf (file, "0x%lx", l);
01609 }
01610 return;
01611
01612 case UNSPEC:
01613 ASSERT_PLT_UNSPEC (operand);
01614
01615
01616 case CONST:
01617 cris_output_addr_const (file, operand);
01618 return;
01619
01620 case MULT:
01621 case ASHIFT:
01622 {
01623
01624 int i = GET_CODE (XEXP (operand, 1)) == CONST_INT
01625 ? INTVAL (XEXP (operand, 1)) : INTVAL (XEXP (operand, 0));
01626 rtx reg = GET_CODE (XEXP (operand, 1)) == CONST_INT
01627 ? XEXP (operand, 0) : XEXP (operand, 1);
01628
01629 if (GET_CODE (reg) != REG
01630 || (GET_CODE (XEXP (operand, 0)) != CONST_INT
01631 && GET_CODE (XEXP (operand, 1)) != CONST_INT))
01632 LOSE_AND_RETURN ("unexpected multiplicative operand", x);
01633
01634 cris_print_base (reg, file);
01635 fprintf (file, ".%c",
01636 i == 0 || (i == 1 && GET_CODE (operand) == MULT) ? 'b'
01637 : i == 4 ? 'd'
01638 : (i == 2 && GET_CODE (operand) == MULT) || i == 1 ? 'w'
01639 : 'd');
01640 return;
01641 }
01642
01643 default:
01644
01645
01646 if (CONSTANT_P (operand))
01647 {
01648 cris_output_addr_const (file, operand);
01649 return;
01650 }
01651
01652 LOSE_AND_RETURN ("unexpected operand", x);
01653 }
01654 }
01655
01656
01657
01658 void
01659 cris_print_operand_address (FILE *file, rtx x)
01660 {
01661
01662 putc ('[', file);
01663
01664 if (CONSTANT_ADDRESS_P (x))
01665 cris_output_addr_const (file, x);
01666 else if (BASE_OR_AUTOINCR_P (x))
01667 cris_print_base (x, file);
01668 else if (GET_CODE (x) == PLUS)
01669 {
01670 rtx x1, x2;
01671
01672 x1 = XEXP (x, 0);
01673 x2 = XEXP (x, 1);
01674 if (BASE_P (x1))
01675 {
01676 cris_print_base (x1, file);
01677 cris_print_index (x2, file);
01678 }
01679 else if (BASE_P (x2))
01680 {
01681 cris_print_base (x2, file);
01682 cris_print_index (x1, file);
01683 }
01684 else
01685 LOSE_AND_RETURN ("unrecognized address", x);
01686 }
01687 else if (GET_CODE (x) == MEM)
01688 {
01689
01690 putc ('[', file);
01691 cris_print_base (XEXP (x, 0), file);
01692 putc (']', file);
01693 }
01694 else
01695 LOSE_AND_RETURN ("unrecognized address", x);
01696
01697 putc (']', file);
01698 }
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708 rtx
01709 cris_return_addr_rtx (int count, rtx frameaddr ATTRIBUTE_UNUSED)
01710 {
01711 cfun->machine->needs_return_address_on_stack = 1;
01712
01713
01714
01715
01716 return count == 0
01717 ? gen_rtx_MEM (Pmode, plus_constant (virtual_incoming_args_rtx, -4))
01718 : NULL_RTX;
01719 }
01720
01721
01722
01723
01724 int
01725 cris_return_address_on_stack ()
01726 {
01727 return cfun->machine->needs_return_address_on_stack;
01728 }
01729
01730
01731
01732
01733 static int
01734 cris_initial_frame_pointer_offset (void)
01735 {
01736 int regno;
01737
01738
01739 int offs = 0;
01740
01741
01742 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
01743 if ((((regs_ever_live[regno]
01744 && !call_used_regs[regno])
01745 || (regno == (int) PIC_OFFSET_TABLE_REGNUM
01746 && (current_function_uses_pic_offset_table
01747
01748 || (flag_pic
01749 && regs_ever_live[regno + 1]
01750 && !call_used_regs[regno + 1]))))
01751 && (regno != FRAME_POINTER_REGNUM || !frame_pointer_needed)
01752 && regno != CRIS_SRP_REGNUM)
01753 || (current_function_calls_eh_return
01754 && (regno == EH_RETURN_DATA_REGNO (0)
01755 || regno == EH_RETURN_DATA_REGNO (1)
01756 || regno == EH_RETURN_DATA_REGNO (2)
01757 || regno == EH_RETURN_DATA_REGNO (3))))
01758 offs += 4;
01759
01760
01761 offs += get_frame_size ();
01762
01763
01764 offs += current_function_outgoing_args_size;
01765
01766
01767 if (TARGET_STACK_ALIGN)
01768 offs = TARGET_ALIGN_BY_32 ? (offs + 3) & ~3 : (offs + 1) & ~1;
01769
01770 return offs;
01771 }
01772
01773
01774
01775
01776
01777
01778 int
01779 cris_initial_elimination_offset (int fromreg, int toreg)
01780 {
01781 int fp_sp_offset
01782 = cris_initial_frame_pointer_offset ();
01783
01784
01785
01786 int return_address_on_stack
01787 = regs_ever_live[CRIS_SRP_REGNUM]
01788 || cfun->machine->needs_return_address_on_stack != 0;
01789
01790
01791 int ap_fp_offset = 4 + (return_address_on_stack ? 4 : 0);
01792
01793 if (fromreg == ARG_POINTER_REGNUM
01794 && toreg == FRAME_POINTER_REGNUM)
01795 return ap_fp_offset;
01796
01797
01798
01799 if (fromreg == FRAME_POINTER_REGNUM
01800 && toreg == STACK_POINTER_REGNUM)
01801 return fp_sp_offset;
01802
01803
01804 if (fromreg == ARG_POINTER_REGNUM
01805 && toreg == STACK_POINTER_REGNUM)
01806 return ap_fp_offset + fp_sp_offset - 4;
01807
01808 abort ();
01809 }
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822 void
01823 cris_notice_update_cc (rtx exp, rtx insn)
01824 {
01825
01826
01827
01828
01829 if (TARGET_CCINIT)
01830 {
01831 CC_STATUS_INIT;
01832 return;
01833 }
01834
01835
01836
01837 switch (get_attr_cc (insn))
01838 {
01839 case CC_NONE:
01840
01841
01842 if (GET_CODE (exp) == SET)
01843 {
01844 if (cc_status.value1
01845 && modified_in_p (cc_status.value1, insn))
01846 cc_status.value1 = 0;
01847
01848 if (cc_status.value2
01849 && modified_in_p (cc_status.value2, insn))
01850 cc_status.value2 = 0;
01851 }
01852 return;
01853
01854 case CC_CLOBBER:
01855 CC_STATUS_INIT;
01856 break;
01857
01858 case CC_NORMAL:
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894
01895 if (GET_CODE (exp) == SET)
01896 {
01897
01898
01899 if (SET_DEST (exp) == pc_rtx)
01900 return;
01901
01902
01903
01904 if (SET_DEST (exp) == cc0_rtx)
01905 {
01906 cc_status.value1 = SET_SRC (exp);
01907 cc_status.value2 = 0;
01908
01909
01910 if (GET_CODE (SET_SRC (exp)) == ZERO_EXTRACT
01911 && XEXP (SET_SRC (exp), 1) == const1_rtx)
01912 {
01913 if (GET_CODE (XEXP (SET_SRC (exp), 0)) == CONST_INT)
01914
01915 cc_status.flags = CC_INVERTED;
01916 else
01917
01918 cc_status.flags = CC_Z_IN_NOT_N;
01919 }
01920 else
01921 cc_status.flags = 0;
01922
01923 if (GET_CODE (SET_SRC (exp)) == COMPARE)
01924 {
01925 if (!REG_P (XEXP (SET_SRC (exp), 0))
01926 && XEXP (SET_SRC (exp), 1) != const0_rtx)
01927
01928
01929
01930
01931 cc_status.flags = CC_REVERSED;
01932
01933
01934
01935 cc_status.value2
01936 = gen_rtx_MINUS (GET_MODE (SET_SRC (exp)),
01937 XEXP (SET_SRC (exp), 0),
01938 XEXP (SET_SRC (exp), 1));
01939 }
01940 return;
01941 }
01942 else if (REG_P (SET_DEST (exp))
01943 || (GET_CODE (SET_DEST (exp)) == STRICT_LOW_PART
01944 && REG_P (XEXP (SET_DEST (exp), 0))))
01945 {
01946
01947
01948
01949
01950
01951 if (GET_MODE_SIZE (GET_MODE (SET_DEST (exp))) > UNITS_PER_WORD
01952 || GET_MODE_CLASS (GET_MODE (SET_DEST (exp))) == MODE_FLOAT)
01953 {
01954
01955 if (GET_MODE (SET_DEST (exp)) == DImode
01956 && (GET_CODE (SET_SRC (exp)) == PLUS
01957 || GET_CODE (SET_SRC (exp)) == MINUS))
01958 {
01959 cc_status.flags = 0;
01960 cc_status.value1 = SET_DEST (exp);
01961 cc_status.value2 = SET_SRC (exp);
01962
01963 if (cris_reg_overlap_mentioned_p (cc_status.value1,
01964 cc_status.value2))
01965 cc_status.value2 = 0;
01966
01967
01968
01969
01970 cc_status.flags |= CC_NO_OVERFLOW;
01971
01972 return;
01973 }
01974 }
01975 else if (SET_SRC (exp) == const0_rtx)
01976 {
01977
01978
01979 if (cc_status.value1
01980 && modified_in_p (cc_status.value1, insn))
01981 cc_status.value1 = 0;
01982
01983 if (cc_status.value2
01984 && modified_in_p (cc_status.value2, insn))
01985 cc_status.value2 = 0;
01986
01987 return;
01988 }
01989 else
01990 {
01991 cc_status.flags = 0;
01992 cc_status.value1 = SET_DEST (exp);
01993 cc_status.value2 = SET_SRC (exp);
01994
01995 if (cris_reg_overlap_mentioned_p (cc_status.value1,
01996 cc_status.value2))
01997 cc_status.value2 = 0;
01998
01999
02000
02001
02002 if (GET_CODE (SET_SRC (exp)) == PLUS
02003 || GET_CODE (SET_SRC (exp)) == MINUS
02004 || GET_CODE (SET_SRC (exp)) == NEG)
02005 cc_status.flags |= CC_NO_OVERFLOW;
02006
02007 return;
02008 }
02009 }
02010 else if (GET_CODE (SET_DEST (exp)) == MEM
02011 || (GET_CODE (SET_DEST (exp)) == STRICT_LOW_PART
02012 && GET_CODE (XEXP (SET_DEST (exp), 0)) == MEM))
02013 {
02014
02015
02016 if (cc_status.value1
02017 && modified_in_p (cc_status.value1, insn))
02018 cc_status.value1 = 0;
02019
02020 if (cc_status.value2
02021 && modified_in_p (cc_status.value2, insn))
02022 cc_status.value2 = 0;
02023
02024 return;
02025 }
02026 }
02027 else if (GET_CODE (exp) == PARALLEL)
02028 {
02029 if (GET_CODE (XVECEXP (exp, 0, 0)) == SET
02030 && GET_CODE (XVECEXP (exp, 0, 1)) == SET
02031 && REG_P (XEXP (XVECEXP (exp, 0, 1), 0)))
02032 {
02033 if (REG_P (XEXP (XVECEXP (exp, 0, 0), 0))
02034 && GET_CODE (XEXP (XVECEXP (exp, 0, 0), 1)) == MEM)
02035 {
02036
02037
02038 cc_status.value1 = XEXP (XVECEXP (exp, 0, 0), 0);
02039 cc_status.value2
02040 = replace_equiv_address (XEXP (XVECEXP (exp, 0, 0), 1),
02041 XEXP (XVECEXP (exp, 0, 1), 0));
02042 cc_status.flags = 0;
02043
02044
02045
02046 if (cris_reg_overlap_mentioned_p (cc_status.value1,
02047 cc_status.value2))
02048 internal_error ("internal error: sideeffect-insn affecting main effect");
02049 return;
02050 }
02051 else if ((REG_P (XEXP (XVECEXP (exp, 0, 0), 1))
02052 || XEXP (XVECEXP (exp, 0, 0), 1) == const0_rtx)
02053 && GET_CODE (XEXP (XVECEXP (exp, 0, 0), 0)) == MEM)
02054 {
02055
02056
02057 if (cc_status.value1
02058 && modified_in_p (cc_status.value1, insn))
02059 cc_status.value1 = 0;
02060
02061 if (cc_status.value2
02062 && modified_in_p (cc_status.value2, insn))
02063 cc_status.value2 = 0;
02064
02065 return;
02066 }
02067 }
02068 }
02069 break;
02070
02071 default:
02072
02073 abort ();
02074 }
02075
02076 CC_STATUS_INIT;
02077 }
02078
02079
02080
02081
02082
02083 int
02084 cris_simple_epilogue (void)
02085 {
02086 int regno;
02087 int reglimit = STACK_POINTER_REGNUM;
02088 int lastreg = -1;
02089
02090 if (! reload_completed
02091 || frame_pointer_needed
02092 || get_frame_size () != 0
02093 || current_function_pretend_args_size
02094 || current_function_args_size
02095 || current_function_outgoing_args_size
02096 || current_function_calls_eh_return
02097
02098
02099
02100 || !TARGET_PROLOGUE_EPILOGUE)
02101 return 0;
02102
02103
02104
02105 for (regno = 0; regno < reglimit; regno++)
02106 if ((regs_ever_live[regno] && ! call_used_regs[regno])
02107 || (regno == (int) PIC_OFFSET_TABLE_REGNUM
02108 && (current_function_uses_pic_offset_table
02109
02110 || (flag_pic
02111 && regs_ever_live[regno + 1]
02112 && !call_used_regs[regno + 1]))))
02113 {
02114 if (lastreg != regno - 1)
02115 return 0;
02116 lastreg = regno;
02117 }
02118
02119 return 1;
02120 }
02121
02122
02123
02124
02125
02126 static bool
02127 cris_rtx_costs (rtx x, int code, int outer_code, int *total)
02128 {
02129 switch (code)
02130 {
02131 case CONST_INT:
02132 {
02133 HOST_WIDE_INT val = INTVAL (x);
02134 if (val == 0)
02135 *total = 0;
02136 else if (val < 32 && val >= -32)
02137 *total = 1;
02138
02139 else if (val <= 32767 && val >= -32768)
02140 *total = 2;
02141
02142
02143 else
02144 *total = 4;
02145 return true;
02146 }
02147
02148 case LABEL_REF:
02149 *total = 6;
02150 return true;
02151
02152 case CONST:
02153 case SYMBOL_REF:
02154
02155
02156
02157 if (flag_pic)
02158 {
02159 if (cris_got_symbol (x))
02160 *total = 2 + 4 + 6;
02161 else
02162 *total = 2 + 6;
02163 }
02164 else
02165 *total = 6;
02166 return true;
02167
02168 case CONST_DOUBLE:
02169 if (x != CONST0_RTX (GET_MODE (x) == VOIDmode ? DImode : GET_MODE (x)))
02170 *total = 12;
02171 else
02172
02173 *total = 0;
02174 return true;
02175
02176 case MULT:
02177
02178
02179 if (GET_CODE (XEXP (x, 1)) != CONST_INT
02180 || exact_log2 (INTVAL (XEXP (x, 1)) < 0))
02181 {
02182
02183
02184 if (TARGET_HAS_MUL_INSNS)
02185 {
02186 *total = COSTS_N_INSNS (1) + COSTS_N_INSNS (1) / 2;
02187 return true;
02188 }
02189
02190
02191 *total = COSTS_N_INSNS (132);
02192 return true;
02193 }
02194 return false;
02195
02196 case UDIV:
02197 case MOD:
02198 case UMOD:
02199 case DIV:
02200 if (GET_CODE (XEXP (x, 1)) != CONST_INT
02201 || exact_log2 (INTVAL (XEXP (x, 1)) < 0))
02202 {
02203
02204 *total = COSTS_N_INSNS (260);
02205 return true;
02206 }
02207 return false;
02208
02209 case AND:
02210 if (GET_CODE (XEXP (x, 1)) == CONST_INT
02211
02212 && GET_CODE (XEXP (x, 0)) != CONST_INT
02213 && !CONST_OK_FOR_LETTER_P (INTVAL (XEXP (x, 1)), 'I'))
02214 {
02215 *total = (rtx_cost (XEXP (x, 0), outer_code) + 2
02216 + 2 * GET_MODE_NUNITS (GET_MODE (XEXP (x, 0))));
02217 return true;
02218 }
02219 return false;
02220
02221 case ZERO_EXTEND: case SIGN_EXTEND:
02222 *total = rtx_cost (XEXP (x, 0), outer_code);
02223 return true;
02224
02225 default:
02226 return false;
02227 }
02228 }
02229
02230
02231
02232 static int
02233 cris_address_cost (rtx x)
02234 {
02235
02236
02237
02238
02239
02240
02241 if (BASE_OR_AUTOINCR_P (x))
02242 return 0;
02243
02244
02245
02246 if (GET_CODE (x) == MEM)
02247 return (2 + 4) / 2;
02248
02249
02250
02251
02252
02253
02254 if (CONSTANT_P (x))
02255 return flag_pic && cris_got_symbol (x) ? 2 * (2 + 4) / 2 : (2 + 4) / 2;
02256
02257
02258 if (GET_CODE (x) == PLUS)
02259 {
02260 rtx tem1 = XEXP (x, 0);
02261 rtx tem2 = XEXP (x, 1);
02262
02263
02264
02265
02266 if ((GET_CODE (tem1) == MULT && BIAP_INDEX_P (tem1))
02267 || REG_P (tem1))
02268 return 2 / 2;
02269
02270
02271
02272 if (GET_CODE (tem2) == CONST_INT
02273 && INTVAL (tem2) < 128 && INTVAL (tem2) >= -128)
02274 return 2 / 2;
02275
02276
02277
02278 if (GET_CODE (tem2) == CONST_INT
02279 && CONST_OK_FOR_LETTER_P (INTVAL (tem2), 'L'))
02280 return (2 + 2) / 2;
02281
02282
02283 if (CONSTANT_P (tem2))
02284 return (2 + 2 + 2) / 2;
02285
02286
02287
02288
02289
02290
02291 return (2 + 2 + 2) / 2;
02292 }
02293
02294
02295
02296 return 10;
02297 }
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308
02309
02310
02311
02312
02313
02314 int
02315 cris_side_effect_mode_ok (enum rtx_code code, rtx *ops,
02316 int lreg, int rreg, int rval,
02317 int multop, int other_op)
02318 {
02319
02320 int mult = multop < 0 ? 1 : INTVAL (ops[multop]);
02321
02322 rtx reg_rtx = ops[rreg];
02323 rtx val_rtx = ops[rval];
02324
02325
02326
02327
02328 if (! BASE_P (reg_rtx))
02329 reg_rtx = val_rtx, val_rtx = ops[rreg];
02330
02331
02332
02333 if (! BASE_P (reg_rtx))
02334 return 0;
02335
02336
02337 if (!TARGET_SIDE_EFFECT_PREFIXES)
02338 return 0;
02339
02340
02341
02342 if (GET_CODE (val_rtx) == MULT)
02343 {
02344 mult = INTVAL (XEXP (val_rtx, 1));
02345 val_rtx = XEXP (val_rtx, 0);
02346 code = MULT;
02347 }
02348
02349
02350 if (other_op >= 0)
02351 {
02352 if (GET_MODE_SIZE (GET_MODE (ops[other_op])) > UNITS_PER_WORD)
02353 return 0;
02354
02355
02356
02357
02358 if ((BASE_P (ops[lreg])
02359 && BASE_P (ops[other_op])
02360 && REGNO (ops[lreg]) == REGNO (ops[other_op]))
02361 || rtx_equal_p (ops[other_op], ops[lreg]))
02362 return 0;
02363 }
02364
02365
02366 if (ops[lreg] == frame_pointer_rtx || ops[rreg] == frame_pointer_rtx
02367 || ops[rval] == frame_pointer_rtx
02368 || (other_op >= 0 && ops[other_op] == frame_pointer_rtx))
02369 return 0;
02370
02371 if (code == PLUS
02372 && ! BASE_P (val_rtx))
02373 {
02374
02375
02376
02377 if (rtx_equal_p (ops[lreg], reg_rtx)
02378 && GET_CODE (val_rtx) == CONST_INT
02379 && (INTVAL (val_rtx) <= 63 && INTVAL (val_rtx) >= -63))
02380 return 0;
02381
02382
02383
02384 if (CONSTANT_P (val_rtx))
02385 return flag_pic == 0 || cris_symbol (val_rtx) == 0;
02386
02387 if (GET_CODE (val_rtx) == MEM
02388 && BASE_OR_AUTOINCR_P (XEXP (val_rtx, 0)))
02389 return 1;
02390
02391 if (GET_CODE (val_rtx) == SIGN_EXTEND
02392 && GET_CODE (XEXP (val_rtx, 0)) == MEM
02393 && BASE_OR_AUTOINCR_P (XEXP (XEXP (val_rtx, 0), 0)))
02394 return 1;
02395
02396
02397 return 0;
02398 }
02399 else if (code == MULT
02400 || (code == PLUS && BASE_P (val_rtx)))
02401 {
02402
02403 if (rtx_equal_p (ops[lreg], reg_rtx)
02404 || (mult == 1 && rtx_equal_p (ops[lreg], val_rtx)))
02405 return 0;
02406
02407
02408 if (mult != 1 && mult != 2 && mult != 4)
02409 return 0;
02410
02411
02412 if (! BASE_P (reg_rtx))
02413 return 0;
02414
02415
02416
02417 return 1;
02418 }
02419
02420
02421 internal_error ("internal error: cris_side_effect_mode_ok with bad operands");
02422 }
02423
02424
02425
02426
02427
02428
02429
02430 static int
02431 cris_reg_overlap_mentioned_p (rtx x, rtx in)
02432 {
02433
02434
02435 if (GET_CODE (in) == STRICT_LOW_PART)
02436 in = XEXP (in, 0);
02437
02438 return reg_overlap_mentioned_p (x, in);
02439 }
02440
02441
02442
02443
02444 void
02445 cris_target_asm_named_section (const char *name, unsigned int flags,
02446 tree decl)
02447 {
02448 if (! TARGET_ELF)
02449 default_no_named_section (name, flags, decl);
02450 else
02451 default_elf_asm_named_section (name, flags, decl);
02452 }
02453
02454
02455
02456 int
02457 cris_legitimate_pic_operand (rtx x)
02458 {
02459
02460
02461
02462
02463
02464
02465
02466 return ! cris_symbol (x) || cris_got_symbol (x);
02467 }
02468
02469
02470
02471
02472 int
02473 cris_symbol (rtx x)
02474 {
02475 switch (GET_CODE (x))
02476 {
02477 case SYMBOL_REF:
02478 case LABEL_REF:
02479 return 1;
02480
02481 case UNSPEC:
02482
02483 ASSERT_PLT_UNSPEC (x);
02484 return 1;
02485
02486 case CONST:
02487 return cris_symbol (XEXP (x, 0));
02488
02489 case PLUS:
02490 case MINUS:
02491 return cris_symbol (XEXP (x, 0)) || cris_symbol (XEXP (x, 1));
02492
02493 case CONST_INT:
02494 case CONST_DOUBLE:
02495 return 0;
02496
02497 default:
02498 fatal_insn ("unrecognized supposed constant", x);
02499 }
02500
02501 return 1;
02502 }
02503
02504
02505
02506
02507
02508
02509 int
02510 cris_gotless_symbol (rtx x)
02511 {
02512 #ifdef ENABLE_CHECKING
02513 if (!flag_pic)
02514 abort ();
02515 #endif
02516
02517 switch (GET_CODE (x))
02518 {
02519 case UNSPEC:
02520 ASSERT_PLT_UNSPEC (x);
02521 return 1;
02522
02523 case SYMBOL_REF:
02524 if (cfun != NULL)
02525 current_function_uses_pic_offset_table = 1;
02526 return SYMBOL_REF_LOCAL_P (x);
02527
02528 case LABEL_REF:
02529
02530
02531
02532
02533
02534
02535 return 1;
02536
02537 case CONST:
02538 return cris_gotless_symbol (XEXP (x, 0));
02539
02540 case PLUS:
02541 case MINUS:
02542 {
02543 int x0 = cris_gotless_symbol (XEXP (x, 0)) != 0;
02544 int x1 = cris_gotless_symbol (XEXP (x, 1)) != 0;
02545
02546
02547
02548 return
02549 (x0 ^ x1)
02550 && ! (x0 == 0 && cris_symbol (XEXP (x, 0)))
02551 && ! (x1 == 0 && cris_symbol (XEXP (x, 1)));
02552 }
02553
02554 case CONST_INT:
02555 case CONST_DOUBLE:
02556 return 0;
02557
02558 default:
02559 fatal_insn ("unrecognized supposed constant", x);
02560 }
02561
02562 return 1;
02563 }
02564
02565
02566
02567
02568 int
02569 cris_got_symbol (rtx x)
02570 {
02571 #ifdef ENABLE_CHECKING
02572 if (!flag_pic)
02573 abort ();
02574 #endif
02575
02576 switch (GET_CODE (x))
02577 {
02578 case UNSPEC:
02579 ASSERT_PLT_UNSPEC (x);
02580 return 0;
02581
02582 case SYMBOL_REF:
02583 if (cfun != NULL)
02584 current_function_uses_pic_offset_table = 1;
02585 return ! SYMBOL_REF_LOCAL_P (x);
02586
02587 case CONST:
02588 return cris_got_symbol (XEXP (x, 0));
02589
02590 case LABEL_REF:
02591
02592
02593 case PLUS:
02594 case MINUS:
02595
02596 return 0;
02597
02598 case CONST_INT:
02599 case CONST_DOUBLE:
02600 return 0;
02601
02602 default:
02603 fatal_insn ("unrecognized supposed constant in cris_global_pic_symbol",
02604 x);
02605 }
02606
02607 return 1;
02608 }
02609
02610
02611
02612
02613 void
02614 cris_override_options (void)
02615 {
02616 if (cris_max_stackframe_str)
02617 {
02618 cris_max_stackframe = atoi (cris_max_stackframe_str);
02619
02620
02621 if (cris_max_stackframe < 0 || cris_max_stackframe > 0x20000000)
02622 internal_error ("-max-stackframe=%d is not usable, not between 0 and %d",
02623 cris_max_stackframe, 0x20000000);
02624 }
02625
02626
02627 if (TARGET_SVINTO && cris_cpu_version < CRIS_CPU_SVINTO)
02628 cris_cpu_version = CRIS_CPU_SVINTO;
02629 else if (TARGET_ETRAX4_ADD && cris_cpu_version < CRIS_CPU_ETRAX4)
02630 cris_cpu_version = CRIS_CPU_ETRAX4;
02631
02632
02633 if (cris_cpu_str)
02634 {
02635 cris_cpu_version
02636 = (*cris_cpu_str == 'v' ? atoi (cris_cpu_str + 1) : -1);
02637
02638 if (strcmp ("etrax4", cris_cpu_str) == 0)
02639 cris_cpu_version = 3;
02640
02641 if (strcmp ("svinto", cris_cpu_str) == 0
02642 || strcmp ("etrax100", cris_cpu_str) == 0)
02643 cris_cpu_version = 8;
02644
02645 if (strcmp ("ng", cris_cpu_str) == 0
02646 || strcmp ("etrax100lx", cris_cpu_str) == 0)
02647 cris_cpu_version = 10;
02648
02649 if (cris_cpu_version < 0 || cris_cpu_version > 10)
02650 error ("unknown CRIS version specification in -march= or -mcpu= : %s",
02651 cris_cpu_str);
02652
02653
02654 if (cris_cpu_version >= CRIS_CPU_ETRAX4)
02655 target_flags |= TARGET_MASK_ETRAX4_ADD;
02656
02657
02658 if (cris_cpu_version >= CRIS_CPU_SVINTO)
02659 target_flags
02660 |= (TARGET_MASK_SVINTO | TARGET_MASK_ALIGN_BY_32
02661 | TARGET_MASK_STACK_ALIGN | TARGET_MASK_CONST_ALIGN
02662 | TARGET_MASK_DATA_ALIGN);
02663
02664
02665
02666
02667 }
02668
02669 if (cris_tune_str)
02670 {
02671 int cris_tune
02672 = (*cris_tune_str == 'v' ? atoi (cris_tune_str + 1) : -1);
02673
02674 if (strcmp ("etrax4", cris_tune_str) == 0)
02675 cris_tune = 3;
02676
02677 if (strcmp ("svinto", cris_tune_str) == 0
02678 || strcmp ("etrax100", cris_tune_str) == 0)
02679 cris_tune = 8;
02680
02681 if (strcmp ("ng", cris_tune_str) == 0
02682 || strcmp ("etrax100lx", cris_tune_str) == 0)
02683 cris_tune = 10;
02684
02685 if (cris_tune < 0 || cris_tune > 10)
02686 error ("unknown CRIS cpu version specification in -mtune= : %s",
02687 cris_tune_str);
02688
02689 if (cris_tune >= CRIS_CPU_SVINTO)
02690
02691
02692 target_flags
02693 |= (TARGET_MASK_STACK_ALIGN | TARGET_MASK_CONST_ALIGN
02694 | TARGET_MASK_DATA_ALIGN | TARGET_MASK_ALIGN_BY_32);
02695 }
02696
02697 if (flag_pic)
02698 {
02699
02700
02701
02702 if (! TARGET_LINUX)
02703 {
02704 error ("-fPIC and -fpic are not supported in this configuration");
02705 flag_pic = 0;
02706 }
02707
02708
02709
02710
02711
02712
02713
02714 flag_no_function_cse = 1;
02715 }
02716
02717 if (write_symbols == DWARF2_DEBUG && ! TARGET_ELF)
02718 {
02719 warning ("that particular -g option is invalid with -maout and -melinux");
02720 write_symbols = DBX_DEBUG;
02721 }
02722
02723
02724 init_machine_status = cris_init_machine_status;
02725 }
02726
02727
02728
02729 static void
02730 cris_asm_output_mi_thunk (FILE *stream,
02731 tree thunkdecl ATTRIBUTE_UNUSED,
02732 HOST_WIDE_INT delta,
02733 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
02734 tree funcdecl)
02735 {
02736 if (delta > 0)
02737 fprintf (stream, "\tadd%s " HOST_WIDE_INT_PRINT_DEC ",$%s\n",
02738 ADDITIVE_SIZE_MODIFIER (delta), delta,
02739 reg_names[CRIS_FIRST_ARG_REG]);
02740 else if (delta < 0)
02741 fprintf (stream, "\tsub%s " HOST_WIDE_INT_PRINT_DEC ",$%s\n",
02742 ADDITIVE_SIZE_MODIFIER (-delta), -delta,
02743 reg_names[CRIS_FIRST_ARG_REG]);
02744
02745 if (flag_pic)
02746 {
02747 const char *name = XSTR (XEXP (DECL_RTL (funcdecl), 0), 0);
02748
02749 name = (* targetm.strip_name_encoding) (name);
02750 fprintf (stream, "add.d ");
02751 assemble_name (stream, name);
02752 fprintf (stream, "%s,$pc\n", CRIS_PLT_PCOFFSET_SUFFIX);
02753 }
02754 else
02755 {
02756 fprintf (stream, "jump ");
02757 assemble_name (stream, XSTR (XEXP (DECL_RTL (funcdecl), 0), 0));
02758 fprintf (stream, "\n");
02759 }
02760 }
02761
02762
02763
02764
02765
02766
02767
02768
02769 static void
02770 cris_file_start (void)
02771 {
02772
02773
02774 targetm.file_start_app_off = !(TARGET_PDEBUG || flag_print_asm_name);
02775 targetm.file_start_file_directive = TARGET_ELF;
02776
02777 default_file_start ();
02778 }
02779
02780
02781 static void
02782 cris_init_libfuncs (void)
02783 {
02784 set_optab_libfunc (smul_optab, SImode, "__Mul");
02785 set_optab_libfunc (sdiv_optab, SImode, "__Div");
02786 set_optab_libfunc (udiv_optab, SImode, "__Udiv");
02787 set_optab_libfunc (smod_optab, SImode, "__Mod");
02788 set_optab_libfunc (umod_optab, SImode, "__Umod");
02789 }
02790
02791
02792
02793
02794 void
02795 cris_init_expanders (void)
02796 {
02797
02798 }
02799
02800
02801
02802 static struct machine_function *
02803 cris_init_machine_status (void)
02804 {
02805 return ggc_alloc_cleared (sizeof (struct machine_function));
02806 }
02807
02808
02809
02810
02811 rtx
02812 cris_split_movdx (rtx *operands)
02813 {
02814 enum machine_mode mode = GET_MODE (operands[0]);
02815 rtx dest = operands[0];
02816 rtx src = operands[1];
02817 rtx val;
02818
02819
02820
02821
02822 if (GET_CODE (dest) == SUBREG || GET_CODE (src) == SUBREG)
02823 abort ();
02824
02825 start_sequence ();
02826 if (GET_CODE (dest) == REG)
02827 {
02828 int dregno = REGNO (dest);
02829
02830
02831 if (GET_CODE (src) == REG)
02832 {
02833 int sregno = REGNO (src);
02834
02835 int reverse = (dregno == sregno + 1);
02836
02837
02838
02839
02840 emit_insn (gen_rtx_SET (VOIDmode,
02841 operand_subword (dest, reverse, TRUE, mode),
02842 operand_subword (src, reverse, TRUE, mode)));
02843
02844 emit_insn (gen_rtx_SET (VOIDmode,
02845 operand_subword (dest, !reverse, TRUE, mode),
02846 operand_subword (src, !reverse, TRUE, mode)));
02847 }
02848
02849 else if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE)
02850 {
02851 rtx words[2];
02852 split_double (src, &words[0], &words[1]);
02853 emit_insn (gen_rtx_SET (VOIDmode,
02854 operand_subword (dest, 0, TRUE, mode),
02855 words[0]));
02856
02857 emit_insn (gen_rtx_SET (VOIDmode,
02858 operand_subword (dest, 1, TRUE, mode),
02859 words[1]));
02860 }
02861
02862 else if (GET_CODE (src) == MEM)
02863 {
02864
02865
02866 rtx addr = XEXP (src, 0);
02867 int reverse
02868 = (refers_to_regno_p (dregno, dregno + 1, addr, NULL) != 0);
02869
02870
02871
02872
02873
02874
02875
02876
02877
02878 if (GET_CODE (addr) == POST_INC)
02879 {
02880 emit_insn (gen_rtx_SET (VOIDmode,
02881 operand_subword (dest, 0, TRUE, mode),
02882 change_address (src, SImode, addr)));
02883 emit_insn (gen_rtx_SET (VOIDmode,
02884 operand_subword (dest, 1, TRUE, mode),
02885 change_address (src, SImode, addr)));
02886 }
02887 else
02888 {
02889
02890
02891
02892
02893 if (side_effects_p (addr))
02894 fatal_insn ("unexpected side-effects in address", addr);
02895
02896 emit_insn (gen_rtx_SET
02897 (VOIDmode,
02898 operand_subword (dest, reverse, TRUE, mode),
02899 change_address
02900 (src, SImode,
02901 plus_constant (addr,
02902 reverse * UNITS_PER_WORD))));
02903 emit_insn (gen_rtx_SET
02904 (VOIDmode,
02905 operand_subword (dest, ! reverse, TRUE, mode),
02906 change_address
02907 (src, SImode,
02908 plus_constant (addr,
02909 (! reverse) *
02910 UNITS_PER_WORD))));
02911 }
02912 }
02913 else
02914 abort ();
02915 }
02916
02917 else if (GET_CODE (dest) == MEM
02918 && (GET_CODE (src) == REG
02919 || src == const0_rtx
02920 || src == CONST0_RTX (DFmode)))
02921 {
02922 rtx addr = XEXP (dest, 0);
02923
02924 if (GET_CODE (addr) == POST_INC)
02925 {
02926 emit_insn (gen_rtx_SET (VOIDmode,
02927 change_address (dest, SImode, addr),
02928 operand_subword (src, 0, TRUE, mode)));
02929 emit_insn (gen_rtx_SET (VOIDmode,
02930 change_address (dest, SImode, addr),
02931 operand_subword (src, 1, TRUE, mode)));
02932 }
02933 else
02934 {
02935
02936
02937
02938 if (side_effects_p (addr))
02939 fatal_insn ("unexpected side-effects in address", addr);
02940
02941 emit_insn (gen_rtx_SET
02942 (VOIDmode,
02943 change_address (dest, SImode, addr),
02944 operand_subword (src, 0, TRUE, mode)));
02945
02946 emit_insn (gen_rtx_SET
02947 (VOIDmode,
02948 change_address (dest, SImode,
02949 plus_constant (addr,
02950 UNITS_PER_WORD)),
02951 operand_subword (src, 1, TRUE, mode)));
02952 }
02953 }
02954
02955 else
02956 abort ();
02957
02958 val = get_insns ();
02959 end_sequence ();
02960 return val;
02961 }
02962
02963
02964
02965
02966
02967
02968 static void
02969 cris_output_addr_const (FILE *file, rtx x)
02970 {
02971 in_code++;
02972 output_addr_const (file, x);
02973 in_code--;
02974 }
02975
02976
02977
02978 void
02979 cris_asm_output_symbol_ref (FILE *file, rtx x)
02980 {
02981 if (flag_pic && in_code > 0)
02982 {
02983 const char *origstr = XSTR (x, 0);
02984 const char *str;
02985
02986 str = (* targetm.strip_name_encoding) (origstr);
02987
02988 if (cris_gotless_symbol (x))
02989 {
02990 if (! cris_pic_sympart_only)
02991 fprintf (file, "$%s+", reg_names [PIC_OFFSET_TABLE_REGNUM]);
02992 assemble_name (file, str);
02993 fprintf (file, ":GOTOFF");
02994 }
02995 else if (cris_got_symbol (x))
02996 {
02997 if (cris_pic_sympart_only)
02998 abort ();
02999 fprintf (file, "[$%s+", reg_names [PIC_OFFSET_TABLE_REGNUM]);
03000 assemble_name (file, XSTR (x, 0));
03001
03002 if (flag_pic == 1)
03003 fprintf (file, ":GOT16]");
03004 else
03005 fprintf (file, ":GOT]");
03006 }
03007 else
03008 LOSE_AND_RETURN ("unexpected PIC symbol", x);
03009
03010
03011 if (! current_function_uses_pic_offset_table)
03012 output_operand_lossage ("PIC register isn't set up");
03013 }
03014 else
03015 assemble_name (file, XSTR (x, 0));
03016 }
03017
03018
03019
03020 void
03021 cris_asm_output_label_ref (FILE *file, char *buf)
03022 {
03023 if (flag_pic && in_code > 0)
03024 {
03025 if (! cris_pic_sympart_only)
03026 fprintf (file, "$%s+", reg_names [PIC_OFFSET_TABLE_REGNUM]);
03027 assemble_name (file, buf);
03028
03029 fprintf (file, ":GOTOFF");
03030
03031
03032 if (! current_function_uses_pic_offset_table)
03033 internal_error ("emitting PIC operand, but PIC register isn't set up");
03034 }
03035 else
03036 assemble_name (file, buf);
03037 }
03038
03039
03040
03041 bool
03042 cris_output_addr_const_extra (FILE *file, rtx x)
03043 {
03044 switch (GET_CODE (x))
03045 {
03046 const char *origstr;
03047 const char *str;
03048
03049 case UNSPEC:
03050 ASSERT_PLT_UNSPEC (x);
03051 x = XVECEXP (x, 0, 0);
03052 origstr = XSTR (x, 0);
03053 str = (* targetm.strip_name_encoding) (origstr);
03054 if (cris_pic_sympart_only)
03055 {
03056 assemble_name (file, str);
03057 fprintf (file, ":PLTG");
03058 }
03059 else
03060 {
03061 if (TARGET_AVOID_GOTPLT)
03062
03063 abort ();
03064
03065 fprintf (file, "[$%s+", reg_names [PIC_OFFSET_TABLE_REGNUM]);
03066 assemble_name (file, XSTR (x, 0));
03067
03068 if (flag_pic == 1)
03069 fprintf (file, ":GOTPLT16]");
03070 else
03071 fprintf (file, ":GOTPLT]");
03072 }
03073 return true;
03074
03075 default:
03076 return false;
03077 }
03078 }
03079
03080
03081
03082 static rtx
03083 cris_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
03084 int incoming ATTRIBUTE_UNUSED)
03085 {
03086 return gen_rtx_REG (Pmode, CRIS_STRUCT_VALUE_REGNUM);
03087 }
03088
03089
03090
03091 static void
03092 cris_setup_incoming_varargs (CUMULATIVE_ARGS *ca,
03093 enum machine_mode mode ATTRIBUTE_UNUSED,
03094 tree type ATTRIBUTE_UNUSED,
03095 int *pretend_arg_size,
03096 int second_time)
03097 {
03098 if (ca->regs < CRIS_MAX_ARGS_IN_REGS)
03099 *pretend_arg_size = (CRIS_MAX_ARGS_IN_REGS - ca->regs) * 4;
03100 if (TARGET_PDEBUG)
03101 {
03102 fprintf (asm_out_file,
03103 "\n; VA:: ANSI: %d args before, anon @ #%d, %dtime\n",
03104 ca->regs, *pretend_arg_size, second_time);
03105 }
03106 }
03107
03108
03109
03110
03111 static bool
03112 cris_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
03113 enum machine_mode mode, tree type,
03114 bool named ATTRIBUTE_UNUSED)
03115 {
03116 return (targetm.calls.must_pass_in_stack (mode, type)
03117 || CRIS_FUNCTION_ARG_SIZE (mode, type) > 8);
03118 }
03119
03120
03121 static int
03122 cris_arg_partial_bytes (CUMULATIVE_ARGS *ca, enum machine_mode mode,
03123 tree type, bool named ATTRIBUTE_UNUSED)
03124 {
03125 if (ca->regs == CRIS_MAX_ARGS_IN_REGS - 1
03126 && !targetm.calls.must_pass_in_stack (mode, type)
03127 && CRIS_FUNCTION_ARG_SIZE (mode, type) > 4
03128 && CRIS_FUNCTION_ARG_SIZE (mode, type) <= 8)
03129 return UNITS_PER_WORD;
03130 else
03131 return 0;
03132 }
03133
03134
03135 #if 0
03136
03137
03138
03139
03140 enum rtx_code Get_code (rtx);
03141
03142 enum rtx_code
03143 Get_code (rtx x)
03144 {
03145 return GET_CODE (x);
03146 }
03147
03148 const char *Get_mode (rtx);
03149
03150 const char *
03151 Get_mode (rtx x)
03152 {
03153 return GET_MODE_NAME (GET_MODE (x));
03154 }
03155
03156 rtx Xexp (rtx, int);
03157
03158 rtx
03159 Xexp (rtx x, int n)
03160 {
03161 return XEXP (x, n);
03162 }
03163
03164 rtx Xvecexp (rtx, int, int);
03165
03166 rtx
03167 Xvecexp (rtx x, int n, int m)
03168 {
03169 return XVECEXP (x, n, m);
03170 }
03171
03172 int Get_rtx_len (rtx);
03173
03174 int
03175 Get_rtx_len (rtx x)
03176 {
03177 return GET_RTX_LENGTH (GET_CODE (x));
03178 }
03179
03180
03181
03182
03183 rtx Next_insn (rtx);
03184
03185 rtx
03186 Next_insn (rtx insn)
03187 {
03188 return NEXT_INSN (insn);
03189 }
03190
03191 rtx Prev_insn (rtx);
03192
03193 rtx
03194 Prev_insn (rtx insn)
03195 {
03196 return PREV_INSN (insn);
03197 }
03198 #endif
03199
03200 #include "gt-cris.h"
03201
03202
03203
03204
03205
03206
03207