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 "coretypes.h"
00027 #include "tm.h"
00028 #include "rtl.h"
00029 #include "regs.h"
00030 #include "hard-reg-set.h"
00031 #include "real.h"
00032 #include "insn-config.h"
00033 #include "conditions.h"
00034 #include "insn-flags.h"
00035 #include "output.h"
00036 #include "insn-attr.h"
00037 #include "insn-addr.h"
00038 #include "flags.h"
00039 #include "reload.h"
00040 #include "tree.h"
00041 #include "expr.h"
00042 #include "optabs.h"
00043 #include "toplev.h"
00044 #include "obstack.h"
00045 #include "function.h"
00046 #include "recog.h"
00047 #include "tm_p.h"
00048 #include "target.h"
00049 #include "target-def.h"
00050 #include "basic-block.h"
00051
00052
00053
00054
00055
00056 #define CHAIN_FRAMES (frame_pointer_needed || FRAME_POINTER_REQUIRED)
00057
00058 static int ip2k_naked_function_p (tree);
00059 #ifdef IP2K_MD_REORG_PASS
00060 static void mdr_resequence_xy_yx (rtx);
00061 static void mdr_pres_replace_and_recurse (rtx, rtx, rtx);
00062 static void mdr_propagate_reg_equivs_sequence (rtx, rtx, rtx);
00063 static void mdr_propagate_reg_equivs (rtx);
00064 static int track_dp_reload (rtx , rtx *, int , int);
00065 static void mdr_try_dp_reload_elim (rtx);
00066 static void mdr_try_move_dp_reload (rtx);
00067 static void mdr_try_move_pushes (rtx);
00068 static void mdr_try_propagate_clr_sequence (rtx, unsigned int);
00069 static void mdr_try_propagate_clr (rtx);
00070 static void mdr_try_propagate_move_sequence (rtx, rtx, rtx);
00071 static void mdr_try_propagate_move (rtx);
00072 static void mdr_try_remove_redundant_insns (rtx);
00073 static int track_w_reload (rtx, rtx *, int , int);
00074 static void mdr_try_wreg_elim (rtx);
00075 #endif
00076 static void ip2k_reorg (void);
00077 static int ip2k_check_can_adjust_stack_ref (rtx, int);
00078 static void ip2k_adjust_stack_ref (rtx *, int);
00079 static int ip2k_xexp_not_uses_reg_for_mem (rtx, unsigned int);
00080 static tree ip2k_handle_progmem_attribute (tree *, tree, tree, int, bool *);
00081 static tree ip2k_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
00082 static bool ip2k_rtx_costs (rtx, int, int, int *);
00083 static int ip2k_address_cost (rtx);
00084 static void ip2k_init_libfuncs (void);
00085 static bool ip2k_return_in_memory (tree, tree);
00086 static void ip2k_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
00087 tree, int *, int);
00088
00089 const struct attribute_spec ip2k_attribute_table[];
00090
00091
00092
00093 #undef TARGET_ASM_ALIGNED_HI_OP
00094 #define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
00095
00096 #undef TARGET_ASM_FUNCTION_PROLOGUE
00097 #define TARGET_ASM_FUNCTION_PROLOGUE function_prologue
00098
00099 #undef TARGET_ASM_FUNCTION_EPILOGUE
00100 #define TARGET_ASM_FUNCTION_EPILOGUE function_epilogue
00101
00102 #undef TARGET_ASM_UNIQUE_SECTION
00103 #define TARGET_ASM_UNIQUE_SECTION unique_section
00104
00105 #undef TARGET_ASM_FUNCTION_RODATA_SECTION
00106 #define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
00107
00108 #undef TARGET_ATTRIBUTE_TABLE
00109 #define TARGET_ATTRIBUTE_TABLE ip2k_attribute_table
00110
00111 #undef TARGET_RTX_COSTS
00112 #define TARGET_RTX_COSTS ip2k_rtx_costs
00113 #undef TARGET_ADDRESS_COST
00114 #define TARGET_ADDRESS_COST ip2k_address_cost
00115
00116 #undef TARGET_MACHINE_DEPENDENT_REORG
00117 #define TARGET_MACHINE_DEPENDENT_REORG ip2k_reorg
00118
00119 #undef TARGET_INIT_LIBFUNCS
00120 #define TARGET_INIT_LIBFUNCS ip2k_init_libfuncs
00121
00122 #undef TARGET_RETURN_IN_MEMORY
00123 #define TARGET_RETURN_IN_MEMORY ip2k_return_in_memory
00124
00125 #undef TARGET_SETUP_INCOMING_VARARGS
00126 #define TARGET_SETUP_INCOMING_VARARGS ip2k_setup_incoming_varargs
00127
00128 struct gcc_target targetm = TARGET_INITIALIZER;
00129
00130
00131 static int prologue_size;
00132 static int epilogue_size;
00133
00134
00135
00136
00137 rtx ip2k_compare_operands[3];
00138 int ip2k_test_flag;
00139
00140
00141
00142
00143
00144
00145 static int ip2k_stack_delta;
00146
00147
00148 int ip2k_reorg_in_progress = 0;
00149 int ip2k_reorg_completed = 0;
00150 int ip2k_reorg_split_dimode = 0;
00151 int ip2k_reorg_split_simode = 0;
00152 int ip2k_reorg_split_himode = 0;
00153 int ip2k_reorg_split_qimode = 0;
00154 int ip2k_reorg_merge_qimode = 0;
00155
00156
00157
00158 void
00159 ip2k_init_local_alloc (int *rao)
00160 {
00161 static const int alloc_order[] = REG_ALLOC_ORDER;
00162
00163 memcpy (rao, alloc_order, sizeof (alloc_order));
00164 }
00165
00166
00167
00168
00169
00170
00171
00172
00173 int
00174 ip2k_return_pops_args (tree fundecl ATTRIBUTE_UNUSED, tree funtype, int size)
00175 {
00176 if (TREE_CODE (funtype) == IDENTIFIER_NODE)
00177 return size;
00178
00179 if (TYPE_ARG_TYPES (funtype) == NULL_TREE
00180 || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype))) == void_type_node))
00181 return size;
00182
00183 return 0;
00184 }
00185
00186
00187
00188 static int
00189 ip2k_naked_function_p (tree func)
00190 {
00191 tree a;
00192
00193 if (TREE_CODE (func) != FUNCTION_DECL)
00194 abort ();
00195
00196 a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
00197 return a != NULL_TREE;
00198 }
00199
00200
00201 void
00202 function_prologue (FILE *file, HOST_WIDE_INT size)
00203 {
00204 int leaf_func_p;
00205 int main_p;
00206 int reg;
00207 rtx operands[2];
00208
00209 prologue_size = epilogue_size = 0;
00210
00211 if (ip2k_naked_function_p (current_function_decl))
00212 {
00213 fprintf (file, "/* prologue: naked */\n");
00214 return;
00215 }
00216
00217 leaf_func_p = leaf_function_p ();
00218 main_p = MAIN_NAME_P (DECL_NAME (current_function_decl));
00219
00220
00221
00222
00223 prologue_size = 0;
00224 fprintf (file, "/* prologue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n",
00225 size);
00226
00227
00228
00229 if (! leaf_func_p)
00230 {
00231 OUT_AS1 (push, calll);
00232 OUT_AS1 (push, callh);
00233 prologue_size += 4;
00234 }
00235
00236
00237
00238
00239
00240
00241 if (CHAIN_FRAMES)
00242 {
00243 OUT_AS1 (push, REG_FP+1);
00244 OUT_AS2 (mov, w, spl);
00245 OUT_AS2 (mov, REG_FP+1, w);
00246
00247 OUT_AS2 (mov, w, sph);
00248 OUT_AS1 (push, REG_FP);
00249 OUT_AS2 (mov, REG_FP, w);
00250 prologue_size += 12;
00251 }
00252
00253 for (reg = (CHAIN_FRAMES) ? (REG_FP - 1) : (REG_FP + 1);
00254 reg > 0; --reg)
00255 {
00256 if (regs_ever_live[reg] && ! call_used_regs[reg])
00257 {
00258 fprintf (file, "\t" AS1 (push,%s) "\n", reg_names[reg]);
00259 prologue_size += 2;
00260 }
00261 }
00262
00263 if (size)
00264 {
00265 operands[0] = GEN_INT (size);
00266
00267 switch (size & 0xff)
00268 {
00269 case 0:
00270 break;
00271 case 1:
00272 OUT_AS1 (dec, spl);
00273 prologue_size += 2;
00274 break;
00275 default:
00276 OUT_AS2 (mov, w, %L0);
00277 OUT_AS2 (sub, spl, w);
00278 prologue_size += 4;
00279 }
00280
00281 switch (size & 0xff00)
00282 {
00283 case 0:
00284 break;
00285 case 0x100:
00286 OUT_AS1 (dec, sph);
00287 prologue_size += 2;
00288 break;
00289 default:
00290 if ((size & 0xff) != ((size >> 8) & 0xff))
00291 OUT_AS2 (mov, w, %H0);
00292 OUT_AS2 (sub, sph, w);
00293 prologue_size += 4;
00294 }
00295 }
00296
00297
00298 if (flag_stack_check)
00299 {
00300 OUT_AS2 (mov, w, sph);
00301 OUT_AS2 (cmp, w, #%%hi8data(_end));
00302 OUT_AS1 (sc, );
00303 OUT_AS1 (page, 1f);
00304 OUT_AS1 (jmp, 1f);
00305 OUT_AS1 (sz, );
00306 OUT_AS1 (page,0f);
00307 OUT_AS1 (jmp,0f);
00308 OUT_AS2 (mov, w, spl);
00309 OUT_AS2 (cmp, w, #%%lo8data(_end));
00310 OUT_AS1 (sc,);
00311 OUT_AS1 (page,1f);
00312 OUT_AS1 (jmp,1f);
00313 OUT_AS1 (0:,);
00314 output_asm_insn ("push\t$ff", operands);
00315 OUT_AS1 (system,);
00316 OUT_AS1 (1:, );
00317 prologue_size += 30;
00318 }
00319 }
00320
00321
00322 void
00323 function_epilogue (FILE *file, HOST_WIDE_INT size)
00324 {
00325 int leaf_func_p;
00326 int reg,savelimit;
00327 rtx operands[2];
00328 int args_locals_size = current_function_args_size;
00329 int saved_regs_p = 0;
00330 int need_ret = 1;
00331
00332
00333 ip2k_reorg_in_progress = 0;
00334 ip2k_reorg_completed = 0;
00335 ip2k_reorg_split_dimode = 0;
00336 ip2k_reorg_split_simode = 0;
00337 ip2k_reorg_split_himode = 0;
00338 ip2k_reorg_split_qimode = 0;
00339 ip2k_reorg_merge_qimode = 0;
00340
00341 if (ip2k_naked_function_p (current_function_decl))
00342 {
00343 fprintf (file, "/* epilogue: naked */\n");
00344 return;
00345 }
00346
00347 leaf_func_p = leaf_function_p ();
00348 epilogue_size = 0;
00349 fprintf (file, "/* epilogue: frame size=" HOST_WIDE_INT_PRINT_DEC " */\n",
00350 size);
00351
00352 savelimit = (CHAIN_FRAMES) ? REG_FP : (REG_FP + 2);
00353 for (reg = 0; reg < savelimit; reg++)
00354 if (regs_ever_live[reg] && ! call_used_regs[reg])
00355 {
00356 saved_regs_p = 1;
00357 break;
00358 }
00359
00360 if (size)
00361 {
00362 if (leaf_func_p && !CHAIN_FRAMES && !saved_regs_p
00363 && current_function_pops_args)
00364 args_locals_size = current_function_args_size + size;
00365 else
00366 {
00367 operands[0] = GEN_INT (size);
00368
00369 switch (size & 0xff)
00370 {
00371 default:
00372 OUT_AS2 (mov, w, %L0);
00373 OUT_AS2 (add, spl, w);
00374 epilogue_size += 4;
00375
00376 case 0:
00377 break;
00378 case 1:
00379 OUT_AS1 (inc, spl);
00380 epilogue_size += 2;
00381 }
00382
00383 switch (size & 0xff00)
00384 {
00385 default:
00386 if ((size & 0xff) != ((size >> 8) & 0xff))
00387 OUT_AS2 (mov, w, %H0);
00388 OUT_AS2 (add, sph, w);
00389 epilogue_size += 4;
00390
00391 case 0:
00392 break;
00393 case 0x100:
00394 OUT_AS1 (inc, sph);
00395 epilogue_size += 2;
00396 }
00397 }
00398 }
00399
00400 for (reg = 0; reg < savelimit; reg++)
00401 {
00402 if (regs_ever_live[reg] && ! call_used_regs[reg])
00403 {
00404 fprintf (file, "\t" AS1 (pop,%s) "\n", reg_names[reg]);
00405 prologue_size += 2;
00406 }
00407 }
00408
00409 if (CHAIN_FRAMES
00410 && ! (current_function_pops_args
00411 && current_function_args_size >= 2
00412 && current_function_args_size < 0x100))
00413 {
00414 OUT_AS1 (pop, REG_FP);
00415 OUT_AS1 (pop, REG_FP+1);
00416 epilogue_size += 4;
00417 }
00418
00419 if (! leaf_func_p)
00420 {
00421 if (current_function_pops_args
00422 && current_function_args_size >= 2
00423 && current_function_args_size < 0x100)
00424 {
00425 if (current_function_args_size == 2)
00426 {
00427 if (CHAIN_FRAMES)
00428 {
00429 OUT_AS1 (page, __fp_pop2_args_ret);
00430 OUT_AS1 (jmp, __fp_pop2_args_ret);
00431 }
00432 else
00433 {
00434 OUT_AS1 (page, __pop2_args_ret);
00435 OUT_AS1 (jmp, __pop2_args_ret);
00436 }
00437 epilogue_size += 4;
00438 }
00439 else
00440 {
00441 operands[0] = GEN_INT (current_function_args_size);
00442 OUT_AS2 (mov, w, %L0);
00443 if (CHAIN_FRAMES)
00444 {
00445 OUT_AS1 (page, __fp_pop_args_ret);
00446 OUT_AS1 (jmp, __fp_pop_args_ret);
00447 }
00448 else
00449 {
00450 OUT_AS1 (page, __pop_args_ret);
00451 OUT_AS1 (jmp, __pop_args_ret);
00452 }
00453 epilogue_size += 6;
00454 }
00455 need_ret = 0;
00456 }
00457 else
00458 {
00459 OUT_AS1 (pop, callh);
00460 OUT_AS1 (pop, calll);
00461 epilogue_size += 4;
00462 }
00463 }
00464 else
00465 {
00466 if (current_function_pops_args
00467 && args_locals_size >= 2
00468 && args_locals_size < 0x100)
00469 {
00470 if (args_locals_size == 2)
00471 {
00472 if (CHAIN_FRAMES)
00473 {
00474 OUT_AS1 (page, __leaf_fp_pop2_args_ret);
00475 OUT_AS1 (jmp, __leaf_fp_pop2_args_ret);
00476 epilogue_size += 4;
00477 need_ret = 0;
00478 }
00479 }
00480 else
00481 {
00482 operands[0] = GEN_INT (args_locals_size);
00483 if (CHAIN_FRAMES)
00484 {
00485 OUT_AS2 (mov, w, %L0);
00486 OUT_AS1 (page, __leaf_fp_pop_args_ret);
00487 OUT_AS1 (jmp, __leaf_fp_pop_args_ret);
00488 epilogue_size += 6;
00489 need_ret = 0;
00490 }
00491 }
00492 }
00493 }
00494
00495 if (current_function_pops_args && args_locals_size && need_ret)
00496 {
00497 operands[0] = GEN_INT (args_locals_size);
00498
00499 switch (args_locals_size & 0xff)
00500 {
00501 default:
00502 OUT_AS2 (mov, w, %L0);
00503 OUT_AS2 (add, spl, w);
00504 epilogue_size += 4;
00505
00506
00507 case 0:
00508 break;
00509
00510 case 1:
00511 OUT_AS1 (inc, spl);
00512 epilogue_size += 2;
00513 }
00514
00515 switch (args_locals_size & 0xff00)
00516 {
00517 default:
00518 if ((args_locals_size & 0xff) != ((args_locals_size >> 8) & 0xff))
00519 OUT_AS2 (mov, w, %H0);
00520 OUT_AS2 (add, sph, w);
00521 epilogue_size += 4;
00522
00523
00524 case 0:
00525 break;
00526
00527 case 0x100:
00528 OUT_AS1 (inc, sph);
00529 epilogue_size += 2;
00530 }
00531 }
00532
00533 if (need_ret)
00534 {
00535 OUT_AS1 (ret,);
00536 epilogue_size += 2;
00537 }
00538
00539 fprintf (file, "/* epilogue end (size=%d) */\n", epilogue_size);
00540 }
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556 int
00557 ip2k_init_elim_offset (int from, int to)
00558 {
00559 int leaf_func_p = leaf_function_p ();
00560 int no_saved_pc = leaf_func_p
00561 || ip2k_naked_function_p (current_function_decl);
00562 int offset;
00563 int reg;
00564 int reglimit;
00565
00566 if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
00567 return get_frame_size () + 1;
00568
00569 if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
00570 return (CHAIN_FRAMES ? 2 : 0) + (no_saved_pc ? 0 : 2);
00571
00572
00573
00574 reglimit = CHAIN_FRAMES ? REG_FP : (REG_FP + 2);
00575 for (offset = 0,reg = 0; reg < reglimit; ++reg)
00576 {
00577 if ((regs_ever_live[reg] && ! call_used_regs[reg]))
00578 {
00579 ++offset;
00580 }
00581 }
00582
00583 if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
00584 return -offset;
00585
00586 if (from == HARD_FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
00587
00588 return offset + get_frame_size () + 1;
00589
00590 if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
00591
00592 return offset + get_frame_size () + 1
00593 + (CHAIN_FRAMES ? 2 : 0) + (no_saved_pc ? 0 : 2);
00594
00595 abort ();
00596 }
00597
00598
00599
00600
00601 int
00602 legitimate_address_p (enum machine_mode mode, rtx x, int strict)
00603 {
00604 int off;
00605
00606 if (GET_CODE (x) == SUBREG)
00607 x = SUBREG_REG (x);
00608
00609 switch (GET_CODE (x))
00610 {
00611 case REG:
00612
00613
00614 if (REGNO (x) == REG_IP)
00615 return (GET_MODE_SIZE (mode) == 1) ? 'R' : 0;
00616
00617
00618 if (strict ? REG_OK_FOR_BASE_STRICT_P (x)
00619 : REG_OK_FOR_BASE_NOSTRICT_P (x))
00620 return 'S';
00621 break;
00622
00623 case PLUS:
00624
00625 {
00626 rtx op1, op2;
00627
00628 op1 = XEXP (x, 0);
00629 op2 = XEXP (x, 1);
00630
00631 if (REG_P (op2) && ! REG_P (op1))
00632 {
00633 rtx tmp = op1;
00634 op1 = op2;
00635 op2 = tmp;
00636 }
00637
00638
00639 if (! REG_P (op1)
00640 || REG_P (op2)
00641 || GET_CODE (op2) != CONST_INT)
00642 return 0;
00643
00644 switch (REGNO (op1))
00645 {
00646 case REG_DP:
00647 case REG_SP:
00648 off = 2 * GET_MODE_SIZE (mode);
00649 if (! off)
00650 off = 1;
00651
00652 if (INTVAL (op2) < 0 || INTVAL (op2) > (128 - off))
00653 return 0;
00654
00655 return 'S';
00656
00657 case REG_IP:
00658 if (GET_MODE_SIZE (mode) <= 1 && INTVAL (op2) == 0)
00659 return (GET_MODE_SIZE (mode) == 1) ? 'R' : 0;
00660 return 0;
00661
00662 case REG_AP:
00663 case REG_FP:
00664 case REG_VFP:
00665 default:
00666 if (strict || ! REG_OK_FOR_BASE_NOSTRICT_P (op1))
00667 return 0;
00668
00669 return 'S';
00670 }
00671 }
00672 break;
00673
00674 case CONST:
00675 case SYMBOL_REF:
00676
00677 return is_regfile_address (x) ? 0 : 'C';
00678
00679 case LABEL_REF:
00680 return 'L';
00681
00682 default:
00683 return 0;
00684 }
00685
00686 return 0;
00687 }
00688
00689
00690 int
00691 ip2k_mode_dependent_address (rtx addr)
00692 {
00693 switch (GET_CODE (addr))
00694 {
00695 case POST_INC:
00696 case POST_DEC:
00697 case PRE_INC:
00698 case PRE_DEC:
00699 return 1;
00700
00701 case REG:
00702 return (REGNO (addr) == REG_IP);
00703
00704 default:
00705 return 0;
00706 }
00707 }
00708
00709
00710
00711
00712 rtx
00713 legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
00714 enum machine_mode mode ATTRIBUTE_UNUSED, rtx scratch)
00715 {
00716 rtx reg;
00717
00718
00719
00720
00721
00722
00723
00724 if (GET_CODE (x) == PLUS && REG_P (XEXP (x, 0))
00725 && GET_CODE (XEXP (x, 1)) == CONST_INT
00726 && ! CONST_OK_FOR_LETTER_P (INTVAL (XEXP (x, 1)), 'K'))
00727 {
00728 int offset = INTVAL (XEXP (x, 1));
00729
00730 reg = scratch ? scratch : gen_reg_rtx (Pmode);
00731
00732 emit_insn (gen_rtx_SET (VOIDmode, reg,
00733 gen_rtx_PLUS (Pmode, XEXP (x, 0),
00734 GEN_INT (offset & 0xffc0))));
00735 x = gen_rtx_PLUS (Pmode, reg, GEN_INT (offset & 0x3f));
00736 }
00737
00738 return x;
00739 }
00740
00741
00742
00743
00744 int
00745 is_regfile_address (rtx x)
00746 {
00747 while (1)
00748 switch (GET_CODE (x))
00749 {
00750 case SYMBOL_REF:
00751 return ! SYMBOL_REF_FUNCTION_P (x);
00752 case CONST:
00753 case PLUS:
00754 x = XEXP (x, 0);
00755 break;
00756 case CONST_INT:
00757 case REG:
00758 case SUBREG:
00759 return 1;
00760 case LABEL_REF:
00761 return 0;
00762 default:
00763 return 0;
00764 }
00765
00766 return 0;
00767 }
00768
00769
00770
00771 void
00772 print_operand_address (FILE *file, rtx addr)
00773 {
00774 switch (GET_CODE (addr))
00775 {
00776 case SUBREG:
00777 addr = alter_subreg (&addr);
00778
00779
00780 case REG:
00781 fprintf (file, "(%s)",
00782 REGNO (addr) == REG_DP ? "DP"
00783 : REGNO (addr) == REG_SP ? "SP"
00784 : REGNO (addr) == REG_IP ? "IP"
00785 : REGNO (addr) == REG_VFP ? "VFP"
00786 : REGNO (addr) == REG_AP ? "AP"
00787 : reg_names[REGNO (addr)]);
00788 break;
00789
00790 case PRE_DEC:
00791 case POST_INC:
00792 abort ();
00793 break;
00794
00795 case CONST:
00796 addr = XEXP (addr, 0);
00797 print_operand_address (file, XEXP (addr, 0));
00798 fprintf (file, "+");
00799 print_operand_address (file, XEXP (addr, 1));
00800 return;
00801
00802 case LO_SUM:
00803 if (is_regfile_address (XEXP (addr, 1)))
00804 fprintf (file, "%%lo8data(");
00805 else
00806 fprintf (file, "%%lo8insn(");
00807 print_operand_address (file, XEXP (addr, 1));
00808 fprintf (file, ")");
00809 print_operand_address (file, XEXP (addr, 0));
00810 break;
00811
00812 case PLUS:
00813 if (XEXP (addr, 1) == const0_rtx
00814 && GET_CODE (XEXP (addr, 0)) == PLUS)
00815 {
00816 print_operand_address (file, XEXP (addr, 0));
00817 return;
00818 }
00819
00820 if (! REG_P (XEXP (addr, 0)) || REGNO (XEXP (addr, 0)) != REG_IP)
00821 print_operand_address (file, XEXP (addr, 1));
00822 print_operand_address (file, XEXP (addr, 0));
00823 break;
00824
00825 case HIGH:
00826 if (is_regfile_address (XEXP (addr, 0)))
00827 fprintf (file, "%%hi8data(");
00828 else
00829 fprintf (file, "%%hi8insn(");
00830 output_addr_const (file, XEXP (addr, 0));
00831 fprintf (file, ")");
00832 break;
00833
00834 default:
00835 output_addr_const (file, addr);
00836 }
00837 }
00838
00839
00840
00841
00842 void
00843 print_operand (FILE *file, rtx x, int code)
00844 {
00845 int abcd = 0;
00846 unsigned long value;
00847
00848 switch (code)
00849 {
00850 case '<':
00851 ip2k_stack_delta++;
00852 return;
00853
00854 case '>':
00855 ip2k_stack_delta--;
00856 return;
00857
00858 case 'A':
00859 case 'B':
00860 case 'C':
00861 case 'D':
00862 abcd = code - 'A';
00863 break;
00864
00865 case 'H':
00866 abcd = 0;
00867 break;
00868
00869 case 'L':
00870 abcd = 1;
00871 break;
00872
00873 case 'S':
00874 case 'T':
00875 case 'U':
00876 case 'V':
00877 case 'W':
00878 case 'X':
00879 case 'Y':
00880 case 'Z':
00881 abcd = code - 'S';
00882
00883 default:
00884 break;
00885 }
00886
00887 if (ip2k_short_operand (x, GET_MODE (x))
00888 && ip2k_address_uses_reg_p (x, REG_SP))
00889
00890
00891
00892 abcd += ip2k_stack_delta;
00893
00894 switch (GET_CODE (x))
00895 {
00896 case SUBREG:
00897 x = alter_subreg (&x);
00898
00899
00900 case REG:
00901 fprintf (file, reg_names[true_regnum (x) + abcd]);
00902 break;
00903
00904 case CONST_INT:
00905 switch (code)
00906 {
00907 case 'x':
00908 fprintf (file, "$%x", (int)(INTVAL (x) & 0xffff));
00909 break;
00910
00911 case 'b':
00912 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
00913 break;
00914
00915 case 'e':
00916 fprintf (file, "#%d", 1 << INTVAL (x));
00917 break;
00918
00919 case 'A':
00920 case 'B':
00921 case 'C':
00922 case 'D':
00923 value = INTVAL (x);
00924 value >>= 8 * (3 - abcd);
00925 value &= 0xff;
00926
00927 fprintf (file, "#%ld", value);
00928 break;
00929
00930 case 'H':
00931 fprintf (file, "#%d", (int)((INTVAL (x) >> 8) & 0xff));
00932 break;
00933
00934 case 'L':
00935 fprintf (file, "#%d", (int)(INTVAL (x) & 0xff));
00936 break;
00937
00938 case 'S':
00939 case 'T':
00940 case 'U':
00941 case 'V':
00942 case 'W':
00943 case 'X':
00944 case 'Y':
00945 case 'Z':
00946 value = ((unsigned long long)INTVAL (x)) >> (8 * (7 - abcd)) & 0xff;
00947 fprintf (file, "#%ld", value);
00948 break;
00949
00950 default:
00951 fprintf (file, "#" HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
00952 }
00953 break;
00954
00955 case SYMBOL_REF:
00956 case LABEL_REF:
00957 case CODE_LABEL:
00958 case CONST:
00959 switch (code)
00960 {
00961 case 'A':
00962 case 'B':
00963 case 'C':
00964 case 'D':
00965 case 'S':
00966 case 'T':
00967 case 'U':
00968 case 'V':
00969 case 'W':
00970 case 'X':
00971 case 'Y':
00972 case 'Z':
00973 abort ();
00974 break;
00975
00976 case 'H':
00977 fprintf (file, "#%s(",
00978 is_regfile_address (x) ? "%hi8data"
00979 : "%hi8insn");
00980 print_operand_address (file, x);
00981 fputc (')', file);
00982 break;
00983
00984 case 'L':
00985 fprintf (file, "#%s(",
00986 is_regfile_address (x) ? "%lo8data"
00987 : "%lo8insn");
00988 print_operand_address (file, x);
00989 fputc (')', file);
00990 break;
00991
00992 default:
00993 print_operand_address (file, x);
00994 }
00995 break;
00996
00997 case MEM:
00998 {
00999 rtx addr = XEXP (x, 0);
01000
01001 if (GET_CODE (addr) == SUBREG)
01002 addr = alter_subreg (&x);
01003
01004 if (CONSTANT_P (addr) && abcd)
01005 {
01006 fputc ('(', file);
01007 print_operand_address (file, addr);
01008 fprintf (file, ")+%d", abcd);
01009 }
01010 else if (abcd)
01011 {
01012 switch (GET_CODE (addr))
01013 {
01014 case PLUS:
01015 abcd += INTVAL (XEXP (addr, 1));
01016
01017
01018
01019 if (GET_CODE (XEXP (addr, 0)) == PLUS)
01020 {
01021 addr = XEXP (addr, 0);
01022 abcd += INTVAL (XEXP (addr, 1));
01023 }
01024
01025 fprintf (file, "%d", abcd);
01026 print_operand_address (file, XEXP (addr, 0));
01027 break;
01028
01029 case REG:
01030 default:
01031 fprintf (file, "%d", abcd);
01032 print_operand_address (file, addr);
01033 }
01034 }
01035 else if (GET_CODE (addr) == REG
01036 && (REGNO (addr) == REG_DP || REGNO (addr) == REG_SP))
01037 {
01038 fprintf (file, "0");
01039 print_operand_address (file, addr);
01040 }
01041 else
01042 print_operand_address (file, addr);
01043 }
01044 break;
01045
01046 case CONST_DOUBLE:
01047
01048 if (GET_MODE (x) == VOIDmode)
01049 {
01050 switch (code)
01051 {
01052 case 'S':
01053 case 'T':
01054 case 'U':
01055 case 'V':
01056 value = CONST_DOUBLE_HIGH (x);
01057 value >>= 8 * (3 - abcd);
01058 value &= 0xff;
01059
01060 fprintf (file, "#%ld", value);
01061 break;
01062
01063 case 'W':
01064 case 'X':
01065 case 'Y':
01066 case 'Z':
01067 value = CONST_DOUBLE_LOW (x);
01068 value >>= 8 * (7 - abcd);
01069 value &= 0xff;
01070
01071 fprintf (file, "#%ld", value);
01072 break;
01073 }
01074
01075 }
01076 else
01077 {
01078 REAL_VALUE_TYPE rv;
01079
01080 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
01081 REAL_VALUE_TO_TARGET_SINGLE (rv, value);
01082 fprintf (file, "0x%lx", value);
01083 }
01084 break;
01085
01086 default:
01087 fatal_insn ("bad operand", x);
01088 }
01089 }
01090
01091
01092 const char *
01093 ip2k_set_compare (rtx x, rtx y)
01094 {
01095 ip2k_compare_operands[0] = x;
01096 ip2k_compare_operands[1] = y;
01097 return "";
01098 }
01099
01100
01101 const char *
01102 ip2k_gen_sCOND (rtx insn ATTRIBUTE_UNUSED, enum rtx_code code, rtx dest)
01103 {
01104 #define operands ip2k_compare_operands
01105 enum machine_mode mode;
01106
01107 operands[2] = dest;
01108
01109 mode = GET_MODE (operands[0]);
01110 if ((mode != QImode) && (mode != HImode)
01111 && (mode != SImode) && (mode != DImode))
01112 mode = GET_MODE (operands[1]);
01113
01114
01115
01116
01117 if (mode == QImode
01118 && !rtx_equal_p (operands[0], operands[2])
01119 && !rtx_equal_p (operands[1], operands[2])
01120 && (! REG_P (operands[2])
01121 || (ip2k_xexp_not_uses_reg_p (operands[0], REGNO (operands[2]), 1)
01122 && ip2k_xexp_not_uses_reg_p (operands[1],
01123 REGNO (operands[2]), 1))))
01124 {
01125 OUT_AS1 (clr, %2);
01126 if (immediate_operand (operands[1], QImode)
01127 && ((INTVAL (operands[1]) & 0xff) == 0xff))
01128 {
01129 if (code == EQ)
01130 OUT_AS2 (incsnz, w, %0);
01131 else
01132 OUT_AS2 (incsz, w, %0);
01133 }
01134 else if (immediate_operand (operands[1], QImode)
01135 && ((INTVAL (operands[1]) & 0xff) == 0x01))
01136 {
01137 if (code == EQ)
01138 OUT_AS2 (decsnz, w, %0);
01139 else
01140 OUT_AS2 (decsz, w, %0);
01141 }
01142 else if (ip2k_compare_operands[1] == const0_rtx)
01143 {
01144 OUT_AS2 (mov, w, %0);
01145 if (code == EQ)
01146 OUT_AS1 (snz,);
01147 else
01148 OUT_AS1 (sz,);
01149 }
01150 else
01151 {
01152 OUT_AS2 (mov, w, %0);
01153 if (code == EQ)
01154 OUT_AS2 (csne, w, %1);
01155 else
01156 OUT_AS2 (cse, w, %1);
01157 }
01158 OUT_AS1 (inc, %2);
01159 }
01160 else
01161 {
01162 if (ip2k_compare_operands[1] == const0_rtx)
01163 {
01164 switch (mode)
01165 {
01166 case QImode:
01167 OUT_AS2 (mov, w, %0);
01168 break;
01169
01170 case HImode:
01171 OUT_AS2 (mov, w, %H0);
01172 OUT_AS2 (or, w, %L0);
01173 break;
01174
01175 case SImode:
01176 OUT_AS2 (mov, w, %A0);
01177 OUT_AS2 (or, w, %B0);
01178 OUT_AS2 (or, w, %C0);
01179 OUT_AS2 (or, w, %D0);
01180 break;
01181
01182 case DImode:
01183 OUT_AS2 (mov, w, %S0);
01184 OUT_AS2 (or, w, %T0);
01185 OUT_AS2 (or, w, %U0);
01186 OUT_AS2 (or, w, %V0);
01187 OUT_AS2 (or, w, %W0);
01188 OUT_AS2 (or, w, %X0);
01189 OUT_AS2 (or, w, %Y0);
01190 OUT_AS2 (or, w, %Z0);
01191 break;
01192
01193 default:
01194 abort ();
01195 }
01196 }
01197 else
01198 {
01199 switch (mode)
01200 {
01201 case QImode:
01202 OUT_AS2 (mov, w, %1);
01203 OUT_AS2 (cmp, w, %0);
01204 break;
01205
01206 case HImode:
01207 OUT_AS2 (mov, w, %H1);
01208 OUT_AS2 (cmp, w, %H0);
01209 OUT_AS1 (sz,);
01210 OUT_AS1 (page, 2f);
01211 OUT_AS1 (jmp, 2f);
01212 OUT_AS2 (mov, w, %L1);
01213 OUT_AS2 (cmp, w, %L0);
01214 OUT_AS1 (2:,);
01215 break;
01216
01217 case SImode:
01218 if (code == EQ)
01219 {
01220 OUT_AS2 (mov, w, #1);
01221 OUT_AS2 (mov, mulh, w);
01222 }
01223 else
01224 OUT_AS1 (clr, mulh);
01225 OUT_AS2 (mov, w, %A1);
01226 OUT_AS2 (cse, w, %A0);
01227 OUT_AS1 (page, 2f);
01228 OUT_AS1 (jmp, 2f);
01229 OUT_AS2 (mov, w, %B1);
01230 OUT_AS2 (cse, w, %B0);
01231 OUT_AS1 (page, 2f);
01232 OUT_AS1 (jmp, 2f);
01233 OUT_AS2 (mov, w, %C1);
01234 OUT_AS2 (cse, w, %C0);
01235 OUT_AS1 (page, 2f);
01236 OUT_AS1 (jmp, 2f);
01237 OUT_AS2 (mov, w, %D1);
01238 OUT_AS2 (cse, w, %D0);
01239 OUT_AS1 (2:,);
01240 if (code == EQ)
01241 OUT_AS1 (dec, mulh);
01242 else
01243 OUT_AS1 (inc, mulh);
01244 OUT_AS2 (mov, w, mulh);
01245 OUT_AS2 (mov, %2, w);
01246 return "";
01247
01248 case DImode:
01249 if (code == EQ)
01250 {
01251 OUT_AS2 (mov, w, #1);
01252 OUT_AS2 (mov, mulh, w);
01253 }
01254 else
01255 OUT_AS1 (clr, mulh);
01256 OUT_AS2 (mov, w, %S1);
01257 OUT_AS2 (cse, w, %S0);
01258 OUT_AS1 (page, 2f);
01259 OUT_AS1 (jmp, 2f);
01260 OUT_AS2 (mov, w, %T1);
01261 OUT_AS2 (cse, w, %T0);
01262 OUT_AS1 (page, 2f);
01263 OUT_AS1 (jmp, 2f);
01264 OUT_AS2 (mov, w, %U1);
01265 OUT_AS2 (cse, w, %U0);
01266 OUT_AS1 (page, 2f);
01267 OUT_AS1 (jmp, 2f);
01268 OUT_AS2 (mov, w, %V1);
01269 OUT_AS2 (cse, w, %V0);
01270 OUT_AS1 (page, 2f);
01271 OUT_AS1 (jmp, 2f);
01272 OUT_AS2 (mov, w, %W1);
01273 OUT_AS2 (cse, w, %W0);
01274 OUT_AS1 (page, 2f);
01275 OUT_AS1 (jmp, 2f);
01276 OUT_AS2 (mov, w, %X1);
01277 OUT_AS2 (cse, w, %X0);
01278 OUT_AS1 (page, 2f);
01279 OUT_AS1 (jmp, 2f);
01280 OUT_AS2 (mov, w, %Y1);
01281 OUT_AS2 (cse, w, %Y0);
01282 OUT_AS1 (page, 2f);
01283 OUT_AS1 (jmp, 2f);
01284 OUT_AS2 (mov, w, %Z1);
01285 OUT_AS2 (cse, w, %Z0);
01286 OUT_AS1 (2:,);
01287 if (code == EQ)
01288 OUT_AS1 (dec, mulh);
01289 else
01290 OUT_AS1 (inc, mulh);
01291 OUT_AS2 (mov, w, mulh);
01292 OUT_AS2 (mov, %2, w);
01293 return "";
01294
01295 default:
01296 abort ();
01297 }
01298 }
01299 OUT_AS2 (mov, w, #0);
01300 if (code == EQ)
01301 OUT_AS1 (snz,);
01302 else
01303 OUT_AS1 (sz,);
01304 OUT_AS1 (inc, wreg);
01305 OUT_AS2 (mov, %2, w);
01306 }
01307
01308 return "";
01309 #undef operands
01310 }
01311
01312 const char *
01313 ip2k_gen_signed_comp_branch (rtx insn, enum rtx_code code, rtx label)
01314 {
01315 #define operands ip2k_compare_operands
01316 enum machine_mode mode;
01317 int can_use_skip = 0;
01318 rtx ninsn;
01319
01320 operands[2] = label;
01321
01322 mode = GET_MODE (operands[0]);
01323 if ((mode != QImode) && (mode != HImode)
01324 && (mode != SImode) && (mode != DImode))
01325 mode = GET_MODE (operands[1]);
01326
01327
01328
01329 ninsn = next_real_insn (insn);
01330 if (ninsn
01331 && (recog_memoized (ninsn) >= 0)
01332 && get_attr_skip (ninsn) == SKIP_YES)
01333 {
01334 rtx skip_tgt = next_nonnote_insn (next_real_insn (insn));
01335
01336
01337
01338
01339 if (label == skip_tgt)
01340 can_use_skip = 1;
01341 else
01342 {
01343
01344
01345
01346 if (GET_CODE (skip_tgt) == CODE_LABEL)
01347 skip_tgt = next_nonnote_insn (skip_tgt);
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360 if (GET_CODE (skip_tgt) == JUMP_INSN)
01361 {
01362 rtx set = single_set (skip_tgt);
01363 if (GET_CODE (XEXP (set, 0)) == PC
01364 && GET_CODE (XEXP (set, 1)) == LABEL_REF
01365 && label == JUMP_LABEL (skip_tgt))
01366 can_use_skip = 2;
01367 }
01368 }
01369 }
01370
01371
01372
01373
01374 extract_constrain_insn_cached (insn);
01375
01376 if (ip2k_compare_operands[1] == const0_rtx)
01377 {
01378 switch (code)
01379 {
01380 case LT:
01381 if (can_use_skip)
01382 {
01383 OUT_AS2 (sb, %0, 7);
01384 }
01385 else
01386 {
01387 OUT_AS2 (snb, %0, 7);
01388 OUT_AS1 (page, %2);
01389 OUT_AS1 (jmp, %2);
01390 }
01391 break;
01392
01393 case GT:
01394 switch (mode)
01395 {
01396 case DImode:
01397 OUT_AS2 (rl, w, %S0);
01398 OUT_AS2 (mov, w, %S0);
01399 OUT_AS2 (or, w, %T0);
01400 OUT_AS2 (or, w, %U0);
01401 OUT_AS2 (or, w, %V0);
01402 OUT_AS2 (or, w, %W0);
01403 OUT_AS2 (or, w, %X0);
01404 OUT_AS2 (or, w, %Y0);
01405 OUT_AS2 (or, w, %Z0);
01406 OUT_AS1 (snz, );
01407 OUT_AS2 (setb, status, 0);
01408 OUT_AS2 (sb, status, 0);
01409 OUT_AS1 (page, %2);
01410 OUT_AS1 (jmp, %2);
01411 break;
01412
01413 case SImode:
01414 OUT_AS2 (rl, w, %A0);
01415 OUT_AS2 (mov, w, %A0);
01416 OUT_AS2 (or, w, %B0);
01417 OUT_AS2 (or, w, %C0);
01418 OUT_AS2 (or, w, %D0);
01419 OUT_AS1 (snz, );
01420 OUT_AS2 (setb, status, 0);
01421 OUT_AS2 (sb, status, 0);
01422 OUT_AS1 (page, %2);
01423 OUT_AS1 (jmp, %2);
01424 break;
01425
01426 case HImode:
01427 OUT_AS2 (rl, w, %H0);
01428 OUT_AS2 (mov, w, %H0);
01429 OUT_AS2 (or, w, %L0);
01430 OUT_AS1 (snz, );
01431 OUT_AS2 (setb, status, 0);
01432 OUT_AS2 (sb, status, 0);
01433 OUT_AS1 (page, %2);
01434 OUT_AS1 (jmp, %2);
01435 break;
01436
01437 case QImode:
01438 OUT_AS2 (mov, w, %0);
01439 OUT_AS1 (snz, );
01440 OUT_AS2 (setb, wreg, 7);
01441 OUT_AS2 (sb, wreg, 7);
01442 OUT_AS1 (page, %2);
01443 OUT_AS1 (jmp, %2);
01444 break;
01445
01446 default:
01447 abort ();
01448 }
01449 break;
01450
01451 case LE:
01452 switch (mode)
01453 {
01454 case DImode:
01455 OUT_AS2 (mov, w, %S0);
01456 OUT_AS2 (or, w, %T0);
01457 OUT_AS2 (or, w, %U0);
01458 OUT_AS2 (or, w, %V0);
01459 OUT_AS2 (or, w, %W0);
01460 OUT_AS2 (or, w, %X0);
01461 OUT_AS2 (or, w, %Y0);
01462 OUT_AS2 (or, w, %Z0);
01463 OUT_AS1 (sz, );
01464 OUT_AS2 (snb, %S0, 7);
01465 OUT_AS1 (page, %2);
01466 OUT_AS1 (jmp, %2);
01467 break;
01468
01469 case SImode:
01470 OUT_AS2 (mov, w, %A0);
01471 OUT_AS2 (or, w, %B0);
01472 OUT_AS2 (or, w, %C0);
01473 OUT_AS2 (or, w, %D0);
01474 OUT_AS1 (sz, );
01475 OUT_AS2 (snb, %A0, 7);
01476 OUT_AS1 (page, %2);
01477 OUT_AS1 (jmp, %2);
01478 break;
01479
01480 case HImode:
01481 OUT_AS2 (mov, w, %H0);
01482 OUT_AS2 (or, w, %L0);
01483 OUT_AS1 (sz, );
01484 OUT_AS2 (snb, %H0, 7);
01485 OUT_AS1 (page, %2);
01486 OUT_AS1 (jmp, %2);
01487 break;
01488
01489 case QImode:
01490 OUT_AS2 (mov, w, %0);
01491 OUT_AS1 (sz, );
01492 OUT_AS2 (snb, wreg, 7);
01493 OUT_AS1 (page, %2);
01494 OUT_AS1 (jmp, %2);
01495 break;
01496
01497 default:
01498 abort ();
01499 }
01500 break;
01501
01502 case GE:
01503 if (can_use_skip)
01504 {
01505 OUT_AS2 (snb, %0, 7);
01506 }
01507 else
01508 {
01509 OUT_AS2 (sb, %0, 7);
01510 OUT_AS1 (page, %2);
01511 OUT_AS1 (jmp, %2);
01512 }
01513 break;
01514
01515 default:
01516 abort ();
01517 }
01518 return "";
01519 }
01520
01521
01522
01523
01524 switch (mode)
01525 {
01526 case QImode:
01527 OUT_AS1 (push, %1%<);
01528 OUT_AS1 (push, %0%>);
01529 OUT_AS1 (page, __cmpqi2);
01530 OUT_AS1 (call, __cmpqi2);
01531 break;
01532
01533 case HImode:
01534 OUT_AS1 (push, %L1%<);
01535 OUT_AS1 (push, %H1%<);
01536 OUT_AS1 (push, %L0%<);
01537 OUT_AS1 (push, %H0%>%>%>);
01538 OUT_AS1 (page, __cmphi2);
01539 OUT_AS1 (call, __cmphi2);
01540 break;
01541
01542 case SImode:
01543 OUT_AS1 (push, %D1%<);
01544 OUT_AS1 (push, %C1%<);
01545 OUT_AS1 (push, %B1%<);
01546 OUT_AS1 (push, %A1%<);
01547 OUT_AS1 (push, %D0%<);
01548 OUT_AS1 (push, %C0%<);
01549 OUT_AS1 (push, %B0%<);
01550 OUT_AS1 (push, %A0%>%>%>%>%>%>%>);
01551 OUT_AS1 (page, __cmpsi2);
01552 OUT_AS1 (call, __cmpsi2);
01553 break;
01554
01555 case DImode:
01556 if (GET_CODE (operands[0]) == MEM
01557 && true_regnum (XEXP (operands[0], 0)) == REG_DP)
01558 {
01559 OUT_AS1 (push, %Z1%<);
01560 OUT_AS1 (push, %Y1%<);
01561 OUT_AS1 (push, %X1%<);
01562 OUT_AS1 (push, %W1%<);
01563 OUT_AS1 (push, %V1%<);
01564 OUT_AS1 (push, %U1%<);
01565 OUT_AS1 (push, %T1%<);
01566 OUT_AS1 (push, %S1%>%>%>%>%>%>%>);
01567 OUT_AS1 (page, __cmpdi2_dp);
01568 OUT_AS1 (call, __cmpdi2_dp);
01569 }
01570 else
01571 {
01572 OUT_AS1 (push, %Z1%<);
01573 OUT_AS1 (push, %Y1%<);
01574 OUT_AS1 (push, %X1%<);
01575 OUT_AS1 (push, %W1%<);
01576 OUT_AS1 (push, %V1%<);
01577 OUT_AS1 (push, %U1%<);
01578 OUT_AS1 (push, %T1%<);
01579 OUT_AS1 (push, %S1%<);
01580 OUT_AS1 (push, %Z0%<);
01581 OUT_AS1 (push, %Y0%<);
01582 OUT_AS1 (push, %X0%<);
01583 OUT_AS1 (push, %W0%<);
01584 OUT_AS1 (push, %V0%<);
01585 OUT_AS1 (push, %U0%<);
01586 OUT_AS1 (push, %T0%<);
01587 OUT_AS1 (push, %S0%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>);
01588 OUT_AS1 (page, __cmpdi2);
01589 OUT_AS1 (call, __cmpdi2);
01590 }
01591 break;
01592
01593 default:
01594 abort ();
01595 }
01596
01597 switch (code)
01598 {
01599 case LT:
01600 if (can_use_skip)
01601 {
01602 OUT_AS2 (cse, w, #0);
01603 }
01604 else
01605 {
01606 OUT_AS2 (csne, w, #0);
01607 OUT_AS1 (page, %2);
01608 OUT_AS1 (jmp, %2);
01609 }
01610 break;
01611
01612 case GT:
01613 if (can_use_skip)
01614 {
01615 OUT_AS2 (cse, w, #2);
01616 }
01617 else
01618 {
01619 OUT_AS2 (csne, w, #2);
01620 OUT_AS1 (page, %2);
01621 OUT_AS1 (jmp, %2);
01622 }
01623 break;
01624
01625 case LE:
01626 if (can_use_skip)
01627 {
01628 OUT_AS2 (snb, wreg, 1);
01629 }
01630 else
01631 {
01632 OUT_AS2 (sb, wreg, 1);
01633 OUT_AS1 (page, %2);
01634 OUT_AS1 (jmp, %2);
01635 }
01636 break;
01637
01638 case GE:
01639 if (can_use_skip)
01640 {
01641 OUT_AS2 (csne, w, #0);
01642 }
01643 else
01644 {
01645 OUT_AS2 (cse, w, #0);
01646 OUT_AS1 (page, %2);
01647 OUT_AS1 (jmp, %2);
01648 }
01649 break;
01650
01651 default:
01652 abort ();
01653 }
01654 return "";
01655 #undef operands
01656 }
01657
01658 const char *
01659 ip2k_gen_unsigned_comp_branch (rtx insn, enum rtx_code code, rtx label)
01660 {
01661 #define operands ip2k_compare_operands
01662 enum machine_mode mode;
01663 int imm_sub = 0;
01664 int imm_cmp = 0;
01665 int can_use_skip = 0;
01666 rtx ninsn;
01667 HOST_WIDE_INT const_low;
01668 HOST_WIDE_INT const_high;
01669
01670 operands[2] = label;
01671
01672 mode = GET_MODE (operands[0]);
01673 if ((mode != QImode) && (mode != HImode) && (mode != SImode)
01674 && (mode != DImode))
01675 {
01676 mode = GET_MODE (operands[1]);
01677 }
01678
01679
01680
01681 ninsn = next_real_insn (insn);
01682 if (ninsn
01683 && (recog_memoized (ninsn) >= 0)
01684 && get_attr_skip (ninsn) == SKIP_YES)
01685 {
01686 rtx skip_tgt = next_nonnote_insn (next_real_insn (insn));
01687
01688
01689
01690
01691 if (label == skip_tgt)
01692 can_use_skip = 1;
01693 else
01694 {
01695
01696
01697
01698 if (GET_CODE (skip_tgt) == CODE_LABEL)
01699 skip_tgt = next_nonnote_insn (skip_tgt);
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712 if (GET_CODE (skip_tgt) == JUMP_INSN)
01713 {
01714 rtx set = single_set (skip_tgt);
01715 if (GET_CODE (XEXP (set, 0)) == PC
01716 && GET_CODE (XEXP (set, 1)) == LABEL_REF
01717 && label == JUMP_LABEL (skip_tgt))
01718 can_use_skip = 2;
01719 }
01720 }
01721 }
01722
01723
01724
01725
01726 extract_constrain_insn_cached (insn);
01727
01728 if (ip2k_compare_operands[1] == const0_rtx)
01729 {
01730 switch (code)
01731 {
01732 case LEU:
01733 code = EQ;
01734 goto zero;
01735
01736 case GTU:
01737 code = NE;
01738
01739
01740 case EQ:
01741 case NE:
01742
01743 zero:
01744 switch (mode)
01745 {
01746 case DImode:
01747 OUT_AS2 (mov, w, %S0);
01748 OUT_AS2 (or, w, %T0);
01749 OUT_AS2 (or, w, %U0);
01750 OUT_AS2 (or, w, %V0);
01751 OUT_AS2 (or, w, %W0);
01752 OUT_AS2 (or, w, %X0);
01753 OUT_AS2 (or, w, %Y0);
01754 OUT_AS2 (or, w, %Z0);
01755 break;
01756
01757 case SImode:
01758 OUT_AS2 (mov, w, %A0);
01759 OUT_AS2 (or, w, %B0);
01760 OUT_AS2 (or, w, %C0);
01761 OUT_AS2 (or, w, %D0);
01762 break;
01763
01764 case HImode:
01765 OUT_AS2 (mov, w, %H0);
01766 OUT_AS2 (or, w, %L0);
01767 break;
01768
01769 case QImode:
01770 OUT_AS2 (mov, w, %0);
01771 break;
01772
01773 default:
01774 abort ();
01775 }
01776
01777 if (can_use_skip)
01778 {
01779 if (code == EQ)
01780 OUT_AS1 (sz, );
01781 else
01782 OUT_AS1 (snz, );
01783 }
01784 else
01785 {
01786 if (code == EQ)
01787 OUT_AS1 (snz,);
01788 else
01789 OUT_AS1 (sz,);
01790 OUT_AS1 (page, %2);
01791 OUT_AS1 (jmp, %2);
01792 }
01793 break;
01794
01795 case GEU:
01796
01797 OUT_AS1 (page, %2);
01798 OUT_AS1 (jmp, %2);
01799 break;
01800
01801 case LTU:
01802
01803 break;
01804
01805 default:
01806 abort ();
01807 }
01808 return "";
01809 }
01810
01811
01812
01813
01814
01815 if (mode != QImode)
01816 {
01817 if ((immediate_operand (operands[1], GET_MODE (operands[1]))
01818 && ((code == LEU) || (code == GTU)))
01819 || (immediate_operand (operands[0], GET_MODE (operands[0]))
01820 && ((code == LTU) || (code == GEU))))
01821 {
01822 imm_sub = 1;
01823 }
01824 }
01825
01826
01827
01828
01829
01830 if ((code == EQ) || (code == NE))
01831 {
01832 imm_cmp = immediate_operand (operands[1], GET_MODE (operands[1]));
01833 if (! imm_cmp)
01834 {
01835 imm_cmp = immediate_operand (operands[0], GET_MODE (operands[0]));
01836 if (imm_cmp)
01837 {
01838 rtx tmp = operands[1];
01839 operands[1] = operands[0];
01840 operands[0] = tmp;
01841 }
01842 }
01843 }
01844
01845 switch (mode)
01846 {
01847 case QImode:
01848 switch (code)
01849 {
01850 case EQ:
01851 if (imm_cmp && ((INTVAL (operands[1]) & 0xff) == 0xff))
01852 OUT_AS2 (incsnz, w, %0);
01853 else if (imm_cmp && ((INTVAL (operands[1]) & 0xff) == 0x01))
01854 OUT_AS2 (decsnz, w, %0);
01855 else
01856 {
01857 OUT_AS2 (mov, w, %1);
01858 OUT_AS2 (csne, w, %0);
01859 }
01860 OUT_AS1 (page, %2);
01861 OUT_AS1 (jmp, %2);
01862 break;
01863
01864 case NE:
01865 if (imm_cmp && ((INTVAL (operands[1]) & 0xff) == 0xff))
01866 OUT_AS2 (incsz, w, %0);
01867 else if (imm_cmp && ((INTVAL (operands[1]) & 0xff) == 0x01))
01868 OUT_AS2 (decsz, w, %0);
01869 else
01870 {
01871 OUT_AS2 (mov, w, %1);
01872 OUT_AS2 (cse, w, %0);
01873 }
01874 OUT_AS1 (page, %2);
01875 OUT_AS1 (jmp, %2);
01876 break;
01877
01878 case GTU:
01879 OUT_AS2 (mov, w, %0);
01880 OUT_AS2 (cmp, w, %1);
01881 OUT_AS1 (sc,);
01882 OUT_AS1 (page, %2);
01883 OUT_AS1 (jmp, %2);
01884 break;
01885
01886 case GEU:
01887 OUT_AS2 (mov, w, %1);
01888 OUT_AS2 (cmp, w, %0);
01889 OUT_AS1 (snc,);
01890 OUT_AS1 (page, %2);
01891 OUT_AS1 (jmp, %2);
01892 break;
01893
01894 case LTU:
01895 OUT_AS2 (mov, w, %1);
01896 OUT_AS2 (cmp, w, %0);
01897 OUT_AS1 (sc,);
01898 OUT_AS1 (page, %2);
01899 OUT_AS1 (jmp, %2);
01900 break;
01901
01902 case LEU:
01903 OUT_AS2 (mov, w, %0);
01904 OUT_AS2 (cmp, w, %1);
01905 OUT_AS1 (snc,);
01906 OUT_AS1 (page, %2);
01907 OUT_AS1 (jmp, %2);
01908 break;
01909
01910 default:
01911 abort ();
01912 }
01913 break;
01914
01915 case HImode:
01916 switch (code)
01917 {
01918 case EQ:
01919 {
01920 unsigned char h = 0, l = 1;
01921
01922 if (imm_cmp)
01923 {
01924 h = (INTVAL (operands[1]) >> 8) & 0xff;
01925 l = INTVAL (operands[1]) & 0xff;
01926
01927 if ((h == 0xff) && (l == 0xff))
01928 {
01929
01930
01931
01932 OUT_AS2 (incsnz, w, %L0);
01933 OUT_AS2 (incsz, w, %H0);
01934
01935 OUT_AS1 (page, 1f);
01936 OUT_AS1 (jmp, 1f);
01937 OUT_AS1 (page, %2);
01938 OUT_AS1 (jmp, %2);
01939 OUT_AS1 (1:,);
01940 break;
01941 }
01942 else if (h == 0)
01943 {
01944 if (l == 1)
01945 OUT_AS2 (dec, w, %L0);
01946 else
01947 {
01948 OUT_AS2 (mov, w, %L0);
01949 OUT_AS2 (sub, w, %L1);
01950 }
01951 OUT_AS2 (or, w, %H0);
01952 OUT_AS1 (snz,);
01953 OUT_AS1 (page, %2);
01954 OUT_AS1 (jmp, %2);
01955 break;
01956 }
01957 else if (l == 0)
01958 {
01959 if (h == 1)
01960 OUT_AS2 (dec, w, %H0);
01961 else
01962 {
01963 OUT_AS2 (mov, w, %H0);
01964 OUT_AS2 (sub, w, %H1);
01965 }
01966 OUT_AS2 (or, w, %L0);
01967 OUT_AS1 (snz,);
01968 OUT_AS1 (page, %2);
01969 OUT_AS1 (jmp, %2);
01970 break;
01971 }
01972 }
01973
01974 OUT_AS2 (mov, w, %H1);
01975 OUT_AS2 (cse, w, %H0);
01976 OUT_AS1 (page, 2f);
01977 OUT_AS1 (jmp, 2f);
01978 if (! imm_cmp || (h != l))
01979 OUT_AS2 (mov, w, %L1);
01980 OUT_AS2 (csne, w, %L0);
01981 OUT_AS1 (page, %2);
01982 OUT_AS1 (jmp, %2);
01983 OUT_AS1 (2:,);
01984 }
01985 break;
01986
01987 case NE:
01988 {
01989 unsigned char h = 0, l = 1;
01990
01991 if (imm_cmp)
01992 {
01993 h = (INTVAL (operands[1]) >> 8) & 0xff;
01994 l = INTVAL (operands[1]) & 0xff;
01995
01996 if ((h == 0xff) && (l == 0xff))
01997 {
01998 OUT_AS2 (incsnz, w, %L0);
01999 OUT_AS2 (incsz, w, %H0);
02000 OUT_AS1 (page, %2);
02001 OUT_AS1 (jmp, %2);
02002 break;
02003 }
02004 else if (h == 0)
02005 {
02006 if (l == 1)
02007 OUT_AS2 (dec, w, %L0);
02008 else
02009 {
02010 OUT_AS2 (mov, w, %L0);
02011 OUT_AS2 (sub, w, %L1);
02012 }
02013 OUT_AS2 (or, w, %H0);
02014 OUT_AS1 (sz,);
02015 OUT_AS1 (page, %2);
02016 OUT_AS1 (jmp, %2);
02017 break;
02018 }
02019 else if (l == 0)
02020 {
02021 if (h == 1)
02022 OUT_AS2 (dec, w, %H0);
02023 else
02024 {
02025 OUT_AS2 (mov, w, %H0);
02026 OUT_AS2 (sub, w, %H1);
02027 }
02028 OUT_AS2 (or, w, %L0);
02029 OUT_AS1 (sz,);
02030 OUT_AS1 (page, %2);
02031 OUT_AS1 (jmp, %2);
02032 break;
02033 }
02034 }
02035
02036 OUT_AS2 (mov, w, %H1);
02037 if (imm_cmp && (h == l))
02038 {
02039 OUT_AS2 (csne, w, %H0);
02040 OUT_AS2 (cse, w, %L0);
02041 }
02042 else
02043 {
02044 OUT_AS2 (cse, w, %H0);
02045 OUT_AS1 (page, %2);
02046 OUT_AS1 (jmp, %2);
02047 OUT_AS2 (mov, w, %L1);
02048 OUT_AS2 (cse, w, %L0);
02049 }
02050 OUT_AS1 (page, %2);
02051 OUT_AS1 (jmp, %2);
02052 }
02053 break;
02054
02055 case GTU:
02056 if (imm_sub)
02057 {
02058
02059 if ((INTVAL (operands[1]) & 0xffff) != 0xffff)
02060 {
02061 operands[3] = GEN_INT (INTVAL (operands[1]) + 1);
02062 OUT_AS2 (mov, w, %L3);
02063 OUT_AS2 (sub, w, %L0);
02064 OUT_AS2 (mov, w, %H3);
02065 OUT_AS2 (subc, w, %H0);
02066 OUT_AS1 (snc,);
02067 OUT_AS1 (page, %2);
02068 OUT_AS1 (jmp, %2);
02069 }
02070 }
02071 else
02072 {
02073 OUT_AS2 (mov, w, %L0);
02074 OUT_AS2 (sub, w, %L1);
02075 OUT_AS2 (mov, w, %H0);
02076 OUT_AS2 (subc, w, %H1);
02077 OUT_AS1 (sc,);
02078 OUT_AS1 (page, %2);
02079 OUT_AS1 (jmp, %2);
02080 }
02081 break;
02082
02083 case GEU:
02084 if (imm_sub)
02085 {
02086 if (INTVAL (operands[0]) == 0)
02087 {
02088 OUT_AS2 (mov, w, %H1);
02089 OUT_AS2 (or, w, %L1);
02090 OUT_AS1 (snz,);
02091 OUT_AS1 (page, %2);
02092 OUT_AS1 (jmp, %2);
02093 }
02094 else
02095 {
02096 operands[3] = GEN_INT (INTVAL (operands[0]) - 1);
02097 OUT_AS2 (mov, w, %L3);
02098 OUT_AS2 (sub, w, %L1);
02099 OUT_AS2 (mov, w, %H3);
02100 OUT_AS2 (subc, w, %H1);
02101 OUT_AS1 (sc,);
02102 OUT_AS1 (page, %2);
02103 OUT_AS1 (jmp, %2);
02104 }
02105 }
02106 else
02107 {
02108 OUT_AS2 (mov, w, %L1);
02109 OUT_AS2 (sub, w, %L0);
02110 OUT_AS2 (mov, w, %H1);
02111 OUT_AS2 (subc, w, %H0);
02112 OUT_AS1 (snc,);
02113 OUT_AS1 (page, %2);
02114 OUT_AS1 (jmp, %2);
02115 }
02116 break;
02117
02118 case LTU:
02119 if (imm_sub)
02120 {
02121 if (INTVAL (operands[0]) == 0)
02122 {
02123 OUT_AS2 (mov, w, %H1);
02124 OUT_AS2 (or, w, %L1);
02125 OUT_AS1 (sz,);
02126 OUT_AS1 (page, %2);
02127 OUT_AS1 (jmp, %2);
02128 }
02129 else
02130 {
02131 operands[3] = GEN_INT (INTVAL (operands[0]) - 1);
02132 OUT_AS2 (mov, w, %L3);
02133 OUT_AS2 (sub, w, %L1);
02134 OUT_AS2 (mov, w, %H3);
02135 OUT_AS2 (subc, w, %H1);
02136 OUT_AS1 (snc,);
02137 OUT_AS1 (page, %2);
02138 OUT_AS1 (jmp, %2);
02139 }
02140 }
02141 else
02142 {
02143 OUT_AS2 (mov, w, %L1);
02144 OUT_AS2 (sub, w, %L0);
02145 OUT_AS2 (mov, w, %H1);
02146 OUT_AS2 (subc, w, %H0);
02147 OUT_AS1 (sc,);
02148 OUT_AS1 (page, %2);
02149 OUT_AS1 (jmp, %2);
02150 }
02151 break;
02152
02153 case LEU:
02154 if (imm_sub)
02155 {
02156 if ((INTVAL (operands[1]) & 0xffff) == 0xffff)
02157 {
02158
02159 OUT_AS1 (page, %2);
02160 OUT_AS1 (jmp, %2);
02161 }
02162 else
02163 {
02164 operands[3] = GEN_INT (INTVAL (operands[1]) + 1);
02165 OUT_AS2 (mov, w, %L3);
02166 OUT_AS2 (sub, w, %L0);
02167 OUT_AS2 (mov, w, %H3);
02168 OUT_AS2 (subc, w, %H0);
02169 OUT_AS1 (sc,);
02170 OUT_AS1 (page, %2);
02171 OUT_AS1 (jmp, %2);
02172 }
02173 }
02174 else
02175 {
02176 OUT_AS2 (mov, w, %L0);
02177 OUT_AS2 (sub, w, %L1);
02178 OUT_AS2 (mov, w, %H0);
02179 OUT_AS2 (subc, w, %H1);
02180 OUT_AS1 (snc,);
02181 OUT_AS1 (page, %2);
02182 OUT_AS1 (jmp, %2);
02183 }
02184 break;
02185
02186 default:
02187 abort ();
02188 }
02189 break;
02190
02191 case SImode:
02192 switch (code)
02193 {
02194 case EQ:
02195 {
02196 unsigned char a = 0, b = 1, c = 2, d = 3;
02197
02198 if (imm_cmp)
02199 {
02200 a = (INTVAL (operands[1]) >> 24) & 0xff;
02201 b = (INTVAL (operands[1]) >> 16) & 0xff;
02202 c = (INTVAL (operands[1]) >> 8) & 0xff;
02203 d = INTVAL (operands[1]) & 0xff;
02204 }
02205
02206 OUT_AS2 (mov, w, %A1);
02207 if (imm_cmp && (b == a))
02208 {
02209 OUT_AS2 (csne, w, %A0);
02210 OUT_AS2 (cse, w, %B0);
02211 }
02212 else
02213 {
02214 OUT_AS2 (cse, w, %A0);
02215 OUT_AS1 (page, 2f);
02216 OUT_AS1 (jmp, 2f);
02217 OUT_AS2 (mov, w, %B1);
02218 OUT_AS2 (cse, w, %B0);
02219 }
02220 OUT_AS1 (page, 2f);
02221 OUT_AS1 (jmp, 2f);
02222 if (! imm_cmp || (c != b))
02223 OUT_AS2 (mov, w, %C1);
02224 OUT_AS2 (cse, w, %C0);
02225 OUT_AS1 (page, 2f);
02226 OUT_AS1 (jmp, 2f);
02227 if (! imm_cmp || (d != c))
02228 OUT_AS2 (mov, w, %D1);
02229 OUT_AS2 (csne, w, %D0);
02230 OUT_AS1 (page, %2);
02231 OUT_AS1 (jmp, %2);
02232 OUT_AS1 (2:,);
02233 }
02234 break;
02235
02236 case NE:
02237 {
02238 unsigned char a = 0, b = 1, c = 2, d = 3;
02239
02240 if (imm_cmp)
02241 {
02242 a = (INTVAL (operands[1]) >> 24) & 0xff;
02243 b = (INTVAL (operands[1]) >> 16) & 0xff;
02244 c = (INTVAL (operands[1]) >> 8) & 0xff;
02245 d = INTVAL (operands[1]) & 0xff;
02246 }
02247
02248 OUT_AS2 (mov, w, %A1);
02249 if (imm_cmp && (b == a))
02250 {
02251 OUT_AS2 (csne, w, %A0);
02252 OUT_AS2 (cse, w, %B0);
02253 }
02254 else
02255 {
02256 OUT_AS2 (cse, w, %A0);
02257 OUT_AS1 (page, %2);
02258 OUT_AS1 (jmp, %2);
02259 OUT_AS2 (mov, w, %B1);
02260 OUT_AS2 (cse, w, %B0);
02261 }
02262 OUT_AS1 (page, %2);
02263 OUT_AS1 (jmp, %2);
02264 if (! imm_cmp || (c != b))
02265 OUT_AS2 (mov, w, %C1);
02266 if (imm_cmp && (d == c))
02267 {
02268 OUT_AS2 (csne, w, %C0);
02269 OUT_AS2 (cse, w, %D0);
02270 }
02271 else
02272 {
02273 OUT_AS2 (cse, w, %C0);
02274 OUT_AS1 (page, %2);
02275 OUT_AS1 (jmp, %2);
02276 OUT_AS2 (mov, w, %D1);
02277 OUT_AS2 (cse, w, %D0);
02278 }
02279 OUT_AS1 (page, %2);
02280 OUT_AS1 (jmp, %2);
02281 }
02282 break;
02283
02284 case GTU:
02285 if (imm_sub)
02286 {
02287
02288 if ((unsigned HOST_WIDE_INT)(INTVAL (operands[1]) & 0xffffffff)
02289 != 0xffffffff)
02290 {
02291 operands[3] = GEN_INT (INTVAL (operands[1]) + 1);
02292 OUT_AS2 (mov, w, %D3);
02293 OUT_AS2 (sub, w, %D0);
02294 OUT_AS2 (mov, w, %C3);
02295 OUT_AS2 (subc, w, %C0);
02296 OUT_AS2 (mov, w, %B3);
02297 OUT_AS2 (subc, w, %B0);
02298 OUT_AS2 (mov, w, %A3);
02299 OUT_AS2 (subc, w, %A0);
02300 OUT_AS1 (snc,);
02301 OUT_AS1 (page, %2);
02302 OUT_AS1 (jmp, %2);
02303 }
02304 }
02305 else
02306 {
02307 OUT_AS2 (mov, w, %D0);
02308 OUT_AS2 (sub, w, %D1);
02309 OUT_AS2 (mov, w, %C0);
02310 OUT_AS2 (subc, w, %C1);
02311 OUT_AS2 (mov, w, %B0);
02312 OUT_AS2 (subc, w, %B1);
02313 OUT_AS2 (mov, w, %A0);
02314 OUT_AS2 (subc, w, %A1);
02315 OUT_AS1 (sc,);
02316 OUT_AS1 (page, %2);
02317 OUT_AS1 (jmp, %2);
02318 }
02319 break;
02320
02321 case GEU:
02322 if (imm_sub)
02323 {
02324 if (INTVAL (operands[0]) == 0)
02325 {
02326 OUT_AS2 (mov, w, %A1);
02327 OUT_AS2 (or, w, %B1);
02328 OUT_AS2 (or, w, %C1);
02329 OUT_AS2 (or, w, %D1);
02330 OUT_AS1 (snz,);
02331 OUT_AS1 (page, %2);
02332 OUT_AS1 (jmp, %2);
02333 }
02334 else
02335 {
02336 operands[3] = GEN_INT (INTVAL (operands[0]) - 1);
02337 OUT_AS2 (mov, w, %D3);
02338 OUT_AS2 (sub, w, %D1);
02339 OUT_AS2 (mov, w, %C3);
02340 OUT_AS2 (subc, w, %C1);
02341 OUT_AS2 (mov, w, %B3);
02342 OUT_AS2 (subc, w, %B1);
02343 OUT_AS2 (mov, w, %A3);
02344 OUT_AS2 (subc, w, %A1);
02345 OUT_AS1 (sc,);
02346 OUT_AS1 (page, %2);
02347 OUT_AS1 (jmp, %2);
02348 }
02349 }
02350 else
02351 {
02352 OUT_AS2 (mov, w, %D1);
02353 OUT_AS2 (sub, w, %D0);
02354 OUT_AS2 (mov, w, %C1);
02355 OUT_AS2 (subc, w, %C0);
02356 OUT_AS2 (mov, w, %B1);
02357 OUT_AS2 (subc, w, %B0);
02358 OUT_AS2 (mov, w, %A1);
02359 OUT_AS2 (subc, w, %A0);
02360 OUT_AS1 (snc,);
02361 OUT_AS1 (page, %2);
02362 OUT_AS1 (jmp, %2);
02363 }
02364 break;
02365
02366 case LTU:
02367 if (imm_sub)
02368 {
02369 if (INTVAL (operands[0]) == 0)
02370 {
02371 OUT_AS2 (mov, w, %A1);
02372 OUT_AS2 (or, w, %B1);
02373 OUT_AS2 (or, w, %C1);
02374 OUT_AS2 (or, w, %D1);
02375 OUT_AS1 (sz,);
02376 OUT_AS1 (page, %2);
02377 OUT_AS1 (jmp, %2);
02378 }
02379 else
02380 {
02381 operands[3] = GEN_INT (INTVAL (operands[0]) - 1);
02382 OUT_AS2 (mov, w, %D3);
02383 OUT_AS2 (sub, w, %D1);
02384 OUT_AS2 (mov, w, %C3);
02385 OUT_AS2 (subc, w, %C1);
02386 OUT_AS2 (mov, w, %B3);
02387 OUT_AS2 (subc, w, %B1);
02388 OUT_AS2 (mov, w, %A3);
02389 OUT_AS2 (subc, w, %A1);
02390 OUT_AS1 (snc,);
02391 OUT_AS1 (page, %2);
02392 OUT_AS1 (jmp, %2);
02393 }
02394 }
02395 else
02396 {
02397 OUT_AS2 (mov, w, %D1);
02398 OUT_AS2 (sub, w, %D0);
02399 OUT_AS2 (mov, w, %C1);
02400 OUT_AS2 (subc, w, %C0);
02401 OUT_AS2 (mov, w, %B1);
02402 OUT_AS2 (subc, w, %B0);
02403 OUT_AS2 (mov, w, %A1);
02404 OUT_AS2 (subc, w, %A0);
02405 OUT_AS1 (sc,);
02406 OUT_AS1 (page, %2);
02407 OUT_AS1 (jmp, %2);
02408 }
02409 break;
02410
02411 case LEU:
02412 if (imm_sub)
02413 {
02414 if ((unsigned HOST_WIDE_INT)(INTVAL (operands[1]) & 0xffffffff)
02415 == 0xffffffff)
02416 {
02417
02418 OUT_AS1 (page, %2);
02419 OUT_AS1 (jmp, %2);
02420 }
02421 else
02422 {
02423 operands[3] = GEN_INT (INTVAL (operands[1]) + 1);
02424 OUT_AS2 (mov, w, %D3);
02425 OUT_AS2 (sub, w, %D0);
02426 OUT_AS2 (mov, w, %C3);
02427 OUT_AS2 (subc, w, %C0);
02428 OUT_AS2 (mov, w, %B3);
02429 OUT_AS2 (subc, w, %B0);
02430 OUT_AS2 (mov, w, %A3);
02431 OUT_AS2 (subc, w, %A0);
02432 OUT_AS1 (sc,);
02433 OUT_AS1 (page, %2);
02434 OUT_AS1 (jmp, %2);
02435 }
02436 }
02437 else
02438 {
02439 OUT_AS2 (mov, w, %D0);
02440 OUT_AS2 (sub, w, %D1);
02441 OUT_AS2 (mov, w, %C0);
02442 OUT_AS2 (subc, w, %C1);
02443 OUT_AS2 (mov, w, %B0);
02444 OUT_AS2 (subc, w, %B1);
02445 OUT_AS2 (mov, w, %A0);
02446 OUT_AS2 (subc, w, %A1);
02447 OUT_AS1 (snc,);
02448 OUT_AS1 (page, %2);
02449 OUT_AS1 (jmp, %2);
02450 }
02451 break;
02452
02453 default:
02454 abort ();
02455 }
02456 break;
02457
02458 case DImode:
02459 if (GET_CODE (operands[1]) == CONST_INT)
02460 {
02461 const_low = INTVAL (operands[1]);
02462 const_high = (const_low >= 0) - 1;
02463 }
02464 else if (GET_CODE (operands[1]) == CONST_DOUBLE)
02465 {
02466 const_low = CONST_DOUBLE_LOW (operands[1]);
02467 const_high = CONST_DOUBLE_HIGH (operands[1]);
02468 }
02469 switch (code)
02470 {
02471 case EQ:
02472 {
02473 unsigned char s = 0, t = 1, u = 2, v = 3;
02474 unsigned char w = 4, x = 5, y = 6, z = 7;
02475 if (optimize_size)
02476 {
02477 if (GET_CODE (operands[0]) == MEM
02478 && true_regnum (XEXP (operands[0], 0)) == REG_DP)
02479 {
02480 OUT_AS1 (push, %Z1%<);
02481 OUT_AS1 (push, %Y1%<);
02482 OUT_AS1 (push, %X1%<);
02483 OUT_AS1 (push, %W1%<);
02484 OUT_AS1 (push, %V1%<);
02485 OUT_AS1 (push, %U1%<);
02486 OUT_AS1 (push, %T1%<);
02487 OUT_AS1 (push, %S1%>%>%>%>%>%>%>);
02488 OUT_AS1 (page, __cmpdi2_dp);
02489 OUT_AS1 (call, __cmpdi2_dp);
02490 OUT_AS2 (csne, w, #1);
02491 OUT_AS1 (page, %2);
02492 OUT_AS1 (jmp, %2);
02493 }
02494 else
02495 {
02496 OUT_AS1 (push, %Z1%<);
02497 OUT_AS1 (push, %Y1%<);
02498 OUT_AS1 (push, %X1%<);
02499 OUT_AS1 (push, %W1%<);
02500 OUT_AS1 (push, %V1%<);
02501 OUT_AS1 (push, %U1%<);
02502 OUT_AS1 (push, %T1%<);
02503 OUT_AS1 (push, %S1%<);
02504 OUT_AS1 (push, %Z0%<);
02505 OUT_AS1 (push, %Y0%<);
02506 OUT_AS1 (push, %X0%<);
02507 OUT_AS1 (push, %W0%<);
02508 OUT_AS1 (push, %V0%<);
02509 OUT_AS1 (push, %U0%<);
02510 OUT_AS1 (push, %T0%<);
02511 OUT_AS1 (push, %S0%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>);
02512 OUT_AS1 (page, __cmpdi2);
02513 OUT_AS1 (call, __cmpdi2);
02514 OUT_AS2 (csne, w, #1);
02515 OUT_AS1 (page, %2);
02516 OUT_AS1 (jmp, %2);
02517 }
02518 }
02519 else
02520 {
02521 if (imm_cmp)
02522 {
02523 s = (const_high >> 24) & 0xff;
02524 t = (const_high >> 16) & 0xff;
02525 u = (const_high >> 8) & 0xff;
02526 v = const_high & 0xff;
02527 w = (const_low >> 24) & 0xff;
02528 x = (const_low >> 16) & 0xff;
02529 y = (const_low >> 8) & 0xff;
02530 z = const_low & 0xff;
02531 }
02532
02533 OUT_AS2 (mov, w, %S1);
02534 if (imm_cmp && (s == t))
02535 {
02536 OUT_AS2 (csne, w, %S0);
02537 OUT_AS2 (cse, w, %T0);
02538 }
02539 else
02540 {
02541 OUT_AS2 (cse, w, %S0);
02542 OUT_AS1 (page, 2f);
02543 OUT_AS1 (jmp, 2f);
02544 OUT_AS2 (mov, w, %T1);
02545 OUT_AS2 (cse, w, %T0);
02546 }
02547 OUT_AS1 (page, 2f);
02548 OUT_AS1 (jmp, 2f);
02549
02550 OUT_AS2 (mov, w, %U1);
02551 if (imm_cmp && (u == v))
02552 {
02553 OUT_AS2 (csne, w, %U0);
02554 OUT_AS2 (cse, w, %V0);
02555 }
02556 else
02557 {
02558 OUT_AS2 (cse, w, %U0);
02559 OUT_AS1 (page, 2f);
02560 OUT_AS1 (jmp, 2f);
02561 OUT_AS2 (mov, w, %V1);
02562 OUT_AS2 (cse, w, %V0);
02563 }
02564 OUT_AS1 (page, 2f);
02565 OUT_AS1 (jmp, 2f);
02566
02567 OUT_AS2 (mov, w, %W1);
02568 if (imm_cmp && (w == x))
02569 {
02570 OUT_AS2 (csne, w, %W0);
02571 OUT_AS2 (cse, w, %X0);
02572 }
02573 else
02574 {
02575 OUT_AS2 (cse, w, %W0);
02576 OUT_AS1 (page, 2f);
02577 OUT_AS1 (jmp, 2f);
02578 OUT_AS2 (mov, w, %X1);
02579 OUT_AS2 (cse, w, %X0);
02580 }
02581 OUT_AS1 (page, 2f);
02582 OUT_AS1 (jmp, 2f);
02583
02584 if (! imm_cmp || (x != y))
02585 OUT_AS2 (mov, w, %Y1);
02586 OUT_AS2 (cse, w, %Y0);
02587 OUT_AS1 (page, 2f);
02588 OUT_AS1 (jmp, 2f);
02589 if (! imm_cmp || (z != y))
02590 OUT_AS2 (mov, w, %Z1);
02591 OUT_AS2 (csne, w, %Z0);
02592 OUT_AS1 (page, %2);
02593 OUT_AS1 (jmp, %2);
02594 OUT_AS1 (2:,);
02595 }
02596 }
02597 break;
02598
02599 case NE:
02600 {
02601 unsigned char s = 0, t = 1, u = 2, v = 3;
02602 unsigned char w = 4, x = 5, y = 6, z = 7;
02603
02604 if (optimize_size)
02605 {
02606 if (GET_CODE (operands[0]) == MEM
02607 && true_regnum (XEXP (operands[0], 0)) == REG_DP)
02608 {
02609 OUT_AS1 (push, %Z1%<);
02610 OUT_AS1 (push, %Y1%<);
02611 OUT_AS1 (push, %X1%<);
02612 OUT_AS1 (push, %W1%<);
02613 OUT_AS1 (push, %V1%<);
02614 OUT_AS1 (push, %U1%<);
02615 OUT_AS1 (push, %T1%<);
02616 OUT_AS1 (push, %S1%>%>%>%>%>%>%>);
02617 OUT_AS1 (page, __cmpdi2_dp);
02618 OUT_AS1 (call, __cmpdi2_dp);
02619 OUT_AS2 (cse, w, #1);
02620 OUT_AS1 (page, %2);
02621 OUT_AS1 (jmp, %2);
02622 }
02623 else
02624 {
02625 OUT_AS1 (push, %Z1%<);
02626 OUT_AS1 (push, %Y1%<);
02627 OUT_AS1 (push, %X1%<);
02628 OUT_AS1 (push, %W1%<);
02629 OUT_AS1 (push, %V1%<);
02630 OUT_AS1 (push, %U1%<);
02631 OUT_AS1 (push, %T1%<);
02632 OUT_AS1 (push, %S1%<);
02633 OUT_AS1 (push, %Z0%<);
02634 OUT_AS1 (push, %Y0%<);
02635 OUT_AS1 (push, %X0%<);
02636 OUT_AS1 (push, %W0%<);
02637 OUT_AS1 (push, %V0%<);
02638 OUT_AS1 (push, %U0%<);
02639 OUT_AS1 (push, %T0%<);
02640 OUT_AS1 (push, %S0%>%>%>%>%>%>%>%>%>%>%>%>%>%>%>);
02641 OUT_AS1 (page, __cmpdi2);
02642 OUT_AS1 (call, __cmpdi2);
02643 OUT_AS2 (cse, w, #1);
02644 OUT_AS1 (page, %2);
02645 OUT_AS1 (jmp, %2);
02646 }
02647 }
02648 else
02649 {
02650 if (imm_cmp)
02651 {
02652 s = (const_high >> 24) & 0xff;
02653 t = (const_high >> 16) & 0xff;
02654 u = (const_high >> 8) & 0xff;
02655 v = const_high & 0xff;
02656 w = (const_low >> 24) & 0xff;
02657 x = (const_low >> 16) & 0xff;
02658 y = (const_low >> 8) & 0xff;
02659 z = const_low & 0xff;
02660 }
02661
02662 OUT_AS2 (mov, w, %S1);
02663 if (imm_cmp && (s == t))
02664 {
02665 OUT_AS2 (csne, w, %S0);
02666 OUT_AS2 (cse, w, %T0);
02667 }
02668 else
02669 {
02670 OUT_AS2 (cse, w, %S0);
02671 OUT_AS1 (page, %2);
02672 OUT_AS1 (jmp, %2);
02673 OUT_AS2 (mov, w, %T1);
02674 OUT_AS2 (cse, w, %T0);
02675 }
02676 OUT_AS1 (page, %2);
02677 OUT_AS1 (jmp, %2);
02678
02679 OUT_AS2 (mov, w, %U1);
02680 if (imm_cmp && (u == v))
02681 {
02682 OUT_AS2 (csne, w, %U0);
02683 OUT_AS2 (cse, w, %V0);
02684 }
02685 else
02686 {
02687 OUT_AS2 (cse, w, %U0);
02688 OUT_AS1 (page, %2);
02689 OUT_AS1 (jmp, %2);
02690 OUT_AS2 (mov, w, %V1);
02691 OUT_AS2 (cse, w, %V0);
02692 }
02693 OUT_AS1 (page, %2);
02694 OUT_AS1 (jmp, %2);
02695
02696 OUT_AS2 (mov, w, %W1);
02697 if (imm_cmp && (w == x))
02698 {
02699 OUT_AS2 (csne, w, %W0);
02700 OUT_AS2 (cse, w, %X0);
02701 }
02702 else
02703 {
02704 OUT_AS2 (cse, w, %W0);
02705 OUT_AS1 (page, %2);
02706 OUT_AS1 (jmp, %2);
02707 OUT_AS2 (mov, w, %X1);
02708 OUT_AS2 (cse, w, %X0);
02709 }
02710 OUT_AS1 (page, %2);
02711 OUT_AS1 (jmp, %2);
02712
02713 if (! imm_cmp || (y != x))
02714 OUT_AS2 (mov, w, %Y1);
02715 if (imm_cmp && (z == y))
02716 {
02717 OUT_AS2 (csne, w, %Y0);
02718 OUT_AS2 (cse, w, %Z0);
02719 }
02720 else
02721 {
02722 OUT_AS2 (cse, w, %Y0);
02723 OUT_AS1 (page, %2);
02724 OUT_AS1 (jmp, %2);
02725 OUT_AS2 (mov, w, %Z1);
02726 OUT_AS2 (cse, w, %Z0);
02727 }
02728 OUT_AS1 (page, %2);
02729 OUT_AS1 (jmp, %2);
02730 }
02731 }
02732 break;
02733
02734 case GTU:
02735 if (imm_sub)
02736 {
02737
02738 if (((const_high & 0xffffffff) != 0xffffffff)
02739 || ((const_low & 0xffffffff) != 0xffffffff))
02740 {
02741 operands[3] = GEN_INT (const_low + 1);
02742 operands[4] = GEN_INT (const_high
02743 + (INTVAL (operands[3]) ? 0 : 1));
02744 OUT_AS2 (mov, w, %D3);
02745 OUT_AS2 (sub, w, %Z0);
02746 OUT_AS2 (mov, w, %C3);
02747 OUT_AS2 (subc, w, %Y0);
02748 OUT_AS2 (mov, w, %B3);
02749 OUT_AS2 (subc, w, %X0);
02750 OUT_AS2 (mov, w, %A3);
02751 OUT_AS2 (subc, w, %W0);
02752 OUT_AS2 (mov, w, %D4);
02753 OUT_AS2 (subc, w, %V0);
02754 OUT_AS2 (mov, w, %C4);
02755 OUT_AS2 (subc, w, %U0);
02756 OUT_AS2 (mov, w, %B4);
02757 OUT_AS2 (subc, w, %T0);
02758 OUT_AS2 (mov, w, %A4);
02759 OUT_AS2 (subc, w, %S0);
02760 OUT_AS1 (snc,);
02761 OUT_AS1 (page, %2);
02762 OUT_AS1 (jmp, %2);
02763 }
02764 }
02765 else
02766 {
02767 OUT_AS2 (mov, w, %Z0);
02768 OUT_AS2 (sub, w, %Z1);
02769 OUT_AS2 (mov, w, %Y0);
02770 OUT_AS2 (subc, w, %Y1);
02771 OUT_AS2 (mov, w, %X0);
02772 OUT_AS2 (subc, w, %X1);
02773 OUT_AS2 (mov, w, %W0);
02774 OUT_AS2 (subc, w, %W1);
02775 OUT_AS2 (mov, w, %V0);
02776 OUT_AS2 (subc, w, %V1);
02777 OUT_AS2 (mov, w, %U0);
02778 OUT_AS2 (subc, w, %U1);
02779 OUT_AS2 (mov, w, %T0);
02780 OUT_AS2 (subc, w, %T1);
02781 OUT_AS2 (mov, w, %S0);
02782 OUT_AS2 (subc, w, %S1);
02783 OUT_AS1 (sc,);
02784 OUT_AS1 (page, %2);
02785 OUT_AS1 (jmp, %2);
02786 }
02787 break;
02788
02789 case GEU:
02790 if (imm_sub)
02791 {
02792 HOST_WIDE_INT const_low0;
02793 HOST_WIDE_INT const_high0;
02794
02795 if (GET_CODE (operands[0]) == CONST_INT)
02796 {
02797 const_low0 = INTVAL (operands[0]);
02798 const_high0 = (const_low >= 0) - 1;
02799 }
02800 else if (GET_CODE (operands[0]) == CONST_DOUBLE)
02801 {
02802 const_low0 = CONST_DOUBLE_LOW (operands[0]);
02803 const_high0 = CONST_DOUBLE_HIGH (operands[0]);
02804 }
02805
02806 if (const_high0 == 0 && const_low0 == 0)
02807 {
02808 OUT_AS2 (mov, w, %S1);
02809 OUT_AS2 (or, w, %T1);
02810 OUT_AS2 (or, w, %U1);
02811 OUT_AS2 (or, w, %V1);
02812 OUT_AS2 (or, w, %W1);
02813 OUT_AS2 (or, w, %X1);
02814 OUT_AS2 (or, w, %Y1);
02815 OUT_AS2 (or, w, %Z1);
02816 OUT_AS1 (snz,);
02817 OUT_AS1 (page, %2);
02818 OUT_AS1 (jmp, %2);
02819 }
02820 else
02821 {
02822 operands[3] = GEN_INT (const_low0 - 1);
02823 operands[4] = GEN_INT (const_high0 - (const_low0 ? 1 : 0));
02824 OUT_AS2 (mov, w, %D3);
02825 OUT_AS2 (sub, w, %Z1);
02826 OUT_AS2 (mov, w, %C3);
02827 OUT_AS2 (subc, w, %Y1);
02828 OUT_AS2 (mov, w, %B3);
02829 OUT_AS2 (subc, w, %X1);
02830 OUT_AS2 (mov, w, %A3);
02831 OUT_AS2 (subc, w, %W1);
02832 OUT_AS2 (mov, w, %D4);
02833 OUT_AS2 (subc, w, %V1);
02834 OUT_AS2 (mov, w, %C4);
02835 OUT_AS2 (subc, w, %U1);
02836 OUT_AS2 (mov, w, %B4);
02837 OUT_AS2 (subc, w, %T1);
02838 OUT_AS2 (mov, w, %A4);
02839 OUT_AS2 (subc, w, %S1);
02840 OUT_AS1 (sc,);
02841 OUT_AS1 (page, %2);
02842 OUT_AS1 (jmp, %2);
02843 }
02844 }
02845 else
02846 {
02847 OUT_AS2 (mov, w, %Z1);
02848 OUT_AS2 (sub, w, %Z0);
02849 OUT_AS2 (mov, w, %Y1);
02850 OUT_AS2 (subc, w, %Y0);
02851 OUT_AS2 (mov, w, %X1);
02852 OUT_AS2 (subc, w, %X0);
02853 OUT_AS2 (mov, w, %W1);
02854 OUT_AS2 (subc, w, %W0);
02855 OUT_AS2 (mov, w, %V1);
02856 OUT_AS2 (subc, w, %V0);
02857 OUT_AS2 (mov, w, %U1);
02858 OUT_AS2 (subc, w, %U0);
02859 OUT_AS2 (mov, w, %T1);
02860 OUT_AS2 (subc, w, %T0);
02861 OUT_AS2 (mov, w, %S1);
02862 OUT_AS2 (subc, w, %S0);
02863 OUT_AS1 (snc,);
02864 OUT_AS1 (page, %2);
02865 OUT_AS1 (jmp, %2);
02866 }
02867 break;
02868
02869 case LTU:
02870 if (imm_sub)
02871 {
02872 HOST_WIDE_INT const_low0;
02873 HOST_WIDE_INT const_high0;
02874
02875 if (GET_CODE (operands[0]) == CONST_INT)
02876 {
02877 const_low0 = INTVAL (operands[0]);
02878 const_high0 = (const_low >= 0) - 1;
02879 }
02880 else if (GET_CODE (operands[0]) == CONST_DOUBLE)
02881 {
02882 const_low0 = CONST_DOUBLE_LOW (operands[0]);
02883 const_high0 = CONST_DOUBLE_HIGH (operands[0]);
02884 }
02885
02886 if (const_high0 == 0 && const_low0 == 0)
02887 {
02888 OUT_AS2 (mov, w, %S1);
02889 OUT_AS2 (or, w, %T1);
02890 OUT_AS2 (or, w, %U1);
02891 OUT_AS2 (or, w, %V1);
02892 OUT_AS2 (or, w, %W1);
02893 OUT_AS2 (or, w, %X1);
02894 OUT_AS2 (or, w, %Y1);
02895 OUT_AS2 (or, w, %Z1);
02896 OUT_AS1 (sz,);
02897 OUT_AS1 (page, %2);
02898 OUT_AS1 (jmp, %2);
02899 }
02900 else
02901 {
02902 operands[3] = GEN_INT (const_low0 - 1);
02903 operands[4] = GEN_INT (const_high0 - (const_low0 ? 1 : 0));
02904 OUT_AS2 (mov, w, %D3);
02905 OUT_AS2 (sub, w, %Z1);
02906 OUT_AS2 (mov, w, %C3);
02907 OUT_AS2 (subc, w, %Y1);
02908 OUT_AS2 (mov, w, %B3);
02909 OUT_AS2 (subc, w, %X1);
02910 OUT_AS2 (mov, w, %A3);
02911 OUT_AS2 (subc, w, %W1);
02912 OUT_AS2 (mov, w, %D4);
02913 OUT_AS2 (subc, w, %V1);
02914 OUT_AS2 (mov, w, %C4);
02915 OUT_AS2 (subc, w, %U1);
02916 OUT_AS2 (mov, w, %B4);
02917 OUT_AS2 (subc, w, %T1);
02918 OUT_AS2 (mov, w, %A4);
02919 OUT_AS2 (subc, w, %S1);
02920 OUT_AS1 (snc,);
02921 OUT_AS1 (page, %2);
02922 OUT_AS1 (jmp, %2);
02923 }
02924 }
02925 else
02926 {
02927 OUT_AS2 (mov, w, %Z1);
02928 OUT_AS2 (sub, w, %Z0);
02929 OUT_AS2 (mov, w, %Y1);
02930 OUT_AS2 (subc, w, %Y0);
02931 OUT_AS2 (mov, w, %X1);
02932 OUT_AS2 (subc, w, %X0);
02933 OUT_AS2 (mov, w, %W1);
02934 OUT_AS2 (subc, w, %W0);
02935 OUT_AS2 (mov, w, %V1);
02936 OUT_AS2 (subc, w, %V0);
02937 OUT_AS2 (mov, w, %U1);
02938 OUT_AS2 (subc, w, %U0);
02939 OUT_AS2 (mov, w, %T1);
02940 OUT_AS2 (subc, w, %T0);
02941 OUT_AS2 (mov, w, %S1);
02942 OUT_AS2 (subc, w, %S0);
02943 OUT_AS1 (sc,);
02944 OUT_AS1 (page, %2);
02945 OUT_AS1 (jmp, %2);
02946 }
02947 break;
02948
02949 case LEU:
02950 if (imm_sub)
02951 {
02952 if (((const_high & 0xffffffff) == 0xffffffff)
02953 && ((const_low & 0xffffffff) == 0xffffffff))
02954 {
02955
02956 OUT_AS1 (page, %2);
02957 OUT_AS1 (jmp, %2);
02958 }
02959 else
02960 {
02961 operands[3] = GEN_INT (const_low + 1);
02962 operands[4] = GEN_INT (const_high
02963 + (INTVAL (operands[3]) ? 0 : 1));
02964 OUT_AS2 (mov, w, %D3);
02965 OUT_AS2 (sub, w, %Z0);
02966 OUT_AS2 (mov, w, %C3);
02967 OUT_AS2 (subc, w, %Y0);
02968 OUT_AS2 (mov, w, %B3);
02969 OUT_AS2 (subc, w, %X0);
02970 OUT_AS2 (mov, w, %A3);
02971 OUT_AS2 (subc, w, %W0);
02972 OUT_AS2 (mov, w, %D4);
02973 OUT_AS2 (subc, w, %V0);
02974 OUT_AS2 (mov, w, %C4);
02975 OUT_AS2 (subc, w, %U0);
02976 OUT_AS2 (mov, w, %B4);
02977 OUT_AS2 (subc, w, %T0);
02978 OUT_AS2 (mov, w, %A4);
02979 OUT_AS2 (subc, w, %S0);
02980 OUT_AS1 (sc,);
02981 OUT_AS1 (page, %2);
02982 OUT_AS1 (jmp, %2);
02983 }
02984 }
02985 else
02986 {
02987 OUT_AS2 (mov, w, %Z0);
02988 OUT_AS2 (sub, w, %Z1);
02989 OUT_AS2 (mov, w, %Y0);
02990 OUT_AS2 (subc, w, %Y1);
02991 OUT_AS2 (mov, w, %X0);
02992 OUT_AS2 (subc, w, %X1);
02993 OUT_AS2 (mov, w, %W0);
02994 OUT_AS2 (subc, w, %W1);
02995 OUT_AS2 (mov, w, %V0);
02996 OUT_AS2 (subc, w, %V1);
02997 OUT_AS2 (mov, w, %U0);
02998 OUT_AS2 (subc, w, %U1);
02999 OUT_AS2 (mov, w, %T0);
03000 OUT_AS2 (subc, w, %T1);
03001 OUT_AS2 (mov, w, %S0);
03002 OUT_AS2 (subc, w, %S1);
03003 OUT_AS1 (snc,);
03004 OUT_AS1 (page, %2);
03005 OUT_AS1 (jmp, %2);
03006 }
03007 break;
03008
03009 default:
03010 abort ();
03011 }
03012 break;
03013
03014 default:
03015 abort ();
03016 }
03017 #undef operands
03018 return "";
03019 }
03020
03021
03022
03023 void
03024 asm_output_char (FILE *file, rtx value)
03025 {
03026 fprintf (file, "\t.byte ");
03027 output_addr_const (file, value);
03028 fprintf (file, "\n");
03029 }
03030
03031
03032
03033
03034 void
03035 asm_output_byte (FILE *file, int value)
03036 {
03037 fprintf (file, "\t.byte 0x%x\n",value & 0xff);
03038 }
03039
03040
03041
03042
03043 void
03044 asm_output_short (FILE *file, rtx value)
03045 {
03046 fprintf (file, "\t.word ");
03047 output_addr_const (file, (value));
03048 fprintf (file, "\n");
03049 }
03050
03051
03052
03053
03054 void
03055 asm_output_float (FILE *file, REAL_VALUE_TYPE n)
03056 {
03057 long val;
03058 char dstr[100];
03059
03060 REAL_VALUE_TO_TARGET_SINGLE (n, val);
03061 real_to_decimal (dstr, &n, sizeof (dstr), 0, 1);
03062
03063 fprintf (file, "\t.long 0x%08lx\t/* %s */\n", val, dstr);
03064 }
03065
03066
03067
03068 void
03069 unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
03070 {
03071 int len;
03072 const char *name;
03073 char *string;
03074 const char *prefix;
03075 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
03076
03077 name = (* targetm.strip_name_encoding) (name);
03078
03079 if (TREE_CODE (decl) == FUNCTION_DECL)
03080 {
03081 if (flag_function_sections)
03082 prefix = ".text.";
03083 else
03084 prefix = ".text";
03085 }
03086 else
03087 abort ();
03088
03089 if (flag_function_sections)
03090 {
03091 len = strlen (name) + strlen (prefix);
03092 string = alloca (len + 1);
03093 sprintf (string, "%s%s", prefix, name);
03094 DECL_SECTION_NAME (decl) = build_string (len, string);
03095 }
03096 }
03097
03098
03099
03100
03101
03102 enum reg_class
03103 class_likely_spilled_p (int c)
03104 {
03105 return (c == IP_REGS
03106 || c == IPL_REGS
03107 || c == IPH_REGS
03108 || c == DP_SP_REGS
03109 || c == SP_REGS
03110 || c == DP_REGS
03111 || c == DPL_REGS
03112 || c == DPH_REGS
03113 || c == PTR_REGS);
03114 }
03115
03116
03117
03118
03119
03120
03121
03122 const struct attribute_spec ip2k_attribute_table[] =
03123 {
03124
03125 { "progmem", 0, 0, false, false, false, ip2k_handle_progmem_attribute },
03126 { "naked", 0, 0, true, false, false, ip2k_handle_fndecl_attribute },
03127 { NULL, 0, 0, false, false, false, NULL }
03128 };
03129
03130
03131
03132 static tree
03133 ip2k_handle_progmem_attribute (tree *node, tree name,
03134 tree args ATTRIBUTE_UNUSED,
03135 int flags ATTRIBUTE_UNUSED,
03136 bool *no_add_attrs)
03137 {
03138 if (DECL_P (*node))
03139 {
03140 if (TREE_CODE (*node) == TYPE_DECL)
03141 {
03142
03143
03144
03145 tree type = TREE_TYPE (*node);
03146 tree attr = tree_cons (name, args, TYPE_ATTRIBUTES (type));
03147 tree newtype = build_type_attribute_variant (type, attr);
03148
03149 TYPE_MAIN_VARIANT (newtype) = TYPE_MAIN_VARIANT (type);
03150 TREE_TYPE (*node) = newtype;
03151 *no_add_attrs = true;
03152 }
03153 else if (TREE_STATIC (*node) || DECL_EXTERNAL (*node))
03154 {
03155 if (DECL_INITIAL (*node) == NULL_TREE && !DECL_EXTERNAL (*node))
03156 {
03157 warning ("only initialized variables can be placed into "
03158 "program memory area");
03159 *no_add_attrs = true;
03160 }
03161 }
03162 else
03163 {
03164 warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
03165 *no_add_attrs = true;
03166 }
03167 }
03168
03169 return NULL_TREE;
03170 }
03171
03172
03173
03174 static tree
03175 ip2k_handle_fndecl_attribute (tree *node, tree name,
03176 tree args ATTRIBUTE_UNUSED,
03177 int flags ATTRIBUTE_UNUSED,
03178 bool *no_add_attrs)
03179 {
03180 if (TREE_CODE (*node) != FUNCTION_DECL)
03181 {
03182 warning ("%qs attribute only applies to functions",
03183 IDENTIFIER_POINTER (name));
03184 *no_add_attrs = true;
03185 }
03186
03187 return NULL_TREE;
03188 }
03189
03190
03191
03192
03193
03194
03195
03196 static bool
03197 ip2k_rtx_costs (rtx x, int code, int outer_code, int *total)
03198 {
03199 enum machine_mode mode = GET_MODE (x);
03200 int extra_cost = 0;
03201
03202 switch (code)
03203 {
03204 case CONST_INT:
03205 case CONST_DOUBLE:
03206 case LABEL_REF:
03207 *total = 0;
03208 return true;
03209 case CONST:
03210 case SYMBOL_REF:
03211 *total = 8;
03212 return true;
03213
03214 case MEM:
03215 *total = ip2k_address_cost (XEXP (x, 0));
03216 return true;
03217
03218 case ROTATE:
03219 case ROTATERT:
03220 case ASHIFT:
03221 case LSHIFTRT:
03222 case ASHIFTRT:
03223 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
03224 {
03225 int val = INTVAL (XEXP (x, 1));
03226 int cost;
03227
03228
03229
03230
03231 cost = COSTS_N_INSNS (abs (val) % 8);
03232 cost += rtx_cost (XEXP (x, 0), code);
03233 cost *= (GET_MODE_SIZE (mode) + 1);
03234
03235
03236 if (code == ASHIFT)
03237 cost += COSTS_N_INSNS (2);
03238
03239 *total = cost;
03240 return true;
03241 }
03242 *total = rtx_cost (XEXP (x, 0), code);
03243 *total += COSTS_N_INSNS (GET_MODE_SIZE (mode) * 8);
03244 return true;
03245
03246 case MINUS:
03247 case PLUS:
03248 case AND:
03249 case XOR:
03250 case IOR:
03251 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) * 3);
03252 return false;
03253
03254 case MOD:
03255 case DIV:
03256 if (mode == QImode)
03257 *total = COSTS_N_INSNS (20);
03258 else if (mode == HImode)
03259 *total = COSTS_N_INSNS (60);
03260 else if (mode == SImode)
03261 *total = COSTS_N_INSNS (180);
03262 else
03263 *total = COSTS_N_INSNS (540);
03264 return true;
03265
03266 case MULT:
03267
03268
03269
03270 if (mode == QImode)
03271 *total = COSTS_N_INSNS (4);
03272 else if (mode == HImode)
03273 *total = COSTS_N_INSNS (12);
03274 else if (mode == SImode)
03275 *total = COSTS_N_INSNS (36);
03276 else
03277 *total = COSTS_N_INSNS (108);
03278 return true;
03279
03280 case NEG:
03281 case SIGN_EXTEND:
03282 extra_cost = COSTS_N_INSNS (GET_MODE_SIZE (mode));
03283
03284
03285 case NOT:
03286 case COMPARE:
03287 case ABS:
03288 *total = extra_cost + COSTS_N_INSNS (GET_MODE_SIZE (mode) * 2);
03289 return false;
03290
03291 case TRUNCATE:
03292 case ZERO_EXTEND:
03293 if (outer_code == SET)
03294 {
03295 *total = COSTS_N_INSNS (GET_MODE_SIZE (mode) * 3 / 2);
03296 return false;
03297 }
03298 else
03299 {
03300 *total = -(COSTS_N_INSNS (GET_MODE_SIZE (mode)) / 2);
03301 return true;
03302 }
03303
03304 case IF_THEN_ELSE:
03305 *total = rtx_cost (XEXP (x, 0), code) + COSTS_N_INSNS (2);
03306 return true;
03307
03308 case EQ:
03309 case NE:
03310 case LTU:
03311 case GTU:
03312 case LEU:
03313 case GEU:
03314 case LT:
03315 case GT:
03316 case LE:
03317 case GE:
03318 *total = 0;
03319 return false;
03320
03321 default:
03322 *total = COSTS_N_INSNS (4);
03323 return true;
03324 }
03325 }
03326
03327
03328
03329 static int
03330 ip2k_address_cost (rtx x)
03331 {
03332 switch (legitimate_address_p (VOIDmode, x, 0))
03333 {
03334 case 'S':
03335 return 8;
03336
03337 case 'R':
03338 return 8;
03339
03340 case 'L':
03341 return 0;
03342
03343 case 'C':
03344 return 4;
03345
03346 default:
03347 return 1000;
03348 }
03349 }
03350
03351
03352
03353
03354
03355
03356
03357 #ifdef IP2K_MD_REORG_PASS
03358 static void
03359 mdr_resequence_xy_yx (first_insn)
03360 rtx first_insn;
03361 {
03362 rtx insn;
03363
03364 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
03365 {
03366 rtx set;
03367
03368 if (GET_CODE (insn) != INSN)
03369 continue;
03370
03371 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
03372 if (set == NULL_RTX)
03373 continue;
03374
03375
03376
03377
03378
03379 if ((GET_CODE (XEXP (set, 0)) == REG
03380 || GET_CODE (XEXP (set, 0)) == MEM)
03381 && (GET_CODE (XEXP (set, 1)) == ASHIFT
03382 || GET_CODE (XEXP (set, 1)) == ASHIFTRT
03383 || GET_CODE (XEXP (set, 1)) == LSHIFTRT
03384 || GET_CODE (XEXP (set, 1)) == XOR
03385 || GET_CODE (XEXP (set, 1)) == IOR
03386 || GET_CODE (XEXP (set, 1)) == AND
03387 || GET_CODE (XEXP (set, 1)) == PLUS
03388 || GET_CODE (XEXP (set, 1)) == MINUS
03389 || GET_CODE (XEXP (set, 1)) == MULT))
03390 {
03391 rtx set2;
03392 rtx next_insn;
03393
03394 next_insn = next_nonnote_insn (insn);
03395 if (! next_insn)
03396 continue;
03397
03398 if (GET_CODE (next_insn) != INSN)
03399 continue;
03400
03401 set2 = ((GET_CODE (PATTERN (next_insn)) == SET)
03402 ? PATTERN (next_insn) : NULL_RTX);
03403 if (set2 == NULL_RTX)
03404 continue;
03405
03406 if ((GET_CODE (XEXP (XEXP (set, 1), 0)) == REG
03407 || GET_CODE (XEXP (XEXP (set, 1), 0)) == MEM)
03408 && rtx_equal_p (XEXP (set2, 0), XEXP (XEXP (set, 1), 0))
03409 && rtx_equal_p (XEXP (set2, 1), XEXP (set, 0)))
03410 {
03411 rtx next2_insn;
03412 rtx b_insn;
03413
03414 b_insn = gen_rtx_SET (VOIDmode,
03415 XEXP (XEXP (set, 1), 0),
03416 gen_rtx_fmt_ee (GET_CODE (XEXP (set, 1)),
03417 GET_MODE (XEXP (set, 0)),
03418 XEXP (XEXP (set, 1), 0),
03419 XEXP (XEXP (set, 1), 1)));
03420
03421 emit_insn_before (b_insn, insn);
03422 b_insn = gen_rtx_SET (GET_MODE (XEXP (set, 0)), XEXP (set, 0),
03423 XEXP (XEXP (set, 1), 0));
03424 next2_insn = emit_insn_before (b_insn, insn);
03425 delete_insn (insn);
03426 delete_insn (next_insn);
03427 insn = next2_insn;
03428 continue;
03429 }
03430
03431
03432
03433
03434
03435 if (GET_RTX_CLASS (GET_CODE (XEXP (set, 1))) == RTX_COMM_ARITH
03436 && (GET_CODE (XEXP (XEXP (set, 1), 1)) == REG
03437 || GET_CODE (XEXP (XEXP (set, 1), 1)) == MEM)
03438 && rtx_equal_p (XEXP (set2, 0), XEXP (XEXP (set, 1), 1))
03439 && rtx_equal_p (XEXP (set2, 1), XEXP (set, 0)))
03440 {
03441 rtx rtx_ee;
03442 rtx next2_insn;
03443 int swap_args;
03444
03445
03446 swap_args = (GET_CODE (XEXP (XEXP (set, 1), 0)) == REG
03447 || GET_CODE (XEXP (XEXP (set, 1), 0)) == MEM);
03448 rtx_ee = gen_rtx_fmt_ee (GET_CODE (XEXP (set, 1)),
03449 GET_MODE (XEXP (set, 0)),
03450 XEXP (XEXP (set, 1), swap_args ? 1 : 0),
03451 XEXP (XEXP (set, 1),
03452 swap_args ? 0 : 1));
03453
03454 emit_insn_before (gen_rtx_SET (VOIDmode,
03455 XEXP (XEXP (set, 1), 1),
03456 rtx_ee),
03457 insn);
03458 next2_insn = emit_insn_before (gen_rtx_SET
03459 (GET_MODE (XEXP (set, 0)),
03460 XEXP (set, 0),
03461 XEXP (XEXP (set, 1), 1)),
03462 insn);
03463 delete_insn (insn);
03464 delete_insn (next_insn);
03465 insn = next2_insn;
03466 }
03467 }
03468 }
03469 }
03470
03471
03472
03473 static void
03474 mdr_pres_replace_and_recurse (orig, with, insn)
03475 rtx orig;
03476 rtx with;
03477 rtx insn;
03478 {
03479 enum machine_mode new_mode;
03480
03481 validate_replace_rtx (orig, with, insn);
03482
03483 switch (GET_MODE (orig))
03484 {
03485 case DImode:
03486 case DFmode:
03487 new_mode = SImode;
03488 break;
03489
03490 case SImode:
03491 case SFmode:
03492 new_mode = HImode;
03493 break;
03494
03495 case HImode:
03496 new_mode = QImode;
03497 break;
03498
03499 default:
03500 return;
03501 }
03502
03503 mdr_pres_replace_and_recurse (ip2k_get_low_half (orig, new_mode),
03504 ip2k_get_low_half (with, new_mode),
03505 insn);
03506 mdr_pres_replace_and_recurse (ip2k_get_high_half (orig, new_mode),
03507 ip2k_get_high_half (with, new_mode),
03508 insn);
03509 }
03510
03511
03512
03513 static void
03514 mdr_propagate_reg_equivs_sequence (first_insn, orig, equiv)
03515 rtx first_insn;
03516 rtx orig;
03517 rtx equiv;
03518 {
03519 rtx try_insn;
03520 rtx try_equiv = equiv;
03521
03522
03523
03524 for (try_insn = next_nonnote_insn (first_insn);
03525 try_insn; try_insn = next_nonnote_insn (try_insn))
03526 {
03527 rtx pattern;
03528
03529 if (GET_CODE (try_insn) != JUMP_INSN && GET_CODE (try_insn) != INSN)
03530 continue;
03531
03532 pattern = PATTERN (try_insn);
03533 if (GET_CODE (pattern) == PARALLEL)
03534 {
03535 int j;
03536
03537 for (j = 0; j < XVECLEN (pattern, 0); j++)
03538 {
03539 rtx px = XVECEXP (pattern, 0, j);
03540
03541 if (GET_CODE (px) == SET)
03542 if (! ip2k_composite_xexp_not_uses_reg_p (XEXP (px, 0),
03543 REGNO (orig),
03544 GET_MODE_SIZE (GET_MODE (orig))))
03545 return;
03546 }
03547 }
03548 else if (GET_CODE (pattern) == SET)
03549 {
03550 if (! ip2k_composite_xexp_not_uses_reg_p (XEXP (pattern, 0),
03551 REGNO (orig),
03552 GET_MODE_SIZE (GET_MODE (orig))))
03553 return;
03554 }
03555 }
03556
03557
03558
03559 for (try_insn = next_nonnote_insn (first_insn); try_insn;
03560 try_insn = next_nonnote_insn (try_insn))
03561 {
03562 rtx set;
03563 rtx new_equiv = NULL_RTX;
03564
03565 if (GET_CODE (try_insn) != JUMP_INSN && GET_CODE (try_insn) != INSN)
03566 {
03567 try_equiv = equiv;
03568 continue;
03569 }
03570
03571 set = ((GET_CODE (PATTERN (try_insn)) == SET)
03572 ? PATTERN (try_insn) : NULL_RTX);
03573 if (set == NULL_RTX)
03574 continue;
03575
03576
03577
03578
03579
03580 if (GET_CODE (XEXP (set, 0)) == MEM
03581 && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC
03582 && REG_P (XEXP (XEXP (XEXP (set, 0), 0), 0))
03583 && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP)
03584 {
03585
03586
03587 HOST_WIDE_INT disp = (INTVAL (XEXP (XEXP (try_equiv, 0), 1))
03588 + GET_MODE_SIZE (GET_MODE (XEXP (set, 0))));
03589 new_equiv = gen_rtx_MEM (GET_MODE (try_equiv),
03590 gen_rtx_PLUS (Pmode,
03591 gen_rtx_REG (HImode, REG_SP),
03592 GEN_INT (disp)));
03593 }
03594
03595
03596
03597
03598 mdr_pres_replace_and_recurse (orig, try_equiv, try_insn);
03599
03600 if (new_equiv != NULL_RTX)
03601 try_equiv = new_equiv;
03602 }
03603 }
03604
03605
03606
03607
03608
03609
03610 static void
03611 mdr_propagate_reg_equivs (first_insn)
03612 rtx first_insn;
03613 {
03614 rtx insn;
03615 rtx set;
03616
03617 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
03618 {
03619 if (GET_CODE (insn) != INSN)
03620 continue;
03621
03622 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
03623 if (set == NULL_RTX)
03624 continue;
03625
03626
03627 if (REG_P (XEXP (set, 0))
03628 && REGNO (XEXP (set, 0)) >= 0x88
03629 && GET_CODE (XEXP (set, 1)) == MEM
03630 && GET_CODE (XEXP (XEXP (set, 1), 0)) == PLUS
03631 && REG_P (XEXP (XEXP (XEXP (set, 1), 0), 0))
03632 && REGNO (XEXP (XEXP (XEXP (set, 1), 0), 0)) == REG_SP
03633 && find_reg_note (insn, REG_EQUIV, NULL_RTX))
03634 {
03635 mdr_propagate_reg_equivs_sequence (insn, XEXP (set, 0),
03636 XEXP (set, 1));
03637 }
03638 }
03639 }
03640
03641
03642
03643 struct dpre_jump_targets
03644 {
03645 int target;
03646 int reach_count;
03647 int touch_count;
03648
03649 rtx dp_equiv;
03650 };
03651
03652 struct dpre_jump_targets *ip2k_dpre_jump_targets;
03653
03654
03655
03656 static int
03657 track_dp_reload (insn, dp_current, dp_current_ok, modifying)
03658 rtx insn;
03659 rtx *dp_current;
03660 int dp_current_ok;
03661 int modifying;
03662 {
03663 rtx set;
03664
03665 if (GET_CODE (insn) != INSN)
03666 {
03667 *dp_current = NULL_RTX;
03668 return 1;
03669 }
03670
03671 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
03672 if (set == NULL_RTX)
03673 {
03674 *dp_current = NULL_RTX;
03675 return 1;
03676 }
03677
03678
03679
03680
03681
03682 if (*dp_current != NULL_RTX
03683 && GET_CODE (XEXP (set, 0)) == MEM
03684 && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC
03685 && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG
03686 && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP
03687 && (GET_CODE (XEXP (set, 1)) == PLUS
03688 || GET_CODE (XEXP (set, 1)) == MINUS)
03689 && GET_CODE (*dp_current) != SYMBOL_REF
03690 && GET_CODE (*dp_current) != LABEL_REF
03691 && GET_CODE (*dp_current) != CONST)
03692 {
03693 if (modifying)
03694 validate_replace_rtx (*dp_current, gen_rtx_REG (HImode, REG_DP), insn);
03695 }
03696
03697
03698
03699 if (GET_CODE (XEXP (set, 0)) == REG
03700 && REGNO (XEXP (set, 0)) == REG_DP
03701 && GET_MODE (XEXP (set, 0)) == HImode)
03702 {
03703
03704 if (*dp_current != NULL_RTX
03705 && rtx_equal_p (XEXP (set, 1), *dp_current))
03706 {
03707 if (modifying)
03708 delete_insn (insn);
03709 }
03710 else
03711 {
03712
03713
03714
03715
03716 if (*dp_current != NULL_RTX
03717 && GET_CODE (*dp_current) != SYMBOL_REF
03718 && GET_CODE (*dp_current) != LABEL_REF
03719 && GET_CODE (*dp_current) != CONST
03720 && modifying)
03721 validate_replace_rtx (*dp_current, XEXP (set, 0), insn);
03722
03723
03724
03725
03726 if (ip2k_xexp_not_uses_reg_p (XEXP (set, 1), REG_DP, 2))
03727 {
03728 *dp_current = XEXP (set, 1);
03729 return 1;
03730 }
03731 else
03732 {
03733 *dp_current = NULL_RTX;
03734 return 1;
03735 }
03736 }
03737 }
03738 else if (GET_CODE (XEXP (set, 0)) == REG
03739 && (REGNO (XEXP (set, 0)) == REG_DPL
03740 || REGNO (XEXP (set, 0)) == REG_DPH))
03741 {
03742
03743 *dp_current = NULL_RTX;
03744 return 1;
03745 }
03746 else if (! ip2k_xexp_not_uses_reg_p (XEXP (set, 0), REG_SP, 2)
03747 && *dp_current != NULL_RTX
03748 && !ip2k_xexp_not_uses_reg_p (*dp_current, REG_SP, 2))
03749 {
03750
03751
03752
03753 if (GET_CODE (XEXP (set, 0)) == MEM
03754 && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC
03755 && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG
03756 && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP
03757 && GET_CODE (*dp_current) == MEM
03758 && GET_CODE (XEXP (*dp_current, 0)) == PLUS)
03759 {
03760
03761
03762 HOST_WIDE_INT disp = (INTVAL (XEXP (XEXP (*dp_current, 0), 1))
03763 + GET_MODE_SIZE (GET_MODE (XEXP (set, 0))));
03764 *dp_current = gen_rtx_MEM (HImode,
03765 gen_rtx_PLUS (Pmode,
03766 gen_rtx_REG (HImode, REG_SP),
03767 GEN_INT (disp)));
03768 return 1;
03769 }
03770
03771
03772
03773
03774 if (GET_CODE (XEXP (set, 0)) == MEM
03775 && GET_CODE (*dp_current) == MEM)
03776 {
03777
03778 int dp_cur_sp_offs = INTVAL (XEXP (XEXP (*dp_current, 0), 1));
03779 int set_sp_offs = INTVAL (XEXP (XEXP (XEXP (set, 0), 0), 1));
03780
03781 if (abs (dp_cur_sp_offs - set_sp_offs) < 2)
03782 {
03783 *dp_current = NULL_RTX;
03784 return 1;
03785 }
03786 }
03787 }
03788 else if (GET_CODE (XEXP (set, 0)) == REG
03789 && *dp_current != NULL_RTX
03790 && !ip2k_xexp_not_uses_reg_p (*dp_current, REGNO (XEXP (set, 0)),
03791 GET_MODE_SIZE (GET_MODE (XEXP (set,
03792 0)))))
03793 {
03794
03795
03796 *dp_current = NULL_RTX;
03797 }
03798
03799 return dp_current_ok;
03800 }
03801
03802
03803
03804
03805
03806
03807 static void
03808 mdr_try_dp_reload_elim (first_insn)
03809 rtx first_insn;
03810 {
03811 rtx insn;
03812 struct dpre_jump_targets *djt;
03813 rtx dp_current;
03814 int incomplete_scan;
03815 int last_incomplete_scan;
03816
03817 ip2k_dpre_jump_targets
03818 = (struct dpre_jump_targets *) xcalloc (get_max_uid (),
03819 sizeof (struct dpre_jump_targets));
03820
03821
03822
03823 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
03824 {
03825 if (GET_CODE (insn) == CODE_LABEL)
03826 {
03827 djt = &ip2k_dpre_jump_targets[INSN_UID (insn)];
03828 djt->target = 1;
03829 djt->reach_count = LABEL_NUSES (insn);
03830 djt->touch_count = 0;
03831 djt->dp_equiv = NULL_RTX;
03832 if (! prev_nonnote_insn (insn)
03833 || (prev_nonnote_insn (insn)
03834 && GET_CODE (prev_nonnote_insn (insn)) != BARRIER))
03835 djt->reach_count++;
03836 }
03837 }
03838
03839
03840
03841
03842
03843
03844
03845 incomplete_scan = -1;
03846 do
03847 {
03848 int dp_current_ok = 0;
03849 last_incomplete_scan = incomplete_scan;
03850 dp_current = NULL_RTX;
03851
03852 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
03853 {
03854
03855
03856
03857
03858
03859
03860 if (GET_CODE (insn) == CODE_LABEL)
03861 {
03862 djt = &ip2k_dpre_jump_targets[INSN_UID (insn)];
03863
03864
03865 if (djt->touch_count == djt->reach_count)
03866 {
03867 dp_current = djt->dp_equiv;
03868 dp_current_ok = 1;
03869 continue;
03870 }
03871
03872
03873
03874 if (dp_current_ok
03875 && (! prev_nonnote_insn (insn)
03876 || (prev_nonnote_insn (insn)
03877 && GET_CODE (prev_nonnote_insn (insn)) != BARRIER)))
03878 {
03879 if (djt->touch_count == 0)
03880 djt->dp_equiv = dp_current;
03881
03882 if (djt->touch_count < djt->reach_count)
03883 {
03884 djt->touch_count++;
03885 if (! rtx_equal_p (djt->dp_equiv, dp_current))
03886 {
03887
03888
03889
03890 djt->dp_equiv = NULL_RTX;
03891 dp_current = NULL_RTX;
03892 dp_current_ok = 1;
03893 }
03894 }
03895 }
03896
03897
03898
03899
03900 if (djt->touch_count < djt->reach_count)
03901 {
03902 dp_current = NULL_RTX;
03903 dp_current_ok = 0;
03904 }
03905
03906 continue;
03907 }
03908
03909
03910
03911 if (GET_CODE (insn) == JUMP_INSN)
03912 {
03913
03914
03915 if (dp_current_ok)
03916 {
03917 rtx pat = PATTERN (insn);
03918 if (GET_CODE (pat) == ADDR_VEC)
03919 {
03920 int i;
03921 int len = XVECLEN (pat, 0);
03922
03923 for (i = 0; i < len; i++)
03924 {
03925 rtx vec_insn = XEXP (XVECEXP (pat, 0, i), 0);
03926 djt = &ip2k_dpre_jump_targets [INSN_UID (vec_insn)];
03927
03928 if (djt->touch_count == 0)
03929 djt->dp_equiv = dp_current;
03930
03931 if (djt->touch_count < djt->reach_count)
03932 {
03933 djt->touch_count++;
03934 if (! rtx_equal_p (djt->dp_equiv, dp_current))
03935 djt->dp_equiv = NULL_RTX;
03936 }
03937 }
03938 }
03939 else if (JUMP_LABEL (insn))
03940 {
03941 rtx j_insn = JUMP_LABEL (insn);
03942 djt = &ip2k_dpre_jump_targets[INSN_UID (j_insn)];
03943
03944 if (djt->touch_count == 0)
03945 djt->dp_equiv = dp_current;
03946
03947 if (djt->touch_count < djt->reach_count)
03948 {
03949 djt->touch_count++;
03950 if (! rtx_equal_p (djt->dp_equiv, dp_current))
03951 djt->dp_equiv = NULL_RTX;
03952 }
03953 }
03954 }
03955
03956 continue;
03957 }
03958
03959
03960
03961 dp_current_ok = track_dp_reload (insn, &dp_current,
03962 dp_current_ok, 0);
03963 }
03964
03965
03966
03967
03968
03969
03970
03971
03972 incomplete_scan = 0;
03973 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
03974 {
03975 if (GET_CODE (insn) == CODE_LABEL)
03976 {
03977 djt = &ip2k_dpre_jump_targets[INSN_UID (insn)];
03978 if (djt->touch_count != djt->reach_count)
03979 {
03980 incomplete_scan += (djt->reach_count - djt->touch_count);
03981 djt->dp_equiv = NULL_RTX;
03982 djt->touch_count = 0;
03983 }
03984 }
03985 }
03986 }
03987 while (incomplete_scan && incomplete_scan != last_incomplete_scan);
03988
03989
03990
03991
03992
03993 dp_current = NULL_RTX;
03994 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
03995 {
03996 if (GET_CODE (insn) == JUMP_INSN)
03997 continue;
03998
03999 if (GET_CODE (insn) == CODE_LABEL)
04000 {
04001 djt = &ip2k_dpre_jump_targets[INSN_UID (insn)];
04002 dp_current = djt->dp_equiv;
04003 continue;
04004 }
04005
04006 track_dp_reload (insn, &dp_current, 1, 1);
04007 }
04008
04009 free (ip2k_dpre_jump_targets);
04010 }
04011
04012
04013
04014
04015
04016 static void
04017 mdr_try_move_dp_reload (first_insn)
04018 rtx first_insn;
04019 {
04020 rtx insn;
04021 rtx set;
04022 rtx orig_first;
04023
04024
04025
04026 orig_first = first_insn;
04027 first_insn = next_nonnote_insn (first_insn);
04028
04029 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
04030 {
04031 if (GET_CODE (insn) != INSN)
04032 continue;
04033
04034 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
04035 if (set == NULL_RTX)
04036 continue;
04037
04038
04039
04040 if (GET_CODE (XEXP (set, 0)) == REG
04041 && REGNO (XEXP (set, 0)) == REG_DP
04042 && GET_MODE (XEXP (set, 0)) == HImode)
04043 {
04044 int try_again;
04045 rtx try_insn = insn;
04046
04047 do
04048 {
04049 rtx rewind;
04050 rtx check;
04051
04052 try_again = 0;
04053
04054
04055
04056 rewind = prev_nonnote_insn (try_insn);
04057 if (rewind != orig_first && rewind != NULL_RTX
04058 && GET_CODE (rewind) == INSN)
04059 {
04060 check = ((GET_CODE (PATTERN (rewind)) == SET)
04061 ? PATTERN (rewind) : NULL_RTX);
04062 if (check != NULL_RTX
04063 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (check, 0))
04064 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (check, 1)))
04065 {
04066 if (GET_CODE (XEXP (check, 0)) == REG
04067 && REGNO (XEXP (check, 0)) != REG_DPH
04068 && REGNO (XEXP (check, 0)) != REG_DPL
04069 && (ip2k_composite_xexp_not_uses_reg_p
04070 (XEXP (check, 1), REG_DP, 2))
04071 && (ip2k_composite_xexp_not_uses_reg_p
04072 (XEXP (set, 1),
04073 REGNO (XEXP (check, 0)),
04074 GET_MODE_SIZE (GET_MODE (XEXP (check, 0))))))
04075 {
04076 emit_insn_before (set, rewind);
04077 if (try_insn == insn)
04078 insn = prev_nonnote_insn (insn);
04079 delete_insn (try_insn);
04080 try_insn = prev_nonnote_insn (rewind);
04081 try_again = 1;
04082 }
04083 else if (GET_CODE (XEXP (set, 1)) == REG
04084 && ip2k_composite_xexp_not_uses_reg_p (XEXP (check, 1), REG_DP, 2)
04085 && ip2k_composite_xexp_not_uses_reg_p (XEXP (check, 0), REG_DP, 2)
04086 && ip2k_composite_xexp_not_uses_reg_p (XEXP (check, 0), REGNO (XEXP (set, 1)),
04087 GET_MODE_SIZE (GET_MODE (XEXP (set, 1)))))
04088 {
04089 emit_insn_before (set, rewind);
04090 if (try_insn == insn)
04091 insn = prev_nonnote_insn (insn);
04092 delete_insn (try_insn);
04093 try_insn = prev_nonnote_insn (rewind);
04094 try_again = 1;
04095 }
04096 }
04097 }
04098 }
04099 while (try_again && try_insn);
04100 }
04101 }
04102 }
04103 #endif
04104
04105
04106
04107
04108 static int
04109 ip2k_check_can_adjust_stack_ref (rtx x, int offset)
04110 {
04111 if (ARITHMETIC_P (x))
04112 return (ip2k_check_can_adjust_stack_ref (XEXP (x, 0), offset)
04113 && ip2k_check_can_adjust_stack_ref (XEXP (x, 1), offset));
04114
04115 if (UNARY_P (x))
04116 return ip2k_check_can_adjust_stack_ref (XEXP (x, 0), offset);
04117
04118 switch (GET_CODE (x))
04119 {
04120 case REG:
04121 return (REGNO (x) != REG_SPH && REGNO (x) != REG_SPL);
04122
04123 case MEM:
04124 if (GET_CODE (XEXP (x, 0)) != PLUS)
04125 return 1;
04126
04127 if (GET_CODE (XEXP (XEXP (x, 0), 0)) != REG)
04128 return 1;
04129
04130 if (REGNO (XEXP (XEXP (x, 0), 0)) != REG_SP)
04131 return 1;
04132
04133
04134
04135 return (INTVAL (XEXP (XEXP (x, 0), 1))
04136 + offset <= (128 - 2 * GET_MODE_SIZE (GET_MODE (x))));
04137
04138 case CONST:
04139 case CONST_INT:
04140 case CONST_DOUBLE:
04141 case SYMBOL_REF:
04142 case LABEL_REF:
04143 return 1;
04144
04145 default:
04146 return 0;
04147 }
04148 }
04149
04150
04151
04152
04153 static void
04154 ip2k_adjust_stack_ref (rtx *x, int offset)
04155 {
04156 if (ARITHMETIC_P (*x))
04157 {
04158 ip2k_adjust_stack_ref (&XEXP (*x, 0), offset);
04159 ip2k_adjust_stack_ref (&XEXP (*x, 1), offset);
04160 return;
04161 }
04162
04163 if (UNARY_P (*x))
04164 {
04165 ip2k_adjust_stack_ref (&XEXP (*x, 0), offset);
04166 return;
04167 }
04168
04169 switch (GET_CODE (*x))
04170 {
04171 case MEM:
04172 if (GET_CODE (XEXP (*x, 0)) != PLUS)
04173 return;
04174
04175 if (GET_CODE (XEXP (XEXP (*x, 0), 0)) != REG)
04176 return;
04177
04178 if (REGNO (XEXP (XEXP (*x, 0), 0)) != REG_SP)
04179 return;
04180
04181 *x = copy_rtx (*x);
04182 XEXP (XEXP (*x, 0), 1) = GEN_INT (INTVAL (XEXP (XEXP (*x, 0), 1))
04183 + offset);
04184 break;
04185
04186 default:
04187 break;
04188 }
04189 }
04190
04191 #ifdef IP2K_MD_REORG_PASS
04192
04193
04194
04195
04196 static void
04197 mdr_try_move_pushes (first_insn)
04198 rtx first_insn;
04199 {
04200 rtx insn;
04201 rtx set;
04202 rtx orig_first;
04203
04204
04205
04206 orig_first = first_insn;
04207 first_insn = next_nonnote_insn (first_insn);
04208
04209 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
04210 {
04211 if (GET_CODE (insn) != INSN)
04212 continue;
04213
04214 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
04215 if (set == NULL_RTX)
04216 continue;
04217
04218
04219 if (GET_CODE (XEXP (set, 0)) == MEM
04220 && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC
04221 && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG
04222 && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP
04223 && GET_CODE (XEXP (set, 1)) == REG)
04224 {
04225 rtx try_insn = insn;
04226 unsigned int regno = REGNO (XEXP (set, 1));
04227 int reg_range = GET_MODE_SIZE (GET_MODE (XEXP (set, 1)));
04228
04229 while (1)
04230 {
04231 rtx rewind;
04232 rtx check;
04233
04234 rewind = prev_nonnote_insn (try_insn);
04235 if (rewind == orig_first || rewind == NULL_RTX
04236 || GET_CODE (rewind) != INSN)
04237 break;
04238
04239 check = (GET_CODE (PATTERN (rewind)) == SET) ? PATTERN (rewind) : NULL_RTX;
04240 if (check == NULL_RTX)
04241 break;
04242
04243 if (! ip2k_check_can_adjust_stack_ref (XEXP (check, 0),
04244 reg_range)
04245 || ! ip2k_check_can_adjust_stack_ref (XEXP (check, 1),
04246 reg_range))
04247 break;
04248
04249
04250
04251 if (GET_CODE (XEXP (check, 0)) == MEM
04252 && GET_CODE (XEXP (XEXP (check, 0), 0)) == POST_DEC
04253 && GET_CODE (XEXP (XEXP (XEXP (check, 0), 0), 0)) == REG
04254 && REGNO (XEXP (XEXP (XEXP (check, 0), 0), 0)) == REG_SP)
04255 break;
04256
04257
04258
04259 if (GET_CODE (XEXP (check, 0)) == REG)
04260 {
04261 unsigned int check_reg = REGNO (XEXP (check, 0));
04262 int check_reg_range = GET_MODE_SIZE (GET_MODE (XEXP (check,
04263 0)));
04264
04265
04266
04267
04268
04269
04270
04271
04272
04273 if (check_reg == regno
04274 && check_reg_range == reg_range
04275 && ((GET_CODE (XEXP (check, 1)) == REG
04276 || (GET_CODE (XEXP (check, 1)) == MEM
04277 && (GET_MODE (XEXP (check, 1)) != HImode
04278 || ip2k_xexp_not_uses_reg_for_mem (XEXP (check, 1), REG_IP))))))
04279 {
04280 switch (check_reg_range)
04281 {
04282 case 1:
04283 emit_insn_before (gen_movqi (XEXP (set, 0),
04284 XEXP (check, 1)),
04285 rewind);
04286 delete_insn (try_insn);
04287 break;
04288
04289 case 2:
04290 emit_insn_before (gen_movhi (XEXP (set, 0),
04291 XEXP (check, 1)),
04292 rewind);
04293 delete_insn (try_insn);
04294 break;
04295
04296 case 4:
04297 emit_insn_before (gen_movsi (XEXP (set, 0),
04298 XEXP (check, 1)),
04299 rewind);
04300 delete_insn (try_insn);
04301 break;
04302
04303 case 8:
04304 emit_insn_before (gen_movdi (XEXP (set, 0),
04305 XEXP (check, 1)),
04306 rewind);
04307 delete_insn (try_insn);
04308 break;
04309 }
04310
04311 ip2k_adjust_stack_ref (&XEXP (check, 0), reg_range);
04312 ip2k_adjust_stack_ref (&XEXP (check, 1), reg_range);
04313 try_insn = prev_nonnote_insn (rewind);
04314
04315 break;
04316 }
04317
04318 if ((check_reg == REG_SPL)
04319 || (check_reg == REG_SPH)
04320 || (((regno <= check_reg)
04321 && (regno + reg_range - 1) >= check_reg)
04322 || ((regno <= (check_reg + check_reg_range - 1))
04323 && ((regno + reg_range - 1)
04324 >= (check_reg + check_reg_range - 1)))))
04325 break;
04326 }
04327
04328 emit_insn_before (set, rewind);
04329 delete_insn (try_insn);
04330 ip2k_adjust_stack_ref (&XEXP (check, 0), reg_range);
04331 ip2k_adjust_stack_ref (&XEXP (check, 1), reg_range);
04332 try_insn = prev_nonnote_insn (rewind);
04333 }
04334 }
04335 }
04336 }
04337
04338
04339
04340 static void
04341 mdr_try_propagate_clr_sequence (first_insn, regno)
04342 rtx first_insn;
04343 unsigned int regno;
04344 {
04345 rtx try_insn;
04346
04347 for (try_insn = next_nonnote_insn (first_insn); try_insn;
04348 try_insn = next_nonnote_insn (try_insn))
04349 {
04350 rtx new_insn = NULL_RTX;
04351 rtx set2;
04352
04353 if (GET_CODE (try_insn) == JUMP_INSN)
04354 continue;
04355
04356 if (GET_CODE (try_insn) != INSN)
04357 break;
04358
04359 set2 = ((GET_CODE (PATTERN (try_insn)) == SET)
04360 ? PATTERN (try_insn) : NULL_RTX);
04361 if (set2 == NULL_RTX)
04362 continue;
04363
04364 if (GET_CODE (XEXP (set2, 1)) == AND
04365 && ((GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG
04366 && REGNO (XEXP (XEXP (set2, 1), 0)) == regno)
04367 || (GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG
04368 && REGNO (XEXP (XEXP (set2, 1), 1)) == regno)))
04369 {
04370 rtx remove_insn = try_insn;
04371 try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0),
04372 const0_rtx), try_insn);
04373 delete_insn (remove_insn);
04374 }
04375 else if (GET_CODE (XEXP (set2, 1)) == IOR
04376 && GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG
04377 && REGNO (XEXP (XEXP (set2, 1), 0)) == regno)
04378 {
04379 rtx remove_insn = try_insn;
04380 try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0),
04381 XEXP (XEXP (set2, 1), 1)),
04382 try_insn);
04383 delete_insn (remove_insn);
04384 }
04385 else if (GET_CODE (XEXP (set2, 1)) == IOR
04386 && GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG
04387 && REGNO (XEXP (XEXP (set2, 1), 1)) == regno)
04388 {
04389 rtx remove_insn = try_insn;
04390 try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0),
04391 XEXP (XEXP (set2, 1), 0)),
04392 try_insn);
04393 delete_insn (remove_insn);
04394 }
04395 else if (GET_CODE (XEXP (set2, 1)) == XOR
04396 && GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG
04397 && REGNO (XEXP (XEXP (set2, 1), 0)) == regno)
04398 {
04399 rtx remove_insn = try_insn;
04400 try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0),
04401 XEXP (XEXP (set2, 1), 1)),
04402 try_insn);
04403 delete_insn (remove_insn);
04404 }
04405 else if (GET_CODE (XEXP (set2, 1)) == XOR
04406 && GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG
04407 && REGNO (XEXP (XEXP (set2, 1), 1)) == regno)
04408 {
04409 rtx remove_insn = try_insn;
04410 try_insn = emit_insn_before (gen_rtx_SET (QImode, XEXP (set2, 0),
04411 XEXP (XEXP (set2, 1), 0)),
04412 try_insn);
04413 delete_insn (remove_insn);
04414 }
04415
04416 if (GET_CODE (XEXP (set2, 0)) == REG)
04417 {
04418 int reg2_range = GET_MODE_SIZE (GET_MODE (XEXP (set2, 0)));
04419 unsigned int regno2 = REGNO (XEXP (set2, 0));
04420
04421 if (reg2_range == 1
04422 && regno == regno2
04423 && GET_CODE (XEXP (set2, 1)) == CONST_INT)
04424 {
04425 int iv = INTVAL (XEXP (set2, 1));
04426 if (iv == 0xff)
04427 iv = -1;
04428 if (iv == 1 || iv == -1)
04429 {
04430 new_insn = gen_rtx_SET (QImode, XEXP (set2, 0),
04431 gen_rtx_PLUS (QImode, XEXP (set2, 0),
04432 GEN_INT (iv)));
04433 new_insn = emit_insn_before (new_insn, try_insn);
04434 delete_insn (try_insn);
04435 try_insn = new_insn;
04436 }
04437 break;
04438 }
04439
04440 if ((regno >= regno2) && (regno <= regno2 + reg2_range - 1))
04441 break;
04442
04443 if (GET_CODE (XEXP (set2, 1)) == REG
04444 && REGNO (XEXP (set2, 1)) == regno)
04445 {
04446 new_insn = emit_insn_before (gen_rtx_SET (QImode,
04447 XEXP (set2, 0),
04448 const0_rtx),
04449 try_insn);
04450 delete_insn (try_insn);
04451 try_insn = new_insn;
04452 }
04453 }
04454
04455 if (GET_CODE (XEXP (set2, 0)) == CC0)
04456 {
04457 if (GET_CODE (XEXP (set2, 1)) == REG
04458 && GET_MODE_SIZE (GET_MODE (XEXP (set2, 1))) == 2
04459 && REGNO (XEXP (set2, 1)) == regno)
04460 {
04461 new_insn = gen_rtx_SET (VOIDmode, gen_rtx_CC0 (VOIDmode),
04462 gen_rtx_REG(QImode, regno + 1));
04463 new_insn = emit_insn_before (new_insn, try_insn);
04464 }
04465 else if (GET_CODE (XEXP (set2, 1)) == COMPARE
04466 && GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG
04467 && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2, 1), 0))) == 2
04468 && REGNO (XEXP (XEXP (set2, 1), 0)) == regno
04469 && GET_CODE (XEXP (XEXP (set2, 1), 1)) == CONST_INT
04470 && INTVAL (XEXP (XEXP (set2, 1), 1)) >= 0
04471 && INTVAL (XEXP (XEXP (set2, 1), 1)) < 256)
04472 {
04473 new_insn = gen_rtx_SET (VOIDmode, cc0_rtx,
04474 gen_rtx_COMPARE(QImode,
04475 gen_rtx_REG (QImode,
04476 regno + 1),
04477 XEXP (XEXP (set2, 1),
04478 1)));
04479 new_insn = emit_insn_before (new_insn, try_insn);
04480 }
04481
04482
04483
04484 if (new_insn != NULL_RTX)
04485 {
04486 delete_insn (try_insn);
04487 try_insn = new_insn;
04488
04489
04490
04491
04492
04493 if (GET_CODE (next_nonnote_insn (try_insn)) == JUMP_INSN)
04494 {
04495 rtx set3;
04496
04497 try_insn = next_nonnote_insn (try_insn);
04498 set3 = ((GET_CODE (PATTERN (try_insn)) == SET)
04499 ? PATTERN (try_insn) : NULL_RTX);
04500 if (set3 == NULL_RTX)
04501 continue;
04502
04503
04504
04505
04506 if (LABEL_NUSES (JUMP_LABEL (try_insn)) == 1)
04507 mdr_try_propagate_clr_sequence (JUMP_LABEL (try_insn),
04508 regno);
04509
04510 if (GET_CODE (XEXP (set3, 0)) == PC
04511 && GET_CODE (XEXP (set3, 1)) == IF_THEN_ELSE
04512 && (GET_CODE (XEXP (XEXP (set3, 1), 0)) == GT
04513 || GET_CODE (XEXP (XEXP (set3, 1), 0)) == GE
04514 || GET_CODE (XEXP (XEXP (set3, 1), 0)) == LT
04515 || GET_CODE (XEXP (XEXP (set3, 1), 0)) == LE)
04516 && GET_CODE (XEXP (XEXP (XEXP (set3, 1), 0), 0)) == CC0
04517 && (GET_CODE (XEXP (XEXP (XEXP (set3, 1), 0), 1))
04518 == CONST_INT)
04519 && GET_CODE (XEXP (XEXP (set3, 1), 1)) == LABEL_REF
04520 && GET_CODE (XEXP (XEXP (set3, 1), 2)) == PC)
04521 {
04522 enum rtx_code code;
04523 rtx new_if;
04524 rtx cmp;
04525
04526
04527
04528
04529 code = GET_CODE (XEXP (XEXP (set3, 1), 0));
04530 cmp = gen_rtx_fmt_ee ((code == GT
04531 ? GTU
04532 : (code == GE
04533 ? GEU
04534 : (code == LT ? LTU : LEU))),
04535 VOIDmode,
04536 XEXP (XEXP (XEXP (set3, 1), 0), 0),
04537 XEXP (XEXP (XEXP (set3, 1), 0),
04538 1));
04539 new_if
04540 = gen_rtx_SET (GET_MODE (set3),
04541 pc_rtx,
04542 gen_rtx_IF_THEN_ELSE
04543 (GET_MODE (XEXP (set3, 1)), cmp,
04544 XEXP (XEXP (set3, 1), 1),
04545 XEXP (XEXP (set3, 1), 2)));
04546 new_insn = emit_jump_insn_before (new_if, try_insn);
04547 LABEL_NUSES (JUMP_LABEL (try_insn))++;
04548 delete_insn (try_insn);
04549 try_insn = new_insn;
04550 }
04551 }
04552 }
04553 }
04554 else if (GET_CODE (XEXP (set2, 1)) == PLUS
04555 && GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG
04556 && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2, 1), 0))) == 2
04557 && REGNO (XEXP (XEXP (set2, 1), 0)) == regno
04558 && (GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG
04559 || GET_CODE (XEXP (XEXP (set2, 1), 1)) == MEM
04560 || GET_CODE (XEXP (XEXP (set2, 1), 1)) == CONST_INT
04561 || GET_CODE (XEXP (XEXP (set2, 1), 1)) == CONST
04562 || GET_CODE (XEXP (XEXP (set2, 1), 1)) == SYMBOL_REF))
04563 {
04564 rtx extend = gen_rtx_ZERO_EXTEND (HImode,
04565 gen_rtx_REG (QImode, regno + 1));
04566 new_insn = gen_rtx_SET (HImode, XEXP (set2, 0),
04567 gen_rtx_PLUS (HImode, extend,
04568 XEXP (XEXP (set2, 1), 1)));
04569 new_insn = emit_insn_before (new_insn, try_insn);
04570 delete_insn (try_insn);
04571 try_insn = new_insn;
04572 }
04573 else if (GET_CODE (XEXP (set2, 1)) == PLUS
04574 && GET_CODE (XEXP (XEXP (set2, 1), 1)) == REG
04575 && GET_MODE_SIZE (GET_MODE (XEXP (XEXP (set2, 1), 1))) == 2
04576 && REGNO (XEXP (XEXP (set2, 1), 1)) == regno
04577 && (GET_CODE (XEXP (XEXP (set2, 1), 0)) == REG
04578 || GET_CODE (XEXP (XEXP (set2, 1), 0)) == MEM
04579 || GET_CODE (XEXP (XEXP (set2, 1), 0)) == CONST_INT
04580 || GET_CODE (XEXP (XEXP (set2, 1), 0)) == CONST
04581 || GET_CODE (XEXP (XEXP (set2, 1), 0)) == SYMBOL_REF))
04582 {
04583 rtx t_src = gen_rtx_PLUS (HImode,
04584 gen_rtx_ZERO_EXTEND (HImode,
04585 gen_rtx_REG (QImode,
04586 regno
04587 + 1)),
04588 XEXP (XEXP (set2, 1), 0));
04589 new_insn = emit_insn_before (gen_rtx_SET (HImode, XEXP (set2, 0),
04590 t_src),
04591 try_insn);
04592 delete_insn (try_insn);
04593 try_insn = new_insn;
04594 }
04595 }
04596 }
04597
04598
04599
04600
04601
04602
04603
04604
04605
04606
04607
04608
04609 static void
04610 mdr_try_propagate_clr (first_insn)
04611 rtx first_insn;
04612 {
04613 rtx insn;
04614 rtx set;
04615
04616 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
04617 {
04618 if (GET_CODE (insn) != INSN)
04619 continue;
04620
04621 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
04622 if (set == NULL_RTX)
04623 continue;
04624
04625
04626 if (GET_CODE (XEXP (set, 0)) == REG
04627 && GET_CODE (XEXP (set, 1)) == CONST_INT
04628 && GET_MODE_SIZE (GET_MODE (XEXP (set, 0))) == 1
04629 && INTVAL (XEXP (set, 1)) == 0)
04630 {
04631 mdr_try_propagate_clr_sequence (insn, REGNO (XEXP (set, 0)));
04632 }
04633 }
04634 }
04635 #endif
04636
04637
04638
04639
04640
04641 static int
04642 ip2k_xexp_not_uses_reg_for_mem (rtx x, unsigned int regno)
04643 {
04644 if (regno & 1)
04645 regno &= 0xfffffffe;
04646
04647 switch (GET_CODE (x))
04648 {
04649 case REG:
04650 return 1;
04651
04652 case MEM:
04653 if ((GET_CODE (XEXP (x, 0)) == PLUS
04654 && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
04655 && REGNO (XEXP (XEXP (x, 0), 0)) == regno)
04656 || (GET_CODE (XEXP (x, 0)) == REG
04657 && REGNO (XEXP (x, 0)) == regno))
04658 return 0;
04659 else
04660 return 1;
04661
04662 case CONST:
04663 case CONST_INT:
04664 case CONST_DOUBLE:
04665 case SYMBOL_REF:
04666 case LABEL_REF:
04667 case CC0:
04668 case PC:
04669 return 1;
04670
04671 default:
04672 if (GET_RTX_CLASS (GET_CODE (x)) == RTX_BITFIELD_OPS)
04673 return (ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 0), regno)
04674 && ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 1), regno)
04675 && ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 2), regno));
04676
04677 if (BINARY_P (x))
04678 return (ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 0), regno)
04679 && ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 1), regno));
04680
04681 if (UNARY_P (x)
04682 || GET_RTX_CLASS (GET_CODE (x)) == '3')
04683 return ip2k_xexp_not_uses_reg_for_mem (XEXP (x, 0), regno);
04684
04685 return 0;
04686 }
04687 }
04688
04689 #ifdef IP2K_MD_REORG_PASS
04690
04691
04692 static void
04693 mdr_try_propagate_move_sequence (first_insn, orig, equiv)
04694 rtx first_insn;
04695 rtx orig;
04696 rtx equiv;
04697 {
04698 rtx try_insn;
04699
04700 for (try_insn = next_nonnote_insn (first_insn); try_insn;
04701 try_insn = next_nonnote_insn (try_insn))
04702 {
04703 rtx set;
04704 int range;
04705 rtx new_equiv = NULL_RTX;
04706
04707 if (GET_CODE (try_insn) != JUMP_INSN && GET_CODE (try_insn) != INSN)
04708 break;
04709
04710 set = single_set (try_insn);
04711 if (set == NULL_RTX)
04712 break;
04713
04714 range = MAX (GET_MODE_SIZE (GET_MODE (equiv)),
04715 GET_MODE_SIZE (GET_MODE (XEXP (set, 0))));
04716
04717 if (GET_CODE (equiv) == REG
04718 && REGNO (equiv) == REG_W
04719 && (recog_memoized (try_insn) < 0
04720 || get_attr_clobberw (try_insn) != CLOBBERW_NO)
04721 && (! (GET_CODE (XEXP (set, 0)) == REG
04722 && REGNO (XEXP (set, 0)) == REG_W
04723 && rtx_equal_p (XEXP (set, 1), orig))))
04724 break;
04725 else if (GET_CODE (XEXP (set, 0)) == REG
04726 && (REGNO (XEXP (set, 0)) == REG_SP
04727 || ! ip2k_xexp_not_uses_reg_p (equiv, REGNO (XEXP (set, 0)),
04728 range)
04729 || ! ip2k_xexp_not_uses_reg_p (orig, REGNO (XEXP (set, 0)),
04730 range))
04731 && ! rtx_equal_p (equiv, XEXP (set, 0))
04732 && ! rtx_equal_p (orig, XEXP (set, 0)))
04733 break;
04734 else if (GET_CODE (orig) == REG
04735 && (REGNO (orig) == REG_IPL
04736 || REGNO (orig) == REG_IPH
04737 || REGNO (orig) == REG_DPL
04738 || REGNO (orig) == REG_DPH)
04739 && (! ip2k_xexp_not_uses_reg_for_mem (XEXP (set, 0),
04740 REGNO (orig))
04741 || ! ip2k_xexp_not_uses_reg_for_mem (XEXP (set, 1),
04742 REGNO (orig))))
04743 break;
04744 else if (GET_CODE (XEXP (set, 0)) == MEM
04745 && GET_CODE (equiv) == MEM)
04746 {
04747 if (! ip2k_xexp_not_uses_reg_p (equiv, REG_SP, 2))
04748 {
04749 if (! ip2k_xexp_not_uses_reg_p (XEXP (set, 0), REG_SP, 2))
04750 {
04751
04752
04753
04754
04755 if (GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC
04756 && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG
04757 && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP
04758 && GET_CODE (XEXP (equiv, 0)) == PLUS
04759 && REGNO (XEXP (XEXP (equiv, 0), 0)) == REG_SP)
04760 {
04761 int md_size = GET_MODE_SIZE (GET_MODE (XEXP (set, 0)));
04762 int new_sp_offs = INTVAL (XEXP (XEXP (equiv, 0), 1))
04763 + md_size;
04764
04765
04766
04767 if (new_sp_offs > (128 - 2 * md_size))
04768 break;
04769
04770 new_equiv
04771 = gen_rtx_MEM (GET_MODE (equiv),
04772 gen_rtx_PLUS (Pmode,
04773 gen_rtx_REG (HImode ,
04774 REG_SP),
04775 GEN_INT (new_sp_offs)));
04776 }
04777 else if (! rtx_equal_p (equiv, XEXP (set, 0)))
04778 {
04779
04780 int equiv_offs = GET_CODE (XEXP (equiv, 0)) == PLUS
04781 ? INTVAL (XEXP (XEXP (equiv, 0), 1))
04782 : 0;
04783 int set_offs
04784 = (GET_CODE (XEXP (XEXP (set, 0), 0)) == PLUS
04785 ? INTVAL (XEXP (XEXP (XEXP (set, 0), 0), 1))
04786 : 0);
04787
04788 if (abs (equiv_offs - set_offs) < range)
04789 break;
04790 }
04791 }
04792 }
04793
04794 if (! ip2k_xexp_not_uses_reg_p (equiv, REG_IP, 2))
04795 break;
04796
04797 if (! ip2k_xexp_not_uses_reg_p (XEXP (set, 0), REG_DP, 2)
04798 && ! ip2k_xexp_not_uses_reg_p (equiv, REG_DP, 2)
04799 && ! rtx_equal_p (equiv, XEXP (set, 0)))
04800 {
04801
04802 int equiv_offs = GET_CODE (XEXP (equiv, 0)) == PLUS
04803 ? INTVAL (XEXP (XEXP (equiv, 0), 1))
04804 : 0;
04805 int set_offs = GET_CODE (XEXP (XEXP (set, 0), 0)) == PLUS
04806 ? INTVAL (XEXP (XEXP (XEXP (set, 0), 0), 1))
04807 : 0;
04808
04809 if (abs (equiv_offs - set_offs) < range)
04810 break;
04811 }
04812 }
04813
04814 validate_replace_rtx_subexp (orig, equiv, try_insn, &XEXP (set, 1));
04815
04816 if (rtx_equal_p (equiv, XEXP (set, 0))
04817 || rtx_equal_p (orig, XEXP (set, 0)))
04818 break;
04819
04820 if (new_equiv != NULL_RTX)
04821 equiv = new_equiv;
04822 }
04823 }
04824
04825
04826
04827
04828
04829
04830 static void
04831 mdr_try_propagate_move (first_insn)
04832 rtx first_insn;
04833 {
04834 rtx insn;
04835 rtx set;
04836
04837 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
04838 {
04839 if (GET_CODE (insn) != INSN)
04840 continue;
04841
04842 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
04843 if (set == NULL_RTX)
04844 continue;
04845
04846
04847 if (GET_CODE (XEXP (set, 0)) == REG
04848 && (REGNO (XEXP (set, 0)) >= 0x80
04849 || REGNO (XEXP (set, 0)) == REG_DPL
04850 || REGNO (XEXP (set, 0)) == REG_DPH
04851 || REGNO (XEXP (set, 0)) == REG_IPL
04852 || REGNO (XEXP (set, 0)) == REG_IPH)
04853 && ((GET_CODE (XEXP (set, 1)) == REG
04854 && REGNO (XEXP (set, 1)) != REG_SP
04855 && ip2k_xexp_not_uses_reg_p (XEXP (set, 0),
04856 REGNO (XEXP (set, 1)),
04857 GET_MODE_SIZE (GET_MODE (XEXP (set,
04858 0)))))
04859 || (GET_CODE (XEXP (set, 1)) == MEM
04860 && (ip2k_xexp_not_uses_reg_p (XEXP (set, 1), REG_IP, 2)
04861 || GET_MODE (XEXP (set, 1)) == QImode)
04862 && ((REGNO (XEXP (set, 0)) != REG_DPH
04863 && REGNO (XEXP (set, 0)) != REG_DPL)
04864 || ip2k_xexp_not_uses_reg_p (XEXP (set, 1), REG_DP, 2)))
04865 || (GET_CODE (XEXP (set, 1)) == CONST_INT
04866 && (GET_MODE (XEXP (set, 0)) != QImode
04867 || INTVAL (XEXP (set, 1)) != 0))
04868 || GET_CODE (XEXP (set, 1)) == CONST_DOUBLE
04869 || GET_CODE (XEXP (set, 1)) == CONST
04870 || GET_CODE (XEXP (set, 1)) == SYMBOL_REF))
04871 {
04872 mdr_try_propagate_move_sequence (insn, XEXP (set, 0), XEXP (set, 1));
04873 }
04874 }
04875 }
04876
04877
04878
04879 static void
04880 mdr_try_remove_redundant_insns (first_insn)
04881 rtx first_insn;
04882 {
04883 rtx insn;
04884
04885 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
04886 {
04887 rtx set;
04888 enum machine_mode mode;
04889 int md_size;
04890 HOST_WIDE_INT pattern;
04891 int i;
04892
04893 if (GET_CODE (insn) != INSN)
04894 continue;
04895
04896 if (GET_CODE (PATTERN (insn)) == CONST_INT)
04897 {
04898
04899 rtx remove_insn = insn;
04900 insn = prev_nonnote_insn (insn);
04901 delete_insn (remove_insn);
04902 continue;
04903 }
04904
04905 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
04906 if (set == NULL_RTX)
04907 continue;
04908
04909 mode = GET_MODE (XEXP (set, 0));
04910 md_size = GET_MODE_SIZE (mode);
04911 if ((md_size < 1) || (md_size > 4))
04912 continue;
04913
04914 pattern = 0;
04915 for (i = 0; i < md_size; i++)
04916 {
04917 pattern <<= 8;
04918 pattern |= 0xff;
04919 }
04920
04921 if ((GET_CODE (XEXP (set, 1)) == AND
04922 && GET_CODE (XEXP (XEXP (set, 1), 1)) == CONST_INT
04923 && INTVAL (XEXP (XEXP (set, 1), 1)) == pattern)
04924 || ((GET_CODE (XEXP (set, 1)) == IOR
04925 || GET_CODE (XEXP (set, 1)) == XOR)
04926 && GET_CODE (XEXP (XEXP (set, 1), 1)) == CONST_INT
04927 && INTVAL (XEXP (XEXP (set, 1), 1)) == 0x00))
04928 {
04929
04930
04931 rtx remove_insn = insn;
04932
04933
04934 if (! rtx_equal_p (XEXP (set, 0), XEXP (XEXP (set, 1), 0)))
04935 {
04936 emit_insn_before (gen_rtx_SET (mode,
04937 XEXP (set, 0),
04938 XEXP (XEXP (set, 1), 0)),
04939 insn);
04940 }
04941
04942 insn = prev_nonnote_insn(insn);
04943 delete_insn (remove_insn);
04944 }
04945 else if (GET_CODE (XEXP (set, 1)) == AND
04946 && GET_CODE (XEXP (XEXP (set, 1), 1)) == CONST_INT
04947 && INTVAL (XEXP (XEXP (set, 1), 1)) == 0)
04948 {
04949
04950 rtx remove_insn = insn;
04951 insn = emit_insn_before (gen_rtx_SET (mode,
04952 XEXP (set, 0),
04953 XEXP (XEXP (set, 1), 1)),
04954 insn);
04955 delete_insn (remove_insn);
04956 }
04957 }
04958 }
04959
04960
04961
04962 struct we_jump_targets
04963 {
04964 int target;
04965 int reach_count;
04966 int touch_count;
04967
04968 rtx w_equiv;
04969 };
04970
04971 struct we_jump_targets *ip2k_we_jump_targets;
04972
04973
04974
04975 static int
04976 track_w_reload (insn, w_current, w_current_ok, modifying)
04977 rtx insn;
04978 rtx *w_current;
04979 int w_current_ok;
04980 int modifying;
04981 {
04982 rtx set;
04983
04984 if (GET_CODE (insn) != INSN)
04985 {
04986 *w_current = NULL_RTX;
04987 return 1;
04988 }
04989
04990 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
04991 if (set == NULL_RTX)
04992 {
04993 *w_current = NULL_RTX;
04994 return 1;
04995 }
04996
04997
04998
04999 if (GET_CODE (XEXP (set, 0)) == REG
05000 && REGNO (XEXP (set, 0)) == REG_W
05001 && GET_MODE (XEXP (set, 0)) == QImode)
05002 {
05003
05004 if (*w_current != NULL_RTX
05005 && rtx_equal_p (XEXP (set, 1), *w_current))
05006 {
05007 if (modifying)
05008 delete_insn (insn);
05009 }
05010 else
05011 {
05012 *w_current = XEXP (set, 1);
05013 return 1;
05014 }
05015 }
05016 else if (recog_memoized (insn) < 0
05017 || get_attr_clobberw (insn) != CLOBBERW_NO)
05018 {
05019
05020 *w_current = NULL_RTX;
05021 return 1;
05022 }
05023 else if (! ip2k_xexp_not_uses_reg_p (XEXP (set, 0), REG_SP, 2)
05024 && *w_current != NULL_RTX
05025 && !ip2k_xexp_not_uses_reg_p (*w_current, REG_SP, 2))
05026 {
05027
05028
05029
05030 if (GET_CODE (XEXP (set, 0)) == MEM
05031 && GET_CODE (XEXP (XEXP (set, 0), 0)) == POST_DEC
05032 && GET_CODE (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG
05033 && REGNO (XEXP (XEXP (XEXP (set, 0), 0), 0)) == REG_SP
05034 && GET_CODE (*w_current) == MEM
05035 && GET_CODE (XEXP (*w_current, 0)) == PLUS)
05036 {
05037
05038
05039 rtx val = GEN_INT (INTVAL (XEXP (XEXP (*w_current, 0), 1))
05040 + GET_MODE_SIZE (GET_MODE (XEXP (set, 0))));
05041 *w_current
05042 = gen_rtx_MEM (HImode, gen_rtx_PLUS (Pmode,
05043 gen_rtx_REG(HImode, REG_SP),
05044 val));
05045 return 1;
05046 }
05047 }
05048 else if (GET_CODE (XEXP (set, 0)) == REG
05049 && *w_current != NULL_RTX
05050 && !ip2k_xexp_not_uses_reg_p (*w_current, REGNO (XEXP (set, 0)),
05051 GET_MODE_SIZE (GET_MODE (XEXP (set
05052 , 0)))))
05053 {
05054
05055
05056 *w_current = NULL_RTX;
05057 }
05058
05059 return w_current_ok;
05060 }
05061
05062
05063
05064
05065 static void
05066 mdr_try_wreg_elim (first_insn)
05067 rtx first_insn;
05068 {
05069 rtx insn;
05070 struct we_jump_targets *wjt;
05071 rtx w_current;
05072 int incomplete_scan;
05073 int last_incomplete_scan;
05074
05075 ip2k_we_jump_targets
05076 = (struct we_jump_targets *) xcalloc (get_max_uid (),
05077 sizeof (struct we_jump_targets));
05078
05079
05080
05081 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
05082 {
05083 if (GET_CODE (insn) == CODE_LABEL)
05084 {
05085 wjt = &ip2k_we_jump_targets[INSN_UID (insn)];
05086 wjt->target = 1;
05087 wjt->reach_count = LABEL_NUSES (insn);
05088 wjt->touch_count = 0;
05089 wjt->w_equiv = NULL_RTX;
05090 if (! prev_nonnote_insn (insn)
05091 || (prev_nonnote_insn (insn)
05092 && GET_CODE (prev_nonnote_insn (insn)) != BARRIER))
05093 wjt->reach_count++;
05094 }
05095 }
05096
05097
05098
05099
05100
05101
05102
05103 incomplete_scan = -1;
05104 do
05105 {
05106 int w_current_ok = 0;
05107 last_incomplete_scan = incomplete_scan;
05108 w_current = NULL_RTX;
05109
05110 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
05111 {
05112
05113
05114
05115
05116
05117
05118 if (GET_CODE (insn) == CODE_LABEL)
05119 {
05120 wjt = &ip2k_we_jump_targets[INSN_UID (insn)];
05121
05122
05123 if (wjt->touch_count == wjt->reach_count)
05124 {
05125 w_current = wjt->w_equiv;
05126 w_current_ok = 1;
05127 continue;
05128 }
05129
05130
05131
05132 if (w_current_ok
05133 && (! prev_nonnote_insn (insn)
05134 || (prev_nonnote_insn (insn)
05135 && GET_CODE (prev_nonnote_insn (insn)) != BARRIER)))
05136 {
05137 if (wjt->touch_count == 0)
05138 wjt->w_equiv = w_current;
05139
05140 if (wjt->touch_count < wjt->reach_count)
05141 {
05142 wjt->touch_count++;
05143 if (! rtx_equal_p (wjt->w_equiv, w_current))
05144 {
05145
05146
05147
05148 wjt->w_equiv = NULL_RTX;
05149 w_current = NULL_RTX;
05150 w_current_ok = 1;
05151 }
05152 }
05153 }
05154
05155
05156
05157
05158 if (wjt->touch_count < wjt->reach_count)
05159 {
05160 w_current = NULL_RTX;
05161 w_current_ok = 0;
05162 }
05163
05164 continue;
05165 }
05166
05167
05168
05169 if (GET_CODE (insn) == JUMP_INSN)
05170 {
05171
05172
05173 if (w_current_ok)
05174 {
05175 if (JUMP_LABEL (insn))
05176 {
05177 wjt
05178 = &ip2k_we_jump_targets[INSN_UID (JUMP_LABEL (insn))];
05179
05180 if (wjt->touch_count == 0)
05181 wjt->w_equiv = w_current;
05182
05183 if (wjt->touch_count < wjt->reach_count)
05184 {
05185 wjt->touch_count++;
05186 if (! rtx_equal_p (wjt->w_equiv, w_current))
05187 wjt->w_equiv = NULL_RTX;
05188 }
05189 }
05190 }
05191
05192 continue;
05193 }
05194
05195
05196
05197 w_current_ok = track_w_reload (insn, &w_current, w_current_ok, 0);
05198 }
05199
05200
05201
05202
05203
05204
05205
05206
05207 incomplete_scan = 0;
05208 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
05209 {
05210 if (GET_CODE (insn) == CODE_LABEL)
05211 {
05212 wjt = &ip2k_we_jump_targets[INSN_UID (insn)];
05213 if (wjt->touch_count != wjt->reach_count)
05214 {
05215 incomplete_scan += (wjt->reach_count - wjt->touch_count);
05216 wjt->w_equiv = NULL_RTX;
05217 wjt->touch_count = 0;
05218 }
05219 }
05220 }
05221 }
05222 while (incomplete_scan && incomplete_scan != last_incomplete_scan);
05223
05224
05225
05226
05227
05228 w_current = NULL_RTX;
05229 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
05230 {
05231 if (GET_CODE (insn) == JUMP_INSN)
05232 continue;
05233
05234 if (GET_CODE (insn) == CODE_LABEL)
05235 {
05236 wjt = &ip2k_we_jump_targets[INSN_UID (insn)];
05237 w_current = wjt->w_equiv;
05238 continue;
05239 }
05240
05241 track_w_reload (insn, &w_current, 1, 1);
05242 }
05243
05244 free (ip2k_we_jump_targets);
05245 }
05246 #endif
05247
05248
05249
05250
05251
05252
05253
05254 static void
05255 ip2k_reorg (void)
05256 {
05257 #ifdef IP2K_MD_REORG_PASS
05258 rtx first_insn, insn, set;
05259 #endif
05260
05261 CC_STATUS_INIT;
05262
05263 if (optimize == 0)
05264 {
05265 ip2k_reorg_completed = 1;
05266 ip2k_reorg_split_dimode = 1;
05267 ip2k_reorg_split_simode = 1;
05268 ip2k_reorg_split_himode = 1;
05269 ip2k_reorg_split_qimode = 1;
05270 ip2k_reorg_merge_qimode = 1;
05271 return;
05272 }
05273 #ifndef IP2K_MD_REORG_PASS
05274 ip2k_reorg_completed = 1;
05275 ip2k_reorg_split_dimode = 1;
05276 ip2k_reorg_split_simode = 1;
05277 ip2k_reorg_split_himode = 1;
05278 ip2k_reorg_split_qimode = 1;
05279 ip2k_reorg_merge_qimode = 1;
05280 #else
05281
05282
05283
05284 ip2k_reorg_in_progress = 1;
05285
05286 first_insn = get_insns ();
05287
05288
05289
05290
05291
05292 for (insn = first_insn; insn; insn = NEXT_INSN (insn))
05293 {
05294 rtx body;
05295
05296 if (GET_CODE (insn) == CODE_LABEL
05297 || GET_CODE (insn) == NOTE
05298 || GET_CODE (insn) == BARRIER)
05299 continue;
05300
05301 if (!INSN_P (insn))
05302 continue;
05303
05304 body = PATTERN (insn);
05305 if (GET_CODE (body) == USE)
05306 if (GET_CODE (XEXP (body, 0)) == REG)
05307 {
05308 int reg;
05309
05310 reg = REGNO (XEXP (body, 0));
05311 if (find_regno_note (insn, REG_DEAD, reg))
05312 {
05313 delete_insn (insn);
05314 }
05315 }
05316 }
05317
05318
05319
05320 reload_cse_regs (first_insn);
05321 find_basic_blocks (first_insn);
05322 life_analysis (0, PROP_REG_INFO | PROP_DEATH_NOTES);
05323
05324
05325 mdr_try_dp_reload_elim (first_insn);
05326
05327 ip2k_reorg_in_progress = 0;
05328 ip2k_reorg_completed = 1;
05329
05330 split_all_insns (0);
05331
05332 reload_cse_regs (first_insn);
05333 find_basic_blocks (first_insn);
05334 life_analysis (0, PROP_REG_INFO | PROP_DEATH_NOTES);
05335 if (flag_peephole2)
05336 peephole2_optimize (NULL);
05337
05338 mdr_resequence_xy_yx (first_insn);
05339 mdr_propagate_reg_equivs (first_insn);
05340
05341
05342
05343
05344 for (insn = first_insn; insn; insn = next_nonnote_insn (insn))
05345 {
05346 if (GET_CODE (insn) == INSN)
05347 {
05348 set = (GET_CODE (PATTERN (insn)) == SET) ? PATTERN (insn) : NULL_RTX;
05349 if ((set != NULL_RTX)
05350 && (GET_CODE (XEXP (set, 0)) == REG)
05351 && (GET_MODE (XEXP (set, 0)) == QImode)
05352 && (find_regno_note (insn, REG_UNUSED, REGNO (XEXP (set, 0)))))
05353 delete_insn (insn);
05354 }
05355 }
05356
05357 mdr_try_move_dp_reload (first_insn);
05358 mdr_try_move_pushes (first_insn);
05359
05360 find_basic_blocks (first_insn);
05361 life_analysis (0, PROP_FINAL);
05362
05363 mdr_try_propagate_move (first_insn);
05364 mdr_resequence_xy_yx (first_insn);
05365
05366 ip2k_reorg_split_dimode = 1;
05367 split_all_insns (0);
05368
05369 mdr_try_remove_redundant_insns (first_insn);
05370
05371 mdr_try_propagate_move (first_insn);
05372
05373 reload_cse_regs (first_insn);
05374 find_basic_blocks (first_insn);
05375 life_analysis (0, PROP_FINAL);
05376 if (flag_peephole2)
05377 peephole2_optimize (NULL);
05378
05379 mdr_try_propagate_move (first_insn);
05380
05381 find_basic_blocks (first_insn);
05382 life_analysis (0, PROP_FINAL);
05383
05384 ip2k_reorg_split_simode = 1;
05385 split_all_insns (0);
05386
05387 mdr_try_remove_redundant_insns (first_insn);
05388
05389 mdr_try_propagate_move (first_insn);
05390
05391 reload_cse_regs (first_insn);
05392 find_basic_blocks (first_insn);
05393 life_analysis (0, PROP_FINAL);
05394 if (flag_peephole2)
05395 peephole2_optimize (NULL);
05396
05397 mdr_try_propagate_move (first_insn);
05398
05399 find_basic_blocks (first_insn);
05400 life_analysis (0, PROP_FINAL);
05401
05402 ip2k_reorg_split_himode = 1;
05403 ip2k_reorg_merge_qimode = 1;
05404 split_all_insns (0);
05405
05406 mdr_try_remove_redundant_insns (first_insn);
05407 mdr_try_propagate_clr (first_insn);
05408 mdr_try_propagate_move (first_insn);
05409
05410 mdr_try_dp_reload_elim (first_insn);
05411 mdr_try_move_dp_reload (first_insn);
05412
05413 rebuild_jump_labels (first_insn);
05414
05415
05416
05417 find_basic_blocks (first_insn);
05418 life_analysis (0, PROP_FINAL);
05419 if (flag_peephole2)
05420 peephole2_optimize (NULL);
05421
05422 mdr_try_propagate_move (first_insn);
05423
05424 find_basic_blocks (first_insn);
05425 life_analysis (0, PROP_FINAL);
05426 mdr_try_remove_redundant_insns (first_insn);
05427
05428 mdr_try_propagate_clr (first_insn);
05429 mdr_try_propagate_move (first_insn);
05430
05431 find_basic_blocks (first_insn);
05432 life_analysis (0, PROP_FINAL);
05433
05434 ip2k_reorg_split_qimode = 1;
05435 split_all_insns (0);
05436
05437 mdr_try_wreg_elim (first_insn);
05438 mdr_try_propagate_move (first_insn);
05439
05440 find_basic_blocks (first_insn);
05441 life_analysis (0, PROP_FINAL);
05442 #endif
05443 }
05444
05445 static void
05446 ip2k_init_libfuncs (void)
05447 {
05448 set_optab_libfunc (smul_optab, SImode, "_mulsi3");
05449 set_optab_libfunc (smul_optab, DImode, "_muldi3");
05450 set_optab_libfunc (cmp_optab, HImode, "_cmphi2");
05451 set_optab_libfunc (cmp_optab, SImode, "_cmpsi2");
05452 }
05453
05454
05455
05456 int
05457 find_one_set_bit_p (HOST_WIDE_INT mask)
05458 {
05459 int i;
05460 unsigned HOST_WIDE_INT n = mask;
05461 for (i = 0; i < 32; i++)
05462 {
05463 if (n & 0x80000000UL)
05464 {
05465 if (n & 0x7fffffffUL)
05466 return -1;
05467 else
05468 return 31 - i;
05469 }
05470 n <<= 1;
05471 }
05472 return -1;
05473 }
05474
05475
05476
05477 int
05478 find_one_clear_bit_p (HOST_WIDE_INT mask)
05479 {
05480 int i;
05481 unsigned HOST_WIDE_INT n = mask;
05482 for (i = 0; i < 32; i++)
05483 {
05484 if ((n & 0x80000000UL) == 0UL)
05485 {
05486 if ((n & 0x7fffffffUL) != 0x7fffffffUL)
05487 return -1;
05488 else
05489 return 31 - i;
05490 }
05491 n <<= 1;
05492 n |= 1;
05493 }
05494 return -1;
05495 }
05496
05497
05498
05499
05500
05501
05502
05503
05504 void
05505 ip2k_split_words (enum machine_mode nmode, enum machine_mode omode,
05506 rtx *operands)
05507 {
05508 rtx dl, dh;
05509 rtx sl, sh;
05510 int move_high_first = 0;
05511 int pushflag = 0;
05512
05513 switch (GET_CODE (operands[0]))
05514 {
05515 case SUBREG:
05516 case REG:
05517 if ((GET_CODE (operands[1]) == REG
05518 || GET_CODE (operands[1]) == SUBREG)
05519 && (true_regnum (operands[0]) <= true_regnum (operands[1])
05520 || (true_regnum (operands[1])
05521 + GET_MODE_SIZE (omode) - 1 < true_regnum (operands[0]))))
05522 move_high_first = 1;
05523
05524 if (GET_CODE (operands[0]) == SUBREG)
05525 {
05526 dl = simplify_gen_subreg (nmode, operands[0], omode,
05527 GET_MODE_SIZE (nmode));
05528 dh = simplify_gen_subreg (nmode, operands[0], omode, 0);
05529 }
05530 else if (GET_CODE (operands[0]) == REG && ! IS_PSEUDO_P (operands[0]))
05531 {
05532 int r = REGNO (operands[0]);
05533 dh = gen_rtx_REG (nmode, r);
05534 dl = gen_rtx_REG (nmode, r + HARD_REGNO_NREGS (r, nmode));
05535 }
05536 else
05537 {
05538 dh = gen_rtx_SUBREG (nmode, operands[0], 0);
05539 dl = gen_rtx_SUBREG (nmode, operands[0], GET_MODE_SIZE (nmode));
05540 }
05541 break;
05542
05543 case MEM:
05544 switch (GET_CODE (XEXP (operands[0], 0)))
05545 {
05546 case POST_INC:
05547 abort ();
05548 case POST_DEC:
05549 dl = dh = gen_rtx_MEM (nmode, XEXP (operands[0], 0));
05550 pushflag = 1;
05551 break;
05552 default:
05553 dl = change_address (operands[0], nmode,
05554 plus_constant (XEXP (operands[0], 0),
05555 GET_MODE_SIZE (nmode)));
05556 dh = gen_rtx_MEM (nmode, XEXP (operands[0], 0));
05557 }
05558 break;
05559 default:
05560 abort ();
05561 }
05562
05563 switch (GET_CODE (operands[1]))
05564 {
05565 case REG:
05566 if (! IS_PSEUDO_P (operands[1]))
05567 {
05568 int r = REGNO (operands[1]);
05569
05570 sh = gen_rtx_REG (nmode, r);
05571 sl = gen_rtx_REG (nmode, r + HARD_REGNO_NREGS (r, nmode));
05572 }
05573 else
05574 {
05575 sh = gen_rtx_SUBREG (nmode, operands[1], 0);
05576 sl = gen_rtx_SUBREG (nmode, operands[1], GET_MODE_SIZE (nmode));
05577 }
05578 break;
05579
05580 case CONST_DOUBLE:
05581 if (operands[1] == const0_rtx)
05582 sh = sl = const0_rtx;
05583 else
05584 {
05585 if (GET_MODE (operands[0]) != DImode)
05586 {
05587 REAL_VALUE_TYPE rv;
05588 long value;
05589
05590 REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
05591 REAL_VALUE_TO_TARGET_SINGLE (rv, value);
05592
05593 sh = gen_int_mode ((value >> 16) & 0xffff, nmode);
05594 sl = gen_int_mode (value & 0xffff, nmode);
05595 }
05596 else
05597 {
05598 sh = gen_int_mode (CONST_DOUBLE_HIGH (operands[1]), nmode);
05599 sl = gen_int_mode (CONST_DOUBLE_LOW (operands[1]), nmode);
05600 }
05601 }
05602 break;
05603
05604 case CONST_INT:
05605 if (operands[1] == const0_rtx)
05606 sh = sl = const0_rtx;
05607 else
05608 {
05609 int val = INTVAL (operands[1]);
05610 int vl, vh;
05611
05612 switch (nmode)
05613 {
05614 case QImode:
05615 vh = (val >> 8) & 0xff;
05616 vl = val & 0xff;
05617 break;
05618
05619 case HImode:
05620 vh = (val >> 16) & 0xffff;
05621 vl = val & 0xffff;
05622 break;
05623
05624 case SImode:
05625 if (val < 0)
05626 vh = -1;
05627 else
05628 vh = 0;
05629 vl = val;
05630 break;
05631
05632 default:
05633 abort ();
05634 }
05635
05636 sl = gen_int_mode (vl, nmode);
05637 sh = gen_int_mode (vh, nmode);
05638 }
05639 break;
05640
05641 case SUBREG:
05642 sl = simplify_gen_subreg (nmode, operands[1], omode,
05643 GET_MODE_SIZE (nmode));
05644 sh = simplify_gen_subreg (nmode, operands[1], omode, 0);
05645 break;
05646
05647 case MEM:
05648 switch (GET_CODE (XEXP (operands[1], 0)))
05649 {
05650 case POST_DEC:
05651 case POST_INC:
05652 abort ();
05653 break;
05654
05655 default:
05656
05657 if (pushflag && ip2k_address_uses_reg_p (operands[1], REG_SP))
05658 sl = sh = change_address (operands[1], nmode,
05659 plus_constant (XEXP (operands[1], 0),
05660 GET_MODE_SIZE (nmode)));
05661 else
05662 {
05663 sl = change_address (operands[1], nmode,
05664 plus_constant (XEXP (operands[1], 0),
05665 GET_MODE_SIZE (nmode)));
05666 sh = gen_rtx_MEM (nmode, XEXP (operands[1], 0));
05667 }
05668 }
05669 break;
05670
05671 default:
05672 abort ();
05673 }
05674
05675 if (move_high_first)
05676 {
05677 operands[2] = dh;
05678 operands[3] = sh;
05679 operands[4] = dl;
05680 operands[5] = sl;
05681 }
05682 else
05683 {
05684 operands[2] = dl;
05685 operands[3] = sl;
05686 operands[4] = dh;
05687 operands[5] = sh;
05688 }
05689 return;
05690 }
05691
05692
05693 rtx
05694 ip2k_get_low_half (rtx x, enum machine_mode mode)
05695 {
05696 switch (GET_CODE (x))
05697 {
05698 case REG:
05699 if (! IS_PSEUDO_P (x))
05700 {
05701 unsigned int r = REGNO (x);
05702
05703 return gen_rtx_REG (mode, r + HARD_REGNO_NREGS (r, mode));
05704 }
05705 else
05706 {
05707 return gen_rtx_SUBREG (mode, x, GET_MODE_SIZE (mode));
05708 }
05709 break;
05710
05711 case CONST_DOUBLE:
05712 if (x == const0_rtx)
05713 return const0_rtx;
05714 else
05715 {
05716 if (mode != SImode)
05717 {
05718 REAL_VALUE_TYPE rv;
05719 long value;
05720
05721 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
05722 REAL_VALUE_TO_TARGET_SINGLE (rv, value);
05723
05724 return gen_int_mode (value & 0xffff, mode);
05725 }
05726 else
05727 return gen_int_mode (CONST_DOUBLE_LOW (x), mode);
05728 }
05729 break;
05730
05731 case CONST_INT:
05732 if (x == const0_rtx)
05733 return const0_rtx;
05734 else
05735 {
05736 int val = INTVAL (x);
05737 int vl, vh;
05738
05739 switch (mode)
05740 {
05741 case QImode:
05742 vh = (val >> 8) & 0xff;
05743 vl = val & 0xff;
05744 break;
05745
05746 case HImode:
05747 vh = (val >> 16) & 0xffff;
05748 vl = val & 0xffff;
05749 break;
05750
05751 case SImode:
05752 if (val < 0)
05753 vh = -1;
05754 else
05755 vh = 0;
05756 vl = val;
05757 break;
05758
05759 default:
05760 abort ();
05761 }
05762
05763 return gen_int_mode (vl, mode);
05764 }
05765 break;
05766
05767 case SUBREG:
05768 return simplify_gen_subreg (mode, x, GET_MODE (x), GET_MODE_SIZE (mode));
05769
05770 case MEM:
05771 switch (GET_CODE (XEXP (x, 0)))
05772 {
05773 case POST_DEC:
05774 case POST_INC:
05775 abort ();
05776 break;
05777
05778 default:
05779 return change_address (x, mode,
05780 plus_constant (XEXP (x, 0),
05781 GET_MODE_SIZE (mode)));
05782 }
05783 break;
05784
05785 default:
05786 abort ();
05787 }
05788 return NULL_RTX;
05789 }
05790
05791
05792 rtx
05793 ip2k_get_high_half (rtx x, enum machine_mode mode)
05794 {
05795 switch (GET_CODE (x))
05796 {
05797 case REG:
05798 if (! IS_PSEUDO_P (x))
05799 {
05800 unsigned int r = REGNO (x);
05801
05802 return gen_rtx_REG (mode, r);
05803 }
05804 else
05805 {
05806 return gen_rtx_SUBREG (mode, x, 0);
05807 }
05808 break;
05809
05810 case CONST_DOUBLE:
05811 if (x == const0_rtx)
05812 return const0_rtx;
05813 else
05814 {
05815 if (mode != SImode)
05816 {
05817 REAL_VALUE_TYPE rv;
05818 long value;
05819
05820 REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
05821 REAL_VALUE_TO_TARGET_SINGLE (rv, value);
05822
05823 return gen_int_mode ((value >> 16) & 0xffff, mode);
05824 }
05825 else
05826 return gen_int_mode (CONST_DOUBLE_HIGH (x), mode);
05827 }
05828 break;
05829
05830 case CONST_INT:
05831 if (x == const0_rtx)
05832 return const0_rtx;
05833 else
05834 {
05835 int val = INTVAL (x);
05836 int vl, vh;
05837
05838 switch (mode)
05839 {
05840 case QImode:
05841 vh = (val >> 8) & 0xff;
05842 vl = val & 0xff;
05843 break;
05844
05845 case HImode:
05846 vh = (val >> 16) & 0xffff;
05847 vl = val & 0xffff;
05848 break;
05849
05850 case SImode:
05851 if (val < 0)
05852 vh = -1;
05853 else
05854 vh = 0;
05855 vl = val;
05856 break;
05857
05858 default:
05859 abort ();
05860 }
05861
05862 return gen_int_mode (vh, mode);
05863 }
05864 break;
05865
05866 case SUBREG:
05867 return simplify_gen_subreg (mode, x, GET_MODE (x), 0);
05868 break;
05869
05870 case MEM:
05871 switch (GET_CODE (XEXP (x, 0)))
05872 {
05873 case POST_DEC:
05874 case POST_INC:
05875 abort ();
05876 break;
05877
05878 default:
05879 return change_address (x, mode, plus_constant (XEXP (x, 0), 0));
05880 }
05881 break;
05882
05883 default:
05884 abort ();
05885 }
05886 return NULL_RTX;
05887 }
05888
05889
05890
05891
05892 int
05893 ip2k_address_uses_reg_p (rtx x, unsigned int r)
05894 {
05895 if (GET_CODE (x) != MEM)
05896 return 0;
05897
05898 x = XEXP (x, 0);
05899
05900 while (1)
05901 switch (GET_CODE (x))
05902 {
05903 case POST_DEC:
05904 case POST_INC:
05905 case PRE_DEC:
05906 case PRE_INC:
05907 x = XEXP (x, 0);
05908 break;
05909
05910 case PLUS:
05911 if (ip2k_address_uses_reg_p (XEXP (x, 1), r))
05912 return 1;
05913
05914 x = XEXP (x, 0);
05915 break;
05916
05917 case SUBREG:
05918
05919 x = SUBREG_REG (x);
05920 break;
05921
05922 case REG:
05923
05924 return ((REGNO (x) == r) || (REGNO (x) == (r - 1))) ? 1 : 0;
05925
05926 case MEM:
05927
05928 x = XEXP (x, 0);
05929 break;
05930
05931 default:
05932 return 0;
05933 };
05934 }
05935
05936
05937
05938
05939 int
05940 ip2k_xexp_not_uses_reg_p (rtx x, unsigned int r, int rsz)
05941 {
05942 switch (GET_CODE (x))
05943 {
05944 case REG:
05945 {
05946 int msz = GET_MODE_SIZE (GET_MODE (x));
05947
05948 return (((REGNO (x) + msz - 1) < r)
05949 || (REGNO (x) > (r + rsz - 1)));
05950 }
05951
05952 case MEM:
05953 return !ip2k_address_uses_reg_p (x, r);
05954
05955 case LABEL_REF:
05956 case SYMBOL_REF:
05957 case CONST:
05958 case CONST_INT:
05959 case CONST_DOUBLE:
05960 case CC0:
05961 case PC:
05962 return 1;
05963
05964 default:
05965 return 0;
05966 }
05967 }
05968
05969
05970
05971
05972 int
05973 ip2k_composite_xexp_not_uses_reg_p (rtx x, unsigned int r, int rsz)
05974 {
05975 if (GET_RTX_CLASS (GET_CODE (x)) == RTX_BITFIELD_OPS)
05976 return (ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 0), r, rsz)
05977 && ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 1), r, rsz)
05978 && ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 2), r, rsz));
05979
05980 if (BINARY_P (x))
05981 return (ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 0), r, rsz)
05982 && ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 1), r, rsz));
05983
05984 if (UNARY_P (x)
05985 || GET_RTX_CLASS (GET_CODE (x)) == RTX_TERNARY)
05986 return ip2k_composite_xexp_not_uses_reg_p (XEXP (x, 0), r, rsz);
05987
05988 return ip2k_xexp_not_uses_reg_p (x, r, rsz);
05989 }
05990
05991
05992
05993
05994 int
05995 ip2k_composite_xexp_not_uses_cc0_p (rtx x)
05996 {
05997 if (GET_RTX_CLASS (GET_CODE (x)) == RTX_BITFIELD_OPS)
05998 return (ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 0))
05999 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 1))
06000 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 2)));
06001
06002 if (BINARY_P (x))
06003 return (ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 0))
06004 && ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 1)));
06005
06006 if (UNARY_P (x)
06007 || GET_RTX_CLASS (GET_CODE (x)) == RTX_TERNARY)
06008 return ip2k_composite_xexp_not_uses_cc0_p (XEXP (x, 0));
06009
06010 return GET_CODE (x) != CC0;
06011 }
06012
06013 int
06014 ip2k_split_dest_operand (rtx x, enum machine_mode mode)
06015 {
06016 return nonimmediate_operand (x, mode) || push_operand (x, mode);
06017 }
06018
06019 int
06020 ip2k_nonptr_operand (rtx x, enum machine_mode mode)
06021 {
06022 return register_operand (x, mode) && !ip2k_ptr_operand (x, mode);
06023 }
06024
06025
06026
06027 int
06028 ip2k_ptr_operand (rtx x, enum machine_mode mode)
06029
06030 {
06031 if (GET_CODE (x) == SUBREG)
06032 x = SUBREG_REG (x);
06033
06034 return (REG_P (x)
06035 && (mode == HImode || mode == VOIDmode)
06036 && (REGNO (x) == REG_IP
06037 || REGNO (x) == REG_DP
06038 || REGNO (x) == REG_SP));
06039 }
06040
06041 int
06042 ip2k_sp_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
06043
06044 {
06045 return REG_P (x) && REGNO (x) == REG_SP;
06046 }
06047
06048 int
06049 ip2k_ip_operand (rtx x, enum machine_mode mode)
06050
06051 {
06052 if (GET_CODE (x) != MEM)
06053 return 0;
06054
06055 x = XEXP (x, 0);
06056
06057 if (GET_CODE (x) == PLUS && XEXP (x, 1) == const0_rtx)
06058 x = XEXP (x, 0);
06059
06060 if (! REG_P (x))
06061 return 0;
06062
06063 if (GET_MODE_SIZE (mode) > 1)
06064 return 0;
06065
06066 return REGNO (x) == REG_IP;
06067 }
06068
06069
06070 int
06071 ip2k_short_operand (rtx x, enum machine_mode mode)
06072 {
06073 int r;
06074 unsigned int offs = 0;
06075
06076 if (! memory_operand (x, mode))
06077 return 0;
06078
06079 x = XEXP (x, 0);
06080 switch (GET_CODE (x))
06081 {
06082 default:
06083 return 0;
06084
06085 case PLUS:
06086 if (! REG_P (XEXP (x, 0))
06087 || GET_CODE (XEXP (x, 1)) != CONST_INT)
06088 return 0;
06089
06090 offs = INTVAL (XEXP (x, 1));
06091
06092 if (128 <= offs)
06093 return 0;
06094
06095 x = XEXP (x, 0);
06096
06097
06098
06099 case REG:
06100 if (IS_PSEUDO_P (x))
06101 return 0;
06102
06103 r = REGNO (x);
06104
06105
06106
06107
06108
06109 if (r == REG_IP && offs == 0 && GET_MODE_SIZE (mode) <= 1)
06110 return 1;
06111
06112 return (r == REG_SP || r == REG_DP);
06113 }
06114 }
06115
06116 int
06117 ip2k_nonsp_reg_operand (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
06118 {
06119 if (GET_CODE (x) == SUBREG)
06120 x = SUBREG_REG (x);
06121
06122 return (REG_P (x) && REGNO (x) != REG_SP);
06123 }
06124
06125 int
06126 ip2k_gen_operand (rtx x, enum machine_mode mode)
06127 {
06128 return ip2k_short_operand (x, mode)
06129 || (GET_CODE (x) == SUBREG
06130 && REG_P (SUBREG_REG (x)))
06131 || (ip2k_nonsp_reg_operand (x, mode));
06132 }
06133
06134 int
06135 ip2k_extra_constraint (rtx x, int c)
06136 {
06137 switch (c)
06138 {
06139 case 'S':
06140 return ip2k_short_operand (x, GET_MODE (x));
06141
06142 case 'R':
06143 return ip2k_ip_operand (x, GET_MODE (x));
06144
06145 case 'T':
06146 return CONSTANT_P (x) && is_regfile_address (x);
06147
06148 default:
06149 return 0;
06150 }
06151 }
06152
06153 int
06154 ip2k_unary_operator (rtx op, enum machine_mode mode)
06155 {
06156 return ((mode == VOIDmode || GET_MODE (op) == mode)
06157 && UNARY_P (op));
06158 }
06159
06160 int
06161 ip2k_binary_operator (rtx op, enum machine_mode mode)
06162 {
06163 return ((mode == VOIDmode || GET_MODE (op) == mode)
06164 && ARITHMETIC_P (op));
06165 }
06166
06167 int
06168 ip2k_symbol_ref_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
06169 {
06170
06171
06172 return (GET_CODE (op) == SYMBOL_REF)
06173 || (GET_CODE (op) == CONST
06174 && GET_CODE (XEXP (op, 0)) == PLUS
06175 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF);
06176 }
06177
06178 int
06179 ip2k_signed_comparison_operator (rtx op, enum machine_mode mode)
06180 {
06181 return (comparison_operator (op, mode)
06182 && signed_condition (GET_CODE (op)) == GET_CODE (op));
06183 }
06184
06185 int
06186 ip2k_unsigned_comparison_operator (rtx op, enum machine_mode mode)
06187 {
06188 return (comparison_operator (op, mode)
06189 && unsigned_condition (GET_CODE (op)) == GET_CODE (op));
06190 }
06191
06192
06193
06194 static bool
06195 ip2k_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
06196 {
06197 if (TYPE_MODE (type) == BLKmode)
06198 {
06199 HOST_WIDE_INT size = int_size_in_bytes (type);
06200 return (size == -1 || size > 8);
06201 }
06202 else
06203 return false;
06204 }
06205
06206
06207
06208 static void
06209 ip2k_setup_incoming_varargs (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
06210 enum machine_mode mode ATTRIBUTE_UNUSED,
06211 tree type ATTRIBUTE_UNUSED,
06212 int *pretend_arg_size,
06213 int second_time ATTRIBUTE_UNUSED)
06214 {
06215 *pretend_arg_size = 0;
06216 }