hotspot/agent/src/share/classes/sun/jvm/hotspot/asm/x86/InstructionDecoder.java
changeset 13909 9b94bf4dcc0c
parent 13908 6fa036b39eb9
parent 13907 52873e4bbeaa
child 13911 e59cfb5f223b
equal deleted inserted replaced
13908:6fa036b39eb9 13909:9b94bf4dcc0c
     1 /*
       
     2  * Copyright (c) 2002, 2003, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  *
       
    23  */
       
    24 
       
    25 package sun.jvm.hotspot.asm.x86;
       
    26 
       
    27 import sun.jvm.hotspot.asm.*;
       
    28 
       
    29 // basic instruction decoder class
       
    30 public class InstructionDecoder implements /* imports */ X86Opcodes , RTLDataTypes, RTLOperations {
       
    31 
       
    32    protected String name;
       
    33    protected int addrMode1;
       
    34    protected int operandType1;
       
    35    protected int addrMode2;
       
    36    protected int operandType2;
       
    37    protected int addrMode3;
       
    38    protected int operandType3;
       
    39 
       
    40    private int mod;
       
    41    private int regOrOpcode;
       
    42    private int rm;
       
    43    protected int prefixes;
       
    44 
       
    45    protected int byteIndex;
       
    46    protected int instrStartIndex;
       
    47 
       
    48    public InstructionDecoder(String name) {
       
    49       this.name = name;
       
    50       this.operandType1 = INVALID_OPERANDTYPE;
       
    51       this.operandType2 = INVALID_OPERANDTYPE;
       
    52       this.operandType3 = INVALID_OPERANDTYPE;
       
    53       this.addrMode1 = INVALID_ADDRMODE;
       
    54       this.addrMode2 = INVALID_ADDRMODE;
       
    55       this.addrMode3 = INVALID_ADDRMODE;
       
    56    }
       
    57    public InstructionDecoder(String name, int addrMode1, int operandType1) {
       
    58       this(name);
       
    59       this.addrMode1 = addrMode1;
       
    60       this.operandType1 = operandType1;
       
    61    }
       
    62    public InstructionDecoder(String name, int addrMode1, int operandType1, int addrMode2, int operandType2) {
       
    63       this(name, addrMode1, operandType1);
       
    64       this.addrMode2 = addrMode2;
       
    65       this.operandType2 = operandType2;
       
    66    }
       
    67    public InstructionDecoder(String name, int addrMode1, int operandType1, int addrMode2, int operandType2,
       
    68                                        int addrMode3, int operandType3) {
       
    69       this(name, addrMode1, operandType1, addrMode2, operandType2);
       
    70       this.addrMode3 = addrMode3;
       
    71       this.operandType3 = operandType3;
       
    72    }
       
    73    // "operand1"
       
    74    protected Operand getOperand1(byte[] bytesArray, boolean operandSize, boolean addrSize) {
       
    75       if( (addrMode1 != INVALID_ADDRMODE) && (operandType1 != INVALID_OPERANDTYPE) )
       
    76          return getOperand(bytesArray, addrMode1, operandType1, operandSize, addrSize);
       
    77       else
       
    78          return null;
       
    79    }
       
    80 
       
    81    // "operand2"
       
    82    protected Operand getOperand2(byte[] bytesArray, boolean operandSize, boolean addrSize) {
       
    83       if( (addrMode2 != INVALID_ADDRMODE) && (operandType2 != INVALID_OPERANDTYPE) )
       
    84          return getOperand(bytesArray, addrMode2, operandType2, operandSize, addrSize);
       
    85       else
       
    86          return null;
       
    87    }
       
    88 
       
    89    // "operand3"
       
    90    protected Operand getOperand3(byte[] bytesArray, boolean operandSize, boolean addrSize) {
       
    91       if( (addrMode3 != INVALID_ADDRMODE) && (operandType3 != INVALID_OPERANDTYPE) )
       
    92          return getOperand(bytesArray, addrMode3, operandType3, operandSize, addrSize);
       
    93       else
       
    94          return null;
       
    95    }
       
    96 
       
    97    static int readInt32(byte[] bytesArray, int index) {
       
    98       int ret = 0;
       
    99       ret = readByte(bytesArray, index);
       
   100       ret |= readByte(bytesArray, index+1) << 8;
       
   101       ret |= readByte(bytesArray, index+2) << 16;
       
   102       ret |= readByte(bytesArray, index+3) << 24;
       
   103       return ret;
       
   104    }
       
   105    static int readInt16(byte[] bytesArray, int index) {
       
   106       int ret = 0;
       
   107       ret = readByte(bytesArray, index);
       
   108       ret |= readByte(bytesArray, index+1) << 8;
       
   109       return ret;
       
   110    }
       
   111    static int readByte(byte[] bytesArray, int index) {
       
   112       int ret = 0;
       
   113       if (index < bytesArray.length) {
       
   114          ret = (int)bytesArray[index];
       
   115          ret = ret & 0xff;
       
   116       }
       
   117       return ret;
       
   118    }
       
   119    private boolean isModRMPresent(int addrMode) {
       
   120       if( (addrMode == ADDR_E) || (addrMode == ADDR_G) || (addrMode == ADDR_FPREG) || (addrMode == ADDR_Q) || (addrMode == ADDR_W) )
       
   121          return true;
       
   122       else
       
   123          return false;
       
   124    }
       
   125    public int getCurrentIndex() {
       
   126       return byteIndex;
       
   127    }
       
   128 
       
   129    public Instruction decode(byte[] bytesArray, int index, int instrStartIndex, int segmentOverride, int prefixes, X86InstructionFactory factory) {
       
   130       this.byteIndex = index;
       
   131       this.instrStartIndex = instrStartIndex;
       
   132       this.prefixes = prefixes;
       
   133       boolean operandSize; //operand-size prefix
       
   134       boolean addrSize;    //address-size prefix
       
   135       if ( ( (prefixes & PREFIX_DATA) ^ segmentOverride ) == 1)
       
   136          operandSize = true;
       
   137       else
       
   138          operandSize = false;
       
   139       if ( ((prefixes & PREFIX_ADR) ^ segmentOverride) == 1)
       
   140          addrSize = true;
       
   141       else
       
   142          addrSize = false;
       
   143       this.name = getCorrectOpcodeName(name, prefixes, operandSize, addrSize);
       
   144 
       
   145       //Fetch the mod/reg/rm byte only if it is present.
       
   146       if( isModRMPresent(addrMode1) || isModRMPresent(addrMode2) || isModRMPresent(addrMode3) ) {
       
   147 
       
   148          int ModRM = readByte(bytesArray, byteIndex);
       
   149          byteIndex++;
       
   150          mod = (ModRM >> 6) & 3;
       
   151          regOrOpcode = (ModRM >> 3) & 7;
       
   152          rm = ModRM & 7;
       
   153       }
       
   154       return decodeInstruction(bytesArray, operandSize, addrSize, factory);
       
   155    }
       
   156 
       
   157    protected Instruction decodeInstruction(byte[] bytesArray, boolean operandSize, boolean addrSize, X86InstructionFactory factory) {
       
   158       Operand op1 = getOperand1(bytesArray, operandSize, addrSize);
       
   159       Operand op2 = getOperand2(bytesArray, operandSize, addrSize);
       
   160       Operand op3 = getOperand3(bytesArray, operandSize, addrSize);
       
   161       int size = byteIndex - instrStartIndex;
       
   162       return factory.newGeneralInstruction(name, op1, op2, op3, size, prefixes);
       
   163    }
       
   164 
       
   165    // capital letters in template are macros
       
   166    private String getCorrectOpcodeName(String oldName, int prefixes, boolean operandSize, boolean addrSize) {
       
   167       StringBuffer newName = new StringBuffer(oldName);
       
   168       int index = 0;
       
   169       for(index=0; index<oldName.length(); index++) {
       
   170          switch (oldName.charAt(index)) {
       
   171             case 'C':           /* For jcxz/jecxz */
       
   172                if (addrSize)
       
   173                   newName.setCharAt(index, 'e');
       
   174                index++;
       
   175                break;
       
   176             case 'N':
       
   177                if ((prefixes & PREFIX_FWAIT) == 0)
       
   178                   newName.setCharAt(index, 'n');
       
   179                index++;
       
   180                break;
       
   181             case 'S':
       
   182             /* operand size flag */
       
   183                if (operandSize == true)
       
   184                   newName.setCharAt(index, 'l');
       
   185                else
       
   186                   newName.setCharAt(index, 'w');
       
   187                index++;
       
   188                break;
       
   189             default:
       
   190                break;
       
   191          }
       
   192       }
       
   193       return newName.toString();
       
   194    }
       
   195 
       
   196    //IA-32 Intel Architecture Software Developer's Manual Volume 2
       
   197    //Refer to Chapter 2 - Instruction Format
       
   198 
       
   199    //Get the Operand object from the address type and the operand type
       
   200    private Operand getOperand(byte[] bytesArray, int addrMode, int operandType, boolean operandSize, boolean addrSize) {
       
   201       Operand op = null;
       
   202       switch(addrMode) {
       
   203          case ADDR_E:
       
   204          case ADDR_W:   //SSE: ModR/M byte specifies either 128 bit XMM register or memory
       
   205          case ADDR_Q:   //SSE: ModR/M byte specifies either 128 bit MMX register or memory
       
   206             X86SegmentRegister segReg = getSegmentRegisterFromPrefix(prefixes);
       
   207 
       
   208             if (mod == 3) {    //Register operand, no SIB follows
       
   209                if (addrMode == ADDR_E) {
       
   210                   switch (operandType) {
       
   211                      case b_mode:
       
   212                         op = X86Registers.getRegister8(rm);
       
   213                         break;
       
   214                      case w_mode:
       
   215                         op = X86Registers.getRegister16(rm);
       
   216                         break;
       
   217                      case v_mode:
       
   218                         if (operandSize == true) //Operand size prefix is present
       
   219                            op = X86Registers.getRegister32(rm);
       
   220                         else
       
   221                            op = X86Registers.getRegister16(rm);
       
   222                         break;
       
   223                      case p_mode:
       
   224                         X86Register reg;
       
   225                         if (operandSize == true) //Operand size prefix is present
       
   226                            reg = X86Registers.getRegister32(rm);
       
   227                         else
       
   228                            reg = X86Registers.getRegister16(rm);
       
   229 
       
   230                         op = new X86RegisterIndirectAddress(segReg, reg, null, 0);
       
   231                         break;
       
   232                      default:
       
   233                         break;
       
   234                   }
       
   235                } else if (addrMode == ADDR_W) {
       
   236                   op = X86XMMRegisters.getRegister(rm);
       
   237                } else if (addrMode == ADDR_Q) {
       
   238                   op = X86MMXRegisters.getRegister(rm);
       
   239                }
       
   240 
       
   241             } else {   //mod != 3
       
   242                //SIB follows for (rm==4), SIB gives scale, index and base in this case
       
   243                //disp32 is present for (mod==0 && rm==5) || (mod==2)
       
   244                //disp8 is present for (mod==1)
       
   245                //for (rm!=4) base is register at rm.
       
   246                int scale = 0;
       
   247                int index = 0;
       
   248                int base = 0;
       
   249                long disp = 0;
       
   250                if(rm == 4) {
       
   251                   int sib = readByte(bytesArray, byteIndex);
       
   252                   byteIndex++;
       
   253                   scale = (sib >> 6) & 3;
       
   254                   index = (sib >> 3) & 7;
       
   255                   base = sib & 7;
       
   256                }
       
   257 
       
   258                switch (mod) {
       
   259                   case 0:
       
   260                      switch(rm) {
       
   261                         case 4:
       
   262                            if(base == 5) {
       
   263                               disp = readInt32(bytesArray, byteIndex);
       
   264                               byteIndex += 4;
       
   265                               if (index != 4) {
       
   266                                  op = new X86RegisterIndirectAddress(segReg, null, X86Registers.getRegister32(index), disp, scale);
       
   267                               } else {
       
   268                                  op = new X86RegisterIndirectAddress(segReg, null, null, disp, scale);
       
   269                               }
       
   270                            }
       
   271                            else {
       
   272                               if (index != 4) {
       
   273                                  op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), X86Registers.getRegister32(index), 0, scale);
       
   274                               } else {
       
   275                                  op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), null, 0, scale);
       
   276                               }
       
   277                            }
       
   278                            break;
       
   279                         case 5:
       
   280                            disp = readInt32(bytesArray, byteIndex);
       
   281                            byteIndex += 4;
       
   282                            //Create an Address object only with displacement
       
   283                            op = new X86RegisterIndirectAddress(segReg, null, null, disp);
       
   284                            break;
       
   285                         default:
       
   286                            base = rm;
       
   287                            //Create an Address object only with base
       
   288                            op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), null, 0);
       
   289                            break;
       
   290                         }
       
   291                         break;
       
   292                   case 1:
       
   293                      disp = (byte)readByte(bytesArray, byteIndex);
       
   294                      byteIndex++;
       
   295                      if (rm !=4) {
       
   296                         base = rm;
       
   297                         //Address with base and disp only
       
   298                         op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), null, disp);
       
   299                      } else {
       
   300                         if (index != 4) {
       
   301                            op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), X86Registers.getRegister32(index), disp, scale);
       
   302                         } else {
       
   303                            op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), null, disp, scale);
       
   304                         }
       
   305                      }
       
   306                      break;
       
   307                   case 2:
       
   308                      disp = readInt32(bytesArray, byteIndex);
       
   309                      byteIndex += 4;
       
   310                      if (rm !=4) {
       
   311                         base = rm;
       
   312                         //Address with base and disp
       
   313                         op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), null, disp);
       
   314                      } else if (index != 4) {
       
   315                         op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), X86Registers.getRegister32(index), disp, scale);
       
   316                      } else {
       
   317                         op = new X86RegisterIndirectAddress(segReg, X86Registers.getRegister32(base), null, disp, scale);
       
   318                      }
       
   319                      break;
       
   320                }
       
   321             }
       
   322             break;
       
   323 
       
   324          case ADDR_I:
       
   325             switch (operandType) {
       
   326                case b_mode:
       
   327                   op = new Immediate(new Integer(readByte(bytesArray, byteIndex)));
       
   328                   byteIndex++;
       
   329                   break;
       
   330                case w_mode:
       
   331                   op = new Immediate(new Integer(readInt16(bytesArray, byteIndex)));
       
   332                   byteIndex += 2;
       
   333                   break;
       
   334                case v_mode:
       
   335                   if (operandSize == true) { //Operand size prefix is present
       
   336                      op = new Immediate(new Integer(readInt32(bytesArray, byteIndex)));
       
   337                      byteIndex += 4;
       
   338                   } else {
       
   339                      op = new Immediate(new Integer(readInt16(bytesArray, byteIndex)));
       
   340                      byteIndex += 2;
       
   341                   }
       
   342                   break;
       
   343                default:
       
   344                   break;
       
   345             }
       
   346             break;
       
   347          case ADDR_REG: //registers
       
   348             switch(operandType) {
       
   349                case EAX:
       
   350                case ECX:
       
   351                case EDX:
       
   352                case EBX:
       
   353                case ESP:
       
   354                case EBP:
       
   355                case ESI:
       
   356                case EDI:
       
   357                   if(operandSize == true) {
       
   358                      op = X86Registers.getRegister32(operandType - EAX);
       
   359                   }
       
   360                   else {
       
   361                      op = X86Registers.getRegister16(operandType - EAX);
       
   362                   }
       
   363                   break;
       
   364                case AX:
       
   365                case CX:
       
   366                case DX:
       
   367                case BX:
       
   368                case SP:
       
   369                case BP:
       
   370                case SI:
       
   371                case DI:
       
   372                   op = X86Registers.getRegister16(operandType - AX);
       
   373                   break;
       
   374                case AL:
       
   375                case CL:
       
   376                case DL:
       
   377                case BL:
       
   378                case AH:
       
   379                case CH:
       
   380                case DH:
       
   381                case BH:
       
   382                   op = X86Registers.getRegister8(operandType - AL);
       
   383                   break;
       
   384                case ES:  //ES, CS, SS, DS, FS, GS
       
   385                case CS:
       
   386                case SS:
       
   387                case DS:
       
   388                case FS:
       
   389                case GS:
       
   390                   op = X86SegmentRegisters.getSegmentRegister(operandType - ES);
       
   391                   break;
       
   392            }
       
   393            break;
       
   394          case ADDR_DIR: //segment and offset
       
   395             long segment = 0;
       
   396             long offset = 0;
       
   397             switch (operandType) {
       
   398                case p_mode:
       
   399                   if (addrSize == true) {
       
   400                      offset = readInt32(bytesArray, byteIndex);
       
   401                      byteIndex += 4;
       
   402                      segment = readInt16(bytesArray, byteIndex);
       
   403                      byteIndex += 2;
       
   404                   } else {
       
   405                      offset = readInt16(bytesArray, byteIndex);
       
   406                      byteIndex += 2;
       
   407                      segment = readInt16(bytesArray, byteIndex);
       
   408                      byteIndex += 2;
       
   409                   }
       
   410                   op = new X86DirectAddress(segment, offset); //with offset
       
   411                   break;
       
   412                case v_mode:
       
   413                   if (addrSize == true) {
       
   414                      offset = readInt32(bytesArray, byteIndex);
       
   415                      byteIndex += 4;
       
   416                   } else {
       
   417                      offset = readInt16(bytesArray, byteIndex);
       
   418                      byteIndex += 2;
       
   419                   }
       
   420                   op = new X86DirectAddress(offset); //with offset
       
   421                   break;
       
   422                default:
       
   423                   break;
       
   424             }
       
   425             break;
       
   426          case ADDR_G:
       
   427             switch (operandType) {
       
   428                case b_mode:
       
   429                   op = X86Registers.getRegister8(regOrOpcode);
       
   430                   break;
       
   431                case w_mode:
       
   432                   op = X86Registers.getRegister16(regOrOpcode);
       
   433                   break;
       
   434                case d_mode:
       
   435                   op = X86Registers.getRegister32(regOrOpcode);
       
   436                   break;
       
   437               case v_mode:
       
   438                  if (operandSize == true)
       
   439                     op = X86Registers.getRegister32(regOrOpcode);
       
   440                  else
       
   441                     op = X86Registers.getRegister16(regOrOpcode);
       
   442                     break;
       
   443               default:
       
   444                  break;
       
   445             }
       
   446             break;
       
   447          case ADDR_SEG:
       
   448             op = X86SegmentRegisters.getSegmentRegister(regOrOpcode);
       
   449             break;
       
   450          case ADDR_OFF:
       
   451             int off = 0;
       
   452             if (addrSize == true) {
       
   453                off = readInt32(bytesArray, byteIndex);
       
   454                byteIndex += 4;
       
   455             }
       
   456             else {
       
   457                off = readInt16(bytesArray, byteIndex);
       
   458                byteIndex += 2;
       
   459             }
       
   460             op = new X86DirectAddress((long)off);
       
   461             break;
       
   462          case ADDR_J:
       
   463             long disp = 0;
       
   464             //The effective address is Instruction pointer + relative offset
       
   465             switch(operandType) {
       
   466                case b_mode:
       
   467                   disp = (byte)readByte(bytesArray, byteIndex);
       
   468                   byteIndex++;
       
   469                   break;
       
   470                case v_mode:
       
   471                   if (operandSize == true) {
       
   472                      disp = readInt32(bytesArray, byteIndex);
       
   473                      byteIndex += 4;
       
   474                   }
       
   475                   else {
       
   476                      disp = readInt16(bytesArray, byteIndex);
       
   477                      byteIndex += 2;
       
   478                   }
       
   479                   //disp = disp + (byteIndex-instrStartIndex);
       
   480                   break;
       
   481             }
       
   482             op = new X86PCRelativeAddress(disp);
       
   483             break;
       
   484          case ADDR_ESDI:
       
   485             op = new X86SegmentRegisterAddress(X86SegmentRegisters.ES, X86Registers.DI);
       
   486             break;
       
   487          case ADDR_DSSI:
       
   488             op = new X86SegmentRegisterAddress(X86SegmentRegisters.DS, X86Registers.SI);
       
   489             break;
       
   490          case ADDR_R:
       
   491             switch (operandType) {
       
   492                case b_mode:
       
   493                   op = X86Registers.getRegister8(mod);
       
   494                   break;
       
   495               case w_mode:
       
   496                  op = X86Registers.getRegister16(mod);
       
   497                  break;
       
   498               case d_mode:
       
   499                  op = X86Registers.getRegister32(mod);
       
   500                  break;
       
   501              case v_mode:
       
   502                 if (operandSize == true)
       
   503                    op = X86Registers.getRegister32(mod);
       
   504                 else
       
   505                    op = X86Registers.getRegister16(mod);
       
   506                    break;
       
   507              default:
       
   508                 break;
       
   509             }
       
   510             break;
       
   511          case ADDR_FPREG:
       
   512             switch (operandType) {
       
   513                case 0:
       
   514                   op = X86FloatRegisters.getRegister(0);
       
   515                   break;
       
   516                case 1:
       
   517                   op = X86FloatRegisters.getRegister(rm);
       
   518                   break;
       
   519             }
       
   520             break;
       
   521 
       
   522          //SSE: reg field of ModR/M byte selects a 128-bit XMM register
       
   523          case ADDR_V:
       
   524             op = X86XMMRegisters.getRegister(regOrOpcode);
       
   525             break;
       
   526 
       
   527          //SSE: reg field of ModR/M byte selects a 64-bit MMX register
       
   528          case ADDR_P:
       
   529             op = X86MMXRegisters.getRegister(regOrOpcode);
       
   530             break;
       
   531       }
       
   532       return op;
       
   533    }
       
   534 
       
   535    private X86SegmentRegister getSegmentRegisterFromPrefix(int prefixes) {
       
   536       X86SegmentRegister segRegister = null;
       
   537 
       
   538       if ( (prefixes & PREFIX_CS) != 0)
       
   539          segRegister = X86SegmentRegisters.CS;
       
   540       if ( (prefixes & PREFIX_DS) != 0)
       
   541          segRegister =  X86SegmentRegisters.DS;
       
   542       if ( (prefixes & PREFIX_ES) != 0)
       
   543          segRegister =  X86SegmentRegisters.ES;
       
   544       if ( (prefixes & PREFIX_FS) != 0)
       
   545          segRegister =  X86SegmentRegisters.FS;
       
   546       if ( (prefixes & PREFIX_SS) != 0)
       
   547          segRegister =  X86SegmentRegisters.SS;
       
   548       if ( (prefixes & PREFIX_GS) != 0)
       
   549          segRegister =  X86SegmentRegisters.GS;
       
   550 
       
   551       return segRegister;
       
   552    }
       
   553 
       
   554 }