diff --git a/src/main/java/haidnor/jvm/instruction/InstructionFactory.java b/src/main/java/haidnor/jvm/instruction/InstructionFactory.java index 7e2958a..27f87b8 100644 --- a/src/main/java/haidnor/jvm/instruction/InstructionFactory.java +++ b/src/main/java/haidnor/jvm/instruction/InstructionFactory.java @@ -301,10 +301,10 @@ public abstract class InstructionFactory { return new DUP2(codeStream); } case Const.DUP2_X1 -> { - throw new Error("Not support JavaVM opcode DUP2_X1"); + return new DUP2_X1(codeStream); } case Const.DUP2_X2 -> { - throw new Error("Not support JavaVM opcode DUP2_X2"); + return new DUP2_X2(codeStream); } case Const.SWAP -> { return new SWAP(codeStream); diff --git a/src/main/java/haidnor/jvm/instruction/stack/DUP2_X1.java b/src/main/java/haidnor/jvm/instruction/stack/DUP2_X1.java new file mode 100644 index 0000000..eb94553 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stack/DUP2_X1.java @@ -0,0 +1,36 @@ +package haidnor.jvm.instruction.stack; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; +import org.apache.bcel.Const; + +public class DUP2_X1 extends Instruction { + + public DUP2_X1(CodeStream codeStream) { + super(codeStream); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + StackValue stackValue1 = frame.pop(); + StackValue stackValue2 = frame.pop(); + + if (stackValue1.getType() == Const.T_DOUBLE || stackValue1.getType() == Const.T_LONG) { + frame.push(stackValue1); + frame.push(stackValue2); + frame.push(stackValue1); + } else { + StackValue stackValue3 = frame.pop(); + frame.push(stackValue1); + frame.push(stackValue2); + frame.push(stackValue3); + frame.push(stackValue1); + frame.push(stackValue2); + } + } + +} diff --git a/src/main/java/haidnor/jvm/instruction/stack/DUP2_X2.java b/src/main/java/haidnor/jvm/instruction/stack/DUP2_X2.java new file mode 100644 index 0000000..68b8b36 --- /dev/null +++ b/src/main/java/haidnor/jvm/instruction/stack/DUP2_X2.java @@ -0,0 +1,70 @@ +package haidnor.jvm.instruction.stack; + +import haidnor.jvm.instruction.Instruction; +import haidnor.jvm.runtime.Frame; +import haidnor.jvm.runtime.StackValue; +import haidnor.jvm.util.CodeStream; +import lombok.SneakyThrows; +import org.apache.bcel.Const; + +/** + * @author wang xiang + */ +public class DUP2_X2 extends Instruction { + + public DUP2_X2(CodeStream codeStream) { + super(codeStream); + } + + @Override + @SneakyThrows + public void execute(Frame frame) { + StackValue stackValue1 = frame.pop(); + // v1(64) + if (stackValue1.getType() == Const.T_DOUBLE || stackValue1.getType() == Const.T_LONG) { + StackValue stackValue2 = frame.pop(); + + // v1(64) v2(64) + if (stackValue2.getType() == Const.T_DOUBLE || stackValue2.getType() == Const.T_LONG) { + frame.push(stackValue1); + frame.push(stackValue2); + frame.push(stackValue1); + } + // v1(64) v2(32) + else { + StackValue stackValue3 = frame.pop(); + + frame.push(stackValue1); + frame.push(stackValue2); + frame.push(stackValue3); + frame.push(stackValue1); + } + } + // v1(32) + else { + StackValue stackValue2 = frame.pop(); + StackValue stackValue3 = frame.pop(); + + // v1(32) v2(32) v3(64) + if (stackValue3.getType() == Const.T_DOUBLE || stackValue3.getType() == Const.T_LONG) { + frame.push(stackValue1); + frame.push(stackValue2); + frame.push(stackValue3); + frame.push(stackValue1); + frame.push(stackValue2); + } + // v1(32) v2(32) v3(32) v4(32) + else { + StackValue stackValue4 = frame.pop(); + + frame.push(stackValue1); + frame.push(stackValue2); + frame.push(stackValue3); + frame.push(stackValue4); + frame.push(stackValue1); + frame.push(stackValue2); + } + } + } + +}