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.llvm.runtime.nodes.asm.support.LLVMAMD64UpdateFlagsNode.LLVMAMD64UpdateCPAZSOFlagsNode;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMStatementNode;
@NodeChild(value = "left", type = LLVMExpressionNode.class)
@NodeChild(value = "right", type = LLVMExpressionNode.class)
public abstract class LLVMAMD64CmpNode extends LLVMStatementNode {
@Child protected LLVMAMD64UpdateCPAZSOFlagsNode flags;
public LLVMAMD64CmpNode(LLVMAMD64UpdateCPAZSOFlagsNode flags) {
this.flags = flags;
}
public abstract static class LLVMAMD64CmpbNode extends LLVMAMD64CmpNode {
public LLVMAMD64CmpbNode(LLVMAMD64UpdateCPAZSOFlagsNode flags) {
super(flags);
}
@Specialization
protected void doOp(VirtualFrame frame, byte left, byte right) {
int result = left - right;
boolean overflow = (byte) ((left ^ right) & (left ^ result)) < 0;
boolean carry = Byte.toUnsignedInt(left) < Byte.toUnsignedInt(right);
boolean adjust = (((left ^ right) ^ result) & 0x10) != 0;
flags.execute(frame, overflow, carry, adjust, result);
}
}
public abstract static class LLVMAMD64CmpwNode extends LLVMAMD64CmpNode {
public LLVMAMD64CmpwNode(LLVMAMD64UpdateCPAZSOFlagsNode flags) {
super(flags);
}
@Specialization
protected void doOp(VirtualFrame frame, short left, short right) {
int result = left - right;
boolean overflow = (short) ((left ^ right) & (left ^ result)) < 0;
boolean carry = Short.toUnsignedInt(left) < Short.toUnsignedInt(right);
boolean adjust = (((left ^ right) ^ result) & 0x10) != 0;
flags.execute(frame, overflow, carry, adjust, result);
}
}
public abstract static class LLVMAMD64CmplNode extends LLVMAMD64CmpNode {
public LLVMAMD64CmplNode(LLVMAMD64UpdateCPAZSOFlagsNode flags) {
super(flags);
}
@Specialization
protected void doOp(VirtualFrame frame, int left, int right) {
int result = left - right;
boolean overflow = ((left ^ right) & (left ^ result)) < 0;
boolean carry = Integer.compareUnsigned(left, right) < 0;
boolean adjust = (((left ^ right) ^ result) & 0x10) != 0;
flags.execute(frame, overflow, carry, adjust, result);
}
}
public abstract static class LLVMAMD64CmpqNode extends LLVMAMD64CmpNode {
public LLVMAMD64CmpqNode(LLVMAMD64UpdateCPAZSOFlagsNode flags) {
super(flags);
}
@Specialization
protected void doOp(VirtualFrame frame, long left, long right) {
long result = left - right;
boolean overflow = ((left ^ right) & (left ^ result)) < 0;
boolean carry = Long.compareUnsigned(left, right) < 0;
boolean adjust = (((left ^ right) ^ result) & 0x10) != 0;
flags.execute(frame, overflow, carry, adjust, result);
}
}
}