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