Blame sysdeps/aarch64/tst-vpcs.c

Packit Service 399ab1
/* Test that variant PCS calls don't clobber registers with lazy binding.
Packit Service 399ab1
   Copyright (C) 2020 Free Software Foundation, Inc.
Packit Service 399ab1
   This file is part of the GNU C Library.
Packit Service 399ab1
Packit Service 399ab1
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 399ab1
   modify it under the terms of the GNU Lesser General Public
Packit Service 399ab1
   License as published by the Free Software Foundation; either
Packit Service 399ab1
   version 2.1 of the License, or (at your option) any later version.
Packit Service 399ab1
Packit Service 399ab1
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 399ab1
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 399ab1
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 399ab1
   Lesser General Public License for more details.
Packit Service 399ab1
Packit Service 399ab1
   You should have received a copy of the GNU Lesser General Public
Packit Service 399ab1
   License along with the GNU C Library; if not, see
Packit Service 399ab1
   <https://www.gnu.org/licenses/>.  */
Packit Service 399ab1
Packit Service 399ab1
#include <stdint.h>
Packit Service 399ab1
#include <stdio.h>
Packit Service 399ab1
#include <support/check.h>
Packit Service 399ab1
Packit Service 399ab1
struct regs
Packit Service 399ab1
{
Packit Service 399ab1
  uint64_t x[32];
Packit Service 399ab1
  union {
Packit Service 399ab1
    long double q[32];
Packit Service 399ab1
    uint64_t u[64];
Packit Service 399ab1
  } v;
Packit Service 399ab1
};
Packit Service 399ab1
Packit Service 399ab1
/* Gives the registers in the caller and callee around a variant PCS call.
Packit Service 399ab1
   Most registers are initialized from BEFORE in the caller so they can
Packit Service 399ab1
   have values that likely show clobbers.  Register state extensions such
Packit Service 399ab1
   as SVE is not covered here, only the base registers.  */
Packit Service 399ab1
void vpcs_call_regs (struct regs *after, struct regs *before);
Packit Service 399ab1
Packit Service 399ab1
static int
Packit Service 399ab1
do_test (void)
Packit Service 399ab1
{
Packit Service 399ab1
  struct regs before, after;
Packit Service 399ab1
  int err = 0;
Packit Service 399ab1
Packit Service 399ab1
  unsigned char *p = (unsigned char *)&before;
Packit Service 399ab1
  for (int i = 0; i < sizeof before; i++)
Packit Service 399ab1
    p[i] = i & 0xff;
Packit Service 399ab1
Packit Service 399ab1
  vpcs_call_regs (&after, &before);
Packit Service 399ab1
Packit Service 399ab1
  for (int i = 0; i < 32; i++)
Packit Service 399ab1
    if (before.x[i] != after.x[i])
Packit Service 399ab1
      {
Packit Service 399ab1
	if (i == 16 || i == 17)
Packit Service 399ab1
	  /* Variant PCS allows clobbering x16 and x17.  */
Packit Service 399ab1
	  continue;
Packit Service 399ab1
	err++;
Packit Service 399ab1
	printf ("x%d: before: 0x%016llx after: 0x%016llx\n",
Packit Service 399ab1
	  i,
Packit Service 399ab1
	  (unsigned long long)before.x[i],
Packit Service 399ab1
	  (unsigned long long)after.x[i]);
Packit Service 399ab1
      }
Packit Service 399ab1
  for (int i = 0; i < 64; i++)
Packit Service 399ab1
    if (before.v.u[i] != after.v.u[i])
Packit Service 399ab1
      {
Packit Service 399ab1
	err++;
Packit Service 399ab1
	printf ("v%d: before: 0x%016llx %016llx after: 0x%016llx %016llx\n",
Packit Service 399ab1
	  i/2,
Packit Service 399ab1
	  (unsigned long long)before.v.u[2*(i/2)+1],
Packit Service 399ab1
	  (unsigned long long)before.v.u[2*(i/2)],
Packit Service 399ab1
	  (unsigned long long)after.v.u[2*(i/2)+1],
Packit Service 399ab1
	  (unsigned long long)after.v.u[2*(i/2)]);
Packit Service 399ab1
      }
Packit Service 399ab1
  if (err)
Packit Service 399ab1
    FAIL_EXIT1 ("The variant PCS call clobbered %d registers.\n", err);
Packit Service 399ab1
  return 0;
Packit Service 399ab1
}
Packit Service 399ab1
Packit Service 399ab1
#include <support/test-driver.c>