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, "??");