File: power_insn_available.c

package info (click to toggle)
valgrind 1:3.10.0-4~bpo7+1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy-backports
  • size: 97,940 kB
  • sloc: ansic: 589,429; xml: 21,096; exp: 8,751; cpp: 7,366; asm: 6,526; perl: 5,656; sh: 5,334; makefile: 4,946; haskell: 195
file content (92 lines) | stat: -rw-r--r-- 2,379 bytes parent folder | download | duplicates (3)
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <setjmp.h>

typedef enum exit_codes_ {

#if defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
  /* If the insn that got queried for: exists */
  POWER_INSN_AVAILABLE    = 0,
  /* If the insn that got queried for: does not exist on this platform */
  POWER_INSN_UNAVAILABLE  = 1,
  /* If the insn that got queried for: does not exist in the vocabulary of this program */
  POWER_INSN_UNRECOGNIZED = 2,

  /* Note: Please keep USAGE_ERROR last. */
  USAGE_ERROR
#else
  /* When not on a POWER system: */
  NOT_POWER_ARCH          = 255,
#endif

} exit_code;

#if defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
/* Signal Handling support for unsupported instructions. */
static jmp_buf unsup_insn_env;
static void unsup_insn_handler(int signal_number)
{
  if (signal_number == SIGILL)
    longjmp(unsup_insn_env, 1);
  return;
}
static struct sigaction unsup_insn_action = (struct sigaction) {
  .sa_handler = &unsup_insn_handler,
};

/* Instruction existence tests. */
static bool dcbzl_available(void)
{
#define MAX_DCBZL_SZB (128) /* largest known effect of dcbzl */
  char *test_block = NULL;
  register char *rb asm ("r14");
  int err;
  bool dcbzl_exists = false;

  err = posix_memalign ((void **)&test_block, MAX_DCBZL_SZB, 4 * MAX_DCBZL_SZB);
  if (err) {
    fprintf(stderr, "posix_memalign() failed (err = %d [%s])\n", err, strerror(err));
    return err;
  }

  rb = test_block;

  if (setjmp(unsup_insn_env) != 0)
    dcbzl_exists = false;
  else {
    sigaction(SIGILL, &unsup_insn_action, NULL);
    asm volatile ("dcbzl 0, %[RB]" : : [RB] "r" (rb));
    dcbzl_exists = true;
  }

  free(test_block);
  return dcbzl_exists;
}
#endif

/* main() */
int main(int argc, char **argv)
{
  exit_code status;

#if defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
  char *insn;
  if (argc != 2) {
    fprintf(stderr, "usage: power_insn_available <insn>\n" );
    exit(USAGE_ERROR);
  }

  insn = argv[1];
  if (strcmp (insn, "dcbzl") == 0)
    status = ((dcbzl_available ()) ? POWER_INSN_AVAILABLE : POWER_INSN_UNAVAILABLE);
  else
    /* power_insn_available has not been taught anything about this insn yet. */
    status = POWER_INSN_UNRECOGNIZED;
#else
    status = NOT_POWER_ARCH;
#endif
  return status;
}