amd64check.c revision 1.1.1.1
11828Serikj/* AMD64 calling conventions checking.
21828Serikj
31828SerikjCopyright 2000, 2001, 2004, 2007 Free Software Foundation, Inc.
41828Serikj
51828SerikjThis file is part of the GNU MP Library.
61828Serikj
71828SerikjThe GNU MP Library is free software; you can redistribute it and/or modify
81828Serikjit under the terms of the GNU Lesser General Public License as published by
91828Serikjthe Free Software Foundation; either version 3 of the License, or (at your
101828Serikjoption) any later version.
111828Serikj
121828SerikjThe GNU MP Library is distributed in the hope that it will be useful, but
131828SerikjWITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
141828Serikjor FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
151828SerikjLicense for more details.
161839Serikj
171828SerikjYou should have received a copy of the GNU Lesser General Public License
181828Serikjalong with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
191828Serikj
201828Serikj#include <stdio.h>
211828Serikj#include "gmp.h"
221828Serikj#include "gmp-impl.h"
231828Serikj#include "tests.h"
241828Serikj
251828Serikj
261828Serikj/* Vector if constants and register values.  We use one vector to allow access
271828Serikj   via a base pointer, very beneficial for the PIC-enabled amd64call.asm.  */
281828Serikjmp_limb_t calling_conventions_values[23] =
291828Serikj{
301828Serikj  CNST_LIMB(0x1234567887654321),	/* want_rbx */
311828Serikj  CNST_LIMB(0x89ABCDEFFEDCBA98),	/* want_rbp */
321828Serikj  CNST_LIMB(0xDEADBEEFBADECAFE),	/* want_r12 */
331828Serikj  CNST_LIMB(0xFFEEDDCCBBAA9988),	/* want_r13 */
341828Serikj  CNST_LIMB(0x0011223344556677),	/* want_r14 */
351828Serikj  CNST_LIMB(0x1234432156788765),	/* want_r15 */
361828Serikj
371828Serikj  CNST_LIMB(0xFEEDABBACAAFBEED),	/* JUNK_RAX */
381828Serikj  CNST_LIMB(0xAB78DE89FF5125BB),	/* JUNK_R10 */
391828Serikj  CNST_LIMB(0x1238901890189031)		/* JUNK_R11 */
401828Serikj
411828Serikj  /* rest of array used for dynamic values.  */
421828Serikj};
431828Serikj
441828Serikj/* Index starts for various regions in above vector.  */
451828Serikj#define WANT	0
461828Serikj#define JUNK	6
471828Serikj#define SAVE	9
481828Serikj#define RETADDR	15
491828Serikj#define VAL	16
501828Serikj#define RFLAGS	22
511828Serikj
521828Serikj/* values to check */
531828Serikjstruct {
541828Serikj  int  control;
551828Serikj  int  status;
561828Serikj  int  tag;
571828Serikj  int  other[4];
581828Serikj} calling_conventions_fenv;
591828Serikj
601828Serikj
611828Serikjchar *regname[6] = {"rbx", "rbp", "r12", "r13", "r14", "r15"};
621828Serikj
631828Serikj#define DIR_BIT(rflags)   (((rflags) & (1<<10)) != 0)
641828Serikj
651828Serikj
661828Serikj/* Return 1 if ok, 0 if not */
671828Serikj
681828Serikjint
691828Serikjcalling_conventions_check (void)
701828Serikj{
711828Serikj  const char  *header = "Violated calling conventions:\n";
721828Serikj  int  ret = 1;
731828Serikj  int i;
741828Serikj
751828Serikj#define CHECK(callreg, regstr, value)			\
761828Serikj  if (callreg != value)					\
771828Serikj    {							\
781828Serikj      printf ("%s   %s	got 0x%016lX want 0x%016lX\n",	\
791828Serikj	      header, regstr, callreg, value);		\
801828Serikj      header = "";					\
811828Serikj      ret = 0;						\
821828Serikj    }
831828Serikj
841828Serikj  for (i = 0; i < 6; i++)
851828Serikj    {
861828Serikj      CHECK (calling_conventions_values[VAL+i], regname[i], calling_conventions_values[WANT+i]);
871828Serikj    }
881828Serikj
891828Serikj  if (DIR_BIT (calling_conventions_values[RFLAGS]) != 0)
901828Serikj    {
911828Serikj      printf ("%s   rflags dir bit  got %d want 0\n",
921828Serikj	      header, DIR_BIT (calling_conventions_values[RFLAGS]));
931828Serikj      header = "";
941828Serikj      ret = 0;
951828Serikj    }
961828Serikj
971828Serikj  if ((calling_conventions_fenv.tag & 0xFFFF) != 0xFFFF)
981828Serikj    {
991828Serikj      printf ("%s   fpu tags  got 0x%X want 0xFFFF\n",
1001828Serikj	      header, calling_conventions_fenv.tag & 0xFFFF);
1011828Serikj      header = "";
1021828Serikj      ret = 0;
1031828Serikj    }
1041828Serikj
1051828Serikj  return ret;
1061828Serikj}
1071828Serikj