1 /*
   2  * Copyright (c) 2016, 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 package jdk.tools.jaotc.amd64;
  25 
  26 import jdk.tools.jaotc.InstructionDecoder;
  27 
  28 import jdk.vm.ci.code.TargetDescription;
  29 
  30 public final class AMD64InstructionDecoder extends InstructionDecoder {
  31 
  32     private boolean targetIs64Bit;
  33     private int currentEndOfInstruction;
  34 
  35     private static class Prefix {
  36 
  37         // segment overrides
  38         public static final int CSSegment = 0x2e;
  39         public static final int SSSegment = 0x36;
  40         public static final int DSSegment = 0x3e;
  41         public static final int ESSegment = 0x26;
  42         public static final int FSSegment = 0x64;
  43         public static final int GSSegment = 0x65;
  44         public static final int REX = 0x40;
  45         public static final int REXB = 0x41;
  46         public static final int REXX = 0x42;
  47         public static final int REXXB = 0x43;
  48         public static final int REXR = 0x44;
  49         public static final int REXRB = 0x45;
  50         public static final int REXRX = 0x46;
  51         public static final int REXRXB = 0x47;
  52         public static final int REXW = 0x48;
  53         public static final int REXWB = 0x49;
  54         public static final int REXWX = 0x4A;
  55         public static final int REXWXB = 0x4B;
  56         public static final int REXWR = 0x4C;
  57         public static final int REXWRB = 0x4D;
  58         public static final int REXWRX = 0x4E;
  59         public static final int REXWRXB = 0x4F;
  60         public static final int VEX_3BYTES = 0xC4;
  61         public static final int VEX_2BYTES = 0xC5;
  62     }
  63 
  64     public static class VexPrefix {
  65         public static final int VEX_R = 0x80;
  66         public static final int VEX_W = 0x80;
  67     }
  68 
  69     public static class VexOpcode {
  70         public static final int VEX_OPCODE_NONE = 0x0;
  71         public static final int VEX_OPCODE_0F = 0x1;
  72         public static final int VEX_OPCODE_0F_38 = 0x2;
  73         public static final int VEX_OPCODE_0F_3A = 0x3;
  74         public static final int VEX_OPCODE_MASK = 0x1F;
  75     }
  76 
  77     public AMD64InstructionDecoder(TargetDescription target) {
  78         this.targetIs64Bit = target.wordSize == 8;
  79     }
  80 
  81     @Override
  82     public int currentEndOfInstruction() {
  83         return currentEndOfInstruction;
  84     }
  85 
  86     @Override
  87     @SuppressWarnings("fallthrough")
  88     public void decodePosition(final byte[] code, int pcOffset) {
  89         assert pcOffset >= 0 && pcOffset < code.length;
  90 
  91         // Decode the given instruction, and return the Pointer of
  92         // an embedded 32-bit operand word.
  93 
  94         // If "which" is WhichOperand.disp32operand, selects the displacement portion
  95         // of an effective Pointer specifier.
  96         // If "which" is imm64Operand, selects the trailing immediate constant.
  97         // If "which" is WhichOperand.call32operand, selects the displacement of a call or jump.
  98         // Caller is responsible for ensuring that there is such an operand,
  99         // and that it is 32/64 bits wide.
 100 
 101         // If "which" is endPcOperand, find the end of the instruction.
 102 
 103         int ip = pcOffset;
 104         boolean is64bit = false;
 105 
 106         boolean hasDisp32 = false;
 107         int tailSize = 0; // other random bytes (#32, #16, etc.) at end of insn
 108 
 109         boolean againAfterPrefix = true;
 110 
 111         while (againAfterPrefix) {
 112             againAfterPrefix = false;
 113             switch (0xFF & code[ip++]) {
 114 
 115                 // These convenience macros generate groups of "case" labels for the switch.
 116 
 117                 case Prefix.CSSegment:
 118                 case Prefix.SSSegment:
 119                 case Prefix.DSSegment:
 120                 case Prefix.ESSegment:
 121                 case Prefix.FSSegment:
 122                 case Prefix.GSSegment:
 123                     // Seems dubious
 124                     assert !targetIs64Bit : "shouldn't have that prefix";
 125                     assert ip == pcOffset + 1 : "only one prefix allowed";
 126                     againAfterPrefix = true;
 127                     break;
 128 
 129                 case 0x67:
 130                 case Prefix.REX:
 131                 case Prefix.REXB:
 132                 case Prefix.REXX:
 133                 case Prefix.REXXB:
 134                 case Prefix.REXR:
 135                 case Prefix.REXRB:
 136                 case Prefix.REXRX:
 137                 case Prefix.REXRXB:
 138                     assert targetIs64Bit : "64bit prefixes";
 139                     againAfterPrefix = true;
 140                     break;
 141 
 142                 case Prefix.REXW:
 143                 case Prefix.REXWB:
 144                 case Prefix.REXWX:
 145                 case Prefix.REXWXB:
 146                 case Prefix.REXWR:
 147                 case Prefix.REXWRB:
 148                 case Prefix.REXWRX:
 149                 case Prefix.REXWRXB:
 150                     assert targetIs64Bit : "64bit prefixes";
 151                     is64bit = true;
 152                     againAfterPrefix = true;
 153                     break;
 154 
 155                 case 0xFF: // pushq a; decl a; incl a; call a; jmp a
 156                 case 0x88: // movb a, r
 157                 case 0x89: // movl a, r
 158                 case 0x8A: // movb r, a
 159                 case 0x8B: // movl r, a
 160                 case 0x8F: // popl a
 161                     hasDisp32 = true;
 162                     break;
 163 
 164                 case 0x68: // pushq #32
 165                     currentEndOfInstruction = ip + 4;
 166                     return; // not produced by emitOperand
 167 
 168                 case 0x66: // movw ... (size prefix)
 169                     boolean againAfterSizePrefix2 = true;
 170                     while (againAfterSizePrefix2) {
 171                         againAfterSizePrefix2 = false;
 172                         switch (0xFF & code[ip++]) {
 173                             case Prefix.REX:
 174                             case Prefix.REXB:
 175                             case Prefix.REXX:
 176                             case Prefix.REXXB:
 177                             case Prefix.REXR:
 178                             case Prefix.REXRB:
 179                             case Prefix.REXRX:
 180                             case Prefix.REXRXB:
 181                             case Prefix.REXW:
 182                             case Prefix.REXWB:
 183                             case Prefix.REXWX:
 184                             case Prefix.REXWXB:
 185                             case Prefix.REXWR:
 186                             case Prefix.REXWRB:
 187                             case Prefix.REXWRX:
 188                             case Prefix.REXWRXB:
 189                                 assert targetIs64Bit : "64bit prefix found";
 190                                 againAfterSizePrefix2 = true;
 191                                 break;
 192                             case 0x8B: // movw r, a
 193                             case 0x89: // movw a, r
 194                                 hasDisp32 = true;
 195                                 break;
 196                             case 0xC7: // movw a, #16
 197                                 hasDisp32 = true;
 198                                 tailSize = 2; // the imm16
 199                                 break;
 200                             case 0x0F: // several SSE/SSE2 variants
 201                                 ip--; // reparse the 0x0F
 202                                 againAfterPrefix = true;
 203                                 break;
 204                             default:
 205                                 throw new InternalError("should not reach here");
 206                         }
 207                     }
 208                     break;
 209 
 210                 case 0xB8: // movl/q r, #32/#64(oop?)
 211                 case 0xB9:
 212                 case 0xBA:
 213                 case 0xBB:
 214                 case 0xBC:
 215                 case 0xBD:
 216                 case 0xBE:
 217                 case 0xBF:
 218                     currentEndOfInstruction = ip + (is64bit ? 8 : 4);
 219                     return;
 220 
 221                 case 0x69: // imul r, a, #32
 222                 case 0xC7: // movl a, #32(oop?)
 223                     tailSize = 4;
 224                     hasDisp32 = true; // has both kinds of operands!
 225                     break;
 226 
 227                 case 0x0F: // movx..., etc.
 228                     switch (0xFF & code[ip++]) {
 229                         case 0x3A: // pcmpestri
 230                             ip++; // skip opcode
 231                             tailSize = 1;
 232                             hasDisp32 = true; // has both kinds of operands!
 233                             break;
 234 
 235                         case 0x38: // ptest, pmovzxbw
 236                             ip++; // skip opcode
 237                             hasDisp32 = true; // has both kinds of operands!
 238                             break;
 239 
 240                         case 0x70: // pshufd r, r/a, #8
 241                             hasDisp32 = true; // has both kinds of operands!
 242                             tailSize = 1;
 243                             break;
 244 
 245                         case 0x73: // psrldq r, #8
 246                             tailSize = 1;
 247                             break;
 248 
 249                         case 0x12: // movlps
 250                         case 0x28: // movaps
 251                         case 0x2E: // ucomiss
 252                         case 0x2F: // comiss
 253                         case 0x54: // andps
 254                         case 0x55: // andnps
 255                         case 0x56: // orps
 256                         case 0x57: // xorps
 257                         case 0x58: // addpd
 258                         case 0x59: // mulpd
 259                         case 0x6E: // movd
 260                         case 0x7E: // movd
 261                         case 0xAE: // ldmxcsr, stmxcsr, fxrstor, fxsave, clflush
 262                         case 0xFE: // paddd
 263                             // 64bit side says it these have both operands but that doesn't
 264                             // appear to be true
 265                             hasDisp32 = true;
 266                             break;
 267 
 268                         case 0xAD: // shrd r, a, %cl
 269                         case 0xAF: // imul r, a
 270                         case 0xBE: // movsbl r, a (movsxb)
 271                         case 0xBF: // movswl r, a (movsxw)
 272                         case 0xB6: // movzbl r, a (movzxb)
 273                         case 0xB7: // movzwl r, a (movzxw)
 274                         case 0x40: // cmovl cc, r, a
 275                         case 0x41:
 276                         case 0x42:
 277                         case 0x43:
 278                         case 0x44:
 279                         case 0x45:
 280                         case 0x46:
 281                         case 0x47:
 282                         case 0x48:
 283                         case 0x49:
 284                         case 0x4A:
 285                         case 0x4B:
 286                         case 0x4C:
 287                         case 0x4D:
 288                         case 0x4E:
 289                         case 0x4F:
 290                         case 0xB0: // cmpxchgb
 291                         case 0xB1: // cmpxchg
 292                         case 0xC1: // xaddl
 293                         case 0xC7: // cmpxchg8
 294                         case 0x90: // setcc a
 295                         case 0x91:
 296                         case 0x92:
 297                         case 0x93:
 298                         case 0x94:
 299                         case 0x95:
 300                         case 0x96:
 301                         case 0x97:
 302                         case 0x98:
 303                         case 0x99:
 304                         case 0x9A:
 305                         case 0x9B:
 306                         case 0x9C:
 307                         case 0x9D:
 308                         case 0x9E:
 309                         case 0x9F:
 310                             hasDisp32 = true;
 311                             // fall out of the switch to decode the Pointer
 312                             break;
 313 
 314                         case 0xC4: // pinsrw r, a, #8
 315                             hasDisp32 = true;
 316                             tailSize = 1;  // the imm8
 317                             break;
 318 
 319                         case 0xC5: // pextrw r, r, #8
 320                             tailSize = 1;  // the imm8
 321                             break;
 322 
 323                         case 0xAC: // shrd r, a, #8
 324                             hasDisp32 = true;
 325                             tailSize = 1; // the imm8
 326                             break;
 327 
 328                         case 0x80: // jcc rdisp32
 329                         case 0x81:
 330                         case 0x82:
 331                         case 0x83:
 332                         case 0x84:
 333                         case 0x85:
 334                         case 0x86:
 335                         case 0x87:
 336                         case 0x88:
 337                         case 0x89:
 338                         case 0x8A:
 339                         case 0x8B:
 340                         case 0x8C:
 341                         case 0x8D:
 342                         case 0x8E:
 343                         case 0x8F:
 344                             currentEndOfInstruction = ip + 4;
 345                             return;
 346                         default:
 347                             throw new InternalError("should not reach here");
 348                     }
 349                     break;
 350 
 351                 case 0x81: // addl a, #32; addl r, #32
 352                     // also: orl, adcl, sbbl, andl, subl, xorl, cmpl
 353                     // on 32bit in the case of cmpl, the imm might be an oop
 354                     tailSize = 4;
 355                     hasDisp32 = true; // has both kinds of operands!
 356                     break;
 357 
 358                 case 0x83: // addl a, #8; addl r, #8
 359                     // also: orl, adcl, sbbl, andl, subl, xorl, cmpl
 360                     hasDisp32 = true; // has both kinds of operands!
 361                     tailSize = 1;
 362                     break;
 363 
 364                 case 0x9B:
 365                     switch (0xFF & code[ip++]) {
 366                         case 0xD9: // fnstcw a
 367                             hasDisp32 = true;
 368                             break;
 369                         default:
 370                             throw new InternalError("should not reach here");
 371                     }
 372                     break;
 373 
 374                 case 0x00: // addb a, r; addl a, r; addb r, a; addl r, a
 375                 case 0x01:
 376                 case 0x02:
 377                 case 0x03:
 378                 case 0x10: // adc...
 379                 case 0x11:
 380                 case 0x12:
 381                 case 0x13:
 382                 case 0x20: // and...
 383                 case 0x21:
 384                 case 0x22:
 385                 case 0x23:
 386                 case 0x30: // xor...
 387                 case 0x31:
 388                 case 0x32:
 389                 case 0x33:
 390                 case 0x08: // or...
 391                 case 0x09:
 392                 case 0x0a:
 393                 case 0x0b:
 394                 case 0x18: // sbb...
 395                 case 0x19:
 396                 case 0x1a:
 397                 case 0x1b:
 398                 case 0x28: // sub...
 399                 case 0x29:
 400                 case 0x2a:
 401                 case 0x2b:
 402                 case 0xF7: // mull a
 403                 case 0x8D: // lea r, a
 404                 case 0x87: // xchg r, a
 405                 case 0x38: // cmp...
 406                 case 0x39:
 407                 case 0x3a:
 408                 case 0x3b:
 409                 case 0x85: // test r, a
 410                     hasDisp32 = true; // has both kinds of operands!
 411                     break;
 412 
 413                 case 0xC1: // sal a, #8; sar a, #8; shl a, #8; shr a, #8
 414                 case 0xC6: // movb a, #8
 415                 case 0x80: // cmpb a, #8
 416                 case 0x6B: // imul r, a, #8
 417                     hasDisp32 = true; // has both kinds of operands!
 418                     tailSize = 1; // the imm8
 419                     break;
 420 
 421                 case Prefix.VEX_3BYTES:
 422                 case Prefix.VEX_2BYTES:
 423                     assert ip == pcOffset + 1 : "no prefixes allowed";
 424                     int vex_opcode;
 425                     // First byte
 426                     if ((code[pcOffset] & 0xFF) == Prefix.VEX_3BYTES) {
 427                         vex_opcode = VexOpcode.VEX_OPCODE_MASK & code[ip];
 428                         ip++; // third byte
 429                         is64bit = ((VexPrefix.VEX_W & code[ip]) == VexPrefix.VEX_W);
 430                     } else {
 431                         vex_opcode = VexOpcode.VEX_OPCODE_0F;
 432                     }
 433                     ip++; // opcode
 434                     // To find the end of instruction (which == end_pc_operand).
 435                     switch (vex_opcode) {
 436                         case VexOpcode.VEX_OPCODE_0F:
 437                             switch (0xFF & code[ip]) {
 438                                 case 0x70: // pshufd r, r/a, #8
 439                                 case 0x71: // ps[rl|ra|ll]w r, #8
 440                                 case 0x72: // ps[rl|ra|ll]d r, #8
 441                                 case 0x73: // ps[rl|ra|ll]q r, #8
 442                                 case 0xC2: // cmp[ps|pd|ss|sd] r, r, r/a, #8
 443                                 case 0xC4: // pinsrw r, r, r/a, #8
 444                                 case 0xC5: // pextrw r/a, r, #8
 445                                 case 0xC6: // shufp[s|d] r, r, r/a, #8
 446                                     tailSize = 1;  // the imm8
 447                                     break;
 448                                 default:
 449                                     ; // no imm8
 450                             }
 451                             break;
 452                         case VexOpcode.VEX_OPCODE_0F_3A:
 453                             tailSize = 1;
 454                             break;
 455                         default:
 456                             throw new InternalError("should not reach here");
 457                     }
 458                     ip++; // skip opcode
 459                     hasDisp32 = true;
 460                     break;
 461 
 462                 case 0xE8: // call rdisp32
 463                 case 0xE9: // jmp rdisp32
 464                     currentEndOfInstruction = ip + 4;
 465                     return;
 466 
 467                 case 0xD1: // sal a, 1; sar a, 1; shl a, 1; shr a, 1
 468                 case 0xD3: // sal a, %cl; sar a, %cl; shl a, %cl; shr a, %cl
 469                 case 0xD9: // fldS a; fstS a; fstpS a; fldcw a
 470                 case 0xDD: // fldD a; fstD a; fstpD a
 471                 case 0xDB: // fildS a; fistpS a; fldX a; fstpX a
 472                 case 0xDF: // fildD a; fistpD a
 473                 case 0xD8: // faddS a; fsubrS a; fmulS a; fdivrS a; fcompS a
 474                 case 0xDC: // faddD a; fsubrD a; fmulD a; fdivrD a; fcompD a
 475                 case 0xDE: // faddpD a; fsubrpD a; fmulpD a; fdivrpD a; fcomppD a
 476                     hasDisp32 = true;
 477                     break;
 478 
 479                 case 0xF0: // Lock
 480                     againAfterPrefix = true;
 481                     break;
 482 
 483                 case 0xF3: // For SSE
 484                 case 0xF2: // For SSE2
 485                     switch (0xFF & code[ip++]) {
 486                         case Prefix.REX:
 487                         case Prefix.REXB:
 488                         case Prefix.REXX:
 489                         case Prefix.REXXB:
 490                         case Prefix.REXR:
 491                         case Prefix.REXRB:
 492                         case Prefix.REXRX:
 493                         case Prefix.REXRXB:
 494                         case Prefix.REXW:
 495                         case Prefix.REXWB:
 496                         case Prefix.REXWX:
 497                         case Prefix.REXWXB:
 498                         case Prefix.REXWR:
 499                         case Prefix.REXWRB:
 500                         case Prefix.REXWRX:
 501                         case Prefix.REXWRXB:
 502                             assert targetIs64Bit : "found 64bit prefix";
 503                             ip++;
 504                             ip++;
 505                             break;
 506                         default:
 507                             ip++;
 508                     }
 509                     hasDisp32 = true; // has both kinds of operands!
 510                     break;
 511 
 512                 default:
 513                     throw new InternalError("should not reach here");
 514             }
 515         }
 516 
 517         assert hasDisp32 : "(tw) not sure if this holds: instruction has no disp32 field";
 518 
 519         // parse the output of emitOperand
 520         int op2 = 0xFF & code[ip++];
 521         int base = op2 & 0x07;
 522         int op3 = -1;
 523         int b100 = 4;
 524         int b101 = 5;
 525         if (base == b100 && (op2 >> 6) != 3) {
 526             op3 = 0xFF & code[ip++];
 527             base = op3 & 0x07; // refetch the base
 528         }
 529         // now ip points at the disp (if any)
 530 
 531         switch (op2 >> 6) {
 532             case 0:
 533                 // [00 reg 100][ss index base]
 534                 // [00 reg 100][00 100 esp]
 535                 // [00 reg base]
 536                 // [00 reg 100][ss index 101][disp32]
 537                 // [00 reg 101] [disp32]
 538                 if (base == b101) {
 539                     ip += 4; // skip the disp32
 540                 }
 541                 break;
 542 
 543             case 1:
 544                 // [01 reg 100][ss index base][disp8]
 545                 // [01 reg 100][00 100 esp][disp8]
 546                 // [01 reg base] [disp8]
 547                 ip += 1; // skip the disp8
 548                 break;
 549 
 550             case 2:
 551                 // [10 reg 100][ss index base][disp32]
 552                 // [10 reg 100][00 100 esp][disp32]
 553                 // [10 reg base] [disp32]
 554                 ip += 4; // skip the disp32
 555                 break;
 556 
 557             case 3:
 558                 // [11 reg base] (not a memory addressing mode)
 559                 break;
 560         }
 561 
 562         currentEndOfInstruction = ip + tailSize;
 563     }
 564 
 565 }