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 }