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