diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-08-22 10:27:46 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-08-22 10:27:46 +0000 |
commit | f733cf303bcdc952c92b81dd62199a40a1f555ec (patch) | |
tree | 0a9a9e0f28aa7c7f5bc4d1d1d0e9647163cac4f7 /gcc/config/visium/visium.c | |
parent | e0e4357b88efe5dc53e50d341a09de4d02331200 (diff) | |
download | gcc-tarball-51b577d7e597bf27e0277cae6b3b54bbf2e90ee2.tar.gz |
gcc-6.2.0gcc-6.2.0
Diffstat (limited to 'gcc/config/visium/visium.c')
-rw-r--r-- | gcc/config/visium/visium.c | 107 |
1 files changed, 82 insertions, 25 deletions
diff --git a/gcc/config/visium/visium.c b/gcc/config/visium/visium.c index cd28f9bf90..6712fed72b 100644 --- a/gcc/config/visium/visium.c +++ b/gcc/config/visium/visium.c @@ -2026,7 +2026,7 @@ visium_rtx_costs (rtx x, machine_mode mode, int outer_code ATTRIBUTE_UNUSED, /* Split a double move of OPERANDS in MODE. */ void -split_double_move (rtx *operands, enum machine_mode mode) +visium_split_double_move (rtx *operands, enum machine_mode mode) { bool swap = false; @@ -2076,14 +2076,74 @@ split_double_move (rtx *operands, enum machine_mode mode) } } +/* Split a double addition or subtraction of operands. */ + +void +visium_split_double_add (enum rtx_code code, rtx op0, rtx op1, rtx op2) +{ + rtx op3 = gen_lowpart (SImode, op0); + rtx op4 = gen_lowpart (SImode, op1); + rtx op5; + rtx op6 = gen_highpart (SImode, op0); + rtx op7 = (op1 == const0_rtx ? op1 : gen_highpart (SImode, op1)); + rtx op8; + rtx x, pat, flags; + + /* If operand #2 is a small constant, then its high part is null. */ + if (CONST_INT_P (op2)) + { + HOST_WIDE_INT val = INTVAL (op2); + + if (val < 0) + { + code = (code == MINUS ? PLUS : MINUS); + val = -val; + } + + op5 = gen_int_mode (val, SImode); + op8 = const0_rtx; + } + else + { + op5 = gen_lowpart (SImode, op2); + op8 = gen_highpart (SImode, op2); + } + + /* This is the {add,sub,neg}si3_insn_set_flags pattern. */ + if (op4 == const0_rtx) + x = gen_rtx_NEG (SImode, op5); + else + x = gen_rtx_fmt_ee (code, SImode, op4, op5); + pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2)); + XVECEXP (pat, 0, 0) = gen_rtx_SET (op3, x); + flags = gen_rtx_REG (CC_NOOVmode, FLAGS_REGNUM); + x = gen_rtx_COMPARE (CC_NOOVmode, shallow_copy_rtx (x), const0_rtx); + XVECEXP (pat, 0, 1) = gen_rtx_SET (flags, x); + emit_insn (pat); + + /* This is the plus_[plus_]sltu_flags or minus_[minus_]sltu_flags pattern. */ + if (op8 == const0_rtx) + x = op7; + else + x = gen_rtx_fmt_ee (code, SImode, op7, op8); + x = gen_rtx_fmt_ee (code, SImode, x, gen_rtx_LTU (SImode, flags, const0_rtx)); + pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2)); + XVECEXP (pat, 0, 0) = gen_rtx_SET (op6, x); + flags = gen_rtx_REG (CCmode, FLAGS_REGNUM); + XVECEXP (pat, 0, 1) = gen_rtx_CLOBBER (VOIDmode, flags); + emit_insn (pat); + + visium_flags_exposed = true; +} + /* Expand a copysign of OPERANDS in MODE. */ void visium_expand_copysign (rtx *operands, enum machine_mode mode) { - rtx dest = operands[0]; - rtx op0 = operands[1]; - rtx op1 = operands[2]; + rtx op0 = operands[0]; + rtx op1 = operands[1]; + rtx op2 = operands[2]; rtx mask = force_reg (SImode, GEN_INT (0x7fffffff)); rtx x; @@ -2091,37 +2151,37 @@ visium_expand_copysign (rtx *operands, enum machine_mode mode) the FPU on the MCM have a non-standard behavior wrt NaNs. */ gcc_assert (mode == SFmode); - /* First get all the non-sign bits of OP0. */ - if (GET_CODE (op0) == CONST_DOUBLE) + /* First get all the non-sign bits of op1. */ + if (GET_CODE (op1) == CONST_DOUBLE) { - if (real_isneg (CONST_DOUBLE_REAL_VALUE (op0))) - op0 = simplify_unary_operation (ABS, mode, op0, mode); - if (op0 != CONST0_RTX (mode)) + if (real_isneg (CONST_DOUBLE_REAL_VALUE (op1))) + op1 = simplify_unary_operation (ABS, mode, op1, mode); + if (op1 != CONST0_RTX (mode)) { long l; - REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op0), l); - op0 = force_reg (SImode, GEN_INT (trunc_int_for_mode (l, SImode))); + REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op1), l); + op1 = force_reg (SImode, gen_int_mode (l, SImode)); } } else { - op0 = copy_to_mode_reg (SImode, gen_lowpart (SImode, op0)); - op0 = force_reg (SImode, gen_rtx_AND (SImode, op0, mask)); + op1 = copy_to_mode_reg (SImode, gen_lowpart (SImode, op1)); + op1 = force_reg (SImode, gen_rtx_AND (SImode, op1, mask)); } - /* Then get the sign bit of OP1. */ + /* Then get the sign bit of op2. */ mask = force_reg (SImode, gen_rtx_NOT (SImode, mask)); - op1 = copy_to_mode_reg (SImode, gen_lowpart (SImode, op1)); - op1 = force_reg (SImode, gen_rtx_AND (SImode, op1, mask)); + op2 = copy_to_mode_reg (SImode, gen_lowpart (SImode, op2)); + op2 = force_reg (SImode, gen_rtx_AND (SImode, op2, mask)); /* Finally OR the two values. */ - if (op0 == CONST0_RTX (SFmode)) - x = op1; + if (op1 == CONST0_RTX (SFmode)) + x = op2; else - x = force_reg (SImode, gen_rtx_IOR (SImode, op0, op1)); + x = force_reg (SImode, gen_rtx_IOR (SImode, op1, op2)); /* And move the result to the destination. */ - emit_insn (gen_rtx_SET (dest, gen_lowpart (SFmode, x))); + emit_insn (gen_rtx_SET (op0, gen_lowpart (SFmode, x))); } /* Expand a cstore of OPERANDS in MODE for EQ/NE/LTU/GTU/GEU/LEU. We generate @@ -3537,18 +3597,15 @@ visium_compute_frame_size (int size) int visium_initial_elimination_offset (int from, int to ATTRIBUTE_UNUSED) { - const int frame_size = visium_compute_frame_size (get_frame_size ()); const int save_fp = current_frame_info.save_fp; const int save_lr = current_frame_info.save_lr; const int lr_slot = current_frame_info.lr_slot; - const int local_frame_offset - = (save_fp + save_lr + lr_slot) * UNITS_PER_WORD; int offset; if (from == FRAME_POINTER_REGNUM) - offset = local_frame_offset; + offset = (save_fp + save_lr + lr_slot) * UNITS_PER_WORD; else if (from == ARG_POINTER_REGNUM) - offset = frame_size; + offset = visium_compute_frame_size (get_frame_size ()); else gcc_unreachable (); |