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 #include "bitmap.h"
00060
00061
00062 #define UNSPEC_ADDRESS_P(X) \
00063 (GET_CODE (X) == UNSPEC \
00064 && XINT (X, 1) >= UNSPEC_ADDRESS_FIRST \
00065 && XINT (X, 1) < UNSPEC_ADDRESS_FIRST + NUM_SYMBOL_TYPES)
00066
00067
00068 #define UNSPEC_ADDRESS(X) \
00069 XVECEXP (X, 0, 0)
00070
00071
00072 #define UNSPEC_ADDRESS_TYPE(X) \
00073 ((enum mips_symbol_type) (XINT (X, 1) - UNSPEC_ADDRESS_FIRST))
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 #define MIPS_MAX_FIRST_STACK_STEP (TARGET_MIPS16 ? 0x100 : 0x7ff0)
00085
00086
00087 #define USEFUL_INSN_P(INSN) \
00088 (INSN_P (INSN) \
00089 && GET_CODE (PATTERN (INSN)) != USE \
00090 && GET_CODE (PATTERN (INSN)) != CLOBBER \
00091 && GET_CODE (PATTERN (INSN)) != ADDR_VEC \
00092 && GET_CODE (PATTERN (INSN)) != ADDR_DIFF_VEC)
00093
00094
00095
00096 #define SEQ_BEGIN(INSN) \
00097 (INSN_P (INSN) && GET_CODE (PATTERN (INSN)) == SEQUENCE \
00098 ? XVECEXP (PATTERN (INSN), 0, 0) \
00099 : (INSN))
00100
00101
00102 #define SEQ_END(INSN) \
00103 (INSN_P (INSN) && GET_CODE (PATTERN (INSN)) == SEQUENCE \
00104 ? XVECEXP (PATTERN (INSN), 0, XVECLEN (PATTERN (INSN), 0) - 1) \
00105 : (INSN))
00106
00107
00108
00109 #define FOR_EACH_SUBINSN(SUBINSN, INSN) \
00110 for ((SUBINSN) = SEQ_BEGIN (INSN); \
00111 (SUBINSN) != NEXT_INSN (SEQ_END (INSN)); \
00112 (SUBINSN) = NEXT_INSN (SUBINSN))
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129 enum mips_address_type {
00130 ADDRESS_REG,
00131 ADDRESS_LO_SUM,
00132 ADDRESS_CONST_INT,
00133 ADDRESS_SYMBOLIC
00134 };
00135
00136
00137 enum mips_function_type
00138 {
00139 MIPS_V2SF_FTYPE_V2SF,
00140 MIPS_V2SF_FTYPE_V2SF_V2SF,
00141 MIPS_V2SF_FTYPE_V2SF_V2SF_INT,
00142 MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
00143 MIPS_V2SF_FTYPE_SF_SF,
00144 MIPS_INT_FTYPE_V2SF_V2SF,
00145 MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
00146 MIPS_INT_FTYPE_SF_SF,
00147 MIPS_INT_FTYPE_DF_DF,
00148 MIPS_SF_FTYPE_V2SF,
00149 MIPS_SF_FTYPE_SF,
00150 MIPS_SF_FTYPE_SF_SF,
00151 MIPS_DF_FTYPE_DF,
00152 MIPS_DF_FTYPE_DF_DF,
00153
00154
00155 MIPS_DI_FTYPE_DI_SI,
00156 MIPS_DI_FTYPE_DI_SI_SI,
00157 MIPS_DI_FTYPE_DI_V2HI_V2HI,
00158 MIPS_DI_FTYPE_DI_V4QI_V4QI,
00159 MIPS_SI_FTYPE_DI_SI,
00160 MIPS_SI_FTYPE_PTR_SI,
00161 MIPS_SI_FTYPE_SI,
00162 MIPS_SI_FTYPE_SI_SI,
00163 MIPS_SI_FTYPE_V2HI,
00164 MIPS_SI_FTYPE_V2HI_V2HI,
00165 MIPS_SI_FTYPE_V4QI,
00166 MIPS_SI_FTYPE_V4QI_V4QI,
00167 MIPS_SI_FTYPE_VOID,
00168 MIPS_V2HI_FTYPE_SI,
00169 MIPS_V2HI_FTYPE_SI_SI,
00170 MIPS_V2HI_FTYPE_V2HI,
00171 MIPS_V2HI_FTYPE_V2HI_SI,
00172 MIPS_V2HI_FTYPE_V2HI_V2HI,
00173 MIPS_V2HI_FTYPE_V4QI,
00174 MIPS_V2HI_FTYPE_V4QI_V2HI,
00175 MIPS_V4QI_FTYPE_SI,
00176 MIPS_V4QI_FTYPE_V2HI_V2HI,
00177 MIPS_V4QI_FTYPE_V4QI_SI,
00178 MIPS_V4QI_FTYPE_V4QI_V4QI,
00179 MIPS_VOID_FTYPE_SI_SI,
00180 MIPS_VOID_FTYPE_V2HI_V2HI,
00181 MIPS_VOID_FTYPE_V4QI_V4QI,
00182
00183
00184 MIPS_MAX_FTYPE_MAX
00185 };
00186
00187
00188 enum mips_builtin_type
00189 {
00190
00191
00192
00193 MIPS_BUILTIN_DIRECT,
00194
00195
00196
00197 MIPS_BUILTIN_DIRECT_NO_TARGET,
00198
00199
00200
00201
00202
00203 MIPS_BUILTIN_MOVF,
00204 MIPS_BUILTIN_MOVT,
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 MIPS_BUILTIN_CMP_ANY,
00217 MIPS_BUILTIN_CMP_ALL,
00218 MIPS_BUILTIN_CMP_UPPER,
00219 MIPS_BUILTIN_CMP_LOWER,
00220
00221
00222 MIPS_BUILTIN_CMP_SINGLE,
00223
00224
00225 MIPS_BUILTIN_BPOSGE32
00226 };
00227
00228
00229 #define MIPS_FP_CONDITIONS(MACRO) \
00230 MACRO (f), \
00231 MACRO (un), \
00232 MACRO (eq), \
00233 MACRO (ueq), \
00234 MACRO (olt), \
00235 MACRO (ult), \
00236 MACRO (ole), \
00237 MACRO (ule), \
00238 MACRO (sf), \
00239 MACRO (ngle), \
00240 MACRO (seq), \
00241 MACRO (ngl), \
00242 MACRO (lt), \
00243 MACRO (nge), \
00244 MACRO (le), \
00245 MACRO (ngt)
00246
00247
00248 #define DECLARE_MIPS_COND(X) MIPS_FP_COND_ ## X
00249 enum mips_fp_condition {
00250 MIPS_FP_CONDITIONS (DECLARE_MIPS_COND)
00251 };
00252
00253
00254 #define STRINGIFY(X) #X
00255 static const char *const mips_fp_conditions[] = {
00256 MIPS_FP_CONDITIONS (STRINGIFY)
00257 };
00258
00259
00260
00261 typedef void (*mips_save_restore_fn) (rtx, rtx);
00262
00263 struct mips16_constant;
00264 struct mips_arg_info;
00265 struct mips_address_info;
00266 struct mips_integer_op;
00267 struct mips_sim;
00268
00269 static enum mips_symbol_type mips_classify_symbol (rtx);
00270 static void mips_split_const (rtx, rtx *, HOST_WIDE_INT *);
00271 static bool mips_offset_within_object_p (rtx, HOST_WIDE_INT);
00272 static bool mips_valid_base_register_p (rtx, enum machine_mode, int);
00273 static bool mips_symbolic_address_p (enum mips_symbol_type, enum machine_mode);
00274 static bool mips_classify_address (struct mips_address_info *, rtx,
00275 enum machine_mode, int);
00276 static bool mips_cannot_force_const_mem (rtx);
00277 static bool mips_use_blocks_for_constant_p (enum machine_mode, rtx);
00278 static int mips_symbol_insns (enum mips_symbol_type);
00279 static bool mips16_unextended_reference_p (enum machine_mode mode, rtx, rtx);
00280 static rtx mips_force_temporary (rtx, rtx);
00281 static rtx mips_unspec_offset_high (rtx, rtx, rtx, enum mips_symbol_type);
00282 static rtx mips_add_offset (rtx, rtx, HOST_WIDE_INT);
00283 static unsigned int mips_build_shift (struct mips_integer_op *, HOST_WIDE_INT);
00284 static unsigned int mips_build_lower (struct mips_integer_op *,
00285 unsigned HOST_WIDE_INT);
00286 static unsigned int mips_build_integer (struct mips_integer_op *,
00287 unsigned HOST_WIDE_INT);
00288 static void mips_legitimize_const_move (enum machine_mode, rtx, rtx);
00289 static int m16_check_op (rtx, int, int, int);
00290 static bool mips_rtx_costs (rtx, int, int, int *);
00291 static int mips_address_cost (rtx);
00292 static void mips_emit_compare (enum rtx_code *, rtx *, rtx *, bool);
00293 static void mips_load_call_address (rtx, rtx, int);
00294 static bool mips_function_ok_for_sibcall (tree, tree);
00295 static void mips_block_move_straight (rtx, rtx, HOST_WIDE_INT);
00296 static void mips_adjust_block_mem (rtx, HOST_WIDE_INT, rtx *, rtx *);
00297 static void mips_block_move_loop (rtx, rtx, HOST_WIDE_INT);
00298 static void mips_arg_info (const CUMULATIVE_ARGS *, enum machine_mode,
00299 tree, int, struct mips_arg_info *);
00300 static bool mips_get_unaligned_mem (rtx *, unsigned int, int, rtx *, rtx *);
00301 static void mips_set_architecture (const struct mips_cpu_info *);
00302 static void mips_set_tune (const struct mips_cpu_info *);
00303 static bool mips_handle_option (size_t, const char *, int);
00304 static struct machine_function *mips_init_machine_status (void);
00305 static void print_operand_reloc (FILE *, rtx, const char **);
00306 #if TARGET_IRIX
00307 static void irix_output_external_libcall (rtx);
00308 #endif
00309 static void mips_file_start (void);
00310 static void mips_file_end (void);
00311 static bool mips_rewrite_small_data_p (rtx);
00312 static int mips_small_data_pattern_1 (rtx *, void *);
00313 static int mips_rewrite_small_data_1 (rtx *, void *);
00314 static bool mips_function_has_gp_insn (void);
00315 static unsigned int mips_global_pointer (void);
00316 static bool mips_save_reg_p (unsigned int);
00317 static void mips_save_restore_reg (enum machine_mode, int, HOST_WIDE_INT,
00318 mips_save_restore_fn);
00319 static void mips_for_each_saved_reg (HOST_WIDE_INT, mips_save_restore_fn);
00320 static void mips_output_cplocal (void);
00321 static void mips_emit_loadgp (void);
00322 static void mips_output_function_prologue (FILE *, HOST_WIDE_INT);
00323 static void mips_set_frame_expr (rtx);
00324 static rtx mips_frame_set (rtx, rtx);
00325 static void mips_save_reg (rtx, rtx);
00326 static void mips_output_function_epilogue (FILE *, HOST_WIDE_INT);
00327 static void mips_restore_reg (rtx, rtx);
00328 static void mips_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
00329 HOST_WIDE_INT, tree);
00330 static int symbolic_expression_p (rtx);
00331 static section *mips_select_rtx_section (enum machine_mode, rtx,
00332 unsigned HOST_WIDE_INT);
00333 static section *mips_function_rodata_section (tree);
00334 static bool mips_in_small_data_p (tree);
00335 static bool mips_use_anchors_for_symbol_p (rtx);
00336 static int mips_fpr_return_fields (tree, tree *);
00337 static bool mips_return_in_msb (tree);
00338 static rtx mips_return_fpr_pair (enum machine_mode mode,
00339 enum machine_mode mode1, HOST_WIDE_INT,
00340 enum machine_mode mode2, HOST_WIDE_INT);
00341 static rtx mips16_gp_pseudo_reg (void);
00342 static void mips16_fp_args (FILE *, int, int);
00343 static void build_mips16_function_stub (FILE *);
00344 static rtx dump_constants_1 (enum machine_mode, rtx, rtx);
00345 static void dump_constants (struct mips16_constant *, rtx);
00346 static int mips16_insn_length (rtx);
00347 static int mips16_rewrite_pool_refs (rtx *, void *);
00348 static void mips16_lay_out_constants (void);
00349 static void mips_sim_reset (struct mips_sim *);
00350 static void mips_sim_init (struct mips_sim *, state_t);
00351 static void mips_sim_next_cycle (struct mips_sim *);
00352 static void mips_sim_wait_reg (struct mips_sim *, rtx, rtx);
00353 static int mips_sim_wait_regs_2 (rtx *, void *);
00354 static void mips_sim_wait_regs_1 (rtx *, void *);
00355 static void mips_sim_wait_regs (struct mips_sim *, rtx);
00356 static void mips_sim_wait_units (struct mips_sim *, rtx);
00357 static void mips_sim_wait_insn (struct mips_sim *, rtx);
00358 static void mips_sim_record_set (rtx, rtx, void *);
00359 static void mips_sim_issue_insn (struct mips_sim *, rtx);
00360 static void mips_sim_issue_nop (struct mips_sim *);
00361 static void mips_sim_finish_insn (struct mips_sim *, rtx);
00362 static void vr4130_avoid_branch_rt_conflict (rtx);
00363 static void vr4130_align_insns (void);
00364 static void mips_avoid_hazard (rtx, rtx, int *, rtx *, rtx);
00365 static void mips_avoid_hazards (void);
00366 static void mips_reorg (void);
00367 static bool mips_strict_matching_cpu_name_p (const char *, const char *);
00368 static bool mips_matching_cpu_name_p (const char *, const char *);
00369 static const struct mips_cpu_info *mips_parse_cpu (const char *);
00370 static const struct mips_cpu_info *mips_cpu_info_from_isa (int);
00371 static bool mips_return_in_memory (tree, tree);
00372 static bool mips_strict_argument_naming (CUMULATIVE_ARGS *);
00373 static void mips_macc_chains_record (rtx);
00374 static void mips_macc_chains_reorder (rtx *, int);
00375 static void vr4130_true_reg_dependence_p_1 (rtx, rtx, void *);
00376 static bool vr4130_true_reg_dependence_p (rtx);
00377 static bool vr4130_swap_insns_p (rtx, rtx);
00378 static void vr4130_reorder (rtx *, int);
00379 static void mips_promote_ready (rtx *, int, int);
00380 static int mips_sched_reorder (FILE *, int, rtx *, int *, int);
00381 static int mips_variable_issue (FILE *, int, rtx, int);
00382 static int mips_adjust_cost (rtx, rtx, rtx, int);
00383 static int mips_issue_rate (void);
00384 static int mips_multipass_dfa_lookahead (void);
00385 static void mips_init_libfuncs (void);
00386 static void mips_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
00387 tree, int *, int);
00388 static tree mips_build_builtin_va_list (void);
00389 static tree mips_gimplify_va_arg_expr (tree, tree, tree *, tree *);
00390 static bool mips_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode mode,
00391 tree, bool);
00392 static bool mips_callee_copies (CUMULATIVE_ARGS *, enum machine_mode mode,
00393 tree, bool);
00394 static int mips_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode mode,
00395 tree, bool);
00396 static bool mips_valid_pointer_mode (enum machine_mode);
00397 static bool mips_vector_mode_supported_p (enum machine_mode);
00398 static rtx mips_prepare_builtin_arg (enum insn_code, unsigned int, tree *);
00399 static rtx mips_prepare_builtin_target (enum insn_code, unsigned int, rtx);
00400 static rtx mips_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
00401 static void mips_init_builtins (void);
00402 static rtx mips_expand_builtin_direct (enum insn_code, rtx, tree, bool);
00403 static rtx mips_expand_builtin_movtf (enum mips_builtin_type,
00404 enum insn_code, enum mips_fp_condition,
00405 rtx, tree);
00406 static rtx mips_expand_builtin_compare (enum mips_builtin_type,
00407 enum insn_code, enum mips_fp_condition,
00408 rtx, tree);
00409 static rtx mips_expand_builtin_bposge (enum mips_builtin_type, rtx);
00410 static void mips_encode_section_info (tree, rtx, int);
00411 static void mips_extra_live_on_entry (bitmap);
00412 static int mips_mode_rep_extended (enum machine_mode, enum machine_mode);
00413
00414
00415
00416
00417 struct mips_frame_info GTY(())
00418 {
00419 HOST_WIDE_INT total_size;
00420 HOST_WIDE_INT var_size;
00421 HOST_WIDE_INT args_size;
00422 HOST_WIDE_INT cprestore_size;
00423 HOST_WIDE_INT gp_reg_size;
00424 HOST_WIDE_INT fp_reg_size;
00425 unsigned int mask;
00426 unsigned int fmask;
00427 HOST_WIDE_INT gp_save_offset;
00428 HOST_WIDE_INT fp_save_offset;
00429 HOST_WIDE_INT gp_sp_offset;
00430 HOST_WIDE_INT fp_sp_offset;
00431 bool initialized;
00432 int num_gp;
00433 int num_fp;
00434 };
00435
00436 struct machine_function GTY(()) {
00437
00438
00439 rtx mips16_gp_pseudo_rtx;
00440
00441
00442
00443 int varargs_size;
00444
00445
00446 struct mips_frame_info frame;
00447
00448
00449 unsigned int global_pointer;
00450
00451
00452
00453 bool ignore_hazard_length_p;
00454
00455
00456
00457 bool all_noreorder_p;
00458
00459
00460 bool has_gp_insn_p;
00461 };
00462
00463
00464 struct mips_arg_info
00465 {
00466
00467
00468 bool fpr_p;
00469
00470
00471 unsigned int reg_words;
00472
00473
00474
00475
00476
00477
00478
00479
00480 unsigned int reg_offset;
00481
00482
00483 unsigned int stack_words;
00484
00485
00486
00487 unsigned int stack_offset;
00488 };
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507 struct mips_address_info
00508 {
00509 enum mips_address_type type;
00510 rtx reg;
00511 rtx offset;
00512 enum mips_symbol_type symbol_type;
00513 };
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526 struct mips_integer_op {
00527 enum rtx_code code;
00528 unsigned HOST_WIDE_INT value;
00529 };
00530
00531
00532
00533
00534
00535
00536 #define MIPS_MAX_INTEGER_OPS 7
00537
00538
00539
00540
00541
00542
00543 int mips_section_threshold = -1;
00544
00545
00546 int num_source_filenames = 0;
00547
00548
00549
00550 int sdb_label_count = 0;
00551
00552
00553 int sym_lineno = 0;
00554
00555
00556
00557
00558
00559 struct extern_list GTY (())
00560 {
00561 struct extern_list *next;
00562 const char *name;
00563 int size;
00564 };
00565
00566 static GTY (()) struct extern_list *extern_head = 0;
00567
00568
00569 const char *current_function_file = "";
00570
00571
00572 int set_noreorder;
00573 int set_noat;
00574 int set_nomacro;
00575 int set_volatile;
00576
00577
00578 int mips_branch_likely;
00579
00580
00581 rtx cmp_operands[2];
00582
00583
00584 enum processor_type mips_arch;
00585 const struct mips_cpu_info *mips_arch_info;
00586
00587
00588 enum processor_type mips_tune;
00589 const struct mips_cpu_info *mips_tune_info;
00590
00591
00592 int mips_isa;
00593
00594
00595 int mips_abi = MIPS_ABI_DEFAULT;
00596
00597
00598 const struct mips_rtx_cost_data *mips_cost;
00599
00600
00601
00602
00603
00604 int mips16_hard_float;
00605
00606
00607 static const struct mips_cpu_info *mips_isa_info;
00608
00609
00610 int mips_split_addresses;
00611
00612
00613 static enum machine_mode gpr_mode;
00614
00615
00616
00617 char mips_hard_regno_mode_ok[(int)MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER];
00618
00619
00620 char mips_print_operand_punct[256];
00621
00622
00623 int mips_dbx_regno[FIRST_PSEUDO_REGISTER];
00624
00625
00626 static int mips_flag_delayed_branch;
00627
00628 static GTY (()) int mips_output_filename_first_time = 1;
00629
00630
00631
00632 bool mips_split_p[NUM_SYMBOL_TYPES];
00633
00634
00635
00636
00637 static const char *mips_lo_relocs[NUM_SYMBOL_TYPES];
00638
00639
00640 static const char *mips_hi_relocs[NUM_SYMBOL_TYPES];
00641
00642
00643 const enum reg_class mips_regno_to_class[] =
00644 {
00645 LEA_REGS, LEA_REGS, M16_NA_REGS, V1_REG,
00646 M16_REGS, M16_REGS, M16_REGS, M16_REGS,
00647 LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS,
00648 LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS,
00649 M16_NA_REGS, M16_NA_REGS, LEA_REGS, LEA_REGS,
00650 LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS,
00651 T_REG, PIC_FN_ADDR_REG, LEA_REGS, LEA_REGS,
00652 LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS,
00653 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00654 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00655 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00656 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00657 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00658 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00659 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00660 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00661 HI_REG, LO_REG, NO_REGS, ST_REGS,
00662 ST_REGS, ST_REGS, ST_REGS, ST_REGS,
00663 ST_REGS, ST_REGS, ST_REGS, NO_REGS,
00664 NO_REGS, ALL_REGS, ALL_REGS, NO_REGS,
00665 COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
00666 COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
00667 COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
00668 COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
00669 COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
00670 COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
00671 COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
00672 COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
00673 COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
00674 COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
00675 COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
00676 COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
00677 COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
00678 COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
00679 COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
00680 COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
00681 COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
00682 COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
00683 COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
00684 COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
00685 COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
00686 COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
00687 COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
00688 COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
00689 DSP_ACC_REGS, DSP_ACC_REGS, DSP_ACC_REGS, DSP_ACC_REGS,
00690 DSP_ACC_REGS, DSP_ACC_REGS, ALL_REGS, ALL_REGS,
00691 ALL_REGS, ALL_REGS, ALL_REGS, ALL_REGS
00692 };
00693
00694
00695 const struct attribute_spec mips_attribute_table[] =
00696 {
00697 { "long_call", 0, 0, false, true, true, NULL },
00698 { NULL, 0, 0, false, false, false, NULL }
00699 };
00700
00701
00702
00703
00704
00705
00706
00707 const struct mips_cpu_info mips_cpu_info_table[] = {
00708
00709 { "mips1", PROCESSOR_R3000, 1 },
00710 { "mips2", PROCESSOR_R6000, 2 },
00711 { "mips3", PROCESSOR_R4000, 3 },
00712 { "mips4", PROCESSOR_R8000, 4 },
00713 { "mips32", PROCESSOR_4KC, 32 },
00714 { "mips32r2", PROCESSOR_M4K, 33 },
00715 { "mips64", PROCESSOR_5KC, 64 },
00716
00717
00718 { "r3000", PROCESSOR_R3000, 1 },
00719 { "r2000", PROCESSOR_R3000, 1 },
00720 { "r3900", PROCESSOR_R3900, 1 },
00721
00722
00723 { "r6000", PROCESSOR_R6000, 2 },
00724
00725
00726 { "r4000", PROCESSOR_R4000, 3 },
00727 { "vr4100", PROCESSOR_R4100, 3 },
00728 { "vr4111", PROCESSOR_R4111, 3 },
00729 { "vr4120", PROCESSOR_R4120, 3 },
00730 { "vr4130", PROCESSOR_R4130, 3 },
00731 { "vr4300", PROCESSOR_R4300, 3 },
00732 { "r4400", PROCESSOR_R4000, 3 },
00733 { "r4600", PROCESSOR_R4600, 3 },
00734 { "orion", PROCESSOR_R4600, 3 },
00735 { "r4650", PROCESSOR_R4650, 3 },
00736
00737
00738 { "r8000", PROCESSOR_R8000, 4 },
00739 { "vr5000", PROCESSOR_R5000, 4 },
00740 { "vr5400", PROCESSOR_R5400, 4 },
00741 { "vr5500", PROCESSOR_R5500, 4 },
00742 { "rm7000", PROCESSOR_R7000, 4 },
00743 { "rm9000", PROCESSOR_R9000, 4 },
00744
00745
00746 { "4kc", PROCESSOR_4KC, 32 },
00747 { "4km", PROCESSOR_4KC, 32 },
00748 { "4kp", PROCESSOR_4KP, 32 },
00749
00750
00751 { "m4k", PROCESSOR_M4K, 33 },
00752 { "24k", PROCESSOR_24K, 33 },
00753 { "24kc", PROCESSOR_24K, 33 },
00754 { "24kf", PROCESSOR_24K, 33 },
00755 { "24kx", PROCESSOR_24KX, 33 },
00756
00757
00758 { "5kc", PROCESSOR_5KC, 64 },
00759 { "5kf", PROCESSOR_5KF, 64 },
00760 { "20kc", PROCESSOR_20KC, 64 },
00761 { "sb1", PROCESSOR_SB1, 64 },
00762 { "sb1a", PROCESSOR_SB1A, 64 },
00763 { "sr71000", PROCESSOR_SR71000, 64 },
00764
00765
00766 { 0, 0, 0 }
00767 };
00768
00769
00770
00771 #define DEFAULT_COSTS COSTS_N_INSNS (6), \
00772 COSTS_N_INSNS (7), \
00773 COSTS_N_INSNS (8), \
00774 COSTS_N_INSNS (23), \
00775 COSTS_N_INSNS (36), \
00776 COSTS_N_INSNS (10), \
00777 COSTS_N_INSNS (10), \
00778 COSTS_N_INSNS (69), \
00779 COSTS_N_INSNS (69), \
00780 2, \
00781 4
00782
00783
00784
00785 #define SOFT_FP_COSTS COSTS_N_INSNS (256), \
00786 COSTS_N_INSNS (256), \
00787 COSTS_N_INSNS (256), \
00788 COSTS_N_INSNS (256), \
00789 COSTS_N_INSNS (256)
00790
00791 static struct mips_rtx_cost_data const mips_rtx_cost_data[PROCESSOR_MAX] =
00792 {
00793 {
00794 COSTS_N_INSNS (2),
00795 COSTS_N_INSNS (4),
00796 COSTS_N_INSNS (5),
00797 COSTS_N_INSNS (12),
00798 COSTS_N_INSNS (19),
00799 COSTS_N_INSNS (12),
00800 COSTS_N_INSNS (12),
00801 COSTS_N_INSNS (35),
00802 COSTS_N_INSNS (35),
00803 1,
00804 4
00805
00806 },
00807 {
00808 SOFT_FP_COSTS,
00809 COSTS_N_INSNS (6),
00810 COSTS_N_INSNS (6),
00811 COSTS_N_INSNS (36),
00812 COSTS_N_INSNS (36),
00813 1,
00814 4
00815 },
00816 {
00817 SOFT_FP_COSTS,
00818 COSTS_N_INSNS (36),
00819 COSTS_N_INSNS (36),
00820 COSTS_N_INSNS (37),
00821 COSTS_N_INSNS (37),
00822 1,
00823 4
00824 },
00825 {
00826 SOFT_FP_COSTS,
00827 COSTS_N_INSNS (4),
00828 COSTS_N_INSNS (11),
00829 COSTS_N_INSNS (36),
00830 COSTS_N_INSNS (68),
00831 1,
00832 4
00833 },
00834 {
00835 COSTS_N_INSNS (4),
00836 COSTS_N_INSNS (4),
00837 COSTS_N_INSNS (5),
00838 COSTS_N_INSNS (17),
00839 COSTS_N_INSNS (32),
00840 COSTS_N_INSNS (4),
00841 COSTS_N_INSNS (11),
00842 COSTS_N_INSNS (36),
00843 COSTS_N_INSNS (68),
00844 1,
00845 4
00846 },
00847 {
00848 DEFAULT_COSTS
00849 },
00850 {
00851 COSTS_N_INSNS (8),
00852 COSTS_N_INSNS (8),
00853 COSTS_N_INSNS (10),
00854 COSTS_N_INSNS (34),
00855 COSTS_N_INSNS (64),
00856 COSTS_N_INSNS (5),
00857 COSTS_N_INSNS (5),
00858 COSTS_N_INSNS (41),
00859 COSTS_N_INSNS (41),
00860 1,
00861 4
00862 },
00863 {
00864 COSTS_N_INSNS (4),
00865 COSTS_N_INSNS (4),
00866 COSTS_N_INSNS (5),
00867 COSTS_N_INSNS (17),
00868 COSTS_N_INSNS (32),
00869 COSTS_N_INSNS (5),
00870 COSTS_N_INSNS (5),
00871 COSTS_N_INSNS (41),
00872 COSTS_N_INSNS (41),
00873 1,
00874 4
00875 },
00876 {
00877 DEFAULT_COSTS
00878 },
00879 {
00880 COSTS_N_INSNS (2),
00881 COSTS_N_INSNS (4),
00882 COSTS_N_INSNS (5),
00883 COSTS_N_INSNS (12),
00884 COSTS_N_INSNS (19),
00885 COSTS_N_INSNS (2),
00886 COSTS_N_INSNS (2),
00887 COSTS_N_INSNS (35),
00888 COSTS_N_INSNS (35),
00889 1,
00890 4
00891 },
00892 {
00893 COSTS_N_INSNS (3),
00894 COSTS_N_INSNS (5),
00895 COSTS_N_INSNS (6),
00896 COSTS_N_INSNS (15),
00897 COSTS_N_INSNS (16),
00898 COSTS_N_INSNS (17),
00899 COSTS_N_INSNS (17),
00900 COSTS_N_INSNS (38),
00901 COSTS_N_INSNS (38),
00902 2,
00903 6
00904 },
00905 {
00906 COSTS_N_INSNS (6),
00907 COSTS_N_INSNS (7),
00908 COSTS_N_INSNS (8),
00909 COSTS_N_INSNS (23),
00910 COSTS_N_INSNS (36),
00911 COSTS_N_INSNS (10),
00912 COSTS_N_INSNS (10),
00913 COSTS_N_INSNS (69),
00914 COSTS_N_INSNS (69),
00915 2,
00916 6
00917 },
00918 {
00919 DEFAULT_COSTS
00920 },
00921 {
00922 DEFAULT_COSTS
00923 },
00924 {
00925 DEFAULT_COSTS
00926 },
00927 {
00928
00929
00930 SOFT_FP_COSTS,
00931 COSTS_N_INSNS (4),
00932 COSTS_N_INSNS (6),
00933 COSTS_N_INSNS (69),
00934 COSTS_N_INSNS (69),
00935 1,
00936 4
00937 },
00938 {
00939 DEFAULT_COSTS
00940 },
00941 {
00942 DEFAULT_COSTS
00943 },
00944 {
00945 DEFAULT_COSTS
00946 },
00947 {
00948 COSTS_N_INSNS (6),
00949 COSTS_N_INSNS (4),
00950 COSTS_N_INSNS (5),
00951 COSTS_N_INSNS (23),
00952 COSTS_N_INSNS (36),
00953 COSTS_N_INSNS (5),
00954 COSTS_N_INSNS (5),
00955 COSTS_N_INSNS (36),
00956 COSTS_N_INSNS (36),
00957 1,
00958 4
00959 },
00960 {
00961 COSTS_N_INSNS (6),
00962 COSTS_N_INSNS (5),
00963 COSTS_N_INSNS (6),
00964 COSTS_N_INSNS (30),
00965 COSTS_N_INSNS (59),
00966 COSTS_N_INSNS (3),
00967 COSTS_N_INSNS (4),
00968 COSTS_N_INSNS (42),
00969 COSTS_N_INSNS (74),
00970 1,
00971 4
00972 },
00973 {
00974 COSTS_N_INSNS (6),
00975 COSTS_N_INSNS (5),
00976 COSTS_N_INSNS (6),
00977 COSTS_N_INSNS (30),
00978 COSTS_N_INSNS (59),
00979 COSTS_N_INSNS (5),
00980 COSTS_N_INSNS (9),
00981 COSTS_N_INSNS (42),
00982 COSTS_N_INSNS (74),
00983 1,
00984 4
00985 },
00986 {
00987
00988
00989 COSTS_N_INSNS (6),
00990 COSTS_N_INSNS (7),
00991 COSTS_N_INSNS (8),
00992 COSTS_N_INSNS (23),
00993 COSTS_N_INSNS (36),
00994 COSTS_N_INSNS (5),
00995 COSTS_N_INSNS (9),
00996 COSTS_N_INSNS (69),
00997 COSTS_N_INSNS (69),
00998 1,
00999 4
01000 },
01001 {
01002 DEFAULT_COSTS
01003 },
01004 {
01005
01006
01007 COSTS_N_INSNS (6),
01008 COSTS_N_INSNS (7),
01009 COSTS_N_INSNS (8),
01010 COSTS_N_INSNS (23),
01011 COSTS_N_INSNS (36),
01012 COSTS_N_INSNS (3),
01013 COSTS_N_INSNS (8),
01014 COSTS_N_INSNS (69),
01015 COSTS_N_INSNS (69),
01016 1,
01017 4
01018 },
01019 {
01020
01021 COSTS_N_INSNS (4),
01022 COSTS_N_INSNS (4),
01023 COSTS_N_INSNS (4),
01024 COSTS_N_INSNS (24),
01025 COSTS_N_INSNS (32),
01026 COSTS_N_INSNS (3),
01027 COSTS_N_INSNS (4),
01028 COSTS_N_INSNS (36),
01029 COSTS_N_INSNS (68),
01030 1,
01031 4
01032 },
01033 {
01034
01035 COSTS_N_INSNS (4),
01036 COSTS_N_INSNS (4),
01037 COSTS_N_INSNS (4),
01038 COSTS_N_INSNS (24),
01039 COSTS_N_INSNS (32),
01040 COSTS_N_INSNS (3),
01041 COSTS_N_INSNS (4),
01042 COSTS_N_INSNS (36),
01043 COSTS_N_INSNS (68),
01044 1,
01045 4
01046 },
01047 {
01048 DEFAULT_COSTS
01049 },
01050 };
01051
01052
01053
01054 #ifndef MIPS_MARCH_CONTROLS_SOFT_FLOAT
01055 #define MIPS_MARCH_CONTROLS_SOFT_FLOAT 0
01056 #endif
01057
01058
01059 #undef TARGET_ASM_ALIGNED_HI_OP
01060 #define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
01061 #undef TARGET_ASM_ALIGNED_SI_OP
01062 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
01063 #undef TARGET_ASM_ALIGNED_DI_OP
01064 #define TARGET_ASM_ALIGNED_DI_OP "\t.dword\t"
01065
01066 #undef TARGET_ASM_FUNCTION_PROLOGUE
01067 #define TARGET_ASM_FUNCTION_PROLOGUE mips_output_function_prologue
01068 #undef TARGET_ASM_FUNCTION_EPILOGUE
01069 #define TARGET_ASM_FUNCTION_EPILOGUE mips_output_function_epilogue
01070 #undef TARGET_ASM_SELECT_RTX_SECTION
01071 #define TARGET_ASM_SELECT_RTX_SECTION mips_select_rtx_section
01072 #undef TARGET_ASM_FUNCTION_RODATA_SECTION
01073 #define TARGET_ASM_FUNCTION_RODATA_SECTION mips_function_rodata_section
01074
01075 #undef TARGET_SCHED_REORDER
01076 #define TARGET_SCHED_REORDER mips_sched_reorder
01077 #undef TARGET_SCHED_VARIABLE_ISSUE
01078 #define TARGET_SCHED_VARIABLE_ISSUE mips_variable_issue
01079 #undef TARGET_SCHED_ADJUST_COST
01080 #define TARGET_SCHED_ADJUST_COST mips_adjust_cost
01081 #undef TARGET_SCHED_ISSUE_RATE
01082 #define TARGET_SCHED_ISSUE_RATE mips_issue_rate
01083 #undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
01084 #define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \
01085 mips_multipass_dfa_lookahead
01086
01087 #undef TARGET_DEFAULT_TARGET_FLAGS
01088 #define TARGET_DEFAULT_TARGET_FLAGS \
01089 (TARGET_DEFAULT \
01090 | TARGET_CPU_DEFAULT \
01091 | TARGET_ENDIAN_DEFAULT \
01092 | TARGET_FP_EXCEPTIONS_DEFAULT \
01093 | MASK_CHECK_ZERO_DIV \
01094 | MASK_FUSED_MADD)
01095 #undef TARGET_HANDLE_OPTION
01096 #define TARGET_HANDLE_OPTION mips_handle_option
01097
01098 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
01099 #define TARGET_FUNCTION_OK_FOR_SIBCALL mips_function_ok_for_sibcall
01100
01101 #undef TARGET_VALID_POINTER_MODE
01102 #define TARGET_VALID_POINTER_MODE mips_valid_pointer_mode
01103 #undef TARGET_RTX_COSTS
01104 #define TARGET_RTX_COSTS mips_rtx_costs
01105 #undef TARGET_ADDRESS_COST
01106 #define TARGET_ADDRESS_COST mips_address_cost
01107
01108 #undef TARGET_IN_SMALL_DATA_P
01109 #define TARGET_IN_SMALL_DATA_P mips_in_small_data_p
01110
01111 #undef TARGET_MACHINE_DEPENDENT_REORG
01112 #define TARGET_MACHINE_DEPENDENT_REORG mips_reorg
01113
01114 #undef TARGET_ASM_FILE_START
01115 #undef TARGET_ASM_FILE_END
01116 #define TARGET_ASM_FILE_START mips_file_start
01117 #define TARGET_ASM_FILE_END mips_file_end
01118 #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
01119 #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
01120
01121 #undef TARGET_INIT_LIBFUNCS
01122 #define TARGET_INIT_LIBFUNCS mips_init_libfuncs
01123
01124 #undef TARGET_BUILD_BUILTIN_VA_LIST
01125 #define TARGET_BUILD_BUILTIN_VA_LIST mips_build_builtin_va_list
01126 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
01127 #define TARGET_GIMPLIFY_VA_ARG_EXPR mips_gimplify_va_arg_expr
01128
01129 #undef TARGET_PROMOTE_FUNCTION_ARGS
01130 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
01131 #undef TARGET_PROMOTE_FUNCTION_RETURN
01132 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
01133 #undef TARGET_PROMOTE_PROTOTYPES
01134 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
01135
01136 #undef TARGET_RETURN_IN_MEMORY
01137 #define TARGET_RETURN_IN_MEMORY mips_return_in_memory
01138 #undef TARGET_RETURN_IN_MSB
01139 #define TARGET_RETURN_IN_MSB mips_return_in_msb
01140
01141 #undef TARGET_ASM_OUTPUT_MI_THUNK
01142 #define TARGET_ASM_OUTPUT_MI_THUNK mips_output_mi_thunk
01143 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
01144 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
01145
01146 #undef TARGET_SETUP_INCOMING_VARARGS
01147 #define TARGET_SETUP_INCOMING_VARARGS mips_setup_incoming_varargs
01148 #undef TARGET_STRICT_ARGUMENT_NAMING
01149 #define TARGET_STRICT_ARGUMENT_NAMING mips_strict_argument_naming
01150 #undef TARGET_MUST_PASS_IN_STACK
01151 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
01152 #undef TARGET_PASS_BY_REFERENCE
01153 #define TARGET_PASS_BY_REFERENCE mips_pass_by_reference
01154 #undef TARGET_CALLEE_COPIES
01155 #define TARGET_CALLEE_COPIES mips_callee_copies
01156 #undef TARGET_ARG_PARTIAL_BYTES
01157 #define TARGET_ARG_PARTIAL_BYTES mips_arg_partial_bytes
01158
01159 #undef TARGET_MODE_REP_EXTENDED
01160 #define TARGET_MODE_REP_EXTENDED mips_mode_rep_extended
01161
01162 #undef TARGET_VECTOR_MODE_SUPPORTED_P
01163 #define TARGET_VECTOR_MODE_SUPPORTED_P mips_vector_mode_supported_p
01164
01165 #undef TARGET_INIT_BUILTINS
01166 #define TARGET_INIT_BUILTINS mips_init_builtins
01167 #undef TARGET_EXPAND_BUILTIN
01168 #define TARGET_EXPAND_BUILTIN mips_expand_builtin
01169
01170 #undef TARGET_HAVE_TLS
01171 #define TARGET_HAVE_TLS HAVE_AS_TLS
01172
01173 #undef TARGET_CANNOT_FORCE_CONST_MEM
01174 #define TARGET_CANNOT_FORCE_CONST_MEM mips_cannot_force_const_mem
01175
01176 #undef TARGET_ENCODE_SECTION_INFO
01177 #define TARGET_ENCODE_SECTION_INFO mips_encode_section_info
01178
01179 #undef TARGET_ATTRIBUTE_TABLE
01180 #define TARGET_ATTRIBUTE_TABLE mips_attribute_table
01181
01182 #undef TARGET_EXTRA_LIVE_ON_ENTRY
01183 #define TARGET_EXTRA_LIVE_ON_ENTRY mips_extra_live_on_entry
01184
01185 #undef TARGET_MIN_ANCHOR_OFFSET
01186 #define TARGET_MIN_ANCHOR_OFFSET -32768
01187 #undef TARGET_MAX_ANCHOR_OFFSET
01188 #define TARGET_MAX_ANCHOR_OFFSET 32767
01189 #undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
01190 #define TARGET_USE_BLOCKS_FOR_CONSTANT_P mips_use_blocks_for_constant_p
01191 #undef TARGET_USE_ANCHORS_FOR_SYMBOL_P
01192 #define TARGET_USE_ANCHORS_FOR_SYMBOL_P mips_use_anchors_for_symbol_p
01193
01194 struct gcc_target targetm = TARGET_INITIALIZER;
01195
01196
01197
01198 static enum mips_symbol_type
01199 mips_classify_symbol (rtx x)
01200 {
01201 if (GET_CODE (x) == LABEL_REF)
01202 {
01203 if (TARGET_MIPS16)
01204 return SYMBOL_CONSTANT_POOL;
01205 if (TARGET_ABICALLS && !TARGET_ABSOLUTE_ABICALLS)
01206 return SYMBOL_GOT_LOCAL;
01207 return SYMBOL_GENERAL;
01208 }
01209
01210 gcc_assert (GET_CODE (x) == SYMBOL_REF);
01211
01212 if (SYMBOL_REF_TLS_MODEL (x))
01213 return SYMBOL_TLS;
01214
01215 if (CONSTANT_POOL_ADDRESS_P (x))
01216 {
01217 if (TARGET_MIPS16)
01218 return SYMBOL_CONSTANT_POOL;
01219
01220 if (GET_MODE_SIZE (get_pool_mode (x)) <= mips_section_threshold)
01221 return SYMBOL_SMALL_DATA;
01222 }
01223
01224
01225
01226 if (SYMBOL_REF_SMALL_P (x)
01227 && !SYMBOL_REF_WEAK (x))
01228 return SYMBOL_SMALL_DATA;
01229
01230 if (TARGET_ABICALLS)
01231 {
01232 if (SYMBOL_REF_DECL (x) == 0)
01233 {
01234 if (!SYMBOL_REF_LOCAL_P (x))
01235 return SYMBOL_GOT_GLOBAL;
01236 }
01237 else
01238 {
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261 if (DECL_P (SYMBOL_REF_DECL (x))
01262 && TREE_PUBLIC (SYMBOL_REF_DECL (x))
01263 && !(TARGET_ABSOLUTE_ABICALLS
01264 && targetm.binds_local_p (SYMBOL_REF_DECL (x))))
01265 return SYMBOL_GOT_GLOBAL;
01266 }
01267
01268 if (!TARGET_ABSOLUTE_ABICALLS)
01269 return SYMBOL_GOT_LOCAL;
01270 }
01271
01272 return SYMBOL_GENERAL;
01273 }
01274
01275
01276
01277
01278
01279 static void
01280 mips_split_const (rtx x, rtx *base, HOST_WIDE_INT *offset)
01281 {
01282 *offset = 0;
01283
01284 if (GET_CODE (x) == CONST)
01285 {
01286 x = XEXP (x, 0);
01287 if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT)
01288 {
01289 *offset += INTVAL (XEXP (x, 1));
01290 x = XEXP (x, 0);
01291 }
01292 }
01293 *base = x;
01294 }
01295
01296
01297
01298
01299
01300 static bool
01301 mips_offset_within_object_p (rtx symbol, HOST_WIDE_INT offset)
01302 {
01303 if (GET_CODE (symbol) != SYMBOL_REF)
01304 return false;
01305
01306 if (CONSTANT_POOL_ADDRESS_P (symbol)
01307 && offset >= 0
01308 && offset < (int) GET_MODE_SIZE (get_pool_mode (symbol)))
01309 return true;
01310
01311 if (SYMBOL_REF_DECL (symbol) != 0
01312 && offset >= 0
01313 && offset < int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (symbol))))
01314 return true;
01315
01316 if (SYMBOL_REF_HAS_BLOCK_INFO_P (symbol)
01317 && SYMBOL_REF_BLOCK (symbol)
01318 && SYMBOL_REF_BLOCK_OFFSET (symbol) >= 0
01319 && ((unsigned HOST_WIDE_INT) offset + SYMBOL_REF_BLOCK_OFFSET (symbol)
01320 < (unsigned HOST_WIDE_INT) SYMBOL_REF_BLOCK (symbol)->size))
01321 return true;
01322
01323 return false;
01324 }
01325
01326
01327
01328
01329
01330
01331 bool
01332 mips_symbolic_constant_p (rtx x, enum mips_symbol_type *symbol_type)
01333 {
01334 HOST_WIDE_INT offset;
01335
01336 mips_split_const (x, &x, &offset);
01337 if (UNSPEC_ADDRESS_P (x))
01338 *symbol_type = UNSPEC_ADDRESS_TYPE (x);
01339 else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
01340 {
01341 *symbol_type = mips_classify_symbol (x);
01342 if (*symbol_type == SYMBOL_TLS)
01343 return false;
01344 }
01345 else
01346 return false;
01347
01348 if (offset == 0)
01349 return true;
01350
01351
01352
01353 switch (*symbol_type)
01354 {
01355 case SYMBOL_GENERAL:
01356 case SYMBOL_64_HIGH:
01357 case SYMBOL_64_MID:
01358 case SYMBOL_64_LOW:
01359
01360
01361
01362
01363 if (Pmode == DImode && !ABI_HAS_64BIT_SYMBOLS)
01364 return mips_offset_within_object_p (x, offset);
01365
01366
01367 return true;
01368
01369 case SYMBOL_CONSTANT_POOL:
01370
01371
01372
01373 if (GET_CODE (x) == LABEL_REF)
01374 return true;
01375
01376
01377
01378 case SYMBOL_SMALL_DATA:
01379
01380
01381
01382 return mips_offset_within_object_p (x, offset);
01383
01384 case SYMBOL_GOT_LOCAL:
01385 case SYMBOL_GOTOFF_PAGE:
01386
01387
01388 return SMALL_OPERAND (offset);
01389
01390 case SYMBOL_GOT_GLOBAL:
01391 case SYMBOL_GOTOFF_GLOBAL:
01392 case SYMBOL_GOTOFF_CALL:
01393 case SYMBOL_GOTOFF_LOADGP:
01394 case SYMBOL_TLSGD:
01395 case SYMBOL_TLSLDM:
01396 case SYMBOL_DTPREL:
01397 case SYMBOL_TPREL:
01398 case SYMBOL_GOTTPREL:
01399 case SYMBOL_TLS:
01400 return false;
01401 }
01402 gcc_unreachable ();
01403 }
01404
01405
01406
01407
01408 int
01409 mips_regno_mode_ok_for_base_p (int regno, enum machine_mode mode, int strict)
01410 {
01411 if (regno >= FIRST_PSEUDO_REGISTER)
01412 {
01413 if (!strict)
01414 return true;
01415 regno = reg_renumber[regno];
01416 }
01417
01418
01419
01420
01421 if (regno == ARG_POINTER_REGNUM || regno == FRAME_POINTER_REGNUM)
01422 return true;
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439 if (TARGET_MIPS16 && regno == STACK_POINTER_REGNUM)
01440 return !strict || GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8;
01441
01442 return TARGET_MIPS16 ? M16_REG_P (regno) : GP_REG_P (regno);
01443 }
01444
01445
01446
01447
01448
01449 static bool
01450 mips_valid_base_register_p (rtx x, enum machine_mode mode, int strict)
01451 {
01452 if (!strict && GET_CODE (x) == SUBREG)
01453 x = SUBREG_REG (x);
01454
01455 return (REG_P (x)
01456 && mips_regno_mode_ok_for_base_p (REGNO (x), mode, strict));
01457 }
01458
01459
01460
01461
01462
01463 static bool
01464 mips_symbolic_address_p (enum mips_symbol_type symbol_type,
01465 enum machine_mode mode)
01466 {
01467 switch (symbol_type)
01468 {
01469 case SYMBOL_GENERAL:
01470 return !TARGET_MIPS16;
01471
01472 case SYMBOL_SMALL_DATA:
01473 return true;
01474
01475 case SYMBOL_CONSTANT_POOL:
01476
01477 return GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8;
01478
01479 case SYMBOL_GOT_LOCAL:
01480 return true;
01481
01482 case SYMBOL_GOT_GLOBAL:
01483
01484 return false;
01485
01486 case SYMBOL_GOTOFF_PAGE:
01487 case SYMBOL_GOTOFF_GLOBAL:
01488 case SYMBOL_GOTOFF_CALL:
01489 case SYMBOL_GOTOFF_LOADGP:
01490 case SYMBOL_TLS:
01491 case SYMBOL_TLSGD:
01492 case SYMBOL_TLSLDM:
01493 case SYMBOL_DTPREL:
01494 case SYMBOL_GOTTPREL:
01495 case SYMBOL_TPREL:
01496 case SYMBOL_64_HIGH:
01497 case SYMBOL_64_MID:
01498 case SYMBOL_64_LOW:
01499 return true;
01500 }
01501 gcc_unreachable ();
01502 }
01503
01504
01505
01506
01507
01508
01509 static bool
01510 mips_classify_address (struct mips_address_info *info, rtx x,
01511 enum machine_mode mode, int strict)
01512 {
01513 switch (GET_CODE (x))
01514 {
01515 case REG:
01516 case SUBREG:
01517 info->type = ADDRESS_REG;
01518 info->reg = x;
01519 info->offset = const0_rtx;
01520 return mips_valid_base_register_p (info->reg, mode, strict);
01521
01522 case PLUS:
01523 info->type = ADDRESS_REG;
01524 info->reg = XEXP (x, 0);
01525 info->offset = XEXP (x, 1);
01526 return (mips_valid_base_register_p (info->reg, mode, strict)
01527 && const_arith_operand (info->offset, VOIDmode));
01528
01529 case LO_SUM:
01530 info->type = ADDRESS_LO_SUM;
01531 info->reg = XEXP (x, 0);
01532 info->offset = XEXP (x, 1);
01533 return (mips_valid_base_register_p (info->reg, mode, strict)
01534 && mips_symbolic_constant_p (info->offset, &info->symbol_type)
01535 && mips_symbolic_address_p (info->symbol_type, mode)
01536 && mips_lo_relocs[info->symbol_type] != 0);
01537
01538 case CONST_INT:
01539
01540
01541 info->type = ADDRESS_CONST_INT;
01542 return !TARGET_MIPS16 && SMALL_INT (x);
01543
01544 case CONST:
01545 case LABEL_REF:
01546 case SYMBOL_REF:
01547 info->type = ADDRESS_SYMBOLIC;
01548 return (mips_symbolic_constant_p (x, &info->symbol_type)
01549 && mips_symbolic_address_p (info->symbol_type, mode)
01550 && !mips_split_p[info->symbol_type]);
01551
01552 default:
01553 return false;
01554 }
01555 }
01556
01557
01558
01559 static bool
01560 mips_tls_operand_p (rtx x)
01561 {
01562 return GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x) != 0;
01563 }
01564
01565
01566
01567 static int
01568 mips_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
01569 {
01570 return mips_tls_operand_p (*x);
01571 }
01572
01573
01574
01575 static bool
01576 mips_cannot_force_const_mem (rtx x)
01577 {
01578 rtx base;
01579 HOST_WIDE_INT offset;
01580
01581 if (!TARGET_MIPS16)
01582 {
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592 if (GET_CODE (x) == CONST_INT)
01593 return true;
01594
01595 mips_split_const (x, &base, &offset);
01596 if (symbolic_operand (base, VOIDmode) && SMALL_OPERAND (offset))
01597 return true;
01598 }
01599
01600 if (TARGET_HAVE_TLS && for_each_rtx (&x, &mips_tls_symbol_ref_1, 0))
01601 return true;
01602
01603 return false;
01604 }
01605
01606
01607
01608
01609 static bool
01610 mips_use_blocks_for_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED,
01611 rtx x ATTRIBUTE_UNUSED)
01612 {
01613 return !TARGET_MIPS16;
01614 }
01615
01616
01617
01618
01619
01620
01621 static int
01622 mips_symbol_insns (enum mips_symbol_type type)
01623 {
01624 switch (type)
01625 {
01626 case SYMBOL_GENERAL:
01627
01628
01629 if (TARGET_MIPS16)
01630 return 0;
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643 return (ABI_HAS_64BIT_SYMBOLS ? 6 : 2);
01644
01645 case SYMBOL_SMALL_DATA:
01646 return 1;
01647
01648 case SYMBOL_CONSTANT_POOL:
01649
01650
01651 return 2;
01652
01653 case SYMBOL_GOT_LOCAL:
01654 case SYMBOL_GOT_GLOBAL:
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675 return 3;
01676
01677 case SYMBOL_GOTOFF_PAGE:
01678 case SYMBOL_GOTOFF_GLOBAL:
01679 case SYMBOL_GOTOFF_CALL:
01680 case SYMBOL_GOTOFF_LOADGP:
01681 case SYMBOL_64_HIGH:
01682 case SYMBOL_64_MID:
01683 case SYMBOL_64_LOW:
01684 case SYMBOL_TLSGD:
01685 case SYMBOL_TLSLDM:
01686 case SYMBOL_DTPREL:
01687 case SYMBOL_GOTTPREL:
01688 case SYMBOL_TPREL:
01689
01690 return mips_split_p[type] ? 2 : 1;
01691
01692 case SYMBOL_TLS:
01693
01694 return 0;
01695 }
01696 gcc_unreachable ();
01697 }
01698
01699
01700
01701 bool
01702 mips_stack_address_p (rtx x, enum machine_mode mode)
01703 {
01704 struct mips_address_info addr;
01705
01706 return (mips_classify_address (&addr, x, mode, false)
01707 && addr.type == ADDRESS_REG
01708 && addr.reg == stack_pointer_rtx);
01709 }
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720 static bool
01721 mips16_unextended_reference_p (enum machine_mode mode, rtx base, rtx offset)
01722 {
01723 if (TARGET_MIPS16
01724 && GET_CODE (offset) == CONST_INT
01725 && INTVAL (offset) >= 0
01726 && (INTVAL (offset) & (GET_MODE_SIZE (mode) - 1)) == 0)
01727 {
01728 if (GET_MODE_SIZE (mode) == 4 && base == stack_pointer_rtx)
01729 return INTVAL (offset) < 256 * GET_MODE_SIZE (mode);
01730 return INTVAL (offset) < 32 * GET_MODE_SIZE (mode);
01731 }
01732 return false;
01733 }
01734
01735
01736
01737
01738
01739
01740
01741 int
01742 mips_address_insns (rtx x, enum machine_mode mode)
01743 {
01744 struct mips_address_info addr;
01745 int factor;
01746
01747 if (mode == BLKmode)
01748
01749 factor = 1;
01750 else
01751
01752 factor = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
01753
01754 if (mips_classify_address (&addr, x, mode, false))
01755 switch (addr.type)
01756 {
01757 case ADDRESS_REG:
01758 if (TARGET_MIPS16
01759 && !mips16_unextended_reference_p (mode, addr.reg, addr.offset))
01760 return factor * 2;
01761 return factor;
01762
01763 case ADDRESS_LO_SUM:
01764 return (TARGET_MIPS16 ? factor * 2 : factor);
01765
01766 case ADDRESS_CONST_INT:
01767 return factor;
01768
01769 case ADDRESS_SYMBOLIC:
01770 return factor * mips_symbol_insns (addr.symbol_type);
01771 }
01772 return 0;
01773 }
01774
01775
01776
01777
01778 int
01779 mips_const_insns (rtx x)
01780 {
01781 struct mips_integer_op codes[MIPS_MAX_INTEGER_OPS];
01782 enum mips_symbol_type symbol_type;
01783 HOST_WIDE_INT offset;
01784
01785 switch (GET_CODE (x))
01786 {
01787 case HIGH:
01788 if (TARGET_MIPS16
01789 || !mips_symbolic_constant_p (XEXP (x, 0), &symbol_type)
01790 || !mips_split_p[symbol_type])
01791 return 0;
01792
01793 return 1;
01794
01795 case CONST_INT:
01796 if (TARGET_MIPS16)
01797
01798
01799
01800
01801 return (INTVAL (x) >= 0 && INTVAL (x) < 256 ? 1
01802 : SMALL_OPERAND_UNSIGNED (INTVAL (x)) ? 2
01803 : INTVAL (x) > -256 && INTVAL (x) < 0 ? 2
01804 : SMALL_OPERAND_UNSIGNED (-INTVAL (x)) ? 3
01805 : 0);
01806
01807 return mips_build_integer (codes, INTVAL (x));
01808
01809 case CONST_DOUBLE:
01810 case CONST_VECTOR:
01811 return (!TARGET_MIPS16 && x == CONST0_RTX (GET_MODE (x)) ? 1 : 0);
01812
01813 case CONST:
01814 if (CONST_GP_P (x))
01815 return 1;
01816
01817
01818 if (mips_symbolic_constant_p (x, &symbol_type))
01819 return mips_symbol_insns (symbol_type);
01820
01821
01822
01823
01824 mips_split_const (x, &x, &offset);
01825 if (offset != 0)
01826 {
01827 int n = mips_const_insns (x);
01828 if (n != 0)
01829 {
01830 if (SMALL_OPERAND (offset))
01831 return n + 1;
01832 else
01833 return n + 1 + mips_build_integer (codes, offset);
01834 }
01835 }
01836 return 0;
01837
01838 case SYMBOL_REF:
01839 case LABEL_REF:
01840 return mips_symbol_insns (mips_classify_symbol (x));
01841
01842 default:
01843 return 0;
01844 }
01845 }
01846
01847
01848
01849
01850
01851 int
01852 mips_fetch_insns (rtx x)
01853 {
01854 gcc_assert (MEM_P (x));
01855 return mips_address_insns (XEXP (x, 0), GET_MODE (x));
01856 }
01857
01858
01859
01860
01861 int
01862 mips_idiv_insns (void)
01863 {
01864 int count;
01865
01866 count = 1;
01867 if (TARGET_CHECK_ZERO_DIV)
01868 {
01869 if (GENERATE_DIVIDE_TRAPS)
01870 count++;
01871 else
01872 count += 2;
01873 }
01874
01875 if (TARGET_FIX_R4000 || TARGET_FIX_R4400)
01876 count++;
01877 return count;
01878 }
01879
01880
01881
01882
01883
01884
01885 bool
01886 mips_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
01887 {
01888 struct mips_address_info addr;
01889
01890 return mips_classify_address (&addr, x, mode, strict);
01891 }
01892
01893
01894
01895
01896
01897 static rtx
01898 mips_force_temporary (rtx dest, rtx value)
01899 {
01900 if (!no_new_pseudos)
01901 return force_reg (Pmode, value);
01902 else
01903 {
01904 emit_move_insn (copy_rtx (dest), value);
01905 return dest;
01906 }
01907 }
01908
01909
01910
01911
01912
01913 rtx
01914 mips_split_symbol (rtx temp, rtx addr)
01915 {
01916 rtx high;
01917
01918 if (TARGET_MIPS16)
01919 high = mips16_gp_pseudo_reg ();
01920 else
01921 high = mips_force_temporary (temp, gen_rtx_HIGH (Pmode, copy_rtx (addr)));
01922 return gen_rtx_LO_SUM (Pmode, high, addr);
01923 }
01924
01925
01926
01927
01928
01929 rtx
01930 mips_unspec_address (rtx address, enum mips_symbol_type symbol_type)
01931 {
01932 rtx base;
01933 HOST_WIDE_INT offset;
01934
01935 mips_split_const (address, &base, &offset);
01936 base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base),
01937 UNSPEC_ADDRESS_FIRST + symbol_type);
01938 return plus_constant (gen_rtx_CONST (Pmode, base), offset);
01939 }
01940
01941
01942
01943
01944
01945
01946
01947
01948 static rtx
01949 mips_unspec_offset_high (rtx temp, rtx base, rtx addr,
01950 enum mips_symbol_type symbol_type)
01951 {
01952 if (mips_split_p[symbol_type])
01953 {
01954 addr = gen_rtx_HIGH (Pmode, mips_unspec_address (addr, symbol_type));
01955 addr = mips_force_temporary (temp, addr);
01956 return mips_force_temporary (temp, gen_rtx_PLUS (Pmode, addr, base));
01957 }
01958 return base;
01959 }
01960
01961
01962
01963
01964
01965
01966 static rtx
01967 mips_add_offset (rtx temp, rtx reg, HOST_WIDE_INT offset)
01968 {
01969 if (!SMALL_OPERAND (offset))
01970 {
01971 rtx high;
01972 if (TARGET_MIPS16)
01973 {
01974
01975
01976 high = GEN_INT (offset);
01977 offset = 0;
01978 }
01979 else
01980 {
01981
01982 high = GEN_INT (CONST_HIGH_PART (offset));
01983 offset = CONST_LOW_PART (offset);
01984 }
01985 high = mips_force_temporary (temp, high);
01986 reg = mips_force_temporary (temp, gen_rtx_PLUS (Pmode, high, reg));
01987 }
01988 return plus_constant (reg, offset);
01989 }
01990
01991
01992
01993
01994
01995
01996 static GTY(()) rtx mips_tls_symbol;
01997
01998 static rtx
01999 mips_call_tls_get_addr (rtx sym, enum mips_symbol_type type, rtx v0)
02000 {
02001 rtx insn, loc, tga, a0;
02002
02003 a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
02004
02005 if (!mips_tls_symbol)
02006 mips_tls_symbol = init_one_libfunc ("__tls_get_addr");
02007
02008 loc = mips_unspec_address (sym, type);
02009
02010 start_sequence ();
02011
02012 emit_insn (gen_rtx_SET (Pmode, a0,
02013 gen_rtx_LO_SUM (Pmode, pic_offset_table_rtx, loc)));
02014 tga = gen_rtx_MEM (Pmode, mips_tls_symbol);
02015 insn = emit_call_insn (gen_call_value (v0, tga, const0_rtx, const0_rtx));
02016 CONST_OR_PURE_CALL_P (insn) = 1;
02017 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), v0);
02018 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), a0);
02019 insn = get_insns ();
02020
02021 end_sequence ();
02022
02023 return insn;
02024 }
02025
02026
02027
02028
02029
02030 static rtx
02031 mips_legitimize_tls_address (rtx loc)
02032 {
02033 rtx dest, insn, v0, v1, tmp1, tmp2, eqv;
02034 enum tls_model model;
02035
02036 v0 = gen_rtx_REG (Pmode, GP_RETURN);
02037 v1 = gen_rtx_REG (Pmode, GP_RETURN + 1);
02038
02039 model = SYMBOL_REF_TLS_MODEL (loc);
02040
02041
02042
02043 if (!TARGET_ABICALLS)
02044 model = TLS_MODEL_LOCAL_EXEC;
02045
02046 switch (model)
02047 {
02048 case TLS_MODEL_GLOBAL_DYNAMIC:
02049 insn = mips_call_tls_get_addr (loc, SYMBOL_TLSGD, v0);
02050 dest = gen_reg_rtx (Pmode);
02051 emit_libcall_block (insn, dest, v0, loc);
02052 break;
02053
02054 case TLS_MODEL_LOCAL_DYNAMIC:
02055 insn = mips_call_tls_get_addr (loc, SYMBOL_TLSLDM, v0);
02056 tmp1 = gen_reg_rtx (Pmode);
02057
02058
02059
02060 eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
02061 UNSPEC_TLS_LDM);
02062 emit_libcall_block (insn, tmp1, v0, eqv);
02063
02064 tmp2 = mips_unspec_offset_high (NULL, tmp1, loc, SYMBOL_DTPREL);
02065 dest = gen_rtx_LO_SUM (Pmode, tmp2,
02066 mips_unspec_address (loc, SYMBOL_DTPREL));
02067 break;
02068
02069 case TLS_MODEL_INITIAL_EXEC:
02070 tmp1 = gen_reg_rtx (Pmode);
02071 tmp2 = mips_unspec_address (loc, SYMBOL_GOTTPREL);
02072 if (Pmode == DImode)
02073 {
02074 emit_insn (gen_tls_get_tp_di (v1));
02075 emit_insn (gen_load_gotdi (tmp1, pic_offset_table_rtx, tmp2));
02076 }
02077 else
02078 {
02079 emit_insn (gen_tls_get_tp_si (v1));
02080 emit_insn (gen_load_gotsi (tmp1, pic_offset_table_rtx, tmp2));
02081 }
02082 dest = gen_reg_rtx (Pmode);
02083 emit_insn (gen_add3_insn (dest, tmp1, v1));
02084 break;
02085
02086 case TLS_MODEL_LOCAL_EXEC:
02087 if (Pmode == DImode)
02088 emit_insn (gen_tls_get_tp_di (v1));
02089 else
02090 emit_insn (gen_tls_get_tp_si (v1));
02091
02092 tmp1 = mips_unspec_offset_high (NULL, v1, loc, SYMBOL_TPREL);
02093 dest = gen_rtx_LO_SUM (Pmode, tmp1,
02094 mips_unspec_address (loc, SYMBOL_TPREL));
02095 break;
02096
02097 default:
02098 gcc_unreachable ();
02099 }
02100
02101 return dest;
02102 }
02103
02104
02105
02106
02107
02108
02109 bool
02110 mips_legitimize_address (rtx *xloc, enum machine_mode mode)
02111 {
02112 enum mips_symbol_type symbol_type;
02113
02114 if (mips_tls_operand_p (*xloc))
02115 {
02116 *xloc = mips_legitimize_tls_address (*xloc);
02117 return true;
02118 }
02119
02120
02121 if (mips_symbolic_constant_p (*xloc, &symbol_type)
02122 && mips_symbolic_address_p (symbol_type, mode)
02123 && mips_split_p[symbol_type])
02124 {
02125 *xloc = mips_split_symbol (0, *xloc);
02126 return true;
02127 }
02128
02129 if (GET_CODE (*xloc) == PLUS && GET_CODE (XEXP (*xloc, 1)) == CONST_INT)
02130 {
02131
02132 rtx reg;
02133
02134 reg = XEXP (*xloc, 0);
02135 if (!mips_valid_base_register_p (reg, mode, 0))
02136 reg = copy_to_mode_reg (Pmode, reg);
02137 *xloc = mips_add_offset (0, reg, INTVAL (XEXP (*xloc, 1)));
02138 return true;
02139 }
02140
02141 return false;
02142 }
02143
02144
02145
02146
02147
02148 static unsigned int
02149 mips_build_shift (struct mips_integer_op *codes, HOST_WIDE_INT value)
02150 {
02151 unsigned int i, shift;
02152
02153
02154
02155 shift = 0;
02156 while ((value & 1) == 0)
02157 value /= 2, shift++;
02158
02159 i = mips_build_integer (codes, value);
02160 codes[i].code = ASHIFT;
02161 codes[i].value = shift;
02162 return i + 1;
02163 }
02164
02165
02166
02167
02168
02169 static unsigned int
02170 mips_build_lower (struct mips_integer_op *codes, unsigned HOST_WIDE_INT value)
02171 {
02172 unsigned HOST_WIDE_INT high;
02173 unsigned int i;
02174
02175 high = value & ~(unsigned HOST_WIDE_INT) 0xffff;
02176 if (!LUI_OPERAND (high) && (value & 0x18000) == 0x18000)
02177 {
02178
02179
02180
02181
02182
02183 i = mips_build_integer (codes, CONST_HIGH_PART (value));
02184 codes[i].code = PLUS;
02185 codes[i].value = CONST_LOW_PART (value);
02186 }
02187 else
02188 {
02189 i = mips_build_integer (codes, high);
02190 codes[i].code = IOR;
02191 codes[i].value = value & 0xffff;
02192 }
02193 return i + 1;
02194 }
02195
02196
02197
02198
02199
02200 static unsigned int
02201 mips_build_integer (struct mips_integer_op *codes,
02202 unsigned HOST_WIDE_INT value)
02203 {
02204 if (SMALL_OPERAND (value)
02205 || SMALL_OPERAND_UNSIGNED (value)
02206 || LUI_OPERAND (value))
02207 {
02208
02209 codes[0].code = UNKNOWN;
02210 codes[0].value = value;
02211 return 1;
02212 }
02213 else if ((value & 1) != 0 || LUI_OPERAND (CONST_HIGH_PART (value)))
02214 {
02215
02216
02217 return mips_build_lower (codes, value);
02218 }
02219 else if ((value & 0xffff) == 0)
02220 {
02221
02222
02223 return mips_build_shift (codes, value);
02224 }
02225 else
02226 {
02227
02228
02229
02230
02231
02232 struct mips_integer_op alt_codes[MIPS_MAX_INTEGER_OPS];
02233 unsigned int cost, alt_cost;
02234
02235 cost = mips_build_shift (codes, value);
02236 alt_cost = mips_build_lower (alt_codes, value);
02237 if (alt_cost < cost)
02238 {
02239 memcpy (codes, alt_codes, alt_cost * sizeof (codes[0]));
02240 cost = alt_cost;
02241 }
02242 return cost;
02243 }
02244 }
02245
02246
02247
02248
02249 void
02250 mips_move_integer (rtx dest, rtx temp, unsigned HOST_WIDE_INT value)
02251 {
02252 struct mips_integer_op codes[MIPS_MAX_INTEGER_OPS];
02253 enum machine_mode mode;
02254 unsigned int i, cost;
02255 rtx x;
02256
02257 mode = GET_MODE (dest);
02258 cost = mips_build_integer (codes, value);
02259
02260
02261
02262 x = GEN_INT (codes[0].value);
02263 for (i = 1; i < cost; i++)
02264 {
02265 if (no_new_pseudos)
02266 {
02267 emit_insn (gen_rtx_SET (VOIDmode, temp, x));
02268 x = temp;
02269 }
02270 else
02271 x = force_reg (mode, x);
02272 x = gen_rtx_fmt_ee (codes[i].code, mode, x, GEN_INT (codes[i].value));
02273 }
02274
02275 emit_insn (gen_rtx_SET (VOIDmode, dest, x));
02276 }
02277
02278
02279
02280
02281
02282
02283 static void
02284 mips_legitimize_const_move (enum machine_mode mode, rtx dest, rtx src)
02285 {
02286 rtx base;
02287 HOST_WIDE_INT offset;
02288
02289
02290 if (splittable_const_int_operand (src, mode))
02291 {
02292 mips_move_integer (dest, dest, INTVAL (src));
02293 return;
02294 }
02295
02296
02297 if (splittable_symbolic_operand (src, mode))
02298 {
02299 emit_insn (gen_rtx_SET (VOIDmode, dest, mips_split_symbol (dest, src)));
02300 return;
02301 }
02302
02303 if (mips_tls_operand_p (src))
02304 {
02305 emit_move_insn (dest, mips_legitimize_tls_address (src));
02306 return;
02307 }
02308
02309
02310
02311
02312 mips_split_const (src, &base, &offset);
02313 if (!TARGET_MIPS16
02314 && offset != 0
02315 && (!no_new_pseudos || SMALL_OPERAND (offset)))
02316 {
02317 base = mips_force_temporary (dest, base);
02318 emit_move_insn (dest, mips_add_offset (0, base, offset));
02319 return;
02320 }
02321
02322 src = force_const_mem (mode, src);
02323
02324
02325
02326 if (!memory_operand (src, VOIDmode))
02327 src = replace_equiv_address (src, mips_split_symbol (dest, XEXP (src, 0)));
02328 emit_move_insn (dest, src);
02329 }
02330
02331
02332
02333
02334
02335 bool
02336 mips_legitimize_move (enum machine_mode mode, rtx dest, rtx src)
02337 {
02338 if (!register_operand (dest, mode) && !reg_or_0_operand (src, mode))
02339 {
02340 emit_move_insn (dest, force_reg (mode, src));
02341 return true;
02342 }
02343
02344
02345 if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
02346 && REG_P (src) && MD_REG_P (REGNO (src))
02347 && REG_P (dest) && GP_REG_P (REGNO (dest)))
02348 {
02349 int other_regno = REGNO (src) == HI_REGNUM ? LO_REGNUM : HI_REGNUM;
02350 if (GET_MODE_SIZE (mode) <= 4)
02351 emit_insn (gen_mfhilo_si (gen_rtx_REG (SImode, REGNO (dest)),
02352 gen_rtx_REG (SImode, REGNO (src)),
02353 gen_rtx_REG (SImode, other_regno)));
02354 else
02355 emit_insn (gen_mfhilo_di (gen_rtx_REG (DImode, REGNO (dest)),
02356 gen_rtx_REG (DImode, REGNO (src)),
02357 gen_rtx_REG (DImode, other_regno)));
02358 return true;
02359 }
02360
02361
02362
02363 if (CONSTANT_P (src) && !move_operand (src, mode))
02364 {
02365 mips_legitimize_const_move (mode, dest, src);
02366 set_unique_reg_note (get_last_insn (), REG_EQUAL, copy_rtx (src));
02367 return true;
02368 }
02369 return false;
02370 }
02371
02372
02373
02374
02375
02376
02377 static int
02378 m16_check_op (rtx op, int low, int high, int mask)
02379 {
02380 return (GET_CODE (op) == CONST_INT
02381 && INTVAL (op) >= low
02382 && INTVAL (op) <= high
02383 && (INTVAL (op) & mask) == 0);
02384 }
02385
02386 int
02387 m16_uimm3_b (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02388 {
02389 return m16_check_op (op, 0x1, 0x8, 0);
02390 }
02391
02392 int
02393 m16_simm4_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02394 {
02395 return m16_check_op (op, - 0x8, 0x7, 0);
02396 }
02397
02398 int
02399 m16_nsimm4_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02400 {
02401 return m16_check_op (op, - 0x7, 0x8, 0);
02402 }
02403
02404 int
02405 m16_simm5_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02406 {
02407 return m16_check_op (op, - 0x10, 0xf, 0);
02408 }
02409
02410 int
02411 m16_nsimm5_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02412 {
02413 return m16_check_op (op, - 0xf, 0x10, 0);
02414 }
02415
02416 int
02417 m16_uimm5_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02418 {
02419 return m16_check_op (op, (- 0x10) << 2, 0xf << 2, 3);
02420 }
02421
02422 int
02423 m16_nuimm5_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02424 {
02425 return m16_check_op (op, (- 0xf) << 2, 0x10 << 2, 3);
02426 }
02427
02428 int
02429 m16_simm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02430 {
02431 return m16_check_op (op, - 0x80, 0x7f, 0);
02432 }
02433
02434 int
02435 m16_nsimm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02436 {
02437 return m16_check_op (op, - 0x7f, 0x80, 0);
02438 }
02439
02440 int
02441 m16_uimm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02442 {
02443 return m16_check_op (op, 0x0, 0xff, 0);
02444 }
02445
02446 int
02447 m16_nuimm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02448 {
02449 return m16_check_op (op, - 0xff, 0x0, 0);
02450 }
02451
02452 int
02453 m16_uimm8_m1_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02454 {
02455 return m16_check_op (op, - 0x1, 0xfe, 0);
02456 }
02457
02458 int
02459 m16_uimm8_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02460 {
02461 return m16_check_op (op, 0x0, 0xff << 2, 3);
02462 }
02463
02464 int
02465 m16_nuimm8_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02466 {
02467 return m16_check_op (op, (- 0xff) << 2, 0x0, 3);
02468 }
02469
02470 int
02471 m16_simm8_8 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02472 {
02473 return m16_check_op (op, (- 0x80) << 3, 0x7f << 3, 7);
02474 }
02475
02476 int
02477 m16_nsimm8_8 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
02478 {
02479 return m16_check_op (op, (- 0x7f) << 3, 0x80 << 3, 7);
02480 }
02481
02482 static bool
02483 mips_rtx_costs (rtx x, int code, int outer_code, int *total)
02484 {
02485 enum machine_mode mode = GET_MODE (x);
02486 bool float_mode_p = FLOAT_MODE_P (mode);
02487
02488 switch (code)
02489 {
02490 case CONST_INT:
02491 if (TARGET_MIPS16)
02492 {
02493
02494
02495 if ((outer_code) == ASHIFT || (outer_code) == ASHIFTRT
02496 || (outer_code) == LSHIFTRT)
02497 {
02498 if (INTVAL (x) >= 1 && INTVAL (x) <= 8)
02499 *total = 0;
02500 else
02501 *total = COSTS_N_INSNS (1);
02502 return true;
02503 }
02504
02505
02506 if ((outer_code) == XOR
02507 && INTVAL (x) >= 0 && INTVAL (x) < 0x10000)
02508 {
02509 *total = 0;
02510 return true;
02511 }
02512
02513
02514
02515
02516 if (((outer_code) == LT || (outer_code) == LE
02517 || (outer_code) == GE || (outer_code) == GT
02518 || (outer_code) == LTU || (outer_code) == LEU
02519 || (outer_code) == GEU || (outer_code) == GTU)
02520 && INTVAL (x) >= -0x8000 && INTVAL (x) < 0x8000)
02521 {
02522 *total = 0;
02523 return true;
02524 }
02525
02526
02527 if (((outer_code) == EQ || (outer_code) == NE)
02528 && INTVAL (x) == 0)
02529 {
02530 *total = 0;
02531 return true;
02532 }
02533
02534
02535
02536
02537
02538
02539
02540
02541 if (outer_code == SET
02542 && INTVAL (x) >= 0
02543 && INTVAL (x) < 256)
02544 {
02545 *total = 0;
02546 return true;
02547 }
02548 }
02549 else
02550 {
02551
02552 *total = 0;
02553 return true;
02554 }
02555
02556
02557
02558
02559 case CONST:
02560 case SYMBOL_REF:
02561 case LABEL_REF:
02562 case CONST_DOUBLE:
02563 if (LEGITIMATE_CONSTANT_P (x))
02564 {
02565 *total = COSTS_N_INSNS (1);
02566 return true;
02567 }
02568 else
02569 {
02570
02571 *total = CONSTANT_POOL_COST;
02572 return true;
02573 }
02574
02575 case MEM:
02576 {
02577
02578
02579 int n = mips_address_insns (XEXP (x, 0), GET_MODE (x));
02580 if (n > 0)
02581 {
02582 *total = COSTS_N_INSNS (n + 1);
02583 return true;
02584 }
02585 return false;
02586 }
02587
02588 case FFS:
02589 *total = COSTS_N_INSNS (6);
02590 return true;
02591
02592 case NOT:
02593 *total = COSTS_N_INSNS ((mode == DImode && !TARGET_64BIT) ? 2 : 1);
02594 return true;
02595
02596 case AND:
02597 case IOR:
02598 case XOR:
02599 if (mode == DImode && !TARGET_64BIT)
02600 {
02601 *total = COSTS_N_INSNS (2);
02602 return true;
02603 }
02604 return false;
02605
02606 case ASHIFT:
02607 case ASHIFTRT:
02608 case LSHIFTRT:
02609 if (mode == DImode && !TARGET_64BIT)
02610 {
02611 *total = COSTS_N_INSNS ((GET_CODE (XEXP (x, 1)) == CONST_INT)
02612 ? 4 : 12);
02613 return true;
02614 }
02615 return false;
02616
02617 case ABS:
02618 if (float_mode_p)
02619 *total = COSTS_N_INSNS (1);
02620 else
02621 *total = COSTS_N_INSNS (4);
02622 return true;
02623
02624 case LO_SUM:
02625 *total = COSTS_N_INSNS (1);
02626 return true;
02627
02628 case PLUS:
02629 case MINUS:
02630 if (float_mode_p)
02631 {
02632 *total = mips_cost->fp_add;
02633 return true;
02634 }
02635
02636 else if (mode == DImode && !TARGET_64BIT)
02637 {
02638 *total = COSTS_N_INSNS (4);
02639 return true;
02640 }
02641 return false;
02642
02643 case NEG:
02644 if (mode == DImode && !TARGET_64BIT)
02645 {
02646 *total = COSTS_N_INSNS (4);
02647 return true;
02648 }
02649 return false;
02650
02651 case MULT:
02652 if (mode == SFmode)
02653 *total = mips_cost->fp_mult_sf;
02654
02655 else if (mode == DFmode)
02656 *total = mips_cost->fp_mult_df;
02657
02658 else if (mode == SImode)
02659 *total = mips_cost->int_mult_si;
02660
02661 else
02662 *total = mips_cost->int_mult_di;
02663
02664 return true;
02665
02666 case DIV:
02667 case MOD:
02668 if (float_mode_p)
02669 {
02670 if (mode == SFmode)
02671 *total = mips_cost->fp_div_sf;
02672 else
02673 *total = mips_cost->fp_div_df;
02674
02675 return true;
02676 }
02677
02678
02679 case UDIV:
02680 case UMOD:
02681 if (mode == DImode)
02682 *total = mips_cost->int_div_di;
02683 else
02684 *total = mips_cost->int_div_si;
02685
02686 return true;
02687
02688 case SIGN_EXTEND:
02689
02690
02691
02692 if (TARGET_64BIT && mode == DImode
02693 && GET_MODE (XEXP (x, 0)) == SImode)
02694 *total = COSTS_N_INSNS (1);
02695 else
02696 *total = COSTS_N_INSNS (2);
02697 return true;
02698
02699 case ZERO_EXTEND:
02700 if (TARGET_64BIT && mode == DImode
02701 && GET_MODE (XEXP (x, 0)) == SImode)
02702 *total = COSTS_N_INSNS (2);
02703 else
02704 *total = COSTS_N_INSNS (1);
02705 return true;
02706
02707 case FLOAT:
02708 case UNSIGNED_FLOAT:
02709 case FIX:
02710 case FLOAT_EXTEND:
02711 case FLOAT_TRUNCATE:
02712 case SQRT:
02713 *total = mips_cost->fp_add;
02714 return true;
02715
02716 default:
02717 return false;
02718 }
02719 }
02720
02721
02722
02723
02724 static int
02725 mips_address_cost (rtx addr)
02726 {
02727 return mips_address_insns (addr, SImode);
02728 }
02729
02730
02731
02732
02733
02734 rtx
02735 mips_subword (rtx op, int high_p)
02736 {
02737 unsigned int byte;
02738 enum machine_mode mode;
02739
02740 mode = GET_MODE (op);
02741 if (mode == VOIDmode)
02742 mode = DImode;
02743
02744 if (TARGET_BIG_ENDIAN ? !high_p : high_p)
02745 byte = UNITS_PER_WORD;
02746 else
02747 byte = 0;
02748
02749 if (REG_P (op))
02750 {
02751 if (FP_REG_P (REGNO (op)))
02752 return gen_rtx_REG (word_mode, high_p ? REGNO (op) + 1 : REGNO (op));
02753 if (ACC_HI_REG_P (REGNO (op)))
02754 return gen_rtx_REG (word_mode, high_p ? REGNO (op) : REGNO (op) + 1);
02755 }
02756
02757 if (MEM_P (op))
02758 return mips_rewrite_small_data (adjust_address (op, word_mode, byte));
02759
02760 return simplify_gen_subreg (word_mode, op, mode, byte);
02761 }
02762
02763
02764
02765
02766 bool
02767 mips_split_64bit_move_p (rtx dest, rtx src)
02768 {
02769 if (TARGET_64BIT)
02770 return false;
02771
02772
02773 if (FP_REG_RTX_P (src) && FP_REG_RTX_P (dest))
02774 return false;
02775
02776
02777
02778 if (mips_isa > 1)
02779 {
02780 if (FP_REG_RTX_P (dest) && MEM_P (src))
02781 return false;
02782 if (FP_REG_RTX_P (src) && MEM_P (dest))
02783 return false;
02784 }
02785 return true;
02786 }
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796
02797
02798
02799
02800
02801
02802
02803
02804 void
02805 mips_split_64bit_move (rtx dest, rtx src)
02806 {
02807 if (FP_REG_RTX_P (dest))
02808 {
02809
02810 emit_insn (gen_load_df_low (copy_rtx (dest), mips_subword (src, 0)));
02811 emit_insn (gen_load_df_high (dest, mips_subword (src, 1),
02812 copy_rtx (dest)));
02813 }
02814 else if (FP_REG_RTX_P (src))
02815 {
02816
02817 emit_move_insn (mips_subword (dest, 0), mips_subword (src, 0));
02818 emit_insn (gen_store_df_high (mips_subword (dest, 1), src));
02819 }
02820 else
02821 {
02822
02823
02824 rtx low_dest;
02825
02826 low_dest = mips_subword (dest, 0);
02827 if (REG_P (low_dest)
02828 && reg_overlap_mentioned_p (low_dest, src))
02829 {
02830 emit_move_insn (mips_subword (dest, 1), mips_subword (src, 1));
02831 emit_move_insn (low_dest, mips_subword (src, 0));
02832 }
02833 else
02834 {
02835 emit_move_insn (low_dest, mips_subword (src, 0));
02836 emit_move_insn (mips_subword (dest, 1), mips_subword (src, 1));
02837 }
02838 }
02839 }
02840
02841
02842
02843
02844 const char *
02845 mips_output_move (rtx dest, rtx src)
02846 {
02847 enum rtx_code dest_code, src_code;
02848 bool dbl_p;
02849
02850 dest_code = GET_CODE (dest);
02851 src_code = GET_CODE (src);
02852 dbl_p = (GET_MODE_SIZE (GET_MODE (dest)) == 8);
02853
02854 if (dbl_p && mips_split_64bit_move_p (dest, src))
02855 return "#";
02856
02857 if ((src_code == REG && GP_REG_P (REGNO (src)))
02858 || (!TARGET_MIPS16 && src == CONST0_RTX (GET_MODE (dest))))
02859 {
02860 if (dest_code == REG)
02861 {
02862 if (GP_REG_P (REGNO (dest)))
02863 return "move\t%0,%z1";
02864
02865 if (MD_REG_P (REGNO (dest)))
02866 return "mt%0\t%z1";
02867
02868 if (DSP_ACC_REG_P (REGNO (dest)))
02869 {
02870 static char retval[] = "mt__\t%z1,%q0";
02871 retval[2] = reg_names[REGNO (dest)][4];
02872 retval[3] = reg_names[REGNO (dest)][5];
02873 return retval;
02874 }
02875
02876 if (FP_REG_P (REGNO (dest)))
02877 return (dbl_p ? "dmtc1\t%z1,%0" : "mtc1\t%z1,%0");
02878
02879 if (ALL_COP_REG_P (REGNO (dest)))
02880 {
02881 static char retval[] = "dmtc_\t%z1,%0";
02882
02883 retval[4] = COPNUM_AS_CHAR_FROM_REGNUM (REGNO (dest));
02884 return (dbl_p ? retval : retval + 1);
02885 }
02886 }
02887 if (dest_code == MEM)
02888 return (dbl_p ? "sd\t%z1,%0" : "sw\t%z1,%0");
02889 }
02890 if (dest_code == REG && GP_REG_P (REGNO (dest)))
02891 {
02892 if (src_code == REG)
02893 {
02894 if (DSP_ACC_REG_P (REGNO (src)))
02895 {
02896 static char retval[] = "mf__\t%0,%q1";
02897 retval[2] = reg_names[REGNO (src)][4];
02898 retval[3] = reg_names[REGNO (src)][5];
02899 return retval;
02900 }
02901
02902 if (ST_REG_P (REGNO (src)) && ISA_HAS_8CC)
02903 return "lui\t%0,0x3f80\n\tmovf\t%0,%.,%1";
02904
02905 if (FP_REG_P (REGNO (src)))
02906 return (dbl_p ? "dmfc1\t%0,%1" : "mfc1\t%0,%1");
02907
02908 if (ALL_COP_REG_P (REGNO (src)))
02909 {
02910 static char retval[] = "dmfc_\t%0,%1";
02911
02912 retval[4] = COPNUM_AS_CHAR_FROM_REGNUM (REGNO (src));
02913 return (dbl_p ? retval : retval + 1);
02914 }
02915 }
02916
02917 if (src_code == MEM)
02918 return (dbl_p ? "ld\t%0,%1" : "lw\t%0,%1");
02919
02920 if (src_code == CONST_INT)
02921 {
02922
02923
02924 if (!TARGET_MIPS16)
02925 return "li\t%0,%1\t\t\t# %X1";
02926
02927 if (INTVAL (src) >= 0 && INTVAL (src) <= 0xffff)
02928 return "li\t%0,%1";
02929
02930 if (INTVAL (src) < 0 && INTVAL (src) >= -0xffff)
02931 return "#";
02932 }
02933
02934 if (src_code == HIGH)
02935 return "lui\t%0,%h1";
02936
02937 if (CONST_GP_P (src))
02938 return "move\t%0,%1";
02939
02940 if (symbolic_operand (src, VOIDmode))
02941 return (dbl_p ? "dla\t%0,%1" : "la\t%0,%1");
02942 }
02943 if (src_code == REG && FP_REG_P (REGNO (src)))
02944 {
02945 if (dest_code == REG && FP_REG_P (REGNO (dest)))
02946 {
02947 if (GET_MODE (dest) == V2SFmode)
02948 return "mov.ps\t%0,%1";
02949 else
02950 return (dbl_p ? "mov.d\t%0,%1" : "mov.s\t%0,%1");
02951 }
02952
02953 if (dest_code == MEM)
02954 return (dbl_p ? "sdc1\t%1,%0" : "swc1\t%1,%0");
02955 }
02956 if (dest_code == REG && FP_REG_P (REGNO (dest)))
02957 {
02958 if (src_code == MEM)
02959 return (dbl_p ? "ldc1\t%0,%1" : "lwc1\t%0,%1");
02960 }
02961 if (dest_code == REG && ALL_COP_REG_P (REGNO (dest)) && src_code == MEM)
02962 {
02963 static char retval[] = "l_c_\t%0,%1";
02964
02965 retval[1] = (dbl_p ? 'd' : 'w');
02966 retval[3] = COPNUM_AS_CHAR_FROM_REGNUM (REGNO (dest));
02967 return retval;
02968 }
02969 if (dest_code == MEM && src_code == REG && ALL_COP_REG_P (REGNO (src)))
02970 {
02971 static char retval[] = "s_c_\t%1,%0";
02972
02973 retval[1] = (dbl_p ? 'd' : 'w');
02974 retval[3] = COPNUM_AS_CHAR_FROM_REGNUM (REGNO (src));
02975 return retval;
02976 }
02977 gcc_unreachable ();
02978 }
02979
02980
02981
02982
02983 void
02984 mips_restore_gp (void)
02985 {
02986 rtx address, slot;
02987
02988 gcc_assert (TARGET_ABICALLS && TARGET_OLDABI);
02989
02990 address = mips_add_offset (pic_offset_table_rtx,
02991 frame_pointer_needed
02992 ? hard_frame_pointer_rtx
02993 : stack_pointer_rtx,
02994 current_function_outgoing_args_size);
02995 slot = gen_rtx_MEM (Pmode, address);
02996
02997 emit_move_insn (pic_offset_table_rtx, slot);
02998 if (!TARGET_EXPLICIT_RELOCS)
02999 emit_insn (gen_blockage ());
03000 }
03001
03002
03003
03004 static void
03005 mips_emit_binary (enum rtx_code code, rtx target, rtx op0, rtx op1)
03006 {
03007 emit_insn (gen_rtx_SET (VOIDmode, target,
03008 gen_rtx_fmt_ee (code, GET_MODE (target), op0, op1)));
03009 }
03010
03011
03012
03013
03014 static bool
03015 mips_relational_operand_ok_p (enum rtx_code code, rtx cmp1)
03016 {
03017 switch (code)
03018 {
03019 case GT:
03020 case GTU:
03021 return reg_or_0_operand (cmp1, VOIDmode);
03022
03023 case GE:
03024 case GEU:
03025 return !TARGET_MIPS16 && cmp1 == const1_rtx;
03026
03027 case LT:
03028 case LTU:
03029 return arith_operand (cmp1, VOIDmode);
03030
03031 case LE:
03032 return sle_operand (cmp1, VOIDmode);
03033
03034 case LEU:
03035 return sleu_operand (cmp1, VOIDmode);
03036
03037 default:
03038 gcc_unreachable ();
03039 }
03040 }
03041
03042
03043
03044
03045
03046 static bool
03047 mips_canonicalize_comparison (enum rtx_code *code, rtx *cmp1,
03048 enum machine_mode mode)
03049 {
03050 HOST_WIDE_INT original, plus_one;
03051
03052 if (GET_CODE (*cmp1) != CONST_INT)
03053 return false;
03054
03055 original = INTVAL (*cmp1);
03056 plus_one = trunc_int_for_mode ((unsigned HOST_WIDE_INT) original + 1, mode);
03057
03058 switch (*code)
03059 {
03060 case LE:
03061 if (original < plus_one)
03062 {
03063 *code = LT;
03064 *cmp1 = force_reg (mode, GEN_INT (plus_one));
03065 return true;
03066 }
03067 break;
03068
03069 case LEU:
03070 if (plus_one != 0)
03071 {
03072 *code = LTU;
03073 *cmp1 = force_reg (mode, GEN_INT (plus_one));
03074 return true;
03075 }
03076 break;
03077
03078 default:
03079 return false;
03080 }
03081
03082 return false;
03083
03084 }
03085
03086
03087
03088
03089
03090
03091 static void
03092 mips_emit_int_relational (enum rtx_code code, bool *invert_ptr,
03093 rtx target, rtx cmp0, rtx cmp1)
03094 {
03095
03096
03097
03098
03099
03100 if (mips_relational_operand_ok_p (code, cmp1))
03101 mips_emit_binary (code, target, cmp0, cmp1);
03102 else if (mips_canonicalize_comparison (&code, &cmp1, GET_MODE (target)))
03103 mips_emit_binary (code, target, cmp0, cmp1);
03104 else
03105 {
03106 enum rtx_code inv_code = reverse_condition (code);
03107 if (!mips_relational_operand_ok_p (inv_code, cmp1))
03108 {
03109 cmp1 = force_reg (GET_MODE (cmp0), cmp1);
03110 mips_emit_int_relational (code, invert_ptr, target, cmp0, cmp1);
03111 }
03112 else if (invert_ptr == 0)
03113 {
03114 rtx inv_target = gen_reg_rtx (GET_MODE (target));
03115 mips_emit_binary (inv_code, inv_target, cmp0, cmp1);
03116 mips_emit_binary (XOR, target, inv_target, const1_rtx);
03117 }
03118 else
03119 {
03120 *invert_ptr = !*invert_ptr;
03121 mips_emit_binary (inv_code, target, cmp0, cmp1);
03122 }
03123 }
03124 }
03125
03126
03127
03128
03129 static rtx
03130 mips_zero_if_equal (rtx cmp0, rtx cmp1)
03131 {
03132 if (cmp1 == const0_rtx)
03133 return cmp0;
03134
03135 if (uns_arith_operand (cmp1, VOIDmode))
03136 return expand_binop (GET_MODE (cmp0), xor_optab,
03137 cmp0, cmp1, 0, 0, OPTAB_DIRECT);
03138
03139 return expand_binop (GET_MODE (cmp0), sub_optab,
03140 cmp0, cmp1, 0, 0, OPTAB_DIRECT);
03141 }
03142
03143
03144
03145
03146
03147
03148 static bool
03149 mips_reverse_fp_cond_p (enum rtx_code *code)
03150 {
03151 switch (*code)
03152 {
03153 case NE:
03154 case LTGT:
03155 case ORDERED:
03156 *code = reverse_condition_maybe_unordered (*code);
03157 return true;
03158
03159 default:
03160 return false;
03161 }
03162 }
03163
03164
03165
03166
03167
03168
03169
03170
03171
03172
03173
03174
03175
03176 static void
03177 mips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p)
03178 {
03179 if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) == MODE_INT)
03180 {
03181 if (!need_eq_ne_p && cmp_operands[1] == const0_rtx)
03182 {
03183 *op0 = cmp_operands[0];
03184 *op1 = cmp_operands[1];
03185 }
03186 else if (*code == EQ || *code == NE)
03187 {
03188 if (need_eq_ne_p)
03189 {
03190 *op0 = mips_zero_if_equal (cmp_operands[0], cmp_operands[1]);
03191 *op1 = const0_rtx;
03192 }
03193 else
03194 {
03195 *op0 = cmp_operands[0];
03196 *op1 = force_reg (GET_MODE (*op0), cmp_operands[1]);
03197 }
03198 }
03199 else
03200 {
03201
03202
03203 bool invert = false;
03204 *op0 = gen_reg_rtx (GET_MODE (cmp_operands[0]));
03205 *op1 = const0_rtx;
03206 mips_emit_int_relational (*code, &invert, *op0,
03207 cmp_operands[0], cmp_operands[1]);
03208 *code = (invert ? EQ : NE);
03209 }
03210 }
03211 else
03212 {
03213 enum rtx_code cmp_code;
03214
03215
03216
03217
03218
03219
03220
03221 cmp_code = *code;
03222 *code = mips_reverse_fp_cond_p (&cmp_code) ? EQ : NE;
03223 *op0 = (ISA_HAS_8CC
03224 ? gen_reg_rtx (CCmode)
03225 : gen_rtx_REG (CCmode, FPSW_REGNUM));
03226 *op1 = const0_rtx;
03227 mips_emit_binary (cmp_code, *op0, cmp_operands[0], cmp_operands[1]);
03228 }
03229 }
03230
03231
03232
03233
03234
03235
03236 bool
03237 mips_emit_scc (enum rtx_code code, rtx target)
03238 {
03239 if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) != MODE_INT)
03240 return false;
03241
03242 target = gen_lowpart (GET_MODE (cmp_operands[0]), target);
03243 if (code == EQ || code == NE)
03244 {
03245 rtx zie = mips_zero_if_equal (cmp_operands[0], cmp_operands[1]);
03246 mips_emit_binary (code, target, zie, const0_rtx);
03247 }
03248 else
03249 mips_emit_int_relational (code, 0, target,
03250 cmp_operands[0], cmp_operands[1]);
03251 return true;
03252 }
03253
03254
03255
03256
03257
03258 void
03259 gen_conditional_branch (rtx *operands, enum rtx_code code)
03260 {
03261 rtx op0, op1, condition;
03262
03263 mips_emit_compare (&code, &op0, &op1, TARGET_MIPS16);
03264 condition = gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
03265 emit_jump_insn (gen_condjump (condition, operands[0]));
03266 }
03267
03268
03269
03270
03271
03272
03273 void
03274 mips_expand_vcondv2sf (rtx dest, rtx true_src, rtx false_src,
03275 enum rtx_code cond, rtx cmp_op0, rtx cmp_op1)
03276 {
03277 rtx cmp_result;
03278 bool reversed_p;
03279
03280 reversed_p = mips_reverse_fp_cond_p (&cond);
03281 cmp_result = gen_reg_rtx (CCV2mode);
03282 emit_insn (gen_scc_ps (cmp_result,
03283 gen_rtx_fmt_ee (cond, VOIDmode, cmp_op0, cmp_op1)));
03284 if (reversed_p)
03285 emit_insn (gen_mips_cond_move_tf_ps (dest, false_src, true_src,
03286 cmp_result));
03287 else
03288 emit_insn (gen_mips_cond_move_tf_ps (dest, true_src, false_src,
03289 cmp_result));
03290 }
03291
03292
03293
03294
03295 void
03296 gen_conditional_move (rtx *operands)
03297 {
03298 enum rtx_code code;
03299 rtx op0, op1;
03300
03301 code = GET_CODE (operands[1]);
03302 mips_emit_compare (&code, &op0, &op1, true);
03303 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
03304 gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
03305 gen_rtx_fmt_ee (code,
03306 GET_MODE (op0),
03307 op0, op1),
03308 operands[2], operands[3])));
03309 }
03310
03311
03312
03313
03314 void
03315 mips_gen_conditional_trap (rtx *operands)
03316 {
03317 rtx op0, op1;
03318 enum rtx_code cmp_code = GET_CODE (operands[0]);
03319 enum machine_mode mode = GET_MODE (cmp_operands[0]);
03320
03321
03322
03323
03324 switch (cmp_code)
03325 {
03326 case GT: cmp_code = LT; break;
03327 case LE: cmp_code = GE; break;
03328 case GTU: cmp_code = LTU; break;
03329 case LEU: cmp_code = GEU; break;
03330 default: break;
03331 }
03332 if (cmp_code == GET_CODE (operands[0]))
03333 {
03334 op0 = cmp_operands[0];
03335 op1 = cmp_operands[1];
03336 }
03337 else
03338 {
03339 op0 = cmp_operands[1];
03340 op1 = cmp_operands[0];
03341 }
03342 op0 = force_reg (mode, op0);
03343 if (!arith_operand (op1, mode))
03344 op1 = force_reg (mode, op1);
03345
03346 emit_insn (gen_rtx_TRAP_IF (VOIDmode,
03347 gen_rtx_fmt_ee (cmp_code, mode, op0, op1),
03348 operands[1]));
03349 }
03350
03351
03352
03353
03354 static void
03355 mips_load_call_address (rtx dest, rtx addr, int sibcall_p)
03356 {
03357
03358
03359
03360
03361 if (TARGET_EXPLICIT_RELOCS
03362 && !(sibcall_p && TARGET_NEWABI)
03363 && global_got_operand (addr, VOIDmode))
03364 {
03365 rtx high, lo_sum_symbol;
03366
03367 high = mips_unspec_offset_high (dest, pic_offset_table_rtx,
03368 addr, SYMBOL_GOTOFF_CALL);
03369 lo_sum_symbol = mips_unspec_address (addr, SYMBOL_GOTOFF_CALL);
03370 if (Pmode == SImode)
03371 emit_insn (gen_load_callsi (dest, high, lo_sum_symbol));
03372 else
03373 emit_insn (gen_load_calldi (dest, high, lo_sum_symbol));
03374 }
03375 else
03376 emit_move_insn (dest, addr);
03377 }
03378
03379
03380
03381
03382
03383
03384
03385
03386
03387 void
03388 mips_expand_call (rtx result, rtx addr, rtx args_size, rtx aux, int sibcall_p)
03389 {
03390 rtx orig_addr, pattern, insn;
03391
03392 orig_addr = addr;
03393 if (!call_insn_operand (addr, VOIDmode))
03394 {
03395 addr = gen_reg_rtx (Pmode);
03396 mips_load_call_address (addr, orig_addr, sibcall_p);
03397 }
03398
03399 if (TARGET_MIPS16
03400 && mips16_hard_float
03401 && build_mips16_call_stub (result, addr, args_size,
03402 aux == 0 ? 0 : (int) GET_MODE (aux)))
03403 return;
03404
03405 if (result == 0)
03406 pattern = (sibcall_p
03407 ? gen_sibcall_internal (addr, args_size)
03408 : gen_call_internal (addr, args_size));
03409 else if (GET_CODE (result) == PARALLEL && XVECLEN (result, 0) == 2)
03410 {
03411 rtx reg1, reg2;
03412
03413 reg1 = XEXP (XVECEXP (result, 0, 0), 0);
03414 reg2 = XEXP (XVECEXP (result, 0, 1), 0);
03415 pattern =
03416 (sibcall_p
03417 ? gen_sibcall_value_multiple_internal (reg1, addr, args_size, reg2)
03418 : gen_call_value_multiple_internal (reg1, addr, args_size, reg2));
03419 }
03420 else
03421 pattern = (sibcall_p
03422 ? gen_sibcall_value_internal (result, addr, args_size)
03423 : gen_call_value_internal (result, addr, args_size));
03424
03425 insn = emit_call_insn (pattern);
03426
03427
03428 if (global_got_operand (orig_addr, VOIDmode))
03429 use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
03430 }
03431
03432
03433
03434
03435 static bool
03436 mips_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
03437 tree exp ATTRIBUTE_UNUSED)
03438 {
03439 return TARGET_SIBCALLS;
03440 }
03441
03442
03443
03444
03445
03446
03447
03448
03449
03450
03451
03452
03453 void
03454 mips_emit_fcc_reload (rtx dest, rtx src, rtx scratch)
03455 {
03456 rtx fp1, fp2;
03457
03458
03459 if (MEM_P (src))
03460 src = adjust_address (src, SFmode, 0);
03461 else if (REG_P (src) || GET_CODE (src) == SUBREG)
03462 src = gen_rtx_REG (SFmode, true_regnum (src));
03463
03464 fp1 = gen_rtx_REG (SFmode, REGNO (scratch));
03465 fp2 = gen_rtx_REG (SFmode, REGNO (scratch) + FP_INC);
03466
03467 emit_move_insn (copy_rtx (fp1), src);
03468 emit_move_insn (copy_rtx (fp2), CONST0_RTX (SFmode));
03469 emit_insn (gen_slt_sf (dest, fp2, fp1));
03470 }
03471
03472
03473
03474
03475
03476 void
03477 mips_set_return_address (rtx address, rtx scratch)
03478 {
03479 rtx slot_address;
03480
03481 compute_frame_size (get_frame_size ());
03482 gcc_assert ((cfun->machine->frame.mask >> 31) & 1);
03483 slot_address = mips_add_offset (scratch, stack_pointer_rtx,
03484 cfun->machine->frame.gp_sp_offset);
03485
03486 emit_move_insn (gen_rtx_MEM (GET_MODE (address), slot_address), address);
03487 }
03488
03489
03490
03491
03492 static void
03493 mips_block_move_straight (rtx dest, rtx src, HOST_WIDE_INT length)
03494 {
03495 HOST_WIDE_INT offset, delta;
03496 unsigned HOST_WIDE_INT bits;
03497 int i;
03498 enum machine_mode mode;
03499 rtx *regs;
03500
03501
03502
03503
03504
03505
03506 if (MEM_ALIGN (src) == BITS_PER_WORD / 2
03507 && MEM_ALIGN (dest) == BITS_PER_WORD / 2)
03508 bits = BITS_PER_WORD / 2;
03509 else
03510 bits = BITS_PER_WORD;
03511
03512 mode = mode_for_size (bits, MODE_INT, 0);
03513 delta = bits / BITS_PER_UNIT;
03514
03515
03516 regs = alloca (sizeof (rtx) * length / delta);
03517
03518
03519
03520 for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++)
03521 {
03522 regs[i] = gen_reg_rtx (mode);
03523 if (MEM_ALIGN (src) >= bits)
03524 emit_move_insn (regs[i], adjust_address (src, mode, offset));
03525 else
03526 {
03527 rtx part = adjust_address (src, BLKmode, offset);
03528 if (!mips_expand_unaligned_load (regs[i], part, bits, 0))
03529 gcc_unreachable ();
03530 }
03531 }
03532
03533
03534 for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++)
03535 if (MEM_ALIGN (dest) >= bits)
03536 emit_move_insn (adjust_address (dest, mode, offset), regs[i]);
03537 else
03538 {
03539 rtx part = adjust_address (dest, BLKmode, offset);
03540 if (!mips_expand_unaligned_store (part, regs[i], bits, 0))
03541 gcc_unreachable ();
03542 }
03543
03544
03545 if (offset < length)
03546 {
03547 src = adjust_address (src, BLKmode, offset);
03548 dest = adjust_address (dest, BLKmode, offset);
03549 move_by_pieces (dest, src, length - offset,
03550 MIN (MEM_ALIGN (src), MEM_ALIGN (dest)), 0);
03551 }
03552 }
03553
03554 #define MAX_MOVE_REGS 4
03555 #define MAX_MOVE_BYTES (MAX_MOVE_REGS * UNITS_PER_WORD)
03556
03557
03558
03559
03560
03561
03562
03563
03564
03565
03566 static void
03567 mips_adjust_block_mem (rtx mem, HOST_WIDE_INT length,
03568 rtx *loop_reg, rtx *loop_mem)
03569 {
03570 *loop_reg = copy_addr_to_reg (XEXP (mem, 0));
03571
03572
03573
03574 *loop_mem = change_address (mem, BLKmode, *loop_reg);
03575 set_mem_align (*loop_mem, MIN (MEM_ALIGN (mem), length * BITS_PER_UNIT));
03576 }
03577
03578
03579
03580
03581
03582
03583 static void
03584 mips_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length)
03585 {
03586 rtx label, src_reg, dest_reg, final_src;
03587 HOST_WIDE_INT leftover;
03588
03589 leftover = length % MAX_MOVE_BYTES;
03590 length -= leftover;
03591
03592
03593 mips_adjust_block_mem (src, MAX_MOVE_BYTES, &src_reg, &src);
03594 mips_adjust_block_mem (dest, MAX_MOVE_BYTES, &dest_reg, &dest);
03595
03596
03597
03598 final_src = expand_simple_binop (Pmode, PLUS, src_reg, GEN_INT (length),
03599 0, 0, OPTAB_WIDEN);
03600
03601
03602 label = gen_label_rtx ();
03603 emit_label (label);
03604
03605
03606 mips_block_move_straight (dest, src, MAX_MOVE_BYTES);
03607
03608
03609 emit_move_insn (src_reg, plus_constant (src_reg, MAX_MOVE_BYTES));
03610 emit_move_insn (dest_reg, plus_constant (dest_reg, MAX_MOVE_BYTES));
03611
03612
03613 if (Pmode == DImode)
03614 emit_insn (gen_cmpdi (src_reg, final_src));
03615 else
03616 emit_insn (gen_cmpsi (src_reg, final_src));
03617 emit_jump_insn (gen_bne (label));
03618
03619
03620 if (leftover)
03621 mips_block_move_straight (dest, src, leftover);
03622 }
03623
03624
03625
03626 bool
03627 mips_expand_block_move (rtx dest, rtx src, rtx length)
03628 {
03629 if (GET_CODE (length) == CONST_INT)
03630 {
03631 if (INTVAL (length) <= 2 * MAX_MOVE_BYTES)
03632 {
03633 mips_block_move_straight (dest, src, INTVAL (length));
03634 return true;
03635 }
03636 else if (optimize)
03637 {
03638 mips_block_move_loop (dest, src, INTVAL (length));
03639 return true;
03640 }
03641 }
03642 return false;
03643 }
03644
03645
03646
03647
03648
03649 void
03650 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
03651 rtx libname ATTRIBUTE_UNUSED)
03652 {
03653 static CUMULATIVE_ARGS zero_cum;
03654 tree param, next_param;
03655
03656 *cum = zero_cum;
03657 cum->prototype = (fntype && TYPE_ARG_TYPES (fntype));
03658
03659
03660
03661
03662
03663
03664 for (param = fntype ? TYPE_ARG_TYPES (fntype) : 0;
03665 param != 0; param = next_param)
03666 {
03667 next_param = TREE_CHAIN (param);
03668 if (next_param == 0 && TREE_VALUE (param) != void_type_node)
03669 cum->gp_reg_found = 1;
03670 }
03671 }
03672
03673
03674
03675
03676
03677
03678
03679 static void
03680 mips_arg_info (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
03681 tree type, int named, struct mips_arg_info *info)
03682 {
03683 bool doubleword_aligned_p;
03684 unsigned int num_bytes, num_words, max_regs;
03685
03686
03687 num_bytes = type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
03688 num_words = (num_bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
03689
03690
03691
03692
03693
03694
03695 switch (mips_abi)
03696 {
03697 case ABI_EABI:
03698
03699
03700 info->fpr_p = ((GET_MODE_CLASS (mode) == MODE_FLOAT
03701 || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
03702 && GET_MODE_SIZE (mode) <= UNITS_PER_FPVALUE);
03703 break;
03704
03705 case ABI_32:
03706 case ABI_O64:
03707
03708
03709
03710 info->fpr_p = (!cum->gp_reg_found
03711 && cum->arg_number < 2
03712 && (type == 0 || SCALAR_FLOAT_TYPE_P (type)
03713 || VECTOR_FLOAT_TYPE_P (type))
03714 && (GET_MODE_CLASS (mode) == MODE_FLOAT
03715 || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
03716 && GET_MODE_SIZE (mode) <= UNITS_PER_FPVALUE);
03717 break;
03718
03719 case ABI_N32:
03720 case ABI_64:
03721
03722
03723 info->fpr_p = (named
03724 && (type == 0 || FLOAT_TYPE_P (type))
03725 && (GET_MODE_CLASS (mode) == MODE_FLOAT
03726 || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
03727 || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
03728 && GET_MODE_UNIT_SIZE (mode) <= UNITS_PER_FPVALUE);
03729
03730
03731
03732
03733
03734
03735
03736
03737
03738
03739
03740
03741
03742
03743
03744
03745 if (info->fpr_p
03746 && GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
03747 && GET_MODE_UNIT_SIZE (mode) < UNITS_PER_FPVALUE)
03748 {
03749 if (cum->num_gprs >= MAX_ARGS_IN_REGISTERS - 1)
03750 info->fpr_p = false;
03751 else
03752 num_words = 2;
03753 }
03754 break;
03755
03756 default:
03757 gcc_unreachable ();
03758 }
03759
03760
03761 doubleword_aligned_p = FUNCTION_ARG_BOUNDARY (mode, type) > BITS_PER_WORD;
03762
03763
03764
03765
03766 info->reg_offset = (mips_abi == ABI_EABI && info->fpr_p
03767 ? cum->num_fprs
03768 : cum->num_gprs);
03769
03770
03771 if (doubleword_aligned_p)
03772 info->reg_offset += info->reg_offset & 1;
03773
03774
03775 info->stack_offset = cum->stack_words;
03776 if (doubleword_aligned_p)
03777 info->stack_offset += info->stack_offset & 1;
03778
03779 max_regs = MAX_ARGS_IN_REGISTERS - info->reg_offset;
03780
03781
03782 info->reg_words = MIN (num_words, max_regs);
03783 info->stack_words = num_words - info->reg_words;
03784 }
03785
03786
03787
03788
03789 void
03790 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
03791 tree type, int named)
03792 {
03793 struct mips_arg_info info;
03794
03795 mips_arg_info (cum, mode, type, named, &info);
03796
03797 if (!info.fpr_p)
03798 cum->gp_reg_found = true;
03799
03800
03801
03802
03803 if (cum->arg_number < 2 && info.fpr_p)
03804 cum->fp_code += (mode == SFmode ? 1 : 2) << ((cum->arg_number - 1) * 2);
03805
03806 if (mips_abi != ABI_EABI || !info.fpr_p)
03807 cum->num_gprs = info.reg_offset + info.reg_words;
03808 else if (info.reg_words > 0)
03809 cum->num_fprs += FP_INC;
03810
03811 if (info.stack_words > 0)
03812 cum->stack_words = info.stack_offset + info.stack_words;
03813
03814 cum->arg_number++;
03815 }
03816
03817
03818
03819 struct rtx_def *
03820 function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
03821 tree type, int named)
03822 {
03823 struct mips_arg_info info;
03824
03825
03826
03827
03828
03829 if (mode == VOIDmode)
03830 {
03831 if (TARGET_MIPS16 && cum->fp_code != 0)
03832 return gen_rtx_REG ((enum machine_mode) cum->fp_code, 0);
03833
03834 else
03835 return 0;
03836 }
03837
03838 mips_arg_info (cum, mode, type, named, &info);
03839
03840
03841 if (info.reg_offset == MAX_ARGS_IN_REGISTERS)
03842 return 0;
03843
03844 if (type != 0
03845 && TREE_CODE (type) == RECORD_TYPE
03846 && TARGET_NEWABI
03847 && TYPE_SIZE_UNIT (type)
03848 && host_integerp (TYPE_SIZE_UNIT (type), 1)
03849 && named)
03850 {
03851
03852
03853
03854 tree field;
03855
03856
03857 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
03858 if (TREE_CODE (field) == FIELD_DECL
03859 && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
03860 && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD
03861 && host_integerp (bit_position (field), 0)
03862 && int_bit_position (field) % BITS_PER_WORD == 0)
03863 break;
03864
03865 if (field != 0)
03866 {
03867
03868
03869
03870 unsigned int i;
03871 HOST_WIDE_INT bitpos;
03872 rtx ret;
03873
03874
03875
03876 ret = gen_rtx_PARALLEL (mode, rtvec_alloc (info.reg_words));
03877
03878 bitpos = 0;
03879 field = TYPE_FIELDS (type);
03880 for (i = 0; i < info.reg_words; i++)
03881 {
03882 rtx reg;
03883
03884 for (; field; field = TREE_CHAIN (field))
03885 if (TREE_CODE (field) == FIELD_DECL
03886 && int_bit_position (field) >= bitpos)
03887 break;
03888
03889 if (field
03890 && int_bit_position (field) == bitpos
03891 && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
03892 && !TARGET_SOFT_FLOAT
03893 && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD)
03894 reg = gen_rtx_REG (DFmode, FP_ARG_FIRST + info.reg_offset + i);
03895 else
03896 reg = gen_rtx_REG (DImode, GP_ARG_FIRST + info.reg_offset + i);
03897
03898 XVECEXP (ret, 0, i)
03899 = gen_rtx_EXPR_LIST (VOIDmode, reg,
03900 GEN_INT (bitpos / BITS_PER_UNIT));
03901
03902 bitpos += BITS_PER_WORD;
03903 }
03904 return ret;
03905 }
03906 }
03907
03908
03909
03910
03911 if (TARGET_NEWABI
03912 && info.fpr_p
03913 && GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
03914 {
03915 rtx real, imag;
03916 enum machine_mode inner;
03917 int reg;
03918
03919 inner = GET_MODE_INNER (mode);
03920 reg = FP_ARG_FIRST + info.reg_offset;
03921 if (info.reg_words * UNITS_PER_WORD == GET_MODE_SIZE (inner))
03922 {
03923
03924 gcc_assert (info.stack_words == info.reg_words);
03925 return gen_rtx_REG (inner, reg);
03926 }
03927 else
03928 {
03929 gcc_assert (info.stack_words == 0);
03930 real = gen_rtx_EXPR_LIST (VOIDmode,
03931 gen_rtx_REG (inner, reg),
03932 const0_rtx);
03933 imag = gen_rtx_EXPR_LIST (VOIDmode,
03934 gen_rtx_REG (inner,
03935 reg + info.reg_words / 2),
03936 GEN_INT (GET_MODE_SIZE (inner)));
03937 return gen_rtx_PARALLEL (mode, gen_rtvec (2, real, imag));
03938 }
03939 }
03940
03941 if (!info.fpr_p)
03942 return gen_rtx_REG (mode, GP_ARG_FIRST + info.reg_offset);
03943 else if (info.reg_offset == 1)
03944
03945
03946 return gen_rtx_REG (mode, FP_ARG_FIRST + FP_INC);
03947 else
03948 return gen_rtx_REG (mode, FP_ARG_FIRST + info.reg_offset);
03949 }
03950
03951
03952
03953
03954 static int
03955 mips_arg_partial_bytes (CUMULATIVE_ARGS *cum,
03956 enum machine_mode mode, tree type, bool named)
03957 {
03958 struct mips_arg_info info;
03959
03960 mips_arg_info (cum, mode, type, named, &info);
03961 return info.stack_words > 0 ? info.reg_words * UNITS_PER_WORD : 0;
03962 }
03963
03964
03965
03966
03967
03968
03969 int
03970 function_arg_boundary (enum machine_mode mode, tree type)
03971 {
03972 unsigned int alignment;
03973
03974 alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode);
03975 if (alignment < PARM_BOUNDARY)
03976 alignment = PARM_BOUNDARY;
03977 if (alignment > STACK_BOUNDARY)
03978 alignment = STACK_BOUNDARY;
03979 return alignment;
03980 }
03981
03982
03983
03984
03985
03986
03987 bool
03988 mips_pad_arg_upward (enum machine_mode mode, tree type)
03989 {
03990
03991
03992 if (!BYTES_BIG_ENDIAN)
03993 return true;
03994
03995
03996
03997 if (type != 0
03998 ? INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)
03999 : GET_MODE_CLASS (mode) == MODE_INT)
04000 return false;
04001
04002
04003 if (mips_abi == ABI_O64)
04004 if (type != 0 ? FLOAT_TYPE_P (type) : GET_MODE_CLASS (mode) == MODE_FLOAT)
04005 return false;
04006
04007
04008 if (mips_abi != ABI_EABI)
04009 return true;
04010
04011
04012 if (mode != BLKmode)
04013 return (GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY);
04014 else
04015 return (int_size_in_bytes (type) >= (PARM_BOUNDARY / BITS_PER_UNIT));
04016 }
04017
04018
04019
04020
04021
04022
04023 bool
04024 mips_pad_reg_upward (enum machine_mode mode, tree type)
04025 {
04026
04027 if (type != 0 ? FLOAT_TYPE_P (type) : GET_MODE_CLASS (mode) == MODE_FLOAT)
04028 return !BYTES_BIG_ENDIAN;
04029
04030
04031
04032 return mips_pad_arg_upward (mode, type);
04033 }
04034
04035 static void
04036 mips_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
04037 tree type, int *pretend_size ATTRIBUTE_UNUSED,
04038 int no_rtl)
04039 {
04040 CUMULATIVE_ARGS local_cum;
04041 int gp_saved, fp_saved;
04042
04043
04044
04045
04046
04047 local_cum = *cum;
04048 FUNCTION_ARG_ADVANCE (local_cum, mode, type, 1);
04049
04050
04051 gp_saved = MAX_ARGS_IN_REGISTERS - local_cum.num_gprs;
04052 fp_saved = (EABI_FLOAT_VARARGS_P
04053 ? MAX_ARGS_IN_REGISTERS - local_cum.num_fprs
04054 : 0);
04055
04056 if (!no_rtl)
04057 {
04058 if (gp_saved > 0)
04059 {
04060 rtx ptr, mem;
04061
04062 ptr = plus_constant (virtual_incoming_args_rtx,
04063 REG_PARM_STACK_SPACE (cfun->decl)
04064 - gp_saved * UNITS_PER_WORD);
04065 mem = gen_rtx_MEM (BLKmode, ptr);
04066 set_mem_alias_set (mem, get_varargs_alias_set ());
04067
04068 move_block_from_reg (local_cum.num_gprs + GP_ARG_FIRST,
04069 mem, gp_saved);
04070 }
04071 if (fp_saved > 0)
04072 {
04073
04074
04075 enum machine_mode mode;
04076 int off, i;
04077
04078
04079
04080
04081 off = -gp_saved * UNITS_PER_WORD;
04082 off &= ~(UNITS_PER_FPVALUE - 1);
04083 off -= fp_saved * UNITS_PER_FPREG;
04084
04085 mode = TARGET_SINGLE_FLOAT ? SFmode : DFmode;
04086
04087 for (i = local_cum.num_fprs; i < MAX_ARGS_IN_REGISTERS; i += FP_INC)
04088 {
04089 rtx ptr, mem;
04090
04091 ptr = plus_constant (virtual_incoming_args_rtx, off);
04092 mem = gen_rtx_MEM (mode, ptr);
04093 set_mem_alias_set (mem, get_varargs_alias_set ());
04094 emit_move_insn (mem, gen_rtx_REG (mode, FP_ARG_FIRST + i));
04095 off += UNITS_PER_HWFPVALUE;
04096 }
04097 }
04098 }
04099 if (REG_PARM_STACK_SPACE (cfun->decl) == 0)
04100 cfun->machine->varargs_size = (gp_saved * UNITS_PER_WORD
04101 + fp_saved * UNITS_PER_FPREG);
04102 }
04103
04104
04105
04106
04107
04108
04109
04110
04111
04112
04113
04114
04115
04116
04117
04118
04119
04120
04121
04122
04123
04124 static tree
04125 mips_build_builtin_va_list (void)
04126 {
04127 if (EABI_FLOAT_VARARGS_P)
04128 {
04129 tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff, f_res, record;
04130 tree array, index;
04131
04132 record = (*lang_hooks.types.make_type) (RECORD_TYPE);
04133
04134 f_ovfl = build_decl (FIELD_DECL, get_identifier ("__overflow_argptr"),
04135 ptr_type_node);
04136 f_gtop = build_decl (FIELD_DECL, get_identifier ("__gpr_top"),
04137 ptr_type_node);
04138 f_ftop = build_decl (FIELD_DECL, get_identifier ("__fpr_top"),
04139 ptr_type_node);
04140 f_goff = build_decl (FIELD_DECL, get_identifier ("__gpr_offset"),
04141 unsigned_char_type_node);
04142 f_foff = build_decl (FIELD_DECL, get_identifier ("__fpr_offset"),
04143 unsigned_char_type_node);
04144
04145
04146 index = build_int_cst (NULL_TREE, GET_MODE_SIZE (ptr_mode) - 2 - 1);
04147 array = build_array_type (unsigned_char_type_node,
04148 build_index_type (index));
04149 f_res = build_decl (FIELD_DECL, get_identifier ("__reserved"), array);
04150
04151 DECL_FIELD_CONTEXT (f_ovfl) = record;
04152 DECL_FIELD_CONTEXT (f_gtop) = record;
04153 DECL_FIELD_CONTEXT (f_ftop) = record;
04154 DECL_FIELD_CONTEXT (f_goff) = record;
04155 DECL_FIELD_CONTEXT (f_foff) = record;
04156 DECL_FIELD_CONTEXT (f_res) = record;
04157
04158 TYPE_FIELDS (record) = f_ovfl;
04159 TREE_CHAIN (f_ovfl) = f_gtop;
04160 TREE_CHAIN (f_gtop) = f_ftop;
04161 TREE_CHAIN (f_ftop) = f_goff;
04162 TREE_CHAIN (f_goff) = f_foff;
04163 TREE_CHAIN (f_foff) = f_res;
04164
04165 layout_type (record);
04166 return record;
04167 }
04168 else if (TARGET_IRIX && TARGET_IRIX6)
04169
04170 return build_pointer_type (char_type_node);
04171 else
04172
04173 return ptr_type_node;
04174 }
04175
04176
04177
04178 void
04179 mips_va_start (tree valist, rtx nextarg)
04180 {
04181 if (EABI_FLOAT_VARARGS_P)
04182 {
04183 const CUMULATIVE_ARGS *cum;
04184 tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff;
04185 tree ovfl, gtop, ftop, goff, foff;
04186 tree t;
04187 int gpr_save_area_size;
04188 int fpr_save_area_size;
04189 int fpr_offset;
04190
04191 cum = ¤t_function_args_info;
04192 gpr_save_area_size
04193 = (MAX_ARGS_IN_REGISTERS - cum->num_gprs) * UNITS_PER_WORD;
04194 fpr_save_area_size
04195 = (MAX_ARGS_IN_REGISTERS - cum->num_fprs) * UNITS_PER_FPREG;
04196
04197 f_ovfl = TYPE_FIELDS (va_list_type_node);
04198 f_gtop = TREE_CHAIN (f_ovfl);
04199 f_ftop = TREE_CHAIN (f_gtop);
04200 f_goff = TREE_CHAIN (f_ftop);
04201 f_foff = TREE_CHAIN (f_goff);
04202
04203 ovfl = build3 (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl,
04204 NULL_TREE);
04205 gtop = build3 (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop,
04206 NULL_TREE);
04207 ftop = build3 (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop,
04208 NULL_TREE);
04209 goff = build3 (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff,
04210 NULL_TREE);
04211 foff = build3 (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff,
04212 NULL_TREE);
04213
04214
04215
04216
04217 t = make_tree (TREE_TYPE (ovfl), virtual_incoming_args_rtx);
04218 if (cum->stack_words > 0)
04219 t = build2 (PLUS_EXPR, TREE_TYPE (ovfl), t,
04220 build_int_cst (NULL_TREE,
04221 cum->stack_words * UNITS_PER_WORD));
04222 t = build2 (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t);
04223 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
04224
04225
04226 t = make_tree (TREE_TYPE (gtop), virtual_incoming_args_rtx);
04227 t = build2 (MODIFY_EXPR, TREE_TYPE (gtop), gtop, t);
04228 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
04229
04230
04231
04232
04233 t = make_tree (TREE_TYPE (ftop), virtual_incoming_args_rtx);
04234 fpr_offset = gpr_save_area_size + UNITS_PER_FPVALUE - 1;
04235 fpr_offset &= ~(UNITS_PER_FPVALUE - 1);
04236 if (fpr_offset)
04237 t = build2 (PLUS_EXPR, TREE_TYPE (ftop), t,
04238 build_int_cst (NULL_TREE, -fpr_offset));
04239 t = build2 (MODIFY_EXPR, TREE_TYPE (ftop), ftop, t);
04240 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
04241
04242
04243
04244 t = build2 (MODIFY_EXPR, TREE_TYPE (goff), goff,
04245 build_int_cst (NULL_TREE, gpr_save_area_size));
04246 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
04247
04248
04249
04250 t = build2 (MODIFY_EXPR, TREE_TYPE (foff), foff,
04251 build_int_cst (NULL_TREE, fpr_save_area_size));
04252 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
04253 }
04254 else
04255 {
04256 nextarg = plus_constant (nextarg, -cfun->machine->varargs_size);
04257 std_expand_builtin_va_start (valist, nextarg);
04258 }
04259 }
04260
04261
04262
04263 static tree
04264 mips_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
04265 {
04266 HOST_WIDE_INT size, rsize;
04267 tree addr;
04268 bool indirect;
04269
04270 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, 0);
04271
04272 if (indirect)
04273 type = build_pointer_type (type);
04274
04275 size = int_size_in_bytes (type);
04276 rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
04277
04278 if (mips_abi != ABI_EABI || !EABI_FLOAT_VARARGS_P)
04279 addr = std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
04280 else
04281 {
04282
04283
04284 tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff;
04285 tree ovfl, top, off, align;
04286 HOST_WIDE_INT osize;
04287 tree t, u;
04288
04289 f_ovfl = TYPE_FIELDS (va_list_type_node);
04290 f_gtop = TREE_CHAIN (f_ovfl);
04291 f_ftop = TREE_CHAIN (f_gtop);
04292 f_goff = TREE_CHAIN (f_ftop);
04293 f_foff = TREE_CHAIN (f_goff);
04294
04295
04296
04297
04298
04299
04300
04301
04302
04303
04304
04305
04306
04307
04308
04309
04310
04311
04312
04313
04314
04315
04316
04317
04318
04319
04320
04321
04322
04323
04324
04325 ovfl = build3 (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl,
04326 NULL_TREE);
04327
04328 if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT
04329 && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_FPVALUE)
04330 {
04331 top = build3 (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop,
04332 NULL_TREE);
04333 off = build3 (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff,
04334 NULL_TREE);
04335
04336
04337
04338
04339 rsize = UNITS_PER_HWFPVALUE;
04340
04341
04342
04343
04344
04345
04346
04347
04348
04349
04350
04351
04352
04353
04354
04355
04356
04357
04358 osize = MAX (GET_MODE_SIZE (TYPE_MODE (type)), UNITS_PER_WORD);
04359 }
04360 else
04361 {
04362 top = build3 (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop,
04363 NULL_TREE);
04364 off = build3 (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff,
04365 NULL_TREE);
04366 if (rsize > UNITS_PER_WORD)
04367 {
04368
04369 t = build2 (BIT_AND_EXPR, TREE_TYPE (off), off,
04370 build_int_cst (NULL_TREE, -rsize));
04371 t = build2 (MODIFY_EXPR, TREE_TYPE (off), off, t);
04372 gimplify_and_add (t, pre_p);
04373 }
04374 osize = rsize;
04375 }
04376
04377
04378 t = build2 (NE_EXPR, boolean_type_node, off,
04379 build_int_cst (TREE_TYPE (off), 0));
04380 addr = build3 (COND_EXPR, ptr_type_node, t, NULL_TREE, NULL_TREE);
04381
04382
04383
04384
04385 t = fold_convert (TREE_TYPE (off), build_int_cst (NULL_TREE, rsize));
04386 t = build2 (POSTDECREMENT_EXPR, TREE_TYPE (off), off, t);
04387 t = fold_convert (sizetype, t);
04388 t = fold_convert (TREE_TYPE (top), t);
04389
04390
04391
04392 t = build2 (MINUS_EXPR, TREE_TYPE (top), top, t);
04393 if (BYTES_BIG_ENDIAN && rsize > size)
04394 {
04395 u = fold_convert (TREE_TYPE (t), build_int_cst (NULL_TREE,
04396 rsize - size));
04397 t = build2 (PLUS_EXPR, TREE_TYPE (t), t, u);
04398 }
04399 COND_EXPR_THEN (addr) = t;
04400
04401 if (osize > UNITS_PER_WORD)
04402 {
04403
04404 u = fold_convert (TREE_TYPE (ovfl),
04405 build_int_cst (NULL_TREE, osize - 1));
04406 t = build2 (PLUS_EXPR, TREE_TYPE (ovfl), ovfl, u);
04407 u = fold_convert (TREE_TYPE (ovfl),
04408 build_int_cst (NULL_TREE, -osize));
04409 t = build2 (BIT_AND_EXPR, TREE_TYPE (ovfl), t, u);
04410 align = build2 (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t);
04411 }
04412 else
04413 align = NULL;
04414
04415
04416
04417
04418 u = fold_convert (TREE_TYPE (ovfl),
04419 build_int_cst (NULL_TREE, osize));
04420 t = build2 (POSTINCREMENT_EXPR, TREE_TYPE (ovfl), ovfl, u);
04421 if (BYTES_BIG_ENDIAN && osize > size)
04422 {
04423 u = fold_convert (TREE_TYPE (t),
04424 build_int_cst (NULL_TREE, osize - size));
04425 t = build2 (PLUS_EXPR, TREE_TYPE (t), t, u);
04426 }
04427
04428
04429 if (align)
04430 t = build2 (COMPOUND_EXPR, TREE_TYPE (t), align, t);
04431 COND_EXPR_ELSE (addr) = t;
04432
04433 addr = fold_convert (build_pointer_type (type), addr);
04434 addr = build_va_arg_indirect_ref (addr);
04435 }
04436
04437 if (indirect)
04438 addr = build_va_arg_indirect_ref (addr);
04439
04440 return addr;
04441 }
04442
04443
04444
04445
04446
04447
04448
04449
04450
04451
04452
04453
04454
04455
04456 static bool
04457 mips_get_unaligned_mem (rtx *op, unsigned int width, int bitpos,
04458 rtx *left, rtx *right)
04459 {
04460 rtx first, last;
04461
04462
04463
04464 if (!MEM_P (*op))
04465 return false;
04466
04467
04468 if (width != 32 && (!TARGET_64BIT || width != 64))
04469 return false;
04470
04471
04472
04473
04474 if (bitpos % BITS_PER_UNIT != 0)
04475 return false;
04476
04477
04478
04479 if (MEM_ALIGN (*op) >= width)
04480 return false;
04481
04482
04483
04484 *op = adjust_address (*op, BLKmode, 0);
04485 set_mem_size (*op, GEN_INT (width / BITS_PER_UNIT));
04486
04487
04488
04489
04490 first = adjust_address (*op, QImode, 0);
04491 last = adjust_address (*op, QImode, width / BITS_PER_UNIT - 1);
04492
04493
04494
04495 if (TARGET_BIG_ENDIAN)
04496 *left = first, *right = last;
04497 else
04498 *left = last, *right = first;
04499
04500 return true;
04501 }
04502
04503
04504
04505
04506
04507
04508 bool
04509 mips_expand_unaligned_load (rtx dest, rtx src, unsigned int width, int bitpos)
04510 {
04511 rtx left, right, temp;
04512
04513
04514
04515
04516 if (GET_CODE (dest) == SUBREG
04517 && GET_MODE (dest) == DImode
04518 && SUBREG_BYTE (dest) == 0
04519 && GET_MODE (SUBREG_REG (dest)) == SImode)
04520 dest = SUBREG_REG (dest);
04521
04522
04523
04524 if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
04525 return false;
04526
04527 if (!mips_get_unaligned_mem (&src, width, bitpos, &left, &right))
04528 return false;
04529
04530 temp = gen_reg_rtx (GET_MODE (dest));
04531 if (GET_MODE (dest) == DImode)
04532 {
04533 emit_insn (gen_mov_ldl (temp, src, left));
04534 emit_insn (gen_mov_ldr (dest, copy_rtx (src), right, temp));
04535 }
04536 else
04537 {
04538 emit_insn (gen_mov_lwl (temp, src, left));
04539 emit_insn (gen_mov_lwr (dest, copy_rtx (src), right, temp));
04540 }
04541 return true;
04542 }
04543
04544
04545
04546
04547
04548 bool
04549 mips_expand_unaligned_store (rtx dest, rtx src, unsigned int width, int bitpos)
04550 {
04551 rtx left, right;
04552 enum machine_mode mode;
04553
04554 if (!mips_get_unaligned_mem (&dest, width, bitpos, &left, &right))
04555 return false;
04556
04557 mode = mode_for_size (width, MODE_INT, 0);
04558 src = gen_lowpart (mode, src);
04559
04560 if (mode == DImode)
04561 {
04562 emit_insn (gen_mov_sdl (dest, src, left));
04563 emit_insn (gen_mov_sdr (copy_rtx (dest), copy_rtx (src), right));
04564 }
04565 else
04566 {
04567 emit_insn (gen_mov_swl (dest, src, left));
04568 emit_insn (gen_mov_swr (copy_rtx (dest), copy_rtx (src), right));
04569 }
04570 return true;
04571 }
04572
04573
04574
04575 bool
04576 mips_mem_fits_mode_p (enum machine_mode mode, rtx x)
04577 {
04578 rtx size;
04579
04580 if (!MEM_P (x))
04581 return false;
04582
04583 size = MEM_SIZE (x);
04584 return size && INTVAL (size) == GET_MODE_SIZE (mode);
04585 }
04586
04587
04588
04589
04590
04591
04592
04593
04594
04595
04596
04597
04598
04599 bool
04600 mips_use_ins_ext_p (rtx op, rtx size, rtx position)
04601 {
04602 HOST_WIDE_INT len, pos;
04603
04604 if (!ISA_HAS_EXT_INS
04605 || !register_operand (op, VOIDmode)
04606 || GET_MODE_BITSIZE (GET_MODE (op)) > BITS_PER_WORD)
04607 return false;
04608
04609 len = INTVAL (size);
04610 pos = INTVAL (position);
04611
04612 if (len <= 0 || len >= GET_MODE_BITSIZE (GET_MODE (op))
04613 || pos < 0 || pos + len > GET_MODE_BITSIZE (GET_MODE (op)))
04614 return false;
04615
04616 return true;
04617 }
04618
04619
04620
04621
04622 static void
04623 mips_set_architecture (const struct mips_cpu_info *info)
04624 {
04625 if (info != 0)
04626 {
04627 mips_arch_info = info;
04628 mips_arch = info->cpu;
04629 mips_isa = info->isa;
04630 }
04631 }
04632
04633
04634
04635
04636 static void
04637 mips_set_tune (const struct mips_cpu_info *info)
04638 {
04639 if (info != 0)
04640 {
04641 mips_tune_info = info;
04642 mips_tune = info->cpu;
04643 }
04644 }
04645
04646
04647
04648 static bool
04649 mips_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
04650 {
04651 switch (code)
04652 {
04653 case OPT_mabi_:
04654 if (strcmp (arg, "32") == 0)
04655 mips_abi = ABI_32;
04656 else if (strcmp (arg, "o64") == 0)
04657 mips_abi = ABI_O64;
04658 else if (strcmp (arg, "n32") == 0)
04659 mips_abi = ABI_N32;
04660 else if (strcmp (arg, "64") == 0)
04661 mips_abi = ABI_64;
04662 else if (strcmp (arg, "eabi") == 0)
04663 mips_abi = ABI_EABI;
04664 else
04665 return false;
04666 return true;
04667
04668 case OPT_march_:
04669 case OPT_mtune_:
04670 return mips_parse_cpu (arg) != 0;
04671
04672 case OPT_mips:
04673 mips_isa_info = mips_parse_cpu (ACONCAT (("mips", arg, NULL)));
04674 return mips_isa_info != 0;
04675
04676 case OPT_mno_flush_func:
04677 mips_cache_flush_func = NULL;
04678 return true;
04679
04680 default:
04681 return true;
04682 }
04683 }
04684
04685
04686
04687
04688 void
04689 override_options (void)
04690 {
04691 int i, start, regno;
04692 enum machine_mode mode;
04693
04694 mips_section_threshold = g_switch_set ? g_switch_value : MIPS_DEFAULT_GVALUE;
04695
04696
04697
04698
04699
04700 if (mips_arch_string != 0)
04701 mips_set_architecture (mips_parse_cpu (mips_arch_string));
04702
04703 if (mips_isa_info != 0)
04704 {
04705 if (mips_arch_info == 0)
04706 mips_set_architecture (mips_isa_info);
04707 else if (mips_arch_info->isa != mips_isa_info->isa)
04708 error ("-%s conflicts with the other architecture options, "
04709 "which specify a %s processor",
04710 mips_isa_info->name,
04711 mips_cpu_info_from_isa (mips_arch_info->isa)->name);
04712 }
04713
04714 if (mips_arch_info == 0)
04715 {
04716 #ifdef MIPS_CPU_STRING_DEFAULT
04717 mips_set_architecture (mips_parse_cpu (MIPS_CPU_STRING_DEFAULT));
04718 #else
04719 mips_set_architecture (mips_cpu_info_from_isa (MIPS_ISA_DEFAULT));
04720 #endif
04721 }
04722
04723 if (ABI_NEEDS_64BIT_REGS && !ISA_HAS_64BIT_REGS)
04724 error ("-march=%s is not compatible with the selected ABI",
04725 mips_arch_info->name);
04726
04727
04728 if (mips_tune_string != 0)
04729 mips_set_tune (mips_parse_cpu (mips_tune_string));
04730
04731 if (mips_tune_info == 0)
04732 mips_set_tune (mips_arch_info);
04733
04734
04735 mips_cost = &mips_rtx_cost_data[mips_tune];
04736
04737 if ((target_flags_explicit & MASK_64BIT) != 0)
04738 {
04739
04740
04741 if (TARGET_64BIT && !ISA_HAS_64BIT_REGS)
04742 error ("-mgp64 used with a 32-bit processor");
04743 else if (!TARGET_64BIT && ABI_NEEDS_64BIT_REGS)
04744 error ("-mgp32 used with a 64-bit ABI");
04745 else if (TARGET_64BIT && ABI_NEEDS_32BIT_REGS)
04746 error ("-mgp64 used with a 32-bit ABI");
04747 }
04748 else
04749 {
04750
04751
04752
04753 if (ABI_NEEDS_32BIT_REGS || !ISA_HAS_64BIT_REGS)
04754 target_flags &= ~MASK_64BIT;
04755 else
04756 target_flags |= MASK_64BIT;
04757 }
04758
04759 if ((target_flags_explicit & MASK_FLOAT64) != 0)
04760 {
04761
04762
04763 if (TARGET_64BIT && TARGET_DOUBLE_FLOAT && !TARGET_FLOAT64)
04764 error ("unsupported combination: %s", "-mgp64 -mfp32 -mdouble-float");
04765 else if (!TARGET_64BIT && TARGET_FLOAT64)
04766 error ("unsupported combination: %s", "-mgp32 -mfp64");
04767 else if (TARGET_SINGLE_FLOAT && TARGET_FLOAT64)
04768 error ("unsupported combination: %s", "-mfp64 -msingle-float");
04769 }
04770 else
04771 {
04772
04773
04774 if (TARGET_64BIT && TARGET_DOUBLE_FLOAT)
04775 target_flags |= MASK_FLOAT64;
04776 else
04777 target_flags &= ~MASK_FLOAT64;
04778 }
04779
04780
04781
04782 if ((target_flags_explicit & MASK_LONG64) == 0)
04783 {
04784 if ((mips_abi == ABI_EABI && TARGET_64BIT) || mips_abi == ABI_64)
04785 target_flags |= MASK_LONG64;
04786 else
04787 target_flags &= ~MASK_LONG64;
04788 }
04789
04790 if (MIPS_MARCH_CONTROLS_SOFT_FLOAT
04791 && (target_flags_explicit & MASK_SOFT_FLOAT) == 0)
04792 {
04793
04794
04795 switch ((int) mips_arch)
04796 {
04797 case PROCESSOR_R4100:
04798 case PROCESSOR_R4111:
04799 case PROCESSOR_R4120:
04800 case PROCESSOR_R4130:
04801 target_flags |= MASK_SOFT_FLOAT;
04802 break;
04803
04804 default:
04805 target_flags &= ~MASK_SOFT_FLOAT;
04806 break;
04807 }
04808 }
04809
04810 if (!TARGET_OLDABI)
04811 flag_pcc_struct_return = 0;
04812
04813 if ((target_flags_explicit & MASK_BRANCHLIKELY) == 0)
04814 {
04815
04816
04817
04818
04819
04820
04821
04822
04823
04824
04825
04826
04827
04828
04829
04830
04831 if (ISA_HAS_BRANCHLIKELY
04832 && !(ISA_MIPS32 || ISA_MIPS32R2 || ISA_MIPS64)
04833 && !(TUNE_MIPS5500 || TUNE_SB1))
04834 target_flags |= MASK_BRANCHLIKELY;
04835 else
04836 target_flags &= ~MASK_BRANCHLIKELY;
04837 }
04838 if (TARGET_BRANCHLIKELY && !ISA_HAS_BRANCHLIKELY)
04839 warning (0, "generation of Branch Likely instructions enabled, but not supported by architecture");
04840
04841
04842 if (mips_abi == ABI_EABI && TARGET_ABICALLS)
04843 {
04844 error ("unsupported combination: %s", "-mabicalls -mabi=eabi");
04845 target_flags &= ~MASK_ABICALLS;
04846 }
04847
04848 if (TARGET_ABICALLS)
04849 {
04850
04851
04852
04853
04854
04855
04856
04857 flag_pic = 1;
04858 if (mips_section_threshold > 0)
04859 warning (0, "%<-G%> is incompatible with %<-mabicalls%>");
04860 }
04861
04862
04863
04864
04865
04866
04867
04868
04869
04870
04871
04872 if (!TARGET_MIPS16 && TARGET_SPLIT_ADDRESSES
04873 && optimize && !flag_pic
04874 && !ABI_HAS_64BIT_SYMBOLS)
04875 mips_split_addresses = 1;
04876 else
04877 mips_split_addresses = 0;
04878
04879
04880
04881
04882 if (optimize > 2 && (target_flags_explicit & MASK_VR4130_ALIGN) == 0)
04883 target_flags |= MASK_VR4130_ALIGN;
04884
04885
04886
04887 if (TARGET_MIPS16)
04888 {
04889 if (TARGET_SOFT_FLOAT)
04890 mips16_hard_float = 0;
04891 else
04892 mips16_hard_float = 1;
04893 target_flags |= MASK_SOFT_FLOAT;
04894
04895
04896
04897 flag_schedule_insns = 0;
04898
04899
04900
04901 flag_reorder_blocks_and_partition = 0;
04902
04903
04904
04905
04906
04907 target_flags &= ~MASK_EXPLICIT_RELOCS;
04908 }
04909
04910
04911
04912 if (TARGET_EXPLICIT_RELOCS)
04913 {
04914 mips_flag_delayed_branch = flag_delayed_branch;
04915 flag_delayed_branch = 0;
04916 }
04917
04918 #ifdef MIPS_TFMODE_FORMAT
04919 REAL_MODE_FORMAT (TFmode) = &MIPS_TFMODE_FORMAT;
04920 #endif
04921
04922
04923
04924 if (TARGET_MIPS3D && (target_flags_explicit & MASK_PAIRED_SINGLE_FLOAT)
04925 && !TARGET_PAIRED_SINGLE_FLOAT)
04926 error ("-mips3d requires -mpaired-single");
04927
04928
04929 if (TARGET_MIPS3D)
04930 target_flags |= MASK_PAIRED_SINGLE_FLOAT;
04931
04932
04933
04934 if (TARGET_PAIRED_SINGLE_FLOAT && !(TARGET_FLOAT64 && TARGET_HARD_FLOAT))
04935 error ("-mips3d/-mpaired-single must be used with -mfp64 -mhard-float");
04936
04937
04938
04939 if (TARGET_PAIRED_SINGLE_FLOAT && !ISA_MIPS64)
04940 error ("-mips3d/-mpaired-single must be used with -mips64");
04941
04942 if (TARGET_MIPS16 && TARGET_DSP)
04943 error ("-mips16 and -mdsp cannot be used together");
04944
04945 mips_print_operand_punct['?'] = 1;
04946 mips_print_operand_punct['#'] = 1;
04947 mips_print_operand_punct['/'] = 1;
04948 mips_print_operand_punct['&'] = 1;
04949 mips_print_operand_punct['!'] = 1;
04950 mips_print_operand_punct['*'] = 1;
04951 mips_print_operand_punct['@'] = 1;
04952 mips_print_operand_punct['.'] = 1;
04953 mips_print_operand_punct['('] = 1;
04954 mips_print_operand_punct[')'] = 1;
04955 mips_print_operand_punct['['] = 1;
04956 mips_print_operand_punct[']'] = 1;
04957 mips_print_operand_punct['<'] = 1;
04958 mips_print_operand_punct['>'] = 1;
04959 mips_print_operand_punct['{'] = 1;
04960 mips_print_operand_punct['}'] = 1;
04961 mips_print_operand_punct['^'] = 1;
04962 mips_print_operand_punct['$'] = 1;
04963 mips_print_operand_punct['+'] = 1;
04964 mips_print_operand_punct['~'] = 1;
04965
04966
04967
04968
04969 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
04970 mips_dbx_regno[i] = -1;
04971
04972 start = GP_DBX_FIRST - GP_REG_FIRST;
04973 for (i = GP_REG_FIRST; i <= GP_REG_LAST; i++)
04974 mips_dbx_regno[i] = i + start;
04975
04976 start = FP_DBX_FIRST - FP_REG_FIRST;
04977 for (i = FP_REG_FIRST; i <= FP_REG_LAST; i++)
04978 mips_dbx_regno[i] = i + start;
04979
04980 mips_dbx_regno[HI_REGNUM] = MD_DBX_FIRST + 0;
04981 mips_dbx_regno[LO_REGNUM] = MD_DBX_FIRST + 1;
04982
04983
04984
04985 for (mode = VOIDmode;
04986 mode != MAX_MACHINE_MODE;
04987 mode = (enum machine_mode) ((int)mode + 1))
04988 {
04989 register int size = GET_MODE_SIZE (mode);
04990 register enum mode_class class = GET_MODE_CLASS (mode);
04991
04992 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
04993 {
04994 register int temp;
04995
04996 if (mode == CCV2mode)
04997 temp = (ISA_HAS_8CC
04998 && ST_REG_P (regno)
04999 && (regno - ST_REG_FIRST) % 2 == 0);
05000
05001 else if (mode == CCV4mode)
05002 temp = (ISA_HAS_8CC
05003 && ST_REG_P (regno)
05004 && (regno - ST_REG_FIRST) % 4 == 0);
05005
05006 else if (mode == CCmode)
05007 {
05008 if (! ISA_HAS_8CC)
05009 temp = (regno == FPSW_REGNUM);
05010 else
05011 temp = (ST_REG_P (regno) || GP_REG_P (regno)
05012 || FP_REG_P (regno));
05013 }
05014
05015 else if (GP_REG_P (regno))
05016 temp = ((regno & 1) == 0 || size <= UNITS_PER_WORD);
05017
05018 else if (FP_REG_P (regno))
05019 temp = ((regno % FP_INC) == 0)
05020 && (((class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT
05021 || class == MODE_VECTOR_FLOAT)
05022 && size <= UNITS_PER_FPVALUE)
05023
05024
05025
05026
05027
05028
05029 || (class == MODE_INT
05030 && size >= MIN_UNITS_PER_WORD
05031 && size <= UNITS_PER_FPREG)
05032
05033 || (ISA_HAS_8CC && mode == TFmode));
05034
05035 else if (ACC_REG_P (regno))
05036 temp = (INTEGRAL_MODE_P (mode)
05037 && (size <= UNITS_PER_WORD
05038 || (ACC_HI_REG_P (regno)
05039 && size == 2 * UNITS_PER_WORD)));
05040
05041 else if (ALL_COP_REG_P (regno))
05042 temp = (class == MODE_INT && size <= UNITS_PER_WORD);
05043 else
05044 temp = 0;
05045
05046 mips_hard_regno_mode_ok[(int)mode][regno] = temp;
05047 }
05048 }
05049
05050
05051
05052 gpr_mode = TARGET_64BIT ? DImode : SImode;
05053
05054
05055 if (TARGET_64BIT && !TARGET_MIPS16)
05056 {
05057 if (align_loops == 0)
05058 align_loops = 8;
05059 if (align_jumps == 0)
05060 align_jumps = 8;
05061 if (align_functions == 0)
05062 align_functions = 8;
05063 }
05064
05065
05066 init_machine_status = &mips_init_machine_status;
05067
05068 if (ABI_HAS_64BIT_SYMBOLS)
05069 {
05070 if (TARGET_EXPLICIT_RELOCS)
05071 {
05072 mips_split_p[SYMBOL_64_HIGH] = true;
05073 mips_hi_relocs[SYMBOL_64_HIGH] = "%highest(";
05074 mips_lo_relocs[SYMBOL_64_HIGH] = "%higher(";
05075
05076 mips_split_p[SYMBOL_64_MID] = true;
05077 mips_hi_relocs[SYMBOL_64_MID] = "%higher(";
05078 mips_lo_relocs[SYMBOL_64_MID] = "%hi(";
05079
05080 mips_split_p[SYMBOL_64_LOW] = true;
05081 mips_hi_relocs[SYMBOL_64_LOW] = "%hi(";
05082 mips_lo_relocs[SYMBOL_64_LOW] = "%lo(";
05083
05084 mips_split_p[SYMBOL_GENERAL] = true;
05085 mips_lo_relocs[SYMBOL_GENERAL] = "%lo(";
05086 }
05087 }
05088 else
05089 {
05090 if (TARGET_EXPLICIT_RELOCS || mips_split_addresses)
05091 {
05092 mips_split_p[SYMBOL_GENERAL] = true;
05093 mips_hi_relocs[SYMBOL_GENERAL] = "%hi(";
05094 mips_lo_relocs[SYMBOL_GENERAL] = "%lo(";
05095 }
05096 }
05097
05098 if (TARGET_MIPS16)
05099 {
05100
05101 mips_split_p[SYMBOL_SMALL_DATA] = true;
05102 mips_lo_relocs[SYMBOL_SMALL_DATA] = "%gprel(";
05103 }
05104
05105 if (TARGET_EXPLICIT_RELOCS)
05106 {
05107
05108
05109 mips_lo_relocs[SYMBOL_SMALL_DATA] = "%gp_rel(";
05110
05111 mips_split_p[SYMBOL_GOT_LOCAL] = true;
05112 if (TARGET_NEWABI)
05113 {
05114 mips_lo_relocs[SYMBOL_GOTOFF_PAGE] = "%got_page(";
05115 mips_lo_relocs[SYMBOL_GOT_LOCAL] = "%got_ofst(";
05116 }
05117 else
05118 {
05119 mips_lo_relocs[SYMBOL_GOTOFF_PAGE] = "%got(";
05120 mips_lo_relocs[SYMBOL_GOT_LOCAL] = "%lo(";
05121 }
05122
05123 if (TARGET_XGOT)
05124 {
05125
05126 mips_split_p[SYMBOL_GOT_GLOBAL] = true;
05127
05128 mips_split_p[SYMBOL_GOTOFF_GLOBAL] = true;
05129 mips_hi_relocs[SYMBOL_GOTOFF_GLOBAL] = "%got_hi(";
05130 mips_lo_relocs[SYMBOL_GOTOFF_GLOBAL] = "%got_lo(";
05131
05132 mips_split_p[SYMBOL_GOTOFF_CALL] = true;
05133 mips_hi_relocs[SYMBOL_GOTOFF_CALL] = "%call_hi(";
05134 mips_lo_relocs[SYMBOL_GOTOFF_CALL] = "%call_lo(";
05135 }
05136 else
05137 {
05138 if (TARGET_NEWABI)
05139 mips_lo_relocs[SYMBOL_GOTOFF_GLOBAL] = "%got_disp(";
05140 else
05141 mips_lo_relocs[SYMBOL_GOTOFF_GLOBAL] = "%got(";
05142 mips_lo_relocs[SYMBOL_GOTOFF_CALL] = "%call16(";
05143 }
05144 }
05145
05146 if (TARGET_NEWABI)
05147 {
05148 mips_split_p[SYMBOL_GOTOFF_LOADGP] = true;
05149 mips_hi_relocs[SYMBOL_GOTOFF_LOADGP] = "%hi(%neg(%gp_rel(";
05150 mips_lo_relocs[SYMBOL_GOTOFF_LOADGP] = "%lo(%neg(%gp_rel(";
05151 }
05152
05153
05154 mips_lo_relocs[SYMBOL_TLSGD] = "%tlsgd(";
05155 mips_lo_relocs[SYMBOL_TLSLDM] = "%tlsldm(";
05156 mips_split_p[SYMBOL_DTPREL] = 1;
05157 mips_hi_relocs[SYMBOL_DTPREL] = "%dtprel_hi(";
05158 mips_lo_relocs[SYMBOL_DTPREL] = "%dtprel_lo(";
05159 mips_lo_relocs[SYMBOL_GOTTPREL] = "%gottprel(";
05160 mips_split_p[SYMBOL_TPREL] = 1;
05161 mips_hi_relocs[SYMBOL_TPREL] = "%tprel_hi(";
05162 mips_lo_relocs[SYMBOL_TPREL] = "%tprel_lo(";
05163
05164
05165
05166 if (TARGET_MIPS16)
05167 targetm.have_tls = false;
05168
05169
05170
05171 if ((target_flags_explicit & MASK_FIX_R4000) == 0
05172 && mips_matching_cpu_name_p (mips_arch_info->name, "r4000"))
05173 target_flags |= MASK_FIX_R4000;
05174
05175
05176
05177 if ((target_flags_explicit & MASK_FIX_R4400) == 0
05178 && mips_matching_cpu_name_p (mips_arch_info->name, "r4400"))
05179 target_flags |= MASK_FIX_R4400;
05180 }
05181
05182
05183
05184 void
05185 mips_conditional_register_usage (void)
05186 {
05187 if (!TARGET_DSP)
05188 {
05189 int regno;
05190
05191 for (regno = DSP_ACC_REG_FIRST; regno <= DSP_ACC_REG_LAST; regno++)
05192 fixed_regs[regno] = call_used_regs[regno] = 1;
05193 }
05194 if (!TARGET_HARD_FLOAT)
05195 {
05196 int regno;
05197
05198 for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
05199 fixed_regs[regno] = call_used_regs[regno] = 1;
05200 for (regno = ST_REG_FIRST; regno <= ST_REG_LAST; regno++)
05201 fixed_regs[regno] = call_used_regs[regno] = 1;
05202 }
05203 else if (! ISA_HAS_8CC)
05204 {
05205 int regno;
05206
05207
05208
05209
05210 for (regno = ST_REG_FIRST; regno <= ST_REG_LAST; regno++)
05211 fixed_regs[regno] = call_used_regs[regno] = 1;
05212 }
05213
05214
05215
05216
05217 if (TARGET_MIPS16)
05218 {
05219 fixed_regs[18] = call_used_regs[18] = 1;
05220 fixed_regs[19] = call_used_regs[19] = 1;
05221 fixed_regs[20] = call_used_regs[20] = 1;
05222 fixed_regs[21] = call_used_regs[21] = 1;
05223 fixed_regs[22] = call_used_regs[22] = 1;
05224 fixed_regs[23] = call_used_regs[23] = 1;
05225 fixed_regs[26] = call_used_regs[26] = 1;
05226 fixed_regs[27] = call_used_regs[27] = 1;
05227 fixed_regs[30] = call_used_regs[30] = 1;
05228 }
05229
05230 if (mips_abi == ABI_64)
05231 {
05232 int regno;
05233 for (regno = FP_REG_FIRST + 20; regno < FP_REG_FIRST + 24; regno++)
05234 call_really_used_regs[regno] = call_used_regs[regno] = 1;
05235 }
05236
05237 if (mips_abi == ABI_N32)
05238 {
05239 int regno;
05240 for (regno = FP_REG_FIRST + 21; regno <= FP_REG_FIRST + 31; regno+=2)
05241 call_really_used_regs[regno] = call_used_regs[regno] = 1;
05242 }
05243 }
05244
05245
05246 static struct machine_function *
05247 mips_init_machine_status (void)
05248 {
05249 return ((struct machine_function *)
05250 ggc_alloc_cleared (sizeof (struct machine_function)));
05251 }
05252
05253
05254
05255
05256
05257
05258 void
05259 mips_order_regs_for_local_alloc (void)
05260 {
05261 register int i;
05262
05263 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
05264 reg_alloc_order[i] = i;
05265
05266 if (TARGET_MIPS16)
05267 {
05268
05269
05270 reg_alloc_order[0] = 24;
05271 reg_alloc_order[24] = 0;
05272 }
05273 }
05274
05275
05276
05277
05278
05279
05280
05281
05282
05283
05284
05285 HOST_WIDE_INT
05286 mips_debugger_offset (rtx addr, HOST_WIDE_INT offset)
05287 {
05288 rtx offset2 = const0_rtx;
05289 rtx reg = eliminate_constant_term (addr, &offset2);
05290
05291 if (offset == 0)
05292 offset = INTVAL (offset2);
05293
05294 if (reg == stack_pointer_rtx || reg == frame_pointer_rtx
05295 || reg == hard_frame_pointer_rtx)
05296 {
05297 HOST_WIDE_INT frame_size = (!cfun->machine->frame.initialized)
05298 ? compute_frame_size (get_frame_size ())
05299 : cfun->machine->frame.total_size;
05300
05301
05302 if (frame_pointer_needed && TARGET_MIPS16)
05303 frame_size -= cfun->machine->frame.args_size;
05304
05305 offset = offset - frame_size;
05306 }
05307
05308
05309 #if 0
05310 else if (reg != arg_pointer_rtx)
05311 fatal_insn ("mips_debugger_offset called with non stack/frame/arg pointer",
05312 addr);
05313 #endif
05314
05315 return offset;
05316 }
05317
05318
05319
05320
05321
05322
05323
05324
05325
05326
05327
05328
05329
05330
05331
05332
05333
05334
05335
05336
05337
05338
05339
05340
05341
05342
05343
05344
05345
05346
05347
05348
05349
05350
05351
05352
05353
05354
05355
05356
05357
05358
05359
05360
05361
05362
05363 void
05364 print_operand (FILE *file, rtx op, int letter)
05365 {
05366 register enum rtx_code code;
05367
05368 if (PRINT_OPERAND_PUNCT_VALID_P (letter))
05369 {
05370 switch (letter)
05371 {
05372 case '?':
05373 if (mips_branch_likely)
05374 putc ('l', file);
05375 break;
05376
05377 case '@':
05378 fputs (reg_names [GP_REG_FIRST + 1], file);
05379 break;
05380
05381 case '^':
05382 fputs (reg_names [PIC_FUNCTION_ADDR_REGNUM], file);
05383 break;
05384
05385 case '.':
05386 fputs (reg_names [GP_REG_FIRST + 0], file);
05387 break;
05388
05389 case '$':
05390 fputs (reg_names[STACK_POINTER_REGNUM], file);
05391 break;
05392
05393 case '+':
05394 fputs (reg_names[PIC_OFFSET_TABLE_REGNUM], file);
05395 break;
05396
05397 case '&':
05398 if (final_sequence != 0 && set_noreorder++ == 0)
05399 fputs (".set\tnoreorder\n\t", file);
05400 break;
05401
05402 case '*':
05403 if (final_sequence != 0)
05404 {
05405 if (set_noreorder++ == 0)
05406 fputs (".set\tnoreorder\n\t", file);
05407
05408 if (set_nomacro++ == 0)
05409 fputs (".set\tnomacro\n\t", file);
05410 }
05411 break;
05412
05413 case '!':
05414 if (final_sequence != 0 && set_nomacro++ == 0)
05415 fputs ("\n\t.set\tnomacro", file);
05416 break;
05417
05418 case '#':
05419 if (set_noreorder != 0)
05420 fputs ("\n\tnop", file);
05421 break;
05422
05423 case '/':
05424
05425
05426
05427 if (set_noreorder != 0 && final_sequence == 0)
05428 fputs ("\n\tnop\n", file);
05429 break;
05430
05431 case '(':
05432 if (set_noreorder++ == 0)
05433 fputs (".set\tnoreorder\n\t", file);
05434 break;
05435
05436 case ')':
05437 if (set_noreorder == 0)
05438 error ("internal error: %%) found without a %%( in assembler pattern");
05439
05440 else if (--set_noreorder == 0)
05441 fputs ("\n\t.set\treorder", file);
05442
05443 break;
05444
05445 case '[':
05446 if (set_noat++ == 0)
05447 fputs (".set\tnoat\n\t", file);
05448 break;
05449
05450 case ']':
05451 if (set_noat == 0)
05452 error ("internal error: %%] found without a %%[ in assembler pattern");
05453 else if (--set_noat == 0)
05454 fputs ("\n\t.set\tat", file);
05455
05456 break;
05457
05458 case '<':
05459 if (set_nomacro++ == 0)
05460 fputs (".set\tnomacro\n\t", file);
05461 break;
05462
05463 case '>':
05464 if (set_nomacro == 0)
05465 error ("internal error: %%> found without a %%< in assembler pattern");
05466 else if (--set_nomacro == 0)
05467 fputs ("\n\t.set\tmacro", file);
05468
05469 break;
05470
05471 case '{':
05472 if (set_volatile++ == 0)
05473 fputs ("#.set\tvolatile\n\t", file);
05474 break;
05475
05476 case '}':
05477 if (set_volatile == 0)
05478 error ("internal error: %%} found without a %%{ in assembler pattern");
05479 else if (--set_volatile == 0)
05480 fputs ("\n\t#.set\tnovolatile", file);
05481
05482 break;
05483
05484 case '~':
05485 {
05486 if (align_labels_log > 0)
05487 ASM_OUTPUT_ALIGN (file, align_labels_log);
05488 }
05489 break;
05490
05491 default:
05492 error ("PRINT_OPERAND: unknown punctuation '%c'", letter);
05493 break;
05494 }
05495
05496 return;
05497 }
05498
05499 if (! op)
05500 {
05501 error ("PRINT_OPERAND null pointer");
05502 return;
05503 }
05504
05505 code = GET_CODE (op);
05506
05507 if (letter == 'C')
05508 switch (code)
05509 {
05510 case EQ: fputs ("eq", file); break;
05511 case NE: fputs ("ne", file); break;
05512 case GT: fputs ("gt", file); break;
05513 case GE: fputs ("ge", file); break;
05514 case LT: fputs ("lt", file); break;
05515 case LE: fputs ("le", file); break;
05516 case GTU: fputs ("gtu", file); break;
05517 case GEU: fputs ("geu", file); break;
05518 case LTU: fputs ("ltu", file); break;
05519 case LEU: fputs ("leu", file); break;
05520 default:
05521 fatal_insn ("PRINT_OPERAND, invalid insn for %%C", op);
05522 }
05523
05524 else if (letter == 'N')
05525 switch (code)
05526 {
05527 case EQ: fputs ("ne", file); break;
05528 case NE: fputs ("eq", file); break;
05529 case GT: fputs ("le", file); break;
05530 case GE: fputs ("lt", file); break;
05531 case LT: fputs ("ge", file); break;
05532 case LE: fputs ("gt", file); break;
05533 case GTU: fputs ("leu", file); break;
05534 case GEU: fputs ("ltu", file); break;
05535 case LTU: fputs ("geu", file); break;
05536 case LEU: fputs ("gtu", file); break;
05537 default:
05538 fatal_insn ("PRINT_OPERAND, invalid insn for %%N", op);
05539 }
05540
05541 else if (letter == 'F')
05542 switch (code)
05543 {
05544 case EQ: fputs ("c1f", file); break;
05545 case NE: fputs ("c1t", file); break;
05546 default:
05547 fatal_insn ("PRINT_OPERAND, invalid insn for %%F", op);
05548 }
05549
05550 else if (letter == 'W')
05551 switch (code)
05552 {
05553 case EQ: fputs ("c1t", file); break;
05554 case NE: fputs ("c1f", file); break;
05555 default:
05556 fatal_insn ("PRINT_OPERAND, invalid insn for %%W", op);
05557 }
05558
05559 else if (letter == 'h')
05560 {
05561 if (GET_CODE (op) == HIGH)
05562 op = XEXP (op, 0);
05563
05564 print_operand_reloc (file, op, mips_hi_relocs);
05565 }
05566
05567 else if (letter == 'R')
05568 print_operand_reloc (file, op, mips_lo_relocs);
05569
05570 else if (letter == 'Y')
05571 {
05572 if (GET_CODE (op) == CONST_INT
05573 && ((unsigned HOST_WIDE_INT) INTVAL (op)
05574 < ARRAY_SIZE (mips_fp_conditions)))
05575 fputs (mips_fp_conditions[INTVAL (op)], file);
05576 else
05577 output_operand_lossage ("invalid %%Y value");
05578 }
05579
05580 else if (letter == 'Z')
05581 {
05582 if (ISA_HAS_8CC)
05583 {
05584 print_operand (file, op, 0);
05585 fputc (',', file);
05586 }
05587 }
05588
05589 else if (letter == 'q')
05590 {
05591 int regnum;
05592
05593 if (code != REG)
05594 fatal_insn ("PRINT_OPERAND, invalid insn for %%q", op);
05595
05596 regnum = REGNO (op);
05597 if (MD_REG_P (regnum))
05598 fprintf (file, "$ac0");
05599 else if (DSP_ACC_REG_P (regnum))
05600 fprintf (file, "$ac%c", reg_names[regnum][3]);
05601 else
05602 fatal_insn ("PRINT_OPERAND, invalid insn for %%q", op);
05603 }
05604
05605 else if (code == REG || code == SUBREG)
05606 {
05607 register int regnum;
05608
05609 if (code == REG)
05610 regnum = REGNO (op);
05611 else
05612 regnum = true_regnum (op);
05613
05614 if ((letter == 'M' && ! WORDS_BIG_ENDIAN)
05615 || (letter == 'L' && WORDS_BIG_ENDIAN)
05616 || letter == 'D')
05617 regnum++;
05618
05619 fprintf (file, "%s", reg_names[regnum]);
05620 }
05621
05622 else if (code == MEM)
05623 {
05624 if (letter == 'D')
05625 output_address (plus_constant (XEXP (op, 0), 4));
05626 else
05627 output_address (XEXP (op, 0));
05628 }
05629
05630 else if (letter == 'x' && GET_CODE (op) == CONST_INT)
05631 fprintf (file, HOST_WIDE_INT_PRINT_HEX, 0xffff & INTVAL(op));
05632
05633 else if (letter == 'X' && GET_CODE(op) == CONST_INT)
05634 fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (op));
05635
05636 else if (letter == 'd' && GET_CODE(op) == CONST_INT)
05637 fprintf (file, HOST_WIDE_INT_PRINT_DEC, (INTVAL(op)));
05638
05639 else if (letter == 'z' && op == CONST0_RTX (GET_MODE (op)))
05640 fputs (reg_names[GP_REG_FIRST], file);
05641
05642 else if (letter == 'd' || letter == 'x' || letter == 'X')
05643 output_operand_lossage ("invalid use of %%d, %%x, or %%X");
05644
05645 else if (letter == 'T' || letter == 't')
05646 {
05647 int truth = (code == NE) == (letter == 'T');
05648 fputc ("zfnt"[truth * 2 + (GET_MODE (op) == CCmode)], file);
05649 }
05650
05651 else if (CONST_GP_P (op))
05652 fputs (reg_names[GLOBAL_POINTER_REGNUM], file);
05653
05654 else
05655 output_addr_const (file, op);
05656 }
05657
05658
05659
05660
05661
05662 static void
05663 print_operand_reloc (FILE *file, rtx op, const char **relocs)
05664 {
05665 enum mips_symbol_type symbol_type;
05666 const char *p;
05667 rtx base;
05668 HOST_WIDE_INT offset;
05669
05670 if (!mips_symbolic_constant_p (op, &symbol_type) || relocs[symbol_type] == 0)
05671 fatal_insn ("PRINT_OPERAND, invalid operand for relocation", op);
05672
05673
05674 mips_split_const (op, &base, &offset);
05675 if (UNSPEC_ADDRESS_P (base))
05676 op = plus_constant (UNSPEC_ADDRESS (base), offset);
05677
05678 fputs (relocs[symbol_type], file);
05679 output_addr_const (file, op);
05680 for (p = relocs[symbol_type]; *p != 0; p++)
05681 if (*p == '(')
05682 fputc (')', file);
05683 }
05684
05685
05686
05687 void
05688 print_operand_address (FILE *file, rtx x)
05689 {
05690 struct mips_address_info addr;
05691
05692 if (mips_classify_address (&addr, x, word_mode, true))
05693 switch (addr.type)
05694 {
05695 case ADDRESS_REG:
05696 print_operand (file, addr.offset, 0);
05697 fprintf (file, "(%s)", reg_names[REGNO (addr.reg)]);
05698 return;
05699
05700 case ADDRESS_LO_SUM:
05701 print_operand (file, addr.offset, 'R');
05702 fprintf (file, "(%s)", reg_names[REGNO (addr.reg)]);
05703 return;
05704
05705 case ADDRESS_CONST_INT:
05706 output_addr_const (file, x);
05707 fprintf (file, "(%s)", reg_names[0]);
05708 return;
05709
05710 case ADDRESS_SYMBOLIC:
05711 output_addr_const (file, x);
05712 return;
05713 }
05714 gcc_unreachable ();
05715 }
05716
05717
05718
05719
05720
05721
05722
05723
05724
05725 int
05726 mips_output_external (FILE *file ATTRIBUTE_UNUSED, tree decl, const char *name)
05727 {
05728 register struct extern_list *p;
05729
05730 if (!TARGET_EXPLICIT_RELOCS && mips_in_small_data_p (decl))
05731 {
05732 p = (struct extern_list *) ggc_alloc (sizeof (struct extern_list));
05733 p->next = extern_head;
05734 p->name = name;
05735 p->size = int_size_in_bytes (TREE_TYPE (decl));
05736 extern_head = p;
05737 }
05738
05739 if (TARGET_IRIX && mips_abi == ABI_32 && TREE_CODE (decl) == FUNCTION_DECL)
05740 {
05741 p = (struct extern_list *) ggc_alloc (sizeof (struct extern_list));
05742 p->next = extern_head;
05743 p->name = name;
05744 p->size = -1;
05745 extern_head = p;
05746 }
05747
05748 return 0;
05749 }
05750
05751 #if TARGET_IRIX
05752 static void
05753 irix_output_external_libcall (rtx fun)
05754 {
05755 register struct extern_list *p;
05756
05757 if (mips_abi == ABI_32)
05758 {
05759 p = (struct extern_list *) ggc_alloc (sizeof (struct extern_list));
05760 p->next = extern_head;
05761 p->name = XSTR (fun, 0);
05762 p->size = -1;
05763 extern_head = p;
05764 }
05765 }
05766 #endif
05767
05768
05769
05770
05771 void
05772 mips_output_filename (FILE *stream, const char *name)
05773 {
05774
05775
05776
05777 if (write_symbols == DWARF2_DEBUG)
05778 return;
05779 else if (mips_output_filename_first_time)
05780 {
05781 mips_output_filename_first_time = 0;
05782 num_source_filenames += 1;
05783 current_function_file = name;
05784 fprintf (stream, "\t.file\t%d ", num_source_filenames);
05785 output_quoted_string (stream, name);
05786 putc ('\n', stream);
05787 }
05788
05789
05790
05791 else if (write_symbols == DBX_DEBUG)
05792 return;
05793
05794 else if (name != current_function_file
05795 && strcmp (name, current_function_file) != 0)
05796 {
05797 num_source_filenames += 1;
05798 current_function_file = name;
05799 fprintf (stream, "\t.file\t%d ", num_source_filenames);
05800 output_quoted_string (stream, name);
05801 putc ('\n', stream);
05802 }
05803 }
05804
05805
05806
05807
05808
05809 void
05810 mips_output_ascii (FILE *stream, const char *string_param, size_t len,
05811 const char *prefix)
05812 {
05813 size_t i;
05814 int cur_pos = 17;
05815 register const unsigned char *string =
05816 (const unsigned char *)string_param;
05817
05818 fprintf (stream, "%s\"", prefix);
05819 for (i = 0; i < len; i++)
05820 {
05821 register int c = string[i];
05822
05823 if (ISPRINT (c))
05824 {
05825 if (c == '\\' || c == '\"')
05826 {
05827 putc ('\\', stream);
05828 cur_pos++;
05829 }
05830 putc (c, stream);
05831 cur_pos++;
05832 }
05833 else
05834 {
05835 fprintf (stream, "\\%03o", c);
05836 cur_pos += 4;
05837 }
05838
05839 if (cur_pos > 72 && i+1 < len)
05840 {
05841 cur_pos = 17;
05842 fprintf (stream, "\"\n%s\"", prefix);
05843 }
05844 }
05845 fprintf (stream, "\"\n");
05846 }
05847
05848
05849
05850 static void
05851 mips_file_start (void)
05852 {
05853 default_file_start ();
05854
05855 if (!TARGET_IRIX)
05856 {
05857
05858
05859
05860
05861
05862
05863
05864 const char * abi_string = NULL;
05865
05866 switch (mips_abi)
05867 {
05868 case ABI_32: abi_string = "abi32"; break;
05869 case ABI_N32: abi_string = "abiN32"; break;
05870 case ABI_64: abi_string = "abi64"; break;
05871 case ABI_O64: abi_string = "abiO64"; break;
05872 case ABI_EABI: abi_string = TARGET_64BIT ? "eabi64" : "eabi32"; break;
05873 default:
05874 gcc_unreachable ();
05875 }
05876
05877
05878
05879
05880 fprintf (asm_out_file, "\t.section .mdebug.%s\n", abi_string);
05881
05882
05883
05884
05885
05886 if (mips_abi == ABI_EABI || mips_abi == ABI_O64)
05887 fprintf (asm_out_file, "\t.section .gcc_compiled_long%d\n",
05888 TARGET_LONG64 ? 64 : 32);
05889
05890
05891 fprintf (asm_out_file, "\t.previous\n");
05892 }
05893
05894
05895 if (TARGET_ABICALLS)
05896 fprintf (asm_out_file, "\t.abicalls\n");
05897
05898 if (TARGET_MIPS16)
05899 fprintf (asm_out_file, "\t.set\tmips16\n");
05900
05901 if (flag_verbose_asm)
05902 fprintf (asm_out_file, "\n%s -G value = %d, Arch = %s, ISA = %d\n",
05903 ASM_COMMENT_START,
05904 mips_section_threshold, mips_arch_info->name, mips_isa);
05905 }
05906
05907 #ifdef BSS_SECTION_ASM_OP
05908
05909
05910
05911 void
05912 mips_output_aligned_bss (FILE *stream, tree decl, const char *name,
05913 unsigned HOST_WIDE_INT size, int align)
05914 {
05915 extern tree last_assemble_variable_decl;
05916
05917 if (mips_in_small_data_p (decl))
05918 switch_to_section (get_named_section (NULL, ".sbss", 0));
05919 else
05920 switch_to_section (bss_section);
05921 ASM_OUTPUT_ALIGN (stream, floor_log2 (align / BITS_PER_UNIT));
05922 last_assemble_variable_decl = decl;
05923 ASM_DECLARE_OBJECT_NAME (stream, name, decl);
05924 ASM_OUTPUT_SKIP (stream, size != 0 ? size : 1);
05925 }
05926 #endif
05927
05928
05929
05930
05931 static void
05932 mips_file_end (void)
05933 {
05934 tree name_tree;
05935 struct extern_list *p;
05936
05937 if (extern_head)
05938 {
05939 fputs ("\n", asm_out_file);
05940
05941 for (p = extern_head; p != 0; p = p->next)
05942 {
05943 name_tree = get_identifier (p->name);
05944
05945
05946 if (!TREE_ASM_WRITTEN (name_tree)
05947 && TREE_SYMBOL_REFERENCED (name_tree))
05948 {
05949 TREE_ASM_WRITTEN (name_tree) = 1;
05950
05951
05952
05953
05954
05955 if (TARGET_IRIX && mips_abi == ABI_32 && p->size == -1)
05956 {
05957 fputs ("\t.globl ", asm_out_file);
05958 assemble_name (asm_out_file, p->name);
05959 fputs (" .text\n", asm_out_file);
05960 }
05961 else
05962 {
05963 fputs ("\t.extern\t", asm_out_file);
05964 assemble_name (asm_out_file, p->name);
05965 fprintf (asm_out_file, ", %d\n", p->size);
05966 }
05967 }
05968 }
05969 }
05970 }
05971
05972
05973
05974
05975 void
05976 mips_output_aligned_decl_common (FILE *stream, tree decl, const char *name,
05977 unsigned HOST_WIDE_INT size,
05978 unsigned int align)
05979 {
05980
05981
05982 if (TARGET_EMBEDDED_DATA && TARGET_UNINIT_CONST_IN_RODATA
05983 && TREE_CODE (decl) == VAR_DECL && TREE_READONLY (decl)
05984 && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node))
05985 {
05986 if (TREE_PUBLIC (decl) && DECL_NAME (decl))
05987 targetm.asm_out.globalize_label (stream, name);
05988
05989 switch_to_section (readonly_data_section);
05990 ASM_OUTPUT_ALIGN (stream, floor_log2 (align / BITS_PER_UNIT));
05991 mips_declare_object (stream, name, "",
05992 ":\n\t.space\t" HOST_WIDE_INT_PRINT_UNSIGNED "\n",
05993 size);
05994 }
05995 else
05996 mips_declare_common_object (stream, name, "\n\t.comm\t",
05997 size, align, true);
05998 }
05999
06000
06001
06002
06003
06004
06005 void
06006 mips_declare_common_object (FILE *stream, const char *name,
06007 const char *init_string,
06008 unsigned HOST_WIDE_INT size,
06009 unsigned int align, bool takes_alignment_p)
06010 {
06011 if (!takes_alignment_p)
06012 {
06013 size += (align / BITS_PER_UNIT) - 1;
06014 size -= size % (align / BITS_PER_UNIT);
06015 mips_declare_object (stream, name, init_string,
06016 "," HOST_WIDE_INT_PRINT_UNSIGNED "\n", size);
06017 }
06018 else
06019 mips_declare_object (stream, name, init_string,
06020 "," HOST_WIDE_INT_PRINT_UNSIGNED ",%u\n",
06021 size, align / BITS_PER_UNIT);
06022 }
06023
06024
06025
06026
06027
06028
06029
06030
06031 void
06032 mips_declare_object (FILE *stream, const char *name, const char *init_string,
06033 const char *final_string, ...)
06034 {
06035 va_list ap;
06036
06037 fputs (init_string, stream);
06038 assemble_name (stream, name);
06039 va_start (ap, final_string);
06040 vfprintf (stream, final_string, ap);
06041 va_end (ap);
06042
06043 if (!TARGET_EXPLICIT_RELOCS)
06044 {
06045 tree name_tree = get_identifier (name);
06046 TREE_ASM_WRITTEN (name_tree) = 1;
06047 }
06048 }
06049
06050 #ifdef ASM_OUTPUT_SIZE_DIRECTIVE
06051 extern int size_directive_output;
06052
06053
06054
06055
06056 void
06057 mips_declare_object_name (FILE *stream, const char *name,
06058 tree decl ATTRIBUTE_UNUSED)
06059 {
06060 #ifdef ASM_OUTPUT_TYPE_DIRECTIVE
06061 ASM_OUTPUT_TYPE_DIRECTIVE (stream, name, "object");
06062 #endif
06063
06064 size_directive_output = 0;
06065 if (!flag_inhibit_size_directive && DECL_SIZE (decl))
06066 {
06067 HOST_WIDE_INT size;
06068
06069 size_directive_output = 1;
06070 size = int_size_in_bytes (TREE_TYPE (decl));
06071 ASM_OUTPUT_SIZE_DIRECTIVE (stream, name, size);
06072 }
06073
06074 mips_declare_object (stream, name, "", ":\n");
06075 }
06076
06077
06078
06079 void
06080 mips_finish_declare_object (FILE *stream, tree decl, int top_level, int at_end)
06081 {
06082 const char *name;
06083
06084 name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
06085 if (!flag_inhibit_size_directive
06086 && DECL_SIZE (decl) != 0
06087 && !at_end && top_level
06088 && DECL_INITIAL (decl) == error_mark_node
06089 && !size_directive_output)
06090 {
06091 HOST_WIDE_INT size;
06092
06093 size_directive_output = 1;
06094 size = int_size_in_bytes (TREE_TYPE (decl));
06095 ASM_OUTPUT_SIZE_DIRECTIVE (stream, name, size);
06096 }
06097 }
06098 #endif
06099
06100
06101
06102
06103 static bool
06104 mips_rewrite_small_data_p (rtx x)
06105 {
06106 enum mips_symbol_type symbol_type;
06107
06108 return (TARGET_EXPLICIT_RELOCS
06109 && mips_symbolic_constant_p (x, &symbol_type)
06110 && symbol_type == SYMBOL_SMALL_DATA);
06111 }
06112
06113
06114
06115
06116 static int
06117 mips_small_data_pattern_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
06118 {
06119 if (GET_CODE (*loc) == LO_SUM)
06120 return -1;
06121
06122 return mips_rewrite_small_data_p (*loc);
06123 }
06124
06125
06126
06127
06128 bool
06129 mips_small_data_pattern_p (rtx op)
06130 {
06131 return for_each_rtx (&op, mips_small_data_pattern_1, 0);
06132 }
06133
06134
06135
06136 static int
06137 mips_rewrite_small_data_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
06138 {
06139 if (mips_rewrite_small_data_p (*loc))
06140 *loc = gen_rtx_LO_SUM (Pmode, pic_offset_table_rtx, *loc);
06141
06142 if (GET_CODE (*loc) == LO_SUM)
06143 return -1;
06144
06145 return 0;
06146 }
06147
06148
06149
06150
06151 rtx
06152 mips_rewrite_small_data (rtx op)
06153 {
06154 op = copy_insn (op);
06155 for_each_rtx (&op, mips_rewrite_small_data_1, 0);
06156 return op;
06157 }
06158
06159
06160
06161
06162 static bool
06163 mips_function_has_gp_insn (void)
06164 {
06165
06166 if (!cfun->machine->has_gp_insn_p)
06167 {
06168 rtx insn;
06169
06170 push_topmost_sequence ();
06171 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
06172 if (INSN_P (insn)
06173 && GET_CODE (PATTERN (insn)) != USE
06174 && GET_CODE (PATTERN (insn)) != CLOBBER
06175 && (get_attr_got (insn) != GOT_UNSET
06176 || small_data_pattern (PATTERN (insn), VOIDmode)))
06177 break;
06178 pop_topmost_sequence ();
06179
06180 cfun->machine->has_gp_insn_p = (insn != 0);
06181 }
06182 return cfun->machine->has_gp_insn_p;
06183 }
06184
06185
06186
06187
06188
06189
06190 static unsigned int
06191 mips_global_pointer (void)
06192 {
06193 unsigned int regno;
06194
06195
06196 if (!TARGET_ABICALLS)
06197 return GLOBAL_POINTER_REGNUM;
06198
06199
06200 if (!TARGET_EXPLICIT_RELOCS)
06201 return GLOBAL_POINTER_REGNUM;
06202
06203
06204
06205 if (current_function_profile)
06206 return GLOBAL_POINTER_REGNUM;
06207
06208
06209
06210 if (current_function_has_nonlocal_goto)
06211 return GLOBAL_POINTER_REGNUM;
06212
06213
06214
06215
06216
06217
06218
06219
06220
06221
06222
06223
06224
06225
06226 if (!regs_ever_live[GLOBAL_POINTER_REGNUM]
06227 && !current_function_uses_const_pool
06228 && !mips_function_has_gp_insn ())
06229 return 0;
06230
06231
06232
06233 if (TARGET_NEWABI && current_function_is_leaf)
06234 for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
06235 if (!regs_ever_live[regno]
06236 && call_used_regs[regno]
06237 && !fixed_regs[regno]
06238 && regno != PIC_FUNCTION_ADDR_REGNUM)
06239 return regno;
06240
06241 return GLOBAL_POINTER_REGNUM;
06242 }
06243
06244
06245
06246
06247 static bool
06248 mips_save_reg_p (unsigned int regno)
06249 {
06250
06251 if (regno == GLOBAL_POINTER_REGNUM)
06252 return (TARGET_ABICALLS && TARGET_NEWABI
06253 && cfun->machine->global_pointer == regno);
06254
06255
06256 if (regs_ever_live[regno] && !call_used_regs[regno])
06257 return true;
06258
06259
06260 if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
06261 return true;
06262
06263
06264
06265 if (regno == GP_REG_FIRST + 31 && regs_ever_live[regno])
06266 return true;
06267
06268 if (TARGET_MIPS16)
06269 {
06270 tree return_type;
06271
06272 return_type = DECL_RESULT (current_function_decl);
06273
06274
06275
06276
06277 if (regno == GP_REG_FIRST + 18 && regs_ever_live[regno])
06278 return true;
06279
06280
06281
06282
06283 if (regno == GP_REG_FIRST + 31
06284 && mips16_hard_float
06285 && !aggregate_value_p (return_type, current_function_decl)
06286 && GET_MODE_CLASS (DECL_MODE (return_type)) == MODE_FLOAT
06287 && GET_MODE_SIZE (DECL_MODE (return_type)) <= UNITS_PER_FPVALUE)
06288 return true;
06289 }
06290
06291 return false;
06292 }
06293
06294
06295
06296
06297
06298
06299
06300
06301
06302
06303
06304
06305
06306
06307
06308
06309
06310
06311
06312
06313
06314
06315
06316
06317
06318
06319
06320
06321
06322
06323
06324
06325
06326
06327
06328
06329
06330
06331
06332
06333
06334
06335
06336
06337
06338
06339
06340
06341
06342
06343
06344
06345
06346
06347
06348 HOST_WIDE_INT
06349 compute_frame_size (HOST_WIDE_INT size)
06350 {
06351 unsigned int regno;
06352 HOST_WIDE_INT total_size;
06353 HOST_WIDE_INT var_size;
06354 HOST_WIDE_INT args_size;
06355 HOST_WIDE_INT cprestore_size;
06356 HOST_WIDE_INT gp_reg_rounded;
06357 HOST_WIDE_INT gp_reg_size;
06358 HOST_WIDE_INT fp_reg_size;
06359 unsigned int mask;
06360 unsigned int fmask;
06361
06362 cfun->machine->global_pointer = mips_global_pointer ();
06363
06364 gp_reg_size = 0;
06365 fp_reg_size = 0;
06366 mask = 0;
06367 fmask = 0;
06368 var_size = MIPS_STACK_ALIGN (size);
06369 args_size = current_function_outgoing_args_size;
06370 cprestore_size = MIPS_STACK_ALIGN (STARTING_FRAME_OFFSET) - args_size;
06371
06372
06373
06374
06375 if (var_size == 0 && current_function_is_leaf)
06376 cprestore_size = args_size = 0;
06377
06378
06379
06380
06381
06382
06383 if (args_size == 0 && current_function_calls_alloca)
06384 args_size = 4 * UNITS_PER_WORD;
06385
06386 total_size = var_size + args_size + cprestore_size;
06387
06388
06389 for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
06390 if (mips_save_reg_p (regno))
06391 {
06392 gp_reg_size += GET_MODE_SIZE (gpr_mode);
06393 mask |= 1 << (regno - GP_REG_FIRST);
06394 }
06395
06396
06397 if (current_function_calls_eh_return)
06398 {
06399 unsigned int i;
06400 for (i = 0; ; ++i)
06401 {
06402 regno = EH_RETURN_DATA_REGNO (i);
06403 if (regno == INVALID_REGNUM)
06404 break;
06405 gp_reg_size += GET_MODE_SIZE (gpr_mode);
06406 mask |= 1 << (regno - GP_REG_FIRST);
06407 }
06408 }
06409
06410
06411
06412 for (regno = (FP_REG_LAST - FP_INC + 1);
06413 regno >= FP_REG_FIRST;
06414 regno -= FP_INC)
06415 {
06416 if (mips_save_reg_p (regno))
06417 {
06418 fp_reg_size += FP_INC * UNITS_PER_FPREG;
06419 fmask |= ((1 << FP_INC) - 1) << (regno - FP_REG_FIRST);
06420 }
06421 }
06422
06423 gp_reg_rounded = MIPS_STACK_ALIGN (gp_reg_size);
06424 total_size += gp_reg_rounded + MIPS_STACK_ALIGN (fp_reg_size);
06425
06426
06427 total_size += current_function_pretend_args_size;
06428 total_size += MIPS_STACK_ALIGN (cfun->machine->varargs_size);
06429
06430
06431 cfun->machine->frame.total_size = total_size;
06432 cfun->machine->frame.var_size = var_size;
06433 cfun->machine->frame.args_size = args_size;
06434 cfun->machine->frame.cprestore_size = cprestore_size;
06435 cfun->machine->frame.gp_reg_size = gp_reg_size;
06436 cfun->machine->frame.fp_reg_size = fp_reg_size;
06437 cfun->machine->frame.mask = mask;
06438 cfun->machine->frame.fmask = fmask;
06439 cfun->machine->frame.initialized = reload_completed;
06440 cfun->machine->frame.num_gp = gp_reg_size / UNITS_PER_WORD;
06441 cfun->machine->frame.num_fp = fp_reg_size / (FP_INC * UNITS_PER_FPREG);
06442
06443 if (mask)
06444 {
06445 HOST_WIDE_INT offset;
06446
06447 offset = (args_size + cprestore_size + var_size
06448 + gp_reg_size - GET_MODE_SIZE (gpr_mode));
06449 cfun->machine->frame.gp_sp_offset = offset;
06450 cfun->machine->frame.gp_save_offset = offset - total_size;
06451 }
06452 else
06453 {
06454 cfun->machine->frame.gp_sp_offset = 0;
06455 cfun->machine->frame.gp_save_offset = 0;
06456 }
06457
06458 if (fmask)
06459 {
06460 HOST_WIDE_INT offset;
06461
06462 offset = (args_size + cprestore_size + var_size
06463 + gp_reg_rounded + fp_reg_size
06464 - FP_INC * UNITS_PER_FPREG);
06465 cfun->machine->frame.fp_sp_offset = offset;
06466 cfun->machine->frame.fp_save_offset = offset - total_size;
06467 }
06468 else
06469 {
06470 cfun->machine->frame.fp_sp_offset = 0;
06471 cfun->machine->frame.fp_save_offset = 0;
06472 }
06473
06474
06475 return total_size;
06476 }
06477
06478
06479
06480
06481
06482 HOST_WIDE_INT
06483 mips_initial_elimination_offset (int from, int to)
06484 {
06485 HOST_WIDE_INT offset;
06486
06487 compute_frame_size (get_frame_size ());
06488
06489
06490 switch (from)
06491 {
06492 case FRAME_POINTER_REGNUM:
06493 offset = 0;
06494 break;
06495
06496 case ARG_POINTER_REGNUM:
06497 offset = (cfun->machine->frame.total_size
06498 - current_function_pretend_args_size);
06499 break;
06500
06501 default:
06502 gcc_unreachable ();
06503 }
06504
06505 if (TARGET_MIPS16 && to == HARD_FRAME_POINTER_REGNUM)
06506 offset -= cfun->machine->frame.args_size;
06507
06508 return offset;
06509 }
06510
06511
06512
06513 rtx
06514 mips_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
06515 {
06516 if (count != 0)
06517 return const0_rtx;
06518
06519 return get_hard_reg_initial_val (Pmode, GP_REG_FIRST + 31);
06520 }
06521
06522
06523
06524
06525
06526 static void
06527 mips_save_restore_reg (enum machine_mode mode, int regno,
06528 HOST_WIDE_INT offset, mips_save_restore_fn fn)
06529 {
06530 rtx mem;
06531
06532 mem = gen_frame_mem (mode, plus_constant (stack_pointer_rtx, offset));
06533
06534 fn (gen_rtx_REG (mode, regno), mem);
06535 }
06536
06537
06538
06539
06540
06541
06542 static void
06543 mips_for_each_saved_reg (HOST_WIDE_INT sp_offset, mips_save_restore_fn fn)
06544 {
06545 #define BITSET_P(VALUE, BIT) (((VALUE) & (1L << (BIT))) != 0)
06546
06547 enum machine_mode fpr_mode;
06548 HOST_WIDE_INT offset;
06549 int regno;
06550
06551
06552
06553
06554
06555 offset = cfun->machine->frame.gp_sp_offset - sp_offset;
06556 for (regno = GP_REG_LAST; regno >= GP_REG_FIRST; regno--)
06557 if (BITSET_P (cfun->machine->frame.mask, regno - GP_REG_FIRST))
06558 {
06559 mips_save_restore_reg (gpr_mode, regno, offset, fn);
06560 offset -= GET_MODE_SIZE (gpr_mode);
06561 }
06562
06563
06564
06565 offset = cfun->machine->frame.fp_sp_offset - sp_offset;
06566 fpr_mode = (TARGET_SINGLE_FLOAT ? SFmode : DFmode);
06567 for (regno = (FP_REG_LAST - FP_INC + 1);
06568 regno >= FP_REG_FIRST;
06569 regno -= FP_INC)
06570 if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST))
06571 {
06572 mips_save_restore_reg (fpr_mode, regno, offset, fn);
06573 offset -= GET_MODE_SIZE (fpr_mode);
06574 }
06575 #undef BITSET_P
06576 }
06577
06578
06579
06580
06581
06582 static void
06583 mips_output_cplocal (void)
06584 {
06585 if (!TARGET_EXPLICIT_RELOCS
06586 && cfun->machine->global_pointer > 0
06587 && cfun->machine->global_pointer != GLOBAL_POINTER_REGNUM)
06588 output_asm_insn (".cplocal %+", 0);
06589 }
06590
06591
06592
06593
06594 enum mips_loadgp_style
06595 mips_current_loadgp_style (void)
06596 {
06597 if (!TARGET_ABICALLS || cfun->machine->global_pointer == 0)
06598 return LOADGP_NONE;
06599
06600 if (TARGET_ABSOLUTE_ABICALLS)
06601 return LOADGP_ABSOLUTE;
06602
06603 return TARGET_NEWABI ? LOADGP_NEWABI : LOADGP_OLDABI;
06604 }
06605
06606
06607
06608 static GTY(()) rtx mips_gnu_local_gp;
06609
06610
06611
06612
06613 static void
06614 mips_emit_loadgp (void)
06615 {
06616 rtx addr, offset, incoming_address;
06617
06618 switch (mips_current_loadgp_style ())
06619 {
06620 case LOADGP_ABSOLUTE:
06621 if (mips_gnu_local_gp == NULL)
06622 {
06623 mips_gnu_local_gp = gen_rtx_SYMBOL_REF (Pmode, "__gnu_local_gp");
06624 SYMBOL_REF_FLAGS (mips_gnu_local_gp) |= SYMBOL_FLAG_LOCAL;
06625 }
06626 emit_insn (gen_loadgp_noshared (mips_gnu_local_gp));
06627 break;
06628
06629 case LOADGP_NEWABI:
06630 addr = XEXP (DECL_RTL (current_function_decl), 0);
06631 offset = mips_unspec_address (addr, SYMBOL_GOTOFF_LOADGP);
06632 incoming_address = gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM);
06633 emit_insn (gen_loadgp (offset, incoming_address));
06634 if (!TARGET_EXPLICIT_RELOCS)
06635 emit_insn (gen_loadgp_blockage ());
06636 break;
06637
06638 default:
06639 break;
06640 }
06641 }
06642
06643
06644
06645 static void
06646 mips_output_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
06647 {
06648 const char *fnname;
06649 HOST_WIDE_INT tsize = cfun->machine->frame.total_size;
06650
06651 #ifdef SDB_DEBUGGING_INFO
06652 if (debug_info_level != DINFO_LEVEL_TERSE && write_symbols == SDB_DEBUG)
06653 SDB_OUTPUT_SOURCE_LINE (file, DECL_SOURCE_LINE (current_function_decl));
06654 #endif
06655
06656
06657
06658
06659
06660 if (TARGET_MIPS16 && !TARGET_SOFT_FLOAT
06661 && current_function_args_info.fp_code != 0)
06662 build_mips16_function_stub (file);
06663
06664 if (!FUNCTION_NAME_ALREADY_DECLARED)
06665 {
06666
06667
06668
06669 fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
06670
06671 if (!flag_inhibit_size_directive)
06672 {
06673 fputs ("\t.ent\t", file);
06674 assemble_name (file, fnname);
06675 fputs ("\n", file);
06676 }
06677
06678 assemble_name (file, fnname);
06679 fputs (":\n", file);
06680 }
06681
06682
06683 if (TARGET_IRIX && mips_abi == ABI_32)
06684 TREE_ASM_WRITTEN (DECL_NAME (cfun->decl)) = 1;
06685
06686 if (!flag_inhibit_size_directive)
06687 {
06688
06689 fprintf (file,
06690 "\t.frame\t%s," HOST_WIDE_INT_PRINT_DEC ",%s\t\t"
06691 "# vars= " HOST_WIDE_INT_PRINT_DEC ", regs= %d/%d"
06692 ", args= " HOST_WIDE_INT_PRINT_DEC
06693 ", gp= " HOST_WIDE_INT_PRINT_DEC "\n",
06694 (reg_names[(frame_pointer_needed)
06695 ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM]),
06696 ((frame_pointer_needed && TARGET_MIPS16)
06697 ? tsize - cfun->machine->frame.args_size
06698 : tsize),
06699 reg_names[GP_REG_FIRST + 31],
06700 cfun->machine->frame.var_size,
06701 cfun->machine->frame.num_gp,
06702 cfun->machine->frame.num_fp,
06703 cfun->machine->frame.args_size,
06704 cfun->machine->frame.cprestore_size);
06705
06706
06707 fprintf (file, "\t.mask\t0x%08x," HOST_WIDE_INT_PRINT_DEC "\n",
06708 cfun->machine->frame.mask,
06709 cfun->machine->frame.gp_save_offset);
06710 fprintf (file, "\t.fmask\t0x%08x," HOST_WIDE_INT_PRINT_DEC "\n",
06711 cfun->machine->frame.fmask,
06712 cfun->machine->frame.fp_save_offset);
06713
06714
06715
06716
06717 }
06718
06719 if (mips_current_loadgp_style () == LOADGP_OLDABI)
06720 {
06721
06722 if (!cfun->machine->all_noreorder_p)
06723 output_asm_insn ("%(.cpload\t%^%)", 0);
06724 else
06725 output_asm_insn ("%(.cpload\t%^\n\t%<", 0);
06726 }
06727 else if (cfun->machine->all_noreorder_p)
06728 output_asm_insn ("%(%<", 0);
06729
06730
06731
06732
06733 mips_output_cplocal ();
06734 }
06735
06736
06737
06738
06739 static void
06740 mips_set_frame_expr (rtx frame_pattern)
06741 {
06742 rtx insn;
06743
06744 insn = get_last_insn ();
06745 RTX_FRAME_RELATED_P (insn) = 1;
06746 REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR,
06747 frame_pattern,
06748 REG_NOTES (insn));
06749 }
06750
06751
06752
06753
06754
06755 static rtx
06756 mips_frame_set (rtx mem, rtx reg)
06757 {
06758 rtx set;
06759
06760
06761
06762
06763 if (REGNO (reg) == GP_REG_FIRST + 31
06764 && DWARF_FRAME_RETURN_COLUMN != GP_REG_FIRST + 31)
06765 reg = gen_rtx_REG (GET_MODE (reg), DWARF_FRAME_RETURN_COLUMN);
06766
06767 set = gen_rtx_SET (VOIDmode, mem, reg);
06768 RTX_FRAME_RELATED_P (set) = 1;
06769
06770 return set;
06771 }
06772
06773
06774
06775
06776 static void
06777 mips_save_reg (rtx reg, rtx mem)
06778 {
06779 if (GET_MODE (reg) == DFmode && !TARGET_FLOAT64)
06780 {
06781 rtx x1, x2;
06782
06783 if (mips_split_64bit_move_p (mem, reg))
06784 mips_split_64bit_move (mem, reg);
06785 else
06786 emit_move_insn (mem, reg);
06787
06788 x1 = mips_frame_set (mips_subword (mem, 0), mips_subword (reg, 0));
06789 x2 = mips_frame_set (mips_subword (mem, 1), mips_subword (reg, 1));
06790 mips_set_frame_expr (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, x1, x2)));
06791 }
06792 else
06793 {
06794 if (TARGET_MIPS16
06795 && REGNO (reg) != GP_REG_FIRST + 31
06796 && !M16_REG_P (REGNO (reg)))
06797 {
06798
06799
06800
06801 emit_move_insn (MIPS_PROLOGUE_TEMP (GET_MODE (reg)), reg);
06802 emit_move_insn (mem, MIPS_PROLOGUE_TEMP (GET_MODE (reg)));
06803 }
06804 else
06805 emit_move_insn (mem, reg);
06806
06807 mips_set_frame_expr (mips_frame_set (mem, reg));
06808 }
06809 }
06810
06811
06812
06813
06814 void
06815 mips_expand_prologue (void)
06816 {
06817 HOST_WIDE_INT size;
06818
06819 if (cfun->machine->global_pointer > 0)
06820 REGNO (pic_offset_table_rtx) = cfun->machine->global_pointer;
06821
06822 size = compute_frame_size (get_frame_size ());
06823
06824
06825
06826
06827 if ((cfun->machine->frame.mask | cfun->machine->frame.fmask) != 0)
06828 {
06829 HOST_WIDE_INT step1;
06830
06831 step1 = MIN (size, MIPS_MAX_FIRST_STACK_STEP);
06832 RTX_FRAME_RELATED_P (emit_insn (gen_add3_insn (stack_pointer_rtx,
06833 stack_pointer_rtx,
06834 GEN_INT (-step1)))) = 1;
06835 size -= step1;
06836 mips_for_each_saved_reg (size, mips_save_reg);
06837 }
06838
06839
06840 if (size > 0)
06841 {
06842 if (SMALL_OPERAND (-size))
06843 RTX_FRAME_RELATED_P (emit_insn (gen_add3_insn (stack_pointer_rtx,
06844 stack_pointer_rtx,
06845 GEN_INT (-size)))) = 1;
06846 else
06847 {
06848 emit_move_insn (MIPS_PROLOGUE_TEMP (Pmode), GEN_INT (size));
06849 if (TARGET_MIPS16)
06850 {
06851
06852
06853
06854
06855 gcc_assert (frame_pointer_needed);
06856 emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
06857 emit_insn (gen_sub3_insn (hard_frame_pointer_rtx,
06858 hard_frame_pointer_rtx,
06859 MIPS_PROLOGUE_TEMP (Pmode)));
06860 emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);
06861 }
06862 else
06863 emit_insn (gen_sub3_insn (stack_pointer_rtx,
06864 stack_pointer_rtx,
06865 MIPS_PROLOGUE_TEMP (Pmode)));
06866
06867
06868 mips_set_frame_expr
06869 (gen_rtx_SET (VOIDmode, stack_pointer_rtx,
06870 plus_constant (stack_pointer_rtx, -size)));
06871 }
06872 }
06873
06874
06875
06876
06877
06878 if (frame_pointer_needed)
06879 {
06880 if (TARGET_MIPS16 && cfun->machine->frame.args_size != 0)
06881 {
06882 rtx offset = GEN_INT (cfun->machine->frame.args_size);
06883 if (SMALL_OPERAND (cfun->machine->frame.args_size))
06884 RTX_FRAME_RELATED_P
06885 (emit_insn (gen_add3_insn (hard_frame_pointer_rtx,
06886 stack_pointer_rtx,
06887 offset))) = 1;
06888 else
06889 {
06890 emit_move_insn (MIPS_PROLOGUE_TEMP (Pmode), offset);
06891 emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
06892 emit_insn (gen_add3_insn (hard_frame_pointer_rtx,
06893 hard_frame_pointer_rtx,
06894 MIPS_PROLOGUE_TEMP (Pmode)));
06895 mips_set_frame_expr
06896 (gen_rtx_SET (VOIDmode, hard_frame_pointer_rtx,
06897 plus_constant (stack_pointer_rtx,
06898 cfun->machine->frame.args_size)));
06899 }
06900 }
06901 else
06902 RTX_FRAME_RELATED_P (emit_move_insn (hard_frame_pointer_rtx,
06903 stack_pointer_rtx)) = 1;
06904 }
06905
06906 mips_emit_loadgp ();
06907
06908
06909 if (TARGET_ABICALLS && !TARGET_NEWABI && !current_function_is_leaf)
06910 emit_insn (gen_cprestore (GEN_INT (current_function_outgoing_args_size)));
06911
06912
06913
06914
06915 if (current_function_profile)
06916 emit_insn (gen_blockage ());
06917 }
06918
06919
06920
06921
06922 #define RA_MASK BITMASK_HIGH
06923
06924 static void
06925 mips_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
06926 HOST_WIDE_INT size ATTRIBUTE_UNUSED)
06927 {
06928
06929 REGNO (pic_offset_table_rtx) = GLOBAL_POINTER_REGNUM;
06930 mips_output_cplocal ();
06931
06932 if (cfun->machine->all_noreorder_p)
06933 {
06934
06935 output_asm_insn (".set\tmacro", 0);
06936 output_asm_insn (".set\treorder", 0);
06937 set_noreorder = set_nomacro = 0;
06938 }
06939
06940 if (!FUNCTION_NAME_ALREADY_DECLARED && !flag_inhibit_size_directive)
06941 {
06942 const char *fnname;
06943
06944
06945
06946
06947 fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
06948 fputs ("\t.end\t", file);
06949 assemble_name (file, fnname);
06950 fputs ("\n", file);
06951 }
06952 }
06953
06954
06955
06956 static void
06957 mips_restore_reg (rtx reg, rtx mem)
06958 {
06959
06960
06961 if (TARGET_MIPS16 && REGNO (reg) == GP_REG_FIRST + 31)
06962 reg = gen_rtx_REG (GET_MODE (reg), 7);
06963
06964 if (TARGET_MIPS16 && !M16_REG_P (REGNO (reg)))
06965 {
06966
06967 emit_move_insn (MIPS_EPILOGUE_TEMP (GET_MODE (reg)), mem);
06968 emit_move_insn (reg, MIPS_EPILOGUE_TEMP (GET_MODE (reg)));
06969 }
06970 else
06971 emit_move_insn (reg, mem);
06972 }
06973
06974
06975
06976
06977
06978
06979 void
06980 mips_expand_epilogue (int sibcall_p)
06981 {
06982 HOST_WIDE_INT step1, step2;
06983 rtx base, target;
06984
06985 if (!sibcall_p && mips_can_use_return_insn ())
06986 {
06987 emit_jump_insn (gen_return ());
06988 return;
06989 }
06990
06991
06992
06993
06994
06995
06996 step1 = cfun->machine->frame.total_size;
06997 step2 = 0;
06998
06999
07000
07001 if (!frame_pointer_needed)
07002 base = stack_pointer_rtx;
07003 else
07004 {
07005 base = hard_frame_pointer_rtx;
07006 if (TARGET_MIPS16)
07007 step1 -= cfun->machine->frame.args_size;
07008 }
07009
07010
07011
07012 if ((cfun->machine->frame.mask | cfun->machine->frame.fmask) != 0)
07013 {
07014 step2 = MIN (step1, MIPS_MAX_FIRST_STACK_STEP);
07015 step1 -= step2;
07016 }
07017
07018
07019 target = base;
07020 if (step1 > 0)
07021 {
07022 rtx adjust;
07023
07024
07025 adjust = GEN_INT (step1);
07026 if (!SMALL_OPERAND (step1))
07027 {
07028 emit_move_insn (MIPS_EPILOGUE_TEMP (Pmode), adjust);
07029 adjust = MIPS_EPILOGUE_TEMP (Pmode);
07030 }
07031
07032
07033 if (!TARGET_MIPS16)
07034 target = stack_pointer_rtx;
07035
07036 emit_insn (gen_add3_insn (target, base, adjust));
07037 }
07038
07039
07040 if (target != stack_pointer_rtx)
07041 emit_move_insn (stack_pointer_rtx, target);
07042
07043
07044
07045
07046 if (TARGET_ABICALLS && TARGET_NEWABI && !TARGET_EXPLICIT_RELOCS)
07047 emit_insn (gen_blockage ());
07048
07049
07050 mips_for_each_saved_reg (cfun->machine->frame.total_size - step2,
07051 mips_restore_reg);
07052
07053
07054 if (step2 > 0)
07055 emit_insn (gen_add3_insn (stack_pointer_rtx,
07056 stack_pointer_rtx,
07057 GEN_INT (step2)));
07058
07059
07060
07061 if (current_function_calls_eh_return)
07062 {
07063 if (TARGET_MIPS16)
07064 {
07065 emit_move_insn (MIPS_EPILOGUE_TEMP (Pmode), stack_pointer_rtx);
07066 emit_insn (gen_add3_insn (MIPS_EPILOGUE_TEMP (Pmode),
07067 MIPS_EPILOGUE_TEMP (Pmode),
07068 EH_RETURN_STACKADJ_RTX));
07069 emit_move_insn (stack_pointer_rtx, MIPS_EPILOGUE_TEMP (Pmode));
07070 }
07071 else
07072 emit_insn (gen_add3_insn (stack_pointer_rtx,
07073 stack_pointer_rtx,
07074 EH_RETURN_STACKADJ_RTX));
07075 }
07076
07077 if (!sibcall_p)
07078 {
07079
07080 if (TARGET_MIPS16 && (cfun->machine->frame.mask & RA_MASK) != 0)
07081 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode,
07082 GP_REG_FIRST + 7)));
07083 else
07084 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode,
07085 GP_REG_FIRST + 31)));
07086 }
07087 }
07088
07089
07090
07091
07092
07093 int
07094 mips_can_use_return_insn (void)
07095 {
07096 tree return_type;
07097
07098 if (! reload_completed)
07099 return 0;
07100
07101 if (regs_ever_live[31] || current_function_profile)
07102 return 0;
07103
07104 return_type = DECL_RESULT (current_function_decl);
07105
07106
07107
07108
07109 if (TARGET_MIPS16
07110 && mips16_hard_float
07111 && ! aggregate_value_p (return_type, current_function_decl)
07112 && GET_MODE_CLASS (DECL_MODE (return_type)) == MODE_FLOAT
07113 && GET_MODE_SIZE (DECL_MODE (return_type)) <= UNITS_PER_FPVALUE)
07114 return 0;
07115
07116 if (cfun->machine->frame.initialized)
07117 return cfun->machine->frame.total_size == 0;
07118
07119 return compute_frame_size (get_frame_size ()) == 0;
07120 }
07121
07122
07123
07124
07125 static void
07126 mips_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
07127 HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
07128 tree function)
07129 {
07130 rtx this, temp1, temp2, insn, fnaddr;
07131
07132
07133 no_new_pseudos = 1;
07134 reload_completed = 1;
07135 reset_block_changes ();
07136
07137
07138
07139 if (TARGET_ABICALLS)
07140 cfun->machine->global_pointer
07141 = REGNO (pic_offset_table_rtx)
07142 = TARGET_NEWABI ? 15 : GLOBAL_POINTER_REGNUM;
07143
07144
07145 mips_emit_loadgp ();
07146
07147
07148 temp1 = gen_rtx_REG (Pmode, 2);
07149 temp2 = gen_rtx_REG (Pmode, 3);
07150
07151
07152 if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
07153 this = gen_rtx_REG (Pmode, GP_ARG_FIRST + 1);
07154 else
07155 this = gen_rtx_REG (Pmode, GP_ARG_FIRST);
07156
07157
07158 if (delta != 0)
07159 {
07160 rtx offset = GEN_INT (delta);
07161 if (!SMALL_OPERAND (delta))
07162 {
07163 emit_move_insn (temp1, offset);
07164 offset = temp1;
07165 }
07166 emit_insn (gen_add3_insn (this, this, offset));
07167 }
07168
07169
07170 if (vcall_offset != 0)
07171 {
07172 rtx addr;
07173
07174
07175 emit_move_insn (temp1, gen_rtx_MEM (Pmode, this));
07176
07177
07178 addr = mips_add_offset (temp2, temp1, vcall_offset);
07179
07180
07181 emit_move_insn (temp1, gen_rtx_MEM (Pmode, addr));
07182 emit_insn (gen_add3_insn (this, this, temp1));
07183 }
07184
07185
07186
07187 fnaddr = XEXP (DECL_RTL (function), 0);
07188 if (TARGET_MIPS16 || TARGET_ABICALLS || TARGET_LONG_CALLS)
07189 {
07190
07191
07192
07193
07194
07195
07196
07197
07198
07199
07200
07201 if (TARGET_ABICALLS && !mips_dangerous_for_la25_p (fnaddr))
07202 temp1 = gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM);
07203 mips_load_call_address (temp1, fnaddr, true);
07204
07205 if (TARGET_ABICALLS && REGNO (temp1) != PIC_FUNCTION_ADDR_REGNUM)
07206 emit_move_insn (gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM), temp1);
07207 emit_jump_insn (gen_indirect_jump (temp1));
07208 }
07209 else
07210 {
07211 insn = emit_call_insn (gen_sibcall_internal (fnaddr, const0_rtx));
07212 SIBLING_CALL_P (insn) = 1;
07213 }
07214
07215
07216
07217 insn = get_insns ();
07218 insn_locators_initialize ();
07219 split_all_insns_noflow ();
07220 if (TARGET_MIPS16)
07221 mips16_lay_out_constants ();
07222 shorten_branches (insn);
07223 final_start_function (insn, file, 1);
07224 final (insn, file, 1);
07225 final_end_function ();
07226
07227
07228
07229 reload_completed = 0;
07230 no_new_pseudos = 0;
07231 }
07232
07233
07234
07235 static int
07236 symbolic_expression_p (rtx x)
07237 {
07238 if (GET_CODE (x) == SYMBOL_REF)
07239 return 1;
07240
07241 if (GET_CODE (x) == CONST)
07242 return symbolic_expression_p (XEXP (x, 0));
07243
07244 if (UNARY_P (x))
07245 return symbolic_expression_p (XEXP (x, 0));
07246
07247 if (ARITHMETIC_P (x))
07248 return (symbolic_expression_p (XEXP (x, 0))
07249 || symbolic_expression_p (XEXP (x, 1)));
07250
07251 return 0;
07252 }
07253
07254
07255
07256
07257 static section *
07258 mips_select_rtx_section (enum machine_mode mode, rtx x,
07259 unsigned HOST_WIDE_INT align)
07260 {
07261 if (TARGET_MIPS16)
07262 {
07263
07264
07265
07266 return function_section (current_function_decl);
07267 }
07268 else if (TARGET_EMBEDDED_DATA)
07269 {
07270
07271
07272 return mergeable_constant_section (mode, align, 0);
07273 }
07274 else
07275 {
07276
07277
07278
07279
07280 if (GET_MODE_SIZE (mode) <= (unsigned) mips_section_threshold
07281 && mips_section_threshold > 0)
07282 return get_named_section (NULL, ".sdata", 0);
07283 else if (flag_pic && symbolic_expression_p (x))
07284 return get_named_section (NULL, ".data.rel.ro", 3);
07285 else
07286 return mergeable_constant_section (mode, align, 0);
07287 }
07288 }
07289
07290
07291
07292
07293
07294
07295
07296
07297
07298 static section *
07299 mips_function_rodata_section (tree decl)
07300 {
07301 if (!TARGET_ABICALLS || TARGET_GPWORD)
07302 return default_function_rodata_section (decl);
07303
07304 if (decl && DECL_SECTION_NAME (decl))
07305 {
07306 const char *name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
07307 if (DECL_ONE_ONLY (decl) && strncmp (name, ".gnu.linkonce.t.", 16) == 0)
07308 {
07309 char *rname = ASTRDUP (name);
07310 rname[14] = 'd';
07311 return get_section (rname, SECTION_LINKONCE | SECTION_WRITE, decl);
07312 }
07313 else if (flag_function_sections && flag_data_sections
07314 && strncmp (name, ".text.", 6) == 0)
07315 {
07316 char *rname = ASTRDUP (name);
07317 memcpy (rname + 1, "data", 4);
07318 return get_section (rname, SECTION_WRITE, decl);
07319 }
07320 }
07321 return data_section;
07322 }
07323
07324
07325
07326
07327
07328
07329 static bool
07330 mips_in_small_data_p (tree decl)
07331 {
07332 HOST_WIDE_INT size;
07333
07334 if (TREE_CODE (decl) == STRING_CST || TREE_CODE (decl) == FUNCTION_DECL)
07335 return false;
07336
07337
07338
07339 if (TARGET_ABICALLS)
07340 return false;
07341
07342 if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl) != 0)
07343 {
07344 const char *name;
07345
07346
07347 name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
07348 if (strcmp (name, ".sdata") != 0 && strcmp (name, ".sbss") != 0)
07349 return false;
07350
07351
07352
07353 if (TARGET_EXPLICIT_RELOCS || !DECL_EXTERNAL (decl))
07354 return true;
07355 }
07356 else if (TARGET_EMBEDDED_DATA)
07357 {
07358
07359
07360 if (TREE_CODE (decl) != VAR_DECL)
07361 return false;
07362
07363 if (TREE_READONLY (decl)
07364 && !TREE_SIDE_EFFECTS (decl)
07365 && (!DECL_INITIAL (decl) || TREE_CONSTANT (DECL_INITIAL (decl))))
07366 return false;
07367 }
07368
07369 size = int_size_in_bytes (TREE_TYPE (decl));
07370 return (size > 0 && size <= mips_section_threshold);
07371 }
07372
07373
07374
07375
07376
07377
07378 static bool
07379 mips_use_anchors_for_symbol_p (rtx symbol)
07380 {
07381 switch (mips_classify_symbol (symbol))
07382 {
07383 case SYMBOL_CONSTANT_POOL:
07384 case SYMBOL_SMALL_DATA:
07385 return false;
07386
07387 default:
07388 return true;
07389 }
07390 }
07391
07392
07393
07394
07395
07396
07397
07398
07399
07400
07401 static int
07402 mips_fpr_return_fields (tree valtype, tree *fields)
07403 {
07404 tree field;
07405 int i;
07406
07407 if (!TARGET_NEWABI)
07408 return 0;
07409
07410 if (TREE_CODE (valtype) != RECORD_TYPE)
07411 return 0;
07412
07413 i = 0;
07414 for (field = TYPE_FIELDS (valtype); field != 0; field = TREE_CHAIN (field))
07415 {
07416 if (TREE_CODE (field) != FIELD_DECL)
07417 continue;
07418
07419 if (TREE_CODE (TREE_TYPE (field)) != REAL_TYPE)
07420 return 0;
07421
07422 if (i == 2)
07423 return 0;
07424
07425 fields[i++] = field;
07426 }
07427 return i;
07428 }
07429
07430
07431
07432
07433
07434
07435
07436
07437
07438
07439
07440
07441 static bool
07442 mips_return_in_msb (tree valtype)
07443 {
07444 tree fields[2];
07445
07446 return (TARGET_NEWABI
07447 && TARGET_BIG_ENDIAN
07448 && AGGREGATE_TYPE_P (valtype)
07449 && mips_fpr_return_fields (valtype, fields) == 0);
07450 }
07451
07452
07453
07454
07455
07456
07457
07458
07459
07460
07461 static rtx
07462 mips_return_fpr_pair (enum machine_mode mode,
07463 enum machine_mode mode1, HOST_WIDE_INT offset1,
07464 enum machine_mode mode2, HOST_WIDE_INT offset2)
07465 {
07466 int inc;
07467
07468 inc = (TARGET_NEWABI ? 2 : FP_INC);
07469 return gen_rtx_PARALLEL
07470 (mode,
07471 gen_rtvec (2,
07472 gen_rtx_EXPR_LIST (VOIDmode,
07473 gen_rtx_REG (mode1, FP_RETURN),
07474 GEN_INT (offset1)),
07475 gen_rtx_EXPR_LIST (VOIDmode,
07476 gen_rtx_REG (mode2, FP_RETURN + inc),
07477 GEN_INT (offset2))));
07478
07479 }
07480
07481
07482
07483
07484
07485
07486 rtx
07487 mips_function_value (tree valtype, tree func ATTRIBUTE_UNUSED,
07488 enum machine_mode mode)
07489 {
07490 if (valtype)
07491 {
07492 tree fields[2];
07493 int unsignedp;
07494
07495 mode = TYPE_MODE (valtype);
07496 unsignedp = TYPE_UNSIGNED (valtype);
07497
07498
07499
07500 mode = promote_mode (valtype, mode, &unsignedp, 1);
07501
07502
07503 switch (mips_fpr_return_fields (valtype, fields))
07504 {
07505 case 1:
07506 return gen_rtx_REG (mode, FP_RETURN);
07507
07508 case 2:
07509 return mips_return_fpr_pair (mode,
07510 TYPE_MODE (TREE_TYPE (fields[0])),
07511 int_byte_position (fields[0]),
07512 TYPE_MODE (TREE_TYPE (fields[1])),
07513 int_byte_position (fields[1]));
07514 }
07515
07516
07517
07518 if (mips_return_in_msb (valtype))
07519 {
07520 HOST_WIDE_INT size = int_size_in_bytes (valtype);
07521 if (size % UNITS_PER_WORD != 0)
07522 {
07523 size += UNITS_PER_WORD - size % UNITS_PER_WORD;
07524 mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
07525 }
07526 }
07527
07528
07529
07530
07531
07532 if (mips_abi != ABI_EABI && !FLOAT_TYPE_P (valtype))
07533 return gen_rtx_REG (mode, GP_RETURN);
07534 }
07535
07536 if ((GET_MODE_CLASS (mode) == MODE_FLOAT
07537 || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
07538 && GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE)
07539 return gen_rtx_REG (mode, FP_RETURN);
07540
07541
07542 if (mode == TFmode)
07543 return mips_return_fpr_pair (mode,
07544 DImode, 0,
07545 DImode, GET_MODE_SIZE (mode) / 2);
07546
07547 if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
07548 && GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE * 2)
07549 return mips_return_fpr_pair (mode,
07550 GET_MODE_INNER (mode), 0,
07551 GET_MODE_INNER (mode),
07552 GET_MODE_SIZE (mode) / 2);
07553
07554 return gen_rtx_REG (mode, GP_RETURN);
07555 }
07556
07557
07558
07559 static bool
07560 mips_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
07561 enum machine_mode mode, tree type,
07562 bool named ATTRIBUTE_UNUSED)
07563 {
07564 if (mips_abi == ABI_EABI)
07565 {
07566 int size;
07567
07568
07569 if (mode == DImode || mode == DFmode)
07570 return 0;
07571
07572 size = type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
07573 return size == -1 || size > UNITS_PER_WORD;
07574 }
07575 else
07576 {
07577
07578 return targetm.calls.must_pass_in_stack (mode, type);
07579 }
07580 }
07581
07582 static bool
07583 mips_callee_copies (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
07584 enum machine_mode mode ATTRIBUTE_UNUSED,
07585 tree type ATTRIBUTE_UNUSED, bool named)
07586 {
07587 return mips_abi == ABI_EABI && named;
07588 }
07589
07590
07591
07592
07593 bool
07594 mips_cannot_change_mode_class (enum machine_mode from,
07595 enum machine_mode to, enum reg_class class)
07596 {
07597 if (MIN (GET_MODE_SIZE (from), GET_MODE_SIZE (to)) <= UNITS_PER_WORD
07598 && MAX (GET_MODE_SIZE (from), GET_MODE_SIZE (to)) > UNITS_PER_WORD)
07599 {
07600 if (TARGET_BIG_ENDIAN)
07601 {
07602
07603
07604
07605
07606 if (FP_INC > 1 && reg_classes_intersect_p (FP_REGS, class))
07607 return true;
07608 }
07609 else
07610 {
07611
07612
07613
07614
07615
07616
07617 if (reg_classes_intersect_p (ACC_REGS, class))
07618 return true;
07619 }
07620 }
07621
07622
07623
07624
07625 if (TARGET_FLOAT64
07626 && from == SImode
07627 && GET_MODE_SIZE (to) >= UNITS_PER_WORD
07628 && reg_classes_intersect_p (FP_REGS, class))
07629 return true;
07630 return false;
07631 }
07632
07633
07634
07635
07636
07637 bool
07638 mips_dangerous_for_la25_p (rtx x)
07639 {
07640 HOST_WIDE_INT offset;
07641
07642 if (TARGET_EXPLICIT_RELOCS)
07643 return false;
07644
07645 mips_split_const (x, &x, &offset);
07646 return global_got_operand (x, VOIDmode);
07647 }
07648
07649
07650
07651 enum reg_class
07652 mips_preferred_reload_class (rtx x, enum reg_class class)
07653 {
07654 if (mips_dangerous_for_la25_p (x) && reg_class_subset_p (LEA_REGS, class))
07655 return LEA_REGS;
07656
07657 if (TARGET_HARD_FLOAT
07658 && FLOAT_MODE_P (GET_MODE (x))
07659 && reg_class_subset_p (FP_REGS, class))
07660 return FP_REGS;
07661
07662 if (reg_class_subset_p (GR_REGS, class))
07663 class = GR_REGS;
07664
07665 if (TARGET_MIPS16 && reg_class_subset_p (M16_REGS, class))
07666 class = M16_REGS;
07667
07668 return class;
07669 }
07670
07671
07672
07673
07674
07675
07676
07677 enum reg_class
07678 mips_secondary_reload_class (enum reg_class class,
07679 enum machine_mode mode, rtx x, int in_p)
07680 {
07681 enum reg_class gr_regs = TARGET_MIPS16 ? M16_REGS : GR_REGS;
07682 int regno = -1;
07683 int gp_reg_p;
07684
07685 if (REG_P (x)|| GET_CODE (x) == SUBREG)
07686 regno = true_regnum (x);
07687
07688 gp_reg_p = TARGET_MIPS16 ? M16_REG_P (regno) : GP_REG_P (regno);
07689
07690 if (mips_dangerous_for_la25_p (x))
07691 {
07692 gr_regs = LEA_REGS;
07693 if (TEST_HARD_REG_BIT (reg_class_contents[(int) class], 25))
07694 return gr_regs;
07695 }
07696
07697
07698
07699
07700
07701 if (reg_class_subset_p (class, ACC_REGS))
07702 {
07703 if (TARGET_MIPS16 && in_p)
07704 {
07705
07706 return M16_REGS;
07707 }
07708 return gp_reg_p ? NO_REGS : gr_regs;
07709 }
07710 if (ACC_REG_P (regno))
07711 {
07712 if (TARGET_MIPS16 && ! in_p)
07713 {
07714
07715 return M16_REGS;
07716 }
07717 return class == gr_regs ? NO_REGS : gr_regs;
07718 }
07719
07720
07721
07722
07723
07724 if (class == ST_REGS)
07725 {
07726 if (in_p)
07727 return FP_REGS;
07728 return gp_reg_p ? NO_REGS : gr_regs;
07729 }
07730 if (ST_REG_P (regno))
07731 {
07732 if (! in_p)
07733 return FP_REGS;
07734 return class == gr_regs ? NO_REGS : gr_regs;
07735 }
07736
07737 if (class == FP_REGS)
07738 {
07739 if (MEM_P (x))
07740 {
07741
07742 return NO_REGS;
07743 }
07744 else if (CONSTANT_P (x) && GET_MODE_CLASS (mode) == MODE_FLOAT)
07745 {
07746
07747
07748
07749 return NO_REGS;
07750 }
07751 else if (gp_reg_p || x == CONST0_RTX (mode))
07752 {
07753
07754 return NO_REGS;
07755 }
07756 else if (FP_REG_P (regno))
07757 {
07758
07759 return NO_REGS;
07760 }
07761 else
07762 {
07763
07764 return gr_regs;
07765 }
07766 }
07767
07768
07769
07770 if (TARGET_MIPS16)
07771 {
07772 if (class != M16_REGS && class != M16_NA_REGS)
07773 {
07774 if (gp_reg_p)
07775 return NO_REGS;
07776 return M16_REGS;
07777 }
07778 if (! gp_reg_p)
07779 {
07780 if (class == M16_REGS || class == M16_NA_REGS)
07781 return NO_REGS;
07782 return M16_REGS;
07783 }
07784 }
07785
07786 return NO_REGS;
07787 }
07788
07789
07790
07791
07792
07793
07794
07795
07796
07797
07798
07799
07800 int
07801 mips_class_max_nregs (enum reg_class class ATTRIBUTE_UNUSED,
07802 enum machine_mode mode)
07803 {
07804 if (class == ST_REGS)
07805 return (GET_MODE_SIZE (mode) + 3) / 4;
07806 else
07807 return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
07808 }
07809
07810 static bool
07811 mips_valid_pointer_mode (enum machine_mode mode)
07812 {
07813 return (mode == SImode || (TARGET_64BIT && mode == DImode));
07814 }
07815
07816
07817
07818 static bool
07819 mips_vector_mode_supported_p (enum machine_mode mode)
07820 {
07821 switch (mode)
07822 {
07823 case V2SFmode:
07824 return TARGET_PAIRED_SINGLE_FLOAT;
07825
07826 case V2HImode:
07827 case V4QImode:
07828 return TARGET_DSP;
07829
07830 default:
07831 return false;
07832 }
07833 }
07834
07835
07836
07837
07838
07839
07840
07841
07842 static rtx
07843 mips16_gp_pseudo_reg (void)
07844 {
07845 if (cfun->machine->mips16_gp_pseudo_rtx == NULL_RTX)
07846 {
07847 rtx unspec;
07848 rtx insn, scan;
07849
07850 cfun->machine->mips16_gp_pseudo_rtx = gen_reg_rtx (Pmode);
07851
07852
07853
07854 start_sequence ();
07855 unspec = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, const0_rtx), UNSPEC_GP);
07856 emit_move_insn (cfun->machine->mips16_gp_pseudo_rtx,
07857 gen_rtx_CONST (Pmode, unspec));
07858 insn = get_insns ();
07859 end_sequence ();
07860
07861 push_topmost_sequence ();
07862
07863
07864 for (scan = get_insns (); scan != NULL_RTX; scan = NEXT_INSN (scan))
07865 if (NOTE_P (scan)
07866 && NOTE_LINE_NUMBER (scan) == NOTE_INSN_FUNCTION_BEG)
07867 break;
07868 if (scan == NULL_RTX)
07869 scan = get_insns ();
07870 insn = emit_insn_after (insn, scan);
07871 pop_topmost_sequence ();
07872 }
07873
07874 return cfun->machine->mips16_gp_pseudo_rtx;
07875 }
07876
07877
07878
07879
07880
07881
07882
07883 static void
07884 mips16_fp_args (FILE *file, int fp_code, int from_fp_p)
07885 {
07886 const char *s;
07887 int gparg, fparg;
07888 unsigned int f;
07889
07890
07891 gcc_assert (TARGET_OLDABI);
07892
07893 if (from_fp_p)
07894 s = "mfc1";
07895 else
07896 s = "mtc1";
07897 gparg = GP_ARG_FIRST;
07898 fparg = FP_ARG_FIRST;
07899 for (f = (unsigned int) fp_code; f != 0; f >>= 2)
07900 {
07901 if ((f & 3) == 1)
07902 {
07903 if ((fparg & 1) != 0)
07904 ++fparg;
07905 fprintf (file, "\t%s\t%s,%s\n", s,
07906 reg_names[gparg], reg_names[fparg]);
07907 }
07908 else if ((f & 3) == 2)
07909 {
07910 if (TARGET_64BIT)
07911 fprintf (file, "\td%s\t%s,%s\n", s,
07912 reg_names[gparg], reg_names[fparg]);
07913 else
07914 {
07915 if ((fparg & 1) != 0)
07916 ++fparg;
07917 if (TARGET_BIG_ENDIAN)
07918 fprintf (file, "\t%s\t%s,%s\n\t%s\t%s,%s\n", s,
07919 reg_names[gparg], reg_names[fparg + 1], s,
07920 reg_names[gparg + 1], reg_names[fparg]);
07921 else
07922 fprintf (file, "\t%s\t%s,%s\n\t%s\t%s,%s\n", s,
07923 reg_names[gparg], reg_names[fparg], s,
07924 reg_names[gparg + 1], reg_names[fparg + 1]);
07925 ++gparg;
07926 ++fparg;
07927 }
07928 }
07929 else
07930 gcc_unreachable ();
07931
07932 ++gparg;
07933 ++fparg;
07934 }
07935 }
07936
07937
07938
07939
07940
07941
07942 static void
07943 build_mips16_function_stub (FILE *file)
07944 {
07945 const char *fnname;
07946 char *secname, *stubname;
07947 tree stubid, stubdecl;
07948 int need_comma;
07949 unsigned int f;
07950
07951 fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
07952 secname = (char *) alloca (strlen (fnname) + 20);
07953 sprintf (secname, ".mips16.fn.%s", fnname);
07954 stubname = (char *) alloca (strlen (fnname) + 20);
07955 sprintf (stubname, "__fn_stub_%s", fnname);
07956 stubid = get_identifier (stubname);
07957 stubdecl = build_decl (FUNCTION_DECL, stubid,
07958 build_function_type (void_type_node, NULL_TREE));
07959 DECL_SECTION_NAME (stubdecl) = build_string (strlen (secname), secname);
07960
07961 fprintf (file, "\t# Stub function for %s (", current_function_name ());
07962 need_comma = 0;
07963 for (f = (unsigned int) current_function_args_info.fp_code; f != 0; f >>= 2)
07964 {
07965 fprintf (file, "%s%s",
07966 need_comma ? ", " : "",
07967 (f & 3) == 1 ? "float" : "double");
07968 need_comma = 1;
07969 }
07970 fprintf (file, ")\n");
07971
07972 fprintf (file, "\t.set\tnomips16\n");
07973 switch_to_section (function_section (stubdecl));
07974 ASM_OUTPUT_ALIGN (file, floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT));
07975
07976
07977
07978 if (!FUNCTION_NAME_ALREADY_DECLARED)
07979 {
07980 fputs ("\t.ent\t", file);
07981 assemble_name (file, stubname);
07982 fputs ("\n", file);
07983 }
07984
07985 assemble_name (file, stubname);
07986 fputs (":\n", file);
07987
07988
07989 fprintf (file, "\t.set\tnoreorder\n");
07990
07991 mips16_fp_args (file, current_function_args_info.fp_code, 1);
07992
07993 fprintf (asm_out_file, "\t.set\tnoat\n");
07994 fprintf (asm_out_file, "\tla\t%s,", reg_names[GP_REG_FIRST + 1]);
07995 assemble_name (file, fnname);
07996 fprintf (file, "\n");
07997 fprintf (asm_out_file, "\tjr\t%s\n", reg_names[GP_REG_FIRST + 1]);
07998 fprintf (asm_out_file, "\t.set\tat\n");
07999
08000
08001
08002
08003
08004
08005 fprintf (file, "\tnop\n");
08006
08007 fprintf (file, "\t.set\treorder\n");
08008
08009 if (!FUNCTION_NAME_ALREADY_DECLARED)
08010 {
08011 fputs ("\t.end\t", file);
08012 assemble_name (file, stubname);
08013 fputs ("\n", file);
08014 }
08015
08016 fprintf (file, "\t.set\tmips16\n");
08017
08018 switch_to_section (function_section (current_function_decl));
08019 }
08020
08021
08022
08023
08024 struct mips16_stub
08025 {
08026 struct mips16_stub *next;
08027 char *name;
08028 int fpret;
08029 };
08030
08031 static struct mips16_stub *mips16_stubs;
08032
08033
08034
08035
08036
08037
08038
08039
08040
08041
08042
08043
08044
08045
08046
08047
08048
08049
08050
08051 int
08052 build_mips16_call_stub (rtx retval, rtx fn, rtx arg_size, int fp_code)
08053 {
08054 int fpret;
08055 const char *fnname;
08056 char *secname, *stubname;
08057 struct mips16_stub *l;
08058 tree stubid, stubdecl;
08059 int need_comma;
08060 unsigned int f;
08061
08062
08063
08064 if (! TARGET_MIPS16 || ! mips16_hard_float)
08065 return 0;
08066
08067
08068
08069 fpret = (retval != 0
08070 && GET_MODE_CLASS (GET_MODE (retval)) == MODE_FLOAT
08071 && GET_MODE_SIZE (GET_MODE (retval)) <= UNITS_PER_FPVALUE);
08072
08073
08074
08075
08076 if (fp_code == 0 && ! fpret)
08077 return 0;
08078
08079
08080
08081 if (GET_CODE (fn) == SYMBOL_REF
08082 && strncmp (XSTR (fn, 0), "__mips16_", 9) == 0)
08083 return 0;
08084
08085
08086
08087 gcc_assert (TARGET_OLDABI);
08088
08089
08090
08091 if (fpret)
08092 gcc_assert (GET_MODE (retval) == SFmode || GET_MODE (retval) == DFmode);
08093
08094
08095
08096
08097
08098
08099 if (GET_CODE (fn) != SYMBOL_REF)
08100 {
08101 char buf[30];
08102 tree id;
08103 rtx stub_fn, insn;
08104
08105
08106
08107
08108 sprintf (buf, "__mips16_call_stub_%s%d",
08109 (fpret
08110 ? (GET_MODE (retval) == SFmode ? "sf_" : "df_")
08111 : ""),
08112 fp_code);
08113 id = get_identifier (buf);
08114 stub_fn = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (id));
08115
08116 emit_move_insn (gen_rtx_REG (Pmode, 2), fn);
08117
08118 if (retval == NULL_RTX)
08119 insn = gen_call_internal (stub_fn, arg_size);
08120 else
08121 insn = gen_call_value_internal (retval, stub_fn, arg_size);
08122 insn = emit_call_insn (insn);
08123
08124
08125 CALL_INSN_FUNCTION_USAGE (insn) =
08126 gen_rtx_EXPR_LIST (VOIDmode,
08127 gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, 2)),
08128 CALL_INSN_FUNCTION_USAGE (insn));
08129
08130
08131
08132
08133
08134
08135 if (fpret)
08136 CALL_INSN_FUNCTION_USAGE (insn) =
08137 gen_rtx_EXPR_LIST (VOIDmode,
08138 gen_rtx_USE (VOIDmode,
08139 gen_rtx_REG (word_mode, 18)),
08140 CALL_INSN_FUNCTION_USAGE (insn));
08141
08142
08143
08144 return 1;
08145 }
08146
08147
08148
08149
08150 fnname = XSTR (fn, 0);
08151 for (l = mips16_stubs; l != NULL; l = l->next)
08152 if (strcmp (l->name, fnname) == 0)
08153 break;
08154
08155 if (l == NULL)
08156 {
08157
08158
08159
08160
08161
08162
08163
08164
08165
08166
08167
08168
08169
08170
08171
08172
08173
08174
08175
08176 secname = (char *) alloca (strlen (fnname) + 40);
08177 sprintf (secname, ".mips16.call.%s%s",
08178 fpret ? "fp." : "",
08179 fnname);
08180 stubname = (char *) alloca (strlen (fnname) + 20);
08181 sprintf (stubname, "__call_stub_%s%s",
08182 fpret ? "fp_" : "",
08183 fnname);
08184 stubid = get_identifier (stubname);
08185 stubdecl = build_decl (FUNCTION_DECL, stubid,
08186 build_function_type (void_type_node, NULL_TREE));
08187 DECL_SECTION_NAME (stubdecl) = build_string (strlen (secname), secname);
08188
08189 fprintf (asm_out_file, "\t# Stub function to call %s%s (",
08190 (fpret
08191 ? (GET_MODE (retval) == SFmode ? "float " : "double ")
08192 : ""),
08193 fnname);
08194 need_comma = 0;
08195 for (f = (unsigned int) fp_code; f != 0; f >>= 2)
08196 {
08197 fprintf (asm_out_file, "%s%s",
08198 need_comma ? ", " : "",
08199 (f & 3) == 1 ? "float" : "double");
08200 need_comma = 1;
08201 }
08202 fprintf (asm_out_file, ")\n");
08203
08204 fprintf (asm_out_file, "\t.set\tnomips16\n");
08205 assemble_start_function (stubdecl, stubname);
08206
08207 if (!FUNCTION_NAME_ALREADY_DECLARED)
08208 {
08209 fputs ("\t.ent\t", asm_out_file);
08210 assemble_name (asm_out_file, stubname);
08211 fputs ("\n", asm_out_file);
08212
08213 assemble_name (asm_out_file, stubname);
08214 fputs (":\n", asm_out_file);
08215 }
08216
08217
08218
08219
08220
08221
08222 fprintf (asm_out_file, "\t.set\tnoreorder\n");
08223
08224 mips16_fp_args (asm_out_file, fp_code, 0);
08225
08226 if (! fpret)
08227 {
08228 fprintf (asm_out_file, "\t.set\tnoat\n");
08229 fprintf (asm_out_file, "\tla\t%s,%s\n", reg_names[GP_REG_FIRST + 1],
08230 fnname);
08231 fprintf (asm_out_file, "\tjr\t%s\n", reg_names[GP_REG_FIRST + 1]);
08232 fprintf (asm_out_file, "\t.set\tat\n");
08233
08234
08235
08236
08237
08238 fprintf (asm_out_file, "\tnop\n");
08239 }
08240 else
08241 {
08242 fprintf (asm_out_file, "\tmove\t%s,%s\n",
08243 reg_names[GP_REG_FIRST + 18], reg_names[GP_REG_FIRST + 31]);
08244 fprintf (asm_out_file, "\tjal\t%s\n", fnname);
08245
08246 fprintf (asm_out_file, "\tnop\n");
08247 if (GET_MODE (retval) == SFmode)
08248 fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
08249 reg_names[GP_REG_FIRST + 2], reg_names[FP_REG_FIRST + 0]);
08250 else
08251 {
08252 if (TARGET_BIG_ENDIAN)
08253 {
08254 fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
08255 reg_names[GP_REG_FIRST + 2],
08256 reg_names[FP_REG_FIRST + 1]);
08257 fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
08258 reg_names[GP_REG_FIRST + 3],
08259 reg_names[FP_REG_FIRST + 0]);
08260 }
08261 else
08262 {
08263 fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
08264 reg_names[GP_REG_FIRST + 2],
08265 reg_names[FP_REG_FIRST + 0]);
08266 fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
08267 reg_names[GP_REG_FIRST + 3],
08268 reg_names[FP_REG_FIRST + 1]);
08269 }
08270 }
08271 fprintf (asm_out_file, "\tj\t%s\n", reg_names[GP_REG_FIRST + 18]);
08272
08273 fprintf (asm_out_file, "\tnop\n");
08274 }
08275
08276 fprintf (asm_out_file, "\t.set\treorder\n");
08277
08278 #ifdef ASM_DECLARE_FUNCTION_SIZE
08279 ASM_DECLARE_FUNCTION_SIZE (asm_out_file, stubname, stubdecl);
08280 #endif
08281
08282 if (!FUNCTION_NAME_ALREADY_DECLARED)
08283 {
08284 fputs ("\t.end\t", asm_out_file);
08285 assemble_name (asm_out_file, stubname);
08286 fputs ("\n", asm_out_file);
08287 }
08288
08289 fprintf (asm_out_file, "\t.set\tmips16\n");
08290
08291
08292 l = (struct mips16_stub *) xmalloc (sizeof *l);
08293 l->name = xstrdup (fnname);
08294 l->fpret = fpret;
08295 l->next = mips16_stubs;
08296 mips16_stubs = l;
08297 }
08298
08299
08300
08301
08302
08303
08304
08305
08306 if (fpret && ! l->fpret)
08307 error ("cannot handle inconsistent calls to %qs", fnname);
08308
08309
08310
08311
08312
08313
08314
08315 if (l->fpret)
08316 {
08317 rtx insn;
08318
08319 if (retval == NULL_RTX)
08320 insn = gen_call_internal (fn, arg_size);
08321 else
08322 insn = gen_call_value_internal (retval, fn, arg_size);
08323 insn = emit_call_insn (insn);
08324
08325 CALL_INSN_FUNCTION_USAGE (insn) =
08326 gen_rtx_EXPR_LIST (VOIDmode,
08327 gen_rtx_USE (VOIDmode, gen_rtx_REG (word_mode, 18)),
08328 CALL_INSN_FUNCTION_USAGE (insn));
08329
08330
08331
08332 return 1;
08333 }
08334
08335
08336 return 0;
08337 }
08338
08339
08340
08341
08342 struct mips16_constant {
08343 struct mips16_constant *next;
08344 rtx value;
08345 rtx label;
08346 enum machine_mode mode;
08347 };
08348
08349
08350
08351
08352
08353
08354 struct mips16_constant_pool {
08355 struct mips16_constant *first;
08356 int highest_address;
08357 int insn_address;
08358 };
08359
08360
08361
08362
08363 static rtx
08364 add_constant (struct mips16_constant_pool *pool,
08365 rtx value, enum machine_mode mode)
08366 {
08367 struct mips16_constant **p, *c;
08368 bool first_of_size_p;
08369
08370
08371
08372
08373
08374
08375
08376 first_of_size_p = true;
08377 for (p = &pool->first; *p != 0; p = &(*p)->next)
08378 {
08379 if (mode == (*p)->mode && rtx_equal_p (value, (*p)->value))
08380 return (*p)->label;
08381 if (GET_MODE_SIZE (mode) < GET_MODE_SIZE ((*p)->mode))
08382 break;
08383 if (GET_MODE_SIZE (mode) == GET_MODE_SIZE ((*p)->mode))
08384 first_of_size_p = false;
08385 }
08386
08387
08388
08389
08390
08391
08392
08393
08394 if (pool->first == 0)
08395
08396
08397
08398
08399 pool->highest_address = pool->insn_address - (UNITS_PER_WORD - 2) + 0x8000;
08400 pool->highest_address -= GET_MODE_SIZE (mode);
08401 if (first_of_size_p)
08402
08403 pool->highest_address -= GET_MODE_SIZE (mode) - 1;
08404
08405
08406 c = (struct mips16_constant *) xmalloc (sizeof *c);
08407 c->value = value;
08408 c->mode = mode;
08409 c->label = gen_label_rtx ();
08410 c->next = *p;
08411 *p = c;
08412
08413 return c->label;
08414 }
08415
08416
08417
08418
08419 static rtx
08420 dump_constants_1 (enum machine_mode mode, rtx value, rtx insn)
08421 {
08422 switch (GET_MODE_CLASS (mode))
08423 {
08424 case MODE_INT:
08425 {
08426 rtx size = GEN_INT (GET_MODE_SIZE (mode));
08427 return emit_insn_after (gen_consttable_int (value, size), insn);
08428 }
08429
08430 case MODE_FLOAT:
08431 return emit_insn_after (gen_consttable_float (value), insn);
08432
08433 case MODE_VECTOR_FLOAT:
08434 case MODE_VECTOR_INT:
08435 {
08436 int i;
08437 for (i = 0; i < CONST_VECTOR_NUNITS (value); i++)
08438 insn = dump_constants_1 (GET_MODE_INNER (mode),
08439 CONST_VECTOR_ELT (value, i), insn);
08440 return insn;
08441 }
08442
08443 default:
08444 gcc_unreachable ();
08445 }
08446 }
08447
08448
08449
08450
08451 static void
08452 dump_constants (struct mips16_constant *constants, rtx insn)
08453 {
08454 struct mips16_constant *c, *next;
08455 int align;
08456
08457 align = 0;
08458 for (c = constants; c != NULL; c = next)
08459 {
08460
08461 if (align < GET_MODE_SIZE (c->mode))
08462 {
08463 int align_log = floor_log2 (GET_MODE_SIZE (c->mode));
08464 insn = emit_insn_after (gen_align (GEN_INT (align_log)), insn);
08465 }
08466 align = GET_MODE_SIZE (c->mode);
08467
08468 insn = emit_label_after (c->label, insn);
08469 insn = dump_constants_1 (c->mode, c->value, insn);
08470
08471 next = c->next;
08472 free (c);
08473 }
08474
08475 emit_barrier_after (insn);
08476 }
08477
08478
08479
08480 static int
08481 mips16_insn_length (rtx insn)
08482 {
08483 if (JUMP_P (insn))
08484 {
08485 rtx body = PATTERN (insn);
08486 if (GET_CODE (body) == ADDR_VEC)
08487 return GET_MODE_SIZE (GET_MODE (body)) * XVECLEN (body, 0);
08488 if (GET_CODE (body) == ADDR_DIFF_VEC)
08489 return GET_MODE_SIZE (GET_MODE (body)) * XVECLEN (body, 1);
08490 }
08491 return get_attr_length (insn);
08492 }
08493
08494
08495
08496
08497 static int
08498 mips16_rewrite_pool_refs (rtx *x, void *data)
08499 {
08500 struct mips16_constant_pool *pool = data;
08501 if (GET_CODE (*x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (*x))
08502 *x = gen_rtx_LABEL_REF (Pmode, add_constant (pool,
08503 get_pool_constant (*x),
08504 get_pool_mode (*x)));
08505 return 0;
08506 }
08507
08508
08509
08510 static void
08511 mips16_lay_out_constants (void)
08512 {
08513 struct mips16_constant_pool pool;
08514 rtx insn, barrier;
08515
08516 barrier = 0;
08517 memset (&pool, 0, sizeof (pool));
08518 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
08519 {
08520
08521 if (INSN_P (insn))
08522 for_each_rtx (&PATTERN (insn), mips16_rewrite_pool_refs, &pool);
08523
08524 pool.insn_address += mips16_insn_length (insn);
08525
08526 if (pool.first != NULL)
08527 {
08528
08529
08530
08531
08532
08533
08534
08535 if (barrier == 0 && pool.insn_address + 4 > pool.highest_address)
08536 {
08537 rtx label, jump;
08538
08539 label = gen_label_rtx ();
08540
08541 jump = emit_jump_insn_before (gen_jump (label), insn);
08542 JUMP_LABEL (jump) = label;
08543 LABEL_NUSES (label) = 1;
08544 barrier = emit_barrier_after (jump);
08545
08546 emit_label_after (label, barrier);
08547 pool.insn_address += 4;
08548 }
08549
08550
08551
08552
08553
08554 if (pool.insn_address > pool.highest_address)
08555 {
08556 dump_constants (pool.first, barrier);
08557 pool.first = NULL;
08558 barrier = 0;
08559 }
08560 else if (BARRIER_P (insn))
08561 barrier = insn;
08562 }
08563 }
08564 dump_constants (pool.first, get_last_insn ());
08565 }
08566
08567
08568 static rtx mips_sim_insn;
08569
08570
08571
08572 struct mips_sim {
08573
08574
08575 unsigned int issue_rate;
08576
08577
08578 unsigned int time;
08579
08580
08581 unsigned int insns_left;
08582
08583
08584
08585
08586 struct {
08587 rtx insn;
08588 unsigned int time;
08589 } last_set[FIRST_PSEUDO_REGISTER];
08590
08591
08592 state_t dfa_state;
08593 };
08594
08595
08596
08597 static void
08598 mips_sim_reset (struct mips_sim *state)
08599 {
08600 state->time = 0;
08601 state->insns_left = state->issue_rate;
08602 memset (&state->last_set, 0, sizeof (state->last_set));
08603 state_reset (state->dfa_state);
08604 }
08605
08606
08607
08608
08609 static void
08610 mips_sim_init (struct mips_sim *state, state_t dfa_state)
08611 {
08612 state->issue_rate = mips_issue_rate ();
08613 state->dfa_state = dfa_state;
08614 mips_sim_reset (state);
08615 }
08616
08617
08618
08619 static void
08620 mips_sim_next_cycle (struct mips_sim *state)
08621 {
08622 state->time++;
08623 state->insns_left = state->issue_rate;
08624 state_transition (state->dfa_state, 0);
08625 }
08626
08627
08628
08629
08630 static void
08631 mips_sim_wait_reg (struct mips_sim *state, rtx insn, rtx reg)
08632 {
08633 unsigned int i;
08634
08635 for (i = 0; i < HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg)); i++)
08636 if (state->last_set[REGNO (reg) + i].insn != 0)
08637 {
08638 unsigned int t;
08639
08640 t = state->last_set[REGNO (reg) + i].time;
08641 t += insn_latency (state->last_set[REGNO (reg) + i].insn, insn);
08642 while (state->time < t)
08643 mips_sim_next_cycle (state);
08644 }
08645 }
08646
08647
08648
08649
08650 static int
08651 mips_sim_wait_regs_2 (rtx *x, void *data)
08652 {
08653 if (REG_P (*x))
08654 mips_sim_wait_reg (data, mips_sim_insn, *x);
08655 return 0;
08656 }
08657
08658
08659
08660 static void
08661 mips_sim_wait_regs_1 (rtx *x, void *data)
08662 {
08663 for_each_rtx (x, mips_sim_wait_regs_2, data);
08664 }
08665
08666
08667
08668
08669 static void
08670 mips_sim_wait_regs (struct mips_sim *state, rtx insn)
08671 {
08672 mips_sim_insn = insn;
08673 note_uses (&PATTERN (insn), mips_sim_wait_regs_1, state);
08674 }
08675
08676
08677
08678
08679 static void
08680 mips_sim_wait_units (struct mips_sim *state, rtx insn)
08681 {
08682 state_t tmp_state;
08683
08684 tmp_state = alloca (state_size ());
08685 while (state->insns_left == 0
08686 || (memcpy (tmp_state, state->dfa_state, state_size ()),
08687 state_transition (tmp_state, insn) >= 0))
08688 mips_sim_next_cycle (state);
08689 }
08690
08691
08692
08693 static void
08694 mips_sim_wait_insn (struct mips_sim *state, rtx insn)
08695 {
08696 mips_sim_wait_regs (state, insn);
08697 mips_sim_wait_units (state, insn);
08698 }
08699
08700
08701
08702
08703 static void
08704 mips_sim_record_set (rtx x, rtx pat ATTRIBUTE_UNUSED, void *data)
08705 {
08706 struct mips_sim *state;
08707 unsigned int i;
08708
08709 state = data;
08710 if (REG_P (x))
08711 for (i = 0; i < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); i++)
08712 {
08713 state->last_set[REGNO (x) + i].insn = mips_sim_insn;
08714 state->last_set[REGNO (x) + i].time = state->time;
08715 }
08716 }
08717
08718
08719
08720
08721
08722 static void
08723 mips_sim_issue_insn (struct mips_sim *state, rtx insn)
08724 {
08725 state_transition (state->dfa_state, insn);
08726 state->insns_left--;
08727
08728 mips_sim_insn = insn;
08729 note_stores (PATTERN (insn), mips_sim_record_set, state);
08730 }
08731
08732
08733
08734 static void
08735 mips_sim_issue_nop (struct mips_sim *state)
08736 {
08737 if (state->insns_left == 0)
08738 mips_sim_next_cycle (state);
08739 state->insns_left--;
08740 }
08741
08742
08743
08744
08745
08746 static void
08747 mips_sim_finish_insn (struct mips_sim *state, rtx insn)
08748 {
08749
08750 if (JUMP_P (insn))
08751 mips_sim_issue_nop (state);
08752
08753 switch (GET_CODE (SEQ_BEGIN (insn)))
08754 {
08755 case CODE_LABEL:
08756 case CALL_INSN:
08757
08758 mips_sim_reset (state);
08759 break;
08760
08761 case JUMP_INSN:
08762
08763
08764
08765
08766
08767
08768
08769 if (INSN_ANNULLED_BRANCH_P (SEQ_BEGIN (insn)))
08770 mips_sim_reset (state);
08771 break;
08772
08773 default:
08774 break;
08775 }
08776 }
08777
08778
08779
08780
08781
08782
08783
08784
08785
08786
08787
08788
08789
08790 static void
08791 vr4130_avoid_branch_rt_conflict (rtx insn)
08792 {
08793 rtx first, second;
08794
08795 first = SEQ_BEGIN (insn);
08796 second = SEQ_END (insn);
08797 if (JUMP_P (first)
08798 && NONJUMP_INSN_P (second)
08799 && GET_CODE (PATTERN (first)) == SET
08800 && GET_CODE (SET_DEST (PATTERN (first))) == PC
08801 && GET_CODE (SET_SRC (PATTERN (first))) == IF_THEN_ELSE)
08802 {
08803
08804 rtx cond = XEXP (SET_SRC (PATTERN (first)), 0);
08805 if ((GET_CODE (cond) == EQ || GET_CODE (cond) == NE)
08806 && REG_P (XEXP (cond, 0))
08807 && REG_P (XEXP (cond, 1))
08808 && reg_referenced_p (XEXP (cond, 1), PATTERN (second))
08809 && !reg_referenced_p (XEXP (cond, 0), PATTERN (second)))
08810 {
08811
08812 rtx tmp = XEXP (cond, 0);
08813 XEXP (cond, 0) = XEXP (cond, 1);
08814 XEXP (cond, 1) = tmp;
08815 }
08816 }
08817 }
08818
08819
08820
08821
08822
08823
08824 static void
08825 vr4130_align_insns (void)
08826 {
08827 struct mips_sim state;
08828 rtx insn, subinsn, last, last2, next;
08829 bool aligned_p;
08830
08831 dfa_start ();
08832
08833
08834
08835 last = 0;
08836 last2 = 0;
08837
08838
08839 aligned_p = true;
08840
08841 mips_sim_init (&state, alloca (state_size ()));
08842 for (insn = get_insns (); insn != 0; insn = next)
08843 {
08844 unsigned int length;
08845
08846 next = NEXT_INSN (insn);
08847
08848
08849
08850
08851 vr4130_avoid_branch_rt_conflict (insn);
08852
08853 if (USEFUL_INSN_P (insn))
08854 FOR_EACH_SUBINSN (subinsn, insn)
08855 {
08856 mips_sim_wait_insn (&state, subinsn);
08857
08858
08859
08860
08861
08862
08863
08864
08865
08866
08867
08868
08869
08870
08871
08872 if (state.insns_left != state.issue_rate
08873 && !CALL_P (subinsn))
08874 {
08875 if (subinsn == SEQ_BEGIN (insn) && aligned_p)
08876 {
08877
08878
08879
08880
08881
08882
08883
08884
08885
08886
08887
08888 emit_insn_after (gen_nop (), last2);
08889 aligned_p = false;
08890 }
08891 else if (subinsn != SEQ_BEGIN (insn) && !aligned_p)
08892 {
08893
08894
08895
08896 emit_insn_after (gen_nop (), last);
08897 aligned_p = true;
08898 }
08899 }
08900 mips_sim_issue_insn (&state, subinsn);
08901 }
08902 mips_sim_finish_insn (&state, insn);
08903
08904
08905 length = get_attr_length (insn);
08906 if (length > 0)
08907 {
08908
08909
08910
08911
08912 if (NONJUMP_INSN_P (SEQ_BEGIN (insn))
08913 && (recog_memoized (insn) < 0 || length >= 8))
08914 {
08915 next = emit_insn_after (gen_align (GEN_INT (3)), insn);
08916 next = NEXT_INSN (next);
08917 mips_sim_next_cycle (&state);
08918 aligned_p = true;
08919 }
08920 else if (length & 4)
08921 aligned_p = !aligned_p;
08922 last2 = last;
08923 last = insn;
08924 }
08925
08926
08927 if (LABEL_P (insn) && label_to_alignment (insn) >= 3)
08928 aligned_p = true;
08929 }
08930 dfa_finish ();
08931 }
08932
08933
08934
08935
08936
08937
08938
08939
08940
08941
08942
08943
08944
08945
08946
08947
08948 static void
08949 mips_avoid_hazard (rtx after, rtx insn, int *hilo_delay,
08950 rtx *delayed_reg, rtx lo_reg)
08951 {
08952 rtx pattern, set;
08953 int nops, ninsns;
08954
08955 if (!INSN_P (insn))
08956 return;
08957
08958 pattern = PATTERN (insn);
08959
08960
08961
08962
08963 if (GET_CODE (pattern) == ASM_INPUT || asm_noperands (pattern) >= 0)
08964 cfun->machine->all_noreorder_p = false;
08965
08966
08967 ninsns = get_attr_length (insn) / 4;
08968 if (ninsns == 0)
08969 return;
08970
08971
08972
08973
08974
08975 if (*hilo_delay < 2 && reg_set_p (lo_reg, pattern))
08976 nops = 2 - *hilo_delay;
08977 else if (*delayed_reg != 0 && reg_referenced_p (*delayed_reg, pattern))
08978 nops = 1;
08979 else
08980 nops = 0;
08981
08982
08983
08984 *hilo_delay += nops;
08985 while (nops-- > 0)
08986 emit_insn_after (gen_hazard_nop (), after);
08987
08988
08989 *hilo_delay += ninsns;
08990 *delayed_reg = 0;
08991 if (INSN_CODE (insn) >= 0)
08992 switch (get_attr_hazard (insn))
08993 {
08994 case HAZARD_NONE:
08995 break;
08996
08997 case HAZARD_HILO:
08998 *hilo_delay = 0;
08999 break;
09000
09001 case HAZARD_DELAY:
09002 set = single_set (insn);
09003 gcc_assert (set != 0);
09004 *delayed_reg = SET_DEST (set);
09005 break;
09006 }
09007 }
09008
09009
09010
09011
09012
09013
09014 static void
09015 mips_avoid_hazards (void)
09016 {
09017 rtx insn, last_insn, lo_reg, delayed_reg;
09018 int hilo_delay, i;
09019
09020
09021 split_all_insns_noflow ();
09022
09023
09024 cfun->machine->ignore_hazard_length_p = true;
09025 shorten_branches (get_insns ());
09026
09027 cfun->machine->all_noreorder_p = true;
09028
09029
09030
09031 if (current_function_profile)
09032 cfun->machine->all_noreorder_p = false;
09033
09034
09035
09036 if (TARGET_FIX_VR4120)
09037 cfun->machine->all_noreorder_p = false;
09038
09039
09040
09041
09042
09043 if (TARGET_FIX_VR4130 && !ISA_HAS_MACCHI)
09044 cfun->machine->all_noreorder_p = false;
09045
09046 last_insn = 0;
09047 hilo_delay = 2;
09048 delayed_reg = 0;
09049 lo_reg = gen_rtx_REG (SImode, LO_REGNUM);
09050
09051 for (insn = get_insns (); insn != 0; insn = NEXT_INSN (insn))
09052 if (INSN_P (insn))
09053 {
09054 if (GET_CODE (PATTERN (insn)) == SEQUENCE)
09055 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
09056 mips_avoid_hazard (last_insn, XVECEXP (PATTERN (insn), 0, i),
09057 &hilo_delay, &delayed_reg, lo_reg);
09058 else
09059 mips_avoid_hazard (last_insn, insn, &hilo_delay,
09060 &delayed_reg, lo_reg);
09061
09062 last_insn = insn;
09063 }
09064 }
09065
09066
09067
09068
09069 static void
09070 mips_reorg (void)
09071 {
09072 if (TARGET_MIPS16)
09073 mips16_lay_out_constants ();
09074 else if (TARGET_EXPLICIT_RELOCS)
09075 {
09076 if (mips_flag_delayed_branch)
09077 dbr_schedule (get_insns ());
09078 mips_avoid_hazards ();
09079 if (TUNE_MIPS4130 && TARGET_VR4130_ALIGN)
09080 vr4130_align_insns ();
09081 }
09082 }
09083
09084
09085
09086
09087
09088
09089
09090 #include "config/gofast.h"
09091
09092 static void
09093 mips_init_libfuncs (void)
09094 {
09095 if (TARGET_FIX_VR4120)
09096 {
09097 set_optab_libfunc (sdiv_optab, SImode, "__vr4120_divsi3");
09098 set_optab_libfunc (smod_optab, SImode, "__vr4120_modsi3");
09099 }
09100
09101 if (TARGET_MIPS16 && mips16_hard_float)
09102 {
09103 set_optab_libfunc (add_optab, SFmode, "__mips16_addsf3");
09104 set_optab_libfunc (sub_optab, SFmode, "__mips16_subsf3");
09105 set_optab_libfunc (smul_optab, SFmode, "__mips16_mulsf3");
09106 set_optab_libfunc (sdiv_optab, SFmode, "__mips16_divsf3");
09107
09108 set_optab_libfunc (eq_optab, SFmode, "__mips16_eqsf2");
09109 set_optab_libfunc (ne_optab, SFmode, "__mips16_nesf2");
09110 set_optab_libfunc (gt_optab, SFmode, "__mips16_gtsf2");
09111 set_optab_libfunc (ge_optab, SFmode, "__mips16_gesf2");
09112 set_optab_libfunc (lt_optab, SFmode, "__mips16_ltsf2");
09113 set_optab_libfunc (le_optab, SFmode, "__mips16_lesf2");
09114
09115 set_conv_libfunc (sfix_optab, SImode, SFmode, "__mips16_fix_truncsfsi");
09116 set_conv_libfunc (sfloat_optab, SFmode, SImode, "__mips16_floatsisf");
09117
09118 if (TARGET_DOUBLE_FLOAT)
09119 {
09120 set_optab_libfunc (add_optab, DFmode, "__mips16_adddf3");
09121 set_optab_libfunc (sub_optab, DFmode, "__mips16_subdf3");
09122 set_optab_libfunc (smul_optab, DFmode, "__mips16_muldf3");
09123 set_optab_libfunc (sdiv_optab, DFmode, "__mips16_divdf3");
09124
09125 set_optab_libfunc (eq_optab, DFmode, "__mips16_eqdf2");
09126 set_optab_libfunc (ne_optab, DFmode, "__mips16_nedf2");
09127 set_optab_libfunc (gt_optab, DFmode, "__mips16_gtdf2");
09128 set_optab_libfunc (ge_optab, DFmode, "__mips16_gedf2");
09129 set_optab_libfunc (lt_optab, DFmode, "__mips16_ltdf2");
09130 set_optab_libfunc (le_optab, DFmode, "__mips16_ledf2");
09131
09132 set_conv_libfunc (sext_optab, DFmode, SFmode, "__mips16_extendsfdf2");
09133 set_conv_libfunc (trunc_optab, SFmode, DFmode, "__mips16_truncdfsf2");
09134
09135 set_conv_libfunc (sfix_optab, SImode, DFmode, "__mips16_fix_truncdfsi");
09136 set_conv_libfunc (sfloat_optab, DFmode, SImode, "__mips16_floatsidf");
09137 }
09138 }
09139 else
09140 gofast_maybe_init_libfuncs ();
09141 }
09142
09143
09144
09145
09146
09147
09148
09149
09150
09151
09152
09153
09154
09155
09156
09157
09158
09159
09160
09161
09162
09163
09164
09165
09166
09167
09168
09169
09170
09171
09172
09173
09174 int
09175 mips_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
09176 enum reg_class to, enum reg_class from)
09177 {
09178 if (from == M16_REGS && GR_REG_CLASS_P (to))
09179 return 2;
09180 else if (from == M16_NA_REGS && GR_REG_CLASS_P (to))
09181 return 2;
09182 else if (GR_REG_CLASS_P (from))
09183 {
09184 if (to == M16_REGS)
09185 return 2;
09186 else if (to == M16_NA_REGS)
09187 return 2;
09188 else if (GR_REG_CLASS_P (to))
09189 {
09190 if (TARGET_MIPS16)
09191 return 4;
09192 else
09193 return 2;
09194 }
09195 else if (to == FP_REGS)
09196 return 4;
09197 else if (reg_class_subset_p (to, ACC_REGS))
09198 {
09199 if (TARGET_MIPS16)
09200 return 12;
09201 else
09202 return 6;
09203 }
09204 else if (COP_REG_CLASS_P (to))
09205 {
09206 return 5;
09207 }
09208 }
09209 else if (from == FP_REGS)
09210 {
09211 if (GR_REG_CLASS_P (to))
09212 return 4;
09213 else if (to == FP_REGS)
09214 return 2;
09215 else if (to == ST_REGS)
09216 return 8;
09217 }
09218 else if (reg_class_subset_p (from, ACC_REGS))
09219 {
09220 if (GR_REG_CLASS_P (to))
09221 {
09222 if (TARGET_MIPS16)
09223 return 12;
09224 else
09225 return 6;
09226 }
09227 }
09228 else if (from == ST_REGS && GR_REG_CLASS_P (to))
09229 return 4;
09230 else if (COP_REG_CLASS_P (from))
09231 {
09232 return 5;
09233 }
09234
09235
09236
09237
09238 return 12;
09239 }
09240
09241
09242
09243
09244 int
09245 mips_adjust_insn_length (rtx insn, int length)
09246 {
09247
09248
09249
09250 if (CALL_P (insn) || (TARGET_MIPS16 ? simplejump_p (insn) : JUMP_P (insn)))
09251 length += 4;
09252
09253
09254 if (!cfun->machine->ignore_hazard_length_p && INSN_CODE (insn) >= 0)
09255 switch (get_attr_hazard (insn))
09256 {
09257 case HAZARD_NONE:
09258 break;
09259
09260 case HAZARD_DELAY:
09261 length += 4;
09262 break;
09263
09264 case HAZARD_HILO:
09265 length += 8;
09266 break;
09267 }
09268
09269
09270 if (TARGET_MIPS16)
09271 length /= 2;
09272
09273 return length;
09274 }
09275
09276
09277
09278
09279
09280 const char *
09281 mips_output_load_label (void)
09282 {
09283 if (TARGET_EXPLICIT_RELOCS)
09284 switch (mips_abi)
09285 {
09286 case ABI_N32:
09287 return "%[lw\t%@,%%got_page(%0)(%+)\n\taddiu\t%@,%@,%%got_ofst(%0)";
09288
09289 case ABI_64:
09290 return "%[ld\t%@,%%got_page(%0)(%+)\n\tdaddiu\t%@,%@,%%got_ofst(%0)";
09291
09292 default:
09293 if (ISA_HAS_LOAD_DELAY)
09294 return "%[lw\t%@,%%got(%0)(%+)%#\n\taddiu\t%@,%@,%%lo(%0)";
09295 return "%[lw\t%@,%%got(%0)(%+)\n\taddiu\t%@,%@,%%lo(%0)";
09296 }
09297 else
09298 {
09299 if (Pmode == DImode)
09300 return "%[dla\t%@,%0";
09301 else
09302 return "%[la\t%@,%0";
09303 }
09304 }
09305
09306
09307
09308
09309
09310
09311
09312 const char *
09313 mips_output_conditional_branch (rtx insn, rtx *operands,
09314 const char *branch_if_true,
09315 const char *branch_if_false)
09316 {
09317 unsigned int length;
09318 rtx taken, not_taken;
09319
09320 length = get_attr_length (insn);
09321 if (length <= 8)
09322 {
09323
09324 mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
09325 return branch_if_true;
09326 }
09327
09328
09329
09330 mips_branch_likely = false;
09331 not_taken = gen_label_rtx ();
09332 taken = operands[1];
09333
09334
09335 operands[1] = not_taken;
09336 output_asm_insn (branch_if_false, operands);
09337
09338
09339
09340
09341 if (final_sequence)
09342 {
09343
09344
09345 if (!INSN_ANNULLED_BRANCH_P (insn))
09346 {
09347 final_scan_insn (XVECEXP (final_sequence, 0, 1),
09348 asm_out_file, optimize, 1, NULL);
09349 INSN_DELETED_P (XVECEXP (final_sequence, 0, 1)) = 1;
09350 }
09351 else
09352 output_asm_insn ("nop", 0);
09353 fprintf (asm_out_file, "\n");
09354 }
09355
09356
09357 if (length <= 16)
09358 output_asm_insn ("j\t%0%/", &taken);
09359 else
09360 {
09361 output_asm_insn (mips_output_load_label (), &taken);
09362 output_asm_insn ("jr\t%@%]%/", 0);
09363 }
09364
09365
09366 if (final_sequence)
09367 {
09368
09369
09370 if (INSN_ANNULLED_BRANCH_P (insn))
09371 {
09372 final_scan_insn (XVECEXP (final_sequence, 0, 1),
09373 asm_out_file, optimize, 1, NULL);
09374 INSN_DELETED_P (XVECEXP (final_sequence, 0, 1)) = 1;
09375 }
09376 else
09377 output_asm_insn ("nop", 0);
09378 fprintf (asm_out_file, "\n");
09379 }
09380
09381
09382 (*targetm.asm_out.internal_label) (asm_out_file, "L",
09383 CODE_LABEL_NUMBER (not_taken));
09384 return "";
09385 }
09386
09387
09388
09389
09390
09391
09392
09393 const char *
09394 mips_output_order_conditional_branch (rtx insn, rtx *operands, bool inverted_p)
09395 {
09396 const char *branch[2];
09397
09398
09399
09400 switch (GET_CODE (operands[0]))
09401 {
09402
09403 case LEU:
09404 inverted_p = !inverted_p;
09405
09406 case GTU:
09407 branch[!inverted_p] = MIPS_BRANCH ("bne", "%2,%.,%1");
09408 branch[inverted_p] = MIPS_BRANCH ("beq", "%2,%.,%1");
09409 break;
09410
09411
09412 case LTU:
09413 inverted_p = !inverted_p;
09414
09415 case GEU:
09416 branch[!inverted_p] = MIPS_BRANCH ("beq", "%.,%.,%1");
09417 branch[inverted_p] = MIPS_BRANCH ("bne", "%.,%.,%1");
09418 break;
09419
09420 default:
09421 branch[!inverted_p] = MIPS_BRANCH ("b%C0z", "%2,%1");
09422 branch[inverted_p] = MIPS_BRANCH ("b%N0z", "%2,%1");
09423 break;
09424 }
09425 return mips_output_conditional_branch (insn, operands, branch[1], branch[0]);
09426 }
09427
09428
09429
09430
09431
09432
09433
09434
09435
09436
09437
09438
09439
09440
09441
09442
09443
09444
09445
09446
09447
09448
09449
09450
09451
09452
09453
09454
09455
09456
09457
09458
09459
09460
09461
09462
09463
09464
09465
09466
09467
09468
09469
09470
09471
09472
09473
09474
09475
09476
09477
09478
09479
09480
09481
09482
09483
09484
09485
09486
09487
09488
09489
09490
09491
09492
09493
09494
09495
09496
09497
09498
09499
09500
09501
09502
09503
09504
09505
09506
09507
09508
09509
09510
09511
09512
09513
09514
09515
09516
09517 const char *
09518 mips_output_division (const char *division, rtx *operands)
09519 {
09520 const char *s;
09521
09522 s = division;
09523 if (TARGET_FIX_R4000 || TARGET_FIX_R4400)
09524 {
09525 output_asm_insn (s, operands);
09526 s = "nop";
09527 }
09528 if (TARGET_CHECK_ZERO_DIV)
09529 {
09530 if (TARGET_MIPS16)
09531 {
09532 output_asm_insn (s, operands);
09533 s = "bnez\t%2,1f\n\tbreak\t7\n1:";
09534 }
09535 else if (GENERATE_DIVIDE_TRAPS)
09536 {
09537 output_asm_insn (s, operands);
09538 s = "teq\t%2,%.,7";
09539 }
09540 else
09541 {
09542 output_asm_insn ("%(bne\t%2,%.,1f", operands);
09543 output_asm_insn (s, operands);
09544 s = "break\t7%)\n1:";
09545 }
09546 }
09547 return s;
09548 }
09549
09550
09551
09552
09553
09554
09555 static bool
09556 mips_strict_matching_cpu_name_p (const char *canonical, const char *given)
09557 {
09558 while (*given != 0 && TOLOWER (*given) == TOLOWER (*canonical))
09559 given++, canonical++;
09560
09561 return ((*given == 0 && *canonical == 0)
09562 || (strcmp (canonical, "000") == 0 && strcasecmp (given, "k") == 0));
09563 }
09564
09565
09566
09567
09568
09569
09570
09571 static bool
09572 mips_matching_cpu_name_p (const char *canonical, const char *given)
09573 {
09574
09575
09576 if (mips_strict_matching_cpu_name_p (canonical, given))
09577 return true;
09578
09579
09580
09581 if (TOLOWER (*given) == 'r')
09582 given++;
09583 if (!ISDIGIT (*given))
09584 return false;
09585
09586
09587
09588 if (TOLOWER (canonical[0]) == 'v' && TOLOWER (canonical[1]) == 'r')
09589 canonical += 2;
09590 else if (TOLOWER (canonical[0]) == 'r' && TOLOWER (canonical[1]) == 'm')
09591 canonical += 2;
09592 else if (TOLOWER (canonical[0]) == 'r')
09593 canonical += 1;
09594
09595 return mips_strict_matching_cpu_name_p (canonical, given);
09596 }
09597
09598
09599
09600
09601
09602
09603
09604 static const struct mips_cpu_info *
09605 mips_parse_cpu (const char *cpu_string)
09606 {
09607 const struct mips_cpu_info *p;
09608 const char *s;
09609
09610
09611
09612 for (s = cpu_string; *s != 0; s++)
09613 if (ISUPPER (*s))
09614 {
09615 warning (0, "the cpu name must be lower case");
09616 break;
09617 }
09618
09619
09620
09621
09622
09623
09624 if (strcasecmp (cpu_string, "from-abi") == 0)
09625 return mips_cpu_info_from_isa (ABI_NEEDS_32BIT_REGS ? 1
09626 : ABI_NEEDS_64BIT_REGS ? 3
09627 : (TARGET_64BIT ? 3 : 1));
09628
09629
09630 if (strcasecmp (cpu_string, "default") == 0)
09631 return 0;
09632
09633 for (p = mips_cpu_info_table; p->name != 0; p++)
09634 if (mips_matching_cpu_name_p (p->name, cpu_string))
09635 return p;
09636
09637 return 0;
09638 }
09639
09640
09641
09642
09643
09644 static const struct mips_cpu_info *
09645 mips_cpu_info_from_isa (int isa)
09646 {
09647 const struct mips_cpu_info *p;
09648
09649 for (p = mips_cpu_info_table; p->name != 0; p++)
09650 if (p->isa == isa)
09651 return p;
09652
09653 return 0;
09654 }
09655
09656
09657
09658
09659
09660
09661 unsigned int
09662 mips_hard_regno_nregs (int regno, enum machine_mode mode)
09663 {
09664 if (ST_REG_P (regno))
09665 return ((GET_MODE_SIZE (mode) + 3) / 4);
09666 else if (! FP_REG_P (regno))
09667 return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
09668 else
09669 return ((GET_MODE_SIZE (mode) + UNITS_PER_FPREG - 1) / UNITS_PER_FPREG);
09670 }
09671
09672
09673
09674
09675
09676
09677
09678 static bool
09679 mips_return_in_memory (tree type, tree fndecl ATTRIBUTE_UNUSED)
09680 {
09681 if (TARGET_OLDABI)
09682 return (TYPE_MODE (type) == BLKmode);
09683 else
09684 return ((int_size_in_bytes (type) > (2 * UNITS_PER_WORD))
09685 || (int_size_in_bytes (type) == -1));
09686 }
09687
09688 static bool
09689 mips_strict_argument_naming (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED)
09690 {
09691 return !TARGET_OLDABI;
09692 }
09693
09694
09695
09696
09697 bool
09698 mips_linked_madd_p (rtx prev, rtx insn)
09699 {
09700 rtx x;
09701
09702 x = single_set (insn);
09703 if (x == 0)
09704 return false;
09705
09706 x = SET_SRC (x);
09707
09708 if (GET_CODE (x) == PLUS
09709 && GET_CODE (XEXP (x, 0)) == MULT
09710 && reg_set_p (XEXP (x, 1), prev))
09711 return true;
09712
09713 if (GET_CODE (x) == MINUS
09714 && GET_CODE (XEXP (x, 1)) == MULT
09715 && reg_set_p (XEXP (x, 0), prev))
09716 return true;
09717
09718 return false;
09719 }
09720
09721
09722
09723
09724 static rtx mips_macc_chains_last_hilo;
09725
09726
09727
09728
09729 static void
09730 mips_macc_chains_record (rtx insn)
09731 {
09732 if (get_attr_may_clobber_hilo (insn))
09733 mips_macc_chains_last_hilo = insn;
09734 }
09735
09736
09737
09738
09739
09740
09741
09742 static void
09743 mips_macc_chains_reorder (rtx *ready, int nready)
09744 {
09745 int i, j;
09746
09747 if (mips_macc_chains_last_hilo != 0)
09748 for (i = nready - 1; i >= 0; i--)
09749 if (mips_linked_madd_p (mips_macc_chains_last_hilo, ready[i]))
09750 {
09751 for (j = nready - 1; j > i; j--)
09752 if (recog_memoized (ready[j]) >= 0
09753 && get_attr_may_clobber_hilo (ready[j]))
09754 {
09755 mips_promote_ready (ready, i, j);
09756 break;
09757 }
09758 break;
09759 }
09760 }
09761
09762
09763
09764 static rtx vr4130_last_insn;
09765
09766
09767
09768
09769
09770 static void
09771 vr4130_true_reg_dependence_p_1 (rtx x, rtx pat ATTRIBUTE_UNUSED, void *data)
09772 {
09773 rtx *insn_ptr = data;
09774 if (REG_P (x)
09775 && *insn_ptr != 0
09776 && reg_referenced_p (x, PATTERN (*insn_ptr)))
09777 *insn_ptr = 0;
09778 }
09779
09780
09781
09782
09783 static bool
09784 vr4130_true_reg_dependence_p (rtx insn)
09785 {
09786 note_stores (PATTERN (vr4130_last_insn),
09787 vr4130_true_reg_dependence_p_1, &insn);
09788 return insn == 0;
09789 }
09790
09791
09792
09793
09794
09795
09796
09797
09798 static bool
09799 vr4130_swap_insns_p (rtx insn1, rtx insn2)
09800 {
09801 rtx dep;
09802
09803
09804
09805
09806
09807
09808
09809
09810
09811 for (dep = INSN_DEPEND (insn1); dep != 0; dep = XEXP (dep, 1))
09812 if (REG_NOTE_KIND (dep) == REG_DEP_ANTI
09813 && INSN_PRIORITY (XEXP (dep, 0)) > INSN_PRIORITY (insn2)
09814 && recog_memoized (XEXP (dep, 0)) >= 0
09815 && get_attr_vr4130_class (XEXP (dep, 0)) == VR4130_CLASS_ALU)
09816 return false;
09817
09818 if (vr4130_last_insn != 0
09819 && recog_memoized (insn1) >= 0
09820 && recog_memoized (insn2) >= 0)
09821 {
09822
09823
09824
09825 enum attr_vr4130_class class1 = get_attr_vr4130_class (insn1);
09826 enum attr_vr4130_class class2 = get_attr_vr4130_class (insn2);
09827 if (class1 != class2 || class1 == VR4130_CLASS_ALU)
09828 {
09829
09830
09831 bool dep1 = vr4130_true_reg_dependence_p (insn1);
09832 bool dep2 = vr4130_true_reg_dependence_p (insn2);
09833 if (dep1 != dep2)
09834 return dep1;
09835
09836
09837
09838
09839
09840 if (class1 != VR4130_CLASS_ALU
09841 && recog_memoized (vr4130_last_insn) >= 0
09842 && class1 == get_attr_vr4130_class (vr4130_last_insn))
09843 return true;
09844 }
09845 }
09846 return false;
09847 }
09848
09849
09850
09851
09852
09853 static void
09854 vr4130_reorder (rtx *ready, int nready)
09855 {
09856 if (vr4130_swap_insns_p (ready[nready - 1], ready[nready - 2]))
09857 mips_promote_ready (ready, nready - 2, nready - 1);
09858 }
09859
09860
09861
09862
09863
09864 static void
09865 mips_promote_ready (rtx *ready, int lower, int higher)
09866 {
09867 rtx new_head;
09868 int i;
09869
09870 new_head = ready[lower];
09871 for (i = lower; i < higher; i++)
09872 ready[i] = ready[i + 1];
09873 ready[i] = new_head;
09874 }
09875
09876
09877
09878 static int
09879 mips_sched_reorder (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
09880 rtx *ready, int *nreadyp, int cycle)
09881 {
09882 if (!reload_completed && TUNE_MACC_CHAINS)
09883 {
09884 if (cycle == 0)
09885 mips_macc_chains_last_hilo = 0;
09886 if (*nreadyp > 0)
09887 mips_macc_chains_reorder (ready, *nreadyp);
09888 }
09889 if (reload_completed && TUNE_MIPS4130 && !TARGET_VR4130_ALIGN)
09890 {
09891 if (cycle == 0)
09892 vr4130_last_insn = 0;
09893 if (*nreadyp > 1)
09894 vr4130_reorder (ready, *nreadyp);
09895 }
09896 return mips_issue_rate ();
09897 }
09898
09899
09900
09901 static int
09902 mips_variable_issue (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
09903 rtx insn, int more)
09904 {
09905 switch (GET_CODE (PATTERN (insn)))
09906 {
09907 case USE:
09908 case CLOBBER:
09909
09910 break;
09911
09912 default:
09913 more--;
09914 if (!reload_completed && TUNE_MACC_CHAINS)
09915 mips_macc_chains_record (insn);
09916 vr4130_last_insn = insn;
09917 break;
09918 }
09919 return more;
09920 }
09921
09922
09923
09924
09925 static int
09926 mips_adjust_cost (rtx insn ATTRIBUTE_UNUSED, rtx link,
09927 rtx dep ATTRIBUTE_UNUSED, int cost)
09928 {
09929 if (REG_NOTE_KIND (link) != 0)
09930 return 0;
09931 return cost;
09932 }
09933
09934
09935
09936 static int
09937 mips_issue_rate (void)
09938 {
09939 switch (mips_tune)
09940 {
09941 case PROCESSOR_R4130:
09942 case PROCESSOR_R5400:
09943 case PROCESSOR_R5500:
09944 case PROCESSOR_R7000:
09945 case PROCESSOR_R9000:
09946 return 2;
09947
09948 case PROCESSOR_SB1:
09949 case PROCESSOR_SB1A:
09950
09951
09952
09953
09954 return 3;
09955
09956 default:
09957 return 1;
09958 }
09959 }
09960
09961
09962
09963
09964 static int
09965 mips_multipass_dfa_lookahead (void)
09966 {
09967
09968 if (TUNE_SB1)
09969 return 4;
09970
09971 return 0;
09972 }
09973
09974
09975
09976
09977
09978
09979 int
09980 mips_store_data_bypass_p (rtx out_insn, rtx in_insn)
09981 {
09982 if (GET_CODE (PATTERN (in_insn)) == UNSPEC_VOLATILE)
09983 return false;
09984
09985 return ! store_data_bypass_p (out_insn, in_insn);
09986 }
09987
09988
09989
09990
09991 rtx
09992 mips_prefetch_cookie (rtx write, rtx locality)
09993 {
09994
09995 if (INTVAL (locality) <= 0)
09996 return GEN_INT (INTVAL (write) + 4);
09997
09998
09999 if (INTVAL (locality) <= 2)
10000 return write;
10001
10002
10003 return GEN_INT (INTVAL (write) + 6);
10004 }
10005
10006
10007
10008 struct builtin_description
10009 {
10010
10011
10012 enum insn_code icode;
10013
10014
10015 enum mips_fp_condition cond;
10016
10017
10018 const char *name;
10019
10020
10021 enum mips_builtin_type builtin_type;
10022
10023
10024 enum mips_function_type function_type;
10025
10026
10027 int target_flags;
10028 };
10029
10030
10031
10032 #define DIRECT_BUILTIN(INSN, FUNCTION_TYPE, TARGET_FLAGS) \
10033 { CODE_FOR_mips_ ## INSN, 0, "__builtin_mips_" #INSN, \
10034 MIPS_BUILTIN_DIRECT, FUNCTION_TYPE, TARGET_FLAGS }
10035
10036
10037
10038 #define CMP_SCALAR_BUILTINS(INSN, COND, TARGET_FLAGS) \
10039 { CODE_FOR_mips_ ## INSN ## _cond_s, MIPS_FP_COND_ ## COND, \
10040 "__builtin_mips_" #INSN "_" #COND "_s", \
10041 MIPS_BUILTIN_CMP_SINGLE, MIPS_INT_FTYPE_SF_SF, TARGET_FLAGS }, \
10042 { CODE_FOR_mips_ ## INSN ## _cond_d, MIPS_FP_COND_ ## COND, \
10043 "__builtin_mips_" #INSN "_" #COND "_d", \
10044 MIPS_BUILTIN_CMP_SINGLE, MIPS_INT_FTYPE_DF_DF, TARGET_FLAGS }
10045
10046
10047
10048
10049 #define CMP_PS_BUILTINS(INSN, COND, TARGET_FLAGS) \
10050 { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
10051 "__builtin_mips_any_" #INSN "_" #COND "_ps", \
10052 MIPS_BUILTIN_CMP_ANY, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D }, \
10053 { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
10054 "__builtin_mips_all_" #INSN "_" #COND "_ps", \
10055 MIPS_BUILTIN_CMP_ALL, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D }, \
10056 { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
10057 "__builtin_mips_lower_" #INSN "_" #COND "_ps", \
10058 MIPS_BUILTIN_CMP_LOWER, MIPS_INT_FTYPE_V2SF_V2SF, TARGET_FLAGS }, \
10059 { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
10060 "__builtin_mips_upper_" #INSN "_" #COND "_ps", \
10061 MIPS_BUILTIN_CMP_UPPER, MIPS_INT_FTYPE_V2SF_V2SF, TARGET_FLAGS }
10062
10063
10064
10065 #define CMP_4S_BUILTINS(INSN, COND) \
10066 { CODE_FOR_mips_ ## INSN ## _cond_4s, MIPS_FP_COND_ ## COND, \
10067 "__builtin_mips_any_" #INSN "_" #COND "_4s", \
10068 MIPS_BUILTIN_CMP_ANY, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF, \
10069 MASK_MIPS3D }, \
10070 { CODE_FOR_mips_ ## INSN ## _cond_4s, MIPS_FP_COND_ ## COND, \
10071 "__builtin_mips_all_" #INSN "_" #COND "_4s", \
10072 MIPS_BUILTIN_CMP_ALL, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF, \
10073 MASK_MIPS3D }
10074
10075
10076
10077 #define MOVTF_BUILTINS(INSN, COND, TARGET_FLAGS) \
10078 { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
10079 "__builtin_mips_movt_" #INSN "_" #COND "_ps", \
10080 MIPS_BUILTIN_MOVT, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF, \
10081 TARGET_FLAGS }, \
10082 { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
10083 "__builtin_mips_movf_" #INSN "_" #COND "_ps", \
10084 MIPS_BUILTIN_MOVF, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF, \
10085 TARGET_FLAGS }
10086
10087
10088 #define CMP_BUILTINS(COND) \
10089 MOVTF_BUILTINS (c, COND, MASK_PAIRED_SINGLE_FLOAT), \
10090 MOVTF_BUILTINS (cabs, COND, MASK_MIPS3D), \
10091 CMP_SCALAR_BUILTINS (cabs, COND, MASK_MIPS3D), \
10092 CMP_PS_BUILTINS (c, COND, MASK_PAIRED_SINGLE_FLOAT), \
10093 CMP_PS_BUILTINS (cabs, COND, MASK_MIPS3D), \
10094 CMP_4S_BUILTINS (c, COND), \
10095 CMP_4S_BUILTINS (cabs, COND)
10096
10097 static const struct builtin_description mips_bdesc[] =
10098 {
10099 DIRECT_BUILTIN (pll_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE_FLOAT),
10100 DIRECT_BUILTIN (pul_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE_FLOAT),
10101 DIRECT_BUILTIN (plu_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE_FLOAT),
10102 DIRECT_BUILTIN (puu_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE_FLOAT),
10103 DIRECT_BUILTIN (cvt_ps_s, MIPS_V2SF_FTYPE_SF_SF, MASK_PAIRED_SINGLE_FLOAT),
10104 DIRECT_BUILTIN (cvt_s_pl, MIPS_SF_FTYPE_V2SF, MASK_PAIRED_SINGLE_FLOAT),
10105 DIRECT_BUILTIN (cvt_s_pu, MIPS_SF_FTYPE_V2SF, MASK_PAIRED_SINGLE_FLOAT),
10106 DIRECT_BUILTIN (abs_ps, MIPS_V2SF_FTYPE_V2SF, MASK_PAIRED_SINGLE_FLOAT),
10107
10108 DIRECT_BUILTIN (alnv_ps, MIPS_V2SF_FTYPE_V2SF_V2SF_INT,
10109 MASK_PAIRED_SINGLE_FLOAT),
10110 DIRECT_BUILTIN (addr_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D),
10111 DIRECT_BUILTIN (mulr_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D),
10112 DIRECT_BUILTIN (cvt_pw_ps, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D),
10113 DIRECT_BUILTIN (cvt_ps_pw, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D),
10114
10115 DIRECT_BUILTIN (recip1_s, MIPS_SF_FTYPE_SF, MASK_MIPS3D),
10116 DIRECT_BUILTIN (recip1_d, MIPS_DF_FTYPE_DF, MASK_MIPS3D),
10117 DIRECT_BUILTIN (recip1_ps, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D),
10118 DIRECT_BUILTIN (recip2_s, MIPS_SF_FTYPE_SF_SF, MASK_MIPS3D),
10119 DIRECT_BUILTIN (recip2_d, MIPS_DF_FTYPE_DF_DF, MASK_MIPS3D),
10120 DIRECT_BUILTIN (recip2_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D),
10121
10122 DIRECT_BUILTIN (rsqrt1_s, MIPS_SF_FTYPE_SF, MASK_MIPS3D),
10123 DIRECT_BUILTIN (rsqrt1_d, MIPS_DF_FTYPE_DF, MASK_MIPS3D),
10124 DIRECT_BUILTIN (rsqrt1_ps, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D),
10125 DIRECT_BUILTIN (rsqrt2_s, MIPS_SF_FTYPE_SF_SF, MASK_MIPS3D),
10126 DIRECT_BUILTIN (rsqrt2_d, MIPS_DF_FTYPE_DF_DF, MASK_MIPS3D),
10127 DIRECT_BUILTIN (rsqrt2_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D),
10128
10129 MIPS_FP_CONDITIONS (CMP_BUILTINS)
10130 };
10131
10132
10133
10134 #define CODE_FOR_mips_sqrt_ps CODE_FOR_sqrtv2sf2
10135
10136 static const struct builtin_description sb1_bdesc[] =
10137 {
10138 DIRECT_BUILTIN (sqrt_ps, MIPS_V2SF_FTYPE_V2SF, MASK_PAIRED_SINGLE_FLOAT)
10139 };
10140
10141
10142
10143 #define CODE_FOR_mips_addq_ph CODE_FOR_addv2hi3
10144 #define CODE_FOR_mips_addu_qb CODE_FOR_addv4qi3
10145 #define CODE_FOR_mips_subq_ph CODE_FOR_subv2hi3
10146 #define CODE_FOR_mips_subu_qb CODE_FOR_subv4qi3
10147
10148
10149
10150
10151 #define DIRECT_NO_TARGET_BUILTIN(INSN, FUNCTION_TYPE, TARGET_FLAGS) \
10152 { CODE_FOR_mips_ ## INSN, 0, "__builtin_mips_" #INSN, \
10153 MIPS_BUILTIN_DIRECT_NO_TARGET, FUNCTION_TYPE, TARGET_FLAGS }
10154
10155
10156
10157 #define BPOSGE_BUILTIN(VALUE, TARGET_FLAGS) \
10158 { CODE_FOR_mips_bposge, 0, "__builtin_mips_bposge" #VALUE, \
10159 MIPS_BUILTIN_BPOSGE ## VALUE, MIPS_SI_FTYPE_VOID, TARGET_FLAGS }
10160
10161 static const struct builtin_description dsp_bdesc[] =
10162 {
10163 DIRECT_BUILTIN (addq_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
10164 DIRECT_BUILTIN (addq_s_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
10165 DIRECT_BUILTIN (addq_s_w, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
10166 DIRECT_BUILTIN (addu_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP),
10167 DIRECT_BUILTIN (addu_s_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP),
10168 DIRECT_BUILTIN (subq_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
10169 DIRECT_BUILTIN (subq_s_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
10170 DIRECT_BUILTIN (subq_s_w, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
10171 DIRECT_BUILTIN (subu_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP),
10172 DIRECT_BUILTIN (subu_s_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP),
10173 DIRECT_BUILTIN (addsc, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
10174 DIRECT_BUILTIN (addwc, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
10175 DIRECT_BUILTIN (modsub, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
10176 DIRECT_BUILTIN (raddu_w_qb, MIPS_SI_FTYPE_V4QI, MASK_DSP),
10177 DIRECT_BUILTIN (absq_s_ph, MIPS_V2HI_FTYPE_V2HI, MASK_DSP),
10178 DIRECT_BUILTIN (absq_s_w, MIPS_SI_FTYPE_SI, MASK_DSP),
10179 DIRECT_BUILTIN (precrq_qb_ph, MIPS_V4QI_FTYPE_V2HI_V2HI, MASK_DSP),
10180 DIRECT_BUILTIN (precrq_ph_w, MIPS_V2HI_FTYPE_SI_SI, MASK_DSP),
10181 DIRECT_BUILTIN (precrq_rs_ph_w, MIPS_V2HI_FTYPE_SI_SI, MASK_DSP),
10182 DIRECT_BUILTIN (precrqu_s_qb_ph, MIPS_V4QI_FTYPE_V2HI_V2HI, MASK_DSP),
10183 DIRECT_BUILTIN (preceq_w_phl, MIPS_SI_FTYPE_V2HI, MASK_DSP),
10184 DIRECT_BUILTIN (preceq_w_phr, MIPS_SI_FTYPE_V2HI, MASK_DSP),
10185 DIRECT_BUILTIN (precequ_ph_qbl, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
10186 DIRECT_BUILTIN (precequ_ph_qbr, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
10187 DIRECT_BUILTIN (precequ_ph_qbla, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
10188 DIRECT_BUILTIN (precequ_ph_qbra, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
10189 DIRECT_BUILTIN (preceu_ph_qbl, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
10190 DIRECT_BUILTIN (preceu_ph_qbr, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
10191 DIRECT_BUILTIN (preceu_ph_qbla, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
10192 DIRECT_BUILTIN (preceu_ph_qbra, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
10193 DIRECT_BUILTIN (shll_qb, MIPS_V4QI_FTYPE_V4QI_SI, MASK_DSP),
10194 DIRECT_BUILTIN (shll_ph, MIPS_V2HI_FTYPE_V2HI_SI, MASK_DSP),
10195 DIRECT_BUILTIN (shll_s_ph, MIPS_V2HI_FTYPE_V2HI_SI, MASK_DSP),
10196 DIRECT_BUILTIN (shll_s_w, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
10197 DIRECT_BUILTIN (shrl_qb, MIPS_V4QI_FTYPE_V4QI_SI, MASK_DSP),
10198 DIRECT_BUILTIN (shra_ph, MIPS_V2HI_FTYPE_V2HI_SI, MASK_DSP),
10199 DIRECT_BUILTIN (shra_r_ph, MIPS_V2HI_FTYPE_V2HI_SI, MASK_DSP),
10200 DIRECT_BUILTIN (shra_r_w, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
10201 DIRECT_BUILTIN (muleu_s_ph_qbl, MIPS_V2HI_FTYPE_V4QI_V2HI, MASK_DSP),
10202 DIRECT_BUILTIN (muleu_s_ph_qbr, MIPS_V2HI_FTYPE_V4QI_V2HI, MASK_DSP),
10203 DIRECT_BUILTIN (mulq_rs_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
10204 DIRECT_BUILTIN (muleq_s_w_phl, MIPS_SI_FTYPE_V2HI_V2HI, MASK_DSP),
10205 DIRECT_BUILTIN (muleq_s_w_phr, MIPS_SI_FTYPE_V2HI_V2HI, MASK_DSP),
10206 DIRECT_BUILTIN (dpau_h_qbl, MIPS_DI_FTYPE_DI_V4QI_V4QI, MASK_DSP),
10207 DIRECT_BUILTIN (dpau_h_qbr, MIPS_DI_FTYPE_DI_V4QI_V4QI, MASK_DSP),
10208 DIRECT_BUILTIN (dpsu_h_qbl, MIPS_DI_FTYPE_DI_V4QI_V4QI, MASK_DSP),
10209 DIRECT_BUILTIN (dpsu_h_qbr, MIPS_DI_FTYPE_DI_V4QI_V4QI, MASK_DSP),
10210 DIRECT_BUILTIN (dpaq_s_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
10211 DIRECT_BUILTIN (dpsq_s_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
10212 DIRECT_BUILTIN (mulsaq_s_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
10213 DIRECT_BUILTIN (dpaq_sa_l_w, MIPS_DI_FTYPE_DI_SI_SI, MASK_DSP),
10214 DIRECT_BUILTIN (dpsq_sa_l_w, MIPS_DI_FTYPE_DI_SI_SI, MASK_DSP),
10215 DIRECT_BUILTIN (maq_s_w_phl, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
10216 DIRECT_BUILTIN (maq_s_w_phr, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
10217 DIRECT_BUILTIN (maq_sa_w_phl, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
10218 DIRECT_BUILTIN (maq_sa_w_phr, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
10219 DIRECT_BUILTIN (bitrev, MIPS_SI_FTYPE_SI, MASK_DSP),
10220 DIRECT_BUILTIN (insv, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
10221 DIRECT_BUILTIN (repl_qb, MIPS_V4QI_FTYPE_SI, MASK_DSP),
10222 DIRECT_BUILTIN (repl_ph, MIPS_V2HI_FTYPE_SI, MASK_DSP),
10223 DIRECT_NO_TARGET_BUILTIN (cmpu_eq_qb, MIPS_VOID_FTYPE_V4QI_V4QI, MASK_DSP),
10224 DIRECT_NO_TARGET_BUILTIN (cmpu_lt_qb, MIPS_VOID_FTYPE_V4QI_V4QI, MASK_DSP),
10225 DIRECT_NO_TARGET_BUILTIN (cmpu_le_qb, MIPS_VOID_FTYPE_V4QI_V4QI, MASK_DSP),
10226 DIRECT_BUILTIN (cmpgu_eq_qb, MIPS_SI_FTYPE_V4QI_V4QI, MASK_DSP),
10227 DIRECT_BUILTIN (cmpgu_lt_qb, MIPS_SI_FTYPE_V4QI_V4QI, MASK_DSP),
10228 DIRECT_BUILTIN (cmpgu_le_qb, MIPS_SI_FTYPE_V4QI_V4QI, MASK_DSP),
10229 DIRECT_NO_TARGET_BUILTIN (cmp_eq_ph, MIPS_VOID_FTYPE_V2HI_V2HI, MASK_DSP),
10230 DIRECT_NO_TARGET_BUILTIN (cmp_lt_ph, MIPS_VOID_FTYPE_V2HI_V2HI, MASK_DSP),
10231 DIRECT_NO_TARGET_BUILTIN (cmp_le_ph, MIPS_VOID_FTYPE_V2HI_V2HI, MASK_DSP),
10232 DIRECT_BUILTIN (pick_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP),
10233 DIRECT_BUILTIN (pick_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
10234 DIRECT_BUILTIN (packrl_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
10235 DIRECT_BUILTIN (extr_w, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
10236 DIRECT_BUILTIN (extr_r_w, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
10237 DIRECT_BUILTIN (extr_rs_w, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
10238 DIRECT_BUILTIN (extr_s_h, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
10239 DIRECT_BUILTIN (extp, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
10240 DIRECT_BUILTIN (extpdp, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
10241 DIRECT_BUILTIN (shilo, MIPS_DI_FTYPE_DI_SI, MASK_DSP),
10242 DIRECT_BUILTIN (mthlip, MIPS_DI_FTYPE_DI_SI, MASK_DSP),
10243 DIRECT_NO_TARGET_BUILTIN (wrdsp, MIPS_VOID_FTYPE_SI_SI, MASK_DSP),
10244 DIRECT_BUILTIN (rddsp, MIPS_SI_FTYPE_SI, MASK_DSP),
10245 DIRECT_BUILTIN (lbux, MIPS_SI_FTYPE_PTR_SI, MASK_DSP),
10246 DIRECT_BUILTIN (lhx, MIPS_SI_FTYPE_PTR_SI, MASK_DSP),
10247 DIRECT_BUILTIN (lwx, MIPS_SI_FTYPE_PTR_SI, MASK_DSP),
10248 BPOSGE_BUILTIN (32, MASK_DSP)
10249 };
10250
10251
10252
10253
10254 struct bdesc_map
10255 {
10256
10257 const struct builtin_description *bdesc;
10258
10259
10260 unsigned int size;
10261
10262
10263
10264 enum processor_type proc;
10265 };
10266
10267 static const struct bdesc_map bdesc_arrays[] =
10268 {
10269 { mips_bdesc, ARRAY_SIZE (mips_bdesc), PROCESSOR_MAX },
10270 { sb1_bdesc, ARRAY_SIZE (sb1_bdesc), PROCESSOR_SB1 },
10271 { dsp_bdesc, ARRAY_SIZE (dsp_bdesc), PROCESSOR_MAX }
10272 };
10273
10274
10275
10276
10277
10278 static rtx
10279 mips_prepare_builtin_arg (enum insn_code icode,
10280 unsigned int op, tree *arglist)
10281 {
10282 rtx value;
10283 enum machine_mode mode;
10284
10285 value = expand_normal (TREE_VALUE (*arglist));
10286 mode = insn_data[icode].operand[op].mode;
10287 if (!insn_data[icode].operand[op].predicate (value, mode))
10288 {
10289 value = copy_to_mode_reg (mode, value);
10290
10291 if (!insn_data[icode].operand[op].predicate (value, mode))
10292 {
10293 error ("invalid argument to builtin function");
10294 return const0_rtx;
10295 }
10296 }
10297
10298 *arglist = TREE_CHAIN (*arglist);
10299 return value;
10300 }
10301
10302
10303
10304
10305 static rtx
10306 mips_prepare_builtin_target (enum insn_code icode, unsigned int op, rtx target)
10307 {
10308 enum machine_mode mode;
10309
10310 mode = insn_data[icode].operand[op].mode;
10311 if (target == 0 || !insn_data[icode].operand[op].predicate (target, mode))
10312 target = gen_reg_rtx (mode);
10313
10314 return target;
10315 }
10316
10317
10318
10319 rtx
10320 mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
10321 enum machine_mode mode ATTRIBUTE_UNUSED,
10322 int ignore ATTRIBUTE_UNUSED)
10323 {
10324 enum insn_code icode;
10325 enum mips_builtin_type type;
10326 tree fndecl, arglist;
10327 unsigned int fcode;
10328 const struct builtin_description *bdesc;
10329 const struct bdesc_map *m;
10330
10331 fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
10332 arglist = TREE_OPERAND (exp, 1);
10333 fcode = DECL_FUNCTION_CODE (fndecl);
10334
10335 bdesc = NULL;
10336 for (m = bdesc_arrays; m < &bdesc_arrays[ARRAY_SIZE (bdesc_arrays)]; m++)
10337 {
10338 if (fcode < m->size)
10339 {
10340 bdesc = m->bdesc;
10341 icode = bdesc[fcode].icode;
10342 type = bdesc[fcode].builtin_type;
10343 break;
10344 }
10345 fcode -= m->size;
10346 }
10347 if (bdesc == NULL)
10348 return 0;
10349
10350 switch (type)
10351 {
10352 case MIPS_BUILTIN_DIRECT:
10353 return mips_expand_builtin_direct (icode, target, arglist, true);
10354
10355 case MIPS_BUILTIN_DIRECT_NO_TARGET:
10356 return mips_expand_builtin_direct (icode, target, arglist, false);
10357
10358 case MIPS_BUILTIN_MOVT:
10359 case MIPS_BUILTIN_MOVF:
10360 return mips_expand_builtin_movtf (type, icode, bdesc[fcode].cond,
10361 target, arglist);
10362
10363 case MIPS_BUILTIN_CMP_ANY:
10364 case MIPS_BUILTIN_CMP_ALL:
10365 case MIPS_BUILTIN_CMP_UPPER:
10366 case MIPS_BUILTIN_CMP_LOWER:
10367 case MIPS_BUILTIN_CMP_SINGLE:
10368 return mips_expand_builtin_compare (type, icode, bdesc[fcode].cond,
10369 target, arglist);
10370
10371 case MIPS_BUILTIN_BPOSGE32:
10372 return mips_expand_builtin_bposge (type, target);
10373
10374 default:
10375 return 0;
10376 }
10377 }
10378
10379
10380
10381 void
10382 mips_init_builtins (void)
10383 {
10384 const struct builtin_description *d;
10385 const struct bdesc_map *m;
10386 tree types[(int) MIPS_MAX_FTYPE_MAX];
10387 tree V2SF_type_node;
10388 tree V2HI_type_node;
10389 tree V4QI_type_node;
10390 unsigned int offset;
10391
10392
10393 if (!TARGET_PAIRED_SINGLE_FLOAT && !TARGET_DSP)
10394 return;
10395
10396 if (TARGET_PAIRED_SINGLE_FLOAT)
10397 {
10398 V2SF_type_node = build_vector_type_for_mode (float_type_node, V2SFmode);
10399
10400 types[MIPS_V2SF_FTYPE_V2SF]
10401 = build_function_type_list (V2SF_type_node, V2SF_type_node, NULL_TREE);
10402
10403 types[MIPS_V2SF_FTYPE_V2SF_V2SF]
10404 = build_function_type_list (V2SF_type_node,
10405 V2SF_type_node, V2SF_type_node, NULL_TREE);
10406
10407 types[MIPS_V2SF_FTYPE_V2SF_V2SF_INT]
10408 = build_function_type_list (V2SF_type_node,
10409 V2SF_type_node, V2SF_type_node,
10410 integer_type_node, NULL_TREE);
10411
10412 types[MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF]
10413 = build_function_type_list (V2SF_type_node,
10414 V2SF_type_node, V2SF_type_node,
10415 V2SF_type_node, V2SF_type_node, NULL_TREE);
10416
10417 types[MIPS_V2SF_FTYPE_SF_SF]
10418 = build_function_type_list (V2SF_type_node,
10419 float_type_node, float_type_node, NULL_TREE);
10420
10421 types[MIPS_INT_FTYPE_V2SF_V2SF]
10422 = build_function_type_list (integer_type_node,
10423 V2SF_type_node, V2SF_type_node, NULL_TREE);
10424
10425 types[MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF]
10426 = build_function_type_list (integer_type_node,
10427 V2SF_type_node, V2SF_type_node,
10428 V2SF_type_node, V2SF_type_node, NULL_TREE);
10429
10430 types[MIPS_INT_FTYPE_SF_SF]
10431 = build_function_type_list (integer_type_node,
10432 float_type_node, float_type_node, NULL_TREE);
10433
10434 types[MIPS_INT_FTYPE_DF_DF]
10435 = build_function_type_list (integer_type_node,
10436 double_type_node, double_type_node, NULL_TREE);
10437
10438 types[MIPS_SF_FTYPE_V2SF]
10439 = build_function_type_list (float_type_node, V2SF_type_node, NULL_TREE);
10440
10441 types[MIPS_SF_FTYPE_SF]
10442 = build_function_type_list (float_type_node,
10443 float_type_node, NULL_TREE);
10444
10445 types[MIPS_SF_FTYPE_SF_SF]
10446 = build_function_type_list (float_type_node,
10447 float_type_node, float_type_node, NULL_TREE);
10448
10449 types[MIPS_DF_FTYPE_DF]
10450 = build_function_type_list (double_type_node,
10451 double_type_node, NULL_TREE);
10452
10453 types[MIPS_DF_FTYPE_DF_DF]
10454 = build_function_type_list (double_type_node,
10455 double_type_node, double_type_node, NULL_TREE);
10456 }
10457
10458 if (TARGET_DSP)
10459 {
10460 V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
10461 V4QI_type_node = build_vector_type_for_mode (intQI_type_node, V4QImode);
10462
10463 types[MIPS_V2HI_FTYPE_V2HI_V2HI]
10464 = build_function_type_list (V2HI_type_node,
10465 V2HI_type_node, V2HI_type_node,
10466 NULL_TREE);
10467
10468 types[MIPS_SI_FTYPE_SI_SI]
10469 = build_function_type_list (intSI_type_node,
10470 intSI_type_node, intSI_type_node,
10471 NULL_TREE);
10472
10473 types[MIPS_V4QI_FTYPE_V4QI_V4QI]
10474 = build_function_type_list (V4QI_type_node,
10475 V4QI_type_node, V4QI_type_node,
10476 NULL_TREE);
10477
10478 types[MIPS_SI_FTYPE_V4QI]
10479 = build_function_type_list (intSI_type_node,
10480 V4QI_type_node,
10481 NULL_TREE);
10482
10483 types[MIPS_V2HI_FTYPE_V2HI]
10484 = build_function_type_list (V2HI_type_node,
10485 V2HI_type_node,
10486 NULL_TREE);
10487
10488 types[MIPS_SI_FTYPE_SI]
10489 = build_function_type_list (intSI_type_node,
10490 intSI_type_node,
10491 NULL_TREE);
10492
10493 types[MIPS_V4QI_FTYPE_V2HI_V2HI]
10494 = build_function_type_list (V4QI_type_node,
10495 V2HI_type_node, V2HI_type_node,
10496 NULL_TREE);
10497
10498 types[MIPS_V2HI_FTYPE_SI_SI]
10499 = build_function_type_list (V2HI_type_node,
10500 intSI_type_node, intSI_type_node,
10501 NULL_TREE);
10502
10503 types[MIPS_SI_FTYPE_V2HI]
10504 = build_function_type_list (intSI_type_node,
10505 V2HI_type_node,
10506 NULL_TREE);
10507
10508 types[MIPS_V2HI_FTYPE_V4QI]
10509 = build_function_type_list (V2HI_type_node,
10510 V4QI_type_node,
10511 NULL_TREE);
10512
10513 types[MIPS_V4QI_FTYPE_V4QI_SI]
10514 = build_function_type_list (V4QI_type_node,
10515 V4QI_type_node, intSI_type_node,
10516 NULL_TREE);
10517
10518 types[MIPS_V2HI_FTYPE_V2HI_SI]
10519 = build_function_type_list (V2HI_type_node,
10520 V2HI_type_node, intSI_type_node,
10521 NULL_TREE);
10522
10523 types[MIPS_V2HI_FTYPE_V4QI_V2HI]
10524 = build_function_type_list (V2HI_type_node,
10525 V4QI_type_node, V2HI_type_node,
10526 NULL_TREE);
10527
10528 types[MIPS_SI_FTYPE_V2HI_V2HI]
10529 = build_function_type_list (intSI_type_node,
10530 V2HI_type_node, V2HI_type_node,
10531 NULL_TREE);
10532
10533 types[MIPS_DI_FTYPE_DI_V4QI_V4QI]
10534 = build_function_type_list (intDI_type_node,
10535 intDI_type_node, V4QI_type_node, V4QI_type_node,
10536 NULL_TREE);
10537
10538 types[MIPS_DI_FTYPE_DI_V2HI_V2HI]
10539 = build_function_type_list (intDI_type_node,
10540 intDI_type_node, V2HI_type_node, V2HI_type_node,
10541 NULL_TREE);
10542
10543 types[MIPS_DI_FTYPE_DI_SI_SI]
10544 = build_function_type_list (intDI_type_node,
10545 intDI_type_node, intSI_type_node, intSI_type_node,
10546 NULL_TREE);
10547
10548 types[MIPS_V4QI_FTYPE_SI]
10549 = build_function_type_list (V4QI_type_node,
10550 intSI_type_node,
10551 NULL_TREE);
10552
10553 types[MIPS_V2HI_FTYPE_SI]
10554 = build_function_type_list (V2HI_type_node,
10555 intSI_type_node,
10556 NULL_TREE);
10557
10558 types[MIPS_VOID_FTYPE_V4QI_V4QI]
10559 = build_function_type_list (void_type_node,
10560 V4QI_type_node, V4QI_type_node,
10561 NULL_TREE);
10562
10563 types[MIPS_SI_FTYPE_V4QI_V4QI]
10564 = build_function_type_list (intSI_type_node,
10565 V4QI_type_node, V4QI_type_node,
10566 NULL_TREE);
10567
10568 types[MIPS_VOID_FTYPE_V2HI_V2HI]
10569 = build_function_type_list (void_type_node,
10570 V2HI_type_node, V2HI_type_node,
10571 NULL_TREE);
10572
10573 types[MIPS_SI_FTYPE_DI_SI]
10574 = build_function_type_list (intSI_type_node,
10575 intDI_type_node, intSI_type_node,
10576 NULL_TREE);
10577
10578 types[MIPS_DI_FTYPE_DI_SI]
10579 = build_function_type_list (intDI_type_node,
10580 intDI_type_node, intSI_type_node,
10581 NULL_TREE);
10582
10583 types[MIPS_VOID_FTYPE_SI_SI]
10584 = build_function_type_list (void_type_node,
10585 intSI_type_node, intSI_type_node,
10586 NULL_TREE);
10587
10588 types[MIPS_SI_FTYPE_PTR_SI]
10589 = build_function_type_list (intSI_type_node,
10590 ptr_type_node, intSI_type_node,
10591 NULL_TREE);
10592
10593 types[MIPS_SI_FTYPE_VOID]
10594 = build_function_type (intSI_type_node, void_list_node);
10595 }
10596
10597
10598
10599
10600 offset = 0;
10601 for (m = bdesc_arrays; m < &bdesc_arrays[ARRAY_SIZE (bdesc_arrays)]; m++)
10602 {
10603 if (m->proc == PROCESSOR_MAX || (m->proc == mips_arch))
10604 for (d = m->bdesc; d < &m->bdesc[m->size]; d++)
10605 if ((d->target_flags & target_flags) == d->target_flags)
10606 lang_hooks.builtin_function (d->name, types[d->function_type],
10607 d - m->bdesc + offset,
10608 BUILT_IN_MD, NULL, NULL);
10609 offset += m->size;
10610 }
10611 }
10612
10613
10614
10615
10616
10617
10618 static rtx
10619 mips_expand_builtin_direct (enum insn_code icode, rtx target, tree arglist,
10620 bool has_target)
10621 {
10622 rtx ops[MAX_RECOG_OPERANDS];
10623 int i = 0;
10624
10625 if (has_target)
10626 {
10627
10628 ops[0] = mips_prepare_builtin_target (icode, 0, target);
10629 i = 1;
10630 }
10631
10632
10633
10634 for (; i < insn_data[icode].n_operands && arglist != 0; i++)
10635 ops[i] = mips_prepare_builtin_arg (icode, i, &arglist);
10636
10637 switch (i)
10638 {
10639 case 2:
10640 emit_insn (GEN_FCN (icode) (ops[0], ops[1]));
10641 break;
10642
10643 case 3:
10644 emit_insn (GEN_FCN (icode) (ops[0], ops[1], ops[2]));
10645 break;
10646
10647 case 4:
10648 emit_insn (GEN_FCN (icode) (ops[0], ops[1], ops[2], ops[3]));
10649 break;
10650
10651 default:
10652 gcc_unreachable ();
10653 }
10654 return target;
10655 }
10656
10657
10658
10659
10660
10661
10662
10663 static rtx
10664 mips_expand_builtin_movtf (enum mips_builtin_type type,
10665 enum insn_code icode, enum mips_fp_condition cond,
10666 rtx target, tree arglist)
10667 {
10668 rtx cmp_result, op0, op1;
10669
10670 cmp_result = mips_prepare_builtin_target (icode, 0, 0);
10671 op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
10672 op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
10673 emit_insn (GEN_FCN (icode) (cmp_result, op0, op1, GEN_INT (cond)));
10674
10675 icode = CODE_FOR_mips_cond_move_tf_ps;
10676 target = mips_prepare_builtin_target (icode, 0, target);
10677 if (type == MIPS_BUILTIN_MOVT)
10678 {
10679 op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
10680 op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
10681 }
10682 else
10683 {
10684 op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
10685 op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
10686 }
10687 emit_insn (gen_mips_cond_move_tf_ps (target, op0, op1, cmp_result));
10688 return target;
10689 }
10690
10691
10692
10693
10694 static rtx
10695 mips_builtin_branch_and_move (rtx condition, rtx target,
10696 rtx value_if_true, rtx value_if_false)
10697 {
10698 rtx true_label, done_label;
10699
10700 true_label = gen_label_rtx ();
10701 done_label = gen_label_rtx ();
10702
10703
10704 emit_move_insn (target, value_if_false);
10705
10706
10707 emit_jump_insn (gen_condjump (condition, true_label));
10708 emit_jump_insn (gen_jump (done_label));
10709 emit_barrier ();
10710
10711
10712 emit_label (true_label);
10713 emit_move_insn (target, value_if_true);
10714
10715 emit_label (done_label);
10716 return target;
10717 }
10718
10719
10720
10721
10722
10723
10724 static rtx
10725 mips_expand_builtin_compare (enum mips_builtin_type builtin_type,
10726 enum insn_code icode, enum mips_fp_condition cond,
10727 rtx target, tree arglist)
10728 {
10729 rtx offset, condition, cmp_result, ops[MAX_RECOG_OPERANDS];
10730 int i;
10731
10732 if (target == 0 || GET_MODE (target) != SImode)
10733 target = gen_reg_rtx (SImode);
10734
10735
10736 cmp_result = mips_prepare_builtin_target (icode, 0, 0);
10737 for (i = 1; i < insn_data[icode].n_operands - 1; i++)
10738 ops[i] = mips_prepare_builtin_arg (icode, i, &arglist);
10739
10740 switch (insn_data[icode].n_operands)
10741 {
10742 case 4:
10743 emit_insn (GEN_FCN (icode) (cmp_result, ops[1], ops[2], GEN_INT (cond)));
10744 break;
10745
10746 case 6:
10747 emit_insn (GEN_FCN (icode) (cmp_result, ops[1], ops[2],
10748 ops[3], ops[4], GEN_INT (cond)));
10749 break;
10750
10751 default:
10752 gcc_unreachable ();
10753 }
10754
10755
10756
10757
10758 switch (builtin_type)
10759 {
10760 case MIPS_BUILTIN_CMP_ALL:
10761 condition = gen_rtx_NE (VOIDmode, cmp_result, constm1_rtx);
10762 return mips_builtin_branch_and_move (condition, target,
10763 const0_rtx, const1_rtx);
10764
10765 case MIPS_BUILTIN_CMP_UPPER:
10766 case MIPS_BUILTIN_CMP_LOWER:
10767 offset = GEN_INT (builtin_type == MIPS_BUILTIN_CMP_UPPER);
10768 condition = gen_single_cc (cmp_result, offset);
10769 return mips_builtin_branch_and_move (condition, target,
10770 const1_rtx, const0_rtx);
10771
10772 default:
10773 condition = gen_rtx_NE (VOIDmode, cmp_result, const0_rtx);
10774 return mips_builtin_branch_and_move (condition, target,
10775 const1_rtx, const0_rtx);
10776 }
10777 }
10778
10779
10780
10781
10782 static rtx
10783 mips_expand_builtin_bposge (enum mips_builtin_type builtin_type, rtx target)
10784 {
10785 rtx condition, cmp_result;
10786 int cmp_value;
10787
10788 if (target == 0 || GET_MODE (target) != SImode)
10789 target = gen_reg_rtx (SImode);
10790
10791 cmp_result = gen_rtx_REG (CCDSPmode, CCDSP_PO_REGNUM);
10792
10793 if (builtin_type == MIPS_BUILTIN_BPOSGE32)
10794 cmp_value = 32;
10795 else
10796 gcc_assert (0);
10797
10798 condition = gen_rtx_GE (VOIDmode, cmp_result, GEN_INT (cmp_value));
10799 return mips_builtin_branch_and_move (condition, target,
10800 const1_rtx, const0_rtx);
10801 }
10802
10803
10804
10805
10806 static void
10807 mips_encode_section_info (tree decl, rtx rtl, int first)
10808 {
10809 default_encode_section_info (decl, rtl, first);
10810
10811 if (TREE_CODE (decl) == FUNCTION_DECL
10812 && lookup_attribute ("long_call", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
10813 {
10814 rtx symbol = XEXP (rtl, 0);
10815 SYMBOL_REF_FLAGS (symbol) |= SYMBOL_FLAG_LONG_CALL;
10816 }
10817 }
10818
10819
10820
10821
10822 static void
10823 mips_extra_live_on_entry (bitmap regs)
10824 {
10825 if (TARGET_ABICALLS && !TARGET_ABSOLUTE_ABICALLS)
10826 bitmap_set_bit (regs, PIC_FUNCTION_ADDR_REGNUM);
10827 }
10828
10829
10830
10831 int
10832 mips_mode_rep_extended (enum machine_mode mode, enum machine_mode mode_rep)
10833 {
10834 if (TARGET_64BIT && mode == SImode && mode_rep == DImode)
10835 return SIGN_EXTEND;
10836
10837 return UNKNOWN;
10838 }
10839
10840 #include "gt-mips.h"