amd64check.c revision 1.1.1.3
1/* AMD64 calling conventions checking.
2
3Copyright 2000, 2001, 2004, 2007 Free Software Foundation, Inc.
4
5This file is part of the GNU MP Library test suite.
6
7The GNU MP Library test suite is free software; you can redistribute it
8and/or modify it under the terms of the GNU General Public License as
9published by the Free Software Foundation; either version 3 of the License,
10or (at your option) any later version.
11
12The GNU MP Library test suite is distributed in the hope that it will be
13useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
15Public License for more details.
16
17You should have received a copy of the GNU General Public License along with
18the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
19
20#include <stdio.h>
21#include "gmp.h"
22#include "gmp-impl.h"
23#include "tests.h"
24
25
26/* Vector if constants and register values.  We use one vector to allow access
27   via a base pointer, very beneficial for the PIC-enabled amd64call.asm.  */
28mp_limb_t calling_conventions_values[23] =
29{
30  CNST_LIMB(0x1234567887654321),	/* want_rbx */
31  CNST_LIMB(0x89ABCDEFFEDCBA98),	/* want_rbp */
32  CNST_LIMB(0xDEADBEEFBADECAFE),	/* want_r12 */
33  CNST_LIMB(0xFFEEDDCCBBAA9988),	/* want_r13 */
34  CNST_LIMB(0x0011223344556677),	/* want_r14 */
35  CNST_LIMB(0x1234432156788765),	/* want_r15 */
36
37  CNST_LIMB(0xFEEDABBACAAFBEED),	/* JUNK_RAX */
38  CNST_LIMB(0xAB78DE89FF5125BB),	/* JUNK_R10 */
39  CNST_LIMB(0x1238901890189031)		/* JUNK_R11 */
40
41  /* rest of array used for dynamic values.  */
42};
43
44/* Index starts for various regions in above vector.  */
45#define WANT	0
46#define JUNK	6
47#define SAVE	9
48#define RETADDR	15
49#define VAL	16
50#define RFLAGS	22
51
52/* values to check */
53#ifdef __cplusplus
54extern "C" {
55#endif
56struct {
57  int  control;
58  int  status;
59  int  tag;
60  int  other[4];
61} calling_conventions_fenv;
62#ifdef __cplusplus
63}
64#endif
65
66
67const char *regname[6] = {"rbx", "rbp", "r12", "r13", "r14", "r15"};
68
69#define DIR_BIT(rflags)   (((rflags) & (1<<10)) != 0)
70
71
72/* Return 1 if ok, 0 if not */
73
74int
75calling_conventions_check (void)
76{
77  const char  *header = "Violated calling conventions:\n";
78  int  ret = 1;
79  int i;
80
81#define CHECK(callreg, regstr, value)			\
82  if (callreg != value)					\
83    {							\
84      printf ("%s   %s	got 0x%016lX want 0x%016lX\n",	\
85	      header, regstr, callreg, value);		\
86      header = "";					\
87      ret = 0;						\
88    }
89
90  for (i = 0; i < 6; i++)
91    {
92      CHECK (calling_conventions_values[VAL+i], regname[i], calling_conventions_values[WANT+i]);
93    }
94
95  if (DIR_BIT (calling_conventions_values[RFLAGS]) != 0)
96    {
97      printf ("%s   rflags dir bit  got %d want 0\n",
98	      header, DIR_BIT (calling_conventions_values[RFLAGS]));
99      header = "";
100      ret = 0;
101    }
102
103  if ((calling_conventions_fenv.tag & 0xFFFF) != 0xFFFF)
104    {
105      printf ("%s   fpu tags  got 0x%X want 0xFFFF\n",
106	      header, calling_conventions_fenv.tag & 0xFFFF);
107      header = "";
108      ret = 0;
109    }
110
111  return ret;
112}
113