blob: bcd079885a8351cdd07f0232040bd45bdc075f8e [file] [log] [blame]
carlla1b78a82014-02-08 02:19:12 +00001#include <stdio.h>
2#include <stdbool.h>
3#include <stdlib.h>
4#include <string.h>
5#include <signal.h>
6#include <setjmp.h>
7
8typedef enum exit_codes_ {
9
carllcae0cc22014-08-07 23:17:29 +000010#if defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
carlla1b78a82014-02-08 02:19:12 +000011 /* If the insn that got queried for: exists */
12 POWER_INSN_AVAILABLE = 0,
13 /* If the insn that got queried for: does not exist on this platform */
14 POWER_INSN_UNAVAILABLE = 1,
15 /* If the insn that got queried for: does not exist in the vocabulary of this program */
16 POWER_INSN_UNRECOGNIZED = 2,
17
18 /* Note: Please keep USAGE_ERROR last. */
19 USAGE_ERROR
20#else
21 /* When not on a POWER system: */
22 NOT_POWER_ARCH = 255,
23#endif
24
25} exit_code;
26
carllcae0cc22014-08-07 23:17:29 +000027#if defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
carlla1b78a82014-02-08 02:19:12 +000028/* Signal Handling support for unsupported instructions. */
29static jmp_buf unsup_insn_env;
30static void unsup_insn_handler(int signal_number)
31{
32 if (signal_number == SIGILL)
33 longjmp(unsup_insn_env, 1);
34 return;
35}
36static struct sigaction unsup_insn_action = (struct sigaction) {
37 .sa_handler = &unsup_insn_handler,
38};
39
40/* Instruction existence tests. */
41static bool dcbzl_available(void)
42{
43#define MAX_DCBZL_SZB (128) /* largest known effect of dcbzl */
44 char *test_block = NULL;
45 register char *rb asm ("r14");
46 int err;
47 bool dcbzl_exists = false;
48
49 err = posix_memalign ((void **)&test_block, MAX_DCBZL_SZB, 4 * MAX_DCBZL_SZB);
50 if (err) {
51 fprintf(stderr, "posix_memalign() failed (err = %d [%s])\n", err, strerror(err));
52 return err;
53 }
54
55 rb = test_block;
56
57 if (setjmp(unsup_insn_env) != 0)
58 dcbzl_exists = false;
59 else {
60 sigaction(SIGILL, &unsup_insn_action, NULL);
61 asm volatile ("dcbzl 0, %[RB]" : : [RB] "r" (rb));
62 dcbzl_exists = true;
63 }
64
65 free(test_block);
66 return dcbzl_exists;
67}
68#endif
69
70/* main() */
71int main(int argc, char **argv)
72{
73 exit_code status;
74
carllcae0cc22014-08-07 23:17:29 +000075#if defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
carlla1b78a82014-02-08 02:19:12 +000076 char *insn;
77 if (argc != 2) {
78 fprintf(stderr, "usage: power_insn_available <insn>\n" );
79 exit(USAGE_ERROR);
80 }
81
82 insn = argv[1];
83 if (strcmp (insn, "dcbzl") == 0)
84 status = ((dcbzl_available ()) ? POWER_INSN_AVAILABLE : POWER_INSN_UNAVAILABLE);
85 else
86 /* power_insn_available has not been taught anything about this insn yet. */
87 status = POWER_INSN_UNRECOGNIZED;
88#else
89 status = NOT_POWER_ARCH;
90#endif
91 return status;
92}