package com.oracle.truffle.llvm.runtime.nodes.asm;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.llvm.runtime.nodes.asm.support.LLVMAMD64WriteBooleanNode;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode;
@NodeChild("src")
@NodeChild("dst")
public abstract class LLVMAMD64BsrNode extends LLVMExpressionNode {
@Child protected LLVMAMD64WriteBooleanNode writeZFNode;
protected final ConditionProfile profile;
public LLVMAMD64BsrNode(LLVMAMD64WriteBooleanNode writeZFNode) {
this.writeZFNode = writeZFNode;
profile = ConditionProfile.createCountingProfile();
}
public abstract static class LLVMAMD64BsrwNode extends LLVMAMD64BsrNode {
public LLVMAMD64BsrwNode(LLVMAMD64WriteBooleanNode writeZFNode) {
super(writeZFNode);
}
@Specialization
protected short doI16(VirtualFrame frame, short src, short dst) {
if (profile.profile(src == 0)) {
writeZFNode.execute(frame, true);
return dst;
} else {
writeZFNode.execute(frame, false);
int val = Short.toUnsignedInt(src);
int numberOfLeadingZeros = Integer.numberOfLeadingZeros(val) - LLVMExpressionNode.I32_SIZE_IN_BITS + LLVMExpressionNode.I16_SIZE_IN_BITS;
return (short) (LLVMExpressionNode.I16_SIZE_IN_BITS - numberOfLeadingZeros - 1);
}
}
}
public abstract static class LLVMAMD64BsrlNode extends LLVMAMD64BsrNode {
public LLVMAMD64BsrlNode(LLVMAMD64WriteBooleanNode writeZFNode) {
super(writeZFNode);
}
@Specialization
protected int doI32(VirtualFrame frame, int src, int dst) {
if (profile.profile(src == 0)) {
writeZFNode.execute(frame, true);
return dst;
} else {
writeZFNode.execute(frame, false);
int numberOfLeadingZeros = Integer.numberOfLeadingZeros(src);
return LLVMExpressionNode.I32_SIZE_IN_BITS - numberOfLeadingZeros - 1;
}
}
}
public abstract static class LLVMAMD64BsrqNode extends LLVMAMD64BsrNode {
public LLVMAMD64BsrqNode(LLVMAMD64WriteBooleanNode writeZFNode) {
super(writeZFNode);
}
@Specialization
protected long doI64(VirtualFrame frame, long src, long dst) {
if (profile.profile(src == 0)) {
writeZFNode.execute(frame, true);
return dst;
} else {
writeZFNode.execute(frame, false);
int numberOfLeadingZeros = Long.numberOfLeadingZeros(src);
return LLVMExpressionNode.I64_SIZE_IN_BITS - numberOfLeadingZeros - 1;
}
}
}
}