📄 sparc.c
字号:
static voidsparc_emit_set_const64_quick1 (op0, temp, low_bits, is_neg) rtx op0; rtx temp; unsigned HOST_WIDE_INT low_bits; int is_neg;{ unsigned HOST_WIDE_INT high_bits; if (is_neg) high_bits = (~low_bits) & 0xffffffff; else high_bits = low_bits; sparc_emit_set_safe_HIGH64 (temp, high_bits); if (!is_neg) { emit_insn (gen_rtx_SET (VOIDmode, op0, gen_safe_OR64 (temp, (high_bits & 0x3ff)))); } else { /* If we are XOR'ing with -1, then we should emit a one's complement instead. This way the combiner will notice logical operations such as ANDN later on and substitute. */ if ((low_bits & 0x3ff) == 0x3ff) { emit_insn (gen_rtx_SET (VOIDmode, op0, gen_rtx_NOT (DImode, temp))); } else { emit_insn (gen_rtx_SET (VOIDmode, op0, gen_safe_XOR64 (temp, (-0x400 | (low_bits & 0x3ff))))); } }}static void sparc_emit_set_const64_quick2 PROTO((rtx, rtx, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, int));static voidsparc_emit_set_const64_quick2 (op0, temp, high_bits, low_immediate, shift_count) rtx op0; rtx temp; unsigned HOST_WIDE_INT high_bits; unsigned HOST_WIDE_INT low_immediate; int shift_count;{ rtx temp2 = op0; if ((high_bits & 0xfffffc00) != 0) { sparc_emit_set_safe_HIGH64 (temp, high_bits); if ((high_bits & ~0xfffffc00) != 0) emit_insn (gen_rtx_SET (VOIDmode, op0, gen_safe_OR64 (temp, (high_bits & 0x3ff)))); else temp2 = temp; } else { emit_insn (gen_safe_SET64 (temp, high_bits)); temp2 = temp; } /* Now shift it up into place. */ emit_insn (gen_rtx_SET (VOIDmode, op0, gen_rtx_ASHIFT (DImode, temp2, GEN_INT (shift_count)))); /* If there is a low immediate part piece, finish up by putting that in as well. */ if (low_immediate != 0) emit_insn (gen_rtx_SET (VOIDmode, op0, gen_safe_OR64 (op0, low_immediate)));}static void sparc_emit_set_const64_longway PROTO((rtx, rtx, unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT));/* Full 64-bit constant decomposition. Even though this is the 'worst' case, we still optimize a few things away. */static voidsparc_emit_set_const64_longway (op0, temp, high_bits, low_bits) rtx op0; rtx temp; unsigned HOST_WIDE_INT high_bits; unsigned HOST_WIDE_INT low_bits;{ rtx sub_temp; if (reload_in_progress || reload_completed) sub_temp = op0; else sub_temp = gen_reg_rtx (DImode); if ((high_bits & 0xfffffc00) != 0) { sparc_emit_set_safe_HIGH64 (temp, high_bits); if ((high_bits & ~0xfffffc00) != 0) emit_insn (gen_rtx_SET (VOIDmode, sub_temp, gen_safe_OR64 (temp, (high_bits & 0x3ff)))); else sub_temp = temp; } else { emit_insn (gen_safe_SET64 (temp, high_bits)); sub_temp = temp; } if (!reload_in_progress && !reload_completed) { rtx temp2 = gen_reg_rtx (DImode); rtx temp3 = gen_reg_rtx (DImode); rtx temp4 = gen_reg_rtx (DImode); emit_insn (gen_rtx_SET (VOIDmode, temp4, gen_rtx_ASHIFT (DImode, sub_temp, GEN_INT (32)))); sparc_emit_set_safe_HIGH64 (temp2, low_bits); if ((low_bits & ~0xfffffc00) != 0) { emit_insn (gen_rtx_SET (VOIDmode, temp3, gen_safe_OR64 (temp2, (low_bits & 0x3ff)))); emit_insn (gen_rtx_SET (VOIDmode, op0, gen_rtx_PLUS (DImode, temp4, temp3))); } else { emit_insn (gen_rtx_SET (VOIDmode, op0, gen_rtx_PLUS (DImode, temp4, temp2))); } } else { rtx low1 = GEN_INT ((low_bits >> (32 - 12)) & 0xfff); rtx low2 = GEN_INT ((low_bits >> (32 - 12 - 12)) & 0xfff); rtx low3 = GEN_INT ((low_bits >> (32 - 12 - 12 - 8)) & 0x0ff); int to_shift = 12; /* We are in the middle of reload, so this is really painful. However we do still make an attempt to avoid emitting truly stupid code. */ if (low1 != const0_rtx) { emit_insn (gen_rtx_SET (VOIDmode, op0, gen_rtx_ASHIFT (DImode, sub_temp, GEN_INT (to_shift)))); emit_insn (gen_rtx_SET (VOIDmode, op0, gen_rtx_IOR (DImode, op0, low1))); sub_temp = op0; to_shift = 12; } else { to_shift += 12; } if (low2 != const0_rtx) { emit_insn (gen_rtx_SET (VOIDmode, op0, gen_rtx_ASHIFT (DImode, sub_temp, GEN_INT (to_shift)))); emit_insn (gen_rtx_SET (VOIDmode, op0, gen_rtx_IOR (DImode, op0, low2))); sub_temp = op0; to_shift = 8; } else { to_shift += 8; } emit_insn (gen_rtx_SET (VOIDmode, op0, gen_rtx_ASHIFT (DImode, sub_temp, GEN_INT (to_shift)))); if (low3 != const0_rtx) emit_insn (gen_rtx_SET (VOIDmode, op0, gen_rtx_IOR (DImode, op0, low3))); /* phew... */ }}/* Analyze a 64-bit constant for certain properties. */static void analyze_64bit_constant PROTO((unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, int *, int *, int *));static voidanalyze_64bit_constant (high_bits, low_bits, hbsp, lbsp, abbasp) unsigned HOST_WIDE_INT high_bits, low_bits; int *hbsp, *lbsp, *abbasp;{ int lowest_bit_set, highest_bit_set, all_bits_between_are_set; int i; lowest_bit_set = highest_bit_set = -1; i = 0; do { if ((lowest_bit_set == -1) && ((low_bits >> i) & 1)) lowest_bit_set = i; if ((highest_bit_set == -1) && ((high_bits >> (32 - i - 1)) & 1)) highest_bit_set = (64 - i - 1); } while (++i < 32 && ((highest_bit_set == -1) || (lowest_bit_set == -1))); if (i == 32) { i = 0; do { if ((lowest_bit_set == -1) && ((high_bits >> i) & 1)) lowest_bit_set = i + 32; if ((highest_bit_set == -1) && ((low_bits >> (32 - i - 1)) & 1)) highest_bit_set = 32 - i - 1; } while (++i < 32 && ((highest_bit_set == -1) || (lowest_bit_set == -1))); } /* If there are no bits set this should have gone out as one instruction! */ if (lowest_bit_set == -1 || highest_bit_set == -1) abort (); all_bits_between_are_set = 1; for (i = lowest_bit_set; i <= highest_bit_set; i++) { if (i < 32) { if ((low_bits & (1 << i)) != 0) continue; } else { if ((high_bits & (1 << (i - 32))) != 0) continue; } all_bits_between_are_set = 0; break; } *hbsp = highest_bit_set; *lbsp = lowest_bit_set; *abbasp = all_bits_between_are_set;}static int const64_is_2insns PROTO((unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT));static intconst64_is_2insns (high_bits, low_bits) unsigned HOST_WIDE_INT high_bits, low_bits;{ int highest_bit_set, lowest_bit_set, all_bits_between_are_set; if (high_bits == 0 || high_bits == 0xffffffff) return 1; analyze_64bit_constant (high_bits, low_bits, &highest_bit_set, &lowest_bit_set, &all_bits_between_are_set); if ((highest_bit_set == 63 || lowest_bit_set == 0) && all_bits_between_are_set != 0) return 1; if ((highest_bit_set - lowest_bit_set) < 21) return 1; return 0;}static unsigned HOST_WIDE_INT create_simple_focus_bits PROTO((unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, int, int));static unsigned HOST_WIDE_INTcreate_simple_focus_bits (high_bits, low_bits, lowest_bit_set, shift) unsigned HOST_WIDE_INT high_bits, low_bits; int lowest_bit_set, shift;{ HOST_WIDE_INT hi, lo; if (lowest_bit_set < 32) { lo = (low_bits >> lowest_bit_set) << shift; hi = ((high_bits << (32 - lowest_bit_set)) << shift); } else { lo = 0; hi = ((high_bits >> (lowest_bit_set - 32)) << shift); } if (hi & lo) abort (); return (hi | lo);}/* Here we are sure to be arch64 and this is an integer constant being loaded into a register. Emit the most efficient insn sequence possible. Detection of all the 1-insn cases has been done already. */voidsparc_emit_set_const64 (op0, op1) rtx op0; rtx op1;{ unsigned HOST_WIDE_INT high_bits, low_bits; int lowest_bit_set, highest_bit_set; int all_bits_between_are_set; rtx temp; /* Sanity check that we know what we are working with. */ if (! TARGET_ARCH64 || GET_CODE (op0) != REG || (REGNO (op0) >= SPARC_FIRST_FP_REG && REGNO (op0) <= SPARC_LAST_V9_FP_REG)) abort (); if (reload_in_progress || reload_completed) temp = op0; else temp = gen_reg_rtx (DImode); if (GET_CODE (op1) != CONST_DOUBLE && GET_CODE (op1) != CONST_INT) { sparc_emit_set_symbolic_const64 (op0, op1, temp); return; } if (GET_CODE (op1) == CONST_DOUBLE) {#if HOST_BITS_PER_WIDE_INT == 64 high_bits = (CONST_DOUBLE_LOW (op1) >> 32) & 0xffffffff; low_bits = CONST_DOUBLE_LOW (op1) & 0xffffffff;#else high_bits = CONST_DOUBLE_HIGH (op1); low_bits = CONST_DOUBLE_LOW (op1);#endif } else {#if HOST_BITS_PER_WIDE_INT == 64 high_bits = ((INTVAL (op1) >> 32) & 0xffffffff); low_bits = (INTVAL (op1) & 0xffffffff);#else high_bits = ((INTVAL (op1) < 0) ? 0xffffffff : 0x00000000); low_bits = INTVAL (op1);#endif } /* low_bits bits 0 --> 31 high_bits bits 32 --> 63 */ analyze_64bit_constant (high_bits, low_bits, &highest_bit_set, &lowest_bit_set, &all_bits_between_are_set); /* First try for a 2-insn sequence. */ /* These situations are preferred because the optimizer can * do more things with them: * 1) mov -1, %reg * sllx %reg, shift, %reg * 2) mov -1, %reg * srlx %reg, shift, %reg * 3) mov some_small_const, %reg * sllx %reg, shift, %reg */ if (((highest_bit_set == 63 || lowest_bit_set == 0) && all_bits_between_are_set != 0) || ((highest_bit_set - lowest_bit_set) < 12)) { HOST_WIDE_INT the_const = -1; int shift = lowest_bit_set; if ((highest_bit_set != 63 && lowest_bit_set != 0) || all_bits_between_are_set == 0) { the_const = create_simple_focus_bits (high_bits, low_bits, lowest_bit_set, 0); } else if (lowest_bit_set == 0) shift = -(63 - highest_bit_set); if (! SPARC_SIMM13_P (the_const)) abort (); emit_insn (gen_safe_SET64 (temp, the_const)); if (shift > 0) emit_insn (gen_rtx_SET (VOIDmode, op0, gen_rtx_ASHIFT (DImode, temp, GEN_INT (shift)))); else if (shift < 0) emit_insn (gen_rtx_SET (VOIDmode, op0, gen_rtx_LSHIFTRT (DImode, temp, GEN_INT (-shift)))); else abort (); return; } /* Now a range of 22 or less bits set somewhere. * 1) sethi %hi(focus_bits), %reg * sllx %reg, shift, %reg * 2) sethi %hi(focus_bits), %reg * srlx %reg, shift, %reg */ if ((highest_bit_set - lowest_bit_set) < 21) { unsigned HOST_WIDE_INT focus_bits = create_simple_focus_bits (high_bits, low_bits, lowest_bit_set, 10); if (! SPARC_SETHI_P (focus_bits)) abort (); sparc_emit_set_safe_HIGH64 (temp, focus_bits); /* If lowest_bit_set == 10 then a sethi alone could have done it. */ if (lowest_bit_set < 10) emit_insn (gen_rtx_SET (VOIDmode, op0, gen_rtx_LSHIFTRT (DImode, temp, GEN_INT (10 - lowest_bit_set)))); else if (lowest_bit_set > 10) emit_insn (gen_rtx_SET (VOIDmode, op0, gen_rtx_ASHIFT (DImode, temp, GEN_INT (lowest_bit_set - 10)))); else abort (); return; } /* 1) sethi %hi(low_bits), %reg * or %reg, %lo(low_bits), %reg * 2) sethi %hi(~low_bits), %reg * xor %reg, %lo(-0x400 | (low_bits & 0x3ff)), %reg */ if (high_bits == 0 || high_bits == 0xffffffff) { sparc_emit_set_const64_quick1 (op0, temp, low_bits, (high_bits == 0xffffffff)); return; } /* Now, try 3-insn sequences. */ /* 1) sethi %hi(high_bits), %reg
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -