diff options
author | H. Peter Anvin <hpa@zytor.com> | 2009-06-24 21:38:29 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2009-06-24 21:38:29 -0700 |
commit | 9472dab6ed91507235a4ba4031566bc5c2a0df39 (patch) | |
tree | 73e5f5c185280687e8a4643246a05c87e36725f0 | |
parent | f9fc3fde55dc6b3008103fed1cc5173da22d2dac (diff) | |
download | nasm-9472dab6ed91507235a4ba4031566bc5c2a0df39.tar.gz nasm-9472dab6ed91507235a4ba4031566bc5c2a0df39.tar.bz2 nasm-9472dab6ed91507235a4ba4031566bc5c2a0df39.zip |
Add support for instructions which always use low 8-bit registers
Add a byte code to explicitly support instructions which only uses the
low 8-bit registers (as if a REX prefix always was present.) This is
usable for instructions which are officially documented as using "the
low byte of a 32-bit register" and so on.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r-- | assemble.c | 18 | ||||
-rw-r--r-- | disasm.c | 8 | ||||
-rw-r--r-- | nasm.h | 1 |
3 files changed, 24 insertions, 3 deletions
@@ -88,13 +88,14 @@ * generates no code in the assembler) * \323 - indicates fixed 64-bit operand size, REX on extensions only. * \324 - indicates 64-bit operand size requiring REX prefix. + * \325 - instruction which always uses spl/bpl/sil/dil * \330 - a literal byte follows in the code stream, to be added * to the condition code value of the instruction. * \331 - instruction not valid with REP prefix. Hint for * disassembler only; for SSE instructions. * \332 - REP prefix (0xF2 byte) used as opcode extension. * \333 - REP prefix (0xF3 byte) used as opcode extension. - * \334 - LOCK prefix used instead of REX.R + * \334 - LOCK prefix used as REX.R (used in non-64-bit mode) * \335 - disassemble a rep (0xF3 byte) prefix as repe not rep. * \336 - force a REP(E) prefix (0xF2) even if not specified. * \337 - force a REPNE prefix (0xF3) even if not specified. @@ -996,6 +997,10 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits, ins->rex |= REX_W; break; + case 0325: + ins->rex |= REX_NH; + break; + case 0330: codes++, length++; break; @@ -1117,6 +1122,14 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits, ins->rex &= rex_mask; + if (ins->rex & REX_NH) { + if (ins->rex & REX_H) { + errfunc(ERR_NONFATAL, "instruction cannot use high registers"); + return -1; + } + ins->rex &= ~REX_P; /* Don't force REX prefix due to high reg */ + } + if (ins->rex & REX_V) { int bad32 = REX_R|REX_W|REX_X|REX_B; @@ -1645,6 +1658,9 @@ static void gencode(int32_t segment, int64_t offset, int bits, ins->rex |= REX_W; break; + case 0325: + break; + case 0330: *bytes = *codes++ ^ condval[ins->condition]; out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG); @@ -135,7 +135,7 @@ static enum reg_enum whichreg(int32_t regflags, int regval, int rex) return 0; if (!(REG8 & ~regflags)) { - if (rex & REX_P) + if (rex & (REX_P|REX_NH)) return nasm_rd_reg8_rex[regval]; else return nasm_rd_reg8[regval]; @@ -153,7 +153,7 @@ static enum reg_enum whichreg(int32_t regflags, int regval, int rex) if (!(REG_DREG & ~regflags)) return nasm_rd_dreg[regval]; if (!(REG_TREG & ~regflags)) { - if (rex & REX_P) + if (regval > 7) return 0; /* TR registers are ill-defined with rex */ return nasm_rd_treg[regval]; } @@ -799,6 +799,10 @@ static int matches(const struct itemplate *t, uint8_t *data, o_used = true; break; + case 0325: + ins->rex |= REX_NH; + break; + case 0330: { int t = *r++, d = *data++; @@ -600,6 +600,7 @@ enum ccode { /* condition code names */ #define REX_D 0x0100 /* Instruction uses DREX instead of REX */ #define REX_OC 0x0200 /* DREX suffix has the OC0 bit set */ #define REX_V 0x0400 /* Instruction uses VEX/XOP instead of REX */ +#define REX_NH 0x0800 /* Instruction which doesn't use high regs */ /* * REX_V "classes" (prefixes which behave like VEX) |