00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023 #include "system.h"
00024 #include "coretypes.h"
00025 #include "tm.h"
00026 #include "rtl.h"
00027 #include "regs.h"
00028 #include "hard-reg-set.h"
00029 #include "basic-block.h"
00030 #include "real.h"
00031 #include "insn-config.h"
00032 #include "conditions.h"
00033 #include "insn-flags.h"
00034 #include "insn-attr.h"
00035 #include "insn-codes.h"
00036 #include "recog.h"
00037 #include "output.h"
00038 #include "tree.h"
00039 #include "expr.h"
00040 #include "flags.h"
00041 #include "reload.h"
00042 #include "tm_p.h"
00043 #include "function.h"
00044 #include "toplev.h"
00045 #include "optabs.h"
00046 #include "libfuncs.h"
00047 #include "ggc.h"
00048 #include "target.h"
00049 #include "target-def.h"
00050 #include "langhooks.h"
00051 #include "tree-gimple.h"
00052
00053
00054
00055
00056
00057
00058 enum internal_test
00059 {
00060 ITEST_EQ,
00061 ITEST_NE,
00062 ITEST_GT,
00063 ITEST_GE,
00064 ITEST_LT,
00065 ITEST_LE,
00066 ITEST_GTU,
00067 ITEST_GEU,
00068 ITEST_LTU,
00069 ITEST_LEU,
00070 ITEST_MAX
00071 };
00072
00073
00074
00075 rtx branch_cmp[2];
00076
00077
00078 enum cmp_type branch_type;
00079
00080
00081
00082 char xtensa_hard_regno_mode_ok[(int) MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER];
00083
00084
00085 unsigned xtensa_current_frame_size;
00086
00087
00088 #define LARGEST_MOVE_RATIO 15
00089
00090
00091 struct machine_function GTY(())
00092 {
00093 int accesses_prev_frame;
00094 bool need_a7_copy;
00095 bool vararg_a7;
00096 rtx set_frame_ptr_insn;
00097 };
00098
00099
00100
00101
00102
00103 const char xtensa_leaf_regs[FIRST_PSEUDO_REGISTER] =
00104 {
00105 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00106 1, 1, 1,
00107 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
00108 1
00109 };
00110
00111
00112 const enum reg_class xtensa_regno_to_class[FIRST_PSEUDO_REGISTER] =
00113 {
00114 RL_REGS, SP_REG, RL_REGS, RL_REGS,
00115 RL_REGS, RL_REGS, RL_REGS, GR_REGS,
00116 RL_REGS, RL_REGS, RL_REGS, RL_REGS,
00117 RL_REGS, RL_REGS, RL_REGS, RL_REGS,
00118 AR_REGS, AR_REGS, BR_REGS,
00119 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00120 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00121 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00122 FP_REGS, FP_REGS, FP_REGS, FP_REGS,
00123 ACC_REG,
00124 };
00125
00126
00127 enum reg_class xtensa_char_to_class[256] =
00128 {
00129 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00130 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00131 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00132 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00133 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00134 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00135 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00136 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00137 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00138 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00139 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00140 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00141 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00142 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00143 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00144 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00145 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00146 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00147 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00148 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00149 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00150 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00151 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00152 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00153 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00154 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00155 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00156 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00157 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00158 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00159 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00160 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00161 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00162 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00163 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00164 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00165 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00166 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00167 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00168 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00169 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00170 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00171 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00172 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00173 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00174 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00175 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00176 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00177 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00178 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00179 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00180 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00181 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00182 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00183 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00184 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00185 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00186 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00187 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00188 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00189 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00190 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00191 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00192 NO_REGS, NO_REGS, NO_REGS, NO_REGS,
00193 };
00194
00195 static int b4const_or_zero (int);
00196 static enum internal_test map_test_to_internal_test (enum rtx_code);
00197 static rtx gen_int_relational (enum rtx_code, rtx, rtx, int *);
00198 static rtx gen_float_relational (enum rtx_code, rtx, rtx);
00199 static rtx gen_conditional_move (rtx);
00200 static rtx fixup_subreg_mem (rtx);
00201 static struct machine_function * xtensa_init_machine_status (void);
00202 static bool xtensa_return_in_msb (tree);
00203 static void printx (FILE *, signed int);
00204 static void xtensa_function_epilogue (FILE *, HOST_WIDE_INT);
00205 static rtx xtensa_builtin_saveregs (void);
00206 static unsigned int xtensa_multibss_section_type_flags (tree, const char *,
00207 int) ATTRIBUTE_UNUSED;
00208 static void xtensa_select_rtx_section (enum machine_mode, rtx,
00209 unsigned HOST_WIDE_INT);
00210 static bool xtensa_rtx_costs (rtx, int, int, int *);
00211 static tree xtensa_build_builtin_va_list (void);
00212 static bool xtensa_return_in_memory (tree, tree);
00213 static tree xtensa_gimplify_va_arg_expr (tree, tree, tree *, tree *);
00214
00215 static const int reg_nonleaf_alloc_order[FIRST_PSEUDO_REGISTER] =
00216 REG_ALLOC_ORDER;
00217
00218
00219
00220
00221
00222
00223
00224 #undef TARGET_ASM_FUNCTION_EPILOGUE
00225 #define TARGET_ASM_FUNCTION_EPILOGUE xtensa_function_epilogue
00226
00227
00228
00229
00230 #undef TARGET_ASM_ALIGNED_SI_OP
00231 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
00232
00233 #undef TARGET_ASM_SELECT_RTX_SECTION
00234 #define TARGET_ASM_SELECT_RTX_SECTION xtensa_select_rtx_section
00235
00236 #undef TARGET_RTX_COSTS
00237 #define TARGET_RTX_COSTS xtensa_rtx_costs
00238 #undef TARGET_ADDRESS_COST
00239 #define TARGET_ADDRESS_COST hook_int_rtx_0
00240
00241 #undef TARGET_BUILD_BUILTIN_VA_LIST
00242 #define TARGET_BUILD_BUILTIN_VA_LIST xtensa_build_builtin_va_list
00243
00244 #undef TARGET_PROMOTE_FUNCTION_ARGS
00245 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
00246 #undef TARGET_PROMOTE_FUNCTION_RETURN
00247 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
00248 #undef TARGET_PROMOTE_PROTOTYPES
00249 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
00250
00251 #undef TARGET_RETURN_IN_MEMORY
00252 #define TARGET_RETURN_IN_MEMORY xtensa_return_in_memory
00253 #undef TARGET_SPLIT_COMPLEX_ARG
00254 #define TARGET_SPLIT_COMPLEX_ARG hook_bool_tree_true
00255 #undef TARGET_MUST_PASS_IN_STACK
00256 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
00257
00258 #undef TARGET_EXPAND_BUILTIN_SAVEREGS
00259 #define TARGET_EXPAND_BUILTIN_SAVEREGS xtensa_builtin_saveregs
00260 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
00261 #define TARGET_GIMPLIFY_VA_ARG_EXPR xtensa_gimplify_va_arg_expr
00262
00263 #undef TARGET_RETURN_IN_MSB
00264 #define TARGET_RETURN_IN_MSB xtensa_return_in_msb
00265
00266 struct gcc_target targetm = TARGET_INITIALIZER;
00267
00268
00269
00270
00271
00272
00273 int
00274 xtensa_b4constu (int v)
00275 {
00276 switch (v)
00277 {
00278 case 32768:
00279 case 65536:
00280 case 2:
00281 case 3:
00282 case 4:
00283 case 5:
00284 case 6:
00285 case 7:
00286 case 8:
00287 case 10:
00288 case 12:
00289 case 16:
00290 case 32:
00291 case 64:
00292 case 128:
00293 case 256:
00294 return 1;
00295 }
00296 return 0;
00297 }
00298
00299 int
00300 xtensa_simm8x256 (int v)
00301 {
00302 return (v & 255) == 0 && (v >= -32768 && v <= 32512);
00303 }
00304
00305 int
00306 xtensa_ai4const (int v)
00307 {
00308 return (v == -1 || (v >= 1 && v <= 15));
00309 }
00310
00311 int
00312 xtensa_simm7 (int v)
00313 {
00314 return v >= -32 && v <= 95;
00315 }
00316
00317 int
00318 xtensa_b4const (int v)
00319 {
00320 switch (v)
00321 {
00322 case -1:
00323 case 1:
00324 case 2:
00325 case 3:
00326 case 4:
00327 case 5:
00328 case 6:
00329 case 7:
00330 case 8:
00331 case 10:
00332 case 12:
00333 case 16:
00334 case 32:
00335 case 64:
00336 case 128:
00337 case 256:
00338 return 1;
00339 }
00340 return 0;
00341 }
00342
00343 int
00344 xtensa_simm8 (int v)
00345 {
00346 return v >= -128 && v <= 127;
00347 }
00348
00349 int
00350 xtensa_tp7 (int v)
00351 {
00352 return (v >= 7 && v <= 22);
00353 }
00354
00355 int
00356 xtensa_lsi4x4 (int v)
00357 {
00358 return (v & 3) == 0 && (v >= 0 && v <= 60);
00359 }
00360
00361 int
00362 xtensa_simm12b (int v)
00363 {
00364 return v >= -2048 && v <= 2047;
00365 }
00366
00367 int
00368 xtensa_uimm8 (int v)
00369 {
00370 return v >= 0 && v <= 255;
00371 }
00372
00373 int
00374 xtensa_uimm8x2 (int v)
00375 {
00376 return (v & 1) == 0 && (v >= 0 && v <= 510);
00377 }
00378
00379 int
00380 xtensa_uimm8x4 (int v)
00381 {
00382 return (v & 3) == 0 && (v >= 0 && v <= 1020);
00383 }
00384
00385
00386
00387
00388
00389 int
00390 xt_true_regnum (rtx x)
00391 {
00392 if (GET_CODE (x) == REG)
00393 {
00394 if (reg_renumber
00395 && REGNO (x) >= FIRST_PSEUDO_REGISTER
00396 && reg_renumber[REGNO (x)] >= 0)
00397 return reg_renumber[REGNO (x)];
00398 return REGNO (x);
00399 }
00400 if (GET_CODE (x) == SUBREG)
00401 {
00402 int base = xt_true_regnum (SUBREG_REG (x));
00403 if (base >= 0 && base < FIRST_PSEUDO_REGISTER)
00404 return base + subreg_regno_offset (REGNO (SUBREG_REG (x)),
00405 GET_MODE (SUBREG_REG (x)),
00406 SUBREG_BYTE (x), GET_MODE (x));
00407 }
00408 return -1;
00409 }
00410
00411
00412 int
00413 add_operand (rtx op, enum machine_mode mode)
00414 {
00415 if (GET_CODE (op) == CONST_INT)
00416 return (xtensa_simm8 (INTVAL (op)) || xtensa_simm8x256 (INTVAL (op)));
00417
00418 return register_operand (op, mode);
00419 }
00420
00421
00422 int
00423 arith_operand (rtx op, enum machine_mode mode)
00424 {
00425 if (GET_CODE (op) == CONST_INT)
00426 return xtensa_simm8 (INTVAL (op));
00427
00428 return register_operand (op, mode);
00429 }
00430
00431
00432 int
00433 nonimmed_operand (rtx op, enum machine_mode mode)
00434 {
00435
00436
00437
00438 if (memory_operand (op, mode))
00439 return !constantpool_address_p (XEXP (op, 0));
00440
00441 return register_operand (op, mode);
00442 }
00443
00444
00445 int
00446 mem_operand (rtx op, enum machine_mode mode)
00447 {
00448
00449
00450
00451 if (memory_operand (op, mode))
00452 return !constantpool_address_p (XEXP (op, 0));
00453
00454 return FALSE;
00455 }
00456
00457
00458 int
00459 xtensa_valid_move (enum machine_mode mode, rtx *operands)
00460 {
00461
00462
00463
00464 if (register_operand (operands[0], mode))
00465 {
00466 int dst_regnum = xt_true_regnum (operands[0]);
00467
00468
00469 if (dst_regnum == STACK_POINTER_REGNUM)
00470 return (mode == SImode
00471 && register_operand (operands[1], mode)
00472 && !ACC_REG_P (xt_true_regnum (operands[1])));
00473
00474 if (!ACC_REG_P (dst_regnum))
00475 return true;
00476 }
00477 if (register_operand (operands[1], mode))
00478 {
00479 int src_regnum = xt_true_regnum (operands[1]);
00480 if (!ACC_REG_P (src_regnum))
00481 return true;
00482 }
00483 return FALSE;
00484 }
00485
00486
00487 int
00488 mask_operand (rtx op, enum machine_mode mode)
00489 {
00490 if (GET_CODE (op) == CONST_INT)
00491 return xtensa_mask_immediate (INTVAL (op));
00492
00493 return register_operand (op, mode);
00494 }
00495
00496
00497 int
00498 extui_fldsz_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
00499 {
00500 return ((GET_CODE (op) == CONST_INT)
00501 && xtensa_mask_immediate ((1 << INTVAL (op)) - 1));
00502 }
00503
00504
00505 int
00506 sext_operand (rtx op, enum machine_mode mode)
00507 {
00508 if (TARGET_SEXT)
00509 return nonimmed_operand (op, mode);
00510 return mem_operand (op, mode);
00511 }
00512
00513
00514 int
00515 sext_fldsz_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
00516 {
00517 return ((GET_CODE (op) == CONST_INT) && xtensa_tp7 (INTVAL (op) - 1));
00518 }
00519
00520
00521 int
00522 lsbitnum_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
00523 {
00524 if (GET_CODE (op) == CONST_INT)
00525 {
00526 return (BITS_BIG_ENDIAN
00527 ? (INTVAL (op) == BITS_PER_WORD-1)
00528 : (INTVAL (op) == 0));
00529 }
00530 return FALSE;
00531 }
00532
00533
00534 static int
00535 b4const_or_zero (int v)
00536 {
00537 if (v == 0)
00538 return TRUE;
00539 return xtensa_b4const (v);
00540 }
00541
00542
00543 int
00544 branch_operand (rtx op, enum machine_mode mode)
00545 {
00546 if (GET_CODE (op) == CONST_INT)
00547 return b4const_or_zero (INTVAL (op));
00548
00549 return register_operand (op, mode);
00550 }
00551
00552
00553 int
00554 ubranch_operand (rtx op, enum machine_mode mode)
00555 {
00556 if (GET_CODE (op) == CONST_INT)
00557 return xtensa_b4constu (INTVAL (op));
00558
00559 return register_operand (op, mode);
00560 }
00561
00562
00563 int
00564 call_insn_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
00565 {
00566 if ((GET_CODE (op) == REG)
00567 && (op != arg_pointer_rtx)
00568 && ((REGNO (op) < FRAME_POINTER_REGNUM)
00569 || (REGNO (op) > LAST_VIRTUAL_REGISTER)))
00570 return TRUE;
00571
00572 if (CONSTANT_ADDRESS_P (op))
00573 {
00574
00575 if (flag_pic)
00576 {
00577 tree callee, callee_sec, caller_sec;
00578
00579 if (GET_CODE (op) != SYMBOL_REF
00580 || !SYMBOL_REF_LOCAL_P (op) || SYMBOL_REF_EXTERNAL_P (op))
00581 return FALSE;
00582
00583
00584
00585
00586
00587 if (flag_function_sections
00588 || DECL_ONE_ONLY (current_function_decl))
00589 return FALSE;
00590 caller_sec = DECL_SECTION_NAME (current_function_decl);
00591 callee = SYMBOL_REF_DECL (op);
00592 if (callee)
00593 {
00594 if (DECL_ONE_ONLY (callee))
00595 return FALSE;
00596 callee_sec = DECL_SECTION_NAME (callee);
00597 if (((caller_sec == NULL_TREE) ^ (callee_sec == NULL_TREE))
00598 || (caller_sec != NULL_TREE
00599 && strcmp (TREE_STRING_POINTER (caller_sec),
00600 TREE_STRING_POINTER (callee_sec)) != 0))
00601 return FALSE;
00602 }
00603 else if (caller_sec != NULL_TREE)
00604 return FALSE;
00605 }
00606 return TRUE;
00607 }
00608
00609 return FALSE;
00610 }
00611
00612
00613 int
00614 move_operand (rtx op, enum machine_mode mode)
00615 {
00616 if (register_operand (op, mode)
00617 || memory_operand (op, mode))
00618 return TRUE;
00619
00620 switch (mode)
00621 {
00622 case DFmode:
00623 case SFmode:
00624 return TARGET_CONST16 && CONSTANT_P (op);
00625
00626 case DImode:
00627 case SImode:
00628 if (TARGET_CONST16)
00629 return CONSTANT_P (op);
00630
00631
00632 case HImode:
00633 case QImode:
00634 if (GET_CODE (op) == CONST_INT && xtensa_simm12b (INTVAL (op)))
00635 return TRUE;
00636 break;
00637
00638 default:
00639 break;
00640 }
00641
00642 return FALSE;
00643 }
00644
00645
00646 int
00647 smalloffset_mem_p (rtx op)
00648 {
00649 if (GET_CODE (op) == MEM)
00650 {
00651 rtx addr = XEXP (op, 0);
00652 if (GET_CODE (addr) == REG)
00653 return REG_OK_FOR_BASE_P (addr);
00654 if (GET_CODE (addr) == PLUS)
00655 {
00656 rtx offset = XEXP (addr, 0);
00657 if (GET_CODE (offset) != CONST_INT)
00658 offset = XEXP (addr, 1);
00659 if (GET_CODE (offset) != CONST_INT)
00660 return FALSE;
00661 return xtensa_lsi4x4 (INTVAL (offset));
00662 }
00663 }
00664 return FALSE;
00665 }
00666
00667
00668 int
00669 constantpool_address_p (rtx addr)
00670 {
00671 rtx sym = addr;
00672
00673 if (GET_CODE (addr) == CONST)
00674 {
00675 rtx offset;
00676
00677
00678 addr = XEXP (addr, 0);
00679 if (GET_CODE (addr) != PLUS)
00680 return FALSE;
00681
00682
00683 offset = XEXP (addr, 1);
00684 if ((GET_CODE (offset) != CONST_INT)
00685 || ((INTVAL (offset) & 3) != 0))
00686 return FALSE;
00687
00688 sym = XEXP (addr, 0);
00689 }
00690
00691 if ((GET_CODE (sym) == SYMBOL_REF)
00692 && CONSTANT_POOL_ADDRESS_P (sym))
00693 return TRUE;
00694 return FALSE;
00695 }
00696
00697
00698 int
00699 constantpool_mem_p (rtx op)
00700 {
00701 if (GET_CODE (op) == MEM)
00702 return constantpool_address_p (XEXP (op, 0));
00703 return FALSE;
00704 }
00705
00706
00707
00708
00709 int
00710 const_float_1_operand (rtx op, enum machine_mode mode)
00711 {
00712 REAL_VALUE_TYPE d;
00713 static REAL_VALUE_TYPE onedf;
00714 static REAL_VALUE_TYPE onesf;
00715 static int one_initialized;
00716
00717 if ((GET_CODE (op) != CONST_DOUBLE)
00718 || (mode != GET_MODE (op))
00719 || (mode != DFmode && mode != SFmode))
00720 return FALSE;
00721
00722 REAL_VALUE_FROM_CONST_DOUBLE (d, op);
00723
00724 if (! one_initialized)
00725 {
00726 onedf = REAL_VALUE_ATOF ("1.0", DFmode);
00727 onesf = REAL_VALUE_ATOF ("1.0", SFmode);
00728 one_initialized = TRUE;
00729 }
00730
00731 if (mode == DFmode)
00732 return REAL_VALUES_EQUAL (d, onedf);
00733 else
00734 return REAL_VALUES_EQUAL (d, onesf);
00735 }
00736
00737
00738 int
00739 fpmem_offset_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
00740 {
00741 if (GET_CODE (op) == CONST_INT)
00742 return xtensa_mem_offset (INTVAL (op), SFmode);
00743 return 0;
00744 }
00745
00746
00747 void
00748 xtensa_extend_reg (rtx dst, rtx src)
00749 {
00750 rtx temp = gen_reg_rtx (SImode);
00751 rtx shift = GEN_INT (BITS_PER_WORD - GET_MODE_BITSIZE (GET_MODE (src)));
00752
00753
00754 src = simplify_gen_subreg (SImode, src, GET_MODE (src), 0);
00755 dst = simplify_gen_subreg (SImode, dst, GET_MODE (dst), 0);
00756
00757 emit_insn (gen_ashlsi3 (temp, src, shift));
00758 emit_insn (gen_ashrsi3 (dst, temp, shift));
00759 }
00760
00761
00762 int
00763 branch_operator (rtx x, enum machine_mode mode)
00764 {
00765 if (GET_MODE (x) != mode)
00766 return FALSE;
00767
00768 switch (GET_CODE (x))
00769 {
00770 case EQ:
00771 case NE:
00772 case LT:
00773 case GE:
00774 return TRUE;
00775 default:
00776 break;
00777 }
00778 return FALSE;
00779 }
00780
00781
00782 int
00783 ubranch_operator (rtx x, enum machine_mode mode)
00784 {
00785 if (GET_MODE (x) != mode)
00786 return FALSE;
00787
00788 switch (GET_CODE (x))
00789 {
00790 case LTU:
00791 case GEU:
00792 return TRUE;
00793 default:
00794 break;
00795 }
00796 return FALSE;
00797 }
00798
00799
00800 int
00801 boolean_operator (rtx x, enum machine_mode mode)
00802 {
00803 if (GET_MODE (x) != mode)
00804 return FALSE;
00805
00806 switch (GET_CODE (x))
00807 {
00808 case EQ:
00809 case NE:
00810 return TRUE;
00811 default:
00812 break;
00813 }
00814 return FALSE;
00815 }
00816
00817
00818 int
00819 xtensa_mask_immediate (int v)
00820 {
00821 #define MAX_MASK_SIZE 16
00822 int mask_size;
00823
00824 for (mask_size = 1; mask_size <= MAX_MASK_SIZE; mask_size++)
00825 {
00826 if ((v & 1) == 0)
00827 return FALSE;
00828 v = v >> 1;
00829 if (v == 0)
00830 return TRUE;
00831 }
00832
00833 return FALSE;
00834 }
00835
00836
00837 int
00838 xtensa_mem_offset (unsigned v, enum machine_mode mode)
00839 {
00840 switch (mode)
00841 {
00842 case BLKmode:
00843
00844
00845
00846
00847
00848 return (xtensa_uimm8 (v)
00849 && xtensa_uimm8 (v + MOVE_MAX * LARGEST_MOVE_RATIO));
00850
00851 case QImode:
00852 return xtensa_uimm8 (v);
00853
00854 case HImode:
00855 return xtensa_uimm8x2 (v);
00856
00857 case DFmode:
00858 return (xtensa_uimm8x4 (v) && xtensa_uimm8x4 (v + 4));
00859
00860 default:
00861 break;
00862 }
00863
00864 return xtensa_uimm8x4 (v);
00865 }
00866
00867
00868
00869
00870 static enum internal_test
00871 map_test_to_internal_test (enum rtx_code test_code)
00872 {
00873 enum internal_test test = ITEST_MAX;
00874
00875 switch (test_code)
00876 {
00877 default: break;
00878 case EQ: test = ITEST_EQ; break;
00879 case NE: test = ITEST_NE; break;
00880 case GT: test = ITEST_GT; break;
00881 case GE: test = ITEST_GE; break;
00882 case LT: test = ITEST_LT; break;
00883 case LE: test = ITEST_LE; break;
00884 case GTU: test = ITEST_GTU; break;
00885 case GEU: test = ITEST_GEU; break;
00886 case LTU: test = ITEST_LTU; break;
00887 case LEU: test = ITEST_LEU; break;
00888 }
00889
00890 return test;
00891 }
00892
00893
00894
00895
00896
00897 static rtx
00898 gen_int_relational (enum rtx_code test_code,
00899 rtx cmp0,
00900 rtx cmp1,
00901 int *p_invert )
00902 {
00903 struct cmp_info
00904 {
00905 enum rtx_code test_code;
00906 int (*const_range_p) (int);
00907 int const_add;
00908 int reverse_regs;
00909 int invert_const;
00910 int invert_reg;
00911 int unsignedp;
00912 };
00913
00914 static struct cmp_info info[ (int)ITEST_MAX ] = {
00915
00916 { EQ, b4const_or_zero, 0, 0, 0, 0, 0 },
00917 { NE, b4const_or_zero, 0, 0, 0, 0, 0 },
00918
00919 { LT, b4const_or_zero, 1, 1, 1, 0, 0 },
00920 { GE, b4const_or_zero, 0, 0, 0, 0, 0 },
00921 { LT, b4const_or_zero, 0, 0, 0, 0, 0 },
00922 { GE, b4const_or_zero, 1, 1, 1, 0, 0 },
00923
00924 { LTU, xtensa_b4constu, 1, 1, 1, 0, 1 },
00925 { GEU, xtensa_b4constu, 0, 0, 0, 0, 1 },
00926 { LTU, xtensa_b4constu, 0, 0, 0, 0, 1 },
00927 { GEU, xtensa_b4constu, 1, 1, 1, 0, 1 },
00928 };
00929
00930 enum internal_test test;
00931 enum machine_mode mode;
00932 struct cmp_info *p_info;
00933
00934 test = map_test_to_internal_test (test_code);
00935 if (test == ITEST_MAX)
00936 abort ();
00937
00938 p_info = &info[ (int)test ];
00939
00940 mode = GET_MODE (cmp0);
00941 if (mode == VOIDmode)
00942 mode = GET_MODE (cmp1);
00943
00944
00945 if (GET_CODE (cmp1) == CONST_INT)
00946 {
00947 HOST_WIDE_INT value = INTVAL (cmp1);
00948 unsigned HOST_WIDE_INT uvalue = (unsigned HOST_WIDE_INT)value;
00949
00950
00951
00952
00953 if ((p_info->unsignedp ?
00954 (uvalue + p_info->const_add > uvalue) :
00955 (value + p_info->const_add > value)) != (p_info->const_add > 0))
00956 {
00957 cmp1 = force_reg (mode, cmp1);
00958 }
00959 else if (!(p_info->const_range_p) (value + p_info->const_add))
00960 {
00961 cmp1 = force_reg (mode, cmp1);
00962 }
00963 }
00964 else if ((GET_CODE (cmp1) != REG) && (GET_CODE (cmp1) != SUBREG))
00965 {
00966 cmp1 = force_reg (mode, cmp1);
00967 }
00968
00969
00970 *p_invert = ((GET_CODE (cmp1) == CONST_INT)
00971 ? p_info->invert_const
00972 : p_info->invert_reg);
00973
00974
00975
00976 if (GET_CODE (cmp1) == CONST_INT)
00977 {
00978 if (p_info->const_add != 0)
00979 cmp1 = GEN_INT (INTVAL (cmp1) + p_info->const_add);
00980
00981 }
00982 else if (p_info->reverse_regs)
00983 {
00984 rtx temp = cmp0;
00985 cmp0 = cmp1;
00986 cmp1 = temp;
00987 }
00988
00989 return gen_rtx_fmt_ee (p_info->test_code, VOIDmode, cmp0, cmp1);
00990 }
00991
00992
00993
00994
00995
00996 static rtx
00997 gen_float_relational (enum rtx_code test_code,
00998 rtx cmp0,
00999 rtx cmp1 )
01000 {
01001 rtx (*gen_fn) (rtx, rtx, rtx);
01002 rtx brtmp;
01003 int reverse_regs, invert;
01004
01005 switch (test_code)
01006 {
01007 case EQ: reverse_regs = 0; invert = 0; gen_fn = gen_seq_sf; break;
01008 case NE: reverse_regs = 0; invert = 1; gen_fn = gen_seq_sf; break;
01009 case LE: reverse_regs = 0; invert = 0; gen_fn = gen_sle_sf; break;
01010 case GT: reverse_regs = 1; invert = 0; gen_fn = gen_slt_sf; break;
01011 case LT: reverse_regs = 0; invert = 0; gen_fn = gen_slt_sf; break;
01012 case GE: reverse_regs = 1; invert = 0; gen_fn = gen_sle_sf; break;
01013 default:
01014 fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1));
01015 reverse_regs = 0; invert = 0; gen_fn = 0;
01016 }
01017
01018 if (reverse_regs)
01019 {
01020 rtx temp = cmp0;
01021 cmp0 = cmp1;
01022 cmp1 = temp;
01023 }
01024
01025 brtmp = gen_rtx_REG (CCmode, FPCC_REGNUM);
01026 emit_insn (gen_fn (brtmp, cmp0, cmp1));
01027
01028 return gen_rtx_fmt_ee (invert ? EQ : NE, VOIDmode, brtmp, const0_rtx);
01029 }
01030
01031
01032 void
01033 xtensa_expand_conditional_branch (rtx *operands, enum rtx_code test_code)
01034 {
01035 enum cmp_type type = branch_type;
01036 rtx cmp0 = branch_cmp[0];
01037 rtx cmp1 = branch_cmp[1];
01038 rtx cmp;
01039 int invert;
01040 rtx label1, label2;
01041
01042 switch (type)
01043 {
01044 case CMP_DF:
01045 default:
01046 fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1));
01047
01048 case CMP_SI:
01049 invert = FALSE;
01050 cmp = gen_int_relational (test_code, cmp0, cmp1, &invert);
01051 break;
01052
01053 case CMP_SF:
01054 if (!TARGET_HARD_FLOAT)
01055 fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1));
01056 invert = FALSE;
01057 cmp = gen_float_relational (test_code, cmp0, cmp1);
01058 break;
01059 }
01060
01061
01062
01063 label1 = gen_rtx_LABEL_REF (VOIDmode, operands[0]);
01064 label2 = pc_rtx;
01065
01066 if (invert)
01067 {
01068 label2 = label1;
01069 label1 = pc_rtx;
01070 }
01071
01072 emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
01073 gen_rtx_IF_THEN_ELSE (VOIDmode, cmp,
01074 label1,
01075 label2)));
01076 }
01077
01078
01079 static rtx
01080 gen_conditional_move (rtx cmp)
01081 {
01082 enum rtx_code code = GET_CODE (cmp);
01083 rtx op0 = branch_cmp[0];
01084 rtx op1 = branch_cmp[1];
01085
01086 if (branch_type == CMP_SI)
01087 {
01088
01089
01090
01091
01092
01093
01094
01095
01096 if ((code == GT) && (op1 == constm1_rtx))
01097 {
01098 code = GE;
01099 op1 = const0_rtx;
01100 }
01101 cmp = gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
01102
01103 if (boolean_operator (cmp, VOIDmode))
01104 {
01105
01106 if (op0 == const0_rtx)
01107 {
01108 op0 = op1;
01109 op1 = const0_rtx;
01110 }
01111
01112
01113 if (op1 != const0_rtx)
01114 {
01115 op0 = expand_binop (SImode, sub_optab, op0, op1,
01116 0, 0, OPTAB_LIB_WIDEN);
01117 op1 = const0_rtx;
01118 }
01119 }
01120 else if (branch_operator (cmp, VOIDmode))
01121 {
01122
01123 if (op0 == const0_rtx)
01124 {
01125 op0 = op1;
01126 op1 = const0_rtx;
01127
01128 switch (code)
01129 {
01130 case LT: code = GE; break;
01131 case GE: code = LT; break;
01132 default: abort ();
01133 }
01134 }
01135
01136 if (op1 != const0_rtx)
01137 return 0;
01138 }
01139 else
01140 return 0;
01141
01142 return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
01143 }
01144
01145 if (TARGET_HARD_FLOAT && (branch_type == CMP_SF))
01146 return gen_float_relational (code, op0, op1);
01147
01148 return 0;
01149 }
01150
01151
01152 int
01153 xtensa_expand_conditional_move (rtx *operands, int isflt)
01154 {
01155 rtx cmp;
01156 rtx (*gen_fn) (rtx, rtx, rtx, rtx, rtx);
01157
01158 if (!(cmp = gen_conditional_move (operands[1])))
01159 return 0;
01160
01161 if (isflt)
01162 gen_fn = (branch_type == CMP_SI
01163 ? gen_movsfcc_internal0
01164 : gen_movsfcc_internal1);
01165 else
01166 gen_fn = (branch_type == CMP_SI
01167 ? gen_movsicc_internal0
01168 : gen_movsicc_internal1);
01169
01170 emit_insn (gen_fn (operands[0], XEXP (cmp, 0),
01171 operands[2], operands[3], cmp));
01172 return 1;
01173 }
01174
01175
01176 int
01177 xtensa_expand_scc (rtx *operands)
01178 {
01179 rtx dest = operands[0];
01180 rtx cmp = operands[1];
01181 rtx one_tmp, zero_tmp;
01182 rtx (*gen_fn) (rtx, rtx, rtx, rtx, rtx);
01183
01184 if (!(cmp = gen_conditional_move (cmp)))
01185 return 0;
01186
01187 one_tmp = gen_reg_rtx (SImode);
01188 zero_tmp = gen_reg_rtx (SImode);
01189 emit_insn (gen_movsi (one_tmp, const_true_rtx));
01190 emit_insn (gen_movsi (zero_tmp, const0_rtx));
01191
01192 gen_fn = (branch_type == CMP_SI
01193 ? gen_movsicc_internal0
01194 : gen_movsicc_internal1);
01195 emit_insn (gen_fn (dest, XEXP (cmp, 0), one_tmp, zero_tmp, cmp));
01196 return 1;
01197 }
01198
01199
01200
01201
01202
01203 void
01204 xtensa_split_operand_pair (rtx operands[4], enum machine_mode mode)
01205 {
01206 switch (GET_CODE (operands[1]))
01207 {
01208 case REG:
01209 operands[3] = gen_rtx_REG (mode, REGNO (operands[1]) + 1);
01210 operands[2] = gen_rtx_REG (mode, REGNO (operands[1]));
01211 break;
01212
01213 case MEM:
01214 operands[3] = adjust_address (operands[1], mode, GET_MODE_SIZE (mode));
01215 operands[2] = adjust_address (operands[1], mode, 0);
01216 break;
01217
01218 case CONST_INT:
01219 case CONST_DOUBLE:
01220 split_double (operands[1], &operands[2], &operands[3]);
01221 break;
01222
01223 default:
01224 abort ();
01225 }
01226
01227 switch (GET_CODE (operands[0]))
01228 {
01229 case REG:
01230 operands[1] = gen_rtx_REG (mode, REGNO (operands[0]) + 1);
01231 operands[0] = gen_rtx_REG (mode, REGNO (operands[0]));
01232 break;
01233
01234 case MEM:
01235 operands[1] = adjust_address (operands[0], mode, GET_MODE_SIZE (mode));
01236 operands[0] = adjust_address (operands[0], mode, 0);
01237 break;
01238
01239 default:
01240 abort ();
01241 }
01242 }
01243
01244
01245
01246
01247
01248
01249
01250 int
01251 xtensa_emit_move_sequence (rtx *operands, enum machine_mode mode)
01252 {
01253 if (CONSTANT_P (operands[1])
01254 && (GET_CODE (operands[1]) != CONST_INT
01255 || !xtensa_simm12b (INTVAL (operands[1]))))
01256 {
01257 if (!TARGET_CONST16)
01258 operands[1] = force_const_mem (SImode, operands[1]);
01259
01260
01261
01262
01263
01264 if (mode != SImode)
01265 {
01266 if (register_operand (operands[0], mode))
01267 {
01268 operands[0] = simplify_gen_subreg (SImode, operands[0], mode, 0);
01269 emit_move_insn (operands[0], operands[1]);
01270 return 1;
01271 }
01272 else
01273 {
01274 operands[1] = force_reg (SImode, operands[1]);
01275 operands[1] = gen_lowpart_SUBREG (mode, operands[1]);
01276 }
01277 }
01278 }
01279
01280 if (!(reload_in_progress | reload_completed)
01281 && !xtensa_valid_move (mode, operands))
01282 operands[1] = force_reg (mode, operands[1]);
01283
01284 operands[1] = xtensa_copy_incoming_a7 (operands[1]);
01285
01286
01287
01288
01289 if (reload_in_progress)
01290 {
01291 operands[0] = fixup_subreg_mem (operands[0]);
01292 operands[1] = fixup_subreg_mem (operands[1]);
01293 }
01294 return 0;
01295 }
01296
01297
01298 static rtx
01299 fixup_subreg_mem (rtx x)
01300 {
01301 if (GET_CODE (x) == SUBREG
01302 && GET_CODE (SUBREG_REG (x)) == REG
01303 && REGNO (SUBREG_REG (x)) >= FIRST_PSEUDO_REGISTER)
01304 {
01305 rtx temp =
01306 gen_rtx_SUBREG (GET_MODE (x),
01307 reg_equiv_mem [REGNO (SUBREG_REG (x))],
01308 SUBREG_BYTE (x));
01309 x = alter_subreg (&temp);
01310 }
01311 return x;
01312 }
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333 rtx
01334 xtensa_copy_incoming_a7 (rtx opnd)
01335 {
01336 rtx entry_insns = 0;
01337 rtx reg, tmp;
01338 enum machine_mode mode;
01339
01340 if (!cfun->machine->need_a7_copy)
01341 return opnd;
01342
01343
01344 if (cfun->machine->set_frame_ptr_insn)
01345 abort ();
01346
01347 mode = GET_MODE (opnd);
01348
01349
01350
01351 reg = opnd;
01352 if (GET_CODE (reg) == SUBREG)
01353 {
01354 if (SUBREG_BYTE (reg) != 0)
01355 abort ();
01356 reg = SUBREG_REG (reg);
01357 }
01358 if (GET_CODE (reg) != REG
01359 || REGNO (reg) > A7_REG
01360 || REGNO (reg) + HARD_REGNO_NREGS (A7_REG, mode) <= A7_REG)
01361 return opnd;
01362
01363
01364 if (REGNO (reg) + HARD_REGNO_NREGS (A7_REG, mode) - 1 != A7_REG)
01365 abort ();
01366
01367 cfun->machine->need_a7_copy = false;
01368
01369
01370
01371
01372 push_to_sequence (entry_insns);
01373 tmp = gen_reg_rtx (mode);
01374
01375 switch (mode)
01376 {
01377 case DFmode:
01378 case DImode:
01379 emit_insn (gen_movsi_internal (gen_rtx_SUBREG (SImode, tmp, 0),
01380 gen_rtx_REG (SImode, A7_REG - 1)));
01381 emit_insn (gen_movsi_internal (gen_rtx_SUBREG (SImode, tmp, 4),
01382 gen_raw_REG (SImode, A7_REG)));
01383 break;
01384 case SFmode:
01385 emit_insn (gen_movsf_internal (tmp, gen_raw_REG (mode, A7_REG)));
01386 break;
01387 case SImode:
01388 emit_insn (gen_movsi_internal (tmp, gen_raw_REG (mode, A7_REG)));
01389 break;
01390 case HImode:
01391 emit_insn (gen_movhi_internal (tmp, gen_raw_REG (mode, A7_REG)));
01392 break;
01393 case QImode:
01394 emit_insn (gen_movqi_internal (tmp, gen_raw_REG (mode, A7_REG)));
01395 break;
01396 default:
01397 abort ();
01398 }
01399
01400 cfun->machine->set_frame_ptr_insn = emit_insn (gen_set_frame_ptr ());
01401 entry_insns = get_insns ();
01402 end_sequence ();
01403
01404 if (cfun->machine->vararg_a7)
01405 {
01406
01407
01408
01409 emit_insn (entry_insns);
01410 }
01411 else
01412 {
01413
01414
01415
01416
01417 push_topmost_sequence ();
01418 emit_insn_after (entry_insns, get_insns ());
01419 pop_topmost_sequence ();
01420 }
01421
01422 return tmp;
01423 }
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436 int
01437 xtensa_expand_block_move (rtx *operands)
01438 {
01439 static const enum machine_mode mode_from_align[] =
01440 {
01441 VOIDmode, QImode, HImode, VOIDmode, SImode,
01442 };
01443
01444 rtx dst_mem = operands[0];
01445 rtx src_mem = operands[1];
01446 HOST_WIDE_INT bytes, align;
01447 int num_pieces, move_ratio;
01448 rtx temp[2];
01449 enum machine_mode mode[2];
01450 int amount[2];
01451 bool active[2];
01452 int phase = 0;
01453 int next;
01454 int offset_ld = 0;
01455 int offset_st = 0;
01456 rtx x;
01457
01458
01459 if (!optimize || (GET_CODE (operands[2]) != CONST_INT))
01460 return 0;
01461
01462 bytes = INTVAL (operands[2]);
01463 align = INTVAL (operands[3]);
01464
01465
01466 if (bytes <= 0)
01467 return 0;
01468
01469 if (align > MOVE_MAX)
01470 align = MOVE_MAX;
01471
01472
01473 move_ratio = 4;
01474 if (optimize > 2)
01475 move_ratio = LARGEST_MOVE_RATIO;
01476 num_pieces = (bytes / align) + (bytes % align);
01477 if (num_pieces > move_ratio)
01478 return 0;
01479
01480 x = XEXP (dst_mem, 0);
01481 if (!REG_P (x))
01482 {
01483 x = force_reg (Pmode, x);
01484 dst_mem = replace_equiv_address (dst_mem, x);
01485 }
01486
01487 x = XEXP (src_mem, 0);
01488 if (!REG_P (x))
01489 {
01490 x = force_reg (Pmode, x);
01491 src_mem = replace_equiv_address (src_mem, x);
01492 }
01493
01494 active[0] = active[1] = false;
01495
01496 do
01497 {
01498 next = phase;
01499 phase ^= 1;
01500
01501 if (bytes > 0)
01502 {
01503 int next_amount;
01504
01505 next_amount = (bytes >= 4 ? 4 : (bytes >= 2 ? 2 : 1));
01506 next_amount = MIN (next_amount, align);
01507
01508 amount[next] = next_amount;
01509 mode[next] = mode_from_align[next_amount];
01510 temp[next] = gen_reg_rtx (mode[next]);
01511
01512 x = adjust_address (src_mem, mode[next], offset_ld);
01513 emit_insn (gen_rtx_SET (VOIDmode, temp[next], x));
01514
01515 offset_ld += next_amount;
01516 bytes -= next_amount;
01517 active[next] = true;
01518 }
01519
01520 if (active[phase])
01521 {
01522 active[phase] = false;
01523
01524 x = adjust_address (dst_mem, mode[phase], offset_st);
01525 emit_insn (gen_rtx_SET (VOIDmode, x, temp[phase]));
01526
01527 offset_st += amount[phase];
01528 }
01529 }
01530 while (active[next]);
01531
01532 return 1;
01533 }
01534
01535
01536 void
01537 xtensa_expand_nonlocal_goto (rtx *operands)
01538 {
01539 rtx goto_handler = operands[1];
01540 rtx containing_fp = operands[3];
01541
01542
01543
01544
01545 if (GET_CODE (containing_fp) != REG)
01546 containing_fp = force_reg (Pmode, containing_fp);
01547
01548 goto_handler = replace_rtx (copy_rtx (goto_handler),
01549 virtual_stack_vars_rtx,
01550 containing_fp);
01551
01552 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_nonlocal_goto"),
01553 0, VOIDmode, 2,
01554 containing_fp, Pmode,
01555 goto_handler, Pmode);
01556 }
01557
01558
01559 static struct machine_function *
01560 xtensa_init_machine_status (void)
01561 {
01562 return ggc_alloc_cleared (sizeof (struct machine_function));
01563 }
01564
01565
01566 void
01567 xtensa_setup_frame_addresses (void)
01568 {
01569
01570 cfun->machine->accesses_prev_frame = 1;
01571
01572 emit_library_call
01573 (gen_rtx_SYMBOL_REF (Pmode, "__xtensa_libgcc_window_spill"),
01574 0, VOIDmode, 0);
01575 }
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591 void
01592 xtensa_emit_loop_end (rtx insn, rtx *operands)
01593 {
01594 char done = 0;
01595
01596 for (insn = PREV_INSN (insn); insn && !done; insn = PREV_INSN (insn))
01597 {
01598 switch (GET_CODE (insn))
01599 {
01600 case NOTE:
01601 case BARRIER:
01602 break;
01603
01604 case CODE_LABEL:
01605 output_asm_insn (TARGET_DENSITY ? "nop.n" : "nop", operands);
01606 done = 1;
01607 break;
01608
01609 default:
01610 {
01611 rtx body = PATTERN (insn);
01612
01613 if (GET_CODE (body) == JUMP_INSN)
01614 {
01615 output_asm_insn (TARGET_DENSITY ? "nop.n" : "nop", operands);
01616 done = 1;
01617 }
01618 else if ((GET_CODE (body) != USE)
01619 && (GET_CODE (body) != CLOBBER))
01620 done = 1;
01621 }
01622 break;
01623 }
01624 }
01625
01626 output_asm_insn ("# loop end for %0", operands);
01627 }
01628
01629
01630 char *
01631 xtensa_emit_call (int callop, rtx *operands)
01632 {
01633 static char result[64];
01634 rtx tgt = operands[callop];
01635
01636 if (GET_CODE (tgt) == CONST_INT)
01637 sprintf (result, "call8\t0x%lx", INTVAL (tgt));
01638 else if (register_operand (tgt, VOIDmode))
01639 sprintf (result, "callx8\t%%%d", callop);
01640 else
01641 sprintf (result, "call8\t%%%d", callop);
01642
01643 return result;
01644 }
01645
01646
01647
01648
01649 int
01650 xtensa_dbx_register_number (int regno)
01651 {
01652 int first = -1;
01653
01654 if (GP_REG_P (regno))
01655 {
01656 regno -= GP_REG_FIRST;
01657 first = 0;
01658 }
01659 else if (BR_REG_P (regno))
01660 {
01661 regno -= BR_REG_FIRST;
01662 first = 16;
01663 }
01664 else if (FP_REG_P (regno))
01665 {
01666 regno -= FP_REG_FIRST;
01667 first = 48;
01668 }
01669 else if (ACC_REG_P (regno))
01670 {
01671 first = 0x200;
01672 regno = 16;
01673 }
01674
01675
01676
01677 if (first == -1)
01678 return 0;
01679
01680 return first + regno;
01681 }
01682
01683
01684
01685
01686
01687
01688 void
01689 init_cumulative_args (CUMULATIVE_ARGS *cum, int incoming)
01690 {
01691 cum->arg_words = 0;
01692 cum->incoming = incoming;
01693 }
01694
01695
01696
01697
01698 void
01699 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type)
01700 {
01701 int words, max;
01702 int *arg_words;
01703
01704 arg_words = &cum->arg_words;
01705 max = MAX_ARGS_IN_REGISTERS;
01706
01707 words = (((mode != BLKmode)
01708 ? (int) GET_MODE_SIZE (mode)
01709 : int_size_in_bytes (type)) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
01710
01711 if (*arg_words < max
01712 && (targetm.calls.must_pass_in_stack (mode, type)
01713 || *arg_words + words > max))
01714 *arg_words = max;
01715
01716 *arg_words += words;
01717 }
01718
01719
01720
01721
01722
01723
01724 rtx
01725 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
01726 int incoming_p)
01727 {
01728 int regbase, words, max;
01729 int *arg_words;
01730 int regno;
01731
01732 arg_words = &cum->arg_words;
01733 regbase = (incoming_p ? GP_ARG_FIRST : GP_OUTGOING_ARG_FIRST);
01734 max = MAX_ARGS_IN_REGISTERS;
01735
01736 words = (((mode != BLKmode)
01737 ? (int) GET_MODE_SIZE (mode)
01738 : int_size_in_bytes (type)) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
01739
01740 if (type && (TYPE_ALIGN (type) > BITS_PER_WORD))
01741 {
01742 int align = TYPE_ALIGN (type) / BITS_PER_WORD;
01743 *arg_words = (*arg_words + align - 1) & -align;
01744 }
01745
01746 if (*arg_words + words > max)
01747 return (rtx)0;
01748
01749 regno = regbase + *arg_words;
01750
01751 if (cum->incoming && regno <= A7_REG && regno + words > A7_REG)
01752 cfun->machine->need_a7_copy = true;
01753
01754 return gen_rtx_REG (mode, regno);
01755 }
01756
01757
01758 static bool
01759 xtensa_return_in_msb (tree valtype)
01760 {
01761 return (TARGET_BIG_ENDIAN
01762 && AGGREGATE_TYPE_P (valtype)
01763 && int_size_in_bytes (valtype) >= UNITS_PER_WORD);
01764 }
01765
01766
01767 void
01768 override_options (void)
01769 {
01770 int regno;
01771 enum machine_mode mode;
01772
01773 if (!TARGET_BOOLEANS && TARGET_HARD_FLOAT)
01774 error ("boolean registers required for the floating-point option");
01775
01776 xtensa_char_to_class['q'] = SP_REG;
01777 xtensa_char_to_class['a'] = GR_REGS;
01778 xtensa_char_to_class['b'] = ((TARGET_BOOLEANS) ? BR_REGS : NO_REGS);
01779 xtensa_char_to_class['f'] = ((TARGET_HARD_FLOAT) ? FP_REGS : NO_REGS);
01780 xtensa_char_to_class['A'] = ((TARGET_MAC16) ? ACC_REG : NO_REGS);
01781 xtensa_char_to_class['B'] = ((TARGET_SEXT) ? GR_REGS : NO_REGS);
01782 xtensa_char_to_class['C'] = ((TARGET_MUL16) ? GR_REGS: NO_REGS);
01783 xtensa_char_to_class['D'] = ((TARGET_DENSITY) ? GR_REGS: NO_REGS);
01784 xtensa_char_to_class['d'] = ((TARGET_DENSITY) ? AR_REGS: NO_REGS);
01785 xtensa_char_to_class['W'] = ((TARGET_CONST16) ? GR_REGS: NO_REGS);
01786
01787
01788 for (mode = VOIDmode;
01789 mode != MAX_MACHINE_MODE;
01790 mode = (enum machine_mode) ((int) mode + 1))
01791 {
01792 int size = GET_MODE_SIZE (mode);
01793 enum mode_class class = GET_MODE_CLASS (mode);
01794
01795 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
01796 {
01797 int temp;
01798
01799 if (ACC_REG_P (regno))
01800 temp = (TARGET_MAC16
01801 && (class == MODE_INT) && (size <= UNITS_PER_WORD));
01802 else if (GP_REG_P (regno))
01803 temp = ((regno & 1) == 0 || (size <= UNITS_PER_WORD));
01804 else if (FP_REG_P (regno))
01805 temp = (TARGET_HARD_FLOAT && (mode == SFmode));
01806 else if (BR_REG_P (regno))
01807 temp = (TARGET_BOOLEANS && (mode == CCmode));
01808 else
01809 temp = FALSE;
01810
01811 xtensa_hard_regno_mode_ok[(int) mode][regno] = temp;
01812 }
01813 }
01814
01815 init_machine_status = xtensa_init_machine_status;
01816
01817
01818
01819 if (flag_pic && TARGET_CONST16)
01820 error ("-f%s is not supported with CONST16 instructions",
01821 (flag_pic > 1 ? "PIC" : "pic"));
01822 else if (XTENSA_ALWAYS_PIC)
01823 {
01824 if (TARGET_CONST16)
01825 error ("PIC is required but not supported with CONST16 instructions");
01826 flag_pic = 1;
01827 }
01828
01829 if (flag_pic > 1)
01830 flag_pic = 1;
01831 }
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870 static void
01871 printx (FILE *file, signed int val)
01872 {
01873
01874 if ((val > -0xa) && (val < 0xa))
01875 fprintf (file, "%d", val);
01876 else if (val < 0)
01877 fprintf (file, "-0x%x", -val);
01878 else
01879 fprintf (file, "0x%x", val);
01880 }
01881
01882
01883 void
01884 print_operand (FILE *file, rtx x, int letter)
01885 {
01886 if (!x)
01887 error ("PRINT_OPERAND null pointer");
01888
01889 switch (letter)
01890 {
01891 case 'D':
01892 if (GET_CODE (x) == REG || GET_CODE (x) == SUBREG)
01893 fprintf (file, "%s", reg_names[xt_true_regnum (x) + 1]);
01894 else
01895 output_operand_lossage ("invalid %%D value");
01896 break;
01897
01898 case 'v':
01899 if (GET_CODE (x) == MEM)
01900 {
01901
01902
01903 if (MEM_VOLATILE_P (x))
01904 fprintf (file, "memw\n\t");
01905 }
01906 else
01907 output_operand_lossage ("invalid %%v value");
01908 break;
01909
01910 case 'N':
01911 if (GET_CODE (x) == MEM
01912 && (GET_MODE (x) == DFmode || GET_MODE (x) == DImode))
01913 {
01914 x = adjust_address (x, GET_MODE (x) == DFmode ? SFmode : SImode, 4);
01915 output_address (XEXP (x, 0));
01916 }
01917 else
01918 output_operand_lossage ("invalid %%N value");
01919 break;
01920
01921 case 'K':
01922 if (GET_CODE (x) == CONST_INT)
01923 {
01924 int num_bits = 0;
01925 unsigned val = INTVAL (x);
01926 while (val & 1)
01927 {
01928 num_bits += 1;
01929 val = val >> 1;
01930 }
01931 if ((val != 0) || (num_bits == 0) || (num_bits > 16))
01932 fatal_insn ("invalid mask", x);
01933
01934 fprintf (file, "%d", num_bits);
01935 }
01936 else
01937 output_operand_lossage ("invalid %%K value");
01938 break;
01939
01940 case 'L':
01941 if (GET_CODE (x) == CONST_INT)
01942 fprintf (file, "%ld", (32 - INTVAL (x)) & 0x1f);
01943 else
01944 output_operand_lossage ("invalid %%L value");
01945 break;
01946
01947 case 'R':
01948 if (GET_CODE (x) == CONST_INT)
01949 fprintf (file, "%ld", INTVAL (x) & 0x1f);
01950 else
01951 output_operand_lossage ("invalid %%R value");
01952 break;
01953
01954 case 'x':
01955 if (GET_CODE (x) == CONST_INT)
01956 printx (file, INTVAL (x));
01957 else
01958 output_operand_lossage ("invalid %%x value");
01959 break;
01960
01961 case 'd':
01962 if (GET_CODE (x) == CONST_INT)
01963 fprintf (file, "%ld", INTVAL (x));
01964 else
01965 output_operand_lossage ("invalid %%d value");
01966 break;
01967
01968 case 't':
01969 case 'b':
01970 if (GET_CODE (x) == CONST_INT)
01971 {
01972 printx (file, INTVAL (x));
01973 fputs (letter == 't' ? "@h" : "@l", file);
01974 }
01975 else if (GET_CODE (x) == CONST_DOUBLE)
01976 {
01977 REAL_VALUE_TYPE r;
01978 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
01979 if (GET_MODE (x) == SFmode)
01980 {
01981 long l;
01982 REAL_VALUE_TO_TARGET_SINGLE (r, l);
01983 fprintf (file, "0x%08lx@%c", l, letter == 't' ? 'h' : 'l');
01984 }
01985 else
01986 output_operand_lossage ("invalid %%t/%%b value");
01987 }
01988 else if (GET_CODE (x) == CONST)
01989 {
01990
01991
01992 if (GET_CODE (XEXP (x, 0)) != PLUS
01993 || (GET_CODE (XEXP (XEXP (x, 0), 0)) != SYMBOL_REF
01994 && GET_CODE (XEXP (XEXP (x, 0), 0)) != LABEL_REF)
01995 || GET_CODE (XEXP (XEXP (x, 0), 1)) != CONST_INT)
01996 output_operand_lossage ("invalid %%t/%%b value");
01997 print_operand (file, XEXP (XEXP (x, 0), 0), 0);
01998 fputs (letter == 't' ? "@h" : "@l", file);
01999
02000
02001 if (INTVAL (XEXP (XEXP (x, 0), 1)) >= 0)
02002 fputs ("+", file);
02003 print_operand (file, XEXP (XEXP (x, 0), 1), 0);
02004 }
02005 else
02006 {
02007 output_addr_const (file, x);
02008 fputs (letter == 't' ? "@h" : "@l", file);
02009 }
02010 break;
02011
02012 default:
02013 if (GET_CODE (x) == REG || GET_CODE (x) == SUBREG)
02014 fprintf (file, "%s", reg_names[xt_true_regnum (x)]);
02015 else if (GET_CODE (x) == MEM)
02016 output_address (XEXP (x, 0));
02017 else if (GET_CODE (x) == CONST_INT)
02018 fprintf (file, "%ld", INTVAL (x));
02019 else
02020 output_addr_const (file, x);
02021 }
02022 }
02023
02024
02025
02026
02027
02028
02029 void
02030 print_operand_address (FILE *file, rtx addr)
02031 {
02032 if (!addr)
02033 error ("PRINT_OPERAND_ADDRESS, null pointer");
02034
02035 switch (GET_CODE (addr))
02036 {
02037 default:
02038 fatal_insn ("invalid address", addr);
02039 break;
02040
02041 case REG:
02042 fprintf (file, "%s, 0", reg_names [REGNO (addr)]);
02043 break;
02044
02045 case PLUS:
02046 {
02047 rtx reg = (rtx)0;
02048 rtx offset = (rtx)0;
02049 rtx arg0 = XEXP (addr, 0);
02050 rtx arg1 = XEXP (addr, 1);
02051
02052 if (GET_CODE (arg0) == REG)
02053 {
02054 reg = arg0;
02055 offset = arg1;
02056 }
02057 else if (GET_CODE (arg1) == REG)
02058 {
02059 reg = arg1;
02060 offset = arg0;
02061 }
02062 else
02063 fatal_insn ("no register in address", addr);
02064
02065 if (CONSTANT_P (offset))
02066 {
02067 fprintf (file, "%s, ", reg_names [REGNO (reg)]);
02068 output_addr_const (file, offset);
02069 }
02070 else
02071 fatal_insn ("address offset not a constant", addr);
02072 }
02073 break;
02074
02075 case LABEL_REF:
02076 case SYMBOL_REF:
02077 case CONST_INT:
02078 case CONST:
02079 output_addr_const (file, addr);
02080 break;
02081 }
02082 }
02083
02084
02085 void
02086 xtensa_output_literal (FILE *file, rtx x, enum machine_mode mode, int labelno)
02087 {
02088 long value_long[2];
02089 REAL_VALUE_TYPE r;
02090 int size;
02091
02092 fprintf (file, "\t.literal .LC%u, ", (unsigned) labelno);
02093
02094 switch (GET_MODE_CLASS (mode))
02095 {
02096 case MODE_FLOAT:
02097 if (GET_CODE (x) != CONST_DOUBLE)
02098 abort ();
02099
02100 REAL_VALUE_FROM_CONST_DOUBLE (r, x);
02101 switch (mode)
02102 {
02103 case SFmode:
02104 REAL_VALUE_TO_TARGET_SINGLE (r, value_long[0]);
02105 fprintf (file, "0x%08lx\n", value_long[0]);
02106 break;
02107
02108 case DFmode:
02109 REAL_VALUE_TO_TARGET_DOUBLE (r, value_long);
02110 fprintf (file, "0x%08lx, 0x%08lx\n",
02111 value_long[0], value_long[1]);
02112 break;
02113
02114 default:
02115 abort ();
02116 }
02117
02118 break;
02119
02120 case MODE_INT:
02121 case MODE_PARTIAL_INT:
02122 size = GET_MODE_SIZE (mode);
02123 if (size == 4)
02124 {
02125 output_addr_const (file, x);
02126 fputs ("\n", file);
02127 }
02128 else if (size == 8)
02129 {
02130 output_addr_const (file, operand_subword (x, 0, 0, DImode));
02131 fputs (", ", file);
02132 output_addr_const (file, operand_subword (x, 1, 0, DImode));
02133 fputs ("\n", file);
02134 }
02135 else
02136 abort ();
02137 break;
02138
02139 default:
02140 abort ();
02141 }
02142 }
02143
02144
02145
02146
02147
02148 #define STACK_BYTES (STACK_BOUNDARY / BITS_PER_UNIT)
02149 #define XTENSA_STACK_ALIGN(LOC) (((LOC) + STACK_BYTES-1) & ~(STACK_BYTES-1))
02150
02151 long
02152 compute_frame_size (int size)
02153 {
02154
02155 if (cfun->static_chain_decl != NULL)
02156 size += (1 * UNITS_PER_WORD);
02157
02158 xtensa_current_frame_size =
02159 XTENSA_STACK_ALIGN (size
02160 + current_function_outgoing_args_size
02161 + (WINDOW_SIZE * UNITS_PER_WORD));
02162 return xtensa_current_frame_size;
02163 }
02164
02165
02166 int
02167 xtensa_frame_pointer_required (void)
02168 {
02169
02170
02171
02172
02173
02174 if (cfun->machine->accesses_prev_frame)
02175 return 1;
02176
02177 return 0;
02178 }
02179
02180
02181 void
02182 xtensa_expand_prologue (void)
02183 {
02184 HOST_WIDE_INT total_size;
02185 rtx size_rtx;
02186
02187 total_size = compute_frame_size (get_frame_size ());
02188 size_rtx = GEN_INT (total_size);
02189
02190 if (total_size < (1 << (12+3)))
02191 emit_insn (gen_entry (size_rtx, size_rtx));
02192 else
02193 {
02194
02195 rtx tmp_reg = gen_rtx_REG (Pmode, A8_REG);
02196 emit_insn (gen_entry (size_rtx, GEN_INT (MIN_FRAME_SIZE)));
02197 emit_move_insn (tmp_reg, GEN_INT (total_size - MIN_FRAME_SIZE));
02198 emit_insn (gen_subsi3 (tmp_reg, stack_pointer_rtx, tmp_reg));
02199 emit_move_insn (stack_pointer_rtx, tmp_reg);
02200 }
02201
02202 if (frame_pointer_needed)
02203 {
02204 if (cfun->machine->set_frame_ptr_insn)
02205 {
02206 rtx first, insn;
02207
02208 push_topmost_sequence ();
02209 first = get_insns ();
02210 pop_topmost_sequence ();
02211
02212
02213
02214 for (insn = first;
02215 insn != cfun->machine->set_frame_ptr_insn;
02216 insn = NEXT_INSN (insn))
02217 {
02218 if (INSN_P (insn))
02219 PATTERN (insn) = replace_rtx (copy_rtx (PATTERN (insn)),
02220 hard_frame_pointer_rtx,
02221 stack_pointer_rtx);
02222 }
02223 }
02224 else
02225 emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
02226 }
02227 }
02228
02229
02230
02231
02232 void
02233 xtensa_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
02234 HOST_WIDE_INT size ATTRIBUTE_UNUSED)
02235 {
02236 xtensa_current_frame_size = 0;
02237 }
02238
02239
02240 rtx
02241 xtensa_return_addr (int count, rtx frame)
02242 {
02243 rtx result, retaddr;
02244
02245 if (count == -1)
02246 retaddr = gen_rtx_REG (Pmode, A0_REG);
02247 else
02248 {
02249 rtx addr = plus_constant (frame, -4 * UNITS_PER_WORD);
02250 addr = memory_address (Pmode, addr);
02251 retaddr = gen_reg_rtx (Pmode);
02252 emit_move_insn (retaddr, gen_rtx_MEM (Pmode, addr));
02253 }
02254
02255
02256
02257
02258
02259 result = gen_reg_rtx (Pmode);
02260 emit_insn (gen_fix_return_addr (result, retaddr));
02261 return result;
02262 }
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281 static tree
02282 xtensa_build_builtin_va_list (void)
02283 {
02284 tree f_stk, f_reg, f_ndx, record, type_decl;
02285
02286 record = (*lang_hooks.types.make_type) (RECORD_TYPE);
02287 type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);
02288
02289 f_stk = build_decl (FIELD_DECL, get_identifier ("__va_stk"),
02290 ptr_type_node);
02291 f_reg = build_decl (FIELD_DECL, get_identifier ("__va_reg"),
02292 ptr_type_node);
02293 f_ndx = build_decl (FIELD_DECL, get_identifier ("__va_ndx"),
02294 integer_type_node);
02295
02296 DECL_FIELD_CONTEXT (f_stk) = record;
02297 DECL_FIELD_CONTEXT (f_reg) = record;
02298 DECL_FIELD_CONTEXT (f_ndx) = record;
02299
02300 TREE_CHAIN (record) = type_decl;
02301 TYPE_NAME (record) = type_decl;
02302 TYPE_FIELDS (record) = f_stk;
02303 TREE_CHAIN (f_stk) = f_reg;
02304 TREE_CHAIN (f_reg) = f_ndx;
02305
02306 layout_type (record);
02307 return record;
02308 }
02309
02310
02311
02312
02313
02314 static rtx
02315 xtensa_builtin_saveregs (void)
02316 {
02317 rtx gp_regs, dest;
02318 int arg_words = current_function_args_info.arg_words;
02319 int gp_left = MAX_ARGS_IN_REGISTERS - arg_words;
02320
02321 if (gp_left <= 0)
02322 return const0_rtx;
02323
02324
02325 gp_regs = assign_stack_local
02326 (BLKmode, MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD, -1);
02327 set_mem_alias_set (gp_regs, get_varargs_alias_set ());
02328
02329
02330 dest = change_address (gp_regs, SImode,
02331 plus_constant (XEXP (gp_regs, 0),
02332 arg_words * UNITS_PER_WORD));
02333 cfun->machine->need_a7_copy = true;
02334 cfun->machine->vararg_a7 = true;
02335 move_block_from_reg (GP_ARG_FIRST + arg_words, dest, gp_left);
02336
02337 return XEXP (gp_regs, 0);
02338 }
02339
02340
02341
02342
02343
02344 void
02345 xtensa_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
02346 {
02347 tree f_stk, stk;
02348 tree f_reg, reg;
02349 tree f_ndx, ndx;
02350 tree t, u;
02351 int arg_words;
02352
02353 arg_words = current_function_args_info.arg_words;
02354
02355 f_stk = TYPE_FIELDS (va_list_type_node);
02356 f_reg = TREE_CHAIN (f_stk);
02357 f_ndx = TREE_CHAIN (f_reg);
02358
02359 stk = build (COMPONENT_REF, TREE_TYPE (f_stk), valist, f_stk, NULL_TREE);
02360 reg = build (COMPONENT_REF, TREE_TYPE (f_reg), valist, f_reg, NULL_TREE);
02361 ndx = build (COMPONENT_REF, TREE_TYPE (f_ndx), valist, f_ndx, NULL_TREE);
02362
02363
02364 u = make_tree (ptr_type_node, expand_builtin_saveregs ());
02365 t = build (MODIFY_EXPR, ptr_type_node, reg, u);
02366 TREE_SIDE_EFFECTS (t) = 1;
02367 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
02368
02369
02370 u = make_tree (ptr_type_node, virtual_incoming_args_rtx);
02371 u = fold (build (PLUS_EXPR, ptr_type_node, u,
02372 build_int_cst (NULL_TREE, -32)));
02373 t = build (MODIFY_EXPR, ptr_type_node, stk, u);
02374 TREE_SIDE_EFFECTS (t) = 1;
02375 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
02376
02377
02378
02379
02380 if (arg_words >= MAX_ARGS_IN_REGISTERS)
02381 arg_words += 2;
02382 u = build_int_cst (NULL_TREE, arg_words * UNITS_PER_WORD);
02383 t = build (MODIFY_EXPR, integer_type_node, ndx, u);
02384 TREE_SIDE_EFFECTS (t) = 1;
02385 expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
02386 }
02387
02388
02389
02390
02391 static tree
02392 xtensa_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p,
02393 tree *post_p ATTRIBUTE_UNUSED)
02394 {
02395 tree f_stk, stk;
02396 tree f_reg, reg;
02397 tree f_ndx, ndx;
02398 tree type_size, array, orig_ndx, addr, size, va_size, t;
02399 tree lab_false, lab_over, lab_false2;
02400 bool indirect;
02401
02402 indirect = pass_by_reference (NULL, TYPE_MODE (type), type, false);
02403 if (indirect)
02404 type = build_pointer_type (type);
02405
02406
02407 if (TREE_CODE (type) == COMPLEX_TYPE)
02408 {
02409 tree real_part, imag_part;
02410
02411 real_part = xtensa_gimplify_va_arg_expr (valist, TREE_TYPE (type),
02412 pre_p, NULL);
02413 real_part = get_initialized_tmp_var (real_part, pre_p, NULL);
02414
02415 imag_part = xtensa_gimplify_va_arg_expr (valist, TREE_TYPE (type),
02416 pre_p, NULL);
02417 imag_part = get_initialized_tmp_var (imag_part, pre_p, NULL);
02418
02419 return build (COMPLEX_EXPR, type, real_part, imag_part);
02420 }
02421
02422 f_stk = TYPE_FIELDS (va_list_type_node);
02423 f_reg = TREE_CHAIN (f_stk);
02424 f_ndx = TREE_CHAIN (f_reg);
02425
02426 stk = build (COMPONENT_REF, TREE_TYPE (f_stk), valist, f_stk, NULL_TREE);
02427 reg = build (COMPONENT_REF, TREE_TYPE (f_reg), valist, f_reg, NULL_TREE);
02428 ndx = build (COMPONENT_REF, TREE_TYPE (f_ndx), valist, f_ndx, NULL_TREE);
02429
02430 type_size = size_in_bytes (type);
02431 va_size = round_up (type_size, UNITS_PER_WORD);
02432 gimplify_expr (&va_size, pre_p, NULL, is_gimple_val, fb_rvalue);
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442 orig_ndx = get_initialized_tmp_var (ndx, pre_p, NULL);
02443
02444 if (TYPE_ALIGN (type) > BITS_PER_WORD)
02445 {
02446 int align = TYPE_ALIGN (type) / BITS_PER_UNIT;
02447
02448 t = build (PLUS_EXPR, integer_type_node, orig_ndx,
02449 build_int_cst (NULL_TREE, align - 1));
02450 t = build (BIT_AND_EXPR, integer_type_node, t,
02451 build_int_cst (NULL_TREE, -align));
02452 t = build (MODIFY_EXPR, integer_type_node, orig_ndx, t);
02453 gimplify_and_add (t, pre_p);
02454 }
02455
02456
02457
02458
02459
02460
02461 t = fold_convert (integer_type_node, va_size);
02462 t = build (PLUS_EXPR, integer_type_node, orig_ndx, t);
02463 t = build (MODIFY_EXPR, integer_type_node, ndx, t);
02464 gimplify_and_add (t, pre_p);
02465
02466
02467
02468
02469
02470
02471
02472
02473 array = create_tmp_var (ptr_type_node, NULL);
02474
02475 lab_over = NULL;
02476 if (!targetm.calls.must_pass_in_stack (TYPE_MODE (type), type))
02477 {
02478 lab_false = create_artificial_label ();
02479 lab_over = create_artificial_label ();
02480
02481 t = build_int_cst (NULL_TREE, MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD);
02482 t = build (GT_EXPR, boolean_type_node, ndx, t);
02483 t = build (COND_EXPR, void_type_node, t,
02484 build (GOTO_EXPR, void_type_node, lab_false),
02485 NULL);
02486 gimplify_and_add (t, pre_p);
02487
02488 t = build (MODIFY_EXPR, void_type_node, array, reg);
02489 gimplify_and_add (t, pre_p);
02490
02491 t = build (GOTO_EXPR, void_type_node, lab_over);
02492 gimplify_and_add (t, pre_p);
02493
02494 t = build (LABEL_EXPR, void_type_node, lab_false);
02495 gimplify_and_add (t, pre_p);
02496 }
02497
02498
02499
02500
02501
02502
02503
02504
02505
02506
02507
02508
02509 lab_false2 = create_artificial_label ();
02510
02511 t = build_int_cst (NULL_TREE, MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD);
02512 t = build (GT_EXPR, boolean_type_node, orig_ndx, t);
02513 t = build (COND_EXPR, void_type_node, t,
02514 build (GOTO_EXPR, void_type_node, lab_false2),
02515 NULL);
02516 gimplify_and_add (t, pre_p);
02517
02518 t = size_binop (PLUS_EXPR, va_size, size_int (32));
02519 t = fold_convert (integer_type_node, t);
02520 t = build (MODIFY_EXPR, integer_type_node, ndx, t);
02521 gimplify_and_add (t, pre_p);
02522
02523 t = build (LABEL_EXPR, void_type_node, lab_false2);
02524 gimplify_and_add (t, pre_p);
02525
02526 t = build (MODIFY_EXPR, void_type_node, array, stk);
02527 gimplify_and_add (t, pre_p);
02528
02529 if (lab_over)
02530 {
02531 t = build (LABEL_EXPR, void_type_node, lab_over);
02532 gimplify_and_add (t, pre_p);
02533 }
02534
02535
02536
02537
02538
02539
02540
02541
02542
02543
02544
02545
02546
02547 if (BYTES_BIG_ENDIAN && TREE_CODE (type_size) == INTEGER_CST)
02548 {
02549 t = size_int (PARM_BOUNDARY / BITS_PER_UNIT);
02550 t = fold (build (GE_EXPR, boolean_type_node, type_size, t));
02551 t = fold (build (COND_EXPR, sizetype, t, va_size, type_size));
02552 size = t;
02553 }
02554 else
02555 size = va_size;
02556
02557 t = fold_convert (ptr_type_node, ndx);
02558 addr = build (PLUS_EXPR, ptr_type_node, array, t);
02559 t = fold_convert (ptr_type_node, size);
02560 addr = build (MINUS_EXPR, ptr_type_node, addr, t);
02561
02562 addr = fold_convert (build_pointer_type (type), addr);
02563 if (indirect)
02564 addr = build_fold_indirect_ref (addr);
02565 return build_fold_indirect_ref (addr);
02566 }
02567
02568
02569 enum reg_class
02570 xtensa_preferred_reload_class (rtx x, enum reg_class class, int isoutput)
02571 {
02572 if (!isoutput && CONSTANT_P (x) && GET_CODE (x) == CONST_DOUBLE)
02573 return NO_REGS;
02574
02575
02576
02577
02578
02579
02580
02581 if (class == AR_REGS || class == GR_REGS)
02582 return RL_REGS;
02583
02584 return class;
02585 }
02586
02587
02588 enum reg_class
02589 xtensa_secondary_reload_class (enum reg_class class,
02590 enum machine_mode mode ATTRIBUTE_UNUSED,
02591 rtx x, int isoutput)
02592 {
02593 int regno;
02594
02595 if (GET_CODE (x) == SIGN_EXTEND)
02596 x = XEXP (x, 0);
02597 regno = xt_true_regnum (x);
02598
02599 if (!isoutput)
02600 {
02601 if (class == FP_REGS && constantpool_mem_p (x))
02602 return RL_REGS;
02603 }
02604
02605 if (ACC_REG_P (regno))
02606 return ((class == GR_REGS || class == RL_REGS) ? NO_REGS : RL_REGS);
02607 if (class == ACC_REG)
02608 return (GP_REG_P (regno) ? NO_REGS : RL_REGS);
02609
02610 return NO_REGS;
02611 }
02612
02613
02614 void
02615 order_regs_for_local_alloc (void)
02616 {
02617 if (!leaf_function_p ())
02618 {
02619 memcpy (reg_alloc_order, reg_nonleaf_alloc_order,
02620 FIRST_PSEUDO_REGISTER * sizeof (int));
02621 }
02622 else
02623 {
02624 int i, num_arg_regs;
02625 int nxt = 0;
02626
02627
02628
02629 num_arg_regs = current_function_args_info.arg_words;
02630 if (num_arg_regs > MAX_ARGS_IN_REGISTERS)
02631 num_arg_regs = MAX_ARGS_IN_REGISTERS;
02632 for (i = GP_ARG_FIRST; i < 16 - num_arg_regs; i++)
02633 reg_alloc_order[nxt++] = i + num_arg_regs;
02634 for (i = 0; i < num_arg_regs; i++)
02635 reg_alloc_order[nxt++] = GP_ARG_FIRST + i;
02636
02637
02638 for (i = 0; i < BR_REG_NUM; i++)
02639 reg_alloc_order[nxt++] = BR_REG_FIRST + i;
02640
02641
02642 for (i = 0; i < 16; i++)
02643 reg_alloc_order[nxt++] = FP_REG_FIRST + i;
02644
02645
02646 reg_alloc_order[nxt++] = 0;
02647 reg_alloc_order[nxt++] = 1;
02648 reg_alloc_order[nxt++] = 16;
02649 reg_alloc_order[nxt++] = 17;
02650
02651 reg_alloc_order[nxt++] = ACC_REG_FIRST;
02652 }
02653 }
02654
02655
02656
02657
02658
02659 static unsigned int
02660 xtensa_multibss_section_type_flags (tree decl, const char *name, int reloc)
02661 {
02662 unsigned int flags = default_section_type_flags (decl, name, reloc);
02663 const char *suffix;
02664
02665 suffix = strrchr (name, '.');
02666 if (suffix && strcmp (suffix, ".bss") == 0)
02667 {
02668 if (!decl || (TREE_CODE (decl) == VAR_DECL
02669 && DECL_INITIAL (decl) == NULL_TREE))
02670 flags |= SECTION_BSS;
02671 else
02672 warning ("only uninitialized variables can be placed in a "
02673 ".bss section");
02674 }
02675
02676 return flags;
02677 }
02678
02679
02680
02681
02682 static void
02683 xtensa_select_rtx_section (enum machine_mode mode ATTRIBUTE_UNUSED,
02684 rtx x ATTRIBUTE_UNUSED,
02685 unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
02686 {
02687 function_section (current_function_decl);
02688 }
02689
02690
02691
02692
02693
02694
02695 static bool
02696 xtensa_rtx_costs (rtx x, int code, int outer_code, int *total)
02697 {
02698 switch (code)
02699 {
02700 case CONST_INT:
02701 switch (outer_code)
02702 {
02703 case SET:
02704 if (xtensa_simm12b (INTVAL (x)))
02705 {
02706 *total = 4;
02707 return true;
02708 }
02709 break;
02710 case PLUS:
02711 if (xtensa_simm8 (INTVAL (x))
02712 || xtensa_simm8x256 (INTVAL (x)))
02713 {
02714 *total = 0;
02715 return true;
02716 }
02717 break;
02718 case AND:
02719 if (xtensa_mask_immediate (INTVAL (x)))
02720 {
02721 *total = 0;
02722 return true;
02723 }
02724 break;
02725 case COMPARE:
02726 if ((INTVAL (x) == 0) || xtensa_b4const (INTVAL (x)))
02727 {
02728 *total = 0;
02729 return true;
02730 }
02731 break;
02732 case ASHIFT:
02733 case ASHIFTRT:
02734 case LSHIFTRT:
02735 case ROTATE:
02736 case ROTATERT:
02737
02738 default: break;
02739 }
02740 if (xtensa_simm12b (INTVAL (x)))
02741 *total = 5;
02742 else if (TARGET_CONST16)
02743 *total = COSTS_N_INSNS (2);
02744 else
02745 *total = 6;
02746 return true;
02747
02748 case CONST:
02749 case LABEL_REF:
02750 case SYMBOL_REF:
02751 if (TARGET_CONST16)
02752 *total = COSTS_N_INSNS (2);
02753 else
02754 *total = 5;
02755 return true;
02756
02757 case CONST_DOUBLE:
02758 if (TARGET_CONST16)
02759 *total = COSTS_N_INSNS (4);
02760 else
02761 *total = 7;
02762 return true;
02763
02764 case MEM:
02765 {
02766 int num_words =
02767 (GET_MODE_SIZE (GET_MODE (x)) > UNITS_PER_WORD) ? 2 : 1;
02768
02769 if (memory_address_p (GET_MODE (x), XEXP ((x), 0)))
02770 *total = COSTS_N_INSNS (num_words);
02771 else
02772 *total = COSTS_N_INSNS (2*num_words);
02773 return true;
02774 }
02775
02776 case FFS:
02777 *total = COSTS_N_INSNS (TARGET_NSA ? 5 : 50);
02778 return true;
02779
02780 case NOT:
02781 *total = COSTS_N_INSNS ((GET_MODE (x) == DImode) ? 3 : 2);
02782 return true;
02783
02784 case AND:
02785 case IOR:
02786 case XOR:
02787 if (GET_MODE (x) == DImode)
02788 *total = COSTS_N_INSNS (2);
02789 else
02790 *total = COSTS_N_INSNS (1);
02791 return true;
02792
02793 case ASHIFT:
02794 case ASHIFTRT:
02795 case LSHIFTRT:
02796 if (GET_MODE (x) == DImode)
02797 *total = COSTS_N_INSNS (50);
02798 else
02799 *total = COSTS_N_INSNS (1);
02800 return true;
02801
02802 case ABS:
02803 {
02804 enum machine_mode xmode = GET_MODE (x);
02805 if (xmode == SFmode)
02806 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 1 : 50);
02807 else if (xmode == DFmode)
02808 *total = COSTS_N_INSNS (50);
02809 else
02810 *total = COSTS_N_INSNS (4);
02811 return true;
02812 }
02813
02814 case PLUS:
02815 case MINUS:
02816 {
02817 enum machine_mode xmode = GET_MODE (x);
02818 if (xmode == SFmode)
02819 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 1 : 50);
02820 else if (xmode == DFmode || xmode == DImode)
02821 *total = COSTS_N_INSNS (50);
02822 else
02823 *total = COSTS_N_INSNS (1);
02824 return true;
02825 }
02826
02827 case NEG:
02828 *total = COSTS_N_INSNS ((GET_MODE (x) == DImode) ? 4 : 2);
02829 return true;
02830
02831 case MULT:
02832 {
02833 enum machine_mode xmode = GET_MODE (x);
02834 if (xmode == SFmode)
02835 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT ? 4 : 50);
02836 else if (xmode == DFmode || xmode == DImode)
02837 *total = COSTS_N_INSNS (50);
02838 else if (TARGET_MUL32)
02839 *total = COSTS_N_INSNS (4);
02840 else if (TARGET_MAC16)
02841 *total = COSTS_N_INSNS (16);
02842 else if (TARGET_MUL16)
02843 *total = COSTS_N_INSNS (12);
02844 else
02845 *total = COSTS_N_INSNS (50);
02846 return true;
02847 }
02848
02849 case DIV:
02850 case MOD:
02851 {
02852 enum machine_mode xmode = GET_MODE (x);
02853 if (xmode == SFmode)
02854 {
02855 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT_DIV ? 8 : 50);
02856 return true;
02857 }
02858 else if (xmode == DFmode)
02859 {
02860 *total = COSTS_N_INSNS (50);
02861 return true;
02862 }
02863 }
02864
02865
02866 case UDIV:
02867 case UMOD:
02868 {
02869 enum machine_mode xmode = GET_MODE (x);
02870 if (xmode == DImode)
02871 *total = COSTS_N_INSNS (50);
02872 else if (TARGET_DIV32)
02873 *total = COSTS_N_INSNS (32);
02874 else
02875 *total = COSTS_N_INSNS (50);
02876 return true;
02877 }
02878
02879 case SQRT:
02880 if (GET_MODE (x) == SFmode)
02881 *total = COSTS_N_INSNS (TARGET_HARD_FLOAT_SQRT ? 8 : 50);
02882 else
02883 *total = COSTS_N_INSNS (50);
02884 return true;
02885
02886 case SMIN:
02887 case UMIN:
02888 case SMAX:
02889 case UMAX:
02890 *total = COSTS_N_INSNS (TARGET_MINMAX ? 1 : 50);
02891 return true;
02892
02893 case SIGN_EXTRACT:
02894 case SIGN_EXTEND:
02895 *total = COSTS_N_INSNS (TARGET_SEXT ? 1 : 2);
02896 return true;
02897
02898 case ZERO_EXTRACT:
02899 case ZERO_EXTEND:
02900 *total = COSTS_N_INSNS (1);
02901 return true;
02902
02903 default:
02904 return false;
02905 }
02906 }
02907
02908
02909
02910 static bool
02911 xtensa_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
02912 {
02913 return ((unsigned HOST_WIDE_INT) int_size_in_bytes (type)
02914 > 4 * UNITS_PER_WORD);
02915 }
02916
02917 #include "gt-xtensa.h"