Search in sources :

Example 1 with OperandDataAnnotation

use of org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandDataAnnotation in project graal by oracle.

the class AMD64HostedPatcher method afterRegistration.

@Override
public void afterRegistration(AfterRegistrationAccess access) {
    ImageSingletons.add(PatchConsumerFactory.HostedPatchConsumerFactory.class, new PatchConsumerFactory.HostedPatchConsumerFactory() {

        @Override
        public Consumer<Assembler.CodeAnnotation> newConsumer(CompilationResult compilationResult) {
            return new Consumer<>() {

                @Override
                public void accept(Assembler.CodeAnnotation annotation) {
                    if (annotation instanceof OperandDataAnnotation) {
                        compilationResult.addAnnotation(new AMD64HostedPatcher((OperandDataAnnotation) annotation));
                    } else if (annotation instanceof AddressDisplacementAnnotation) {
                        AddressDisplacementAnnotation dispAnnotation = (AddressDisplacementAnnotation) annotation;
                        compilationResult.addAnnotation(new HostedImageHeapConstantPatch(dispAnnotation.operandPosition, (SubstrateObjectConstant) dispAnnotation.annotation));
                    }
                }
            };
        }
    });
}
Also used : OperandDataAnnotation(org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandDataAnnotation) Consumer(java.util.function.Consumer) SubstrateObjectConstant(com.oracle.svm.core.meta.SubstrateObjectConstant) HostedImageHeapConstantPatch(com.oracle.svm.hosted.code.HostedImageHeapConstantPatch) PatchConsumerFactory(com.oracle.svm.core.graal.code.PatchConsumerFactory) CompilationResult(org.graalvm.compiler.code.CompilationResult) Assembler(org.graalvm.compiler.asm.Assembler) AddressDisplacementAnnotation(org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.AddressDisplacementAnnotation)

Example 2 with OperandDataAnnotation

use of org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandDataAnnotation in project graal by oracle.

the class AMD64BaseAssembler method emitOperandHelper.

/**
 * Emits the ModR/M byte and optionally the SIB byte for one memory operand and an opcode
 * extension in the R field.
 *
 * @param force4Byte use 4 byte encoding for displacements that would normally fit in a byte
 * @param additionalInstructionSize the number of bytes that will be emitted after the operand,
 *            so that the start position of the next instruction can be computed even though
 *            this instruction has not been completely emitted yet.
 * @param evexDisp8Scale the scaling factor for computing the compressed displacement of
 *            EVEX-encoded instructions. This scaling factor only matters when the emitted
 *            instruction uses one-byte-displacement form.
 */
