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