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_PER_WORD)
06855 {
06856 if (TARGET_BIG_ENDIAN)
06857 {
06858
06859
06860
06861
06862 if (FP_INC > 1 && reg_classes_intersect_p (FP_REGS, class))
06863 return true;
06864 }
06865 else
06866 {
06867
06868
06869
06870
06871 if (reg_classes_intersect_p (HI_REG, class))
06872 return true;
06873 }
06874 }
06875
06876
06877
06878
06879 if (TARGET_FLOAT64
06880 && from == SImode
06881 && GET_MODE_SIZE (to) >= UNITS_PER_WORD
06882 && reg_classes_intersect_p (FP_REGS, class))
06883 return true;
06884 return false;
06885 }
06886
06887
06888
06889
06890
06891 bool
06892 mips_dangerous_for_la25_p (rtx x)
06893 {
06894 HOST_WIDE_INT offset;
06895
06896 if (TARGET_EXPLICIT_RELOCS)
06897 return false;
06898
06899 mips_split_const (x, &x, &offset);
06900 return global_got_operand (x, VOIDmode);
06901 }
06902
06903
06904
06905 enum reg_class
06906 mips_preferred_reload_class (rtx x, enum reg_class class)
06907 {
06908 if (mips_dangerous_for_la25_p (x) && reg_class_subset_p (LEA_REGS, class))
06909 return LEA_REGS;
06910
06911 if (TARGET_HARD_FLOAT
06912 && FLOAT_MODE_P (GET_MODE (x))
06913 && reg_class_subset_p (FP_REGS, class))
06914 return FP_REGS;
06915
06916 if (reg_class_subset_p (GR_REGS, class))
06917 class = GR_REGS;
06918
06919 if (TARGET_MIPS16 && reg_class_subset_p (M16_REGS, class))
06920 class = M16_REGS;
06921
06922 return class;
06923 }
06924
06925
06926
06927
06928
06929
06930
06931 enum reg_class
06932 mips_secondary_reload_class (enum reg_class class,
06933 enum machine_mode mode, rtx x, int in_p)
06934 {
06935 enum reg_class gr_regs = TARGET_MIPS16 ? M16_REGS : GR_REGS;
06936 int regno = -1;
06937 int gp_reg_p;
06938
06939 if (REG_P (x)|| GET_CODE (x) == SUBREG)
06940 regno = true_regnum (x);
06941
06942 gp_reg_p = TARGET_MIPS16 ? M16_REG_P (regno) : GP_REG_P (regno);
06943
06944 if (mips_dangerous_for_la25_p (x))
06945 {
06946 gr_regs = LEA_REGS;
06947 if (TEST_HARD_REG_BIT (reg_class_contents[(int) class], 25))
06948 return gr_regs;
06949 }
06950
06951
06952
06953 if (class == HI_REG || class == LO_REG || class == MD_REGS)
06954 {
06955 if (TARGET_MIPS16 && in_p)
06956 {
06957
06958 return M16_REGS;
06959 }
06960 return gp_reg_p ? NO_REGS : gr_regs;
06961 }
06962 if (MD_REG_P (regno))
06963 {
06964 if (TARGET_MIPS16 && ! in_p)
06965 {
06966
06967 return M16_REGS;
06968 }
06969 return class == gr_regs ? NO_REGS : gr_regs;
06970 }
06971
06972
06973
06974
06975
06976 if (class == ST_REGS)
06977 {
06978 if (in_p)
06979 return FP_REGS;
06980 return gp_reg_p ? NO_REGS : gr_regs;
06981 }
06982 if (ST_REG_P (regno))
06983 {
06984 if (! in_p)
06985 return FP_REGS;
06986 return class == gr_regs ? NO_REGS : gr_regs;
06987 }
06988
06989 if (class == FP_REGS)
06990 {
06991 if (MEM_P (x))
06992 {
06993
06994 return NO_REGS;
06995 }
06996 else if (CONSTANT_P (x) && GET_MODE_CLASS (mode) == MODE_FLOAT)
06997 {
06998
06999
07000
07001 return NO_REGS;
07002 }
07003 else if (gp_reg_p || x == CONST0_RTX (mode))
07004 {
07005
07006 return NO_REGS;
07007 }
07008 else if (FP_REG_P (regno))
07009 {
07010
07011 return NO_REGS;
07012 }
07013 else
07014 {
07015
07016 return gr_regs;
07017 }
07018 }
07019
07020
07021
07022 if (TARGET_MIPS16)
07023 {
07024 if (class != M16_REGS && class != M16_NA_REGS)
07025 {
07026 if (gp_reg_p)
07027 return NO_REGS;
07028 return M16_REGS;
07029 }
07030 if (! gp_reg_p)
07031 {
07032 if (class == M16_REGS || class == M16_NA_REGS)
07033 return NO_REGS;
07034 return M16_REGS;
07035 }
07036 }
07037
07038 return NO_REGS;
07039 }
07040
07041
07042
07043
07044
07045
07046
07047
07048
07049
07050
07051
07052 int
07053 mips_class_max_nregs (enum reg_class class ATTRIBUTE_UNUSED,
07054 enum machine_mode mode)
07055 {
07056 if (class == ST_REGS)
07057 return (GET_MODE_SIZE (mode) + 3) / 4;
07058 else
07059 return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
07060 }
07061
07062 static bool
07063 mips_valid_pointer_mode (enum machine_mode mode)
07064 {
07065 return (mode == SImode || (TARGET_64BIT && mode == DImode));
07066 }
07067
07068
07069
07070
07071
07072
07073
07074
07075
07076 static bool
07077 mips_scalar_mode_supported_p (enum machine_mode mode)
07078 {
07079 switch (mode)
07080 {
07081 case QImode:
07082 case HImode:
07083 case SImode:
07084 case DImode:
07085 return true;
07086
07087
07088 case TImode:
07089 return TARGET_64BIT;
07090
07091 case SFmode:
07092 case DFmode:
07093 return true;
07094
07095
07096 case TFmode:
07097 return TARGET_NEWABI;
07098
07099 default:
07100 return false;
07101 }
07102 }
07103
07104
07105
07106 static bool
07107 mips_vector_mode_supported_p (enum machine_mode mode)
07108 {
07109 if (mode == V2SFmode && TARGET_PAIRED_SINGLE_FLOAT)
07110 return true;
07111 else
07112 return false;
07113 }
07114
07115
07116
07117
07118
07119
07120
07121
07122 static rtx
07123 mips16_gp_pseudo_reg (void)
07124 {
07125 if (cfun->machine->mips16_gp_pseudo_rtx == NULL_RTX)
07126 {
07127 rtx unspec;
07128 rtx insn, scan;
07129
07130 cfun->machine->mips16_gp_pseudo_rtx = gen_reg_rtx (Pmode);
07131
07132
07133
07134 start_sequence ();
07135 unspec = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, const0_rtx), UNSPEC_GP);
07136 emit_move_insn (cfun->machine->mips16_gp_pseudo_rtx,
07137 gen_rtx_CONST (Pmode, unspec));
07138 insn = get_insns ();
07139 end_sequence ();
07140
07141 push_topmost_sequence ();
07142
07143
07144 for (scan = get_insns (); scan != NULL_RTX; scan = NEXT_INSN (scan))
07145 if (NOTE_P (scan)
07146 && NOTE_LINE_NUMBER (scan) == NOTE_INSN_FUNCTION_BEG)
07147 break;
07148 if (scan == NULL_RTX)
07149 scan = get_insns ();
07150 insn = emit_insn_after (insn, scan);
07151 pop_topmost_sequence ();
07152 }
07153
07154 return cfun->machine->mips16_gp_pseudo_rtx;
07155 }
07156
07157
07158
07159
07160
07161
07162
07163 static void
07164 mips16_fp_args (FILE *file, int fp_code, int from_fp_p)
07165 {
07166 const char *s;
07167 int gparg, fparg;
07168 unsigned int f;
07169
07170
07171 gcc_assert (TARGET_OLDABI);
07172
07173 if (from_fp_p)
07174 s = "mfc1";
07175 else
07176 s = "mtc1";
07177 gparg = GP_ARG_FIRST;
07178 fparg = FP_ARG_FIRST;
07179 for (f = (unsigned int) fp_code; f != 0; f >>= 2)
07180 {
07181 if ((f & 3) == 1)
07182 {
07183 if ((fparg & 1) != 0)
07184 ++fparg;
07185 fprintf (file, "\t%s\t%s,%s\n", s,
07186 reg_names[gparg], reg_names[fparg]);
07187 }
07188 else if ((f & 3) == 2)
07189 {
07190 if (TARGET_64BIT)
07191 fprintf (file, "\td%s\t%s,%s\n", s,
07192 reg_names[gparg], reg_names[fparg]);
07193 else
07194 {
07195 if ((fparg & 1) != 0)
07196 ++fparg;
07197 if (TARGET_BIG_ENDIAN)
07198 fprintf (file, "\t%s\t%s,%s\n\t%s\t%s,%s\n", s,
07199 reg_names[gparg], reg_names[fparg + 1], s,
07200 reg_names[gparg + 1], reg_names[fparg]);
07201 else
07202 fprintf (file, "\t%s\t%s,%s\n\t%s\t%s,%s\n", s,
07203 reg_names[gparg], reg_names[fparg], s,
07204 reg_names[gparg + 1], reg_names[fparg + 1]);
07205 ++gparg;
07206 ++fparg;
07207 }
07208 }
07209 else
07210 gcc_unreachable ();
07211
07212 ++gparg;
07213 ++fparg;
07214 }
07215 }
07216
07217
07218
07219
07220
07221
07222 static void
07223 build_mips16_function_stub (FILE *file)
07224 {
07225 const char *fnname;
07226 char *secname, *stubname;
07227 tree stubid, stubdecl;
07228 int need_comma;
07229 unsigned int f;
07230
07231 fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
07232 secname = (char *) alloca (strlen (fnname) + 20);
07233 sprintf (secname, ".mips16.fn.%s", fnname);
07234 stubname = (char *) alloca (strlen (fnname) + 20);
07235 sprintf (stubname, "__fn_stub_%s", fnname);
07236 stubid = get_identifier (stubname);
07237 stubdecl = build_decl (FUNCTION_DECL, stubid,
07238 build_function_type (void_type_node, NULL_TREE));
07239 DECL_SECTION_NAME (stubdecl) = build_string (strlen (secname), secname);
07240
07241 fprintf (file, "\t# Stub function for %s (", current_function_name ());
07242 need_comma = 0;
07243 for (f = (unsigned int) current_function_args_info.fp_code; f != 0; f >>= 2)
07244 {
07245 fprintf (file, "%s%s",
07246 need_comma ? ", " : "",
07247 (f & 3) == 1 ? "float" : "double");
07248 need_comma = 1;
07249 }
07250 fprintf (file, ")\n");
07251
07252 fprintf (file, "\t.set\tnomips16\n");
07253 function_section (stubdecl);
07254 ASM_OUTPUT_ALIGN (file, floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT));
07255
07256
07257
07258 if (!FUNCTION_NAME_ALREADY_DECLARED)
07259 {
07260 fputs ("\t.ent\t", file);
07261 assemble_name (file, stubname);
07262 fputs ("\n", file);
07263 }
07264
07265 assemble_name (file, stubname);
07266 fputs (":\n", file);
07267
07268
07269 fprintf (file, "\t.set\tnoreorder\n");
07270
07271 mips16_fp_args (file, current_function_args_info.fp_code, 1);
07272
07273 fprintf (asm_out_file, "\t.set\tnoat\n");
07274 fprintf (asm_out_file, "\tla\t%s,", reg_names[GP_REG_FIRST + 1]);
07275 assemble_name (file, fnname);
07276 fprintf (file, "\n");
07277 fprintf (asm_out_file, "\tjr\t%s\n", reg_names[GP_REG_FIRST + 1]);
07278 fprintf (asm_out_file, "\t.set\tat\n");
07279
07280
07281
07282
07283
07284
07285 fprintf (file, "\tnop\n");
07286
07287 fprintf (file, "\t.set\treorder\n");
07288
07289 if (!FUNCTION_NAME_ALREADY_DECLARED)
07290 {
07291 fputs ("\t.end\t", file);
07292 assemble_name (file, stubname);
07293 fputs ("\n", file);
07294 }
07295
07296 fprintf (file, "\t.set\tmips16\n");
07297
07298 function_section (current_function_decl);
07299 }
07300
07301
07302
07303
07304 struct mips16_stub
07305 {
07306 struct mips16_stub *next;
07307 char *name;
07308 int fpret;
07309 };
07310
07311 static struct mips16_stub *mips16_stubs;
07312
07313
07314
07315
07316
07317
07318
07319
07320
07321
07322
07323
07324
07325
07326
07327
07328
07329
07330
07331 int
07332 build_mips16_call_stub (rtx retval, rtx fn, rtx arg_size, int fp_code)
07333 {
07334 int fpret;
07335 const char *fnname;
07336 char *secname, *stubname;
07337 struct mips16_stub *l;
07338 tree stubid, stubdecl;
07339 int need_comma;
07340 unsigned int f;
07341
07342
07343
07344 if (! TARGET_MIPS16 || ! mips16_hard_float)
07345 return 0;
07346
07347
07348
07349 fpret = (retval != 0
07350 && GET_MODE_CLASS (GET_MODE (retval)) == MODE_FLOAT
07351 && GET_MODE_SIZE (GET_MODE (retval)) <= UNITS_PER_FPVALUE);
07352
07353
07354
07355
07356 if (fp_code == 0 && ! fpret)
07357 return 0;
07358
07359
07360
07361 if (GET_CODE (fn) == SYMBOL_REF
07362 && strncmp (XSTR (fn, 0), "__mips16_", 9) == 0)
07363 return 0;
07364
07365
07366
07367 gcc_assert (TARGET_OLDABI);
07368
07369
07370
07371 if (fpret)
07372 gcc_assert (GET_MODE (retval) == SFmode || GET_MODE (retval) == DFmode);
07373
07374
07375
07376
07377
07378
07379 if (GET_CODE (fn) != SYMBOL_REF)
07380 {
07381 char buf[30];
07382 tree id;
07383 rtx stub_fn, insn;
07384
07385
07386
07387
07388 sprintf (buf, "__mips16_call_stub_%s%d",
07389 (fpret
07390 ? (GET_MODE (retval) == SFmode ? "sf_" : "df_")
07391 : ""),
07392 fp_code);
07393 id = get_identifier (buf);
07394 stub_fn = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (id));
07395
07396 emit_move_insn (gen_rtx_REG (Pmode, 2), fn);
07397
07398 if (retval == NULL_RTX)
07399 insn = gen_call_internal (stub_fn, arg_size);
07400 else
07401 insn = gen_call_value_internal (retval, stub_fn, arg_size);
07402 insn = emit_call_insn (insn);
07403
07404
07405 CALL_INSN_FUNCTION_USAGE (insn) =
07406 gen_rtx_EXPR_LIST (VOIDmode,
07407 gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, 2)),
07408 CALL_INSN_FUNCTION_USAGE (insn));
07409
07410
07411
07412
07413
07414
07415 if (fpret)
07416 CALL_INSN_FUNCTION_USAGE (insn) =
07417 gen_rtx_EXPR_LIST (VOIDmode,
07418 gen_rtx_USE (VOIDmode,
07419 gen_rtx_REG (word_mode, 18)),
07420 CALL_INSN_FUNCTION_USAGE (insn));
07421
07422
07423
07424 return 1;
07425 }
07426
07427
07428
07429
07430 fnname = XSTR (fn, 0);
07431 for (l = mips16_stubs; l != NULL; l = l->next)
07432 if (strcmp (l->name, fnname) == 0)
07433 break;
07434
07435 if (l == NULL)
07436 {
07437
07438
07439
07440
07441
07442
07443
07444
07445
07446
07447
07448
07449
07450
07451
07452
07453
07454
07455
07456 secname = (char *) alloca (strlen (fnname) + 40);
07457 sprintf (secname, ".mips16.call.%s%s",
07458 fpret ? "fp." : "",
07459 fnname);
07460 stubname = (char *) alloca (strlen (fnname) + 20);
07461 sprintf (stubname, "__call_stub_%s%s",
07462 fpret ? "fp_" : "",
07463 fnname);
07464 stubid = get_identifier (stubname);
07465 stubdecl = build_decl (FUNCTION_DECL, stubid,
07466 build_function_type (void_type_node, NULL_TREE));
07467 DECL_SECTION_NAME (stubdecl) = build_string (strlen (secname), secname);
07468
07469 fprintf (asm_out_file, "\t# Stub function to call %s%s (",
07470 (fpret
07471 ? (GET_MODE (retval) == SFmode ? "float " : "double ")
07472 : ""),
07473 fnname);
07474 need_comma = 0;
07475 for (f = (unsigned int) fp_code; f != 0; f >>= 2)
07476 {
07477 fprintf (asm_out_file, "%s%s",
07478 need_comma ? ", " : "",
07479 (f & 3) == 1 ? "float" : "double");
07480 need_comma = 1;
07481 }
07482 fprintf (asm_out_file, ")\n");
07483
07484 fprintf (asm_out_file, "\t.set\tnomips16\n");
07485 assemble_start_function (stubdecl, stubname);
07486
07487 if (!FUNCTION_NAME_ALREADY_DECLARED)
07488 {
07489 fputs ("\t.ent\t", asm_out_file);
07490 assemble_name (asm_out_file, stubname);
07491 fputs ("\n", asm_out_file);
07492
07493 assemble_name (asm_out_file, stubname);
07494 fputs (":\n", asm_out_file);
07495 }
07496
07497
07498
07499
07500
07501
07502 fprintf (asm_out_file, "\t.set\tnoreorder\n");
07503
07504 mips16_fp_args (asm_out_file, fp_code, 0);
07505
07506 if (! fpret)
07507 {
07508 fprintf (asm_out_file, "\t.set\tnoat\n");
07509 fprintf (asm_out_file, "\tla\t%s,%s\n", reg_names[GP_REG_FIRST + 1],
07510 fnname);
07511 fprintf (asm_out_file, "\tjr\t%s\n", reg_names[GP_REG_FIRST + 1]);
07512 fprintf (asm_out_file, "\t.set\tat\n");
07513
07514
07515
07516
07517
07518 fprintf (asm_out_file, "\tnop\n");
07519 }
07520 else
07521 {
07522 fprintf (asm_out_file, "\tmove\t%s,%s\n",
07523 reg_names[GP_REG_FIRST + 18], reg_names[GP_REG_FIRST + 31]);
07524 fprintf (asm_out_file, "\tjal\t%s\n", fnname);
07525
07526 fprintf (asm_out_file, "\tnop\n");
07527 if (GET_MODE (retval) == SFmode)
07528 fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
07529 reg_names[GP_REG_FIRST + 2], reg_names[FP_REG_FIRST + 0]);
07530 else
07531 {
07532 if (TARGET_BIG_ENDIAN)
07533 {
07534 fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
07535 reg_names[GP_REG_FIRST + 2],
07536 reg_names[FP_REG_FIRST + 1]);
07537 fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
07538 reg_names[GP_REG_FIRST + 3],
07539 reg_names[FP_REG_FIRST + 0]);
07540 }
07541 else
07542 {
07543 fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
07544 reg_names[GP_REG_FIRST + 2],
07545 reg_names[FP_REG_FIRST + 0]);
07546 fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
07547 reg_names[GP_REG_FIRST + 3],
07548 reg_names[FP_REG_FIRST + 1]);
07549 }
07550 }
07551 fprintf (asm_out_file, "\tj\t%s\n", reg_names[GP_REG_FIRST + 18]);
07552
07553 fprintf (asm_out_file, "\tnop\n");
07554 }
07555
07556 fprintf (asm_out_file, "\t.set\treorder\n");
07557
07558 #ifdef ASM_DECLARE_FUNCTION_SIZE
07559 ASM_DECLARE_FUNCTION_SIZE (asm_out_file, stubname, stubdecl);
07560 #endif
07561
07562 if (!FUNCTION_NAME_ALREADY_DECLARED)
07563 {
07564 fputs ("\t.end\t", asm_out_file);
07565 assemble_name (asm_out_file, stubname);
07566 fputs ("\n", asm_out_file);
07567 }
07568
07569 fprintf (asm_out_file, "\t.set\tmips16\n");
07570
07571
07572 l = (struct mips16_stub *) xmalloc (sizeof *l);
07573 l->name = xstrdup (fnname);
07574 l->fpret = fpret;
07575 l->next = mips16_stubs;
07576 mips16_stubs = l;
07577 }
07578
07579
07580
07581
07582
07583
07584
07585
07586 if (fpret && ! l->fpret)
07587 error ("cannot handle inconsistent calls to %qs", fnname);
07588
07589
07590
07591
07592
07593
07594
07595 if (l->fpret)
07596 {
07597 rtx insn;
07598
07599 if (retval == NULL_RTX)
07600 insn = gen_call_internal (fn, arg_size);
07601 else
07602 insn = gen_call_value_internal (retval, fn, arg_size);
07603 insn = emit_call_insn (insn);
07604
07605 CALL_INSN_FUNCTION_USAGE (insn) =
07606 gen_rtx_EXPR_LIST (VOIDmode,
07607 gen_rtx_USE (VOIDmode, gen_rtx_REG (word_mode, 18)),
07608 CALL_INSN_FUNCTION_USAGE (insn));
07609
07610
07611
07612 return 1;
07613 }
07614
07615
07616 return 0;
07617 }
07618
07619
07620
07621
07622 struct mips16_constant {
07623 struct mips16_constant *next;
07624 rtx value;
07625 rtx label;
07626 enum machine_mode mode;
07627 };
07628
07629
07630
07631
07632
07633
07634 struct mips16_constant_pool {
07635 struct mips16_constant *first;
07636 int highest_address;
07637 int insn_address;
07638 };
07639
07640
07641
07642
07643 static rtx
07644 add_constant (struct mips16_constant_pool *pool,
07645 rtx value, enum machine_mode mode)
07646 {
07647 struct mips16_constant **p, *c;
07648 bool first_of_size_p;
07649
07650
07651
07652
07653
07654
07655
07656 first_of_size_p = true;
07657 for (p = &pool->first; *p != 0; p = &(*p)->next)
07658 {
07659 if (mode == (*p)->mode && rtx_equal_p (value, (*p)->value))
07660 return (*p)->label;
07661 if (GET_MODE_SIZE (mode) < GET_MODE_SIZE ((*p)->mode))
07662 break;
07663 if (GET_MODE_SIZE (mode) == GET_MODE_SIZE ((*p)->mode))
07664 first_of_size_p = false;
07665 }
07666
07667
07668
07669
07670
07671
07672
07673
07674 if (pool->first == 0)
07675
07676
07677
07678
07679 pool->highest_address = pool->insn_address - (UNITS_PER_WORD - 2) + 0x8000;
07680 pool->highest_address -= GET_MODE_SIZE (mode);
07681 if (first_of_size_p)
07682
07683 pool->highest_address -= GET_MODE_SIZE (mode) - 1;
07684
07685
07686 c = (struct mips16_constant *) xmalloc (sizeof *c);
07687 c->value = value;
07688 c->mode = mode;
07689 c->label = gen_label_rtx ();
07690 c->next = *p;
07691 *p = c;
07692
07693 return c->label;
07694 }
07695
07696
07697
07698
07699 static rtx
07700 dump_constants_1 (enum machine_mode mode, rtx value, rtx insn)
07701 {
07702 switch (GET_MODE_CLASS (mode))
07703 {
07704 case MODE_INT:
07705 {
07706 rtx size = GEN_INT (GET_MODE_SIZE (mode));
07707 return emit_insn_after (gen_consttable_int (value, size), insn);
07708 }
07709
07710 case MODE_FLOAT:
07711 return emit_insn_after (gen_consttable_float (value), insn);
07712
07713 case MODE_VECTOR_FLOAT:
07714 case MODE_VECTOR_INT:
07715 {
07716 int i;
07717 for (i = 0; i < CONST_VECTOR_NUNITS (value); i++)
07718 insn = dump_constants_1 (GET_MODE_INNER (mode),
07719 CONST_VECTOR_ELT (value, i), insn);
07720 return insn;
07721 }
07722
07723 default:
07724 gcc_unreachable ();
07725 }
07726 }
07727
07728
07729
07730
07731 static void
07732 dump_constants (struct mips16_constant *constants, rtx insn)
07733 {
07734 struct mips16_constant *c, *next;
07735 int align;
07736
07737 align = 0;
07738 for (c = constants; c != NULL; c = next)
07739 {
07740
07741 if (align < GET_MODE_SIZE (c->mode))
07742 {
07743 int align_log = floor_log2 (GET_MODE_SIZE (c->mode));
07744 insn = emit_insn_after (gen_align (GEN_INT (align_log)), insn);
07745 }
07746 align = GET_MODE_SIZE (c->mode);
07747
07748 insn = emit_label_after (c->label, insn);
07749 insn = dump_constants_1 (c->mode, c->value, insn);
07750
07751 next = c->next;
07752 free (c);
07753 }
07754
07755 emit_barrier_after (insn);
07756 }
07757
07758
07759
07760 static int
07761 mips16_insn_length (rtx insn)
07762 {
07763 if (JUMP_P (insn))
07764 {
07765 rtx body = PATTERN (insn);
07766 if (GET_CODE (body) == ADDR_VEC)
07767 return GET_MODE_SIZE (GET_MODE (body)) * XVECLEN (body, 0);
07768 if (GET_CODE (body) == ADDR_DIFF_VEC)
07769 return GET_MODE_SIZE (GET_MODE (body)) * XVECLEN (body, 1);
07770 }
07771 return get_attr_length (insn);
07772 }
07773
07774
07775
07776
07777 static int
07778 mips16_rewrite_pool_refs (rtx *x, void *data)
07779 {
07780 struct mips16_constant_pool *pool = data;
07781 if (GET_CODE (*x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (*x))
07782 *x = gen_rtx_LABEL_REF (Pmode, add_constant (pool,
07783 get_pool_constant (*x),
07784 get_pool_mode (*x)));
07785 return 0;
07786 }
07787
07788
07789
07790 static void
07791 mips16_lay_out_constants (void)
07792 {
07793 struct mips16_constant_pool pool;
07794 rtx insn, barrier;
07795
07796 barrier = 0;
07797 memset (&pool, 0, sizeof (pool));
07798 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
07799 {
07800
07801 if (INSN_P (insn))
07802 for_each_rtx (&PATTERN (insn), mips16_rewrite_pool_refs, &pool);
07803
07804 pool.insn_address += mips16_insn_length (insn);
07805
07806 if (pool.first != NULL)
07807 {
07808
07809
07810
07811
07812
07813
07814
07815 if (barrier == 0 && pool.insn_address + 4 > pool.highest_address)
07816 {
07817 rtx label, jump;
07818
07819 label = gen_label_rtx ();
07820
07821 jump = emit_jump_insn_before (gen_jump (label), insn);
07822 JUMP_LABEL (jump) = label;
07823 LABEL_NUSES (label) = 1;
07824 barrier = emit_barrier_after (jump);
07825
07826 emit_label_after (label, barrier);
07827 pool.insn_address += 4;
07828 }
07829
07830
07831
07832
07833
07834 if (pool.insn_address > pool.highest_address)
07835 {
07836 dump_constants (pool.first, barrier);
07837 pool.first = NULL;
07838 barrier = 0;
07839 }
07840 else if (BARRIER_P (insn))
07841 barrier = insn;
07842 }
07843 }
07844 dump_constants (pool.first, get_last_insn ());
07845 }
07846
07847
07848 static rtx mips_sim_insn;
07849
07850
07851
07852 struct mips_sim {
07853
07854
07855 unsigned int issue_rate;
07856
07857
07858 unsigned int time;
07859
07860
07861 unsigned int insns_left;
07862
07863
07864
07865
07866 struct {
07867 rtx insn;
07868 unsigned int time;
07869 } last_set[FIRST_PSEUDO_REGISTER];
07870
07871
07872 state_t dfa_state;
07873 };
07874
07875
07876
07877 static void
07878 mips_sim_reset (struct mips_sim *state)
07879 {
07880 state->time = 0;
07881 state->insns_left = state->issue_rate;
07882 memset (&state->last_set, 0, sizeof (state->last_set));
07883 state_reset (state->dfa_state);
07884 }
07885
07886
07887
07888
07889 static void
07890 mips_sim_init (struct mips_sim *state, state_t dfa_state)
07891 {
07892 state->issue_rate = mips_issue_rate ();
07893 state->dfa_state = dfa_state;
07894 mips_sim_reset (state);
07895 }
07896
07897
07898
07899 static void
07900 mips_sim_next_cycle (struct mips_sim *state)
07901 {
07902 state->time++;
07903 state->insns_left = state->issue_rate;
07904 state_transition (state->dfa_state, 0);
07905 }
07906
07907
07908
07909
07910 static void
07911 mips_sim_wait_reg (struct mips_sim *state, rtx insn, rtx reg)
07912 {
07913 unsigned int i;
07914
07915 for (i = 0; i < HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg)); i++)
07916 if (state->last_set[REGNO (reg) + i].insn != 0)
07917 {
07918 unsigned int t;
07919
07920 t = state->last_set[REGNO (reg) + i].time;
07921 t += insn_latency (state->last_set[REGNO (reg) + i].insn, insn);
07922 while (state->time < t)
07923 mips_sim_next_cycle (state);
07924 }
07925 }
07926
07927
07928
07929
07930 static int
07931 mips_sim_wait_regs_2 (rtx *x, void *data)
07932 {
07933 if (REG_P (*x))
07934 mips_sim_wait_reg (data, mips_sim_insn, *x);
07935 return 0;
07936 }
07937
07938
07939
07940 static void
07941 mips_sim_wait_regs_1 (rtx *x, void *data)
07942 {
07943 for_each_rtx (x, mips_sim_wait_regs_2, data);
07944 }
07945
07946
07947
07948
07949 static void
07950 mips_sim_wait_regs (struct mips_sim *state, rtx insn)
07951 {
07952 mips_sim_insn = insn;
07953 note_uses (&PATTERN (insn), mips_sim_wait_regs_1, state);
07954 }
07955
07956
07957
07958
07959 static void
07960 mips_sim_wait_units (struct mips_sim *state, rtx insn)
07961 {
07962 state_t tmp_state;
07963
07964 tmp_state = alloca (state_size ());
07965 while (state->insns_left == 0
07966 || (memcpy (tmp_state, state->dfa_state, state_size ()),
07967 state_transition (tmp_state, insn) >= 0))
07968 mips_sim_next_cycle (state);
07969 }
07970
07971
07972
07973 static void
07974 mips_sim_wait_insn (struct mips_sim *state, rtx insn)
07975 {
07976 mips_sim_wait_regs (state, insn);
07977 mips_sim_wait_units (state, insn);
07978 }
07979
07980
07981
07982
07983 static void
07984 mips_sim_record_set (rtx x, rtx pat ATTRIBUTE_UNUSED, void *data)
07985 {
07986 struct mips_sim *state;
07987 unsigned int i;
07988
07989 state = data;
07990 if (REG_P (x))
07991 for (i = 0; i < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); i++)
07992 {
07993 state->last_set[REGNO (x) + i].insn = mips_sim_insn;
07994 state->last_set[REGNO (x) + i].time = state->time;
07995 }
07996 }
07997
07998
07999
08000
08001
08002 static void
08003 mips_sim_issue_insn (struct mips_sim *state, rtx insn)
08004 {
08005 state_transition (state->dfa_state, insn);
08006 state->insns_left--;
08007
08008 mips_sim_insn = insn;
08009 note_stores (PATTERN (insn), mips_sim_record_set, state);
08010 }
08011
08012
08013
08014 static void
08015 mips_sim_issue_nop (struct mips_sim *state)
08016 {
08017 if (state->insns_left == 0)
08018 mips_sim_next_cycle (state);
08019 state->insns_left--;
08020 }
08021
08022
08023
08024
08025
08026 static void
08027 mips_sim_finish_insn (struct mips_sim *state, rtx insn)
08028 {
08029
08030 if (JUMP_P (insn))
08031 mips_sim_issue_nop (state);
08032
08033 switch (GET_CODE (SEQ_BEGIN (insn)))
08034 {
08035 case CODE_LABEL:
08036 case CALL_INSN:
08037
08038 mips_sim_reset (state);
08039 break;
08040
08041 case JUMP_INSN:
08042
08043
08044
08045
08046
08047
08048
08049 if (INSN_ANNULLED_BRANCH_P (SEQ_BEGIN (insn)))
08050 mips_sim_reset (state);
08051 break;
08052
08053 default:
08054 break;
08055 }
08056 }
08057
08058
08059
08060
08061
08062
08063
08064
08065
08066
08067
08068
08069
08070 static void
08071 vr4130_avoid_branch_rt_conflict (rtx insn)
08072 {
08073 rtx first, second;
08074
08075 first = SEQ_BEGIN (insn);
08076 second = SEQ_END (insn);
08077 if (JUMP_P (first)
08078 && NONJUMP_INSN_P (second)
08079 && GET_CODE (PATTERN (first)) == SET
08080 && GET_CODE (SET_DEST (PATTERN (first))) == PC
08081 && GET_CODE (SET_SRC (PATTERN (first))) == IF_THEN_ELSE)
08082 {
08083
08084 rtx cond = XEXP (SET_SRC (PATTERN (first)), 0);
08085 if ((GET_CODE (cond) == EQ || GET_CODE (cond) == NE)
08086 && REG_P (XEXP (cond, 0))
08087 && REG_P (XEXP (cond, 1))
08088 && reg_referenced_p (XEXP (cond, 1), PATTERN (second))
08089 && !reg_referenced_p (XEXP (cond, 0), PATTERN (second)))
08090 {
08091
08092 rtx tmp = XEXP (cond, 0);
08093 XEXP (cond, 0) = XEXP (cond, 1);
08094 XEXP (cond, 1) = tmp;
08095 }
08096 }
08097 }
08098
08099
08100
08101
08102
08103
08104 static void
08105 vr4130_align_insns (void)
08106 {
08107 struct mips_sim state;
08108 rtx insn, subinsn, last, last2, next;
08109 bool aligned_p;
08110
08111 dfa_start ();
08112
08113
08114
08115 last = 0;
08116 last2 = 0;
08117
08118
08119 aligned_p = true;
08120
08121 mips_sim_init (&state, alloca (state_size ()));
08122 for (insn = get_insns (); insn != 0; insn = next)
08123 {
08124 unsigned int length;
08125
08126 next = NEXT_INSN (insn);
08127
08128
08129
08130
08131 vr4130_avoid_branch_rt_conflict (insn);
08132
08133 if (USEFUL_INSN_P (insn))
08134 FOR_EACH_SUBINSN (subinsn, insn)
08135 {
08136 mips_sim_wait_insn (&state, subinsn);
08137
08138
08139
08140
08141
08142
08143
08144
08145
08146
08147
08148
08149
08150
08151
08152 if (state.insns_left != state.issue_rate
08153 && !CALL_P (subinsn))
08154 {
08155 if (subinsn == SEQ_BEGIN (insn) && aligned_p)
08156 {
08157
08158
08159
08160
08161
08162
08163
08164
08165
08166
08167
08168 emit_insn_after (gen_nop (), last2);
08169 aligned_p = false;
08170 }
08171 else if (subinsn != SEQ_BEGIN (insn) && !aligned_p)
08172 {
08173
08174
08175
08176 emit_insn_after (gen_nop (), last);
08177 aligned_p = true;
08178 }
08179 }
08180 mips_sim_issue_insn (&state, subinsn);
08181 }
08182 mips_sim_finish_insn (&state, insn);
08183
08184
08185 length = get_attr_length (insn);
08186 if (length > 0)
08187 {
08188
08189
08190
08191
08192 if (NONJUMP_INSN_P (SEQ_BEGIN (insn))
08193 && (recog_memoized (insn) < 0 || length >= 8))
08194 {
08195 next = emit_insn_after (gen_align (GEN_INT (3)), insn);
08196 next = NEXT_INSN (next);
08197 mips_sim_next_cycle (&state);
08198 aligned_p = true;
08199 }
08200 else if (length & 4)
08201 aligned_p = !aligned_p;
08202 last2 = last;
08203 last = insn;
08204 }
08205
08206
08207 if (LABEL_P (insn) && label_to_alignment (insn) >= 3)
08208 aligned_p = true;
08209 }
08210 dfa_finish ();
08211 }
08212
08213
08214
08215
08216
08217
08218
08219
08220
08221
08222
08223
08224
08225
08226
08227
08228 static void
08229 mips_avoid_hazard (rtx after, rtx insn, int *hilo_delay,
08230 rtx *delayed_reg, rtx lo_reg)
08231 {
08232 rtx pattern, set;
08233 int nops, ninsns;
08234
08235 if (!INSN_P (insn))
08236 return;
08237
08238 pattern = PATTERN (insn);
08239
08240
08241
08242
08243 if (GET_CODE (pattern) == ASM_INPUT || asm_noperands (pattern) >= 0)
08244 cfun->machine->all_noreorder_p = false;
08245
08246
08247 ninsns = get_attr_length (insn) / 4;
08248 if (ninsns == 0)
08249 return;
08250
08251
08252
08253
08254
08255 if (*hilo_delay < 2 && reg_set_p (lo_reg, pattern))
08256 nops = 2 - *hilo_delay;
08257 else if (*delayed_reg != 0 && reg_referenced_p (*delayed_reg, pattern))
08258 nops = 1;
08259 else
08260 nops = 0;
08261
08262
08263
08264 *hilo_delay += nops;
08265 while (nops-- > 0)
08266 emit_insn_after (gen_hazard_nop (), after);
08267
08268
08269 *hilo_delay += ninsns;
08270 *delayed_reg = 0;
08271 if (INSN_CODE (insn) >= 0)
08272 switch (get_attr_hazard (insn))
08273 {
08274 case HAZARD_NONE:
08275 break;
08276
08277 case HAZARD_HILO:
08278 *hilo_delay = 0;
08279 break;
08280
08281 case HAZARD_DELAY:
08282 set = single_set (insn);
08283 gcc_assert (set != 0);
08284 *delayed_reg = SET_DEST (set);
08285 break;
08286 }
08287 }
08288
08289
08290
08291
08292
08293
08294 static void
08295 mips_avoid_hazards (void)
08296 {
08297 rtx insn, last_insn, lo_reg, delayed_reg;
08298 int hilo_delay, i;
08299
08300
08301 split_all_insns_noflow ();
08302
08303
08304 cfun->machine->ignore_hazard_length_p = true;
08305 shorten_branches (get_insns ());
08306
08307 cfun->machine->all_noreorder_p = true;
08308
08309
08310
08311 if (current_function_profile)
08312 cfun->machine->all_noreorder_p = false;
08313
08314
08315
08316 if (TARGET_FIX_VR4120)
08317 cfun->machine->all_noreorder_p = false;
08318
08319
08320
08321
08322
08323 if (TARGET_FIX_VR4130 && !ISA_HAS_MACCHI)
08324 cfun->machine->all_noreorder_p = false;
08325
08326 last_insn = 0;
08327 hilo_delay = 2;
08328 delayed_reg = 0;
08329 lo_reg = gen_rtx_REG (SImode, LO_REGNUM);
08330
08331 for (insn = get_insns (); insn != 0; insn = NEXT_INSN (insn))
08332 if (INSN_P (insn))
08333 {
08334 if (GET_CODE (PATTERN (insn)) == SEQUENCE)
08335 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
08336 mips_avoid_hazard (last_insn, XVECEXP (PATTERN (insn), 0, i),
08337 &hilo_delay, &delayed_reg, lo_reg);
08338 else
08339 mips_avoid_hazard (last_insn, insn, &hilo_delay,
08340 &delayed_reg, lo_reg);
08341
08342 last_insn = insn;
08343 }
08344 }
08345
08346
08347
08348
08349 static void
08350 mips_reorg (void)
08351 {
08352 if (TARGET_MIPS16)
08353 mips16_lay_out_constants ();
08354 else if (TARGET_EXPLICIT_RELOCS)
08355 {
08356 if (mips_flag_delayed_branch)
08357 dbr_schedule (get_insns (), dump_file);
08358 mips_avoid_hazards ();
08359 if (TUNE_MIPS4130 && TARGET_VR4130_ALIGN)
08360 vr4130_align_insns ();
08361 }
08362 }
08363
08364
08365
08366
08367
08368
08369
08370 #include "config/gofast.h"
08371
08372 static void
08373 mips_init_libfuncs (void)
08374 {
08375 if (TARGET_FIX_VR4120)
08376 {
08377 set_optab_libfunc (sdiv_optab, SImode, "__vr4120_divsi3");
08378 set_optab_libfunc (smod_optab, SImode, "__vr4120_modsi3");
08379 }
08380
08381 if (TARGET_MIPS16 && mips16_hard_float)
08382 {
08383 set_optab_libfunc (add_optab, SFmode, "__mips16_addsf3");
08384 set_optab_libfunc (sub_optab, SFmode, "__mips16_subsf3");
08385 set_optab_libfunc (smul_optab, SFmode, "__mips16_mulsf3");
08386 set_optab_libfunc (sdiv_optab, SFmode, "__mips16_divsf3");
08387
08388 set_optab_libfunc (eq_optab, SFmode, "__mips16_eqsf2");
08389 set_optab_libfunc (ne_optab, SFmode, "__mips16_nesf2");
08390 set_optab_libfunc (gt_optab, SFmode, "__mips16_gtsf2");
08391 set_optab_libfunc (ge_optab, SFmode, "__mips16_gesf2");
08392 set_optab_libfunc (lt_optab, SFmode, "__mips16_ltsf2");
08393 set_optab_libfunc (le_optab, SFmode, "__mips16_lesf2");
08394
08395 set_conv_libfunc (sfix_optab, SImode, SFmode, "__mips16_fix_truncsfsi");
08396 set_conv_libfunc (sfloat_optab, SFmode, SImode, "__mips16_floatsisf");
08397
08398 if (TARGET_DOUBLE_FLOAT)
08399 {
08400 set_optab_libfunc (add_optab, DFmode, "__mips16_adddf3");
08401 set_optab_libfunc (sub_optab, DFmode, "__mips16_subdf3");
08402 set_optab_libfunc (smul_optab, DFmode, "__mips16_muldf3");
08403 set_optab_libfunc (sdiv_optab, DFmode, "__mips16_divdf3");
08404
08405 set_optab_libfunc (eq_optab, DFmode, "__mips16_eqdf2");
08406 set_optab_libfunc (ne_optab, DFmode, "__mips16_nedf2");
08407 set_optab_libfunc (gt_optab, DFmode, "__mips16_gtdf2");
08408 set_optab_libfunc (ge_optab, DFmode, "__mips16_gedf2");
08409 set_optab_libfunc (lt_optab, DFmode, "__mips16_ltdf2");
08410 set_optab_libfunc (le_optab, DFmode, "__mips16_ledf2");
08411
08412 set_conv_libfunc (sext_optab, DFmode, SFmode, "__mips16_extendsfdf2");
08413 set_conv_libfunc (trunc_optab, SFmode, DFmode, "__mips16_truncdfsf2");
08414
08415 set_conv_libfunc (sfix_optab, SImode, DFmode, "__mips16_fix_truncdfsi");
08416 set_conv_libfunc (sfloat_optab, DFmode, SImode, "__mips16_floatsidf");
08417 }
08418 }
08419 else
08420 gofast_maybe_init_libfuncs ();
08421 }
08422
08423
08424
08425
08426
08427
08428
08429
08430
08431
08432
08433
08434
08435
08436
08437
08438
08439
08440
08441
08442
08443
08444
08445
08446
08447
08448
08449
08450
08451
08452
08453
08454 int
08455 mips_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
08456 enum reg_class to, enum reg_class from)
08457 {
08458 if (from == M16_REGS && GR_REG_CLASS_P (to))
08459 return 2;
08460 else if (from == M16_NA_REGS && GR_REG_CLASS_P (to))
08461 return 2;
08462 else if (GR_REG_CLASS_P (from))
08463 {
08464 if (to == M16_REGS)
08465 return 2;
08466 else if (to == M16_NA_REGS)
08467 return 2;
08468 else if (GR_REG_CLASS_P (to))
08469 {
08470 if (TARGET_MIPS16)
08471 return 4;
08472 else
08473 return 2;
08474 }
08475 else if (to == FP_REGS)
08476 return 4;
08477 else if (to == HI_REG || to == LO_REG || to == MD_REGS)
08478 {
08479 if (TARGET_MIPS16)
08480 return 12;
08481 else
08482 return 6;
08483 }
08484 else if (COP_REG_CLASS_P (to))
08485 {
08486 return 5;
08487 }
08488 }
08489 else if (from == FP_REGS)
08490 {
08491 if (GR_REG_CLASS_P (to))
08492 return 4;
08493 else if (to == FP_REGS)
08494 return 2;
08495 else if (to == ST_REGS)
08496 return 8;
08497 }
08498 else if (from == HI_REG || from == LO_REG || from == MD_REGS)
08499 {
08500 if (GR_REG_CLASS_P (to))
08501 {
08502 if (TARGET_MIPS16)
08503 return 12;
08504 else
08505 return 6;
08506 }
08507 }
08508 else if (from == ST_REGS && GR_REG_CLASS_P (to))
08509 return 4;
08510 else if (COP_REG_CLASS_P (from))
08511 {
08512 return 5;
08513 }
08514
08515
08516
08517 return 12;
08518 }
08519
08520
08521
08522
08523 int
08524 mips_adjust_insn_length (rtx insn, int length)
08525 {
08526
08527
08528
08529 if (CALL_P (insn) || (TARGET_MIPS16 ? simplejump_p (insn) : JUMP_P (insn)))
08530 length += 4;
08531
08532
08533 if (!cfun->machine->ignore_hazard_length_p && INSN_CODE (insn) >= 0)
08534 switch (get_attr_hazard (insn))
08535 {
08536 case HAZARD_NONE:
08537 break;
08538
08539 case HAZARD_DELAY:
08540 length += 4;
08541 break;
08542
08543 case HAZARD_HILO:
08544 length += 8;
08545 break;
08546 }
08547
08548
08549 if (TARGET_MIPS16)
08550 length /= 2;
08551
08552 return length;
08553 }
08554
08555
08556
08557
08558
08559 const char *
08560 mips_output_load_label (void)
08561 {
08562 if (TARGET_EXPLICIT_RELOCS)
08563 switch (mips_abi)
08564 {
08565 case ABI_N32:
08566 return "%[lw\t%@,%%got_page(%0)(%+)\n\taddiu\t%@,%@,%%got_ofst(%0)";
08567
08568 case ABI_64:
08569 return "%[ld\t%@,%%got_page(%0)(%+)\n\tdaddiu\t%@,%@,%%got_ofst(%0)";
08570
08571 default:
08572 if (ISA_HAS_LOAD_DELAY)
08573 return "%[lw\t%@,%%got(%0)(%+)%#\n\taddiu\t%@,%@,%%lo(%0)";
08574 return "%[lw\t%@,%%got(%0)(%+)\n\taddiu\t%@,%@,%%lo(%0)";
08575 }
08576 else
08577 {
08578 if (Pmode == DImode)
08579 return "%[dla\t%@,%0";
08580 else
08581 return "%[la\t%@,%0";
08582 }
08583 }
08584
08585
08586
08587
08588
08589
08590
08591
08592
08593
08594
08595
08596
08597
08598
08599
08600 const char *
08601 mips_output_conditional_branch (rtx insn, rtx *operands, int two_operands_p,
08602 int float_p, int inverted_p, int length)
08603 {
08604 static char buffer[200];
08605
08606 enum rtx_code code = GET_CODE (operands[0]);
08607
08608
08609 int need_z_p;
08610
08611
08612 const char *op1 = "%z2";
08613
08614
08615
08616 const char *op2 = (two_operands_p ? ",%z3" : ",%.");
08617
08618 const char *const comp = (float_p ? "%F0" : "%C0");
08619
08620 const char *const inverted_comp = (float_p ? "%W0" : "%N0");
08621
08622
08623
08624
08625
08626 mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
08627
08628 if (!two_operands_p)
08629 {
08630
08631
08632
08633
08634
08635
08636 switch (code)
08637 {
08638 case GTU:
08639 code = NE;
08640 break;
08641
08642 case LEU:
08643 code = EQ;
08644 break;
08645
08646 case GEU:
08647
08648 code = EQ;
08649 op1 = "%.";
08650 break;
08651
08652 case LTU:
08653
08654 code = NE;
08655 op1 = "%.";
08656 break;
08657
08658 default:
08659
08660 break;
08661 }
08662 }
08663
08664
08665
08666
08667 need_z_p = (!float_p && code != EQ && code != NE);
08668
08669
08670 if (need_z_p)
08671 op2 = "";
08672
08673
08674
08675 buffer[0] = '\0';
08676
08677 switch (length)
08678 {
08679 case 4:
08680 case 8:
08681
08682 if (float_p)
08683 sprintf (buffer, "%%*b%s%%?\t%%Z2%%1%%/",
08684 inverted_p ? inverted_comp : comp);
08685 else
08686 sprintf (buffer, "%%*b%s%s%%?\t%s%s,%%1%%/",
08687 inverted_p ? inverted_comp : comp,
08688 need_z_p ? "z" : "",
08689 op1,
08690 op2);
08691 return buffer;
08692
08693 case 12:
08694 case 16:
08695 case 24:
08696 case 28:
08697 {
08698
08699
08700
08701
08702
08703
08704
08705
08706
08707
08708
08709
08710
08711
08712
08713
08714
08715
08716
08717
08718
08719
08720
08721
08722
08723
08724
08725
08726
08727
08728
08729
08730
08731
08732
08733
08734
08735
08736 rtx orig_target;
08737 rtx target = gen_label_rtx ();
08738
08739 orig_target = operands[1];
08740 operands[1] = target;
08741
08742
08743 if (float_p)
08744 sprintf (buffer, "%%*b%s\t%%Z2%%1",
08745 inverted_p ? comp : inverted_comp);
08746 else
08747 sprintf (buffer, "%%*b%s%s\t%s%s,%%1",
08748 inverted_p ? comp : inverted_comp,
08749 need_z_p ? "z" : "",
08750 op1,
08751 op2);
08752 output_asm_insn (buffer, operands);
08753
08754 if (length != 16 && length != 28 && ! mips_branch_likely)
08755 {
08756
08757 rtx insn = final_sequence;
08758 final_scan_insn (XVECEXP (insn, 0, 1), asm_out_file,
08759 optimize, 0, 1, NULL);
08760 INSN_DELETED_P (XVECEXP (insn, 0, 1)) = 1;
08761 }
08762 else
08763 output_asm_insn ("%#", 0);
08764
08765 if (length <= 16)
08766 output_asm_insn ("j\t%0", &orig_target);
08767 else
08768 {
08769 output_asm_insn (mips_output_load_label (), &orig_target);
08770 output_asm_insn ("jr\t%@%]", 0);
08771 }
08772
08773 if (length != 16 && length != 28 && mips_branch_likely)
08774 {
08775
08776 rtx insn = final_sequence;
08777 final_scan_insn (XVECEXP (insn, 0, 1), asm_out_file,
08778 optimize, 0, 1, NULL);
08779 INSN_DELETED_P (XVECEXP (insn, 0, 1)) = 1;
08780 }
08781 else
08782 output_asm_insn ("%#", 0);
08783
08784 (*targetm.asm_out.internal_label) (asm_out_file, "L",
08785 CODE_LABEL_NUMBER (target));
08786
08787 return "";
08788 }
08789
08790 default:
08791 gcc_unreachable ();
08792 }
08793
08794
08795 return 0;
08796 }
08797
08798
08799
08800
08801
08802
08803
08804
08805
08806
08807
08808
08809
08810
08811
08812
08813
08814
08815
08816
08817
08818
08819
08820
08821
08822
08823
08824
08825
08826
08827
08828
08829
08830
08831
08832
08833
08834
08835
08836
08837
08838
08839
08840
08841
08842
08843
08844
08845
08846
08847
08848
08849
08850
08851
08852
08853
08854
08855
08856
08857
08858
08859
08860
08861
08862
08863
08864
08865
08866
08867
08868
08869
08870
08871
08872
08873
08874
08875
08876
08877
08878
08879
08880
08881
08882
08883
08884
08885
08886
08887 const char *
08888 mips_output_division (const char *division, rtx *operands)
08889 {
08890 const char *s;
08891
08892 s = division;
08893 if (TARGET_FIX_R4000 || TARGET_FIX_R4400)
08894 {
08895 output_asm_insn (s, operands);
08896 s = "nop";
08897 }
08898 if (TARGET_CHECK_ZERO_DIV)
08899 {
08900 if (TARGET_MIPS16)
08901 {
08902 output_asm_insn (s, operands);
08903 s = "bnez\t%2,1f\n\tbreak\t7\n1:";
08904 }
08905 else if (GENERATE_DIVIDE_TRAPS)
08906 {
08907 output_asm_insn (s, operands);
08908 s = "teq\t%2,%.,7";
08909 }
08910 else
08911 {
08912 output_asm_insn ("%(bne\t%2,%.,1f", operands);
08913 output_asm_insn (s, operands);
08914 s = "break\t7%)\n1:";
08915 }
08916 }
08917 return s;
08918 }
08919
08920
08921
08922
08923
08924
08925 static bool
08926 mips_strict_matching_cpu_name_p (const char *canonical, const char *given)
08927 {
08928 while (*given != 0 && TOLOWER (*given) == TOLOWER (*canonical))
08929 given++, canonical++;
08930
08931 return ((*given == 0 && *canonical == 0)
08932 || (strcmp (canonical, "000") == 0 && strcasecmp (given, "k") == 0));
08933 }
08934
08935
08936
08937
08938
08939
08940
08941 static bool
08942 mips_matching_cpu_name_p (const char *canonical, const char *given)
08943 {
08944
08945
08946 if (mips_strict_matching_cpu_name_p (canonical, given))
08947 return true;
08948
08949
08950
08951 if (TOLOWER (*given) == 'r')
08952 given++;
08953 if (!ISDIGIT (*given))
08954 return false;
08955
08956
08957
08958 if (TOLOWER (canonical[0]) == 'v' && TOLOWER (canonical[1]) == 'r')
08959 canonical += 2;
08960 else if (TOLOWER (canonical[0]) == 'r' && TOLOWER (canonical[1]) == 'm')
08961 canonical += 2;
08962 else if (TOLOWER (canonical[0]) == 'r')
08963 canonical += 1;
08964
08965 return mips_strict_matching_cpu_name_p (canonical, given);
08966 }
08967
08968
08969
08970
08971
08972
08973
08974
08975
08976 static const struct mips_cpu_info *
08977 mips_parse_cpu (const char *option, const char *cpu_string)
08978 {
08979 const struct mips_cpu_info *p;
08980 const char *s;
08981
08982
08983
08984 for (s = cpu_string; *s != 0; s++)
08985 if (ISUPPER (*s))
08986 {
08987 warning ("the cpu name must be lower case");
08988 break;
08989 }
08990
08991
08992
08993
08994
08995
08996 if (strcasecmp (cpu_string, "from-abi") == 0)
08997 return mips_cpu_info_from_isa (ABI_NEEDS_32BIT_REGS ? 1
08998 : ABI_NEEDS_64BIT_REGS ? 3
08999 : (TARGET_64BIT ? 3 : 1));
09000
09001
09002 if (strcasecmp (cpu_string, "default") == 0)
09003 return 0;
09004
09005 for (p = mips_cpu_info_table; p->name != 0; p++)
09006 if (mips_matching_cpu_name_p (p->name, cpu_string))
09007 return p;
09008
09009 error ("bad value (%s) for %s", cpu_string, option);
09010 return 0;
09011 }
09012
09013
09014
09015
09016
09017 static const struct mips_cpu_info *
09018 mips_cpu_info_from_isa (int isa)
09019 {
09020 const struct mips_cpu_info *p;
09021
09022 for (p = mips_cpu_info_table; p->name != 0; p++)
09023 if (p->isa == isa)
09024 return p;
09025
09026 return 0;
09027 }
09028
09029
09030
09031
09032
09033
09034 unsigned int
09035 mips_hard_regno_nregs (int regno, enum machine_mode mode)
09036 {
09037 if (ST_REG_P (regno))
09038 return ((GET_MODE_SIZE (mode) + 3) / 4);
09039 else if (! FP_REG_P (regno))
09040 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
09041 else
09042 return ((GET_MODE_SIZE (mode) + UNITS_PER_FPREG - 1) / UNITS_PER_FPREG);
09043 }
09044
09045
09046
09047
09048
09049
09050
09051 static bool
09052 mips_return_in_memory (tree type, tree fndecl ATTRIBUTE_UNUSED)
09053 {
09054 if (TARGET_OLDABI)
09055 return (TYPE_MODE (type) == BLKmode);
09056 else
09057 return ((int_size_in_bytes (type) > (2 * UNITS_PER_WORD))
09058 || (int_size_in_bytes (type) == -1));
09059 }
09060
09061 static bool
09062 mips_strict_argument_naming (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED)
09063 {
09064 return !TARGET_OLDABI;
09065 }
09066
09067
09068
09069
09070 bool
09071 mips_linked_madd_p (rtx prev, rtx insn)
09072 {
09073 rtx x;
09074
09075 x = single_set (insn);
09076 if (x == 0)
09077 return false;
09078
09079 x = SET_SRC (x);
09080
09081 if (GET_CODE (x) == PLUS
09082 && GET_CODE (XEXP (x, 0)) == MULT
09083 && reg_set_p (XEXP (x, 1), prev))
09084 return true;
09085
09086 if (GET_CODE (x) == MINUS
09087 && GET_CODE (XEXP (x, 1)) == MULT
09088 && reg_set_p (XEXP (x, 0), prev))
09089 return true;
09090
09091 return false;
09092 }
09093
09094
09095
09096
09097 static rtx mips_macc_chains_last_hilo;
09098
09099
09100
09101
09102 static void
09103 mips_macc_chains_record (rtx insn)
09104 {
09105 if (get_attr_may_clobber_hilo (insn))
09106 mips_macc_chains_last_hilo = insn;
09107 }
09108
09109
09110
09111
09112
09113
09114
09115 static void
09116 mips_macc_chains_reorder (rtx *ready, int nready)
09117 {
09118 int i, j;
09119
09120 if (mips_macc_chains_last_hilo != 0)
09121 for (i = nready - 1; i >= 0; i--)
09122 if (mips_linked_madd_p (mips_macc_chains_last_hilo, ready[i]))
09123 {
09124 for (j = nready - 1; j > i; j--)
09125 if (recog_memoized (ready[j]) >= 0
09126 && get_attr_may_clobber_hilo (ready[j]))
09127 {
09128 mips_promote_ready (ready, i, j);
09129 break;
09130 }
09131 break;
09132 }
09133 }
09134
09135
09136
09137 static rtx vr4130_last_insn;
09138
09139
09140
09141
09142
09143 static void
09144 vr4130_true_reg_dependence_p_1 (rtx x, rtx pat ATTRIBUTE_UNUSED, void *data)
09145 {
09146 rtx *insn_ptr = data;
09147 if (REG_P (x)
09148 && *insn_ptr != 0
09149 && reg_referenced_p (x, PATTERN (*insn_ptr)))
09150 *insn_ptr = 0;
09151 }
09152
09153
09154
09155
09156 static bool
09157 vr4130_true_reg_dependence_p (rtx insn)
09158 {
09159 note_stores (PATTERN (vr4130_last_insn),
09160 vr4130_true_reg_dependence_p_1, &insn);
09161 return insn == 0;
09162 }
09163
09164
09165
09166
09167
09168
09169
09170
09171 static bool
09172 vr4130_swap_insns_p (rtx insn1, rtx insn2)
09173 {
09174 rtx dep;
09175
09176
09177
09178
09179
09180
09181
09182
09183
09184 for (dep = INSN_DEPEND (insn1); dep != 0; dep = XEXP (dep, 1))
09185 if (REG_NOTE_KIND (dep) == REG_DEP_ANTI
09186 && INSN_PRIORITY (XEXP (dep, 0)) > INSN_PRIORITY (insn2)
09187 && recog_memoized (XEXP (dep, 0)) >= 0
09188 && get_attr_vr4130_class (XEXP (dep, 0)) == VR4130_CLASS_ALU)
09189 return false;
09190
09191 if (vr4130_last_insn != 0
09192 && recog_memoized (insn1) >= 0
09193 && recog_memoized (insn2) >= 0)
09194 {
09195
09196
09197
09198 enum attr_vr4130_class class1 = get_attr_vr4130_class (insn1);
09199 enum attr_vr4130_class class2 = get_attr_vr4130_class (insn2);
09200 if (class1 != class2 || class1 == VR4130_CLASS_ALU)
09201 {
09202
09203
09204 bool dep1 = vr4130_true_reg_dependence_p (insn1);
09205 bool dep2 = vr4130_true_reg_dependence_p (insn2);
09206 if (dep1 != dep2)
09207 return dep1;
09208
09209
09210
09211
09212
09213 if (class1 != VR4130_CLASS_ALU
09214 && recog_memoized (vr4130_last_insn) >= 0
09215 && class1 == get_attr_vr4130_class (vr4130_last_insn))
09216 return true;
09217 }
09218 }
09219 return false;
09220 }
09221
09222
09223
09224
09225
09226 static void
09227 vr4130_reorder (rtx *ready, int nready)
09228 {
09229 if (vr4130_swap_insns_p (ready[nready - 1], ready[nready - 2]))
09230 mips_promote_ready (ready, nready - 2, nready - 1);
09231 }
09232
09233
09234
09235
09236
09237 static void
09238 mips_promote_ready (rtx *ready, int lower, int higher)
09239 {
09240 rtx new_head;
09241 int i;
09242
09243 new_head = ready[lower];
09244 for (i = lower; i < higher; i++)
09245 ready[i] = ready[i + 1];
09246 ready[i] = new_head;
09247 }
09248
09249
09250
09251 static int
09252 mips_sched_reorder (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
09253 rtx *ready, int *nreadyp, int cycle)
09254 {
09255 if (!reload_completed && TUNE_MACC_CHAINS)
09256 {
09257 if (cycle == 0)
09258 mips_macc_chains_last_hilo = 0;
09259 if (*nreadyp > 0)
09260 mips_macc_chains_reorder (ready, *nreadyp);
09261 }
09262 if (reload_completed && TUNE_MIPS4130 && !TARGET_VR4130_ALIGN)
09263 {
09264 if (cycle == 0)
09265 vr4130_last_insn = 0;
09266 if (*nreadyp > 1)
09267 vr4130_reorder (ready, *nreadyp);
09268 }
09269 return mips_issue_rate ();
09270 }
09271
09272
09273
09274 static int
09275 mips_variable_issue (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
09276 rtx insn, int more)
09277 {
09278 switch (GET_CODE (PATTERN (insn)))
09279 {
09280 case USE:
09281 case CLOBBER:
09282
09283 break;
09284
09285 default:
09286 more--;
09287 if (!reload_completed && TUNE_MACC_CHAINS)
09288 mips_macc_chains_record (insn);
09289 vr4130_last_insn = insn;
09290 break;
09291 }
09292 return more;
09293 }
09294
09295
09296
09297
09298 static int
09299 mips_adjust_cost (rtx insn ATTRIBUTE_UNUSED, rtx link,
09300 rtx dep ATTRIBUTE_UNUSED, int cost)
09301 {
09302 if (REG_NOTE_KIND (link) != 0)
09303 return 0;
09304 return cost;
09305 }
09306
09307
09308
09309 static int
09310 mips_issue_rate (void)
09311 {
09312 switch (mips_tune)
09313 {
09314 case PROCESSOR_R4130:
09315 case PROCESSOR_R5400:
09316 case PROCESSOR_R5500:
09317 case PROCESSOR_R7000:
09318 case PROCESSOR_R9000:
09319 return 2;
09320
09321 case PROCESSOR_SB1:
09322
09323
09324
09325
09326 return 3;
09327
09328 default:
09329 return 1;
09330 }
09331 }
09332
09333
09334
09335
09336 static int
09337 mips_multipass_dfa_lookahead (void)
09338 {
09339
09340 if (mips_tune == PROCESSOR_SB1)
09341 return 4;
09342
09343 return 0;
09344 }
09345
09346
09347
09348
09349 rtx
09350 mips_prefetch_cookie (rtx write, rtx locality)
09351 {
09352
09353 if (INTVAL (locality) <= 0)
09354 return GEN_INT (INTVAL (write) + 4);
09355
09356
09357 if (INTVAL (locality) <= 2)
09358 return write;
09359
09360
09361 return GEN_INT (INTVAL (write) + 6);
09362 }
09363
09364
09365
09366 struct builtin_description
09367 {
09368
09369
09370 enum insn_code icode;
09371
09372
09373 enum mips_fp_condition cond;
09374
09375
09376 const char *name;
09377
09378
09379 enum mips_builtin_type builtin_type;
09380
09381
09382 enum mips_function_type function_type;
09383
09384
09385 int target_flags;
09386 };
09387
09388
09389
09390 #define DIRECT_BUILTIN(INSN, FUNCTION_TYPE, TARGET_FLAGS) \
09391 { CODE_FOR_mips_ ## INSN, 0, "__builtin_mips_" #INSN, \
09392 MIPS_BUILTIN_DIRECT, FUNCTION_TYPE, TARGET_FLAGS }
09393
09394
09395
09396 #define CMP_SCALAR_BUILTINS(INSN, COND, TARGET_FLAGS) \
09397 { CODE_FOR_mips_ ## INSN ## _cond_s, MIPS_FP_COND_ ## COND, \
09398 "__builtin_mips_" #INSN "_" #COND "_s", \
09399 MIPS_BUILTIN_CMP_SINGLE, MIPS_INT_FTYPE_SF_SF, TARGET_FLAGS }, \
09400 { CODE_FOR_mips_ ## INSN ## _cond_d, MIPS_FP_COND_ ## COND, \
09401 "__builtin_mips_" #INSN "_" #COND "_d", \
09402 MIPS_BUILTIN_CMP_SINGLE, MIPS_INT_FTYPE_DF_DF, TARGET_FLAGS }
09403
09404
09405
09406
09407 #define CMP_PS_BUILTINS(INSN, COND, TARGET_FLAGS) \
09408 { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
09409 "__builtin_mips_any_" #INSN "_" #COND "_ps", \
09410 MIPS_BUILTIN_CMP_ANY, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D }, \
09411 { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
09412 "__builtin_mips_all_" #INSN "_" #COND "_ps", \
09413 MIPS_BUILTIN_CMP_ALL, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D }, \
09414 { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
09415 "__builtin_mips_lower_" #INSN "_" #COND "_ps", \
09416 MIPS_BUILTIN_CMP_LOWER, MIPS_INT_FTYPE_V2SF_V2SF, TARGET_FLAGS }, \
09417 { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
09418 "__builtin_mips_upper_" #INSN "_" #COND "_ps", \
09419 MIPS_BUILTIN_CMP_UPPER, MIPS_INT_FTYPE_V2SF_V2SF, TARGET_FLAGS }
09420
09421
09422
09423 #define CMP_4S_BUILTINS(INSN, COND) \
09424 { CODE_FOR_mips_ ## INSN ## _cond_4s, MIPS_FP_COND_ ## COND, \
09425 "__builtin_mips_any_" #INSN "_" #COND "_4s", \
09426 MIPS_BUILTIN_CMP_ANY, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF, \
09427 MASK_MIPS3D }, \
09428 { CODE_FOR_mips_ ## INSN ## _cond_4s, MIPS_FP_COND_ ## COND, \
09429 "__builtin_mips_all_" #INSN "_" #COND "_4s", \
09430 MIPS_BUILTIN_CMP_ALL, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF, \
09431 MASK_MIPS3D }
09432
09433
09434
09435 #define MOVTF_BUILTINS(INSN, COND, TARGET_FLAGS) \
09436 { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
09437 "__builtin_mips_movt_" #INSN "_" #COND "_ps", \
09438 MIPS_BUILTIN_MOVT, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF, \
09439 TARGET_FLAGS }, \
09440 { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
09441 "__builtin_mips_movf_" #INSN "_" #COND "_ps", \
09442 MIPS_BUILTIN_MOVF, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF, \
09443 TARGET_FLAGS }
09444
09445
09446 #define CMP_BUILTINS(COND) \
09447 MOVTF_BUILTINS (c, COND, MASK_PAIRED_SINGLE), \
09448 MOVTF_BUILTINS (cabs, COND, MASK_MIPS3D), \
09449 CMP_SCALAR_BUILTINS (cabs, COND, MASK_MIPS3D), \
09450 CMP_PS_BUILTINS (c, COND, MASK_PAIRED_SINGLE), \
09451 CMP_PS_BUILTINS (cabs, COND, MASK_MIPS3D), \
09452 CMP_4S_BUILTINS (c, COND), \
09453 CMP_4S_BUILTINS (cabs, COND)
09454
09455
09456 #define CODE_FOR_mips_abs_ps CODE_FOR_absv2sf2
09457
09458 static const struct builtin_description mips_bdesc[] =
09459 {
09460 DIRECT_BUILTIN (pll_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE),
09461 DIRECT_BUILTIN (pul_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE),
09462 DIRECT_BUILTIN (plu_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE),
09463 DIRECT_BUILTIN (puu_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE),
09464 DIRECT_BUILTIN (cvt_ps_s, MIPS_V2SF_FTYPE_SF_SF, MASK_PAIRED_SINGLE),
09465 DIRECT_BUILTIN (cvt_s_pl, MIPS_SF_FTYPE_V2SF, MASK_PAIRED_SINGLE),
09466 DIRECT_BUILTIN (cvt_s_pu, MIPS_SF_FTYPE_V2SF, MASK_PAIRED_SINGLE),
09467 DIRECT_BUILTIN (abs_ps, MIPS_V2SF_FTYPE_V2SF, MASK_PAIRED_SINGLE),
09468
09469 DIRECT_BUILTIN (alnv_ps, MIPS_V2SF_FTYPE_V2SF_V2SF_INT, MASK_PAIRED_SINGLE),
09470 DIRECT_BUILTIN (addr_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D),
09471 DIRECT_BUILTIN (mulr_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D),
09472 DIRECT_BUILTIN (cvt_pw_ps, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D),
09473 DIRECT_BUILTIN (cvt_ps_pw, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D),
09474
09475 DIRECT_BUILTIN (recip1_s, MIPS_SF_FTYPE_SF, MASK_MIPS3D),
09476 DIRECT_BUILTIN (recip1_d, MIPS_DF_FTYPE_DF, MASK_MIPS3D),
09477 DIRECT_BUILTIN (recip1_ps, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D),
09478 DIRECT_BUILTIN (recip2_s, MIPS_SF_FTYPE_SF_SF, MASK_MIPS3D),
09479 DIRECT_BUILTIN (recip2_d, MIPS_DF_FTYPE_DF_DF, MASK_MIPS3D),
09480 DIRECT_BUILTIN (recip2_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D),
09481
09482 DIRECT_BUILTIN (rsqrt1_s, MIPS_SF_FTYPE_SF, MASK_MIPS3D),
09483 DIRECT_BUILTIN (rsqrt1_d, MIPS_DF_FTYPE_DF, MASK_MIPS3D),
09484 DIRECT_BUILTIN (rsqrt1_ps, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D),
09485 DIRECT_BUILTIN (rsqrt2_s, MIPS_SF_FTYPE_SF_SF, MASK_MIPS3D),
09486 DIRECT_BUILTIN (rsqrt2_d, MIPS_DF_FTYPE_DF_DF, MASK_MIPS3D),
09487 DIRECT_BUILTIN (rsqrt2_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D),
09488
09489 MIPS_FP_CONDITIONS (CMP_BUILTINS)
09490 };
09491
09492
09493
09494 #define CODE_FOR_mips_sqrt_ps CODE_FOR_sqrtv2sf2
09495
09496 static const struct builtin_description sb1_bdesc[] =
09497 {
09498 DIRECT_BUILTIN (sqrt_ps, MIPS_V2SF_FTYPE_V2SF, MASK_PAIRED_SINGLE)
09499 };
09500
09501
09502
09503
09504 struct bdesc_map
09505 {
09506
09507 const struct builtin_description *bdesc;
09508
09509
09510 unsigned int size;
09511
09512
09513
09514 enum processor_type proc;
09515 };
09516
09517 static const struct bdesc_map bdesc_arrays[] =
09518 {
09519 { mips_bdesc, ARRAY_SIZE (mips_bdesc), PROCESSOR_DEFAULT },
09520 { sb1_bdesc, ARRAY_SIZE (sb1_bdesc), PROCESSOR_SB1 }
09521 };
09522
09523
09524
09525
09526
09527 static rtx
09528 mips_prepare_builtin_arg (enum insn_code icode,
09529 unsigned int op, tree *arglist)
09530 {
09531 rtx value;
09532 enum machine_mode mode;
09533
09534 value = expand_expr (TREE_VALUE (*arglist), NULL_RTX, VOIDmode, 0);
09535 mode = insn_data[icode].operand[op].mode;
09536 if (!insn_data[icode].operand[op].predicate (value, mode))
09537 value = copy_to_mode_reg (mode, value);
09538
09539 *arglist = TREE_CHAIN (*arglist);
09540 return value;
09541 }
09542
09543
09544
09545
09546 static rtx
09547 mips_prepare_builtin_target (enum insn_code icode, unsigned int op, rtx target)
09548 {
09549 enum machine_mode mode;
09550
09551 mode = insn_data[icode].operand[op].mode;
09552 if (target == 0 || !insn_data[icode].operand[op].predicate (target, mode))
09553 target = gen_reg_rtx (mode);
09554
09555 return target;
09556 }
09557
09558
09559
09560 rtx
09561 mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
09562 enum machine_mode mode ATTRIBUTE_UNUSED,
09563 int ignore ATTRIBUTE_UNUSED)
09564 {
09565 enum insn_code icode;
09566 enum mips_builtin_type type;
09567 tree fndecl, arglist;
09568 unsigned int fcode;
09569 const struct builtin_description *bdesc;
09570 const struct bdesc_map *m;
09571
09572 fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
09573 arglist = TREE_OPERAND (exp, 1);
09574 fcode = DECL_FUNCTION_CODE (fndecl);
09575
09576 bdesc = NULL;
09577 for (m = bdesc_arrays; m < &bdesc_arrays[ARRAY_SIZE (bdesc_arrays)]; m++)
09578 {
09579 if (fcode < m->size)
09580 {
09581 bdesc = m->bdesc;
09582 icode = bdesc[fcode].icode;
09583 type = bdesc[fcode].builtin_type;
09584 break;
09585 }
09586 fcode -= m->size;
09587 }
09588 if (bdesc == NULL)
09589 return 0;
09590
09591 switch (type)
09592 {
09593 case MIPS_BUILTIN_DIRECT:
09594 return mips_expand_builtin_direct (icode, target, arglist);
09595
09596 case MIPS_BUILTIN_MOVT:
09597 case MIPS_BUILTIN_MOVF:
09598 return mips_expand_builtin_movtf (type, icode, bdesc[fcode].cond,
09599 target, arglist);
09600
09601 case MIPS_BUILTIN_CMP_ANY:
09602 case MIPS_BUILTIN_CMP_ALL:
09603 case MIPS_BUILTIN_CMP_UPPER:
09604 case MIPS_BUILTIN_CMP_LOWER:
09605 case MIPS_BUILTIN_CMP_SINGLE:
09606 return mips_expand_builtin_compare (type, icode, bdesc[fcode].cond,
09607 target, arglist);
09608
09609 default:
09610 return 0;
09611 }
09612 }
09613
09614
09615
09616 void
09617 mips_init_builtins (void)
09618 {
09619 const struct builtin_description *d;
09620 const struct bdesc_map *m;
09621 tree types[(int) MIPS_MAX_FTYPE_MAX];
09622 tree V2SF_type_node;
09623 unsigned int offset;
09624
09625
09626 if (!TARGET_PAIRED_SINGLE_FLOAT)
09627 return;
09628
09629 V2SF_type_node = build_vector_type_for_mode (float_type_node, V2SFmode);
09630
09631 types[MIPS_V2SF_FTYPE_V2SF]
09632 = build_function_type_list (V2SF_type_node, V2SF_type_node, NULL_TREE);
09633
09634 types[MIPS_V2SF_FTYPE_V2SF_V2SF]
09635 = build_function_type_list (V2SF_type_node,
09636 V2SF_type_node, V2SF_type_node, NULL_TREE);
09637
09638 types[MIPS_V2SF_FTYPE_V2SF_V2SF_INT]
09639 = build_function_type_list (V2SF_type_node,
09640 V2SF_type_node, V2SF_type_node,
09641 integer_type_node, NULL_TREE);
09642
09643 types[MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF]
09644 = build_function_type_list (V2SF_type_node,
09645 V2SF_type_node, V2SF_type_node,
09646 V2SF_type_node, V2SF_type_node, NULL_TREE);
09647
09648 types[MIPS_V2SF_FTYPE_SF_SF]
09649 = build_function_type_list (V2SF_type_node,
09650 float_type_node, float_type_node, NULL_TREE);
09651
09652 types[MIPS_INT_FTYPE_V2SF_V2SF]
09653 = build_function_type_list (integer_type_node,
09654 V2SF_type_node, V2SF_type_node, NULL_TREE);
09655
09656 types[MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF]
09657 = build_function_type_list (integer_type_node,
09658 V2SF_type_node, V2SF_type_node,
09659 V2SF_type_node, V2SF_type_node, NULL_TREE);
09660
09661 types[MIPS_INT_FTYPE_SF_SF]
09662 = build_function_type_list (integer_type_node,
09663 float_type_node, float_type_node, NULL_TREE);
09664
09665 types[MIPS_INT_FTYPE_DF_DF]
09666 = build_function_type_list (integer_type_node,
09667 double_type_node, double_type_node, NULL_TREE);
09668
09669 types[MIPS_SF_FTYPE_V2SF]
09670 = build_function_type_list (float_type_node, V2SF_type_node, NULL_TREE);
09671
09672 types[MIPS_SF_FTYPE_SF]
09673 = build_function_type_list (float_type_node,
09674 float_type_node, NULL_TREE);
09675
09676 types[MIPS_SF_FTYPE_SF_SF]
09677 = build_function_type_list (float_type_node,
09678 float_type_node, float_type_node, NULL_TREE);
09679
09680 types[MIPS_DF_FTYPE_DF]
09681 = build_function_type_list (double_type_node,
09682 double_type_node, NULL_TREE);
09683
09684 types[MIPS_DF_FTYPE_DF_DF]
09685 = build_function_type_list (double_type_node,
09686 double_type_node, double_type_node, NULL_TREE);
09687
09688
09689
09690
09691 offset = 0;
09692 for (m = bdesc_arrays; m < &bdesc_arrays[ARRAY_SIZE (bdesc_arrays)]; m++)
09693 {
09694 if (m->proc == PROCESSOR_DEFAULT || (m->proc == mips_arch))
09695 for (d = m->bdesc; d < &m->bdesc[m->size]; d++)
09696 if ((d->target_flags & target_flags) == d->target_flags)
09697 lang_hooks.builtin_function (d->name, types[d->function_type],
09698 d - m->bdesc + offset,
09699 BUILT_IN_MD, NULL, NULL);
09700 offset += m->size;
09701 }
09702 }
09703
09704
09705
09706
09707
09708 static rtx
09709 mips_expand_builtin_direct (enum insn_code icode, rtx target, tree arglist)
09710 {
09711 rtx ops[MAX_RECOG_OPERANDS];
09712 int i;
09713
09714 target = mips_prepare_builtin_target (icode, 0, target);
09715 for (i = 1; i < insn_data[icode].n_operands; i++)
09716 ops[i] = mips_prepare_builtin_arg (icode, i, &arglist);
09717
09718 switch (insn_data[icode].n_operands)
09719 {
09720 case 2:
09721 emit_insn (GEN_FCN (icode) (target, ops[1]));
09722 break;
09723
09724 case 3:
09725 emit_insn (GEN_FCN (icode) (target, ops[1], ops[2]));
09726 break;
09727
09728 case 4:
09729 emit_insn (GEN_FCN (icode) (target, ops[1], ops[2], ops[3]));
09730 break;
09731
09732 default:
09733 gcc_unreachable ();
09734 }
09735 return target;
09736 }
09737
09738
09739
09740
09741
09742
09743
09744 static rtx
09745 mips_expand_builtin_movtf (enum mips_builtin_type type,
09746 enum insn_code icode, enum mips_fp_condition cond,
09747 rtx target, tree arglist)
09748 {
09749 rtx cmp_result, op0, op1;
09750
09751 cmp_result = mips_prepare_builtin_target (icode, 0, 0);
09752 op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
09753 op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
09754 emit_insn (GEN_FCN (icode) (cmp_result, op0, op1, GEN_INT (cond)));
09755
09756 icode = CODE_FOR_mips_cond_move_tf_ps;
09757 target = mips_prepare_builtin_target (icode, 0, target);
09758 if (type == MIPS_BUILTIN_MOVT)
09759 {
09760 op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
09761 op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
09762 }
09763 else
09764 {
09765 op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
09766 op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
09767 }
09768 emit_insn (gen_mips_cond_move_tf_ps (target, op0, op1, cmp_result));
09769 return target;
09770 }
09771
09772
09773
09774
09775
09776
09777 static rtx
09778 mips_expand_builtin_compare (enum mips_builtin_type builtin_type,
09779 enum insn_code icode, enum mips_fp_condition cond,
09780 rtx target, tree arglist)
09781 {
09782 rtx label1, label2, if_then_else;
09783 rtx pat, cmp_result, ops[MAX_RECOG_OPERANDS];
09784 rtx target_if_equal, target_if_unequal;
09785 int cmp_value, i;
09786
09787 if (target == 0 || GET_MODE (target) != SImode)
09788 target = gen_reg_rtx (SImode);
09789
09790
09791 cmp_result = mips_prepare_builtin_target (icode, 0, 0);
09792 for (i = 1; i < insn_data[icode].n_operands - 1; i++)
09793 ops[i] = mips_prepare_builtin_arg (icode, i, &arglist);
09794
09795 switch (insn_data[icode].n_operands)
09796 {
09797 case 4:
09798 pat = GEN_FCN (icode) (cmp_result, ops[1], ops[2], GEN_INT (cond));
09799 break;
09800
09801 case 6:
09802 pat = GEN_FCN (icode) (cmp_result, ops[1], ops[2],
09803 ops[3], ops[4], GEN_INT (cond));
09804 break;
09805
09806 default:
09807 gcc_unreachable ();
09808 }
09809
09810
09811
09812
09813
09814
09815
09816
09817
09818 if (builtin_type == MIPS_BUILTIN_CMP_ALL)
09819 {
09820 cmp_value = -1;
09821 target_if_equal = const1_rtx;
09822 target_if_unequal = const0_rtx;
09823 }
09824 else
09825 {
09826 cmp_value = 0;
09827 target_if_equal = const0_rtx;
09828 target_if_unequal = const1_rtx;
09829 if (builtin_type == MIPS_BUILTIN_CMP_UPPER)
09830 cmp_result = simplify_gen_subreg (CCmode, cmp_result, CCV2mode, 4);
09831 else if (builtin_type == MIPS_BUILTIN_CMP_LOWER)
09832 cmp_result = simplify_gen_subreg (CCmode, cmp_result, CCV2mode, 0);
09833 }
09834
09835
09836 emit_move_insn (target, target_if_equal);
09837
09838
09839 emit_insn (pat);
09840 label1 = gen_label_rtx ();
09841 label2 = gen_label_rtx ();
09842 if_then_else
09843 = gen_rtx_IF_THEN_ELSE (VOIDmode,
09844 gen_rtx_fmt_ee (NE, GET_MODE (cmp_result),
09845 cmp_result, GEN_INT (cmp_value)),
09846 gen_rtx_LABEL_REF (VOIDmode, label1), pc_rtx);
09847 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, if_then_else));
09848 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
09849 gen_rtx_LABEL_REF (VOIDmode, label2)));
09850 emit_barrier ();
09851 emit_label (label1);
09852
09853
09854 emit_move_insn (target, target_if_unequal);
09855 emit_label (label2);
09856
09857 return target;
09858 }
09859
09860 #include "gt-mips.h"