1 /*
   2  * Copyright 2002-2003 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  20  * CA 95054 USA or visit www.sun.com if you need additional information or
  21  * have any 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 }