00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "config.h"
00022 #include "system.h"
00023 #include "coretypes.h"
00024 #include <signal.h>
00025 #include "tm.h"
00026 #include "tree.h"
00027 #include "rtl.h"
00028 #include "regs.h"
00029 #include "hard-reg-set.h"
00030 #include "real.h"
00031 #include "insn-config.h"
00032 #include "conditions.h"
00033 #include "output.h"
00034 #include "insn-attr.h"
00035 #include "flags.h"
00036 #include "function.h"
00037 #include "expr.h"
00038 #include "optabs.h"
00039 #include "libfuncs.h"
00040 #include "recog.h"
00041 #include "toplev.h"
00042 #include "reload.h"
00043 #include "ggc.h"
00044 #include "tm_p.h"
00045 #include "debug.h"
00046 #include "target.h"
00047 #include "target-def.h"
00048 #include "langhooks.h"
00049
00050
00051
00052
00053
00054 enum internal_test
00055 {
00056 ITEST_EQ,
00057 ITEST_NE,
00058 ITEST_GT,
00059 ITEST_GE,
00060 ITEST_LT,
00061 ITEST_LE,
00062 ITEST_GTU,
00063 ITEST_GEU,
00064 ITEST_LTU,
00065 ITEST_LEU,
00066 ITEST_MAX
00067 };
00068
00069 struct constant;
00070
00071
00072
00073
00074
00075 struct iq2000_frame_info
00076 {
00077 long total_size;
00078 long var_size;
00079 long args_size;
00080 long extra_size;
00081 int gp_reg_size;
00082 int fp_reg_size;
00083 long mask;
00084 long gp_save_offset;
00085 long fp_save_offset;
00086 long gp_sp_offset;
00087 long fp_sp_offset;
00088 int initialized;
00089 int num_gp;
00090 } iq2000_frame_info;
00091
00092 struct machine_function GTY(())
00093 {
00094
00095 long total_size;
00096 long var_size;
00097 long args_size;
00098 long extra_size;
00099 int gp_reg_size;
00100 int fp_reg_size;
00101 long mask;
00102 long gp_save_offset;
00103 long fp_save_offset;
00104 long gp_sp_offset;
00105 long fp_sp_offset;
00106 int initialized;
00107 int num_gp;
00108 };
00109
00110
00111
00112
00113 char iq2000_print_operand_punct[256];
00114
00115
00116 enum processor_type iq2000_tune;
00117
00118
00119 int iq2000_isa;
00120
00121
00122
00123 rtx branch_cmp[2];
00124
00125
00126 enum cmp_type branch_type;
00127
00128
00129
00130
00131 static int iq2000_branch_likely;
00132
00133
00134 static int dslots_load_total;
00135 static int dslots_load_filled;
00136 static int dslots_jump_total;
00137
00138
00139 static int dslots_number_nops;
00140
00141
00142 static int num_refs[3];
00143
00144
00145 static rtx iq2000_load_reg;
00146 static rtx iq2000_load_reg2;
00147 static rtx iq2000_load_reg3;
00148 static rtx iq2000_load_reg4;
00149
00150
00151 static enum machine_mode gpr_mode;
00152
00153
00154
00155 static struct machine_function* iq2000_init_machine_status (void);
00156 static bool iq2000_handle_option (size_t, const char *, int);
00157 static section *iq2000_select_rtx_section (enum machine_mode, rtx,
00158 unsigned HOST_WIDE_INT);
00159 static void iq2000_init_builtins (void);
00160 static rtx iq2000_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
00161 static bool iq2000_return_in_memory (tree, tree);
00162 static void iq2000_setup_incoming_varargs (CUMULATIVE_ARGS *,
00163 enum machine_mode, tree, int *,
00164 int);
00165 static bool iq2000_rtx_costs (rtx, int, int, int *);
00166 static int iq2000_address_cost (rtx);
00167 static section *iq2000_select_section (tree, int, unsigned HOST_WIDE_INT);
00168 static bool iq2000_return_in_memory (tree, tree);
00169 static bool iq2000_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
00170 tree, bool);
00171 static int iq2000_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
00172 tree, bool);
00173
00174 #undef TARGET_INIT_BUILTINS
00175 #define TARGET_INIT_BUILTINS iq2000_init_builtins
00176 #undef TARGET_EXPAND_BUILTIN
00177 #define TARGET_EXPAND_BUILTIN iq2000_expand_builtin
00178 #undef TARGET_ASM_SELECT_RTX_SECTION
00179 #define TARGET_ASM_SELECT_RTX_SECTION iq2000_select_rtx_section
00180 #undef TARGET_HANDLE_OPTION
00181 #define TARGET_HANDLE_OPTION iq2000_handle_option
00182 #undef TARGET_RTX_COSTS
00183 #define TARGET_RTX_COSTS iq2000_rtx_costs
00184 #undef TARGET_ADDRESS_COST
00185 #define TARGET_ADDRESS_COST iq2000_address_cost
00186 #undef TARGET_ASM_SELECT_SECTION
00187 #define TARGET_ASM_SELECT_SECTION iq2000_select_section
00188
00189
00190
00191 #undef TARGET_HAVE_SWITCHABLE_BSS_SECTIONS
00192 #define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS false
00193
00194 #undef TARGET_PROMOTE_FUNCTION_ARGS
00195 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
00196 #undef TARGET_PROMOTE_FUNCTION_RETURN
00197 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
00198 #undef TARGET_PROMOTE_PROTOTYPES
00199 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
00200
00201 #undef TARGET_RETURN_IN_MEMORY
00202 #define TARGET_RETURN_IN_MEMORY iq2000_return_in_memory
00203 #undef TARGET_PASS_BY_REFERENCE
00204 #define TARGET_PASS_BY_REFERENCE iq2000_pass_by_reference
00205 #undef TARGET_CALLEE_COPIES
00206 #define TARGET_CALLEE_COPIES hook_callee_copies_named
00207 #undef TARGET_ARG_PARTIAL_BYTES
00208 #define TARGET_ARG_PARTIAL_BYTES iq2000_arg_partial_bytes
00209
00210 #undef TARGET_SETUP_INCOMING_VARARGS
00211 #define TARGET_SETUP_INCOMING_VARARGS iq2000_setup_incoming_varargs
00212 #undef TARGET_STRICT_ARGUMENT_NAMING
00213 #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
00214
00215 struct gcc_target targetm = TARGET_INITIALIZER;
00216
00217
00218
00219 int
00220 iq2000_check_split (rtx address, enum machine_mode mode)
00221 {
00222
00223
00224 if (GET_MODE_SIZE (mode) > (unsigned) UNITS_PER_WORD)
00225 return 0;
00226
00227 if ((GET_CODE (address) == SYMBOL_REF)
00228 || (GET_CODE (address) == CONST
00229 && GET_CODE (XEXP (XEXP (address, 0), 0)) == SYMBOL_REF)
00230 || GET_CODE (address) == LABEL_REF)
00231 return 1;
00232
00233 return 0;
00234 }
00235
00236
00237
00238 int
00239 iq2000_reg_mode_ok_for_base_p (rtx reg,
00240 enum machine_mode mode ATTRIBUTE_UNUSED,
00241 int strict)
00242 {
00243 return (strict
00244 ? REGNO_MODE_OK_FOR_BASE_P (REGNO (reg), mode)
00245 : GP_REG_OR_PSEUDO_NONSTRICT_P (REGNO (reg), mode));
00246 }
00247
00248
00249
00250
00251
00252 int
00253 iq2000_legitimate_address_p (enum machine_mode mode, rtx xinsn, int strict)
00254 {
00255 if (TARGET_DEBUG_A_MODE)
00256 {
00257 GO_PRINTF2 ("\n========== GO_IF_LEGITIMATE_ADDRESS, %sstrict\n",
00258 strict ? "" : "not ");
00259 GO_DEBUG_RTX (xinsn);
00260 }
00261
00262
00263
00264 if (CONSTANT_ADDRESS_P (xinsn)
00265 && ! (iq2000_check_split (xinsn, mode))
00266 && ! (GET_CODE (xinsn) == CONST_INT && ! SMALL_INT (xinsn)))
00267 return 1;
00268
00269 while (GET_CODE (xinsn) == SUBREG)
00270 xinsn = SUBREG_REG (xinsn);
00271
00272 if (GET_CODE (xinsn) == REG
00273 && iq2000_reg_mode_ok_for_base_p (xinsn, mode, strict))
00274 return 1;
00275
00276 if (GET_CODE (xinsn) == LO_SUM)
00277 {
00278 rtx xlow0 = XEXP (xinsn, 0);
00279 rtx xlow1 = XEXP (xinsn, 1);
00280
00281 while (GET_CODE (xlow0) == SUBREG)
00282 xlow0 = SUBREG_REG (xlow0);
00283 if (GET_CODE (xlow0) == REG
00284 && iq2000_reg_mode_ok_for_base_p (xlow0, mode, strict)
00285 && iq2000_check_split (xlow1, mode))
00286 return 1;
00287 }
00288
00289 if (GET_CODE (xinsn) == PLUS)
00290 {
00291 rtx xplus0 = XEXP (xinsn, 0);
00292 rtx xplus1 = XEXP (xinsn, 1);
00293 enum rtx_code code0;
00294 enum rtx_code code1;
00295
00296 while (GET_CODE (xplus0) == SUBREG)
00297 xplus0 = SUBREG_REG (xplus0);
00298 code0 = GET_CODE (xplus0);
00299
00300 while (GET_CODE (xplus1) == SUBREG)
00301 xplus1 = SUBREG_REG (xplus1);
00302 code1 = GET_CODE (xplus1);
00303
00304 if (code0 == REG
00305 && iq2000_reg_mode_ok_for_base_p (xplus0, mode, strict))
00306 {
00307 if (code1 == CONST_INT && SMALL_INT (xplus1)
00308 && SMALL_INT_UNSIGNED (xplus1) )
00309 return 1;
00310 }
00311 }
00312
00313 if (TARGET_DEBUG_A_MODE)
00314 GO_PRINTF ("Not a legitimate address\n");
00315
00316
00317 return 0;
00318 }
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329 const char *
00330 iq2000_fill_delay_slot (const char *ret, enum delay_type type, rtx operands[],
00331 rtx cur_insn)
00332 {
00333 rtx set_reg;
00334 enum machine_mode mode;
00335 rtx next_insn = cur_insn ? NEXT_INSN (cur_insn) : NULL_RTX;
00336 int num_nops;
00337
00338 if (type == DELAY_LOAD || type == DELAY_FCMP)
00339 num_nops = 1;
00340
00341 else
00342 num_nops = 0;
00343
00344
00345 next_insn = NEXT_INSN (cur_insn);
00346 while (next_insn != 0
00347 && (GET_CODE (next_insn) == NOTE
00348 || GET_CODE (next_insn) == CODE_LABEL))
00349 next_insn = NEXT_INSN (next_insn);
00350
00351 dslots_load_total += num_nops;
00352 if (TARGET_DEBUG_C_MODE
00353 || type == DELAY_NONE
00354 || operands == 0
00355 || cur_insn == 0
00356 || next_insn == 0
00357 || GET_CODE (next_insn) == CODE_LABEL
00358 || (set_reg = operands[0]) == 0)
00359 {
00360 dslots_number_nops = 0;
00361 iq2000_load_reg = 0;
00362 iq2000_load_reg2 = 0;
00363 iq2000_load_reg3 = 0;
00364 iq2000_load_reg4 = 0;
00365
00366 return ret;
00367 }
00368
00369 set_reg = operands[0];
00370 if (set_reg == 0)
00371 return ret;
00372
00373 while (GET_CODE (set_reg) == SUBREG)
00374 set_reg = SUBREG_REG (set_reg);
00375
00376 mode = GET_MODE (set_reg);
00377 dslots_number_nops = num_nops;
00378 iq2000_load_reg = set_reg;
00379 if (GET_MODE_SIZE (mode)
00380 > (unsigned) (UNITS_PER_WORD))
00381 iq2000_load_reg2 = gen_rtx_REG (SImode, REGNO (set_reg) + 1);
00382 else
00383 iq2000_load_reg2 = 0;
00384
00385 return ret;
00386 }
00387
00388
00389
00390
00391
00392 static void
00393 iq2000_count_memory_refs (rtx op, int num)
00394 {
00395 int additional = 0;
00396 int n_words = 0;
00397 rtx addr, plus0, plus1;
00398 enum rtx_code code0, code1;
00399 int looping;
00400
00401 if (TARGET_DEBUG_B_MODE)
00402 {
00403 fprintf (stderr, "\n========== iq2000_count_memory_refs:\n");
00404 debug_rtx (op);
00405 }
00406
00407
00408 addr = (GET_CODE (op) != MEM) ? op : XEXP (op, 0);
00409
00410
00411 do
00412 {
00413 looping = FALSE;
00414 switch (GET_CODE (addr))
00415 {
00416 case REG:
00417 case CONST_INT:
00418 case LO_SUM:
00419 break;
00420
00421 case PLUS:
00422 plus0 = XEXP (addr, 0);
00423 plus1 = XEXP (addr, 1);
00424 code0 = GET_CODE (plus0);
00425 code1 = GET_CODE (plus1);
00426
00427 if (code0 == REG)
00428 {
00429 additional++;
00430 addr = plus1;
00431 looping = 1;
00432 continue;
00433 }
00434
00435 if (code0 == CONST_INT)
00436 {
00437 addr = plus1;
00438 looping = 1;
00439 continue;
00440 }
00441
00442 if (code1 == REG)
00443 {
00444 additional++;
00445 addr = plus0;
00446 looping = 1;
00447 continue;
00448 }
00449
00450 if (code1 == CONST_INT)
00451 {
00452 addr = plus0;
00453 looping = 1;
00454 continue;
00455 }
00456
00457 if (code0 == SYMBOL_REF || code0 == LABEL_REF || code0 == CONST)
00458 {
00459 addr = plus0;
00460 looping = 1;
00461 continue;
00462 }
00463
00464 if (code1 == SYMBOL_REF || code1 == LABEL_REF || code1 == CONST)
00465 {
00466 addr = plus1;
00467 looping = 1;
00468 continue;
00469 }
00470
00471 break;
00472
00473 case LABEL_REF:
00474 n_words = 2;
00475 break;
00476
00477 case CONST:
00478 addr = XEXP (addr, 0);
00479 looping = 1;
00480 continue;
00481
00482 case SYMBOL_REF:
00483 n_words = SYMBOL_REF_FLAG (addr) ? 1 : 2;
00484 break;
00485
00486 default:
00487 break;
00488 }
00489 }
00490 while (looping);
00491
00492 if (n_words == 0)
00493 return;
00494
00495 n_words += additional;
00496 if (n_words > 3)
00497 n_words = 3;
00498
00499 num_refs[n_words-1] += num;
00500 }
00501
00502
00503
00504 static void
00505 abort_with_insn (rtx insn, const char * reason)
00506 {
00507 error (reason);
00508 debug_rtx (insn);
00509 fancy_abort (__FILE__, __LINE__, __FUNCTION__);
00510 }
00511
00512
00513
00514 const char *
00515 iq2000_move_1word (rtx operands[], rtx insn, int unsignedp)
00516 {
00517 const char *ret = 0;
00518 rtx op0 = operands[0];
00519 rtx op1 = operands[1];
00520 enum rtx_code code0 = GET_CODE (op0);
00521 enum rtx_code code1 = GET_CODE (op1);
00522 enum machine_mode mode = GET_MODE (op0);
00523 int subreg_offset0 = 0;
00524 int subreg_offset1 = 0;
00525 enum delay_type delay = DELAY_NONE;
00526
00527 while (code0 == SUBREG)
00528 {
00529 subreg_offset0 += subreg_regno_offset (REGNO (SUBREG_REG (op0)),
00530 GET_MODE (SUBREG_REG (op0)),
00531 SUBREG_BYTE (op0),
00532 GET_MODE (op0));
00533 op0 = SUBREG_REG (op0);
00534 code0 = GET_CODE (op0);
00535 }
00536
00537 while (code1 == SUBREG)
00538 {
00539 subreg_offset1 += subreg_regno_offset (REGNO (SUBREG_REG (op1)),
00540 GET_MODE (SUBREG_REG (op1)),
00541 SUBREG_BYTE (op1),
00542 GET_MODE (op1));
00543 op1 = SUBREG_REG (op1);
00544 code1 = GET_CODE (op1);
00545 }
00546
00547
00548 if (mode == CCmode)
00549 mode = SImode;
00550
00551 if (code0 == REG)
00552 {
00553 int regno0 = REGNO (op0) + subreg_offset0;
00554
00555 if (code1 == REG)
00556 {
00557 int regno1 = REGNO (op1) + subreg_offset1;
00558
00559
00560 if (regno0 == regno1)
00561 ret = "";
00562
00563 else if (GP_REG_P (regno0))
00564 {
00565 if (GP_REG_P (regno1))
00566 ret = "or\t%0,%%0,%1";
00567 }
00568
00569 }
00570
00571 else if (code1 == MEM)
00572 {
00573 delay = DELAY_LOAD;
00574
00575 if (TARGET_STATS)
00576 iq2000_count_memory_refs (op1, 1);
00577
00578 if (GP_REG_P (regno0))
00579 {
00580
00581
00582 switch (GET_MODE (op1))
00583 {
00584 default:
00585 break;
00586 case SFmode:
00587 ret = "lw\t%0,%1";
00588 break;
00589 case SImode:
00590 case CCmode:
00591 ret = "lw\t%0,%1";
00592 break;
00593 case HImode:
00594 ret = (unsignedp) ? "lhu\t%0,%1" : "lh\t%0,%1";
00595 break;
00596 case QImode:
00597 ret = (unsignedp) ? "lbu\t%0,%1" : "lb\t%0,%1";
00598 break;
00599 }
00600 }
00601 }
00602
00603 else if (code1 == CONST_INT
00604 || (code1 == CONST_DOUBLE
00605 && GET_MODE (op1) == VOIDmode))
00606 {
00607 if (code1 == CONST_DOUBLE)
00608 {
00609
00610
00611
00612 operands[1] = op1 = GEN_INT (CONST_DOUBLE_LOW (op1));
00613 }
00614
00615 if (INTVAL (op1) == 0)
00616 {
00617 if (GP_REG_P (regno0))
00618 ret = "or\t%0,%%0,%z1";
00619 }
00620 else if (GP_REG_P (regno0))
00621 {
00622 if (SMALL_INT_UNSIGNED (op1))
00623 ret = "ori\t%0,%%0,%x1\t\t\t# %1";
00624 else if (SMALL_INT (op1))
00625 ret = "addiu\t%0,%%0,%1\t\t\t# %1";
00626 else
00627 ret = "lui\t%0,%X1\t\t\t# %1\n\tori\t%0,%0,%x1";
00628 }
00629 }
00630
00631 else if (code1 == CONST_DOUBLE && mode == SFmode)
00632 {
00633 if (op1 == CONST0_RTX (SFmode))
00634 {
00635 if (GP_REG_P (regno0))
00636 ret = "or\t%0,%%0,%.";
00637 }
00638
00639 else
00640 {
00641 delay = DELAY_LOAD;
00642 ret = "li.s\t%0,%1";
00643 }
00644 }
00645
00646 else if (code1 == LABEL_REF)
00647 {
00648 if (TARGET_STATS)
00649 iq2000_count_memory_refs (op1, 1);
00650
00651 ret = "la\t%0,%a1";
00652 }
00653
00654 else if (code1 == SYMBOL_REF || code1 == CONST)
00655 {
00656 if (TARGET_STATS)
00657 iq2000_count_memory_refs (op1, 1);
00658
00659 ret = "la\t%0,%a1";
00660 }
00661
00662 else if (code1 == PLUS)
00663 {
00664 rtx add_op0 = XEXP (op1, 0);
00665 rtx add_op1 = XEXP (op1, 1);
00666
00667 if (GET_CODE (XEXP (op1, 1)) == REG
00668 && GET_CODE (XEXP (op1, 0)) == CONST_INT)
00669 add_op0 = XEXP (op1, 1), add_op1 = XEXP (op1, 0);
00670
00671 operands[2] = add_op0;
00672 operands[3] = add_op1;
00673 ret = "add%:\t%0,%2,%3";
00674 }
00675
00676 else if (code1 == HIGH)
00677 {
00678 operands[1] = XEXP (op1, 0);
00679 ret = "lui\t%0,%%hi(%1)";
00680 }
00681 }
00682
00683 else if (code0 == MEM)
00684 {
00685 if (TARGET_STATS)
00686 iq2000_count_memory_refs (op0, 1);
00687
00688 if (code1 == REG)
00689 {
00690 int regno1 = REGNO (op1) + subreg_offset1;
00691
00692 if (GP_REG_P (regno1))
00693 {
00694 switch (mode)
00695 {
00696 case SFmode: ret = "sw\t%1,%0"; break;
00697 case SImode: ret = "sw\t%1,%0"; break;
00698 case HImode: ret = "sh\t%1,%0"; break;
00699 case QImode: ret = "sb\t%1,%0"; break;
00700 default: break;
00701 }
00702 }
00703 }
00704
00705 else if (code1 == CONST_INT && INTVAL (op1) == 0)
00706 {
00707 switch (mode)
00708 {
00709 case SFmode: ret = "sw\t%z1,%0"; break;
00710 case SImode: ret = "sw\t%z1,%0"; break;
00711 case HImode: ret = "sh\t%z1,%0"; break;
00712 case QImode: ret = "sb\t%z1,%0"; break;
00713 default: break;
00714 }
00715 }
00716
00717 else if (code1 == CONST_DOUBLE && op1 == CONST0_RTX (mode))
00718 {
00719 switch (mode)
00720 {
00721 case SFmode: ret = "sw\t%.,%0"; break;
00722 case SImode: ret = "sw\t%.,%0"; break;
00723 case HImode: ret = "sh\t%.,%0"; break;
00724 case QImode: ret = "sb\t%.,%0"; break;
00725 default: break;
00726 }
00727 }
00728 }
00729
00730 if (ret == 0)
00731 {
00732 abort_with_insn (insn, "Bad move");
00733 return 0;
00734 }
00735
00736 if (delay != DELAY_NONE)
00737 return iq2000_fill_delay_slot (ret, delay, operands, insn);
00738
00739 return ret;
00740 }
00741
00742
00743
00744 static int
00745 iq2000_address_cost (rtx addr)
00746 {
00747 switch (GET_CODE (addr))
00748 {
00749 case LO_SUM:
00750 return 1;
00751
00752 case LABEL_REF:
00753 return 2;
00754
00755 case CONST:
00756 {
00757 rtx offset = const0_rtx;
00758
00759 addr = eliminate_constant_term (XEXP (addr, 0), & offset);
00760 if (GET_CODE (addr) == LABEL_REF)
00761 return 2;
00762
00763 if (GET_CODE (addr) != SYMBOL_REF)
00764 return 4;
00765
00766 if (! SMALL_INT (offset))
00767 return 2;
00768 }
00769
00770
00771
00772 case SYMBOL_REF:
00773 return SYMBOL_REF_FLAG (addr) ? 1 : 2;
00774
00775 case PLUS:
00776 {
00777 rtx plus0 = XEXP (addr, 0);
00778 rtx plus1 = XEXP (addr, 1);
00779
00780 if (GET_CODE (plus0) != REG && GET_CODE (plus1) == REG)
00781 plus0 = XEXP (addr, 1), plus1 = XEXP (addr, 0);
00782
00783 if (GET_CODE (plus0) != REG)
00784 break;
00785
00786 switch (GET_CODE (plus1))
00787 {
00788 case CONST_INT:
00789 return SMALL_INT (plus1) ? 1 : 2;
00790
00791 case CONST:
00792 case SYMBOL_REF:
00793 case LABEL_REF:
00794 case HIGH:
00795 case LO_SUM:
00796 return iq2000_address_cost (plus1) + 1;
00797
00798 default:
00799 break;
00800 }
00801 }
00802
00803 default:
00804 break;
00805 }
00806
00807 return 4;
00808 }
00809
00810
00811
00812 static enum internal_test
00813 map_test_to_internal_test (enum rtx_code test_code)
00814 {
00815 enum internal_test test = ITEST_MAX;
00816
00817 switch (test_code)
00818 {
00819 case EQ: test = ITEST_EQ; break;
00820 case NE: test = ITEST_NE; break;
00821 case GT: test = ITEST_GT; break;
00822 case GE: test = ITEST_GE; break;
00823 case LT: test = ITEST_LT; break;
00824 case LE: test = ITEST_LE; break;
00825 case GTU: test = ITEST_GTU; break;
00826 case GEU: test = ITEST_GEU; break;
00827 case LTU: test = ITEST_LTU; break;
00828 case LEU: test = ITEST_LEU; break;
00829 default: break;
00830 }
00831
00832 return test;
00833 }
00834
00835
00836
00837
00838
00839
00840
00841 rtx
00842 gen_int_relational (enum rtx_code test_code, rtx result, rtx cmp0, rtx cmp1,
00843 int *p_invert)
00844 {
00845 struct cmp_info
00846 {
00847 enum rtx_code test_code;
00848 int const_low;
00849 int const_high;
00850 int const_add;
00851 int reverse_regs;
00852 int invert_const;
00853 int invert_reg;
00854 int unsignedp;
00855 };
00856
00857 static struct cmp_info info[ (int)ITEST_MAX ] =
00858 {
00859 { XOR, 0, 65535, 0, 0, 0, 0, 0 },
00860 { XOR, 0, 65535, 0, 0, 1, 1, 0 },
00861 { LT, -32769, 32766, 1, 1, 1, 0, 0 },
00862 { LT, -32768, 32767, 0, 0, 1, 1, 0 },
00863 { LT, -32768, 32767, 0, 0, 0, 0, 0 },
00864 { LT, -32769, 32766, 1, 1, 0, 1, 0 },
00865 { LTU, -32769, 32766, 1, 1, 1, 0, 1 },
00866 { LTU, -32768, 32767, 0, 0, 1, 1, 1 },
00867 { LTU, -32768, 32767, 0, 0, 0, 0, 1 },
00868 { LTU, -32769, 32766, 1, 1, 0, 1, 1 },
00869 };
00870
00871 enum internal_test test;
00872 enum machine_mode mode;
00873 struct cmp_info *p_info;
00874 int branch_p;
00875 int eqne_p;
00876 int invert;
00877 rtx reg;
00878 rtx reg2;
00879
00880 test = map_test_to_internal_test (test_code);
00881 gcc_assert (test != ITEST_MAX);
00882
00883 p_info = &info[(int) test];
00884 eqne_p = (p_info->test_code == XOR);
00885
00886 mode = GET_MODE (cmp0);
00887 if (mode == VOIDmode)
00888 mode = GET_MODE (cmp1);
00889
00890
00891 branch_p = (result == 0);
00892 if (branch_p)
00893 {
00894 if (GET_CODE (cmp0) == REG || GET_CODE (cmp0) == SUBREG)
00895 {
00896
00897 if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0)
00898 return 0;
00899
00900
00901 if (eqne_p)
00902 return 0;
00903 }
00904
00905
00906 result = gen_reg_rtx (mode);
00907 }
00908
00909
00910 if (GET_CODE (cmp0) == CONST_INT)
00911 cmp0 = force_reg (mode, cmp0);
00912
00913 if (GET_CODE (cmp1) == CONST_INT)
00914 {
00915 HOST_WIDE_INT value = INTVAL (cmp1);
00916
00917 if (value < p_info->const_low
00918 || value > p_info->const_high)
00919 cmp1 = force_reg (mode, cmp1);
00920 }
00921
00922
00923 invert = (GET_CODE (cmp1) == CONST_INT
00924 ? p_info->invert_const : p_info->invert_reg);
00925
00926 if (p_invert != (int *)0)
00927 {
00928 *p_invert = invert;
00929 invert = 0;
00930 }
00931
00932
00933
00934 if (GET_CODE (cmp1) == CONST_INT)
00935 {
00936 if (p_info->const_add != 0)
00937 {
00938 HOST_WIDE_INT new = INTVAL (cmp1) + p_info->const_add;
00939
00940
00941
00942
00943 if ((p_info->unsignedp
00944 ? (unsigned HOST_WIDE_INT) new >
00945 (unsigned HOST_WIDE_INT) INTVAL (cmp1)
00946 : new > INTVAL (cmp1))
00947 != (p_info->const_add > 0))
00948 {
00949
00950
00951
00952 emit_move_insn (result, invert ? const0_rtx : const_true_rtx);
00953 return result;
00954 }
00955 else
00956 cmp1 = GEN_INT (new);
00957 }
00958 }
00959
00960 else if (p_info->reverse_regs)
00961 {
00962 rtx temp = cmp0;
00963 cmp0 = cmp1;
00964 cmp1 = temp;
00965 }
00966
00967 if (test == ITEST_NE && GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) == 0)
00968 reg = cmp0;
00969 else
00970 {
00971 reg = (invert || eqne_p) ? gen_reg_rtx (mode) : result;
00972 convert_move (reg, gen_rtx_fmt_ee (p_info->test_code, mode, cmp0, cmp1), 0);
00973 }
00974
00975 if (test == ITEST_NE)
00976 {
00977 convert_move (result, gen_rtx_GTU (mode, reg, const0_rtx), 0);
00978 if (p_invert != NULL)
00979 *p_invert = 0;
00980 invert = 0;
00981 }
00982
00983 else if (test == ITEST_EQ)
00984 {
00985 reg2 = invert ? gen_reg_rtx (mode) : result;
00986 convert_move (reg2, gen_rtx_LTU (mode, reg, const1_rtx), 0);
00987 reg = reg2;
00988 }
00989
00990 if (invert)
00991 {
00992 rtx one;
00993
00994 one = const1_rtx;
00995 convert_move (result, gen_rtx_XOR (mode, reg, one), 0);
00996 }
00997
00998 return result;
00999 }
01000
01001
01002
01003
01004
01005 void
01006 gen_conditional_branch (rtx operands[], enum rtx_code test_code)
01007 {
01008 enum cmp_type type = branch_type;
01009 rtx cmp0 = branch_cmp[0];
01010 rtx cmp1 = branch_cmp[1];
01011 enum machine_mode mode;
01012 rtx reg;
01013 int invert;
01014 rtx label1, label2;
01015
01016 switch (type)
01017 {
01018 case CMP_SI:
01019 case CMP_DI:
01020 mode = type == CMP_SI ? SImode : DImode;
01021 invert = 0;
01022 reg = gen_int_relational (test_code, NULL_RTX, cmp0, cmp1, &invert);
01023
01024 if (reg)
01025 {
01026 cmp0 = reg;
01027 cmp1 = const0_rtx;
01028 test_code = NE;
01029 }
01030 else if (GET_CODE (cmp1) == CONST_INT && INTVAL (cmp1) != 0)
01031
01032
01033 cmp1 = force_reg (mode, cmp1);
01034
01035 break;
01036
01037 case CMP_SF:
01038 case CMP_DF:
01039 reg = gen_reg_rtx (CCmode);
01040
01041
01042 emit_insn (gen_rtx_SET (VOIDmode, reg,
01043 gen_rtx_fmt_ee (test_code == NE ? EQ : test_code,
01044 CCmode, cmp0, cmp1)));
01045
01046 test_code = test_code == NE ? EQ : NE;
01047 mode = CCmode;
01048 cmp0 = reg;
01049 cmp1 = const0_rtx;
01050 invert = 0;
01051 break;
01052
01053 default:
01054 abort_with_insn (gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1),
01055 "bad test");
01056 }
01057
01058
01059 label1 = gen_rtx_LABEL_REF (VOIDmode, operands[0]);
01060 label2 = pc_rtx;
01061
01062 if (invert)
01063 {
01064 label2 = label1;
01065 label1 = pc_rtx;
01066 }
01067
01068 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
01069 gen_rtx_IF_THEN_ELSE (VOIDmode,
01070 gen_rtx_fmt_ee (test_code,
01071 mode,
01072 cmp0, cmp1),
01073 label1, label2)));
01074 }
01075
01076
01077
01078 void
01079 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
01080 rtx libname ATTRIBUTE_UNUSED)
01081 {
01082 static CUMULATIVE_ARGS zero_cum;
01083 tree param;
01084 tree next_param;
01085
01086 if (TARGET_DEBUG_D_MODE)
01087 {
01088 fprintf (stderr,
01089 "\ninit_cumulative_args, fntype = 0x%.8lx", (long) fntype);
01090
01091 if (!fntype)
01092 fputc ('\n', stderr);
01093
01094 else
01095 {
01096 tree ret_type = TREE_TYPE (fntype);
01097
01098 fprintf (stderr, ", fntype code = %s, ret code = %s\n",
01099 tree_code_name[(int)TREE_CODE (fntype)],
01100 tree_code_name[(int)TREE_CODE (ret_type)]);
01101 }
01102 }
01103
01104 *cum = zero_cum;
01105
01106
01107
01108
01109
01110
01111 for (param = fntype ? TYPE_ARG_TYPES (fntype) : 0;
01112 param != 0; param = next_param)
01113 {
01114 next_param = TREE_CHAIN (param);
01115 if (next_param == 0 && TREE_VALUE (param) != void_type_node)
01116 cum->gp_reg_found = 1;
01117 }
01118 }
01119
01120
01121
01122
01123 void
01124 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
01125 int named)
01126 {
01127 if (TARGET_DEBUG_D_MODE)
01128 {
01129 fprintf (stderr,
01130 "function_adv({gp reg found = %d, arg # = %2d, words = %2d}, %4s, ",
01131 cum->gp_reg_found, cum->arg_number, cum->arg_words,
01132 GET_MODE_NAME (mode));
01133 fprintf (stderr, "%p", (void *) type);
01134 fprintf (stderr, ", %d )\n\n", named);
01135 }
01136
01137 cum->arg_number++;
01138 switch (mode)
01139 {
01140 case VOIDmode:
01141 break;
01142
01143 default:
01144 gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
01145 || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT);
01146
01147 cum->gp_reg_found = 1;
01148 cum->arg_words += ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1)
01149 / UNITS_PER_WORD);
01150 break;
01151
01152 case BLKmode:
01153 cum->gp_reg_found = 1;
01154 cum->arg_words += ((int_size_in_bytes (type) + UNITS_PER_WORD - 1)
01155 / UNITS_PER_WORD);
01156 break;
01157
01158 case SFmode:
01159 cum->arg_words ++;
01160 if (! cum->gp_reg_found && cum->arg_number <= 2)
01161 cum->fp_code += 1 << ((cum->arg_number - 1) * 2);
01162 break;
01163
01164 case DFmode:
01165 cum->arg_words += 2;
01166 if (! cum->gp_reg_found && cum->arg_number <= 2)
01167 cum->fp_code += 2 << ((cum->arg_number - 1) * 2);
01168 break;
01169
01170 case DImode:
01171 cum->gp_reg_found = 1;
01172 cum->arg_words += 2;
01173 break;
01174
01175 case QImode:
01176 case HImode:
01177 case SImode:
01178 cum->gp_reg_found = 1;
01179 cum->arg_words ++;
01180 break;
01181 }
01182 }
01183
01184
01185
01186
01187 struct rtx_def *
01188 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
01189 int named)
01190 {
01191 rtx ret;
01192 int regbase = -1;
01193 int bias = 0;
01194 unsigned int *arg_words = &cum->arg_words;
01195 int struct_p = (type != 0
01196 && (TREE_CODE (type) == RECORD_TYPE
01197 || TREE_CODE (type) == UNION_TYPE
01198 || TREE_CODE (type) == QUAL_UNION_TYPE));
01199
01200 if (TARGET_DEBUG_D_MODE)
01201 {
01202 fprintf (stderr,
01203 "function_arg( {gp reg found = %d, arg # = %2d, words = %2d}, %4s, ",
01204 cum->gp_reg_found, cum->arg_number, cum->arg_words,
01205 GET_MODE_NAME (mode));
01206 fprintf (stderr, "%p", (void *) type);
01207 fprintf (stderr, ", %d ) = ", named);
01208 }
01209
01210
01211 cum->last_arg_fp = 0;
01212 switch (mode)
01213 {
01214 case SFmode:
01215 regbase = GP_ARG_FIRST;
01216 break;
01217
01218 case DFmode:
01219 cum->arg_words += cum->arg_words & 1;
01220
01221 regbase = GP_ARG_FIRST;
01222 break;
01223
01224 default:
01225 gcc_assert (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
01226 || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT);
01227
01228
01229 case BLKmode:
01230 if (type != NULL_TREE && TYPE_ALIGN (type) > (unsigned) BITS_PER_WORD)
01231 cum->arg_words += (cum->arg_words & 1);
01232 regbase = GP_ARG_FIRST;
01233 break;
01234
01235 case VOIDmode:
01236 case QImode:
01237 case HImode:
01238 case SImode:
01239 regbase = GP_ARG_FIRST;
01240 break;
01241
01242 case DImode:
01243 cum->arg_words += (cum->arg_words & 1);
01244 regbase = GP_ARG_FIRST;
01245 }
01246
01247 if (*arg_words >= (unsigned) MAX_ARGS_IN_REGISTERS)
01248 {
01249 if (TARGET_DEBUG_D_MODE)
01250 fprintf (stderr, "<stack>%s\n", struct_p ? ", [struct]" : "");
01251
01252 ret = 0;
01253 }
01254 else
01255 {
01256 gcc_assert (regbase != -1);
01257
01258 if (! type || TREE_CODE (type) != RECORD_TYPE
01259 || ! named || ! TYPE_SIZE_UNIT (type)
01260 || ! host_integerp (TYPE_SIZE_UNIT (type), 1))
01261 ret = gen_rtx_REG (mode, regbase + *arg_words + bias);
01262 else
01263 {
01264 tree field;
01265
01266 for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
01267 if (TREE_CODE (field) == FIELD_DECL
01268 && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
01269 && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD
01270 && host_integerp (bit_position (field), 0)
01271 && int_bit_position (field) % BITS_PER_WORD == 0)
01272 break;
01273
01274
01275
01276 if (! field || mode == DFmode)
01277 ret = gen_rtx_REG (mode, regbase + *arg_words + bias);
01278 else
01279 {
01280 unsigned int chunks;
01281 HOST_WIDE_INT bitpos;
01282 unsigned int regno;
01283 unsigned int i;
01284
01285
01286
01287 chunks
01288 = tree_low_cst (TYPE_SIZE_UNIT (type), 1) / UNITS_PER_WORD;
01289 if (chunks + *arg_words + bias > (unsigned) MAX_ARGS_IN_REGISTERS)
01290 chunks = MAX_ARGS_IN_REGISTERS - *arg_words - bias;
01291
01292
01293
01294 ret = gen_rtx_PARALLEL (mode, rtvec_alloc (chunks));
01295
01296 bitpos = 0;
01297 regno = regbase + *arg_words + bias;
01298 field = TYPE_FIELDS (type);
01299 for (i = 0; i < chunks; i++)
01300 {
01301 rtx reg;
01302
01303 for (; field; field = TREE_CHAIN (field))
01304 if (TREE_CODE (field) == FIELD_DECL
01305 && int_bit_position (field) >= bitpos)
01306 break;
01307
01308 if (field
01309 && int_bit_position (field) == bitpos
01310 && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
01311 && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD)
01312 reg = gen_rtx_REG (DFmode, regno++);
01313 else
01314 reg = gen_rtx_REG (word_mode, regno);
01315
01316 XVECEXP (ret, 0, i)
01317 = gen_rtx_EXPR_LIST (VOIDmode, reg,
01318 GEN_INT (bitpos / BITS_PER_UNIT));
01319
01320 bitpos += 64;
01321 regno++;
01322 }
01323 }
01324 }
01325
01326 if (TARGET_DEBUG_D_MODE)
01327 fprintf (stderr, "%s%s\n", reg_names[regbase + *arg_words + bias],
01328 struct_p ? ", [struct]" : "");
01329 }
01330
01331
01332
01333
01334
01335 if (mode == VOIDmode)
01336 {
01337 if (cum->num_adjusts > 0)
01338 ret = gen_rtx_PARALLEL ((enum machine_mode) cum->fp_code,
01339 gen_rtvec_v (cum->num_adjusts, cum->adjust));
01340 }
01341
01342 return ret;
01343 }
01344
01345 static int
01346 iq2000_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
01347 tree type ATTRIBUTE_UNUSED,
01348 bool named ATTRIBUTE_UNUSED)
01349 {
01350 if (mode == DImode && cum->arg_words == MAX_ARGS_IN_REGISTERS - 1)
01351 {
01352 if (TARGET_DEBUG_D_MODE)
01353 fprintf (stderr, "iq2000_arg_partial_bytes=%d\n", UNITS_PER_WORD);
01354 return UNITS_PER_WORD;
01355 }
01356
01357 return 0;
01358 }
01359
01360
01361
01362 void
01363 iq2000_va_start (tree valist, rtx nextarg)
01364 {
01365 int int_arg_words;
01366
01367 int gpr_save_area_size;
01368
01369 int_arg_words = current_function_args_info.arg_words;
01370
01371 if (int_arg_words < 8 )
01372
01373 gpr_save_area_size = (8 - int_arg_words) * UNITS_PER_WORD;
01374 else
01375 gpr_save_area_size = 0;
01376
01377
01378
01379 nextarg = plus_constant (nextarg, - gpr_save_area_size);
01380 std_expand_builtin_va_start (valist, nextarg);
01381 }
01382
01383
01384
01385 static struct machine_function *
01386 iq2000_init_machine_status (void)
01387 {
01388 struct machine_function *f;
01389
01390 f = ggc_alloc_cleared (sizeof (struct machine_function));
01391
01392 return f;
01393 }
01394
01395
01396
01397 static bool
01398 iq2000_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
01399 {
01400 switch (code)
01401 {
01402 case OPT_mcpu_:
01403 if (strcmp (arg, "iq10") == 0)
01404 iq2000_tune = PROCESSOR_IQ10;
01405 else if (strcmp (arg, "iq2000") == 0)
01406 iq2000_tune = PROCESSOR_IQ2000;
01407 else
01408 return false;
01409 return true;
01410
01411 case OPT_march_:
01412
01413 return (strcmp (arg, "default") == 0
01414 || strcmp (arg, "DEFAULT") == 0
01415 || strcmp (arg, "iq2000") == 0);
01416
01417 default:
01418 return true;
01419 }
01420 }
01421
01422
01423
01424 void
01425 override_options (void)
01426 {
01427 target_flags &= ~MASK_GPOPT;
01428
01429 iq2000_isa = IQ2000_ISA_DEFAULT;
01430
01431
01432
01433 iq2000_print_operand_punct['?'] = 1;
01434 iq2000_print_operand_punct['#'] = 1;
01435 iq2000_print_operand_punct['&'] = 1;
01436 iq2000_print_operand_punct['!'] = 1;
01437 iq2000_print_operand_punct['*'] = 1;
01438 iq2000_print_operand_punct['@'] = 1;
01439 iq2000_print_operand_punct['.'] = 1;
01440 iq2000_print_operand_punct['('] = 1;
01441 iq2000_print_operand_punct[')'] = 1;
01442 iq2000_print_operand_punct['['] = 1;
01443 iq2000_print_operand_punct[']'] = 1;
01444 iq2000_print_operand_punct['<'] = 1;
01445 iq2000_print_operand_punct['>'] = 1;
01446 iq2000_print_operand_punct['{'] = 1;
01447 iq2000_print_operand_punct['}'] = 1;
01448 iq2000_print_operand_punct['^'] = 1;
01449 iq2000_print_operand_punct['$'] = 1;
01450 iq2000_print_operand_punct['+'] = 1;
01451 iq2000_print_operand_punct['~'] = 1;
01452
01453
01454
01455 gpr_mode = SImode;
01456
01457
01458 init_machine_status = iq2000_init_machine_status;
01459 }
01460
01461
01462
01463
01464
01465 HOST_WIDE_INT
01466 iq2000_debugger_offset (rtx addr, HOST_WIDE_INT offset)
01467 {
01468 rtx offset2 = const0_rtx;
01469 rtx reg = eliminate_constant_term (addr, & offset2);
01470
01471 if (offset == 0)
01472 offset = INTVAL (offset2);
01473
01474 if (reg == stack_pointer_rtx || reg == frame_pointer_rtx
01475 || reg == hard_frame_pointer_rtx)
01476 {
01477 HOST_WIDE_INT frame_size = (!cfun->machine->initialized)
01478 ? compute_frame_size (get_frame_size ())
01479 : cfun->machine->total_size;
01480
01481 offset = offset - frame_size;
01482 }
01483
01484 return offset;
01485 }
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500 void
01501 final_prescan_insn (rtx insn, rtx opvec[] ATTRIBUTE_UNUSED,
01502 int noperands ATTRIBUTE_UNUSED)
01503 {
01504 if (dslots_number_nops > 0)
01505 {
01506 rtx pattern = PATTERN (insn);
01507 int length = get_attr_length (insn);
01508
01509
01510 if (length == 0
01511 || (iq2000_load_reg != 0 && reg_mentioned_p (iq2000_load_reg, pattern))
01512 || (iq2000_load_reg2 != 0 && reg_mentioned_p (iq2000_load_reg2, pattern))
01513 || (iq2000_load_reg3 != 0 && reg_mentioned_p (iq2000_load_reg3, pattern))
01514 || (iq2000_load_reg4 != 0
01515 && reg_mentioned_p (iq2000_load_reg4, pattern)))
01516 fputs ("\tnop\n", asm_out_file);
01517
01518 else
01519 dslots_load_filled ++;
01520
01521 while (--dslots_number_nops > 0)
01522 fputs ("\tnop\n", asm_out_file);
01523
01524 iq2000_load_reg = 0;
01525 iq2000_load_reg2 = 0;
01526 iq2000_load_reg3 = 0;
01527 iq2000_load_reg4 = 0;
01528 }
01529
01530 if ( (GET_CODE (insn) == JUMP_INSN
01531 || GET_CODE (insn) == CALL_INSN
01532 || (GET_CODE (PATTERN (insn)) == RETURN))
01533 && NEXT_INSN (PREV_INSN (insn)) == insn)
01534 {
01535 rtx nop_insn = emit_insn_after (gen_nop (), insn);
01536
01537 INSN_ADDRESSES_NEW (nop_insn, -1);
01538 }
01539
01540 if (TARGET_STATS
01541 && (GET_CODE (insn) == JUMP_INSN || GET_CODE (insn) == CALL_INSN))
01542 dslots_jump_total ++;
01543 }
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596 HOST_WIDE_INT
01597 compute_frame_size (HOST_WIDE_INT size)
01598 {
01599 int regno;
01600 HOST_WIDE_INT total_size;
01601 HOST_WIDE_INT var_size;
01602 HOST_WIDE_INT args_size;
01603 HOST_WIDE_INT extra_size;
01604 HOST_WIDE_INT gp_reg_rounded;
01605 HOST_WIDE_INT gp_reg_size;
01606 HOST_WIDE_INT fp_reg_size;
01607 long mask;
01608 int fp_inc;
01609 long fp_bits;
01610
01611 gp_reg_size = 0;
01612 fp_reg_size = 0;
01613 mask = 0;
01614 extra_size = IQ2000_STACK_ALIGN ((0));
01615 var_size = IQ2000_STACK_ALIGN (size);
01616 args_size = IQ2000_STACK_ALIGN (current_function_outgoing_args_size);
01617
01618
01619
01620 if (args_size == 0 && current_function_calls_alloca)
01621 args_size = 4 * UNITS_PER_WORD;
01622
01623 total_size = var_size + args_size + extra_size;
01624
01625
01626 for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
01627 {
01628 if (MUST_SAVE_REGISTER (regno))
01629 {
01630 gp_reg_size += GET_MODE_SIZE (gpr_mode);
01631 mask |= 1L << (regno - GP_REG_FIRST);
01632 }
01633 }
01634
01635
01636 if (current_function_calls_eh_return)
01637 {
01638 unsigned int i;
01639
01640 for (i = 0; ; ++i)
01641 {
01642 regno = EH_RETURN_DATA_REGNO (i);
01643 if (regno == (int) INVALID_REGNUM)
01644 break;
01645 gp_reg_size += GET_MODE_SIZE (gpr_mode);
01646 mask |= 1L << (regno - GP_REG_FIRST);
01647 }
01648 }
01649
01650 fp_inc = 2;
01651 fp_bits = 3;
01652 gp_reg_rounded = IQ2000_STACK_ALIGN (gp_reg_size);
01653 total_size += gp_reg_rounded + IQ2000_STACK_ALIGN (fp_reg_size);
01654
01655
01656
01657 if (total_size == extra_size
01658 && ! profile_flag)
01659 total_size = extra_size = 0;
01660
01661 total_size += IQ2000_STACK_ALIGN (current_function_pretend_args_size);
01662
01663
01664 cfun->machine->total_size = total_size;
01665 cfun->machine->var_size = var_size;
01666 cfun->machine->args_size = args_size;
01667 cfun->machine->extra_size = extra_size;
01668 cfun->machine->gp_reg_size = gp_reg_size;
01669 cfun->machine->fp_reg_size = fp_reg_size;
01670 cfun->machine->mask = mask;
01671 cfun->machine->initialized = reload_completed;
01672 cfun->machine->num_gp = gp_reg_size / UNITS_PER_WORD;
01673
01674 if (mask)
01675 {
01676 unsigned long offset;
01677
01678 offset = (args_size + extra_size + var_size
01679 + gp_reg_size - GET_MODE_SIZE (gpr_mode));
01680
01681 cfun->machine->gp_sp_offset = offset;
01682 cfun->machine->gp_save_offset = offset - total_size;
01683 }
01684 else
01685 {
01686 cfun->machine->gp_sp_offset = 0;
01687 cfun->machine->gp_save_offset = 0;
01688 }
01689
01690 cfun->machine->fp_sp_offset = 0;
01691 cfun->machine->fp_save_offset = 0;
01692
01693
01694 return total_size;
01695 }
01696
01697
01698
01699
01700
01701 int
01702 iq2000_initial_elimination_offset (int from, int to ATTRIBUTE_UNUSED)
01703 {
01704 int offset;
01705
01706 compute_frame_size (get_frame_size ());
01707 if ((from) == FRAME_POINTER_REGNUM)
01708 (offset) = 0;
01709 else if ((from) == ARG_POINTER_REGNUM)
01710 (offset) = (cfun->machine->total_size);
01711 else if ((from) == RETURN_ADDRESS_POINTER_REGNUM)
01712 {
01713 if (leaf_function_p ())
01714 (offset) = 0;
01715 else (offset) = cfun->machine->gp_sp_offset
01716 + ((UNITS_PER_WORD - (POINTER_SIZE / BITS_PER_UNIT))
01717 * (BYTES_BIG_ENDIAN != 0));
01718 }
01719
01720 return offset;
01721 }
01722
01723
01724
01725
01726
01727
01728 #define BITSET_P(VALUE,BIT) (((VALUE) & (1L << (BIT))) != 0)
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738 static rtx
01739 iq2000_add_large_offset_to_sp (HOST_WIDE_INT offset)
01740 {
01741 rtx reg = gen_rtx_REG (Pmode, IQ2000_TEMP2_REGNUM);
01742 rtx offset_rtx = GEN_INT (offset);
01743
01744 emit_move_insn (reg, offset_rtx);
01745 emit_insn (gen_addsi3 (reg, reg, stack_pointer_rtx));
01746 return reg;
01747 }
01748
01749
01750
01751
01752 static void
01753 iq2000_annotate_frame_insn (rtx insn, rtx dwarf_pattern)
01754 {
01755 RTX_FRAME_RELATED_P (insn) = 1;
01756 REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR,
01757 dwarf_pattern,
01758 REG_NOTES (insn));
01759 }
01760
01761
01762
01763
01764 static void
01765 iq2000_emit_frame_related_store (rtx mem, rtx reg, HOST_WIDE_INT offset)
01766 {
01767 rtx dwarf_address = plus_constant (stack_pointer_rtx, offset);
01768 rtx dwarf_mem = gen_rtx_MEM (GET_MODE (reg), dwarf_address);
01769
01770 iq2000_annotate_frame_insn (emit_move_insn (mem, reg),
01771 gen_rtx_SET (GET_MODE (reg), dwarf_mem, reg));
01772 }
01773
01774
01775
01776 static void
01777 save_restore_insns (int store_p)
01778 {
01779 long mask = cfun->machine->mask;
01780 int regno;
01781 rtx base_reg_rtx;
01782 HOST_WIDE_INT base_offset;
01783 HOST_WIDE_INT gp_offset;
01784 HOST_WIDE_INT end_offset;
01785
01786 gcc_assert (!frame_pointer_needed
01787 || BITSET_P (mask, HARD_FRAME_POINTER_REGNUM - GP_REG_FIRST));
01788
01789 if (mask == 0)
01790 {
01791 base_reg_rtx = 0, base_offset = 0;
01792 return;
01793 }
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807 gp_offset = cfun->machine->gp_sp_offset;
01808 end_offset
01809 = gp_offset - (cfun->machine->gp_reg_size
01810 - GET_MODE_SIZE (gpr_mode));
01811
01812 if (gp_offset < 0 || end_offset < 0)
01813 internal_error
01814 ("gp_offset (%ld) or end_offset (%ld) is less than zero",
01815 (long) gp_offset, (long) end_offset);
01816
01817 else if (gp_offset < 32768)
01818 base_reg_rtx = stack_pointer_rtx, base_offset = 0;
01819 else
01820 {
01821 int regno;
01822 int reg_save_count = 0;
01823
01824 for (regno = GP_REG_LAST; regno >= GP_REG_FIRST; regno--)
01825 if (BITSET_P (mask, regno - GP_REG_FIRST)) reg_save_count += 1;
01826 base_offset = gp_offset - ((reg_save_count - 1) * 4);
01827 base_reg_rtx = iq2000_add_large_offset_to_sp (base_offset);
01828 }
01829
01830 for (regno = GP_REG_LAST; regno >= GP_REG_FIRST; regno--)
01831 {
01832 if (BITSET_P (mask, regno - GP_REG_FIRST))
01833 {
01834 rtx reg_rtx;
01835 rtx mem_rtx
01836 = gen_rtx_MEM (gpr_mode,
01837 gen_rtx_PLUS (Pmode, base_reg_rtx,
01838 GEN_INT (gp_offset - base_offset)));
01839
01840 reg_rtx = gen_rtx_REG (gpr_mode, regno);
01841
01842 if (store_p)
01843 iq2000_emit_frame_related_store (mem_rtx, reg_rtx, gp_offset);
01844 else
01845 {
01846 emit_move_insn (reg_rtx, mem_rtx);
01847 }
01848 gp_offset -= GET_MODE_SIZE (gpr_mode);
01849 }
01850 }
01851 }
01852
01853
01854
01855 void
01856 iq2000_expand_prologue (void)
01857 {
01858 int regno;
01859 HOST_WIDE_INT tsize;
01860 int last_arg_is_vararg_marker = 0;
01861 tree fndecl = current_function_decl;
01862 tree fntype = TREE_TYPE (fndecl);
01863 tree fnargs = DECL_ARGUMENTS (fndecl);
01864 rtx next_arg_reg;
01865 int i;
01866 tree next_arg;
01867 tree cur_arg;
01868 CUMULATIVE_ARGS args_so_far;
01869 int store_args_on_stack = (iq2000_can_use_return_insn ());
01870
01871
01872 if (aggregate_value_p (DECL_RESULT (fndecl), fndecl)
01873 && ! current_function_returns_pcc_struct
01874 && targetm.calls.struct_value_rtx (TREE_TYPE (fndecl), 1) == 0)
01875 {
01876 tree type = build_pointer_type (fntype);
01877 tree function_result_decl = build_decl (PARM_DECL, NULL_TREE, type);
01878
01879 DECL_ARG_TYPE (function_result_decl) = type;
01880 TREE_CHAIN (function_result_decl) = fnargs;
01881 fnargs = function_result_decl;
01882 }
01883
01884
01885
01886
01887
01888
01889
01890
01891 INIT_CUMULATIVE_ARGS (args_so_far, fntype, NULL_RTX, 0, 0);
01892 regno = GP_ARG_FIRST;
01893
01894 for (cur_arg = fnargs; cur_arg != 0; cur_arg = next_arg)
01895 {
01896 tree passed_type = DECL_ARG_TYPE (cur_arg);
01897 enum machine_mode passed_mode = TYPE_MODE (passed_type);
01898 rtx entry_parm;
01899
01900 if (TREE_ADDRESSABLE (passed_type))
01901 {
01902 passed_type = build_pointer_type (passed_type);
01903 passed_mode = Pmode;
01904 }
01905
01906 entry_parm = FUNCTION_ARG (args_so_far, passed_mode, passed_type, 1);
01907
01908 FUNCTION_ARG_ADVANCE (args_so_far, passed_mode, passed_type, 1);
01909 next_arg = TREE_CHAIN (cur_arg);
01910
01911 if (entry_parm && store_args_on_stack)
01912 {
01913 if (next_arg == 0
01914 && DECL_NAME (cur_arg)
01915 && ((0 == strcmp (IDENTIFIER_POINTER (DECL_NAME (cur_arg)),
01916 "__builtin_va_alist"))
01917 || (0 == strcmp (IDENTIFIER_POINTER (DECL_NAME (cur_arg)),
01918 "va_alist"))))
01919 {
01920 last_arg_is_vararg_marker = 1;
01921 break;
01922 }
01923 else
01924 {
01925 int words;
01926
01927 gcc_assert (GET_CODE (entry_parm) == REG);
01928
01929
01930 if (GET_MODE (entry_parm) == BLKmode)
01931 words = (int_size_in_bytes (passed_type) + 3) / 4;
01932 else
01933 words = (GET_MODE_SIZE (GET_MODE (entry_parm)) + 3) / 4;
01934
01935 regno = REGNO (entry_parm) + words - 1;
01936 }
01937 }
01938 else
01939 {
01940 regno = GP_ARG_LAST+1;
01941 break;
01942 }
01943 }
01944
01945
01946
01947
01948
01949
01950 next_arg_reg = FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1);
01951 if (next_arg_reg != 0 && GET_CODE (next_arg_reg) == PARALLEL)
01952 {
01953 rtvec adjust = XVEC (next_arg_reg, 0);
01954 int num = GET_NUM_ELEM (adjust);
01955
01956 for (i = 0; i < num; i++)
01957 {
01958 rtx insn, pattern;
01959
01960 pattern = RTVEC_ELT (adjust, i);
01961 if (GET_CODE (pattern) != SET
01962 || GET_CODE (SET_SRC (pattern)) != ASHIFT)
01963 abort_with_insn (pattern, "Insn is not a shift");
01964 PUT_CODE (SET_SRC (pattern), ASHIFTRT);
01965
01966 insn = emit_insn (pattern);
01967
01968
01969
01970
01971
01972 REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX,
01973 REG_NOTES (insn));
01974 }
01975 }
01976
01977 tsize = compute_frame_size (get_frame_size ());
01978
01979
01980
01981 if (store_args_on_stack
01982 && ((TYPE_ARG_TYPES (fntype) != 0
01983 && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
01984 != void_type_node))
01985 || last_arg_is_vararg_marker))
01986 {
01987 int offset = (regno - GP_ARG_FIRST) * UNITS_PER_WORD;
01988 rtx ptr = stack_pointer_rtx;
01989
01990 for (; regno <= GP_ARG_LAST; regno++)
01991 {
01992 if (offset != 0)
01993 ptr = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset));
01994 emit_move_insn (gen_rtx_MEM (gpr_mode, ptr),
01995 gen_rtx_REG (gpr_mode, regno));
01996
01997 offset += GET_MODE_SIZE (gpr_mode);
01998 }
01999 }
02000
02001 if (tsize > 0)
02002 {
02003 rtx tsize_rtx = GEN_INT (tsize);
02004 rtx adjustment_rtx, insn, dwarf_pattern;
02005
02006 if (tsize > 32767)
02007 {
02008 adjustment_rtx = gen_rtx_REG (Pmode, IQ2000_TEMP1_REGNUM);
02009 emit_move_insn (adjustment_rtx, tsize_rtx);
02010 }
02011 else
02012 adjustment_rtx = tsize_rtx;
02013
02014 insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
02015 adjustment_rtx));
02016
02017 dwarf_pattern = gen_rtx_SET (Pmode, stack_pointer_rtx,
02018 plus_constant (stack_pointer_rtx, -tsize));
02019
02020 iq2000_annotate_frame_insn (insn, dwarf_pattern);
02021
02022 save_restore_insns (1);
02023
02024 if (frame_pointer_needed)
02025 {
02026 rtx insn = 0;
02027
02028 insn = emit_insn (gen_movsi (hard_frame_pointer_rtx,
02029 stack_pointer_rtx));
02030
02031 if (insn)
02032 RTX_FRAME_RELATED_P (insn) = 1;
02033 }
02034 }
02035
02036 emit_insn (gen_blockage ());
02037 }
02038
02039
02040
02041 void
02042 iq2000_expand_epilogue (void)
02043 {
02044 HOST_WIDE_INT tsize = cfun->machine->total_size;
02045 rtx tsize_rtx = GEN_INT (tsize);
02046 rtx tmp_rtx = (rtx)0;
02047
02048 if (iq2000_can_use_return_insn ())
02049 {
02050 emit_jump_insn (gen_return ());
02051 return;
02052 }
02053
02054 if (tsize > 32767)
02055 {
02056 tmp_rtx = gen_rtx_REG (Pmode, IQ2000_TEMP1_REGNUM);
02057 emit_move_insn (tmp_rtx, tsize_rtx);
02058 tsize_rtx = tmp_rtx;
02059 }
02060
02061 if (tsize > 0)
02062 {
02063 if (frame_pointer_needed)
02064 {
02065 emit_insn (gen_blockage ());
02066
02067 emit_insn (gen_movsi (stack_pointer_rtx, hard_frame_pointer_rtx));
02068 }
02069
02070 save_restore_insns (0);
02071
02072 if (current_function_calls_eh_return)
02073 {
02074 rtx eh_ofs = EH_RETURN_STACKADJ_RTX;
02075 emit_insn (gen_addsi3 (eh_ofs, eh_ofs, tsize_rtx));
02076 tsize_rtx = eh_ofs;
02077 }
02078
02079 emit_insn (gen_blockage ());
02080
02081 if (tsize != 0 || current_function_calls_eh_return)
02082 {
02083 emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
02084 tsize_rtx));
02085 }
02086 }
02087
02088 if (current_function_calls_eh_return)
02089 {
02090
02091 emit_move_insn (gen_rtx_REG (Pmode, HARD_FRAME_POINTER_REGNUM),
02092 stack_pointer_rtx);
02093 emit_insn (gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode,
02094 HARD_FRAME_POINTER_REGNUM)));
02095 emit_jump_insn (gen_eh_return_internal ());
02096 }
02097 else
02098 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode,
02099 GP_REG_FIRST + 31)));
02100 }
02101
02102 void
02103 iq2000_expand_eh_return (rtx address)
02104 {
02105 HOST_WIDE_INT gp_offset = cfun->machine->gp_sp_offset;
02106 rtx scratch;
02107
02108 scratch = plus_constant (stack_pointer_rtx, gp_offset);
02109 emit_move_insn (gen_rtx_MEM (GET_MODE (address), scratch), address);
02110 }
02111
02112
02113
02114
02115
02116 int
02117 iq2000_can_use_return_insn (void)
02118 {
02119 if (! reload_completed)
02120 return 0;
02121
02122 if (regs_ever_live[31] || profile_flag)
02123 return 0;
02124
02125 if (cfun->machine->initialized)
02126 return cfun->machine->total_size == 0;
02127
02128 return compute_frame_size (get_frame_size ()) == 0;
02129 }
02130
02131
02132
02133 static int
02134 symbolic_expression_p (rtx x)
02135 {
02136 if (GET_CODE (x) == SYMBOL_REF)
02137 return 1;
02138
02139 if (GET_CODE (x) == CONST)
02140 return symbolic_expression_p (XEXP (x, 0));
02141
02142 if (UNARY_P (x))
02143 return symbolic_expression_p (XEXP (x, 0));
02144
02145 if (ARITHMETIC_P (x))
02146 return (symbolic_expression_p (XEXP (x, 0))
02147 || symbolic_expression_p (XEXP (x, 1)));
02148
02149 return 0;
02150 }
02151
02152
02153
02154
02155 static section *
02156 iq2000_select_rtx_section (enum machine_mode mode, rtx x ATTRIBUTE_UNUSED,
02157 unsigned HOST_WIDE_INT align)
02158 {
02159
02160
02161 return mergeable_constant_section (mode, align, 0);
02162 }
02163
02164
02165
02166
02167
02168
02169
02170
02171 static section *
02172 iq2000_select_section (tree decl, int reloc ATTRIBUTE_UNUSED,
02173 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
02174 {
02175 if (TARGET_EMBEDDED_DATA)
02176 {
02177
02178
02179 if ((TREE_CODE (decl) == VAR_DECL
02180 && TREE_READONLY (decl) && !TREE_SIDE_EFFECTS (decl)
02181 && DECL_INITIAL (decl)
02182 && (DECL_INITIAL (decl) == error_mark_node
02183 || TREE_CONSTANT (DECL_INITIAL (decl))))
02184
02185 || TREE_CODE (decl) != VAR_DECL)
02186 return readonly_data_section;
02187 else
02188 return data_section;
02189 }
02190 else
02191 {
02192
02193
02194 if ((TREE_CODE (decl) == VAR_DECL
02195 && TREE_READONLY (decl) && !TREE_SIDE_EFFECTS (decl)
02196 && DECL_INITIAL (decl)
02197 && (DECL_INITIAL (decl) == error_mark_node
02198 || TREE_CONSTANT (DECL_INITIAL (decl))))
02199
02200 || TREE_CODE (decl) != VAR_DECL)
02201 return readonly_data_section;
02202 else
02203 return data_section;
02204 }
02205 }
02206
02207
02208
02209 rtx
02210 iq2000_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
02211 {
02212 int reg = GP_RETURN;
02213 enum machine_mode mode = TYPE_MODE (valtype);
02214 int unsignedp = TYPE_UNSIGNED (valtype);
02215
02216
02217
02218 mode = promote_mode (valtype, mode, &unsignedp, 1);
02219
02220 return gen_rtx_REG (mode, reg);
02221 }
02222
02223
02224
02225 static bool
02226 iq2000_pass_by_reference (CUMULATIVE_ARGS *cum, enum machine_mode mode,
02227 tree type, bool named ATTRIBUTE_UNUSED)
02228 {
02229 int size;
02230
02231
02232
02233
02234 if (cum && targetm.calls.must_pass_in_stack (mode, type))
02235 {
02236
02237
02238
02239 CUMULATIVE_ARGS temp;
02240
02241 temp = *cum;
02242 if (FUNCTION_ARG (temp, mode, type, named) != 0)
02243 return 1;
02244 }
02245
02246 if (type == NULL_TREE || mode == DImode || mode == DFmode)
02247 return 0;
02248
02249 size = int_size_in_bytes (type);
02250 return size == -1 || size > UNITS_PER_WORD;
02251 }
02252
02253
02254
02255
02256 int
02257 iq2000_adjust_insn_length (rtx insn, int length)
02258 {
02259
02260
02261 if (simplejump_p (insn)
02262 || ( (GET_CODE (insn) == JUMP_INSN
02263 || GET_CODE (insn) == CALL_INSN)))
02264 length += 4;
02265
02266 return length;
02267 }
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284 char *
02285 iq2000_output_conditional_branch (rtx insn, rtx * operands, int two_operands_p,
02286 int float_p, int inverted_p, int length)
02287 {
02288 static char buffer[200];
02289
02290 enum rtx_code code = GET_CODE (operands[0]);
02291
02292
02293 int need_z_p;
02294
02295
02296 const char *op1 = "%z2";
02297
02298
02299
02300 const char *op2 = (two_operands_p ? ",%z3" : ",%.");
02301
02302 const char *comp = (float_p ? "%F0" : "%C0");
02303
02304 const char *inverted_comp = (float_p ? "%W0" : "%N0");
02305
02306
02307
02308 iq2000_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
02309
02310 if (!two_operands_p)
02311 {
02312
02313
02314
02315
02316
02317
02318 switch (code)
02319 {
02320 case GTU:
02321 code = NE;
02322 break;
02323
02324 case LEU:
02325 code = EQ;
02326 break;
02327
02328 case GEU:
02329
02330 code = EQ;
02331 op1 = "%.";
02332 break;
02333
02334 case LTU:
02335
02336 code = NE;
02337 op1 = "%.";
02338 break;
02339
02340 default:
02341
02342 break;
02343 }
02344 }
02345
02346
02347
02348
02349 need_z_p = (!float_p && code != EQ && code != NE);
02350
02351
02352 if (need_z_p)
02353 op2 = "";
02354
02355
02356
02357 buffer[0] = '\0';
02358
02359 switch (length)
02360 {
02361 case 4:
02362 case 8:
02363
02364 if (float_p)
02365 sprintf (buffer, "b%s%%?\t%%Z2%%1",
02366 inverted_p ? inverted_comp : comp);
02367 else
02368 sprintf (buffer, "b%s%s%%?\t%s%s,%%1",
02369 inverted_p ? inverted_comp : comp,
02370 need_z_p ? "z" : "",
02371 op1,
02372 op2);
02373 return buffer;
02374
02375 case 12:
02376 case 16:
02377 {
02378
02379
02380
02381
02382
02383
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401
02402
02403 const char *target
02404 = ((iq2000_branch_likely || length == 16) ? ".+16" : ".+12");
02405 char *c;
02406
02407 c = strchr (buffer, '\0');
02408
02409
02410 if (float_p)
02411 sprintf (c, "b%s\t%%Z2%s",
02412 inverted_p ? comp : inverted_comp,
02413 target);
02414 else
02415 sprintf (c, "b%s%s\t%s%s,%s",
02416 inverted_p ? comp : inverted_comp,
02417 need_z_p ? "z" : "",
02418 op1,
02419 op2,
02420 target);
02421 strcat (c, "\n\tnop\n\tj\t%1");
02422 if (length == 16)
02423
02424
02425
02426 strcat (buffer, "\n\tnop");
02427 return buffer;
02428 }
02429
02430 default:
02431 gcc_unreachable ();
02432 }
02433
02434
02435 return 0;
02436 }
02437
02438 #define def_builtin(NAME, TYPE, CODE) \
02439 lang_hooks.builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
02440 NULL, NULL_TREE)
02441
02442 static void
02443 iq2000_init_builtins (void)
02444 {
02445 tree endlink = void_list_node;
02446 tree void_ftype, void_ftype_int, void_ftype_int_int;
02447 tree void_ftype_int_int_int;
02448 tree int_ftype_int, int_ftype_int_int, int_ftype_int_int_int;
02449 tree int_ftype_int_int_int_int;
02450
02451
02452 void_ftype
02453 = build_function_type (void_type_node,
02454 tree_cons (NULL_TREE, void_type_node, endlink));
02455
02456
02457 void_ftype_int
02458 = build_function_type (void_type_node,
02459 tree_cons (NULL_TREE, integer_type_node, endlink));
02460
02461
02462 void_ftype_int_int
02463 = build_function_type (void_type_node,
02464 tree_cons (NULL_TREE, integer_type_node,
02465 tree_cons (NULL_TREE, integer_type_node,
02466 endlink)));
02467
02468
02469 int_ftype_int
02470 = build_function_type (integer_type_node,
02471 tree_cons (NULL_TREE, integer_type_node, endlink));
02472
02473
02474 int_ftype_int_int
02475 = build_function_type (integer_type_node,
02476 tree_cons (NULL_TREE, integer_type_node,
02477 tree_cons (NULL_TREE, integer_type_node,
02478 endlink)));
02479
02480
02481 void_ftype_int_int_int
02482 = build_function_type
02483 (void_type_node,
02484 tree_cons (NULL_TREE, integer_type_node,
02485 tree_cons (NULL_TREE, integer_type_node,
02486 tree_cons (NULL_TREE,
02487 integer_type_node,
02488 endlink))));
02489
02490
02491 int_ftype_int_int_int_int
02492 = build_function_type
02493 (integer_type_node,
02494 tree_cons (NULL_TREE, integer_type_node,
02495 tree_cons (NULL_TREE, integer_type_node,
02496 tree_cons (NULL_TREE,
02497 integer_type_node,
02498 tree_cons (NULL_TREE,
02499 integer_type_node,
02500 endlink)))));
02501
02502
02503 int_ftype_int_int_int
02504 = build_function_type
02505 (integer_type_node,
02506 tree_cons (NULL_TREE, integer_type_node,
02507 tree_cons (NULL_TREE, integer_type_node,
02508 tree_cons (NULL_TREE,
02509 integer_type_node,
02510 endlink))));
02511
02512
02513 int_ftype_int_int_int_int
02514 = build_function_type
02515 (integer_type_node,
02516 tree_cons (NULL_TREE, integer_type_node,
02517 tree_cons (NULL_TREE, integer_type_node,
02518 tree_cons (NULL_TREE,
02519 integer_type_node,
02520 tree_cons (NULL_TREE,
02521 integer_type_node,
02522 endlink)))));
02523
02524 def_builtin ("__builtin_ado16", int_ftype_int_int, IQ2000_BUILTIN_ADO16);
02525 def_builtin ("__builtin_ram", int_ftype_int_int_int_int, IQ2000_BUILTIN_RAM);
02526 def_builtin ("__builtin_chkhdr", void_ftype_int_int, IQ2000_BUILTIN_CHKHDR);
02527 def_builtin ("__builtin_pkrl", void_ftype_int_int, IQ2000_BUILTIN_PKRL);
02528 def_builtin ("__builtin_cfc0", int_ftype_int, IQ2000_BUILTIN_CFC0);
02529 def_builtin ("__builtin_cfc1", int_ftype_int, IQ2000_BUILTIN_CFC1);
02530 def_builtin ("__builtin_cfc2", int_ftype_int, IQ2000_BUILTIN_CFC2);
02531 def_builtin ("__builtin_cfc3", int_ftype_int, IQ2000_BUILTIN_CFC3);
02532 def_builtin ("__builtin_ctc0", void_ftype_int_int, IQ2000_BUILTIN_CTC0);
02533 def_builtin ("__builtin_ctc1", void_ftype_int_int, IQ2000_BUILTIN_CTC1);
02534 def_builtin ("__builtin_ctc2", void_ftype_int_int, IQ2000_BUILTIN_CTC2);
02535 def_builtin ("__builtin_ctc3", void_ftype_int_int, IQ2000_BUILTIN_CTC3);
02536 def_builtin ("__builtin_mfc0", int_ftype_int, IQ2000_BUILTIN_MFC0);
02537 def_builtin ("__builtin_mfc1", int_ftype_int, IQ2000_BUILTIN_MFC1);
02538 def_builtin ("__builtin_mfc2", int_ftype_int, IQ2000_BUILTIN_MFC2);
02539 def_builtin ("__builtin_mfc3", int_ftype_int, IQ2000_BUILTIN_MFC3);
02540 def_builtin ("__builtin_mtc0", void_ftype_int_int, IQ2000_BUILTIN_MTC0);
02541 def_builtin ("__builtin_mtc1", void_ftype_int_int, IQ2000_BUILTIN_MTC1);
02542 def_builtin ("__builtin_mtc2", void_ftype_int_int, IQ2000_BUILTIN_MTC2);
02543 def_builtin ("__builtin_mtc3", void_ftype_int_int, IQ2000_BUILTIN_MTC3);
02544 def_builtin ("__builtin_lur", void_ftype_int_int, IQ2000_BUILTIN_LUR);
02545 def_builtin ("__builtin_rb", void_ftype_int_int, IQ2000_BUILTIN_RB);
02546 def_builtin ("__builtin_rx", void_ftype_int_int, IQ2000_BUILTIN_RX);
02547 def_builtin ("__builtin_srrd", void_ftype_int, IQ2000_BUILTIN_SRRD);
02548 def_builtin ("__builtin_srwr", void_ftype_int_int, IQ2000_BUILTIN_SRWR);
02549 def_builtin ("__builtin_wb", void_ftype_int_int, IQ2000_BUILTIN_WB);
02550 def_builtin ("__builtin_wx", void_ftype_int_int, IQ2000_BUILTIN_WX);
02551 def_builtin ("__builtin_luc32l", void_ftype_int_int, IQ2000_BUILTIN_LUC32L);
02552 def_builtin ("__builtin_luc64", void_ftype_int_int, IQ2000_BUILTIN_LUC64);
02553 def_builtin ("__builtin_luc64l", void_ftype_int_int, IQ2000_BUILTIN_LUC64L);
02554 def_builtin ("__builtin_luk", void_ftype_int_int, IQ2000_BUILTIN_LUK);
02555 def_builtin ("__builtin_lulck", void_ftype_int, IQ2000_BUILTIN_LULCK);
02556 def_builtin ("__builtin_lum32", void_ftype_int_int, IQ2000_BUILTIN_LUM32);
02557 def_builtin ("__builtin_lum32l", void_ftype_int_int, IQ2000_BUILTIN_LUM32L);
02558 def_builtin ("__builtin_lum64", void_ftype_int_int, IQ2000_BUILTIN_LUM64);
02559 def_builtin ("__builtin_lum64l", void_ftype_int_int, IQ2000_BUILTIN_LUM64L);
02560 def_builtin ("__builtin_lurl", void_ftype_int_int, IQ2000_BUILTIN_LURL);
02561 def_builtin ("__builtin_mrgb", int_ftype_int_int_int, IQ2000_BUILTIN_MRGB);
02562 def_builtin ("__builtin_srrdl", void_ftype_int, IQ2000_BUILTIN_SRRDL);
02563 def_builtin ("__builtin_srulck", void_ftype_int, IQ2000_BUILTIN_SRULCK);
02564 def_builtin ("__builtin_srwru", void_ftype_int_int, IQ2000_BUILTIN_SRWRU);
02565 def_builtin ("__builtin_trapqfl", void_ftype, IQ2000_BUILTIN_TRAPQFL);
02566 def_builtin ("__builtin_trapqne", void_ftype, IQ2000_BUILTIN_TRAPQNE);
02567 def_builtin ("__builtin_traprel", void_ftype_int, IQ2000_BUILTIN_TRAPREL);
02568 def_builtin ("__builtin_wbu", void_ftype_int_int_int, IQ2000_BUILTIN_WBU);
02569 def_builtin ("__builtin_syscall", void_ftype, IQ2000_BUILTIN_SYSCALL);
02570 }
02571
02572
02573
02574
02575 static rtx
02576 expand_one_builtin (enum insn_code icode, rtx target, tree arglist,
02577 enum rtx_code *code, int argcount)
02578 {
02579 rtx pat;
02580 tree arg [5];
02581 rtx op [5];
02582 enum machine_mode mode [5];
02583 int i;
02584
02585 mode[0] = insn_data[icode].operand[0].mode;
02586 for (i = 0; i < argcount; i++)
02587 {
02588 arg[i] = TREE_VALUE (arglist);
02589 arglist = TREE_CHAIN (arglist);
02590 op[i] = expand_expr (arg[i], NULL_RTX, VOIDmode, 0);
02591 mode[i] = insn_data[icode].operand[i].mode;
02592 if (code[i] == CONST_INT && GET_CODE (op[i]) != CONST_INT)
02593 error ("argument %qd is not a constant", i + 1);
02594 if (code[i] == REG
02595 && ! (*insn_data[icode].operand[i].predicate) (op[i], mode[i]))
02596 op[i] = copy_to_mode_reg (mode[i], op[i]);
02597 }
02598
02599 if (insn_data[icode].operand[0].constraint[0] == '=')
02600 {
02601 if (target == 0
02602 || GET_MODE (target) != mode[0]
02603 || ! (*insn_data[icode].operand[0].predicate) (target, mode[0]))
02604 target = gen_reg_rtx (mode[0]);
02605 }
02606 else
02607 target = 0;
02608
02609 switch (argcount)
02610 {
02611 case 0:
02612 pat = GEN_FCN (icode) (target);
02613 case 1:
02614 if (target)
02615 pat = GEN_FCN (icode) (target, op[0]);
02616 else
02617 pat = GEN_FCN (icode) (op[0]);
02618 break;
02619 case 2:
02620 if (target)
02621 pat = GEN_FCN (icode) (target, op[0], op[1]);
02622 else
02623 pat = GEN_FCN (icode) (op[0], op[1]);
02624 break;
02625 case 3:
02626 if (target)
02627 pat = GEN_FCN (icode) (target, op[0], op[1], op[2]);
02628 else
02629 pat = GEN_FCN (icode) (op[0], op[1], op[2]);
02630 break;
02631 case 4:
02632 if (target)
02633 pat = GEN_FCN (icode) (target, op[0], op[1], op[2], op[3]);
02634 else
02635 pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
02636 break;
02637 default:
02638 gcc_unreachable ();
02639 }
02640
02641 if (! pat)
02642 return 0;
02643 emit_insn (pat);
02644 return target;
02645 }
02646
02647
02648
02649
02650
02651
02652
02653 static rtx
02654 iq2000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
02655 enum machine_mode mode ATTRIBUTE_UNUSED,
02656 int ignore ATTRIBUTE_UNUSED)
02657 {
02658 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
02659 tree arglist = TREE_OPERAND (exp, 1);
02660 int fcode = DECL_FUNCTION_CODE (fndecl);
02661 enum rtx_code code [5];
02662
02663 code[0] = REG;
02664 code[1] = REG;
02665 code[2] = REG;
02666 code[3] = REG;
02667 code[4] = REG;
02668 switch (fcode)
02669 {
02670 default:
02671 break;
02672
02673 case IQ2000_BUILTIN_ADO16:
02674 return expand_one_builtin (CODE_FOR_ado16, target, arglist, code, 2);
02675
02676 case IQ2000_BUILTIN_RAM:
02677 code[1] = CONST_INT;
02678 code[2] = CONST_INT;
02679 code[3] = CONST_INT;
02680 return expand_one_builtin (CODE_FOR_ram, target, arglist, code, 4);
02681
02682 case IQ2000_BUILTIN_CHKHDR:
02683 return expand_one_builtin (CODE_FOR_chkhdr, target, arglist, code, 2);
02684
02685 case IQ2000_BUILTIN_PKRL:
02686 return expand_one_builtin (CODE_FOR_pkrl, target, arglist, code, 2);
02687
02688 case IQ2000_BUILTIN_CFC0:
02689 code[0] = CONST_INT;
02690 return expand_one_builtin (CODE_FOR_cfc0, target, arglist, code, 1);
02691
02692 case IQ2000_BUILTIN_CFC1:
02693 code[0] = CONST_INT;
02694 return expand_one_builtin (CODE_FOR_cfc1, target, arglist, code, 1);
02695
02696 case IQ2000_BUILTIN_CFC2:
02697 code[0] = CONST_INT;
02698 return expand_one_builtin (CODE_FOR_cfc2, target, arglist, code, 1);
02699
02700 case IQ2000_BUILTIN_CFC3:
02701 code[0] = CONST_INT;
02702 return expand_one_builtin (CODE_FOR_cfc3, target, arglist, code, 1);
02703
02704 case IQ2000_BUILTIN_CTC0:
02705 code[1] = CONST_INT;
02706 return expand_one_builtin (CODE_FOR_ctc0, target, arglist, code, 2);
02707
02708 case IQ2000_BUILTIN_CTC1:
02709 code[1] = CONST_INT;
02710 return expand_one_builtin (CODE_FOR_ctc1, target, arglist, code, 2);
02711
02712 case IQ2000_BUILTIN_CTC2:
02713 code[1] = CONST_INT;
02714 return expand_one_builtin (CODE_FOR_ctc2, target, arglist, code, 2);
02715
02716 case IQ2000_BUILTIN_CTC3:
02717 code[1] = CONST_INT;
02718 return expand_one_builtin (CODE_FOR_ctc3, target, arglist, code, 2);
02719
02720 case IQ2000_BUILTIN_MFC0:
02721 code[0] = CONST_INT;
02722 return expand_one_builtin (CODE_FOR_mfc0, target, arglist, code, 1);
02723
02724 case IQ2000_BUILTIN_MFC1:
02725 code[0] = CONST_INT;
02726 return expand_one_builtin (CODE_FOR_mfc1, target, arglist, code, 1);
02727
02728 case IQ2000_BUILTIN_MFC2:
02729 code[0] = CONST_INT;
02730 return expand_one_builtin (CODE_FOR_mfc2, target, arglist, code, 1);
02731
02732 case IQ2000_BUILTIN_MFC3:
02733 code[0] = CONST_INT;
02734 return expand_one_builtin (CODE_FOR_mfc3, target, arglist, code, 1);
02735
02736 case IQ2000_BUILTIN_MTC0:
02737 code[1] = CONST_INT;
02738 return expand_one_builtin (CODE_FOR_mtc0, target, arglist, code, 2);
02739
02740 case IQ2000_BUILTIN_MTC1:
02741 code[1] = CONST_INT;
02742 return expand_one_builtin (CODE_FOR_mtc1, target, arglist, code, 2);
02743
02744 case IQ2000_BUILTIN_MTC2:
02745 code[1] = CONST_INT;
02746 return expand_one_builtin (CODE_FOR_mtc2, target, arglist, code, 2);
02747
02748 case IQ2000_BUILTIN_MTC3:
02749 code[1] = CONST_INT;
02750 return expand_one_builtin (CODE_FOR_mtc3, target, arglist, code, 2);
02751
02752 case IQ2000_BUILTIN_LUR:
02753 return expand_one_builtin (CODE_FOR_lur, target, arglist, code, 2);
02754
02755 case IQ2000_BUILTIN_RB:
02756 return expand_one_builtin (CODE_FOR_rb, target, arglist, code, 2);
02757
02758 case IQ2000_BUILTIN_RX:
02759 return expand_one_builtin (CODE_FOR_rx, target, arglist, code, 2);
02760
02761 case IQ2000_BUILTIN_SRRD:
02762 return expand_one_builtin (CODE_FOR_srrd, target, arglist, code, 1);
02763
02764 case IQ2000_BUILTIN_SRWR:
02765 return expand_one_builtin (CODE_FOR_srwr, target, arglist, code, 2);
02766
02767 case IQ2000_BUILTIN_WB:
02768 return expand_one_builtin (CODE_FOR_wb, target, arglist, code, 2);
02769
02770 case IQ2000_BUILTIN_WX:
02771 return expand_one_builtin (CODE_FOR_wx, target, arglist, code, 2);
02772
02773 case IQ2000_BUILTIN_LUC32L:
02774 return expand_one_builtin (CODE_FOR_luc32l, target, arglist, code, 2);
02775
02776 case IQ2000_BUILTIN_LUC64:
02777 return expand_one_builtin (CODE_FOR_luc64, target, arglist, code, 2);
02778
02779 case IQ2000_BUILTIN_LUC64L:
02780 return expand_one_builtin (CODE_FOR_luc64l, target, arglist, code, 2);
02781
02782 case IQ2000_BUILTIN_LUK:
02783 return expand_one_builtin (CODE_FOR_luk, target, arglist, code, 2);
02784
02785 case IQ2000_BUILTIN_LULCK:
02786 return expand_one_builtin (CODE_FOR_lulck, target, arglist, code, 1);
02787
02788 case IQ2000_BUILTIN_LUM32:
02789 return expand_one_builtin (CODE_FOR_lum32, target, arglist, code, 2);
02790
02791 case IQ2000_BUILTIN_LUM32L:
02792 return expand_one_builtin (CODE_FOR_lum32l, target, arglist, code, 2);
02793
02794 case IQ2000_BUILTIN_LUM64:
02795 return expand_one_builtin (CODE_FOR_lum64, target, arglist, code, 2);
02796
02797 case IQ2000_BUILTIN_LUM64L:
02798 return expand_one_builtin (CODE_FOR_lum64l, target, arglist, code, 2);
02799
02800 case IQ2000_BUILTIN_LURL:
02801 return expand_one_builtin (CODE_FOR_lurl, target, arglist, code, 2);
02802
02803 case IQ2000_BUILTIN_MRGB:
02804 code[2] = CONST_INT;
02805 return expand_one_builtin (CODE_FOR_mrgb, target, arglist, code, 3);
02806
02807 case IQ2000_BUILTIN_SRRDL:
02808 return expand_one_builtin (CODE_FOR_srrdl, target, arglist, code, 1);
02809
02810 case IQ2000_BUILTIN_SRULCK:
02811 return expand_one_builtin (CODE_FOR_srulck, target, arglist, code, 1);
02812
02813 case IQ2000_BUILTIN_SRWRU:
02814 return expand_one_builtin (CODE_FOR_srwru, target, arglist, code, 2);
02815
02816 case IQ2000_BUILTIN_TRAPQFL:
02817 return expand_one_builtin (CODE_FOR_trapqfl, target, arglist, code, 0);
02818
02819 case IQ2000_BUILTIN_TRAPQNE:
02820 return expand_one_builtin (CODE_FOR_trapqne, target, arglist, code, 0);
02821
02822 case IQ2000_BUILTIN_TRAPREL:
02823 return expand_one_builtin (CODE_FOR_traprel, target, arglist, code, 1);
02824
02825 case IQ2000_BUILTIN_WBU:
02826 return expand_one_builtin (CODE_FOR_wbu, target, arglist, code, 3);
02827
02828 case IQ2000_BUILTIN_SYSCALL:
02829 return expand_one_builtin (CODE_FOR_syscall, target, arglist, code, 0);
02830 }
02831
02832 return NULL_RTX;
02833 }
02834
02835
02836
02837 static bool
02838 iq2000_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
02839 {
02840 return ((int_size_in_bytes (type) > (2 * UNITS_PER_WORD))
02841 || (int_size_in_bytes (type) == -1));
02842 }
02843
02844
02845
02846 static void
02847 iq2000_setup_incoming_varargs (CUMULATIVE_ARGS *cum,
02848 enum machine_mode mode ATTRIBUTE_UNUSED,
02849 tree type ATTRIBUTE_UNUSED, int * pretend_size,
02850 int no_rtl)
02851 {
02852 unsigned int iq2000_off = ! cum->last_arg_fp;
02853 unsigned int iq2000_fp_off = cum->last_arg_fp;
02854
02855 if ((cum->arg_words < MAX_ARGS_IN_REGISTERS - iq2000_off))
02856 {
02857 int iq2000_save_gp_regs
02858 = MAX_ARGS_IN_REGISTERS - cum->arg_words - iq2000_off;
02859 int iq2000_save_fp_regs
02860 = (MAX_ARGS_IN_REGISTERS - cum->fp_arg_words - iq2000_fp_off);
02861
02862 if (iq2000_save_gp_regs < 0)
02863 iq2000_save_gp_regs = 0;
02864 if (iq2000_save_fp_regs < 0)
02865 iq2000_save_fp_regs = 0;
02866
02867 *pretend_size = ((iq2000_save_gp_regs * UNITS_PER_WORD)
02868 + (iq2000_save_fp_regs * UNITS_PER_FPREG));
02869
02870 if (! (no_rtl))
02871 {
02872 if (cum->arg_words < MAX_ARGS_IN_REGISTERS - iq2000_off)
02873 {
02874 rtx ptr, mem;
02875 ptr = plus_constant (virtual_incoming_args_rtx,
02876 - (iq2000_save_gp_regs
02877 * UNITS_PER_WORD));
02878 mem = gen_rtx_MEM (BLKmode, ptr);
02879 move_block_from_reg
02880 (cum->arg_words + GP_ARG_FIRST + iq2000_off,
02881 mem,
02882 iq2000_save_gp_regs);
02883 }
02884 }
02885 }
02886 }
02887
02888
02889
02890
02891
02892 void
02893 print_operand_address (FILE * file, rtx addr)
02894 {
02895 if (!addr)
02896 error ("PRINT_OPERAND_ADDRESS, null pointer");
02897
02898 else
02899 switch (GET_CODE (addr))
02900 {
02901 case REG:
02902 if (REGNO (addr) == ARG_POINTER_REGNUM)
02903 abort_with_insn (addr, "Arg pointer not eliminated.");
02904
02905 fprintf (file, "0(%s)", reg_names [REGNO (addr)]);
02906 break;
02907
02908 case LO_SUM:
02909 {
02910 rtx arg0 = XEXP (addr, 0);
02911 rtx arg1 = XEXP (addr, 1);
02912
02913 if (GET_CODE (arg0) != REG)
02914 abort_with_insn (addr,
02915 "PRINT_OPERAND_ADDRESS, LO_SUM with #1 not REG.");
02916
02917 fprintf (file, "%%lo(");
02918 print_operand_address (file, arg1);
02919 fprintf (file, ")(%s)", reg_names [REGNO (arg0)]);
02920 }
02921 break;
02922
02923 case PLUS:
02924 {
02925 rtx reg = 0;
02926 rtx offset = 0;
02927 rtx arg0 = XEXP (addr, 0);
02928 rtx arg1 = XEXP (addr, 1);
02929
02930 if (GET_CODE (arg0) == REG)
02931 {
02932 reg = arg0;
02933 offset = arg1;
02934 if (GET_CODE (offset) == REG)
02935 abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, 2 regs");
02936 }
02937
02938 else if (GET_CODE (arg1) == REG)
02939 reg = arg1, offset = arg0;
02940 else if (CONSTANT_P (arg0) && CONSTANT_P (arg1))
02941 {
02942 output_addr_const (file, addr);
02943 break;
02944 }
02945 else
02946 abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, no regs");
02947
02948 if (! CONSTANT_P (offset))
02949 abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, invalid insn #2");
02950
02951 if (REGNO (reg) == ARG_POINTER_REGNUM)
02952 abort_with_insn (addr, "Arg pointer not eliminated.");
02953
02954 output_addr_const (file, offset);
02955 fprintf (file, "(%s)", reg_names [REGNO (reg)]);
02956 }
02957 break;
02958
02959 case LABEL_REF:
02960 case SYMBOL_REF:
02961 case CONST_INT:
02962 case CONST:
02963 output_addr_const (file, addr);
02964 if (GET_CODE (addr) == CONST_INT)
02965 fprintf (file, "(%s)", reg_names [0]);
02966 break;
02967
02968 default:
02969 abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, invalid insn #1");
02970 break;
02971 }
02972 }
02973
02974
02975
02976
02977
02978
02979
02980
02981
02982
02983
02984
02985
02986
02987
02988
02989
02990
02991
02992
02993
02994
02995
02996
02997
02998
02999
03000
03001
03002
03003
03004
03005
03006
03007
03008
03009
03010
03011
03012
03013
03014
03015
03016
03017
03018
03019
03020 void
03021 print_operand (FILE *file, rtx op, int letter)
03022 {
03023 enum rtx_code code;
03024
03025 if (PRINT_OPERAND_PUNCT_VALID_P (letter))
03026 {
03027 switch (letter)
03028 {
03029 case '?':
03030 if (iq2000_branch_likely)
03031 putc ('l', file);
03032 break;
03033
03034 case '@':
03035 fputs (reg_names [GP_REG_FIRST + 1], file);
03036 break;
03037
03038 case '.':
03039 fputs (reg_names [GP_REG_FIRST + 0], file);
03040 break;
03041
03042 case '$':
03043 fputs (reg_names[STACK_POINTER_REGNUM], file);
03044 break;
03045
03046 case '+':
03047 fputs (reg_names[GP_REG_FIRST + 28], file);
03048 break;
03049
03050 default:
03051 error ("PRINT_OPERAND: Unknown punctuation '%c'", letter);
03052 break;
03053 }
03054
03055 return;
03056 }
03057
03058 if (! op)
03059 {
03060 error ("PRINT_OPERAND null pointer");
03061 return;
03062 }
03063
03064 code = GET_CODE (op);
03065
03066 if (code == SIGN_EXTEND)
03067 op = XEXP (op, 0), code = GET_CODE (op);
03068
03069 if (letter == 'C')
03070 switch (code)
03071 {
03072 case EQ: fputs ("eq", file); break;
03073 case NE: fputs ("ne", file); break;
03074 case GT: fputs ("gt", file); break;
03075 case GE: fputs ("ge", file); break;
03076 case LT: fputs ("lt", file); break;
03077 case LE: fputs ("le", file); break;
03078 case GTU: fputs ("ne", file); break;
03079 case GEU: fputs ("geu", file); break;
03080 case LTU: fputs ("ltu", file); break;
03081 case LEU: fputs ("eq", file); break;
03082 default:
03083 abort_with_insn (op, "PRINT_OPERAND, invalid insn for %%C");
03084 }
03085
03086 else if (letter == 'N')
03087 switch (code)
03088 {
03089 case EQ: fputs ("ne", file); break;
03090 case NE: fputs ("eq", file); break;
03091 case GT: fputs ("le", file); break;
03092 case GE: fputs ("lt", file); break;
03093 case LT: fputs ("ge", file); break;
03094 case LE: fputs ("gt", file); break;
03095 case GTU: fputs ("leu", file); break;
03096 case GEU: fputs ("ltu", file); break;
03097 case LTU: fputs ("geu", file); break;
03098 case LEU: fputs ("gtu", file); break;
03099 default:
03100 abort_with_insn (op, "PRINT_OPERAND, invalid insn for %%N");
03101 }
03102
03103 else if (letter == 'F')
03104 switch (code)
03105 {
03106 case EQ: fputs ("c1f", file); break;
03107 case NE: fputs ("c1t", file); break;
03108 default:
03109 abort_with_insn (op, "PRINT_OPERAND, invalid insn for %%F");
03110 }
03111
03112 else if (letter == 'W')
03113 switch (code)
03114 {
03115 case EQ: fputs ("c1t", file); break;
03116 case NE: fputs ("c1f", file); break;
03117 default:
03118 abort_with_insn (op, "PRINT_OPERAND, invalid insn for %%W");
03119 }
03120
03121 else if (letter == 'A')
03122 fputs (code == LABEL_REF ? "i" : "in", file);
03123
03124 else if (letter == 'P')
03125 {
03126 if (code == LABEL_REF)
03127 output_addr_const (file, op);
03128 else if (code != PC)
03129 output_operand_lossage ("invalid %%P operand");
03130 }
03131
03132 else if (letter == 'p')
03133 {
03134 int value;
03135 if (code != CONST_INT
03136 || (value = exact_log2 (INTVAL (op))) < 0)
03137 output_operand_lossage ("invalid %%p value");
03138 fprintf (file, "%d", value);
03139 }
03140
03141 else if (letter == 'Z')
03142 {
03143 gcc_unreachable ();
03144 }
03145
03146 else if (code == REG || code == SUBREG)
03147 {
03148 int regnum;
03149
03150 if (code == REG)
03151 regnum = REGNO (op);
03152 else
03153 regnum = true_regnum (op);
03154
03155 if ((letter == 'M' && ! WORDS_BIG_ENDIAN)
03156 || (letter == 'L' && WORDS_BIG_ENDIAN)
03157 || letter == 'D')
03158 regnum++;
03159
03160 fprintf (file, "%s", reg_names[regnum]);
03161 }
03162
03163 else if (code == MEM)
03164 {
03165 if (letter == 'D')
03166 output_address (plus_constant (XEXP (op, 0), 4));
03167 else
03168 output_address (XEXP (op, 0));
03169 }
03170
03171 else if (code == CONST_DOUBLE
03172 && GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT)
03173 {
03174 char s[60];
03175
03176 real_to_decimal (s, CONST_DOUBLE_REAL_VALUE (op), sizeof (s), 0, 1);
03177 fputs (s, file);
03178 }
03179
03180 else if (letter == 'x' && GET_CODE (op) == CONST_INT)
03181 fprintf (file, HOST_WIDE_INT_PRINT_HEX, 0xffff & INTVAL(op));
03182
03183 else if (letter == 'X' && GET_CODE(op) == CONST_INT)
03184 fprintf (file, HOST_WIDE_INT_PRINT_HEX, 0xffff & (INTVAL (op) >> 16));
03185
03186 else if (letter == 'd' && GET_CODE(op) == CONST_INT)
03187 fprintf (file, HOST_WIDE_INT_PRINT_DEC, (INTVAL(op)));
03188
03189 else if (letter == 'z' && GET_CODE (op) == CONST_INT && INTVAL (op) == 0)
03190 fputs (reg_names[GP_REG_FIRST], file);
03191
03192 else if (letter == 'd' || letter == 'x' || letter == 'X')
03193 output_operand_lossage ("invalid use of %%d, %%x, or %%X");
03194
03195 else if (letter == 'B')
03196 fputs (code == EQ ? "z" : "n", file);
03197 else if (letter == 'b')
03198 fputs (code == EQ ? "n" : "z", file);
03199 else if (letter == 'T')
03200 fputs (code == EQ ? "f" : "t", file);
03201 else if (letter == 't')
03202 fputs (code == EQ ? "t" : "f", file);
03203
03204 else if (code == CONST && GET_CODE (XEXP (op, 0)) == REG)
03205 {
03206 print_operand (file, XEXP (op, 0), letter);
03207 }
03208
03209 else
03210 output_addr_const (file, op);
03211 }
03212
03213 static bool
03214 iq2000_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int * total)
03215 {
03216 enum machine_mode mode = GET_MODE (x);
03217
03218 switch (code)
03219 {
03220 case MEM:
03221 {
03222 int num_words = (GET_MODE_SIZE (mode) > UNITS_PER_WORD) ? 2 : 1;
03223
03224 if (simple_memory_operand (x, mode))
03225 return COSTS_N_INSNS (num_words);
03226
03227 * total = COSTS_N_INSNS (2 * num_words);
03228 break;
03229 }
03230
03231 case FFS:
03232 * total = COSTS_N_INSNS (6);
03233 break;
03234
03235 case AND:
03236 case IOR:
03237 case XOR:
03238 case NOT:
03239 * total = COSTS_N_INSNS (mode == DImode ? 2 : 1);
03240 break;
03241
03242 case ASHIFT:
03243 case ASHIFTRT:
03244 case LSHIFTRT:
03245 if (mode == DImode)
03246 * total = COSTS_N_INSNS ((GET_CODE (XEXP (x, 1)) == CONST_INT) ? 4 : 12);
03247 else
03248 * total = COSTS_N_INSNS (1);
03249 break;
03250
03251 case ABS:
03252 if (mode == SFmode || mode == DFmode)
03253 * total = COSTS_N_INSNS (1);
03254 else
03255 * total = COSTS_N_INSNS (4);
03256 break;
03257
03258 case PLUS:
03259 case MINUS:
03260 if (mode == SFmode || mode == DFmode)
03261 * total = COSTS_N_INSNS (6);
03262 else if (mode == DImode)
03263 * total = COSTS_N_INSNS (4);
03264 else
03265 * total = COSTS_N_INSNS (1);
03266 break;
03267
03268 case NEG:
03269 * total = (mode == DImode) ? 4 : 1;
03270 break;
03271
03272 case MULT:
03273 if (mode == SFmode)
03274 * total = COSTS_N_INSNS (7);
03275 else if (mode == DFmode)
03276 * total = COSTS_N_INSNS (8);
03277 else
03278 * total = COSTS_N_INSNS (10);
03279 break;
03280
03281 case DIV:
03282 case MOD:
03283 if (mode == SFmode)
03284 * total = COSTS_N_INSNS (23);
03285 else if (mode == DFmode)
03286 * total = COSTS_N_INSNS (36);
03287 else
03288 * total = COSTS_N_INSNS (69);
03289 break;
03290
03291 case UDIV:
03292 case UMOD:
03293 * total = COSTS_N_INSNS (69);
03294 break;
03295
03296 case SIGN_EXTEND:
03297 * total = COSTS_N_INSNS (2);
03298 break;
03299
03300 case ZERO_EXTEND:
03301 * total = COSTS_N_INSNS (1);
03302 break;
03303
03304 case CONST_INT:
03305 * total = 0;
03306 break;
03307
03308 case LABEL_REF:
03309 * total = COSTS_N_INSNS (2);
03310 break;
03311
03312 case CONST:
03313 {
03314 rtx offset = const0_rtx;
03315 rtx symref = eliminate_constant_term (XEXP (x, 0), & offset);
03316
03317 if (GET_CODE (symref) == LABEL_REF)
03318 * total = COSTS_N_INSNS (2);
03319 else if (GET_CODE (symref) != SYMBOL_REF)
03320 * total = COSTS_N_INSNS (4);
03321
03322 else if (INTVAL (offset) < -32768 || INTVAL (offset) > 32767)
03323 * total = COSTS_N_INSNS (2);
03324 else
03325 * total = COSTS_N_INSNS (SYMBOL_REF_FLAG (symref) ? 1 : 2);
03326 break;
03327 }
03328
03329 case SYMBOL_REF:
03330 * total = COSTS_N_INSNS (SYMBOL_REF_FLAG (x) ? 1 : 2);
03331 break;
03332
03333 case CONST_DOUBLE:
03334 {
03335 rtx high, low;
03336
03337 split_double (x, & high, & low);
03338
03339 * total = COSTS_N_INSNS ( (high == CONST0_RTX (GET_MODE (high))
03340 || low == CONST0_RTX (GET_MODE (low)))
03341 ? 2 : 4);
03342 break;
03343 }
03344
03345 default:
03346 return false;
03347 }
03348 return true;
03349 }
03350
03351 #include "gt-iq2000.h"