Print this page
patch fixups

Split Close
Expand all
Collapse all
          --- old/usr/src/lib/libdisasm/common/dis_s390x.c
          +++ new/usr/src/lib/libdisasm/common/dis_s390x.c
↓ open down ↓ 8 lines elided ↑ open up ↑
   9    9   * http://www.illumos.org/license/CDDL.
  10   10   */
  11   11  
  12   12  /*
  13   13   * Copyright 2015 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
  14   14   */
  15   15  
  16   16  #include <stdio.h>
  17   17  #include <libdisasm.h>
  18   18  #include <sys/sysmacros.h>
       19 +#include <sys/debug.h>
  19   20  #include <sys/byteorder.h>
  20   21  
  21   22  #include "libdisasm_impl.h"
  22   23  
  23   24  #define ILC2LEN(ilc)    (2 * ((ilc) >= 2 ? (ilc) : (ilc) + 1))
  24   25  
  25   26  /*
  26   27   * Throughout this file, the instruction format names based on:
  27   28   *   SA22-7832-09  z/Architecture Principles of Operation
  28   29   *
↓ open down ↓ 34 lines elided ↑ open up ↑
  63   64   *
  64   65   * If an instruction is encountered, its format field is used to format the
  65   66   * instruction.
  66   67   *
  67   68   * There are two types of sub-tables: extended opcode tables (indicated with
  68   69   * IF_TBL) or a multiple mnemonics tables (indicated with IF_MULTI).
  69   70   *
  70   71   * Extended opcode tables indicade which additional bits of the instruction
  71   72   * should be inspected.  These bits are used as an index into the sub table.
  72   73   *
  73      - * Multiple mnemonic tables, are used to print different mnemonics depending
       74 + * Multiple mnemonic tables are used to print different mnemonics depending
  74   75   * on the architecture.  Over the years, certain instructions got a new
  75   76   * preferred mnemonic.  For example, 0xa70 is test-under-mask-high (tmh) on
  76   77   * System/390.  On z/Architecture systems, the instruction behaves
  77   78   * identically (and the assembler hapilly accepts tmh), but the preferred
  78   79   * mnemonic is tmlh (test-under-mask-low-high) because z/Architecture
  79   80   * extended the general purpose registers from 32 bits to 64 bits.  The
  80   81   * current architecture flag (e.g., F_390) is used to index into the
  81   82   * sub-table.
  82   83   *
  83   84   * Regardless of which sub-table is encountered, the selected entry in the
↓ open down ↓ 4 lines elided ↑ open up ↑
  88   89   * 4-bit mask indicating which value of the condition code will result in a
  89   90   * taken branch.  In order to produce a more human friendly output, we use
  90   91   * the 4-bit mask as an extended opcode to break up the branching
  91   92   * instruction into 16 different ones.  For example, instead of printing:
  92   93   *
  93   94   *    bc   7,0x123(%r1,%r2)
  94   95   *
  95   96   * we print:
  96   97   *
  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.
  98  103   */
  99  104  
 100  105  /* BEGIN CSTYLED */
 101  106  enum ifmt {
 102  107          /* invalid */
 103  108          IF_INVAL = 0,
 104  109  
 105  110          /* indirection */
 106  111          IF_TBL,
 107  112          IF_MULTI,
↓ open down ↓ 66 lines elided ↑ open up ↑
 174  179  #define F_Z                     0x0004                  /*           z */
 175  180  #define F_SIGNED_IMM            0x0010                  /* 370, 390, z */
 176  181  #define F_CTL_REG               0x0020                  /* 370, 390, z */
 177  182  #define F_HIDE_MASK             0x0040                  /* 370, 390, z */
 178  183  #define F_R1_IS_MASK            0x0080                  /* 370, 390, z */
 179  184  /* END CSTYLED */
 180  185  
 181  186  struct inst_table {
 182  187          union {
 183  188                  struct {
 184      -                        const char *name;
 185      -                        unsigned flags;
 186      -                } inst;
      189 +                        const char *it_name;
      190 +                        unsigned it_flags;
      191 +                } it_inst;
 187  192                  struct {
 188      -                        const struct inst_table *ptr;
 189      -                        uint8_t off:4;
 190      -                        uint8_t shift:4;
 191      -                        uint8_t mask;
 192      -                } table;
      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;
 193  198                  struct {
 194      -                        const struct inst_table *ptr;
 195      -                } multi;
 196      -        } u;
 197      -        enum ifmt fmt;
      199 +                        const struct inst_table *it_ptr;
      200 +                } it_multi;
      201 +        } it_u;
      202 +        enum ifmt it_fmt;
 198  203  };
 199  204  
 200  205  #define BITFLD(a, b)            DECL_BITFIELD2(b:4, a:4)
 201  206  
 202  207  union inst {
 203  208          uint8_t raw[6];
 204  209          struct {
 205  210                  uint8_t op;
 206  211                  uint8_t par1;
 207  212                  uint16_t par2;
↓ open down ↓ 315 lines elided ↑ open up ↑
 523  528                  uint8_t op1;
 524  529                  BITFLD(r3, op2);
 525  530                  BITFLD(b1, d1h);
 526  531                  uint8_t d1l;
 527  532                  BITFLD(b2, d2h);
 528  533                  uint8_t d2l;
 529  534          } ssf;
 530  535  };
 531  536  
 532  537  #define INSTR(op, m, fm, fl)    [op] = { \
 533      -                                        .u.inst = { \
 534      -                                                .name = (m), \
 535      -                                                .flags = (fl), \
      538 +                                        .it_u.it_inst = { \
      539 +                                                .it_name = (m), \
      540 +                                                .it_flags = (fl), \
 536  541                                          }, \
 537      -                                        .fmt = (fm), \
      542 +                                        .it_fmt = (fm), \
 538  543                                  }
 539  544  #define TABLE(op, tbl, o, s, m) [op] = { \
 540      -                                        .u.table = { \
 541      -                                                .ptr = (tbl), \
 542      -                                                .off = (o), \
 543      -                                                .shift = (s), \
 544      -                                                .mask = (m), \
      545 +                                        .it_u.it_table = { \
      546 +                                                .it_ptr = (tbl), \
      547 +                                                .it_off = (o), \
      548 +                                                .it_shift = (s), \
      549 +                                                .it_mask = (m), \
 545  550                                          }, \
 546      -                                        .fmt = IF_TBL, \
      551 +                                        .it_fmt = IF_TBL, \
 547  552                                  }
 548  553  #define MULTI(op, tbl)          [op] = { \
 549      -                                        .u.multi.ptr = (tbl), \
 550      -                                        .fmt = IF_MULTI, \
      554 +                                        .it_u.it_multi.it_ptr = (tbl), \
      555 +                                        .it_fmt = IF_MULTI, \
 551  556                                  }
 552  557  
 553  558  /*
 554  559   * Instruction tables based on:
 555  560   *   GA22-7000-4   System/370 Principles of Operation
 556  561   *   SA22-7201-08  ESA/390 Principles of Operation
 557  562   *   SA22-7832-09  z/Architecture Principles of Operation
 558  563   */
 559  564  
 560  565  /* BEGIN CSTYLED */
