Print this page
patch fixups
@@ -14,10 +14,11 @@
*/
#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,11 +69,11 @@
* 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
+ * 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,10 +94,14 @@
* 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,24 +184,24 @@
/* 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;
+ 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,28 +533,28 @@
uint8_t d2l;
} ssf;
};
#define INSTR(op, m, fm, fl) [op] = { \
- .u.inst = { \
- .name = (m), \
- .flags = (fl), \
+ .it_u.it_inst = { \
+ .it_name = (m), \
+ .it_flags = (fl), \
}, \
- .fmt = (fm), \
+ .it_fmt = (fm), \
}
#define TABLE(op, tbl, o, s, m) [op] = { \
- .u.table = { \
- .ptr = (tbl), \
- .off = (o), \
- .shift = (s), \
- .mask = (m), \
+ .it_u.it_table = { \
+ .it_ptr = (tbl), \
+ .it_off = (o), \
+ .it_shift = (s), \
+ .it_mask = (m), \
}, \
- .fmt = IF_TBL, \
+ .it_fmt = IF_TBL, \
}
#define MULTI(op, tbl) [op] = { \
- .u.multi.ptr = (tbl), \
- .fmt = IF_MULTI, \
+ .it_u.it_multi.it_ptr = (tbl), \
+ .it_fmt = IF_MULTI, \
}
/*
* Instruction tables based on:
* GA22-7000-4 System/370 Principles of Operation
@@ -1788,16 +1793,21 @@
#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,34 +1816,40 @@
}
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,34 +2482,34 @@
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) {
+ while (tbl->it_fmt == IF_TBL || tbl->it_fmt == IF_MULTI) {
+ if (tbl->it_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];
+ 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->fmt == IF_INVAL)
+ if (tbl->it_fmt == IF_INVAL)
goto inval;
- if ((tbl->u.inst.flags & mach) == 0)
+ if ((tbl->it_u.it_inst.it_flags & mach) == 0)
goto inval;
- tmp = snprintf(buf, buflen, "%-7s ", tbl->u.inst.name);
+ tmp = snprintf(buf, buflen, "%-7s ", tbl->it_u.it_inst.it_name);
- fmt_fxns[tbl->fmt](addr, inst, buf + tmp, buflen - tmp,
- tbl->u.inst.flags);
+ 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, "??");