/* Output addition of register XOP[0] and compile time constant XOP[2].
+ INSN is a single_set insn or an insn pattern.
CODE == PLUS: perform addition by using ADD instructions or
CODE == MINUS: perform addition by using SUB instructions:
If PLEN == NULL, print assembler instructions to perform the operation;
otherwise, set *PLEN to the length of the instruction sequence (in words)
printed with PLEN == NULL. XOP[3] is an 8-bit scratch register or NULL_RTX.
- Set *PCC to effect on cc0 according to respective CC_* insn attribute.
CODE_SAT == UNKNOWN: Perform ordinary, non-saturating operation.
CODE_SAT != UNKNOWN: Perform operation and saturate according to CODE_SAT.
fixed-point rounding, cf. `avr_out_round'. */
static void
-avr_out_plus_1 (rtx *xop, int *plen, enum rtx_code code, int *pcc,
+avr_out_plus_1 (rtx /*insn*/, rtx *xop, int *plen, enum rtx_code code,
enum rtx_code code_sat, int sign, bool out_label)
{
/* MODE of the operation. */
if (REG_P (xop[2]))
{
- *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_CLOBBER;
-
for (int i = 0; i < n_bytes; i++)
{
/* We operate byte-wise on the destination. */
goto saturate;
}
- /* Except in the case of ADIW with 16-bit register (see below)
- addition does not set cc0 in a usable way. */
-
- *pcc = (MINUS == code) ? CC_SET_CZN : CC_CLOBBER;
-
if (CONST_FIXED_P (xval))
xval = avr_to_int_mode (xval);
/* Adding/Subtracting zero is a no-op. */
if (xval == const0_rtx)
- {
- *pcc = CC_NONE;
- return;
- }
+ return;
if (MINUS == code)
xval = simplify_unary_operation (NEG, imode, xval, imode);
/* To get usable cc0 no low-bytes must have been skipped. */
- if (i && !started)
- *pcc = CC_CLOBBER;
-
if (!started
&& i % 2 == 0
&& i + 2 <= n_bytes
started = true;
avr_asm_len (code == PLUS ? "adiw %0,%1" : "sbiw %0,%1",
op, plen, 1);
-
- if (n_bytes == 2 && PLUS == code)
- *pcc = CC_SET_CZN;
}
i++;
{
avr_asm_len ((code == PLUS) ^ (val8 == 1) ? "dec %0" : "inc %0",
op, plen, 1);
- *pcc = CC_CLOBBER;
break;
}
if (UNKNOWN == code_sat)
return;
- *pcc = (int) CC_CLOBBER;
-
/* Vanilla addition/subtraction is done. We are left with saturation.
We have to compute A = A <op> B where A is a register and
/* Output addition/subtraction of register XOP[0] and a constant XOP[2] that
- is ont a compile-time constant:
+ is not a compile-time constant:
XOP[0] = XOP[0] +/- XOP[2]
are additions/subtraction for pointer modes, i.e. HImode and PSImode. */
static const char *
-avr_out_plus_symbol (rtx *xop, enum rtx_code code, int *plen, int *pcc)
+avr_out_plus_symbol (rtx *xop, enum rtx_code code, int *plen)
{
machine_mode mode = GET_MODE (xop[0]);
gcc_assert (mode == HImode || mode == PSImode);
- *pcc = MINUS == code ? (int) CC_SET_CZN : (int) CC_SET_N;
-
avr_asm_len (PLUS == code
? "subi %A0,lo8(-(%2))" CR_TAB "sbci %B0,hi8(-(%2))"
: "subi %A0,lo8(%2)" CR_TAB "sbci %B0,hi8(%2)",
If PLEN == NULL output the instructions.
If PLEN != NULL set *PLEN to the length of the sequence in words.
- PCC is a pointer to store the instructions' effect on cc0.
- PCC may be NULL.
-
- PLEN and PCC default to NULL.
+ PLEN defaults to NULL.
OUT_LABEL defaults to TRUE. For a description, see AVR_OUT_PLUS_1.
Return "" */
const char *
-avr_out_plus (rtx insn, rtx *xop, int *plen, int *pcc, bool out_label)
+avr_out_plus (rtx insn, rtx *xop, int *plen, bool out_label)
{
- int cc_plus, cc_minus, cc_dummy;
int len_plus, len_minus;
rtx op[4];
rtx xpattern = INSN_P (insn) ? single_set (as_a <rtx_insn *> (insn)) : insn;
= (PLUS == code_sat || SS_PLUS == code_sat || US_PLUS == code_sat
? PLUS : MINUS);
- if (!pcc)
- pcc = &cc_dummy;
-
/* PLUS and MINUS don't saturate: Use modular wrap-around. */
if (PLUS == code_sat || MINUS == code_sat)
if (n_bytes <= 4 && REG_P (xop[2]))
{
- avr_out_plus_1 (xop, plen, code, pcc, code_sat, 0, out_label);
+ avr_out_plus_1 (insn, xop, plen, code, code_sat, 0, out_label);
return "";
}
&& !CONST_INT_P (xop[2])
&& !CONST_FIXED_P (xop[2]))
{
- return avr_out_plus_symbol (xop, code, plen, pcc);
+ return avr_out_plus_symbol (xop, code, plen);
}
op[0] = avr_to_int_mode (xop[0]);
/* Work out the shortest sequence. */
- avr_out_plus_1 (op, &len_minus, MINUS, &cc_minus, code_sat, sign, out_label);
- avr_out_plus_1 (op, &len_plus, PLUS, &cc_plus, code_sat, sign, out_label);
+ avr_out_plus_1 (insn, op, &len_minus, MINUS, code_sat, sign, out_label);
+ avr_out_plus_1 (insn, op, &len_plus, PLUS, code_sat, sign, out_label);
if (plen)
- {
- *plen = (len_minus <= len_plus) ? len_minus : len_plus;
- *pcc = (len_minus <= len_plus) ? cc_minus : cc_plus;
- }
+ *plen = (len_minus <= len_plus) ? len_minus : len_plus;
else if (len_minus <= len_plus)
- avr_out_plus_1 (op, NULL, MINUS, pcc, code_sat, sign, out_label);
+ avr_out_plus_1 (insn, op, NULL, MINUS, code_sat, sign, out_label);
else
- avr_out_plus_1 (op, NULL, PLUS, pcc, code_sat, sign, out_label);
+ avr_out_plus_1 (insn, op, NULL, PLUS, code_sat, sign, out_label);
return "";
}
op[0] = xop[0];
op[1] = xop[1];
op[2] = xadd;
- avr_out_plus (xpattern, op, plen_add, NULL, false /* Don't print "0:" */);
+ avr_out_plus (xpattern, op, plen_add, false /* Don't print "0:" */);
avr_asm_len ("rjmp 1f" CR_TAB
"0:", NULL, plen_add, 1);