summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJin Kyu Song <jin.kyu.song@intel.com>2013-11-19 18:43:04 -0800
committerJin Kyu Song <jin.kyu.song@intel.com>2013-11-20 11:29:42 -0800
commit5f80dace3a2b15ecc07d07d8ce37bac6cb5f1d4c (patch)
treeb058a667354482fa6b6cefc54f39bffafd7835b0
parent6076e8f3354529fbb0cf7be3cff01d9be2c39dbd (diff)
downloadnasm-5f80dace3a2b15ecc07d07d8ce37bac6cb5f1d4c.tar.gz
disasm: Add EVEX decorator syntax
Broadcasting, opmask, embedded rounding and SAE decorators are not added at proper position. Signed-off-by: Jin Kyu Song <jin.kyu.song@intel.com>
-rw-r--r--disasm.c101
1 files changed, 92 insertions, 9 deletions
diff --git a/disasm.c b/disasm.c
index 49c3051a..50a49c54 100644
--- a/disasm.c
+++ b/disasm.c
@@ -266,6 +266,71 @@ static uint8_t get_disp8N(insn *ins)
return n;
}
+static uint32_t append_evex_reg_deco(char *buf, uint32_t num,
+ decoflags_t deco, uint8_t *evex)
+{
+ const char * const er_names[] = {"rn-sae", "rd-sae", "ru-sae", "rz-sae"};
+ uint32_t num_chars = 0;
+
+ if ((deco & MASK) && (evex[2] & EVEX_P2AAA)) {
+ enum reg_enum opmasknum = nasm_rd_opmaskreg[evex[2] & EVEX_P2AAA];
+ const char * regname = nasm_reg_names[opmasknum - EXPR_REG_START];
+
+ num_chars += snprintf(buf + num_chars, num - num_chars,
+ "{%s}", regname);
+
+ if ((deco & Z) && (evex[2] & EVEX_P2Z)) {
+ num_chars += snprintf(buf + num_chars, num - num_chars,
+ "{z}");
+ }
+ }
+
+ if (evex[2] & EVEX_P2B) {
+ if (deco & ER) {
+ uint8_t er_type = (evex[2] & EVEX_P2LL) >> 5;
+ num_chars += snprintf(buf + num_chars, num - num_chars,
+ ",{%s}", er_names[er_type]);
+ } else if (deco & SAE) {
+ num_chars += snprintf(buf + num_chars, num - num_chars,
+ ",{sae}");
+ }
+ }
+
+ return num_chars;
+}
+
+static uint32_t append_evex_mem_deco(char *buf, uint32_t num, opflags_t type,
+ decoflags_t deco, uint8_t *evex)
+{
+ uint32_t num_chars = 0;
+
+ if ((evex[2] & EVEX_P2B) && (deco & BRDCAST_MASK)) {
+ decoflags_t deco_brsize = deco & BRSIZE_MASK;
+ opflags_t template_opsize = (deco_brsize == BR_BITS32 ? BITS32 : BITS64);
+ uint8_t br_num = (type & SIZE_MASK) / BITS128 *
+ BITS64 / template_opsize * 2;
+
+ num_chars += snprintf(buf + num_chars, num - num_chars,
+ "{1to%d}", br_num);
+ }
+
+ if ((deco & MASK) && (evex[2] & EVEX_P2AAA)) {
+ enum reg_enum opmasknum = nasm_rd_opmaskreg[evex[2] & EVEX_P2AAA];
+ const char * regname = nasm_reg_names[opmasknum - EXPR_REG_START];
+
+ num_chars += snprintf(buf + num_chars, num - num_chars,
+ "{%s}", regname);
+
+ if ((deco & Z) && (evex[2] & EVEX_P2Z)) {
+ num_chars += snprintf(buf + num_chars, num - num_chars,
+ "{z}");
+ }
+ }
+
+
+ return num_chars;
+}
+
/*
* Process an effective address (ModRM) specification.
*/
@@ -1382,6 +1447,7 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
length += data - origdata; /* fix up for prefixes */
for (i = 0; i < (*p)->operands; i++) {
opflags_t t = (*p)->opd[i];
+ decoflags_t deco = (*p)->deco[i];
const operand *o = &ins.oprs[i];
int64_t offs;
@@ -1418,6 +1484,9 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
slen += snprintf(output + slen, outbufsize - slen, "to ");
slen += snprintf(output + slen, outbufsize - slen, "%s",
nasm_reg_names[reg-EXPR_REG_START]);
+ if (is_evex && deco)
+ slen += append_evex_reg_deco(output + slen, outbufsize - slen,
+ deco, ins.evex_p);
} else if (!(UNITY & ~t)) {
output[slen++] = '1';
} else if (t & IMMEDIATE) {
@@ -1477,15 +1546,25 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
if (t & BITS80)
slen +=
snprintf(output + slen, outbufsize - slen, "tword ");
- if (t & BITS128)
- slen +=
- snprintf(output + slen, outbufsize - slen, "oword ");
- if (t & BITS256)
- slen +=
- snprintf(output + slen, outbufsize - slen, "yword ");
- if (t & BITS512)
- slen +=
- snprintf(output + slen, outbufsize - slen, "zword ");
+ if ((ins.evex_p[2] & EVEX_P2B) && (deco & BRDCAST_MASK)) {
+ /* when broadcasting, each element size should be used */
+ if (deco & BR_BITS32)
+ slen +=
+ snprintf(output + slen, outbufsize - slen, "dword ");
+ else if (deco & BR_BITS64)
+ slen +=
+ snprintf(output + slen, outbufsize - slen, "qword ");
+ } else {
+ if (t & BITS128)
+ slen +=
+ snprintf(output + slen, outbufsize - slen, "oword ");
+ if (t & BITS256)
+ slen +=
+ snprintf(output + slen, outbufsize - slen, "yword ");
+ if (t & BITS512)
+ slen +=
+ snprintf(output + slen, outbufsize - slen, "zword ");
+ }
if (t & FAR)
slen += snprintf(output + slen, outbufsize - slen, "far ");
if (t & NEAR)
@@ -1602,6 +1681,10 @@ int32_t disasm(uint8_t *data, char *output, int outbufsize, int segsize,
}
output[slen++] = ']';
+
+ if (is_evex && deco)
+ slen += append_evex_mem_deco(output + slen, outbufsize - slen,
+ t, deco, ins.evex_p);
} else {
slen +=
snprintf(output + slen, outbufsize - slen, "<operand%d>",