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