Print this page
patch fixups

*** 14,23 **** --- 14,24 ---- */ #include <stdio.h> #include <libdisasm.h> #include <sys/sysmacros.h> + #include <sys/debug.h> #include <sys/byteorder.h> #include "libdisasm_impl.h" #define ILC2LEN(ilc) (2 * ((ilc) >= 2 ? (ilc) : (ilc) + 1))
*** 68,78 **** * IF_TBL) or a multiple mnemonics tables (indicated with IF_MULTI). * * Extended opcode tables indicade which additional bits of the instruction * should be inspected. These bits are used as an index into the sub table. * ! * Multiple mnemonic tables, are used to print different mnemonics depending * on the architecture. Over the years, certain instructions got a new * preferred mnemonic. For example, 0xa70 is test-under-mask-high (tmh) on * System/390. On z/Architecture systems, the instruction behaves * identically (and the assembler hapilly accepts tmh), but the preferred * mnemonic is tmlh (test-under-mask-low-high) because z/Architecture --- 69,79 ---- * IF_TBL) or a multiple mnemonics tables (indicated with IF_MULTI). * * Extended opcode tables indicade which additional bits of the instruction * should be inspected. These bits are used as an index into the sub table. * ! * Multiple mnemonic tables are used to print different mnemonics depending * on the architecture. Over the years, certain instructions got a new * preferred mnemonic. For example, 0xa70 is test-under-mask-high (tmh) on * System/390. On z/Architecture systems, the instruction behaves * identically (and the assembler hapilly accepts tmh), but the preferred * mnemonic is tmlh (test-under-mask-low-high) because z/Architecture
*** 93,102 **** --- 94,107 ---- * bc 7,0x123(%r1,%r2) * * we print: * * bne 0x123(%r1,%r2) + * + * Note that we are using designated initializers via the INSTR/TABLE/MULTI + * macros and therefore the below tables can be sparse. We rely on unset + * entries having zero format fields (aka. IF_INVAL) per C99. */ /* BEGIN CSTYLED */ enum ifmt { /* invalid */
*** 179,202 **** /* END CSTYLED */ struct inst_table { union { struct { ! const char *name; ! unsigned flags; ! } inst; ! struct { ! const struct inst_table *ptr; ! uint8_t off:4; ! uint8_t shift:4; ! uint8_t mask; ! } table; ! struct { ! const struct inst_table *ptr; ! } multi; ! } u; ! enum ifmt fmt; }; #define BITFLD(a, b) DECL_BITFIELD2(b:4, a:4) union inst { --- 184,207 ---- /* END CSTYLED */ struct inst_table { union { struct { ! const char *it_name; ! unsigned it_flags; ! } it_inst; ! struct { ! const struct inst_table *it_ptr; ! uint8_t it_off:4; ! uint8_t it_shift:4; ! uint8_t it_mask; ! } it_table; ! struct { ! const struct inst_table *it_ptr; ! } it_multi; ! } it_u; ! enum ifmt it_fmt; }; #define BITFLD(a, b) DECL_BITFIELD2(b:4, a:4) union inst {
*** 528,555 **** uint8_t d2l; } ssf; }; #define INSTR(op, m, fm, fl) [op] = { \ ! .u.inst = { \ ! .name = (m), \ ! .flags = (fl), \ }, \ ! .fmt = (fm), \ } #define TABLE(op, tbl, o, s, m) [op] = { \ ! .u.table = { \ ! .ptr = (tbl), \ ! .off = (o), \ ! .shift = (s), \ ! .mask = (m), \ }, \ ! .fmt = IF_TBL, \ } #define MULTI(op, tbl) [op] = { \ ! .u.multi.ptr = (tbl), \ ! .fmt = IF_MULTI, \ } /* * Instruction tables based on: * GA22-7000-4 System/370 Principles of Operation --- 533,560 ---- uint8_t d2l; } ssf; }; #define INSTR(op, m, fm, fl) [op] = { \ ! .it_u.it_inst = { \ ! .it_name = (m), \ ! .it_flags = (fl), \ }, \ ! .it_fmt = (fm), \ } #define TABLE(op, tbl, o, s, m) [op] = { \ ! .it_u.it_table = { \ ! .it_ptr = (tbl), \ ! .it_off = (o), \ ! .it_shift = (s), \ ! .it_mask = (m), \ }, \ ! .it_fmt = IF_TBL, \ } #define MULTI(op, tbl) [op] = { \ ! .it_u.it_multi.it_ptr = (tbl), \ ! .it_fmt = IF_MULTI, \ } /* * Instruction tables based on: * GA22-7000-4 System/370 Principles of Operation
*** 1788,1803 **** --- 1793,1813 ---- #define X R static inline uint32_t val_8_4_8(uint32_t hi, uint32_t mid, uint32_t lo) { + ASSERT0(hi & ~0xff); + ASSERT0(mid & ~0xf); + ASSERT0(lo & ~0xff); return ((hi << 12) | (mid << 8) | lo); } static inline uint32_t val_16_16(uint32_t hi, uint32_t lo) { + ASSERT0(hi & ~0xffff); + ASSERT0(lo & ~0xffff); return ((BE_16(hi) << 16) | BE_16(lo)); } static inline int32_t sval_16_16(uint32_t hi, uint32_t lo)
*** 1806,1839 **** --- 1816,1855 ---- } static inline uint32_t val_8_16(uint32_t hi, uint32_t lo) { + ASSERT0(hi & ~0xff); + ASSERT0(lo & ~0xffff); return ((hi << 16) | BE_16(lo)); } static inline int32_t sval_8_16(uint32_t hi, uint32_t lo) { int32_t tmp = val_8_16(hi, lo); + /* sign extend */ if (tmp & 0x00800000) return (0xff000000 | tmp); return (tmp); } static inline uint32_t val_4_8(uint32_t hi, uint32_t lo) { + ASSERT0(hi & ~0xf); + ASSERT0(lo & ~0xff); return ((hi << 8) | lo); } static inline int32_t sval_4_8(uint32_t hi, uint32_t lo) { uint32_t tmp = val_4_8(hi, lo); + /* sign extend */ if (tmp & 0x800) return (0xfffff000 | tmp); return (tmp); }
*** 2466,2499 **** dis_s390(uint64_t addr, union inst *inst, char *buf, size_t buflen, int mach) { const struct inst_table *tbl = &tbl_xx[inst->raw[0]]; int tmp; ! while (tbl->fmt == IF_TBL || tbl->fmt == IF_MULTI) { ! if (tbl->fmt == IF_TBL) { int idx; ! idx = inst->raw[tbl->u.table.off]; ! idx >>= tbl->u.table.shift; ! idx &= tbl->u.table.mask; ! ! tbl = &tbl->u.table.ptr[idx]; ! } else if (tbl->fmt == IF_MULTI) { ! tbl = &tbl->u.multi.ptr[mach]; } } ! if (tbl->fmt == IF_INVAL) goto inval; ! if ((tbl->u.inst.flags & mach) == 0) goto inval; ! tmp = snprintf(buf, buflen, "%-7s ", tbl->u.inst.name); ! fmt_fxns[tbl->fmt](addr, inst, buf + tmp, buflen - tmp, ! tbl->u.inst.flags); return (0); inval: (void) snprintf(buf, buflen, "??"); --- 2482,2515 ---- dis_s390(uint64_t addr, union inst *inst, char *buf, size_t buflen, int mach) { const struct inst_table *tbl = &tbl_xx[inst->raw[0]]; int tmp; ! while (tbl->it_fmt == IF_TBL || tbl->it_fmt == IF_MULTI) { ! if (tbl->it_fmt == IF_TBL) { int idx; ! idx = inst->raw[tbl->it_u.it_table.it_off]; ! idx >>= tbl->it_u.it_table.it_shift; ! idx &= tbl->it_u.it_table.it_mask; ! ! tbl = &tbl->it_u.it_table.it_ptr[idx]; ! } else if (tbl->it_fmt == IF_MULTI) { ! tbl = &tbl->it_u.it_multi.it_ptr[mach]; } } ! if (tbl->it_fmt == IF_INVAL) goto inval; ! if ((tbl->it_u.it_inst.it_flags & mach) == 0) goto inval; ! tmp = snprintf(buf, buflen, "%-7s ", tbl->it_u.it_inst.it_name); ! fmt_fxns[tbl->it_fmt](addr, inst, buf + tmp, buflen - tmp, ! tbl->it_u.it_inst.it_flags); return (0); inval: (void) snprintf(buf, buflen, "??");