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