Ah, yes.  The problem is that reload assumes any valid address
can be loaded into a register with a single instruction, and
it will thus simply generate such instructions unconditionally
-- and if the target then doesn't actually provide such a pattern,
it will fail with "unrecognizable insn".

Hi Ulrich. Thanks for your reply.

This approach seems to be quite complicated. What do you think
about the option of NOT adding this (which triggers off errors I
hadn't seen before):

#define EXTRA_MEMORY_CONSTRAINT(C, STR) \
  ((C) == 'S')

and instead making a change similar to what I have already put in
under "hack" below? Is that legitimate?

;
; movstrsi instruction pattern(s).
; block must be less than 16M (24 bits) in length

(define_expand "movstrsi"
 [(set (match_operand:BLK 0 "general_operand" "")
       (match_operand:BLK 1 "general_operand" ""))
  (use (match_operand:SI  2 "general_operand" ""))
  (match_operand 3 "" "")]
  ""
  "
{
 rtx op0, op1;

 op0 = XEXP (operands[0], 0);
 if (GET_CODE (op0) == REG
     || (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 0)) == REG
         && GET_CODE (XEXP (op0, 1)) == CONST_INT
         && (unsigned) INTVAL (XEXP (op0, 1)) < 4096))
   op0 = operands[0];
 else
op0 = replace_equiv_address (operands[0], copy_to_mode_reg (SImode, op0));

 op1 = XEXP (operands[1], 0);
 if (GET_CODE (op1) == REG
     || (GET_CODE (op1) == PLUS && GET_CODE (XEXP (op1, 0)) == REG
         && GET_CODE (XEXP (op1, 1)) == CONST_INT
         && (unsigned) INTVAL (XEXP (op1, 1)) < 4096))
   op1 = operands[1];
 else
op1 = replace_equiv_address (operands[1], copy_to_mode_reg (SImode, op1));

 /* first line is a hack - if target address involves two registers,
    we can't use an MVC, even if the length to move is less than 256,
    because MVC takes an S parameter. I'm unsure of the best way to
    distinguish a two-register target. */
 if (!((GET_CODE(op0) == MEM) && REG_P(XEXP(op0,0))) &&
     GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 256)
   emit_insn (gen_rtx_PARALLEL (VOIDmode,
                       gen_rtvec (2,
                                  gen_rtx_SET (VOIDmode, op0, op1),
                                  gen_rtx_USE (VOIDmode, operands[2]))));

 else
   {
       /* implementation provided by  Richard Henderson <r...@cygnus.com> */
       rtx reg1 = gen_reg_rtx (DImode);
       rtx reg2 = gen_reg_rtx (DImode);
       rtx mem1 = operands[0];
       rtx mem2 = operands[1];
       rtx len = operands[2];
       if (!CONSTANT_P (len))
         len = force_reg (SImode, len);

       /* Load up the address+length pairs.  */
       emit_insn (gen_rtx_CLOBBER (VOIDmode, reg1));
       emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 0),
                       force_operand (XEXP (mem1, 0), NULL_RTX));
emit_move_insn (gen_rtx_SUBREG (SImode, reg1, GET_MODE_SIZE (SImode)), len);

       emit_insn (gen_rtx_CLOBBER (VOIDmode, reg2));
       emit_move_insn (gen_rtx_SUBREG (SImode, reg2, 0),
                       force_operand (XEXP (mem2, 0), NULL_RTX));
emit_move_insn (gen_rtx_SUBREG (SImode, reg2, GET_MODE_SIZE (SImode)), len);

       /* Copy! */
       emit_insn (gen_movstrsi_1 (reg1, reg2));
   }
 DONE;
}")


Thanks.  Paul.

Reply via email to