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