00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "config.h"
00027 #include "system.h"
00028 #include "coretypes.h"
00029 #include "tm.h"
00030 #include <signal.h>
00031 #include "rtl.h"
00032 #include "regs.h"
00033 #include "hard-reg-set.h"
00034 #include "real.h"
00035 #include "insn-config.h"
00036 #include "conditions.h"
00037 #include "insn-attr.h"
00038 #include "recog.h"
00039 #include "toplev.h"
00040 #include "output.h"
00041 #include "tree.h"
00042 #include "function.h"
00043 #include "expr.h"
00044 #include "optabs.h"
00045 #include "flags.h"
00046 #include "reload.h"
00047 #include "tm_p.h"
00048 #include "ggc.h"
00049 #include "gstab.h"
00050 #include "hashtab.h"
00051 #include "debug.h"
00052 #include "target.h"
00053 #include "target-def.h"
00054 #include "integrate.h"
00055 #include "langhooks.h"
00056 #include "cfglayout.h"
00057 #include "sched-int.h"
00058 #include "tree-gimple.h"
00059
00060
00061 #define UNSPEC_ADDRESS_P(X) \
00062 (GET_CODE (X) == UNSPEC \
00063 && XINT (X, 1) >= UNSPEC_ADDRESS_FIRST \
00064 && XINT (X, 1) < UNSPEC_ADDRESS_FIRST + NUM_SYMBOL_TYPES)
00065
00066
00067 #define UNSPEC_ADDRESS(X) \
00068 XVECEXP (X, 0, 0)
00069
00070
00071 #define UNSPEC_ADDRESS_TYPE(X) \
00072 ((enum mips_symbol_type) (XINT (X, 1) - UNSPEC_ADDRESS_FIRST))
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 #define MIPS_MAX_FIRST_STACK_STEP (TARGET_MIPS16 ? 0x100 : 0x7ff0)
00084
00085
00086 #define USEFUL_INSN_P(INSN) \
00087 (INSN_P (INSN) \
00088 && GET_CODE (PATTERN (INSN)) != USE \
00089 && GET_CODE (PATTERN (INSN)) != CLOBBER \
00090 && GET_CODE (PATTERN (INSN)) != ADDR_VEC \
00091 && GET_CODE (PATTERN (INSN)) != ADDR_DIFF_VEC)
00092
00093
00094
00095 #define SEQ_BEGIN(INSN) \
00096 (INSN_P (INSN) && GET_CODE (PATTERN (INSN)) == SEQUENCE \
00097 ? XVECEXP (PATTERN (INSN), 0, 0) \
00098 : (INSN))
00099
00100
00101 #define SEQ_END(INSN) \
00102 (INSN_P (INSN) && GET_CODE (PATTERN (INSN)) == SEQUENCE \
00103 ? XVECEXP (PATTERN (INSN), 0, XVECLEN (PATTERN (INSN), 0) - 1) \
00104 : (INSN))
00105
00106
00107
00108 #define FOR_EACH_SUBINSN(SUBINSN, INSN) \
00109 for ((SUBINSN) = SEQ_BEGIN (INSN); \
00110 (SUBINSN) != NEXT_INSN (SEQ_END (INSN)); \
00111 (SUBINSN) = NEXT_INSN (SUBINSN))
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 enum mips_address_type {
00129 ADDRESS_REG,
00130 ADDRESS_LO_SUM,
00131 ADDRESS_CONST_INT,
00132 ADDRESS_SYMBOLIC
00133 };
00134
00135
00136 enum mips_function_type
00137 {
00138 MIPS_V2SF_FTYPE_V2SF,
00139 MIPS_V2SF_FTYPE_V2SF_V2SF,
00140 MIPS_V2SF_FTYPE_V2SF_V2SF_INT,
00141 MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
00142 MIPS_V2SF_FTYPE_SF_SF,
00143 MIPS_INT_FTYPE_V2SF_V2SF,
00144 MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
00145 MIPS_INT_FTYPE_SF_SF,
00146 MIPS_INT_FTYPE_DF_DF,
00147 MIPS_SF_FTYPE_V2SF,
00148 MIPS_SF_FTYPE_SF,
00149 MIPS_SF_FTYPE_SF_SF,
00150 MIPS_DF_FTYPE_DF,
00151 MIPS_DF_FTYPE_DF_DF,
00152
00153
00154 MIPS_MAX_FTYPE_MAX
00155 };
00156
00157
00158 enum mips_builtin_type
00159 {
00160
00161
00162
00163 MIPS_BUILTIN_DIRECT,
00164
00165
00166
00167
00168
00169 MIPS_BUILTIN_MOVF,
00170 MIPS_BUILTIN_MOVT,
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 MIPS_BUILTIN_CMP_ANY,
00183 MIPS_BUILTIN_CMP_ALL,
00184 MIPS_BUILTIN_CMP_UPPER,
00185 MIPS_BUILTIN_CMP_LOWER,
00186
00187
00188 MIPS_BUILTIN_CMP_SINGLE
00189 };
00190
00191
00192 #define MIPS_FP_CONDITIONS(MACRO) \
00193 MACRO (f), \
00194 MACRO (un), \
00195 MACRO (eq), \
00196 MACRO (ueq), \
00197 MACRO (olt), \
00198 MACRO (ult), \
00199 MACRO (ole), \
00200 MACRO (ule), \
00201 MACRO (sf), \
00202 MACRO (ngle), \
00203 MACRO (seq), \
00204 MACRO (ngl), \
00205 MACRO (lt), \
00206 MACRO (nge), \
00207 MACRO (le), \
00208 MACRO (ngt)
00209
00210
00211 #define DECLARE_MIPS_COND(X) MIPS_FP_COND_ ## X
00212 enum mips_fp_condition {
00213 MIPS_FP_CONDITIONS (DECLARE_MIPS_COND)
00214 };
00215
00216
00217 #define STRINGIFY(X) #X
00218 static const char *const mips_fp_conditions[] = {
00219 MIPS_FP_CONDITIONS (STRINGIFY)
00220 };
00221
00222
00223
00224 typedef void (*mips_save_restore_fn) (rtx, rtx);
00225
00226 struct mips16_constant;
00227 struct mips_arg_info;
00228 struct mips_address_info;
00229 struct mips_integer_op;
00230 struct mips_sim;
00231
00232 static enum mips_symbol_type mips_classify_symbol (rtx);
00233 static void mips_split_const (rtx, rtx *, HOST_WIDE_INT *);
00234 static bool mips_offset_within_object_p (rtx, HOST_WIDE_INT);
00235 static bool mips_valid_base_register_p (rtx, enum machine_mode, int);
00236 static bool mips_symbolic_address_p (enum mips_symbol_type, enum machine_mode);
00237 static bool mips_classify_address (struct mips_address_info *, rtx,
00238 enum machine_mode, int);
00239 static int mips_symbol_insns (enum mips_symbol_type);
00240 static bool mips16_unextended_reference_p (enum machine_mode mode, rtx, rtx);
00241 static rtx mips_force_temporary (rtx, rtx);
00242 static rtx mips_split_symbol (rtx, rtx);
00243 static rtx mips_unspec_offset_high (rtx, rtx, rtx, enum mips_symbol_type);
00244 static rtx mips_add_offset (rtx, rtx, HOST_WIDE_INT);
00245 static unsigned int mips_build_shift (struct mips_integer_op *, HOST_WIDE_INT);
00246 static unsigned int mips_build_lower (struct mips_integer_op *,
00247 unsigned HOST_WIDE_INT);
00248 static unsigned int mips_build_integer (struct mips_integer_op *,
00249 unsigned HOST_WIDE_INT);
00250 static void mips_move_integer (rtx, unsigned HOST_WIDE_INT);
00251 static void mips_legitimize_const_move (enum machine_mode, rtx, rtx);
00252 static int m16_check_op (rtx, int, int, int);
00253 static bool mips_rtx_costs (rtx, int, int, int *);
00254 static int mips_address_cost (rtx);
00255 static void mips_emit_compare (enum rtx_code *, rtx *, rtx *, bool);
00256 static void mips_load_call_address (rtx, rtx, int);
00257 static bool mips_function_ok_for_sibcall (tree, tree);
00258 static void mips_block_move_straight (rtx, rtx, HOST_WIDE_INT);
00259 static void mips_adjust_block_mem (rtx, HOST_WIDE_INT, rtx *, rtx *);
00260 static void mips_block_move_loop (rtx, rtx, HOST_WIDE_INT);
00261 static void mips_arg_info (const CUMULATIVE_ARGS *, enum machine_mode,
00262 tree, int, struct mips_arg_info *);
00263 static bool mips_get_unaligned_mem (rtx *, unsigned int, int, rtx *, rtx *);
00264 static void mips_set_architecture (const struct mips_cpu_info *);
00265 static void mips_set_tune (const struct mips_cpu_info *);
00266 static struct machine_function *mips_init_machine_status (void);
00267 static void print_operand_reloc (FILE *, rtx, const char **);
00268 #if TARGET_IRIX
00269 static void irix_output_external_libcall (rtx);
00270 #endif
00271 static void mips_file_start (void);
00272 static void mips_file_end (void);
00273 static bool mips_rewrite_small_data_p (rtx);
00274 static int mips_small_data_pattern_1 (rtx *, void *);
00275 static int mips_rewrite_small_data_1 (rtx *, void *);
00276 static bool mips_function_has_gp_insn (void);
00277 static unsigned int mips_global_pointer (void);
00278 static bool mips_save_reg_p (unsigned int);
00279 static void mips_save_restore_reg (enum machine_mode, int, HOST_WIDE_INT,
00280 mips_save_restore_fn);
00281 static void mips_for_each_saved_reg (HOST_WIDE_INT, mips_save_restore_fn);
00282 static void mips_output_cplocal (void);
00283 static void mips_emit_loadgp (void);
00284 static void mips_output_function_prologue (FILE *, HOST_WIDE_INT);
00285 static void mips_set_frame_expr (rtx);
00286 static rtx mips_frame_set (rtx, rtx);
00287 static void mips_save_reg (rtx, rtx);
00288 static void mips_output_function_epilogue (FILE *, HOST_WIDE_INT);
00289 static void mips_restore_reg (rtx, rtx);
00290 static void mips_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
00291 HOST_WIDE_INT, tree);
00292 static int symbolic_expression_p (rtx);
00293 static void mips_select_rtx_section (enum machine_mode, rtx,
00294 unsigned HOST_WIDE_INT);
00295 static void mips_function_rodata_section (tree);
00296 static bool mips_in_small_data_p (tree);
00297 static int mips_fpr_return_fields (tree, tree *);
00298 static bool mips_return_in_msb (tree);
00299 static rtx mips_return_fpr_pair (enum machine_mode mode,
00300 enum machine_mode mode1, HOST_WIDE_INT,
00301 enum machine_mode mode2, HOST_WIDE_INT);
00302 static rtx mips16_gp_pseudo_reg (void);
00303 static void mips16_fp_args (FILE *, int, int);
00304 static void build_mips16_function_stub (FILE *);
00305 static rtx dump_constants_1 (enum machine_mode, rtx, rtx);
00306 static void dump_constants (struct mips16_constant *, rtx);
00307 static int mips16_insn_length (rtx);
00308 static int mips16_rewrite_pool_refs (rtx *, void *);
00309 static void mips16_lay_out_constants (void);
00310 static void mips_sim_reset (struct mips_sim *);
00311 static void mips_sim_init (struct mips_sim *, state_t);
00312 static void mips_sim_next_cycle (struct mips_sim *);
00313 static void mips_sim_wait_reg (struct mips_sim *, rtx, rtx);
00314 static int mips_sim_wait_regs_2 (rtx *, void *);
00315 static void mips_sim_wait_regs_1 (rtx *, void *);
00316 static void mips_sim_wait_regs (struct mips_sim *, rtx);
00317 static void mips_sim_wait_units (struct mips_sim *, rtx);
00318 static void mips_sim_wait_insn (struct mips_sim *, rtx);
00319 static void mips_sim_record_set (rtx, rtx, void *);
00320 static void mips_sim_issue_insn (struct mips_sim *, rtx);
00321 static void mips_sim_issue_nop (struct mips_sim *);
00322 static void mips_sim_finish_insn (struct mips_sim *, rtx);
00323 static void vr4130_avoid_branch_rt_conflict (rtx);
00324 static void vr4130_align_insns (void);
00325 static void mips_avoid_hazard (rtx, rtx, int *, rtx *, rtx);
00326 static void mips_avoid_hazards (void);
00327 static void mips_reorg (void);
00328 static bool mips_strict_matching_cpu_name_p (const char *, const char *);
00329 static bool mips_matching_cpu_name_p (const char *, const char *);
00330 static const struct mips_cpu_info *mips_parse_cpu (const char *, const char *);
00331 static const struct mips_cpu_info *mips_cpu_info_from_isa (int);
00332 static bool mips_return_in_memory (tree, tree);
00333 static bool mips_strict_argument_naming (CUMULATIVE_ARGS *);
00334 static void mips_macc_chains_record (rtx);
00335 static void mips_macc_chains_reorder (rtx *, int);
00336 static void vr4130_true_reg_dependence_p_1 (rtx, rtx, void *);
00337 static bool vr4130_true_reg_dependence_p (rtx);
00338 static bool vr4130_swap_insns_p (rtx, rtx);
00339 static void vr4130_reorder (rtx *, int);
00340 static void mips_promote_ready (rtx *, int, int);
00341 static int mips_sched_reorder (FILE *, int, rtx *, int *, int);
00342 static int mips_variable_issue (FILE *, int, rtx, int);
00343 static int mips_adjust_cost (rtx, rtx, rtx, int);
00344 static int mips_issue_rate (void);
00345 static int mips_multipass_dfa_lookahead (void);
00346 static void mips_init_libfuncs (void);
00347 static void mips_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
00348 tree, int *, int);
00349 static tree mips_build_builtin_va_list (void);
00350 static tree mips_gimplify_va_arg_expr (tree, tree, tree *, tree *);
00351 static bool mips_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode mode,
00352 tree, bool);
00353 static bool mips_callee_copies (CUMULATIVE_ARGS *, enum machine_mode mode,
00354 tree, bool);
00355 static int mips_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode mode,
00356 tree, bool);
00357 static bool mips_valid_pointer_mode (enum machine_mode);
00358 static bool mips_scalar_mode_supported_p (enum machine_mode);
00359 static bool mips_vector_mode_supported_p (enum machine_mode);
00360 static rtx mips_prepare_builtin_arg (enum insn_code, unsigned int, tree *);
00361 static rtx mips_prepare_builtin_target (enum insn_code, unsigned int, rtx);
00362 static rtx mips_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
00363 static void mips_init_builtins (void);
00364 static rtx mips_expand_builtin_direct (enum insn_code, rtx, tree);
00365 static rtx mips_expand_builtin_movtf (enum mips_builtin_type,
00366 enum insn_code, enum mips_fp_condition,
00367 rtx, tree);
00368 static rtx mips_expand_builtin_compare (enum mips_builtin_type,
00369 enum insn_code, enum mips_fp_condition,
00370 rtx, tree);
00371
00372
00373
00374
00375 struct mips_frame_info GTY(())
00376 {
00377 HOST_WIDE_INT total_size;
00378 HOST_WIDE_INT var_size;
00379 HOST_WIDE_INT args_size;
00380 HOST_WIDE_INT cprestore_size;
00381 HOST_WIDE_INT gp_reg_size;
00382 HOST_WIDE_INT fp_reg_size;
00383 unsigned int mask;
00384 unsigned int fmask;
00385 HOST_WIDE_INT gp_save_offset;
00386 HOST_WIDE_INT fp_save_offset;
00387 HOST_WIDE_INT gp_sp_offset;
00388 HOST_WIDE_INT fp_sp_offset;
00389 bool initialized;
00390 int num_gp;
00391 int num_fp;
00392 };
00393
00394 struct machine_function GTY(()) {
00395
00396
00397 rtx mips16_gp_pseudo_rtx;
00398
00399
00400 struct mips_frame_info frame;
00401
00402
00403 unsigned int global_pointer;
00404
00405
00406
00407 bool ignore_hazard_length_p;
00408
00409
00410
00411 bool all_noreorder_p;
00412
00413
00414 bool has_gp_insn_p;
00415 };
00416
00417
00418 struct mips_arg_info
00419 {
00420
00421
00422 bool fpr_p;
00423
00424
00425 unsigned int reg_words;
00426
00427
00428
00429
00430
00431
00432
00433
00434 unsigned int reg_offset;
00435
00436
00437 unsigned int stack_words;
00438
00439
00440
00441 unsigned int stack_offset;
00442 };
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461 struct mips_address_info
00462 {
00463 enum mips_address_type type;
00464 rtx reg;
00465 rtx offset;
00466 enum mips_symbol_type symbol_type;
00467 };
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480 struct mips_integer_op {
00481 enum rtx_code code;
00482 unsigned HOST_WIDE_INT value;
00483 };
00484
00485
00486
00487
00488
00489
00490 #define MIPS_MAX_INTEGER_OPS 7
00491
00492
00493
00494
00495
00496
00497 int mips_section_threshold = -1;
00498
00499
00500 int num_source_filenames = 0;
00501
00502
00503
00504 int sdb_label_count = 0;
00505
00506
00507 int sym_lineno = 0;
00508
00509
00510
00511
00512
00513 struct extern_list GTY (())
00514 {
00515 struct extern_list *next;
00516 const char *name;
00517 int size;
00518 };
00519
00520 static GTY (()) struct extern_list *extern_head = 0;
00521
00522
00523 const char *current_function_file = "";
00524
00525
00526 int set_noreorder;
00527 int set_noat;
00528 int set_nomacro;
00529 int set_volatile;
00530
00531
00532 int mips_branch_likely;
00533
00534
00535 rtx cmp_operands[2];
00536
00537
00538 enum processor_type mips_arch;
00539 const struct mips_cpu_info *mips_arch_info;
00540
00541
00542 enum processor_type mips_tune;
00543 const struct mips_cpu_info *mips_tune_info;
00544
00545
00546 int mips_isa;
00547
00548
00549 int mips_abi;
00550
00551
00552 const char *mips_arch_string;
00553 const char *mips_tune_string;
00554 const char *mips_isa_string;
00555 const char *mips_abi_string;
00556
00557
00558
00559
00560
00561 int mips16_hard_float;
00562
00563 const char *mips_cache_flush_func = CACHE_FLUSH_FUNC;
00564
00565
00566 const char *mips_fix_vr4130_string;
00567
00568
00569 int mips_split_addresses;
00570
00571
00572 static enum machine_mode gpr_mode;
00573
00574
00575
00576 char mips_hard_regno_mode_ok[(int)MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER];
00577
00578
00579 char mips_print_operand_punct[256];
00580
00581
00582 int mips_dbx_regno[FIRST_PSEUDO_REGISTER];
00583
00584
00585 static int mips_flag_delayed_branch;
00586
00587 static GTY (()) int mips_output_filename_first_time = 1;
00588
00589
00590
00591 static bool mips_split_p[NUM_SYMBOL_TYPES];
00592
00593
00594
00595
00596 static const char *mips_lo_relocs[NUM_SYMBOL_TYPES];
00597
00598
00599 static const char *mips_hi_relocs[NUM_SYMBOL_TYPES];
00600
00601
00602 const enum reg_class mips_regno_to_class[] =
00603 {
00604 LEA_REGS, LEA_REGS, M16_NA_REGS, M16_NA_REGS,
00605 M16_REGS, M16_REGS, M16_REGS, M16_REGS,
00606 LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS,
00607 LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS,
00608 M16_NA_REGS, M16_NA_REGS, LEA_REGS, LEA_REGS,
00609 LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS,
00610 T_REG, PIC_FN_ADDR_REG, LEA_REGS, LEA_REGS,
00611 LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS,
00612 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00613 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00614 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00615 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00616 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00617 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00618 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00619 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00620 HI_REG, LO_REG, NO_REGS, ST_REGS,
00621 ST_REGS, ST_REGS, ST_REGS, ST_REGS,
00622 ST_REGS, ST_REGS, ST_REGS, NO_REGS,
00623 NO_REGS, ALL_REGS, ALL_REGS, NO_REGS,
00624 COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
00625 COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
00626 COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
00627 COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
00628 COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
00629 COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
00630 COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
00631 COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
00632 COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
00633 COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
00634 COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
00635 COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
00636 COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
00637 COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
00638 COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
00639 COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
00640 COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
00641 COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
00642 COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
00643 COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
00644 COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
00645 COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
00646 COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
00647 COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS
00648 };
00649
00650
00651 enum reg_class mips_char_to_class[256];
00652
00653
00654
00655
00656
00657
00658
00659 const struct mips_cpu_info mips_cpu_info_table[] = {
00660
00661 { "mips1", PROCESSOR_R3000, 1 },
00662 { "mips2", PROCESSOR_R6000, 2 },
00663 { "mips3", PROCESSOR_R4000, 3 },
00664 { "mips4", PROCESSOR_R8000, 4 },
00665 { "mips32", PROCESSOR_4KC, 32 },
00666 { "mips32r2", PROCESSOR_M4K, 33 },
00667 { "mips64", PROCESSOR_5KC, 64 },
00668
00669
00670 { "r3000", PROCESSOR_R3000, 1 },
00671 { "r2000", PROCESSOR_R3000, 1 },
00672 { "r3900", PROCESSOR_R3900, 1 },
00673
00674
00675 { "r6000", PROCESSOR_R6000, 2 },
00676
00677
00678 { "r4000", PROCESSOR_R4000, 3 },
00679 { "vr4100", PROCESSOR_R4100, 3 },
00680 { "vr4111", PROCESSOR_R4111, 3 },
00681 { "vr4120", PROCESSOR_R4120, 3 },
00682 { "vr4130", PROCESSOR_R4130, 3 },
00683 { "vr4300", PROCESSOR_R4300, 3 },
00684 { "r4400", PROCESSOR_R4000, 3 },
00685 { "r4600", PROCESSOR_R4600, 3 },
00686 { "orion", PROCESSOR_R4600, 3 },
00687 { "r4650", PROCESSOR_R4650, 3 },
00688
00689
00690 { "r8000", PROCESSOR_R8000, 4 },
00691 { "vr5000", PROCESSOR_R5000, 4 },
00692 { "vr5400", PROCESSOR_R5400, 4 },
00693 { "vr5500", PROCESSOR_R5500, 4 },
00694 { "rm7000", PROCESSOR_R7000, 4 },
00695 { "rm9000", PROCESSOR_R9000, 4 },
00696
00697
00698 { "4kc", PROCESSOR_4KC, 32 },
00699 { "4kp", PROCESSOR_4KC, 32 },
00700
00701
00702 { "m4k", PROCESSOR_M4K, 33 },
00703
00704
00705 { "5kc", PROCESSOR_5KC, 64 },
00706 { "20kc", PROCESSOR_20KC, 64 },
00707 { "sb1", PROCESSOR_SB1, 64 },
00708 { "sr71000", PROCESSOR_SR71000, 64 },
00709
00710
00711 { 0, 0, 0 }
00712 };
00713
00714
00715 #ifndef MIPS_MARCH_CONTROLS_SOFT_FLOAT
00716 #define MIPS_MARCH_CONTROLS_SOFT_FLOAT 0
00717 #endif
00718
00719
00720 #undef TARGET_ASM_ALIGNED_HI_OP
00721 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
00722 #undef TARGET_ASM_ALIGNED_SI_OP
00723 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
00724 #undef TARGET_ASM_ALIGNED_DI_OP
00725 #define TARGET_ASM_ALIGNED_DI_OP "\t.dword\t"
00726
00727 #undef TARGET_ASM_FUNCTION_PROLOGUE
00728 #define TARGET_ASM_FUNCTION_PROLOGUE mips_output_function_prologue
00729 #undef TARGET_ASM_FUNCTION_EPILOGUE
00730 #define TARGET_ASM_FUNCTION_EPILOGUE mips_output_function_epilogue
00731 #undef TARGET_ASM_SELECT_RTX_SECTION
00732 #define TARGET_ASM_SELECT_RTX_SECTION mips_select_rtx_section
00733 #undef TARGET_ASM_FUNCTION_RODATA_SECTION
00734 #define TARGET_ASM_FUNCTION_RODATA_SECTION mips_function_rodata_section
00735
00736 #undef TARGET_SCHED_REORDER
00737 #define TARGET_SCHED_REORDER mips_sched_reorder
00738 #undef TARGET_SCHED_VARIABLE_ISSUE
00739 #define TARGET_SCHED_VARIABLE_ISSUE mips_variable_issue
00740 #undef TARGET_SCHED_ADJUST_COST
00741 #define TARGET_SCHED_ADJUST_COST mips_adjust_cost
00742 #undef TARGET_SCHED_ISSUE_RATE
00743 #define TARGET_SCHED_ISSUE_RATE mips_issue_rate
00744 #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
00745 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \
00746 mips_multipass_dfa_lookahead
00747
00748 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
00749 #define TARGET_FUNCTION_OK_FOR_SIBCALL mips_function_ok_for_sibcall
00750
00751 #undef TARGET_VALID_POINTER_MODE
00752 #define TARGET_VALID_POINTER_MODE mips_valid_pointer_mode
00753 #undef TARGET_RTX_COSTS
00754 #define TARGET_RTX_COSTS mips_rtx_costs
00755 #undef TARGET_ADDRESS_COST
00756 #define TARGET_ADDRESS_COST mips_address_cost
00757
00758 #undef TARGET_IN_SMALL_DATA_P
00759 #define TARGET_IN_SMALL_DATA_P mips_in_small_data_p
00760
00761 #undef TARGET_MACHINE_DEPENDENT_REORG
00762 #define TARGET_MACHINE_DEPENDENT_REORG mips_reorg
00763
00764 #undef TARGET_ASM_FILE_START
00765 #undef TARGET_ASM_FILE_END
00766 #define TARGET_ASM_FILE_START mips_file_start
00767 #define TARGET_ASM_FILE_END mips_file_end
00768 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
00769 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
00770
00771 #undef TARGET_INIT_LIBFUNCS
00772 #define TARGET_INIT_LIBFUNCS mips_init_libfuncs
00773
00774 #undef TARGET_BUILD_BUILTIN_VA_LIST
00775 #define TARGET_BUILD_BUILTIN_VA_LIST mips_build_builtin_va_list
00776 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
00777 #define TARGET_GIMPLIFY_VA_ARG_EXPR mips_gimplify_va_arg_expr
00778
00779 #undef TARGET_PROMOTE_FUNCTION_ARGS
00780 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
00781 #undef TARGET_PROMOTE_FUNCTION_RETURN
00782 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
00783 #undef TARGET_PROMOTE_PROTOTYPES
00784 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
00785
00786 #undef TARGET_RETURN_IN_MEMORY
00787 #define TARGET_RETURN_IN_MEMORY mips_return_in_memory
00788 #undef TARGET_RETURN_IN_MSB
00789 #define TARGET_RETURN_IN_MSB mips_return_in_msb
00790
00791 #undef TARGET_ASM_OUTPUT_MI_THUNK
00792 #define TARGET_ASM_OUTPUT_MI_THUNK mips_output_mi_thunk
00793 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
00794 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
00795
00796 #undef TARGET_SETUP_INCOMING_VARARGS
00797 #define TARGET_SETUP_INCOMING_VARARGS mips_setup_incoming_varargs
00798 #undef TARGET_STRICT_ARGUMENT_NAMING
00799 #define TARGET_STRICT_ARGUMENT_NAMING mips_strict_argument_naming
00800 #undef TARGET_MUST_PASS_IN_STACK
00801 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
00802 #undef TARGET_PASS_BY_REFERENCE
00803 #define TARGET_PASS_BY_REFERENCE mips_pass_by_reference
00804 #undef TARGET_CALLEE_COPIES
00805 #define TARGET_CALLEE_COPIES mips_callee_copies
00806 #undef TARGET_ARG_PARTIAL_BYTES
00807 #define TARGET_ARG_PARTIAL_BYTES mips_arg_partial_bytes
00808
00809 #undef TARGET_VECTOR_MODE_SUPPORTED_P
00810 #define TARGET_VECTOR_MODE_SUPPORTED_P mips_vector_mode_supported_p
00811
00812 #undef TARGET_SCALAR_MODE_SUPPORTED_P
00813 #define TARGET_SCALAR_MODE_SUPPORTED_P mips_scalar_mode_supported_p
00814
00815 #undef TARGET_INIT_BUILTINS
00816 #define TARGET_INIT_BUILTINS mips_init_builtins
00817 #undef TARGET_EXPAND_BUILTIN
00818 #define TARGET_EXPAND_BUILTIN mips_expand_builtin
00819
00820 struct gcc_target targetm = TARGET_INITIALIZER;
00821
00822
00823
00824 static enum mips_symbol_type
00825 mips_classify_symbol (rtx x)
00826 {
00827 if (GET_CODE (x) == LABEL_REF)
00828 {
00829 if (TARGET_MIPS16)
00830 return SYMBOL_CONSTANT_POOL;
00831 if (TARGET_ABICALLS)
00832 return SYMBOL_GOT_LOCAL;
00833 return SYMBOL_GENERAL;
00834 }
00835
00836 gcc_assert (GET_CODE (x) == SYMBOL_REF);
00837
00838 if (CONSTANT_POOL_ADDRESS_P (x))
00839 {
00840 if (TARGET_MIPS16)
00841 return SYMBOL_CONSTANT_POOL;
00842
00843 if (TARGET_ABICALLS)
00844 return SYMBOL_GOT_LOCAL;
00845
00846 if (GET_MODE_SIZE (get_pool_mode (x)) <= mips_section_threshold)
00847 return SYMBOL_SMALL_DATA;
00848
00849 return SYMBOL_GENERAL;
00850 }
00851
00852 if (SYMBOL_REF_SMALL_P (x))
00853 return SYMBOL_SMALL_DATA;
00854
00855 if (TARGET_ABICALLS)
00856 {
00857 if (SYMBOL_REF_DECL (x) == 0)
00858 return SYMBOL_REF_LOCAL_P (x) ? SYMBOL_GOT_LOCAL : SYMBOL_GOT_GLOBAL;
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880 if (DECL_P (SYMBOL_REF_DECL (x)) && TREE_PUBLIC (SYMBOL_REF_DECL (x)))
00881 return SYMBOL_GOT_GLOBAL;
00882
00883 return SYMBOL_GOT_LOCAL;
00884 }
00885
00886 return SYMBOL_GENERAL;
00887 }
00888
00889
00890
00891
00892
00893 static void
00894 mips_split_const (rtx x, rtx *base, HOST_WIDE_INT *offset)
00895 {
00896 *offset = 0;
00897
00898 if (GET_CODE (x) == CONST)
00899 x = XEXP (x, 0);
00900
00901 if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT)
00902 {
00903 *offset += INTVAL (XEXP (x, 1));
00904 x = XEXP (x, 0);
00905 }
00906 *base = x;
00907 }
00908
00909
00910
00911
00912
00913 static bool
00914 mips_offset_within_object_p (rtx symbol, HOST_WIDE_INT offset)
00915 {
00916 if (GET_CODE (symbol) != SYMBOL_REF)
00917 return false;
00918
00919 if (CONSTANT_POOL_ADDRESS_P (symbol)
00920 && offset >= 0
00921 && offset < (int) GET_MODE_SIZE (get_pool_mode (symbol)))
00922 return true;
00923
00924 if (SYMBOL_REF_DECL (symbol) != 0
00925 && offset >= 0
00926 && offset < int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (symbol))))
00927 return true;
00928
00929 return false;
00930 }
00931
00932
00933
00934
00935
00936
00937 bool
00938 mips_symbolic_constant_p (rtx x, enum mips_symbol_type *symbol_type)
00939 {
00940 HOST_WIDE_INT offset;
00941
00942 mips_split_const (x, &x, &offset);
00943 if (UNSPEC_ADDRESS_P (x))
00944 *symbol_type = UNSPEC_ADDRESS_TYPE (x);
00945 else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
00946 *symbol_type = mips_classify_symbol (x);
00947 else
00948 return false;
00949
00950 if (offset == 0)
00951 return true;
00952
00953
00954
00955 switch (*symbol_type)
00956 {
00957 case SYMBOL_GENERAL:
00958 case SYMBOL_64_HIGH:
00959 case SYMBOL_64_MID:
00960 case SYMBOL_64_LOW:
00961
00962
00963
00964
00965 if (Pmode == DImode && !ABI_HAS_64BIT_SYMBOLS)
00966 return mips_offset_within_object_p (x, offset);
00967
00968
00969 return true;
00970
00971 case SYMBOL_CONSTANT_POOL:
00972
00973
00974
00975 if (GET_CODE (x) == LABEL_REF)
00976 return true;
00977
00978
00979
00980 case SYMBOL_SMALL_DATA:
00981
00982
00983
00984 return mips_offset_within_object_p (x, offset);
00985
00986 case SYMBOL_GOT_LOCAL:
00987 case SYMBOL_GOTOFF_PAGE:
00988
00989
00990 return SMALL_OPERAND (offset);
00991
00992 case SYMBOL_GOT_GLOBAL:
00993 case SYMBOL_GOTOFF_GLOBAL:
00994 case SYMBOL_GOTOFF_CALL:
00995 case SYMBOL_GOTOFF_LOADGP:
00996 return false;
00997 }
00998 gcc_unreachable ();
00999 }
01000
01001
01002
01003
01004
01005 bool
01006 mips_atomic_symbolic_constant_p (rtx x)
01007 {
01008 enum mips_symbol_type type;
01009 return mips_symbolic_constant_p (x, &type) && !mips_split_p[type];
01010 }
01011
01012
01013
01014
01015 int
01016 mips_regno_mode_ok_for_base_p (int regno, enum machine_mode mode, int strict)
01017 {
01018 if (regno >= FIRST_PSEUDO_REGISTER)
01019 {
01020 if (!strict)
01021 return true;
01022 regno = reg_renumber[regno];
01023 }
01024
01025
01026
01027
01028 if (regno == ARG_POINTER_REGNUM || regno == FRAME_POINTER_REGNUM)
01029 return true;
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046 if (TARGET_MIPS16 && regno == STACK_POINTER_REGNUM)
01047 return !strict || GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8;
01048
01049 return TARGET_MIPS16 ? M16_REG_P (regno) : GP_REG_P (regno);
01050 }
01051
01052
01053
01054
01055
01056 static bool
01057 mips_valid_base_register_p (rtx x, enum machine_mode mode, int strict)
01058 {
01059 if (!strict && GET_CODE (x) == SUBREG)
01060 x = SUBREG_REG (x);
01061
01062 return (REG_P (x)
01063 && mips_regno_mode_ok_for_base_p (REGNO (x), mode, strict));
01064 }
01065
01066
01067
01068
01069
01070 static bool
01071 mips_symbolic_address_p (enum mips_symbol_type symbol_type,
01072 enum machine_mode mode)
01073 {
01074 switch (symbol_type)
01075 {
01076 case SYMBOL_GENERAL:
01077 return !TARGET_MIPS16;
01078
01079 case SYMBOL_SMALL_DATA:
01080 return true;
01081
01082 case SYMBOL_CONSTANT_POOL:
01083
01084 return GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8;
01085
01086 case SYMBOL_GOT_LOCAL:
01087 return true;
01088
01089 case SYMBOL_GOT_GLOBAL:
01090
01091 return false;
01092
01093 case SYMBOL_GOTOFF_PAGE:
01094 case SYMBOL_GOTOFF_GLOBAL:
01095 case SYMBOL_GOTOFF_CALL:
01096 case SYMBOL_GOTOFF_LOADGP:
01097 case SYMBOL_64_HIGH:
01098 case SYMBOL_64_MID:
01099 case SYMBOL_64_LOW:
01100 return true;
01101 }
01102 gcc_unreachable ();
01103 }
01104
01105
01106
01107
01108
01109
01110 static bool
01111 mips_classify_address (struct mips_address_info *info, rtx x,
01112 enum machine_mode mode, int strict)
01113 {
01114 switch (GET_CODE (x))
01115 {
01116 case REG:
01117 case SUBREG:
01118 info->type = ADDRESS_REG;
01119 info->reg = x;
01120 info->offset = const0_rtx;
01121 return mips_valid_base_register_p (info->reg, mode, strict);
01122
01123 case PLUS:
01124 info->type = ADDRESS_REG;
01125 info->reg = XEXP (x, 0);
01126 info->offset = XEXP (x, 1);
01127 return (mips_valid_base_register_p (info->reg, mode, strict)
01128 && const_arith_operand (info->offset, VOIDmode));
01129
01130 case LO_SUM:
01131 info->type = ADDRESS_LO_SUM;
01132 info->reg = XEXP (x, 0);
01133 info->offset = XEXP (x, 1);
01134 return (mips_valid_base_register_p (info->reg, mode, strict)
01135 && mips_symbolic_constant_p (info->offset, &info->symbol_type)
01136 && mips_symbolic_address_p (info->symbol_type, mode)
01137 && mips_lo_relocs[info->symbol_type] != 0);
01138
01139 case CONST_INT:
01140
01141
01142 info->type = ADDRESS_CONST_INT;
01143 return !TARGET_MIPS16 && SMALL_INT (x);
01144
01145 case CONST:
01146 case LABEL_REF:
01147 case SYMBOL_REF:
01148 info->type = ADDRESS_SYMBOLIC;
01149 return (mips_symbolic_constant_p (x, &info->symbol_type)
01150 && mips_symbolic_address_p (info->symbol_type, mode)
01151 && !mips_split_p[info->symbol_type]);
01152
01153 default:
01154 return false;
01155 }
01156 }
01157
01158
01159
01160
01161
01162
01163 static int
01164 mips_symbol_insns (enum mips_symbol_type type)
01165 {
01166 switch (type)
01167 {
01168 case SYMBOL_GENERAL:
01169
01170
01171 if (TARGET_MIPS16)
01172 return 0;
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185 return (ABI_HAS_64BIT_SYMBOLS ? 6 : 2);
01186
01187 case SYMBOL_SMALL_DATA:
01188 return 1;
01189
01190 case SYMBOL_CONSTANT_POOL:
01191
01192
01193 return 2;
01194
01195 case SYMBOL_GOT_LOCAL:
01196 case SYMBOL_GOT_GLOBAL:
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217 return 3;
01218
01219 case SYMBOL_GOTOFF_PAGE:
01220 case SYMBOL_GOTOFF_GLOBAL:
01221 case SYMBOL_GOTOFF_CALL:
01222 case SYMBOL_GOTOFF_LOADGP:
01223 case SYMBOL_64_HIGH:
01224 case SYMBOL_64_MID:
01225 case SYMBOL_64_LOW:
01226
01227 return mips_split_p[type] ? 2 : 1;
01228 }
01229 gcc_unreachable ();
01230 }
01231
01232
01233
01234 bool
01235 mips_stack_address_p (rtx x, enum machine_mode mode)
01236 {
01237 struct mips_address_info addr;
01238
01239 return (mips_classify_address (&addr, x, mode, false)
01240 && addr.type == ADDRESS_REG
01241 && addr.reg == stack_pointer_rtx);
01242 }
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253 static bool
01254 mips16_unextended_reference_p (enum machine_mode mode, rtx base, rtx offset)
01255 {
01256 if (TARGET_MIPS16
01257 && GET_CODE (offset) == CONST_INT
01258 && INTVAL (offset) >= 0
01259 && (INTVAL (offset) & (GET_MODE_SIZE (mode) - 1)) == 0)
01260 {
01261 if (GET_MODE_SIZE (mode) == 4 && base == stack_pointer_rtx)
01262 return INTVAL (offset) < 256 * GET_MODE_SIZE (mode);
01263 return INTVAL (offset) < 32 * GET_MODE_SIZE (mode);
01264 }
01265 return false;
01266 }
01267
01268
01269
01270
01271
01272
01273
01274 int
01275 mips_address_insns (rtx x, enum machine_mode mode)
01276 {
01277 struct mips_address_info addr;
01278 int factor;
01279
01280 if (mode == BLKmode)
01281
01282 factor = 1;
01283 else
01284
01285 factor = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
01286
01287 if (mips_classify_address (&addr, x, mode, false))
01288 switch (addr.type)
01289 {
01290 case ADDRESS_REG:
01291 if (TARGET_MIPS16
01292 && !mips16_unextended_reference_p (mode, addr.reg, addr.offset))
01293 return factor * 2;
01294 return factor;
01295
01296 case ADDRESS_LO_SUM:
01297 return (TARGET_MIPS16 ? factor * 2 : factor);
01298
01299 case ADDRESS_CONST_INT:
01300 return factor;
01301
01302 case ADDRESS_SYMBOLIC:
01303 return factor * mips_symbol_insns (addr.symbol_type);
01304 }
01305 return 0;
01306 }
01307
01308
01309
01310
01311 int
01312 mips_const_insns (rtx x)
01313 {
01314 struct mips_integer_op codes[MIPS_MAX_INTEGER_OPS];
01315 enum mips_symbol_type symbol_type;
01316 HOST_WIDE_INT offset;
01317
01318 switch (GET_CODE (x))
01319 {
01320 case HIGH:
01321 if (TARGET_MIPS16
01322 || !mips_symbolic_constant_p (XEXP (x, 0), &symbol_type)
01323 || !mips_split_p[symbol_type])
01324 return 0;
01325
01326 return 1;
01327
01328 case CONST_INT:
01329 if (TARGET_MIPS16)
01330
01331
01332
01333
01334 return (INTVAL (x) >= 0 && INTVAL (x) < 256 ? 1
01335 : SMALL_OPERAND_UNSIGNED (INTVAL (x)) ? 2
01336 : INTVAL (x) > -256 && INTVAL (x) < 0 ? 2
01337 : SMALL_OPERAND_UNSIGNED (-INTVAL (x)) ? 3
01338 : 0);
01339
01340 return mips_build_integer (codes, INTVAL (x));
01341
01342 case CONST_DOUBLE:
01343 case CONST_VECTOR:
01344 return (!TARGET_MIPS16 && x == CONST0_RTX (GET_MODE (x)) ? 1 : 0);
01345
01346 case CONST:
01347 if (CONST_GP_P (x))
01348 return 1;
01349
01350
01351 if (mips_symbolic_constant_p (x, &symbol_type))
01352 return mips_symbol_insns (symbol_type);
01353
01354
01355
01356
01357 mips_split_const (x, &x, &offset);
01358 if (offset != 0)
01359 {
01360 int n = mips_const_insns (x);
01361 if (n != 0)
01362 {
01363 if (SMALL_OPERAND (offset))
01364 return n + 1;
01365 else
01366 return n + 1 + mips_build_integer (codes, offset);
01367 }
01368 }
01369 return 0;
01370
01371 case SYMBOL_REF:
01372 case LABEL_REF:
01373 return mips_symbol_insns (mips_classify_symbol (x));
01374
01375 default:
01376 return 0;
01377 }
01378 }
01379
01380
01381
01382
01383
01384 int
01385 mips_fetch_insns (rtx x)
01386 {
01387 gcc_assert (MEM_P (x));
01388 return mips_address_insns (XEXP (x, 0), GET_MODE (x));
01389 }
01390
01391
01392
01393
01394 int
01395 mips_idiv_insns (void)
01396 {
01397 int count;
01398
01399 count = 1;
01400 if (TARGET_CHECK_ZERO_DIV)
01401 {
01402 if (GENERATE_DIVIDE_TRAPS)
01403 count++;
01404 else
01405 count += 2;
01406 }
01407
01408 if (TARGET_FIX_R4000 || TARGET_FIX_R4400)
01409 count++;
01410 return count;
01411 }
01412
01413
01414
01415
01416
01417
01418 bool
01419 mips_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
01420 {
01421 struct mips_address_info addr;
01422
01423 return mips_classify_address (&addr, x, mode, strict);
01424 }
01425
01426
01427
01428
01429
01430 static rtx
01431 mips_force_temporary (rtx dest, rtx value)
01432 {
01433 if (!no_new_pseudos)
01434 return force_reg (Pmode, value);
01435 else
01436 {
01437 emit_move_insn (copy_rtx (dest), value);
01438 return dest;
01439 }
01440 }
01441
01442
01443
01444
01445
01446 static rtx
01447 mips_split_symbol (rtx temp, rtx addr)
01448 {
01449 rtx high;
01450
01451 if (TARGET_MIPS16)
01452 high = mips16_gp_pseudo_reg ();
01453 else
01454 high = mips_force_temporary (temp, gen_rtx_HIGH (Pmode, copy_rtx (addr)));
01455 return gen_rtx_LO_SUM (Pmode, high, addr);
01456 }
01457
01458
01459
01460
01461
01462 rtx
01463 mips_unspec_address (rtx address, enum mips_symbol_type symbol_type)
01464 {
01465 rtx base;
01466 HOST_WIDE_INT offset;
01467
01468 mips_split_const (address, &base, &offset);
01469 base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base),
01470 UNSPEC_ADDRESS_FIRST + symbol_type);
01471 return plus_constant (gen_rtx_CONST (Pmode, base), offset);
01472 }
01473
01474
01475
01476
01477
01478
01479
01480
01481 static rtx
01482 mips_unspec_offset_high (rtx temp, rtx base, rtx addr,
01483 enum mips_symbol_type symbol_type)
01484 {
01485 if (mips_split_p[symbol_type])
01486 {
01487 addr = gen_rtx_HIGH (Pmode, mips_unspec_address (addr, symbol_type));
01488 addr = mips_force_temporary (temp, addr);
01489 return mips_force_temporary (temp, gen_rtx_PLUS (Pmode, addr, base));
01490 }
01491 return base;
01492 }
01493
01494
01495
01496
01497
01498
01499 static rtx
01500 mips_add_offset (rtx temp, rtx reg, HOST_WIDE_INT offset)
01501 {
01502 if (!SMALL_OPERAND (offset))
01503 {
01504 rtx high;
01505 if (TARGET_MIPS16)
01506 {
01507
01508
01509 high = GEN_INT (offset);
01510 offset = 0;
01511 }
01512 else
01513 {
01514
01515 high = GEN_INT (CONST_HIGH_PART (offset));
01516 offset = CONST_LOW_PART (offset);
01517 }
01518 high = mips_force_temporary (temp, high);
01519 reg = mips_force_temporary (temp, gen_rtx_PLUS (Pmode, high, reg));
01520 }
01521 return plus_constant (reg, offset);
01522 }
01523
01524
01525
01526
01527
01528
01529
01530 bool
01531 mips_legitimize_address (rtx *xloc, enum machine_mode mode)
01532 {
01533 enum mips_symbol_type symbol_type;
01534
01535
01536 if (mips_symbolic_constant_p (*xloc, &symbol_type)
01537 && mips_symbolic_address_p (symbol_type, mode)
01538 && mips_split_p[symbol_type])
01539 {
01540 *xloc = mips_split_symbol (0, *xloc);
01541 return true;
01542 }
01543
01544 if (GET_CODE (*xloc) == PLUS && GET_CODE (XEXP (*xloc, 1)) == CONST_INT)
01545 {
01546
01547 rtx reg;
01548
01549 reg = XEXP (*xloc, 0);
01550 if (!mips_valid_base_register_p (reg, mode, 0))
01551 reg = copy_to_mode_reg (Pmode, reg);
01552 *xloc = mips_add_offset (0, reg, INTVAL (XEXP (*xloc, 1)));
01553 return true;
01554 }
01555
01556 return false;
01557 }
01558
01559
01560
01561
01562
01563 static unsigned int
01564 mips_build_shift (struct mips_integer_op *codes, HOST_WIDE_INT value)
01565 {
01566 unsigned int i, shift;
01567
01568
01569
01570 shift = 0;
01571 while ((value & 1) == 0)
01572 value /= 2, shift++;
01573
01574 i = mips_build_integer (codes, value);
01575 codes[i].code = ASHIFT;
01576 codes[i].value = shift;
01577 return i + 1;
01578 }
01579
01580
01581
01582
01583
01584 static unsigned int
01585 mips_build_lower (struct mips_integer_op *codes, unsigned HOST_WIDE_INT value)
01586 {
01587 unsigned HOST_WIDE_INT high;
01588 unsigned int i;
01589
01590 high = value & ~(unsigned HOST_WIDE_INT) 0xffff;
01591 if (!LUI_OPERAND (high) && (value & 0x18000) == 0x18000)
01592 {
01593
01594
01595
01596
01597
01598 i = mips_build_integer (codes, CONST_HIGH_PART (value));
01599 codes[i].code = PLUS;
01600 codes[i].value = CONST_LOW_PART (value);
01601 }
01602 else
01603 {
01604 i = mips_build_integer (codes, high);
01605 codes[i].code = IOR;
01606 codes[i].value = value & 0xffff;
01607 }
01608 return i + 1;
01609 }
01610
01611
01612
01613
01614
01615 static unsigned int
01616 mips_build_integer (struct mips_integer_op *codes,
01617 unsigned HOST_WIDE_INT value)
01618 {
01619 if (SMALL_OPERAND (value)
01620 || SMALL_OPERAND_UNSIGNED (value)
01621 || LUI_OPERAND (value))
01622 {
01623
01624 codes[0].code = UNKNOWN;
01625 codes[0].value = value;
01626 return 1;
01627 }
01628 else if ((value & 1) != 0 || LUI_OPERAND (CONST_HIGH_PART (value)))
01629 {
01630
01631
01632 return mips_build_lower (codes, value);
01633 }
01634 else if ((value & 0xffff) == 0)
01635 {
01636
01637
01638 return mips_build_shift (codes, value);
01639 }
01640 else
01641 {
01642
01643
01644
01645
01646
01647 struct mips_integer_op alt_codes[MIPS_MAX_INTEGER_OPS];
01648 unsigned int cost, alt_cost;
01649
01650 cost = mips_build_shift (codes, value);
01651 alt_cost = mips_build_lower (alt_codes, value);
01652 if (alt_cost < cost)
01653 {
01654 memcpy (codes, alt_codes, alt_cost * sizeof (codes[0]));
01655 cost = alt_cost;
01656 }
01657 return cost;
01658 }
01659 }
01660
01661
01662
01663
01664 static void
01665 mips_move_integer (rtx dest, unsigned HOST_WIDE_INT value)
01666 {
01667 struct mips_integer_op codes[MIPS_MAX_INTEGER_OPS];
01668 enum machine_mode mode;
01669 unsigned int i, cost;
01670 rtx x;
01671
01672 mode = GET_MODE (dest);
01673 cost = mips_build_integer (codes, value);
01674
01675
01676
01677 x = GEN_INT (codes[0].value);
01678 for (i = 1; i < cost; i++)
01679 {
01680 if (no_new_pseudos)
01681 emit_move_insn (dest, x), x = dest;
01682 else
01683 x = force_reg (mode, x);
01684 x = gen_rtx_fmt_ee (codes[i].code, mode, x, GEN_INT (codes[i].value));
01685 }
01686
01687 emit_insn (gen_rtx_SET (VOIDmode, dest, x));
01688 }
01689
01690
01691
01692
01693
01694
01695 static void
01696 mips_legitimize_const_move (enum machine_mode mode, rtx dest, rtx src)
01697 {
01698 rtx base;
01699 HOST_WIDE_INT offset;
01700 enum mips_symbol_type symbol_type;
01701
01702
01703
01704 if (GET_CODE (src) == CONST_INT && !TARGET_MIPS16)
01705 {
01706 mips_move_integer (dest, INTVAL (src));
01707 return;
01708 }
01709
01710
01711
01712
01713 if (!TARGET_MIPS16
01714 && mips_symbolic_constant_p (src, &symbol_type)
01715 && mips_split_p[symbol_type])
01716 {
01717 emit_move_insn (dest, mips_split_symbol (dest, src));
01718 return;
01719 }
01720
01721
01722
01723
01724 mips_split_const (src, &base, &offset);
01725 if (!TARGET_MIPS16
01726 && offset != 0
01727 && (!no_new_pseudos || SMALL_OPERAND (offset)))
01728 {
01729 base = mips_force_temporary (dest, base);
01730 emit_move_insn (dest, mips_add_offset (0, base, offset));
01731 return;
01732 }
01733
01734 src = force_const_mem (mode, src);
01735
01736
01737
01738 if (!memory_operand (src, VOIDmode))
01739 src = replace_equiv_address (src, mips_split_symbol (dest, XEXP (src, 0)));
01740 emit_move_insn (dest, src);
01741 }
01742
01743
01744
01745
01746
01747 bool
01748 mips_legitimize_move (enum machine_mode mode, rtx dest, rtx src)
01749 {
01750 if (!register_operand (dest, mode) && !reg_or_0_operand (src, mode))
01751 {
01752 emit_move_insn (dest, force_reg (mode, src));
01753 return true;
01754 }
01755
01756
01757 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
01758 && REG_P (src) && MD_REG_P (REGNO (src))
01759 && REG_P (dest) && GP_REG_P (REGNO (dest)))
01760 {
01761 int other_regno = REGNO (src) == HI_REGNUM ? LO_REGNUM : HI_REGNUM;
01762 if (GET_MODE_SIZE (mode) <= 4)
01763 emit_insn (gen_mfhilo_si (gen_rtx_REG (SImode, REGNO (dest)),
01764 gen_rtx_REG (SImode, REGNO (src)),
01765 gen_rtx_REG (SImode, other_regno)));
01766 else
01767 emit_insn (gen_mfhilo_di (gen_rtx_REG (DImode, REGNO (dest)),
01768 gen_rtx_REG (DImode, REGNO (src)),
01769 gen_rtx_REG (DImode, other_regno)));
01770 return true;
01771 }
01772
01773
01774
01775 if (CONSTANT_P (src) && !move_operand (src, mode))
01776 {
01777 mips_legitimize_const_move (mode, dest, src);
01778 set_unique_reg_note (get_last_insn (), REG_EQUAL, copy_rtx (src));
01779 return true;
01780 }
01781 return false;
01782 }
01783
01784
01785
01786
01787
01788
01789 static int
01790 m16_check_op (rtx op, int low, int high, int mask)
01791 {
01792 return (GET_CODE (op) == CONST_INT
01793 && INTVAL (op) >= low
01794 && INTVAL (op) <= high
01795 && (INTVAL (op) & mask) == 0);
01796 }
01797
01798 int
01799 m16_uimm3_b (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01800 {
01801 return m16_check_op (op, 0x1, 0x8, 0);
01802 }
01803
01804 int
01805 m16_simm4_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01806 {
01807 return m16_check_op (op, - 0x8, 0x7, 0);
01808 }
01809
01810 int
01811 m16_nsimm4_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01812 {
01813 return m16_check_op (op, - 0x7, 0x8, 0);
01814 }
01815
01816 int
01817 m16_simm5_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01818 {
01819 return m16_check_op (op, - 0x10, 0xf, 0);
01820 }
01821
01822 int
01823 m16_nsimm5_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01824 {
01825 return m16_check_op (op, - 0xf, 0x10, 0);
01826 }
01827
01828 int
01829 m16_uimm5_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01830 {
01831 return m16_check_op (op, (- 0x10) << 2, 0xf << 2, 3);
01832 }
01833
01834 int
01835 m16_nuimm5_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01836 {
01837 return m16_check_op (op, (- 0xf) << 2, 0x10 << 2, 3);
01838 }
01839
01840 int
01841 m16_simm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01842 {
01843 return m16_check_op (op, - 0x80, 0x7f, 0);
01844 }
01845
01846 int
01847 m16_nsimm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01848 {
01849 return m16_check_op (op, - 0x7f, 0x80, 0);
01850 }
01851
01852 int
01853 m16_uimm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01854 {
01855 return m16_check_op (op, 0x0, 0xff, 0);
01856 }
01857
01858 int
01859 m16_nuimm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01860 {
01861 return m16_check_op (op, - 0xff, 0x0, 0);
01862 }
01863
01864 int
01865 m16_uimm8_m1_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01866 {
01867 return m16_check_op (op, - 0x1, 0xfe, 0);
01868 }
01869
01870 int
01871 m16_uimm8_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01872 {
01873 return m16_check_op (op, 0x0, 0xff << 2, 3);
01874 }
01875
01876 int
01877 m16_nuimm8_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01878 {
01879 return m16_check_op (op, (- 0xff) << 2, 0x0, 3);
01880 }
01881
01882 int
01883 m16_simm8_8 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01884 {
01885 return m16_check_op (op, (- 0x80) << 3, 0x7f << 3, 7);
01886 }
01887
01888 int
01889 m16_nsimm8_8 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
01890 {
01891 return m16_check_op (op, (- 0x7f) << 3, 0x80 << 3, 7);
01892 }
01893
01894 static bool
01895 mips_rtx_costs (rtx x, int code, int outer_code, int *total)
01896 {
01897 enum machine_mode mode = GET_MODE (x);
01898
01899 switch (code)
01900 {
01901 case CONST_INT:
01902 if (!TARGET_MIPS16)
01903 {
01904
01905
01906
01907 *total = 0;
01908 return true;
01909 }
01910
01911
01912
01913 if ((outer_code) == ASHIFT || (outer_code) == ASHIFTRT
01914 || (outer_code) == LSHIFTRT)
01915 {
01916 if (INTVAL (x) >= 1 && INTVAL (x) <= 8)
01917 *total = 0;
01918 else
01919 *total = COSTS_N_INSNS (1);
01920 return true;
01921 }
01922
01923
01924 if ((outer_code) == XOR
01925 && INTVAL (x) >= 0 && INTVAL (x) < 0x10000)
01926 {
01927 *total = 0;
01928 return true;
01929 }
01930
01931
01932
01933
01934 if (((outer_code) == LT || (outer_code) == LE
01935 || (outer_code) == GE || (outer_code) == GT
01936 || (outer_code) == LTU || (outer_code) == LEU
01937 || (outer_code) == GEU || (outer_code) == GTU)
01938 && INTVAL (x) >= -0x8000 && INTVAL (x) < 0x8000)
01939 {
01940 *total = 0;
01941 return true;
01942 }
01943
01944
01945 if (((outer_code) == EQ || (outer_code) == NE)
01946 && INTVAL (x) == 0)
01947 {
01948 *total = 0;
01949 return true;
01950 }
01951
01952
01953
01954
01955
01956
01957
01958 if (outer_code == SET
01959 && INTVAL (x) >= 0
01960 && INTVAL (x) < 256)
01961 {
01962 *total = 0;
01963 return true;
01964 }
01965
01966
01967
01968 case CONST:
01969 case SYMBOL_REF:
01970 case LABEL_REF:
01971 case CONST_DOUBLE:
01972 if (LEGITIMATE_CONSTANT_P (x))
01973 {
01974 *total = COSTS_N_INSNS (1);
01975 return true;
01976 }
01977 else
01978 {
01979
01980 *total = CONSTANT_POOL_COST;
01981 return true;
01982 }
01983
01984 case MEM:
01985 {
01986
01987
01988 int n = mips_address_insns (XEXP (x, 0), GET_MODE (x));
01989 if (n > 0)
01990 {
01991 *total = COSTS_N_INSNS (1 + n);
01992 return true;
01993 }
01994 return false;
01995 }
01996
01997 case FFS:
01998 *total = COSTS_N_INSNS (6);
01999 return true;
02000
02001 case NOT:
02002 *total = COSTS_N_INSNS ((mode == DImode && !TARGET_64BIT) ? 2 : 1);
02003 return true;
02004
02005 case AND:
02006 case IOR:
02007 case XOR:
02008 if (mode == DImode && !TARGET_64BIT)
02009 {
02010 *total = COSTS_N_INSNS (2);
02011 return true;
02012 }
02013 return false;
02014
02015 case ASHIFT:
02016 case ASHIFTRT:
02017 case LSHIFTRT:
02018 if (mode == DImode && !TARGET_64BIT)
02019 {
02020 *total = COSTS_N_INSNS ((GET_CODE (XEXP (x, 1)) == CONST_INT)
02021 ? 4 : 12);
02022 return true;
02023 }
02024 return false;
02025
02026 case ABS:
02027 if (mode == SFmode || mode == DFmode)
02028 *total = COSTS_N_INSNS (1);
02029 else
02030 *total = COSTS_N_INSNS (4);
02031 return true;
02032
02033 case LO_SUM:
02034 *total = COSTS_N_INSNS (1);
02035 return true;
02036
02037 case PLUS:
02038 case MINUS:
02039 if (mode == SFmode || mode == DFmode)
02040 {
02041 if (TUNE_MIPS3000 || TUNE_MIPS3900)
02042 *total = COSTS_N_INSNS (2);
02043 else if (TUNE_MIPS6000)
02044 *total = COSTS_N_INSNS (3);
02045 else if (TUNE_SB1)
02046 *total = COSTS_N_INSNS (4);
02047 else
02048 *total = COSTS_N_INSNS (6);
02049 return true;
02050 }
02051 if (mode == DImode && !TARGET_64BIT)
02052 {
02053 *total = COSTS_N_INSNS (4);
02054 return true;
02055 }
02056 return false;
02057
02058 case NEG:
02059 if (mode == DImode && !TARGET_64BIT)
02060 {
02061 *total = 4;
02062 return true;
02063 }
02064 return false;
02065
02066 case MULT:
02067 if (mode == SFmode)
02068 {
02069 if (TUNE_MIPS3000
02070 || TUNE_MIPS3900
02071 || TUNE_MIPS5000
02072 || TUNE_SB1)
02073 *total = COSTS_N_INSNS (4);
02074 else if (TUNE_MIPS6000
02075 || TUNE_MIPS5400
02076 || TUNE_MIPS5500)
02077 *total = COSTS_N_INSNS (5);
02078 else
02079 *total = COSTS_N_INSNS (7);
02080 return true;
02081 }
02082
02083 if (mode == DFmode)
02084 {
02085 if (TUNE_SB1)
02086 *total = COSTS_N_INSNS (4);
02087 else if (TUNE_MIPS3000
02088 || TUNE_MIPS3900
02089 || TUNE_MIPS5000)
02090 *total = COSTS_N_INSNS (5);
02091 else if (TUNE_MIPS6000
02092 || TUNE_MIPS5400
02093 || TUNE_MIPS5500)
02094 *total = COSTS_N_INSNS (6);
02095 else
02096 *total = COSTS_N_INSNS (8);
02097 return true;
02098 }
02099
02100 if (TUNE_MIPS3000)
02101 *total = COSTS_N_INSNS (12);
02102 else if (TUNE_MIPS3900)
02103 *total = COSTS_N_INSNS (2);
02104 else if (TUNE_MIPS4130)
02105 *total = COSTS_N_INSNS (mode == DImode ? 6 : 4);
02106 else if (TUNE_MIPS5400 || TUNE_SB1)
02107 *total = COSTS_N_INSNS (mode == DImode ? 4 : 3);
02108 else if (TUNE_MIPS5500 || TUNE_MIPS7000)
02109 *total = COSTS_N_INSNS (mode == DImode ? 9 : 5);
02110 else if (TUNE_MIPS9000)
02111 *total = COSTS_N_INSNS (mode == DImode ? 8 : 3);
02112 else if (TUNE_MIPS6000)
02113 *total = COSTS_N_INSNS (17);
02114 else if (TUNE_MIPS5000)
02115 *total = COSTS_N_INSNS (5);
02116 else
02117 *total = COSTS_N_INSNS (10);
02118 return true;
02119
02120 case DIV:
02121 case MOD:
02122 if (mode == SFmode)
02123 {
02124 if (TUNE_MIPS3000
02125 || TUNE_MIPS3900)
02126 *total = COSTS_N_INSNS (12);
02127 else if (TUNE_MIPS6000)
02128 *total = COSTS_N_INSNS (15);
02129 else if (TUNE_SB1)
02130 *total = COSTS_N_INSNS (24);
02131 else if (TUNE_MIPS5400 || TUNE_MIPS5500)
02132 *total = COSTS_N_INSNS (30);
02133 else
02134 *total = COSTS_N_INSNS (23);
02135 return true;
02136 }
02137
02138 if (mode == DFmode)
02139 {
02140 if (TUNE_MIPS3000
02141 || TUNE_MIPS3900)
02142 *total = COSTS_N_INSNS (19);
02143 else if (TUNE_MIPS5400 || TUNE_MIPS5500)
02144 *total = COSTS_N_INSNS (59);
02145 else if (TUNE_MIPS6000)
02146 *total = COSTS_N_INSNS (16);
02147 else if (TUNE_SB1)
02148 *total = COSTS_N_INSNS (32);
02149 else
02150 *total = COSTS_N_INSNS (36);
02151 return true;
02152 }
02153
02154
02155 case UDIV:
02156 case UMOD:
02157 if (TUNE_MIPS3000
02158 || TUNE_MIPS3900)
02159 *total = COSTS_N_INSNS (35);
02160 else if (TUNE_MIPS6000)
02161 *total = COSTS_N_INSNS (38);
02162 else if (TUNE_MIPS5000)
02163 *total = COSTS_N_INSNS (36);
02164 else if (TUNE_SB1)
02165 *total = COSTS_N_INSNS ((mode == SImode) ? 36 : 68);
02166 else if (TUNE_MIPS5400 || TUNE_MIPS5500)
02167 *total = COSTS_N_INSNS ((mode == SImode) ? 42 : 74);
02168 else
02169 *total = COSTS_N_INSNS (69);
02170 return true;
02171
02172 case SIGN_EXTEND:
02173
02174
02175
02176 if (TARGET_64BIT && mode == DImode
02177 && GET_MODE (XEXP (x, 0)) == SImode)
02178 *total = COSTS_N_INSNS (1);
02179 else
02180 *total = COSTS_N_INSNS (2);
02181 return true;
02182
02183 case ZERO_EXTEND:
02184 if (TARGET_64BIT && mode == DImode
02185 && GET_MODE (XEXP (x, 0)) == SImode)
02186 *total = COSTS_N_INSNS (2);
02187 else
02188 *total = COSTS_N_INSNS (1);
02189 return true;
02190
02191 default:
02192 return false;
02193 }
02194 }
02195
02196
02197
02198
02199 static int
02200 mips_address_cost (rtx addr)
02201 {
02202 return mips_address_insns (addr, SImode);
02203 }
02204
02205
02206
02207
02208
02209 rtx
02210 mips_subword (rtx op, int high_p)
02211 {
02212 unsigned int byte;
02213 enum machine_mode mode;
02214
02215 mode = GET_MODE (op);
02216 if (mode == VOIDmode)
02217 mode = DImode;
02218
02219 if (TARGET_BIG_ENDIAN ? !high_p : high_p)
02220 byte = UNITS_PER_WORD;
02221 else
02222 byte = 0;
02223
02224 if (REG_P (op))
02225 {
02226 if (FP_REG_P (REGNO (op)))
02227 return gen_rtx_REG (word_mode, high_p ? REGNO (op) + 1 : REGNO (op));
02228 if (REGNO (op) == HI_REGNUM)
02229 return gen_rtx_REG (word_mode, high_p ? HI_REGNUM : LO_REGNUM);
02230 }
02231
02232 if (MEM_P (op))
02233 return mips_rewrite_small_data (adjust_address (op, word_mode, byte));
02234
02235 return simplify_gen_subreg (word_mode, op, mode, byte);
02236 }
02237
02238
02239
02240
02241 bool
02242 mips_split_64bit_move_p (rtx dest, rtx src)
02243 {
02244 if (TARGET_64BIT)
02245 return false;
02246
02247
02248 if (FP_REG_RTX_P (src) && FP_REG_RTX_P (dest))
02249 return false;
02250
02251
02252
02253 if (mips_isa > 1)
02254 {
02255 if (FP_REG_RTX_P (dest) && MEM_P (src))
02256 return false;
02257 if (FP_REG_RTX_P (src) && MEM_P (dest))
02258 return false;
02259 }
02260 return true;
02261 }
02262
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279 void
02280 mips_split_64bit_move (rtx dest, rtx src)
02281 {
02282 if (FP_REG_RTX_P (dest))
02283 {
02284
02285 emit_insn (gen_load_df_low (copy_rtx (dest), mips_subword (src, 0)));
02286 emit_insn (gen_load_df_high (dest, mips_subword (src, 1),
02287 copy_rtx (dest)));
02288 }
02289 else if (FP_REG_RTX_P (src))
02290 {
02291
02292 emit_move_insn (mips_subword (dest, 0), mips_subword (src, 0));
02293 emit_insn (gen_store_df_high (mips_subword (dest, 1), src));
02294 }
02295 else
02296 {
02297
02298
02299 rtx low_dest;
02300
02301 low_dest = mips_subword (dest, 0);
02302 if (REG_P (low_dest)
02303 && reg_overlap_mentioned_p (low_dest, src))
02304 {
02305 emit_move_insn (mips_subword (dest, 1), mips_subword (src, 1));
02306 emit_move_insn (low_dest, mips_subword (src, 0));
02307 }
02308 else
02309 {
02310 emit_move_insn (low_dest, mips_subword (src, 0));
02311 emit_move_insn (mips_subword (dest, 1), mips_subword (src, 1));
02312 }
02313 }
02314 }
02315
02316
02317
02318
02319 const char *
02320 mips_output_move (rtx dest, rtx src)
02321 {
02322 enum rtx_code dest_code, src_code;
02323 bool dbl_p;
02324
02325 dest_code = GET_CODE (dest);
02326 src_code = GET_CODE (src);
02327 dbl_p = (GET_MODE_SIZE (GET_MODE (dest)) == 8);
02328
02329 if (dbl_p && mips_split_64bit_move_p (dest, src))
02330 return "#";
02331
02332 if ((src_code == REG && GP_REG_P (REGNO (src)))
02333 || (!TARGET_MIPS16 && src == CONST0_RTX (GET_MODE (dest))))
02334 {
02335 if (dest_code == REG)
02336 {
02337 if (GP_REG_P (REGNO (dest)))
02338 return "move\t%0,%z1";
02339
02340 if (MD_REG_P (REGNO (dest)))
02341 return "mt%0\t%z1";
02342
02343 if (FP_REG_P (REGNO (dest)))
02344 return (dbl_p ? "dmtc1\t%z1,%0" : "mtc1\t%z1,%0");
02345
02346 if (ALL_COP_REG_P (REGNO (dest)))
02347 {
02348 static char retval[] = "dmtc_\t%z1,%0";
02349
02350 retval[4] = COPNUM_AS_CHAR_FROM_REGNUM (REGNO (dest));
02351 return (dbl_p ? retval : retval + 1);
02352 }
02353 }
02354 if (dest_code == MEM)
02355 return (dbl_p ? "sd\t%z1,%0" : "sw\t%z1,%0");
02356 }
02357 if (dest_code == REG && GP_REG_P (REGNO (dest)))
02358 {
02359 if (src_code == REG)
02360 {
02361 if (ST_REG_P (REGNO (src)) && ISA_HAS_8CC)
02362 return "lui\t%0,0x3f80\n\tmovf\t%0,%.,%1";
02363
02364 if (FP_REG_P (REGNO (src)))
02365 return (dbl_p ? "dmfc1\t%0,%1" : "mfc1\t%0,%1");
02366
02367 if (ALL_COP_REG_P (REGNO (src)))
02368 {
02369 static char retval[] = "dmfc_\t%0,%1";
02370
02371 retval[4] = COPNUM_AS_CHAR_FROM_REGNUM (REGNO (src));
02372 return (dbl_p ? retval : retval + 1);
02373 }
02374 }
02375
02376 if (src_code == MEM)
02377 return (dbl_p ? "ld\t%0,%1" : "lw\t%0,%1");
02378
02379 if (src_code == CONST_INT)
02380 {
02381
02382
02383 if (!TARGET_MIPS16)
02384 return "li\t%0,%1\t\t\t# %X1";
02385
02386 if (INTVAL (src) >= 0 && INTVAL (src) <= 0xffff)
02387 return "li\t%0,%1";
02388
02389 if (INTVAL (src) < 0 && INTVAL (src) >= -0xffff)
02390 return "#";
02391 }
02392
02393 if (src_code == HIGH)
02394 return "lui\t%0,%h1";
02395
02396 if (CONST_GP_P (src))
02397 return "move\t%0,%1";
02398
02399 if (symbolic_operand (src, VOIDmode))
02400 return (dbl_p ? "dla\t%0,%1" : "la\t%0,%1");
02401 }
02402 if (src_code == REG && FP_REG_P (REGNO (src)))
02403 {
02404 if (dest_code == REG && FP_REG_P (REGNO (dest)))
02405 {
02406 if (GET_MODE (dest) == V2SFmode)
02407 return "mov.ps\t%0,%1";
02408 else
02409 return (dbl_p ? "mov.d\t%0,%1" : "mov.s\t%0,%1");
02410 }
02411
02412 if (dest_code == MEM)
02413 return (dbl_p ? "sdc1\t%1,%0" : "swc1\t%1,%0");
02414 }
02415 if (dest_code == REG && FP_REG_P (REGNO (dest)))
02416 {
02417 if (src_code == MEM)
02418 return (dbl_p ? "ldc1\t%0,%1" : "lwc1\t%0,%1");
02419 }
02420 if (dest_code == REG && ALL_COP_REG_P (REGNO (dest)) && src_code == MEM)
02421 {
02422 static char retval[] = "l_c_\t%0,%1";
02423
02424 retval[1] = (dbl_p ? 'd' : 'w');
02425 retval[3] = COPNUM_AS_CHAR_FROM_REGNUM (REGNO (dest));
02426 return retval;
02427 }
02428 if (dest_code == MEM && src_code == REG && ALL_COP_REG_P (REGNO (src)))
02429 {
02430 static char retval[] = "s_c_\t%1,%0";
02431
02432 retval[1] = (dbl_p ? 'd' : 'w');
02433 retval[3] = COPNUM_AS_CHAR_FROM_REGNUM (REGNO (src));
02434 return retval;
02435 }
02436 gcc_unreachable ();
02437 }
02438
02439
02440
02441
02442 void
02443 mips_restore_gp (void)
02444 {
02445 rtx address, slot;
02446
02447 gcc_assert (TARGET_ABICALLS && TARGET_OLDABI);
02448
02449 address = mips_add_offset (pic_offset_table_rtx,
02450 frame_pointer_needed
02451 ? hard_frame_pointer_rtx
02452 : stack_pointer_rtx,
02453 current_function_outgoing_args_size);
02454 slot = gen_rtx_MEM (Pmode, address);
02455
02456 emit_move_insn (pic_offset_table_rtx, slot);
02457 if (!TARGET_EXPLICIT_RELOCS)
02458 emit_insn (gen_blockage ());
02459 }
02460
02461
02462
02463 static void
02464 mips_emit_binary (enum rtx_code code, rtx target, rtx op0, rtx op1)
02465 {
02466 emit_insn (gen_rtx_SET (VOIDmode, target,
02467 gen_rtx_fmt_ee (code, GET_MODE (target), op0, op1)));
02468 }
02469
02470
02471
02472
02473 static bool
02474 mips_relational_operand_ok_p (enum rtx_code code, rtx cmp1)
02475 {
02476 switch (code)
02477 {
02478 case GT:
02479 case GTU:
02480 return reg_or_0_operand (cmp1, VOIDmode);
02481
02482 case GE:
02483 case GEU:
02484 return !TARGET_MIPS16 && cmp1 == const1_rtx;
02485
02486 case LT:
02487 case LTU:
02488 return arith_operand (cmp1, VOIDmode);
02489
02490 case LE:
02491 return sle_operand (cmp1, VOIDmode);
02492
02493 case LEU:
02494 return sleu_operand (cmp1, VOIDmode);
02495
02496 default:
02497 gcc_unreachable ();
02498 }
02499 }
02500
02501
02502
02503
02504
02505
02506 static void
02507 mips_emit_int_relational (enum rtx_code code, bool *invert_ptr,
02508 rtx target, rtx cmp0, rtx cmp1)
02509 {
02510
02511
02512
02513
02514 if (mips_relational_operand_ok_p (code, cmp1))
02515 mips_emit_binary (code, target, cmp0, cmp1);
02516 else
02517 {
02518 enum rtx_code inv_code = reverse_condition (code);
02519 if (!mips_relational_operand_ok_p (inv_code, cmp1))
02520 {
02521 cmp1 = force_reg (GET_MODE (cmp0), cmp1);
02522 mips_emit_int_relational (code, invert_ptr, target, cmp0, cmp1);
02523 }
02524 else if (invert_ptr == 0)
02525 {
02526 rtx inv_target = gen_reg_rtx (GET_MODE (target));
02527 mips_emit_binary (inv_code, inv_target, cmp0, cmp1);
02528 mips_emit_binary (XOR, target, inv_target, const1_rtx);
02529 }
02530 else
02531 {
02532 *invert_ptr = !*invert_ptr;
02533 mips_emit_binary (inv_code, target, cmp0, cmp1);
02534 }
02535 }
02536 }
02537
02538
02539
02540
02541 static rtx
02542 mips_zero_if_equal (rtx cmp0, rtx cmp1)
02543 {
02544 if (cmp1 == const0_rtx)
02545 return cmp0;
02546
02547 if (uns_arith_operand (cmp1, VOIDmode))
02548 return expand_binop (GET_MODE (cmp0), xor_optab,
02549 cmp0, cmp1, 0, 0, OPTAB_DIRECT);
02550
02551 return expand_binop (GET_MODE (cmp0), sub_optab,
02552 cmp0, cmp1, 0, 0, OPTAB_DIRECT);
02553 }
02554
02555
02556
02557
02558
02559
02560
02561
02562
02563
02564
02565
02566
02567 static void
02568 mips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p)
02569 {
02570 if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) == MODE_INT)
02571 {
02572 if (!need_eq_ne_p && cmp_operands[1] == const0_rtx)
02573 {
02574 *op0 = cmp_operands[0];
02575 *op1 = cmp_operands[1];
02576 }
02577 else if (*code == EQ || *code == NE)
02578 {
02579 if (need_eq_ne_p)
02580 {
02581 *op0 = mips_zero_if_equal (cmp_operands[0], cmp_operands[1]);
02582 *op1 = const0_rtx;
02583 }
02584 else
02585 {
02586 *op0 = cmp_operands[0];
02587 *op1 = force_reg (GET_MODE (*op0), cmp_operands[1]);
02588 }
02589 }
02590 else
02591 {
02592
02593
02594 bool invert = false;
02595 *op0 = gen_reg_rtx (GET_MODE (cmp_operands[0]));
02596 *op1 = const0_rtx;
02597 mips_emit_int_relational (*code, &invert, *op0,
02598 cmp_operands[0], cmp_operands[1]);
02599 *code = (invert ? EQ : NE);
02600 }
02601 }
02602 else
02603 {
02604 enum rtx_code cmp_code;
02605
02606
02607
02608
02609
02610
02611
02612 switch (*code)
02613 {
02614 case NE:
02615 case LTGT:
02616 case ORDERED:
02617 cmp_code = reverse_condition_maybe_unordered (*code);
02618 *code = EQ;
02619 break;
02620
02621 default:
02622 cmp_code = *code;
02623 *code = NE;
02624 break;
02625 }
02626 *op0 = (ISA_HAS_8CC
02627 ? gen_reg_rtx (CCmode)
02628 : gen_rtx_REG (CCmode, FPSW_REGNUM));
02629 *op1 = const0_rtx;
02630 mips_emit_binary (cmp_code, *op0, cmp_operands[0], cmp_operands[1]);
02631 }
02632 }
02633
02634
02635
02636
02637
02638
02639 bool
02640 mips_emit_scc (enum rtx_code code, rtx target)
02641 {
02642 if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) != MODE_INT)
02643 return false;
02644
02645 target = gen_lowpart (GET_MODE (cmp_operands[0]), target);
02646 if (code == EQ || code == NE)
02647 {
02648 rtx zie = mips_zero_if_equal (cmp_operands[0], cmp_operands[1]);
02649 mips_emit_binary (code, target, zie, const0_rtx);
02650 }
02651 else
02652 mips_emit_int_relational (code, 0, target,
02653 cmp_operands[0], cmp_operands[1]);
02654 return true;
02655 }
02656
02657
02658
02659
02660
02661 void
02662 gen_conditional_branch (rtx *operands, enum rtx_code code)
02663 {
02664 rtx op0, op1, target;
02665
02666 mips_emit_compare (&code, &op0, &op1, TARGET_MIPS16);
02667 target = gen_rtx_IF_THEN_ELSE (VOIDmode,
02668 gen_rtx_fmt_ee (code, GET_MODE (op0),
02669 op0, op1),
02670 gen_rtx_LABEL_REF (VOIDmode, operands[0]),
02671 pc_rtx);
02672 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, target));
02673 }
02674
02675
02676
02677
02678 void
02679 gen_conditional_move (rtx *operands)
02680 {
02681 enum rtx_code code;
02682 rtx op0, op1;
02683
02684 code = GET_CODE (operands[1]);
02685 mips_emit_compare (&code, &op0, &op1, true);
02686 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
02687 gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
02688 gen_rtx_fmt_ee (code,
02689 GET_MODE (op0),
02690 op0, op1),
02691 operands[2], operands[3])));
02692 }
02693
02694
02695
02696
02697 void
02698 mips_gen_conditional_trap (rtx *operands)
02699 {
02700 rtx op0, op1;
02701 enum rtx_code cmp_code = GET_CODE (operands[0]);
02702 enum machine_mode mode = GET_MODE (cmp_operands[0]);
02703
02704
02705
02706
02707 switch (cmp_code)
02708 {
02709 case GT: cmp_code = LT; break;
02710 case LE: cmp_code = GE; break;
02711 case GTU: cmp_code = LTU; break;
02712 case LEU: cmp_code = GEU; break;
02713 default: break;
02714 }
02715 if (cmp_code == GET_CODE (operands[0]))
02716 {
02717 op0 = cmp_operands[0];
02718 op1 = cmp_operands[1];
02719 }
02720 else
02721 {
02722 op0 = cmp_operands[1];
02723 op1 = cmp_operands[0];
02724 }
02725 op0 = force_reg (mode, op0);
02726 if (!arith_operand (op1, mode))
02727 op1 = force_reg (mode, op1);
02728
02729 emit_insn (gen_rtx_TRAP_IF (VOIDmode,
02730 gen_rtx_fmt_ee (cmp_code, mode, op0, op1),
02731 operands[1]));
02732 }
02733
02734
02735
02736
02737 static void
02738 mips_load_call_address (rtx dest, rtx addr, int sibcall_p)
02739 {
02740
02741
02742
02743
02744 if (TARGET_EXPLICIT_RELOCS
02745 && !(sibcall_p && TARGET_NEWABI)
02746 && global_got_operand (addr, VOIDmode))
02747 {
02748 rtx high, lo_sum_symbol;
02749
02750 high = mips_unspec_offset_high (dest, pic_offset_table_rtx,
02751 addr, SYMBOL_GOTOFF_CALL);
02752 lo_sum_symbol = mips_unspec_address (addr, SYMBOL_GOTOFF_CALL);
02753 if (Pmode == SImode)
02754 emit_insn (gen_load_callsi (dest, high, lo_sum_symbol));
02755 else
02756 emit_insn (gen_load_calldi (dest, high, lo_sum_symbol));
02757 }
02758 else
02759 emit_move_insn (dest, addr);
02760 }
02761
02762
02763
02764
02765
02766
02767
02768
02769
02770 void
02771 mips_expand_call (rtx result, rtx addr, rtx args_size, rtx aux, int sibcall_p)
02772 {
02773 rtx orig_addr, pattern, insn;
02774
02775 orig_addr = addr;
02776 if (!call_insn_operand (addr, VOIDmode))
02777 {
02778 addr = gen_reg_rtx (Pmode);
02779 mips_load_call_address (addr, orig_addr, sibcall_p);
02780 }
02781
02782 if (TARGET_MIPS16
02783 && mips16_hard_float
02784 && build_mips16_call_stub (result, addr, args_size,
02785 aux == 0 ? 0 : (int) GET_MODE (aux)))
02786 return;
02787
02788 if (result == 0)
02789 pattern = (sibcall_p
02790 ? gen_sibcall_internal (addr, args_size)
02791 : gen_call_internal (addr, args_size));
02792 else if (GET_CODE (result) == PARALLEL && XVECLEN (result, 0) == 2)
02793 {
02794 rtx reg1, reg2;
02795
02796 reg1 = XEXP (XVECEXP (result, 0, 0), 0);
02797 reg2 = XEXP (XVECEXP (result, 0, 1), 0);
02798 pattern =
02799 (sibcall_p
02800 ? gen_sibcall_value_multiple_internal (reg1, addr, args_size, reg2)
02801 : gen_call_value_multiple_internal (reg1, addr, args_size, reg2));
02802 }
02803 else
02804 pattern = (sibcall_p
02805 ? gen_sibcall_value_internal (result, addr, args_size)
02806 : gen_call_value_internal (result, addr, args_size));
02807
02808 insn = emit_call_insn (pattern);
02809
02810
02811 if (global_got_operand (orig_addr, VOIDmode))
02812 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
02813 }
02814
02815
02816
02817
02818 static bool
02819 mips_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
02820 tree exp ATTRIBUTE_UNUSED)
02821 {
02822 return TARGET_SIBCALLS;
02823 }
02824
02825
02826
02827
02828
02829
02830
02831
02832
02833
02834
02835
02836 void
02837 mips_emit_fcc_reload (rtx dest, rtx src, rtx scratch)
02838 {
02839 rtx fp1, fp2;
02840
02841
02842 if (MEM_P (src))
02843 src = adjust_address (src, SFmode, 0);
02844 else if (REG_P (src) || GET_CODE (src) == SUBREG)
02845 src = gen_rtx_REG (SFmode, true_regnum (src));
02846
02847 fp1 = gen_rtx_REG (SFmode, REGNO (scratch));
02848 fp2 = gen_rtx_REG (SFmode, REGNO (scratch) + FP_INC);
02849
02850 emit_move_insn (copy_rtx (fp1), src);
02851 emit_move_insn (copy_rtx (fp2), CONST0_RTX (SFmode));
02852 emit_insn (gen_slt_sf (dest, fp2, fp1));
02853 }
02854
02855
02856
02857
02858
02859 void
02860 mips_set_return_address (rtx address, rtx scratch)
02861 {
02862 rtx slot_address;
02863
02864 compute_frame_size (get_frame_size ());
02865 gcc_assert ((cfun->machine->frame.mask >> 31) & 1);
02866 slot_address = mips_add_offset (scratch, stack_pointer_rtx,
02867 cfun->machine->frame.gp_sp_offset);
02868
02869 emit_move_insn (gen_rtx_MEM (GET_MODE (address), slot_address), address);
02870 }
02871
02872
02873
02874
02875 static void
02876 mips_block_move_straight (rtx dest, rtx src, HOST_WIDE_INT length)
02877 {
02878 HOST_WIDE_INT offset, delta;
02879 unsigned HOST_WIDE_INT bits;
02880 int i;
02881 enum machine_mode mode;
02882 rtx *regs;
02883
02884
02885
02886
02887
02888
02889 if (MEM_ALIGN (src) == BITS_PER_WORD / 2
02890 && MEM_ALIGN (dest) == BITS_PER_WORD / 2)
02891 bits = BITS_PER_WORD / 2;
02892 else
02893 bits = BITS_PER_WORD;
02894
02895 mode = mode_for_size (bits, MODE_INT, 0);
02896 delta = bits / BITS_PER_UNIT;
02897
02898
02899 regs = alloca (sizeof (rtx) * length / delta);
02900
02901
02902
02903 for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++)
02904 {
02905 regs[i] = gen_reg_rtx (mode);
02906 if (MEM_ALIGN (src) >= bits)
02907 emit_move_insn (regs[i], adjust_address (src, mode, offset));
02908 else
02909 {
02910 rtx part = adjust_address (src, BLKmode, offset);
02911 if (!mips_expand_unaligned_load (regs[i], part, bits, 0))
02912 gcc_unreachable ();
02913 }
02914 }
02915
02916
02917 for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++)
02918 if (MEM_ALIGN (dest) >= bits)
02919 emit_move_insn (adjust_address (dest, mode, offset), regs[i]);
02920 else
02921 {
02922 rtx part = adjust_address (dest, BLKmode, offset);
02923 if (!mips_expand_unaligned_store (part, regs[i], bits, 0))
02924 gcc_unreachable ();
02925 }
02926
02927
02928 if (offset < length)
02929 {
02930 src = adjust_address (src, BLKmode, offset);
02931 dest = adjust_address (dest, BLKmode, offset);
02932 move_by_pieces (dest, src, length - offset,
02933 MIN (MEM_ALIGN (src), MEM_ALIGN (dest)), 0);
02934 }
02935 }
02936
02937 #define MAX_MOVE_REGS 4
02938 #define MAX_MOVE_BYTES (MAX_MOVE_REGS * UNITS_PER_WORD)
02939
02940
02941
02942
02943
02944
02945
02946
02947
02948
02949 static void
02950 mips_adjust_block_mem (rtx mem, HOST_WIDE_INT length,
02951 rtx *loop_reg, rtx *loop_mem)
02952 {
02953 *loop_reg = copy_addr_to_reg (XEXP (mem, 0));
02954
02955
02956
02957 *loop_mem = change_address (mem, BLKmode, *loop_reg);
02958 set_mem_align (*loop_mem, MIN (MEM_ALIGN (mem), length * BITS_PER_UNIT));
02959 }
02960
02961
02962
02963
02964
02965
02966 static void
02967 mips_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length)
02968 {
02969 rtx label, src_reg, dest_reg, final_src;
02970 HOST_WIDE_INT leftover;
02971
02972 leftover = length % MAX_MOVE_BYTES;
02973 length -= leftover;
02974
02975
02976 mips_adjust_block_mem (src, MAX_MOVE_BYTES, &src_reg, &src);
02977 mips_adjust_block_mem (dest, MAX_MOVE_BYTES, &dest_reg, &dest);
02978
02979
02980
02981 final_src = expand_simple_binop (Pmode, PLUS, src_reg, GEN_INT (length),
02982 0, 0, OPTAB_WIDEN);
02983
02984
02985 label = gen_label_rtx ();
02986 emit_label (label);
02987
02988
02989 mips_block_move_straight (dest, src, MAX_MOVE_BYTES);
02990
02991
02992 emit_move_insn (src_reg, plus_constant (src_reg, MAX_MOVE_BYTES));
02993 emit_move_insn (dest_reg, plus_constant (dest_reg, MAX_MOVE_BYTES));
02994
02995
02996 if (Pmode == DImode)
02997 emit_insn (gen_cmpdi (src_reg, final_src));
02998 else
02999 emit_insn (gen_cmpsi (src_reg, final_src));
03000 emit_jump_insn (gen_bne (label));
03001
03002
03003 if (leftover)
03004 mips_block_move_straight (dest, src, leftover);
03005 }
03006
03007
03008
03009 bool
03010 mips_expand_block_move (rtx dest, rtx src, rtx length)
03011 {
03012 if (GET_CODE (length) == CONST_INT)
03013 {
03014 if (INTVAL (length) <= 2 * MAX_MOVE_BYTES)
03015 {
03016 mips_block_move_straight (dest, src, INTVAL (length));
03017 return true;
03018 }
03019 else if (optimize)
03020 {
03021 mips_block_move_loop (dest, src, INTVAL (length));
03022 return true;
03023 }
03024 }
03025 return false;
03026 }
03027
03028
03029
03030
03031
03032 void
03033 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
03034 rtx libname ATTRIBUTE_UNUSED)
03035 {
03036 static CUMULATIVE_ARGS zero_cum;
03037 tree param, next_param;
03038
03039 *cum = zero_cum;
03040 cum->prototype = (fntype && TYPE_ARG_TYPES (fntype));
03041
03042
03043
03044
03045
03046
03047 for (param = fntype ? TYPE_ARG_TYPES (fntype) : 0;
03048 param != 0; param = next_param)
03049 {
03050 next_param = TREE_CHAIN (param);
03051 if (next_param == 0 && TREE_VALUE (param) != void_type_node)
03052 cum->gp_reg_found = 1;
03053 }
03054 }
03055
03056
03057
03058
03059
03060
03061
03062 static void
03063 mips_arg_info (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
03064 tree type, int named, struct mips_arg_info *info)
03065 {
03066 bool doubleword_aligned_p;
03067 unsigned int num_bytes, num_words, max_regs;
03068
03069
03070 num_bytes = type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
03071 num_words = (num_bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
03072
03073
03074
03075
03076
03077
03078 switch (mips_abi)
03079 {
03080 case ABI_EABI:
03081
03082
03083 info->fpr_p = ((GET_MODE_CLASS (mode) == MODE_FLOAT
03084 || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
03085 && GET_MODE_SIZE (mode) <= UNITS_PER_FPVALUE);
03086 break;
03087
03088 case ABI_32:
03089 case ABI_O64:
03090
03091
03092
03093 info->fpr_p = (!cum->gp_reg_found
03094 && cum->arg_number < 2
03095 && (type == 0 || SCALAR_FLOAT_TYPE_P (type)
03096 || VECTOR_FLOAT_TYPE_P (type))
03097 && (GET_MODE_CLASS (mode) == MODE_FLOAT
03098 || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
03099 && GET_MODE_SIZE (mode) <= UNITS_PER_FPVALUE);
03100 break;
03101
03102 case ABI_N32:
03103 case ABI_64:
03104
03105
03106 info->fpr_p = (named
03107 && (type == 0 || FLOAT_TYPE_P (type))
03108 && (GET_MODE_CLASS (mode) == MODE_FLOAT
03109 || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
03110 || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
03111 && GET_MODE_UNIT_SIZE (mode) <= UNITS_PER_FPVALUE);
03112
03113
03114
03115
03116
03117
03118
03119
03120
03121
03122
03123
03124
03125
03126
03127
03128 if (info->fpr_p
03129 && GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
03130 && GET_MODE_UNIT_SIZE (mode) < UNITS_PER_FPVALUE)
03131 {
03132 if (cum->num_gprs >= MAX_ARGS_IN_REGISTERS - 1)
03133 info->fpr_p = false;
03134 else
03135 num_words = 2;
03136 }
03137 break;
03138
03139 default:
03140 gcc_unreachable ();
03141 }
03142
03143
03144 doubleword_aligned_p = FUNCTION_ARG_BOUNDARY (mode, type) > BITS_PER_WORD;
03145
03146
03147
03148
03149 info->reg_offset = (mips_abi == ABI_EABI && info->fpr_p
03150 ? cum->num_fprs
03151 : cum->num_gprs);
03152
03153
03154 if (doubleword_aligned_p)
03155 info->reg_offset += info->reg_offset & 1;
03156
03157
03158 info->stack_offset = cum->stack_words;
03159 if (doubleword_aligned_p)
03160 info->stack_offset += info->stack_offset & 1;
03161
03162 max_regs = MAX_ARGS_IN_REGISTERS - info->reg_offset;
03163
03164
03165 info->reg_words = MIN (num_words, max_regs);
03166 info->stack_words = num_words - info->reg_words;
03167 }
03168
03169
03170
03171
03172 void
03173 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
03174 tree type, int named)
03175 {
03176 struct mips_arg_info info;
03177
03178 mips_arg_info (cum, mode, type, named, &info);
03179
03180 if (!info.fpr_p)
03181 cum->gp_reg_found = true;
03182
03183
03184
03185
03186 if (cum->arg_number < 2 && info.fpr_p)
03187 cum->fp_code += (mode == SFmode ? 1 : 2) << ((cum->arg_number - 1) * 2);
03188
03189 if (mips_abi != ABI_EABI || !info.fpr_p)
03190 cum->num_gprs = info.reg_offset + info.reg_words;
03191 else if (info.reg_words > 0)
03192 cum->num_fprs += FP_INC;
03193
03194 if (info.stack_words > 0)
03195 cum->stack_words = info.stack_offset + info.stack_words;
03196
03197 cum->arg_number++;
03198 }
03199
03200
03201
03202 struct rtx_def *
03203 function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
03204 tree type, int named)
03205 {
03206 struct mips_arg_info info;
03207
03208
03209
03210
03211
03212 if (mode == VOIDmode)
03213 {
03214 if (TARGET_MIPS16 && cum->fp_code != 0)
03215 return gen_rtx_REG ((enum machine_mode) cum->fp_code, 0);
03216
03217 else
03218 return 0;
03219 }
03220
03221 mips_arg_info (cum, mode, type, named, &info);
03222
03223
03224 if (info.reg_offset == MAX_ARGS_IN_REGISTERS)
03225 return 0;
03226
03227 if (type != 0
03228 && TREE_CODE (type) == RECORD_TYPE
03229 && TARGET_NEWABI
03230 && TYPE_SIZE_UNIT (type)
03231 && host_integerp (TYPE_SIZE_UNIT (type), 1)
03232 && named)
03233 {
03234
03235
03236
03237 tree field;
03238
03239
03240 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
03241 if (TREE_CODE (field) == FIELD_DECL
03242 && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
03243 && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD
03244 && host_integerp (bit_position (field), 0)
03245 && int_bit_position (field) % BITS_PER_WORD == 0)
03246 break;
03247
03248 if (field != 0)
03249 {
03250
03251
03252
03253 unsigned int i;
03254 HOST_WIDE_INT bitpos;
03255 rtx ret;
03256
03257
03258
03259 ret = gen_rtx_PARALLEL (mode, rtvec_alloc (info.reg_words));
03260
03261 bitpos = 0;
03262 field = TYPE_FIELDS (type);
03263 for (i = 0; i < info.reg_words; i++)
03264 {
03265 rtx reg;
03266
03267 for (; field; field = TREE_CHAIN (field))
03268 if (TREE_CODE (field) == FIELD_DECL
03269 && int_bit_position (field) >= bitpos)
03270 break;
03271
03272 if (field
03273 && int_bit_position (field) == bitpos
03274 && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
03275 && !TARGET_SOFT_FLOAT
03276 && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD)
03277 reg = gen_rtx_REG (DFmode, FP_ARG_FIRST + info.reg_offset + i);
03278 else
03279 reg = gen_rtx_REG (DImode, GP_ARG_FIRST + info.reg_offset + i);
03280
03281 XVECEXP (ret, 0, i)
03282 = gen_rtx_EXPR_LIST (VOIDmode, reg,
03283 GEN_INT (bitpos / BITS_PER_UNIT));
03284
03285 bitpos += BITS_PER_WORD;
03286 }
03287 return ret;
03288 }
03289 }
03290
03291
03292
03293
03294 if (TARGET_NEWABI
03295 && info.fpr_p
03296 && GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
03297 {
03298 rtx real, imag;
03299 enum machine_mode inner;
03300 int reg;
03301
03302 inner = GET_MODE_INNER (mode);
03303 reg = FP_ARG_FIRST + info.reg_offset;
03304 real = gen_rtx_EXPR_LIST (VOIDmode,
03305 gen_rtx_REG (inner, reg),
03306 const0_rtx);
03307 imag = gen_rtx_EXPR_LIST (VOIDmode,
03308 gen_rtx_REG (inner, reg + info.reg_words / 2),
03309 GEN_INT (GET_MODE_SIZE (inner)));
03310 return gen_rtx_PARALLEL (mode, gen_rtvec (2, real, imag));
03311 }
03312
03313 if (!info.fpr_p)
03314 return gen_rtx_REG (mode, GP_ARG_FIRST + info.reg_offset);
03315 else if (info.reg_offset == 1)
03316
03317
03318 return gen_rtx_REG (mode, FP_ARG_FIRST + FP_INC);
03319 else
03320 return gen_rtx_REG (mode, FP_ARG_FIRST + info.reg_offset);
03321 }
03322
03323
03324
03325
03326 static int
03327 mips_arg_partial_bytes (CUMULATIVE_ARGS *cum,
03328 enum machine_mode mode, tree type, bool named)
03329 {
03330 struct mips_arg_info info;
03331
03332 mips_arg_info (cum, mode, type, named, &info);
03333 return info.stack_words > 0 ? info.reg_words * UNITS_PER_WORD : 0;
03334 }
03335
03336
03337
03338
03339
03340
03341 int
03342 function_arg_boundary (enum machine_mode mode, tree type)
03343 {
03344 unsigned int alignment;
03345
03346 alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode);
03347 if (alignment < PARM_BOUNDARY)
03348 alignment = PARM_BOUNDARY;
03349 if (alignment > STACK_BOUNDARY)
03350 alignment = STACK_BOUNDARY;
03351 return alignment;
03352 }
03353
03354
03355
03356
03357
03358
03359 bool
03360 mips_pad_arg_upward (enum machine_mode mode, tree type)
03361 {
03362
03363
03364 if (!BYTES_BIG_ENDIAN)
03365 return true;
03366
03367
03368
03369 if (type != 0
03370 ? INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)
03371 : GET_MODE_CLASS (mode) == MODE_INT)
03372 return false;
03373
03374
03375 if (mips_abi == ABI_O64)
03376 if (type != 0 ? FLOAT_TYPE_P (type) : GET_MODE_CLASS (mode) == MODE_FLOAT)
03377 return false;
03378
03379
03380 if (mips_abi != ABI_EABI)
03381 return true;
03382
03383
03384 if (mode != BLKmode)
03385 return (GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY);
03386 else
03387 return (int_size_in_bytes (type) >= (PARM_BOUNDARY / BITS_PER_UNIT));
03388 }
03389
03390
03391
03392
03393
03394
03395 bool
03396 mips_pad_reg_upward (enum machine_mode mode, tree type)
03397 {
03398
03399 if (type != 0 ? FLOAT_TYPE_P (type) : GET_MODE_CLASS (mode) == MODE_FLOAT)
03400 return !BYTES_BIG_ENDIAN;
03401
03402
03403
03404 return mips_pad_arg_upward (mode, type);
03405 }
03406
03407 static void
03408 mips_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
03409 tree type, int *pretend_size, int no_rtl)
03410 {
03411 CUMULATIVE_ARGS local_cum;
03412 int gp_saved, fp_saved;
03413
03414
03415
03416
03417
03418 local_cum = *cum;
03419 FUNCTION_ARG_ADVANCE (local_cum, mode, type, 1);
03420
03421
03422 gp_saved = MAX_ARGS_IN_REGISTERS - local_cum.num_gprs;
03423 fp_saved = (EABI_FLOAT_VARARGS_P
03424 ? MAX_ARGS_IN_REGISTERS - local_cum.num_fprs
03425 : 0);
03426
03427 if (!no_rtl)
03428 {
03429 if (gp_saved > 0)
03430 {
03431 rtx ptr, mem;
03432
03433 ptr = virtual_incoming_args_rtx;
03434 switch (mips_abi)
03435 {
03436 case ABI_32:
03437 case ABI_O64:
03438 ptr = plus_constant (ptr, local_cum.num_gprs * UNITS_PER_WORD);
03439 break;
03440
03441 case ABI_EABI:
03442 ptr = plus_constant (ptr, -gp_saved * UNITS_PER_WORD);
03443 break;
03444 }
03445 mem = gen_rtx_MEM (BLKmode, ptr);
03446 set_mem_alias_set (mem, get_varargs_alias_set ());
03447
03448 move_block_from_reg (local_cum.num_gprs + GP_ARG_FIRST,
03449 mem, gp_saved);
03450 }
03451 if (fp_saved > 0)
03452 {
03453
03454
03455 enum machine_mode mode;
03456 int off, i;
03457
03458
03459
03460
03461 off = -gp_saved * UNITS_PER_WORD;
03462 off &= ~(UNITS_PER_FPVALUE - 1);
03463 off -= fp_saved * UNITS_PER_FPREG;
03464
03465 mode = TARGET_SINGLE_FLOAT ? SFmode : DFmode;
03466
03467 for (i = local_cum.num_fprs; i < MAX_ARGS_IN_REGISTERS; i += FP_INC)
03468 {
03469 rtx ptr, mem;
03470
03471 ptr = plus_constant (virtual_incoming_args_rtx, off);
03472 mem = gen_rtx_MEM (mode, ptr);
03473 set_mem_alias_set (mem, get_varargs_alias_set ());
03474 emit_move_insn (mem, gen_rtx_REG (mode, FP_ARG_FIRST + i));
03475 off += UNITS_PER_HWFPVALUE;
03476 }
03477 }
03478 }
03479 if (TARGET_OLDABI)
03480 {
03481
03482
03483 *pretend_size = 0;
03484 return;
03485 }
03486 *pretend_size = (gp_saved * UNITS_PER_WORD) + (fp_saved * UNITS_PER_FPREG);
03487 }
03488
03489
03490
03491
03492
03493
03494
03495
03496
03497
03498
03499
03500
03501
03502
03503
03504
03505
03506
03507
03508
03509 static tree
03510 mips_build_builtin_va_list (void)
03511 {
03512 if (EABI_FLOAT_VARARGS_P)
03513 {
03514 tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff, f_res, record;
03515 tree array, index;
03516
03517 record = (*lang_hooks.types.make_type) (RECORD_TYPE);
03518
03519 f_ovfl = build_decl (FIELD_DECL, get_identifier ("__overflow_argptr"),
03520 ptr_type_node);
03521 f_gtop = build_decl (FIELD_DECL, get_identifier ("__gpr_top"),
03522 ptr_type_node);
03523 f_ftop = build_decl (FIELD_DECL, get_identifier ("__fpr_top"),
03524 ptr_type_node);
03525 f_goff = build_decl (FIELD_DECL, get_identifier ("__gpr_offset"),
03526 unsigned_char_type_node);
03527 f_foff = build_decl (FIELD_DECL, get_identifier ("__fpr_offset"),
03528 unsigned_char_type_node);
03529
03530
03531 index = build_int_cst (NULL_TREE, GET_MODE_SIZE (ptr_mode) - 2 - 1);
03532 array = build_array_type (unsigned_char_type_node,
03533 build_index_type (index));
03534 f_res = build_decl (FIELD_DECL, get_identifier ("__reserved"), array);
03535
03536 DECL_FIELD_CONTEXT (f_ovfl) = record;
03537 DECL_FIELD_CONTEXT (f_gtop) = record;
03538 DECL_FIELD_CONTEXT (f_ftop) = record;
03539 DECL_FIELD_CONTEXT (f_goff) = record;
03540 DECL_FIELD_CONTEXT (f_foff) = record;
03541 DECL_FIELD_CONTEXT (f_res) = record;
03542
03543 TYPE_FIELDS (record) = f_ovfl;
03544 TREE_CHAIN (f_ovfl) = f_gtop;
03545 TREE_CHAIN (f_gtop) = f_ftop;
03546 TREE_CHAIN (f_ftop) = f_goff;
03547 TREE_CHAIN (f_goff) = f_foff;
03548 TREE_CHAIN (f_foff) = f_res;
03549
03550 layout_type (record);
03551 return record;
03552 }
03553 else if (TARGET_IRIX && TARGET_IRIX6)
03554
03555 return build_pointer_type (char_type_node);
03556 else
03557
03558 return ptr_type_node;
03559 }
03560
03561
03562
03563 void
03564 mips_va_start (tree valist, rtx nextarg)
03565 {
03566 const CUMULATIVE_ARGS *cum = ¤t_function_args_info;
03567
03568
03569
03570
03571
03572 if (cfun && cfun->emit->regno_pointer_align)
03573 while (((current_function_pretend_args_size * BITS_PER_UNIT)
03574 & (REGNO_POINTER_ALIGN (ARG_POINTER_REGNUM) - 1)) != 0)
03575 REGNO_POINTER_ALIGN (ARG_POINTER_REGNUM) /= 2;
03576
03577 if (mips_abi == ABI_EABI)
03578 {
03579 int gpr_save_area_size;
03580
03581 gpr_save_area_size
03582 = (MAX_ARGS_IN_REGISTERS - cum->num_gprs) * UNITS_PER_WORD;
03583
03584 if (EABI_FLOAT_VARARGS_P)
03585 {
03586 tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff;
03587 tree ovfl, gtop, ftop, goff, foff;
03588 tree t;
03589 int fpr_offset;
03590 int fpr_save_area_size;
03591
03592 f_ovfl = TYPE_FIELDS (va_list_type_node);
03593 f_gtop = TREE_CHAIN (f_ovfl);
03594 f_ftop = TREE_CHAIN (f_gtop);
03595 f_goff = TREE_CHAIN (f_ftop);
03596 f_foff = TREE_CHAIN (f_goff);
03597
03598 ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl,
03599 NULL_TREE);
03600 gtop = build (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop,
03601 NULL_TREE);
03602 ftop = build (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop,
03603 NULL_TREE);
03604 goff = build (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff,
03605 NULL_TREE);
03606 foff = build (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff,
03607 NULL_TREE);
03608
03609
03610
03611
03612 t = make_tree (TREE_TYPE (ovfl), virtual_incoming_args_rtx);
03613 if (cum->stack_words > 0)
03614 t = build (PLUS_EXPR, TREE_TYPE (ovfl), t,
03615 build_int_cst (NULL_TREE,
03616 cum->stack_words * UNITS_PER_WORD));
03617 t = build (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t);
03618 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
03619
03620
03621 t = make_tree (TREE_TYPE (gtop), virtual_incoming_args_rtx);
03622 t = build (MODIFY_EXPR, TREE_TYPE (gtop), gtop, t);
03623 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
03624
03625
03626
03627
03628 t = make_tree (TREE_TYPE (ftop), virtual_incoming_args_rtx);
03629 fpr_offset = gpr_save_area_size + UNITS_PER_FPVALUE - 1;
03630 fpr_offset &= ~(UNITS_PER_FPVALUE - 1);
03631 if (fpr_offset)
03632 t = build (PLUS_EXPR, TREE_TYPE (ftop), t,
03633 build_int_cst (NULL_TREE, -fpr_offset));
03634 t = build (MODIFY_EXPR, TREE_TYPE (ftop), ftop, t);
03635 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
03636
03637
03638
03639 t = build (MODIFY_EXPR, TREE_TYPE (goff), goff,
03640 build_int_cst (NULL_TREE, gpr_save_area_size));
03641 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
03642
03643
03644
03645 fpr_save_area_size
03646 = (MAX_ARGS_IN_REGISTERS - cum->num_fprs) * UNITS_PER_FPREG;
03647 t = build (MODIFY_EXPR, TREE_TYPE (foff), foff,
03648 build_int_cst (NULL_TREE, fpr_save_area_size));
03649 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
03650 }
03651 else
03652 {
03653
03654
03655 nextarg = plus_constant (nextarg, -gpr_save_area_size);
03656 std_expand_builtin_va_start (valist, nextarg);
03657 }
03658 }
03659 else
03660 std_expand_builtin_va_start (valist, nextarg);
03661 }
03662
03663
03664
03665 static tree
03666 mips_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
03667 {
03668 HOST_WIDE_INT size, rsize;
03669 tree addr;
03670 bool indirect;
03671
03672 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, 0);
03673
03674 if (indirect)
03675 type = build_pointer_type (type);
03676
03677 size = int_size_in_bytes (type);
03678 rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
03679
03680 if (mips_abi != ABI_EABI || !EABI_FLOAT_VARARGS_P)
03681 addr = std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
03682 else
03683 {
03684
03685
03686 tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff;
03687 tree ovfl, top, off, align;
03688 HOST_WIDE_INT osize;
03689 tree t, u;
03690
03691 f_ovfl = TYPE_FIELDS (va_list_type_node);
03692 f_gtop = TREE_CHAIN (f_ovfl);
03693 f_ftop = TREE_CHAIN (f_gtop);
03694 f_goff = TREE_CHAIN (f_ftop);
03695 f_foff = TREE_CHAIN (f_goff);
03696
03697
03698
03699
03700
03701
03702
03703
03704
03705
03706
03707
03708
03709
03710
03711
03712
03713
03714
03715
03716
03717
03718
03719
03720
03721
03722
03723
03724
03725
03726
03727 ovfl = build (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl,
03728 NULL_TREE);
03729
03730 if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT
03731 && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_FPVALUE)
03732 {
03733 top = build (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop,
03734 NULL_TREE);
03735 off = build (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff,
03736 NULL_TREE);
03737
03738
03739
03740
03741 rsize = UNITS_PER_HWFPVALUE;
03742
03743
03744
03745
03746
03747
03748
03749
03750
03751
03752
03753
03754
03755
03756
03757
03758
03759
03760 osize = MAX (GET_MODE_SIZE (TYPE_MODE (type)), UNITS_PER_WORD);
03761 }
03762 else
03763 {
03764 top = build (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop,
03765 NULL_TREE);
03766 off = build (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff,
03767 NULL_TREE);
03768 if (rsize > UNITS_PER_WORD)
03769 {
03770
03771 t = build (BIT_AND_EXPR, TREE_TYPE (off), off,
03772 build_int_cst (NULL_TREE, -rsize));
03773 t = build (MODIFY_EXPR, TREE_TYPE (off), off, t);
03774 gimplify_and_add (t, pre_p);
03775 }
03776 osize = rsize;
03777 }
03778
03779
03780 t = lang_hooks.truthvalue_conversion (off);
03781 addr = build (COND_EXPR, ptr_type_node, t, NULL, NULL);
03782
03783
03784
03785
03786 t = fold_convert (TREE_TYPE (off), build_int_cst (NULL_TREE, rsize));
03787 t = build (POSTDECREMENT_EXPR, TREE_TYPE (off), off, t);
03788 t = fold_convert (sizetype, t);
03789 t = fold_convert (TREE_TYPE (top), t);
03790
03791
03792
03793 t = build (MINUS_EXPR, TREE_TYPE (top), top, t);
03794 if (BYTES_BIG_ENDIAN && rsize > size)
03795 {
03796 u = fold_convert (TREE_TYPE (t), build_int_cst (NULL_TREE,
03797 rsize - size));
03798 t = build (PLUS_EXPR, TREE_TYPE (t), t, u);
03799 }
03800 COND_EXPR_THEN (addr) = t;
03801
03802 if (osize > UNITS_PER_WORD)
03803 {
03804
03805 u = fold_convert (TREE_TYPE (ovfl),
03806 build_int_cst (NULL_TREE, osize - 1));
03807 t = build (PLUS_EXPR, TREE_TYPE (ovfl), ovfl, u);
03808 u = fold_convert (TREE_TYPE (ovfl),
03809 build_int_cst (NULL_TREE, -osize));
03810 t = build (BIT_AND_EXPR, TREE_TYPE (ovfl), t, u);
03811 align = build (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t);
03812 }
03813 else
03814 align = NULL;
03815
03816
03817
03818
03819 u = fold_convert (TREE_TYPE (ovfl),
03820 build_int_cst (NULL_TREE, osize));
03821 t = build (POSTINCREMENT_EXPR, TREE_TYPE (ovfl), ovfl, u);
03822 if (BYTES_BIG_ENDIAN && osize > size)
03823 {
03824 u = fold_convert (TREE_TYPE (t),
03825 build_int_cst (NULL_TREE, osize - size));
03826 t = build (PLUS_EXPR, TREE_TYPE (t), t, u);
03827 }
03828
03829
03830 if (align)
03831 t = build (COMPOUND_EXPR, TREE_TYPE (t), align, t);
03832 COND_EXPR_ELSE (addr) = t;
03833
03834 addr = fold_convert (build_pointer_type (type), addr);
03835 addr = build_fold_indirect_ref (addr);
03836 }
03837
03838 if (indirect)
03839 addr = build_fold_indirect_ref (addr);
03840
03841 return addr;
03842 }
03843
03844
03845
03846
03847
03848
03849
03850
03851
03852
03853
03854
03855
03856
03857 static bool
03858 mips_get_unaligned_mem (rtx *op, unsigned int width, int bitpos,
03859 rtx *left, rtx *right)
03860 {
03861 rtx first, last;
03862
03863
03864
03865 if (!MEM_P (*op))
03866 return false;
03867
03868
03869 if (width != 32 && (!TARGET_64BIT || width != 64))
03870 return false;
03871
03872
03873
03874
03875 if (bitpos % BITS_PER_UNIT != 0)
03876 return false;
03877
03878
03879
03880 if (MEM_ALIGN (*op) >= width)
03881 return false;
03882
03883
03884
03885 *op = adjust_address (*op, BLKmode, 0);
03886 set_mem_size (*op, GEN_INT (width / BITS_PER_UNIT));
03887
03888
03889
03890
03891 first = adjust_address (*op, QImode, 0);
03892 last = adjust_address (*op, QImode, width / BITS_PER_UNIT - 1);
03893
03894
03895
03896 if (TARGET_BIG_ENDIAN)
03897 *left = first, *right = last;
03898 else
03899 *left = last, *right = first;
03900
03901 return true;
03902 }
03903
03904
03905
03906
03907
03908
03909 bool
03910 mips_expand_unaligned_load (rtx dest, rtx src, unsigned int width, int bitpos)
03911 {
03912 rtx left, right, temp;
03913
03914
03915
03916
03917 if (GET_CODE (dest) == SUBREG
03918 && GET_MODE (dest) == DImode
03919 && SUBREG_BYTE (dest) == 0
03920 && GET_MODE (SUBREG_REG (dest)) == SImode)
03921 dest = SUBREG_REG (dest);
03922
03923
03924
03925 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
03926 return false;
03927
03928 if (!mips_get_unaligned_mem (&src, width, bitpos, &left, &right))
03929 return false;
03930
03931 temp = gen_reg_rtx (GET_MODE (dest));
03932 if (GET_MODE (dest) == DImode)
03933 {
03934 emit_insn (gen_mov_ldl (temp, src, left));
03935 emit_insn (gen_mov_ldr (dest, copy_rtx (src), right, temp));
03936 }
03937 else
03938 {
03939 emit_insn (gen_mov_lwl (temp, src, left));
03940 emit_insn (gen_mov_lwr (dest, copy_rtx (src), right, temp));
03941 }
03942 return true;
03943 }
03944
03945
03946
03947
03948
03949 bool
03950 mips_expand_unaligned_store (rtx dest, rtx src, unsigned int width, int bitpos)
03951 {
03952 rtx left, right;
03953
03954 if (!mips_get_unaligned_mem (&dest, width, bitpos, &left, &right))
03955 return false;
03956
03957 src = gen_lowpart (mode_for_size (width, MODE_INT, 0), src);
03958
03959 if (GET_MODE (src) == DImode)
03960 {
03961 emit_insn (gen_mov_sdl (dest, src, left));
03962 emit_insn (gen_mov_sdr (copy_rtx (dest), copy_rtx (src), right));
03963 }
03964 else
03965 {
03966 emit_insn (gen_mov_swl (dest, src, left));
03967 emit_insn (gen_mov_swr (copy_rtx (dest), copy_rtx (src), right));
03968 }
03969 return true;
03970 }
03971
03972
03973
03974
03975 static void
03976 mips_set_architecture (const struct mips_cpu_info *info)
03977 {
03978 if (info != 0)
03979 {
03980 mips_arch_info = info;
03981 mips_arch = info->cpu;
03982 mips_isa = info->isa;
03983 }
03984 }
03985
03986
03987
03988
03989 static void
03990 mips_set_tune (const struct mips_cpu_info *info)
03991 {
03992 if (info != 0)
03993 {
03994 mips_tune_info = info;
03995 mips_tune = info->cpu;
03996 }
03997 }
03998
03999
04000
04001
04002
04003 void
04004 override_options (void)
04005 {
04006 int i, start, regno;
04007 enum machine_mode mode;
04008
04009 mips_section_threshold = g_switch_set ? g_switch_value : MIPS_DEFAULT_GVALUE;
04010
04011
04012 mips_abi = MIPS_ABI_DEFAULT;
04013 if (mips_abi_string != 0)
04014 {
04015 if (strcmp (mips_abi_string, "32") == 0)
04016 mips_abi = ABI_32;
04017 else if (strcmp (mips_abi_string, "o64") == 0)
04018 mips_abi = ABI_O64;
04019 else if (strcmp (mips_abi_string, "n32") == 0)
04020 mips_abi = ABI_N32;
04021 else if (strcmp (mips_abi_string, "64") == 0)
04022 mips_abi = ABI_64;
04023 else if (strcmp (mips_abi_string, "eabi") == 0)
04024 mips_abi = ABI_EABI;
04025 else
04026 fatal_error ("bad value (%s) for -mabi= switch", mips_abi_string);
04027 }
04028
04029
04030
04031
04032
04033 if (mips_arch_string != 0)
04034 mips_set_architecture (mips_parse_cpu ("-march", mips_arch_string));
04035
04036 if (mips_isa_string != 0)
04037 {
04038
04039 char *whole_isa_str = concat ("mips", mips_isa_string, NULL);
04040 const struct mips_cpu_info *isa_info;
04041
04042 isa_info = mips_parse_cpu ("-mips option", whole_isa_str);
04043 free (whole_isa_str);
04044
04045
04046
04047
04048 if (mips_arch_info != 0 && mips_isa != isa_info->isa)
04049 error ("-mips%s conflicts with the other architecture options, "
04050 "which specify a MIPS%d processor",
04051 mips_isa_string, mips_isa);
04052
04053
04054 mips_set_architecture (isa_info);
04055 }
04056
04057 if (mips_arch_info == 0)
04058 {
04059 #ifdef MIPS_CPU_STRING_DEFAULT
04060 mips_set_architecture (mips_parse_cpu ("default CPU",
04061 MIPS_CPU_STRING_DEFAULT));
04062 #else
04063 mips_set_architecture (mips_cpu_info_from_isa (MIPS_ISA_DEFAULT));
04064 #endif
04065 }
04066
04067 if (ABI_NEEDS_64BIT_REGS && !ISA_HAS_64BIT_REGS)
04068 error ("-march=%s is not compatible with the selected ABI",
04069 mips_arch_info->name);
04070
04071
04072 if (mips_tune_string != 0)
04073 mips_set_tune (mips_parse_cpu ("-mtune", mips_tune_string));
04074
04075 if (mips_tune_info == 0)
04076 mips_set_tune (mips_arch_info);
04077
04078 if ((target_flags_explicit & MASK_64BIT) != 0)
04079 {
04080
04081
04082 if (TARGET_64BIT && !ISA_HAS_64BIT_REGS)
04083 error ("-mgp64 used with a 32-bit processor");
04084 else if (!TARGET_64BIT && ABI_NEEDS_64BIT_REGS)
04085 error ("-mgp32 used with a 64-bit ABI");
04086 else if (TARGET_64BIT && ABI_NEEDS_32BIT_REGS)
04087 error ("-mgp64 used with a 32-bit ABI");
04088 }
04089 else
04090 {
04091
04092
04093
04094 if (ABI_NEEDS_32BIT_REGS || !ISA_HAS_64BIT_REGS)
04095 target_flags &= ~MASK_64BIT;
04096 else
04097 target_flags |= MASK_64BIT;
04098 }
04099
04100 if ((target_flags_explicit & MASK_FLOAT64) != 0)
04101 {
04102
04103
04104 if (TARGET_64BIT && TARGET_DOUBLE_FLOAT && !TARGET_FLOAT64)
04105 error ("unsupported combination: %s", "-mgp64 -mfp32 -mdouble-float");
04106 else if (!TARGET_64BIT && TARGET_FLOAT64)
04107 error ("unsupported combination: %s", "-mgp32 -mfp64");
04108 else if (TARGET_SINGLE_FLOAT && TARGET_FLOAT64)
04109 error ("unsupported combination: %s", "-mfp64 -msingle-float");
04110 }
04111 else
04112 {
04113
04114
04115 if (TARGET_64BIT && TARGET_DOUBLE_FLOAT)
04116 target_flags |= MASK_FLOAT64;
04117 else
04118 target_flags &= ~MASK_FLOAT64;
04119 }
04120
04121
04122
04123 if ((target_flags_explicit & MASK_LONG64) == 0)
04124 {
04125
04126
04127
04128
04129 if ((mips_abi == ABI_EABI && TARGET_64BIT) || mips_abi == ABI_64)
04130 target_flags |= MASK_LONG64;
04131 else
04132 target_flags &= ~MASK_LONG64;
04133 }
04134
04135
04136 if (TARGET_INT64)
04137 warning ("-mint64 is a deprecated option");
04138
04139 if (mips_fix_vr4130_string && mips_fix_vr4130_string[0] != 0)
04140 error ("unrecognized option %<-mfix-vr4130%s%>", mips_fix_vr4130_string);
04141
04142 if (MIPS_MARCH_CONTROLS_SOFT_FLOAT
04143 && (target_flags_explicit & MASK_SOFT_FLOAT) == 0)
04144 {
04145
04146
04147 switch ((int) mips_arch)
04148 {
04149 case PROCESSOR_R4100:
04150 case PROCESSOR_R4111:
04151 case PROCESSOR_R4120:
04152 case PROCESSOR_R4130:
04153 target_flags |= MASK_SOFT_FLOAT;
04154 break;
04155
04156 default:
04157 target_flags &= ~MASK_SOFT_FLOAT;
04158 break;
04159 }
04160 }
04161
04162 if (!TARGET_OLDABI)
04163 flag_pcc_struct_return = 0;
04164
04165 if ((target_flags_explicit & MASK_BRANCHLIKELY) == 0)
04166 {
04167
04168
04169
04170
04171
04172
04173
04174
04175
04176
04177
04178
04179
04180
04181
04182
04183 if (ISA_HAS_BRANCHLIKELY
04184 && !(ISA_MIPS32 || ISA_MIPS32R2 || ISA_MIPS64)
04185 && !(TUNE_MIPS5500 || TUNE_SB1))
04186 target_flags |= MASK_BRANCHLIKELY;
04187 else
04188 target_flags &= ~MASK_BRANCHLIKELY;
04189 }
04190 if (TARGET_BRANCHLIKELY && !ISA_HAS_BRANCHLIKELY)
04191 warning ("generation of Branch Likely instructions enabled, but not supported by architecture");
04192
04193
04194 if (mips_abi == ABI_EABI && TARGET_ABICALLS)
04195 {
04196 error ("unsupported combination: %s", "-mabicalls -mabi=eabi");
04197 target_flags &= ~MASK_ABICALLS;
04198 }
04199
04200
04201
04202
04203
04204 if (TARGET_ABICALLS)
04205 {
04206 flag_pic = 1;
04207 if (mips_section_threshold > 0)
04208 warning ("-G is incompatible with PIC code which is the default");
04209 }
04210
04211
04212
04213
04214
04215
04216
04217
04218
04219
04220
04221 if (!TARGET_MIPS16 && TARGET_SPLIT_ADDRESSES
04222 && optimize && !flag_pic
04223 && !ABI_HAS_64BIT_SYMBOLS)
04224 mips_split_addresses = 1;
04225 else
04226 mips_split_addresses = 0;
04227
04228
04229
04230
04231 if (optimize > 2 && (target_flags_explicit & MASK_VR4130_ALIGN) == 0)
04232 target_flags |= MASK_VR4130_ALIGN;
04233
04234
04235
04236 if (TARGET_MIPS16)
04237 {
04238 if (TARGET_SOFT_FLOAT)
04239 mips16_hard_float = 0;
04240 else
04241 mips16_hard_float = 1;
04242 target_flags |= MASK_SOFT_FLOAT;
04243
04244
04245
04246 flag_schedule_insns = 0;
04247
04248
04249
04250 flag_reorder_blocks_and_partition = 0;
04251
04252
04253
04254
04255
04256 target_flags &= ~MASK_EXPLICIT_RELOCS;
04257 }
04258
04259
04260
04261 if (TARGET_EXPLICIT_RELOCS)
04262 {
04263 mips_flag_delayed_branch = flag_delayed_branch;
04264 flag_delayed_branch = 0;
04265 }
04266
04267 #ifdef MIPS_TFMODE_FORMAT
04268 REAL_MODE_FORMAT (TFmode) = &MIPS_TFMODE_FORMAT;
04269 #endif
04270
04271
04272
04273 if (TARGET_MIPS3D && (target_flags_explicit & MASK_PAIRED_SINGLE)
04274 && !TARGET_PAIRED_SINGLE_FLOAT)
04275 error ("-mips3d requires -mpaired-single");
04276
04277
04278 if (TARGET_MIPS3D)
04279 target_flags |= MASK_PAIRED_SINGLE;
04280
04281
04282
04283 if (TARGET_PAIRED_SINGLE_FLOAT && !(TARGET_FLOAT64 && TARGET_HARD_FLOAT))
04284 error ("-mips3d/-mpaired-single must be used with -mfp64 -mhard-float");
04285
04286
04287
04288 if (TARGET_PAIRED_SINGLE_FLOAT && !ISA_MIPS64)
04289 error ("-mips3d/-mpaired-single must be used with -mips64");
04290
04291 mips_print_operand_punct['?'] = 1;
04292 mips_print_operand_punct['#'] = 1;
04293 mips_print_operand_punct['/'] = 1;
04294 mips_print_operand_punct['&'] = 1;
04295 mips_print_operand_punct['!'] = 1;
04296 mips_print_operand_punct['*'] = 1;
04297 mips_print_operand_punct['@'] = 1;
04298 mips_print_operand_punct['.'] = 1;
04299 mips_print_operand_punct['('] = 1;
04300 mips_print_operand_punct[')'] = 1;
04301 mips_print_operand_punct['['] = 1;
04302 mips_print_operand_punct[']'] = 1;
04303 mips_print_operand_punct['<'] = 1;
04304 mips_print_operand_punct['>'] = 1;
04305 mips_print_operand_punct['{'] = 1;
04306 mips_print_operand_punct['}'] = 1;
04307 mips_print_operand_punct['^'] = 1;
04308 mips_print_operand_punct['$'] = 1;
04309 mips_print_operand_punct['+'] = 1;
04310 mips_print_operand_punct['~'] = 1;
04311
04312 mips_char_to_class['d'] = TARGET_MIPS16 ? M16_REGS : GR_REGS;
04313 mips_char_to_class['t'] = T_REG;
04314 mips_char_to_class['f'] = (TARGET_HARD_FLOAT ? FP_REGS : NO_REGS);
04315 mips_char_to_class['h'] = HI_REG;
04316 mips_char_to_class['l'] = LO_REG;
04317 mips_char_to_class['x'] = MD_REGS;
04318 mips_char_to_class['b'] = ALL_REGS;
04319 mips_char_to_class['c'] = (TARGET_ABICALLS ? PIC_FN_ADDR_REG :
04320 TARGET_MIPS16 ? M16_NA_REGS :
04321 GR_REGS);
04322 mips_char_to_class['e'] = LEA_REGS;
04323 mips_char_to_class['j'] = PIC_FN_ADDR_REG;
04324 mips_char_to_class['y'] = GR_REGS;
04325 mips_char_to_class['z'] = ST_REGS;
04326 mips_char_to_class['B'] = COP0_REGS;
04327 mips_char_to_class['C'] = COP2_REGS;
04328 mips_char_to_class['D'] = COP3_REGS;
04329
04330
04331
04332
04333 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
04334 mips_dbx_regno[i] = -1;
04335
04336 start = GP_DBX_FIRST - GP_REG_FIRST;
04337 for (i = GP_REG_FIRST; i <= GP_REG_LAST; i++)
04338 mips_dbx_regno[i] = i + start;
04339
04340 start = FP_DBX_FIRST - FP_REG_FIRST;
04341 for (i = FP_REG_FIRST; i <= FP_REG_LAST; i++)
04342 mips_dbx_regno[i] = i + start;
04343
04344 mips_dbx_regno[HI_REGNUM] = MD_DBX_FIRST + 0;
04345 mips_dbx_regno[LO_REGNUM] = MD_DBX_FIRST + 1;
04346
04347
04348
04349 for (mode = VOIDmode;
04350 mode != MAX_MACHINE_MODE;
04351 mode = (enum machine_mode) ((int)mode + 1))
04352 {
04353 register int size = GET_MODE_SIZE (mode);
04354 register enum mode_class class = GET_MODE_CLASS (mode);
04355
04356 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
04357 {
04358 register int temp;
04359
04360 if (mode == CCV2mode)
04361 temp = (ISA_HAS_8CC
04362 && ST_REG_P (regno)
04363 && (regno - ST_REG_FIRST) % 2 == 0);
04364
04365 else if (mode == CCV4mode)
04366 temp = (ISA_HAS_8CC
04367 && ST_REG_P (regno)
04368 && (regno - ST_REG_FIRST) % 4 == 0);
04369
04370 else if (mode == CCmode)
04371 {
04372 if (! ISA_HAS_8CC)
04373 temp = (regno == FPSW_REGNUM);
04374 else
04375 temp = (ST_REG_P (regno) || GP_REG_P (regno)
04376 || FP_REG_P (regno));
04377 }
04378
04379 else if (GP_REG_P (regno))
04380 temp = ((regno & 1) == 0 || size <= UNITS_PER_WORD);
04381
04382 else if (FP_REG_P (regno))
04383 temp = ((regno % FP_INC) == 0)
04384 && (((class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT
04385 || class == MODE_VECTOR_FLOAT)
04386 && size <= UNITS_PER_FPVALUE)
04387
04388
04389
04390 || (class == MODE_INT && size <= UNITS_PER_FPREG)
04391
04392 || (ISA_HAS_8CC && mode == TFmode));
04393
04394 else if (MD_REG_P (regno))
04395 temp = (INTEGRAL_MODE_P (mode)
04396 && (size <= UNITS_PER_WORD
04397 || (regno == MD_REG_FIRST
04398 && size == 2 * UNITS_PER_WORD)));
04399
04400 else if (ALL_COP_REG_P (regno))
04401 temp = (class == MODE_INT && size <= UNITS_PER_WORD);
04402 else
04403 temp = 0;
04404
04405 mips_hard_regno_mode_ok[(int)mode][regno] = temp;
04406 }
04407 }
04408
04409
04410
04411 gpr_mode = TARGET_64BIT ? DImode : SImode;
04412
04413
04414 if (TARGET_64BIT && !TARGET_MIPS16)
04415 {
04416 if (align_loops == 0)
04417 align_loops = 8;
04418 if (align_jumps == 0)
04419 align_jumps = 8;
04420 if (align_functions == 0)
04421 align_functions = 8;
04422 }
04423
04424
04425 init_machine_status = &mips_init_machine_status;
04426
04427 if (ABI_HAS_64BIT_SYMBOLS)
04428 {
04429 if (TARGET_EXPLICIT_RELOCS)
04430 {
04431 mips_split_p[SYMBOL_64_HIGH] = true;
04432 mips_hi_relocs[SYMBOL_64_HIGH] = "%highest(";
04433 mips_lo_relocs[SYMBOL_64_HIGH] = "%higher(";
04434
04435 mips_split_p[SYMBOL_64_MID] = true;
04436 mips_hi_relocs[SYMBOL_64_MID] = "%higher(";
04437 mips_lo_relocs[SYMBOL_64_MID] = "%hi(";
04438
04439 mips_split_p[SYMBOL_64_LOW] = true;
04440 mips_hi_relocs[SYMBOL_64_LOW] = "%hi(";
04441 mips_lo_relocs[SYMBOL_64_LOW] = "%lo(";
04442
04443 mips_split_p[SYMBOL_GENERAL] = true;
04444 mips_lo_relocs[SYMBOL_GENERAL] = "%lo(";
04445 }
04446 }
04447 else
04448 {
04449 if (TARGET_EXPLICIT_RELOCS || mips_split_addresses)
04450 {
04451 mips_split_p[SYMBOL_GENERAL] = true;
04452 mips_hi_relocs[SYMBOL_GENERAL] = "%hi(";
04453 mips_lo_relocs[SYMBOL_GENERAL] = "%lo(";
04454 }
04455 }
04456
04457 if (TARGET_MIPS16)
04458 {
04459
04460 mips_split_p[SYMBOL_SMALL_DATA] = true;
04461 mips_lo_relocs[SYMBOL_SMALL_DATA] = "%gprel(";
04462 }
04463
04464 if (TARGET_EXPLICIT_RELOCS)
04465 {
04466
04467
04468 mips_lo_relocs[SYMBOL_SMALL_DATA] = "%gp_rel(";
04469
04470 mips_split_p[SYMBOL_GOT_LOCAL] = true;
04471 if (TARGET_NEWABI)
04472 {
04473 mips_lo_relocs[SYMBOL_GOTOFF_PAGE] = "%got_page(";
04474 mips_lo_relocs[SYMBOL_GOT_LOCAL] = "%got_ofst(";
04475 }
04476 else
04477 {
04478 mips_lo_relocs[SYMBOL_GOTOFF_PAGE] = "%got(";
04479 mips_lo_relocs[SYMBOL_GOT_LOCAL] = "%lo(";
04480 }
04481
04482 if (TARGET_XGOT)
04483 {
04484
04485 mips_split_p[SYMBOL_GOT_GLOBAL] = true;
04486
04487 mips_split_p[SYMBOL_GOTOFF_GLOBAL] = true;
04488 mips_hi_relocs[SYMBOL_GOTOFF_GLOBAL] = "%got_hi(";
04489 mips_lo_relocs[SYMBOL_GOTOFF_GLOBAL] = "%got_lo(";
04490
04491 mips_split_p[SYMBOL_GOTOFF_CALL] = true;
04492 mips_hi_relocs[SYMBOL_GOTOFF_CALL] = "%call_hi(";
04493 mips_lo_relocs[SYMBOL_GOTOFF_CALL] = "%call_lo(";
04494 }
04495 else
04496 {
04497 if (TARGET_NEWABI)
04498 mips_lo_relocs[SYMBOL_GOTOFF_GLOBAL] = "%got_disp(";
04499 else
04500 mips_lo_relocs[SYMBOL_GOTOFF_GLOBAL] = "%got(";
04501 mips_lo_relocs[SYMBOL_GOTOFF_CALL] = "%call16(";
04502 }
04503 }
04504
04505 if (TARGET_NEWABI)
04506 {
04507 mips_split_p[SYMBOL_GOTOFF_LOADGP] = true;
04508 mips_hi_relocs[SYMBOL_GOTOFF_LOADGP] = "%hi(%neg(%gp_rel(";
04509 mips_lo_relocs[SYMBOL_GOTOFF_LOADGP] = "%lo(%neg(%gp_rel(";
04510 }
04511
04512
04513
04514 if ((target_flags_explicit & MASK_FIX_R4000) == 0
04515 && mips_matching_cpu_name_p (mips_arch_info->name, "r4000"))
04516 target_flags |= MASK_FIX_R4000;
04517
04518
04519
04520 if ((target_flags_explicit & MASK_FIX_R4400) == 0
04521 && mips_matching_cpu_name_p (mips_arch_info->name, "r4400"))
04522 target_flags |= MASK_FIX_R4400;
04523 }
04524
04525
04526
04527 void
04528 mips_conditional_register_usage (void)
04529 {
04530 if (!TARGET_HARD_FLOAT)
04531 {
04532 int regno;
04533
04534 for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
04535 fixed_regs[regno] = call_used_regs[regno] = 1;
04536 for (regno = ST_REG_FIRST; regno <= ST_REG_LAST; regno++)
04537 fixed_regs[regno] = call_used_regs[regno] = 1;
04538 }
04539 else if (! ISA_HAS_8CC)
04540 {
04541 int regno;
04542
04543
04544
04545
04546 for (regno = ST_REG_FIRST; regno <= ST_REG_LAST; regno++)
04547 fixed_regs[regno] = call_used_regs[regno] = 1;
04548 }
04549
04550
04551
04552
04553 if (TARGET_MIPS16)
04554 {
04555 fixed_regs[18] = call_used_regs[18] = 1;
04556 fixed_regs[19] = call_used_regs[19] = 1;
04557 fixed_regs[20] = call_used_regs[20] = 1;
04558 fixed_regs[21] = call_used_regs[21] = 1;
04559 fixed_regs[22] = call_used_regs[22] = 1;
04560 fixed_regs[23] = call_used_regs[23] = 1;
04561 fixed_regs[26] = call_used_regs[26] = 1;
04562 fixed_regs[27] = call_used_regs[27] = 1;
04563 fixed_regs[30] = call_used_regs[30] = 1;
04564 }
04565
04566 if (mips_abi == ABI_64)
04567 {
04568 int regno;
04569 for (regno = FP_REG_FIRST + 20; regno < FP_REG_FIRST + 24; regno++)
04570 call_really_used_regs[regno] = call_used_regs[regno] = 1;
04571 }
04572
04573 if (mips_abi == ABI_N32)
04574 {
04575 int regno;
04576 for (regno = FP_REG_FIRST + 21; regno <= FP_REG_FIRST + 31; regno+=2)
04577 call_really_used_regs[regno] = call_used_regs[regno] = 1;
04578 }
04579 }
04580
04581
04582 static struct machine_function *
04583 mips_init_machine_status (void)
04584 {
04585 return ((struct machine_function *)
04586 ggc_alloc_cleared (sizeof (struct machine_function)));
04587 }
04588
04589
04590
04591
04592
04593
04594 void
04595 mips_order_regs_for_local_alloc (void)
04596 {
04597 register int i;
04598
04599 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
04600 reg_alloc_order[i] = i;
04601
04602 if (TARGET_MIPS16)
04603 {
04604
04605
04606 reg_alloc_order[0] = 24;
04607 reg_alloc_order[24] = 0;
04608 }
04609 }
04610
04611
04612
04613
04614
04615
04616
04617
04618
04619
04620
04621 HOST_WIDE_INT
04622 mips_debugger_offset (rtx addr, HOST_WIDE_INT offset)
04623 {
04624 rtx offset2 = const0_rtx;
04625 rtx reg = eliminate_constant_term (addr, &offset2);
04626
04627 if (offset == 0)
04628 offset = INTVAL (offset2);
04629
04630 if (reg == stack_pointer_rtx || reg == frame_pointer_rtx
04631 || reg == hard_frame_pointer_rtx)
04632 {
04633 HOST_WIDE_INT frame_size = (!cfun->machine->frame.initialized)
04634 ? compute_frame_size (get_frame_size ())
04635 : cfun->machine->frame.total_size;
04636
04637
04638 if (frame_pointer_needed && TARGET_MIPS16)
04639 frame_size -= cfun->machine->frame.args_size;
04640
04641 offset = offset - frame_size;
04642 }
04643
04644
04645 #if 0
04646 else if (reg != arg_pointer_rtx)
04647 fatal_insn ("mips_debugger_offset called with non stack/frame/arg pointer",
04648 addr);
04649 #endif
04650
04651 return offset;
04652 }
04653
04654
04655
04656
04657
04658
04659
04660
04661
04662
04663
04664
04665
04666
04667
04668
04669
04670
04671
04672
04673
04674
04675
04676
04677
04678
04679
04680
04681
04682
04683
04684
04685
04686
04687
04688
04689
04690
04691
04692
04693
04694
04695
04696
04697
04698 void
04699 print_operand (FILE *file, rtx op, int letter)
04700 {
04701 register enum rtx_code code;
04702
04703 if (PRINT_OPERAND_PUNCT_VALID_P (letter))
04704 {
04705 switch (letter)
04706 {
04707 case '?':
04708 if (mips_branch_likely)
04709 putc ('l', file);
04710 break;
04711
04712 case '@':
04713 fputs (reg_names [GP_REG_FIRST + 1], file);
04714 break;
04715
04716 case '^':
04717 fputs (reg_names [PIC_FUNCTION_ADDR_REGNUM], file);
04718 break;
04719
04720 case '.':
04721 fputs (reg_names [GP_REG_FIRST + 0], file);
04722 break;
04723
04724 case '$':
04725 fputs (reg_names[STACK_POINTER_REGNUM], file);
04726 break;
04727
04728 case '+':
04729 fputs (reg_names[PIC_OFFSET_TABLE_REGNUM], file);
04730 break;
04731
04732 case '&':
04733 if (final_sequence != 0 && set_noreorder++ == 0)
04734 fputs (".set\tnoreorder\n\t", file);
04735 break;
04736
04737 case '*':
04738 if (final_sequence != 0)
04739 {
04740 if (set_noreorder++ == 0)
04741 fputs (".set\tnoreorder\n\t", file);
04742
04743 if (set_nomacro++ == 0)
04744 fputs (".set\tnomacro\n\t", file);
04745 }
04746 break;
04747
04748 case '!':
04749 if (final_sequence != 0 && set_nomacro++ == 0)
04750 fputs ("\n\t.set\tnomacro", file);
04751 break;
04752
04753 case '#':
04754 if (set_noreorder != 0)
04755 fputs ("\n\tnop", file);
04756 break;
04757
04758 case '/':
04759
04760
04761
04762 if (set_noreorder != 0 && final_sequence == 0)
04763 fputs ("\n\tnop\n", file);
04764 break;
04765
04766 case '(':
04767 if (set_noreorder++ == 0)
04768 fputs (".set\tnoreorder\n\t", file);
04769 break;
04770
04771 case ')':
04772 if (set_noreorder == 0)
04773 error ("internal error: %%) found without a %%( in assembler pattern");
04774
04775 else if (--set_noreorder == 0)
04776 fputs ("\n\t.set\treorder", file);
04777
04778 break;
04779
04780 case '[':
04781 if (set_noat++ == 0)
04782 fputs (".set\tnoat\n\t", file);
04783 break;
04784
04785 case ']':
04786 if (set_noat == 0)
04787 error ("internal error: %%] found without a %%[ in assembler pattern");
04788 else if (--set_noat == 0)
04789 fputs ("\n\t.set\tat", file);
04790
04791 break;
04792
04793 case '<':
04794 if (set_nomacro++ == 0)
04795 fputs (".set\tnomacro\n\t", file);
04796 break;
04797
04798 case '>':
04799 if (set_nomacro == 0)
04800 error ("internal error: %%> found without a %%< in assembler pattern");
04801 else if (--set_nomacro == 0)
04802 fputs ("\n\t.set\tmacro", file);
04803
04804 break;
04805
04806 case '{':
04807 if (set_volatile++ == 0)
04808 fputs ("#.set\tvolatile\n\t", file);
04809 break;
04810
04811 case '}':
04812 if (set_volatile == 0)
04813 error ("internal error: %%} found without a %%{ in assembler pattern");
04814 else if (--set_volatile == 0)
04815 fputs ("\n\t#.set\tnovolatile", file);
04816
04817 break;
04818
04819 case '~':
04820 {
04821 if (align_labels_log > 0)
04822 ASM_OUTPUT_ALIGN (file, align_labels_log);
04823 }
04824 break;
04825
04826 default:
04827 error ("PRINT_OPERAND: unknown punctuation '%c'", letter);
04828 break;
04829 }
04830
04831 return;
04832 }
04833
04834 if (! op)
04835 {
04836 error ("PRINT_OPERAND null pointer");
04837 return;
04838 }
04839
04840 code = GET_CODE (op);
04841
04842 if (letter == 'C')
04843 switch (code)
04844 {
04845 case EQ: fputs ("eq", file); break;
04846 case NE: fputs ("ne", file); break;
04847 case GT: fputs ("gt", file); break;
04848 case GE: fputs ("ge", file); break;
04849 case LT: fputs ("lt", file); break;
04850 case LE: fputs ("le", file); break;
04851 case GTU: fputs ("gtu", file); break;
04852 case GEU: fputs ("geu", file); break;
04853 case LTU: fputs ("ltu", file); break;
04854 case LEU: fputs ("leu", file); break;
04855 default:
04856 fatal_insn ("PRINT_OPERAND, invalid insn for %%C", op);
04857 }
04858
04859 else if (letter == 'N')
04860 switch (code)
04861 {
04862 case EQ: fputs ("ne", file); break;
04863 case NE: fputs ("eq", file); break;
04864 case GT: fputs ("le", file); break;
04865 case GE: fputs ("lt", file); break;
04866 case LT: fputs ("ge", file); break;
04867 case LE: fputs ("gt", file); break;
04868 case GTU: fputs ("leu", file); break;
04869 case GEU: fputs ("ltu", file); break;
04870 case LTU: fputs ("geu", file); break;
04871 case LEU: fputs ("gtu", file); break;
04872 default:
04873 fatal_insn ("PRINT_OPERAND, invalid insn for %%N", op);
04874 }
04875
04876 else if (letter == 'F')
04877 switch (code)
04878 {
04879 case EQ: fputs ("c1f", file); break;
04880 case NE: fputs ("c1t", file); break;
04881 default:
04882 fatal_insn ("PRINT_OPERAND, invalid insn for %%F", op);
04883 }
04884
04885 else if (letter == 'W')
04886 switch (code)
04887 {
04888 case EQ: fputs ("c1t", file); break;
04889 case NE: fputs ("c1f", file); break;
04890 default:
04891 fatal_insn ("PRINT_OPERAND, invalid insn for %%W", op);
04892 }
04893
04894 else if (letter == 'h')
04895 {
04896 if (GET_CODE (op) == HIGH)
04897 op = XEXP (op, 0);
04898
04899 print_operand_reloc (file, op, mips_hi_relocs);
04900 }
04901
04902 else if (letter == 'R')
04903 print_operand_reloc (file, op, mips_lo_relocs);
04904
04905 else if (letter == 'Y')
04906 {
04907 if (GET_CODE (op) == CONST_INT
04908 && ((unsigned HOST_WIDE_INT) INTVAL (op)
04909 < ARRAY_SIZE (mips_fp_conditions)))
04910 fputs (mips_fp_conditions[INTVAL (op)], file);
04911 else
04912 output_operand_lossage ("invalid %%Y value");
04913 }
04914
04915 else if (letter == 'Z')
04916 {
04917 if (ISA_HAS_8CC)
04918 {
04919 print_operand (file, op, 0);
04920 fputc (',', file);
04921 }
04922 }
04923
04924 else if (code == REG || code == SUBREG)
04925 {
04926 register int regnum;
04927
04928 if (code == REG)
04929 regnum = REGNO (op);
04930 else
04931 regnum = true_regnum (op);
04932
04933 if ((letter == 'M' && ! WORDS_BIG_ENDIAN)
04934 || (letter == 'L' && WORDS_BIG_ENDIAN)
04935 || letter == 'D')
04936 regnum++;
04937
04938 fprintf (file, "%s", reg_names[regnum]);
04939 }
04940
04941 else if (code == MEM)
04942 {
04943 if (letter == 'D')
04944 output_address (plus_constant (XEXP (op, 0), 4));
04945 else
04946 output_address (XEXP (op, 0));
04947 }
04948
04949 else if (letter == 'x' && GET_CODE (op) == CONST_INT)
04950 fprintf (file, HOST_WIDE_INT_PRINT_HEX, 0xffff & INTVAL(op));
04951
04952 else if (letter == 'X' && GET_CODE(op) == CONST_INT)
04953 fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (op));
04954
04955 else if (letter == 'd' && GET_CODE(op) == CONST_INT)
04956 fprintf (file, HOST_WIDE_INT_PRINT_DEC, (INTVAL(op)));
04957
04958 else if (letter == 'z' && op == CONST0_RTX (GET_MODE (op)))
04959 fputs (reg_names[GP_REG_FIRST], file);
04960
04961 else if (letter == 'd' || letter == 'x' || letter == 'X')
04962 output_operand_lossage ("invalid use of %%d, %%x, or %%X");
04963
04964 else if (letter == 'T' || letter == 't')
04965 {
04966 int truth = (code == NE) == (letter == 'T');
04967 fputc ("zfnt"[truth * 2 + (GET_MODE (op) == CCmode)], file);
04968 }
04969
04970 else if (CONST_GP_P (op))
04971 fputs (reg_names[GLOBAL_POINTER_REGNUM], file);
04972
04973 else
04974 output_addr_const (file, op);
04975 }
04976
04977
04978
04979
04980
04981 static void
04982 print_operand_reloc (FILE *file, rtx op, const char **relocs)
04983 {
04984 enum mips_symbol_type symbol_type;
04985 const char *p;
04986 rtx base;
04987 HOST_WIDE_INT offset;
04988
04989 if (!mips_symbolic_constant_p (op, &symbol_type) || relocs[symbol_type] == 0)
04990 fatal_insn ("PRINT_OPERAND, invalid operand for relocation", op);
04991
04992
04993 mips_split_const (op, &base, &offset);
04994 if (UNSPEC_ADDRESS_P (base))
04995 op = plus_constant (UNSPEC_ADDRESS (base), offset);
04996
04997 fputs (relocs[symbol_type], file);
04998 output_addr_const (file, op);
04999 for (p = relocs[symbol_type]; *p != 0; p++)
05000 if (*p == '(')
05001 fputc (')', file);
05002 }
05003
05004
05005
05006 void
05007 print_operand_address (FILE *file, rtx x)
05008 {
05009 struct mips_address_info addr;
05010
05011 if (mips_classify_address (&addr, x, word_mode, true))
05012 switch (addr.type)
05013 {
05014 case ADDRESS_REG:
05015 print_operand (file, addr.offset, 0);
05016 fprintf (file, "(%s)", reg_names[REGNO (addr.reg)]);
05017 return;
05018
05019 case ADDRESS_LO_SUM:
05020 print_operand (file, addr.offset, 'R');
05021 fprintf (file, "(%s)", reg_names[REGNO (addr.reg)]);
05022 return;
05023
05024 case ADDRESS_CONST_INT:
05025 output_addr_const (file, x);
05026 fprintf (file, "(%s)", reg_names[0]);
05027 return;
05028
05029 case ADDRESS_SYMBOLIC:
05030 output_addr_const (file, x);
05031 return;
05032 }
05033 gcc_unreachable ();
05034 }
05035
05036
05037
05038
05039
05040
05041
05042
05043
05044 int
05045 mips_output_external (FILE *file ATTRIBUTE_UNUSED, tree decl, const char *name)
05046 {
05047 register struct extern_list *p;
05048
05049 if (!TARGET_EXPLICIT_RELOCS && mips_in_small_data_p (decl))
05050 {
05051 p = (struct extern_list *) ggc_alloc (sizeof (struct extern_list));
05052 p->next = extern_head;
05053 p->name = name;
05054 p->size = int_size_in_bytes (TREE_TYPE (decl));
05055 extern_head = p;
05056 }
05057
05058 if (TARGET_IRIX && mips_abi == ABI_32 && TREE_CODE (decl) == FUNCTION_DECL)
05059 {
05060 p = (struct extern_list *) ggc_alloc (sizeof (struct extern_list));
05061 p->next = extern_head;
05062 p->name = name;
05063 p->size = -1;
05064 extern_head = p;
05065 }
05066
05067 return 0;
05068 }
05069
05070 #if TARGET_IRIX
05071 static void
05072 irix_output_external_libcall (rtx fun)
05073 {
05074 register struct extern_list *p;
05075
05076 if (mips_abi == ABI_32)
05077 {
05078 p = (struct extern_list *) ggc_alloc (sizeof (struct extern_list));
05079 p->next = extern_head;
05080 p->name = XSTR (fun, 0);
05081 p->size = -1;
05082 extern_head = p;
05083 }
05084 }
05085 #endif
05086
05087
05088
05089
05090 void
05091 mips_output_filename (FILE *stream, const char *name)
05092 {
05093
05094
05095
05096 if (write_symbols == DWARF2_DEBUG)
05097 return;
05098 else if (mips_output_filename_first_time)
05099 {
05100 mips_output_filename_first_time = 0;
05101 num_source_filenames += 1;
05102 current_function_file = name;
05103 fprintf (stream, "\t.file\t%d ", num_source_filenames);
05104 output_quoted_string (stream, name);
05105 putc ('\n', stream);
05106 }
05107
05108
05109
05110 else if (write_symbols == DBX_DEBUG)
05111 return;
05112
05113 else if (name != current_function_file
05114 && strcmp (name, current_function_file) != 0)
05115 {
05116 num_source_filenames += 1;
05117 current_function_file = name;
05118 fprintf (stream, "\t.file\t%d ", num_source_filenames);
05119 output_quoted_string (stream, name);
05120 putc ('\n', stream);
05121 }
05122 }
05123
05124
05125
05126
05127
05128 void
05129 mips_output_ascii (FILE *stream, const char *string_param, size_t len,
05130 const char *prefix)
05131 {
05132 size_t i;
05133 int cur_pos = 17;
05134 register const unsigned char *string =
05135 (const unsigned char *)string_param;
05136
05137 fprintf (stream, "%s\"", prefix);
05138 for (i = 0; i < len; i++)
05139 {
05140 register int c = string[i];
05141
05142 if (ISPRINT (c))
05143 {
05144 if (c == '\\' || c == '\"')
05145 {
05146 putc ('\\', stream);
05147 cur_pos++;
05148 }
05149 putc (c, stream);
05150 cur_pos++;
05151 }
05152 else
05153 {
05154 fprintf (stream, "\\%03o", c);
05155 cur_pos += 4;
05156 }
05157
05158 if (cur_pos > 72 && i+1 < len)
05159 {
05160 cur_pos = 17;
05161 fprintf (stream, "\"\n%s\"", prefix);
05162 }
05163 }
05164 fprintf (stream, "\"\n");
05165 }
05166
05167
05168
05169 static void
05170 mips_file_start (void)
05171 {
05172 default_file_start ();
05173
05174 if (!TARGET_IRIX)
05175 {
05176
05177
05178
05179
05180
05181
05182
05183 const char * abi_string = NULL;
05184
05185 switch (mips_abi)
05186 {
05187 case ABI_32: abi_string = "abi32"; break;
05188 case ABI_N32: abi_string = "abiN32"; break;
05189 case ABI_64: abi_string = "abi64"; break;
05190 case ABI_O64: abi_string = "abiO64"; break;
05191 case ABI_EABI: abi_string = TARGET_64BIT ? "eabi64" : "eabi32"; break;
05192 default:
05193 gcc_unreachable ();
05194 }
05195
05196
05197
05198
05199 fprintf (asm_out_file, "\t.section .mdebug.%s\n", abi_string);
05200
05201
05202
05203
05204 if (mips_abi == ABI_EABI)
05205 fprintf (asm_out_file, "\t.section .gcc_compiled_long%d\n",
05206 TARGET_LONG64 ? 64 : 32);
05207
05208
05209 fprintf (asm_out_file, "\t.previous\n");
05210 }
05211
05212
05213 if (TARGET_ABICALLS)
05214
05215 fprintf (asm_out_file, "\t.abicalls\n");
05216
05217 if (TARGET_MIPS16)
05218 fprintf (asm_out_file, "\t.set\tmips16\n");
05219
05220 if (flag_verbose_asm)
05221 fprintf (asm_out_file, "\n%s -G value = %d, Arch = %s, ISA = %d\n",
05222 ASM_COMMENT_START,
05223 mips_section_threshold, mips_arch_info->name, mips_isa);
05224 }
05225
05226 #ifdef BSS_SECTION_ASM_OP
05227
05228
05229
05230 void
05231 mips_output_aligned_bss (FILE *stream, tree decl, const char *name,
05232 unsigned HOST_WIDE_INT size, int align)
05233 {
05234 extern tree last_assemble_variable_decl;
05235
05236 if (mips_in_small_data_p (decl))
05237 named_section (0, ".sbss", 0);
05238 else
05239 bss_section ();
05240 ASM_OUTPUT_ALIGN (stream, floor_log2 (align / BITS_PER_UNIT));
05241 last_assemble_variable_decl = decl;
05242 ASM_DECLARE_OBJECT_NAME (stream, name, decl);
05243 ASM_OUTPUT_SKIP (stream, size != 0 ? size : 1);
05244 }
05245 #endif
05246
05247
05248
05249
05250 static void
05251 mips_file_end (void)
05252 {
05253 tree name_tree;
05254 struct extern_list *p;
05255
05256 if (extern_head)
05257 {
05258 fputs ("\n", asm_out_file);
05259
05260 for (p = extern_head; p != 0; p = p->next)
05261 {
05262 name_tree = get_identifier (p->name);
05263
05264
05265 if (!TREE_ASM_WRITTEN (name_tree)
05266 && TREE_SYMBOL_REFERENCED (name_tree))
05267 {
05268 TREE_ASM_WRITTEN (name_tree) = 1;
05269
05270
05271
05272
05273
05274 if (TARGET_IRIX && mips_abi == ABI_32 && p->size == -1)
05275 {
05276 fputs ("\t.globl ", asm_out_file);
05277 assemble_name (asm_out_file, p->name);
05278 fputs (" .text\n", asm_out_file);
05279 }
05280 else
05281 {
05282 fputs ("\t.extern\t", asm_out_file);
05283 assemble_name (asm_out_file, p->name);
05284 fprintf (asm_out_file, ", %d\n", p->size);
05285 }
05286 }
05287 }
05288 }
05289 }
05290
05291
05292
05293
05294 void
05295 mips_output_aligned_decl_common (FILE *stream, tree decl, const char *name,
05296 unsigned HOST_WIDE_INT size,
05297 unsigned int align)
05298 {
05299
05300
05301 if (TARGET_EMBEDDED_DATA && TARGET_UNINIT_CONST_IN_RODATA
05302 && TREE_CODE (decl) == VAR_DECL && TREE_READONLY (decl)
05303 && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node))
05304 {
05305 if (TREE_PUBLIC (decl) && DECL_NAME (decl))
05306 targetm.asm_out.globalize_label (stream, name);
05307
05308 readonly_data_section ();
05309 ASM_OUTPUT_ALIGN (stream, floor_log2 (align / BITS_PER_UNIT));
05310 mips_declare_object (stream, name, "",
05311 ":\n\t.space\t" HOST_WIDE_INT_PRINT_UNSIGNED "\n",
05312 size);
05313 }
05314 else
05315 mips_declare_common_object (stream, name, "\n\t.comm\t",
05316 size, align, true);
05317 }
05318
05319
05320
05321
05322
05323
05324 void
05325 mips_declare_common_object (FILE *stream, const char *name,
05326 const char *init_string,
05327 unsigned HOST_WIDE_INT size,
05328 unsigned int align, bool takes_alignment_p)
05329 {
05330 if (!takes_alignment_p)
05331 {
05332 size += (align / BITS_PER_UNIT) - 1;
05333 size -= size % (align / BITS_PER_UNIT);
05334 mips_declare_object (stream, name, init_string,
05335 "," HOST_WIDE_INT_PRINT_UNSIGNED "\n", size);
05336 }
05337 else
05338 mips_declare_object (stream, name, init_string,
05339 "," HOST_WIDE_INT_PRINT_UNSIGNED ",%u\n",
05340 size, align / BITS_PER_UNIT);
05341 }
05342
05343
05344
05345
05346
05347
05348
05349
05350 void
05351 mips_declare_object (FILE *stream, const char *name, const char *init_string,
05352 const char *final_string, ...)
05353 {
05354 va_list ap;
05355
05356 fputs (init_string, stream);
05357 assemble_name (stream, name);
05358 va_start (ap, final_string);
05359 vfprintf (stream, final_string, ap);
05360 va_end (ap);
05361
05362 if (!TARGET_EXPLICIT_RELOCS)
05363 {
05364 tree name_tree = get_identifier (name);
05365 TREE_ASM_WRITTEN (name_tree) = 1;
05366 }
05367 }
05368
05369 #ifdef ASM_OUTPUT_SIZE_DIRECTIVE
05370 extern int size_directive_output;
05371
05372
05373
05374
05375 void
05376 mips_declare_object_name (FILE *stream, const char *name,
05377 tree decl ATTRIBUTE_UNUSED)
05378 {
05379 #ifdef ASM_OUTPUT_TYPE_DIRECTIVE
05380 ASM_OUTPUT_TYPE_DIRECTIVE (stream, name, "object");
05381 #endif
05382
05383 size_directive_output = 0;
05384 if (!flag_inhibit_size_directive && DECL_SIZE (decl))
05385 {
05386 HOST_WIDE_INT size;
05387
05388 size_directive_output = 1;
05389 size = int_size_in_bytes (TREE_TYPE (decl));
05390 ASM_OUTPUT_SIZE_DIRECTIVE (stream, name, size);
05391 }
05392
05393 mips_declare_object (stream, name, "", ":\n", 0);
05394 }
05395
05396
05397
05398 void
05399 mips_finish_declare_object (FILE *stream, tree decl, int top_level, int at_end)
05400 {
05401 const char *name;
05402
05403 name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
05404 if (!flag_inhibit_size_directive
05405 && DECL_SIZE (decl) != 0
05406 && !at_end && top_level
05407 && DECL_INITIAL (decl) == error_mark_node
05408 && !size_directive_output)
05409 {
05410 HOST_WIDE_INT size;
05411
05412 size_directive_output = 1;
05413 size = int_size_in_bytes (TREE_TYPE (decl));
05414 ASM_OUTPUT_SIZE_DIRECTIVE (stream, name, size);
05415 }
05416 }
05417 #endif
05418
05419
05420
05421
05422 static bool
05423 mips_rewrite_small_data_p (rtx x)
05424 {
05425 enum mips_symbol_type symbol_type;
05426
05427 return (TARGET_EXPLICIT_RELOCS
05428 && mips_symbolic_constant_p (x, &symbol_type)
05429 && symbol_type == SYMBOL_SMALL_DATA);
05430 }
05431
05432
05433
05434
05435 static int
05436 mips_small_data_pattern_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
05437 {
05438 if (GET_CODE (*loc) == LO_SUM)
05439 return -1;
05440
05441 return mips_rewrite_small_data_p (*loc);
05442 }
05443
05444
05445
05446
05447 bool
05448 mips_small_data_pattern_p (rtx op)
05449 {
05450 return for_each_rtx (&op, mips_small_data_pattern_1, 0);
05451 }
05452
05453
05454
05455 static int
05456 mips_rewrite_small_data_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
05457 {
05458 if (mips_rewrite_small_data_p (*loc))
05459 *loc = gen_rtx_LO_SUM (Pmode, pic_offset_table_rtx, *loc);
05460
05461 if (GET_CODE (*loc) == LO_SUM)
05462 return -1;
05463
05464 return 0;
05465 }
05466
05467
05468
05469
05470 rtx
05471 mips_rewrite_small_data (rtx op)
05472 {
05473 op = copy_insn (op);
05474 for_each_rtx (&op, mips_rewrite_small_data_1, 0);
05475 return op;
05476 }
05477
05478
05479
05480
05481 static bool
05482 mips_function_has_gp_insn (void)
05483 {
05484
05485 if (!cfun->machine->has_gp_insn_p)
05486 {
05487 rtx insn;
05488
05489 push_topmost_sequence ();
05490 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
05491 if (INSN_P (insn)
05492 && GET_CODE (PATTERN (insn)) != USE
05493 && GET_CODE (PATTERN (insn)) != CLOBBER
05494 && (get_attr_got (insn) != GOT_UNSET
05495 || small_data_pattern (PATTERN (insn), VOIDmode)))
05496 break;
05497 pop_topmost_sequence ();
05498
05499 cfun->machine->has_gp_insn_p = (insn != 0);
05500 }
05501 return cfun->machine->has_gp_insn_p;
05502 }
05503
05504
05505
05506
05507
05508
05509 static unsigned int
05510 mips_global_pointer (void)
05511 {
05512 unsigned int regno;
05513
05514
05515 if (!TARGET_ABICALLS)
05516 return GLOBAL_POINTER_REGNUM;
05517
05518
05519 if (!TARGET_EXPLICIT_RELOCS)
05520 return GLOBAL_POINTER_REGNUM;
05521
05522
05523
05524 if (current_function_profile)
05525 return GLOBAL_POINTER_REGNUM;
05526
05527
05528
05529 if (current_function_has_nonlocal_goto)
05530 return GLOBAL_POINTER_REGNUM;
05531
05532
05533
05534
05535
05536
05537
05538
05539
05540
05541
05542
05543
05544
05545 if (!regs_ever_live[GLOBAL_POINTER_REGNUM]
05546 && !current_function_uses_const_pool
05547 && !mips_function_has_gp_insn ())
05548 return 0;
05549
05550
05551
05552 if (TARGET_NEWABI && current_function_is_leaf)
05553 for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
05554 if (!regs_ever_live[regno]
05555 && call_used_regs[regno]
05556 && !fixed_regs[regno]
05557 && regno != PIC_FUNCTION_ADDR_REGNUM)
05558 return regno;
05559
05560 return GLOBAL_POINTER_REGNUM;
05561 }
05562
05563
05564
05565
05566 static bool
05567 mips_save_reg_p (unsigned int regno)
05568 {
05569
05570 if (regno == GLOBAL_POINTER_REGNUM)
05571 return (TARGET_ABICALLS && TARGET_NEWABI
05572 && cfun->machine->global_pointer == regno);
05573
05574
05575 if (regs_ever_live[regno] && !call_used_regs[regno])
05576 return true;
05577
05578
05579 if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
05580 return true;
05581
05582
05583
05584 if (regno == GP_REG_FIRST + 31 && regs_ever_live[regno])
05585 return true;
05586
05587 if (TARGET_MIPS16)
05588 {
05589 tree return_type;
05590
05591 return_type = DECL_RESULT (current_function_decl);
05592
05593
05594
05595
05596 if (regno == GP_REG_FIRST + 18 && regs_ever_live[regno])
05597 return true;
05598
05599
05600
05601
05602 if (regno == GP_REG_FIRST + 31
05603 && mips16_hard_float
05604 && !aggregate_value_p (return_type, current_function_decl)
05605 && GET_MODE_CLASS (DECL_MODE (return_type)) == MODE_FLOAT
05606 && GET_MODE_SIZE (DECL_MODE (return_type)) <= UNITS_PER_FPVALUE)
05607 return true;
05608 }
05609
05610 return false;
05611 }
05612
05613
05614
05615
05616
05617
05618
05619
05620
05621
05622
05623
05624
05625
05626
05627
05628
05629
05630
05631
05632
05633
05634
05635
05636
05637
05638
05639
05640
05641
05642
05643
05644
05645
05646
05647
05648
05649
05650
05651
05652
05653
05654
05655
05656
05657
05658
05659
05660
05661
05662
05663
05664
05665
05666
05667 HOST_WIDE_INT
05668 compute_frame_size (HOST_WIDE_INT size)
05669 {
05670 unsigned int regno;
05671 HOST_WIDE_INT total_size;
05672 HOST_WIDE_INT var_size;
05673 HOST_WIDE_INT args_size;
05674 HOST_WIDE_INT cprestore_size;
05675 HOST_WIDE_INT gp_reg_rounded;
05676 HOST_WIDE_INT gp_reg_size;
05677 HOST_WIDE_INT fp_reg_size;
05678 unsigned int mask;
05679 unsigned int fmask;
05680
05681 cfun->machine->global_pointer = mips_global_pointer ();
05682
05683 gp_reg_size = 0;
05684 fp_reg_size = 0;
05685 mask = 0;
05686 fmask = 0;
05687 var_size = MIPS_STACK_ALIGN (size);
05688 args_size = current_function_outgoing_args_size;
05689 cprestore_size = MIPS_STACK_ALIGN (STARTING_FRAME_OFFSET) - args_size;
05690
05691
05692
05693
05694 if (var_size == 0 && current_function_is_leaf)
05695 cprestore_size = args_size = 0;
05696
05697
05698
05699
05700
05701
05702 if (args_size == 0 && current_function_calls_alloca)
05703 args_size = 4 * UNITS_PER_WORD;
05704
05705 total_size = var_size + args_size + cprestore_size;
05706
05707
05708 for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
05709 if (mips_save_reg_p (regno))
05710 {
05711 gp_reg_size += GET_MODE_SIZE (gpr_mode);
05712 mask |= 1 << (regno - GP_REG_FIRST);
05713 }
05714
05715
05716 if (current_function_calls_eh_return)
05717 {
05718 unsigned int i;
05719 for (i = 0; ; ++i)
05720 {
05721 regno = EH_RETURN_DATA_REGNO (i);
05722 if (regno == INVALID_REGNUM)
05723 break;
05724 gp_reg_size += GET_MODE_SIZE (gpr_mode);
05725 mask |= 1 << (regno - GP_REG_FIRST);
05726 }
05727 }
05728
05729
05730
05731 for (regno = (FP_REG_LAST - FP_INC + 1);
05732 regno >= FP_REG_FIRST;
05733 regno -= FP_INC)
05734 {
05735 if (mips_save_reg_p (regno))
05736 {
05737 fp_reg_size += FP_INC * UNITS_PER_FPREG;
05738 fmask |= ((1 << FP_INC) - 1) << (regno - FP_REG_FIRST);
05739 }
05740 }
05741
05742 gp_reg_rounded = MIPS_STACK_ALIGN (gp_reg_size);
05743 total_size += gp_reg_rounded + MIPS_STACK_ALIGN (fp_reg_size);
05744
05745
05746
05747 if (!TARGET_OLDABI)
05748 total_size += MIPS_STACK_ALIGN (current_function_pretend_args_size);
05749
05750
05751 cfun->machine->frame.total_size = total_size;
05752 cfun->machine->frame.var_size = var_size;
05753 cfun->machine->frame.args_size = args_size;
05754 cfun->machine->frame.cprestore_size = cprestore_size;
05755 cfun->machine->frame.gp_reg_size = gp_reg_size;
05756 cfun->machine->frame.fp_reg_size = fp_reg_size;
05757 cfun->machine->frame.mask = mask;
05758 cfun->machine->frame.fmask = fmask;
05759 cfun->machine->frame.initialized = reload_completed;
05760 cfun->machine->frame.num_gp = gp_reg_size / UNITS_PER_WORD;
05761 cfun->machine->frame.num_fp = fp_reg_size / (FP_INC * UNITS_PER_FPREG);
05762
05763 if (mask)
05764 {
05765 HOST_WIDE_INT offset;
05766
05767 offset = (args_size + cprestore_size + var_size
05768 + gp_reg_size - GET_MODE_SIZE (gpr_mode));
05769 cfun->machine->frame.gp_sp_offset = offset;
05770 cfun->machine->frame.gp_save_offset = offset - total_size;
05771 }
05772 else
05773 {
05774 cfun->machine->frame.gp_sp_offset = 0;
05775 cfun->machine->frame.gp_save_offset = 0;
05776 }
05777
05778 if (fmask)
05779 {
05780 HOST_WIDE_INT offset;
05781
05782 offset = (args_size + cprestore_size + var_size
05783 + gp_reg_rounded + fp_reg_size
05784 - FP_INC * UNITS_PER_FPREG);
05785 cfun->machine->frame.fp_sp_offset = offset;
05786 cfun->machine->frame.fp_save_offset = offset - total_size;
05787 }
05788 else
05789 {
05790 cfun->machine->frame.fp_sp_offset = 0;
05791 cfun->machine->frame.fp_save_offset = 0;
05792 }
05793
05794
05795 return total_size;
05796 }
05797
05798
05799
05800
05801
05802 HOST_WIDE_INT
05803 mips_initial_elimination_offset (int from, int to)
05804 {
05805 HOST_WIDE_INT offset;
05806
05807 compute_frame_size (get_frame_size ());
05808
05809
05810 switch (from)
05811 {
05812 case FRAME_POINTER_REGNUM:
05813 offset = 0;
05814 break;
05815
05816 case ARG_POINTER_REGNUM:
05817 offset = cfun->machine->frame.total_size;
05818 if (TARGET_NEWABI)
05819 offset -= current_function_pretend_args_size;
05820 break;
05821
05822 default:
05823 gcc_unreachable ();
05824 }
05825
05826 if (TARGET_MIPS16 && to == HARD_FRAME_POINTER_REGNUM)
05827 offset -= cfun->machine->frame.args_size;
05828
05829 return offset;
05830 }
05831
05832
05833
05834 rtx
05835 mips_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
05836 {
05837 if (count != 0)
05838 return const0_rtx;
05839
05840 return get_hard_reg_initial_val (Pmode, GP_REG_FIRST + 31);
05841 }
05842
05843
05844
05845
05846
05847 static void
05848 mips_save_restore_reg (enum machine_mode mode, int regno,
05849 HOST_WIDE_INT offset, mips_save_restore_fn fn)
05850 {
05851 rtx mem;
05852
05853 mem = gen_rtx_MEM (mode, plus_constant (stack_pointer_rtx, offset));
05854
05855 fn (gen_rtx_REG (mode, regno), mem);
05856 }
05857
05858
05859
05860
05861
05862
05863 static void
05864 mips_for_each_saved_reg (HOST_WIDE_INT sp_offset, mips_save_restore_fn fn)
05865 {
05866 #define BITSET_P(VALUE, BIT) (((VALUE) & (1L << (BIT))) != 0)
05867
05868 enum machine_mode fpr_mode;
05869 HOST_WIDE_INT offset;
05870 int regno;
05871
05872
05873
05874
05875
05876 offset = cfun->machine->frame.gp_sp_offset - sp_offset;
05877 for (regno = GP_REG_LAST; regno >= GP_REG_FIRST; regno--)
05878 if (BITSET_P (cfun->machine->frame.mask, regno - GP_REG_FIRST))
05879 {
05880 mips_save_restore_reg (gpr_mode, regno, offset, fn);
05881 offset -= GET_MODE_SIZE (gpr_mode);
05882 }
05883
05884
05885
05886 offset = cfun->machine->frame.fp_sp_offset - sp_offset;
05887 fpr_mode = (TARGET_SINGLE_FLOAT ? SFmode : DFmode);
05888 for (regno = (FP_REG_LAST - FP_INC + 1);
05889 regno >= FP_REG_FIRST;
05890 regno -= FP_INC)
05891 if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST))
05892 {
05893 mips_save_restore_reg (fpr_mode, regno, offset, fn);
05894 offset -= GET_MODE_SIZE (fpr_mode);
05895 }
05896 #undef BITSET_P
05897 }
05898
05899
05900
05901
05902
05903 static void
05904 mips_output_cplocal (void)
05905 {
05906 if (!TARGET_EXPLICIT_RELOCS
05907 && cfun->machine->global_pointer > 0
05908 && cfun->machine->global_pointer != GLOBAL_POINTER_REGNUM)
05909 output_asm_insn (".cplocal %+", 0);
05910 }
05911
05912
05913
05914
05915 static void
05916 mips_emit_loadgp (void)
05917 {
05918 if (TARGET_ABICALLS && TARGET_NEWABI && cfun->machine->global_pointer > 0)
05919 {
05920 rtx addr, offset, incoming_address;
05921
05922 addr = XEXP (DECL_RTL (current_function_decl), 0);
05923 offset = mips_unspec_address (addr, SYMBOL_GOTOFF_LOADGP);
05924 incoming_address = gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM);
05925 emit_insn (gen_loadgp (offset, incoming_address));
05926 if (!TARGET_EXPLICIT_RELOCS)
05927 emit_insn (gen_loadgp_blockage ());
05928 }
05929 }
05930
05931
05932
05933 static void
05934 mips_output_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
05935 {
05936 const char *fnname;
05937 HOST_WIDE_INT tsize = cfun->machine->frame.total_size;
05938
05939 #ifdef SDB_DEBUGGING_INFO
05940 if (debug_info_level != DINFO_LEVEL_TERSE && write_symbols == SDB_DEBUG)
05941 SDB_OUTPUT_SOURCE_LINE (file, DECL_SOURCE_LINE (current_function_decl));
05942 #endif
05943
05944
05945
05946
05947
05948 if (TARGET_MIPS16 && !TARGET_SOFT_FLOAT
05949 && current_function_args_info.fp_code != 0)
05950 build_mips16_function_stub (file);
05951
05952 if (!FUNCTION_NAME_ALREADY_DECLARED)
05953 {
05954
05955
05956
05957 fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
05958
05959 if (!flag_inhibit_size_directive)
05960 {
05961 fputs ("\t.ent\t", file);
05962 assemble_name (file, fnname);
05963 fputs ("\n", file);
05964 }
05965
05966 assemble_name (file, fnname);
05967 fputs (":\n", file);
05968 }
05969
05970
05971 if (TARGET_IRIX && mips_abi == ABI_32)
05972 TREE_ASM_WRITTEN (DECL_NAME (cfun->decl)) = 1;
05973
05974 if (!flag_inhibit_size_directive)
05975 {
05976
05977 fprintf (file,
05978 "\t.frame\t%s," HOST_WIDE_INT_PRINT_DEC ",%s\t\t"
05979 "# vars= " HOST_WIDE_INT_PRINT_DEC ", regs= %d/%d"
05980 ", args= " HOST_WIDE_INT_PRINT_DEC
05981 ", gp= " HOST_WIDE_INT_PRINT_DEC "\n",
05982 (reg_names[(frame_pointer_needed)
05983 ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM]),
05984 ((frame_pointer_needed && TARGET_MIPS16)
05985 ? tsize - cfun->machine->frame.args_size
05986 : tsize),
05987 reg_names[GP_REG_FIRST + 31],
05988 cfun->machine->frame.var_size,
05989 cfun->machine->frame.num_gp,
05990 cfun->machine->frame.num_fp,
05991 cfun->machine->frame.args_size,
05992 cfun->machine->frame.cprestore_size);
05993
05994
05995 fprintf (file, "\t.mask\t0x%08x," HOST_WIDE_INT_PRINT_DEC "\n",
05996 cfun->machine->frame.mask,
05997 cfun->machine->frame.gp_save_offset);
05998 fprintf (file, "\t.fmask\t0x%08x," HOST_WIDE_INT_PRINT_DEC "\n",
05999 cfun->machine->frame.fmask,
06000 cfun->machine->frame.fp_save_offset);
06001
06002
06003
06004
06005 }
06006
06007 if (TARGET_ABICALLS && !TARGET_NEWABI && cfun->machine->global_pointer > 0)
06008 {
06009
06010 if (!cfun->machine->all_noreorder_p)
06011 output_asm_insn ("%(.cpload\t%^%)", 0);
06012 else
06013 output_asm_insn ("%(.cpload\t%^\n\t%<", 0);
06014 }
06015 else if (cfun->machine->all_noreorder_p)
06016 output_asm_insn ("%(%<", 0);
06017
06018
06019
06020
06021 mips_output_cplocal ();
06022 }
06023
06024
06025
06026
06027 static void
06028 mips_set_frame_expr (rtx frame_pattern)
06029 {
06030 rtx insn;
06031
06032 insn = get_last_insn ();
06033 RTX_FRAME_RELATED_P (insn) = 1;
06034 REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR,
06035 frame_pattern,
06036 REG_NOTES (insn));
06037 }
06038
06039
06040
06041
06042
06043 static rtx
06044 mips_frame_set (rtx mem, rtx reg)
06045 {
06046 rtx set;
06047
06048
06049
06050
06051 if (REGNO (reg) == GP_REG_FIRST + 31
06052 && DWARF_FRAME_RETURN_COLUMN != GP_REG_FIRST + 31)
06053 reg = gen_rtx_REG (GET_MODE (reg), DWARF_FRAME_RETURN_COLUMN);
06054
06055 set = gen_rtx_SET (VOIDmode, mem, reg);
06056 RTX_FRAME_RELATED_P (set) = 1;
06057
06058 return set;
06059 }
06060
06061
06062
06063
06064 static void
06065 mips_save_reg (rtx reg, rtx mem)
06066 {
06067 if (GET_MODE (reg) == DFmode && !TARGET_FLOAT64)
06068 {
06069 rtx x1, x2;
06070
06071 if (mips_split_64bit_move_p (mem, reg))
06072 mips_split_64bit_move (mem, reg);
06073 else
06074 emit_move_insn (mem, reg);
06075
06076 x1 = mips_frame_set (mips_subword (mem, 0), mips_subword (reg, 0));
06077 x2 = mips_frame_set (mips_subword (mem, 1), mips_subword (reg, 1));
06078 mips_set_frame_expr (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, x1, x2)));
06079 }
06080 else
06081 {
06082 if (TARGET_MIPS16
06083 && REGNO (reg) != GP_REG_FIRST + 31
06084 && !M16_REG_P (REGNO (reg)))
06085 {
06086
06087
06088
06089 emit_move_insn (MIPS_PROLOGUE_TEMP (GET_MODE (reg)), reg);
06090 emit_move_insn (mem, MIPS_PROLOGUE_TEMP (GET_MODE (reg)));
06091 }
06092 else
06093 emit_move_insn (mem, reg);
06094
06095 mips_set_frame_expr (mips_frame_set (mem, reg));
06096 }
06097 }
06098
06099
06100
06101
06102 void
06103 mips_expand_prologue (void)
06104 {
06105 HOST_WIDE_INT size;
06106
06107 if (cfun->machine->global_pointer > 0)
06108 REGNO (pic_offset_table_rtx) = cfun->machine->global_pointer;
06109
06110 size = compute_frame_size (get_frame_size ());
06111
06112
06113
06114
06115 if ((cfun->machine->frame.mask | cfun->machine->frame.fmask) != 0)
06116 {
06117 HOST_WIDE_INT step1;
06118
06119 step1 = MIN (size, MIPS_MAX_FIRST_STACK_STEP);
06120 RTX_FRAME_RELATED_P (emit_insn (gen_add3_insn (stack_pointer_rtx,
06121 stack_pointer_rtx,
06122 GEN_INT (-step1)))) = 1;
06123 size -= step1;
06124 mips_for_each_saved_reg (size, mips_save_reg);
06125 }
06126
06127
06128 if (size > 0)
06129 {
06130 if (SMALL_OPERAND (-size))
06131 RTX_FRAME_RELATED_P (emit_insn (gen_add3_insn (stack_pointer_rtx,
06132 stack_pointer_rtx,
06133 GEN_INT (-size)))) = 1;
06134 else
06135 {
06136 emit_move_insn (MIPS_PROLOGUE_TEMP (Pmode), GEN_INT (size));
06137 if (TARGET_MIPS16)
06138 {
06139
06140
06141
06142
06143 gcc_assert (frame_pointer_needed);
06144 emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
06145 emit_insn (gen_sub3_insn (hard_frame_pointer_rtx,
06146 hard_frame_pointer_rtx,
06147 MIPS_PROLOGUE_TEMP (Pmode)));
06148 emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);
06149 }
06150 else
06151 emit_insn (gen_sub3_insn (stack_pointer_rtx,
06152 stack_pointer_rtx,
06153 MIPS_PROLOGUE_TEMP (Pmode)));
06154
06155
06156 mips_set_frame_expr
06157 (gen_rtx_SET (VOIDmode, stack_pointer_rtx,
06158 plus_constant (stack_pointer_rtx, -size)));
06159 }
06160 }
06161
06162
06163
06164
06165
06166 if (frame_pointer_needed)
06167 {
06168 if (TARGET_MIPS16 && cfun->machine->frame.args_size != 0)
06169 {
06170 rtx offset = GEN_INT (cfun->machine->frame.args_size);
06171 RTX_FRAME_RELATED_P
06172 (emit_insn (gen_add3_insn (hard_frame_pointer_rtx,
06173 stack_pointer_rtx,
06174 offset))) = 1;
06175 }
06176 else
06177 RTX_FRAME_RELATED_P (emit_move_insn (hard_frame_pointer_rtx,
06178 stack_pointer_rtx)) = 1;
06179 }
06180
06181
06182 if (TARGET_ABICALLS && !TARGET_NEWABI && !current_function_is_leaf)
06183 emit_insn (gen_cprestore (GEN_INT (current_function_outgoing_args_size)));
06184
06185 mips_emit_loadgp ();
06186
06187
06188
06189
06190 if (current_function_profile)
06191 emit_insn (gen_blockage ());
06192 }
06193
06194
06195
06196
06197 #define RA_MASK BITMASK_HIGH
06198
06199 static void
06200 mips_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
06201 HOST_WIDE_INT size ATTRIBUTE_UNUSED)
06202 {
06203
06204 REGNO (pic_offset_table_rtx) = GLOBAL_POINTER_REGNUM;
06205 mips_output_cplocal ();
06206
06207 if (cfun->machine->all_noreorder_p)
06208 {
06209
06210 output_asm_insn (".set\tmacro", 0);
06211 output_asm_insn (".set\treorder", 0);
06212 set_noreorder = set_nomacro = 0;
06213 }
06214
06215 if (!FUNCTION_NAME_ALREADY_DECLARED && !flag_inhibit_size_directive)
06216 {
06217 const char *fnname;
06218
06219
06220
06221
06222 fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
06223 fputs ("\t.end\t", file);
06224 assemble_name (file, fnname);
06225 fputs ("\n", file);
06226 }
06227 }
06228
06229
06230
06231 static void
06232 mips_restore_reg (rtx reg, rtx mem)
06233 {
06234
06235
06236 if (TARGET_MIPS16 && REGNO (reg) == GP_REG_FIRST + 31)
06237 reg = gen_rtx_REG (GET_MODE (reg), 7);
06238
06239 if (TARGET_MIPS16 && !M16_REG_P (REGNO (reg)))
06240 {
06241
06242 emit_move_insn (MIPS_EPILOGUE_TEMP (GET_MODE (reg)), mem);
06243 emit_move_insn (reg, MIPS_EPILOGUE_TEMP (GET_MODE (reg)));
06244 }
06245 else
06246 emit_move_insn (reg, mem);
06247 }
06248
06249
06250
06251
06252
06253
06254 void
06255 mips_expand_epilogue (int sibcall_p)
06256 {
06257 HOST_WIDE_INT step1, step2;
06258 rtx base, target;
06259
06260 if (!sibcall_p && mips_can_use_return_insn ())
06261 {
06262 emit_jump_insn (gen_return ());
06263 return;
06264 }
06265
06266
06267
06268
06269
06270
06271 step1 = cfun->machine->frame.total_size;
06272 step2 = 0;
06273
06274
06275
06276 if (!frame_pointer_needed)
06277 base = stack_pointer_rtx;
06278 else
06279 {
06280 base = hard_frame_pointer_rtx;
06281 if (TARGET_MIPS16)
06282 step1 -= cfun->machine->frame.args_size;
06283 }
06284
06285
06286
06287 if ((cfun->machine->frame.mask | cfun->machine->frame.fmask) != 0)
06288 {
06289 step2 = MIN (step1, MIPS_MAX_FIRST_STACK_STEP);
06290 step1 -= step2;
06291 }
06292
06293
06294 target = base;
06295 if (step1 > 0)
06296 {
06297 rtx adjust;
06298
06299
06300 adjust = GEN_INT (step1);
06301 if (!SMALL_OPERAND (step1))
06302 {
06303 emit_move_insn (MIPS_EPILOGUE_TEMP (Pmode), adjust);
06304 adjust = MIPS_EPILOGUE_TEMP (Pmode);
06305 }
06306
06307
06308 if (!TARGET_MIPS16)
06309 target = stack_pointer_rtx;
06310
06311 emit_insn (gen_add3_insn (target, base, adjust));
06312 }
06313
06314
06315 if (target != stack_pointer_rtx)
06316 emit_move_insn (stack_pointer_rtx, target);
06317
06318
06319
06320
06321 if (TARGET_ABICALLS && TARGET_NEWABI && !TARGET_EXPLICIT_RELOCS)
06322 emit_insn (gen_blockage ());
06323
06324
06325 mips_for_each_saved_reg (cfun->machine->frame.total_size - step2,
06326 mips_restore_reg);
06327
06328
06329 if (step2 > 0)
06330 emit_insn (gen_add3_insn (stack_pointer_rtx,
06331 stack_pointer_rtx,
06332 GEN_INT (step2)));
06333
06334
06335
06336 if (current_function_calls_eh_return)
06337 {
06338 if (TARGET_MIPS16)
06339 {
06340 emit_move_insn (MIPS_EPILOGUE_TEMP (Pmode), stack_pointer_rtx);
06341 emit_insn (gen_add3_insn (MIPS_EPILOGUE_TEMP (Pmode),
06342 MIPS_EPILOGUE_TEMP (Pmode),
06343 EH_RETURN_STACKADJ_RTX));
06344 emit_move_insn (stack_pointer_rtx, MIPS_EPILOGUE_TEMP (Pmode));
06345 }
06346 else
06347 emit_insn (gen_add3_insn (stack_pointer_rtx,
06348 stack_pointer_rtx,
06349 EH_RETURN_STACKADJ_RTX));
06350 }
06351
06352 if (!sibcall_p)
06353 {
06354
06355 if (TARGET_MIPS16 && (cfun->machine->frame.mask & RA_MASK) != 0)
06356 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode,
06357 GP_REG_FIRST + 7)));
06358 else
06359 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode,
06360 GP_REG_FIRST + 31)));
06361 }
06362 }
06363
06364
06365
06366
06367
06368 int
06369 mips_can_use_return_insn (void)
06370 {
06371 tree return_type;
06372
06373 if (! reload_completed)
06374 return 0;
06375
06376 if (regs_ever_live[31] || current_function_profile)
06377 return 0;
06378
06379 return_type = DECL_RESULT (current_function_decl);
06380
06381
06382
06383
06384 if (TARGET_MIPS16
06385 && mips16_hard_float
06386 && ! aggregate_value_p (return_type, current_function_decl)
06387 && GET_MODE_CLASS (DECL_MODE (return_type)) == MODE_FLOAT
06388 && GET_MODE_SIZE (DECL_MODE (return_type)) <= UNITS_PER_FPVALUE)
06389 return 0;
06390
06391 if (cfun->machine->frame.initialized)
06392 return cfun->machine->frame.total_size == 0;
06393
06394 return compute_frame_size (get_frame_size ()) == 0;
06395 }
06396
06397
06398
06399
06400 static void
06401 mips_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
06402 HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
06403 tree function)
06404 {
06405 rtx this, temp1, temp2, insn, fnaddr;
06406
06407
06408 no_new_pseudos = 1;
06409 reload_completed = 1;
06410 reset_block_changes ();
06411
06412
06413
06414 if (TARGET_ABICALLS)
06415 cfun->machine->global_pointer
06416 = REGNO (pic_offset_table_rtx)
06417 = TARGET_NEWABI ? 15 : GLOBAL_POINTER_REGNUM;
06418
06419
06420 mips_emit_loadgp ();
06421
06422
06423 temp1 = gen_rtx_REG (Pmode, 2);
06424 temp2 = gen_rtx_REG (Pmode, 3);
06425
06426
06427 if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
06428 this = gen_rtx_REG (Pmode, GP_ARG_FIRST + 1);
06429 else
06430 this = gen_rtx_REG (Pmode, GP_ARG_FIRST);
06431
06432
06433 if (delta != 0)
06434 {
06435 rtx offset = GEN_INT (delta);
06436 if (!SMALL_OPERAND (delta))
06437 {
06438 emit_move_insn (temp1, offset);
06439 offset = temp1;
06440 }
06441 emit_insn (gen_add3_insn (this, this, offset));
06442 }
06443
06444
06445 if (vcall_offset != 0)
06446 {
06447 rtx addr;
06448
06449
06450 emit_move_insn (temp1, gen_rtx_MEM (Pmode, this));
06451
06452
06453 addr = mips_add_offset (temp2, temp1, vcall_offset);
06454
06455
06456 emit_move_insn (temp1, gen_rtx_MEM (Pmode, addr));
06457 emit_insn (gen_add3_insn (this, this, temp1));
06458 }
06459
06460
06461
06462 fnaddr = XEXP (DECL_RTL (function), 0);
06463 if (TARGET_MIPS16 || TARGET_ABICALLS || TARGET_LONG_CALLS)
06464 {
06465
06466
06467
06468
06469
06470
06471
06472
06473
06474
06475
06476 if (TARGET_ABICALLS && !mips_dangerous_for_la25_p (fnaddr))
06477 temp1 = gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM);
06478 mips_load_call_address (temp1, fnaddr, true);
06479
06480 if (TARGET_ABICALLS && REGNO (temp1) != PIC_FUNCTION_ADDR_REGNUM)
06481 emit_move_insn (gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM), temp1);
06482 emit_jump_insn (gen_indirect_jump (temp1));
06483 }
06484 else
06485 {
06486 insn = emit_call_insn (gen_sibcall_internal (fnaddr, const0_rtx));
06487 SIBLING_CALL_P (insn) = 1;
06488 }
06489
06490
06491
06492 insn = get_insns ();
06493 insn_locators_initialize ();
06494 split_all_insns_noflow ();
06495 if (TARGET_MIPS16)
06496 mips16_lay_out_constants ();
06497 shorten_branches (insn);
06498 final_start_function (insn, file, 1);
06499 final (insn, file, 1, 0);
06500 final_end_function ();
06501
06502
06503
06504 reload_completed = 0;
06505 no_new_pseudos = 0;
06506 }
06507
06508
06509
06510 static int
06511 symbolic_expression_p (rtx x)
06512 {
06513 if (GET_CODE (x) == SYMBOL_REF)
06514 return 1;
06515
06516 if (GET_CODE (x) == CONST)
06517 return symbolic_expression_p (XEXP (x, 0));
06518
06519 if (UNARY_P (x))
06520 return symbolic_expression_p (XEXP (x, 0));
06521
06522 if (ARITHMETIC_P (x))
06523 return (symbolic_expression_p (XEXP (x, 0))
06524 || symbolic_expression_p (XEXP (x, 1)));
06525
06526 return 0;
06527 }
06528
06529
06530
06531
06532 static void
06533 mips_select_rtx_section (enum machine_mode mode, rtx x,
06534 unsigned HOST_WIDE_INT align)
06535 {
06536 if (TARGET_MIPS16)
06537 {
06538
06539
06540
06541 function_section (current_function_decl);
06542 }
06543 else if (TARGET_EMBEDDED_DATA)
06544 {
06545
06546
06547 mergeable_constant_section (mode, align, 0);
06548 }
06549 else
06550 {
06551
06552
06553
06554
06555 if (GET_MODE_SIZE (mode) <= (unsigned) mips_section_threshold
06556 && mips_section_threshold > 0)
06557 named_section (0, ".sdata", 0);
06558 else if (flag_pic && symbolic_expression_p (x))
06559 named_section (0, ".data.rel.ro", 3);
06560 else
06561 mergeable_constant_section (mode, align, 0);
06562 }
06563 }
06564
06565
06566
06567
06568
06569
06570
06571
06572
06573 static void
06574 mips_function_rodata_section (tree decl)
06575 {
06576 if (!TARGET_ABICALLS || TARGET_GPWORD)
06577 default_function_rodata_section (decl);
06578 else if (decl && DECL_SECTION_NAME (decl))
06579 {
06580 const char *name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
06581 if (DECL_ONE_ONLY (decl) && strncmp (name, ".gnu.linkonce.t.", 16) == 0)
06582 {
06583 char *rname = ASTRDUP (name);
06584 rname[14] = 'd';
06585 named_section_real (rname, SECTION_LINKONCE | SECTION_WRITE, decl);
06586 }
06587 else if (flag_function_sections && flag_data_sections
06588 && strncmp (name, ".text.", 6) == 0)
06589 {
06590 char *rname = ASTRDUP (name);
06591 memcpy (rname + 1, "data", 4);
06592 named_section_flags (rname, SECTION_WRITE);
06593 }
06594 else
06595 data_section ();
06596 }
06597 else
06598 data_section ();
06599 }
06600
06601
06602
06603
06604 static bool
06605 mips_in_small_data_p (tree decl)
06606 {
06607 HOST_WIDE_INT size;
06608
06609 if (TREE_CODE (decl) == STRING_CST || TREE_CODE (decl) == FUNCTION_DECL)
06610 return false;
06611
06612
06613
06614 if (TARGET_ABICALLS)
06615 return false;
06616
06617 if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl) != 0)
06618 {
06619 const char *name;
06620
06621
06622 name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
06623 if (strcmp (name, ".sdata") != 0 && strcmp (name, ".sbss") != 0)
06624 return false;
06625
06626
06627
06628 if (TARGET_EXPLICIT_RELOCS || !DECL_EXTERNAL (decl))
06629 return true;
06630 }
06631 else if (TARGET_EMBEDDED_DATA)
06632 {
06633
06634
06635 if (TREE_CODE (decl) != VAR_DECL)
06636 return false;
06637
06638 if (TREE_READONLY (decl)
06639 && !TREE_SIDE_EFFECTS (decl)
06640 && (!DECL_INITIAL (decl) || TREE_CONSTANT (DECL_INITIAL (decl))))
06641 return false;
06642 }
06643
06644 size = int_size_in_bytes (TREE_TYPE (decl));
06645 return (size > 0 && size <= mips_section_threshold);
06646 }
06647
06648
06649
06650
06651
06652
06653
06654
06655
06656
06657 static int
06658 mips_fpr_return_fields (tree valtype, tree *fields)
06659 {
06660 tree field;
06661 int i;
06662
06663 if (!TARGET_NEWABI)
06664 return 0;
06665
06666 if (TREE_CODE (valtype) != RECORD_TYPE)
06667 return 0;
06668
06669 i = 0;
06670 for (field = TYPE_FIELDS (valtype); field != 0; field = TREE_CHAIN (field))
06671 {
06672 if (TREE_CODE (field) != FIELD_DECL)
06673 continue;
06674
06675 if (TREE_CODE (TREE_TYPE (field)) != REAL_TYPE)
06676 return 0;
06677
06678 if (i == 2)
06679 return 0;
06680
06681 fields[i++] = field;
06682 }
06683 return i;
06684 }
06685
06686
06687
06688
06689
06690
06691
06692
06693
06694
06695
06696
06697 static bool
06698 mips_return_in_msb (tree valtype)
06699 {
06700 tree fields[2];
06701
06702 return (TARGET_NEWABI
06703 && TARGET_BIG_ENDIAN
06704 && AGGREGATE_TYPE_P (valtype)
06705 && mips_fpr_return_fields (valtype, fields) == 0);
06706 }
06707
06708
06709
06710
06711
06712
06713
06714
06715
06716
06717 static rtx
06718 mips_return_fpr_pair (enum machine_mode mode,
06719 enum machine_mode mode1, HOST_WIDE_INT offset1,
06720 enum machine_mode mode2, HOST_WIDE_INT offset2)
06721 {
06722 int inc;
06723
06724 inc = (TARGET_NEWABI ? 2 : FP_INC);
06725 return gen_rtx_PARALLEL
06726 (mode,
06727 gen_rtvec (2,
06728 gen_rtx_EXPR_LIST (VOIDmode,
06729 gen_rtx_REG (mode1, FP_RETURN),
06730 GEN_INT (offset1)),
06731 gen_rtx_EXPR_LIST (VOIDmode,
06732 gen_rtx_REG (mode2, FP_RETURN + inc),
06733 GEN_INT (offset2))));
06734
06735 }
06736
06737
06738
06739
06740
06741
06742 rtx
06743 mips_function_value (tree valtype, tree func ATTRIBUTE_UNUSED,
06744 enum machine_mode mode)
06745 {
06746 if (valtype)
06747 {
06748 tree fields[2];
06749 int unsignedp;
06750
06751 mode = TYPE_MODE (valtype);
06752 unsignedp = TYPE_UNSIGNED (valtype);
06753
06754
06755
06756 mode = promote_mode (valtype, mode, &unsignedp, 1);
06757
06758
06759 switch (mips_fpr_return_fields (valtype, fields))
06760 {
06761 case 1:
06762 return gen_rtx_REG (mode, FP_RETURN);
06763
06764 case 2:
06765 return mips_return_fpr_pair (mode,
06766 TYPE_MODE (TREE_TYPE (fields[0])),
06767 int_byte_position (fields[0]),
06768 TYPE_MODE (TREE_TYPE (fields[1])),
06769 int_byte_position (fields[1]));
06770 }
06771
06772
06773
06774 if (mips_return_in_msb (valtype))
06775 {
06776 HOST_WIDE_INT size = int_size_in_bytes (valtype);
06777 if (size % UNITS_PER_WORD != 0)
06778 {
06779 size += UNITS_PER_WORD - size % UNITS_PER_WORD;
06780 mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
06781 }
06782 }
06783
06784
06785
06786
06787
06788 if (mips_abi != ABI_EABI && !FLOAT_TYPE_P (valtype))
06789 return gen_rtx_REG (mode, GP_RETURN);
06790 }
06791
06792 if ((GET_MODE_CLASS (mode) == MODE_FLOAT
06793 || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
06794 && GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE)
06795 return gen_rtx_REG (mode, FP_RETURN);
06796
06797
06798 if (mode == TFmode)
06799 return mips_return_fpr_pair (mode,
06800 DImode, 0,
06801 DImode, GET_MODE_SIZE (mode) / 2);
06802
06803 if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
06804 && GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE * 2)
06805 return mips_return_fpr_pair (mode,
06806 GET_MODE_INNER (mode), 0,
06807 GET_MODE_INNER (mode),
06808 GET_MODE_SIZE (mode) / 2);
06809
06810 return gen_rtx_REG (mode, GP_RETURN);
06811 }
06812
06813
06814
06815 static bool
06816 mips_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
06817 enum machine_mode mode, tree type,
06818 bool named ATTRIBUTE_UNUSED)
06819 {
06820 if (mips_abi == ABI_EABI)
06821 {
06822 int size;
06823
06824
06825 if (type == NULL_TREE || mode == DImode || mode == DFmode)
06826 return 0;
06827
06828 size = int_size_in_bytes (type);
06829 return size == -1 || size > UNITS_PER_WORD;
06830 }
06831 else
06832 {
06833
06834 return targetm.calls.must_pass_in_stack (mode, type);
06835 }
06836 }
06837
06838 static bool
06839 mips_callee_copies (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
06840 enum machine_mode mode ATTRIBUTE_UNUSED,
06841 tree type ATTRIBUTE_UNUSED, bool named)
06842 {
06843 return mips_abi == ABI_EABI && named;
06844 }
06845
06846
06847
06848
06849 bool
06850 mips_cannot_change_mode_class (enum machine_mode from,
06851 enum machine_mode to, enum reg_class class)
06852 {
06853 if (MIN (GET_MODE_SIZE (from), GET_MODE_SIZE (to)) <= UNITS_PER_WORD
06854 && MAX (GET_MODE_SIZE (from), GET_MODE_SIZE (to)) > UNITS