diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2016-09-20 16:39:46 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2016-09-20 16:39:46 -0700 |
commit | 976ba730622ae7c2d5e88d4fb4477ff96c1cd3f4 (patch) | |
tree | a3116c52af810d46b5b49a4285a058ed04527c05 | |
parent | ae707bace4406788714597ec5b4f1a427c9ad9c7 (diff) | |
download | nasm-976ba730622ae7c2d5e88d4fb4477ff96c1cd3f4.tar.gz |
Correct /is4 encoding for EVEX instructions
For EVEX instructions, /is4 can contain a fifth register bit, encoded
in bit 3 of the imm8. Properly generate this case, and simplifiy the
/is4 generation code somewhat.
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r-- | assemble.c | 37 |
1 files changed, 19 insertions, 18 deletions
@@ -1435,6 +1435,7 @@ static void gencode(int32_t segment, int64_t offset, int bits, const uint8_t *codes = temp->code; uint8_t opex = 0; enum ea_type eat = EA_SCALAR; + int r; ins->rex_done = false; @@ -1607,36 +1608,36 @@ static void gencode(int32_t segment, int64_t offset, int bits, break; case 0172: + { + int mask = ins->prefixes[PPS_VEX] == P_EVEX ? 7 : 15; + const struct operand *opy; + c = *codes++; opx = &ins->oprs[c >> 3]; - bytes[0] = nasm_regvals[opx->basereg] << 4; - opx = &ins->oprs[c & 7]; - if (opx->segment != NO_SEG || opx->wrt != NO_SEG) { + opy = &ins->oprs[c & 7]; + if (opy->segment != NO_SEG || opy->wrt != NO_SEG) { nasm_error(ERR_NONFATAL, "non-absolute expression not permitted as argument %d", c & 7); - } else { - if (opx->offset & ~15) { - nasm_error(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV, - "four-bit argument exceeds bounds"); - } - bytes[0] |= opx->offset & 15; + } else if (opy->offset & ~mask) { + nasm_error(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV, + "is4 argument exceeds bounds"); } - out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG); - offset++; - break; + c = opy->offset & mask; + goto emit_is4; + } case 0173: c = *codes++; opx = &ins->oprs[c >> 4]; - bytes[0] = nasm_regvals[opx->basereg] << 4; - bytes[0] |= c & 15; - out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG); - offset++; - break; + c &= 15; + goto emit_is4; case4(0174): - bytes[0] = nasm_regvals[opx->basereg] << 4; + c = 0; + emit_is4: + r = nasm_regvals[opx->basereg]; + bytes[0] = (r << 4) | ((r & 0x10) >> 1) | c; out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG); offset++; break; |