private void emitOperandHelper(int reg, AMD64Address addr, boolean force4Byte, int additionalInstructionSize, int evexDisp8Scale) {
    assert (reg & 0x07) == reg;
    int regenc = reg << 3;
    Register base = addr.getBase();
    Register index = addr.getIndex();
    Scale scale = addr.getScale();
    int disp = addr.getDisplacement();
    Object dispAnnotation = addr.getDisplacementAnnotation();
    if (base.equals(AMD64.rip)) {
        // [00 reg 101] disp32
        assert index.equals(Register.None) : "cannot use RIP relative addressing with index register";
        emitByte(0x05 | regenc);
        if (codePatchingAnnotationConsumer != null && addr.isPlaceholder()) {
            codePatchingAnnotationConsumer.accept(new OperandDataAnnotation(addr.instructionStartPosition, position(), 4, position() + 4 + additionalInstructionSize));
        }
        emitDisplacementInt(disp, dispAnnotation);
    } else if (base.isValid()) {
        boolean overriddenForce4Byte = force4Byte || dispAnnotation != null || (force4ByteNonZeroDisplacements && disp != 0);
        int baseenc = base.isValid() ? encode(base) : 0;
        if (index.isValid()) {
            int indexenc = encode(index) << 3;
            // [base + indexscale + disp]
            if (dispAnnotation == null && disp == 0 && !base.equals(rbp) && !base.equals(r13)) {
                // [00 reg 100][ss index base]
                assert !index.equals(rsp) : "illegal addressing mode";
                emitByte(0x04 | regenc);
                emitByte(scale.log2 << 6 | indexenc | baseenc);
            } else {
                if (evexDisp8Scale > 1 && !overriddenForce4Byte) {
                    if (disp % evexDisp8Scale == 0) {
                        int newDisp = disp / evexDisp8Scale;
                        if (isByte(newDisp)) {
                            disp = newDisp;
                            assert isByte(disp) && !overriddenForce4Byte;
                        }
                    } else {
                        overriddenForce4Byte = true;
                    }
                }
                if (isByte(disp) && !overriddenForce4Byte) {
                    // [01 reg 100][ss index base] imm8
                    assert !index.equals(rsp) : "illegal addressing mode";
                    emitByte(0x44 | regenc);
                    emitByte(scale.log2 << 6 | indexenc | baseenc);
                    assert dispAnnotation == null;
                    emitByte(disp & 0xFF);
                } else {
                    // [10 reg 100][ss index base] disp32
                    assert !index.equals(rsp) : "illegal addressing mode";
                    emitByte(0x84 | regenc);
                    emitByte(scale.log2 << 6 | indexenc | baseenc);
                    emitDisplacementInt(disp, dispAnnotation);
                }
            }
        } else if (base.equals(rsp) || base.equals(r12)) {
            // [rsp + disp]
            if (dispAnnotation == null && disp == 0) {
                // [rsp]
                // [00 reg 100][00 100 100]
                emitByte(0x04 | regenc);
                emitByte(0x24);
            } else {
                if (evexDisp8Scale > 1 && !overriddenForce4Byte) {
                    if (disp % evexDisp8Scale == 0) {
                        int newDisp = disp / evexDisp8Scale;
                        if (isByte(newDisp)) {
                            disp = newDisp;
                            assert isByte(disp) && !overriddenForce4Byte;
                        }
                    } else {
                        overriddenForce4Byte = true;
                    }
                }
                if (isByte(disp) && !overriddenForce4Byte) {
                    // [rsp + imm8]
                    // [01 reg 100][00 100 100] disp8
                    emitByte(0x44 | regenc);
                    emitByte(0x24);
                    assert dispAnnotation == null;
                    emitByte(disp & 0xFF);
                } else {
                    // [rsp + imm32]
                    // [10 reg 100][00 100 100] disp32
                    emitByte(0x84 | regenc);
                    emitByte(0x24);
                    emitDisplacementInt(disp, dispAnnotation);
                }
            }
        } else {
            // [base + disp]
            assert !base.equals(rsp) && !base.equals(r12) : "illegal addressing mode";
            if (dispAnnotation == null && disp == 0 && !base.equals(rbp) && !base.equals(r13)) {
                // [base]
                // [00 reg base]
                emitByte(0x00 | regenc | baseenc);
            } else {
                if (evexDisp8Scale > 1 && !overriddenForce4Byte) {
                    if (disp % evexDisp8Scale == 0) {
                        int newDisp = disp / evexDisp8Scale;
                        if (isByte(newDisp)) {
                            disp = newDisp;
                            assert isByte(disp) && !overriddenForce4Byte;
                        }
                    } else {
                        overriddenForce4Byte = true;
                    }
                }
                if (isByte(disp) && !overriddenForce4Byte) {
                    // [base + disp8]
                    // [01 reg base] disp8
                    emitByte(0x40 | regenc | baseenc);
                    assert dispAnnotation == null;
                    emitByte(disp & 0xFF);
                } else {
                    // [base + disp32]
                    // [10 reg base] disp32
                    emitByte(0x80 | regenc | baseenc);
                    emitDisplacementInt(disp, dispAnnotation);
                }
            }
        }
    } else {
        if (index.isValid()) {
            int indexenc = encode(index) << 3;
            // [00 reg 100][ss index 101] disp32
            assert !index.equals(rsp) : "illegal addressing mode";
            emitByte(0x04 | regenc);
            emitByte(scale.log2 << 6 | indexenc | 0x05);
            emitDisplacementInt(disp, dispAnnotation);
        } else {
            // [disp] ABSOLUTE
            // [00 reg 100][00 100 101] disp32
            emitByte(0x04 | regenc);
            emitByte(0x25);
            emitDisplacementInt(disp, dispAnnotation);
        }
    }
}
Also used : Register(jdk.vm.ci.code.Register) Scale(org.graalvm.compiler.asm.amd64.AMD64Address.Scale)

Aggregations

PatchConsumerFactory (com.oracle.svm.core.graal.code.PatchConsumerFactory)1 SubstrateObjectConstant (com.oracle.svm.core.meta.SubstrateObjectConstant)1 HostedImageHeapConstantPatch (com.oracle.svm.hosted.code.HostedImageHeapConstantPatch)1 Consumer (java.util.function.Consumer)1 Register (jdk.vm.ci.code.Register)1 Assembler (org.graalvm.compiler.asm.Assembler)1 Scale (org.graalvm.compiler.asm.amd64.AMD64Address.Scale)1 AddressDisplacementAnnotation (org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.AddressDisplacementAnnotation)1 OperandDataAnnotation (org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandDataAnnotation)1 CompilationResult (org.graalvm.compiler.code.CompilationResult)1