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.LLVMAMD64UpdateCPZSOFlagsNode;
import com.oracle.truffle.llvm.runtime.nodes.api.LLVMExpressionNode;
@NodeChild("left")
@NodeChild("right")
public abstract class LLVMAMD64AddNode extends LLVMExpressionNode {
@Child protected LLVMAMD64UpdateCPZSOFlagsNode flags;
private LLVMAMD64AddNode(LLVMAMD64UpdateCPZSOFlagsNode flags) {
this.flags = flags;
}
public abstract static class LLVMAMD64AddbNode extends LLVMAMD64AddNode {
public LLVMAMD64AddbNode(LLVMAMD64UpdateCPZSOFlagsNode flags) {
super(flags);
}
@Specialization
protected byte doI8(VirtualFrame frame, byte left, byte right) {
byte result = (byte) (left + right);
boolean overflow = (result < 0 && left > 0 && right > 0) || (result >= 0 && left < 0 && right < 0);
boolean carry = ((left < 0 || right < 0) && result >= 0) || (left < 0 && right < 0);
flags.execute(frame, overflow, carry, result);
return result;
}
}
public abstract static class LLVMAMD64AddwNode extends LLVMAMD64AddNode {
public LLVMAMD64AddwNode(LLVMAMD64UpdateCPZSOFlagsNode flags) {
super(flags);
}
@Specialization
protected short doI16(VirtualFrame frame, short left, short right) {
short result = (short) (left + right);
boolean overflow = (result < 0 && left > 0 && right > 0) || (result >= 0 && left < 0 && right < 0);
boolean carry = ((left < 0 || right < 0) && result >= 0) || (left < 0 && right < 0);
flags.execute(frame, overflow, carry, result);
return result;
}
}
public abstract static class LLVMAMD64AddlNode extends LLVMAMD64AddNode {
public LLVMAMD64AddlNode(LLVMAMD64UpdateCPZSOFlagsNode flags) {
super(flags);
}
@Specialization
protected int doI32(VirtualFrame frame, int left, int right) {
int result = left + right;
boolean overflow = (result < 0 && left > 0 && right > 0) || (result >= 0 && left < 0 && right < 0);
boolean carry = ((left < 0 || right < 0) && result >= 0) || (left < 0 && right < 0);
flags.execute(frame, overflow, carry, result);
return result;
}
}
public abstract static class LLVMAMD64AddqNode extends LLVMAMD64AddNode {
public LLVMAMD64AddqNode(LLVMAMD64UpdateCPZSOFlagsNode flags) {
super(flags);
}
@Specialization
protected long doI64(VirtualFrame frame, long left, long right) {
long result = left + right;
boolean overflow = (result < 0 && left > 0 && right > 0) || (result >= 0 && left < 0 && right < 0);
boolean carry = ((left < 0 || right < 0) && result >= 0) || (left < 0 && right < 0);
flags.execute(frame, overflow, carry, result);
return result;
}
}
}