Hi.

On the i370 port of GCC 3.2.3 (which
can be run in 31-bit mode on z/OS),
we have the below code to do a
builtin_memcpy().

But as per description in i370.md, it
is restricted to moving LESS than
16 MiB.

If we have 16 MiB or more, I am happy
to just call the memcpy() function.

I have tried various incantations to try
to stop this code from being used when
the block size is greater than or equal
to 16 MiB, but I have not been successful.

I was successful with putting in this
code change:

C:\devel\pdos\pdpclib>cvs diff -r 1.19 -r 1.20 string.h
Index: string.h
===================================================================
RCS file: /cvsroot/pdos/pdos/pdpclib/string.h,v
retrieving revision 1.19
retrieving revision 1.20
diff -r1.19 -r1.20
89,90c89,98
< #define memcpy(a,b,c) (__builtin_memcpy((a),(b),(c)))
< #define memcmp(s1,s2,n) (__builtin_memcmp((s1),(s2),(n)))
---
#define memcpy(s1,s2,n) ( \
     (n >= 0x01000000) ? \
     ((memcpy)((s1),(s2),(n))) : \
     (__builtin_memcpy((s1),(s2),(n))) \
    )
#define memcmp(s1,s2,n) ( \
     (n >= 0x01000000) ? \
     ((memcmp)((s1),(s2),(n))) : \
     (__builtin_memcmp((s1),(s2),(n))) \
    )

C:\devel\pdos\pdpclib>


But I believe that is considered to be
technically incorrect, because the "n"
argument is evaluated more than once.

Am I correct in believing that the code
in builtins.c shouldn't be changed,
because that is correct for all platforms,
and that the required change needs
to go in i370.md or some other
i370-specific file?

If so, can anyone tell me how to solve
this problem?

Note that compare has an identical
issue - CLCL is like MVCL.

Thanks. Paul.





/* Expand a call to the memcpy builtin, with arguments in ARGLIST.
  Return 0 if we failed, the caller should emit a normal call, otherwise
  try to get the result in TARGET, if convenient (and in mode MODE if
  that's convenient).  */

static rtx
expand_builtin_memcpy (arglist, target, mode)
    tree arglist;
    rtx target;
    enum machine_mode mode;
{





;
; 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));

 if (GET_CODE (operands[2]) == CONST_INT
     && (unsigned) 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;
}")

; Move a block that is less than or equal to 256 bytes in length.

(define_insn ""
 [(set (match_operand:BLK 0 "s_operand" "=S")
   (match_operand:BLK 1 "s_operand" "S"))
  (use (match_operand 2 "immediate_operand" "i"))]
 "((unsigned) INTVAL (operands[2]) <= 256)"
 "*
{
 check_label_emit ();
 mvs_check_page (0, 6, 0);
 return \"MVC    %O0(%c2,%R0),%1\";
}"
  [(set_attr "length" "6")]
)

; Move a block that is larger than 256 bytes in length.
; [(set (mem:BLK (subreg:SI (match_operand:DI 0 "register_operand" "+d") 0)) ; (mem:BLK (subreg:SI (match_operand:DI 1 "register_operand" "+d") 0)))

(define_insn "movstrsi_1"
 [(set (mem:BLK (match_operand:DI 0 "register_operand" "+d") )
       (mem:BLK (match_operand:DI 1 "register_operand" "+d") ))
  (use (match_dup 0))
  (use (match_dup 1))
  (clobber (match_dup 0))
  (clobber (match_dup 1))]
 ""
 "*
{
 check_label_emit ();
 mvs_check_page (0, 2, 0);
 return \"MVCL    %0,%1\";
}"
  [(set_attr "length" "2")]
)



Reply via email to