mirror of
https://github.com/ioacademy-jikim/debugging
synced 2025-06-08 00:16:11 +00:00
93 lines
2.3 KiB
C
93 lines
2.3 KiB
C
#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;
|
|
}
|