< prev index next >

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64BaseAssembler.java

Print this page


   1 /*
   2  * Copyright (c) 2018, 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  */


 193             }
 194             throw GraalError.shouldNotReachHere("Unexpected kind: " + kind.toString());
 195         }
 196 
 197         /**
 198          * Emit an immediate of this size. Note that immediate {@link #QWORD} operands are encoded
 199          * as sign-extended 32-bit values.
 200          *
 201          * @param asm
 202          * @param imm
 203          */
 204         protected void emitImmediate(AMD64BaseAssembler asm, int imm) {
 205             throw new UnsupportedOperationException();
 206         }
 207 
 208         protected int immediateSize() {
 209             throw new UnsupportedOperationException();
 210         }
 211     }
 212 
 213     public abstract static class OperandDataAnnotation extends CodeAnnotation {
 214         /**
 215          * The position (bytes from the beginning of the method) of the operand.
 216          */
 217         public final int operandPosition;
 218         /**
 219          * The size of the operand, in bytes.
 220          */
 221         public final int operandSize;
 222         /**
 223          * The position (bytes from the beginning of the method) of the next instruction. On AMD64,
 224          * RIP-relative operands are relative to this position.
 225          */
 226         public final int nextInstructionPosition;
 227 
 228         OperandDataAnnotation(int instructionPosition, int operandPosition, int operandSize, int nextInstructionPosition) {
 229             super(instructionPosition);
 230 
 231             this.operandPosition = operandPosition;
 232             this.operandSize = operandSize;
 233             this.nextInstructionPosition = nextInstructionPosition;
 234         }
 235 
 236         @Override
 237         public String toString() {
 238             return getClass().getSimpleName() + " instruction [" + instructionPosition + ", " + nextInstructionPosition + "[ operand at " + operandPosition + " size " + operandSize;
 239         }
 240     }
 241 
 242     /**
 243      * Annotation that stores additional information about the displacement of a
 244      * {@link Assembler#getPlaceholder placeholder address} that needs patching.
 245      */
 246     protected static class AddressDisplacementAnnotation extends OperandDataAnnotation {
 247         AddressDisplacementAnnotation(int instructionPosition, int operandPosition, int operandSize, int nextInstructionPosition) {
 248             super(instructionPosition, operandPosition, operandSize, nextInstructionPosition);
 249         }
 250     }
 251 
 252     /**
 253      * Annotation that stores additional information about the immediate operand, e.g., of a call
 254      * instruction, that needs patching.
 255      */
 256     protected static class ImmediateOperandAnnotation extends OperandDataAnnotation {
 257         ImmediateOperandAnnotation(int instructionPosition, int operandPosition, int operandSize, int nextInstructionPosition) {
 258             super(instructionPosition, operandPosition, operandSize, nextInstructionPosition);
 259         }
 260     }
 261 
 262     protected void annotatePatchingImmediate(int operandOffset, int operandSize) {
 263         if (codePatchingAnnotationConsumer != null) {
 264             int pos = position();
 265             codePatchingAnnotationConsumer.accept(new ImmediateOperandAnnotation(pos, pos + operandOffset, operandSize, pos + operandOffset + operandSize));
 266         }
 267     }
 268 
 269     public final boolean supports(CPUFeature feature) {
 270         return ((AMD64) target.arch).getFeatures().contains(feature);
 271     }
 272 
 273     protected static boolean inRC(RegisterCategory rc, Register r) {
 274         return r.getRegisterCategory().equals(rc);
 275     }
 276 
 277     protected static int encode(Register r) {
 278         assert r.encoding >= 0 && (inRC(XMM, r) ? r.encoding < 32 : r.encoding < 16) : "encoding out of range: " + r.encoding;
 279         return r.encoding & 0x7;
 280     }
 281 
 282     private static final int MinEncodingNeedsRex = 8;
 283 
 284     /**
 285      * Constants for X86 prefix bytes.


 564      *            this instruction has not been completely emitted yet.
 565      * @param evexDisp8Scale the scaling factor for computing the compressed displacement of
 566      *            EVEX-encoded instructions. This scaling factor only matters when the emitted
 567      *            instruction uses one-byte-displacement form.
 568      */
 569     private void emitOperandHelper(int reg, AMD64Address addr, boolean force4Byte, int additionalInstructionSize, int evexDisp8Scale) {
 570         assert (reg & 0x07) == reg;
 571         int regenc = reg << 3;
 572 
 573         Register base = addr.getBase();
 574         Register index = addr.getIndex();
 575 
 576         Scale scale = addr.getScale();
 577         int disp = addr.getDisplacement();
 578 
 579         if (base.equals(AMD64.rip)) { // also matches addresses returned by getPlaceholder()
 580             // [00 000 101] disp32
 581             assert index.equals(Register.None) : "cannot use RIP relative addressing with index register";
 582             emitByte(0x05 | regenc);
 583             if (codePatchingAnnotationConsumer != null && addr.instructionStartPosition >= 0) {
 584                 codePatchingAnnotationConsumer.accept(new AddressDisplacementAnnotation(addr.instructionStartPosition, position(), 4, position() + 4 + additionalInstructionSize));
 585             }
 586             emitInt(disp);
 587         } else if (base.isValid()) {
 588             boolean overriddenForce4Byte = force4Byte;
 589             int baseenc = base.isValid() ? encode(base) : 0;
 590 
 591             if (index.isValid()) {
 592                 int indexenc = encode(index) << 3;
 593                 // [base + indexscale + disp]
 594                 if (disp == 0 && !base.equals(rbp) && !base.equals(r13)) {
 595                     // [base + indexscale]
 596                     // [00 reg 100][ss index base]
 597                     assert !index.equals(rsp) : "illegal addressing mode";
 598                     emitByte(0x04 | regenc);
 599                     emitByte(scale.log2 << 6 | indexenc | baseenc);
 600                 } else {
 601                     if (evexDisp8Scale > 1 && !overriddenForce4Byte) {
 602                         if (disp % evexDisp8Scale == 0) {
 603                             int newDisp = disp / evexDisp8Scale;
 604                             if (isByte(newDisp)) {


   1 /*
   2  * Copyright (c) 2018, 2019, 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  */


 193             }
 194             throw GraalError.shouldNotReachHere("Unexpected kind: " + kind.toString());
 195         }
 196 
 197         /**
 198          * Emit an immediate of this size. Note that immediate {@link #QWORD} operands are encoded
 199          * as sign-extended 32-bit values.
 200          *
 201          * @param asm
 202          * @param imm
 203          */
 204         protected void emitImmediate(AMD64BaseAssembler asm, int imm) {
 205             throw new UnsupportedOperationException();
 206         }
 207 
 208         protected int immediateSize() {
 209             throw new UnsupportedOperationException();
 210         }
 211     }
 212 
 213     public static class OperandDataAnnotation extends CodeAnnotation {
 214         /**
 215          * The position (bytes from the beginning of the method) of the operand.
 216          */
 217         public final int operandPosition;
 218         /**
 219          * The size of the operand, in bytes.
 220          */
 221         public final int operandSize;
 222         /**
 223          * The position (bytes from the beginning of the method) of the next instruction. On AMD64,
 224          * RIP-relative operands are relative to this position.
 225          */
 226         public final int nextInstructionPosition;
 227 
 228         OperandDataAnnotation(int instructionPosition, int operandPosition, int operandSize, int nextInstructionPosition) {
 229             super(instructionPosition);
 230 
 231             this.operandPosition = operandPosition;
 232             this.operandSize = operandSize;
 233             this.nextInstructionPosition = nextInstructionPosition;
 234         }
 235 
 236         @Override
 237         public String toString() {
 238             return getClass().getSimpleName() + " instruction [" + instructionPosition + ", " + nextInstructionPosition + "[ operand at " + operandPosition + " size " + operandSize;
 239         }
 240     }
 241 




















 242     protected void annotatePatchingImmediate(int operandOffset, int operandSize) {
 243         if (codePatchingAnnotationConsumer != null) {
 244             int pos = position();
 245             codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(pos, pos + operandOffset, operandSize, pos + operandOffset + operandSize));
 246         }
 247     }
 248 
 249     public final boolean supports(CPUFeature feature) {
 250         return ((AMD64) target.arch).getFeatures().contains(feature);
 251     }
 252 
 253     protected static boolean inRC(RegisterCategory rc, Register r) {
 254         return r.getRegisterCategory().equals(rc);
 255     }
 256 
 257     protected static int encode(Register r) {
 258         assert r.encoding >= 0 && (inRC(XMM, r) ? r.encoding < 32 : r.encoding < 16) : "encoding out of range: " + r.encoding;
 259         return r.encoding & 0x7;
 260     }
 261 
 262     private static final int MinEncodingNeedsRex = 8;
 263 
 264     /**
 265      * Constants for X86 prefix bytes.


 544      *            this instruction has not been completely emitted yet.
 545      * @param evexDisp8Scale the scaling factor for computing the compressed displacement of
 546      *            EVEX-encoded instructions. This scaling factor only matters when the emitted
 547      *            instruction uses one-byte-displacement form.
 548      */
 549     private void emitOperandHelper(int reg, AMD64Address addr, boolean force4Byte, int additionalInstructionSize, int evexDisp8Scale) {
 550         assert (reg & 0x07) == reg;
 551         int regenc = reg << 3;
 552 
 553         Register base = addr.getBase();
 554         Register index = addr.getIndex();
 555 
 556         Scale scale = addr.getScale();
 557         int disp = addr.getDisplacement();
 558 
 559         if (base.equals(AMD64.rip)) { // also matches addresses returned by getPlaceholder()
 560             // [00 000 101] disp32
 561             assert index.equals(Register.None) : "cannot use RIP relative addressing with index register";
 562             emitByte(0x05 | regenc);
 563             if (codePatchingAnnotationConsumer != null && addr.instructionStartPosition >= 0) {
 564                 codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(addr.instructionStartPosition, position(), 4, position() + 4 + additionalInstructionSize));
 565             }
 566             emitInt(disp);
 567         } else if (base.isValid()) {
 568             boolean overriddenForce4Byte = force4Byte;
 569             int baseenc = base.isValid() ? encode(base) : 0;
 570 
 571             if (index.isValid()) {
 572                 int indexenc = encode(index) << 3;
 573                 // [base + indexscale + disp]
 574                 if (disp == 0 && !base.equals(rbp) && !base.equals(r13)) {
 575                     // [base + indexscale]
 576                     // [00 reg 100][ss index base]
 577                     assert !index.equals(rsp) : "illegal addressing mode";
 578                     emitByte(0x04 | regenc);
 579                     emitByte(scale.log2 << 6 | indexenc | baseenc);
 580                 } else {
 581                     if (evexDisp8Scale > 1 && !overriddenForce4Byte) {
 582                         if (disp % evexDisp8Scale == 0) {
 583                             int newDisp = disp / evexDisp8Scale;
 584                             if (isByte(newDisp)) {


< prev index next >