00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include "system.h"
00026 #include "insn-config.h"
00027 #include "rtl.h"
00028 #include "tree.h"
00029 #include "flags.h"
00030 #include "expr.h"
00031 #include "optabs.h"
00032 #include "function.h"
00033 #include "regs.h"
00034 #include "hard-reg-set.h"
00035 #include "output.h"
00036 #include "insn-attr.h"
00037 #include "toplev.h"
00038 #include "recog.h"
00039 #include "c-pragma.h"
00040 #include "integrate.h"
00041 #include "tm_p.h"
00042 #include "target.h"
00043 #include "target-def.h"
00044
00045 int code_for_indirect_jump_scratch = CODE_FOR_indirect_jump_scratch;
00046
00047 #define MSW (TARGET_LITTLE_ENDIAN ? 1 : 0)
00048 #define LSW (TARGET_LITTLE_ENDIAN ? 0 : 1)
00049
00050
00051 #define CONST_OK_FOR_ADD(size) \
00052 (TARGET_SHMEDIA ? CONST_OK_FOR_P (size) : CONST_OK_FOR_I (size))
00053 #define GEN_MOV (*(TARGET_SHMEDIA64 ? gen_movdi : gen_movsi))
00054 #define GEN_ADD3 (*(TARGET_SHMEDIA64 ? gen_adddi3 : gen_addsi3))
00055 #define GEN_SUB3 (*(TARGET_SHMEDIA64 ? gen_subdi3 : gen_subsi3))
00056
00057
00058 int current_function_interrupt;
00059
00060
00061
00062
00063 int pragma_interrupt;
00064
00065
00066
00067
00068 int trap_exit;
00069
00070
00071
00072
00073 rtx sp_switch;
00074
00075
00076
00077 static int pragma_trapa;
00078
00079
00080
00081
00082
00083
00084 int pragma_nosave_low_regs;
00085
00086
00087
00088 int current_function_anonymous_args;
00089
00090
00091
00092
00093 enum processor_type sh_cpu;
00094
00095
00096
00097
00098 rtx sh_compare_op0;
00099 rtx sh_compare_op1;
00100
00101
00102
00103
00104 int regno_reg_class[FIRST_PSEUDO_REGISTER] =
00105 {
00106 R0_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00107 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00108 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00109 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00110 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00111 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00112 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00113 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00114 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00115 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00116 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00117 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00118 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00119 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00120 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00121 GENERAL_REGS, GENERAL_REGS, GENERAL_REGS, GENERAL_REGS,
00122 FP0_REGS,FP_REGS, FP_REGS, FP_REGS,
00123 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00124 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00125 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00126 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00127 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00128 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00129 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00130 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00131 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00132 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00133 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00134 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00135 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00136 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00137 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00138 TARGET_REGS, TARGET_REGS, TARGET_REGS, TARGET_REGS,
00139 TARGET_REGS, TARGET_REGS, TARGET_REGS, TARGET_REGS,
00140 DF_REGS, DF_REGS, DF_REGS, DF_REGS,
00141 DF_REGS, DF_REGS, DF_REGS, DF_REGS,
00142 NO_REGS, GENERAL_REGS, PR_REGS, T_REGS,
00143 MAC_REGS, MAC_REGS, FPUL_REGS, FPSCR_REGS,
00144 GENERAL_REGS,
00145 };
00146
00147 char sh_register_names[FIRST_PSEUDO_REGISTER] \
00148 [MAX_REGISTER_NAME_LENGTH + 1] = SH_REGISTER_NAMES_INITIALIZER;
00149
00150 char sh_additional_register_names[ADDREGNAMES_SIZE] \
00151 [MAX_ADDITIONAL_REGISTER_NAME_LENGTH + 1]
00152 = SH_ADDITIONAL_REGISTER_NAMES_INITIALIZER;
00153
00154
00155
00156
00157 const enum reg_class reg_class_from_letter[] =
00158 {
00159 ALL_REGS, TARGET_REGS, FPSCR_REGS, DF_REGS,
00160 NO_REGS, FP_REGS, NO_REGS, NO_REGS,
00161 NO_REGS, NO_REGS, SIBCALL_REGS, PR_REGS,
00162 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00163 NO_REGS, NO_REGS, NO_REGS, T_REGS,
00164 NO_REGS, NO_REGS, FP0_REGS, MAC_REGS,
00165 FPUL_REGS, R0_REGS
00166 };
00167
00168 int assembler_dialect;
00169
00170 static void split_branches PARAMS ((rtx));
00171 static int branch_dest PARAMS ((rtx));
00172 static void force_into PARAMS ((rtx, rtx));
00173 static void print_slot PARAMS ((rtx));
00174 static rtx add_constant PARAMS ((rtx, enum machine_mode, rtx));
00175 static void dump_table PARAMS ((rtx));
00176 static int hi_const PARAMS ((rtx));
00177 static int broken_move PARAMS ((rtx));
00178 static int mova_p PARAMS ((rtx));
00179 static rtx find_barrier PARAMS ((int, rtx, rtx));
00180 static int noncall_uses_reg PARAMS ((rtx, rtx, rtx *));
00181 static rtx gen_block_redirect PARAMS ((rtx, int, int));
00182 static void output_stack_adjust PARAMS ((int, rtx, int));
00183 static void push PARAMS ((int));
00184 static void pop PARAMS ((int));
00185 static void push_regs PARAMS ((HOST_WIDE_INT *));
00186 static void calc_live_regs PARAMS ((int *, HOST_WIDE_INT *));
00187 static void mark_use PARAMS ((rtx, rtx *));
00188 static HOST_WIDE_INT rounded_frame_size PARAMS ((int));
00189 static rtx mark_constant_pool_use PARAMS ((rtx));
00190 const struct attribute_spec sh_attribute_table[];
00191 static tree sh_handle_interrupt_handler_attribute PARAMS ((tree *, tree, tree, int, bool *));
00192 static tree sh_handle_sp_switch_attribute PARAMS ((tree *, tree, tree, int, bool *));
00193 static tree sh_handle_trap_exit_attribute PARAMS ((tree *, tree, tree, int, bool *));
00194 static void sh_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
00195 static void sh_insert_attributes PARAMS ((tree, tree *));
00196 #ifndef OBJECT_FORMAT_ELF
00197 static void sh_asm_named_section PARAMS ((const char *, unsigned int));
00198 #endif
00199 static int sh_adjust_cost PARAMS ((rtx, rtx, rtx, int));
00200 static bool sh_cannot_modify_jumps_p PARAMS ((void));
00201
00202 static bool sh_ms_bitfield_layout_p PARAMS ((tree));
00203
00204
00205 #undef TARGET_ATTRIBUTE_TABLE
00206 #define TARGET_ATTRIBUTE_TABLE sh_attribute_table
00207
00208
00209 #undef TARGET_ASM_UNALIGNED_HI_OP
00210 #define TARGET_ASM_UNALIGNED_HI_OP "\t.uaword\t"
00211 #undef TARGET_ASM_UNALIGNED_SI_OP
00212 #define TARGET_ASM_UNALIGNED_SI_OP "\t.ualong\t"
00213
00214
00215 #undef TARGET_ASM_UNALIGNED_DI_OP
00216 #define TARGET_ASM_UNALIGNED_DI_OP "\t.uaquad\t"
00217 #undef TARGET_ASM_ALIGNED_DI_OP
00218 #define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"
00219
00220 #undef TARGET_ASM_FUNCTION_EPILOGUE
00221 #define TARGET_ASM_FUNCTION_EPILOGUE sh_output_function_epilogue
00222
00223 #undef TARGET_INSERT_ATTRIBUTES
00224 #define TARGET_INSERT_ATTRIBUTES sh_insert_attributes
00225
00226 #undef TARGET_SCHED_ADJUST_COST
00227 #define TARGET_SCHED_ADJUST_COST sh_adjust_cost
00228
00229 #undef TARGET_CANNOT_MODIFY_JUMPS_P
00230 #define TARGET_CANNOT_MODIFY_JUMPS_P sh_cannot_modify_jumps_p
00231
00232 #undef TARGET_MS_BITFIELD_LAYOUT_P
00233 #define TARGET_MS_BITFIELD_LAYOUT_P sh_ms_bitfield_layout_p
00234
00235 struct gcc_target targetm = TARGET_INITIALIZER;
00236
00237
00238
00239 void
00240 print_operand_address (stream, x)
00241 FILE *stream;
00242 rtx x;
00243 {
00244 switch (GET_CODE (x))
00245 {
00246 case REG:
00247 case SUBREG:
00248 fprintf (stream, "@%s", reg_names[true_regnum (x)]);
00249 break;
00250
00251 case PLUS:
00252 {
00253 rtx base = XEXP (x, 0);
00254 rtx index = XEXP (x, 1);
00255
00256 switch (GET_CODE (index))
00257 {
00258 case CONST_INT:
00259 fprintf (stream, "@(%d,%s)", (int) INTVAL (index),
00260 reg_names[true_regnum (base)]);
00261 break;
00262
00263 case REG:
00264 case SUBREG:
00265 {
00266 int base_num = true_regnum (base);
00267 int index_num = true_regnum (index);
00268
00269 fprintf (stream, "@(r0,%s)",
00270 reg_names[MAX (base_num, index_num)]);
00271 break;
00272 }
00273
00274 default:
00275 debug_rtx (x);
00276 abort ();
00277 }
00278 }
00279 break;
00280
00281 case PRE_DEC:
00282 fprintf (stream, "@-%s", reg_names[true_regnum (XEXP (x, 0))]);
00283 break;
00284
00285 case POST_INC:
00286 fprintf (stream, "@%s+", reg_names[true_regnum (XEXP (x, 0))]);
00287 break;
00288
00289 default:
00290 x = mark_constant_pool_use (x);
00291 output_addr_const (stream, x);
00292 break;
00293 }
00294 }
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312 void
00313 print_operand (stream, x, code)
00314 FILE *stream;
00315 rtx x;
00316 int code;
00317 {
00318 switch (code)
00319 {
00320 case '.':
00321 if (final_sequence
00322 && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
00323 fprintf (stream, ASSEMBLER_DIALECT ? "/s" : ".s");
00324 break;
00325 case ',':
00326 fprintf (stream, "%s", LOCAL_LABEL_PREFIX);
00327 break;
00328 case '@':
00329 {
00330 int interrupt_handler;
00331
00332 if ((lookup_attribute
00333 ("interrupt_handler",
00334 DECL_ATTRIBUTES (current_function_decl)))
00335 != NULL_TREE)
00336 interrupt_handler = 1;
00337 else
00338 interrupt_handler = 0;
00339
00340 if (trap_exit)
00341 fprintf (stream, "trapa #%d", trap_exit);
00342 else if (interrupt_handler)
00343 fprintf (stream, "rte");
00344 else
00345 fprintf (stream, "rts");
00346 break;
00347 }
00348 case '#':
00349
00350 if (dbr_sequence_length () == 0)
00351 fprintf (stream, "\n\tnop");
00352 break;
00353 case 'O':
00354 x = mark_constant_pool_use (x);
00355 output_addr_const (stream, x);
00356 break;
00357 case 'R':
00358 fputs (reg_names[REGNO (x) + LSW], (stream));
00359 break;
00360 case 'S':
00361 fputs (reg_names[REGNO (x) + MSW], (stream));
00362 break;
00363 case 'T':
00364
00365 switch (GET_CODE (x))
00366 {
00367 case REG:
00368 fputs (reg_names[REGNO (x) + 1], (stream));
00369 break;
00370 case MEM:
00371 if (GET_CODE (XEXP (x, 0)) != PRE_DEC
00372 && GET_CODE (XEXP (x, 0)) != POST_INC)
00373 x = adjust_address (x, SImode, 4);
00374 print_operand_address (stream, XEXP (x, 0));
00375 break;
00376 default:
00377 break;
00378 }
00379 break;
00380 case 'o':
00381 switch (GET_CODE (x))
00382 {
00383 case PLUS: fputs ("add", stream); break;
00384 case MINUS: fputs ("sub", stream); break;
00385 case MULT: fputs ("mul", stream); break;
00386 case DIV: fputs ("div", stream); break;
00387 default:
00388 break;
00389 }
00390 break;
00391 case 'M':
00392 if (GET_CODE (x) == MEM
00393 && GET_CODE (XEXP (x, 0)) == PLUS
00394 && (GET_CODE (XEXP (XEXP (x, 0), 1)) == REG
00395 || GET_CODE (XEXP (XEXP (x, 0), 1)) == SUBREG))
00396 fputc ('x', stream);
00397 break;
00398
00399 case 'm':
00400 if (GET_CODE (x) != MEM)
00401 abort ();
00402 x = XEXP (x, 0);
00403 switch (GET_CODE (x))
00404 {
00405 case REG:
00406 case SUBREG:
00407 print_operand (stream, x, 0);
00408 fputs (", 0", stream);
00409 break;
00410
00411 case PLUS:
00412 print_operand (stream, XEXP (x, 0), 0);
00413 fputs (", ", stream);
00414 print_operand (stream, XEXP (x, 1), 0);
00415 break;
00416
00417 default:
00418 abort ();
00419 }
00420 break;
00421
00422 case 'u':
00423 if (GET_CODE (x) == CONST_INT)
00424 {
00425 fprintf ((stream), "%u", (unsigned) INTVAL (x) & (0x10000 - 1));
00426 break;
00427 }
00428
00429
00430 default:
00431 switch (GET_CODE (x))
00432 {
00433
00434
00435
00436
00437
00438 case SUBREG:
00439 if (SUBREG_BYTE (x) != 0
00440 || GET_CODE (SUBREG_REG (x)) != REG)
00441 abort ();
00442
00443 x = SUBREG_REG (x);
00444
00445
00446 case REG:
00447 if (FP_REGISTER_P (REGNO (x))
00448 && GET_MODE (x) == V16SFmode)
00449 fprintf ((stream), "mtrx%s", reg_names[REGNO (x)] + 2);
00450 else if (FP_REGISTER_P (REGNO (x))
00451 && GET_MODE (x) == V4SFmode)
00452 fprintf ((stream), "fv%s", reg_names[REGNO (x)] + 2);
00453 else if (GET_CODE (x) == REG
00454 && GET_MODE (x) == V2SFmode)
00455 fprintf ((stream), "fp%s", reg_names[REGNO (x)] + 2);
00456 else if (FP_REGISTER_P (REGNO (x))
00457 && GET_MODE_SIZE (GET_MODE (x)) > 4)
00458 fprintf ((stream), "d%s", reg_names[REGNO (x)] + 1);
00459 else
00460 fputs (reg_names[REGNO (x)], (stream));
00461 break;
00462
00463 case MEM:
00464 output_address (XEXP (x, 0));
00465 break;
00466
00467 case CONST:
00468 if (TARGET_SHMEDIA
00469 && GET_CODE (XEXP (x, 0)) == SIGN_EXTEND
00470 && GET_MODE (XEXP (x, 0)) == DImode
00471 && GET_CODE (XEXP (XEXP (x, 0), 0)) == TRUNCATE
00472 && GET_MODE (XEXP (XEXP (x, 0), 0)) == HImode)
00473 {
00474 rtx val = XEXP (XEXP (XEXP (x, 0), 0), 0);
00475
00476 fputc ('(', stream);
00477 if (GET_CODE (val) == ASHIFTRT)
00478 {
00479 fputc ('(', stream);
00480 if (GET_CODE (XEXP (val, 0)) == CONST)
00481 fputc ('(', stream);
00482 output_addr_const (stream, XEXP (val, 0));
00483 if (GET_CODE (XEXP (val, 0)) == CONST)
00484 fputc (')', stream);
00485 fputs (" >> ", stream);
00486 output_addr_const (stream, XEXP (val, 1));
00487 fputc (')', stream);
00488 }
00489 else
00490 {
00491 if (GET_CODE (val) == CONST)
00492 fputc ('(', stream);
00493 output_addr_const (stream, val);
00494 if (GET_CODE (val) == CONST)
00495 fputc (')', stream);
00496 }
00497 fputs (" & 65535)", stream);
00498 break;
00499 }
00500
00501
00502 default:
00503 if (TARGET_SH1)
00504 fputc ('#', stream);
00505 output_addr_const (stream, x);
00506 break;
00507 }
00508 break;
00509 }
00510 }
00511
00512
00513 static void
00514 force_into (value, target)
00515 rtx value, target;
00516 {
00517 value = force_operand (value, target);
00518 if (! rtx_equal_p (value, target))
00519 emit_insn (gen_move_insn (target, value));
00520 }
00521
00522
00523
00524
00525
00526
00527
00528
00529 int
00530 expand_block_move (operands)
00531 rtx *operands;
00532 {
00533 int align = INTVAL (operands[3]);
00534 int constp = (GET_CODE (operands[2]) == CONST_INT);
00535 int bytes = (constp ? INTVAL (operands[2]) : 0);
00536
00537
00538
00539 if (! constp || align < 4 || (bytes % 4 != 0))
00540 return 0;
00541
00542 if (TARGET_HARD_SH4)
00543 {
00544 if (bytes < 12)
00545 return 0;
00546 else if (bytes == 12)
00547 {
00548 tree entry_name;
00549 rtx sym;
00550 rtx func_addr_rtx;
00551 rtx r4 = gen_rtx (REG, SImode, 4);
00552 rtx r5 = gen_rtx (REG, SImode, 5);
00553
00554 entry_name = get_identifier ("__movstrSI12_i4");
00555
00556 sym = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name));
00557 func_addr_rtx = copy_to_mode_reg (Pmode, sym);
00558 force_into (XEXP (operands[0], 0), r4);
00559 force_into (XEXP (operands[1], 0), r5);
00560 emit_insn (gen_block_move_real_i4 (func_addr_rtx));
00561 return 1;
00562 }
00563 else if (! TARGET_SMALLCODE)
00564 {
00565 tree entry_name;
00566 rtx sym;
00567 rtx func_addr_rtx;
00568 int dwords;
00569 rtx r4 = gen_rtx (REG, SImode, 4);
00570 rtx r5 = gen_rtx (REG, SImode, 5);
00571 rtx r6 = gen_rtx (REG, SImode, 6);
00572
00573 entry_name = get_identifier (bytes & 4
00574 ? "__movstr_i4_odd"
00575 : "__movstr_i4_even");
00576 sym = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name));
00577 func_addr_rtx = copy_to_mode_reg (Pmode, sym);
00578 force_into (XEXP (operands[0], 0), r4);
00579 force_into (XEXP (operands[1], 0), r5);
00580
00581 dwords = bytes >> 3;
00582 emit_insn (gen_move_insn (r6, GEN_INT (dwords - 1)));
00583 emit_insn (gen_block_lump_real_i4 (func_addr_rtx));
00584 return 1;
00585 }
00586 else
00587 return 0;
00588 }
00589 if (bytes < 64)
00590 {
00591 char entry[30];
00592 tree entry_name;
00593 rtx sym;
00594 rtx func_addr_rtx;
00595 rtx r4 = gen_rtx_REG (SImode, 4);
00596 rtx r5 = gen_rtx_REG (SImode, 5);
00597
00598 sprintf (entry, "__movstrSI%d", bytes);
00599 entry_name = get_identifier (entry);
00600 sym = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name));
00601 func_addr_rtx = copy_to_mode_reg (Pmode, sym);
00602 force_into (XEXP (operands[0], 0), r4);
00603 force_into (XEXP (operands[1], 0), r5);
00604 emit_insn (gen_block_move_real (func_addr_rtx));
00605 return 1;
00606 }
00607
00608
00609
00610 if (! TARGET_SMALLCODE)
00611 {
00612 tree entry_name;
00613 rtx sym;
00614 rtx func_addr_rtx;
00615 int final_switch, while_loop;
00616 rtx r4 = gen_rtx_REG (SImode, 4);
00617 rtx r5 = gen_rtx_REG (SImode, 5);
00618 rtx r6 = gen_rtx_REG (SImode, 6);
00619
00620 entry_name = get_identifier ("__movstr");
00621 sym = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (entry_name));
00622 func_addr_rtx = copy_to_mode_reg (Pmode, sym);
00623 force_into (XEXP (operands[0], 0), r4);
00624 force_into (XEXP (operands[1], 0), r5);
00625
00626
00627
00628
00629
00630
00631
00632 final_switch = 16 - ((bytes / 4) % 16);
00633 while_loop = ((bytes / 4) / 16 - 1) * 16;
00634 emit_insn (gen_move_insn (r6, GEN_INT (while_loop + final_switch)));
00635 emit_insn (gen_block_lump_real (func_addr_rtx));
00636 return 1;
00637 }
00638
00639 return 0;
00640 }
00641
00642
00643
00644
00645 int
00646 prepare_move_operands (operands, mode)
00647 rtx operands[];
00648 enum machine_mode mode;
00649 {
00650 if ((mode == SImode || mode == DImode) && flag_pic)
00651 {
00652 rtx temp;
00653 if (SYMBOLIC_CONST_P (operands[1]))
00654 {
00655 if (GET_CODE (operands[0]) == MEM)
00656 operands[1] = force_reg (Pmode, operands[1]);
00657 else if (GET_CODE (operands[1]) == LABEL_REF
00658 && target_reg_operand (operands[0], mode))
00659 ;
00660 else
00661 {
00662 temp = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
00663 operands[1] = legitimize_pic_address (operands[1], mode, temp);
00664 }
00665 }
00666 else if (GET_CODE (operands[1]) == CONST
00667 && GET_CODE (XEXP (operands[1], 0)) == PLUS
00668 && SYMBOLIC_CONST_P (XEXP (XEXP (operands[1], 0), 0)))
00669 {
00670 temp = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
00671 temp = legitimize_pic_address (XEXP (XEXP (operands[1], 0), 0),
00672 mode, temp);
00673 operands[1] = expand_binop (mode, add_optab, temp,
00674 XEXP (XEXP (operands[1], 0), 1),
00675 no_new_pseudos ? temp
00676 : gen_reg_rtx (Pmode),
00677 0, OPTAB_LIB_WIDEN);
00678 }
00679 }
00680
00681 if (! reload_in_progress && ! reload_completed)
00682 {
00683
00684 if (! register_operand (operands[0], mode)
00685 && ! register_operand (operands[1], mode))
00686 operands[1] = copy_to_mode_reg (mode, operands[1]);
00687
00688
00689
00690
00691
00692 else if (GET_CODE (operands[1]) == REG && REGNO (operands[1]) == 0
00693 && GET_CODE (operands[0]) == MEM
00694 && GET_CODE (XEXP (operands[0], 0)) == PLUS
00695 && GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == REG)
00696 operands[1] = copy_to_mode_reg (mode, operands[1]);
00697 }
00698
00699 return 0;
00700 }
00701
00702
00703
00704 rtx
00705 prepare_scc_operands (code)
00706 enum rtx_code code;
00707 {
00708 rtx t_reg = gen_rtx_REG (SImode, T_REG);
00709 enum rtx_code oldcode = code;
00710 enum machine_mode mode;
00711
00712
00713 switch (code)
00714 {
00715 case NE:
00716
00717 abort ();
00718 case LT:
00719 code = GT;
00720 break;
00721 case LE:
00722 code = GE;
00723 break;
00724 case LTU:
00725 code = GTU;
00726 break;
00727 case LEU:
00728 code = GEU;
00729 break;
00730 default:
00731 break;
00732 }
00733 if (code != oldcode)
00734 {
00735 rtx tmp = sh_compare_op0;
00736 sh_compare_op0 = sh_compare_op1;
00737 sh_compare_op1 = tmp;
00738 }
00739
00740 mode = GET_MODE (sh_compare_op0);
00741 if (mode == VOIDmode)
00742 mode = GET_MODE (sh_compare_op1);
00743
00744 sh_compare_op0 = force_reg (mode, sh_compare_op0);
00745 if ((code != EQ && code != NE
00746 && (sh_compare_op1 != const0_rtx
00747 || code == GTU || code == GEU || code == LTU || code == LEU))
00748 || (mode == DImode && sh_compare_op1 != const0_rtx)
00749 || (TARGET_SH3E && GET_MODE_CLASS (mode) == MODE_FLOAT))
00750 sh_compare_op1 = force_reg (mode, sh_compare_op1);
00751
00752 if (TARGET_SH4 && GET_MODE_CLASS (mode) == MODE_FLOAT)
00753 (mode == SFmode ? emit_sf_insn : emit_df_insn)
00754 (gen_rtx (PARALLEL, VOIDmode, gen_rtvec (2,
00755 gen_rtx (SET, VOIDmode, t_reg,
00756 gen_rtx (code, SImode,
00757 sh_compare_op0, sh_compare_op1)),
00758 gen_rtx (USE, VOIDmode, get_fpscr_rtx ()))));
00759 else
00760 emit_insn (gen_rtx (SET, VOIDmode, t_reg,
00761 gen_rtx (code, SImode, sh_compare_op0,
00762 sh_compare_op1)));
00763
00764 return t_reg;
00765 }
00766
00767
00768
00769 void
00770 from_compare (operands, code)
00771 rtx *operands;
00772 int code;
00773 {
00774 enum machine_mode mode = GET_MODE (sh_compare_op0);
00775 rtx insn;
00776 if (mode == VOIDmode)
00777 mode = GET_MODE (sh_compare_op1);
00778 if (code != EQ
00779 || mode == DImode
00780 || (TARGET_SH3E && GET_MODE_CLASS (mode) == MODE_FLOAT))
00781 {
00782
00783 sh_compare_op0 = force_reg (mode, sh_compare_op0);
00784 if (sh_compare_op1 != const0_rtx
00785 || code == GTU || code == GEU
00786 || (TARGET_SH3E && GET_MODE_CLASS (mode) == MODE_FLOAT))
00787 sh_compare_op1 = force_reg (mode, sh_compare_op1);
00788 }
00789 if (TARGET_SH3E && GET_MODE_CLASS (mode) == MODE_FLOAT && code == GE)
00790 {
00791 from_compare (operands, GT);
00792 insn = gen_ieee_ccmpeqsf_t (sh_compare_op0, sh_compare_op1);
00793 }
00794 else
00795 insn = gen_rtx_SET (VOIDmode,
00796 gen_rtx_REG (SImode, T_REG),
00797 gen_rtx (code, SImode, sh_compare_op0,
00798 sh_compare_op1));
00799 if (TARGET_SH4 && GET_MODE_CLASS (mode) == MODE_FLOAT)
00800 {
00801 insn = gen_rtx (PARALLEL, VOIDmode,
00802 gen_rtvec (2, insn,
00803 gen_rtx (USE, VOIDmode, get_fpscr_rtx ())));
00804 (mode == SFmode ? emit_sf_insn : emit_df_insn) (insn);
00805 }
00806 else
00807 emit_insn (insn);
00808 }
00809
00810
00811
00812
00813
00814
00815
00816
00817 const char *
00818 output_movedouble (insn, operands, mode)
00819 rtx insn ATTRIBUTE_UNUSED;
00820 rtx operands[];
00821 enum machine_mode mode;
00822 {
00823 rtx dst = operands[0];
00824 rtx src = operands[1];
00825
00826 if (GET_CODE (dst) == MEM
00827 && GET_CODE (XEXP (dst, 0)) == PRE_DEC)
00828 return "mov.l %T1,%0\n\tmov.l %1,%0";
00829
00830 if (register_operand (dst, mode)
00831 && register_operand (src, mode))
00832 {
00833 if (REGNO (src) == MACH_REG)
00834 return "sts mach,%S0\n\tsts macl,%R0";
00835
00836
00837
00838
00839 if (REGNO (src) + 1 == REGNO (dst))
00840 return "mov %T1,%T0\n\tmov %1,%0";
00841 else
00842 return "mov %1,%0\n\tmov %T1,%T0";
00843 }
00844 else if (GET_CODE (src) == CONST_INT)
00845 {
00846 if (INTVAL (src) < 0)
00847 output_asm_insn ("mov #-1,%S0", operands);
00848 else
00849 output_asm_insn ("mov #0,%S0", operands);
00850
00851 return "mov %1,%R0";
00852 }
00853 else if (GET_CODE (src) == MEM)
00854 {
00855 int ptrreg = -1;
00856 int dreg = REGNO (dst);
00857 rtx inside = XEXP (src, 0);
00858
00859 if (GET_CODE (inside) == REG)
00860 ptrreg = REGNO (inside);
00861 else if (GET_CODE (inside) == SUBREG)
00862 ptrreg = subreg_regno (inside);
00863 else if (GET_CODE (inside) == PLUS)
00864 {
00865 ptrreg = REGNO (XEXP (inside, 0));
00866
00867
00868
00869
00870
00871
00872
00873 if (GET_CODE (XEXP (inside, 1)) == REG)
00874 abort ();
00875 }
00876 else if (GET_CODE (inside) == LABEL_REF)
00877 return "mov.l %1,%0\n\tmov.l %1+4,%T0";
00878 else if (GET_CODE (inside) == POST_INC)
00879 return "mov.l %1,%0\n\tmov.l %1,%T0";
00880 else
00881 abort ();
00882
00883
00884 if (dreg == ptrreg)
00885 return "mov.l %T1,%T0\n\tmov.l %1,%0";
00886 }
00887
00888 return "mov.l %1,%0\n\tmov.l %T1,%T0";
00889 }
00890
00891
00892
00893
00894
00895 static void
00896 print_slot (insn)
00897 rtx insn;
00898 {
00899 final_scan_insn (XVECEXP (insn, 0, 1), asm_out_file, optimize, 0, 1);
00900
00901 INSN_DELETED_P (XVECEXP (insn, 0, 1)) = 1;
00902 }
00903
00904 const char *
00905 output_far_jump (insn, op)
00906 rtx insn;
00907 rtx op;
00908 {
00909 struct { rtx lab, reg, op; } this;
00910 rtx braf_base_lab = NULL_RTX;
00911 const char *jump;
00912 int far;
00913 int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
00914
00915 this.lab = gen_label_rtx ();
00916
00917 if (TARGET_SH2
00918 && offset >= -32764
00919 && offset - get_attr_length (insn) <= 32766)
00920 {
00921 far = 0;
00922 jump = "mov.w %O0,%1; braf %1";
00923 }
00924 else
00925 {
00926 far = 1;
00927 if (flag_pic)
00928 {
00929 if (TARGET_SH2)
00930 jump = "mov.l %O0,%1; braf %1";
00931 else
00932 jump = "mov.l r0,@-r15; mova %O0,r0; mov.l @r0,%1; add r0,%1; mov.l @r15+,r0; jmp @%1";
00933 }
00934 else
00935 jump = "mov.l %O0,%1; jmp @%1";
00936 }
00937
00938 if (GET_CODE (PREV_INSN (insn)) == INSN
00939 && INSN_CODE (PREV_INSN (insn)) == CODE_FOR_indirect_jump_scratch)
00940 {
00941 this.reg = SET_DEST (PATTERN (PREV_INSN (insn)));
00942 if (REGNO (this.reg) == R0_REG && flag_pic && ! TARGET_SH2)
00943 jump = "mov.l r1,@-r15; mova %O0,r0; mov.l @r0,r1; add r1,r0; mov.l @r15+,r1; jmp @%1";
00944 output_asm_insn (jump, &this.lab);
00945 if (dbr_sequence_length ())
00946 print_slot (final_sequence);
00947 else
00948 output_asm_insn ("nop", 0);
00949 }
00950 else
00951 {
00952
00953 if (dbr_sequence_length ())
00954 print_slot (final_sequence);
00955
00956 this.reg = gen_rtx_REG (SImode, 13);
00957
00958
00959
00960
00961 if (TARGET_SH5)
00962 output_asm_insn ("lds r13, macl", 0);
00963 else
00964 output_asm_insn ("mov.l r13,@-r15", 0);
00965 output_asm_insn (jump, &this.lab);
00966 if (TARGET_SH5)
00967 output_asm_insn ("sts macl, r13", 0);
00968 else
00969 output_asm_insn ("mov.l @r15+,r13", 0);
00970 }
00971 if (far && flag_pic && TARGET_SH2)
00972 {
00973 braf_base_lab = gen_label_rtx ();
00974 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
00975 CODE_LABEL_NUMBER (braf_base_lab));
00976 }
00977 if (far)
00978 output_asm_insn (".align 2", 0);
00979 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L", CODE_LABEL_NUMBER (this.lab));
00980 this.op = op;
00981 if (far && flag_pic)
00982 {
00983 if (TARGET_SH2)
00984 this.lab = braf_base_lab;
00985 output_asm_insn (".long %O2-%O0", &this.lab);
00986 }
00987 else
00988 output_asm_insn (far ? ".long %O2" : ".word %O2-%O0", &this.lab);
00989 return "";
00990 }
00991
00992
00993
00994
00995 static int lf = 100;
00996
00997
00998
00999 const char *
01000 output_branch (logic, insn, operands)
01001 int logic;
01002 rtx insn;
01003 rtx *operands;
01004 {
01005 switch (get_attr_length (insn))
01006 {
01007 case 6:
01008
01009
01010
01011
01012
01013
01014
01015
01016 if (! TARGET_RELAX)
01017 {
01018 int label = lf++;
01019
01020 rtx op0 = operands[0];
01021
01022
01023
01024
01025
01026 if (final_sequence
01027 && ! INSN_ANNULLED_BRANCH_P (XVECEXP (final_sequence, 0, 0)))
01028 {
01029 asm_fprintf (asm_out_file, "\tb%s%ss\t%LLF%d\n", logic ? "f" : "t",
01030 ASSEMBLER_DIALECT ? "/" : ".", label);
01031 print_slot (final_sequence);
01032 }
01033 else
01034 asm_fprintf (asm_out_file, "\tb%s\t%LLF%d\n", logic ? "f" : "t", label);
01035
01036 output_asm_insn ("bra\t%l0", &op0);
01037 fprintf (asm_out_file, "\tnop\n");
01038 ASM_OUTPUT_INTERNAL_LABEL(asm_out_file, "LF", label);
01039
01040 return "";
01041 }
01042
01043
01044 case 2:
01045 return logic ? "bt%.\t%l0" : "bf%.\t%l0";
01046 default:
01047
01048
01049
01050 abort ();
01051 }
01052 }
01053
01054 const char *
01055 output_branchy_insn (code, template, insn, operands)
01056 enum rtx_code code;
01057 const char *template;
01058 rtx insn;
01059 rtx *operands;
01060 {
01061 rtx next_insn = NEXT_INSN (insn);
01062
01063 if (next_insn && GET_CODE (next_insn) == JUMP_INSN && condjump_p (next_insn))
01064 {
01065 rtx src = SET_SRC (PATTERN (next_insn));
01066 if (GET_CODE (src) == IF_THEN_ELSE && GET_CODE (XEXP (src, 0)) != code)
01067 {
01068
01069 operands[9] = gen_label_rtx ();
01070 emit_label_after (operands[9], next_insn);
01071 INSN_ADDRESSES_NEW (operands[9],
01072 INSN_ADDRESSES (INSN_UID (next_insn))
01073 + get_attr_length (next_insn));
01074 return template;
01075 }
01076 else
01077 {
01078 int offset = (branch_dest (next_insn)
01079 - INSN_ADDRESSES (INSN_UID (next_insn)) + 4);
01080 if (offset >= -252 && offset <= 258)
01081 {
01082 if (GET_CODE (src) == IF_THEN_ELSE)
01083
01084 src = XEXP (src, 1);
01085 operands[9] = src;
01086 return template;
01087 }
01088 }
01089 }
01090 operands[9] = gen_label_rtx ();
01091 emit_label_after (operands[9], insn);
01092 INSN_ADDRESSES_NEW (operands[9],
01093 INSN_ADDRESSES (INSN_UID (insn))
01094 + get_attr_length (insn));
01095 return template;
01096 }
01097
01098 const char *
01099 output_ieee_ccmpeq (insn, operands)
01100 rtx insn, *operands;
01101 {
01102 return output_branchy_insn (NE, "bt\t%l9\\;fcmp/eq\t%1,%0", insn, operands);
01103 }
01104
01105
01106
01107 void
01108 output_file_start (file)
01109 FILE *file;
01110 {
01111 output_file_directive (file, main_input_filename);
01112
01113
01114
01115 data_section ();
01116
01117 if (TARGET_LITTLE_ENDIAN)
01118 fprintf (file, "\t.little\n");
01119
01120 if (TARGET_SHCOMPACT)
01121 fprintf (file, "\t.mode\tSHcompact\n");
01122 else if (TARGET_SHMEDIA)
01123 fprintf (file, "\t.mode\tSHmedia\n\t.abi\t%i\n",
01124 TARGET_SHMEDIA64 ? 64 : 32);
01125 }
01126
01127
01128 static const char ashiftrt_insns[] =
01129 { 0,1,2,3,4,5,8,8,8,8,8,8,8,8,8,8,2,3,4,5,8,8,8,8,8,8,8,8,8,8,8,2};
01130
01131
01132 static const char shift_insns[] =
01133 { 0,1,1,2,2,3,3,4,1,2,2,3,3,4,3,3,1,2,2,3,3,4,3,3,2,3,3,4,4,4,3,3};
01134
01135
01136
01137
01138
01139 static short shift_amounts[32][5] = {
01140 {0}, {1}, {2}, {2, 1},
01141 {2, 2}, {2, 1, 2}, {2, 2, 2}, {2, 2, 1, 2},
01142 {8}, {8, 1}, {8, 2}, {8, 1, 2},
01143 {8, 2, 2}, {8, 2, 1, 2}, {8, -2, 8}, {8, -1, 8},
01144 {16}, {16, 1}, {16, 2}, {16, 1, 2},
01145 {16, 2, 2}, {16, 2, 1, 2}, {16, -2, 8}, {16, -1, 8},
01146 {16, 8}, {16, 1, 8}, {16, 8, 2}, {16, 8, 1, 2},
01147 {16, 8, 2, 2}, {16, -1, -2, 16}, {16, -2, 16}, {16, -1, 16}};
01148
01149
01150
01151
01152
01153 static const char ext_shift_insns[] =
01154 { 0,1,1,2,2,3,2,2,1,2,2,3,3,3,2,2,1,2,2,3,3,4,3,3,2,3,3,4,4,4,3,3};
01155
01156 static const short ext_shift_amounts[32][4] = {
01157 {0}, {1}, {2}, {2, 1},
01158 {2, 2}, {2, 1, 2}, {8, -2}, {8, -1},
01159 {8}, {8, 1}, {8, 2}, {8, 1, 2},
01160 {8, 2, 2}, {16, -2, -1}, {16, -2}, {16, -1},
01161 {16}, {16, 1}, {16, 2}, {16, 1, 2},
01162 {16, 2, 2}, {16, 2, 1, 2}, {16, -2, 8}, {16, -1, 8},
01163 {16, 8}, {16, 1, 8}, {16, 8, 2}, {16, 8, 1, 2},
01164 {16, 8, 2, 2}, {16, -1, -2, 16}, {16, -2, 16}, {16, -1, 16}};
01165
01166
01167
01168
01169 #define EXT_SHIFT_SIGNED(n) (((n) | 8) == 15)
01170
01171
01172
01173
01174 int
01175 shift_insns_rtx (insn)
01176 rtx insn;
01177 {
01178 rtx set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
01179 int shift_count = INTVAL (XEXP (set_src, 1));
01180 enum rtx_code shift_code = GET_CODE (set_src);
01181
01182 switch (shift_code)
01183 {
01184 case ASHIFTRT:
01185 return ashiftrt_insns[shift_count];
01186 case LSHIFTRT:
01187 case ASHIFT:
01188 return shift_insns[shift_count];
01189 default:
01190 abort();
01191 }
01192 }
01193
01194
01195
01196 int
01197 shiftcosts (x)
01198 rtx x;
01199 {
01200 int value;
01201
01202 if (TARGET_SHMEDIA)
01203 return 1;
01204
01205 if (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD)
01206 {
01207 if (GET_MODE (x) == DImode
01208 && GET_CODE (XEXP (x, 1)) == CONST_INT
01209 && INTVAL (XEXP (x, 1)) == 1)
01210 return 2;
01211
01212
01213 return 10000;
01214 }
01215
01216 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
01217 return SH_DYNAMIC_SHIFT_COST;
01218
01219 value = INTVAL (XEXP (x, 1));
01220
01221
01222 if (GET_CODE (x) == ASHIFTRT)
01223 {
01224 int cost = ashiftrt_insns[value];
01225
01226 if (cost > 1 + SH_DYNAMIC_SHIFT_COST)
01227 cost = 1 + SH_DYNAMIC_SHIFT_COST;
01228 return cost;
01229 }
01230 else
01231 return shift_insns[value];
01232 }
01233
01234
01235
01236 int
01237 andcosts (x)
01238 rtx x;
01239 {
01240 int i;
01241
01242
01243 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
01244 return 1;
01245
01246 i = INTVAL (XEXP (x, 1));
01247
01248 if (TARGET_SHMEDIA)
01249 {
01250 if ((GET_CODE (XEXP (x, 1)) == CONST_INT
01251 && CONST_OK_FOR_J (INTVAL (XEXP (x, 1))))
01252 || EXTRA_CONSTRAINT_S (XEXP (x, 1)))
01253 return 1;
01254 else
01255 return 2;
01256 }
01257
01258
01259 if (i == 0xff || i == 0xffff)
01260 return 1;
01261
01262
01263 if (CONST_OK_FOR_L (i))
01264 return 2;
01265
01266
01267 if (CONST_OK_FOR_I (i))
01268 return 2;
01269
01270
01271 return 3;
01272 }
01273
01274
01275
01276 int
01277 addsubcosts (x)
01278 rtx x;
01279 {
01280
01281 if (GET_CODE (XEXP (x, 1)) == REG
01282 || GET_CODE (XEXP (x, 1)) == SUBREG)
01283 return 1;
01284
01285
01286 if (GET_CODE (XEXP (x, 1)) == CONST_INT
01287 && CONST_OK_FOR_ADD (INTVAL (XEXP (x, 1))))
01288 return 1;
01289
01290 if (TARGET_SHMEDIA)
01291 switch (GET_CODE (XEXP (x, 1)))
01292 {
01293 case CONST:
01294 case LABEL_REF:
01295 case SYMBOL_REF:
01296 return TARGET_SHMEDIA64 ? 5 : 3;
01297
01298 case CONST_INT:
01299 if (CONST_OK_FOR_J (INTVAL (XEXP (x, 1))))
01300 return 2;
01301 else if (CONST_OK_FOR_J (INTVAL (XEXP (x, 1)) >> 16))
01302 return 3;
01303 else if (CONST_OK_FOR_J ((INTVAL (XEXP (x, 1)) >> 16) >> 16))
01304 return 4;
01305
01306
01307 default:
01308 return 5;
01309 }
01310
01311
01312
01313 return 3;
01314 }
01315
01316
01317 int
01318 multcosts (x)
01319 rtx x ATTRIBUTE_UNUSED;
01320 {
01321 if (TARGET_SHMEDIA)
01322 return 3;
01323
01324 if (TARGET_SH2)
01325 {
01326
01327
01328
01329 if (TARGET_SMALLCODE)
01330 return 2;
01331 return 3;
01332 }
01333
01334
01335
01336 if (TARGET_SMALLCODE)
01337 return 5;
01338
01339
01340 return 20;
01341 }
01342
01343
01344
01345 void
01346 gen_ashift (type, n, reg)
01347 int type;
01348 int n;
01349 rtx reg;
01350 {
01351
01352 if (n < 0)
01353 {
01354 if (type == ASHIFT)
01355 type = LSHIFTRT;
01356 else
01357 type = ASHIFT;
01358 n = -n;
01359 }
01360
01361 switch (type)
01362 {
01363 case ASHIFTRT:
01364 emit_insn (gen_ashrsi3_k (reg, reg, GEN_INT (n)));
01365 break;
01366 case LSHIFTRT:
01367 if (n == 1)
01368 emit_insn (gen_lshrsi3_m (reg, reg, GEN_INT (n)));
01369 else
01370 emit_insn (gen_lshrsi3_k (reg, reg, GEN_INT (n)));
01371 break;
01372 case ASHIFT:
01373 emit_insn (gen_ashlsi3_std (reg, reg, GEN_INT (n)));
01374 break;
01375 }
01376 }
01377
01378
01379
01380 void
01381 gen_ashift_hi (type, n, reg)
01382 int type;
01383 int n;
01384 rtx reg;
01385 {
01386
01387 if (n < 0)
01388 {
01389 if (type == ASHIFT)
01390 type = LSHIFTRT;
01391 else
01392 type = ASHIFT;
01393 n = -n;
01394 }
01395
01396 switch (type)
01397 {
01398 case ASHIFTRT:
01399 case LSHIFTRT:
01400
01401
01402
01403
01404
01405 {
01406 int offset = 0;
01407 if (GET_CODE (reg) == SUBREG)
01408 {
01409 offset = SUBREG_BYTE (reg);
01410 reg = SUBREG_REG (reg);
01411 }
01412 gen_ashift (type, n, gen_rtx_SUBREG (SImode, reg, offset));
01413 break;
01414 }
01415 case ASHIFT:
01416 emit_insn (gen_ashlhi3_k (reg, reg, GEN_INT (n)));
01417 break;
01418 }
01419 }
01420
01421
01422
01423
01424 void
01425 gen_shifty_op (code, operands)
01426 int code;
01427 rtx *operands;
01428 {
01429 int value = INTVAL (operands[2]);
01430 int max, i;
01431
01432
01433 value = value & 0x1f;
01434
01435 if (value == 31)
01436 {
01437 if (code == LSHIFTRT)
01438 {
01439 emit_insn (gen_rotlsi3_1 (operands[0], operands[0]));
01440 emit_insn (gen_movt (operands[0]));
01441 return;
01442 }
01443 else if (code == ASHIFT)
01444 {
01445
01446
01447 if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == 0)
01448 {
01449 emit_insn (gen_andsi3 (operands[0], operands[0], const1_rtx));
01450 emit_insn (gen_rotlsi3_31 (operands[0], operands[0]));
01451 return;
01452 }
01453 }
01454 }
01455 else if (value == 0)
01456 {
01457
01458
01459
01460 emit_insn (gen_nop ());
01461 return;
01462 }
01463
01464 max = shift_insns[value];
01465 for (i = 0; i < max; i++)
01466 gen_ashift (code, shift_amounts[value][i], operands[0]);
01467 }
01468
01469
01470
01471
01472 void
01473 gen_shifty_hi_op (code, operands)
01474 int code;
01475 rtx *operands;
01476 {
01477 int value = INTVAL (operands[2]);
01478 int max, i;
01479 void (*gen_fun) PARAMS ((int, int, rtx));
01480
01481
01482
01483 value &= 31;
01484 if (value == 0)
01485 {
01486 emit_insn (gen_nop ());
01487 return;
01488 }
01489
01490 gen_fun = GET_MODE (operands[0]) == HImode ? gen_ashift_hi : gen_ashift;
01491 if (code == ASHIFT)
01492 {
01493 max = ext_shift_insns[value];
01494 for (i = 0; i < max; i++)
01495 gen_fun (code, ext_shift_amounts[value][i], operands[0]);
01496 }
01497 else
01498
01499
01500 for (i = ext_shift_insns[value] - 1; i >= 0; i--)
01501 gen_fun (code, ext_shift_amounts[value][i], operands[0]);
01502 }
01503
01504
01505
01506
01507
01508 int
01509 expand_ashiftrt (operands)
01510 rtx *operands;
01511 {
01512 rtx sym;
01513 rtx wrk;
01514 char func[18];
01515 tree func_name;
01516 int value;
01517
01518 if (TARGET_SH3)
01519 {
01520 if (GET_CODE (operands[2]) != CONST_INT)
01521 {
01522 rtx count = copy_to_mode_reg (SImode, operands[2]);
01523 emit_insn (gen_negsi2 (count, count));
01524 emit_insn (gen_ashrsi3_d (operands[0], operands[1], count));
01525 return 1;
01526 }
01527 else if (ashiftrt_insns[INTVAL (operands[2]) & 31]
01528 > 1 + SH_DYNAMIC_SHIFT_COST)
01529 {
01530 rtx count
01531 = force_reg (SImode, GEN_INT (- (INTVAL (operands[2]) & 31)));
01532 emit_insn (gen_ashrsi3_d (operands[0], operands[1], count));
01533 return 1;
01534 }
01535 }
01536 if (GET_CODE (operands[2]) != CONST_INT)
01537 return 0;
01538
01539 value = INTVAL (operands[2]) & 31;
01540
01541 if (value == 31)
01542 {
01543 emit_insn (gen_ashrsi2_31 (operands[0], operands[1]));
01544 return 1;
01545 }
01546 else if (value >= 16 && value <= 19)
01547 {
01548 wrk = gen_reg_rtx (SImode);
01549 emit_insn (gen_ashrsi2_16 (wrk, operands[1]));
01550 value -= 16;
01551 while (value--)
01552 gen_ashift (ASHIFTRT, 1, wrk);
01553 emit_move_insn (operands[0], wrk);
01554 return 1;
01555 }
01556
01557 else if (value <= 5)
01558 {
01559 wrk = gen_reg_rtx (SImode);
01560 emit_move_insn (wrk, operands[1]);
01561 while (value--)
01562 gen_ashift (ASHIFTRT, 1, wrk);
01563 emit_move_insn (operands[0], wrk);
01564 return 1;
01565 }
01566
01567 wrk = gen_reg_rtx (Pmode);
01568
01569
01570 emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
01571 sprintf (func, "__ashiftrt_r4_%d", value);
01572 func_name = get_identifier (func);
01573 sym = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (func_name));
01574 emit_move_insn (wrk, sym);
01575 emit_insn (gen_ashrsi3_n (GEN_INT (value), wrk));
01576 emit_move_insn (operands[0], gen_rtx_REG (SImode, 4));
01577 return 1;
01578 }
01579
01580 int
01581 sh_dynamicalize_shift_p (count)
01582 rtx count;
01583 {
01584 return shift_insns[INTVAL (count)] > 1 + SH_DYNAMIC_SHIFT_COST;
01585 }
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607 int
01608 shl_and_kind (left_rtx, mask_rtx, attrp)
01609 rtx left_rtx, mask_rtx;
01610 int *attrp;
01611 {
01612 unsigned HOST_WIDE_INT mask, lsb, mask2, lsb2;
01613 int left = INTVAL (left_rtx), right;
01614 int best = 0;
01615 int cost, best_cost = 10000;
01616 int best_right = 0, best_len = 0;
01617 int i;
01618 int can_ext;
01619
01620 if (left < 0 || left > 31)
01621 return 0;
01622 if (GET_CODE (mask_rtx) == CONST_INT)
01623 mask = (unsigned HOST_WIDE_INT) INTVAL (mask_rtx) >> left;
01624 else
01625 mask = (unsigned HOST_WIDE_INT) GET_MODE_MASK (SImode) >> left;
01626
01627 lsb = ((mask ^ (mask - 1)) >> 1) + 1;
01628 right = exact_log2 (lsb);
01629 mask2 = ~(mask + lsb - 1);
01630 lsb2 = ((mask2 ^ (mask2 - 1)) >> 1) + 1;
01631
01632 if (! mask2)
01633 best_cost = shift_insns[right] + shift_insns[right + left];
01634
01635 else if (! right && mask2 == ~(lsb2 - 1))
01636 {
01637 int late_right = exact_log2 (lsb2);
01638 best_cost = shift_insns[left + late_right] + shift_insns[late_right];
01639 }
01640
01641 if (mask2 == ~(lsb2 - 1))
01642 {
01643 int width, first;
01644
01645 for (width = 8; width <= 16; width += 8)
01646 {
01647
01648 if (lsb2 == (unsigned HOST_WIDE_INT)1 << width)
01649 {
01650 cost
01651 = 1 + ext_shift_insns[right] + ext_shift_insns[left + right];
01652 if (cost < best_cost)
01653 {
01654 best = 1;
01655 best_cost = cost;
01656 best_right = right;
01657 best_len = cost;
01658 if (attrp)
01659 attrp[2] = -1;
01660 }
01661 continue;
01662 }
01663
01664
01665
01666
01667 first = width - exact_log2 (lsb2) + right;
01668 if (first >= 0 && right + left - first >= 0)
01669 {
01670 cost = ext_shift_insns[right] + ext_shift_insns[first] + 1
01671 + ext_shift_insns[right + left - first];
01672 if (cost < best_cost)
01673 {
01674 best = 1;
01675 best_cost = cost;
01676 best_right = right;
01677 best_len = cost;
01678 if (attrp)
01679 attrp[2] = first;
01680 }
01681 }
01682 }
01683 }
01684
01685 for (i = 0; i <= 2; i++)
01686 {
01687 if (i > right)
01688 break;
01689 if (! CONST_OK_FOR_L (mask >> i))
01690 continue;
01691 cost = (i != 0) + 2 + ext_shift_insns[left + i];
01692 if (cost < best_cost)
01693 {
01694 best = 2;
01695 best_cost = cost;
01696 best_right = i;
01697 best_len = cost - 1;
01698 }
01699 }
01700
01701 can_ext = ((mask << left) & ((unsigned HOST_WIDE_INT)3 << 30)) == 0;
01702 for (i = 0; i <= 2; i++)
01703 {
01704 if (i > right)
01705 break;
01706 cost = (i != 0) + (CONST_OK_FOR_I (mask >> i) ? 2 : 3)
01707 + (can_ext ? ext_shift_insns : shift_insns)[left + i];
01708 if (cost < best_cost)
01709 {
01710 best = 4 - can_ext;
01711 best_cost = cost;
01712 best_right = i;
01713 best_len = cost - 1 - ! CONST_OK_FOR_I (mask >> i);
01714 }
01715 }
01716
01717 if (attrp)
01718 {
01719 attrp[0] = best_right;
01720 attrp[1] = best_len;
01721 }
01722 return best;
01723 }
01724
01725
01726
01727 int
01728 shl_and_length (insn)
01729 rtx insn;
01730 {
01731 rtx set_src, left_rtx, mask_rtx;
01732 int attributes[3];
01733
01734 set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
01735 left_rtx = XEXP (XEXP (set_src, 0), 1);
01736 mask_rtx = XEXP (set_src, 1);
01737 shl_and_kind (left_rtx, mask_rtx, attributes);
01738 return attributes[1];
01739 }
01740
01741
01742
01743 int
01744 shl_and_scr_length (insn)
01745 rtx insn;
01746 {
01747 rtx set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
01748 int len = shift_insns[INTVAL (XEXP (set_src, 1))];
01749 rtx op = XEXP (set_src, 0);
01750 len += shift_insns[INTVAL (XEXP (op, 1))] + 1;
01751 op = XEXP (XEXP (op, 0), 0);
01752 return len + shift_insns[INTVAL (XEXP (op, 1))];
01753 }
01754
01755
01756 extern int rtx_equal_function_value_matters;
01757
01758
01759
01760
01761 int
01762 gen_shl_and (dest, left_rtx, mask_rtx, source)
01763 rtx dest, left_rtx, mask_rtx, source;
01764 {
01765 int attributes[3];
01766 unsigned HOST_WIDE_INT mask;
01767 int kind = shl_and_kind (left_rtx, mask_rtx, attributes);
01768 int right, total_shift;
01769 void (*shift_gen_fun) PARAMS ((int, rtx*)) = gen_shifty_hi_op;
01770
01771 right = attributes[0];
01772 total_shift = INTVAL (left_rtx) + right;
01773 mask = (unsigned HOST_WIDE_INT) INTVAL (mask_rtx) >> total_shift;
01774 switch (kind)
01775 {
01776 default:
01777 return -1;
01778 case 1:
01779 {
01780 int first = attributes[2];
01781 rtx operands[3];
01782
01783 if (first < 0)
01784 {
01785 emit_insn ((mask << right) <= 0xff
01786 ? gen_zero_extendqisi2(dest,
01787 gen_lowpart (QImode, source))
01788 : gen_zero_extendhisi2(dest,
01789 gen_lowpart (HImode, source)));
01790 source = dest;
01791 }
01792 if (source != dest)
01793 emit_insn (gen_movsi (dest, source));
01794 operands[0] = dest;
01795 if (right)
01796 {
01797 operands[2] = GEN_INT (right);
01798 gen_shifty_hi_op (LSHIFTRT, operands);
01799 }
01800 if (first > 0)
01801 {
01802 operands[2] = GEN_INT (first);
01803 gen_shifty_hi_op (ASHIFT, operands);
01804 total_shift -= first;
01805 mask <<= first;
01806 }
01807 if (first >= 0)
01808 emit_insn (mask <= 0xff
01809 ? gen_zero_extendqisi2(dest, gen_lowpart (QImode, dest))
01810 : gen_zero_extendhisi2(dest, gen_lowpart (HImode, dest)));
01811 if (total_shift > 0)
01812 {
01813 operands[2] = GEN_INT (total_shift);
01814 gen_shifty_hi_op (ASHIFT, operands);
01815 }
01816 break;
01817 }
01818 case 4:
01819 shift_gen_fun = gen_shifty_op;
01820 case 3:
01821
01822
01823
01824 if (mask & ((HOST_WIDE_INT)1 << (31 - total_shift)))
01825 mask |= (HOST_WIDE_INT)~0 << (31 - total_shift);
01826 case 2:
01827
01828
01829 if (rtx_equal_function_value_matters
01830 || reload_in_progress || reload_completed)
01831 {
01832 rtx operands[3];
01833
01834
01835
01836 if (kind > 2)
01837 abort ();
01838 if (right)
01839 {
01840 emit_insn (gen_lshrsi3 (dest, source, GEN_INT (right)));
01841 source = dest;
01842 }
01843 emit_insn (gen_andsi3 (dest, source, GEN_INT (mask)));
01844 if (total_shift)
01845 {
01846 operands[0] = dest;
01847 operands[1] = dest;
01848 operands[2] = GEN_INT (total_shift);
01849 shift_gen_fun (ASHIFT, operands);
01850 }
01851 break;
01852 }
01853 else
01854 {
01855 int neg = 0;
01856 if (kind != 4 && total_shift < 16)
01857 {
01858 neg = -ext_shift_amounts[total_shift][1];
01859 if (neg > 0)
01860 neg -= ext_shift_amounts[total_shift][2];
01861 else
01862 neg = 0;
01863 }
01864 emit_insn (gen_and_shl_scratch (dest, source,
01865 GEN_INT (right),
01866 GEN_INT (mask),
01867 GEN_INT (total_shift + neg),
01868 GEN_INT (neg)));
01869 emit_insn (gen_movsi (dest, dest));
01870 break;
01871 }
01872 }
01873 return 0;
01874 }
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892
01893
01894 int
01895 shl_sext_kind (left_rtx, size_rtx, costp)
01896 rtx left_rtx, size_rtx;
01897 int *costp;
01898 {
01899 int left, size, insize, ext;
01900 int cost, best_cost;
01901 int kind;
01902
01903 left = INTVAL (left_rtx);
01904 size = INTVAL (size_rtx);
01905 insize = size - left;
01906 if (insize <= 0)
01907 abort ();
01908
01909 kind = 0;
01910 best_cost = shift_insns[32 - insize] + ashiftrt_insns[32 - size];
01911 if (size <= 16)
01912 {
01913
01914 cost = shift_insns[16 - insize] + 1 + ashiftrt_insns[16 - size];
01915
01916
01917 if (cost < best_cost)
01918 {
01919 kind = 5;
01920 best_cost = cost;
01921 }
01922 }
01923
01924 for (ext = 16; ext >= insize; ext -= 8)
01925 {
01926 if (ext <= size)
01927 {
01928 cost = ext_shift_insns[ext - insize] + 1 + shift_insns[size - ext];
01929 if (cost < best_cost)
01930 {
01931 kind = ext / (unsigned) 8;
01932 best_cost = cost;
01933 }
01934 }
01935
01936
01937 if (EXT_SHIFT_SIGNED (size - ext))
01938 cost = ext_shift_insns[ext - insize] + ext_shift_insns[size - ext] + 1;
01939
01940
01941 else if (size <= 16)
01942 cost = ext_shift_insns[ext - insize] + 1
01943 + ext_shift_insns[size > ext ? size - ext : ext - size] + 1;
01944 else
01945 continue;
01946 if (cost < best_cost)
01947 {
01948 kind = ext / (unsigned) 8 + 2;
01949 best_cost = cost;
01950 }
01951 }
01952
01953 if (insize < 8)
01954 {
01955 cost = 3 + shift_insns[left];
01956 if (cost < best_cost)
01957 {
01958 kind = 6;
01959 best_cost = cost;
01960 }
01961
01962 if (left < 31)
01963 {
01964 cost = 3 + ext_shift_insns[left + 1] + 1;
01965 if (cost < best_cost)
01966 {
01967 kind = 7;
01968 best_cost = cost;
01969 }
01970 }
01971 }
01972 if (TARGET_SH3)
01973 {
01974
01975 cost = shift_insns[32 - insize] + 1 + SH_DYNAMIC_SHIFT_COST;
01976 if (cost < best_cost)
01977 {
01978 kind = 0;
01979 best_cost = cost;
01980 }
01981 }
01982 if (costp)
01983 *costp = cost;
01984 return kind;
01985 }
01986
01987
01988
01989
01990 int
01991 shl_sext_length (insn)
01992 rtx insn;
01993 {
01994 rtx set_src, left_rtx, size_rtx;
01995 int cost;
01996
01997 set_src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
01998 left_rtx = XEXP (XEXP (set_src, 0), 1);
01999 size_rtx = XEXP (set_src, 1);
02000 shl_sext_kind (left_rtx, size_rtx, &cost);
02001 return cost;
02002 }
02003
02004
02005
02006 int
02007 gen_shl_sext (dest, left_rtx, size_rtx, source)
02008 rtx dest, left_rtx, size_rtx, source;
02009 {
02010 int kind;
02011 int left, size, insize, cost;
02012 rtx operands[3];
02013
02014 kind = shl_sext_kind (left_rtx, size_rtx, &cost);
02015 left = INTVAL (left_rtx);
02016 size = INTVAL (size_rtx);
02017 insize = size - left;
02018 switch (kind)
02019 {
02020 case 1:
02021 case 2:
02022 case 3:
02023 case 4:
02024 {
02025 int ext = kind & 1 ? 8 : 16;
02026 int shift2 = size - ext;
02027
02028
02029
02030 if (! rtx_equal_function_value_matters
02031 && ! reload_in_progress && ! reload_completed)
02032 {
02033 emit_insn (gen_shl_sext_ext (dest, source, left_rtx, size_rtx));
02034 emit_insn (gen_movsi (dest, source));
02035 break;
02036 }
02037 if (dest != source)
02038 emit_insn (gen_movsi (dest, source));
02039 operands[0] = dest;
02040 if (ext - insize)
02041 {
02042 operands[2] = GEN_INT (ext - insize);
02043 gen_shifty_hi_op (ASHIFT, operands);
02044 }
02045 emit_insn (kind & 1
02046 ? gen_extendqisi2(dest, gen_lowpart (QImode, dest))
02047 : gen_extendhisi2(dest, gen_lowpart (HImode, dest)));
02048 if (kind <= 2)
02049 {
02050 if (shift2)
02051 {
02052 operands[2] = GEN_INT (shift2);
02053 gen_shifty_op (ASHIFT, operands);
02054 }
02055 }
02056 else
02057 {
02058 if (shift2 > 0)
02059 {
02060 if (EXT_SHIFT_SIGNED (shift2))
02061 {
02062 operands[2] = GEN_INT (shift2 + 1);
02063 gen_shifty_op (ASHIFT, operands);
02064 operands[2] = GEN_INT (1);
02065 gen_shifty_op (ASHIFTRT, operands);
02066 break;
02067 }
02068 operands[2] = GEN_INT (shift2);
02069 gen_shifty_hi_op (ASHIFT, operands);
02070 }
02071 else if (shift2)
02072 {
02073 operands[2] = GEN_INT (-shift2);
02074 gen_shifty_hi_op (LSHIFTRT, operands);
02075 }
02076 emit_insn (size <= 8
02077 ? gen_extendqisi2 (dest, gen_lowpart (QImode, dest))
02078 : gen_extendhisi2 (dest, gen_lowpart (HImode, dest)));
02079 }
02080 break;
02081 }
02082 case 5:
02083 {
02084 int i = 16 - size;
02085 if (! rtx_equal_function_value_matters
02086 && ! reload_in_progress && ! reload_completed)
02087 emit_insn (gen_shl_sext_ext (dest, source, left_rtx, size_rtx));
02088 else
02089 {
02090 operands[0] = dest;
02091 operands[2] = GEN_INT (16 - insize);
02092 gen_shifty_hi_op (ASHIFT, operands);
02093 emit_insn (gen_extendhisi2 (dest, gen_lowpart (HImode, dest)));
02094 }
02095
02096 while (--i >= 0)
02097 gen_ashift (ASHIFTRT, 1, dest);
02098 break;
02099 }
02100 case 6:
02101 case 7:
02102
02103
02104 if (! rtx_equal_function_value_matters
02105 && ! reload_in_progress && ! reload_completed)
02106 {
02107 emit_insn (gen_shl_sext_ext (dest, source, left_rtx, size_rtx));
02108 emit_insn (gen_movsi (dest, source));
02109 break;
02110 }
02111 emit_insn (gen_andsi3 (dest, source, GEN_INT ((1 << insize) - 1)));
02112 emit_insn (gen_xorsi3 (dest, dest, GEN_INT (1 << (insize - 1))));
02113 emit_insn (gen_addsi3 (dest, dest, GEN_INT (-1 << (insize - 1))));
02114 operands[0] = dest;
02115 operands[2] = kind == 7 ? GEN_INT (left + 1) : left_rtx;
02116 gen_shifty_op (ASHIFT, operands);
02117 if (kind == 7)
02118 emit_insn (gen_ashrsi3_k (dest, dest, GEN_INT (1)));
02119 break;
02120 default:
02121 return -1;
02122 }
02123 return 0;
02124 }
02125
02126
02127
02128 rtx
02129 gen_datalabel_ref (sym)
02130 rtx sym;
02131 {
02132 if (GET_CODE (sym) == LABEL_REF)
02133 return gen_rtx_CONST (GET_MODE (sym),
02134 gen_rtx_UNSPEC (GET_MODE (sym),
02135 gen_rtvec (1, sym),
02136 UNSPEC_DATALABEL));
02137
02138 if (GET_CODE (sym) != SYMBOL_REF)
02139 abort ();
02140
02141 XSTR (sym, 0) = concat (SH_DATALABEL_ENCODING, XSTR (sym, 0), NULL);
02142
02143 return sym;
02144 }
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159
02160
02161
02162
02163
02164
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195
02196
02197
02198
02199
02200 typedef struct
02201 {
02202 rtx value;
02203 rtx label;
02204 rtx wend;
02205 enum machine_mode mode;
02206 } pool_node;
02207
02208
02209
02210
02211
02212 #define MAX_POOL_SIZE (1020/4)
02213 static pool_node pool_vector[MAX_POOL_SIZE];
02214 static int pool_size;
02215 static rtx pool_window_label;
02216 static int pool_window_last;
02217
02218
02219
02220
02221
02222
02223
02224
02225
02226
02227
02228
02229
02230 static rtx
02231 add_constant (x, mode, last_value)
02232 rtx x;
02233 enum machine_mode mode;
02234 rtx last_value;
02235 {
02236 int i;
02237 rtx lab, new, ref, newref;
02238
02239
02240 for (i = 0; i < pool_size; i++)
02241 {
02242 if (x->code == pool_vector[i].value->code
02243 && mode == pool_vector[i].mode)
02244 {
02245 if (x->code == CODE_LABEL)
02246 {
02247 if (XINT (x, 3) != XINT (pool_vector[i].value, 3))
02248 continue;
02249 }
02250 if (rtx_equal_p (x, pool_vector[i].value))
02251 {
02252 lab = new = 0;
02253 if (! last_value
02254 || ! i
02255 || ! rtx_equal_p (last_value, pool_vector[i-1].value))
02256 {
02257 new = gen_label_rtx ();
02258 LABEL_REFS (new) = pool_vector[i].label;
02259 pool_vector[i].label = lab = new;
02260 }
02261 if (lab && pool_window_label)
02262 {
02263 newref = gen_rtx_LABEL_REF (VOIDmode, pool_window_label);
02264 ref = pool_vector[pool_window_last].wend;
02265 LABEL_NEXTREF (newref) = ref;
02266 pool_vector[pool_window_last].wend = newref;
02267 }
02268 if (new)
02269 pool_window_label = new;
02270 pool_window_last = i;
02271 return lab;
02272 }
02273 }
02274 }
02275
02276
02277 pool_vector[pool_size].value = x;
02278 if (last_value && rtx_equal_p (last_value, pool_vector[pool_size - 1].value))
02279 lab = 0;
02280 else
02281 lab = gen_label_rtx ();
02282 pool_vector[pool_size].mode = mode;
02283 pool_vector[pool_size].label = lab;
02284 pool_vector[pool_size].wend = NULL_RTX;
02285 if (lab && pool_window_label)
02286 {
02287 newref = gen_rtx_LABEL_REF (VOIDmode, pool_window_label);
02288 ref = pool_vector[pool_window_last].wend;
02289 LABEL_NEXTREF (newref) = ref;
02290 pool_vector[pool_window_last].wend = newref;
02291 }
02292 if (lab)
02293 pool_window_label = lab;
02294 pool_window_last = pool_size;
02295 pool_size++;
02296 return lab;
02297 }
02298
02299
02300
02301 static void
02302 dump_table (scan)
02303 rtx scan;
02304 {
02305 int i;
02306 int need_align = 1;
02307 rtx lab, ref;
02308 int have_di = 0;
02309
02310
02311
02312 for (i = 0; i < pool_size; i++)
02313 {
02314 pool_node *p = &pool_vector[i];
02315
02316 if (p->mode == HImode)
02317 {
02318 if (need_align)
02319 {
02320 scan = emit_insn_after (gen_align_2 (), scan);
02321 need_align = 0;
02322 }
02323 for (lab = p->label; lab; lab = LABEL_REFS (lab))
02324 scan = emit_label_after (lab, scan);
02325 scan = emit_insn_after (gen_consttable_2 (p->value, const0_rtx),
02326 scan);
02327 for (ref = p->wend; ref; ref = LABEL_NEXTREF (ref))
02328 {
02329 lab = XEXP (ref, 0);
02330 scan = emit_insn_after (gen_consttable_window_end (lab), scan);
02331 }
02332 }
02333 else if (p->mode == DImode || p->mode == DFmode)
02334 have_di = 1;
02335 }
02336
02337 need_align = 1;
02338
02339 if (TARGET_SHCOMPACT && have_di)
02340 {
02341 rtx align_insn = NULL_RTX;
02342
02343 scan = emit_label_after (gen_label_rtx (), scan);
02344 scan = emit_insn_after (gen_align_log (GEN_INT (3)), scan);
02345 need_align = 0;
02346
02347 for (i = 0; i < pool_size; i++)
02348 {
02349 pool_node *p = &pool_vector[i];
02350
02351 switch (p->mode)
02352 {
02353 case HImode:
02354 break;
02355 case SImode:
02356 case SFmode:
02357 if (align_insn)
02358 {
02359 for (lab = p->label; lab; lab = LABEL_REFS (lab))
02360 emit_label_before (lab, align_insn);
02361 emit_insn_before (gen_consttable_4 (p->value, const0_rtx),
02362 align_insn);
02363 for (ref = p->wend; ref; ref = LABEL_NEXTREF (ref))
02364 {
02365 lab = XEXP (ref, 0);
02366 emit_insn_before (gen_consttable_window_end (lab),
02367 align_insn);
02368 }
02369 delete_insn (align_insn);
02370 align_insn = NULL_RTX;
02371 continue;
02372 }
02373 else
02374 {
02375 for (lab = p->label; lab; lab = LABEL_REFS (lab))
02376 scan = emit_label_after (lab, scan);
02377 scan = emit_insn_after (gen_consttable_4 (p->value,
02378 const0_rtx), scan);
02379 need_align = ! need_align;
02380 }
02381 break;
02382 case DFmode:
02383 case DImode:
02384 if (need_align)
02385 {
02386 scan = emit_insn_after (gen_align_log (GEN_INT (3)), scan);
02387 align_insn = scan;
02388 need_align = 0;
02389 }
02390 for (lab = p->label; lab; lab = LABEL_REFS (lab))
02391 scan = emit_label_after (lab, scan);
02392 scan = emit_insn_after (gen_consttable_8 (p->value, const0_rtx),
02393 scan);
02394 break;
02395 default:
02396 abort ();
02397 break;
02398 }
02399
02400 if (p->mode != HImode)
02401 {
02402 for (ref = p->wend; ref; ref = LABEL_NEXTREF (ref))
02403 {
02404 lab = XEXP (ref, 0);
02405 scan = emit_insn_after (gen_consttable_window_end (lab),
02406 scan);
02407 }
02408 }
02409 }
02410
02411 pool_size = 0;
02412 }
02413
02414 for (i = 0; i < pool_size; i++)
02415 {
02416 pool_node *p = &pool_vector[i];
02417
02418 switch (p->mode)
02419 {
02420 case HImode:
02421 break;
02422 case SImode:
02423 case SFmode:
02424 if (need_align)
02425 {
02426 need_align = 0;
02427 scan = emit_label_after (gen_label_rtx (), scan);
02428 scan = emit_insn_after (gen_align_4 (), scan);
02429 }
02430 for (lab = p->label; lab; lab = LABEL_REFS (lab))
02431 scan = emit_label_after (lab, scan);
02432 scan = emit_insn_after (gen_consttable_4 (p->value, const0_rtx),
02433 scan);
02434 break;
02435 case DFmode:
02436 case DImode:
02437 if (need_align)
02438 {
02439 need_align = 0;
02440 scan = emit_label_after (gen_label_rtx (), scan);
02441 scan = emit_insn_after (gen_align_4 (), scan);
02442 }
02443 for (lab = p->label; lab; lab = LABEL_REFS (lab))
02444 scan = emit_label_after (lab, scan);
02445 scan = emit_insn_after (gen_consttable_8 (p->value, const0_rtx),
02446 scan);
02447 break;
02448 default:
02449 abort ();
02450 break;
02451 }
02452
02453 if (p->mode != HImode)
02454 {
02455 for (ref = p->wend; ref; ref = LABEL_NEXTREF (ref))
02456 {
02457 lab = XEXP (ref, 0);
02458 scan = emit_insn_after (gen_consttable_window_end (lab), scan);
02459 }
02460 }
02461 }
02462
02463 scan = emit_insn_after (gen_consttable_end (), scan);
02464 scan = emit_barrier_after (scan);
02465 pool_size = 0;
02466 pool_window_label = NULL_RTX;
02467 pool_window_last = 0;
02468 }
02469
02470
02471
02472
02473 static int
02474 hi_const (src)
02475 rtx src;
02476 {
02477 return (GET_CODE (src) == CONST_INT
02478 && INTVAL (src) >= -32768
02479 && INTVAL (src) <= 32767);
02480 }
02481
02482
02483
02484
02485
02486
02487
02488 static int
02489 broken_move (insn)
02490 rtx insn;
02491 {
02492 if (GET_CODE (insn) == INSN)
02493 {
02494 rtx pat = PATTERN (insn);
02495 if (GET_CODE (pat) == PARALLEL)
02496 pat = XVECEXP (pat, 0, 0);
02497 if (GET_CODE (pat) == SET
02498
02499
02500 && GET_MODE (SET_DEST (pat)) != QImode
02501 && (CONSTANT_P (SET_SRC (pat))
02502
02503 || (GET_CODE (SET_SRC (pat)) == UNSPEC
02504 && XINT (SET_SRC (pat), 1) == UNSPEC_MOVA
02505 && GET_CODE (XVECEXP (SET_SRC (pat), 0, 0)) == CONST))
02506 && ! (TARGET_SH3E
02507 && GET_CODE (SET_SRC (pat)) == CONST_DOUBLE
02508 && (fp_zero_operand (SET_SRC (pat))
02509 || fp_one_operand (SET_SRC (pat)))
02510
02511
02512 && (! TARGET_SH4 || TARGET_FMOVD)
02513 && GET_CODE (SET_DEST (pat)) == REG
02514 && FP_REGISTER_P (REGNO (SET_DEST (pat))))
02515 && (GET_CODE (SET_SRC (pat)) != CONST_INT
02516 || ! CONST_OK_FOR_I (INTVAL (SET_SRC (pat)))))
02517 return 1;
02518 }
02519
02520 return 0;
02521 }
02522
02523 static int
02524 mova_p (insn)
02525 rtx insn;
02526 {
02527 return (GET_CODE (insn) == INSN
02528 && GET_CODE (PATTERN (insn)) == SET
02529 && GET_CODE (SET_SRC (PATTERN (insn))) == UNSPEC
02530 && XINT (SET_SRC (PATTERN (insn)), 1) == UNSPEC_MOVA
02531
02532 && GET_CODE (XVECEXP (SET_SRC (PATTERN (insn)), 0, 0)) == LABEL_REF);
02533 }
02534
02535
02536
02537
02538
02539 static rtx
02540 find_barrier (num_mova, mova, from)
02541 int num_mova;
02542 rtx mova, from;
02543 {
02544 int count_si = 0;
02545 int count_hi = 0;
02546 int found_hi = 0;
02547 int found_si = 0;
02548 int found_di = 0;
02549 int hi_align = 2;
02550 int si_align = 2;
02551 int leading_mova = num_mova;
02552 rtx barrier_before_mova, found_barrier = 0, good_barrier = 0;
02553 int si_limit;
02554 int hi_limit;
02555
02556
02557
02558
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572 si_limit = 1018;
02573 hi_limit = 510;
02574
02575 while (from && count_si < si_limit && count_hi < hi_limit)
02576 {
02577 int inc = get_attr_length (from);
02578 int new_align = 1;
02579
02580 if (GET_CODE (from) == CODE_LABEL)
02581 {
02582 if (optimize)
02583 new_align = 1 << label_to_alignment (from);
02584 else if (GET_CODE (prev_nonnote_insn (from)) == BARRIER)
02585 new_align = 1 << barrier_align (from);
02586 else
02587 new_align = 1;
02588 inc = 0;
02589 }
02590
02591 if (GET_CODE (from) == BARRIER)
02592 {
02593
02594 found_barrier = from;
02595
02596
02597
02598
02599 if (barrier_align (from) > 2)
02600 good_barrier = from;
02601 }
02602
02603 if (broken_move (from))
02604 {
02605 rtx pat, src, dst;
02606 enum machine_mode mode;
02607
02608 pat = PATTERN (from);
02609 if (GET_CODE (pat) == PARALLEL)
02610 pat = XVECEXP (pat, 0, 0);
02611 src = SET_SRC (pat);
02612 dst = SET_DEST (pat);
02613 mode = GET_MODE (dst);
02614
02615
02616
02617
02618 if (mode == HImode
02619 || (mode == SImode && hi_const (src) && REGNO (dst) != FPUL_REG))
02620 {
02621 found_hi += 2;
02622
02623
02624
02625
02626 si_limit -= 2;
02627 }
02628 else
02629 {
02630
02631
02632
02633
02634
02635 if (TARGET_SHCOMPACT
02636 && ! found_di
02637 && (mode == DFmode || mode == DImode))
02638 {
02639 found_di = 1;
02640 si_limit -= 8;
02641 }
02642 while (si_align > 2 && found_si + si_align - 2 > count_si)
02643 si_align >>= 1;
02644 if (found_si > count_si)
02645 count_si = found_si;
02646 found_si += GET_MODE_SIZE (mode);
02647 if (num_mova)
02648 si_limit -= GET_MODE_SIZE (mode);
02649 }
02650
02651
02652
02653 if (GET_CODE (dst) == REG && FP_ANY_REGISTER_P (REGNO (dst)))
02654 inc += 2;
02655 }
02656
02657 if (mova_p (from))
02658 {
02659 if (! num_mova++)
02660 {
02661 leading_mova = 0;
02662 mova = from;
02663 barrier_before_mova = good_barrier ? good_barrier : found_barrier;
02664 }
02665 if (found_si > count_si)
02666 count_si = found_si;
02667 }
02668 else if (GET_CODE (from) == JUMP_INSN
02669 && (GET_CODE (PATTERN (from)) == ADDR_VEC
02670 || GET_CODE (PATTERN (from)) == ADDR_DIFF_VEC))
02671 {
02672 if (num_mova)
02673 num_mova--;
02674 if (barrier_align (next_real_insn (from)) == CACHE_LOG)
02675 {
02676
02677
02678
02679
02680
02681
02682
02683
02684 good_barrier = found_barrier;
02685 break;
02686 }
02687 else
02688 {
02689 rtx body = PATTERN (from);
02690 inc = XVECLEN (body, 1) * GET_MODE_SIZE (GET_MODE (body));
02691 }
02692 }
02693
02694 else if (GET_CODE (from) == JUMP_INSN
02695 && ! TARGET_SH2
02696 && ! TARGET_SMALLCODE)
02697 new_align = 4;
02698
02699 if (found_si)
02700 {
02701 count_si += inc;
02702 if (new_align > si_align)
02703 {
02704 si_limit -= (count_si - 1) & (new_align - si_align);
02705 si_align = new_align;
02706 }
02707 count_si = (count_si + new_align - 1) & -new_align;
02708 }
02709 if (found_hi)
02710 {
02711 count_hi += inc;
02712 if (new_align > hi_align)
02713 {
02714 hi_limit -= (count_hi - 1) & (new_align - hi_align);
02715 hi_align = new_align;
02716 }
02717 count_hi = (count_hi + new_align - 1) & -new_align;
02718 }
02719 from = NEXT_INSN (from);
02720 }
02721
02722 if (num_mova)
02723 {
02724 if (leading_mova)
02725 {
02726
02727
02728 SET_SRC (PATTERN (mova)) = XVECEXP (SET_SRC (PATTERN (mova)), 0, 0);
02729 INSN_CODE (mova) = -1;
02730 return find_barrier (0, 0, mova);
02731 }
02732 else
02733 {
02734
02735
02736 from = mova;
02737 good_barrier = found_barrier = barrier_before_mova;
02738 }
02739 }
02740
02741 if (found_barrier)
02742 {
02743 if (good_barrier && next_real_insn (found_barrier))
02744 found_barrier = good_barrier;
02745 }
02746 else
02747 {
02748
02749
02750 rtx label = gen_label_rtx ();
02751
02752
02753
02754
02755 if (count_hi > hi_limit || count_si > si_limit)
02756 from = PREV_INSN (PREV_INSN (from));
02757 else
02758 from = PREV_INSN (from);
02759
02760
02761
02762
02763
02764
02765 while (GET_CODE (from) == JUMP_INSN || GET_CODE (from) == NOTE
02766 || GET_CODE (from) == CODE_LABEL)
02767 from = PREV_INSN (from);
02768
02769 from = emit_jump_insn_after (gen_jump (label), from);
02770 JUMP_LABEL (from) = label;
02771 LABEL_NUSES (label) = 1;
02772 found_barrier = emit_barrier_after (from);
02773 emit_label_after (label, found_barrier);
02774 }
02775
02776 return found_barrier;
02777 }
02778
02779
02780
02781
02782
02783 rtx
02784 sfunc_uses_reg (insn)
02785 rtx insn;
02786 {
02787 int i;
02788 rtx pattern, part, reg_part, reg;
02789
02790 if (GET_CODE (insn) != INSN)
02791 return 0;
02792 pattern = PATTERN (insn);
02793 if (GET_CODE (pattern) != PARALLEL || get_attr_type (insn) != TYPE_SFUNC)
02794 return 0;
02795
02796 for (reg_part = 0, i = XVECLEN (pattern, 0) - 1; i >= 1; i--)
02797 {
02798 part = XVECEXP (pattern, 0, i);
02799 if (GET_CODE (part) == USE && GET_MODE (XEXP (part, 0)) == SImode)
02800 reg_part = part;
02801 }
02802 if (! reg_part)
02803 return 0;
02804 reg = XEXP (reg_part, 0);
02805 for (i = XVECLEN (pattern, 0) - 1; i >= 0; i--)
02806 {
02807 part = XVECEXP (pattern, 0, i);
02808 if (part == reg_part || GET_CODE (part) == CLOBBER)
02809 continue;
02810 if (reg_mentioned_p (reg, ((GET_CODE (part) == SET
02811 && GET_CODE (SET_DEST (part)) == REG)
02812 ? SET_SRC (part) : part)))
02813 return 0;
02814 }
02815 return reg;
02816 }
02817
02818
02819
02820
02821
02822 static int
02823 noncall_uses_reg (reg, insn, set)
02824 rtx reg;
02825 rtx insn;
02826 rtx *set;
02827 {
02828 rtx pattern, reg2;
02829
02830 *set = NULL_RTX;
02831
02832 reg2 = sfunc_uses_reg (insn);
02833 if (reg2 && REGNO (reg2) == REGNO (reg))
02834 {
02835 pattern = single_set (insn);
02836 if (pattern
02837 && GET_CODE (SET_DEST (pattern)) == REG
02838 && REGNO (reg) == REGNO (SET_DEST (pattern)))
02839 *set = pattern;
02840 return 0;
02841 }
02842 if (GET_CODE (insn) != CALL_INSN)
02843 {
02844
02845
02846 pattern = single_set (insn);
02847 if (pattern
02848 && GET_CODE (SET_DEST (pattern)) == REG
02849 && REGNO (reg) == REGNO (SET_DEST (pattern)))
02850 {
02851 rtx par, part;
02852 int i;
02853
02854 *set = pattern;
02855 par = PATTERN (insn);
02856 if (GET_CODE (par) == PARALLEL)
02857 for (i = XVECLEN (par, 0) - 1; i >= 0; i--)
02858 {
02859 part = XVECEXP (par, 0, i);
02860 if (GET_CODE (part) != SET && reg_mentioned_p (reg, part))
02861 return 1;
02862 }
02863 return reg_mentioned_p (reg, SET_SRC (pattern));
02864 }
02865
02866 return 1;
02867 }
02868
02869 pattern = PATTERN (insn);
02870
02871 if (GET_CODE (pattern) == PARALLEL)
02872 {
02873 int i;
02874
02875 for (i = XVECLEN (pattern, 0) - 1; i >= 1; i--)
02876 if (reg_mentioned_p (reg, XVECEXP (pattern, 0, i)))
02877 return 1;
02878 pattern = XVECEXP (pattern, 0, 0);
02879 }
02880
02881 if (GET_CODE (pattern) == SET)
02882 {
02883 if (reg_mentioned_p (reg, SET_DEST (pattern)))
02884 {
02885
02886
02887 if (GET_CODE (SET_DEST (pattern)) != REG
02888 || REGNO (reg) != REGNO (SET_DEST (pattern)))
02889 return 1;
02890
02891 *set = pattern;
02892 }
02893
02894 pattern = SET_SRC (pattern);
02895 }
02896
02897 if (GET_CODE (pattern) != CALL
02898 || GET_CODE (XEXP (pattern, 0)) != MEM
02899 || ! rtx_equal_p (reg, XEXP (XEXP (pattern, 0), 0)))
02900 return 1;
02901
02902 return 0;
02903 }
02904
02905
02906
02907
02908
02909
02910 int
02911 regs_used (x, is_dest)
02912 rtx x; int is_dest;
02913 {
02914 enum rtx_code code;
02915 const char *fmt;
02916 int i, used = 0;
02917
02918 if (! x)
02919 return used;
02920 code = GET_CODE (x);
02921 switch (code)
02922 {
02923 case REG:
02924 if (REGNO (x) < 16)
02925 return (((1 << HARD_REGNO_NREGS (0, GET_MODE (x))) - 1)
02926 << (REGNO (x) + is_dest));
02927 return 0;
02928 case SUBREG:
02929 {
02930 rtx y = SUBREG_REG (x);
02931
02932 if (GET_CODE (y) != REG)
02933 break;
02934 if (REGNO (y) < 16)
02935 return (((1 << HARD_REGNO_NREGS (0, GET_MODE (x))) - 1)
02936 << (REGNO (y) +
02937 subreg_regno_offset (REGNO (y),
02938 GET_MODE (y),
02939 SUBREG_BYTE (x),
02940 GET_MODE (x)) + is_dest));
02941 return 0;
02942 }
02943 case SET:
02944 return regs_used (SET_SRC (x), 0) | regs_used (SET_DEST (x), 16);
02945 case RETURN:
02946
02947 return 0x00ffff00;
02948 case CLOBBER:
02949 is_dest = 1;
02950 break;
02951 case MEM:
02952 is_dest = 0;
02953 break;
02954 case CALL:
02955 used |= 0x00ff00f0;
02956 break;
02957 default:
02958 break;
02959 }
02960
02961 fmt = GET_RTX_FORMAT (code);
02962
02963 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
02964 {
02965 if (fmt[i] == 'E')
02966 {
02967 register int j;
02968 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
02969 used |= regs_used (XVECEXP (x, i, j), is_dest);
02970 }
02971 else if (fmt[i] == 'e')
02972 used |= regs_used (XEXP (x, i), is_dest);
02973 }
02974 return used;
02975 }
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987 static rtx
02988 gen_block_redirect (jump, addr, need_block)
02989 rtx jump;
02990 int addr, need_block;
02991 {
02992 int dead = 0;
02993 rtx prev = prev_nonnote_insn (jump);
02994 rtx dest;
02995
02996
02997 if (prev && GET_CODE (prev) == INSN && ! INSN_DELETED_P (prev))
02998 {
02999 if (INSN_CODE (prev) == CODE_FOR_indirect_jump_scratch)
03000 return prev;
03001 if (GET_CODE (PATTERN (prev)) == USE
03002 || GET_CODE (PATTERN (prev)) == CLOBBER
03003 || get_attr_in_delay_slot (prev) == IN_DELAY_SLOT_YES)
03004 prev = jump;
03005 else if ((need_block &= ~1) < 0)
03006 return prev;
03007 else if (recog_memoized (prev) == CODE_FOR_block_branch_redirect)
03008 need_block = 0;
03009 }
03010
03011
03012 dest = XEXP (SET_SRC (PATTERN (jump)), 0);
03013
03014 if (optimize
03015 && (INSN_ADDRESSES (INSN_UID (dest)) - addr + (unsigned) 4092
03016 > 4092 + 4098))
03017 {
03018 rtx scan;
03019
03020
03021 unsigned try = 0x7fff, used;
03022 int jump_left = flag_expensive_optimizations + 1;
03023
03024
03025
03026
03027
03028 for (scan = jump; (scan = PREV_INSN (scan)); )
03029 {
03030 enum rtx_code code;
03031
03032 if (INSN_DELETED_P (scan))
03033 continue;
03034 code = GET_CODE (scan);
03035 if (code == CODE_LABEL || code == JUMP_INSN)
03036 break;
03037 if (code == INSN
03038 && GET_CODE (PATTERN (scan)) != USE
03039 && GET_CODE (PATTERN (scan)) != CLOBBER
03040 && get_attr_in_delay_slot (scan) == IN_DELAY_SLOT_YES)
03041 {
03042 try &= ~regs_used (PATTERN (scan), 0);
03043 break;
03044 }
03045 }
03046 for (used = dead = 0, scan = JUMP_LABEL (jump);
03047 (scan = NEXT_INSN (scan)); )
03048 {
03049 enum rtx_code code;
03050
03051 if (INSN_DELETED_P (scan))
03052 continue;
03053 code = GET_CODE (scan);
03054 if (GET_RTX_CLASS (code) == 'i')
03055 {
03056 used |= regs_used (PATTERN (scan), 0);
03057 if (code == CALL_INSN)
03058 used |= regs_used (CALL_INSN_FUNCTION_USAGE (scan), 0);
03059 dead |= (used >> 16) & ~used;
03060 if (dead & try)
03061 {
03062 dead &= try;
03063 break;
03064 }
03065 if (code == JUMP_INSN)
03066 {
03067 if (jump_left-- && simplejump_p (scan))
03068 scan = JUMP_LABEL (scan);
03069 else
03070 break;
03071 }
03072 }
03073 }
03074
03075
03076 dead &= 0x7fff;
03077 }
03078
03079
03080
03081
03082
03083 else if (optimize && need_block >= 0)
03084 {
03085 rtx next = next_active_insn (next_active_insn (dest));
03086 if (next && GET_CODE (next) == JUMP_INSN
03087 && GET_CODE (PATTERN (next)) == SET
03088 && recog_memoized (next) == CODE_FOR_jump)
03089 {
03090 dest = JUMP_LABEL (next);
03091 if (dest
03092 && (INSN_ADDRESSES (INSN_UID (dest)) - addr + (unsigned) 4092
03093 > 4092 + 4098))
03094 gen_block_redirect (next, INSN_ADDRESSES (INSN_UID (next)), -1);
03095 }
03096 }
03097
03098 if (dead)
03099 {
03100 rtx reg = gen_rtx_REG (SImode, exact_log2 (dead & -dead));
03101
03102
03103
03104
03105
03106
03107
03108
03109 rtx insn = emit_insn_before (gen_indirect_jump_scratch
03110 (reg, GEN_INT (INSN_UID (JUMP_LABEL (jump))))
03111 , jump);
03112 INSN_CODE (insn) = CODE_FOR_indirect_jump_scratch;
03113 return insn;
03114 }
03115 else if (need_block)
03116
03117
03118 return emit_insn_before (gen_block_branch_redirect
03119 (GEN_INT (INSN_UID (XEXP (SET_SRC (PATTERN (jump)), 0))))
03120 , jump);
03121 return prev;
03122 }
03123
03124 #define CONDJUMP_MIN -252
03125 #define CONDJUMP_MAX 262
03126 struct far_branch
03127 {
03128
03129
03130 rtx near_label;
03131
03132
03133 rtx insert_place;
03134
03135 rtx far_label;
03136 struct far_branch *prev;
03137
03138
03139 int address;
03140 };
03141
03142 static void gen_far_branch PARAMS ((struct far_branch *));
03143 enum mdep_reorg_phase_e mdep_reorg_phase;
03144 static void
03145 gen_far_branch (bp)
03146 struct far_branch *bp;
03147 {
03148 rtx insn = bp->insert_place;
03149 rtx jump;
03150 rtx label = gen_label_rtx ();
03151
03152 emit_label_after (label, insn);
03153 if (bp->far_label)
03154 {
03155 jump = emit_jump_insn_after (gen_jump (bp->far_label), insn);
03156 LABEL_NUSES (bp->far_label)++;
03157 }
03158 else
03159 jump = emit_jump_insn_after (gen_return (), insn);
03160
03161
03162
03163
03164
03165 if (optimize)
03166 emit_barrier_after (jump);
03167 emit_label_after (bp->near_label, insn);
03168 JUMP_LABEL (jump) = bp->far_label;
03169 if (! invert_jump (insn, label, 1))
03170 abort ();
03171
03172 gen_block_redirect (jump, bp->address += 2, 2);
03173 }
03174
03175
03176 void
03177 fixup_addr_diff_vecs (first)
03178 rtx first;
03179 {
03180 rtx insn;
03181
03182 for (insn = first; insn; insn = NEXT_INSN (insn))
03183 {
03184 rtx vec_lab, pat, prev, prevpat, x, braf_label;
03185
03186 if (GET_CODE (insn) != JUMP_INSN
03187 || GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC)
03188 continue;
03189 pat = PATTERN (insn);
03190 vec_lab = XEXP (XEXP (pat, 0), 0);
03191
03192
03193 for (prev = vec_lab; ; prev = PREV_INSN (prev))
03194 {
03195 if (GET_CODE (prev) != JUMP_INSN)
03196 continue;
03197 prevpat = PATTERN (prev);
03198 if (GET_CODE (prevpat) != PARALLEL || XVECLEN (prevpat, 0) != 2)
03199 continue;
03200 x = XVECEXP (prevpat, 0, 1);
03201 if (GET_CODE (x) != USE)
03202 continue;
03203 x = XEXP (x, 0);
03204 if (GET_CODE (x) == LABEL_REF && XEXP (x, 0) == vec_lab)
03205 break;
03206 }
03207
03208
03209
03210 braf_label = XEXP (XEXP (SET_SRC (XVECEXP (prevpat, 0, 0)), 1), 0);
03211 emit_label_after (braf_label, prev);
03212
03213
03214
03215 XEXP (XEXP (pat, 0), 0) = braf_label;
03216 }
03217 }
03218
03219
03220
03221 int
03222 barrier_align (barrier_or_label)
03223 rtx barrier_or_label;
03224 {
03225 rtx next = next_real_insn (barrier_or_label), pat, prev;
03226 int slot, credit, jump_to_next;
03227
03228 if (! next)
03229 return 0;
03230
03231 pat = PATTERN (next);
03232
03233 if (GET_CODE (pat) == ADDR_DIFF_VEC)
03234 return 2;
03235
03236 if (GET_CODE (pat) == UNSPEC_VOLATILE && XINT (pat, 1) == UNSPECV_ALIGN)
03237
03238 return 0;
03239
03240 prev = prev_real_insn (barrier_or_label);
03241 if (GET_CODE (PATTERN (prev)) == ADDR_DIFF_VEC)
03242 {
03243 pat = PATTERN (prev);
03244
03245
03246 return ((TARGET_SMALLCODE
03247 || (XVECLEN (pat, 1) * GET_MODE_SIZE (GET_MODE (pat))
03248 <= (unsigned)1 << (CACHE_LOG - 2)))
03249 ? 1 << TARGET_SHMEDIA : CACHE_LOG);
03250 }
03251
03252 if (TARGET_SMALLCODE)
03253 return 0;
03254
03255 if (! TARGET_SH2 || ! optimize)
03256 return CACHE_LOG;
03257
03258
03259
03260
03261 if (mdep_reorg_phase > SH_FIXUP_PCLOAD)
03262 {
03263
03264
03265
03266
03267
03268
03269
03270
03271
03272
03273
03274
03275
03276
03277
03278 prev = prev_real_insn (prev);
03279
03280 for (slot = 2, credit = (1 << (CACHE_LOG - 2)) + 2;
03281 credit >= 0 && prev && GET_CODE (prev) == INSN;
03282 prev = prev_real_insn (prev))
03283 {
03284 jump_to_next = 0;
03285 if (GET_CODE (PATTERN (prev)) == USE
03286 || GET_CODE (PATTERN (prev)) == CLOBBER)
03287 continue;
03288 if (GET_CODE (PATTERN (prev)) == SEQUENCE)
03289 {
03290 prev = XVECEXP (PATTERN (prev), 0, 1);
03291 if (INSN_UID (prev) == INSN_UID (next))
03292 {
03293
03294 jump_to_next = 1;
03295 continue;
03296 }
03297 }
03298
03299 if (slot &&
03300 get_attr_in_delay_slot (prev) == IN_DELAY_SLOT_YES)
03301 slot = 0;
03302 credit -= get_attr_length (prev);
03303 }
03304 if (prev
03305 && GET_CODE (prev) == JUMP_INSN
03306 && JUMP_LABEL (prev))
03307 {
03308 rtx x;
03309 if (jump_to_next
03310 || next_real_insn (JUMP_LABEL (prev)) == next
03311
03312
03313
03314 || JUMP_LABEL (prev) == next_nonnote_insn (next)
03315
03316
03317
03318 || (x = (NEXT_INSN (NEXT_INSN (PREV_INSN (prev)))),
03319 (INSN_P (x)
03320 && (INSN_CODE (x) == CODE_FOR_block_branch_redirect
03321 || INSN_CODE (x) == CODE_FOR_indirect_jump_scratch))))
03322 {
03323 rtx pat = PATTERN (prev);
03324 if (GET_CODE (pat) == PARALLEL)
03325 pat = XVECEXP (pat, 0, 0);
03326 if (credit - slot >= (GET_CODE (SET_SRC (pat)) == PC ? 2 : 0))
03327 return 0;
03328 }
03329 }
03330 }
03331
03332 return CACHE_LOG;
03333 }
03334
03335
03336
03337
03338
03339
03340
03341 int
03342 sh_loop_align (label)
03343 rtx label;
03344 {
03345 rtx next = label;
03346
03347 do
03348 next = next_nonnote_insn (next);
03349 while (next && GET_CODE (next) == CODE_LABEL);
03350
03351 if (! next
03352 || ! INSN_P (next)
03353 || GET_CODE (PATTERN (next)) == ADDR_DIFF_VEC
03354 || recog_memoized (next) == CODE_FOR_consttable_2)
03355 return 0;
03356
03357 if (TARGET_SH5)
03358 return 3;
03359
03360 return 2;
03361 }
03362
03363
03364
03365
03366
03367
03368 void
03369 machine_dependent_reorg (first)
03370 rtx first;
03371 {
03372 rtx insn, mova;
03373 int num_mova;
03374 rtx r0_rtx = gen_rtx_REG (Pmode, 0);
03375 rtx r0_inc_rtx = gen_rtx_POST_INC (Pmode, r0_rtx);
03376
03377
03378
03379
03380 if (! optimize)
03381 split_all_insns_noflow ();
03382
03383 if (TARGET_SHMEDIA)
03384 return;
03385
03386
03387
03388
03389
03390
03391
03392 mdep_reorg_phase = SH_INSERT_USES_LABELS;
03393 if (TARGET_RELAX)
03394 {
03395
03396
03397
03398
03399
03400
03401 for (insn = first; insn; insn = NEXT_INSN (insn))
03402 {
03403 if (INSN_P (insn))
03404 {
03405 rtx note;
03406
03407 while ((note = find_reg_note (insn, REG_LABEL, NULL_RTX)) != 0)
03408 remove_note (insn, note);
03409 }
03410 }
03411
03412 for (insn = first; insn; insn = NEXT_INSN (insn))
03413 {
03414 rtx pattern, reg, link, set, scan, dies, label;
03415 int rescan = 0, foundinsn = 0;
03416
03417 if (GET_CODE (insn) == CALL_INSN)
03418 {
03419 pattern = PATTERN (insn);
03420
03421 if (GET_CODE (pattern) == PARALLEL)
03422 pattern = XVECEXP (pattern, 0, 0);
03423 if (GET_CODE (pattern) == SET)
03424 pattern = SET_SRC (pattern);
03425
03426 if (GET_CODE (pattern) != CALL
03427 || GET_CODE (XEXP (pattern, 0)) != MEM)
03428 continue;
03429
03430 reg = XEXP (XEXP (pattern, 0), 0);
03431 }
03432 else
03433 {
03434 reg = sfunc_uses_reg (insn);
03435 if (! reg)
03436 continue;
03437 }
03438
03439 if (GET_CODE (reg) != REG)
03440 continue;
03441
03442
03443
03444
03445
03446
03447 for (link = LOG_LINKS (insn); link; link = XEXP (link, 1))
03448 {
03449 if (REG_NOTE_KIND (link) != 0)
03450 continue;
03451 set = single_set (XEXP (link, 0));
03452 if (set && rtx_equal_p (reg, SET_DEST (set)))
03453 {
03454 link = XEXP (link, 0);
03455 break;
03456 }
03457 }
03458
03459 if (! link)
03460 {
03461
03462
03463
03464 for (scan = PREV_INSN (insn);
03465 scan && GET_CODE (scan) != CODE_LABEL;
03466 scan = PREV_INSN (scan))
03467 {
03468 if (! INSN_P (scan))
03469 continue;
03470
03471 if (! reg_mentioned_p (reg, scan))
03472 continue;
03473
03474 if (noncall_uses_reg (reg, scan, &set))
03475 break;
03476
03477 if (set)
03478 {
03479 link = scan;
03480 break;
03481 }
03482 }
03483 }
03484
03485 if (! link)
03486 continue;
03487
03488
03489
03490
03491
03492
03493
03494 if (GET_CODE (SET_SRC (set)) != SYMBOL_REF
03495 && GET_CODE (SET_SRC (set)) != LABEL_REF)
03496 continue;
03497
03498
03499
03500
03501
03502
03503
03504
03505
03506 dies = NULL_RTX;
03507 for (scan = NEXT_INSN (link); scan; scan = NEXT_INSN (scan))
03508 {
03509 rtx scanset;
03510
03511
03512
03513
03514
03515
03516
03517
03518 if (GET_CODE (scan) == CODE_LABEL && ! foundinsn)
03519 break;
03520
03521 if (! INSN_P (scan))
03522 continue;
03523
03524
03525
03526
03527
03528 if (GET_CODE (scan) == JUMP_INSN)
03529 break;
03530
03531 if (! reg_mentioned_p (reg, scan))
03532 continue;
03533
03534 if (noncall_uses_reg (reg, scan, &scanset))
03535 break;
03536
03537 if (scan == insn)
03538 foundinsn = 1;
03539
03540 if (scan != insn
03541 && (GET_CODE (scan) == CALL_INSN || sfunc_uses_reg (scan)))
03542 {
03543
03544
03545
03546 rescan = 1;
03547 }
03548
03549
03550
03551
03552
03553
03554
03555
03556
03557
03558
03559
03560
03561
03562
03563
03564
03565
03566 if (foundinsn
03567 && (scanset
03568 || find_reg_note (scan, REG_DEAD, reg)))
03569 {
03570 dies = scan;
03571 break;
03572 }
03573 }
03574
03575 if (! dies)
03576 {
03577
03578
03579 continue;
03580 }
03581
03582
03583
03584
03585
03586
03587
03588 label = gen_label_rtx ();
03589 REG_NOTES (link) = gen_rtx_INSN_LIST (REG_LABEL, label,
03590 REG_NOTES (link));
03591 REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, label,
03592 REG_NOTES (insn));
03593 if (rescan)
03594 {
03595 scan = link;
03596 do
03597 {
03598 rtx reg2;
03599
03600 scan = NEXT_INSN (scan);
03601 if (scan != insn
03602 && ((GET_CODE (scan) == CALL_INSN
03603 && reg_mentioned_p (reg, scan))
03604 || ((reg2 = sfunc_uses_reg (scan))
03605 && REGNO (reg2) == REGNO (reg))))
03606 REG_NOTES (scan)
03607 = gen_rtx_INSN_LIST (REG_LABEL, label, REG_NOTES (scan));
03608 }
03609 while (scan != dies);
03610 }
03611 }
03612 }
03613
03614 if (TARGET_SH2)
03615 fixup_addr_diff_vecs (first);
03616
03617 if (optimize)
03618 {
03619 mdep_reorg_phase = SH_SHORTEN_BRANCHES0;
03620 shorten_branches (first);
03621 }
03622
03623
03624
03625 mdep_reorg_phase = SH_FIXUP_PCLOAD;
03626 for (insn = first, num_mova = 0; insn; insn = NEXT_INSN (insn))
03627 {
03628 if (mova_p (insn))
03629 {
03630 if (! num_mova++)
03631 mova = insn;
03632 }
03633 else if (GET_CODE (insn) == JUMP_INSN
03634 && GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
03635 && num_mova)
03636 {
03637 rtx scan;
03638 int total;
03639
03640 num_mova--;
03641
03642
03643
03644 for (scan = mova, total = 0; scan != insn; scan = NEXT_INSN (scan))
03645 total += get_attr_length (scan);
03646
03647
03648
03649
03650
03651 if (total > 1022)
03652 {
03653
03654
03655 SET_SRC (PATTERN (mova))
03656 = XVECEXP (SET_SRC (PATTERN (mova)), 0, 0);
03657 INSN_CODE (mova) = -1;
03658 insn = mova;
03659 }
03660 }
03661 if (broken_move (insn))
03662 {
03663 rtx scan;
03664
03665
03666 rtx barrier = find_barrier (num_mova, mova, insn);
03667 rtx last_float_move, last_float = 0, *last_float_addr;
03668 int may_need_align = 1;
03669
03670 if (num_mova && ! mova_p (mova))
03671 {
03672
03673
03674 insn = mova;
03675 num_mova = 0;
03676 }
03677
03678 for (scan = insn; scan != barrier; scan = NEXT_INSN (scan))
03679 {
03680 if (GET_CODE (scan) == CODE_LABEL)
03681 last_float = 0;
03682 if (broken_move (scan))
03683 {
03684 rtx *patp = &PATTERN (scan), pat = *patp;
03685 rtx src, dst;
03686 rtx lab;
03687 rtx newsrc;
03688 enum machine_mode mode;
03689
03690 if (GET_CODE (pat) == PARALLEL)
03691 patp = &XVECEXP (pat, 0, 0), pat = *patp;
03692 src = SET_SRC (pat);
03693 dst = SET_DEST (pat);
03694 mode = GET_MODE (dst);
03695
03696 if (mode == SImode && hi_const (src)
03697 && REGNO (dst) != FPUL_REG)
03698 {
03699 int offset = 0;
03700
03701 mode = HImode;
03702 while (GET_CODE (dst) == SUBREG)
03703 {
03704 offset += subreg_regno_offset (REGNO (SUBREG_REG (dst)),
03705 GET_MODE (SUBREG_REG (dst)),
03706 SUBREG_BYTE (dst),
03707 GET_MODE (dst));
03708 dst = SUBREG_REG (dst);
03709 }
03710 dst = gen_rtx_REG (HImode, REGNO (dst) + offset);
03711 }
03712
03713 if (GET_CODE (dst) == REG && FP_ANY_REGISTER_P (REGNO (dst)))
03714 {
03715
03716 rtx clobber = XVECEXP (PATTERN (scan), 0,
03717 XVECLEN (PATTERN (scan), 0) - 1);
03718
03719 if (GET_CODE (clobber) != CLOBBER
03720 || ! rtx_equal_p (XEXP (clobber, 0), r0_rtx))
03721 abort ();
03722
03723 if (last_float
03724 && reg_set_between_p (r0_rtx, last_float_move, scan))
03725 last_float = 0;
03726 if (TARGET_SHCOMPACT)
03727 {
03728
03729
03730
03731
03732 if (GET_MODE_SIZE (mode) == 4)
03733 {
03734 if (last_float && may_need_align)
03735 last_float = 0;
03736 may_need_align = 0;
03737 }
03738 if (last_float
03739 && (GET_MODE_SIZE (GET_MODE (last_float))
03740 != GET_MODE_SIZE (mode)))
03741 {
03742 last_float = 0;
03743 if (GET_MODE_SIZE (mode) == 4)
03744 may_need_align = 1;
03745 }
03746 }
03747 lab = add_constant (src, mode, last_float);
03748 if (lab)
03749 emit_insn_before (gen_mova (lab), scan);
03750 else
03751 {
03752
03753
03754
03755
03756
03757 rtx note
03758 = find_regno_note (last_float_move, REG_UNUSED, 0);
03759
03760
03761
03762 if (note)
03763 PUT_MODE (note, REG_INC);
03764
03765 *last_float_addr = r0_inc_rtx;
03766 }
03767 last_float_move = scan;
03768 last_float = src;
03769 newsrc = gen_rtx (MEM, mode,
03770 (((TARGET_SH4 && ! TARGET_FMOVD)
03771 || REGNO (dst) == FPUL_REG)
03772 ? r0_inc_rtx
03773 : r0_rtx));
03774 last_float_addr = &XEXP (newsrc, 0);
03775
03776
03777 XEXP (clobber, 0) = gen_rtx_SCRATCH (Pmode);
03778 }
03779
03780 else if (GET_CODE (src) == UNSPEC
03781 && XINT (src, 1) == UNSPEC_MOVA
03782 && GET_CODE (XVECEXP (src, 0, 0)) == CONST)
03783 {
03784 lab = add_constant (XVECEXP (src, 0, 0), mode, 0);
03785 newsrc = gen_rtx_LABEL_REF (VOIDmode, lab);
03786 newsrc = gen_rtx_UNSPEC (VOIDmode,
03787 gen_rtvec (1, newsrc),
03788 UNSPEC_MOVA);
03789 }
03790 else
03791 {
03792 lab = add_constant (src, mode, 0);
03793 newsrc = gen_rtx_MEM (mode,
03794 gen_rtx_LABEL_REF (VOIDmode, lab));
03795 }
03796 RTX_UNCHANGING_P (newsrc) = 1;
03797 *patp = gen_rtx_SET (VOIDmode, dst, newsrc);
03798 INSN_CODE (scan) = -1;
03799 }
03800 }
03801 dump_table (barrier);
03802 insn = barrier;
03803 }
03804 }
03805
03806 mdep_reorg_phase = SH_SHORTEN_BRANCHES1;
03807 INSN_ADDRESSES_FREE ();
03808 split_branches (first);
03809
03810
03811
03812
03813
03814 if (flag_delayed_branch)
03815 {
03816 for (insn = first; insn; insn = NEXT_INSN (insn))
03817 {
03818 rtx reg = sfunc_uses_reg (insn);
03819
03820 if (! reg)
03821 continue;
03822 emit_insn_before (gen_use_sfunc_addr (reg), insn);
03823 }
03824 }
03825 #if 0
03826
03827
03828
03829
03830 if (TARGET_SH4)
03831 REG_USERVAR_P (get_fpscr_rtx ()) = 0;
03832 #endif
03833 mdep_reorg_phase = SH_AFTER_MDEP_REORG;
03834 }
03835
03836 int
03837 get_dest_uid (label, max_uid)
03838 rtx label;
03839 int max_uid;
03840 {
03841 rtx dest = next_real_insn (label);
03842 int dest_uid;
03843 if (! dest)
03844
03845 return 0;
03846 dest_uid = INSN_UID (dest);
03847
03848
03849
03850
03851 while (dest_uid >= max_uid)
03852 {
03853 dest = NEXT_INSN (dest);
03854 dest_uid = INSN_UID (dest);
03855 }
03856 if (GET_CODE (dest) == JUMP_INSN && GET_CODE (PATTERN (dest)) == RETURN)
03857 return 0;
03858 return dest_uid;
03859 }
03860
03861
03862
03863
03864
03865
03866
03867 static void
03868 split_branches (first)
03869 rtx first;
03870 {
03871 rtx insn;
03872 struct far_branch **uid_branch, *far_branch_list = 0;
03873 int max_uid = get_max_uid ();
03874
03875
03876 shorten_branches (first);
03877
03878 uid_branch = (struct far_branch **) alloca (max_uid * sizeof *uid_branch);
03879 memset ((char *) uid_branch, 0, max_uid * sizeof *uid_branch);
03880
03881 for (insn = first; insn; insn = NEXT_INSN (insn))
03882 if (! INSN_P (insn))
03883 continue;
03884 else if (INSN_DELETED_P (insn))
03885 {
03886
03887
03888 PUT_CODE (insn, NOTE);
03889 NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
03890 NOTE_SOURCE_FILE (insn) = 0;
03891 }
03892 else if (GET_CODE (insn) == JUMP_INSN
03893
03894 && (GET_CODE (PATTERN (insn)) == SET
03895 || GET_CODE (PATTERN (insn)) == RETURN))
03896 {
03897 enum attr_type type = get_attr_type (insn);
03898 if (type == TYPE_CBRANCH)
03899 {
03900 rtx next, beyond;
03901
03902 if (get_attr_length (insn) > 4)
03903 {
03904 rtx src = SET_SRC (PATTERN (insn));
03905 rtx olabel = XEXP (XEXP (src, 1), 0);
03906 int addr = INSN_ADDRESSES (INSN_UID (insn));
03907 rtx label = 0;
03908 int dest_uid = get_dest_uid (olabel, max_uid);
03909 struct far_branch *bp = uid_branch[dest_uid];
03910
03911
03912
03913
03914
03915
03916
03917 if (! optimize)
03918 {
03919 JUMP_LABEL (insn) = olabel;
03920 LABEL_NUSES (olabel)++;
03921 }
03922 if (! bp)
03923 {
03924 bp = (struct far_branch *) alloca (sizeof *bp);
03925 uid_branch[dest_uid] = bp;
03926 bp->prev = far_branch_list;
03927 far_branch_list = bp;
03928 bp->far_label
03929 = XEXP (XEXP (SET_SRC (PATTERN (insn)), 1), 0);
03930 LABEL_NUSES (bp->far_label)++;
03931 }
03932 else
03933 {
03934 label = bp->near_label;
03935 if (! label && bp->address - addr >= CONDJUMP_MIN)
03936 {
03937 rtx block = bp->insert_place;
03938
03939 if (GET_CODE (PATTERN (block)) == RETURN)
03940 block = PREV_INSN (block);
03941 else
03942 block = gen_block_redirect (block,
03943 bp->address, 2);
03944 label = emit_label_after (gen_label_rtx (),
03945 PREV_INSN (block));
03946 bp->near_label = label;
03947 }
03948 else if (label && ! NEXT_INSN (label))
03949 {
03950 if (addr + 2 - bp->address <= CONDJUMP_MAX)
03951 bp->insert_place = insn;
03952 else
03953 gen_far_branch (bp);
03954 }
03955 }
03956 if (! label
03957 || (NEXT_INSN (label) && bp->address - addr < CONDJUMP_MIN))
03958 {
03959 bp->near_label = label = gen_label_rtx ();
03960 bp->insert_place = insn;
03961 bp->address = addr;
03962 }
03963 if (! redirect_jump (insn, label, 1))
03964 abort ();
03965 }
03966 else
03967 {
03968
03969
03970
03971
03972
03973
03974
03975 beyond
03976 = next_active_insn (XEXP (XEXP (SET_SRC (PATTERN (insn)), 1),
03977 0));
03978
03979 if (beyond
03980 && (GET_CODE (beyond) == JUMP_INSN
03981 || ((beyond = next_active_insn (beyond))
03982 && GET_CODE (beyond) == JUMP_INSN))
03983 && GET_CODE (PATTERN (beyond)) == SET
03984 && recog_memoized (beyond) == CODE_FOR_jump
03985 && ((INSN_ADDRESSES
03986 (INSN_UID (XEXP (SET_SRC (PATTERN (beyond)), 0)))
03987 - INSN_ADDRESSES (INSN_UID (insn)) + (unsigned) 252)
03988 > 252 + 258 + 2))
03989 gen_block_redirect (beyond,
03990 INSN_ADDRESSES (INSN_UID (beyond)), 1);
03991 }
03992
03993 next = next_active_insn (insn);
03994
03995 if ((GET_CODE (next) == JUMP_INSN
03996 || GET_CODE (next = next_active_insn (next)) == JUMP_INSN)
03997 && GET_CODE (PATTERN (next)) == SET
03998 && recog_memoized (next) == CODE_FOR_jump
03999 && ((INSN_ADDRESSES
04000 (INSN_UID (XEXP (SET_SRC (PATTERN (next)), 0)))
04001 - INSN_ADDRESSES (INSN_UID (insn)) + (unsigned) 252)
04002 > 252 + 258 + 2))
04003 gen_block_redirect (next, INSN_ADDRESSES (INSN_UID (next)), 1);
04004 }
04005 else if (type == TYPE_JUMP || type == TYPE_RETURN)
04006 {
04007 int addr = INSN_ADDRESSES (INSN_UID (insn));
04008 rtx far_label = 0;
04009 int dest_uid = 0;
04010 struct far_branch *bp;
04011
04012 if (type == TYPE_JUMP)
04013 {
04014 far_label = XEXP (SET_SRC (PATTERN (insn)), 0);
04015 dest_uid = get_dest_uid (far_label, max_uid);
04016 if (! dest_uid)
04017 {
04018
04019
04020 if (! NEXT_INSN (far_label))
04021 continue;
04022
04023 if (! optimize)
04024 {
04025 JUMP_LABEL (insn) = far_label;
04026 LABEL_NUSES (far_label)++;
04027 }
04028 redirect_jump (insn, NULL_RTX, 1);
04029 far_label = 0;
04030 }
04031 }
04032 bp = uid_branch[dest_uid];
04033 if (! bp)
04034 {
04035 bp = (struct far_branch *) alloca (sizeof *bp);
04036 uid_branch[dest_uid] = bp;
04037 bp->prev = far_branch_list;
04038 far_branch_list = bp;
04039 bp->near_label = 0;
04040 bp->far_label = far_label;
04041 if (far_label)
04042 LABEL_NUSES (far_label)++;
04043 }
04044 else if (bp->near_label && ! NEXT_INSN (bp->near_label))
04045 if (addr - bp->address <= CONDJUMP_MAX)
04046 emit_label_after (bp->near_label, PREV_INSN (insn));
04047 else
04048 {
04049 gen_far_branch (bp);
04050 bp->near_label = 0;
04051 }
04052 else
04053 bp->near_label = 0;
04054 bp->address = addr;
04055 bp->insert_place = insn;
04056 if (! far_label)
04057 emit_insn_before (gen_block_branch_redirect (const0_rtx), insn);
04058 else
04059 gen_block_redirect (insn, addr, bp->near_label ? 2 : 0);
04060 }
04061 }
04062
04063
04064 while (far_branch_list)
04065 {
04066 if (far_branch_list->near_label
04067 && ! NEXT_INSN (far_branch_list->near_label))
04068 gen_far_branch (far_branch_list);
04069 if (optimize
04070 && far_branch_list->far_label
04071 && ! --LABEL_NUSES (far_branch_list->far_label))
04072 delete_insn (far_branch_list->far_label);
04073 far_branch_list = far_branch_list->prev;
04074 }
04075
04076
04077
04078 init_insn_lengths ();
04079 }
04080
04081
04082
04083
04084
04085
04086
04087
04088
04089
04090
04091
04092
04093
04094
04095 void
04096 final_prescan_insn (insn, opvec, noperands)
04097 rtx insn;
04098 rtx *opvec ATTRIBUTE_UNUSED;
04099 int noperands ATTRIBUTE_UNUSED;
04100 {
04101 if (TARGET_DUMPISIZE)
04102 fprintf (asm_out_file, "\n! at %04x\n", INSN_ADDRESSES (INSN_UID (insn)));
04103
04104 if (TARGET_RELAX)
04105 {
04106 rtx note;
04107
04108 note = find_reg_note (insn, REG_LABEL, NULL_RTX);
04109 if (note)
04110 {
04111 rtx pattern;
04112
04113 pattern = PATTERN (insn);
04114 if (GET_CODE (pattern) == PARALLEL)
04115 pattern = XVECEXP (pattern, 0, 0);
04116 if (GET_CODE (pattern) == CALL
04117 || (GET_CODE (pattern) == SET
04118 && (GET_CODE (SET_SRC (pattern)) == CALL
04119 || get_attr_type (insn) == TYPE_SFUNC)))
04120 asm_fprintf (asm_out_file, "\t.uses %LL%d\n",
04121 CODE_LABEL_NUMBER (XEXP (note, 0)));
04122 else if (GET_CODE (pattern) == SET)
04123 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
04124 CODE_LABEL_NUMBER (XEXP (note, 0)));
04125 else
04126 abort ();
04127 }
04128 }
04129 }
04130
04131
04132
04133
04134 const char *
04135 output_jump_label_table ()
04136 {
04137 int i;
04138
04139 if (pool_size)
04140 {
04141 fprintf (asm_out_file, "\t.align 2\n");
04142 for (i = 0; i < pool_size; i++)
04143 {
04144 pool_node *p = &pool_vector[i];
04145
04146 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "L",
04147 CODE_LABEL_NUMBER (p->label));
04148 output_asm_insn (".long %O0", &p->value);
04149 }
04150 pool_size = 0;
04151 }
04152
04153 return "";
04154 }
04155
04156
04157
04158
04159
04160
04161
04162
04163
04164
04165
04166
04167
04168
04169
04170
04171
04172
04173
04174
04175
04176
04177
04178 static int extra_push;
04179
04180
04181
04182
04183
04184 static void
04185 output_stack_adjust (size, reg, temp)
04186 int size;
04187 rtx reg;
04188 int temp;
04189 {
04190 if (size)
04191 {
04192 HOST_WIDE_INT align = STACK_BOUNDARY / BITS_PER_UNIT;
04193
04194 if (size % align)
04195 abort ();
04196
04197 if (CONST_OK_FOR_ADD (size))
04198 emit_insn (GEN_ADD3 (reg, reg, GEN_INT (size)));
04199
04200
04201
04202 else if (CONST_OK_FOR_ADD (size / 2 & -align)
04203 && CONST_OK_FOR_ADD (size - (size / 2 & -align)))
04204 {
04205 emit_insn (GEN_ADD3 (reg, reg, GEN_INT (size / 2 & -align)));
04206 emit_insn (GEN_ADD3 (reg, reg, GEN_INT (size - (size / 2 & -align))));
04207 }
04208 else
04209 {
04210 rtx const_reg;
04211
04212
04213
04214
04215 if (temp < 0)
04216 abort ();
04217 const_reg = gen_rtx_REG (GET_MODE (reg), temp);
04218
04219
04220
04221
04222 if (size < 0)
04223 {
04224 emit_insn (GEN_MOV (const_reg, GEN_INT (-size)));
04225 emit_insn (GEN_SUB3 (reg, reg, const_reg));
04226 }
04227 else
04228 {
04229 emit_insn (GEN_MOV (const_reg, GEN_INT (size)));
04230 emit_insn (GEN_ADD3 (reg, reg, const_reg));
04231 }
04232 }
04233 }
04234 }
04235
04236
04237
04238 static void
04239 push (rn)
04240 int rn;
04241 {
04242 rtx x;
04243 if (rn == FPUL_REG)
04244 x = gen_push_fpul ();
04245 else if (TARGET_SH4 && TARGET_FMOVD && ! TARGET_FPU_SINGLE
04246 && FP_OR_XD_REGISTER_P (rn))
04247 {
04248 if (FP_REGISTER_P (rn) && (rn - FIRST_FP_REG) & 1)
04249 return;
04250 x = gen_push_4 (gen_rtx_REG (DFmode, rn));
04251 }
04252 else if (TARGET_SH3E && FP_REGISTER_P (rn))
04253 x = gen_push_e (gen_rtx_REG (SFmode, rn));
04254 else
04255 x = gen_push (gen_rtx_REG (SImode, rn));
04256
04257 x = emit_insn (x);
04258 REG_NOTES (x)
04259 = gen_rtx_EXPR_LIST (REG_INC,
04260 gen_rtx_REG (SImode, STACK_POINTER_REGNUM), 0);
04261 }
04262
04263
04264
04265 static void
04266 pop (rn)
04267 int rn;
04268 {
04269 rtx x;
04270 if (rn == FPUL_REG)
04271 x = gen_pop_fpul ();
04272 else if (TARGET_SH4 && TARGET_FMOVD && ! TARGET_FPU_SINGLE
04273 && FP_OR_XD_REGISTER_P (rn))
04274 {
04275 if (FP_REGISTER_P (rn) && (rn - FIRST_FP_REG) & 1)
04276 return;
04277 x = gen_pop_4 (gen_rtx_REG (DFmode, rn));
04278 }
04279 else if (TARGET_SH3E && FP_REGISTER_P (rn))
04280 x = gen_pop_e (gen_rtx_REG (SFmode, rn));
04281 else
04282 x = gen_pop (gen_rtx_REG (SImode, rn));
04283
04284 x = emit_insn (x);
04285 REG_NOTES (x)
04286 = gen_rtx_EXPR_LIST (REG_INC,
04287 gen_rtx_REG (SImode, STACK_POINTER_REGNUM), 0);
04288 }
04289
04290
04291
04292 static void
04293 push_regs (mask)
04294 HOST_WIDE_INT *mask;
04295 {
04296 int i;
04297
04298
04299
04300
04301 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
04302 if (i != PR_REG && mask[i / 32] & (1 << (i % 32)))
04303 push (i);
04304 if (mask[PR_REG / 32] & (1 << (PR_REG % 32)))
04305 push (PR_REG);
04306 }
04307
04308
04309
04310
04311
04312
04313
04314
04315 static void
04316 calc_live_regs (count_ptr, live_regs_mask)
04317 int *count_ptr;
04318 HOST_WIDE_INT *live_regs_mask;
04319 {
04320 int reg;
04321 int count;
04322 int interrupt_handler;
04323 rtx pr_initial;
04324 int pr_live;
04325
04326 if ((lookup_attribute
04327 ("interrupt_handler",
04328 DECL_ATTRIBUTES (current_function_decl)))
04329 != NULL_TREE)
04330 interrupt_handler = 1;
04331 else
04332 interrupt_handler = 0;
04333
04334 for (count = 0; 32 * count < FIRST_PSEUDO_REGISTER; count++)
04335 live_regs_mask[count] = 0;
04336
04337 if (TARGET_SH4 && TARGET_FMOVD && TARGET_FPU_SINGLE)
04338 for (count = 0, reg = FIRST_FP_REG; reg <= LAST_FP_REG; reg += 2)
04339 if (regs_ever_live[reg] && regs_ever_live[reg+1]
04340 && (! call_used_regs[reg] || (interrupt_handler && ! pragma_trapa))
04341 && ++count > 2)
04342 {
04343 target_flags &= ~FPU_SINGLE_BIT;
04344 break;
04345 }
04346 pr_initial = has_hard_reg_initial_val (Pmode, PR_REG);
04347 pr_live = (pr_initial
04348 ? REGNO (pr_initial) != PR_REG
04349 : regs_ever_live[PR_REG]);
04350
04351
04352 if (TARGET_SHCOMPACT
04353 && ((current_function_args_info.call_cookie
04354 & ~ CALL_COOKIE_RET_TRAMP (1))
04355 || current_function_has_nonlocal_label))
04356 pr_live = 1;
04357 for (count = 0, reg = FIRST_PSEUDO_REGISTER - 1; reg >= 0; reg--)
04358 {
04359 if (reg == PR_REG
04360 ? pr_live
04361 : (interrupt_handler && ! pragma_trapa)
04362 ? (
04363 (regs_ever_live[reg]
04364 || (call_used_regs[reg]
04365 && (! fixed_regs[reg] || reg == MACH_REG || reg == MACL_REG)
04366 && pr_live))
04367 && reg != STACK_POINTER_REGNUM && reg != ARG_POINTER_REGNUM
04368 && reg != RETURN_ADDRESS_POINTER_REGNUM
04369 && reg != T_REG && reg != GBR_REG && reg != FPSCR_REG)
04370 : (
04371 regs_ever_live[reg] && ! call_used_regs[reg]))
04372 {
04373 live_regs_mask[reg / 32] |= 1 << (reg % 32);
04374 count += GET_MODE_SIZE (REGISTER_NATURAL_MODE (reg));
04375
04376 if ((TARGET_SH4 || TARGET_SH5) && TARGET_FMOVD
04377 && GET_MODE_CLASS (REGISTER_NATURAL_MODE (reg)) == MODE_FLOAT)
04378 {
04379 if (FP_REGISTER_P (reg))
04380 {
04381 if (! TARGET_FPU_SINGLE && ! regs_ever_live[reg ^ 1])
04382 {
04383 live_regs_mask[(reg ^ 1) / 32] |= 1 << ((reg ^ 1) % 32);
04384 count += GET_MODE_SIZE (REGISTER_NATURAL_MODE (reg ^ 1));
04385 }
04386 }
04387 else if (XD_REGISTER_P (reg))
04388 {
04389
04390 target_flags &= ~FPU_SINGLE_BIT;
04391 }
04392 }
04393 }
04394 }
04395
04396 *count_ptr = count;
04397 }
04398
04399
04400
04401
04402
04403
04404 static HOST_WIDE_INT
04405 rounded_frame_size (pushed)
04406 int pushed;
04407 {
04408 HOST_WIDE_INT size = get_frame_size ();
04409 HOST_WIDE_INT align = STACK_BOUNDARY / BITS_PER_UNIT;
04410
04411 return ((size + pushed + align - 1) & -align) - pushed;
04412 }
04413
04414
04415
04416
04417 int
04418 sh_media_register_for_return ()
04419 {
04420 int regno;
04421 int tr0_used;
04422
04423 if (! current_function_is_leaf)
04424 return -1;
04425
04426 tr0_used = flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM];
04427
04428 for (regno = FIRST_TARGET_REG + tr0_used; regno <= LAST_TARGET_REG; regno++)
04429 if (call_used_regs[regno] && ! regs_ever_live[regno])
04430 return regno;
04431
04432 return -1;
04433 }
04434
04435 void
04436 sh_expand_prologue ()
04437 {
04438 HOST_WIDE_INT live_regs_mask[(FIRST_PSEUDO_REGISTER + 31) / 32];
04439 int d, i;
04440 int d_rounding = 0;
04441 int save_flags = target_flags;
04442
04443 current_function_interrupt
04444 = lookup_attribute ("interrupt_handler",
04445 DECL_ATTRIBUTES (current_function_decl))
04446 != NULL_TREE;
04447
04448
04449
04450 output_stack_adjust (-current_function_pretend_args_size
04451 - current_function_args_info.stack_regs * 8,
04452 stack_pointer_rtx, TARGET_SH5 ? 0 : 1);
04453
04454 extra_push = 0;
04455
04456 if (TARGET_SHCOMPACT && flag_pic && current_function_args_info.call_cookie)
04457
04458
04459
04460
04461 regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
04462
04463 if (TARGET_SHCOMPACT
04464 && (current_function_args_info.call_cookie & ~ CALL_COOKIE_RET_TRAMP(1)))
04465 {
04466 int reg;
04467
04468
04469
04470
04471 for (reg = 0; reg < NPARM_REGS (SImode); reg++)
04472 if (CALL_COOKIE_STACKSEQ_GET (current_function_args_info.call_cookie)
04473 >= NPARM_REGS (SImode) - reg)
04474 for (; reg < NPARM_REGS (SImode); reg++)
04475 emit_insn (gen_shcompact_preserve_incoming_args
04476 (gen_rtx_REG (SImode, FIRST_PARM_REG + reg)));
04477 else if (CALL_COOKIE_INT_REG_GET
04478 (current_function_args_info.call_cookie, reg) == 1)
04479 emit_insn (gen_shcompact_preserve_incoming_args
04480 (gen_rtx_REG (SImode, FIRST_PARM_REG + reg)));
04481
04482 emit_move_insn (gen_rtx_REG (Pmode, MACL_REG),
04483 stack_pointer_rtx);
04484 emit_move_insn (gen_rtx_REG (SImode, R0_REG),
04485 GEN_INT (current_function_args_info.call_cookie));
04486 emit_move_insn (gen_rtx_REG (SImode, MACH_REG),
04487 gen_rtx_REG (SImode, R0_REG));
04488 }
04489 else if (TARGET_SHMEDIA)
04490 {
04491 int tr = sh_media_register_for_return ();
04492
04493 if (tr >= 0)
04494 {
04495 rtx insn = emit_move_insn (gen_rtx_REG (DImode, tr),
04496 gen_rtx_REG (DImode, PR_MEDIA_REG));
04497
04498
04499
04500 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
04501 const0_rtx,
04502 REG_NOTES (insn));
04503 }
04504 }
04505
04506
04507 if (current_function_varargs || current_function_stdarg)
04508 {
04509
04510 if (TARGET_SH1 && ! TARGET_SH3E && ! TARGET_SH5 && ! TARGET_HITACHI)
04511 {
04512
04513 for (i = 0; i < NPARM_REGS(SImode); i++)
04514 {
04515 int rn = NPARM_REGS(SImode) + FIRST_PARM_REG - i - 1;
04516 if (i >= (NPARM_REGS(SImode)
04517 - current_function_args_info.arg_count[(int) SH_ARG_INT]
04518 ))
04519 break;
04520 push (rn);
04521 extra_push += 4;
04522 }
04523 }
04524 }
04525
04526
04527 if (sp_switch)
04528 emit_insn (gen_sp_switch_1 ());
04529
04530 calc_live_regs (&d, live_regs_mask);
04531
04532
04533 if (target_flags != save_flags)
04534 emit_insn (gen_toggle_sz ());
04535
04536 if (TARGET_SH5)
04537 {
04538 int i;
04539 int offset;
04540 int align;
04541 rtx r0 = gen_rtx_REG (Pmode, R0_REG);
04542 int offset_in_r0 = -1;
04543 int sp_in_r0 = 0;
04544
04545 if (d % (STACK_BOUNDARY / BITS_PER_UNIT))
04546 d_rounding = ((STACK_BOUNDARY / BITS_PER_UNIT)
04547 - d % (STACK_BOUNDARY / BITS_PER_UNIT));
04548
04549 offset = d + d_rounding;
04550 output_stack_adjust (-offset, stack_pointer_rtx, 1);
04551
04552
04553
04554
04555
04556 for (align = 1; align >= 0; align--)
04557 for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
04558 if (live_regs_mask[i/32] & (1 << (i % 32)))
04559 {
04560 enum machine_mode mode = REGISTER_NATURAL_MODE (i);
04561 int reg = i;
04562 rtx reg_rtx, mem_rtx, pre_dec = NULL_RTX;
04563
04564 if (mode == SFmode && (i % 2) == 1
04565 && ! TARGET_FPU_SINGLE && FP_REGISTER_P (i)
04566 && (live_regs_mask[(i ^ 1) / 32] & (1 << ((i ^ 1) % 32))))
04567 {
04568 mode = DFmode;
04569 i--;
04570 reg--;
04571 }
04572
04573
04574
04575
04576 if ((GET_MODE_SIZE (mode) % (STACK_BOUNDARY / BITS_PER_UNIT)
04577 == 0) != align)
04578 continue;
04579
04580 offset -= GET_MODE_SIZE (mode);
04581
04582 reg_rtx = gen_rtx_REG (mode, reg);
04583
04584 mem_rtx = gen_rtx_MEM (mode,
04585 gen_rtx_PLUS (Pmode,
04586 stack_pointer_rtx,
04587 GEN_INT (offset)));
04588
04589 GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (mem_rtx, 0), try_pre_dec);
04590
04591 mem_rtx = NULL_RTX;
04592
04593 try_pre_dec:
04594 do
04595 if (HAVE_PRE_DECREMENT
04596 && (offset_in_r0 - offset == GET_MODE_SIZE (mode)
04597 || mem_rtx == NULL_RTX
04598 || i == PR_REG || SPECIAL_REGISTER_P (i)))
04599 {
04600 pre_dec = gen_rtx_MEM (mode,
04601 gen_rtx_PRE_DEC (Pmode, r0));
04602
04603 GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (pre_dec, 0),
04604 pre_dec_ok);
04605
04606 pre_dec = NULL_RTX;
04607
04608 break;
04609
04610 pre_dec_ok:
04611 mem_rtx = NULL_RTX;
04612 offset += GET_MODE_SIZE (mode);
04613 }
04614 while (0);
04615
04616 if (mem_rtx != NULL_RTX)
04617 goto addr_ok;
04618
04619 if (offset_in_r0 == -1)
04620 {
04621 emit_move_insn (r0, GEN_INT (offset));
04622 offset_in_r0 = offset;
04623 }
04624 else if (offset != offset_in_r0)
04625 {
04626 emit_move_insn (r0,
04627 gen_rtx_PLUS
04628 (Pmode, r0,
04629 GEN_INT (offset - offset_in_r0)));
04630 offset_in_r0 += offset - offset_in_r0;
04631 }
04632
04633 if (pre_dec != NULL_RTX)
04634 {
04635 if (! sp_in_r0)
04636 {
04637 emit_move_insn (r0,
04638 gen_rtx_PLUS
04639 (Pmode, r0, stack_pointer_rtx));
04640 sp_in_r0 = 1;
04641 }
04642
04643 offset -= GET_MODE_SIZE (mode);
04644 offset_in_r0 -= GET_MODE_SIZE (mode);
04645
04646 mem_rtx = pre_dec;
04647 }
04648 else if (sp_in_r0)
04649 mem_rtx = gen_rtx_MEM (mode, r0);
04650 else
04651 mem_rtx = gen_rtx_MEM (mode,
04652 gen_rtx_PLUS (Pmode,
04653 stack_pointer_rtx,
04654 r0));
04655
04656
04657
04658
04659
04660 if (TARGET_REGISTER_P (i)
04661 || ((i == PR_REG || SPECIAL_REGISTER_P (i))
04662 && mem_rtx != pre_dec))
04663 abort ();
04664
04665 addr_ok:
04666 if (TARGET_REGISTER_P (i)
04667 || ((i == PR_REG || SPECIAL_REGISTER_P (i))
04668 && mem_rtx != pre_dec))
04669 {
04670 rtx r0mode = gen_rtx_REG (GET_MODE (reg_rtx), R0_REG);
04671
04672 emit_move_insn (r0mode, reg_rtx);
04673
04674 offset_in_r0 = -1;
04675 sp_in_r0 = 0;
04676
04677 reg_rtx = r0mode;
04678 }
04679
04680 emit_move_insn (mem_rtx, reg_rtx);
04681 }
04682
04683 if (offset != d_rounding)
04684 abort ();
04685 }
04686 else
04687 push_regs (live_regs_mask);
04688
04689 if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
04690 {
04691 rtx insn = get_last_insn ();
04692 rtx last = emit_insn (gen_GOTaddr2picreg ());
04693
04694
04695
04696
04697 do
04698 {
04699 insn = NEXT_INSN (insn);
04700
04701 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
04702 const0_rtx,
04703 REG_NOTES (insn));
04704 }
04705 while (insn != last);
04706 }
04707
04708 if (SHMEDIA_REGS_STACK_ADJUST ())
04709 {
04710 emit_move_insn (gen_rtx_REG (Pmode, R0_REG),
04711 gen_rtx_SYMBOL_REF (Pmode,
04712 TARGET_FPU_ANY
04713 ? "__GCC_push_shmedia_regs"
04714 : "__GCC_push_shmedia_regs_nofpu"));
04715
04716
04717 emit_insn (gen_shmedia_save_restore_regs_compact
04718 (GEN_INT (-SHMEDIA_REGS_STACK_ADJUST ())));
04719 }
04720
04721 if (target_flags != save_flags)
04722 {
04723 rtx insn = emit_insn (gen_toggle_sz ());
04724
04725
04726
04727
04728 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD,
04729 const0_rtx,
04730 REG_NOTES (insn));
04731 }
04732
04733 target_flags = save_flags;
04734
04735 output_stack_adjust (-rounded_frame_size (d) + d_rounding,
04736 stack_pointer_rtx, TARGET_SH5 ? 0 : 1);
04737
04738 if (frame_pointer_needed)
04739 emit_insn (GEN_MOV (frame_pointer_rtx, stack_pointer_rtx));
04740
04741 if (TARGET_SHCOMPACT
04742 && (current_function_args_info.call_cookie & ~ CALL_COOKIE_RET_TRAMP(1)))
04743 {
04744
04745
04746 emit_move_insn (gen_rtx_REG (Pmode, R0_REG),
04747 gen_rtx_SYMBOL_REF (Pmode,
04748 "__GCC_shcompact_incoming_args"));
04749 emit_insn (gen_shcompact_incoming_args ());
04750 }
04751 }
04752
04753 void
04754 sh_expand_epilogue ()
04755 {
04756 HOST_WIDE_INT live_regs_mask[(FIRST_PSEUDO_REGISTER + 31) / 32];
04757 int d, i;
04758 int d_rounding = 0;
04759
04760 int save_flags = target_flags;
04761 int frame_size;
04762
04763 calc_live_regs (&d, live_regs_mask);
04764
04765 if (TARGET_SH5 && d % (STACK_BOUNDARY / BITS_PER_UNIT))
04766 d_rounding = ((STACK_BOUNDARY / BITS_PER_UNIT)
04767 - d % (STACK_BOUNDARY / BITS_PER_UNIT));
04768
04769 frame_size = rounded_frame_size (d) - d_rounding;
04770
04771 if (frame_pointer_needed)
04772 {
04773 output_stack_adjust (frame_size, frame_pointer_rtx, 7);
04774
04775
04776
04777
04778
04779 emit_insn (gen_blockage ());
04780 emit_insn (GEN_MOV (stack_pointer_rtx, frame_pointer_rtx));
04781 }
04782 else if (frame_size)
04783 {
04784
04785
04786
04787
04788 emit_insn (gen_blockage ());
04789 output_stack_adjust (frame_size, stack_pointer_rtx, 7);
04790 }
04791
04792 if (SHMEDIA_REGS_STACK_ADJUST ())
04793 {
04794 emit_move_insn (gen_rtx_REG (Pmode, R0_REG),
04795 gen_rtx_SYMBOL_REF (Pmode,
04796 TARGET_FPU_ANY
04797 ? "__GCC_pop_shmedia_regs"
04798 : "__GCC_pop_shmedia_regs_nofpu"));
04799
04800
04801 emit_insn (gen_shmedia_save_restore_regs_compact
04802 (GEN_INT (SHMEDIA_REGS_STACK_ADJUST ())));
04803 }
04804
04805
04806
04807 if (target_flags != save_flags)
04808 emit_insn (gen_toggle_sz ());
04809 if (TARGET_SH5)
04810 {
04811 int offset = d_rounding;
04812 int offset_in_r0 = -1;
04813 int sp_in_r0 = 0;
04814 int align;
04815 rtx r0 = gen_rtx_REG (Pmode, R0_REG);
04816
04817
04818
04819
04820
04821 for (align = 0; align <= 1; align++)
04822 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
04823 if (live_regs_mask[i/32] & (1 << (i % 32)))
04824 {
04825 enum machine_mode mode = REGISTER_NATURAL_MODE (i);
04826 int reg = i;
04827 rtx reg_rtx, mem_rtx, post_inc = NULL_RTX, insn;
04828
04829 if (mode == SFmode && (i % 2) == 0
04830 && ! TARGET_FPU_SINGLE && FP_REGISTER_P (i)
04831 && (live_regs_mask[(i ^ 1) / 32] & (1 << ((i ^ 1) % 32))))
04832 {
04833 mode = DFmode;
04834 i++;
04835 }
04836
04837
04838
04839
04840 if ((GET_MODE_SIZE (mode) % (STACK_BOUNDARY / BITS_PER_UNIT)
04841 == 0) != align)
04842 continue;
04843
04844 reg_rtx = gen_rtx_REG (mode, reg);
04845
04846 mem_rtx = gen_rtx_MEM (mode,
04847 gen_rtx_PLUS (Pmode,
04848 stack_pointer_rtx,
04849 GEN_INT (offset)));
04850
04851 GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (mem_rtx, 0), try_post_inc);
04852
04853 mem_rtx = NULL_RTX;
04854
04855 try_post_inc:
04856 do
04857 if (HAVE_POST_INCREMENT
04858 && (offset == offset_in_r0
04859 || (offset + GET_MODE_SIZE (mode) != d + d_rounding
04860 && mem_rtx == NULL_RTX)
04861 || i == PR_REG || SPECIAL_REGISTER_P (i)))
04862 {
04863 post_inc = gen_rtx_MEM (mode,
04864 gen_rtx_POST_INC (Pmode, r0));
04865
04866 GO_IF_LEGITIMATE_ADDRESS (mode, XEXP (post_inc, 0),
04867 post_inc_ok);
04868
04869 post_inc = NULL_RTX;
04870
04871 break;
04872
04873 post_inc_ok:
04874 mem_rtx = NULL_RTX;
04875 }
04876 while (0);
04877
04878 if (mem_rtx != NULL_RTX)
04879 goto addr_ok;
04880
04881 if (offset_in_r0 == -1)
04882 {
04883 emit_move_insn (r0, GEN_INT (offset));
04884 offset_in_r0 = offset;
04885 }
04886 else if (offset != offset_in_r0)
04887 {
04888 emit_move_insn (r0,
04889 gen_rtx_PLUS
04890 (Pmode, r0,
04891 GEN_INT (offset - offset_in_r0)));
04892 offset_in_r0 += offset - offset_in_r0;
04893 }
04894
04895 if (post_inc != NULL_RTX)
04896 {
04897 if (! sp_in_r0)
04898 {
04899 emit_move_insn (r0,
04900 gen_rtx_PLUS
04901 (Pmode, r0, stack_pointer_rtx));
04902 sp_in_r0 = 1;
04903 }
04904
04905 mem_rtx = post_inc;
04906
04907 offset_in_r0 += GET_MODE_SIZE (mode);
04908 }
04909 else if (sp_in_r0)
04910 mem_rtx = gen_rtx_MEM (mode, r0);
04911 else
04912 mem_rtx = gen_rtx_MEM (mode,
04913 gen_rtx_PLUS (Pmode,
04914 stack_pointer_rtx,
04915 r0));
04916
04917 if ((i == PR_REG || SPECIAL_REGISTER_P (i))
04918 && mem_rtx != post_inc)
04919 abort ();
04920
04921 addr_ok:
04922 if ((i == PR_REG || SPECIAL_REGISTER_P (i))
04923 && mem_rtx != post_inc)
04924 {
04925 insn = emit_move_insn (r0, mem_rtx);
04926 mem_rtx = r0;
04927 }
04928 else if (TARGET_REGISTER_P (i))
04929 {
04930 rtx r1 = gen_rtx_REG (mode, R1_REG);
04931
04932 insn = emit_move_insn (r1, mem_rtx);
04933 mem_rtx = r1;
04934 }
04935
04936 insn = emit_move_insn (reg_rtx, mem_rtx);
04937
04938 offset += GET_MODE_SIZE (mode);
04939 }
04940
04941 if (offset != d + d_rounding)
04942 abort ();
04943
04944 goto finish;
04945 }
04946 else
04947 d = 0;
04948 if (live_regs_mask[PR_REG / 32] & (1 << (PR_REG % 32)))
04949 pop (PR_REG);
04950 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
04951 {
04952 int j = (FIRST_PSEUDO_REGISTER - 1) - i;
04953
04954 if (j != PR_REG && live_regs_mask[j / 32] & (1 << (j % 32)))
04955 pop (j);
04956 }
04957 finish:
04958 if (target_flags != save_flags)
04959 emit_insn (gen_toggle_sz ());
04960 target_flags = save_flags;
04961
04962 output_stack_adjust (extra_push + current_function_pretend_args_size
04963 + d + d_rounding
04964 + current_function_args_info.stack_regs * 8,
04965 stack_pointer_rtx, 7);
04966
04967
04968 if (sp_switch)
04969 emit_insn (gen_sp_switch_2 ());
04970
04971
04972
04973
04974
04975 if (live_regs_mask[PR_REG / 32] & (1 << (PR_REG % 32)))
04976 emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, PR_REG)));
04977 }
04978
04979 static int sh_need_epilogue_known = 0;
04980
04981 int
04982 sh_need_epilogue ()
04983 {
04984 if (! sh_need_epilogue_known)
04985 {
04986 rtx epilogue;
04987
04988 start_sequence ();
04989 sh_expand_epilogue ();
04990 epilogue = gen_sequence ();
04991 end_sequence ();
04992 sh_need_epilogue_known
04993 = (GET_CODE (epilogue) == SEQUENCE && XVECLEN (epilogue, 0) == 0
04994 ? -1 : 1);
04995 }
04996 return sh_need_epilogue_known > 0;
04997 }
04998
04999
05000
05001 static void
05002 sh_output_function_epilogue (file, size)
05003 FILE *file ATTRIBUTE_UNUSED;
05004 HOST_WIDE_INT size ATTRIBUTE_UNUSED;
05005 {
05006 trap_exit = pragma_interrupt = pragma_trapa = pragma_nosave_low_regs = 0;
05007 sh_need_epilogue_known = 0;
05008 sp_switch = NULL_RTX;
05009 }
05010
05011 rtx
05012 sh_builtin_saveregs ()
05013 {
05014
05015 int first_intreg = current_function_args_info.arg_count[(int) SH_ARG_INT];
05016
05017 int n_intregs = MAX (0, NPARM_REGS (SImode) - first_intreg);
05018
05019 int first_floatreg = current_function_args_info.arg_count[(int) SH_ARG_FLOAT];
05020
05021 int n_floatregs = MAX (0, NPARM_REGS (SFmode) - first_floatreg);
05022 rtx regbuf, fpregs;
05023 int bufsize, regno;
05024 HOST_WIDE_INT alias_set;
05025
05026 if (TARGET_SH5)
05027 {
05028 if (n_intregs)
05029 {
05030 int pushregs = n_intregs;
05031
05032 while (pushregs < NPARM_REGS (SImode) - 1
05033 && (CALL_COOKIE_INT_REG_GET
05034 (current_function_args_info.call_cookie,
05035 NPARM_REGS (SImode) - pushregs)
05036 == 1))
05037 {
05038 current_function_args_info.call_cookie
05039 &= ~ CALL_COOKIE_INT_REG (NPARM_REGS (SImode)
05040 - pushregs, 1);
05041 pushregs++;
05042 }
05043
05044 if (pushregs == NPARM_REGS (SImode))
05045 current_function_args_info.call_cookie
05046 |= (CALL_COOKIE_INT_REG (0, 1)
05047 | CALL_COOKIE_STACKSEQ (pushregs - 1));
05048 else
05049 current_function_args_info.call_cookie
05050 |= CALL_COOKIE_STACKSEQ (pushregs);
05051
05052 current_function_pretend_args_size += 8 * n_intregs;
05053 }
05054 if (TARGET_SHCOMPACT)
05055 return const0_rtx;
05056 }
05057
05058 if (! TARGET_SH3E && ! TARGET_SH4 && ! TARGET_SH5)
05059 {
05060 error ("__builtin_saveregs not supported by this subtarget");
05061 return const0_rtx;
05062 }
05063
05064 if (TARGET_SHMEDIA)
05065 n_floatregs = 0;
05066
05067
05068
05069
05070 bufsize = (n_intregs * UNITS_PER_WORD) + (n_floatregs * UNITS_PER_WORD);
05071
05072 if (TARGET_SHMEDIA)
05073 regbuf = gen_rtx_MEM (BLKmode,
05074 gen_rtx_REG (Pmode, ARG_POINTER_REGNUM));
05075 else
05076 regbuf = assign_stack_local (BLKmode, bufsize, 0);
05077 alias_set = get_varargs_alias_set ();
05078 set_mem_alias_set (regbuf, alias_set);
05079
05080
05081
05082
05083 if (n_intregs > 0)
05084 move_block_from_reg (BASE_ARG_REG (SImode) + first_intreg,
05085 adjust_address (regbuf, BLKmode,
05086 n_floatregs * UNITS_PER_WORD),
05087 n_intregs, n_intregs * UNITS_PER_WORD);
05088
05089 if (TARGET_SHMEDIA)
05090
05091 return XEXP (regbuf, 0);
05092
05093
05094
05095
05096
05097
05098
05099
05100
05101 fpregs = gen_reg_rtx (Pmode);
05102 emit_move_insn (fpregs, XEXP (regbuf, 0));
05103 emit_insn (gen_addsi3 (fpregs, fpregs,
05104 GEN_INT (n_floatregs * UNITS_PER_WORD)));
05105 if (TARGET_SH4)
05106 {
05107 rtx mem;
05108 for (regno = NPARM_REGS (DFmode) - 2; regno >= first_floatreg; regno -= 2)
05109 {
05110 emit_insn (gen_addsi3 (fpregs, fpregs,
05111 GEN_INT (-2 * UNITS_PER_WORD)));
05112 mem = gen_rtx_MEM (DFmode, fpregs);
05113 set_mem_alias_set (mem, alias_set);
05114 emit_move_insn (mem,
05115 gen_rtx (REG, DFmode, BASE_ARG_REG (DFmode) + regno));
05116 }
05117 regno = first_floatreg;
05118 if (regno & 1)
05119 {
05120 emit_insn (gen_addsi3 (fpregs, fpregs, GEN_INT (- UNITS_PER_WORD)));
05121 mem = gen_rtx_MEM (SFmode, fpregs);
05122 set_mem_alias_set (mem, alias_set);
05123 emit_move_insn (mem,
05124 gen_rtx (REG, SFmode, BASE_ARG_REG (SFmode) + regno
05125 - (TARGET_LITTLE_ENDIAN != 0)));
05126 }
05127 }
05128 else
05129 for (regno = NPARM_REGS (SFmode) - 1; regno >= first_floatreg; regno--)
05130 {
05131 rtx mem;
05132
05133 emit_insn (gen_addsi3 (fpregs, fpregs, GEN_INT (- UNITS_PER_WORD)));
05134 mem = gen_rtx_MEM (SFmode, fpregs);
05135 set_mem_alias_set (mem, alias_set);
05136 emit_move_insn (mem,
05137 gen_rtx_REG (SFmode, BASE_ARG_REG (SFmode) + regno));
05138 }
05139
05140
05141 return XEXP (regbuf, 0);
05142 }
05143
05144
05145
05146 tree
05147 sh_build_va_list ()
05148 {
05149 tree f_next_o, f_next_o_limit, f_next_fp, f_next_fp_limit, f_next_stack;
05150 tree record;
05151
05152 if (TARGET_SH5 || (! TARGET_SH3E && ! TARGET_SH4) || TARGET_HITACHI)
05153 return ptr_type_node;
05154
05155 record = make_node (RECORD_TYPE);
05156
05157 f_next_o = build_decl (FIELD_DECL, get_identifier ("__va_next_o"),
05158 ptr_type_node);
05159 f_next_o_limit = build_decl (FIELD_DECL,
05160 get_identifier ("__va_next_o_limit"),
05161 ptr_type_node);
05162 f_next_fp = build_decl (FIELD_DECL, get_identifier ("__va_next_fp"),
05163 ptr_type_node);
05164 f_next_fp_limit = build_decl (FIELD_DECL,
05165 get_identifier ("__va_next_fp_limit"),
05166 ptr_type_node);
05167 f_next_stack = build_decl (FIELD_DECL, get_identifier ("__va_next_stack"),
05168 ptr_type_node);
05169
05170 DECL_FIELD_CONTEXT (f_next_o) = record;
05171 DECL_FIELD_CONTEXT (f_next_o_limit) = record;
05172 DECL_FIELD_CONTEXT (f_next_fp) = record;
05173 DECL_FIELD_CONTEXT (f_next_fp_limit) = record;
05174 DECL_FIELD_CONTEXT (f_next_stack) = record;
05175
05176 TYPE_FIELDS (record) = f_next_o;
05177 TREE_CHAIN (f_next_o) = f_next_o_limit;
05178 TREE_CHAIN (f_next_o_limit) = f_next_fp;
05179 TREE_CHAIN (f_next_fp) = f_next_fp_limit;
05180 TREE_CHAIN (f_next_fp_limit) = f_next_stack;
05181
05182 layout_type (record);
05183
05184 return record;
05185 }
05186
05187
05188
05189 void
05190 sh_va_start (stdarg_p, valist, nextarg)
05191 int stdarg_p;
05192 tree valist;
05193 rtx nextarg;
05194 {
05195 tree f_next_o, f_next_o_limit, f_next_fp, f_next_fp_limit, f_next_stack;
05196 tree next_o, next_o_limit, next_fp, next_fp_limit, next_stack;
05197 tree t, u;
05198 int nfp, nint;
05199
05200 if (TARGET_SH5)
05201 {
05202 expand_builtin_saveregs ();
05203
05204
05205
05206
05207 if (current_function_args_info.arg_count[(int) SH_ARG_INT]
05208 < NPARM_REGS (SImode))
05209 stdarg_p = 1;
05210 std_expand_builtin_va_start (stdarg_p, valist, nextarg);
05211 return;
05212 }
05213
05214 if ((! TARGET_SH3E && ! TARGET_SH4) || TARGET_HITACHI)
05215 {
05216 std_expand_builtin_va_start (stdarg_p, valist, nextarg);
05217 return;
05218 }
05219
05220 f_next_o = TYPE_FIELDS (va_list_type_node);
05221 f_next_o_limit = TREE_CHAIN (f_next_o);
05222 f_next_fp = TREE_CHAIN (f_next_o_limit);
05223 f_next_fp_limit = TREE_CHAIN (f_next_fp);
05224 f_next_stack = TREE_CHAIN (f_next_fp_limit);
05225
05226 next_o = build (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o);
05227 next_o_limit = build (COMPONENT_REF, TREE_TYPE (f_next_o_limit),
05228 valist, f_next_o_limit);
05229 next_fp = build (COMPONENT_REF, TREE_TYPE (f_next_fp), valist, f_next_fp);
05230 next_fp_limit = build (COMPONENT_REF, TREE_TYPE (f_next_fp_limit),
05231 valist, f_next_fp_limit);
05232 next_stack = build (COMPONENT_REF, TREE_TYPE (f_next_stack),
05233 valist, f_next_stack);
05234
05235
05236 u = make_tree (ptr_type_node, expand_builtin_saveregs ());
05237 t = build (MODIFY_EXPR, ptr_type_node, next_fp, u);
05238 TREE_SIDE_EFFECTS (t) = 1;
05239 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
05240
05241 nfp = current_function_args_info.arg_count[SH_ARG_FLOAT];
05242 if (nfp < 8)
05243 nfp = 8 - nfp;
05244 else
05245 nfp = 0;
05246 u = fold (build (PLUS_EXPR, ptr_type_node, u,
05247 build_int_2 (UNITS_PER_WORD * nfp, 0)));
05248 t = build (MODIFY_EXPR, ptr_type_node, next_fp_limit, u);
05249 TREE_SIDE_EFFECTS (t) = 1;
05250 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
05251
05252 t = build (MODIFY_EXPR, ptr_type_node, next_o, u);
05253 TREE_SIDE_EFFECTS (t) = 1;
05254 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
05255
05256 nint = current_function_args_info.arg_count[SH_ARG_INT];
05257 if (nint < 4)
05258 nint = 4 - nint;
05259 else
05260 nint = 0;
05261 u = fold (build (PLUS_EXPR, ptr_type_node, u,
05262 build_int_2 (UNITS_PER_WORD * nint, 0)));
05263 t = build (MODIFY_EXPR, ptr_type_node, next_o_limit, u);
05264 TREE_SIDE_EFFECTS (t) = 1;
05265 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
05266
05267 u = make_tree (ptr_type_node, nextarg);
05268 if (! stdarg_p && (nint == 0 || nfp == 0))
05269 {
05270 u = fold (build (PLUS_EXPR, ptr_type_node, u,
05271 build_int_2 (-UNITS_PER_WORD, -1)));
05272 }
05273 t = build (MODIFY_EXPR, ptr_type_node, next_stack, u);
05274 TREE_SIDE_EFFECTS (t) = 1;
05275 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
05276 }
05277
05278
05279
05280 rtx
05281 sh_va_arg (valist, type)
05282 tree valist, type;
05283 {
05284 HOST_WIDE_INT size, rsize;
05285 tree tmp, pptr_type_node;
05286 rtx addr_rtx, r;
05287
05288 size = int_size_in_bytes (type);
05289 rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
05290 pptr_type_node = build_pointer_type (ptr_type_node);
05291
05292 if (! TARGET_SH5 && (TARGET_SH3E || TARGET_SH4) && ! TARGET_HITACHI)
05293 {
05294 tree f_next_o, f_next_o_limit, f_next_fp, f_next_fp_limit, f_next_stack;
05295 tree next_o, next_o_limit, next_fp, next_fp_limit, next_stack;
05296 int pass_as_float;
05297 rtx lab_false, lab_over;
05298
05299 f_next_o = TYPE_FIELDS (va_list_type_node);
05300 f_next_o_limit = TREE_CHAIN (f_next_o);
05301 f_next_fp = TREE_CHAIN (f_next_o_limit);
05302 f_next_fp_limit = TREE_CHAIN (f_next_fp);
05303 f_next_stack = TREE_CHAIN (f_next_fp_limit);
05304
05305 next_o = build (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o);
05306 next_o_limit = build (COMPONENT_REF, TREE_TYPE (f_next_o_limit),
05307 valist, f_next_o_limit);
05308 next_fp = build (COMPONENT_REF, TREE_TYPE (f_next_fp),
05309 valist, f_next_fp);
05310 next_fp_limit = build (COMPONENT_REF, TREE_TYPE (f_next_fp_limit),
05311 valist, f_next_fp_limit);
05312 next_stack = build (COMPONENT_REF, TREE_TYPE (f_next_stack),
05313 valist, f_next_stack);
05314
05315 if (TARGET_SH4)
05316 {
05317 pass_as_float = ((TREE_CODE (type) == REAL_TYPE && size <= 8)
05318 || (TREE_CODE (type) == COMPLEX_TYPE
05319 && TREE_CODE (TREE_TYPE (type)) == REAL_TYPE
05320 && size <= 16));
05321 }
05322 else
05323 {
05324 pass_as_float = (TREE_CODE (type) == REAL_TYPE && size == 4);
05325 }
05326
05327 addr_rtx = gen_reg_rtx (Pmode);
05328 lab_false = gen_label_rtx ();
05329 lab_over = gen_label_rtx ();
05330
05331 if (pass_as_float)
05332 {
05333 emit_cmp_and_jump_insns (expand_expr (next_fp, NULL_RTX, Pmode,
05334 EXPAND_NORMAL),
05335 expand_expr (next_fp_limit, NULL_RTX,
05336 Pmode, EXPAND_NORMAL),
05337 GE, const1_rtx, Pmode, 1, lab_false);
05338
05339 if (TYPE_ALIGN (type) > BITS_PER_WORD)
05340 {
05341 tmp = build (BIT_AND_EXPR, ptr_type_node, next_fp,
05342 build_int_2 (UNITS_PER_WORD, 0));
05343 tmp = build (PLUS_EXPR, ptr_type_node, next_fp, tmp);
05344 tmp = build (MODIFY_EXPR, ptr_type_node, next_fp, tmp);
05345 TREE_SIDE_EFFECTS (tmp) = 1;
05346 expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);
05347 }
05348
05349 tmp = build1 (ADDR_EXPR, pptr_type_node, next_fp);
05350 r = expand_expr (tmp, addr_rtx, Pmode, EXPAND_NORMAL);
05351 if (r != addr_rtx)
05352 emit_move_insn (addr_rtx, r);
05353
05354 emit_jump_insn (gen_jump (lab_over));
05355 emit_barrier ();
05356 emit_label (lab_false);
05357
05358 tmp = build1 (ADDR_EXPR, pptr_type_node, next_stack);
05359 r = expand_expr (tmp, addr_rtx, Pmode, EXPAND_NORMAL);
05360 if (r != addr_rtx)
05361 emit_move_insn (addr_rtx, r);
05362 }
05363 else
05364 {
05365 tmp = build (PLUS_EXPR, ptr_type_node, next_o,
05366 build_int_2 (rsize, 0));
05367
05368 emit_cmp_and_jump_insns (expand_expr (tmp, NULL_RTX, Pmode,
05369 EXPAND_NORMAL),
05370 expand_expr (next_o_limit, NULL_RTX,
05371 Pmode, EXPAND_NORMAL),
05372 GT, const1_rtx, Pmode, 1, lab_false);
05373
05374 tmp = build1 (ADDR_EXPR, pptr_type_node, next_o);
05375 r = expand_expr (tmp, addr_rtx, Pmode, EXPAND_NORMAL);
05376 if (r != addr_rtx)
05377 emit_move_insn (addr_rtx, r);
05378
05379 emit_jump_insn (gen_jump (lab_over));
05380 emit_barrier ();
05381 emit_label (lab_false);
05382
05383 if (size > 4 && ! TARGET_SH4)
05384 {
05385 tmp = build (MODIFY_EXPR, ptr_type_node, next_o, next_o_limit);
05386 TREE_SIDE_EFFECTS (tmp) = 1;
05387 expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);
05388 }
05389
05390 tmp = build1 (ADDR_EXPR, pptr_type_node, next_stack);
05391 r = expand_expr (tmp, addr_rtx, Pmode, EXPAND_NORMAL);
05392 if (r != addr_rtx)
05393 emit_move_insn (addr_rtx, r);
05394 }
05395
05396 emit_label (lab_over);
05397
05398 tmp = make_tree (pptr_type_node, addr_rtx);
05399 valist = build1 (INDIRECT_REF, ptr_type_node, tmp);
05400 }
05401
05402
05403
05404
05405 return std_expand_builtin_va_arg (valist, type);
05406 }
05407
05408
05409
05410
05411 int
05412 initial_elimination_offset (from, to)
05413 int from;
05414 int to;
05415 {
05416 int regs_saved;
05417 int regs_saved_rounding = 0;
05418 int total_saved_regs_space;
05419 int total_auto_space;
05420 int save_flags = target_flags;
05421 int copy_flags;
05422
05423 HOST_WIDE_INT live_regs_mask[(FIRST_PSEUDO_REGISTER + 31) / 32];
05424 calc_live_regs (®s_saved, live_regs_mask);
05425 regs_saved += SHMEDIA_REGS_STACK_ADJUST ();
05426 if (TARGET_SH5 && regs_saved % (STACK_BOUNDARY / BITS_PER_UNIT))
05427 regs_saved_rounding = ((STACK_BOUNDARY / BITS_PER_UNIT)
05428 - regs_saved % (STACK_BOUNDARY / BITS_PER_UNIT));
05429
05430 total_auto_space = rounded_frame_size (regs_saved) - regs_saved_rounding;
05431 copy_flags = target_flags;
05432 target_flags = save_flags;
05433
05434 total_saved_regs_space = regs_saved + regs_saved_rounding;
05435
05436 if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
05437 return total_saved_regs_space + total_auto_space
05438 + current_function_args_info.byref_regs * 8;
05439
05440 if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
05441 return total_saved_regs_space + total_auto_space
05442 + current_function_args_info.byref_regs * 8;
05443
05444
05445 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
05446 return 0;
05447
05448 if (from == RETURN_ADDRESS_POINTER_REGNUM
05449 && (to == FRAME_POINTER_REGNUM || to == STACK_POINTER_REGNUM))
05450 if (TARGET_SH5)
05451 {
05452 int i, n = total_saved_regs_space;
05453 int align;
05454 int pr_reg = TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG;
05455
05456 n += total_auto_space;
05457
05458
05459 if ((live_regs_mask[pr_reg / 32] & (1 << (pr_reg % 32))) == 0)
05460 return n;
05461
05462 target_flags = copy_flags;
05463
05464
05465
05466
05467
05468 for (align = 1; align >= 0; align--)
05469 for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
05470 if (live_regs_mask[i/32] & (1 << (i % 32)))
05471 {
05472 enum machine_mode mode = REGISTER_NATURAL_MODE (i);
05473
05474 if (mode == SFmode && (i % 2) == 1
05475 && ! TARGET_FPU_SINGLE && FP_REGISTER_P (i)
05476 && (live_regs_mask[(i ^ 1) / 32]
05477 & (1 << ((i ^ 1) % 32))))
05478 {
05479 mode = DFmode;
05480 i--;
05481 }
05482
05483
05484
05485
05486 if ((GET_MODE_SIZE (mode) % (STACK_BOUNDARY / BITS_PER_UNIT)
05487 == 0) != align)
05488 continue;
05489
05490 n -= GET_MODE_SIZE (mode);
05491
05492 if (i == pr_reg)
05493 {
05494 target_flags = save_flags;
05495 return n;
05496 }
05497 }
05498
05499 abort ();
05500 }
05501 else
05502 return total_auto_space;
05503
05504 abort ();
05505 }
05506
05507
05508
05509
05510 void
05511 sh_pr_interrupt (pfile)
05512 cpp_reader *pfile ATTRIBUTE_UNUSED;
05513 {
05514 pragma_interrupt = 1;
05515 }
05516
05517 void
05518 sh_pr_trapa (pfile)
05519 cpp_reader *pfile ATTRIBUTE_UNUSED;
05520 {
05521 pragma_interrupt = pragma_trapa = 1;
05522 }
05523
05524 void
05525 sh_pr_nosave_low_regs (pfile)
05526 cpp_reader *pfile ATTRIBUTE_UNUSED;
05527 {
05528 pragma_nosave_low_regs = 1;
05529 }
05530
05531
05532
05533 static void
05534 sh_insert_attributes (node, attributes)
05535 tree node;
05536 tree * attributes;
05537 {
05538 if (! pragma_interrupt
05539 || TREE_CODE (node) != FUNCTION_DECL)
05540 return;
05541
05542
05543 if (TREE_CODE_CLASS (TREE_CODE (node)) != 'd')
05544 return;
05545
05546
05547 * attributes = tree_cons (get_identifier ("interrupt_handler"), NULL, * attributes);
05548
05549 return;
05550 }
05551
05552
05553
05554
05555
05556
05557
05558
05559
05560
05561
05562 const struct attribute_spec sh_attribute_table[] =
05563 {
05564
05565 { "interrupt_handler", 0, 0, true, false, false, sh_handle_interrupt_handler_attribute },
05566 { "sp_switch", 1, 1, true, false, false, sh_handle_sp_switch_attribute },
05567 { "trap_exit", 1, 1, true, false, false, sh_handle_trap_exit_attribute },
05568 { NULL, 0, 0, false, false, false, NULL }
05569 };
05570
05571
05572
05573 static tree
05574 sh_handle_interrupt_handler_attribute (node, name, args, flags, no_add_attrs)
05575 tree *node;
05576 tree name;
05577 tree args ATTRIBUTE_UNUSED;
05578 int flags ATTRIBUTE_UNUSED;
05579 bool *no_add_attrs;
05580 {
05581 if (TREE_CODE (*node) != FUNCTION_DECL)
05582 {
05583 warning ("`%s' attribute only applies to functions",
05584 IDENTIFIER_POINTER (name));
05585 *no_add_attrs = true;
05586 }
05587
05588 return NULL_TREE;
05589 }
05590
05591
05592
05593 static tree
05594 sh_handle_sp_switch_attribute (node, name, args, flags, no_add_attrs)
05595 tree *node;
05596 tree name;
05597 tree args;
05598 int flags ATTRIBUTE_UNUSED;
05599 bool *no_add_attrs;
05600 {
05601 if (TREE_CODE (*node) != FUNCTION_DECL)
05602 {
05603 warning ("`%s' attribute only applies to functions",
05604 IDENTIFIER_POINTER (name));
05605 *no_add_attrs = true;
05606 }
05607 else if (!pragma_interrupt)
05608 {
05609
05610 warning ("`%s' attribute only applies to interrupt functions",
05611 IDENTIFIER_POINTER (name));
05612 *no_add_attrs = true;
05613 }
05614 else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
05615 {
05616
05617 warning ("`%s' attribute argument not a string constant",
05618 IDENTIFIER_POINTER (name));
05619 *no_add_attrs = true;
05620 }
05621 else
05622 {
05623 sp_switch = gen_rtx_SYMBOL_REF (VOIDmode,
05624 TREE_STRING_POINTER (TREE_VALUE (args)));
05625 }
05626
05627 return NULL_TREE;
05628 }
05629
05630
05631
05632 static tree
05633 sh_handle_trap_exit_attribute (node, name, args, flags, no_add_attrs)
05634 tree *node;
05635 tree name;
05636 tree args;
05637 int flags ATTRIBUTE_UNUSED;
05638 bool *no_add_attrs;
05639 {
05640 if (TREE_CODE (*node) != FUNCTION_DECL)
05641 {
05642 warning ("`%s' attribute only applies to functions",
05643 IDENTIFIER_POINTER (name));
05644 *no_add_attrs = true;
05645 }
05646 else if (!pragma_interrupt)
05647 {
05648
05649 warning ("`%s' attribute only applies to interrupt functions",
05650 IDENTIFIER_POINTER (name));
05651 *no_add_attrs = true;
05652 }
05653 else if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST)
05654 {
05655
05656 warning ("`%s' attribute argument not an integer constant",
05657 IDENTIFIER_POINTER (name));
05658 *no_add_attrs = true;
05659 }
05660 else
05661 {
05662 trap_exit = TREE_INT_CST_LOW (TREE_VALUE (args));
05663 }
05664
05665 return NULL_TREE;
05666 }
05667
05668
05669
05670
05671
05672
05673
05674 int
05675 system_reg_operand (op, mode)
05676 rtx op;
05677 enum machine_mode mode ATTRIBUTE_UNUSED;
05678 {
05679 switch (REGNO (op))
05680 {
05681 case PR_REG:
05682 case MACL_REG:
05683 case MACH_REG:
05684 return 1;
05685 }
05686 return 0;
05687 }
05688
05689
05690
05691
05692
05693 int
05694 general_movsrc_operand (op, mode)
05695 rtx op;
05696 enum machine_mode mode;
05697 {
05698 if (GET_CODE (op) == MEM)
05699 {
05700 rtx inside = XEXP (op, 0);
05701 if (GET_CODE (inside) == CONST)
05702 inside = XEXP (inside, 0);
05703
05704 if (GET_CODE (inside) == LABEL_REF)
05705 return 1;
05706
05707 if (GET_CODE (inside) == PLUS
05708 && GET_CODE (XEXP (inside, 0)) == LABEL_REF
05709 && GET_CODE (XEXP (inside, 1)) == CONST_INT)
05710 return 1;
05711
05712
05713 if (GET_CODE (inside) == PRE_DEC)
05714 return 0;
05715 }
05716
05717 if ((mode == QImode || mode == HImode)
05718 && (GET_CODE (op) == SUBREG
05719 && GET_CODE (XEXP (op, 0)) == REG
05720 && system_reg_operand (XEXP (op, 0), mode)))
05721 return 0;
05722
05723 return general_operand (op, mode);
05724 }
05725
05726
05727
05728
05729 int
05730 general_movdst_operand (op, mode)
05731 rtx op;
05732 enum machine_mode mode;
05733 {
05734
05735 if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == POST_INC)
05736 return 0;
05737
05738 return general_operand (op, mode);
05739 }
05740
05741
05742
05743
05744
05745 int
05746 reg_no_subreg_operand (op, mode)
05747 register rtx op;
05748 enum machine_mode mode;
05749 {
05750 if (GET_CODE (op) == SUBREG)
05751 return 0;
05752 return register_operand (op, mode);
05753 }
05754
05755
05756
05757 int
05758 arith_reg_operand (op, mode)
05759 rtx op;
05760 enum machine_mode mode;
05761 {
05762 if (register_operand (op, mode))
05763 {
05764 int regno;
05765
05766 if (GET_CODE (op) == REG)
05767 regno = REGNO (op);
05768 else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)
05769 regno = REGNO (SUBREG_REG (op));
05770 else
05771 return 1;
05772
05773 return (regno != T_REG && regno != PR_REG
05774 && ! TARGET_REGISTER_P (regno)
05775 && (regno != FPUL_REG || TARGET_SH4)
05776 && regno != MACH_REG && regno != MACL_REG);
05777 }
05778 return 0;
05779 }
05780
05781 int
05782 fp_arith_reg_operand (op, mode)
05783 rtx op;
05784 enum machine_mode mode;
05785 {
05786 if (register_operand (op, mode))
05787 {
05788 int regno;
05789
05790 if (GET_CODE (op) == REG)
05791 regno = REGNO (op);
05792 else if (GET_CODE (op) == SUBREG && GET_CODE (SUBREG_REG (op)) == REG)
05793 regno = REGNO (SUBREG_REG (op));
05794 else
05795 return 1;
05796
05797 return (regno >= FIRST_PSEUDO_REGISTER
05798 || FP_REGISTER_P (regno));
05799 }
05800 return 0;
05801 }
05802
05803
05804
05805 int
05806 arith_operand (op, mode)
05807 rtx op;
05808 enum machine_mode mode;
05809 {
05810 if (arith_reg_operand (op, mode))
05811 return 1;
05812
05813 if (TARGET_SHMEDIA)
05814 {
05815
05816
05817
05818
05819
05820 if (GET_CODE (op) == CONST_INT
05821 || EXTRA_CONSTRAINT_S (op))
05822 return 1;
05823 else
05824 return 0;
05825 }
05826 else if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_I (INTVAL (op)))
05827 return 1;
05828
05829 return 0;
05830 }
05831
05832
05833
05834 int
05835 arith_reg_or_0_operand (op, mode)
05836 rtx op;
05837 enum machine_mode mode;
05838 {
05839 if (arith_reg_operand (op, mode))
05840 return 1;
05841
05842 if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_N (INTVAL (op)))
05843 return 1;
05844
05845 return 0;
05846 }
05847
05848
05849
05850
05851 int
05852 shmedia_6bit_operand (op, mode)
05853 rtx op;
05854 enum machine_mode mode;
05855 {
05856 return (arith_reg_operand (op, mode)
05857 || (GET_CODE (op) == CONST_INT && CONST_OK_FOR_O (INTVAL (op))));
05858 }
05859
05860
05861
05862 int
05863 logical_operand (op, mode)
05864 rtx op;
05865 enum machine_mode mode;
05866 {
05867 if (arith_reg_operand (op, mode))
05868 return 1;
05869
05870 if (TARGET_SHMEDIA)
05871 {
05872 if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_P (INTVAL (op)))
05873 return 1;
05874 else
05875 return 0;
05876 }
05877 else if (GET_CODE (op) == CONST_INT && CONST_OK_FOR_L (INTVAL (op)))
05878 return 1;
05879
05880 return 0;
05881 }
05882
05883
05884
05885 int
05886 fp_zero_operand (op)
05887 rtx op;
05888 {
05889 REAL_VALUE_TYPE r;
05890
05891 if (GET_MODE (op) != SFmode)
05892 return 0;
05893
05894 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
05895 return REAL_VALUES_EQUAL (r, dconst0) && ! REAL_VALUE_MINUS_ZERO (r);
05896 }
05897
05898
05899
05900 int
05901 fp_one_operand (op)
05902 rtx op;
05903 {
05904 REAL_VALUE_TYPE r;
05905
05906 if (GET_MODE (op) != SFmode)
05907 return 0;
05908
05909 REAL_VALUE_FROM_CONST_DOUBLE (r, op);
05910 return REAL_VALUES_EQUAL (r, dconst1);
05911 }
05912
05913
05914
05915
05916
05917
05918
05919
05920 int
05921 fldi_ok ()
05922 {
05923 return ! TARGET_SH4 || TARGET_FMOVD || reload_completed;
05924 }
05925
05926 int
05927 tertiary_reload_operand (op, mode)
05928 rtx op;
05929 enum machine_mode mode ATTRIBUTE_UNUSED;
05930 {
05931 enum rtx_code code = GET_CODE (op);
05932 return code == MEM || (TARGET_SH4 && code == CONST_DOUBLE);
05933 }
05934
05935 int
05936 fpscr_operand (op, mode)
05937 rtx op;
05938 enum machine_mode mode ATTRIBUTE_UNUSED;
05939 {
05940 return (GET_CODE (op) == REG && REGNO (op) == FPSCR_REG
05941 && GET_MODE (op) == PSImode);
05942 }
05943
05944 int
05945 fpul_operand (op, mode)
05946 rtx op;
05947 enum machine_mode mode;
05948 {
05949 if (TARGET_SHMEDIA)
05950 return fp_arith_reg_operand (op, mode);
05951
05952 return (GET_CODE (op) == REG
05953 && (REGNO (op) == FPUL_REG || REGNO (op) >= FIRST_PSEUDO_REGISTER)
05954 && GET_MODE (op) == mode);
05955 }
05956
05957 int
05958 symbol_ref_operand (op, mode)
05959 rtx op;
05960 enum machine_mode mode ATTRIBUTE_UNUSED;
05961 {
05962 return (GET_CODE (op) == SYMBOL_REF);
05963 }
05964
05965 int
05966 commutative_float_operator (op, mode)
05967 rtx op;
05968 enum machine_mode mode;
05969 {
05970 if (GET_MODE (op) != mode)
05971 return 0;
05972 switch (GET_CODE (op))
05973 {
05974 case PLUS:
05975 case MULT:
05976 return 1;
05977 default:
05978 break;
05979 }
05980 return 0;
05981 }
05982
05983 int
05984 noncommutative_float_operator (op, mode)
05985 rtx op;
05986 enum machine_mode mode;
05987 {
05988 if (GET_MODE (op) != mode)
05989 return 0;
05990 switch (GET_CODE (op))
05991 {
05992 case MINUS:
05993 case DIV:
05994 return 1;
05995 default:
05996 break;
05997 }
05998 return 0;
05999 }
06000
06001 int
06002 binary_float_operator (op, mode)
06003 rtx op;
06004 enum machine_mode mode;
06005 {
06006 if (GET_MODE (op) != mode)
06007 return 0;
06008 switch (GET_CODE (op))
06009 {
06010 case PLUS:
06011 case MINUS:
06012 case MULT:
06013 case DIV:
06014 return 1;
06015 default:
06016 break;
06017 }
06018 return 0;
06019 }
06020
06021
06022 int
06023 target_reg_operand (op, mode)
06024 rtx op;
06025 enum machine_mode mode;
06026 {
06027 if (mode != DImode
06028 || GET_MODE (op) != DImode)
06029 return 0;
06030
06031 if (GET_CODE (op) == SUBREG)
06032 op = XEXP (op, 0);
06033
06034 if (GET_CODE (op) != REG)
06035 return 0;
06036
06037
06038
06039
06040 if (REGNO (op) > LAST_VIRTUAL_REGISTER
06041 || TARGET_REGISTER_P (REGNO (op)))
06042 return 1;
06043
06044 return 0;
06045 }
06046
06047
06048
06049 int
06050 target_operand (op, mode)
06051 rtx op;
06052 enum machine_mode mode;
06053 {
06054 if (mode != DImode)
06055 return 0;
06056
06057 if ((GET_MODE (op) == DImode || GET_MODE (op) == VOIDmode)
06058 && EXTRA_CONSTRAINT_T (op))
06059 return ! reload_completed;
06060
06061 return target_reg_operand (op, mode);
06062 }
06063
06064
06065
06066
06067 static int
06068 branch_dest (branch)
06069 rtx branch;
06070 {
06071 rtx dest = SET_SRC (PATTERN (branch));
06072 int dest_uid;
06073
06074 if (GET_CODE (dest) == IF_THEN_ELSE)
06075 dest = XEXP (dest, 1);
06076 dest = XEXP (dest, 0);
06077 dest_uid = INSN_UID (dest);
06078 return INSN_ADDRESSES (dest_uid);
06079 }
06080
06081
06082
06083
06084 int
06085 reg_unused_after (reg, insn)
06086 rtx reg;
06087 rtx insn;
06088 {
06089 enum rtx_code code;
06090 rtx set;
06091
06092
06093
06094
06095 set = single_set (insn);
06096 if (set && GET_CODE (SET_DEST (set)) != MEM
06097 && reg_overlap_mentioned_p (reg, SET_DEST (set)))
06098 return 1;
06099
06100 while ((insn = NEXT_INSN (insn)))
06101 {
06102 code = GET_CODE (insn);
06103
06104 #if 0
06105
06106
06107
06108
06109 if (code == CODE_LABEL)
06110 return 1;
06111
06112 #endif
06113
06114 if (code == JUMP_INSN)
06115 return 0;
06116
06117
06118
06119
06120
06121 else if (code == INSN && GET_CODE (PATTERN (insn)) == SEQUENCE)
06122 {
06123 int i;
06124 int retval = 0;
06125
06126 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
06127 {
06128 rtx this_insn = XVECEXP (PATTERN (insn), 0, i);
06129 rtx set = single_set (this_insn);
06130
06131 if (GET_CODE (this_insn) == CALL_INSN)
06132 code = CALL_INSN;
06133 else if (GET_CODE (this_insn) == JUMP_INSN)
06134 {
06135 if (INSN_ANNULLED_BRANCH_P (this_insn))
06136 return 0;
06137 code = JUMP_INSN;
06138 }
06139
06140 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
06141 return 0;
06142 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
06143 {
06144 if (GET_CODE (SET_DEST (set)) != MEM)
06145 retval = 1;
06146 else
06147 return 0;
06148 }
06149 if (set == 0
06150 && reg_overlap_mentioned_p (reg, PATTERN (this_insn)))
06151 return 0;
06152 }
06153 if (retval == 1)
06154 return 1;
06155 else if (code == JUMP_INSN)
06156 return 0;
06157 }
06158 else if (GET_RTX_CLASS (code) == 'i')
06159 {
06160 rtx set = single_set (insn);
06161
06162 if (set && reg_overlap_mentioned_p (reg, SET_SRC (set)))
06163 return 0;
06164 if (set && reg_overlap_mentioned_p (reg, SET_DEST (set)))
06165 return GET_CODE (SET_DEST (set)) != MEM;
06166 if (set == 0 && reg_overlap_mentioned_p (reg, PATTERN (insn)))
06167 return 0;
06168 }
06169
06170 if (code == CALL_INSN && call_used_regs[REGNO (reg)])
06171 return 1;
06172 }
06173 return 1;
06174 }
06175
06176 #include "ggc.h"
06177
06178 rtx
06179 get_fpscr_rtx ()
06180 {
06181 static rtx fpscr_rtx;
06182
06183 if (! fpscr_rtx)
06184 {
06185 fpscr_rtx = gen_rtx (REG, PSImode, FPSCR_REG);
06186 REG_USERVAR_P (fpscr_rtx) = 1;
06187 ggc_add_rtx_root (&fpscr_rtx, 1);
06188 mark_user_reg (fpscr_rtx);
06189 }
06190 if (! reload_completed || mdep_reorg_phase != SH_AFTER_MDEP_REORG)
06191 mark_user_reg (fpscr_rtx);
06192 return fpscr_rtx;
06193 }
06194
06195 void
06196 emit_sf_insn (pat)
06197 rtx pat;
06198 {
06199 emit_insn (pat);
06200 }
06201
06202 void
06203 emit_df_insn (pat)
06204 rtx pat;
06205 {
06206 emit_insn (pat);
06207 }
06208
06209 void
06210 expand_sf_unop (fun, operands)
06211 rtx (*fun) PARAMS ((rtx, rtx, rtx));
06212 rtx *operands;
06213 {
06214 emit_sf_insn ((*fun) (operands[0], operands[1], get_fpscr_rtx ()));
06215 }
06216
06217 void
06218 expand_sf_binop (fun, operands)
06219 rtx (*fun) PARAMS ((rtx, rtx, rtx, rtx));
06220 rtx *operands;
06221 {
06222 emit_sf_insn ((*fun) (operands[0], operands[1], operands[2],
06223 get_fpscr_rtx ()));
06224 }
06225
06226 void
06227 expand_df_unop (fun, operands)
06228 rtx (*fun) PARAMS ((rtx, rtx, rtx));
06229 rtx *operands;
06230 {
06231 emit_df_insn ((*fun) (operands[0], operands[1], get_fpscr_rtx ()));
06232 }
06233
06234 void
06235 expand_df_binop (fun, operands)
06236 rtx (*fun) PARAMS ((rtx, rtx, rtx, rtx));
06237 rtx *operands;
06238 {
06239 emit_df_insn ((*fun) (operands[0], operands[1], operands[2],
06240 get_fpscr_rtx ()));
06241 }
06242
06243
06244
06245
06246
06247
06248
06249
06250
06251
06252
06253
06254
06255
06256
06257
06258
06259
06260
06261
06262
06263
06264
06265
06266
06267
06268
06269
06270 static void
06271 mark_use (x, reg_set_block)
06272 rtx x, *reg_set_block;
06273 {
06274 enum rtx_code code;
06275
06276 if (! x)
06277 return;
06278 code = GET_CODE (x);
06279 switch (code)
06280 {
06281 case REG:
06282 {
06283 int regno = REGNO (x);
06284 int nregs = (regno < FIRST_PSEUDO_REGISTER
06285 ? HARD_REGNO_NREGS (regno, GET_MODE (x))
06286 : 1);
06287 do
06288 {
06289 reg_set_block[regno + nregs - 1] = 0;
06290 }
06291 while (--nregs);
06292 break;
06293 }
06294 case SET:
06295 {
06296 rtx dest = SET_DEST (x);
06297
06298 if (GET_CODE (dest) == SUBREG)
06299 dest = SUBREG_REG (dest);
06300 if (GET_CODE (dest) != REG)
06301 mark_use (dest, reg_set_block);
06302 mark_use (SET_SRC (x), reg_set_block);
06303 break;
06304 }
06305 case CLOBBER:
06306 break;
06307 default:
06308 {
06309 const char *fmt = GET_RTX_FORMAT (code);
06310 int i, j;
06311 for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
06312 {
06313 if (fmt[i] == 'e')
06314 mark_use (XEXP (x, i), reg_set_block);
06315 else if (fmt[i] == 'E')
06316 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
06317 mark_use (XVECEXP (x, i, j), reg_set_block);
06318 }
06319 break;
06320 }
06321 }
06322 }
06323
06324 static rtx get_free_reg PARAMS ((HARD_REG_SET));
06325
06326
06327
06328
06329
06330
06331
06332
06333
06334
06335
06336
06337
06338
06339
06340 static rtx
06341 get_free_reg (regs_live)
06342 HARD_REG_SET regs_live;
06343 {
06344 if (! TEST_HARD_REG_BIT (regs_live, 1))
06345 return gen_rtx_REG (Pmode, 1);
06346
06347
06348
06349 if (! TEST_HARD_REG_BIT (regs_live, 7))
06350 return gen_rtx_REG (Pmode, 7);
06351
06352 abort ();
06353 }
06354
06355
06356
06357 void
06358 fpscr_set_from_mem (mode, regs_live)
06359 int mode;
06360 HARD_REG_SET regs_live;
06361 {
06362 enum attr_fp_mode fp_mode = mode;
06363 rtx addr_reg = get_free_reg (regs_live);
06364
06365 if (fp_mode == (enum attr_fp_mode) NORMAL_MODE (FP_MODE))
06366 emit_insn (gen_fpu_switch1 (addr_reg));
06367 else
06368 emit_insn (gen_fpu_switch0 (addr_reg));
06369 }
06370
06371
06372 #ifndef IS_ASM_LOGICAL_LINE_SEPARATOR
06373 #define IS_ASM_LOGICAL_LINE_SEPARATOR(C) ((C) == ';')
06374 #endif
06375
06376 int
06377 sh_insn_length_adjustment (insn)
06378 rtx insn;
06379 {
06380
06381
06382 if (((GET_CODE (insn) == INSN
06383 && GET_CODE (PATTERN (insn)) != USE
06384 && GET_CODE (PATTERN (insn)) != CLOBBER)
06385 || GET_CODE (insn) == CALL_INSN
06386 || (GET_CODE (insn) == JUMP_INSN
06387 && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC
06388 && GET_CODE (PATTERN (insn)) != ADDR_VEC))
06389 && GET_CODE (PATTERN (NEXT_INSN (PREV_INSN (insn)))) != SEQUENCE
06390 && get_attr_needs_delay_slot (insn) == NEEDS_DELAY_SLOT_YES)
06391 return 2;
06392
06393
06394
06395 if (GET_CODE (insn) == INSN)
06396 {
06397 int sum = 0;
06398 rtx body = PATTERN (insn);
06399 const char *template;
06400 char c;
06401 int maybe_label = 1;
06402
06403 if (GET_CODE (body) == ASM_INPUT)
06404 template = XSTR (body, 0);
06405 else if (asm_noperands (body) >= 0)
06406 template
06407 = decode_asm_operands (body, NULL, NULL, NULL, NULL);
06408 else
06409 return 0;
06410 do
06411 {
06412 int ppi_adjust = 0;
06413
06414 do
06415 c = *template++;
06416 while (c == ' ' || c == '\t');
06417
06418
06419
06420 if ((c == 'p' || c == 'P') && strncasecmp ("re", template, 2))
06421 ppi_adjust = 2;
06422
06423
06424 else if ((c == 'r' || c == 'R')
06425 && ! strncasecmp ("epeat", template, 5))
06426 ppi_adjust = 4;
06427 while (c && c != '\n' && ! IS_ASM_LOGICAL_LINE_SEPARATOR (c))
06428 {
06429
06430 if (c == ':' && maybe_label)
06431 {
06432 ppi_adjust = 0;
06433 break;
06434 }
06435 else if (c == '\'' || c == '"')
06436 maybe_label = 0;
06437 c = *template++;
06438 }
06439 sum += ppi_adjust;
06440 maybe_label = c != ':';
06441 }
06442 while (c);
06443 return sum;
06444 }
06445 return 0;
06446 }
06447
06448
06449
06450 int
06451 nonpic_symbol_mentioned_p (x)
06452 rtx x;
06453 {
06454 register const char *fmt;
06455 register int i;
06456
06457 if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF
06458 || GET_CODE (x) == PC)
06459 return 1;
06460
06461
06462
06463 if (GET_CODE (x) == CONST_DOUBLE)
06464 return 0;
06465
06466 if (GET_CODE (x) == UNSPEC
06467 && (XINT (x, 1) == UNSPEC_PIC
06468 || XINT (x, 1) == UNSPEC_GOT
06469 || XINT (x, 1) == UNSPEC_GOTOFF
06470 || XINT (x, 1) == UNSPEC_GOTPLT
06471 || XINT (x, 1) == UNSPEC_PLT))
06472 return 0;
06473
06474 fmt = GET_RTX_FORMAT (GET_CODE (x));
06475 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
06476 {
06477 if (fmt[i] == 'E')
06478 {
06479 register int j;
06480
06481 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
06482 if (nonpic_symbol_mentioned_p (XVECEXP (x, i, j)))
06483 return 1;
06484 }
06485 else if (fmt[i] == 'e' && nonpic_symbol_mentioned_p (XEXP (x, i)))
06486 return 1;
06487 }
06488
06489 return 0;
06490 }
06491
06492
06493
06494 rtx
06495 legitimize_pic_address (orig, mode, reg)
06496 rtx orig;
06497 enum machine_mode mode ATTRIBUTE_UNUSED;
06498 rtx reg;
06499 {
06500 if (GET_CODE (orig) == LABEL_REF
06501 || (GET_CODE (orig) == SYMBOL_REF
06502 && (CONSTANT_POOL_ADDRESS_P (orig)
06503
06504 || SYMBOL_REF_FLAG (orig))))
06505 {
06506 if (reg == 0)
06507 reg = gen_reg_rtx (Pmode);
06508
06509 emit_insn (gen_symGOTOFF2reg (reg, orig));
06510 return reg;
06511 }
06512 else if (GET_CODE (orig) == SYMBOL_REF)
06513 {
06514 if (reg == 0)
06515 reg = gen_reg_rtx (Pmode);
06516
06517 emit_insn (gen_symGOT2reg (reg, orig));
06518 return reg;
06519 }
06520 return orig;
06521 }
06522
06523
06524
06525 static rtx mark_constant_pool_use (x)
06526 rtx x;
06527 {
06528 rtx insn, lab, pattern;
06529
06530 if (x == NULL)
06531 return x;
06532
06533 switch (GET_CODE (x))
06534 {
06535 case LABEL_REF:
06536 x = XEXP (x, 0);
06537 case CODE_LABEL:
06538 break;
06539 default:
06540 return x;
06541 }
06542
06543
06544
06545 lab = x;
06546 for (insn = PREV_INSN (x); insn; insn = PREV_INSN (insn))
06547 {
06548 if (GET_CODE (insn) != CODE_LABEL
06549 || LABEL_REFS (insn) != NEXT_INSN (insn))
06550 break;
06551 lab = insn;
06552 }
06553
06554 for (insn = LABEL_REFS (lab); insn; insn = LABEL_REFS (insn))
06555 INSN_DELETED_P (insn) = 1;
06556
06557
06558 for (insn = NEXT_INSN (x); insn; insn = NEXT_INSN (insn))
06559 {
06560 if (GET_CODE (insn) != INSN)
06561 continue;
06562
06563 pattern = PATTERN (insn);
06564 if (GET_CODE (pattern) != UNSPEC_VOLATILE)
06565 continue;
06566
06567 switch (XINT (pattern, 1))
06568 {
06569 case UNSPECV_CONST2:
06570 case UNSPECV_CONST4:
06571 case UNSPECV_CONST8:
06572 XVECEXP (pattern, 0, 1) = const1_rtx;
06573 break;
06574 case UNSPECV_WINDOW_END:
06575 if (XVECEXP (pattern, 0, 0) == x)
06576 return lab;
06577 break;
06578 case UNSPECV_CONST_END:
06579 return lab;
06580 default:
06581 break;
06582 }
06583 }
06584
06585 return lab;
06586 }
06587
06588
06589
06590
06591 int
06592 sh_can_redirect_branch (branch1, branch2)
06593 rtx branch1;
06594 rtx branch2;
06595 {
06596 if (flag_expensive_optimizations && simplejump_p (branch2))
06597 {
06598 rtx dest = XEXP (SET_SRC (single_set (branch2)), 0);
06599 rtx insn;
06600 int distance;
06601
06602 for (distance = 0, insn = NEXT_INSN (branch1);
06603 insn && distance < 256;
06604 insn = PREV_INSN (insn))
06605 {
06606 if (insn == dest)
06607 return 1;
06608 else
06609 distance += get_attr_length (insn);
06610 }
06611 for (distance = 0, insn = NEXT_INSN (branch1);
06612 insn && distance < 256;
06613 insn = NEXT_INSN (insn))
06614 {
06615 if (insn == dest)
06616 return 1;
06617 else
06618 distance += get_attr_length (insn);
06619 }
06620 }
06621 return 0;
06622 }
06623
06624 #ifndef OBJECT_FORMAT_ELF
06625 static void
06626 sh_asm_named_section (name, flags)
06627 const char *name;
06628 unsigned int flags ATTRIBUTE_UNUSED;
06629 {
06630
06631 fprintf (asm_out_file, "\t.section %s\n", name);
06632 }
06633 #endif
06634
06635
06636
06637
06638
06639
06640
06641 static int
06642 sh_adjust_cost (insn, link, dep_insn, cost)
06643 rtx insn;
06644 rtx link ATTRIBUTE_UNUSED;
06645 rtx dep_insn;
06646 int cost;
06647 {
06648 rtx reg;
06649
06650 if (GET_CODE(insn) == CALL_INSN)
06651 {
06652
06653
06654 rtx call = PATTERN (insn);
06655
06656 if (GET_CODE (call) == PARALLEL)
06657 call = XVECEXP (call, 0 ,0);
06658 if (GET_CODE (call) == SET)
06659 call = SET_SRC (call);
06660 if (GET_CODE (call) == CALL && GET_CODE (XEXP (call, 0)) == MEM
06661 && ! reg_set_p (XEXP (XEXP (call, 0), 0), dep_insn))
06662 cost = 0;
06663 }
06664
06665
06666 else if (GET_CODE (PATTERN (insn)) == PARALLEL
06667 && XVECLEN (PATTERN (insn), 0) >= 4
06668 && (reg = sfunc_uses_reg (insn)))
06669 {
06670
06671
06672
06673
06674 if (! reg_set_p (reg, dep_insn))
06675 cost -= TARGET_SUPERSCALAR ? 40 : 4;
06676 }
06677
06678
06679 else if (cost == 3
06680 && GET_CODE (PATTERN (dep_insn)) == SET
06681
06682
06683 && general_movsrc_operand (SET_SRC (PATTERN (dep_insn)), SImode))
06684 cost = 2;
06685 else if (cost == 30
06686 && GET_CODE (PATTERN (dep_insn)) == SET
06687 && GET_MODE (SET_SRC (PATTERN (dep_insn))) == SImode)
06688 cost = 20;
06689
06690 return cost;
06691 }
06692
06693
06694
06695
06696
06697 int
06698 sh_pr_n_sets ()
06699 {
06700 return REG_N_SETS (PR_REG);
06701 }
06702
06703
06704
06705 static bool
06706 sh_cannot_modify_jumps_p ()
06707 {
06708 return (TARGET_SHMEDIA && (reload_in_progress || reload_completed));
06709 }
06710
06711 static bool
06712 sh_ms_bitfield_layout_p (record_type)
06713 tree record_type ATTRIBUTE_UNUSED;
06714 {
06715 return TARGET_SH5;
06716 }