Add support for instructions which always use low 8-bit registers
authorH. Peter Anvin <hpa@zytor.com>
Thu, 25 Jun 2009 04:38:29 +0000 (21:38 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Thu, 25 Jun 2009 04:38:29 +0000 (21:38 -0700)
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>
assemble.c
disasm.c
nasm.h

index b72e5a6..705ae27 100644 (file)
  *                 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);
index a48a015..0c13635 100644 (file)
--- a/disasm.c
+++ b/disasm.c
@@ -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++;
diff --git a/nasm.h b/nasm.h
index e2677c2..5e0c017 100644 (file)
--- a/nasm.h
+++ b/nasm.h
@@ -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)