2461 [IF_RXb] = fmt_rx_b,
2462 [IF_RXE] = fmt_rxe,
2463 [IF_RXF] = fmt_rxf,
2464 [IF_RXYa] = fmt_rxy_a,
2465 [IF_RXYb] = fmt_rxy_b,
2466 [IF_S] = fmt_s,
2467 [IF_SI] = fmt_si,
2468 [IF_SIL] = fmt_sil,
2469 [IF_SIY] = fmt_siy,
2470 [IF_SMI] = fmt_smi,
2471 [IF_SSa] = fmt_ss_a,
2472 [IF_SSb] = fmt_ss_b,
2473 [IF_SSc] = fmt_ss_c,
2474 [IF_SSd] = fmt_ss_d,
2475 [IF_SSe] = fmt_ss_e,
2476 [IF_SSf] = fmt_ss_f,
2477 [IF_SSE] = fmt_sse,
2478 [IF_SSF] = fmt_ssf,
2479 };
2480
2481 static int
2482 dis_s390(uint64_t addr, union inst *inst, char *buf, size_t buflen, int mach)
2483 {
2484 const struct inst_table *tbl = &tbl_xx[inst->raw[0]];
2485 int tmp;
2486
2487 while (tbl->it_fmt == IF_TBL || tbl->it_fmt == IF_MULTI) {
2488 if (tbl->it_fmt == IF_TBL) {
2489 int idx;
2490
2491 idx = inst->raw[tbl->it_u.it_table.it_off];
2492 idx >>= tbl->it_u.it_table.it_shift;
2493 idx &= tbl->it_u.it_table.it_mask;
2494
2495 tbl = &tbl->it_u.it_table.it_ptr[idx];
2496 } else if (tbl->it_fmt == IF_MULTI) {
2497 tbl = &tbl->it_u.it_multi.it_ptr[mach];
2498 }
2499 }
2500
2501 if (tbl->it_fmt == IF_INVAL)
2502 goto inval;
2503
2504 if ((tbl->it_u.it_inst.it_flags & mach) == 0)
2505 goto inval;
2506
2507 tmp = snprintf(buf, buflen, "%-7s ", tbl->it_u.it_inst.it_name);
2508
2509 fmt_fxns[tbl->it_fmt](addr, inst, buf + tmp, buflen - tmp,
2510 tbl->it_u.it_inst.it_flags);
2511
2512 return (0);
2513
2514 inval:
2515 (void) snprintf(buf, buflen, "??");
2516
2517 /*
2518 * Even if we don't know how to disassemble the instruction, we know
2519 * how long it is, so we "succeed" even when we fail.
2520 */
2521 return (0);
2522 }
2523
2524 static int
2525 dis_s390_supports_flags(int flags)
2526 {
2527 int archflags = flags & DIS_ARCH_MASK;
2528
2529 if (archflags == DIS_S370 || archflags == DIS_S390_31 ||
2530 archflags == DIS_S390_64)
2531 return (1);
2532
2533 return (0);
2534 }
2535
2536 static int
2537 dis_s390_disassemble(dis_handle_t *dhp, uint64_t addr, char *buf,
2538 size_t buflen)
2539 {
2540 union inst inst;
2541 int mach;
2545 return (-1);
2546
2547 len = ILC2LEN(inst.raw[0] >> 6) - 2;
2548
2549 if (len > 0 &&
2550 dhp->dh_read(dhp->dh_data, addr + 2, &inst.raw[2], len) != len)
2551 return (-1);
2552
2553 switch (dhp->dh_flags & (DIS_S370 | DIS_S390_31 | DIS_S390_64)) {
2554 case DIS_S370:
2555 mach = F_370;
2556 break;
2557 case DIS_S390_31:
2558 mach = F_390;
2559 break;
2560 case DIS_S390_64:
2561 mach = F_Z;
2562 break;
2563 }
2564
2565 return (dis_s390(addr, &inst, buf, buflen, mach));
2566 }
2567
2568 /* ARGSUSED */
2569 static int
2570 dis_s390_min_instrlen(dis_handle_t *dhp)
2571 {
2572 return (2);
2573 }
2574
2575 /* ARGSUSED */
2576 static int
2577 dis_s390_max_instrlen(dis_handle_t *dhp)
2578 {
2579 return (6);
2580 }
2581
2582 dis_arch_t dis_arch_s390 = {
2583 .da_supports_flags = dis_s390_supports_flags,
2584 .da_disassemble = dis_s390_disassemble,
2585 .da_min_instrlen = dis_s390_min_instrlen,
|
2461 [IF_RXb] = fmt_rx_b,
2462 [IF_RXE] = fmt_rxe,
2463 [IF_RXF] = fmt_rxf,
2464 [IF_RXYa] = fmt_rxy_a,
2465 [IF_RXYb] = fmt_rxy_b,
2466 [IF_S] = fmt_s,
2467 [IF_SI] = fmt_si,
2468 [IF_SIL] = fmt_sil,
2469 [IF_SIY] = fmt_siy,
2470 [IF_SMI] = fmt_smi,
2471 [IF_SSa] = fmt_ss_a,
2472 [IF_SSb] = fmt_ss_b,
2473 [IF_SSc] = fmt_ss_c,
2474 [IF_SSd] = fmt_ss_d,
2475 [IF_SSe] = fmt_ss_e,
2476 [IF_SSf] = fmt_ss_f,
2477 [IF_SSE] = fmt_sse,
2478 [IF_SSF] = fmt_ssf,
2479 };
2480
2481 /*
2482 * Even if we don't know how to disassemble the instruction, we know how long
2483 * it is, so we always succeed. That is why we can get away with returning
2484 * void.
2485 */
2486 static void
2487 dis_s390(uint64_t addr, union inst *inst, char *buf, size_t buflen, int mach)
2488 {
2489 const struct inst_table *tbl = &tbl_xx[inst->raw[0]];
2490 int tmp;
2491
2492 /* nothing to do */
2493 if (buflen == 0)
2494 return;
2495
2496 while (tbl->it_fmt == IF_TBL || tbl->it_fmt == IF_MULTI) {
2497 if (tbl->it_fmt == IF_TBL) {
2498 int idx;
2499
2500 idx = inst->raw[tbl->it_u.it_table.it_off];
2501 idx >>= tbl->it_u.it_table.it_shift;
2502 idx &= tbl->it_u.it_table.it_mask;
2503
2504 tbl = &tbl->it_u.it_table.it_ptr[idx];
2505 } else if (tbl->it_fmt == IF_MULTI) {
2506 tbl = &tbl->it_u.it_multi.it_ptr[mach];
2507 }
2508 }
2509
2510 if (tbl->it_fmt == IF_INVAL)
2511 goto inval;
2512
2513 if ((tbl->it_u.it_inst.it_flags & mach) == 0)
2514 goto inval;
2515
2516 tmp = snprintf(buf, buflen, "%-7s ", tbl->it_u.it_inst.it_name);
2517 if (tmp < 0)
2518 return;
2519
2520 fmt_fxns[tbl->it_fmt](addr, inst, buf + tmp, buflen - tmp,
2521 tbl->it_u.it_inst.it_flags);
2522
2523 return;
2524
2525 inval:
2526 (void) snprintf(buf, buflen, "??");
2527 }
2528
2529 static int
2530 dis_s390_supports_flags(int flags)
2531 {
2532 int archflags = flags & DIS_ARCH_MASK;
2533
2534 if (archflags == DIS_S370 || archflags == DIS_S390_31 ||
2535 archflags == DIS_S390_64)
2536 return (1);
2537
2538 return (0);
2539 }
2540
2541 static int
2542 dis_s390_disassemble(dis_handle_t *dhp, uint64_t addr, char *buf,
2543 size_t buflen)
2544 {
2545 union inst inst;
2546 int mach;
2550 return (-1);
2551
2552 len = ILC2LEN(inst.raw[0] >> 6) - 2;
2553
2554 if (len > 0 &&
2555 dhp->dh_read(dhp->dh_data, addr + 2, &inst.raw[2], len) != len)
2556 return (-1);
2557
2558 switch (dhp->dh_flags & (DIS_S370 | DIS_S390_31 | DIS_S390_64)) {
2559 case DIS_S370:
2560 mach = F_370;
2561 break;
2562 case DIS_S390_31:
2563 mach = F_390;
2564 break;
2565 case DIS_S390_64:
2566 mach = F_Z;
2567 break;
2568 }
2569
2570 dis_s390(addr, &inst, buf, buflen, mach);
2571
2572 return (0);
2573 }
2574
2575 /* ARGSUSED */
2576 static int
2577 dis_s390_min_instrlen(dis_handle_t *dhp)
2578 {
2579 return (2);
2580 }
2581
2582 /* ARGSUSED */
2583 static int
2584 dis_s390_max_instrlen(dis_handle_t *dhp)
2585 {
2586 return (6);
2587 }
2588
2589 dis_arch_t dis_arch_s390 = {
2590 .da_supports_flags = dis_s390_supports_flags,
2591 .da_disassemble = dis_s390_disassemble,
2592 .da_min_instrlen = dis_s390_min_instrlen,
|