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