↓ open down ↓ 1222 lines elided ↑ open up ↑
1783 1788          "%c8",  "%c9", "%c10", "%c11", "%c12", "%c13", "%c14", "%c15",
1784 1789  };
1785 1790  
1786 1791  /* B and X registers are still registers - print them the same way */
1787 1792  #define B       R
1788 1793  #define X       R
1789 1794  
1790 1795  static inline uint32_t
1791 1796  val_8_4_8(uint32_t hi, uint32_t mid, uint32_t lo)
1792 1797  {
     1798 +        ASSERT0(hi & ~0xff);
     1799 +        ASSERT0(mid & ~0xf);
     1800 +        ASSERT0(lo & ~0xff);
1793 1801          return ((hi << 12) | (mid << 8) | lo);
1794 1802  }
1795 1803  
1796 1804  static inline uint32_t
1797 1805  val_16_16(uint32_t hi, uint32_t lo)
1798 1806  {
     1807 +        ASSERT0(hi & ~0xffff);
     1808 +        ASSERT0(lo & ~0xffff);
1799 1809          return ((BE_16(hi) << 16) | BE_16(lo));
1800 1810  }
1801 1811  
1802 1812  static inline int32_t
1803 1813  sval_16_16(uint32_t hi, uint32_t lo)
1804 1814  {
1805 1815          return (val_16_16(hi, lo));
1806 1816  }
1807 1817  
1808 1818  static inline uint32_t
1809 1819  val_8_16(uint32_t hi, uint32_t lo)
1810 1820  {
     1821 +        ASSERT0(hi & ~0xff);
     1822 +        ASSERT0(lo & ~0xffff);
1811 1823          return ((hi << 16) | BE_16(lo));
1812 1824  }
1813 1825  
1814 1826  static inline int32_t
1815 1827  sval_8_16(uint32_t hi, uint32_t lo)
1816 1828  {
1817 1829          int32_t tmp = val_8_16(hi, lo);
1818 1830  
     1831 +        /* sign extend */
1819 1832          if (tmp & 0x00800000)
1820 1833                  return (0xff000000 | tmp);
1821 1834          return (tmp);
1822 1835  }
1823 1836  
1824 1837  static inline uint32_t
1825 1838  val_4_8(uint32_t hi, uint32_t lo)
1826 1839  {
     1840 +        ASSERT0(hi & ~0xf);
     1841 +        ASSERT0(lo & ~0xff);
1827 1842          return ((hi << 8) | lo);
1828 1843  }
1829 1844  
1830 1845  static inline int32_t
1831 1846  sval_4_8(uint32_t hi, uint32_t lo)
1832 1847  {
1833 1848          uint32_t tmp = val_4_8(hi, lo);
1834 1849  
     1850 +        /* sign extend */
1835 1851          if (tmp & 0x800)
1836 1852                  return (0xfffff000 | tmp);
1837 1853          return (tmp);
1838 1854  }
1839 1855  
1840 1856  /* ARGSUSED */
1841 1857  static void
1842 1858  fmt_zero(uint64_t addr, union inst *inst, char *buf, size_t buflen, int flags)
1843 1859  {
1844 1860          (void) snprintf(buf, buflen, "0x00, 0x00");
↓ open down ↓ 616 lines elided ↑ open up ↑
2461 2477          [IF_SSE]        = fmt_sse,
2462 2478          [IF_SSF]        = fmt_ssf,
2463 2479  };
2464 2480  
2465 2481  static int
2466 2482  dis_s390(uint64_t addr, union inst *inst, char *buf, size_t buflen, int mach)
2467 2483  {
2468 2484          const struct inst_table *tbl = &tbl_xx[inst->raw[0]];
2469 2485          int tmp;
2470 2486  
2471      -        while (tbl->fmt == IF_TBL || tbl->fmt == IF_MULTI) {
2472      -                if (tbl->fmt == IF_TBL) {
     2487 +        while (tbl->it_fmt == IF_TBL || tbl->it_fmt == IF_MULTI) {
     2488 +                if (tbl->it_fmt == IF_TBL) {
2473 2489                          int idx;
2474 2490  
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];
     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];
2482 2498                  }
2483 2499          }
2484 2500  
2485      -        if (tbl->fmt == IF_INVAL)
     2501 +        if (tbl->it_fmt == IF_INVAL)
2486 2502                  goto inval;
2487 2503  
2488      -        if ((tbl->u.inst.flags & mach) == 0)
     2504 +        if ((tbl->it_u.it_inst.it_flags & mach) == 0)
2489 2505                  goto inval;
2490 2506  
2491      -        tmp = snprintf(buf, buflen, "%-7s ", tbl->u.inst.name);
     2507 +        tmp = snprintf(buf, buflen, "%-7s ", tbl->it_u.it_inst.it_name);
2492 2508  
2493      -        fmt_fxns[tbl->fmt](addr, inst, buf + tmp, buflen - tmp,
2494      -            tbl->u.inst.flags);
     2509 +        fmt_fxns[tbl->it_fmt](addr, inst, buf + tmp, buflen - tmp,
     2510 +            tbl->it_u.it_inst.it_flags);
2495 2511  
2496 2512          return (0);
2497 2513  
2498 2514  inval:
2499 2515          (void) snprintf(buf, buflen, "??");
2500 2516  
2501 2517          /*
2502 2518           * Even if we don't know how to disassemble the instruction, we know
2503 2519           * how long it is, so we "succeed" even when we fail.
2504 2520           */
↓ open down ↓ 67 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX