Print this page
patch fixups
   1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2015 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
  14  */
  15 
  16 #include <stdio.h>
  17 #include <libdisasm.h>
  18 #include <sys/sysmacros.h>

  19 #include <sys/byteorder.h>
  20 
  21 #include "libdisasm_impl.h"
  22 
  23 #define ILC2LEN(ilc)    (2 * ((ilc) >= 2 ? (ilc) : (ilc) + 1))
  24 
  25 /*
  26  * Throughout this file, the instruction format names based on:
  27  *   SA22-7832-09  z/Architecture Principles of Operation
  28  *
  29  * System/370, ESA/390, and earlier z/Architecture POP use slightly
  30  * different names for the formats (the variant names are numeric).  For the
  31  * sake of simplicity, we use the most detailed definitions - z/Architecture.
  32  *
  33  * For ESA/390 we map the formats:
  34  *   E   -> E
  35  *   I   -> I
  36  *   RR  -> RR
  37  *   RRE -> RRE
  38  *   RRF -> RRD & RRFa-e


  53  * For System/370 we map the formats:
  54  *   RR -> RR
  55  *   RX -> RXa-b
  56  *   RS -> RSa-b
  57  *   SI -> SI
  58  *   S  -> S
  59  *   SS -> SSa-c
  60  *
  61  * Disassembly begins in tbl_xx.  The first byte of the instruction is used
  62  * as the index.  This yields either an instruction or a sub-table.
  63  *
  64  * If an instruction is encountered, its format field is used to format the
  65  * instruction.
  66  *
  67  * There are two types of sub-tables: extended opcode tables (indicated with
  68  * IF_TBL) or a multiple mnemonics tables (indicated with IF_MULTI).
  69  *
  70  * Extended opcode tables indicade which additional bits of the instruction
  71  * should be inspected.  These bits are used as an index into the sub table.
  72  *
  73  * Multiple mnemonic tables, are used to print different mnemonics depending
  74  * on the architecture.  Over the years, certain instructions got a new
  75  * preferred mnemonic.  For example, 0xa70 is test-under-mask-high (tmh) on
  76  * System/390.  On z/Architecture systems, the instruction behaves
  77  * identically (and the assembler hapilly accepts tmh), but the preferred
  78  * mnemonic is tmlh (test-under-mask-low-high) because z/Architecture
  79  * extended the general purpose registers from 32 bits to 64 bits.  The
  80  * current architecture flag (e.g., F_390) is used to index into the
  81  * sub-table.
  82  *
  83  * Regardless of which sub-table is encountered, the selected entry in the
  84  * sub-table is interpreted using the same rules as the contents of tbl_xx.
  85  *
  86  * Finally, we use the extended opcode sub-table mechanism to pretty print
  87  * the branching instructions.  All branches are conditional based on a
  88  * 4-bit mask indicating which value of the condition code will result in a
  89  * taken branch.  In order to produce a more human friendly output, we use
  90  * the 4-bit mask as an extended opcode to break up the branching
  91  * instruction into 16 different ones.  For example, instead of printing:
  92  *
  93  *    bc   7,0x123(%r1,%r2)
  94  *
  95  * we print:
  96  *
  97  *    bne  0x123(%r1,%r2)




  98  */
  99 
 100 /* BEGIN CSTYLED */
 101 enum ifmt {
 102         /* invalid */
 103         IF_INVAL = 0,
 104 
 105         /* indirection */
 106         IF_TBL,
 107         IF_MULTI,
 108 
 109         /* 2-byte */
 110         IF_ZERO,                /* 370, 390, z */
 111         IF_E,                   /*      390, z */
 112         IF_I,                   /*      390, z */
 113         IF_RR,                  /* 370, 390, z */
 114 
 115         /* 4-byte */
 116         IF_DIAG,                /* 370, 390, z */
 117         IF_IE,                  /*           z */


 164         IF_SSe,                 /*      390, z */
 165         IF_SSf,                 /*      390, z */
 166         IF_SSE,                 /*      390, z */
 167         IF_SSF,                 /*           z */
 168 };
 169 
 170 #define IF_NFMTS                (IF_SSF + 1)
 171 
 172 #define F_370                   0x0001                  /* 370         */
 173 #define F_390                   0x0002                  /*      390    */
 174 #define F_Z                     0x0004                  /*           z */
 175 #define F_SIGNED_IMM            0x0010                  /* 370, 390, z */
 176 #define F_CTL_REG               0x0020                  /* 370, 390, z */
 177 #define F_HIDE_MASK             0x0040                  /* 370, 390, z */
 178 #define F_R1_IS_MASK            0x0080                  /* 370, 390, z */
 179 /* END CSTYLED */
 180 
 181 struct inst_table {
 182         union {
 183                 struct {
 184                         const char *name;
 185                         unsigned flags;
 186                 } inst;
 187                 struct {
 188                         const struct inst_table *ptr;
 189                         uint8_t off:4;
 190                         uint8_t shift:4;
 191                         uint8_t mask;
 192                 } table;
 193                 struct {
 194                         const struct inst_table *ptr;
 195                 } multi;
 196         } u;
 197         enum ifmt fmt;
 198 };
 199 
 200 #define BITFLD(a, b)            DECL_BITFIELD2(b:4, a:4)
 201 
 202 union inst {
 203         uint8_t raw[6];
 204         struct {
 205                 uint8_t op;
 206                 uint8_t par1;
 207                 uint16_t par2;
 208         } diag;
 209         struct {
 210                 uint8_t op;
 211                 uint8_t i;
 212         } i;
 213         struct {
 214                 uint16_t op;
 215                 uint8_t pad;
 216                 BITFLD(i1, i2);
 217         } ie;


 513                 uint8_t d2l;
 514         } ss_f;
 515         struct {
 516                 uint16_t op;
 517                 BITFLD(b1, d1h);
 518                 uint8_t d1l;
 519                 BITFLD(b2, d2h);
 520                 uint8_t d2l;
 521         } sse;
 522         struct {
 523                 uint8_t op1;
 524                 BITFLD(r3, op2);
 525                 BITFLD(b1, d1h);
 526                 uint8_t d1l;
 527                 BITFLD(b2, d2h);
 528                 uint8_t d2l;
 529         } ssf;
 530 };
 531 
 532 #define INSTR(op, m, fm, fl)    [op] = { \
 533                                         .u.inst = { \
 534                                                 .name = (m), \
 535                                                 .flags = (fl), \
 536                                         }, \
 537                                         .fmt = (fm), \
 538                                 }
 539 #define TABLE(op, tbl, o, s, m) [op] = { \
 540                                         .u.table = { \
 541                                                 .ptr = (tbl), \
 542                                                 .off = (o), \
 543                                                 .shift = (s), \
 544                                                 .mask = (m), \
 545                                         }, \
 546                                         .fmt = IF_TBL, \
 547                                 }
 548 #define MULTI(op, tbl)          [op] = { \
 549                                         .u.multi.ptr = (tbl), \
 550                                         .fmt = IF_MULTI, \
 551                                 }
 552 
 553 /*
 554  * Instruction tables based on:
 555  *   GA22-7000-4   System/370 Principles of Operation
 556  *   SA22-7201-08  ESA/390 Principles of Operation
 557  *   SA22-7832-09  z/Architecture Principles of Operation
 558  */
 559 
 560 /* BEGIN CSTYLED */
 561 static const struct inst_table tbl_01xx[256] = {
 562         INSTR(0x01, "pr",    IF_E, F_390 | F_Z),
 563         INSTR(0x02, "upt",   IF_E, F_390 | F_Z),
 564         INSTR(0x04, "ptff",  IF_E, F_Z),
 565         INSTR(0x07, "sckpf", IF_E, F_390 | F_Z),
 566         INSTR(0x0a, "pfpo",  IF_E, F_Z),
 567         INSTR(0x0b, "tam",   IF_E, F_390 | F_Z),
 568         INSTR(0x0c, "sam24", IF_E, F_390 | F_Z),
 569         INSTR(0x0d, "sam31", IF_E, F_390 | F_Z),
 570         INSTR(0x0e, "sam64", IF_E, F_Z),


1773 
1774 /* how general purpose regs are printed */
1775 static const char *R[16] = {
1776         "%r0",  "%r1",  "%r2",  "%r3",  "%r4",  "%r5",  "%r6",  "%r7",
1777         "%r8",  "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
1778 };
1779 
1780 /* how control regs are printed */
1781 static const char *C[16] = {
1782         "%c0",  "%c1",  "%c2",  "%c3",  "%c4",  "%c5",  "%c6",  "%c7",
1783         "%c8",  "%c9", "%c10", "%c11", "%c12", "%c13", "%c14", "%c15",
1784 };
1785 
1786 /* B and X registers are still registers - print them the same way */
1787 #define B       R
1788 #define X       R
1789 
1790 static inline uint32_t
1791 val_8_4_8(uint32_t hi, uint32_t mid, uint32_t lo)
1792 {



1793         return ((hi << 12) | (mid << 8) | lo);
1794 }
1795 
1796 static inline uint32_t
1797 val_16_16(uint32_t hi, uint32_t lo)
1798 {


1799         return ((BE_16(hi) << 16) | BE_16(lo));
1800 }
1801 
1802 static inline int32_t
1803 sval_16_16(uint32_t hi, uint32_t lo)
1804 {
1805         return (val_16_16(hi, lo));
1806 }
1807 
1808 static inline uint32_t
1809 val_8_16(uint32_t hi, uint32_t lo)
1810 {


1811         return ((hi << 16) | BE_16(lo));
1812 }
1813 
1814 static inline int32_t
1815 sval_8_16(uint32_t hi, uint32_t lo)
1816 {
1817         int32_t tmp = val_8_16(hi, lo);
1818 

1819         if (tmp & 0x00800000)
1820                 return (0xff000000 | tmp);
1821         return (tmp);
1822 }
1823 
1824 static inline uint32_t
1825 val_4_8(uint32_t hi, uint32_t lo)
1826 {


1827         return ((hi << 8) | lo);
1828 }
1829 
1830 static inline int32_t
1831 sval_4_8(uint32_t hi, uint32_t lo)
1832 {
1833         uint32_t tmp = val_4_8(hi, lo);
1834 

1835         if (tmp & 0x800)
1836                 return (0xfffff000 | tmp);
1837         return (tmp);
1838 }
1839 
1840 /* ARGSUSED */
1841 static void
1842 fmt_zero(uint64_t addr, union inst *inst, char *buf, size_t buflen, int flags)
1843 {
1844         (void) snprintf(buf, buflen, "0x00, 0x00");
1845 }
1846 
1847 /* ARGSUSED */
1848 static void
1849 fmt_diag(uint64_t addr, union inst *inst, char *buf, size_t buflen, int flags)
1850 {
1851         (void) snprintf(buf, buflen, "%#x",
1852             val_8_16(inst->diag.par1, inst->diag.par2));
1853 }
1854 


2451         [IF_SI]         = fmt_si,
2452         [IF_SIL]        = fmt_sil,
2453         [IF_SIY]        = fmt_siy,
2454         [IF_SMI]        = fmt_smi,
2455         [IF_SSa]        = fmt_ss_a,
2456         [IF_SSb]        = fmt_ss_b,
2457         [IF_SSc]        = fmt_ss_c,
2458         [IF_SSd]        = fmt_ss_d,
2459         [IF_SSe]        = fmt_ss_e,
2460         [IF_SSf]        = fmt_ss_f,
2461         [IF_SSE]        = fmt_sse,
2462         [IF_SSF]        = fmt_ssf,
2463 };
2464 
2465 static int
2466 dis_s390(uint64_t addr, union inst *inst, char *buf, size_t buflen, int mach)
2467 {
2468         const struct inst_table *tbl = &tbl_xx[inst->raw[0]];
2469         int tmp;
2470 
2471         while (tbl->fmt == IF_TBL || tbl->fmt == IF_MULTI) {
2472                 if (tbl->fmt == IF_TBL) {
2473                         int idx;
2474 
2475                         idx   = inst->raw[tbl->u.table.off];
2476                         idx >>= tbl->u.table.shift;
2477                         idx  &= tbl->u.table.mask;
2478 
2479                         tbl = &tbl->u.table.ptr[idx];
2480                 } else if (tbl->fmt == IF_MULTI) {
2481                         tbl = &tbl->u.multi.ptr[mach];
2482                 }
2483         }
2484 
2485         if (tbl->fmt == IF_INVAL)
2486                 goto inval;
2487 
2488         if ((tbl->u.inst.flags & mach) == 0)
2489                 goto inval;
2490 
2491         tmp = snprintf(buf, buflen, "%-7s ", tbl->u.inst.name);
2492 
2493         fmt_fxns[tbl->fmt](addr, inst, buf + tmp, buflen - tmp,
2494             tbl->u.inst.flags);
2495 
2496         return (0);
2497 
2498 inval:
2499         (void) snprintf(buf, buflen, "??");
2500 
2501         /*
2502          * Even if we don't know how to disassemble the instruction, we know
2503          * how long it is, so we "succeed" even when we fail.
2504          */
2505         return (0);
2506 }
2507 
2508 static int
2509 dis_s390_supports_flags(int flags)
2510 {
2511         int archflags = flags & DIS_ARCH_MASK;
2512 
2513         if (archflags == DIS_S370 || archflags == DIS_S390_31 ||
2514             archflags == DIS_S390_64)


   1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2015 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
  14  */
  15 
  16 #include <stdio.h>
  17 #include <libdisasm.h>
  18 #include <sys/sysmacros.h>
  19 #include <sys/debug.h>
  20 #include <sys/byteorder.h>
  21 
  22 #include "libdisasm_impl.h"
  23 
  24 #define ILC2LEN(ilc)    (2 * ((ilc) >= 2 ? (ilc) : (ilc) + 1))
  25 
  26 /*
  27  * Throughout this file, the instruction format names based on:
  28  *   SA22-7832-09  z/Architecture Principles of Operation
  29  *
  30  * System/370, ESA/390, and earlier z/Architecture POP use slightly
  31  * different names for the formats (the variant names are numeric).  For the
  32  * sake of simplicity, we use the most detailed definitions - z/Architecture.
  33  *
  34  * For ESA/390 we map the formats:
  35  *   E   -> E
  36  *   I   -> I
  37  *   RR  -> RR
  38  *   RRE -> RRE
  39  *   RRF -> RRD & RRFa-e


  54  * For System/370 we map the formats:
  55  *   RR -> RR
  56  *   RX -> RXa-b
  57  *   RS -> RSa-b
  58  *   SI -> SI
  59  *   S  -> S
  60  *   SS -> SSa-c
  61  *
  62  * Disassembly begins in tbl_xx.  The first byte of the instruction is used
  63  * as the index.  This yields either an instruction or a sub-table.
  64  *
  65  * If an instruction is encountered, its format field is used to format the
  66  * instruction.
  67  *
  68  * There are two types of sub-tables: extended opcode tables (indicated with
  69  * IF_TBL) or a multiple mnemonics tables (indicated with IF_MULTI).
  70  *
  71  * Extended opcode tables indicade which additional bits of the instruction
  72  * should be inspected.  These bits are used as an index into the sub table.
  73  *
  74  * Multiple mnemonic tables are used to print different mnemonics depending
  75  * on the architecture.  Over the years, certain instructions got a new
  76  * preferred mnemonic.  For example, 0xa70 is test-under-mask-high (tmh) on
  77  * System/390.  On z/Architecture systems, the instruction behaves
  78  * identically (and the assembler hapilly accepts tmh), but the preferred
  79  * mnemonic is tmlh (test-under-mask-low-high) because z/Architecture
  80  * extended the general purpose registers from 32 bits to 64 bits.  The
  81  * current architecture flag (e.g., F_390) is used to index into the
  82  * sub-table.
  83  *
  84  * Regardless of which sub-table is encountered, the selected entry in the
  85  * sub-table is interpreted using the same rules as the contents of tbl_xx.
  86  *
  87  * Finally, we use the extended opcode sub-table mechanism to pretty print
  88  * the branching instructions.  All branches are conditional based on a
  89  * 4-bit mask indicating which value of the condition code will result in a
  90  * taken branch.  In order to produce a more human friendly output, we use
  91  * the 4-bit mask as an extended opcode to break up the branching
  92  * instruction into 16 different ones.  For example, instead of printing:
  93  *
  94  *    bc   7,0x123(%r1,%r2)
  95  *
  96  * we print:
  97  *
  98  *    bne  0x123(%r1,%r2)
  99  *
 100  * Note that we are using designated initializers via the INSTR/TABLE/MULTI
 101  * macros and therefore the below tables can be sparse.  We rely on unset
 102  * entries having zero format fields (aka. IF_INVAL) per C99.
 103  */
 104 
 105 /* BEGIN CSTYLED */
 106 enum ifmt {
 107         /* invalid */
 108         IF_INVAL = 0,
 109 
 110         /* indirection */
 111         IF_TBL,
 112         IF_MULTI,
 113 
 114         /* 2-byte */
 115         IF_ZERO,                /* 370, 390, z */
 116         IF_E,                   /*      390, z */
 117         IF_I,                   /*      390, z */
 118         IF_RR,                  /* 370, 390, z */
 119 
 120         /* 4-byte */
 121         IF_DIAG,                /* 370, 390, z */
 122         IF_IE,                  /*           z */


 169         IF_SSe,                 /*      390, z */
 170         IF_SSf,                 /*      390, z */
 171         IF_SSE,                 /*      390, z */
 172         IF_SSF,                 /*           z */
 173 };
 174 
 175 #define IF_NFMTS                (IF_SSF + 1)
 176 
 177 #define F_370                   0x0001                  /* 370         */
 178 #define F_390                   0x0002                  /*      390    */
 179 #define F_Z                     0x0004                  /*           z */
 180 #define F_SIGNED_IMM            0x0010                  /* 370, 390, z */
 181 #define F_CTL_REG               0x0020                  /* 370, 390, z */
 182 #define F_HIDE_MASK             0x0040                  /* 370, 390, z */
 183 #define F_R1_IS_MASK            0x0080                  /* 370, 390, z */
 184 /* END CSTYLED */
 185 
 186 struct inst_table {
 187         union {
 188                 struct {
 189                         const char *it_name;
 190                         unsigned it_flags;
 191                 } it_inst;
 192                 struct {
 193                         const struct inst_table *it_ptr;
 194                         uint8_t it_off:4;
 195                         uint8_t it_shift:4;
 196                         uint8_t it_mask;
 197                 } it_table;
 198                 struct {
 199                         const struct inst_table *it_ptr;
 200                 } it_multi;
 201         } it_u;
 202         enum ifmt it_fmt;
 203 };
 204 
 205 #define BITFLD(a, b)            DECL_BITFIELD2(b:4, a:4)
 206 
 207 union inst {
 208         uint8_t raw[6];
 209         struct {
 210                 uint8_t op;
 211                 uint8_t par1;
 212                 uint16_t par2;
 213         } diag;
 214         struct {
 215                 uint8_t op;
 216                 uint8_t i;
 217         } i;
 218         struct {
 219                 uint16_t op;
 220                 uint8_t pad;
 221                 BITFLD(i1, i2);
 222         } ie;


 518                 uint8_t d2l;
 519         } ss_f;
 520         struct {
 521                 uint16_t op;
 522                 BITFLD(b1, d1h);
 523                 uint8_t d1l;
 524                 BITFLD(b2, d2h);
 525                 uint8_t d2l;
 526         } sse;
 527         struct {
 528                 uint8_t op1;
 529                 BITFLD(r3, op2);
 530                 BITFLD(b1, d1h);
 531                 uint8_t d1l;
 532                 BITFLD(b2, d2h);
 533                 uint8_t d2l;
 534         } ssf;
 535 };
 536 
 537 #define INSTR(op, m, fm, fl)    [op] = { \
 538                                         .it_u.it_inst = { \
 539                                                 .it_name = (m), \
 540                                                 .it_flags = (fl), \
 541                                         }, \
 542                                         .it_fmt = (fm), \
 543                                 }
 544 #define TABLE(op, tbl, o, s, m) [op] = { \
 545                                         .it_u.it_table = { \
 546                                                 .it_ptr = (tbl), \
 547                                                 .it_off = (o), \
 548                                                 .it_shift = (s), \
 549                                                 .it_mask = (m), \
 550                                         }, \
 551                                         .it_fmt = IF_TBL, \
 552                                 }
 553 #define MULTI(op, tbl)          [op] = { \
 554                                         .it_u.it_multi.it_ptr = (tbl), \
 555                                         .it_fmt = IF_MULTI, \
 556                                 }
 557 
 558 /*
 559  * Instruction tables based on:
 560  *   GA22-7000-4   System/370 Principles of Operation
 561  *   SA22-7201-08  ESA/390 Principles of Operation
 562  *   SA22-7832-09  z/Architecture Principles of Operation
 563  */
 564 
 565 /* BEGIN CSTYLED */
 566 static const struct inst_table tbl_01xx[256] = {
 567         INSTR(0x01, "pr",    IF_E, F_390 | F_Z),
 568         INSTR(0x02, "upt",   IF_E, F_390 | F_Z),
 569         INSTR(0x04, "ptff",  IF_E, F_Z),
 570         INSTR(0x07, "sckpf", IF_E, F_390 | F_Z),
 571         INSTR(0x0a, "pfpo",  IF_E, F_Z),
 572         INSTR(0x0b, "tam",   IF_E, F_390 | F_Z),
 573         INSTR(0x0c, "sam24", IF_E, F_390 | F_Z),
 574         INSTR(0x0d, "sam31", IF_E, F_390 | F_Z),
 575         INSTR(0x0e, "sam64", IF_E, F_Z),


1778 
1779 /* how general purpose regs are printed */
1780 static const char *R[16] = {
1781         "%r0",  "%r1",  "%r2",  "%r3",  "%r4",  "%r5",  "%r6",  "%r7",
1782         "%r8",  "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
1783 };
1784 
1785 /* how control regs are printed */
1786 static const char *C[16] = {
1787         "%c0",  "%c1",  "%c2",  "%c3",  "%c4",  "%c5",  "%c6",  "%c7",
1788         "%c8",  "%c9", "%c10", "%c11", "%c12", "%c13", "%c14", "%c15",
1789 };
1790 
1791 /* B and X registers are still registers - print them the same way */
1792 #define B       R
1793 #define X       R
1794 
1795 static inline uint32_t
1796 val_8_4_8(uint32_t hi, uint32_t mid, uint32_t lo)
1797 {
1798         ASSERT0(hi & ~0xff);
1799         ASSERT0(mid & ~0xf);
1800         ASSERT0(lo & ~0xff);
1801         return ((hi << 12) | (mid << 8) | lo);
1802 }
1803 
1804 static inline uint32_t
1805 val_16_16(uint32_t hi, uint32_t lo)
1806 {
1807         ASSERT0(hi & ~0xffff);
1808         ASSERT0(lo & ~0xffff);
1809         return ((BE_16(hi) << 16) | BE_16(lo));
1810 }
1811 
1812 static inline int32_t
1813 sval_16_16(uint32_t hi, uint32_t lo)
1814 {
1815         return (val_16_16(hi, lo));
1816 }
1817 
1818 static inline uint32_t
1819 val_8_16(uint32_t hi, uint32_t lo)
1820 {
1821         ASSERT0(hi & ~0xff);
1822         ASSERT0(lo & ~0xffff);
1823         return ((hi << 16) | BE_16(lo));
1824 }
1825 
1826 static inline int32_t
1827 sval_8_16(uint32_t hi, uint32_t lo)
1828 {
1829         int32_t tmp = val_8_16(hi, lo);
1830 
1831         /* sign extend */
1832         if (tmp & 0x00800000)
1833                 return (0xff000000 | tmp);
1834         return (tmp);
1835 }
1836 
1837 static inline uint32_t
1838 val_4_8(uint32_t hi, uint32_t lo)
1839 {
1840         ASSERT0(hi & ~0xf);
1841         ASSERT0(lo & ~0xff);
1842         return ((hi << 8) | lo);
1843 }
1844 
1845 static inline int32_t
1846 sval_4_8(uint32_t hi, uint32_t lo)
1847 {
1848         uint32_t tmp = val_4_8(hi, lo);
1849 
1850         /* sign extend */
1851         if (tmp & 0x800)
1852                 return (0xfffff000 | tmp);
1853         return (tmp);
1854 }
1855 
1856 /* ARGSUSED */
1857 static void
1858 fmt_zero(uint64_t addr, union inst *inst, char *buf, size_t buflen, int flags)
1859 {
1860         (void) snprintf(buf, buflen, "0x00, 0x00");
1861 }
1862 
1863 /* ARGSUSED */
1864 static void
1865 fmt_diag(uint64_t addr, union inst *inst, char *buf, size_t buflen, int flags)
1866 {
1867         (void) snprintf(buf, buflen, "%#x",
1868             val_8_16(inst->diag.par1, inst->diag.par2));
1869 }
1870 


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)