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));
}
}
};
}
});
}
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);
}
}
}
Aggregations