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>
This commit is contained in:
H. Peter Anvin 2016-09-20 16:39:46 -07:00
parent ae707bace4
commit 976ba73062

View file

@ -1435,6 +1435,7 @@ static void gencode(int32_t segment, int64_t offset, int bits,
const uint8_t *codes = temp->code; const uint8_t *codes = temp->code;
uint8_t opex = 0; uint8_t opex = 0;
enum ea_type eat = EA_SCALAR; enum ea_type eat = EA_SCALAR;
int r;
ins->rex_done = false; ins->rex_done = false;
@ -1607,36 +1608,36 @@ static void gencode(int32_t segment, int64_t offset, int bits,
break; break;
case 0172: case 0172:
{
int mask = ins->prefixes[PPS_VEX] == P_EVEX ? 7 : 15;
const struct operand *opy;
c = *codes++; c = *codes++;
opx = &ins->oprs[c >> 3]; opx = &ins->oprs[c >> 3];
bytes[0] = nasm_regvals[opx->basereg] << 4; opy = &ins->oprs[c & 7];
opx = &ins->oprs[c & 7]; if (opy->segment != NO_SEG || opy->wrt != NO_SEG) {
if (opx->segment != NO_SEG || opx->wrt != NO_SEG) {
nasm_error(ERR_NONFATAL, nasm_error(ERR_NONFATAL,
"non-absolute expression not permitted as argument %d", "non-absolute expression not permitted as argument %d",
c & 7); c & 7);
} else { } else if (opy->offset & ~mask) {
if (opx->offset & ~15) { nasm_error(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV,
nasm_error(ERR_WARNING | ERR_PASS2 | ERR_WARN_NOV, "is4 argument exceeds bounds");
"four-bit argument exceeds bounds");
}
bytes[0] |= opx->offset & 15;
} }
out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG); c = opy->offset & mask;
offset++; goto emit_is4;
break; }
case 0173: case 0173:
c = *codes++; c = *codes++;
opx = &ins->oprs[c >> 4]; opx = &ins->oprs[c >> 4];
bytes[0] = nasm_regvals[opx->basereg] << 4; c &= 15;
bytes[0] |= c & 15; goto emit_is4;
out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
offset++;
break;
case4(0174): 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); out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG);
offset++; offset++;
break; break;