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:
parent
ae707bace4
commit
976ba73062
1 changed files with 19 additions and 18 deletions
37
assemble.c
37
assemble.c
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue