122 const unsigned char *p = code;
123 const unsigned char *limit = code + 15;
124 bool operand16 =
false;
128 unsigned char c = *p;
141 if (c == 0xF0 || c == 0xF2 || c == 0xF3 || c == 0x26 || c == 0x2E ||
142 c == 0x36 || c == 0x3E || c == 0x64 || c == 0x65) {
146 if (long_mode && c >= 0x40 && c <= 0x4F) {
147 rex_w = (c & 0x08) != 0;
153 if (addr16 || p >= limit) {
156 unsigned char opcode = *p++;
157 if (opcode != 0xF6 && opcode != 0xF7) {
163 unsigned char modrm = *p++;
164 unsigned mod = modrm >> 6;
165 unsigned reg = (modrm >> 3) & 7u;
166 unsigned rm = modrm & 7u;
167 if (reg != 6u && reg != 7u) {
171 bool have_sib = rm == 4u;
172 unsigned sib_base = 0;
177 sib_base =
static_cast<unsigned>(*p++ & 7u);
179 if ((mod == 0u && rm == 5u) || (have_sib && mod == 0u && sib_base == 5u) ||
185 }
else if (mod == 1u) {
192 int length =
static_cast<int>(p - code);
193 if (length < 2 || length > 15) {
197 if (opcode == 0xF6) {
201 }
else if (operand16) {
217 if (scp ==
nullptr) {
220 auto *ctx =
static_cast<ucontext_t *
>(scp);
221#if defined(__linux__) && defined(__x86_64__)
222 regs.
ip =
reinterpret_cast<uintptr_t *
>(&ctx->uc_mcontext.gregs[REG_RIP]);
223 regs.
ax =
reinterpret_cast<uintptr_t *
>(&ctx->uc_mcontext.gregs[REG_RAX]);
224 regs.
dx =
reinterpret_cast<uintptr_t *
>(&ctx->uc_mcontext.gregs[REG_RDX]);
225#elif defined(__linux__) && defined(__i386__)
226 regs.
ip =
reinterpret_cast<uintptr_t *
>(&ctx->uc_mcontext.gregs[REG_EIP]);
227 regs.
ax =
reinterpret_cast<uintptr_t *
>(&ctx->uc_mcontext.gregs[REG_EAX]);
228 regs.
dx =
reinterpret_cast<uintptr_t *
>(&ctx->uc_mcontext.gregs[REG_EDX]);
229#elif defined(__APPLE__) && defined(__x86_64__)
230 if (ctx->uc_mcontext !=
nullptr) {
231 regs.
ip =
reinterpret_cast<uintptr_t *
>(&ctx->uc_mcontext->__ss.__rip);
232 regs.
ax =
reinterpret_cast<uintptr_t *
>(&ctx->uc_mcontext->__ss.__rax);
233 regs.
dx =
reinterpret_cast<uintptr_t *
>(&ctx->uc_mcontext->__ss.__rdx);
235#elif defined(__APPLE__) && defined(__i386__)
236 if (ctx->uc_mcontext !=
nullptr) {
237 regs.
ip =
reinterpret_cast<uintptr_t *
>(&ctx->uc_mcontext->__ss.__eip);
238 regs.
ax =
reinterpret_cast<uintptr_t *
>(&ctx->uc_mcontext->__ss.__eax);
239 regs.
dx =
reinterpret_cast<uintptr_t *
>(&ctx->uc_mcontext->__ss.__edx);
302 static volatile sig_atomic_t reported_div = 0;
303 static volatile sig_atomic_t reported_inv = 0;
304 static volatile sig_atomic_t reported_ovf = 0;
305 static volatile sig_atomic_t reported_unk = 0;
306 static volatile sig_atomic_t reported_int = 0;
308 static constexpr char prefix[] =
"FPE (continuing, masking further): ";
309 static constexpr char msg_div[] =
"division by zero\n";
310 static constexpr char msg_inv[] =
"invalid operation\n";
311 static constexpr char msg_ovf[] =
"overflow\n";
312 static constexpr char msg_unk[] =
"unknown\n";
317 volatile sig_atomic_t *reported = &reported_unk;
318 const char *msg = msg_unk;
319 size_t msg_len =
sizeof(msg_unk) - 1;
322 if (sip->si_code == FPE_INTDIV || sip->si_code == FPE_INTOVF) {
323 if (reported_int == 0) {
325 static constexpr char iprefix[] =
"FPE (continuing, skipping divide): ";
326 static constexpr char msg_idiv[] =
"integer divide\n";
327 static constexpr char msg_iovf[] =
"integer overflow\n";
328 const char *imsg = sip->si_code == FPE_INTDIV ? msg_idiv : msg_iovf;
329 size_t imsg_len =
sizeof(msg_iovf) - 1;
330 if (sip->si_code == FPE_INTDIV) {
331 imsg_len =
sizeof(msg_idiv) - 1;
333 write(STDERR_FILENO, iprefix,
sizeof(iprefix) - 1);
334 write(STDERR_FILENO, imsg, imsg_len);
338 static constexpr char stuck[] =
339 "FPE integer divide: could not skip faulting instruction\n";
340 write(STDERR_FILENO, stuck,
sizeof(stuck) - 1);
346 switch (sip->si_code) {
348 reported = &reported_div;
350 msg_len =
sizeof(msg_div) - 1;
354 reported = &reported_inv;
356 msg_len =
sizeof(msg_inv) - 1;
360 reported = &reported_ovf;
362 msg_len =
sizeof(msg_ovf) - 1;
369 if (*reported == 0) {
371 write(STDERR_FILENO, prefix,
sizeof(prefix) - 1);
372 write(STDERR_FILENO, msg, msg_len);
377#if defined(__linux__) && (defined(__x86_64__) || defined(__i386__))
378 ucontext_t *ctx =
static_cast<ucontext_t *
>(scp);
379 if (ctx->uc_mcontext.fpregs) {
383 ctx->uc_mcontext.fpregs->swd &= ~0x3Fu;
384 ctx->uc_mcontext.fpregs->mxcsr &= ~0x3Fu;
385 ctx->uc_mcontext.fpregs->mxcsr |= mxcsr_mask_bits;
389 ctx->uc_mcontext.fpregs->cwd |= (1u << 2);
392 ctx->uc_mcontext.fpregs->cwd |= (1u << 0);
395 ctx->uc_mcontext.fpregs->cwd |= (1u << 3);
398#elif defined(__linux__) && defined(__aarch64__)
402 constexpr uint32_t kFpsimdMagic = 0x46508001u;
403 constexpr unsigned kFpcrIoe = 1u << 8;
404 constexpr unsigned kFpcrDze = 1u << 9;
405 constexpr unsigned kFpcrOfe = 1u << 10;
406 unsigned fpcr_clear = kFpcrIoe | kFpcrDze | kFpcrOfe;
408 fpcr_clear = kFpcrDze;
410 fpcr_clear = kFpcrIoe;
412 fpcr_clear = kFpcrOfe;
414 auto *ctx =
static_cast<ucontext_t *
>(scp);
416 reinterpret_cast<unsigned char *
>(ctx->uc_mcontext.__reserved);
417 unsigned char *end = p +
sizeof(ctx->uc_mcontext.__reserved);
427 while (p +
sizeof(A64Head) <= end) {
428 auto *h =
reinterpret_cast<A64Head *
>(p);
429 if (h->magic == 0 || h->size <
sizeof(A64Head)) {
432 if (h->magic == kFpsimdMagic && h->size >=
sizeof(Fpsimd) &&
433 p + h->size <= end) {
434 auto *f =
reinterpret_cast<Fpsimd *
>(p);
436 f->fpcr &= ~fpcr_clear;
444#elif defined(__APPLE__) && defined(__x86_64__)
448 auto *ctx =
static_cast<ucontext_t *
>(scp);
449 if (ctx->uc_mcontext) {
450 auto &fs = ctx->uc_mcontext->__fs;
451 fs.__fpu_mxcsr &= ~0x3Fu;
452 fs.__fpu_mxcsr |= mxcsr_mask_bits;
454 fs.__fpu_fcw.__zdiv = 1;
457 fs.__fpu_fcw.__invalid = 1;
460 fs.__fpu_fcw.__ovrfl = 1;
462 fs.__fpu_fsw.__invalid = 0;
463 fs.__fpu_fsw.__denorm = 0;
464 fs.__fpu_fsw.__zdiv = 0;
465 fs.__fpu_fsw.__ovrfl = 0;
466 fs.__fpu_fsw.__undfl = 0;
467 fs.__fpu_fsw.__precis = 0;
469#elif defined(__APPLE__) && defined(__aarch64__)
470 constexpr unsigned kFpcrIoe = 1u << 8;
471 constexpr unsigned kFpcrDze = 1u << 9;
472 constexpr unsigned kFpcrOfe = 1u << 10;
473 unsigned fpcr_clear = kFpcrIoe | kFpcrDze | kFpcrOfe;
475 fpcr_clear = kFpcrDze;
477 fpcr_clear = kFpcrIoe;
479 fpcr_clear = kFpcrOfe;
481 auto *ctx =
static_cast<ucontext_t *
>(scp);
482 if (ctx->uc_mcontext) {
483 ctx->uc_mcontext->__ns.__fpsr &= ~0x1Fu;
484 ctx->uc_mcontext->__ns.__fpcr &= ~fpcr_clear;
494 SetUnhandledExceptionFilter(windowsFPEHandler);
496 _controlfp_s(
nullptr, 0, _MCW_EM);
497 _controlfp_s(
nullptr, ~(_EM_ZERODIVIDE | _EM_INVALID | _EM_OVERFLOW),
499#elif defined(__unix__)
501 feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
502#elif defined(__APPLE__) && defined(__aarch64__)
506 env.__fpcr |= ((1u << 8) | (1u << 9) | (1u << 10));
508#elif defined(__APPLE__) && defined(__x86_64__)
510 _MM_SET_EXCEPTION_MASK(
512 ~(_MM_MASK_INVALID | _MM_MASK_DIV_ZERO | _MM_MASK_OVERFLOW));
514 fprintf(stderr,
"FPE trapping not supported on this platform.\n");
519 struct sigaction act;
521 sigemptyset(&act.sa_mask);
522 act.sa_flags = SA_SIGINFO;
523 sigaction(SIGFPE, &act,
nullptr);
530 unsigned int control;
531 _controlfp_s(&control, _MCW_EM, _MCW_EM);
532#elif defined(__unix__)
533 fedisableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
534#elif defined(__APPLE__)
537#if defined(__aarch64__)
538 env.__fpcr &= ~((1u << 8) | (1u << 9) | (1u << 10));
539#elif defined(__x86_64__)
543 env.__mxcsr &= ~0x3Fu;
544 env.__control =
static_cast<unsigned short>(env.__control | (1u << 0) |
545 (1u << 2) | (1u << 3));
546 env.__status =
static_cast<unsigned short>(env.__status & ~0x3Fu);
549#if defined(__x86_64__)
550 _MM_SET_EXCEPTION_MASK(_MM_GET_EXCEPTION_MASK() | _MM_MASK_INVALID |
551 _MM_MASK_DIV_ZERO | _MM_MASK_OVERFLOW);