You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by gs...@apache.org on 2007/10/19 13:08:35 UTC

svn commit: r586378 - in /harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t: dec_base.cpp dec_base.h enc_defs.h

Author: gshimansky
Date: Fri Oct 19 04:08:33 2007
New Revision: 586378

URL: http://svn.apache.org/viewvc?rev=586378&view=rev
Log:
Impelemented REX prefixes parsing for x86_64 instructions


Modified:
    harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/dec_base.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/dec_base.h
    harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_defs.h

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/dec_base.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/dec_base.cpp?rev=586378&r1=586377&r2=586378&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/dec_base.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/dec_base.cpp Fri Oct 19 04:08:33 2007
@@ -25,6 +25,7 @@
  */
 
 #include "dec_base.h"
+#include "open/common.h"
 
 bool DecoderBase::is_prefix(const unsigned char * bytes)
 {
@@ -105,8 +106,15 @@
     return tmp.size;
 }
 
+#ifdef _EM64T_
+#define EXTEND_REG(reg, flag)                        \
+    ((NULL == rex || 0 == rex->flag) ? reg : (reg + 8))
+#else
+#define EXTEND_REG(reg, flag) (reg)
+#endif
+
 bool DecoderBase::decode_aux(const EncoderBase::OpcodeDesc& odesc, unsigned aux,
-             const unsigned char ** pbuf, Inst * pinst) 
+    const unsigned char ** pbuf, Inst * pinst, const Rex UNREF *rex)
 {
     OpcodeByteKind kind = (OpcodeByteKind)(aux & OpcodeByteKind_KindMask);
     unsigned byte = (aux & OpcodeByteKind_OpcodeMask);
@@ -120,15 +128,15 @@
         {
         const ModRM& modrm = *(ModRM*)*pbuf;
         unsigned regIndex = odesc.opnds[0].kind == OpndKind_GPReg ? 0 : 1;
-        RegName reg = getRegName(OpndKind_GPReg, opndDesc.size, modrm.reg);
+        RegName reg = getRegName(OpndKind_GPReg, opndDesc.size, EXTEND_REG(modrm.reg, r));
         EncoderBase::Operand& regOpnd = pinst->operands[regIndex];
         if (regIndex == 0) {
             regOpnd = EncoderBase::Operand(reg);
             ++pinst->argc;
-            decodeModRM(odesc, pbuf, pinst);
+            decodeModRM(odesc, pbuf, pinst, rex);
         }
         else {
-            decodeModRM(odesc, pbuf, pinst);
+            decodeModRM(odesc, pbuf, pinst, rex);
             ++pinst->argc;
             regOpnd = EncoderBase::Operand(reg);
         }
@@ -139,6 +147,9 @@
     case OpcodeByteKind_rw:
     case OpcodeByteKind_rd:
         {
+            // Gregory -
+            // Here we don't parse register because for current needs
+            // disassembler doesn't require to parse all operands
             unsigned regid = data_byte - byte;
             if (regid>7) {
                 return false;
@@ -172,7 +183,7 @@
         if (modrm.reg != byte) {
             return false;
         }
-        decodeModRM(odesc, pbuf, pinst);
+        decodeModRM(odesc, pbuf, pinst, rex);
         ++pinst->argc;
         }
         return true;
@@ -238,6 +249,10 @@
         const EncoderBase::OpcodeDesc& odesc = opcodes[i];
         char *opcode_ptr = const_cast<char *>(odesc.opcode);
         int opcode_len = odesc.opcode_len;
+        Rex *prex = NULL;
+#ifdef _EM64T_
+        Rex rex;
+#endif
 
         *pbuf = save_pbuf;
         if (opcode_len != 0) {
@@ -245,6 +260,8 @@
             // Match REX prefixes
             if (((*pbuf)[0] & 0xf0) == 0x40 && opcode_ptr[0] == 0x48)
             {
+                rex = *(Rex *)*pbuf;
+                prex = &rex;
                 (*pbuf)++;
                 opcode_ptr++;
                 opcode_len--;
@@ -258,11 +275,11 @@
         }
         if (odesc.aux0 != 0) {
             
-            if (!decode_aux(odesc, odesc.aux0, pbuf, pinst)) {
+            if (!decode_aux(odesc, odesc.aux0, pbuf, pinst, prex)) {
                 continue;
             }
             if (odesc.aux1 != 0) {
-                if (!decode_aux(odesc, odesc.aux1, pbuf, pinst)) {
+                if (!decode_aux(odesc, odesc.aux1, pbuf, pinst, prex)) {
                     continue;
                 }
             }
@@ -279,14 +296,8 @@
     return false;
 }
 
-#ifdef _IA32_
-#define DISASM_REG_SIZE OpndSize_32
-#else
-#define DISASM_REG_SIZE OpndSize_64
-#endif
-
 bool DecoderBase::decodeModRM(const EncoderBase::OpcodeDesc& odesc,
-                              const unsigned char ** pbuf, Inst * pinst)
+    const unsigned char ** pbuf, Inst * pinst, const Rex *rex)
 {
     EncoderBase::Operand& opnd = pinst->operands[pinst->argc];
     const EncoderBase::OpndDesc& opndDesc = odesc.opnds[pinst->argc];
@@ -300,13 +311,17 @@
     RegName index = RegName_Null;
     int disp = 0;
     unsigned scale = 0; 
-    //XXX
-    scale=scale; base = base; index = index; disp = disp; reg = reg;
+    OpndSize reg_size = OpndSize_32;
+
+#ifdef _EM64T_
+    if (NULL != rex && 0 != rex->w)
+        reg_size = OpndSize_64;
+#endif
 
-    reg = getRegName(OpndKind_GPReg, DISASM_REG_SIZE, modrm.reg);
+    reg = getRegName(OpndKind_GPReg, reg_size, EXTEND_REG(modrm.reg, r));
     if (modrm.mod == 3) {
         // we have only modrm. no sib, no disp.
-        reg = getRegName(OpndKind_GPReg, opndDesc.size, modrm.rm);
+        reg = getRegName(OpndKind_GPReg, opndDesc.size, EXTEND_REG(modrm.rm, b));
         opnd = EncoderBase::Operand(reg);
         return true;
     }
@@ -320,13 +335,13 @@
             // no index
         }
         else {
-            index = getRegName(OpndKind_GPReg, DISASM_REG_SIZE, sib.index);
+            index = getRegName(OpndKind_GPReg, reg_size, EXTEND_REG(sib.index, x));
         }
-        base = getRegName(OpndKind_GPReg, DISASM_REG_SIZE, sib.base);
+        base = getRegName(OpndKind_GPReg, reg_size, EXTEND_REG(sib.base, b));
     }
     else {
         if (modrm.mod != 0 || modrm.rm != 5) {
-            base = getRegName(OpndKind_GPReg, DISASM_REG_SIZE, modrm.rm);
+            base = getRegName(OpndKind_GPReg, reg_size, EXTEND_REG(modrm.rm, b));
         }
         else {
             // mod=0 && rm == 5 => only disp32

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/dec_base.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/dec_base.h?rev=586378&r1=586377&r2=586378&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/dec_base.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/dec_base.h Fri Oct 19 04:08:33 2007
@@ -93,10 +93,10 @@
     static unsigned decode(const void * addr, Inst * pinst);
 private:
     static bool decodeModRM(const EncoderBase::OpcodeDesc& odesc,
-                            const unsigned char ** pbuf, Inst * pinst);
+        const unsigned char ** pbuf, Inst * pinst, const Rex *rex);
     static bool decode_aux(const EncoderBase::OpcodeDesc& odesc,
-                        unsigned aux, const unsigned char ** pbuf, 
-                        Inst * pinst);
+        unsigned aux, const unsigned char ** pbuf, 
+        Inst * pinst, const Rex *rex);
     static bool try_mn(Mnemonic mn, const unsigned char ** pbuf, Inst * pinst);
 
     static bool is_prefix(const unsigned char * bytes);

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_defs.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_defs.h?rev=586378&r1=586377&r2=586378&view=diff
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_defs.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_defs.h Fri Oct 19 04:08:33 2007
@@ -158,6 +158,11 @@
 
 #define REGNAME(k,s,i) ( ((k & OpndKind_Any)<<24) | ((s & OpndSize_Any)<<16) | (i&0xFF) )
 
+// Gregory -
+// It is critical that all register indexes (3rd number) inside of the
+// following table go in ascending order. That is R8 goes after
+// RDI. It is necessary for decoder when extending registers from RAX-DRI
+// to R8-R15 by simply adding 8 to the index on EM64T architecture
 enum RegName {
 
     RegName_Null = 0, 
@@ -207,16 +212,6 @@
     RegName_R13D = REGNAME(OpndKind_GPReg,OpndSize_32,13),
     RegName_R14D = REGNAME(OpndKind_GPReg,OpndSize_32,14),
     RegName_R15D = REGNAME(OpndKind_GPReg,OpndSize_32,15),
-
-    RegName_R8S  = REGNAME(OpndKind_GPReg,OpndSize_16,8),
-    RegName_R9S  = REGNAME(OpndKind_GPReg,OpndSize_16,9),
-    RegName_R10S = REGNAME(OpndKind_GPReg,OpndSize_16,10),
-    RegName_R11S = REGNAME(OpndKind_GPReg,OpndSize_16,11),
-    RegName_R12S = REGNAME(OpndKind_GPReg,OpndSize_16,12),
-    RegName_R13S = REGNAME(OpndKind_GPReg,OpndSize_16,13),
-    RegName_R14S = REGNAME(OpndKind_GPReg,OpndSize_16,14),
-    RegName_R15S = REGNAME(OpndKind_GPReg,OpndSize_16,15),
-
 #endif //~_EM64T_
 
     RegName_AX=REGNAME(OpndKind_GPReg,OpndSize_16,0),
@@ -227,12 +222,25 @@
     RegName_BP=REGNAME(OpndKind_GPReg,OpndSize_16,5),
     RegName_SI=REGNAME(OpndKind_GPReg,OpndSize_16,6),
     RegName_DI=REGNAME(OpndKind_GPReg,OpndSize_16,7),
+
+#ifdef _EM64T_
+    RegName_R8S  = REGNAME(OpndKind_GPReg,OpndSize_16,8),
+    RegName_R9S  = REGNAME(OpndKind_GPReg,OpndSize_16,9),
+    RegName_R10S = REGNAME(OpndKind_GPReg,OpndSize_16,10),
+    RegName_R11S = REGNAME(OpndKind_GPReg,OpndSize_16,11),
+    RegName_R12S = REGNAME(OpndKind_GPReg,OpndSize_16,12),
+    RegName_R13S = REGNAME(OpndKind_GPReg,OpndSize_16,13),
+    RegName_R14S = REGNAME(OpndKind_GPReg,OpndSize_16,14),
+    RegName_R15S = REGNAME(OpndKind_GPReg,OpndSize_16,15),
+#endif //~_EM64T_
     
     RegName_AL=REGNAME(OpndKind_GPReg,OpndSize_8,0),
     RegName_CL=REGNAME(OpndKind_GPReg,OpndSize_8,1),
     RegName_DL=REGNAME(OpndKind_GPReg,OpndSize_8,2),
     RegName_BL=REGNAME(OpndKind_GPReg,OpndSize_8,3),
-    // Used in enc_tabl.cpp
+    // FIXME: Used in enc_tabl.cpp
+    // AH is not accessible on EM64T, instead encoded register is SPL, so decoded
+    // register will return incorrect enum
     RegName_AH=REGNAME(OpndKind_GPReg,OpndSize_8,4),
 #if !defined(_EM64T_)    
     RegName_CH=REGNAME(OpndKind_GPReg,OpndSize_8,5),