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