summaryrefslogtreecommitdiff
path: root/gcc/testsuite/gcc.target/i386/sse-os-support.h
blob: a2b4e2d3c7e2bc879a9bbe41f7258ef828cb0d01 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#if defined(__sun__) && defined(__svr4__)
/* Make sure sigaction() is declared even with -std=c99.  */
#define __EXTENSIONS__
#include <signal.h>
#include <ucontext.h>

static volatile sig_atomic_t sigill_caught;

static void
sigill_hdlr (int sig __attribute((unused)),
	     siginfo_t *sip __attribute__((unused)),
	     ucontext_t *ucp)
{
  sigill_caught = 1;
  /* Set PC to the instruction after the faulting one to skip over it,
     otherwise we enter an infinite loop.  */
  ucp->uc_mcontext.gregs[EIP] += 4;
  setcontext (ucp);
}
#endif

/* Check if the OS supports executing SSE instructions.  This function is
   only used in sse-check.h, sse2-check.h, and sse3-check.h so far since
   Solaris 8 and 9 won't run on newer CPUs anyway.  */

static int
sse_os_support (void)
{
#if defined(__sun__) && defined(__svr4__)
  /* Solaris 2 before Solaris 9 4/04 cannot execute SSE instructions
     even if the CPU supports them.  Programs receive SIGILL instead, so
     check for that at runtime.  */

  struct sigaction act, oact;

  act.sa_handler = sigill_hdlr;
  sigemptyset (&act.sa_mask);
  /* Need to set SA_SIGINFO so a ucontext_t * is passed to the handler.  */
  act.sa_flags = SA_SIGINFO;
  sigaction (SIGILL, &act, &oact);

  /* We need a single SSE instruction here so the handler can safely skip
     over it.  */
  __asm__ volatile ("movss %xmm2,%xmm1");

  sigaction (SIGILL, &oact, NULL);

  if (sigill_caught)
    exit (0);
  else
    return 1;
#else
  return 1;
#endif /* __sun__ && __svr4__ */
}