* config/pdp11/pdp11-protos.h (pdp11_shift_length): New function.
* config/pdp11/pdp11.c (pdp11_shift_length): New function.
* config/pdp11/pdp11.h (ADJUST_INSN_LENGTH): Remove.
* config/pdp11/pdp11.md: Correct "length" attribute calculation
for shift insn patterns.
From-SVN: r262227
+2018-06-28 Paul Koning <ni1d@arrl.net>
+
+ * config/pdp11/pdp11-protos.h (pdp11_shift_length): New function.
+ * config/pdp11/pdp11.c (pdp11_shift_length): New function.
+ * config/pdp11/pdp11.h (ADJUST_INSN_LENGTH): Remove.
+ * config/pdp11/pdp11.md: Correct "length" attribute calculation
+ for shift insn patterns.
+
2018-06-28 David Malcolm <dmalcolm@redhat.com>
* cgraph.c (cgraph_node::get_body): Replace assignments to
extern bool pdp11_expand_shift (rtx *, rtx (*) (rtx, rtx, rtx),
rtx (*) (rtx, rtx, rtx));
extern const char * pdp11_assemble_shift (rtx *, machine_mode, int);
+extern int pdp11_shift_length (rtx *, machine_mode, int, bool);
extern bool pdp11_small_shift (int);
#endif /* RTX_CODE */
return "";
}
+/* Figure out the length of the instructions that will be produced for
+ the given operands by pdp11_assemble_shift above. */
+int
+pdp11_shift_length (rtx *operands, machine_mode m, int code, bool simple_operand_p)
+{
+ int shift_size;
+
+ /* Shift by 1 is 2 bytes if simple operand, 4 bytes if 2-word addressing mode. */
+ shift_size = simple_operand_p ? 2 : 4;
+
+ /* In SImode, two shifts are needed per data item. */
+ if (m == E_SImode)
+ shift_size *= 2;
+
+ /* If shifting by a small constant, the loop is unrolled by the
+ shift count. Otherwise, account for the size of the decrement
+ and branch. */
+ if (CONSTANT_P (operands[2]) && pdp11_small_shift (INTVAL (operands[2])))
+ shift_size *= INTVAL (operands[2]);
+ else
+ shift_size += 4;
+
+ /* Logical right shift takes one more instruction (CLC). */
+ if (code == LSHIFTRT)
+ shift_size += 2;
+
+ return shift_size;
+}
+
/* Worker function for TARGET_TRAMPOLINE_INIT.
trampoline - how should i do it in separate i+d ?
/* Define this if move instructions will actually fail to work
when given unaligned data. */
#define STRICT_ALIGNMENT 1
-
-/* Adjust the length of shifts by small constant amounts. The base
- value (in "length" on input) is the length of a shift by one, not
- including the CLC in logical shifts. */
-#define ADJUST_INSN_LENGTH(insn, length) \
- if ((GET_CODE (insn) == ASHIFT || \
- GET_CODE (insn) == ASHIFTRT || \
- GET_CODE (insn) == LSHIFTRT) && \
- GET_CODE (XEXP (insn, 2)) == CONST_INT && \
- pdp11_small_shift (XINT (insn, 2))) \
- { \
- if (GET_CODE (insn) == LSHIFTRT) \
- length = (length * XINT (insn, 2)) + 2; \
- else \
- length *= XINT (insn, 2); \
- }
\f
/* Standard register usage. */
;; used to reduce the amount of very similar code.
;;
;; First the insns used for small constant shifts.
-;
-;; The "length" attribute values are modified by the ADJUST_INSN_LENGTH
-;; macro for the small constant shift case (first two alternatives).
-;; For those, the value coded in the length attribute is the cost of just
-;; the shift for a single shift.
(define_insn "<code><mode>_sc"
[(set (match_operand:QHSint 0 "nonimmediate_operand" "=rD,Q")
(SHF:QHSint (match_operand:QHSint 1 "general_operand" "0,0")
(match_operand:HI 2 "expand_shift_operand" "O,O")))]
""
"* return pdp11_assemble_shift (operands, <QHSint:mname>, <CODE>);"
- [(set_attr "length" "2,4")])
+ [(set (attr "length")
+ (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>,
+ <CODE>, which_alternative == 0)"))])
;; Next, shifts that are done as a loop on base (11/10 class) machines.
;; This applies to shift counts too large to unroll, or variable shift
(clobber (match_dup 2))]
""
"* return pdp11_assemble_shift (operands, <QHSint:mname>, <CODE>);"
- [(set_attr "length" "2,4")])
+ [(set (attr "length")
+ (symbol_ref "pdp11_shift_length (operands, <QHSint:mname>,
+ <CODE>, which_alternative == 0)"))])
;; Next the insns that use the extended instructions ash and ashc.
;; Note that these are just left shifts, and HI/SI only. (Right shifts